How to integrate WeChat payment?
Purpose: To help you avoid those rabbit holes and set up WeChat payment on your WeChat mini-program.
Prerequisites:
Basic Knowledge of Node.js
Basic Knowledge of WeChat Mini-program
WeChat Mini-Program Account(Apply here: https://mp.weixin.qq.com/)
WeChat Merchant Account
Important Credentials Needed:
Miniprogram’s App ID
Miniprogram’s App Secret
Merchat ID
Vendor Key(or Merchant Key or Partner Key)
Important Note: Never expose these credential in public repositories. Use environment variables.
In a nutshell:
Overwhelmed? No worries. Let’s break it down.
Get user’s OpenID
On Miniprogram side:
wx.login({
success (res) {
if (res.code) { wx.request({
url: 'http://your-back-end.com/login',
data: {
code: res.code
}
})
} else {
// Handle failed request to Tencent API
}
}
})
On Your Backend Server
router.get('/getOpenID/:code', async (req, res) => { const { code } = req.params; const url = `https://api.weixin.qq.com/sns/jscode2session? appid=${your_miniprogram_app_id}&secret=${your_miniprogram_app_secret}&js_code=${code}&grant_type=authorization_code`; // Use axios, request, or whatever to make a GET request to this endpoint then it should return the OpenID and Session of the user});
Bonus tip: You could use wx.setStorage()
to storage the OpenID and Session of the user.
Place an order on Tencent Server
The easy way:
Download npm module here: https://www.npmjs.com/package/wechat-pay
In your backend writes:
var order = {body: 'Product Title',attach: '{"Stringified":"Object"}',out_trade_no: 'kfc' + (+new Date),total_fee: 10 * 100,spbill_create_ip: req.ip,openid: req.user.openid,trade_type: 'JSAPI'};payment.getBrandWCPayRequestParams(order, function(err, payargs){res.json(payargs);});
At your miniprogram:
Use the payargs
from the backend, use the wx.requestPayment
as such
wx.requestPayment({
timeStamp: '',
nonceStr: '',
package: '',
signType: 'MD5',
paySign: '',
success (res) { },
fail (res) { }
})
The hard way(If you are a curious cat):
In your backend:
- Generate signature
Concatenate all params into string by alphabetically order of the params keys
Add WeChat Payment Key at the end like “&key=your_key_here”
Hash the whole string with MD5 or HMAC-SHA256
Params(Bold params are required):
appid, mch_id, device_info, nonce_str, sign, sign_type, body, detail, attach, out_trade_no, fee_type, total_fee, spbill_create_ip, time_start, time_expire, goods_tag, notify_url, trade_type, product_id, limit_pay, openid
Definitions:
mch_id: Merchat ID / Vendor Key(or Merchant Key or Partner Key)
nonce_str: Random String
sign: Signature
sign_type: MD5 or HMAC-SHA256
body: Product title(Usually the name of the product)
detail: Product Description(Usually the quantity and specs)
attach: Extra data stringified
fee_type: Currency type
total_fee: Payment amount. Note: Fee is one hundredth of the value. Example: total_fee: 1 = 0.01 RMB
spbill_create_ip: IP of your server
goods_tag: Used for WeChat coupons
notify_url: The callback url for Tencent server to notify your server
trade_type: Should be JSAPI. You will deal will other types if you are building native apps
out_trade_no: An unique order identification. Alphanumeric. Limited to 32 characters.
Can include _-|*
2. Send it in XML strings as Form Data
3. Make a POST request to this endpoint: https://api.mch.weixin.qq.com/pay/unifiedorder
4. Use the prepay_id from tencent server and generate the signature on our own server the second time
5. params to put into signature:
appId: appid,
nonceStr: nonceStr,
package: package,
signType: signType,
timeStamp: timeStamp
6. Return the params above with the signature to miniprogram
Setup Callback Url for Payment Result
- We get the result of the payment in notify_url in rawBody in XML format
- Validate if signature matches to prevent fake notification
Using the wechat-pay npm module, you can
var middleware = require('wechat-pay').middleware;app.use('<notifyUrl>', middleware(initConfig).getNotify().done(function(message, req, res, next) {var openid = message.openid;var order_id = message.out_trade_no;var attach = {};try{attach = JSON.parse(message.attach);// Do something on your own server about the successful payment}catch(e){
// If there's error, reply with, if you don't Tencent server will ping you server three more timesres.reply(new Error(e));}res.reply('success');}));
Common Pitfall
The first time that I was doing this, I kept receiving invalid signature
from Tencent server. It made me question my life’s choices for two days.
Then I realized my client has given me the wrong vendor key. Because the signature is comprised of several params, you must make sure every params are correct.
Vendor key is not the App key. Reset the vendor key if you have to.
Beware of the 32 character limits of out_trade_no
Hardcode the total_fee
so you don’t accidentally pay too much for testing
Documents
To test signature: https://pay.weixin.qq.com/wiki/tools/signverify/
Official WeChat Miniprogram Doc
Still confused?
If WeChat development is fresh to you, here’s a free glossary to get you up to speed. 1 Billion of WeChat’s user awaits.