版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/php_lzr/article/details/85015413
本人亲自开发 流程基本与微信支付一致 没什么特别的不一样 其中 有俩坑 和大家分享一下 其中一个是 回调地址不允许带参数 一个订单号 只能支付一回 如果中途放弃支付 还用之前的订单号码 微信这边 会报错的 订单状态有待支付 重新支付的时候 最好更新下订单编号 还有需要证书验证 去开通的微信商户号里直接下载就好 话不多说 上代码
首先是微信的统一下单接口
统一下单地址
https://api.mch.weixin.qq.com/pay/unifiedorder
<?php require_once "wxxcxpay.conf.php"; class wxxcxpayExt { //微信小程序接口 public static function weixinapp($par) { //统一下单接口 $unifiedorder = self::xcxpay($par); // 统一下单出错,参数出错等原因 if($unifiedorder['return_code'] == 'FAIL') { $retrunInfo['code'] = 0; $retrunInfo['msg'] = $unifiedorder['return_msg']; return $retrunInfo; } $parameters = array( 'appId' => , // 小程序ID 'timeStamp' => ''.time().'', // 时间戳 'nonceStr' => self::nonce_str(), // 随机串 'package' => 'prepay_id='.$unifiedorder['prepay_id'], // 数据包 'signType' => 'MD5' // 签名方式 ); // 小程序发起支付签名 $parameters['paySign'] = self::sign($parameters); // 成功返回 $retrunInfo['code'] = 1; $retrunInfo['msg'] = $parameters; return $retrunInfo; } //微信小程序支付 public static function xcxpay($par){ //统一支付接口 $url = 'https://api.mch.weixin.qq.com/pay/unifiedorder'; // 这里的参数顺序一定要按下面的,不然可能就一直报商户号此功能未授权等错误 $parameters = array( 'appid' => , // 小程序ID 'body' => $par['subject'], // 商品描述 'mch_id' => , // 商户号 'nonce_str' => self::nonce_str(), // 随机字符串 'notify_url' => $par['notify_url'], //'https://shop.gdpress.cn/syw_jingzhun/index.php/Api/xiaochengxu/notify_url_api', // 通知地址 确保外网能正常访问 'openid' => $par['openid'], // 用户id 'out_trade_no'=> $par['out_trade_no'], // 商户订单号 //'spbill_create_ip' => $_SERVER['REMOTE_ADDR'], // 终端IP 'spbill_create_ip' => $_SERVER['REMOTE_ADDR'], // 终端IP 'total_fee' => $par['total_fee'], // 单位 分 'trade_type' => 'JSAPI', // 交易类型 'attach' => $par['pay_id'] //自定义参数 ); //统一下单签名 $parameters['sign'] =self::sign($parameters); $xmlData = self::arrayToXml($parameters); $return = self::postXmlCurl($xmlData, $url, 60); $return_lists = self::xmlToArray($return); return $return_lists; } // curl请求方法封装 private static function postXmlCurl($xml, $url, $second = 30) { $ch = curl_init(); //设置超时 curl_setopt($ch, CURLOPT_TIMEOUT, $second); curl_setopt($ch, CURLOPT_URL, $url); curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE); curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE); //严格校验 //设置header curl_setopt($ch, CURLOPT_HEADER, FALSE); //要求结果为字符串且输出到屏幕上 curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE); //post提交方式 curl_setopt($ch, CURLOPT_POST, TRUE); curl_setopt($ch, CURLOPT_POSTFIELDS, $xml); curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 20); curl_setopt($ch, CURLOPT_TIMEOUT, 40); set_time_limit(0); //运行curl $data = curl_exec($ch); //返回结果 if ($data) { curl_close($ch); return $data; } else { $error = curl_errno($ch); curl_close($ch); throw new WxPayException("curl出错,错误码:$error"); } } //随机32位字符串 private static function nonce_str(){ $result = ''; $str = 'QWERTYUIOPASDFGHJKLZXVBNMqwertyuioplkjhgfdsamnbvcxz'; for ($i=0;$i<32;$i++){ $result .= $str[rand(0,48)]; } return $result; } //签名 public static function sign($data){ ksort($data); $stringA = ''; foreach ($data as $key=>$value){ if(!$value) continue; if($stringA) $stringA .= '&'.$key."=".$value; else $stringA = $key."=".$value; } $wx_key = ;//申请支付后有给予一个商户账号和密码,登陆后自己设置的key $stringSignTemp = $stringA.'&key='.$wx_key; $sign = strtoupper(md5($stringSignTemp)); return $sign; } //数组转换成xml private static function arrayToXml($arr) { $xml = "<xml>"; foreach ($arr as $key => $val) { if (is_array($val)) { $xml .= "<" . $key . ">" . arrayToXml($val) . "</" . $key . ">"; } else { $xml .= "<" . $key . ">" . $val . "</" . $key . ">"; } } $xml .= "</xml>"; return $xml; } //xml转换成数组 public static function xmlToArray($xml) { //禁止引用外部xml实体 libxml_disable_entity_loader(true); $xmlstring = simplexml_load_string($xml, 'SimpleXMLElement', LIBXML_NOCDATA); $val = json_decode(json_encode($xmlstring), true); return $val; } }
将参数返回给前端 前端拿到数据 调起支付 这块的代码就不写 官方文档写的很详细 百度也有一大堆
下面是回调验证签名
$xml = $GLOBALS['HTTP_RAW_POST_DATA']; $data = json_decode(json_encode(simplexml_load_string($xml, 'SimpleXMLElement', LIBXML_NOCDATA)), true); $request = ' 原始数据 '.var_export($GLOBALS['HTTP_RAW_POST_DATA'], 1).',处理后数据 : '.var_export($data, 1).'.'; if ($data && $data['return_code'] == 'SUCCESS') { 这里面处理自己的业务逻辑 修改订单转态 }else{ setOpeLog('xcxpay',$request,'','xcxpay error'); }
验证签名