這里為大家介紹微信用戶使用小程序進(jìn)行微信支付到微信商家接收微信支付的過程介紹,微信支付是如何實(shí)現(xiàn)支付功能的。
用 thinkjs 封裝了個(gè)小程序支付的 Service 在這里記錄一下,順便梳理一下小程序支付的流程和思路。首先,先把官網(wǎng)的流程圖放上來,然后按照?qǐng)D一步步的來。
第一步:用戶請(qǐng)求開發(fā)者后臺(tái),發(fā)起下單請(qǐng)求
第二步:開發(fā)者查找一下數(shù)據(jù)庫(kù)或者緩存里是否有 openid 和 session_key
第三步:開發(fā)者服務(wù)器請(qǐng)求統(tǒng)一下單 API ,帶上要求的參數(shù):
appid mch_id nonce_str sign body out_trade_no total_fee spbill_create_ip
nonce_str 獲取隨機(jī)字符串:
/* * 功能: 返回32位隨機(jī)字符串 * create by tiankai on 2018-06-25 15:39 */ getNonceStr(){ let char = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'; let len = 32; let result = ''; for(let i = 0; i < len; i++){ let randomNum = Math.floor(Math.random()*char.length); result += char[randomNum]; } return result; }
/* * 功能:sign 參數(shù)簽名 * create by tiankai on 2018-06-26 12:00 */ async makeSign(params, key){ // 生成簽名 sign let strOrderArr = Object.keys(params).sort(); let stringA = ""; strOrderArr.map(val =>{ //如果參數(shù)值為空,或者驗(yàn)證返回的 sign 不參與簽名 if( think.isNullOrUndefined(params[val]) || val === 'sign' || params[val].length === 0 ) return; stringA += val + "=" + params[val] + "&"; }); let stringSignTemp = stringA + "key=" + key; let sign = think.md5(stringSignTemp).toUpperCase(); return sign; }
得到這幾個(gè)參數(shù)就開始發(fā)起請(qǐng)求統(tǒng)一下單 API 了,這里需要注意的是,請(qǐng)求參數(shù)應(yīng)該以 xml 的形式傳送過去,這里借助一個(gè)工具 xml2js 把對(duì)象轉(zhuǎn)換為 xml,也可以把 xml 轉(zhuǎn)換為 對(duì)象、json。
安裝 xml2js
npm i xml2js
使用 xml2js
const xml2js = require('xml2js'); //xml->json //xml2js默認(rèn)會(huì)把子子節(jié)點(diǎn)的值變?yōu)橐粋€(gè)數(shù)組, explicitArray設(shè)置為false var xmlParser = new xml2js.Parser({explicitArray : false, ignoreAttrs : true}) //json->xml var jsonBuilder = new xml2js.Builder();
請(qǐng)求參數(shù)轉(zhuǎn)換為 xml
/* * 功能:獲取統(tǒng)一下單 API 請(qǐng)求XML參數(shù) * create by tiankai on 2018-06-25 15:23 */ async getUnifiedOrderParams(){ let signString = { appid: config.appid, mch_id: config.mchid, nonce_str: await this.getNonceStr(), body: '短信平臺(tái)-短信套餐購(gòu)買', out_trade_no: '20180926125346',//訂單號(hào) total_fee: 88,//訂單金額 //APP和網(wǎng)頁(yè)支付提交用戶端ip,Native支付填調(diào)用微信支付API的機(jī)器IP //需要自行獲取,這里只是為了測(cè)試直接寫上了 spbill_create_ip: '123.12.12.123', notify_url: config.notify_url, trade_type: 'JSAPI', openid: await think.cache('openId') } let sign = await this.makeSign(signString,config.key); signString.sign = sign; /* console.log("--------------------------"); * console.log(sign); * console.log("--------------------------"); */ let xml = await jsonBuilder.buildObject(signString); /* console.log(xml); */ return xml; }
然后就可以發(fā)起統(tǒng)一下單API請(qǐng)求了
/* * 功能:調(diào)用統(tǒng)一下單API接口 * create by tiankai on 2018-06-26 11:01 */ async unifiedOrder(){ let xmlParams = await this.getUnifiedOrderParams(); let unifiedOrderUrl = config.unifiedOrderUrl; let opt = { method: "POST", mode: 'cors', headers: { 'content-type': 'text/xml' }, body: xmlParams } let res = await this.fetch(unifiedOrderUrl, opt); //這里微信返回的也是 xml let result = await res.text(); let data = null; // 微信返回的 XML 轉(zhuǎn)換為 JSON xmlParser.parseString(result,function(err, jsonData){ if(!err){ /* console.log(jsonData); */ data = jsonData; } }); return data; }
第四步:當(dāng)請(qǐng)求成功時(shí) 判斷一下 return_code 和 result_code
第五步:拿上 prepay_id ,進(jìn)行再次簽名,然后返回給前端
/* * 功能:統(tǒng)一下單接口返回 prepay_id 再次簽名 返回給前端 * create by tiankai on 2018-06-26 15:45 */ async payParams(){ let signString = { appid: config.appid, timeStamp: +new Date(), nonce_str: await this.getNonceStr(), package: null, signType: 'MD5' } //調(diào)用 統(tǒng)一下單 API let jsonData = await this.unifiedOrder(); if(think.isNullOrUndefined(jsonData) && jsonData.xml.return_code === 'SUCCESS' && jsonData.xml.result_code === 'SUCCESS' ){ signString.package = 'perpay_id='+jsonData.xml.perpay_id }else{ return jsonData.xml.return_msg; } //進(jìn)行再次簽名 let paySign = await this.makeSign(signString,config.key); signString.paySign = paySign; let { appid, signType, ...result } = signString; // result 中不包括 appid 和 signType 返回給前端 return result; }
第六步:用戶確認(rèn)支付后,小程序端調(diào)用支付接口,根據(jù)返回結(jié)果提示用戶
wx.requestPayment({ 'timeStamp': '', 'nonceStr': '',//后端返回的隨機(jī)字符串 'package': '',//后端返回的 'signType': 'MD5', 'paySign': '',//后端返回的 'success':function(res){ }, 'fail':function(res){ } });
第七步:支付成功后,微信服務(wù)器會(huì)把支付結(jié)果返回給配置的 notify_url ,開發(fā)者根據(jù)支付結(jié)果,更新服務(wù)器的訂單狀態(tài)。
大體流程就是這,現(xiàn)在進(jìn)行到了 第四步 公司小程序 appid 還沒申請(qǐng)下來 商戶號(hào) mch_id 也沒有,等過段時(shí)間繼續(xù)更新。(18/6/27)
KESION 科汛軟件
KESION 科汛軟件是國(guó)內(nèi)領(lǐng)先的在線教育軟件及私域社交電商軟件服務(wù)提供商,長(zhǎng)期專注于為企業(yè)提供在線教育軟件及社交電商SaaS平臺(tái)解決方案。
公司核心產(chǎn)品云開店SaaS社交電商服務(wù)平臺(tái)、在線教育SaaS服務(wù)平臺(tái)、教育企業(yè)數(shù)字化SaaS云平臺(tái)、企微營(yíng)銷助手、私有化獨(dú)立部署品牌網(wǎng)校和在線教育咨詢等。KESION 不斷通過技術(shù)創(chuàng)新,提供產(chǎn)品和服務(wù),助力企業(yè)向數(shù)字化轉(zhuǎn)型,通過科技驅(qū)動(dòng)商業(yè)革新,讓商業(yè)變得更智慧!
普通的電商購(gòu)物小程序一般包括小程序的系統(tǒng)功能頁(yè)面的設(shè)計(jì),以及普通電商購(gòu)物小程序前端后端的開發(fā),那么一般情況下定制一套這樣的小程序需要多少錢,需要多少開發(fā)成本呢?...
蜜芽是一款為年輕媽媽提供品質(zhì)育兒的全方位服務(wù)的應(yīng)用,那么蜜芽對(duì)于小程序是如何打算的,蜜芽小程序的戰(zhàn)略布局如何?...