forked from dedemao/alipay_nodejs
-
Notifications
You must be signed in to change notification settings - Fork 0
/
alipay.js
184 lines (166 loc) · 6.63 KB
/
alipay.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
const crypto = require('crypto');
const request = require('request');
const ALIPAY_ALGORITHM_MAPPING = {
RSA: 'RSA-SHA1',
RSA2: 'RSA-SHA256',
};
class alipayService {
constructor(config) {
if (!config.appid) throw Error('config.appid is required');
if (!config.rsa_private_key) throw Error('config.rsa_private_key is required');
if (!config.method) throw Error('config.method is required');
this.appid = config.appid
this.rsa_private_key = config.rsa_private_key
this.method = config.method
this.method_type = config.method_type ? config.method_type :''
this.alipay_public_key = config.alipay_public_key
this.sign_type = 'RSA2'
this.return_url = config.return_url
this.notify_url = config.notify_url
this.charset = 'utf-8'
this.gateway = 'https://openapi.alipay.com/gateway.do?charset=' + this.charset
}
//发起支付
doPay(requestParams = {}) {
//请求参数
let commonParams = {
//公共参数
'app_id': this.appid,
'method': this.method, //接口名称
'format': 'JSON',
'charset': this.charset,
'sign_type': 'RSA2',
'version': '1.0',
'timestamp': `${this.getCurrentTime()}`,
};
if (this.return_url) {
commonParams.return_url = this.return_url
}
if (this.notify_url) {
commonParams.notify_url = this.notify_url
}
if (requestParams && JSON.stringify(requestParams) != "{}") {
commonParams.biz_content = requestParams;
}
commonParams = this.sign(commonParams);
if (this.method_type == 'page')
return this.buildRequestForm(commonParams)
else return this.postData(commonParams)
}
postData(params = {}) {
return new Promise((resolve, reject) => {
request.post({
url: this.gateway,
form: params,
}, function (error, response, body) {
if (!error && response.statusCode == 200) {
body = JSON.parse(body)
const responseKey = `${params.method.replace(/\./g, '_')}_response`
const response = body[responseKey]
if (response.code == '10000')
resolve(response)
else
reject(response)
} else {
console.log(error)
reject(error)
}
})
})
}
sign(params) {
if (params.biz_content)
params.biz_content = JSON.stringify(params.biz_content);
//获取签名字符串
const signStr = this.getSignContent(params);
let privateKey = this.rsa_private_key
privateKey = "-----BEGIN RSA PRIVATE KEY-----\n" +
(function () {
let arr = [];
let offset = 0;
while (true) {
let str = privateKey.substr(offset, 64);
if (str == '') {
break;
}
arr.push(str);
offset += 64;
}
return arr.join("\n");
})() +
"\n-----END RSA PRIVATE KEY-----";
// 计算签名
const sign = crypto.createSign(ALIPAY_ALGORITHM_MAPPING[params.sign_type])
.update(signStr, 'utf8').sign(privateKey, 'base64');
return Object.assign(params, {sign});
}
getCurrentTime() {
let date = new Date();
let month = (date.getMonth() + 1).toString().padStart(2, '0');
let dateStr = date.getDate().toString().padStart(2, '0');
let hourStr = date.getHours().toString().padStart(2, '0');
let minutesStr = date.getMinutes().toString().padStart(2, '0');
let secondsStr = date.getSeconds().toString().padStart(2, '0');
//时间格式YYYY-mm-dd HH:MM:SS
return `${date.getFullYear()}-${month}-${dateStr} ${hourStr}:${minutesStr}:${secondsStr}`;
}
buildRequestForm(params) {
let sHtml = "正在跳转至支付页面...<form id='alipaysubmit' name='alipaysubmit' action='https://openapi.alipay.com/gateway.do?charset=" + this.charset + "' method='POST'>";
Object.keys(params).map((key) => {
const value = String(params[key]).replace(/\"/g, '"');
// const value = params[key];
sHtml += `<input type="hidden" name="${key}" value="${value}" />`;
}).join('')
//submit按钮控件请不要含有name属性
sHtml = sHtml + "<input type='submit' value='ok' style='display:none;''></form>";
sHtml = sHtml + "<script>document.forms['alipaysubmit'].submit();</script>";
return sHtml;
}
//验证签名
rsaCheck(params) {
let sign_type = params.sign_type;
let sign = params.sign;
delete params.sign_type;
delete params.sign;
return this.verify(this.getSignContent(params), sign, sign_type);
}
//获取签名字符串
getSignContent(params) {
// 排序
const signStr = Object.keys(params).sort().map((key) => {
let data = params[key];
if (data && Array.prototype.toString.call(data) !== '[object String]') {
data = JSON.stringify(data);
}
return `${key}=${data}`;
}).join('&');
return signStr
}
//验证签名
verify(paramStr, sign, signType) {
let publicKey = this.alipay_public_key
// 未设置“支付宝公钥”或签名字符串不存在,验签不通过
if (!publicKey || !paramStr) {
return false;
}
publicKey = "-----BEGIN PUBLIC KEY-----\n" +
(function () {
let arr = [];
let offset = 0;
while (true) {
let str = publicKey.substr(offset, 64);
if (str == '') {
break;
}
arr.push(str);
offset += 64;
}
return arr.join("\n");
})() +
"\n-----END PUBLIC KEY-----";
// 计算签名
const verifier = crypto.createVerify(ALIPAY_ALGORITHM_MAPPING[signType]);
return verifier.update(paramStr, 'utf8').verify(publicKey, sign, 'base64');
}
}
module.exports = alipayService