按照惯例,开头总得写点感想
------------------------------------------------------------------
业务流程
这个微信官网说的还是很详细的,还配了图。我还要再说一遍。
用户点击一个支付按钮-->{后台一大推处理}-->用户看到了一个输入密码的界面,包含金额等一些信息-->用户输入密码后出来一个支付成功的页面(这部分流程都是微信自己完成的,我们什么都不用做)-->返回系统自己的页面(总不能让用户一直看着一个支付完成的页面吧。花了钱,正心疼的,赶紧跳转啊~一会后悔了,申请退款怎么整。可怜的工程师还得开发退款功能)
开发流程
发现了这个。nonce ==number used once.恍然大悟的赶脚。
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<xml>
<appid>wxb1427ebebexxxxxx</appid>
<body>XXX费用</body>
<device_info>WEB</device_info>
<mch_id>132186xxxx</mch_id>
<nonce_str>6AED000AF86A084F9CB0264161E29DD3</nonce_str>
<notify_url>https://一个域名/api/wechatPay/jsapiPayNotify</notify_url>
<openid>oo8WUt0taCqjt552htW1vw-xxxxx</openid>
<out_trade_no>1</out_trade_no>
<sign>各种排序+key生成的那个sign</sign>
<total_fee>1</total_fee>
<trade_type>JSAPI</trade_type>
</xml>
<xml>
<return_code><![CDATA[SUCCESS]]></return_code>
<return_msg><![CDATA[OK]]></return_msg>
<appid><![CDATA[wxb1427ebebexxxxxx]]></appid>
<mch_id><![CDATA[132186xxxx]]></mch_id>
<device_info><![CDATA[WEB]]></device_info>
<nonce_str><![CDATA[Hh4LFHUUvtDYtNdp]]></nonce_str>
<sign><![CDATA[079F8A915FD3044F4A17D75F4945E955]]></sign>
<result_code><![CDATA[SUCCESS]]></result_code>
<prepay_id><![CDATA[wx20160617155030d9e6a0e48b0533061255]]></prepay_id>
<trade_type><![CDATA[JSAPI]]></trade_type>
</xml>
我们需要的,就是这货
prepay_id 获取到这货之后,第一步骤已经结束了,可以去喝个茶,吃个冰棍,小庆祝一下。 2、H5调起微信支付的内置JS
nonceStr ==反正我用的跟刚才签名是同一个随机字符串。理论上不用应该也没有关系的,勤快的小伙伴可以试试
NB:生成prepay_id时appid是小写的i,生成paySign时,appId是大写的I
function onBridgeReady(){
WeixinJSBridge.invoke(
'getBrandWCPayRequest', {
"appId" : appId, //公众号名称,由商户传入
"timeStamp":timeStamp, //时间戳,自1970年以来的秒数
"nonceStr" : nonceStr, //随机串
"package" : Package,
"signType" :signType, //微信签名方式:
"paySign" : paySign //微信签名 },
function(res){
if(res.err_msg == "get_brand_wcpay_request:ok" ) {
window.location.replace("index.html");
}
}
);
}
上述代码中的,红色部分,修改成你想去的页面即可。是不是好奇replace是什么鬼。移步这里,看一下:http://www.xuebuyuan.com/2140432.html
4,最后一部分啦。fighting
该部分有以下3小步骤
1)解析传过来的流信息,通过重新签名的方式验证流中包含的信息的正确性。就是判断这个信息到底是不是微信发的
2)return_code和result_code都是SUCCESS的话,处理商户自己的业务逻辑。就是订单的支付状态啊等一些信息。
3)告诉微信,我收到你的返回值了。不用在发了。
关于以上三点的解释。微信官方是这么说的
//支付完成后,微信会把相关支付和用户信息发送到商户设定的通知URL,
//验证签名,并回应微信。
//对后台通知交互时,如果微信收到商户的应答不是成功或超时,微信认为通知失败,
//微信会通过一定的策略(如30分钟共8次)定期重新发起通知,
//尽可能提高通知的成功率,但微信不保证通知最终能成功。 //商户自行增加处理流程,
//例如:更新订单状态
//例如:数据库操作
//例如:推送支付完成信息
还记得我们在第一步生成预支付id(prepay_id时的那个notify_url吗。如果不记得了,请往上翻。如果当时只是随便写了一个,那么这会需要去改一改了。)
一个能访问的到的action.同样地址需要外网能访问的到。没有试ip好不好使。开发这部分功能的时候,运维同学已经配置了测试域名。好开心啊,终于不用在纠结于一些交互配置了。
和支付宝不同,微信返回的是流。和支付宝不同,微信返回的是流。和支付宝不同,微信返回的是流。重要的事情说三遍
解析之后,得到的格式是这样子的
<xml><appid><![CDATA[wxb1427ebebeeaxxxx]]></appid>
<bank_type><![CDATA[CFT]]></bank_type>
<cash_fee><![CDATA[]]></cash_fee>
<device_info><![CDATA[WEB]]></device_info>
<fee_type><![CDATA[CNY]]></fee_type>
<is_subscribe><![CDATA[Y]]></is_subscribe>
<mch_id><![CDATA[132186xxxx]]></mch_id>
<nonce_str><![CDATA[07FC15C9D169EE48573EDD749D25945D]]></nonce_str>
<openid><![CDATA[oo8WUt0taCqjt552htW1vw-xxxxx]]></openid>
<out_trade_no><![CDATA[你的订单编号]]></out_trade_no>
<result_code><![CDATA[SUCCESS]]></result_code>
<return_code><![CDATA[SUCCESS]]></return_code>
<sign><![CDATA[E69940B3EDC437CB5A181210D523806E]]></sign>
<time_end><![CDATA[]]></time_end>
<total_fee>1</total_fee>
<trade_type><![CDATA[JSAPI]]></trade_type>
<transaction_id><![CDATA[400386200120160621763973xxxx]]></transaction_id>
</xml>
==========================================20170726更新====================================
微信目前有鼓励金支付,在支付过程中支付金额大于鼓励金金额既可以使用。如果在支付时使用了鼓励金,则回调的流的xml格式如下
<xml>
<appid><![CDATA[XXXXXX]]></appid>
<bank_type><![CDATA[CFT]]></bank_type>
<cash_fee><![CDATA[1]]></cash_fee>
<coupon_count><![CDATA[1]]></coupon_count>
<coupon_fee>30</coupon_fee>
<coupon_fee_0><![CDATA[30]]></coupon_fee_0>
<coupon_id_0><![CDATA[2000000001082991244]]></coupon_id_0>
<device_info><![CDATA[WEB]]></device_info>
<fee_type><![CDATA[CNY]]></fee_type>
<is_subscribe><![CDATA[Y]]></is_subscribe>
<mch_id><![CDATA[1321867101]]></mch_id>
<nonce_str><![CDATA[D0AC1ED0C5CB9ECBCA3D2496EC1AD984]]></nonce_str>
<openid><![CDATA[oo8WUt0AjI8G9TNb5W3wmGUxVV1U]]></openid>
<out_trade_no><![CDATA[XXXXXX]]></out_trade_no>
<result_code><![CDATA[SUCCESS]]></result_code>
<return_code><![CDATA[SUCCESS]]></return_code>
<sign><![CDATA[9895XXXXX91E1D3F710A3D021147]]></sign>
<time_end><![CDATA[20170726184839]]></time_end>
<total_fee>31</total_fee>
<trade_type><![CDATA[JSAPI]]></trade_type>
<transaction_id><![CDATA[40027220012017072XXX93391176]]></transaction_id>
</xml>
注意上述代码中阴影的4行代码。
微信返回的
coupon_count
coupon_fee>
coupon_fee_0
coupon_id_0
的这4个参数中coupon_fee_0和coupon_id_0,官方给出的参数是coupon_id_$n和coupon_fee_$n,$n为下标,从0开始编号。笔者在处理验签时是将xml转化成了JAVA对象,对于这种动态的参数目前没有什么好的解决方案,目前因为只有_0,所以只定义了一个参数叫做_0,万能的网友在使用的过程中如果有好的解决方案,请不吝赐教。
============================================20170726更新=================================
对以上第一点和第三点做个解释。
再次吐槽一下。微信真的很喜欢用签名啊。整个过程,3遍签名。也是醉了。
1)我们看到上述微信返回的xml中含有很多字段。使用上述xml中,处sign意外的值+key,进行签名。你没有看错。包含result_code和return_code。
微信的官方对于签名有解释。
原谅我真的好久不学语文了。真的没理解这句话,是用微信回调函数中传的参数,进行重新签名。傻傻的,还在想,用第二次签名是的参数进行签名,时间戳怎么办,要不要存在数据库里面。
将获得的签名与xml中的sign对比,如果相同,证明是微信返回的通知。如果不同,你的通知地址可能被黑客破解了。要不要告诉老板呢,告诉老板了,我怎么解决呢。
2)商户逻辑处理,不解释
3)告诉微信,我收到了你的通知,不需要在发送了。
怎么告诉微信呢。我翻遍了微信的文档,也没有找到回复微信通知这个url。
经人指导,再一次的刷新了认知观。用response.
我是这么写的:(20170727修改)
返回参数参照微信官方文档:https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_7
String xml = "<xml> <return_code><![CDATA[SUCCESS]]></return_code><return_msg><![CDATA[OK]]></return_msg></xml>";
response.getWriter().write(xml);
--------------------------------------------------------------
微信公众号支付--JSAPI的开发思路和一下参数的具体解释,全部完成了。
=====20180414更新======
微信的文档目前做的已经很完善,api以及代码demo.具体见:
https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421141115
(各位小伙伴,好好看文档,不会看文档的程序员不是好工程师啊)
还有一个坑:我们在第一步的时候,body传的是英文,如果传中文,直接能用的赶紧感谢一下上苍,返回参数错误的,应该是正常吧。
我的对象和xml转化是用的Java的JAXBContext。很好用的赶脚。赶脚比XMLStream好用。具体写法,会在稍后的代码中,写明。
----------------------我的幽默你不懂-------------------------------------
最后一个问题:开头说了要讲一个笑话。
最近在学英语,一天和同学一起走路。旁边的建筑特别密集。此为背景。
他说,他不喜欢这边的建筑,楼与楼之间距离太密了,像集装箱一样。
然后我问,你知道集装箱的英文怎么说嘛。
朋友一脸的表情,看着我,问我,是什么。
说完,我就后悔了,我也不知道。然后我镇定自若的说,docker.
-------------------------我的幽默你不懂------------------------------------------
--------------------------AD---------------------------------------
下面的二维码是笔者和几个小伙伴一起做得一个技术分享公众号。
目前的文章主要是solr和Java方面,后期会逐渐丰盈起来。
欢迎各位小伙伴关注支持。