起源
上一期的微信支付初步探索阶段:对微信支付的初步探索(一)
我简单的说到了微信支付的一些东西,这次依旧说说这件事,这个坑暂时还没爬出来….
上次统一下单这一块因为微信支付还没申请下来而搁浅,这次申请下来了,我们来玩一玩吧~
首先第一步:我们这个数组可以精简一下啦,最后是这样:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
$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,将集合M内非空参数值的参数按照参数名ASCII码从小到大排序(字典序),使用URL键值对的格式(即key1=value1&key2=value2…)拼接成字符串stringA。
特别注意以下重要规则:
◆ 参数名ASCII码从小到大排序(字典序);
◆ 如果参数的值为空不参与签名;
◆ 参数名区分大小写;
◆ 验证调用返回或微信主动通知签名时,传送的sign参数不参与签名,将生成的签名与该sign值作校验。
◆ 微信接口可能增加字段,验证签名时必须支持增加的扩展字段
第二步,在stringA最后拼接上key得到stringSignTemp字符串,并对stringSignTemp进行MD5运算,再将得到的字符串所有字符转换为大写,得到sign值signValue。
key设置路径:微信商户平台(pay.weixin.qq.com)–>账户设置–>API安全–>密钥设置
首先明确一点: PHP是全世界最好的语言….
我们利用 ksort() 函数对关联数组按照键名进行升序排序。
调用actionToUrlParams()拼接字符串,
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
ksort($TempArr); $TempStr = $this->actionToUrlParams($TempArr).'&$key=7199F24949FCDCA0A9F18BC2177B38A2'; public function actionToUrlParams($urlObj) { $buff = ""; foreach ($urlObj as $k => $v) { if($k != "sign"){ $buff .= $k . "=" . $v . "&"; } } $buff = trim($buff, "&"); return $buff; } |
注意:这里有一个坑:
在拼接字符串以后,会输出¬…,然而这个字符串会被PHP转义,如文档:http://ask.csdn.net/questions/147899
记住这里千万,不要管,不要管….
血淋淋的教训,其实这里多此一举,还害我一直签名错误…….
接下来:
1 2 3 4 5 6 7 8 9 10 11 12 |
$signValue = strtoupper(MD5($TempSign)); $TempArr['sign'] = $signValue; //把计算出来的签名赋值到统一下单数组 $xmls = $this->actionArrToXml($TempArr); //把统一下单数组转为xml /*数组转xml*/ public function actionArrToXml($arr){ $Tempstr = '<xml>'; foreach ($arr as $k => $v) { $Tempstr .='<'.$k.'>'.$v.'</'.$k.'>'; } $Tempstr .= '</xml>'; return $Tempstr; } |
注意这里也有一个坑….
这时候你会发现生成的xml有问题….如图
这里千万不要惊慌,,,,因为这个字段叫body,在文档里输出被解析了…..
现在开始把我们的xml发送给微信接口获取订单信息
1 |
$Result = https_request('https://api.mch.weixin.qq.com/pay/unifiedorder',$xmls);//使用post 发送xml数据 |
这时候会有各种坑,记住,一定要核对自己传的参数与文档是否一致,注意大小写,
如果一直这样,建议直接到调试页面: 调试页面地址
一点一点把生成好的xml复制到项目里然后对比:
1 |
$xmls = '<xml><appid>'.$TempArr["appid"].'</appid><mch_id>'.$TempArr["mch_id"].'</mch_id><nonce_str>'.$TempArr["nonce_str"].'</nonce_str><body>'.$TempArr["body"].'</body><detail>'.$TempArr["detail"].'</detail><out_trade_no>'.$TempArr["out_trade_no"].'</out_trade_no><total_fee>'.$TempArr["total_fee"].'</total_fee><spbill_create_ip>'.$TempArr["spbill_create_ip"].'</spbill_create_ip><notify_url>'.$TempArr["notify_url"].'</notify_url><trade_type>'.$TempArr["trade_type"].'</trade_type><product_id>'.$TempArr["product_id"].'</product_id><openid>'.$TempArr["openid"].'</openid><sign>'.$TempArr["sign"].'</sign></xml>'; |
下一步,解析xml为数组,取我们需要的数值
1 2 3 4 5 6 7 8 9 10 11 |
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; } |
接下来,把数组里的参数传入到对微信支付的初步探索(一)这里说到的数组….继续下一步算签名…
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'; $jsTicket = $wecaht->getJsTicket($this->actionConfig()['appid']); $string = "jsapi_ticket=$jsTicket&noncestr=$nonceStr×tamp=$timestamp&url=$url"; p($string); $signature = MD5($string); $signPackage = array( "appId" => $package['appid'], "nonceStr" => $package['nonce_str'], "timestamp" => $timestamp, 'package'=>'prepay_id='.$package['prepay_id'], 'signType'=>$signType, 'signature' => $signature, ); return $signPackage; } |
注意这里也有一个坑:
1 2 3 4 5 6 7 8 |
$signPackage = array( "appId" => $package['appid'], "nonceStr" => $package['nonce_str'], "timestamp" => $timestamp, 'package'=>'prepay_id='.$package['prepay_id'], 'signType'=>$signType, 'signature' => $signature, ); |
1 |
这几个参数需要取下单接口返回的数组里面的值 |