import logger from 'logger/logger' import { PayRecord, PayRecordClass, PayStatus } from 'modules/PayRecord' import { TransferRecord, TransferRecordClass } from 'modules/TransferRecord' import { DocumentType } from '@typegoose/typegoose' import { updateOrderStatus } from 'service/alchemy.svr' import { PriceSvr } from 'service/price.svr' import { assembleGameData, checkGameSign } from 'service/game.svr' import { BaseController, role, ROLE_ANON, router, ZError } from 'zutils' import { hmacSha256 } from 'zutils/utils/security.util' const calcHash = function (data: any) { let signStr = JSON.stringify(data) return hmacSha256(signStr, process.env.HASH_SALT_CHAIN).toLowerCase() } const notify = async function (record: DocumentType, subTask: DocumentType) { let data: any = { orderNo: record.outOrderId, // AlchemyPay订单号 crypto: record.crypto, // 用户购买的数字货币 cryptoAmount: record.cryptoSend, //用户的提币数量 cryptoPrice: record.cryptoPrice, // 实时的价格/USDT CEG锚定USDT txHash: record.txHash, // 给用户转账的hash network: record.network, // 用户购买的数字货币对应的网络 // networkFee: record.networkFee, // 网络费用/USDT address: record.address, // 用户的提币地址 status: record.tranStatus === 2 ? 'SUCCESS' : 'FAIL', // SUCCESS/FAIL } try { let price = await new PriceSvr().fetchPrice({ crypto: 'ETH', network: 'ARBITRUM', fiat: 'USD' }) data.networkFee = parseFloat(subTask.gas) * parseFloat(subTask.gasPrice) * 0.0000000001 * parseFloat(price) + '' let result = await updateOrderStatus(data) logger.info('update transfer status success::', JSON.stringify(result)) if (result.success) { subTask.status = 8 await subTask.save() } } catch (err) { logger.error(`notify alchemy error:: ${err.message}`) record.notofyErrCount = record.notofyErrCount + 1 await record.save() if (record.notofyErrCount < 6) { await notify(record, subTask) } } } export default class InternalController extends BaseController { @role(ROLE_ANON) @router('post /api/internal/update_task') async updateTaskInfo(req) { let { sign, id, result, successCount, errorCount, gas, gasPrice, hashList } = req.params if (!sign) { throw new ZError(10, 'sign not found') } let hash = calcHash({ id, result, successCount, errorCount, gas, gasPrice, hashList }) console.log(hash, sign) if (sign !== hash) { throw new ZError(11, 'sign not match') } logger.info(`task report:: ${id}|${result}|${successCount}|${errorCount}|${JSON.stringify(hashList)}}`) if (!id) { throw new ZError(11, 'taskId not found') } let record = await TransferRecord.findById(id) if (!record) { throw new ZError(12, 'TransferRecord not found') } let task = await PayRecord.findById(record.recordId) if (!task) { throw new ZError(13, 'PayRecord not found') } if (result === 2) { record.status = 9 record.gas = gas record.gasPrice = gasPrice record.hashList = hashList task.txHash = hashList[0] task.tranStatus = 2 } else { record.status = 10 task.tranStatus = 99 } await record.save() await task.save() setImmediate(async () => { await notify(task, record) }) 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, false) return repData } }