注意: 我用的是Yii2.0 框架 ..
对微信支付的初步探索(一)
PHP之微信支付的爬坑之旅(中)
上次做到最后还是没解决的问题 : PHP之微信支付的爬坑之旅(中)
今天早上又花了两小时,重新理一理思路,现在终于搞定
首先,我们说一说上一期的几个错误
在下单完成以后获取分配给JSAPI的数据这里用到的签名有错..
刚开始真是傻了,看了方倍工作室的微信支付文章,导致这里的签名搞错了还一直不知道,….
记住,微信支付所有的与签名有关的都需要这样走
第一步,设所有发送或者接收到的数据为集合M,将集合M内非空参数值的参数按照参数名ASCII码从小到大排序(字典序),使用URL键值对的格式(即key1=value1&key2=value2…)拼接成字符串stringA。
特别注意以下重要规则:
◆ 参数名ASCII码从小到大排序(字典序);
◆ 如果参数的值为空不参与签名;
◆ 参数名区分大小写;
◆ 验证调用返回或微信主动通知签名时,传送的sign参数不参与签名,将生成的签名与该sign值作校验。
◆ 微信接口可能增加字段,验证签名时必须支持增加的扩展字段
第二步,在stringA最后拼接上key得到stringSignTemp字符串,并对stringSignTemp进行MD5运算,再将得到的字符串所有字符转换为大写,得到sign值signValue。
文档地址 : 微信支付签名算法
分配时候眼瞎了,大小写写错
计算分配给JSAPI的签名时候的时间戳 这里是大写S timeStamp我写错了….
两次计算签名都要加上Key
商户平台后台获取的Key要加在计算签名字符串最后面,(见下文代码)
微信后台授权目录一定要写对
下面来重新整理一下代码思路
openid 获取暂时略过……
首先第一步, 调用 微信支付统一下单接口 下单获取单号
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
public function actionUnifiedorder($nonceStr='',$openid){ $TempArr = array( 'appid'=>$this->actionConfig()['appid'], 'mch_id'=>'1302450501', 'nonce_str'=>$nonceStr, 'body'=>'测试商品', 'detail'=>'测试商品详情', 'out_trade_no'=>'20150806125346', 'total_fee'=>1, 'spbill_create_ip'=>'123.12.12.123', 'notify_url'=>'http://wxdevelop.kuaiyoujia.com/wxpay.php', 'trade_type'=>'JSAPI', 'product_id'=>'12235413214070356458058', 'openid'=>'oDYxEuJr2LOO6D9PogEUFYKZHPkY', ); /*第一步,设所有发送或者接收到的数据为集合M.....*/ $TempSign = 'appid='.$TempArr["appid"].'&body='.$TempArr["body"].'&detail='.$TempArr["detail"].'&mch_id='.$TempArr["mch_id"].'&nonce_str='.$TempArr["nonce_str"].'¬ify_url='.$TempArr["notify_url"].'&openid='.$TempArr["openid"].'&out_trade_no='.$TempArr["out_trade_no"].'&product_id='.$TempArr["product_id"].'&spbill_create_ip='.$TempArr["spbill_create_ip"].'&total_fee='.$TempArr["total_fee"].'&trade_type='.$TempArr["trade_type"].'&key=****'; /*第二步:MD5运算再将得到的字符串所有字符转换为大写*/ $signValue = strtoupper(MD5($TempSign)); $TempArr['sign'] = $signValue; //把计算出来的签名赋值到统一下单数组 $xmls = $this->actionArrToXml($TempArr); //把统一下单数组转为xml $Result = https_request('https://api.mch.weixin.qq.com/pay/unifiedorder',$xmls);//使用post 发送xml数据 $data = $this->actionXmlToArray($Result); return $data; } |
第二步,单号获取完成,计算JSAPI需要的数据,
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
public function actionWecahtPay($url,$openid){ $wecaht = new Wechats($this->actionConfig()); $timestamp = time();//时间戳 $nonceStr = substr(md5(time()),0,20); //随机字符串 $package = $this->actionUnifiedorder($nonceStr,$openid);//统一下单接口 $signType = 'MD5'; $signPackage = array( "appId" => $package['appid'], "nonceStr" => $package['nonce_str'], "timestamp" => $timestamp, 'package'=>'prepay_id='.$package['prepay_id'], 'signType'=>$signType, ); ksort($signPackage); p($signPackage); $string = 'appId='.$signPackage['appId'].'&nonceStr='.$signPackage['nonceStr'].'&package='.$signPackage['package'].'&signType='.$signPackage['signType'].'&timeStamp='.$signPackage['timestamp'].'&key=*****'; $signature = strtoupper(MD5($string)); $signPackage['signature'] = $signature; return $signPackage; } |
其他用到的几个方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 |
public function actionToUrlParams($urlObj) { $buff = ""; foreach ($urlObj as $k => $v) { if($k != "sign"){ $buff .= $k . "=" . $v . "&"; } } $buff = trim($buff, "&"); return $buff; } /*数组转xml*/ public function actionArrToXml($arr){ $Tempstr = '<xml>'; foreach ($arr as $k => $v) { $Tempstr .='<'.$k.'>'.$v.'</'.$k.'>'; } $Tempstr .= '</xml>'; return $Tempstr; } public function actionXmlToArray($xml) { //将XML转为array $TempData = array(); $array_data = json_decode(json_encode(simplexml_load_string($xml, 'SimpleXMLElement', LIBXML_NOCDATA)), true); foreach ($array_data as $k => $v) { $TempData[$k] = trim(str_replace(']]>','',str_replace('<![CDATA[','',$v))); } return $TempData; } |
最后,附上几张截图
这里是 timeStamp 大小写错误时候的报错图
这里是签名算错的图
这里是ok的图