1、參考支付寶api文檔封裝jsgit
支付寶api文檔參考:https://opendocs.alipay.com/apis/api_1github
封裝結果參考:https://blog.csdn.net/q3585914/article/details/72957548web
對上面大佬的封裝作了些許調整express
(1) alipay.jsjson
1 /** 2 * Created by ference on 2017/4/8. 3 */ 4 5 var fs = require('fs'); 6 var path = require('path'); 7 var utl = require('./utl'); 8 9 var alipay_gate_way = 'https://openapi.alipay.com/gateway.do'; 10 var alipay_gate_way_sandbox = 'https://openapi.alipaydev.com/gateway.do'; 11 12 module.exports = Alipay; 13 14 /** 15 * 16 * @param {Object} opts 17 * @param {String} opts.appId 支付寶的appId 18 * @param {String} opts.notifyUrl 支付寶服務器主動通知商戶服務器裏指定的頁面http/https路徑 19 * @param {String} opts.rsaPrivate 商戶私鑰pem文件路徑 20 * @param {String} opts.rsaPublic 支付寶公鑰pem文件路徑 21 * @param {String} opts.signType 簽名方式, 'RSA' or 'RSA2' 22 * @param {Boolean} [opts.sandbox] 是不是沙盒環境 23 * @constructor 24 */ 25 function Alipay(opts) { 26 this.appId = opts.appId; 27 this.sandbox = !!opts.sandbox; 28 this.notifyUrl = opts.notifyUrl; 29 this.signType = opts.signType; 30 31 this.rsaPrivate = fs.readFileSync(opts.rsaPrivate, 'utf-8'); 32 this.rsaPublic = fs.readFileSync(opts.rsaPublic, 'utf-8'); 33 } 34 35 var props = Alipay.prototype; 36 37 props.makeParams = function(method, biz_content) { 38 return { 39 app_id: this.appId, 40 method: method, 41 format: 'JSON', 42 charset: 'utf-8', 43 sign_type: this.signType, 44 timestamp: new Date().format('yyyy-MM-dd hh:mm:ss'), 45 version: '1.0', 46 biz_content: JSON.stringify(biz_content) 47 }; 48 }; 49 50 /** 51 * 生成支付參數供客戶端使用 52 * @param {Object} opts 53 * @param {String} opts.subject 商品的標題/交易標題/訂單標題/訂單關鍵字等 54 * @param {String} [opts.body] 對一筆交易的具體描述信息。若是是多種商品,請將商品描述字符串累加傳給body 55 * @param {String} opts.outTradeId 商戶網站惟一訂單號 56 * @param {String} [opts.timeout] 設置未付款支付寶交易的超時時間,一旦超時,該筆交易就會自動被關閉。 57 當用戶進入支付寶收銀臺頁面(不包括登陸頁面),會觸發即刻建立支付寶交易,此時開始計時。 58 取值範圍:1m~15d。m-分鐘,h-小時,d-天,1c-當天(1c-當天的狀況下,不管交易什麼時候建立,都在0點關閉)。 59 該參數數值不接受小數點, 如 1.5h,可轉換爲 90m。 60 * @param {String} opts.amount 訂單總金額,單位爲元,精確到小數點後兩位,取值範圍[0.01,100000000] 61 * @param {String} [opts.sellerId] 收款支付寶用戶ID。 若是該值爲空,則默認爲商戶簽約帳號對應的支付寶用戶ID 62 * @param {String} opts.goodsType 商品主類型:0—虛擬類商品,1—實物類商品 注:虛擬類商品不支持使用花唄渠道 63 * @param {String} [opts.passbackParams] 公用回傳參數,若是請求時傳遞了該參數,則返回給商戶時會回傳該參數。支付寶會在異步通知時將該參數原樣返回。本參數必須進行UrlEncode以後才能夠發送給支付寶 64 * @param {String} [opts.promoParams] 優惠參數(僅與支付寶協商後可用) 65 * @param {String} [opts.extendParams] 業務擴展參數 https://doc.open.alipay.com/docs/doc.htm?spm=a219a.7629140.0.0.3oJPAi&treeId=193&articleId=105465&docType=1#kzcs 66 * @param {String} [opts.enablePayChannels] 可用渠道,用戶只能在指定渠道範圍內支付。當有多個渠道時用「,」分隔。注:與disable_pay_channels互斥 67 * @param {String} [opts.disablePayChannels] 禁用渠道,用戶不可用指定渠道支付。當有多個渠道時用「,」分隔。 注:與enable_pay_channels互斥 68 * @param {String} [opts.storeId] 商戶門店編號 69 */ 70 props.pay = function (opts) { 71 72 var biz_content = { 73 body: opts.body, 74 subject: opts.subject, 75 out_trade_no: opts.outTradeId, 76 timeout_express: opts.timeout, 77 total_amount: opts.amount, 78 seller_id: opts.sellerId, 79 product_code: 'QUICK_MSECURITY_PAY', 80 goods_type: opts.goodsType, 81 passback_params: opts.passbackParams, 82 promo_params: opts.promoParams, 83 extend_params: opts.extendParams, 84 enable_pay_channels: opts.enablePayChannels, 85 disable_pay_channels: opts.disablePayChannels, 86 store_id: opts.storeId 87 }; 88 89 var params = this.makeParams('alipay.trade.app.pay', biz_content); 90 params.notify_url = this.notifyUrl; 91 92 return utl.processParams(params, this.rsaPrivate, this.signType); 93 }; 94 95 /** 96 * 生成支付參數供web端使用 97 * @param {Object} opts 98 * @param {String} opts.subject 商品的標題/交易標題/訂單標題/訂單關鍵字等 99 * @param {String} [opts.body] 對一筆交易的具體描述信息。若是是多種商品,請將商品描述字符串累加傳給body 100 * @param {String} opts.outTradeId 商戶網站惟一訂單號 101 * @param {String} [opts.timeout] 設置未付款支付寶交易的超時時間,一旦超時,該筆交易就會自動被關閉。 102 當用戶進入支付寶收銀臺頁面(不包括登陸頁面),會觸發即刻建立支付寶交易,此時開始計時。 103 取值範圍:1m~15d。m-分鐘,h-小時,d-天,1c-當天(1c-當天的狀況下,不管交易什麼時候建立,都在0點關閉)。 104 該參數數值不接受小數點, 如 1.5h,可轉換爲 90m。 105 * @param {String} opts.amount 訂單總金額,單位爲元,精確到小數點後兩位,取值範圍[0.01,100000000] 106 * @param {String} [opts.sellerId] 收款支付寶用戶ID。 若是該值爲空,則默認爲商戶簽約帳號對應的支付寶用戶ID 107 * @param {String} opts.goodsType 商品主類型:0—虛擬類商品,1—實物類商品 注:虛擬類商品不支持使用花唄渠道 108 * @param {String} [opts.passbackParams] 公用回傳參數,若是請求時傳遞了該參數,則返回給商戶時會回傳該參數。支付寶會在異步通知時將該參數原樣返回。本參數必須進行UrlEncode以後才能夠發送給支付寶 109 * @param {String} [opts.promoParams] 優惠參數(僅與支付寶協商後可用) 110 * @param {String} [opts.extendParams] 業務擴展參數 https://doc.open.alipay.com/docs/doc.htm?spm=a219a.7629140.0.0.3oJPAi&treeId=193&articleId=105465&docType=1#kzcs 111 * @param {String} [opts.enablePayChannels] 可用渠道,用戶只能在指定渠道範圍內支付。當有多個渠道時用「,」分隔。注:與disable_pay_channels互斥 112 * @param {String} [opts.disablePayChannels] 禁用渠道,用戶不可用指定渠道支付。當有多個渠道時用「,」分隔。 注:與enable_pay_channels互斥 113 * @param {String} [opts.storeId] 商戶門店編號 114 */ 115 props.webPay = function (opts) { 116 117 var biz_content = { 118 body: opts.body, 119 subject: opts.subject, 120 out_trade_no: opts.outTradeId, 121 timeout_express: opts.timeout, 122 total_amount: opts.amount, 123 seller_id: opts.sellerId, 124 product_code: 'FAST_INSTANT_TRADE_PAY', 125 goods_type: opts.goodsType, 126 passback_params: opts.passbackParams, 127 promo_params: opts.promoParams, 128 extend_params: opts.extendParams, 129 enable_pay_channels: opts.enablePayChannels, 130 disable_pay_channels: opts.disablePayChannels, 131 store_id: opts.storeId 132 }; 133 134 // var params = this.makeParams('alipay.trade.page.pay', biz_content); // PC 135 var params = this.makeParams('alipay.trade.wap.pay', biz_content); // PHONE 136 params.notify_url = this.notifyUrl; 137 138 return utl.processParams(params, this.rsaPrivate, this.signType); 139 }; 140 141 /** 142 * 簽名校驗 143 * @param {Object} response 支付寶的響應報文 144 */ 145 props.signVerify = function (response) { 146 var ret = utl.copy(response); 147 var sign = ret['sign']; 148 ret.sign = undefined; 149 ret.sign_type = undefined; 150 151 var tmp = utl.encodeParams(ret); 152 return utl.signVerify(tmp.unencode, sign, this.rsaPublic, this.signType); 153 } 154 155 /** 156 * 查詢交易狀態 https://doc.open.alipay.com/doc2/apiDetail.htm?spm=a219a.7629065.0.0.PlTwKb&apiId=757&docType=4 157 * @param {Object} opts 158 * @param {String} [opts.outTradeId] 訂單支付時傳入的商戶訂單號,和支付寶交易號不能同時爲空。 tradeId,outTradeId若是同時存在優先取tradeId 159 * @param {String} [opts.tradeId] 支付寶交易號,和商戶訂單號不能同時爲空 160 * @param {String} [opts.appAuthToken] https://doc.open.alipay.com/doc2/detail.htm?treeId=216&articleId=105193&docType=1 161 */ 162 props.query = function (opts) { 163 164 var biz_content = { 165 out_trade_no: opts.outTradeId, 166 trade_no: opts.tradeId 167 }; 168 169 var params = { 170 app_id: this.appId, 171 method: 'alipay.trade.query', 172 format: 'JSON', 173 charset: 'utf-8', 174 sign_type: this.signType, 175 timestamp: new Date().format('yyyy-MM-dd hh:mm:ss'), 176 version: '1.0', 177 app_auth_token: opts.appAuthToken, 178 biz_content: JSON.stringify(biz_content) 179 }; 180 var params = this.makeParams('alipay.trade.query', biz_content); 181 if(this.appAuthToken) { 182 params.app_auth_token = this.appAuthToken; 183 } 184 185 var body = utl.processParams(params, this.rsaPrivate, this.signType); 186 187 return utl.request({ 188 method: 'GET', 189 url: (this.sandbox? alipay_gate_way_sandbox : alipay_gate_way) + '?' + body 190 }); 191 }; 192 193 194 /** 195 * 統一收單交易關閉接口 https://doc.open.alipay.com/doc2/apiDetail.htm?spm=a219a.7629065.0.0.6VzMcn&apiId=1058&docType=4 196 * @param {Object} opts 197 * @param {String} [opts.outTradeId] 訂單支付時傳入的商戶訂單號,和支付寶交易號不能同時爲空。 tradeId,outTradeId若是同時存在優先取tradeId 198 * @param {String} [opts.tradeId] 支付寶交易號,和商戶訂單號不能同時爲空 199 * @param {String} [opts.operatorId] 賣家端自定義的的操做員 ID 200 * @param {String} [opts.appAuthToken] https://doc.open.alipay.com/doc2/detail.htm?treeId=216&articleId=105193&docType=1 201 */ 202 props.close = function (opts) { 203 204 var biz_content = { 205 out_trade_no: opts.outTradeId, 206 trade_no: opts.tradeId, 207 operator_id: opts.operatorId 208 }; 209 210 var params = this.makeParams('alipay.trade.close', biz_content); 211 if(this.appAuthToken) { 212 params.app_auth_token = this.appAuthToken; 213 } 214 215 var body = utl.processParams(params, this.rsaPrivate, this.signType); 216 217 return utl.request({ 218 method: 'GET', 219 url: (this.sandbox? alipay_gate_way_sandbox : alipay_gate_way) + '?' + body 220 }); 221 }; 222 223 224 /** 225 * 統一收單交易退款接口 https://doc.open.alipay.com/doc2/apiDetail.htm?spm=a219a.7629065.0.0.PlTwKb&apiId=759&docType=4 226 * @param {Object} opts 227 * @param {String} [opts.outTradeId] 訂單支付時傳入的商戶訂單號,和支付寶交易號不能同時爲空。 tradeId,outTradeId若是同時存在優先取tradeId 228 * @param {String} [opts.tradeId] 支付寶交易號,和商戶訂單號不能同時爲空 229 * @param {String} [opts.operatorId] 賣家端自定義的的操做員 ID 230 * @param {String} [opts.appAuthToken] https://doc.open.alipay.com/doc2/detail.htm?treeId=216&articleId=105193&docType=1 231 * @param {String} opts.refundAmount 須要退款的金額,該金額不能大於訂單金額,單位爲元,支持兩位小數 232 * @param {String} [opts.refundReason] 退款的緣由說明 233 * @param {String} [opts.outRequestId] 標識一次退款請求,同一筆交易屢次退款須要保證惟一,如需部分退款,則此參數必傳。 234 * @param {String} [opts.storeId] 商戶的門店編號 235 * @param {String} [opts.terminalId] 商戶的終端編號 236 */ 237 props.refund = function (opts) { 238 239 // var biz_content = { 240 // out_trade_no: opts.outTradeId, 241 // trade_no: opts.tradeId, 242 // operator_id: opts.operatorId, 243 // refund_amount: opts.refundAmount, 244 // refund_reason: opts.refundReason, 245 // out_request_no: opts.outRequestId, 246 // store_id: opts.storeId, 247 // terminal_id: opts.terminalId 248 // }; 249 250 // var params = this.makeParams('alipay.trade.refund', biz_content); 251 // if(this.appAuthToken) { 252 // params.app_auth_token = this.appAuthToken; 253 // } 254 255 // var body = utl.processParams(params, this.rsaPrivate, this.signType); 256 257 // utl.request({ 258 // method: 'GET', 259 // url: body 260 // }).then(function (ret) { 261 // console.log("***** ret.body=" + body); 262 // }); 263 }; 264 265 266 /** 267 * 統一收單交易退款查詢 https://doc.open.alipay.com/doc2/apiDetail.htm?docType=4&apiId=1049 268 * @param {Object} opts 269 * @param {String} [opts.outTradeId] 訂單支付時傳入的商戶訂單號,和支付寶交易號不能同時爲空。 tradeId,outTradeId若是同時存在優先取tradeId 270 * @param {String} [opts.tradeId] 支付寶交易號,和商戶訂單號不能同時爲空 271 * @param {String} [opts.outRequestId] 請求退款接口時,傳入的退款請求號,若是在退款請求時未傳入,則該值爲建立交易時的外部交易號 272 * @param {String} [opts.appAuthToken] https://doc.open.alipay.com/doc2/detail.htm?treeId=216&articleId=105193&docType=1 273 */ 274 props.refundQuery = function (opts) { 275 276 var biz_content = { 277 out_trade_no: opts.outTradeId, 278 trade_no: opts.tradeId, 279 out_request_no: opts.outRequestId || opts.outTradeId 280 }; 281 282 var params = this.makeParams('alipay.trade.fastpay.refund.query', biz_content); 283 if(this.appAuthToken) { 284 params.app_auth_token = this.appAuthToken; 285 } 286 287 var body = utl.processParams(params, this.rsaPrivate, this.signType); 288 289 return utl.request({ 290 method: 'GET', 291 url: (this.sandbox? alipay_gate_way_sandbox : alipay_gate_way) + '?' + body 292 }); 293 }; 294 295 296 /** 297 * 查詢對帳單下載地址 https://doc.open.alipay.com/doc2/apiDetail.htm?spm=a219a.7629065.0.0.iX5mPA&apiId=1054&docType=4 298 * @param {Object} opts 299 * @param {String} [opts.billType] 帳單類型,商戶經過接口或商戶經開放平臺受權後其所屬服務商經過接口能夠獲取如下帳單類型: 300 trade、signcustomer;trade指商戶基於支付寶交易收單的業務帳單;signcustomer是指基於商戶支付寶餘額收入及支出等資金變更的賬務帳單; 301 * @param {String} [opts.billDate] 帳單時間:日帳單格式爲yyyy-MM-dd,月帳單格式爲yyyy-MM。 302 * @param {String} [opts.appAuthToken] https://doc.open.alipay.com/doc2/detail.htm?treeId=216&articleId=105193&docType=1 303 */ 304 props.billDownloadUrlQuery = function (opts) { 305 306 var biz_content = { 307 bill_type: opts.billType, 308 bill_date: opts.billDate 309 }; 310 311 var params = this.makeParams('alipay.data.dataservice.bill.downloadurl.query', biz_content); 312 if(this.appAuthToken) { 313 params.app_auth_token = this.appAuthToken; 314 } 315 316 var body = utl.processParams(params, this.rsaPrivate, this.signType); 317 318 return utl.request({ 319 method: 'GET', 320 url: (this.sandbox? alipay_gate_way_sandbox : alipay_gate_way) + '?' + body 321 }); 322 };
(2) utl.jsapi
1 /** 2 * Created by ference on 2017/4/8. 3 */ 4 5 var crypto = require('crypto'); 6 var request = require('request'); 7 8 var utl = module.exports = {}; 9 10 Date.prototype.format = function (fmt) { 11 var o = { 12 "M+": this.getMonth() + 1, //月份 13 "d+": this.getDate(), //日 14 "h+": this.getHours(), //小時 15 "m+": this.getMinutes(), //分 16 "s+": this.getSeconds(), //秒 17 "q+": Math.floor((this.getMonth() + 3) / 3), //季度 18 "S": this.getMilliseconds() //毫秒 19 }; 20 if (/(y+)/.test(fmt)) fmt = fmt.replace(RegExp.$1, (this.getFullYear() + "").substr(4 - RegExp.$1.length)); 21 for (var k in o) 22 if (new RegExp("(" + k + ")").test(fmt)) fmt = fmt.replace(RegExp.$1, (RegExp.$1.length == 1) ? (o[k]) : (("00" + o[k]).substr(("" + o[k]).length))); 23 return fmt; 24 } 25 26 /** 27 * 淺拷貝 28 * @param obj 29 * @returns {{}} 30 */ 31 utl.copy = function (obj) { 32 var ret = {}; 33 for(var k in obj) { 34 ret[k] = obj[k]; 35 } 36 return ret; 37 } 38 39 /** 40 * 對請求參數進行組裝、編碼、簽名,返回已組裝好籤名的參數字符串 41 * @param {{Object} params 請求參數 42 * @param {String} privateKey 商戶應用私鑰 43 * @param {String} [signType] 簽名類型 'RSA2' or 'RSA' 44 * @returns {String} 45 */ 46 utl.processParams = function (params, privateKey, signType) { 47 var ret = utl.encodeParams(params); 48 var sign = utl.sign(ret.unencode, privateKey, signType); 49 return ret.encode + '&sign=' + encodeURIComponent(sign); 50 }; 51 52 /** 53 * 對請求參數進行組裝、編碼 54 * @param {Object} params 請求參數 55 * @returns {Object} 56 */ 57 utl.encodeParams = function (params) { 58 var keys = []; 59 for(var k in params) { 60 var v = params[k]; 61 if (params[k] !== undefined && params[k] !== "") keys.push(k); 62 } 63 keys.sort(); 64 65 var unencodeStr = ""; 66 var encodeStr = ""; 67 var len = keys.length; 68 for(var i = 0; i < len; ++i) { 69 var k = keys[i]; 70 if(i !== 0) { 71 unencodeStr += '&'; 72 encodeStr += '&'; 73 } 74 unencodeStr += k + '=' + params[k]; 75 encodeStr += k + '=' + encodeURIComponent(params[k]); 76 } 77 return {unencode:unencodeStr, encode:encodeStr}; 78 }; 79 80 /** 81 * 對字符串進行簽名驗證 82 * @param {String} str 要驗證的參數字符串 83 * @param {String} sign 要驗證的簽名 84 * @param {String} publicKey 支付寶公鑰 85 * @param {String} [signType] 簽名類型 86 * @returns {Boolean} 87 */ 88 utl.signVerify = function (str, sign, publicKey, signType) { 89 var verify; 90 if(signType === 'RSA2') { 91 verify = crypto.createVerify('RSA-SHA256'); 92 } else { 93 verify = crypto.createVerify('RSA-SHA1'); 94 } 95 verify.update(str, 'utf8'); 96 var result = verify.verify(publicKey, sign, 'base64'); 97 return result; 98 }; 99 100 /** 101 * 對字符串進行簽名 102 * @param {String} str 要簽名的字符串 103 * @param {String} privateKey 商戶應用私鑰 104 * @param {String} [signType] 簽名類型 105 * @returns {String} 106 */ 107 utl.sign = function (str, privateKey, signType) { 108 var sha; 109 if(signType === 'RSA2') { 110 sha = crypto.createSign('RSA-SHA256'); 111 } else { 112 sha = crypto.createSign('RSA-SHA1'); 113 } 114 sha.update(str, 'utf8'); 115 console.log(str) 116 console.log(privateKey) 117 return sha.sign(privateKey, 'base64'); 118 } 119 120 121 /** 122 * 發送請求 https://github.com/request/request 123 * @param {Object} opts 請求參數 124 * @param {String} opts.url 請求地址 125 * @param {String} opts.method GET|POST|PUT... 126 * @param {String} [opts.type] text/xml | application/json | application/x-www-form-urlencoded ... 127 * @param {Object} [opts.headers] {} 128 * @param {Object} [opts.qs] query參數 129 * @param {Buffer|String|ReadStream} [opts.body] 請求體 130 * @param {Object} [opts.form] form表單 131 * @returns {Promise.<Object>} resolve({response, body}) 132 */ 133 utl.request = function(opts){ 134 return new Promise(function(resolve, reject){ 135 request(opts, function(err, res, body){ 136 if(err){ 137 reject(err); 138 return; 139 } 140 let ret = {response:res, body:body}; 141 ret.ok = function() { 142 return res.statusCode === 200; 143 }; 144 ret.json = function () { 145 if(res.body) return JSON.parse(res.body); 146 return null; 147 }; 148 resolve(ret); 149 }); 150 }); 151 };
(3) 調用testpay.js服務器
1 var express = require('express'); 2 var router = express.Router(); 3 var path = require('path'); 4 var Alipay = require('../lib/alipay'); 5 var utl = require('../lib/utl'); 6 7 var outTradeId = Date.now().toString(); 8 9 10 11 var ali = new Alipay({ 12 appId: '', 13 notifyUrl: 'http://127.0.0.1:3000/pay/getback', // 回調參數傳遞 14 rsaPrivate: path.resolve('./alipay_configs/private-key.pem'), 15 rsaPublic: path.resolve('./alipay_configs/public-key.pem'), 16 sandbox: true, 17 return_url: 'http://www.baidu.com', // 要求支付寶可經過外網訪問 18 signType: 'RSA' // 'RSA2' 19 }); 20 21 router.get('/getback', function(req, res, next) { 22 // req 23 }); 24 25 router.get('/', function(req, res, next) { 26 var url= ali.webPay({ 27 body: "ttt", 28 subject: "ttt1", 29 outTradeId: "201503200101010222", 30 timeout: '90m', 31 amount: "0.1", 32 sellerId: '', 33 product_code: 'FAST_INSTANT_TRADE_PAY', 34 goods_type: "1", 35 return_url:"127.0.0.1:9000", 36 }) 37 38 var url_API = 'https://openapi.alipaydev.com/gateway.do?'+url; 39 res.json({url:url_API}) 40 }); 41 42 module.exports = router;
須要install crypto、request、fs 包支持app
2、支付寶開發平臺配置異步
登陸https://openhome.alipay.com/platform/developerIndex.htm,使用實名認證的支付寶帳號ide
點擊後進入沙箱環境配置頁面
大體界面以下
點擊設置密鑰。
這裏順便記錄下密鑰的用處:
經過支付寶密鑰生成工具會生成一個應用私鑰+一個應用公鑰,開發者經過把生成的應用公鑰上傳到這裏配置,會獲得支付寶生成的另外一個公鑰,記做支付寶公鑰。在項目中經過應用私鑰和支付寶公鑰簽名和以後的驗籤。
生成密鑰的工具下載 和 具體操做流程能夠參考支付寶文檔 : https://opendocs.alipay.com/open/291/106097/
注意選擇公鑰不要選擇證書,由於一旦選擇證書就不能夠使用RSA2的公鑰驗證了(血淚史),若是不當心使用過公鑰證書,請選擇RSA的密鑰作驗證,生成方法同RSA2
將生成的應用祕鑰和支付寶公鑰保存到項目中,即.pem後綴的文件(粘進來本身改後綴就行),另外須要添加密鑰文件的頭和尾
1 -----BEGIN RSA PRIVATE KEY----- 2 應用祕鑰 3 -----END RSA PRIVATE KEY-----
1 -----BEGIN PUBLIC KEY----- 2 支付寶公鑰 3 -----END PUBLIC KEY-----
最後項目路徑以下(僅供參考)
運行項目後,生成二維碼,用戶端經過沙箱版支付寶客戶端掃碼支付便可,商家和用戶帳號以下