搜索
首页微信小程序微信开发微信公众号支付开发全过程

微信公众号支付开发全过程

Feb 24, 2017 pm 04:38 PM
微信公众号

业务流程

这个微信官网说的还是很详细的,还配了图。我还要再说一遍。

用户点击一个支付按钮-->{后台一大推处理}-->用户看到了一个输入密码的界面,包含金额等一些信息-->用户输入密码后出来一个支付成功的页面(这部分流程都是微信自己完成的,我们什么都不用做)-->返回系统自己的页面(总不能让用户一直看着一个支付完成的页面吧。花了钱,正心疼的,赶紧跳转啊~一会后悔了,申请退款怎么整。可怜的工程师还得开发退款功能)

开发流程

1)获取用户授权(这个做不做没有啥关系,反正我还没做呢)

2)调用统一下单接口获取预支付id

3)H5调起微信支付的内置JS

4)支付完成后,微信回调URL的处理

 

看着大段的文字,是不是很不爽。忘记了在哪里看到的一句话。One picture instead  thousands of words. (图中红色部分是我们需要做的。好像也没有多少

微信公众号支付开发全过程

本文最主要的部分开始了(想直接看代码,贴上代码,你也不一定能看懂,不是说代码难,各种分离,各种类,不直接。看懂了,不一定能调试通。最后一个签名错误,或者$get_brand_wcpay_request:fail.$key0 还是得回来乖乖的对参数。)最近学习英语有点魔怔了。各种插入语。不懂什么梗的,可略过。朋友一直说我的笑点和别人不一样。文后会讲个笑话。

1、生成统一下单接口,获取prepay_id.

需要的参数 ==名称==从哪里找到他们:

微信官方给了个参数的详细说明。https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_1 部分参数,仍然不知道哪里找的小伙伴们请继续向下看

appid ==应用ID==登陆微信公众号后台-开发-基本配置

mch_id == 微信支付商户号==登陆微信支付后台,即可看到

device_info==设备号==终端设备号(门店号或收银设备ID),注意:PC网页或公众号内支付请传"WEB"

body==商品描述==商品或支付单简要描述(不知道是什么鬼,没关系,先随便传个字符串,随便的传个英文的字符串。你会为你这个时候的英明决定打个满分。如果是中文,可能会遇到毫无头绪的签名错误,严重者开始怀疑人生)

trade_type==交易类型==取值如下:JSAPI,NATIVE,APP。我们这里使用的JSAPI。标题已经说了,是微信公众号支付。

      ps:JSAPI--公众号支付、NATIVE--原生扫码支付、APP--app支付,统一下单接口trade_type的传参可参考这里。MICROPAY--刷卡支付,刷卡支付有单独的支付接口,不调用统一下单接口

nonce_str==随机字符串==随机字符串,不长于32位

       ps:小伙伴们可能会对nonce这个命名,很诧异,微信team的人,都是逗必吗~。查了一下百科,随机数也用nonce表示。瞬间伤害满满的。(好奇的宝宝可用剑桥词典查一下nonce的意思)。在我的不懈努力下,

      发现了这个。nonce ==number used once.恍然大悟的赶脚。

 

notify_url==通知地址==接收微信支付异步通知回调地址,通知url必须为直接可访问的url,不能携带参数。(这,起个什么名字好呢。随便起吧,反正一时半会也用不到)

out_trade_no==商户订单号==商户系统内部的订单号,32个字符内、可包含字母(每次看完微信的官方解释就更迷茫了,有木有。没关系,我就传个1咋了。)

total_fee==总金额==订单总金额,单位为分(为了公司的项目测试,还得自己掏银子,1分钱也是钱啊。ps:这个时候总会想起,一个同学说过,苍蝇腿也是肉啊)

openid==用户标识==trade_type=JSAPI,此参数必传,用户在商户appid下的唯一标识。

还有最最重要的一个,重要的角色总要在最后登场。

sign==签名==官方给的签名算法。https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=4_3。没有看懂,看不太懂,你觉得你看懂了,没关系,不遇到几次签名错误,好意思说自己做过微信支付开发吗。

说道这个sign还有一个更重要的参数。参与签名的参数。反正我是找了好久才找到。(公司运营申请的微信支付,当我找她要的时候,他的表情是这样子的。

key==key设置路径:微信商户平台(pay.weixin.qq.com)-->账户设置-->API安全-->密钥设置

在这里:微信公众号支付开发全过程

网上有说怎么找得。我也懒得去找。直接自己想了一个字符串,然后用MD5加密成32位的字符串,重新设置的。

生成sign签名的时候,要用到这个key值,所以,要保存好。

我看别人生成签名(sign)用了很多,反正我就用了上面给出的那些参数生成的sign.(这个上面指的是我的博客上面,不是微信上面。为了减少误解,贴出我生成sign签名的参数)

我生成sign签名的参数

微信公众号支付开发全过程

 

准备好以上参数之后,封装成XML

格式如下:

b7ae353f057462cf9dd083fe02345d7cb2a0af5a8fd26276da50279a1c63a57a
    b35a05cb1ea078bd77ebc36af577bfa9wxb1427ebebexxxxxx618c20c752a51d5003a5f63018ecb993
    6c04bd5ca3fcae76e30b72ad730ca86dXXX费用36cc49f0c466276486e50c850b7e4956
    34f8176ce4801a0fd1e40b6445b4db38WEB3dc42df156e08b846423b5664041ab64
    488025e54d3b0087ed2268660391b5d1132186xxxx68cff30bbb3022de50baa2f7911d4b25
    7d087b210a914686ed7d02a99d8df2466AED000AF86A084F9CB0264161E29DD323311d44d21e3ea9c6e0b1cc64c4a4ae
    fc2429a6d281024ef5e3eca4c37fd84bhttps://一个域名/api/wechatPay/jsapiPayNotify6b22c59d79c03a67ddb53b1e97c93f3a
    428f7676342f817a7335ade4419b8174oo8WUt0taCqjt552htW1vw-xxxxx13929d82925f73faaec36c4064b5dc66
    4260b01e695c3bf521f7a6f84ca47a671b50cd0757935d06fa1a3cdf5b1790d7b
    737605e9dbc71d9303a969460f22a021各种排序+key生成的那个sign9c8a5870cfe66fa3121cb674ab7d544f
    910bfc20c55caab9a3739b1ef27a7d4c16d47c54a8109c5cd37324e34d797c6c4
    f8b5038c5a41e503887262e36081057fJSAPIdaa0377c4dc7db58b457f727d31b200521118965b89073f60271ef4a3b5d3c58

调用微信的统一下单地址:https://api.mch.weixin.qq.com/pay/unifiedorder

 见证奇迹的时刻。如果以上参数都神奇的对了,那么会收到微信返回的XML字符串,格式如下

b2a0af5a8fd26276da50279a1c63a57a
  4a19504e0a69cd131aa42eaf309c5046b9d5fd5cfd9884ef4df135f29c239180bddfb5e9cbd6bb8c512bb99621b3671d
  f16c3d567c0a38e370f47bbcf068db5a979fa7f9086ec56d26b97ee3da1958c8440a851afc4e996b6e6f596aa1bd9ef7
  b35a05cb1ea078bd77ebc36af577bfa926f6dece7ff69760d00be54bae9d4480618c20c752a51d5003a5f63018ecb993
  488025e54d3b0087ed2268660391b5d1d3a9a65dbb08243dddbbad0de936a6fa68cff30bbb3022de50baa2f7911d4b25
  34f8176ce4801a0fd1e40b6445b4db38498be78773fb872b02a888a0a769be0d3dc42df156e08b846423b5664041ab64
  7d087b210a914686ed7d02a99d8df246f34b05a41ebeb7da2397f2115131a8da23311d44d21e3ea9c6e0b1cc64c4a4ae
  737605e9dbc71d9303a969460f22a021c37038f93d2b6f004ab96a6acdabbf359c8a5870cfe66fa3121cb674ab7d544f
  ce4477626112385980d6b86c03bc4bccb9d5fd5cfd9884ef4df135f29c239180e147b1f0e9972126e2046c6af38efd62
  88a638634f96c4d5385af75458953c577542d56d1ff8e591f3bf9a1b24cc2e316688e7ad0e17c5b2c6aa450a6c842cf4
  f8b5038c5a41e503887262e36081057fc62bf80e99a847cb8ced7ba882750dbddaa0377c4dc7db58b457f727d31b200521118965b89073f60271ef4a3b5d3c58


我们需要的,就是这货

prepay_id

获取到这货之后,第一步骤已经结束了,可以去喝个茶,吃个冰棍,小庆祝一下。

2、H5调起微信支付的内置JS

 后台传回前台的参数中,应包含以下几项:

appId==这个是不变的==永远不变

timeStamp==时间戳==规则:https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=4_2。看完仍是一脸迷茫的,没关系,我们有工具类。谁知道呢,直接调用就好了 

nonceStr ==反正我用的跟刚才签名是同一个随机字符串。理论上不用应该也没有关系的,勤快的小伙伴可以试试

package==订单详情扩展字符串==统一下单接口返回的prepay_id参数值,提交格式如:prepay_id=***(你猜对了。刚才我们费那么大力气,获得到的prepay_id就是在这里用的。第一次使用的时候,一直拿订单ID去请求,然后微信给我的信息就是请求参数错误,缺少参数$key0$.不要告诉我,只有我一个人。)

signType==签名方式==签名算法,暂支持MD5

paySign==签名==这个签名,要重新生成,在后台。使用如上4个参数+一个key(永远不变)。(我生成签名的时间戳和传回给前台的时间戳就是timeStamp是同一个。不一样行不行,木有验证)

生成paySign的代码

微信公众号支付开发全过程

NB:生成prepay_id时appid是小写的i,生成paySign时,appId是大写的I

到此为止如果一切顺利,你会看到这样子的一个页面。

但是如果,你没有看到这个。而是提示,目录未授权,或者测试账号未在白名单中,我觉得,这才是这篇博客的正确打开方式呢。

微信公众号后台,微信支付,开发配置中有一个支付授权目录,测试授权目录,

 支付授权目录:开发时,先放一放。(邓小平爷爷在对待中日关系时曾经说过,我们解决不了的问题,先放一放。)

测试授权目录:我们要填写的就是这个了。要一个外网能访问到的地址。ip也可以(亲测可以的)。如果你的ip,外网不能访问,找运维同学解决。建议,配置一个测试用的外网可访问的域名。

测试白名单:这个不解释

微信公众号支付开发全过程

输入密码,然后,就会看到这样子的结果。(这也不需要我们做什么了)

微信公众号支付开发全过程

 

好激动啊,赶紧去吃点东西,抑制一下,内心的激动。

剩下的,我们还有两件事情要去做。先说简单的。

3、支付成功之后跳转回自己的系统的某个页面

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.php.cn/

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[1]]></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[20160621134204]]></time_end>
<total_fee>1</total_fee>
<trade_type><![CDATA[JSAPI]]></trade_type>
<transaction_id><![CDATA[400386200120160621763973xxxx]]></transaction_id>
</xml>

对以上第一点和第三点做个解释。

再次吐槽一下。微信真的很喜欢用签名啊。整个过程,3遍签名。也是醉了。

1)我们看到上述微信返回的xml中含有很多字段。使用上述xml中,处sign意外的值+key,进行签名。你没有看错。包含result_code和return_code。

微信的官方对于签名有解释。

微信公众号支付开发全过程

原谅我真的好久不学语文了。真的没理解这句话,是用微信回调函数中传的参数,进行重新签名。傻傻的,还在想,用第二次签名是的参数进行签名,时间戳怎么办,要不要存在数据库里面。

将获得的签名与xml中的sign对比,如果相同,证明是微信返回的通知。如果不同,你的通知地址可能被黑客破解了。要不要告诉老板呢,告诉老板了,我怎么解决呢。

 

2)商户逻辑处理,不解释

3)告诉微信,我收到了你的通知,不需要在发送了。

怎么告诉微信呢。我翻遍了微信的文档,也没有找到回复微信通知这个url。

经人知道,再一次的刷新了认知观。用response.

我是这么写的


 response.getWriter().write(xml);


这个xml就是微信给你的那个流转化的字符串。

xml中的return_code要是SUCCESS或者FAIL

别问我怎么知道的。官方的demo里面写的

if($notify->checkSign() == FALSE){
        $notify->setReturnParameter("return_code","FAIL");//返回状态码
        $notify->setReturnParameter("return_msg","签名失败");//返回信息
    }else{
        $notify->setReturnParameter("return_code","SUCCESS");//设置返回码
    }
    $returnXml = $notify->returnXml();

按照这个写法,返回的数据。在没有收到微信的通知。

之前在测试的时候,返回字符串之后,在没有收到微信的通知,这两天偶然查日志,发现,微信在一直的,通知,不一定是8次。从打印的日志看

有4次,6次。突然,好晕啊。有明白的朋友,还请多多指教

--------------------------------------------------------------

微信公众号支付--JSAPI的开发思路和一下参数的具体解释,全部完成了。具体代码。等我从公司项目里面抽出来。在整理。

还有一个坑:我们在第一步的时候,body传的是英文,如果传中文,直接能用的赶紧感谢一下上苍,返回参数错误的,应该是正常吧。

我的对象和xml转化是用的Java的JAXBContext。很好用的赶脚。赶脚比XMLStream好用。

更多微信公众号支付开发全过程相关文章请关注PHP中文网!

声明
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

热AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover

AI Clothes Remover

用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool

Undress AI Tool

免费脱衣服图片

Clothoff.io

Clothoff.io

AI脱衣机

Video Face Swap

Video Face Swap

使用我们完全免费的人工智能换脸工具轻松在任何视频中换脸!

热工具

SublimeText3汉化版

SublimeText3汉化版

中文版,非常好用

VSCode Windows 64位 下载

VSCode Windows 64位 下载

微软推出的免费、功能强大的一款IDE编辑器

Dreamweaver CS6

Dreamweaver CS6

视觉化网页开发工具

Dreamweaver Mac版

Dreamweaver Mac版

视觉化网页开发工具

SublimeText3 Linux新版

SublimeText3 Linux新版

SublimeText3 Linux最新版