本人亲自开发 流程基本与微信支付一致 没什么特别的不一样 其中 有俩坑 和大家分享一下 其中一个是 回调地址不允许带参数 一个订单号 只能支付一回 如果中途放弃支付 还用之前的订单号码 微信这边 会报错的 订单状态有待支付 重新支付的时候 最好更新下订单编号 还有需要证书验证 去开通的微信商户号里直接下载就好 话不多说 上代码
首先是微信的统一下单接口
统一下单地址
https://api.mch.weixin.qq.com/pay/unifiedorder
, // 小程序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 = "";
foreach ($arr as $key => $val) {
if (is_array($val)) {
$xml .= "<" . $key . ">" . arrayToXml($val) . "" . $key . ">";
} else {
$xml .= "<" . $key . ">" . $val . "" . $key . ">";
}
}
$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');
}
验证签名