hn-hlw-service/alipayApi/minialiplay.js
2026-07-27 11:28:33 +08:00

278 lines
11 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.

let alipay = require("alipay-sdk");
const AlipaySdkConfig = {
appId: process.env.CONFIG_ALIPAY_MINI_APPID,
privateKey:process.env.CONFIG_ALIPAY_MINI_PRIVATE_KEY,
alipayPublicKey:process.env.CONFIG_ALIPAY_MINI_PUBLIC_KEY,
};
const AlipaySdk = alipay.AlipaySdk;
const alipaySdk = new AlipaySdk(AlipaySdkConfig);
const notifyUrl = process.env.CONFIG_ALIPAY_PAY_NOTIFY
console.log('===============支付宝AppId')
console.log(AlipaySdkConfig.appId)
console.log('===============支付宝公钥')
console.log(AlipaySdkConfig.alipayPublicKey)
console.log('===============支付宝私钥')
console.log(AlipaySdkConfig.privateKey)
const TradeStatus = {
WAIT_BUYER_PAY: 'WAIT_BUYER_PAY',//交易创建,等待买家付款
TRADE_CLOSED: 'TRADE_CLOSED',//未付款交易超时关闭,或支付完成后全额退款
TRADE_SUCCESS: 'TRADE_SUCCESS',//交易成功
TRADE_FINISHED: 'TRADE_FINISHED',//交易完成
}
class aliplayApi {
/**
* 获取accToken
* @param {obj} param0
*/
static async accToken({ code }) {
try {
let params = {
grantType: 'authorization_code',
code,
};
let options = {};
let res = await alipaySdk.exec("alipay.system.oauth.token", params, options);
const accessToken = res && res.accessToken ? res.accessToken : '';
if (accessToken) return accessToken
return Promise.reject({ message: res && res.subMsg ? res.subMsg : '获取token失败' });
}
catch (e) {
return Promise.reject({ message: e.message || '获取token失败' });
}
}
/**
* 获取用户信息
* @param {obj} param0
*/
static async userInfo(auth_token) {
try {
let res = await alipaySdk.exec("alipay.user.info.share", { auth_token }, {});
if (res && res.code === '10000') {
const { avatar, certNo, mobile, userName, userId } = res;
return { avatar, certNo, mobile, userName, userId };
}
return Promise.reject({ message: res && res.subMsg ? res.subMsg : '获取用户信息失败' });
}
catch (e) {
return Promise.reject({ message: e.message || '获取用户信息失败' });
}
}
/**
* 创建支付宝交易订单
* @param {Object} params - 订单参数
* @param {String} params.outTradeNo - 商户订单号,必填
* @param {String} params.totalAmount - 订单总金额,单位为元,精确到小数点后两位,必填
* @param {String} params.subject - 订单标题,必填
* @param {String} params.buyerId - 买家支付宝用户ID小程序场景下必填
* @param {String} params.timeExpire - 订单绝对超时时间 【示例值】2021-12-31 10:05:00
*/
static async createTrade({ outTradeNo, totalAmount, subject, buyerId, timeExpire }) {
try {
// 参数校验
if (!outTradeNo) {
return Promise.reject({ message: '商户订单号不能为空' });
}
if (!totalAmount) {
return Promise.reject({ message: '订单总金额不能为空' });
}
if (!subject) {
return Promise.reject({ message: '订单标题不能为空' });
}
if (!buyerId) {
return Promise.reject({ message: '买家支付宝用户ID不能为空' });
}
// 构建请求参数
let bizContent = {
out_trade_no: outTradeNo,
total_amount: totalAmount,
subject: subject,
buyer_id: buyerId,
product_code: 'JSAPI_PAY',
time_expire: timeExpire,
op_app_id: AlipaySdkConfig.appId,
};
let res = await alipaySdk.exec("alipay.trade.create", { notifyUrl, bizContent });
console.log('支付宝创建交易订单响应===')
console.log(res)
console.log('notifyUrl', notifyUrl)
// 检查响应结果
if (res && res.code === '10000') {
// 返回交易号
return {
notifyUrl,
appId: AlipaySdkConfig.appId,
tradeNo: res.tradeNo, // 支付宝交易号
outTradeNo: res.outTradeNo, // 商户订单号
};
}
// 返回错误信息
return Promise.reject({
message: res && res.subMsg ? res.subMsg : '创建交易失败',
code: res && res.code ? res.code : '',
});
} catch (e) {
return Promise.reject({ message: `创建交易失败: ${e.message}` });
}
}
static async queryTrade(trade_no) {
try {
let res = await alipaySdk.exec("alipay.trade.query", { bizContent: { trade_no } });
if (res && res.code === '10000') {
return res
}
return Promise.reject({
message: res && res.subMsg ? res.subMsg : '创建交易失败',
code: res && res.code ? res.code : '',
});
} catch (e) {
return Promise.reject({ message: `查询交易失败: ${e.message}` });
}
}
/**
* 解析支付宝支付成功回调
* @param {Object} notifyData - 支付宝回调数据(可以是 req.body 或 req.query
* @returns {Object} 解析后的回调数据
* @returns {String} outTradeNo - 商户订单号
* @returns {String} tradeNo - 支付宝交易号
* @returns {String} tradeStatus - 交易状态
* @returns {String} totalAmount - 订单总金额
* @returns {String} buyerId - 买家支付宝用户ID
* @returns {String} gmtPayment - 支付时间
*/
static parsePayNotify(notifyData) {
try {
// 如果 notifyData 是对象,直接使用;如果是数组,取第一个元素
const params = notifyData && typeof notifyData === 'object' ? notifyData : {};
// 验证签名
// 支付宝SDK的签名验证方法可能因版本而异
// 尝试使用 checkNotifySign 方法验证签名,如果不存在则使用 verify 方法
let signVerified = false;
if (typeof alipaySdk.checkNotifySign === 'function') {
signVerified = alipaySdk.checkNotifySign(params, AlipaySdkConfig.alipayPublicKey);
} else if (typeof alipaySdk.verify === 'function') {
signVerified = alipaySdk.verify(params, AlipaySdkConfig.alipayPublicKey);
} else if (typeof alipay.checkNotifySign === 'function') {
// 尝试使用静态方法
signVerified = alipay.checkNotifySign(params, AlipaySdkConfig.alipayPublicKey);
} else {
// 如果SDK没有提供验证方法记录警告但继续处理生产环境建议实现签名验证
console.warn('警告支付宝SDK未找到签名验证方法请确保实现签名验证逻辑');
}
if (!signVerified) {
return Promise.reject({ message: '签名验证失败', verified: false });
}
// 解析回调数据
const result = {
outTradeNo: params.out_trade_no || params.outTradeNo, // 商户订单号
tradeNo: params.trade_no || params.tradeNo, // 支付宝交易号
tradeStatus: params.trade_status || params.tradeStatus, // 交易状态
totalAmount: params.total_amount || params.totalAmount, // 订单总金额
buyerId: params.buyer_id || params.buyerId, // 买家支付宝用户ID
buyerLogonId: params.buyer_logon_id || params.buyerLogonId, // 买家支付宝账号
sellerId: params.seller_id || params.sellerId, // 卖家支付宝用户ID
sellerEmail: params.seller_email || params.sellerEmail, // 卖家支付宝账号
gmtCreate: params.gmt_create || params.gmtCreate, // 交易创建时间
gmtPayment: params.gmt_payment || params.gmtPayment, // 交易支付时间
gmtClose: params.gmt_close || params.gmtClose, // 交易关闭时间
subject: params.subject, // 订单标题
body: params.body, // 订单描述
receiptAmount: params.receipt_amount || params.receiptAmount, // 实收金额
invoiceAmount: params.invoice_amount || params.invoiceAmount, // 开票金额
pointAmount: params.point_amount || params.pointAmount, // 集分宝金额
fundBillList: params.fund_bill_list || params.fundBillList, // 支付金额信息
charset: params.charset, // 编码格式
notifyId: params.notify_id || params.notifyId, // 通知校验ID
notifyType: params.notify_type || params.notifyType, // 通知类型
notifyTime: params.notify_time || params.notifyTime, // 通知时间
version: params.version, // 接口版本
signType: params.sign_type || params.signType, // 签名类型
sign: params.sign, // 签名
appId: params.app_id || params.appId, // 支付宝分配给开发者的应用Id
verified: true, // 签名验证通过标识
};
// 检查交易状态
const tradeStatus = result.tradeStatus;
if (tradeStatus === 'TRADE_SUCCESS' || tradeStatus === 'TRADE_FINISHED') {
result.isSuccess = true;
} else {
result.isSuccess = false;
}
return result;
} catch (e) {
return Promise.reject({
message: `解析支付回调失败: ${e.message}`,
verified: false,
error: e
});
}
}
static parseRefundNotify(notifyData) {
try {
const params = notifyData && typeof notifyData === 'object' ? notifyData : {};
let signVerified = false;
if (typeof alipaySdk.checkNotifySign === 'function') {
signVerified = alipaySdk.checkNotifySign(params, AlipaySdkConfig.alipayPublicKey);
} else if (typeof alipaySdk.verify === 'function') {
signVerified = alipaySdk.verify(params, AlipaySdkConfig.alipayPublicKey);
} else if (typeof alipay.checkNotifySign === 'function') {
signVerified = alipay.checkNotifySign(params, AlipaySdkConfig.alipayPublicKey);
} else {
console.warn('警告支付宝SDK未找到签名验证方法请确保实现签名验证逻辑');
}
if (!signVerified) {
return Promise.reject({ message: '签名验证失败', verified: false });
}
return params;
} catch (e) {
return Promise.reject({ message: `解析退款回调失败: ${e.message}` });
}
}
static async refundTrade({ tradeNo, totalAmount: refundAmount, refundReason }) {
try {
let res = await alipaySdk.exec("alipay.trade.refund", {
bizContent: {
refund_amount: refundAmount,
trade_no: tradeNo,
refund_reason: refundReason
}
});
if (res && res.code === '10000') {
return res
}
return Promise.reject({
message: res && res.subMsg ? res.subMsg : '退款失败',
code: res && res.code ? res.code : '',
});
} catch (e) {
return Promise.reject({ message: `退款失败: ${e.message}` });
}
}
static async queryRefundDetail(trade_no, out_request_no) {
try {
let res = await alipaySdk.exec("alipay.trade.fastpay.refund.query", { bizContent: { trade_no, out_request_no, query_options: ['gmt_refund_pay'] } });
if (res && res.code === '10000') {
return { success: true, data: res }
}
return { success: false, message: res && res.subMsg ? res.subMsg : '查询退款失败', data: res };
} catch (e) {
return Promise.reject({ message: `查询退款详情失败: ${e.message}` });
}
}
};
module.exports = aliplayApi;