diff --git a/src/controllers/internal.controller.ts b/src/controllers/internal.controller.ts index d96fde4..29cd8be 100644 --- a/src/controllers/internal.controller.ts +++ b/src/controllers/internal.controller.ts @@ -8,6 +8,7 @@ import { hmacsha256 } from 'utils/security.util' import { DocumentType } from '@typegoose/typegoose' import { updateOrderStatus } from 'service/alchemy.svr' import { PriceSvr } from 'service/price.svr' +import { assembleGameData, checkGameSign } from 'service/game.svr' const calcHash = function (data: any) { let signStr = JSON.stringify(data) @@ -88,4 +89,27 @@ export default class InternalController extends BaseController { }) return {} } + /** + * 供Game端二次确认支付结果 + */ + @role(ROLE_ANON) + @router('get /api/internal/alchemy/order/:id') + async queryAlchemyPayOrder(req) { + let { id, timestamp, sign } = req.params + if (!id || !timestamp || !sign) { + throw new ZError(10, 'params mismatch') + } + if (timestamp < Date.now() / 1000 - 60 * 5) { + throw new ZError(11, 'timestamp expired') + } + if (!checkGameSign({ id, timestamp, sign })) { + throw new ZError(12, 'sign not match') + } + let record = await PayRecord.findById(id) + if (!record) { + throw new ZError(13, 'PayRecord not found') + } + const repData = assembleGameData(record) + return repData + } } diff --git a/src/service/game.svr.ts b/src/service/game.svr.ts index b46354b..26da40e 100644 --- a/src/service/game.svr.ts +++ b/src/service/game.svr.ts @@ -12,14 +12,24 @@ export interface IPayResult { status: number } -export async function reportPayResult(data: DocumentType) { - const repData = { +export function assembleGameData(data: DocumentType) { + return { account_id: data.gameAccountId, order_id: data.gameOrderId, status: data.status, id: data.id, txhash: data.txHash, } +} + +export function checkGameSign({ id, timestamp, sign }: { id: string; timestamp: string; sign: string }) { + const signStr = `id=${id}×tamp=${timestamp}` + const hash = hmacsha256(signStr, process.env.HASH_SALT) + return sign === hash +} + +export async function reportPayResult(data: DocumentType) { + const repData = assembleGameData(data) const signStr = Object.keys(repData) .sort() .map(key => `${key}=${encodeURIComponent(repData[key])}`) @@ -37,12 +47,20 @@ export async function reportPayResult(data: DocumentType) { } // 上报google支付结果 export async function reportGooglePurchaseResult(records: IPayResult[]) { + return reportPurchaseResult(records, 'google') +} + +export async function reportApplePurchaseResult(records: IPayResult[]) { + return reportPurchaseResult(records, 'apple') +} + +export async function reportPurchaseResult(records: IPayResult[], channel: string) { const url = `${process.env.GAME_PAY_CB_URL}?c=Shop&a=inappPurchaseDiamonds` let reportData: any = { - channel: 'google', + channel, records, } - let signStr = 'channel=google&' + let signStr = `channel=${channel}&` signStr += records .map(record => Object.keys(record)