| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162 |
- import {Context} from "koa";
- import axios from "axios";
- import {parseString} from "xml2js";
- import {ChannelHandler, LoginResult, PaymentResult} from "../interfaces/ChannelHandler";
- import {ChannelConfig} from "../../config/channelConfig";
- import {SignatureVerifier} from "../../utils/SignatureVerifier";
- import QuickAsy from "../../utils/quickAsy";
- import {PaymentHelper} from "../../utils/PaymentHelper";
- const logger = require("../../utils/log");
- /**
- * 0.1渠道(QuickSDK)渠道处理器
- * 负责登录验证与支付回调处理
- */
- export class ZeroOneChannelHandler implements ChannelHandler {
- /**
- * QuickSDK 登录验证
- * @param ctx Koa上下文
- * @param config 渠道配置
- */
- async handleLogin(ctx: Context, config: ChannelConfig): Promise<LoginResult> {
- const data = ctx.request.body as any;
- const {token, uid, channel_code, product_code} = data || {};
- const finalProductCode = product_code || config.loginConfig?.productCode;
- const tag = `[渠道${config.channelId}]`;
- if (!token || !uid) {
- logger.warn(`${tag}登录验证失败: 缺少必要参数`, {token, uid});
- return {code: 0, msg: "缺少必要参数 token 或 uid"};
- }
- if (!finalProductCode) {
- logger.error(`${tag}登录验证失败: 未配置productCode`);
- return {code: 0, msg: "服务器未配置productCode"};
- }
- const requestUrl = "http://checkuser.quickapi.net/v2/checkUserInfo";
- const params: Record<string, string> = {
- token,
- uid,
- product_code: finalProductCode
- };
- if (channel_code) {
- params.channel_code = channel_code;
- }
- logger.info(`${tag}登录验证请求`, {url: requestUrl, params});
- try {
- const response = await axios.get(requestUrl, {params, timeout: 8000});
- logger.info(`${tag}登录验证响应`, {data: response.data});
- if (response.data == "1") {
- return {code: 1, msg: "success"};
- }
- logger.warn(`${tag}登录验证失败: 接口返回非1`, {data: response.data});
- return {code: 0, msg: "登录验证失败"};
- } catch (error) {
- logger.error(`${tag}登录验证异常`, error);
- return {code: 0, msg: "登录验证异常"};
- }
- }
- /**
- * QuickSDK 支付回调
- * @param ctx Koa上下文
- * @param config 渠道配置
- */
- async handlePayment(ctx: Context, config: ChannelConfig): Promise<PaymentResult> {
- const data = ctx.request.body as any;
- const tag = `[渠道${config.channelId}]`;
- logger.info(`${tag}支付回调参数`, {url: ctx.href, params: data});
- const {nt_data, sign, md5Sign} = data || {};
- if (!nt_data || !sign || !md5Sign) {
- logger.warn(`${tag}支付回调失败: 缺少必要参数`, {nt_data, sign, md5Sign});
- return {code: 0, msg: "缺少必要参数"};
- }
- const md5Key = config.paymentConfig?.signKey;
- const callbackKey = config.paymentConfig?.callbackKey;
- if (!md5Key || !callbackKey) {
- logger.error(`${tag}支付回调失败: 未配置QuickSDK密钥`);
- return {code: 0, msg: "服务器未配置渠道密钥"};
- }
- if (!SignatureVerifier.verifyQuickSign(data, md5Key)) {
- logger.warn(`${tag}支付回调失败: 签名验证失败`);
- return {code: 0, msg: "签名验证失败"};
- }
- try {
- const xmlData = QuickAsy.decode(nt_data, callbackKey);
- const parsed = await this.parseQuickXml(xmlData);
- const message = parsed.quicksdk_message.message[0];
- const orderId = message.game_order?.[0];
- const outTradeNo = message.order_no?.[0];
- const status = message.status?.[0];
- const amountStr = message.amount?.[0];
- if (!orderId || !outTradeNo || typeof status === "undefined" || !amountStr) {
- logger.error(`${tag}支付回调失败: XML缺少必要字段`, {message});
- return {code: 0, msg: "回调数据不完整"};
- }
- if (status !== "0") {
- logger.warn(`${tag}支付状态非成功`, {status});
- return {code: 0, msg: "支付状态失败"};
- }
- const amount = parseFloat(amountStr);
- const validation = await PaymentHelper.validateOrder(orderId);
- if (!validation.valid) {
- return {
- code: validation.message?.includes("重复发货") ? 1 : 0,
- msg: validation.message || "订单验证失败"
- };
- }
- const orderInfo = validation.orderInfo;
- if (Number(orderInfo.amount) !== amount) {
- logger.warn(`${tag}支付金额不匹配`, {
- orderId,
- requestAmount: amount,
- orderAmount: orderInfo.amount
- });
- return {code: 0, msg: "订单金额不一致"};
- }
- logger.info(`${tag}支付订单${orderId}开始发货`);
- const result = await PaymentHelper.deliverOrder(
- orderInfo,
- ctx.request.ip,
- validation.url,
- outTradeNo
- );
- logger.info(`${tag}支付订单${orderId}发货完成`, {result});
- return result;
- } catch (error) {
- logger.error(`${tag}支付回调解析异常`, error);
- return {code: 0, msg: "回调解析异常"};
- }
- }
- private parseQuickXml(xml: string): Promise<any> {
- return new Promise((resolve, reject) => {
- parseString(xml, (err, result) => {
- if (err) {
- return reject(err);
- }
- resolve(result);
- });
- });
- }
- }
|