Files
张成 8309808835 1
2025-11-21 16:53:49 +08:00

256 lines
10 KiB
JavaScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
'use strict';
const IOrder = require('./wx_ipay');
const util = require('../utils/util');
// 支付
class Pay extends IOrder {
constructor({ appid, mch_id, partner_key, pfx }) {
super({ appid, mch_id, partner_key, pfx });
}
// 初始化参数 请求
async init(params, name, properties) {
this._otherParams(params);
this._checkOptions(properties);
this._xml = this._jsontoxml();
const result = await this._request(name, this._xml);
return result;
}
// md5加密 暴露给外部调用
md5(params) {
return this._md5(params);
}
// HMAC-SHA256 加密 暴露给外部调用
hmac(params) {
return this._hmac(params);
}
// xml 转json 暴露给外部调用
xmltojson(data) {
return this._xmltojson(data);
}
// 统一下单
async unifiedorder(params) {
// 必传参数
const properties = ['body', 'out_trade_no', 'total_fee', 'spbill_create_ip', 'notify_url', 'trade_type'];
if (params.trade_type === 'JSAPI') properties.push('openid');
if (params.trade_type === 'NATIVE') properties.push('product_id');
if (params.trade_type === 'MWEB') {
properties.push('scene_info');
properties.push('redirect_url');
};
const result = await this.init(params, 'unifiedorder', properties);
const { prepay_id, return_code, return_msg, result_code } = result;
if (return_code !== 'SUCCESS' || result_code !== 'SUCCESS') return result;
// 参数处理
let _data = {};
switch (this._params.trade_type) {
case 'JSAPI':
_data['appId'] = this._params.appid;
_data['timeStamp'] = `${parseInt((+new Date()) / 1000)}`;
_data['package'] = `prepay_id=${prepay_id}`;
_data['nonceStr'] = util.getNonceStr().toLowerCase();
_data['signType'] = params['sign_type'] || 'MD5';
if (params['sign_type'] === 'HMAC-SHA256') {
_data['paySign'] = this._hmac(_data);
} else {
_data['paySign'] = this._md5(_data);
}
break;
case 'APP':
_data['appid'] = this._params.appid;
_data['timestamp'] = `${parseInt((+new Date()) / 1000)}`;
_data['partnerid'] = this._params.mch_id;
_data['prepayid'] = prepay_id;
_data['package'] = 'Sign=WXPay';
_data['noncestr'] = util.getNonceStr().toLowerCase();
if (params['sign_type'] === 'HMAC-SHA256') {
_data['sign'] = this._hmac(_data);
} else {
_data['sign'] = this._md5(_data);
}
break;
case 'NATIVE': // pc端网站 模式二
_data = { // 把code_url 生成图片
...result,
};
break;
case 'MWEB':
// 不能直接在浏览器中访问mweb_url,会报商家参数错误因为他会检测Referer,所以Referer不能为空
// 手机浏览器中支付 https://wx.tenpay.com/cgi-bin/mmpayweb-bin/checkmweb?prepay_id=wx20161110163838f231619da20804912345&package=1037687096&redirect_url=https%3A%2F%2Fwww.wechatpay.com.cn
_data = {
...result,
'mweb_url': result.mweb_url + `&redirect_url=${encodeURIComponent(this._params.redirect_url)}`,
};
break;
default:
console.error('trade_type参数有误');
_data = {};
}
const req_data = {
...this._params,
};
delete req_data['pfx'];
delete req_data['key'];
delete req_data['sign'];
return {
// req_data, // 创建订单的参数 用于回调验证
..._data,
return_code,
return_msg,
result_code,
};
}
// 支付回调验证
callback_check(data) {
let _sign = '';
if (data.sign_type === 'HMAC-SHA256') {
_sign = this._hmac(data);
} else {
_sign = this._md5(data);
}
return data.sign === _sign; // boolean true 成功
}
// 订单查询
async orderquery(params) {
// 必传参数
const properties = [];
if (!params.transaction_id && !params.out_trade_no) throw new Error('缺少参数transaction_id或out_trade_no!');
let reuslt = await this.init(params, 'orderquery', properties);
return reuslt;
}
// 关闭订单
async closeorder(params) {
const properties = ['out_trade_no'];
let reuslt = await this.init(params, 'closeorder', properties);
return reuslt;
}
// 申请退款
async refund(params) {
if (!params.transaction_id && !params.out_trade_no) throw new Error('缺少参数transaction_id或out_trade_no!');
if (!this._options.pfx) throw new Error('缺少pfx');
const properties = ['out_refund_no', 'total_fee', 'refund_fee'];
let reuslt = await this.init(params, 'refund', properties);
return reuslt;
}
// 查询退款
async refundquery(params) {
if (!params.transaction_id && !params.out_trade_no && !params.out_refund_no && !params.refund_id) {
throw new Error('缺少参数transaction_id或out_trade_no或refund_id或out_refund_no!');
}
const properties = [];
let reuslt = await this.init(params, 'refundquery', properties);
return reuslt;
}
// 下载交易账单
async downloadbill(params) {
this._otherParams(params);
const properties = ['bill_date'];
this._checkOptions(properties);
this._xml = this._jsontoxml();
const result = await this._request2('downloadbill', this._xml);
if (result.status !== 200 && result.statusCode !== 200) return result;
// 参数处理
if (result.type === 'application/x-gzip') {
return {
'data': result.body,
'return_code': 'SUCCESS',
};
} else if (result.type === 'text/plain') {
if (result.text.indexOf('<xml>') !== -1) return this._xmltojson(result.text);
return {
'data': result.text,
'return_code': 'SUCCESS',
};
}
return result;
}
// 下载资金账单
async downloadfundflow(params) {
this._otherParams(params);
if (params.sign_type !== 'HMAC-SHA256') throw new Error('请选择HMAC-SHA256加密');
if (!this._params.pfx) throw new Error('缺少pfx');
const properties = ['bill_date', 'account_type'];
this._checkOptions(properties);
this._xml = this._jsontoxml();
const result = await this._request2('downloadfundflow', this._xml);
if (result.status !== 200 && result.statusCode !== 200) return result;
// 参数处理
if (result.type === 'application/x-gzip') {
return {
'data': result.body,
'return_code': 'SUCCESS',
'result_code': 'SUCCESS',
};
} else if (result.type === 'text/plain') {
if (result.text.indexOf('<xml>') !== -1) return this._xmltojson(result.text);
return {
'data': result.text,
'return_code': 'SUCCESS',
'result_code': 'SUCCESS',
};
}
return result;
}
// 交易保障
async report(params) {
const properties = ['interface_url', 'execute_time_', 'return_code', 'result_code', 'user_ip'];
let reuslt = await this.init(params, 'report', properties);
return reuslt;
}
// 拉取订单评价数据
async batchquerycomment(params) {
this._otherParams(params);
const properties = ['begin_time', 'end_time', 'offset', 'limit'];
if (!this._params.pfx) throw new Error('缺少pfx');
this._checkOptions(properties);
this._xml = this._jsontoxml();
const result = await this._request2('batchquerycomment', this._xml);
if (result.status !== 200 && result.statusCode !== 200) return result;
// 参数处理
if (result.type === 'text/html') {
if (result.text.indexOf('<xml>') !== -1) {
return this._xmltojson(result.text);
}
return {
'data': result.text,
'return_code': 'SUCCESS',
'result_code': 'SUCCESS',
};
}
return result;
}
// 付款码支付
async micropay(params) {
const properties = ['body', 'out_trade_no', 'total_fee', 'spbill_create_ip', 'auth_code'];
let reuslt = await this.init(params, 'micropay', properties);
return reuslt;
}
// 撤销订单(只支持付款码支付的订单才可以撤销,统一下单生成的订单不能撤销)
async reverse(params) {
if (!params.transaction_id && !params.out_trade_no) throw new Error('缺少参数transaction_id或out_trade_no!');
const properties = [];
let reuslt = await this.init(params, 'reverse', properties);
return reuslt;
}
// 付款码查询openid
async authcodetoopenid(params) {
const properties = ['auth_code'];
let reuslt = await this.init(params, 'authcodetoopenid', properties);
return reuslt;
}
}
module.exports = Pay;