pay-svr/src/controllers/alchemy.controller.ts

188 lines
6.6 KiB
TypeScript

import logger from 'logger/logger'
import BaseController from 'common/base.controller'
import { ZError } from 'common/ZError'
import { router } from 'decorators/router'
import { createOrder, queryFiat, queryPrice, refreshToken } from 'service/alchemy.svr'
import { generateKVStr } from 'utils/net.util'
import { PayRecord, PayStatus } from 'modules/PayRecord'
import { PriceSvr } from 'service/price.svr'
import { reportPayResult } from 'service/game.svr'
const CALL_BACK_URL = `${process.env.ALCHEMY_PAY_CB_URL}/pay/out/alchemy/buycb`
class AlchemyController extends BaseController {
@router('post /pay/alchemy/buy')
async beginApiPay(req, res) {
const user = req.user
const { network, crypto, address, fiat, fiatAmount, payWayCode, country, accountId, orderId, env } = req.params
let envStr = env || 'dev'
if (fiat || fiatAmount || country) {
if (!fiat || !fiatAmount || !country || !payWayCode) {
throw new ZError(11, 'fiat, fiatAmount payWayCode and country must be provided')
}
}
if (network || crypto) {
if (!network || !crypto) {
throw new ZError(12, 'network and crypto must be provided')
}
}
const tokenResult = await refreshToken(user.emailReal || user.email)
if (!tokenResult.success || tokenResult.returnCode !== '0000') {
logger.info(`fetch pay token error::code: ${tokenResult.returnCode} msg: ${tokenResult.returnMsg}`)
throw new ZError(10, 'fetch pay token error')
}
const { id, email, accessToken } = tokenResult.data
if (crypto.toLowerCase() === 'agor') {
let today = new Date()
today.setHours(0, 0, 0, 0)
let count = await PayRecord.countDocuments({
account: user.id,
crypto,
status: PayStatus.SUCCESS,
createdAt: { $gte: today },
})
if (count >= 3) {
throw new ZError(13, 'daily limit')
}
}
// 根据 `查询数字货币接口` 返回的数据, 预估可获得的数字货币数量
// 用户法币接口做简单的验证
let priceData = await queryPrice({ crypto, network, fiat, amount: fiatAmount, payWayCode, country })
logger.debug('pirce data::', JSON.stringify(priceData))
let amountEstimate = priceData.data.cryptoAmount
let record = new PayRecord({
account: user.id,
address,
network,
crypto,
env: envStr,
gameAccountId: accountId,
gameOrderId: orderId,
cryptoAmountEstimate: amountEstimate,
})
if (fiat) record.fiat = fiat
if (fiatAmount) record.fiatAmount = fiatAmount
if (country) record.country = country
await record.save()
let payData: any = {
side: 'BUY',
merchantOrderNo: record.id,
amount: record.fiatAmount,
fiatCurrency: record.fiat,
cryptoCurrency: record.crypto,
depositType: '2',
address: address,
network: record.network,
payWayCode,
alpha2: record.country,
callbackUrl: CALL_BACK_URL,
merchantName: 'CEBG',
}
logger.info(`create order data::${JSON.stringify(payData)}`)
let payRes = await createOrder(accessToken, payData)
logger.info(`create order result::${JSON.stringify(payRes)}`)
record.outData = payRes.data
if (payRes.success) {
record.outOrderId = payRes.data.orderNo
await record.save()
} else {
record.status = PayStatus.FAIL
await record.save()
setImmediate(() => {
reportPayResult(record)
})
throw new ZError(payRes.returnCode, payRes.returnMsg)
}
return { url: payRes.data.payUrl }
}
// @router('post /pay/alchemy/buypage')
// async beginPagePay(req, res) {
// const user = req.user
// const { network, crypto, address, fiat, fiatAmount, country } = req.params
// if (fiat || fiatAmount || country) {
// if (!fiat || !fiatAmount || !country) {
// throw new ZError(11, 'fiat, fiatAmount and country must be provided')
// }
// }
// if (network || crypto) {
// if (!network || !crypto) {
// throw new ZError(12, 'network and crypto must be provided')
// }
// }
// const tokenResult = await refreshToken(user.emailReal || user.email)
// console.log(tokenResult)
// if (!tokenResult.success || tokenResult.returnCode !== '0000') {
// logger.info(`fetch pay token error::code: ${tokenResult.returnCode} msg: ${tokenResult.returnMsg}`)
// throw new ZError(10, 'fetch pay token error')
// }
// const { id, email, accessToken } = tokenResult.data
// let record = new PayRecord({ account: user.id, address, network, crypto })
// if (fiat) record.fiat = fiat
// if (fiatAmount) record.fiatAmount = fiatAmount
// if (country) record.country = country
// await record.save()
// const merchantOrderNo = record.id
// let dataOrign: any = {
// token: accessToken,
// email,
// id,
// showTable: 'buy',
// merchantOrderNo,
// }
// if (network) dataOrign.network = network
// if (crypto) dataOrign.crypto = crypto
// if (fiat) dataOrign.fiat = fiat
// if (fiatAmount) dataOrign.fiatAmount = fiatAmount
// if (country) dataOrign.country = country
// let dataSign: any = {
// appId: process.env.ALCHEMY_APPID,
// address,
// callbackUrl: CALL_BACK_URL,
// }
// let signStr = generateKVStr({ data: dataSign, sort: true })
// let sign = createPageSign(signStr)
// dataOrign.sign = sign
// Object.assign(dataOrign, dataSign)
// const urlBase = process.env.ALCHEMY_PAGE_BASE
// let url = `${urlBase}/`
// url = generateKVStr({ data: dataOrign, encode: true, uri: url })
// return { url }
// }
@router('post /pay/alchemy/crypto_price')
async queryCryptoPrice(req, res) {
let { token, chain, currency, env } = req.params
if (!token || !chain) {
throw new ZError(11, 'token or network not found')
}
if (
(chain.toLowerCase() === 'agor' || chain.toLowerCase() === 'eth') &&
(token.toLowerCase() === 'ceg' || token.toLowerCase() === 'cec')
) {
return { price: 1 }
}
if ((chain.toLowerCase() === 'agor' || chain.toLowerCase() === 'eth') && token.toLowerCase() === 'agor') {
token = 'ETH'
chain = 'ETH'
}
if (token.toLowerCase() === 'ceg') {
return { price: 1 }
}
let data = {
crypto: token,
network: chain,
fiat: currency || 'USD',
}
let result = await new PriceSvr().fetchPrice(data)
return { price: result }
}
@router('get /pay/alchemy/fait_list')
async cryptoList(req, res) {
let result = await queryFiat()
if (!result.success) {
throw new ZError(10, result.returnMsg || 'fetch fiat list error')
}
return result.data
}
}