rapid-swiftpass
Version:
SwiftPass module
179 lines (163 loc) • 5.38 kB
JavaScript
/**
* Copyright (c) 2017 Lucky Byte, Inc.
*/
const debug = require('debug')('swiftpass');
const crypto = require('crypto');
const moment = require('moment');
const winston = require('winston');
const utils = require('../lib/utils');
const post = require('../lib/post');
/**
* 根据商户订单号查询订单信息
*
* 参数:
* dest_url: 威富通服务地址
* params: JSON,包含下列的 keys:
* pay_type: 支付方式,见下
* merno: 威富通平台内商户编号
* sign_key: 威富通商户签名密钥
* order_id: 平台内订单号,32 字符内,唯一
* amount: 交易金额,单位为分
* notify_url: 接收平台通知的 URL
* front_url: 交易完成后跳转 URL(可选)
* openid: 微信用户关注商家公众号的 openid,或者买家支付宝 userid
* appid: 微信公众号 APPID
*
* 支付方式(pay_type)取值如下:
* weixin: 微信支付
* alipay: 支付宝
* tenpay: QQ钱包
* jdpay: 京东支付
*
* 返回:
* 成功返回: {
* reqt: 请求报文
* resp: 响应报文
* succ: true
* pay_info: 支付信息
* token_id: 平台生成的预支付ID
* pay_url: 支付链接
* }
* 失败返回: {
* reqt: 请求报文
* resp: 响应报文
* succ: false
* errmsg: 错误信息
* }
*/
const exchange = async (dest_url, params) => {
if (!dest_url || !params) {
throw new Error('JS支付请求参数无效');
}
const required = [
'pay_type', 'merno', 'sign_key', 'order_id',
'amount', 'notify_url'
]
for (let i = 0; i < required.length; i++) {
if (!params[required[i]]) {
throw new Error(`JS支付请求缺少字段[${required[i]}]`);
}
}
const supported_type = [
'weixin', 'alipay', 'tenpay', 'jdpay'
]
if (supported_type.indexOf(params.pay_type) < 0) {
throw new Error(`支付方式[${params.pay_type}]无效`);
}
let reqt_json = {
service: `pay.${params.pay_type}.jspay`,
version: '2.0',
charset: 'UTF-8',
sign_type: 'MD5',
time_start: moment().format('YYYYMMDDHHmmss'),
time_expire: moment().add(60, 'minutes').format('YYYYMMDDHHmmss'),
nonce_str: crypto.randomBytes(16).toString('hex'),
mch_id: params.merno,
out_trade_no: params.order_id,
body: `订单${params.order_id}`,
total_fee: parseInt(params.amount),
mch_create_ip: '127.0.0.1',
notify_url: params.notify_url,
}
fix_reqt_by_pay_type(params, reqt_json);
reqt_json.sign = utils.gen_sign(reqt_json, params.sign_key);
winston.info('威富通JS支付请求报文:', JSON.stringify(reqt_json, null, 2));
const resp_data = await post(dest_url, reqt_json);
const resp_json = await utils.parse_resp_xml(resp_data);
winston.info('威富通JS支付响应报文:', JSON.stringify(resp_json, null, 2));
if (!utils.verify_sign(resp_json, params.sign_key)) {
throw new Error('验证威富通JS支付响应报文签名失败');
}
winston.info('验证威富通JS支付响应报文签名通过');
if (parseInt(resp_json.result_code) != 0) {
return {
reqt: reqt_json,
resp: resp_json,
succ: false,
errmsg: resp_json.err_msg || '交易失败'
}
}
let result = {
reqt: reqt_json,
resp: resp_json,
succ: true,
}
fix_resp_by_pay_type(resp_json, params.pay_type, result);
return result;
}
/**
* 根据支付方式补充请求参数
*/
const fix_reqt_by_pay_type = (params, reqt_json) => {
if (params.pay_type == 'alipay') {
if (!params.openid) {
throw new Error(`请求缺少[openid]字段`);
}
reqt_json.buyer_id = params.openid;
return;
}
if (params.front_url) {
reqt_json.callback_url = params.front_url;
}
if (params.pay_type == 'weixin') {
reqt_json.is_raw = '1';
reqt_json.is_minipg = '0';
if (!params.appid) {
throw new Error(`请求缺少[appid]字段`);
}
if (!params.openid) {
throw new Error(`请求缺少[openid]字段`);
}
reqt_json.sub_appid = params.appid;
reqt_json.sub_openid = params.openid;
}
}
/**
* 根据支付方式设置响应数据
*/
const fix_resp_by_pay_type = (resp_json, pay_type, result) => {
if (pay_type == 'alipay') {
result.pay_info = resp_json.pay_info;
result.pay_url = resp_json.pay_url;
return;
}
if (pay_type == 'weixin') {
result.pay_info = resp_json.pay_info;
result.token_id = resp_json.token_id;
return;
}
if (pay_type == 'tenpay') {
result.pay_info = resp_json.pay_info;
result.token_id = resp_json.token_id;
return;
}
if (pay_type == 'jdpay') {
result.pay_info = resp_json.pay_info;
result.token_id = resp_json.token_id;
result.pay_url = resp_json.pay_url;
return;
}
}
module.exports = {
exchange: exchange,
}