那么,就直接开门见山呗。本篇博客根据个人日志记录整理而成。
其实大部分的文档,微信官方开发文档里面都提供了,我们只需要按照其说明严格执行就可以达到目的。
注意,这里只讲述公众号支付相关的情形,其他的基本类似,本人未作深入实践,故此不敢多言。
这次的讲解,主要从四个方面进行说明:
- 相关账户配置
- 后台的搭建
- 前端页面的展示
- 支付流程
账户
首先,肯定是需要一个微信公众号的。公众号的性质需要满足开通商户号和微信支付,并且实际上已经开通好了。这次我用的账号是认证好了的服务号。
进入公众号设置界面,对相关的域名进行配置,本次调试,我使用的域名是 z.hdk4.com,故此在公众的管理页面的 【设置】-【公众号设置】-【功能设置】 中对 业务域名、JS接口安全域名、网页授权域名 全部进行了相应的设置。
至于开发者的添加和公众号密钥和商户号密钥等数据的获取,属于入门级别,这里不再赘述。
要做微信支付,需要事先对 支付授权目录 进行设置,在商户号管理页面就能够找得到,直接进行设置即可。注意这里是 支付目录 的设置,即浏览器访问下的 location.pathname 对应的访问路径,结尾必须以 / 结束且区分大小写。
后台
这一块最为重要也是核心所在,由于只是演示与测验,所以采用了简单粗暴的 express 来作为后台服务器。详情容后再禀。
前端
前端页面相对来说简单一些,在引入微信的官方 js,即 http://res.wx.qq.com/open/js/jweixin-1.2.0.js 之后,调用 WeixinJSBridge 的 API,发起 getBrandWCPayRequest 请求即可。
1 | WeixinJSBridge.invoke('getBrandWCPayRequest', { |
当然,在这里之前,需要先获取用户的 openid。
当然,在获取 openid 之前,还需要获取一下用户的访问 code。
那么,这个访问的 code 如何获取呢?
根据微信开发文档提供的链接 https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421140842,我们先判断链接是否有 code 字段,如果没有则跳转到微信的链接去进行获取。获取到了之后再进行 openid 的获取。文档方面的信息这里不详细展开,直接上代码进行说明吧!
1 | var code = getUrlParam('code') || sessionStorage.code; |
几点说明:
redirect_uri中的state=7是随便写的一个值。window.location.replace用于直接替换,如果不想要替换效果,可以修改为window.location.href = '...'。- 采用
sessionStorage进行数据的缓存。 getUrlParam为提取链接中的querystring。不要管yoda什么的了
前端差不多能说的就这么多了。
支付流程
整个支付流程浓缩起来就是:
- 获取
code - 获取
openid - 开始进行支付操作
- 后台发起预支付订单
- 后台将获取到的预支付信息返回给前端
- 前端尝试唤起微信支付
- 进行支付
- 前端/后台处理支付回调。是的,都进行处理。前端无所谓,后台必须处理,不然微信会发很多次请求。
- 支付完成
- 后续一些相关操作。由于本次只是演示与测验,就不做处理了。
现在来说一下核心的重点,即后台的相关逻辑处理与接口的设计。
后台
相关的库的引入与声明,这里就不赘述了。
/api/getopenid 接口
1 | // 获取 openid |
wFile是日志记录相关操作,可以无视。
该接口是用来获取用户的 openid 的,要求的东西是 code,这个 code 就是上面前端花费一番周折得到的东西。
前端调用方式:
1 | function getOpenId() { |
- 是的,
$就是大名鼎鼎的jQuery。 - 采用了
Promise对象。
/api/unifiedorder 接口
1 | // 获取微信支付的统一下单相关数据 |
getClientIp是获取客户端真实 IP 地址的方法。createNonceStr是生成随机串的方式,非常简单粗暴。out_trade_no是商户自定义的订单号。getUnifiedOrderXml是用来拼接发送给微信支付统一下单接口的数据,要xml格式的,所以就给一个封装。xml2jsparseString是解析xml文件的库。微信支付统一下单接口返回的数据是xml格式的,需要进行相应的解码。getSign是生成签名的方法。
如果不出意外,下单接口会返回一个 xml 数据,然后我们就可以提取到 prepay_id 这个核心的信息了。
/api/wxresponse 接口
1 | // 处理微信支付的回调 |
该接口是用来处理 notify_url 指定的回调链接的相关数据的,本次用的具体值就是 http://z.hdk4.com/api/wxresponse。
如果不对该接口做回应,微信支付会一直发请求,直至系统判定失败。
注意,使用
express进行开发时,会收不到req.body,采用以下方法进行解决即可:
1 | const bodyParser = require('body-parser'); |
签名算法
1 | // 签名算法 |
非常简单粗暴的算法,嗯,如上所示。如果是其他语言,在生成 MD5 值的时候方法可能会有所不同,使用对应的方法即可。
随机字符串方法
1 | function createNonceStr() { |
是的,这一条是滥竽充数的。