React Native (IOS和Android) 支付寶和微信支付整合實戰(支付寶服務端篇)
序言:React Native無論是在社群和應用程度上,在國內外是十分廣泛和普及的。而支付寶和微信在支付模組上都有或多或少的支援,雖然沒有完整的Demo,不過在我做過一個相關整合的專案後,在此我把相關的步驟和方法總結出來和大家分享,希望能夠幫助大家少走彎路,快速整合。
支付寶——服務端整合
一、獲取你的AppId和配置支付寶公鑰私鑰
在登入螞蟻金服開放平臺後,獲取你App應用對應的APPID (它目前就是在App圖示旁的一串數字)。
緊接著你就需要去配置你的公鑰私鑰了,具體步驟可以參考官方文件,寫的很清楚。
不過需要注意的有以下幾點:
1.如果你的服務端用的是非Java語言的,一定要選擇對應的金鑰格式,本分享用的是NodeJS寫的服務端,至於金鑰長度,1024,或者2048均可,建議以2048,所以選擇如下圖:
2.點選生成金鑰後,你會發現金鑰已經生成,分別為商戶應用私鑰和商戶應用公鑰,兩者請都妥善保管至其他資料夾中。
3.在螞蟻金服開放平臺,開發者中心,該APP應用下的介面加簽方式中,選擇 RSA(SHA256)金鑰 方式,並且上傳該第二步驟產生的應用公鑰並儲存
4.再次開啟支付寶生成金鑰工具,並且切換至【格式轉換】選項卡中,將第二步驟產生的商戶私鑰貼上至商戶應用私鑰中,並點選轉PKCS1(非JAVA適用)私鑰,它會提示該私鑰已經為該格式(如果你是JAVA適用的請選擇前者),我們重複該步驟的目的是為了生成供NodeJS可以讀取並且解析的PEM檔案(其他語言亦然),接著開啟金鑰檔案路徑,開啟私鑰檔案,你會發現,檔案頭會有
--BEGIN RSA PRVIATE KEY -- 字樣。
5. 儲存該檔案並且重新命名alipay_private_key.pem。
6. 將私鑰和公鑰上傳至支付寶開發的應用後,獲取支付寶公鑰,儲存並且建立檔案為alipay_public_key.pem 在開頭和結尾分別加上
-----BEGIN PUBLIC KEY-----
-----END PUBLIC KEY-----
至此,金鑰配置已經完成。
PS: 支付寶也有沙箱應用,其公鑰私鑰配置一模一樣,在此不再贅述
二、編寫服務端程式碼
支付寶生成請求引數可以參考官方文件https://docs.open.alipay.com/204/105465/
,其中公共引數和業務引數是一般支付時所需要的。在服務端生成簽名其中有幾個比較重要的點,一定要牢記,反覆檢查,避免驗簽過程一直失敗,導致無法支付,浪費開發時間。(如果你的服務端語言是Java,.Net或者Php,那麼恭喜你,無需看以下內容,因為支付寶有相關SDK使用,
1.生成簽名sign之前的引數字串(暫且稱為未簽名支付串),一定要ASCII碼遞增排序
2.生成簽名後的sign引數放置未簽名支付串末尾(簽名支付串),其中未簽名支付串的引數個數和值不能有任何改動
3.將簽名支付串進行encode。
可參考NodeJS程式碼如下:
raw = function (args) {
//升序引數,並且拼接為key & value字串
var keys = Object.keys(args);
keys = keys.sort()
var newArgs = {};
keys.forEach(function (key) {
newArgs[key] = args[key];
});
var string = '';
for (var k in newArgs) {
string += '&' + k + '=' + newArgs[k];
}
string = string.substr(1);
return string;
}
// 支付寶生成簽名
var signed = function (order) {
const app_id = ''; //此app_id為你申請的支付寶的應用APPID
//生成一個基本的訂單資訊,必要的引數和值如下,更多引數和用法請參考官方文件
var biz_content = '{"timeout_express":"60m",' + //允許支付的最晚時間
'"product_code":"QUICK_MSECURITY_PAY",' +
'"total_amount":"' + order.total_amount + '",' + //支付金額,以元為單位
'"subject":"' + order.subject + '",' +
'"body":"' + order.body + '",' +
'"out_trade_no":"' + order.out_trade_no + '"}'; //自己平臺的支付訂單號碼
var unsigned = {
app_id: app_id,
method: 'alipay.trade.app.pay',
charset: 'utf-8',
sign_type: 'RSA2',
version: '1.0',
timestamp: moment().format('YYYY-MM-DD HH:mm:ss'),
biz_content: biz_content,
notify_url: 'http://192.168.1.45:3000/alipay/notify_url' //此處為支付寶服務端呼叫成功後通知你時會訪問的url
}
var unsignedStr = raw(unsigned);
let private_key = fs.readFileSync('./config/alipay_private_key.pem'); //獲取商戶應用私鑰
let signer = crypto.createSign('RSA-SHA256'); //建立RSA2加密演算法示例
signer.update(unsignedStr); //新增需要加密的字串
let sign = signer.sign(private_key, 'base64'); //加密並且以base64的形式返回
return qs.stringify(unsigned) + '&sign=' + encodeURIComponent(sign) //encode
}
//收到支付寶非同步通知進行驗籤
var verified = function (response, sign) {
let public_key = fs.readFileSync('./config/alipay_public_key.pem');
var verify = crypto.createVerify('RSA-SHA256');
verify.update(response);
return verify.verify(public_key, sign, 'base64')
}
//支付寶獲取簽名的訂單資訊
alipay.post('/pay', function (req, res) {
var signedStr = signed({
body: '測試支付',//預祝春節快樂,1分錢購,贈送IPhone X一人一部
subject: '測試支付',//免費贈送IPhone X
out_trade_no: '70501111111S501115', //自己平臺的支付訂單號碼
total_amount: '0.01' //支付金額,以元為單位
})
res.send(signedStr);
})
//接受支付寶通知
alipay.post('/notify_url', function (req, res) {
var obj = req.body
var sign = req.body.sign
delete obj['sign']
delete obj['sign_type']
var verRes = verified(raw(obj), sign)
if (verRes) {
/**
* 1、商戶需要驗證該通知資料中的out_trade_no是否為商戶系統中建立的訂單號,
* 2、判斷total_amount是否確實為該訂單的實際金額(即商戶訂單建立時的金額)
* 3、校驗通知中的seller_id(或者seller_email) 是否為out_trade_no這筆單據的對應的操作方(有的時候,一個商戶可能有多個seller_id/seller_email)
* 4、驗證app_id是否為該商戶本身。上述1、2、3、4有任何一個驗證不通過,則表明本次通知是異常通知,務必忽略。在上述驗證通過後商戶必須根據支付寶不同型別的業務通知,
* 正確的進行不同的業務處理,並且過濾重複的通知結果資料。
* 在支付寶的業務通知中,只有交易通知狀態為TRADE_SUCCESS或TRADE_FINISHED時,支付寶才會認定為買家付款成功。
*/
//按照支付結果非同步通知中的描述,對支付結果中的業務內容進行1\2\3\4二次校驗,校驗成功後在response中返回success,校驗失敗返回failure
res.send('success')
} else {
res.send('failure')
}
})
至此支付寶服務端程式碼已經完成,由於本地開發notify_url必須為能夠被訪問的地址,如果想本地測試,建議可以使用ngrok
鳴謝:我是一名來自盛安德的Shinetecher,感謝盛安德公司及同事們對IT技術的支援,分享和熱情,讓我有時間和動力完成此博文。
聯絡:歡迎各位朋友有任何問題和建議留言至此部落格下,或者新增本人微訊號:liyijia428 進行溝通交流學習