import cloud from '@lafjs/cloud'; import * as JungleConfigModule from "@/jungleConfig"; const JungleConfig: any = JungleConfigModule as any; const db = cloud.database(); const ThinkingData = require('thinkingdata-node'); export default async function (ctx: FunctionContext) { let data: any; try { data = JSON.parse(ctx.body?.MiniGame?.Payload || ""); } catch { console.error("微信发货回调 Payload 解析失败"); return { "ErrCode": -1, "ErrMsg": "Invalid Payload" }; } const outTradeNo = String(data.OutTradeNo || ""); const orderResult = await db.collection("order").where({ outTradeNo }).getOne(); const order = orderResult.data; if (!order) { console.error("微信发货回调未找到订单:" + outTradeNo); return { "ErrCode": -1, "ErrMsg": "Order Not Found" }; } const jungleTier = JungleConfig.getJunglePaidTierByProductId(order.itemid); if (jungleTier) { const callbackProductId = String(data.GoodsInfo?.ProductId || ""); const callbackQuantity = Number(data.GoodsInfo?.Quantity); const callbackOriginalPrice = Number(data.GoodsInfo?.OrigPrice); if ((data.OpenId && data.OpenId !== order.openid) || (callbackProductId && callbackProductId !== order.itemid) || (Number.isFinite(callbackQuantity) && callbackQuantity !== Number(order.itemCount)) || (Number.isFinite(callbackOriginalPrice) && callbackOriginalPrice !== Number(order.goodsPrice))) { console.error("Jungle 支付回调与订单信息不一致:" + outTradeNo); return { "ErrCode": -1, "ErrMsg": "Order Mismatch" }; } } const userResult = await db.collection("users").where({ openid: order.openid }).getOne(); const user = userResult.data; if (!user) { console.error("微信发货回调未找到玩家:" + order.openid); return { "ErrCode": -1, "ErrMsg": "User Not Found" }; } const firstPaidCallback = order.state === 0; if (order.state !== 2) { await db.collection("order").where({ outTradeNo }).update({ state: 1, chargeTime: new Date(Date.now() + 8 * 3600000), }); } const userUpdate: any = {}; let jungleUnlockedFromLocked = false; if (jungleTier) { const storedState = JungleConfig.normalizeStoredJungleState(user.jungleTreasureState); const wasLocked = Number(storedState?.tierStates?.[jungleTier.id - 1]) === 0; const unlockResult = JungleConfig.unlockJungleTierByProductId( user.jungleTreasureState, order.itemid, outTradeNo, ); if (unlockResult.ok && unlockResult.changed && unlockResult.state) { userUpdate.jungleTreasureState = JungleConfig.serializeJungleState(unlockResult.state); jungleUnlockedFromLocked = wasLocked && Number(unlockResult.state.tierStates?.[jungleTier.id - 1]) === 1; } } if (order.itemid === "starter_pack") { userUpdate.starter_packState = 1; } if (!user.pay_user) { userUpdate.pay_user = true; } if (Object.keys(userUpdate).length > 0) { await db.collection("users").where({ _id: user._id }).update(userUpdate); } if (firstPaidCallback) { await sead(order, user, getClientIp(ctx)); } if (jungleTier && jungleUnlockedFromLocked) { await db.collection("order").where({ outTradeNo }).update({ state: 2, getTime: new Date(Date.now() + 8 * 3600000), }); } // let query={ // signature: '1c1b5c1c72058436e2f1214e6aeafd258e50acd4', // timestamp: '1751291889', // nonce: '3122546041' // } /** * ToUserName: 'gh_1092576a6ce7', FromUserName: 'orm8I7IA-pMesygmTc5HPufGZHvA', CreateTime: 1751292233, MsgType: 'event', MiniGame: { Payload: '{"OpenId":"orm8I7BRTjhdQ3Mz9V9cg1jzTUcQ","OutTradeNo":"wcx_92778691620421751292218408","WeChatPayInfo":{"MchOrderNo":"20250630714915544","TransactionId":"4200002678202506307565098431"},"Env":0,"GoodsInfo":{"ProductId":"10011","Quantity":1,"ZoneId":"1","OrigPrice":100,"ActualPrice":100,"Attach":"购买道具","OrderSource":1},"PayChannel":0}', PayEventSig: 'ecdaf472c239894706e28ab941d2aebf727b5bed45fe4073c645e922b6eefc1a', IsMock: false }, Event: 'minigame_game_pay_goods_deliver_notify' */ //return ctx.query.echostr; return { "ErrCode": 0, "ErrMsg": "Success" }; } async function sead1(outTradeNo) { let res = await db.collection("order").where({ outTradeNo: outTradeNo }).getOne(); if (res.data.state == 1) { return { code: 1, data: { pay_state: 2 }, msg: "成功" }; } else if (res.data.state == 2) { let userInfo = await db.collection("users").where({ openid: res.data.openid }).getOne(); await sead(outTradeNo, userInfo.data, "") console.log("1"); return { code: 1, data: { pay_state: 1, }, msg: "已领取奖励" } } else { return { code: 1, data: { pay_state: 1, }, msg: "充值未成功" } }; } const getClientIp = (req) => { return ( req.headers['x-forwarded-for']?.split(',')[0]?.trim() || // 代理链中的第一个 IP req.headers['x-real-ip'] || // Nginx 配置的 real-ip req.socket.remoteAddress // 原始 IP(可能是代理) ); }; async function sead(order, userInfo, ip) { db.collection("susu").add({ order: order, time: Date.now() }); if (!userInfo.distinctId) { console.log("未找到distinctId无法上传数数") return; } let id = '95993f9ab6f1402a87abe5147827e5e0'; if (userInfo.isDebug != "true") { id = '40e3d5c5f2af49a4a074205564ce5dbb'; } let teSDK = ThinkingData.initWithBatchMode(id, 'https://data.nika4fun.com/sync_data', { dryRun: false, // report data to TE or not deviceId: "123456789",//设备唯一标识 }); let trackEvent = { accountId: order.openid, distinctId: userInfo.distinctId,//访客id event: 'payment', time: new Date(Date.now() + 8 * 3600000), ip: ip, properties: { order_id: order.outTradeNo, pay_amount: order.goodsPrice, payment_name: order.itemid, payment_num: order.itemCount, payment_type: order.type == "ios" ? "ios" : "Android", is_on_table: Number(userInfo.addLevel) >= 5, current_level: userInfo.levelAmount, //当前关卡等级 number current_health: userInfo.healthAmount, //当前体力值 tmp_coin: userInfo.coinAmount,//当前金币 version: "1.6", user_id: userInfo._id, //用户id pay_user: userInfo.pay_user, register_time: userInfo.register_time, abTest_layer_one: getABTestGroupValue(userInfo.abTests, "layer_1"), abTest_layer_two: getABTestGroupValue(userInfo.abTests, "layer_2"), abTest_layer_three: getABTestGroupValue(userInfo.abTests, "layer_3") }, callback(e) { if (e) { } } }; teSDK.track(trackEvent); teSDK.close(); return; } function getABTestGroupValue(abTests: any, layerKey: string) { if (!abTests) { return 0; } if (typeof abTests === "string") { try { abTests = JSON.parse(abTests); } catch { return 0; } } const groupMap = { A: 1, B: 2, C: 3, D: 4, E: 5 }; const group = String(abTests[layerKey]?.group || "").toUpperCase(); return groupMap[group] || 0; }