微信支付流程记录
最近由于需求用到微信支付功能,由于本人也是第一次开发,也是找了很多资料以及查看文档来理解微信的支付流程,但最后也是云里雾里不知道具体开发步骤是什么,所谓万事开头难在我这用的是淋淋尽致。不够索性最后还是有些启发,所以就先记录备案一下,以免以后用的着的又不知道。
首先我选择的支付是JSAPI支付,主要用于微信公众号支付模式,其他的也没有仔细了解,不过开发流程步骤应该不会差多少,就留以后举一反三吧。
一下是微信支付类型介绍
https://pay.weixin.qq.com/wiki/doc/api/index.html
一、先要申请一个认证的服务公众号,开通微信支付功能
二、通过微信公众平台提供的技术开发文档找到网页开发,着重注意里面微信网页授权和微信JS-SDK这两个文档
后面开发主要也是用到了这两个文档中的信息
三、在开发公众号支付之前的关注你已经申请好的认证的服务号,先做个简单支付页面,如图:
js部分代码
在这个简单页面中需要先引入JSSDK,引入步骤如下
appID:为开通的服务公众号的id
timestap:生成签名的时间戳,不过这里需要注意的是,这里的时间戳应该和下面的signature中签名的时间戳一致
nonceStr:随机字符串,这个按要求随机生成一个16位字符串就OK了
//获取签名的随机串 public static function get_randCode() { $array = array( "A","B","C","D","E","F","G","H","I","G","K","L","M","N","O","P","Q","R","S","T","U","V","W","X","Y","Z", "a","b","c","d","e","f","g","h","i","g","k","l","m","n","o","p","q","r","s","t","u","v","w","x","y","z", "0","1","2","3","4","5","6","7","8","9" ); $tmpStr = ""; for ($i=1; $i <= 16; $i++) { $key = rand(0, count($array)-1); $tmpStr .= $array[$key]; } return $tmpStr; }
signature:签名算法.首先得获取jsapi_ticket
签名需要的参数有:
代码:
最后将$data中的数据传入支付页面就OK了,打开调试功能会弹出:
到这就说明第一步配置成功了。
四、查看微信支付的chooseWxPay接口
也是需要进行参数配置,timestamp和nonceStr这两个参数不用多说
主要是packeage以及paySign这两个参数的配置
打开微信支付开发文档中有个【统一下单】
调用接口:https://api.mch.weixin.qq.com/pay/unifiedorder其中传递的参数有很多,可以查看文档具体的参数,其中有十个左右的参数是必填项。主要有:
公众账号Id | appid |
商户号 | mch_id(这个商户id是在微信商户平台开通微信支付功能后返的id) |
随机字符串 | nonce_str(这个就是前面代码贴出来生成的16位的字符串,ps:好多地方都用到,建议封装调用) |
商品描述 | body(主要就是调起微信支付页面后的描述文字。例:买馍钱) |
商户订单号 | out_trade_no(这个是可以自己随机生成一个订单号。例:E20190509162458011) |
标价金额 |
total_fee(支付金额,需要注意微信支付中1代表的是1分钱,订单总金额,单位为分) |
终端IP | spbill_create_ip(通过$_SERVER获取) |
通知地址 | notify_url(通知的一个回调url地址,自己在项目中指定) |
交易类型 | trade_type(JSAPI -JSAPI支付 NATIVE -Native支付 APP -APP支付 等) |
用户标识 | openid(交易类型为JSAPI时,此参数必传。关于openid可以在用户网页授权中获取) |
签名 | sign(签名快照,到这里是微信支付的第二次签名) |
这些参数是向微信发起支付请求的必须参数,里面还有一些非必须参数,如果在项目需求中用到可以相对应的给加上
前面几个参数都好获取,就是最后一个签名的时候比较麻烦
查看签名算法得知和第一次签名大同小异,就是需要在加上一个参数
最后就可以的到签名(sign)了,以上所有参数都获取了以后,在把它传入微信规定的XML格式内,例:
$xmlTpl = "<xml> <appid><![CDATA[%s]]></appid> <body><![CDATA[%s]]></body> <mch_id><![CDATA[%s]]></mch_id> <nonce_str><![CDATA[%s]]></nonce_str> <notify_url><![CDATA[%s]]></notify_url> <out_trade_no><![CDATA[%s]]></out_trade_no> <spbill_create_ip><![CDATA[%s]]></spbill_create_ip> <total_fee><![CDATA[%s]]></total_fee> <trade_type><![CDATA[%s]]></trade_type> <sign><![CDATA[%s]]></sign> <openid><![CDATA[%s]]></openid> </xml>";
通过sprintf函数建数据渲染到XML上
$post_data =sprintf($xmlTpl,$app_id,$body,$mch_id,$nonce_str,$notify_url,$out_trade_no,$spbill_create_ip,
$total_fee,$trade_type, $openid,$sig);
在利用php中的curl来执行此url(通过post)
$return_data = Wechat_class::https_require($url, 'post', $post_data);
执行成功后会返回如下格式的XML数据
因为prepay_id是我们发起微信支付请求中package参数中必须要传的值,获取后,就可以进行第三次签名了,也就是最后一个签名,这里大家如果忘记了的话,可以看前面【四】中的信息以及下面的备注。
最后需要签名的参数有:appId, timeStamp, nonceStr, package, signType 就多了一个appId.
假设:
$app_id = 2365KUI4568;
$timeStamp = 1569855648;
$nonceStr = 1234567890123456;
$package = 'prepay_id=wx201411104112564485664'; //注意这里得加上【prepay_id=】
$signType = MD5; //签名类型MD5加密
//生成处理签名(ASCII码从小到大排序(字典序)) $stringA = "appId=$app_id&noceStr=$nonceStr&pakeage=$package&signType=$signType&timeStamp=$timeStamp"; $stringSignTemp = $stringA.'&key=申请的商户key值'; $sign = strtoupper(md5($stringSignTemp));
//返回微信支付相关参数 $data = [ 'timestamp' => $timeStamp, 'nonceStr' => $nonceStr, 'package' => $package, 'signType' => $signType, 'paySign' => $sign ];
就是【四】部中前端页面需要发起一个微信请求的的所有参数.到这里基本微信JSAPI支付流程就完了,后面需要完善的就在项目中实际开发遇见的问题在解决吧. 最后我要说的是,在JSAPI支付中需要服务号app_id以及app_secret还有商户id以及key,还有退款需要用到的秘钥都可以先在配置文件中保存好保密。虽然只了解了一种微信支付方式,但还是先记录一下。后面能用到的话在翻出来看看。如果大家能也能用到那就最好。谢谢!