koa3-wechat
Version:
wechat api modified by windsome.feng
1,233 lines (1,026 loc) • 41 kB
JavaScript
'use strict';
Object.defineProperty(exports, "__esModule", {
value: true
});
var _keys = require('babel-runtime/core-js/object/keys');
var _keys2 = _interopRequireDefault(_keys);
var _promise = require('babel-runtime/core-js/promise');
var _promise2 = _interopRequireDefault(_promise);
var _objectWithoutProperties2 = require('babel-runtime/helpers/objectWithoutProperties');
var _objectWithoutProperties3 = _interopRequireDefault(_objectWithoutProperties2);
var _regenerator = require('babel-runtime/regenerator');
var _regenerator2 = _interopRequireDefault(_regenerator);
var _extends2 = require('babel-runtime/helpers/extends');
var _extends3 = _interopRequireDefault(_extends2);
var _asyncToGenerator2 = require('babel-runtime/helpers/asyncToGenerator');
var _asyncToGenerator3 = _interopRequireDefault(_asyncToGenerator2);
var _classCallCheck2 = require('babel-runtime/helpers/classCallCheck');
var _classCallCheck3 = _interopRequireDefault(_classCallCheck2);
var _createClass2 = require('babel-runtime/helpers/createClass');
var _createClass3 = _interopRequireDefault(_createClass2);
var _rawBody = require('raw-body');
var _rawBody2 = _interopRequireDefault(_rawBody);
var _xml2js = require('xml2js');
var _xml2js2 = _interopRequireDefault(_xml2js);
var _request2 = require('request');
var _request3 = _interopRequireDefault(_request2);
var _https = require('https');
var _https2 = _interopRequireDefault(_https);
var _url = require('url');
var _url2 = _interopRequireDefault(_url);
var _md5sum = require('./_md5sum');
var _md5sum2 = _interopRequireDefault(_md5sum);
var _sha1sum = require('./_sha1sum');
var _sha1sum2 = _interopRequireDefault(_sha1sum);
var _crypto = require('crypto');
var _crypto2 = _interopRequireDefault(_crypto);
var _debug2 = require('debug');
var _debug3 = _interopRequireDefault(_debug2);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
var debug = (0, _debug3.default)('app:wepay');
var signTypes = {
MD5: _md5sum2.default,
SHA1: _sha1sum2.default
};
var URLS_NORMAL = {
UNIFIED_ORDER: 'https://api.mch.weixin.qq.com/pay/unifiedorder',
ORDER_QUERY: 'https://api.mch.weixin.qq.com/pay/orderquery',
REFUND: 'https://api.mch.weixin.qq.com/secapi/pay/refund',
REFUND_QUERY: 'https://api.mch.weixin.qq.com/pay/refundquery',
DOWNLOAD_BILL: 'https://api.mch.weixin.qq.com/pay/downloadbill',
SHORT_URL: 'https://api.mch.weixin.qq.com/tools/shorturl',
CLOSE_ORDER: 'https://api.mch.weixin.qq.com/pay/closeorder',
REDPACK_SEND: 'https://api.mch.weixin.qq.com/mmpaymkttransfers/sendredpack',
REDPACK_GROUP_SEND: 'https://api.mch.weixin.qq.com/mmpaymkttransfers/sendgroupredpack',
REDPACK_QUERY: 'https://api.mch.weixin.qq.com/mmpaymkttransfers/gethbinfo',
TRANSFERS: 'https://api.mch.weixin.qq.com/mmpaymkttransfers/promotion/transfers',
GET_TRANSFER_INFO: 'https://api.mch.weixin.qq.com/mmpaymkttransfers/gettransferinfo',
PAY_BANK: 'https://api.mch.weixin.qq.com/mmpaysptrans/pay_bank',
QUERY_BANK: 'https://api.mch.weixin.qq.com/mmpaysptrans/query_bank'
};
var URLS_SANDBOX = {
GET_SIGN_KEY: 'https://api.mch.weixin.qq.com/sandboxnew/pay/getsignkey',
UNIFIED_ORDER: 'https://api.mch.weixin.qq.com/sandboxnew/pay/unifiedorder',
ORDER_QUERY: 'https://api.mch.weixin.qq.com/sandboxnew/pay/orderquery',
REFUND: 'https://api.mch.weixin.qq.com/secapi/sandboxnew/pay/refund',
REFUND_QUERY: 'https://api.mch.weixin.qq.com/sandboxnew/pay/refundquery',
DOWNLOAD_BILL: 'https://api.mch.weixin.qq.com/sandboxnew/pay/downloadbill',
SHORT_URL: 'https://api.mch.weixin.qq.com/tools/shorturl',
CLOSE_ORDER: 'https://api.mch.weixin.qq.com/sandboxnew/pay/closeorder',
REDPACK_SEND: 'https://api.mch.weixin.qq.com/mmpaymkttransfers/sendredpack',
REDPACK_GROUP_SEND: 'https://api.mch.weixin.qq.com/mmpaymkttransfers/sendgroupredpack',
REDPACK_QUERY: 'https://api.mch.weixin.qq.com/mmpaymkttransfers/gethbinfo',
TRANSFERS: 'https://api.mch.weixin.qq.com/mmpaymkttransfers/promotion/transfers',
GET_TRANSFER_INFO: 'https://api.mch.weixin.qq.com/mmpaymkttransfers/gettransferinfo',
PAY_BANK: 'https://api.mch.weixin.qq.com/mmpaysptrans/pay_bank',
QUERY_BANK: 'https://api.mch.weixin.qq.com/mmpaysptrans/query_bank'
};
var PAY_BANK_GETPUBLICKEY = 'https://fraud.mch.weixin.qq.com/risk/getpublickey';
//let URLS = URLS_SANDBOX;
var URLS = URLS_NORMAL;
var Wepay = function () {
function Wepay() {
var config = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
(0, _classCallCheck3.default)(this, Wepay);
this.appId = config.appId;
this.subAppId = config.subAppId;
this.partnerKey = config.partnerKey;
this.orignPartnerKey = config.partnerKey;
this.mchId = config.mchId;
this.subMchId = config.subMchId;
this.notifyUrl = config.notifyUrl;
this.passphrase = config.passphrase || config.mchId;
this.pfx = config.pfx;
}
/**
* 微信内H5调起支付
* 见: <https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=7_7&index=6>
* 在微信浏览器里面打开H5网页中执行JS调起支付。接口输入输出数据格式为JSON。
* 注意:WeixinJSBridge内置对象在其他浏览器中无效。
* @param {*} order 订单信息
*/
(0, _createClass3.default)(Wepay, [{
key: 'getBrandWCPayRequestParams',
value: function () {
var _ref = (0, _asyncToGenerator3.default)( /*#__PURE__*/_regenerator2.default.mark(function _callee(order) {
var self, default_params, retobj, params;
return _regenerator2.default.wrap(function _callee$(_context) {
while (1) {
switch (_context.prev = _context.next) {
case 0:
self = this;
default_params = {
appId: this.appId,
timeStamp: this._generateTimeStamp(),
nonceStr: this._generateNonceStr(),
signType: 'MD5'
};
order = (0, _extends3.default)({ notify_url: this.notifyUrl }, order);
_context.next = 5;
return this.unifiedOrder(order);
case 5:
retobj = _context.sent;
params = (0, _extends3.default)({}, default_params, {
package: 'prepay_id=' + retobj.prepay_id
});
//if (order.total_fee) params.total_fee = order.total_fee+"";
params.paySign = this._getSign(params);
if (order.trade_type == 'NATIVE') {
params.code_url = retobj.code_url;
}
params.timestamp = params.timeStamp;
return _context.abrupt('return', params);
case 11:
case 'end':
return _context.stop();
}
}
}, _callee, this);
}));
function getBrandWCPayRequestParams(_x2) {
return _ref.apply(this, arguments);
}
return getBrandWCPayRequestParams;
}()
/**
* Generate parameters for `WeixinJSBridge.invoke('editAddress', parameters)`.
*
* @param {String} data.url Referer URL that call the API. *Note*: Must contain `code` and `state` in querystring.
* @param {String} data.accessToken
* @param {Function} callback(err, params)
*
* @see https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=7_9
*/
}, {
key: 'getEditAddressParams',
value: function getEditAddressParams(data) {
if (!(data && data.url && data.accessToken)) {
throw new Error('Missing url or accessToken, url=' + (data && data.url) + ', accessToken=' + (data && data.accessToken));
}
var params = {
appId: this.appId,
scope: 'jsapi_address',
signType: 'SHA1',
timeStamp: this._generateTimeStamp(),
nonceStr: this._generateNonceStr()
};
var signParams = {
appid: params.appId,
url: data.url,
timestamp: params.timeStamp,
noncestr: params.nonceStr,
accesstoken: data.accessToken
};
var string = this._toQueryString(signParams);
params.addrSign = signTypes[params.signType](string);
return params;
}
/**
* 获取sandbox测试key
*/
}, {
key: 'getSignKey',
value: function () {
var _ref2 = (0, _asyncToGenerator3.default)( /*#__PURE__*/_regenerator2.default.mark(function _callee2() {
var params, retobj;
return _regenerator2.default.wrap(function _callee2$(_context2) {
while (1) {
switch (_context2.prev = _context2.next) {
case 0:
if (URLS.GET_SIGN_KEY) {
_context2.next = 2;
break;
}
throw new Error('not in sandbox mode!');
case 2:
params = {
mch_id: this.mchId,
nonce_str: this._generateNonceStr()
};
this.partnerKey = this.orignPartnerKey;
_context2.next = 6;
return this.sendAndReceiveData(URLS.GET_SIGN_KEY, params);
case 6:
retobj = _context2.sent;
if (retobj.sandbox_signkey) {
debug('set partnerKey from ', this.partnerKey, ' to ', retobj.sandbox_signkey);
this.partnerKey = retobj.sandbox_signkey;
}
return _context2.abrupt('return', retobj);
case 9:
case 'end':
return _context2.stop();
}
}
}, _callee2, this);
}));
function getSignKey() {
return _ref2.apply(this, arguments);
}
return getSignKey;
}()
/**
* 统一下单接口
* 见:<https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_1>
* 除被扫支付场景以外,商户系统先调用该接口在微信支付服务后台生成预支付交易单,返回正确的预支付交易回话标识后再按扫码、JSAPI、APP等不同场景生成交易串调起支付。
* @param {*} params 订单信息
*/
}, {
key: 'unifiedOrder',
value: function () {
var _ref3 = (0, _asyncToGenerator3.default)( /*#__PURE__*/_regenerator2.default.mark(function _callee3(params) {
var requiredData;
return _regenerator2.default.wrap(function _callee3$(_context3) {
while (1) {
switch (_context3.prev = _context3.next) {
case 0:
requiredData = ['body', 'out_trade_no', 'total_fee', 'spbill_create_ip', 'trade_type'];
if (params.trade_type == 'JSAPI') {
requiredData.push('openid|sub_openid');
requiredData.push('appid|sub_appid');
} else if (params.trade_type == 'NATIVE') {
requiredData.push('product_id');
}
params.notify_url = params.notify_url || this.notifyUrl;
_context3.next = 5;
return this.sendAndReceiveData(URLS.UNIFIED_ORDER, params, {
required: requiredData
});
case 5:
return _context3.abrupt('return', _context3.sent);
case 6:
case 'end':
return _context3.stop();
}
}
}, _callee3, this);
}));
function unifiedOrder(_x3) {
return _ref3.apply(this, arguments);
}
return unifiedOrder;
}()
/**
* 订单查询
* @param {*} params 订单信息
* transaction_id (微信订单号)或 out_trade_no (用户订单号)
*/
}, {
key: 'orderQuery',
value: function () {
var _ref4 = (0, _asyncToGenerator3.default)( /*#__PURE__*/_regenerator2.default.mark(function _callee4(params) {
return _regenerator2.default.wrap(function _callee4$(_context4) {
while (1) {
switch (_context4.prev = _context4.next) {
case 0:
_context4.next = 2;
return this.sendAndReceiveData(URLS.ORDER_QUERY, params, {
required: ['transaction_id|out_trade_no']
});
case 2:
return _context4.abrupt('return', _context4.sent);
case 3:
case 'end':
return _context4.stop();
}
}
}, _callee4, this);
}));
function orderQuery(_x4) {
return _ref4.apply(this, arguments);
}
return orderQuery;
}()
/**
* 退款
* @param {*} params 退款单信息
* 必填信息:['transaction_id|out_trade_no', 'out_refund_no', 'total_fee', 'refund_fee']
*/
}, {
key: 'refund',
value: function () {
var _ref5 = (0, _asyncToGenerator3.default)( /*#__PURE__*/_regenerator2.default.mark(function _callee5(params) {
return _regenerator2.default.wrap(function _callee5$(_context5) {
while (1) {
switch (_context5.prev = _context5.next) {
case 0:
//params = this._extendWithDefault(params, ['op_user_id']);
//params = { op_user_id: this.mchId, ...params };
params = (0, _extends3.default)({ op_user_id: this.subMchId }, params);
_context5.next = 3;
return this.sendAndReceiveData(URLS.REFUND, params, {
required: ['transaction_id|out_trade_no', 'out_refund_no', 'total_fee', 'refund_fee'],
useCert: true
});
case 3:
return _context5.abrupt('return', _context5.sent);
case 4:
case 'end':
return _context5.stop();
}
}
}, _callee5, this);
}));
function refund(_x5) {
return _ref5.apply(this, arguments);
}
return refund;
}()
/**
* 退款查询
* @param {*} params
* 必填信息:['transaction_id|out_trade_no|out_refund_no|refund_id']
*/
}, {
key: 'refundQuery',
value: function () {
var _ref6 = (0, _asyncToGenerator3.default)( /*#__PURE__*/_regenerator2.default.mark(function _callee6(params) {
return _regenerator2.default.wrap(function _callee6$(_context6) {
while (1) {
switch (_context6.prev = _context6.next) {
case 0:
_context6.next = 2;
return this.sendAndReceiveData(URLS.REFUND_QUERY, params, {
required: ['transaction_id|out_trade_no|out_refund_no|refund_id']
});
case 2:
return _context6.abrupt('return', _context6.sent);
case 3:
case 'end':
return _context6.stop();
}
}
}, _callee6, this);
}));
function refundQuery(_x6) {
return _ref6.apply(this, arguments);
}
return refundQuery;
}()
/**
* 下载订单流水
* @param {*} params 退款查询字段
* 必填信息:['bill_date', 'bill_type']
*/
}, {
key: 'downloadBill',
value: function () {
var _ref7 = (0, _asyncToGenerator3.default)( /*#__PURE__*/_regenerator2.default.mark(function _callee7(params) {
var data, rows, toArr;
return _regenerator2.default.wrap(function _callee7$(_context7) {
while (1) {
switch (_context7.prev = _context7.next) {
case 0:
_context7.next = 2;
return this.sendAndReceiveData(URLS.DOWNLOAD_BILL, params, {
required: ['bill_date', 'bill_type']
});
case 2:
data = _context7.sent;
if (!(data.type === 'text')) {
_context7.next = 9;
break;
}
// parse xml fail, parse csv.
rows = data.xml.trim().split(/\r?\n/);
toArr = function toArr(rows) {
var titles = rows[0].split(',');
var bodys = rows.splice(1);
var data = [];
bodys.forEach(function (row) {
var rowData = {};
row.split(',').forEach(function (cell, i) {
rowData[titles[i]] = cell.split('`')[1];
});
data.push(rowData);
});
return data;
};
return _context7.abrupt('return', {
list: toArr(rows.slice(0, rows.length - 2)),
stat: toArr(rows.slice(rows.length - 2, rows.length))[0]
});
case 9:
return _context7.abrupt('return', null);
case 10:
case 'end':
return _context7.stop();
}
}
}, _callee7, this);
}));
function downloadBill(_x7) {
return _ref7.apply(this, arguments);
}
return downloadBill;
}()
/**
* 长连接转短链接
* @param {*} params
* 必填信息:['long_url']
*/
}, {
key: 'shortUrl',
value: function () {
var _ref8 = (0, _asyncToGenerator3.default)( /*#__PURE__*/_regenerator2.default.mark(function _callee8(params) {
return _regenerator2.default.wrap(function _callee8$(_context8) {
while (1) {
switch (_context8.prev = _context8.next) {
case 0:
_context8.next = 2;
return this.sendAndReceiveData(URLS.SHORT_URL, params, {
required: ['long_url']
});
case 2:
return _context8.abrupt('return', _context8.sent);
case 3:
case 'end':
return _context8.stop();
}
}
}, _callee8, this);
}));
function shortUrl(_x8) {
return _ref8.apply(this, arguments);
}
return shortUrl;
}()
/**
* 关闭订单
* @param {*} params
* 必填信息:['out_trade_no']
*/
}, {
key: 'closeOrder',
value: function () {
var _ref9 = (0, _asyncToGenerator3.default)( /*#__PURE__*/_regenerator2.default.mark(function _callee9(params) {
return _regenerator2.default.wrap(function _callee9$(_context9) {
while (1) {
switch (_context9.prev = _context9.next) {
case 0:
_context9.next = 2;
return this.sendAndReceiveData(URLS.CLOSE_ORDER, params, {
required: ['out_trade_no']
});
case 2:
return _context9.abrupt('return', _context9.sent);
case 3:
case 'end':
return _context9.stop();
}
}
}, _callee9, this);
}));
function closeOrder(_x9) {
return _ref9.apply(this, arguments);
}
return closeOrder;
}()
/**
* 发放普通红包
* TODO: 注意里面没有appid, 但存在wxappid,
* @param {*} params
*/
}, {
key: 'sendRedPacket',
value: function () {
var _ref10 = (0, _asyncToGenerator3.default)( /*#__PURE__*/_regenerator2.default.mark(function _callee10(params) {
var requiredData;
return _regenerator2.default.wrap(function _callee10$(_context10) {
while (1) {
switch (_context10.prev = _context10.next) {
case 0:
requiredData = ['wxappid', 'mch_billno', 'send_name', 're_openid', 'total_amount', 'total_num', 'wishing', 'client_ip', 'act_name', 'remark'];
_context10.next = 3;
return this.sendAndReceiveData(URLS.REDPACK_SEND, (0, _extends3.default)({}, params, { wxappid: this.appId }), { required: requiredData, useCert: true, removed: ['appid'] });
case 3:
return _context10.abrupt('return', _context10.sent);
case 4:
case 'end':
return _context10.stop();
}
}
}, _callee10, this);
}));
function sendRedPacket(_x10) {
return _ref10.apply(this, arguments);
}
return sendRedPacket;
}()
/**
* 发放裂变红包
* 裂变红包:一次可以发放一组红包。首先领取的用户为种子用户,种子用户领取一组红包当中的一个,并可以通过社交分享将剩下的红包给其他用户。裂变红包充分利用了人际传播的优势。
* 见: <https://pay.weixin.qq.com/wiki/doc/api/tools/cash_coupon.php?chapter=13_5&index=4>
* @param {*} params
*/
}, {
key: 'sendRedPacketGroup',
value: function () {
var _ref11 = (0, _asyncToGenerator3.default)( /*#__PURE__*/_regenerator2.default.mark(function _callee11(params) {
var requiredData;
return _regenerator2.default.wrap(function _callee11$(_context11) {
while (1) {
switch (_context11.prev = _context11.next) {
case 0:
requiredData = ['wxappid', 'mch_billno', 'send_name', 're_openid', 'total_amount', 'total_num', 'amt_type', 'wishing', 'act_name', 'remark'];
_context11.next = 3;
return this.sendAndReceiveData(URLS.REDPACK_GROUP_SEND, (0, _extends3.default)({}, params, { wxappid: this.appId }), { required: requiredData, useCert: true, removed: ['appid'] });
case 3:
return _context11.abrupt('return', _context11.sent);
case 4:
case 'end':
return _context11.stop();
}
}
}, _callee11, this);
}));
function sendRedPacketGroup(_x11) {
return _ref11.apply(this, arguments);
}
return sendRedPacketGroup;
}()
/**
* 查询红包记录
* 见: <https://pay.weixin.qq.com/wiki/doc/api/tools/cash_coupon.php?chapter=13_6&index=5>
* @param {*} params
*/
}, {
key: 'redPacketQuery',
value: function () {
var _ref12 = (0, _asyncToGenerator3.default)( /*#__PURE__*/_regenerator2.default.mark(function _callee12(params) {
var requiredData;
return _regenerator2.default.wrap(function _callee12$(_context12) {
while (1) {
switch (_context12.prev = _context12.next) {
case 0:
requiredData = ['mch_billno'];
_context12.next = 3;
return this.sendAndReceiveData(URLS.REDPACK_QUERY, (0, _extends3.default)({}, params, { bill_type: 'MCHT' }), { required: requiredData, useCert: true });
case 3:
return _context12.abrupt('return', _context12.sent);
case 4:
case 'end':
return _context12.stop();
}
}
}, _callee12, this);
}));
function redPacketQuery(_x12) {
return _ref12.apply(this, arguments);
}
return redPacketQuery;
}()
////////////////////////////////////////////////////////////
// 企业付款
////////////////////////////////////////////////////////////
/**
* 企业付款到用户微信零钱
* 企业付款业务是基于微信支付商户平台的资金管理能力,为了协助商户方便地实现企业向个人付款,针对部分有开发能力的商户,提供通过API完成企业付款的功能。
* 比如目前的保险行业向客户退保、给付、理赔。
* 企业付款将使用商户的可用余额,需确保可用余额充足。查看可用余额、充值、提现请登录商户平台“资金管理”进行操作。
* 见: <https://pay.weixin.qq.com/wiki/doc/api/tools/mch_pay.php?chapter=14_2>
* @param {*} params 支付参数
* 必选参数: ['partner_trade_no', 'openid', 'check_name', 'amount', 'desc', 'spbill_create_ip']
*/
}, {
key: 'transfers',
value: function () {
var _ref13 = (0, _asyncToGenerator3.default)( /*#__PURE__*/_regenerator2.default.mark(function _callee13(params) {
var requiredData;
return _regenerator2.default.wrap(function _callee13$(_context13) {
while (1) {
switch (_context13.prev = _context13.next) {
case 0:
requiredData = ['partner_trade_no', 'openid', 'check_name', 'amount', 'desc', 'spbill_create_ip'];
_context13.next = 3;
return this.sendAndReceiveData(URLS.TRANSFERS, params, {
required: requiredData,
useCert: true
});
case 3:
return _context13.abrupt('return', _context13.sent);
case 4:
case 'end':
return _context13.stop();
}
}
}, _callee13, this);
}));
function transfers(_x13) {
return _ref13.apply(this, arguments);
}
return transfers;
}()
/**
* 查询企业付款
* 用于商户的企业付款操作进行结果查询,返回付款操作详细结果。
* 查询企业付款API只支持查询30天内的订单,30天之前的订单请登录商户平台查询。
* @param {*} params
* 必选参数: ['partner_trade_no']
*/
}, {
key: 'getTransferInfo',
value: function () {
var _ref14 = (0, _asyncToGenerator3.default)( /*#__PURE__*/_regenerator2.default.mark(function _callee14(params) {
var requiredData;
return _regenerator2.default.wrap(function _callee14$(_context14) {
while (1) {
switch (_context14.prev = _context14.next) {
case 0:
requiredData = ['partner_trade_no'];
_context14.next = 3;
return this.sendAndReceiveData(URLS.GET_TRANSFER_INFO, params, {
required: requiredData,
useCert: true
});
case 3:
return _context14.abrupt('return', _context14.sent);
case 4:
case 'end':
return _context14.stop();
}
}
}, _callee14, this);
}));
function getTransferInfo(_x14) {
return _ref14.apply(this, arguments);
}
return getTransferInfo;
}()
/**
* 企业付款到银行卡
* 见: <https://pay.weixin.qq.com/wiki/doc/api/tools/mch_pay.php?chapter=24_2>
* @param {*} params 支付参数
* 必选参数: ['partner_trade_no', 'enc_bank_no', 'enc_true_name', 'bank_code', 'amount']
*/
}, {
key: 'payBank',
value: function () {
var _ref15 = (0, _asyncToGenerator3.default)( /*#__PURE__*/_regenerator2.default.mark(function _callee15(params) {
var _ref16, bank_no, true_name, rest, publicKey, enc_bank_no, enc_true_name, newParams, requiredData;
return _regenerator2.default.wrap(function _callee15$(_context15) {
while (1) {
switch (_context15.prev = _context15.next) {
case 0:
_ref16 = params || {}, bank_no = _ref16.bank_no, true_name = _ref16.true_name, rest = (0, _objectWithoutProperties3.default)(_ref16, ['bank_no', 'true_name']);
if (!(!bank_no || !true_name)) {
_context15.next = 3;
break;
}
throw new Error('missing required bank_no or true_name!');
case 3:
_context15.next = 5;
return this.payBank_getPublicKey();
case 5:
publicKey = _context15.sent;
enc_bank_no = _crypto2.default.publicEncrypt(publicKey, new Buffer(bank_no)).toString('base64');
enc_true_name = _crypto2.default.publicEncrypt(publicKey, new Buffer(true_name)).toString('base64');
newParams = (0, _extends3.default)({}, rest, { enc_bank_no: enc_bank_no, enc_true_name: enc_true_name });
requiredData = ['partner_trade_no', 'enc_bank_no', 'enc_true_name', 'bank_code', 'amount'];
_context15.next = 12;
return this.sendAndReceiveData(URLS.PAY_BANK, newParams, {
required: requiredData,
useCert: true
});
case 12:
return _context15.abrupt('return', _context15.sent);
case 13:
case 'end':
return _context15.stop();
}
}
}, _callee15, this);
}));
function payBank(_x15) {
return _ref15.apply(this, arguments);
}
return payBank;
}()
/**
* 获取RSA公钥API
* 用来加密银行卡号,姓名等信息,payBank中会用。
* 将密文传给微信侧相应字段,如付款接口(enc_bank_no/enc_true_name)
* 接口默认输出PKCS#1格式的公钥,商户需根据自己开发的语言选择公钥格式
*/
}, {
key: 'payBank_getPublicKey',
value: function () {
var _ref17 = (0, _asyncToGenerator3.default)( /*#__PURE__*/_regenerator2.default.mark(function _callee16() {
var result;
return _regenerator2.default.wrap(function _callee16$(_context16) {
while (1) {
switch (_context16.prev = _context16.next) {
case 0:
if (this._bankPublicKey) {
_context16.next = 6;
break;
}
_context16.next = 3;
return this.sendAndReceiveData(PAY_BANK_GETPUBLICKEY, null, null, true);
case 3:
result = _context16.sent;
console.log('get public key result:', result);
if (result.return_code == 'SUCCESS' && result.result_code == 'SUCCESS') {
this._bankPublicKey = result.pub_key;
}
case 6:
return _context16.abrupt('return', this._bankPublicKey);
case 7:
case 'end':
return _context16.stop();
}
}
}, _callee16, this);
}));
function payBank_getPublicKey() {
return _ref17.apply(this, arguments);
}
return payBank_getPublicKey;
}()
/**
* 查询企业付款银行卡API
* 用于对商户企业付款到银行卡操作进行结果查询,返回付款操作详细结果。
* 见: <https://pay.weixin.qq.com/wiki/doc/api/tools/mch_pay.php?chapter=24_3>
* @param {*} params
* 必选参数: ['partner_trade_no']
*/
}, {
key: 'queryBank',
value: function () {
var _ref18 = (0, _asyncToGenerator3.default)( /*#__PURE__*/_regenerator2.default.mark(function _callee17(params) {
var requiredData;
return _regenerator2.default.wrap(function _callee17$(_context17) {
while (1) {
switch (_context17.prev = _context17.next) {
case 0:
requiredData = ['partner_trade_no'];
_context17.next = 3;
return this.sendAndReceiveData(URLS.QUERY_BANK, params, {
required: requiredData,
useCert: true
});
case 3:
return _context17.abrupt('return', _context17.sent);
case 4:
case 'end':
return _context17.stop();
}
}
}, _callee17, this);
}));
function queryBank(_x16) {
return _ref18.apply(this, arguments);
}
return queryBank;
}()
////////////////////////////////////////////////////////////
// send and receive data:
////////////////////////////////////////////////////////////
}, {
key: 'sendAndReceiveData',
value: function () {
var _ref19 = (0, _asyncToGenerator3.default)( /*#__PURE__*/_regenerator2.default.mark(function _callee18(url, params, options) {
var _ref20, _ref20$required, required, _ref20$useCert, useCert, _ref20$removed, removed, defaults, key, missing, requestFn, xml, data, errmsg;
return _regenerator2.default.wrap(function _callee18$(_context18) {
while (1) {
switch (_context18.prev = _context18.next) {
case 0:
_ref20 = options || {}, _ref20$required = _ref20.required, required = _ref20$required === undefined ? [] : _ref20$required, _ref20$useCert = _ref20.useCert, useCert = _ref20$useCert === undefined ? false : _ref20$useCert, _ref20$removed = _ref20.removed, removed = _ref20$removed === undefined ? [] : _ref20$removed;
defaults = {
appid: this.appId,
mch_id: this.mchId,
nonce_str: this._generateNonceStr()
};
if (this.subAppId && this.subMchId) {
defaults = (0, _extends3.default)({}, defaults, {
sub_appid: this.subAppId,
sub_mch_id: this.subMchId
});
}
params = params || {};
params = (0, _extends3.default)({}, defaults, params);
params.sign = this._getSign(params);
if (params.long_url) {
params.long_url = encodeURIComponent(params.long_url);
}
for (key in params) {
if (params[key] !== undefined && params[key] !== null) {
params[key] = params[key].toString();
}
}
removed && removed.forEach(function (key) {
if (params.hasOwnProperty(key)) {
delete params[key];
}
});
missing = [];
required && required.forEach(function (key) {
var alters = key.split('|');
for (var i = alters.length - 1; i >= 0; i--) {
if (params[alters[i]]) {
return;
}
}
missing.push(key);
});
if (!missing.length) {
_context18.next = 14;
break;
}
debug('error! missing params ' + missing.join(','));
throw new Error('missing params ' + missing.join(','));
case 14:
requestFn = (useCert ? this._requestWithCert : this._request).bind(this);
debug('request:', params);
xml = null;
data = null;
_context18.prev = 18;
_context18.next = 21;
return requestFn(url, this._buildXml(params));
case 21:
xml = _context18.sent;
_context18.next = 24;
return this._parseXml(xml);
case 24:
data = _context18.sent;
_context18.next = 31;
break;
case 27:
_context18.prev = 27;
_context18.t0 = _context18['catch'](18);
debug('parse xml fail! error=', _context18.t0);
return _context18.abrupt('return', { type: 'text', xml: xml });
case 31:
debug('response: parsed=', data, ', orginXml=', xml);
if (!(data.return_code == 'SUCCESS' && data.result_code == 'SUCCESS')) {
_context18.next = 36;
break;
}
debug('pay success!');
_context18.next = 39;
break;
case 36:
debug('error! pay fail!');
errmsg = data.err_code_des || data.err_code || data.result_code || data.return_msg;
throw new Error('pay fail! ' + errmsg);
case 39:
return _context18.abrupt('return', data);
case 40:
case 'end':
return _context18.stop();
}
}
}, _callee18, this, [[18, 27]]);
}));
function sendAndReceiveData(_x17, _x18, _x19) {
return _ref19.apply(this, arguments);
}
return sendAndReceiveData;
}()
}, {
key: 'notifyParse',
value: function () {
var _ref21 = (0, _asyncToGenerator3.default)( /*#__PURE__*/_regenerator2.default.mark(function _callee19(xml) {
return _regenerator2.default.wrap(function _callee19$(_context19) {
while (1) {
switch (_context19.prev = _context19.next) {
case 0:
_context19.next = 2;
return this._parseXml(xml);
case 2:
return _context19.abrupt('return', _context19.sent);
case 3:
case 'end':
return _context19.stop();
}
}
}, _callee19, this);
}));
function notifyParse(_x20) {
return _ref21.apply(this, arguments);
}
return notifyParse;
}()
}, {
key: 'notifyResult',
value: function notifyResult(params) {
return this._buildXml(params);
}
////////////////////////////////////////////////////////////
// util functions:
////////////////////////////////////////////////////////////
}, {
key: '_request',
value: function _request(url, data) {
return new _promise2.default(function (resolve, reject) {
(0, _request3.default)({
url: url,
method: 'POST',
body: data
}, function (err, response, body) {
if (err) reject(err);else resolve(body);
});
});
}
}, {
key: '_requestWithCert',
value: function _requestWithCert(url, data) {
var _this = this;
return new _promise2.default(function (resolve, reject) {
var parsed_url = _url2.default.parse(url);
var opts = {
host: parsed_url.host,
port: 443,
path: parsed_url.path,
pfx: _this.pfx,
passphrase: _this.passphrase,
method: 'POST'
};
debug('_requestWithCert:', opts);
var req = _https2.default.request(opts, function (res) {
var content = '';
res.on('data', function (chunk) {
content += chunk;
});
res.on('end', function () {
resolve(content);
});
});
req.on('error', function (e) {
reject(e);
});
req.write(data);
req.end();
});
}
}, {
key: '_buildXml',
value: function _buildXml(obj) {
var builder = new _xml2js2.default.Builder({
allowSurrogateChars: true
});
var xml = builder.buildObject({
xml: obj
});
//console.dir (xml);
return xml;
}
}, {
key: '_parseXml',
value: function _parseXml(xml) {
return new _promise2.default(function (resolve, reject) {
var parser = new _xml2js2.default.Parser({
trim: true,
explicitArray: false
});
parser.parseString(xml, function (err, result) {
//console.dir(result);
if (err) reject(err);else resolve(result.xml);
});
});
}
}, {
key: '_getSign',
value: function _getSign(pkg, signType) {
var sign = pkg.sign,
pkg2 = (0, _objectWithoutProperties3.default)(pkg, ['sign']);
signType = signType || 'MD5';
var string1 = this._toQueryString(pkg2);
var stringSignTemp = string1 + '&key=' + this.partnerKey;
var signValue = signTypes[signType](stringSignTemp).toUpperCase();
return signValue;
}
}, {
key: '_toQueryString',
value: function _toQueryString(object) {
return (0, _keys2.default)(object).filter(function (key) {
return object[key] !== undefined && object[key] !== '';
}).sort().map(function (key) {
return key + '=' + object[key];
}).join('&');
}
}, {
key: '_generateTimeStamp',
value: function _generateTimeStamp() {
return '' + Math.floor(new Date() / 1000);
}
/**
* [_generateNonceStr description]
* @param {[type]} length [description]
* @return {[type]} [description]
*/
}, {
key: '_generateNonceStr',
value: function _generateNonceStr(length) {
var chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
var maxPos = chars.length;
var noceStr = '';
for (var i = 0; i < (length || 32); i++) {
noceStr += chars.charAt(Math.floor(Math.random() * maxPos));
}
return noceStr;
}
}]);
return Wepay;
}();
exports.default = Wepay;