UNPKG

koishi-plugin-pay-tool

Version:

适用于Koishi框架的易支付工具插件,支持订单创建、查询、退款、分配等功能

226 lines (225 loc) 7.46 kB
"use strict"; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { desc = { enumerable: true, get: function() { return m[k]; } }; } Object.defineProperty(o, k2, desc); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar = (this && this.__importStar) || (function () { var ownKeys = function(o) { ownKeys = Object.getOwnPropertyNames || function (o) { var ar = []; for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k; return ar; }; return ownKeys(o); }; return function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]); __setModuleDefault(result, mod); return result; }; })(); Object.defineProperty(exports, "__esModule", { value: true }); exports.generateSign = generateSign; exports.verifySign = verifySign; exports.generateOrderNo = generateOrderNo; exports.getClientIp = getClientIp; exports.formatAmount = formatAmount; exports.isAdmin = isAdmin; exports.formatPaymentType = formatPaymentType; exports.normalizeQQId = normalizeQQId; exports.isValidTradeNo = isValidTradeNo; exports.isValidAmount = isValidAmount; exports.validateAndConvertPaymentType = validateAndConvertPaymentType; exports.getAvailablePaymentMethods = getAvailablePaymentMethods; const crypto = __importStar(require("crypto")); /** * 生成MD5签名 * @param params 参数对象 * @param key 商户密钥 * @returns MD5签名 */ function generateSign(params, key) { // 1. 过滤空值和sign字段 const filteredParams = Object.keys(params) .filter(k => params[k] !== undefined && params[k] !== null && params[k] !== '' && k !== 'sign' && k !== 'sign_type') .sort() // 2. 按ASCII码排序 .reduce((obj, k) => { obj[k] = params[k]; return obj; }, {}); // 3. 拼接成URL键值对格式 const queryString = Object.keys(filteredParams) .map(k => `${k}=${filteredParams[k]}`) .join('&'); // 4. 添加商户密钥并计算MD5 const signString = queryString + key; return crypto.createHash('md5').update(signString).digest('hex').toLowerCase(); } /** * 验证签名 * @param params 参数对象 * @param key 商户密钥 * @returns 是否验证成功 */ function verifySign(params, key) { const receivedSign = params.sign; if (!receivedSign) return false; const calculatedSign = generateSign(params, key); return receivedSign.toLowerCase() === calculatedSign.toLowerCase(); } /** * 生成订单号 * @param userId 用户ID * @returns 订单号 */ function generateOrderNo(userId) { const timestamp = Date.now(); const random = Math.floor(Math.random() * 10000).toString().padStart(4, '0'); return `${timestamp}${userId.slice(-4)}${random}`; } /** * 获取客户端IP地址 * @returns IP地址 */ function getClientIp() { // 由于插件环境无法获取真实客户端IP,使用固定IP return '192.168.1.100'; } /** * 格式化金额为保留两位小数的字符串 * @param amount 金额 * @returns 格式化后的金额字符串 */ function formatAmount(amount) { const num = typeof amount === 'string' ? parseFloat(amount) : amount; return num.toFixed(2); } /** * 验证管理员权限 * @param userId 用户ID * @param adminQQ 管理员QQ号 * @returns 是否为管理员 */ function isAdmin(userId, adminQQ) { return userId === adminQQ; } /** * 格式化支付方式显示名称 * @param paymentType 支付方式代码 * @param paymentMethods 支付方式配置字典 * @returns 支付方式显示名称 */ function formatPaymentType(paymentType, paymentMethods) { return paymentMethods[paymentType] || paymentType; } /** * 规范化QQ号,处理@用户和平台前缀 * @param userId 用户ID,可能包含平台前缀或@标记 * @returns 纯数字QQ号,无效时返回空字符串 */ function normalizeQQId(userId) { if (!userId) return ''; let extractedId = ''; // 处理 <at id="..."/> 格式的@用户字符串(Koishi标准@标签) const atMatch = userId.match(/<at\s+id="(\d+)"\s*\/?>/); if (atMatch) { extractedId = atMatch[1]; } // 处理直接@+QQ号格式(如 @123456) else if (userId.startsWith('@')) { extractedId = userId.substring(1); // 去掉@符号 } // 处理平台前缀格式(如 onebot:123456) else if (userId.includes(':')) { const colonIndex = userId.indexOf(':'); extractedId = userId.substring(colonIndex + 1); } // 处理纯QQ号 else { extractedId = userId; } // 验证提取的ID是否为纯数字QQ号 if (!/^\d+$/.test(extractedId)) { return ''; // 返回空字符串表示无效 } // 检查QQ号长度是否合理(QQ号通常为5-12位数字) if (extractedId.length < 5 || extractedId.length > 12) { return ''; } return extractedId; } /** * 验证订单号格式 * @param tradeNo 订单号 * @returns 是否为有效的订单号格式 */ function isValidTradeNo(tradeNo) { if (!tradeNo) return false; // 订单号格式:时间戳(13位) + 用户ID后4位 + 随机数4位 = 21位数字 // 或者易支付内部订单号(数字格式,长度可变) if (!/^\d+$/.test(tradeNo)) { return false; } // 支持的订单号长度:10-25位数字(覆盖各种可能的格式) return tradeNo.length >= 10 && tradeNo.length <= 25; } /** * 验证金额格式 * @param amount 金额字符串 * @returns 是否为有效金额 */ function isValidAmount(amount) { if (!amount) return false; const num = parseFloat(amount); return !isNaN(num) && num > 0 && num <= 99999; } /** * 验证并转换支付方式 * @param payment 用户输入的支付方式(可能是代码或显示名称) * @param paymentMethods 支付方式配置字典 * @returns 转换后的支付方式代码,无效时返回null */ function validateAndConvertPaymentType(payment, paymentMethods) { if (!payment) return null; // 1. 检查是否是有效的支付方式代码(键) if (paymentMethods[payment]) { return payment; } // 2. 检查是否是显示名称(值),反向查找对应的代码 for (const [code, displayName] of Object.entries(paymentMethods)) { if (displayName === payment) { return code; } } // 3. 无效的支付方式 return null; } /** * 获取支持的支付方式列表字符串 * @param paymentMethods 支付方式配置字典 * @returns 格式化的支付方式列表 */ function getAvailablePaymentMethods(paymentMethods) { return Object.entries(paymentMethods) .map(([code, name]) => `${name}(${code})`) .join('、'); }