# 微信支付接入指南 本文讲述 如何使用 NodeJs 接入微信支付的流程指引与注意事项 ## 准备 在接入之前需要学习与准备一些内容 - 待接入应用的 - 应用ID appid - 商户ID mch_id - APIKEY(于微信商户平台设置与获取) - AppSecret - 微信商户 微信公众 平台内授权业务运行的域名 - 了解微信 `OAuth2.0` 运作流程 - 了解两款能提升开发效率的外部库 - [tenpay][1] - [wechat-oauth][2] 如果你看完了上方的内容但不理解,请下载`PHP DEMO`并运行,了解工作机制. 或通读`微信支付官方文档`. ## 着手接入 ## 获取用户授权 微信OAuth2.0授权登录让微信用户使用微信身份安全登录第三方应用或网站,在微信用户授权登录已接入微信OAuth2.0的第三方应用后,第三方可以获取到用户的接口调用凭证(access_token),通过access_token可以进行微信开放平台授权关系接口调用,从而可实现获取微信用户基本开放信息和帮助用户实现基础开放功能等。 微信OAuth2.0授权登录目前支持authorization_code模式,适用于拥有server端的应用授权。该模式整体流程为: 1. 第三方发起微信授权登录请求,微信用户允许授权第三方应用后,微信会拉起应用或重定向到第三方网站,并且带上授权临时票据code参数; 2. 通过code参数加上AppID和AppSecret等,通过API换取access_token; 3. 通过access_token进行接口调用,获取用户基本数据资源或帮助用户实现基本操作。 获取access_token时序图: ![how-to-get-access_token](https://res.wx.qq.com/op_res/D0wkkHSbtC6VUSHX4WsjP5ssg5mdnEmXO8NGVGF34dxS9N1WCcq6wvquR4K_Hcut) 在你的项目中引入 `wechat-ouath`, 并实例化 ```Javascript const OAuth = require('wechat-oauth'); const oauthClient = new OAuth('appid', 'appecret'); ``` 在你的业务逻辑中生成用户授权过程需要访问的URL, 比如: ```Javascript let url = oauthClient.getAuthorizeURLForWebsite('重定向URL'); ``` 用户访问该条URL后,CODE会通过参数的形式传递至重定向URL中,像是这样的: `redirect_uri?code=CODE&state=STATE` 在业务中自行捕获返回CODE,用于获取 `openid` 以创建订单 ```Javascript oauthClient.getAccessToken('code', function (err, result) { let accessToken = result.data.access_token; let openId = result.data.openid; }); ``` ## 创建订单 当我们获取到 `openId` 后,可以在业务逻辑中创建订单,并发起支付请求了. 首先引入 `tenpay` 并实例化: ```Javascript const tenpay = require('tenpay'); const config = { appid: '公众号ID', mchid: '微信商户号', partnerKey: '微信支付安全密钥', pfx: require('fs').readFileSync('证书文件路径'), notify_url: '支付回调网址', spbill_create_ip: 'IP地址' }; // 方式一 const api = new tenpay(config); //方式二 const api = tenpay.init(config); // 沙盒模式(用于微信支付验收) const sandboxAPI = await tenpay.sandbox(config); ``` Config说明: - `appid` - 公众号ID(必填) - `mchid` - 微信商户号(必填) - `partnerKey` - 微信支付安全密钥(必填, 在微信商户管理界面获取) - `pfx` - 证书文件(选填, 在微信商户管理界面获取) - 当不需要调用依赖证书的API时可不填此参数 - 若业务流程中使用了依赖证书的API则需要在初始化时传入此参数 - `notify_url` - 支付结果通知回调地址(选填) - 可以在初始化的时候传入设为默认值, 不传则需在调用相关API时传入 - 调用相关API时传入新值则使用新值 - `refund_url` - 退款结果通知回调地址(选填) - 可以在初始化的时候传入设为默认值, 不传则使用微信商户后台配置 - 调用相关API时传入新值则使用新值 - `spbill_create_ip` - IP地址(选填) - 可以在初始化的时候传入设为默认值, 不传则默认值为`127.0.0.1` - 调用相关API时传入新值则使用新值 实例化完成后,尝试使用 `统一下单API` 创建一笔订单: ```Javascript const router = express.Router(); router.get('/', async function (req, res, next) { let result = await api.unifiedOrder({ out_trade_no: '商户内部订单号', //应自行维护订单号 body: '商品简单描述', total_fee: 100, openid: '用户openid' }); console.log(result); }); ``` 支付结果会在支付动作结束后返回到 `result` 中 ## 结语 至此,我们已经完成了微信支付的接入. 本文若有未涵盖到的部分,可参见 `微信支付接入` 文档自行查阅所需信息. 作者 [@Allen][3] 2017 年 3月 28日 [1]: https://github.com/befinal/node-tenpay [2]: https://github.com/node-webot/wechat-oauth [3]: https://xxss.ga