rapid-unipay
Version:
UnionPay module
119 lines (113 loc) • 4.12 kB
JavaScript
/**
* Copyright (c) 2017 Lucky Byte, Inc.
*/
const debug = require('debug')('unipay');
const moment = require('moment');
const winston = require('winston');
const utils = require('../lib/utils');
/**
* 构造手机网页支付 (WAP 支付) 请求数据报文
*
* 参数
* params: 一个 JSON 对象,包含下列的 key:
* * merno: 商户代码
* * cert_sn: 签名证书 Serial Number
* * sign_pem: 签名证书,PEM
* * back_url: 后台通知地址
* * front_url: 前台通知地址
* * front_fail_url: 失败交易前台跳转地址
* * order_id: 商户订单号
* * amount: 交易金额,以分为单位
* * acct_no: 卡号,可选
* * reserved: 保留域,可选
* * encrypt_cer: 加密证书,可选
* * encrypt_cer_sn: 加密证书编号,可选
* 返回
* JSON 报文,这个报文后续传递给 build_html() 生成可跳转支付网页
*/
const build_reqt = async (params) => {
if (!params) {
throw new Error('银联网页支付请求参数无效,用法 build_reqt({...})');
}
const required_keys = [
'merno', 'cert_sn', 'sign_pem', 'amount', 'order_id',
'back_url', 'front_url', 'front_fail_url'
]
for (let i = 0; i < required_keys.length; i++) {
const key = required_keys[i];
if (!params[key]) {
throw new Error(`银联网页支付请求参数缺少[${key}]`);
}
if (key.endsWith('_url') && !params[key].startsWith('http')) {
throw new Error(`银联网页支付请求[${key}][${params[key]}]格式错误`);
}
}
const amount = parseInt(params.amount);
if (!amount) {
throw new Error(`银联网页支付请求金额[${params.amount}]无效`);
}
let reqt_json = {
version: '5.0.0',
encoding: 'UTF-8',
signMethod: '01',
txnType: '01',
txnSubType: '01',
bizType: '000201',
channelType: '08',
accessType: '0',
currencyCode: '156',
txnTime: moment().format('YYYYMMDDHHmmss'),
certId: params.cert_sn,
merId: params.merno,
backUrl: params.back_url,
frontUrl: params.front_url,
frontFailUrl: params.front_fail_url,
orderId: params.order_id,
txnAmt: amount,
}
// 可以提供版本号,默认是 5.0.0
if (params.version) {
if (params.version != '5.0.0' && params.version != '5.1.0') {
throw new Error('参数 version 无效,必须是 5.0.0 或 5.1.0');
}
reqt_json.version = params.version;
}
// 如果提供了账号,则将其添加到请求中,可以进行锁卡
if (params.acct_no) {
if (!params.encrypt_cer) {
reqt_json.accNo = params.acct_no;
} else {
if (!params.encrypt_cer_sn) {
throw new Error('提供了加密证书,但未提供加密证书ID');
}
reqt_json.encryptCertId = params.encrypt_cer_sn;
reqt_json.accNo = utils.pubkey_encrypt(params.encrypt_cer, params.acct_no);
}
}
if (params.reserved) {
reqt_json.reserved = params.reserved;
}
reqt_json.signature = utils.gen_reqt_sign(reqt_json, params.sign_pem);
winston.info('银联网页支付请求报文:', JSON.stringify(reqt_json, null, 2));
return reqt_json;
}
/**
* 生成 HTML 页面在浏览器中打开将自动跳转到银联网关进行支付
*
* 参数
* dest_url: 银联网页支付请求地址
* reqt_json: 请求报文,JSON 格式,通过 build_reqt() 生成
* 返回
* HTML 网页,在客户端使用内置 WebView 打开此网页将自动跳转到银联网站进行支付
*/
const build_html = async (dest_url, reqt_json) => {
if (!dest_url || !reqt_json) {
throw new Error('参数无效,用法 build_html(dest_url, reqt_json)');
}
return utils.build_submit_html(dest_url, reqt_json, 'UnionPayWap');
}
module.exports = {
build_reqt: build_reqt,
build_html: build_html,
front_html: require('./front'),
}