index.js 42 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887
  1. 'use strict';
  2. var __extends = (this && this.__extends) || (function () {
  3. var extendStatics = function (d, b) {
  4. extendStatics = Object.setPrototypeOf ||
  5. ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
  6. function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };
  7. return extendStatics(d, b);
  8. };
  9. return function (d, b) {
  10. if (typeof b !== "function" && b !== null)
  11. throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
  12. extendStatics(d, b);
  13. function __() { this.constructor = d; }
  14. d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
  15. };
  16. })();
  17. var __assign = (this && this.__assign) || function () {
  18. __assign = Object.assign || function(t) {
  19. for (var s, i = 1, n = arguments.length; i < n; i++) {
  20. s = arguments[i];
  21. for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
  22. t[p] = s[p];
  23. }
  24. return t;
  25. };
  26. return __assign.apply(this, arguments);
  27. };
  28. var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
  29. function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
  30. return new (P || (P = Promise))(function (resolve, reject) {
  31. function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
  32. function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
  33. function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
  34. step((generator = generator.apply(thisArg, _arguments || [])).next());
  35. });
  36. };
  37. var __generator = (this && this.__generator) || function (thisArg, body) {
  38. var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
  39. return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
  40. function verb(n) { return function (v) { return step([n, v]); }; }
  41. function step(op) {
  42. if (f) throw new TypeError("Generator is already executing.");
  43. while (_) try {
  44. if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
  45. if (y = 0, t) op = [op[0] & 2, t.value];
  46. switch (op[0]) {
  47. case 0: case 1: t = op; break;
  48. case 4: _.label++; return { value: op[1], done: false };
  49. case 5: _.label++; y = op[1]; op = [0]; continue;
  50. case 7: op = _.ops.pop(); _.trys.pop(); continue;
  51. default:
  52. if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
  53. if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
  54. if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
  55. if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
  56. if (t[2]) _.ops.pop();
  57. _.trys.pop(); continue;
  58. }
  59. op = body.call(thisArg, _);
  60. } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
  61. if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
  62. }
  63. };
  64. var __importDefault = (this && this.__importDefault) || function (mod) {
  65. return (mod && mod.__esModule) ? mod : { "default": mod };
  66. };
  67. var crypto_1 = __importDefault(require("crypto"));
  68. var x509_1 = require('@fidm/x509');
  69. var base_1 = require("./lib/base");
  70. var Pay = /** @class */ (function (_super) {
  71. __extends(Pay, _super);
  72. function Pay(arg1, mchid, publicKey, privateKey, optipns) {
  73. var _this = _super.call(this) || this;
  74. _this.serial_no = ''; // 证书序列号
  75. _this.authType = 'WECHATPAY2-SHA256-RSA2048'; // 认证类型,目前为WECHATPAY2-SHA256-RSA2048
  76. if (arg1 instanceof Object) {
  77. _this.appid = arg1.appid;
  78. _this.mchid = arg1.mchid;
  79. if (arg1.serial_no)
  80. _this.serial_no = arg1.serial_no;
  81. _this.publicKey = arg1.publicKey;
  82. if (!_this.publicKey)
  83. throw new Error('缺少公钥');
  84. _this.privateKey = arg1.privateKey;
  85. if (!arg1.serial_no)
  86. _this.serial_no = _this.getSN(_this.publicKey);
  87. _this.authType = arg1.authType || 'WECHATPAY2-SHA256-RSA2048';
  88. _this.userAgent = arg1.userAgent || '127.0.0.1';
  89. _this.key = arg1.key;
  90. }
  91. else {
  92. var _optipns = optipns || {};
  93. _this.appid = arg1;
  94. _this.mchid = mchid || '';
  95. _this.publicKey = publicKey;
  96. _this.privateKey = privateKey;
  97. _this.authType = _optipns.authType || 'WECHATPAY2-SHA256-RSA2048';
  98. _this.userAgent = _optipns.userAgent || '127.0.0.1';
  99. _this.key = _optipns.key;
  100. _this.serial_no = _optipns.serial_no || '';
  101. if (!_this.publicKey)
  102. throw new Error('缺少公钥');
  103. if (!_this.serial_no)
  104. _this.serial_no = _this.getSN(_this.publicKey);
  105. }
  106. return _this;
  107. }
  108. /**
  109. * 获取微信平台key
  110. * @param apiSecret APIv3密钥
  111. * @returns
  112. */
  113. Pay.prototype.get_certificates = function (apiSecret) {
  114. return __awaiter(this, void 0, void 0, function () {
  115. var url, authorization, result, data, _i, data_1, item, decryptCertificate;
  116. return __generator(this, function (_a) {
  117. switch (_a.label) {
  118. case 0:
  119. url = 'https://api.mch.weixin.qq.com/v3/certificates';
  120. authorization = this.init('GET', url);
  121. return [4 /*yield*/, this.getRequest(url, authorization)];
  122. case 1:
  123. result = _a.sent();
  124. if (result.status === 200) {
  125. data = result.data;
  126. for (_i = 0, data_1 = data; _i < data_1.length; _i++) {
  127. item = data_1[_i];
  128. decryptCertificate = this.decipher_gcm(item.encrypt_certificate.ciphertext, item.encrypt_certificate.associated_data, item.encrypt_certificate.nonce, apiSecret);
  129. item.publicKey = x509_1.Certificate.fromPEM(Buffer.from(decryptCertificate)).publicKey.toPEM();
  130. }
  131. return [2 /*return*/, data];
  132. }
  133. else {
  134. throw new Error('拉取平台证书失败');
  135. }
  136. return [2 /*return*/];
  137. }
  138. });
  139. });
  140. };
  141. /**
  142. * 拉取平台证书到 Pay.certificates 中
  143. * @param apiSecret APIv3密钥
  144. * https://pay.weixin.qq.com/wiki/doc/apiv3/apis/wechatpay5_1.shtml
  145. */
  146. Pay.prototype.fetchCertificates = function (apiSecret) {
  147. return __awaiter(this, void 0, void 0, function () {
  148. var url, authorization, result, data, newCertificates_1;
  149. var _this = this;
  150. return __generator(this, function (_a) {
  151. switch (_a.label) {
  152. case 0:
  153. url = 'https://api.mch.weixin.qq.com/v3/certificates';
  154. authorization = this.init('GET', url);
  155. return [4 /*yield*/, this.getRequest(url, authorization)];
  156. case 1:
  157. result = _a.sent();
  158. if (result.status === 200) {
  159. data = result.data;
  160. newCertificates_1 = {};
  161. data.forEach(function (item) {
  162. var decryptCertificate = _this.decipher_gcm(item.encrypt_certificate.ciphertext, item.encrypt_certificate.associated_data, item.encrypt_certificate.nonce, apiSecret);
  163. newCertificates_1[item.serial_no] = x509_1.Certificate.fromPEM(Buffer.from(decryptCertificate)).publicKey.toPEM();
  164. });
  165. Pay.certificates = __assign(__assign({}, Pay.certificates), newCertificates_1);
  166. }
  167. else {
  168. throw new Error('拉取平台证书失败');
  169. }
  170. return [2 /*return*/];
  171. }
  172. });
  173. });
  174. };
  175. /**
  176. * 验证签名,提醒:node 取头部信息时需要用小写,例如:req.headers['wechatpay-timestamp']
  177. * @param params.timestamp HTTP头Wechatpay-Timestamp 中的应答时间戳
  178. * @param params.nonce HTTP头Wechatpay-Nonce 中的应答随机串
  179. * @param params.body 应答主体(response Body),需要按照接口返回的顺序进行验签,错误的顺序将导致验签失败。
  180. * @param params.serial HTTP头Wechatpay-Serial 证书序列号
  181. * @param params.signature HTTP头Wechatpay-Signature 签名
  182. * @param params.apiSecret APIv3密钥,如果在 构造器 中有初始化该值(this.key),则可以不传入。当然传入也可以
  183. */
  184. Pay.prototype.verifySign = function (params) {
  185. return __awaiter(this, void 0, void 0, function () {
  186. var timestamp, nonce, body, serial, signature, apiSecret, publicKey, bodyStr, data, verify;
  187. return __generator(this, function (_a) {
  188. switch (_a.label) {
  189. case 0:
  190. timestamp = params.timestamp, nonce = params.nonce, body = params.body, serial = params.serial, signature = params.signature, apiSecret = params.apiSecret;
  191. publicKey = Pay.certificates[serial];
  192. if (!!publicKey) return [3 /*break*/, 2];
  193. return [4 /*yield*/, this.fetchCertificates(apiSecret)];
  194. case 1:
  195. _a.sent();
  196. _a.label = 2;
  197. case 2:
  198. publicKey = Pay.certificates[serial];
  199. if (!publicKey) {
  200. throw new Error('平台证书序列号不相符,未找到平台序列号');
  201. }
  202. bodyStr = typeof body === 'string' ? body : JSON.stringify(body);
  203. data = "".concat(timestamp, "\n").concat(nonce, "\n").concat(bodyStr, "\n");
  204. verify = crypto_1.default.createVerify('RSA-SHA256');
  205. verify.update(data);
  206. return [2 /*return*/, verify.verify(publicKey, signature, 'base64')];
  207. }
  208. });
  209. });
  210. };
  211. /**
  212. * 敏感信息加密
  213. * @param str 敏感信息字段(如用户的住址、银行卡号、手机号码等)
  214. * @returns
  215. */
  216. Pay.prototype.publicEncrypt = function (str, wxPublicKey, padding) {
  217. if (padding === void 0) { padding = crypto_1.default.constants.RSA_PKCS1_OAEP_PADDING; }
  218. if (![crypto_1.default.constants.RSA_PKCS1_PADDING, crypto_1.default.constants.RSA_PKCS1_OAEP_PADDING].includes(padding)) {
  219. throw new Error("Doesn't supported the padding mode(".concat(padding, "), here's only support RSA_PKCS1_OAEP_PADDING or RSA_PKCS1_PADDING."));
  220. }
  221. var encrypted = crypto_1.default.publicEncrypt({ key: wxPublicKey, padding: padding, oaepHash: 'sha1' }, Buffer.from(str, 'utf8')).toString('base64');
  222. return encrypted;
  223. };
  224. /**
  225. * 敏感信息解密
  226. * @param str 敏感信息字段(如用户的住址、银行卡号、手机号码等)
  227. * @returns
  228. */
  229. Pay.prototype.privateDecrypt = function (str, padding) {
  230. if (padding === void 0) { padding = crypto_1.default.constants.RSA_PKCS1_OAEP_PADDING; }
  231. if (![crypto_1.default.constants.RSA_PKCS1_PADDING, crypto_1.default.constants.RSA_PKCS1_OAEP_PADDING].includes(padding)) {
  232. throw new Error("Doesn't supported the padding mode(".concat(padding, "), here's only support RSA_PKCS1_OAEP_PADDING or RSA_PKCS1_PADDING."));
  233. }
  234. var decrypted = crypto_1.default.privateDecrypt({ key: this.privateKey, padding: padding, oaepHash: 'sha1' }, Buffer.from(str, 'base64'));
  235. return decrypted.toString('utf8');
  236. };
  237. /**
  238. * 构建请求签名参数
  239. * @param method Http 请求方式
  240. * @param url 请求接口 例如/v3/certificates
  241. * @param timestamp 获取发起请求时的系统当前时间戳
  242. * @param nonceStr 随机字符串
  243. * @param body 请求报文主体
  244. */
  245. Pay.prototype.getSignature = function (method, nonce_str, timestamp, url, body) {
  246. var str = method + '\n' + url + '\n' + timestamp + '\n' + nonce_str + '\n';
  247. if (body && body instanceof Object)
  248. body = JSON.stringify(body);
  249. if (body)
  250. str = str + body + '\n';
  251. if (method === 'GET')
  252. str = str + '\n';
  253. return this.sha256WithRsa(str);
  254. };
  255. // jsapi 和 app 支付参数签名 加密自动顺序如下 不能错乱
  256. // 应用id
  257. // 时间戳
  258. // 随机字符串
  259. // 预支付交易会话ID
  260. Pay.prototype.sign = function (str) {
  261. return this.sha256WithRsa(str);
  262. };
  263. // 获取序列号
  264. Pay.prototype.getSN = function (fileData) {
  265. if (!fileData && !this.publicKey)
  266. throw new Error('缺少公钥');
  267. if (!fileData)
  268. fileData = this.publicKey;
  269. if (typeof fileData == 'string') {
  270. fileData = Buffer.from(fileData);
  271. }
  272. var certificate = x509_1.Certificate.fromPEM(fileData);
  273. return certificate.serialNumber;
  274. };
  275. /**
  276. * SHA256withRSA
  277. * @param data 待加密字符
  278. * @param privatekey 私钥key key.pem fs.readFileSync(keyPath)
  279. */
  280. Pay.prototype.sha256WithRsa = function (data) {
  281. if (!this.privateKey)
  282. throw new Error('缺少秘钥文件');
  283. return crypto_1.default
  284. .createSign('RSA-SHA256')
  285. .update(data)
  286. .sign(this.privateKey, 'base64');
  287. };
  288. /**
  289. * 获取授权认证信息
  290. * @param nonceStr 请求随机串
  291. * @param timestamp 时间戳
  292. * @param signature 签名值
  293. */
  294. Pay.prototype.getAuthorization = function (nonce_str, timestamp, signature) {
  295. var _authorization = 'mchid="' +
  296. this.mchid +
  297. '",' +
  298. 'nonce_str="' +
  299. nonce_str +
  300. '",' +
  301. 'timestamp="' +
  302. timestamp +
  303. '",' +
  304. 'serial_no="' +
  305. this.serial_no +
  306. '",' +
  307. 'signature="' +
  308. signature +
  309. '"';
  310. return this.authType.concat(' ').concat(_authorization);
  311. };
  312. /**
  313. * 回调解密
  314. * @param ciphertext Base64编码后的开启/停用结果数据密文
  315. * @param associated_data 附加数据
  316. * @param nonce 加密使用的随机串
  317. * @param key APIv3密钥
  318. */
  319. Pay.prototype.decipher_gcm = function (ciphertext, associated_data, nonce, key) {
  320. if (key)
  321. this.key = key;
  322. if (!this.key)
  323. throw new Error('缺少key');
  324. var _ciphertext = Buffer.from(ciphertext, 'base64');
  325. // 解密 ciphertext字符 AEAD_AES_256_GCM算法
  326. var authTag = _ciphertext.slice(_ciphertext.length - 16);
  327. var data = _ciphertext.slice(0, _ciphertext.length - 16);
  328. var decipher = crypto_1.default.createDecipheriv('aes-256-gcm', this.key, nonce);
  329. decipher.setAuthTag(authTag);
  330. decipher.setAAD(Buffer.from(associated_data));
  331. var decoded = decipher.update(data, undefined, 'utf8');
  332. decipher.final();
  333. try {
  334. return JSON.parse(decoded);
  335. }
  336. catch (e) {
  337. return decoded;
  338. }
  339. };
  340. /**
  341. * 参数初始化
  342. */
  343. Pay.prototype.init = function (method, url, params) {
  344. var nonce_str = Math.random()
  345. .toString(36)
  346. .substr(2, 15), timestamp = parseInt(+new Date() / 1000 + '').toString();
  347. var signature = this.getSignature(method, nonce_str, timestamp, url.replace('https://api.mch.weixin.qq.com', ''), params);
  348. var authorization = this.getAuthorization(nonce_str, timestamp, signature);
  349. return authorization;
  350. };
  351. // ---------------支付相关接口--------------//
  352. /**
  353. * h5支付
  354. * @param params 请求参数 object 参数介绍 请看文档https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter3_3_1.shtml
  355. */
  356. Pay.prototype.transactions_h5 = function (params) {
  357. return __awaiter(this, void 0, void 0, function () {
  358. var _params, url, authorization;
  359. return __generator(this, function (_a) {
  360. switch (_a.label) {
  361. case 0:
  362. _params = __assign({ appid: this.appid, mchid: this.mchid }, params);
  363. url = 'https://api.mch.weixin.qq.com/v3/pay/transactions/h5';
  364. authorization = this.init('POST', url, _params);
  365. return [4 /*yield*/, this.postRequest(url, _params, authorization)];
  366. case 1: return [2 /*return*/, _a.sent()];
  367. }
  368. });
  369. });
  370. };
  371. /**
  372. * 合单h5支付
  373. * @param params 请求参数 object 参数介绍 请看文档https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter5_1_2.shtml
  374. */
  375. Pay.prototype.combine_transactions_h5 = function (params) {
  376. return __awaiter(this, void 0, void 0, function () {
  377. var _params, url, authorization;
  378. return __generator(this, function (_a) {
  379. switch (_a.label) {
  380. case 0:
  381. _params = __assign({ combine_appid: this.appid, combine_mchid: this.mchid }, params);
  382. url = 'https://api.mch.weixin.qq.com/v3/combine-transactions/h5';
  383. authorization = this.init('POST', url, _params);
  384. return [4 /*yield*/, this.postRequest(url, _params, authorization)];
  385. case 1: return [2 /*return*/, _a.sent()];
  386. }
  387. });
  388. });
  389. };
  390. /**
  391. * native支付
  392. * @param params 请求参数 object 参数介绍 请看文档https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter3_4_1.shtml
  393. */
  394. Pay.prototype.transactions_native = function (params) {
  395. return __awaiter(this, void 0, void 0, function () {
  396. var _params, url, authorization;
  397. return __generator(this, function (_a) {
  398. switch (_a.label) {
  399. case 0:
  400. _params = __assign({ appid: this.appid, mchid: this.mchid }, params);
  401. url = 'https://api.mch.weixin.qq.com/v3/pay/transactions/native';
  402. authorization = this.init('POST', url, _params);
  403. return [4 /*yield*/, this.postRequest(url, _params, authorization)];
  404. case 1: return [2 /*return*/, _a.sent()];
  405. }
  406. });
  407. });
  408. };
  409. /**
  410. * 合单native支付
  411. * @param params 请求参数 object 参数介绍 请看文档https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter5_1_5.shtml
  412. */
  413. Pay.prototype.combine_transactions_native = function (params) {
  414. return __awaiter(this, void 0, void 0, function () {
  415. var _params, url, authorization;
  416. return __generator(this, function (_a) {
  417. switch (_a.label) {
  418. case 0:
  419. _params = __assign({ combine_appid: this.appid, combine_mchid: this.mchid }, params);
  420. url = 'https://api.mch.weixin.qq.com/v3/combine-transactions/native';
  421. authorization = this.init('POST', url, _params);
  422. return [4 /*yield*/, this.postRequest(url, _params, authorization)];
  423. case 1: return [2 /*return*/, _a.sent()];
  424. }
  425. });
  426. });
  427. };
  428. /**
  429. * app支付
  430. * @param params 请求参数 object 参数介绍 请看文档https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter3_2_1.shtml
  431. */
  432. Pay.prototype.transactions_app = function (params) {
  433. return __awaiter(this, void 0, void 0, function () {
  434. var _params, url, authorization, result, data, str;
  435. return __generator(this, function (_a) {
  436. switch (_a.label) {
  437. case 0:
  438. _params = __assign({ appid: this.appid, mchid: this.mchid }, params);
  439. url = 'https://api.mch.weixin.qq.com/v3/pay/transactions/app';
  440. authorization = this.init('POST', url, _params);
  441. return [4 /*yield*/, this.postRequest(url, _params, authorization)];
  442. case 1:
  443. result = _a.sent();
  444. if (result.status === 200 && result.prepay_id) {
  445. data = {
  446. status: result.status,
  447. appid: this.appid,
  448. partnerid: this.mchid,
  449. package: 'Sign=WXPay',
  450. timestamp: parseInt(+new Date() / 1000 + '').toString(),
  451. noncestr: Math.random()
  452. .toString(36)
  453. .substr(2, 15),
  454. prepayid: result.prepay_id,
  455. sign: '',
  456. };
  457. str = [data.appid, data.timestamp, data.noncestr, data.prepayid, ''].join('\n');
  458. data.sign = this.sign(str);
  459. return [2 /*return*/, data];
  460. }
  461. return [2 /*return*/, result];
  462. }
  463. });
  464. });
  465. };
  466. /**
  467. * 合单app支付
  468. * @param params 请求参数 object 参数介绍 请看文档https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter5_1_1.shtml
  469. */
  470. Pay.prototype.combine_transactions_app = function (params) {
  471. return __awaiter(this, void 0, void 0, function () {
  472. var _params, url, authorization, result, data, str;
  473. return __generator(this, function (_a) {
  474. switch (_a.label) {
  475. case 0:
  476. _params = __assign({ combine_appid: this.appid, combine_mchid: this.mchid }, params);
  477. url = 'https://api.mch.weixin.qq.com/v3/combine-transactions/app';
  478. authorization = this.init('POST', url, _params);
  479. return [4 /*yield*/, this.postRequest(url, _params, authorization)];
  480. case 1:
  481. result = _a.sent();
  482. if (result.status === 200 && result.prepay_id) {
  483. data = {
  484. status: result.status,
  485. appid: this.appid,
  486. partnerid: this.mchid,
  487. package: 'Sign=WXPay',
  488. timestamp: parseInt(+new Date() / 1000 + '').toString(),
  489. noncestr: Math.random()
  490. .toString(36)
  491. .substr(2, 15),
  492. prepayid: result.prepay_id,
  493. sign: '',
  494. };
  495. str = [data.appid, data.timestamp, data.noncestr, data.prepayid, ''].join('\n');
  496. data.sign = this.sign(str);
  497. return [2 /*return*/, data];
  498. }
  499. return [2 /*return*/, result];
  500. }
  501. });
  502. });
  503. };
  504. /**
  505. * JSAPI支付 或者 小程序支付
  506. * @param params 请求参数 object 参数介绍 请看文档https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter3_1_1.shtml
  507. */
  508. Pay.prototype.transactions_jsapi = function (params) {
  509. return __awaiter(this, void 0, void 0, function () {
  510. var _params, url, authorization, result, data, str;
  511. return __generator(this, function (_a) {
  512. switch (_a.label) {
  513. case 0:
  514. _params = __assign({ appid: this.appid, mchid: this.mchid }, params);
  515. url = 'https://api.mch.weixin.qq.com/v3/pay/transactions/jsapi';
  516. authorization = this.init('POST', url, _params);
  517. return [4 /*yield*/, this.postRequest(url, _params, authorization)];
  518. case 1:
  519. result = _a.sent();
  520. if (result.status === 200 && result.prepay_id) {
  521. data = {
  522. status: result.status,
  523. appId: this.appid,
  524. timeStamp: parseInt(+new Date() / 1000 + '').toString(),
  525. nonceStr: Math.random()
  526. .toString(36)
  527. .substr(2, 15),
  528. package: "prepay_id=".concat(result.prepay_id),
  529. signType: 'RSA',
  530. paySign: '',
  531. };
  532. str = [data.appId, data.timeStamp, data.nonceStr, data.package, ''].join('\n');
  533. data.paySign = this.sign(str);
  534. return [2 /*return*/, data];
  535. }
  536. return [2 /*return*/, result];
  537. }
  538. });
  539. });
  540. };
  541. /**
  542. * 合单JSAPI支付 或者 小程序支付
  543. * @param params 请求参数 object 参数介绍 请看文档https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter5_1_3.shtml
  544. */
  545. Pay.prototype.combine_transactions_jsapi = function (params) {
  546. return __awaiter(this, void 0, void 0, function () {
  547. var _params, url, authorization, result, data, str;
  548. return __generator(this, function (_a) {
  549. switch (_a.label) {
  550. case 0:
  551. _params = __assign({ combine_appid: this.appid, combine_mchid: this.mchid }, params);
  552. url = 'https://api.mch.weixin.qq.com/v3/combine-transactions/jsapi';
  553. authorization = this.init('POST', url, _params);
  554. return [4 /*yield*/, this.postRequest(url, _params, authorization)];
  555. case 1:
  556. result = _a.sent();
  557. if (result.status === 200 && result.prepay_id) {
  558. data = {
  559. status: result.status,
  560. appId: this.appid,
  561. timeStamp: parseInt(+new Date() / 1000 + '').toString(),
  562. nonceStr: Math.random()
  563. .toString(36)
  564. .substr(2, 15),
  565. package: "prepay_id=".concat(result.prepay_id),
  566. signType: 'RSA',
  567. paySign: '',
  568. };
  569. str = [data.appId, data.timeStamp, data.nonceStr, data.package, ''].join('\n');
  570. data.paySign = this.sign(str);
  571. return [2 /*return*/, data];
  572. }
  573. return [2 /*return*/, result];
  574. }
  575. });
  576. });
  577. };
  578. /**
  579. * 查询订单
  580. * @param params 请求参数 object 参数介绍 请看文档https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter3_3_2.shtml
  581. */
  582. Pay.prototype.query = function (params) {
  583. return __awaiter(this, void 0, void 0, function () {
  584. var url, authorization;
  585. return __generator(this, function (_a) {
  586. switch (_a.label) {
  587. case 0:
  588. url = '';
  589. if (params.transaction_id) {
  590. url = "https://api.mch.weixin.qq.com/v3/pay/transactions/id/".concat(params.transaction_id, "?mchid=").concat(this.mchid);
  591. }
  592. else if (params.out_trade_no) {
  593. url = "https://api.mch.weixin.qq.com/v3/pay/transactions/out-trade-no/".concat(params.out_trade_no, "?mchid=").concat(this.mchid);
  594. }
  595. else {
  596. throw new Error('缺少transaction_id或者out_trade_no');
  597. }
  598. authorization = this.init('GET', url);
  599. return [4 /*yield*/, this.getRequest(url, authorization)];
  600. case 1: return [2 /*return*/, _a.sent()];
  601. }
  602. });
  603. });
  604. };
  605. /**
  606. * 合单查询订单
  607. * @param params 请求参数 object 参数介绍 请看文档https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter5_1_11.shtml
  608. */
  609. Pay.prototype.combine_query = function (combine_out_trade_no) {
  610. return __awaiter(this, void 0, void 0, function () {
  611. var url, authorization;
  612. return __generator(this, function (_a) {
  613. switch (_a.label) {
  614. case 0:
  615. if (!combine_out_trade_no)
  616. throw new Error('缺少combine_out_trade_no');
  617. url = "https://api.mch.weixin.qq.com/v3/combine-transactions/out-trade-no/".concat(combine_out_trade_no);
  618. authorization = this.init('GET', url);
  619. return [4 /*yield*/, this.getRequest(url, authorization)];
  620. case 1: return [2 /*return*/, _a.sent()];
  621. }
  622. });
  623. });
  624. };
  625. /**
  626. * 关闭订单
  627. * @param out_trade_no 请求参数 商户订单号 参数介绍 请看文档https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter3_3_3.shtml
  628. */
  629. Pay.prototype.close = function (out_trade_no) {
  630. return __awaiter(this, void 0, void 0, function () {
  631. var _params, url, authorization;
  632. return __generator(this, function (_a) {
  633. switch (_a.label) {
  634. case 0:
  635. if (!out_trade_no)
  636. throw new Error('缺少out_trade_no');
  637. _params = {
  638. mchid: this.mchid,
  639. };
  640. url = "https://api.mch.weixin.qq.com/v3/pay/transactions/out-trade-no/".concat(out_trade_no, "/close");
  641. authorization = this.init('POST', url, _params);
  642. return [4 /*yield*/, this.postRequest(url, _params, authorization)];
  643. case 1: return [2 /*return*/, _a.sent()];
  644. }
  645. });
  646. });
  647. };
  648. /**
  649. * 合单关闭订单
  650. * @param combine_out_trade_no 请求参数 总订单号 参数介绍 请看文档https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter5_1_12.shtml
  651. * @param sub_orders array 子单信息
  652. */
  653. Pay.prototype.combine_close = function (combine_out_trade_no, sub_orders) {
  654. return __awaiter(this, void 0, void 0, function () {
  655. var _params, url, authorization;
  656. return __generator(this, function (_a) {
  657. switch (_a.label) {
  658. case 0:
  659. if (!combine_out_trade_no)
  660. throw new Error('缺少out_trade_no');
  661. _params = {
  662. combine_appid: this.appid,
  663. sub_orders: sub_orders,
  664. };
  665. url = "https://api.mch.weixin.qq.com/v3/combine-transactions/out-trade-no/".concat(combine_out_trade_no, "/close");
  666. authorization = this.init('POST', url, _params);
  667. return [4 /*yield*/, this.postRequest(url, _params, authorization)];
  668. case 1: return [2 /*return*/, _a.sent()];
  669. }
  670. });
  671. });
  672. };
  673. /**
  674. * 申请交易账单
  675. * @param params 请求参数 object 参数介绍 请看文档https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter3_1_6.shtml
  676. */
  677. Pay.prototype.tradebill = function (params) {
  678. return __awaiter(this, void 0, void 0, function () {
  679. var url, _params, querystring, authorization;
  680. return __generator(this, function (_a) {
  681. switch (_a.label) {
  682. case 0:
  683. url = 'https://api.mch.weixin.qq.com/v3/bill/tradebill';
  684. _params = __assign({}, params);
  685. querystring = Object.keys(_params)
  686. .filter(function (key) {
  687. return !!_params[key];
  688. })
  689. .sort()
  690. .map(function (key) {
  691. return key + '=' + _params[key];
  692. })
  693. .join('&');
  694. url = url + "?".concat(querystring);
  695. authorization = this.init('GET', url);
  696. return [4 /*yield*/, this.getRequest(url, authorization)];
  697. case 1: return [2 /*return*/, _a.sent()];
  698. }
  699. });
  700. });
  701. };
  702. /**
  703. * 申请资金账单
  704. * @param params 请求参数 object 参数介绍 请看文档https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter3_1_7.shtml
  705. */
  706. Pay.prototype.fundflowbill = function (params) {
  707. return __awaiter(this, void 0, void 0, function () {
  708. var url, _params, querystring, authorization;
  709. return __generator(this, function (_a) {
  710. switch (_a.label) {
  711. case 0:
  712. url = 'https://api.mch.weixin.qq.com/v3/bill/fundflowbill';
  713. _params = __assign({}, params);
  714. querystring = Object.keys(_params)
  715. .filter(function (key) {
  716. return !!_params[key];
  717. })
  718. .sort()
  719. .map(function (key) {
  720. return key + '=' + _params[key];
  721. })
  722. .join('&');
  723. url = url + "?".concat(querystring);
  724. authorization = this.init('GET', url);
  725. return [4 /*yield*/, this.getRequest(url, authorization)];
  726. case 1: return [2 /*return*/, _a.sent()];
  727. }
  728. });
  729. });
  730. };
  731. /**
  732. * 下载账单
  733. * @param download_url 请求参数 路径 参数介绍 请看文档https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter3_1_8.shtml
  734. */
  735. Pay.prototype.downloadbill = function (download_url) {
  736. return __awaiter(this, void 0, void 0, function () {
  737. var authorization;
  738. return __generator(this, function (_a) {
  739. switch (_a.label) {
  740. case 0:
  741. authorization = this.init('GET', download_url);
  742. return [4 /*yield*/, this.getRequest(download_url, authorization)];
  743. case 1: return [2 /*return*/, _a.sent()];
  744. }
  745. });
  746. });
  747. };
  748. /**
  749. * 申请退款
  750. * @param params 请求参数 路径 参数介绍 请看文档https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter3_2_9.shtml
  751. */
  752. Pay.prototype.refunds = function (params) {
  753. return __awaiter(this, void 0, void 0, function () {
  754. var url, _params, authorization;
  755. return __generator(this, function (_a) {
  756. switch (_a.label) {
  757. case 0:
  758. url = 'https://api.mch.weixin.qq.com/v3/refund/domestic/refunds';
  759. _params = __assign({}, params);
  760. authorization = this.init('POST', url, _params);
  761. return [4 /*yield*/, this.postRequest(url, _params, authorization)];
  762. case 1: return [2 /*return*/, _a.sent()];
  763. }
  764. });
  765. });
  766. };
  767. /**
  768. * 查询单笔退款
  769. * @documentation 请求参数 路径 参数介绍 请看文档https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter3_2_10.shtml
  770. */
  771. Pay.prototype.find_refunds = function (out_refund_no) {
  772. return __awaiter(this, void 0, void 0, function () {
  773. var url, authorization;
  774. return __generator(this, function (_a) {
  775. switch (_a.label) {
  776. case 0:
  777. if (!out_refund_no)
  778. throw new Error('缺少out_refund_no');
  779. url = "https://api.mch.weixin.qq.com/v3/refund/domestic/refunds/".concat(out_refund_no);
  780. authorization = this.init('GET', url);
  781. return [4 /*yield*/, this.getRequest(url, authorization)];
  782. case 1: return [2 /*return*/, _a.sent()];
  783. }
  784. });
  785. });
  786. };
  787. /**
  788. * 发起商家转账零钱
  789. * @documentation 请看文档https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter4_3_1.shtml
  790. */
  791. Pay.prototype.batches_transfer = function (params) {
  792. return __awaiter(this, void 0, void 0, function () {
  793. var url, _params, serial_no, authorization;
  794. return __generator(this, function (_a) {
  795. switch (_a.label) {
  796. case 0:
  797. url = 'https://api.mch.weixin.qq.com/v3/transfer/batches';
  798. _params = __assign({ appid: this.appid }, params);
  799. serial_no = _params === null || _params === void 0 ? void 0 : _params.wx_serial_no;
  800. delete _params.wx_serial_no;
  801. authorization = this.init('POST', url, _params);
  802. return [4 /*yield*/, this.postRequestV2(url, _params, authorization, { 'Wechatpay-Serial': serial_no || this.serial_no })];
  803. case 1: return [2 /*return*/, _a.sent()];
  804. }
  805. });
  806. });
  807. };
  808. /**
  809. * 微信批次单号查询批次单API
  810. * @documentation 请看文档https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter4_3_2.shtml
  811. */
  812. Pay.prototype.query_batches_transfer_list_wx = function (params) {
  813. return __awaiter(this, void 0, void 0, function () {
  814. var baseUrl, url, authorization;
  815. return __generator(this, function (_a) {
  816. switch (_a.label) {
  817. case 0:
  818. baseUrl = "https://api.mch.weixin.qq.com/v3/transfer/batches/batch-id/".concat(params.batch_id);
  819. url = baseUrl + this.objectToQueryString(params, ['batch_id']);
  820. authorization = this.init('GET', url);
  821. return [4 /*yield*/, this.getRequestV2(url, authorization)];
  822. case 1: return [2 /*return*/, _a.sent()];
  823. }
  824. });
  825. });
  826. };
  827. /**
  828. * 微信明细单号查询明细单API
  829. * @documentation 请看文档https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter4_3_3.shtml
  830. */
  831. Pay.prototype.query_batches_transfer_detail_wx = function (params) {
  832. return __awaiter(this, void 0, void 0, function () {
  833. var baseUrl, url, authorization;
  834. return __generator(this, function (_a) {
  835. switch (_a.label) {
  836. case 0:
  837. baseUrl = "https://api.mch.weixin.qq.com/v3/transfer/batches/batch-id/".concat(params.batch_id, "/details/detail-id/").concat(params.detail_id);
  838. url = baseUrl + this.objectToQueryString(params, ['batch_id', 'detail_id']);
  839. authorization = this.init('GET', url);
  840. return [4 /*yield*/, this.getRequestV2(url, authorization)];
  841. case 1: return [2 /*return*/, _a.sent()];
  842. }
  843. });
  844. });
  845. };
  846. /**
  847. * 商家批次单号查询批次单API
  848. * @documentation 请看文档https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter4_3_5.shtml
  849. */
  850. Pay.prototype.query_batches_transfer_list = function (params) {
  851. return __awaiter(this, void 0, void 0, function () {
  852. var baseUrl, url, authorization;
  853. return __generator(this, function (_a) {
  854. switch (_a.label) {
  855. case 0:
  856. baseUrl = "https://api.mch.weixin.qq.com/v3/transfer/batches/out-batch-no/".concat(params.out_batch_no);
  857. url = baseUrl + this.objectToQueryString(params, ['out_batch_no']);
  858. authorization = this.init('GET', url);
  859. return [4 /*yield*/, this.getRequestV2(url, authorization)];
  860. case 1: return [2 /*return*/, _a.sent()];
  861. }
  862. });
  863. });
  864. };
  865. /**
  866. * 商家明细单号查询明细单API
  867. * @documentation 请看文档https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter4_3_6.shtml
  868. */
  869. Pay.prototype.query_batches_transfer_detail = function (params) {
  870. return __awaiter(this, void 0, void 0, function () {
  871. var baseUrl, url, authorization;
  872. return __generator(this, function (_a) {
  873. switch (_a.label) {
  874. case 0:
  875. baseUrl = "https://api.mch.weixin.qq.com/v3/transfer/batches/out-batch-no/".concat(params.out_batch_no, "/details/out-detail-no/").concat(params.out_detail_no);
  876. url = baseUrl + this.objectToQueryString(params, ['out_batch_no', 'out_detail_no']);
  877. authorization = this.init('GET', url);
  878. return [4 /*yield*/, this.getRequestV2(url, authorization)];
  879. case 1: return [2 /*return*/, _a.sent()];
  880. }
  881. });
  882. });
  883. };
  884. Pay.certificates = {}; // 微信平台证书 key 是 serialNo, value 是 publicKey
  885. return Pay;
  886. }(base_1.Base));
  887. module.exports = Pay;