From e111d8ff52a52526855da4fa9f38c50629812438 Mon Sep 17 00:00:00 2001 From: "COMPUTER\\EDY" <249929363@qq.com> Date: Mon, 12 Oct 2026 17:30:15 +0800 Subject: [PATCH] Add StaminaPack product to existing payment routes --- laf-cloud/functions/wx/KeFuInfo.ts | 2 + laf-cloud/functions/wx/iosorderPaySig.ts | 1 + laf-cloud/functions/wx/orderPaySig.ts | 1 + laf-cloud/tests/stamina-pack.test.mjs | 83 ++++++++++++++++++++++++ 4 files changed, 87 insertions(+) create mode 100644 laf-cloud/tests/stamina-pack.test.mjs diff --git a/laf-cloud/functions/wx/KeFuInfo.ts b/laf-cloud/functions/wx/KeFuInfo.ts index dc9576f..6f2f412 100644 --- a/laf-cloud/functions/wx/KeFuInfo.ts +++ b/laf-cloud/functions/wx/KeFuInfo.ts @@ -103,6 +103,7 @@ async function frontsign(data) { return signature } const propName = { + StaminaPack: "体力加油包", starter_pack: "幸运礼包3元", starter_pack_2: "幸运礼包6元", starter_pack_3: "幸运礼包12元", starter_pack_4: "幸运礼包18元", starter_pack_5: "幸运礼包30元", new_gold_1: "新版金币包1", new_gold_2: "新版金币包2", new_gold_3: "新版金币包3", @@ -164,6 +165,7 @@ async function PostMsg(OpenId, msg) { async function PostImg(OpenId, outTradeNo, name, count, price, passInput: any = {}) { // B 商城商品价格(分);旧商品继续沿用原流程。 const shopPrices = { + StaminaPack: 800, new_gold_1: 600, new_gold_2: 3000, new_gold_3: 6800, new_gold_4: 12800, new_gold_5: 32800, new_gold_6: 64800, new_unlimited_health_bundle_8: 800, new_unlimited_health_bundle_18: 1800, diff --git a/laf-cloud/functions/wx/iosorderPaySig.ts b/laf-cloud/functions/wx/iosorderPaySig.ts index 80cac64..00bbb8a 100644 --- a/laf-cloud/functions/wx/iosorderPaySig.ts +++ b/laf-cloud/functions/wx/iosorderPaySig.ts @@ -24,6 +24,7 @@ export default async function (ctx: FunctionContext) { let itemPrice = ctx.body.itemPrice; // B 商城商品价格(分);旧商品继续沿用原流程。 const shopPrices = { + StaminaPack: 800, new_gold_1: 600, new_gold_2: 3000, new_gold_3: 6800, new_gold_4: 12800, new_gold_5: 32800, new_gold_6: 64800, new_unlimited_health_bundle_8: 800, new_unlimited_health_bundle_18: 1800, diff --git a/laf-cloud/functions/wx/orderPaySig.ts b/laf-cloud/functions/wx/orderPaySig.ts index 4f9c7a3..9c674e9 100644 --- a/laf-cloud/functions/wx/orderPaySig.ts +++ b/laf-cloud/functions/wx/orderPaySig.ts @@ -24,6 +24,7 @@ export default async function (ctx: FunctionContext) { let itemPrice = ctx.body.itemPrice; // B 商城商品价格(分);旧商品继续沿用原流程。 const shopPrices = { + StaminaPack: 800, new_gold_1: 600, new_gold_2: 3000, new_gold_3: 6800, new_gold_4: 12800, new_gold_5: 32800, new_gold_6: 64800, new_unlimited_health_bundle_8: 800, new_unlimited_health_bundle_18: 1800, diff --git a/laf-cloud/tests/stamina-pack.test.mjs b/laf-cloud/tests/stamina-pack.test.mjs new file mode 100644 index 0000000..3481d9c --- /dev/null +++ b/laf-cloud/tests/stamina-pack.test.mjs @@ -0,0 +1,83 @@ +import test from 'node:test'; +import assert from 'node:assert/strict'; +import { registerHooks } from 'node:module'; +import crypto from 'node:crypto'; + +const state = { orders: [], requests: [] }; +globalThis.__staminaCloud = { + database: () => ({ collection: name => ({ + add: async data => { state.orders.push({ ...data, collection: name }); }, + where: () => ({ + getOne: async () => ({ data: { _id: 'u', openid: 'o', session_key: 'test-session' } }), + update: async () => ({ updated: 1 }), + }), + }) }), + shared: { get: () => 'test-token' }, + storage: { bucket: () => ({ readFile: async () => ({ Body: { transformToString: async () => 'test-key' } }) }) }, +}; +globalThis.__staminaCrypto = { + ...crypto, createSign: () => ({ update() {}, sign: () => 'test-signature' }), +}; +registerHooks({ + resolve(specifier, context, nextResolve) { + const mocks = { + '@lafjs/cloud': 'export default globalThis.__staminaCloud;', + '@/limitedTimeEvent': 'export const starterPackOrderMetadata = () => ({});', + '@/goldMiner/payment': 'export const createNativeOrder = () => { throw new Error("Unexpected gold miner order"); };', + '@/goldMiner/legacyPayment': 'export const recordCustomerLink = () => { throw new Error("Unexpected gold miner link"); };', + '@/passCheckUpgrade': 'export const passOrderFields = async () => ({}); export const PASS_PRICES = {};', + '@/jungleConfig': 'export const getJunglePaidTierByProductId = () => null;', + crypto: 'export default globalThis.__staminaCrypto; export const createHmac = globalThis.__staminaCrypto.createHmac;', + }; + if (Object.hasOwn(mocks, specifier)) return { url: 'data:text/javascript,' + encodeURIComponent(mocks[specifier]), shortCircuit: true }; + return nextResolve(specifier, context); + }, +}); + +const [{ default: android }, { default: ios }, { default: customerService }] = await Promise.all([ + import('../functions/wx/orderPaySig.ts'), import('../functions/wx/iosorderPaySig.ts'), import('../functions/wx/KeFuInfo.ts'), +]); + +test('StaminaPack native orders enforce 800 fen and one pack on Android and iOS', async () => { + const oldEnv = process.env.PAYMENT_APP_ENV, oldKey = process.env.WX_MIDAS_PAY_SIGN_KEY; + process.env.PAYMENT_APP_ENV = 'test'; process.env.WX_MIDAS_PAY_SIGN_KEY = 'test-only'; + try { + for (const create of [android, ios]) { + const result = await create({ body: { uid: 'u', itemid: 'StaminaPack', itemPrice: 1, itemCount: 99 } }); + assert.equal(result.code, 1); + const signed = JSON.parse(result.data.signData); + assert.equal(signed.productId, 'StaminaPack'); + assert.equal(signed.goodsPrice, 800); + assert.equal(signed.buyQuantity, 1); + assert.equal(state.orders.at(-1).goodsPrice, 800); + assert.equal(state.orders.at(-1).itemCount, 1); + } + } finally { + if (oldEnv === undefined) delete process.env.PAYMENT_APP_ENV; else process.env.PAYMENT_APP_ENV = oldEnv; + if (oldKey === undefined) delete process.env.WX_MIDAS_PAY_SIGN_KEY; else process.env.WX_MIDAS_PAY_SIGN_KEY = oldKey; + } +}); + +test('legacy iOS customer service creates an 8-yuan StaminaPack order and payment link', async () => { + state.orders = []; state.requests = []; + const oldFetch = globalThis.fetch; + globalThis.fetch = async (url, options) => { + state.requests.push({ url, body: JSON.parse(options.body) }); + return { ok: true, json: async () => ({ prepay_id: 'test-prepay', errcode: 0 }) }; + }; + try { + await customerService({ body: { FromUserName: 'o', SessionFrom: JSON.stringify({ + tpye: 'ios', propName: 'StaminaPack', price: 1, count: 99, outTradeNo: 'test-stamina-order', + }) } }); + const order = state.orders.at(-1); + assert.equal(order.itemid, 'StaminaPack'); + assert.equal(order.goodsPrice, 800); + assert.equal(order.itemCount, 1); + assert.equal(state.requests.find(r => r.url.includes('/v3/pay/transactions/jsapi')).body.amount.total, 800); + const link = state.requests.find(r => r.body.msgtype === 'link').body.link; + assert.equal(link.description, '金额:8.00元'); + const data = JSON.parse(decodeURIComponent(link.url.split('#data=')[1])); + assert.equal(data.price, 800); + assert.equal(data.quantity, 1); + } finally { globalThis.fetch = oldFetch; } +});