小程序后端支付代码亲测可用
<?php namespace Home\Controller; use Think\Controller; class WechatpayController extends Controller { //微信支付 public function pay() { //参数定义 $appid=\'111111\'; $appsecret=\'1111111\'; $mch_id=\'1111111\'; $notify_url=\'https://www.123.com/index.php/Home/Wechatpay/wechatNotify/\'; //获取openid /*if(I("post.userid")) { $infos=M(\'weixin_users\')->find(I("post.userid")); $openid = $infos->openid; }*/ $openid=\'oOnZO5Q8OBzoZYj-1CW_6c1S86zA\'; //支付相关设置 //$fee = I("post.total_fee"); $fee = 0.01;//举例支付0.01 $body =\'test\'; $nonce_str=$this->nonce_str();//随机字符串 $out_trade_no = $this->order_number();//商户订单号 $spbill_create_ip = \'47.105.151.242\';//服务器的ip【自己填写】; $total_fee =$fee*100;// 微信支付单位是分,所以这里需要*100 $trade_type = \'JSAPI\';//交易类型 默认 //这里是按照顺序的 因为下面的签名是按照顺序 排序错误 肯定出错 $post[\'appid\'] = $appid; $post[\'body\'] = $body; $post[\'mch_id\'] = $mch_id; $post[\'nonce_str\'] = $nonce_str;//随机字符串 $post[\'notify_url\'] = $notify_url; $post[\'openid\'] = $openid; $post[\'out_trade_no\'] = $out_trade_no; $post[\'spbill_create_ip\'] = $spbill_create_ip;//终端的ip $post[\'total_fee\'] = $total_fee;//总金额 $post[\'trade_type\'] = $trade_type; //插入微信支付表 $pay=M(\'weixin_pay\'); $count=$pay->where("out_trade_no=\'".$out_trade_no."\'")->count(); $sign = $this->sign($post);//签名 if($count==0) { $data=array(); $data[\'out_trade_no\']=$out_trade_no; $data[\'status\']=1; $data[\'create_time\']=time(); $data[\'sign\']=$sign; $data[\'openid\']=$openid; $data[\'total_fee\']=$total_fee; $data[\'trade_type\']=$trade_type; $data[\'notify_url\']=$notify_url; $pay->add($data); } $post_xml = \'<xml> <appid>\'.$appid.\'</appid> <body>\'.$body.\'</body> <mch_id>\'.$mch_id.\'</mch_id> <nonce_str>\'.$nonce_str.\'</nonce_str> <notify_url>\'.$notify_url.\'</notify_url> <openid>\'.$openid.\'</openid> <out_trade_no>\'.$out_trade_no.\'</out_trade_no> <spbill_create_ip>\'.$spbill_create_ip.\'</spbill_create_ip> <total_fee>\'.$total_fee.\'</total_fee> <trade_type>\'.$trade_type.\'</trade_type> <sign>\'.$sign.\'</sign> </xml>\'; //var_dump($post_xml); //print_r($post_xml);die; //统一接口prepay_id $url = \'https://api.mch.weixin.qq.com/pay/unifiedorder\'; $xml = $this->http_request($url,$post_xml); $array = $this->xml($xml);//全要大写 //print_r($array); if($array[\'RETURN_CODE\'] == \'SUCCESS\' && $array[\'RESULT_CODE\'] == \'SUCCESS\'){ $time = time(); $tmp=\'\';//临时数组用于签名 $tmp[\'appId\'] = $appid; $tmp[\'nonceStr\'] = $nonce_str; $tmp[\'package\'] = \'prepay_id=\'.$array[\'PREPAY_ID\']; $tmp[\'signType\'] = \'MD5\'; $tmp[\'timeStamp\'] = "$time"; $data[\'state\'] = 200; $data[\'timeStamp\'] = "$time";//时间戳 $data[\'nonceStr\'] = $nonce_str;//随机字符串 $data[\'signType\'] = \'MD5\';//签名算法,暂支持 MD5 $data[\'package\'] = \'prepay_id=\'.$array[\'PREPAY_ID\'];//统一下单接口返回的 prepay_id 参数值,提交格式如:prepay_id=* $data[\'paySign\'] = $this->sign($tmp);//签名,具体签名方案参见微信公众号支付帮助文档; $data[\'out_trade_no\'] = $out_trade_no; }else{ $data[\'state\'] = 0; $data[\'text\'] = "错误"; $data[\'RETURN_CODE\'] = $array[\'RETURN_CODE\']; $data[\'RETURN_MSG\'] = $array[\'RETURN_MSG\']; } echo json_encode($data); } //随机32位字符串 private function nonce_str(){ $result = \'\'; $str = \'QWERTYUIOPASDFGHJKLZXVBNMqwertyuioplkjhgfdsamnbvcxz\'; for($i=0;$i<32;$i++){ $result .= $str[rand(0,48)]; } return $result; } //生成订单号 private function order_number($openid){ //date(\'Ymd\',time()).time().rand(10,99);//18位 return md5($openid.time().rand(10,99));//32位 } //签名 $data要先排好顺序 private function sign($data){ $stringA = \'\'; foreach ($data as $key=>$value){ if(!$value) continue; if($stringA) $stringA .= \'&\'.$key."=".$value; else $stringA = $key."=".$value; } //echo $stringA; $wx_key=\'1111111\';//申请支付后有给予一个商户账号和密码,登陆后自己设置的key $stringSignTemp = $stringA.\'&key=\'.$wx_key; return strtoupper(md5($stringSignTemp)); } //curl请求 public function http_request($url,$data = null,$headers=array()) { $curl = curl_init(); if( count($headers) >= 1 ){ curl_setopt($curl, CURLOPT_HTTPHEADER, $headers); } curl_setopt($curl, CURLOPT_URL, $url); curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, FALSE); curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, FALSE); if (!empty($data)){ curl_setopt($curl, CURLOPT_POST, 1); curl_setopt($curl, CURLOPT_POSTFIELDS, $data); } curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1); $output = curl_exec($curl); curl_close($curl); return $output; } //获取xml private function xml($xml){ $p = xml_parser_create(); xml_parse_into_struct($p, $xml, $vals, $index); xml_parser_free($p); $data = ""; foreach ($index as $key=>$value) { if($key == \'xml\' || $key == \'XML\') continue; $tag = $vals[$value[0]][\'tag\']; $value = $vals[$value[0]][\'value\']; $data[$tag] = $value; } return $data; } public function wechatNotify() { //存储微信的回调 $xml = file_get_contents("php://input"); $arr = $this -> XmlToArr($xml); $out_trade_no = $arr[\'out_trade_no\']; $openid=$arr[\'openid\'];//openid $sign=$arr[\'sign\'];//校验码 $total_fee=$arr[\'total_fee\'];//订单金额 $transaction_id=$arr[\'transaction_id\'];//微信支付号 $pay=M(\'weixin_pay\'); $count=$pay->where(array(\'out_trade_no\'=>$out_trade_no))->count(); $myfile = fopen("newfile.txt", "w") or die("Unable to open file!"); $txt = $out_trade_no."\n"; fwrite($myfile, $txt); $txt = $openid."\n"; fwrite($myfile, $txt); $txt=\'count:\'.$count; fwrite($myfile, $txt); fclose($myfile); if($count==1) { $info=$pay->where(array(\'out_trade_no\'=>$out_trade_no))->field(\'id,openid,total_fee\')->find(); if($info[\'openid\']==$openid && $total_fee==$info[\'total_fee\']) { //更新微信支付表 $data=array(); $data[\'update_time\']=time(); $data[\'status\']=2; $data[\'transaction_id\']=$transaction_id; $pay->where("openid=\'".$openid."\' and out_trade_no=\'".$out_trade_no."\'")->save($data); } } echo \'success\'; } private function XmlToArr($xml) { if($xml == \'\') return \'\'; libxml_disable_entity_loader(true); $arr = json_decode(json_encode(simplexml_load_string($xml, \'SimpleXMLElement\', LIBXML_NOCDATA)), true); return $arr; } }