React網頁應用調起支付寶沙箱測試實現
React+Redux網頁應用調起支付寶沙箱測試實現
1、新建React+Redux專案,建立空頁面,增加一個支付連結,編寫Redux方法呼叫Api生成支付連結
render() { let searchParam = { loginState: this.props.loginFailed, schcode: this.props.schcode, stucode: this.props.stucode } return ( <div> <Profile name={this.props.username} image={this.props.photo} /> <div id='testreducer' style={{ color: 'red', textAlign: 'center' }}>{this.state.helloValue}</div> <div onClick={this.alipay.bind(this)} style={{ color: 'red', textAlign: 'center', border: '1px solid blue', marginTop: '100px' }}> 點選跳轉支付寶支付 </div> </div> ); }
alipay() { let obj = {} obj.total_amount = 100; obj.stucode = this.props.stucode; obj.schcode = this.props.schcode; obj.subject = '支付寶沙箱環境支付測試'; this.props.getAlipay.call(this, obj); }
2、支付寶沙箱註冊應用和支付寶沙箱版本安裝
https://openhome.alipay.com/platform/appDaily.htm?tab=info 支付寶登入後檢視個人測試AppID
使用支付寶公鑰私鑰工具,生成公鑰:https://docs.open.alipay.com/291/105971/
在沙箱工具掃描二維碼安裝安卓版本支付寶沙箱測試版本
3、Api專案編寫支付寶調起相關程式碼邏輯
定義appid、閘道器等引數
//支付寶引數 const app_id = 'xxxxxx'; const return_url = 'http://172.16.117.43:3001'; const notify_url = 'http://172.16.117.43:8001/api/alipay/alipaynotify'; const gateway = 'https://openapi.alipaydev.com/gateway.do?';宣告api方法alipaysign,post型別,用於接收React頁面的api請求,最終res.json(util.success(finalparams))返回支付寶支付連結
/** * 獲取支付寶支付地址帶參 */ router.post('/alipaysign', function (req, res) { let total_amount = req.body.total_amount; let schcode = req.body.schcode; let stucode = req.body.stucode; let subject = req.body.subject; let out_trade_no = moment().format('YYYYMMDDHHmmss') + moment().millisecond(); // + '_' + schcode + '_' + stucode; console.log(out_trade_no) //生成系統訂單併入庫 let addJson = { out_trade_no: out_trade_no, schcode: schcode, stucode: stucode }; // alipay.addNewOrder(addJson,function(err,data){ ... }); let params = new Map(); params.set('app_id', app_id); params.set('method', 'alipay.trade.wap.pay'); params.set('charset', 'utf-8'); params.set('sign_type', 'RSA2'); params.set('timestamp', moment().format('YYYY-MM-DD HH:mm:ss')); params.set('version', '1.0'); params.set('return_url', return_url); params.set('notify_url', notify_url); params.set('biz_content', buildBizContent(subject, out_trade_no, total_amount)); params.set('sign', buildSign(params)); let finalparams = gateway + Array.from(params).map(([k, v]) => `${k}=${encodeURIComponent(v)}`).join('&'); console.log(finalparams) res.json(util.success(finalparams)); })
生成業務請求引數的集合
function buildBizContent(subject, outTradeNo, totalAmount) { let bizContent = { subject: subject, out_trade_no: outTradeNo, total_amount: totalAmount, product_code: 'QUICK_MSECURITY_PAY', }; return JSON.stringify(bizContent); }
根據引數構建簽名
function buildSign(paramsMap) { let paramsList = Array.from(paramsMap); paramsList.sort(); let paramsString = paramsList.map(([k, v]) => `${k}=${v}`).join('&'); let privateKey = fs.readFileSync(path.join(__dirname, 'alipay_private.pem'), 'utf8'); let signType = paramsMap.get('sign_type'); return signWithPrivateKey(signType, paramsString, privateKey); }
通過私鑰給字串簽名
function signWithPrivateKey(signType, content, privateKey) { let sign; if (signType.toUpperCase() === 'RSA2') { sign = crypto.createSign("RSA-SHA256"); } else if (signType.toUpperCase() === 'RSA') { sign = crypto.createSign("RSA-SHA1"); } else { throw new Error('請傳入正確的簽名方式,signType:' + signType); } sign.update(content); return sign.sign(privateKey, 'base64'); }
上面的程式碼就是一個完整的生成合規的支付寶支付連結,需要注意要用支付寶工具生成公鑰私鑰檔案放在合適的位置。
4、測試支付
5、接收支付寶非同步通知
/** * 通過私鑰給字串簽名 * @param signType 返回引數的簽名型別:RSA2或RSA * @param content 需要加密的字串 * @param privateKey 私鑰 * @returns {number | PromiseLike<ArrayBuffer>} * @private */ function signWithPrivateKey(signType, content, privateKey) { let sign; if (signType.toUpperCase() === 'RSA2') { sign = crypto.createSign("RSA-SHA256"); } else if (signType.toUpperCase() === 'RSA') { sign = crypto.createSign("RSA-SHA1"); } else { throw new Error('請傳入正確的簽名方式,signType:' + signType); } sign.update(content); return sign.sign(privateKey, 'base64'); } /** * 驗證支付寶非同步通知的合法性 * @param params 支付寶非同步通知結果的引數 * @returns {*} */ function verifySign(params) { try { let sign = params['sign']; //簽名 let signType = params['sign_type']; //簽名型別 let paramsMap = new Map(); for (let key in params) { paramsMap.set(key, params[key]); } let paramsList = Array.from(paramsMap); paramsList.sort(); let paramsString = paramsList.map(([k, v]) => `${k}=${decodeURIComponent(v)}`).join('&'); let publicKey = fs.readFileSync(path.join(__dirname, 'alipay_public.pem'), 'utf8'); return verifyWithPublicKey(signType, sign, paramsString, publicKey); } catch (e) { console.error(e); return false; } } /** * 驗證簽名 * @param signType 返回引數的簽名型別:RSA2或RSA * @param sign 返回引數的簽名 * @param content 引數組成的待驗籤串 * @param publicKey 支付寶公鑰 * @returns {*} 是否驗證成功 * @private */ function verifyWithPublicKey(signType, sign, content, publicKey) { try { let verify; if (signType.toUpperCase() === 'RSA2') { verify = crypto.createVerify('RSA-SHA256'); } else if (signType.toUpperCase() === 'RSA') { verify = crypto.createVerify('RSA-SHA1'); } else { throw new Error('未知signType:' + signType); } verify.update(content); return verify.verify(publicKey, sign, 'base64') } catch (err) { console.error(err); return false; } } /** * 獲取支付寶支付非同步通知 */ router.post('/alipaynotify', function (req, res) { let signType = req.body.sign_type; //簽名型別:商戶生成簽名字串所使用的簽名演算法型別,目前支援RSA2和RSA,推薦使用RSA2 let sign = req.body.sign; //簽名:請參考<a href="#yanqian" class="bi-link">非同步返回結果的驗籤</a> let tradeNo = req.body.trade_no; //支付寶交易號:支付寶交易憑證號 let outTradeNo = req.body.out_trade_no; //商戶訂單號:原支付請求的商戶訂單號 let buyerLogonId = req.body.buyer_logon_id; //買家支付寶賬號:買家支付寶賬號 let sellerId = req.body.seller_id; //賣家支付寶使用者號:賣家支付寶使用者號 let tradeStatus = req.body.trade_status; //交易狀態:交易目前所處的狀態,見<a href="#jiaoyi" class="bi-link">交易狀態說明</a> let totalAmount = req.body.total_amount; //訂單金額:本次交易支付的訂單金額,單位為人民幣(元) let receiptAmount = req.body.receipt_amount; //實收金額:商家在交易中實際收到的款項,單位為元 let gmtPayment = req.body.gmt_payment;//交易付款時間:該筆交易的買家付款時間。格式為yyyy-MM-dd HH:mm:ss let isSuccess = verifySign(req.body); console.log(isSuccess) if (isSuccess) { if (tradeStatus === 'TRADE_FINISHED') { //交易狀態TRADE_FINISHED的通知觸發條件是商戶簽約的產品不支援退款功能的前提下,買家付款成功;或者,商戶簽約的產品支援退款功能的前提下,交易已經成功並且已經超過可退款期限。 } else if (tradeStatus === 'TRADE_SUCCESS') { //狀態TRADE_SUCCESS的通知觸發條件是商戶簽約的產品支援退款功能的前提下,買家付款成功 } else if (tradeStatus === 'WAIT_BUYER_PAY') { //交易建立,等待買家付款 } else if (tradeStatus === 'TRADE_CLOSED') { //未付款交易超時關閉,或支付完成後全額退款 } res.send('success'); } else { res.send('fail'); } });
由請喊我大龍哥最後編輯於:7個月前
內容均為作者獨立觀點,不代表八零IT人立場,如涉及侵權,請及時告知。
相關文章
- SpringMVC 實現支付寶支付功能(沙箱環境)SpringMVC
- [Android] webview調起支付寶支付頁面記錄AndroidWebView
- [譯] 測試 React & Redux 應用良心指南ReactRedux
- 【翻譯】基於 Cypress 測試 React 應用React
- 微前端中實現沙箱環境的方案調研前端
- 【譯】React 應用效能調優React
- [譯] 使用 Puppeteer 和 Jest 測試你的 React 應用React
- java實現沙箱測試環境支付寶支付(demo)和整合微信支付和支付寶支付到springmvc+spring+mybatis環境全過程(支付寶和微信支付、附原始碼)JavaSpringMVCMyBatis原始碼
- Chrome實現自動化測試:錄製回放網頁動作Chrome網頁
- 網際網路App應用程式測試流程及測試總結APP
- 讓react用起來更得心應手——(react-redux)ReactRedux
- 測試嵌入GeoGebra網頁網頁
- 替你解憂!9款免費且超實用的響應式網頁測試工具網頁
- 在 Windows 和 Mac 的網頁上喚起 JavaFX 應用WindowsMac網頁Java
- React單元測試實戰React
- 全棧測試實戰:用Jest測試Vue+Koa全棧應用全棧Vue
- 用Jest和Enzyme測試React元件React元件
- [應用案例]愛舊網 bate測試版BAT
- 讓react用起來更得心應手——(React 基礎簡析)React
- 2行程式碼調起微信支付寶支付行程
- 如何做好移動網際網路應用測試
- 讓react用起來更得心應手——(react-router原理簡析)React
- [貝聊科技]網頁端「應用跳轉」技術實現演變網頁
- React 測試指南React
- iOS實戰之調起QQ加群頁和臨時會話頁iOS會話
- 用React實現一個簡易的markdown部落格應用React
- 如何測試 Flutter 應用? ー 單元測試Flutter
- Jest + React 單元測試最佳實踐React
- webpack4 + react 搭建多頁面應用WebReact
- vue 單頁應用(spa)前端路由實現原理Vue前端路由
- Html網頁實現鍵盤Enter響應功能HTML網頁
- 如何實現介面異常場景測試?測試方法探索與測試工具實現
- 攜程程式碼分析平臺實現精準測試與應用瘦身
- 軟體效能測試分析與調優實踐之路-Java應用程式的效能分析與調優-手稿節選Java
- 實現 JavaScript 沙箱的幾種方式JavaScript
- 微軟允許測試人員在 Windows 11 上試用 Android 應用程式:已支援執行支付寶等APP微軟WindowsAndroidAPP
- 在網頁中呼叫系統調色盤和測試所有安裝字型(轉)網頁
- 【星雲測試】開發者測試-採用精準測試工具對Spring Boot應用進行測試Spring Boot