Wechat mini program wechat Pay
The official flow chart is as follows:
Wechat mini program wechat Pay official flow chart link
The process I simplified:
- The cloud function is invoked and the data is transferred locally
- The cloud function processes the data and returns five parameters
- The local accepts five parameters to initiate a payment request
- End of the deal
Main code:
// The first step is to initiate an order request locally and transmit the data. This step, some element in your WXML
With this pay function,
// Trigger the cloud function and pass some data
pay: function(){
// Data that needs to be uploaded to the cloud function
let uploadData = {
// The amount to be paid this time, in minutes. Such as selections of 1.80 = 180
"total_fee": "180".// IP address of the client
"spbill_create_ip": "123.123.123.123"
}
// Call the cloud function
wx.cloud.callFunction({
// The name of the cloud function, which I define as Payment
name: "payment".// Data to be uploaded
data: uploadData
}).then(res= > {
// The res is the five parameters returned by the cloud function
// Initiate payment with wx.requestPayment
wx.requestPayment({
timeStamp: res.result.data.timeStamp,
nonceStr: res.result.data.nonceStr,
package: res.result.data.package,
signType: res.result.data.signType,
paySign: res.result.data.paySign,
success: res= > {
// The payment was successful
},
fail: err= > {
// Payment failed}})}Copy the code
That’s all the code on the local side, then we just need to get the cloud function code done.
The content of the cloud function is:
- Call applets login API -> Openid
- Generate merchant order
- Call uniform order API -> prepay_id
- The combined data is signed again, returning 5 parameters
The cloud function I created is called Payment, and the structure of the cloud function should be
payment
|__index.js
|__package.json
Copy the code
## Detailed practices for each step
1. Call applets to log in API -> Openid
The purpose of this step is to get the user’s Openid
Add the following code to the index.js of the cloud function
// Get the cloud instance
const cloud = require('wx-server-sdk')
// Cloud initialization
cloud.init()
// Get wechat call context information, including Openid, Appid, etc
const wxContext = cloud.getWXContext()
// Get user openID
const openid = wxContext.OPENID
Copy the code
Here we have achieved our first goal.
2. Generate merchant orders
Wechat Pay development document – unified order
The purpose of this step is to generate an order that calls the Payment unified order API. According to official documents, we need the following data:
-
Appid (applets ID)
-
Openid (User OpenID)
-
McH_id (Merchant number)
-
Nonce_str (random string)
-
Product Description
-
Out_trade_no (Merchant order Number)
-
Total_fee
-
Spbill_create_ip (terminal IP address)
-
Notify_url (notification address)
-
Trade_type (type of trade)
-
Key (key)
-
Sign your name
We’ll take it one at a time.
1. appid
After the administrator enters the public platform and logs in with the mini program account, click “Settings” in the menu on the left and check the AppID of the mini program under “Development Settings”.
The sample value wxd678efh567hg6787
Add the following code to the index.js of the cloud function:
const appid='wxwxd678efh567hg6787'
Copy the code
2. openid
The first step has been achieved.
The sample value oUpF8uMuAJO_M2pxb1Q9zNjWeS6o
3. mch_id
Login wechat payment merchant platform pay.weixin.qq.com, click the upper “Account Center”, in the “personal information” “login account” is McH_id.
Example is worth 1230000109
Add the following code to the index.js of the cloud function:
const mch_id='1230000109'
Copy the code
4. nonce_str
The value is a random number with a maximum of 32 bits. You can write your own function.
5 k8264iltkch16cq2502si8znmtm67vs sample values
I create a new JS file (random.js) in the cloud function to hold the function, and the structure of the cloud function is as follows
payment
|__index.js
|__package.json
|__random.js
Copy the code
Where the content of random.js is:
function random(){
var result = ' '
const wordList = ['a'.'b'.'c'.'d'.'e'.'f'.'g'.'h'.'i'.'j'.'k'.'l'.'m'.'n'.'o'.'p'.'q'.'r'.'s'.'t'.'u'.'v'.'w'.'x'.'y'.'z'.'1'.'2'.'3'.'4'.'5'.'6'.'7'.'8'.'9'.'0']
for(let i=0; i<31; i++){ result += wordList[Math.round(Math.random()*36)]}return result
}
module.exports = random()
Copy the code
Then add the following code to the cloud function index.js:
const random = require("random.js")
Copy the code
5. body
Format: Vendor name – Vendor category
Example value Tencent – games
Add the following code to the cloud function index.js:
const body = "Tencent - Games"
Copy the code
6. out_trade_no
Merchants system internal order number to 32 characters, only Numbers, upper and lower case letters _ – | * and only under the same merchant number. It is recommended to use the current time + product number.
Example is worth 20150806125346
Add the following code to the exports.main function in the cloud function index.js:
// I'm only using the present time here. As long as the number is not repeated.
const out_trade_no = Date.parse(new Date()).toString()
Copy the code
7. total_fee
The total amount of the order, in minutes. For example, if the current payment is ¥6.80, the total_fee is 680.
Example is worth 88
We're going to use the value that we uploaded, so let's just ignore it
8. spbill_create_ip
The IP address can be IPV4 or IPV6. The IP of the machine that invokes the wechat Pay API.
The sample value 123.12.12.123
We're going to use the value that we uploaded, so let's just ignore it
9. notify_url
Callback address for receiving the notification of wechat payment result asynchronously. The notification URL must be accessible to the external network and cannot carry parameters. You can fill in the URL of your own server here.
The sample value http://www.weixin.qq.com/wxpay/pay.php
Add the following code to the cloud function index.js:
// Just fill in the server. I have no problems with it
const notify_url = 'http://www.weixin.qq.com/wxpay/pay.php'
Copy the code
10. trade_type
Trade_type of applets is JSAPI.
The sample value JSAPI
Add the following code to the cloud function index.js:
const trade_type = 'JSAPI'
Copy the code
11. key
Key Key for merchant platform. It is set by you. Key setting path: wechat merchant platform (pay.weixin.qq.com)–> Account setting –>API security –> key setting.
1 a79a4d60de6718e8e5b326e338ae533 sample values
Add the following code to the cloud function index.js:
const key = '1a79a4d60de6718e8e5b326e338ae533'
Copy the code
12. sign
All the above information except the key is concatenated into a string according to the ASCII characters of the parameter name from large to small, split with &, and put the key at the end.
Example string values:
Appid = wxd678efh567hg6787 & body = WeChat - game & MCH_ id = 1230000109 & nonce_str k8264iltkch16cq2502si8znmtm6 = 5 7VS¬ify_url=http://www.weixin.qq.com/wxpay/pay.php& openid=oUpF8uMuAJO_M2pxb1Q9zNjWeS6o&out_trade_no=2015080 6125346 & spbill_create_ip = 123.12.12.123 & total_fee = 88 & trad e_type a79a4d60de6718e8e5b326e338ae533 = JSAPI&key = 1Copy the code
The UPPERcase MD5 code for this string is sign. Since the above total_fee and spbill_create_IP have not been processed, this data will be processed below.
MD5 code C380BEC2BFD727A4B6845133519F3AD6 sample values
At this point your cloud function structure should look like:
payment
|__index.js
|__package.json
|__random.js
Copy the code
The contents of index.js should be:
// Cloud function entry file
const cloud = require('wx-server-sdk')
cloud.init()
const openid = cloud.getWXContext().OPENID
const appid = 'wxwxd678efh567hg6787'
const mch_id = '1230000109'
const random = require('random.js')
const body = "Tencent - Games"
const notify_url = 'http://www.weixin.qq.com/wxpay/pay.php'
const trade_type = 'JSAPI'
const key = '1a79a4d60de6718e8e5b326e338ae533'
// Cloud function entry function
exports.main = async (event, content) => {
const out_trade_no = Date.parse(new Date()).toString()
}
Copy the code
Next we deal with total_fee and spbill_create_IP, which were not dealt with above, and sign. Where total_fee and spbill_create_IP are uploaded by the client, these two data are in the parameter event of the entry function of the cloud function, so we add the following code to the entry function of the cloud function
const total_fee = event.total_fee
const spbill_create_ip = event.spbill_create_ip
Copy the code
Finally, we need to deal with sign and add the following code to the cloud function entry function as mentioned in 12.sign
let stringA = `appid=${appid}&body=${body}&
mch_id=${mch_id}&nonce_str=${random}&
notify_url=${notify_url}&openid=${openid}&
out_trade_no=${out_trade_no}&
spbill_create_ip=${spbill_create_ip}&
total_fee=${total_fee}&trade_type=${trade_type}&
key=1a79a4d60de6718e8e5b326e338ae533`
Copy the code
We now need to encrypt this string with MD5, so we need to install an NPM package to do this. Right click on the cloud function Pyament, select “Open on Terminal” and enter the following command:
npm install --save crypto
Copy the code
Add the following code to the cloud data entry file
const crypto = require("crypto")
Copy the code
So we’ve successfully introduced crypto into our cloud functions. Then we need to use it in the cloud function entry function to MD5 encrypt the stringA we just did. So let stringA =… Add the following code to this line
var sign = crypto.createHash('md5').update(stringA).digest('hex').toUpperCase()
Copy the code
The above 11 information except key is all the data we need to call the unified order API
We now need to convert this data into XML format, for example:
<xml>
<appid>wxd930ea5d5a258f4f</appid>
<mch_id>10000100</mch_id>
<device_info>1000</device_info>
<body>test</body>
<nonce_str>ibuaiVcKdpRxkhJA</nonce_str>
<sign>9A0A8659F005D6984697E2CA0A9CF3B7</sign>.</xml>
Copy the code
Create a new requestData.js function in the cloud and write the following function to convert the data to XML
function requestData(appid, mch_id, nonce_str, sign, body, out_trade_no, total_fee, spbill_create_ip, notify_url, trade_type, openid){
let data = "<xml>"
data += "<appid>"+appid+"</appid>"
data += "<mch_id>"+mch_id+"</mch_id>"
data += "<nonce_str>"+nonce_str+"</nonce_str>"
data += "<sign>"+sign+"</sign>"
data += "<body>"+body+"</body>"
data += "<out_trade_no>"+out_trade_no+"</out_trade_no>"
data += "<total_fee>"+total_fee+"</total_fee>"
data += "<spbill_create_ip>"+spbill_create_ip+"</spbill_create_ip>"
data += "<notify_url>"+notify_url+"</notify_url>"
data += "<trade_type>"+trade_type+"</trade_type>"
data += "<openid>"+openid+"</openid>"
data += "</xml>"
return data
}
module.exports = requestData
Copy the code
At this point, the structure of the cloud function is
Payment | index. Js | __package. Json | __package - lock. Json / / by NPM install the file | __random. Js | __requestData. JsCopy the code
We need to import the requestData.js file into our project. Add the following code to the cloud function entry file
const requestData = require("requestData.js")
Copy the code
Now we can generate an order that calls the Payment unified order API, and the dataBody is the order.
let dataBody = reqData(
appid,
mch_id,
random,
sign,
body,
out_trade_no,
total_fee,
spbill_create_ip,
notify_url,
trade_type,
openid
)
Copy the code
At this point we’ve achieved our goal for part two.
3. Call unified order API -> prepay_id
The official documentation
We need to provide links to the official https://api.mch.weixin.qq.com/pay/unifiedorder launched a unified order, so we need a NPM package here to help us to finish the request requests, and due to a request after the return value is the XML format, So we also need an NPM package to help us parse XML format files. So right click on the cloud payment function, select “Open on Terminal” and type the following command:
npm install --save request
npm install --save xmlreader
Copy the code
Introduce the above two packages in the cloud function entry file:
const request = require("request")
const xmlreader = require("xmlreader")
Copy the code
We can then make a request to the unified single API in the cloud function entry function. Since the request is an asynchronous request, we need to return a Promise.
return new Promise(reslove= > {
request({
// The url of the official unified order API
url: 'https://api.mch.weixin.qq.com/pay/unifiedorder'.// Request method, post
method: "POST".// The order that needs to be sent is the dataBody we just generated
body: dataBody
}, body => {
// Body is the data we received, and we need to get the prepay_id
// Parse the body with xmlReader to get the prepay_id
xmlreader.read(body, res => {
// At this point we have completed the purpose of step 3
let prepay_id = res.xml.prepay_id.text()
}
}
}
Copy the code
Step 3 Goal completion
4. Sign the combined data again and return five parameters
Wx.requestpayment () requires five parameters
- timeStamp
- nonceStr
- package
- signType
- paySign
TimeStamp is the timeStamp and can be obtained by date.parse (new Date()).tostring (). NonceStr is a random string that can be retrieved by our random function. Package is the prepay_id obtained in the previous step, signType is the signature type, and MD5 is selected. So now we are left with paySign unknown, and the method to get paySign is
paySign = MD5(appId=wxd678efh567hg6787&nonceStr=5K826
4ILTKCH16CQ2502SI8ZNMTM67VS&package=prepay_id=wx20170
33010242291fcfe0db70013231072&signType=MD5&timeStamp=
1490840662&key=qazwsxedcrfvtgbyhnujmikolp111111) = 22D
9B4E54AB1950F51E0649E8810ACD6
Copy the code
So let’s pick up where we left off
return new Promise(reslove= > {
request({
url: 'https://api.mch.weixin.qq.com/pay/unifiedorder'.method: "POST".body: dataBody
}, body => {
xmlreader.read(body, res => {
let prepay_id = res.xml.prepay_id.text()
let timeStamp = Date.parse(new Date()).toString()
let str = `appId=${appid}&nonceStr=${random}&package=prepay_id=${prepay_id}&signType=MD5&timeStamp=${timeStamp}&key=1a79a4d60de6718e8e5b326e338ae533`
let paySign = crypto.createHash('md5').update(str).digest('hex')
// Return the five arguments above
reslove({
data: {
timeStamp: timeStamp,
nonceStr: random,
package: `prepay_id=${prepay_id}`.signType: 'MD5'.paySign: paySign
}
})
}
}
}
Copy the code
At this point, the wechat mini program payment process ends.
At this point, the cloud function structure is:
payment
|__index.js
|__package.json
|__package-lock.json
|__random.js
|__requestData.js
Copy the code
index.js:
// Cloud function entry file
const cloud = require('wx-server-sdk')
cloud.init()
const openid = cloud.getWXContext().OPENID
const appid = 'wxwxd678efh567hg6787'
const mch_id = '1230000109'
const random = require('random.js')
const body = "Tencent - Games"
const notify_url = 'http://www.weixin.qq.com/wxpay/pay.php'
const trade_type = 'JSAPI'
const key = '1a79a4d60de6718e8e5b326e338ae533'
const crypto = require("crypto")
const requestData = require("requestData")
const request = require("request")
const xmlreader = require("xmlreader")
// Cloud function entry function
exports.main = async (event, content) => {
const out_trade_no = Date.parse(new Date()).toString()
const total_fee = event.total_fee
const spbill_create_ip = event.spbill_create_ip
let stringA = `appid=${appid}&body=${body}&mch_id=${mch_id}&nonce_str=${random}¬ify_url=${notify_url}&openid=${openid}&out_trade_no=${out_trade_no}&spbill_create_ip=${spbill_create_ip}&total_fee=${total_fee}&trade_type=${trade_type}&key=1a79a4d60de6718e8e5b326e338ae533`
var sign = crypto.createHash('md5').update(stringA).digest('hex').toUpperCase()
let dataBody = reqData(
appid,
mch_id,
random,
sign,
body,
out_trade_no,
total_fee,
spbill_create_ip,
notify_url,
trade_type,
openid
)
return new Promise(reslove= > {
request({
url: 'https://api.mch.weixin.qq.com/pay/unifiedorder'.method: "POST".body: dataBody
}, body => {
xmlreader.read(body, res => {
let prepay_id = res.xml.prepay_id.text()
let timeStamp = Date.parse(new Date()).toString()
let str = `appId=${appid}&nonceStr=${random}&package=prepay_id=${prepay_id}&signType=MD5&timeStamp=${timeStamp}&key=1a79a4d60de6718e8e5b326e338ae533`
let paySign = crypto.createHash('md5').update(str).digest('hex')
// Return the five arguments above
reslove({
data: {
timeStamp: timeStamp,
nonceStr: random,
package: `prepay_id=${prepay_id}`.signType: 'MD5'.paySign: paySign
}
})
}
}
}
Copy the code
random.js:
function random(){
var result = ' '
const wordList = ['a'.'b'.'c'.'d'.'e'.'f'.'g'.'h'.'i'.'j'.'k'.'l'.'m'.'n'.'o'.'p'.'q'.'r'.'s'.'t'.'u'.'v'.'w'.'x'.'y'.'z'.'1'.'2'.'3'.'4'.'5'.'6'.'7'.'8'.'9'.'0']
for(let i=0; i<31; i++){ result += wordList[Math.round(Math.random()*36)]}return result
}
module.exports = random()
Copy the code
requestData.js:
function requestData(appid, mch_id, nonce_str, sign, body, out_trade_no, total_fee, spbill_create_ip, notify_url, trade_type, openid){
let data = "<xml>"
data += "<appid>"+appid+"</appid>"
data += "<mch_id>"+mch_id+"</mch_id>"
data += "<nonce_str>"+nonce_str+"</nonce_str>"
data += "<sign>"+sign+"</sign>"
data += "<body>"+body+"</body>"
data += "<out_trade_no>"+out_trade_no+"</out_trade_no>"
data += "<total_fee>"+total_fee+"</total_fee>"
data += "<spbill_create_ip>"+spbill_create_ip+"</spbill_create_ip>"
data += "<notify_url>"+notify_url+"</notify_url>"
data += "<trade_type>"+trade_type+"</trade_type>"
data += "<openid>"+openid+"</openid>"
data += "</xml>"
return data
}
module.exports = requestData
Copy the code