132 lines
3.8 KiB
TypeScript
132 lines
3.8 KiB
TypeScript
import logger from 'logger/logger'
|
|
import BaseController, { ROLE_ANON } from 'common/base.controller'
|
|
import { ZError } from 'common/ZError'
|
|
import { role, router } from 'decorators/router'
|
|
import { checkPayResultSign, checkSimpleSign } from 'service/alchemy.svr'
|
|
import { PayRecord, PayStatus } from 'modules/PayRecord'
|
|
import { TransferQueue } from 'queue/transfer.queue'
|
|
|
|
let errorRes = function (msg: string) {
|
|
return {
|
|
direct: 1,
|
|
data: null,
|
|
success: false,
|
|
returnCode: '9999',
|
|
returnMsg: msg,
|
|
}
|
|
}
|
|
/**
|
|
* for Alchemy call
|
|
*/
|
|
class AlchemyOutController extends BaseController {
|
|
@role(ROLE_ANON)
|
|
@router('post /pay/out/alchemy/buycb')
|
|
async alchemyCallback(req, res) {
|
|
let { orderNo, status, crypto, network, merchantOrderNo } = req.params
|
|
if (!merchantOrderNo) {
|
|
logger.info(`alchemy callback merchantOrderNo not found`)
|
|
throw new ZError(11, 'alchemy callback merchantOrderNo not found')
|
|
}
|
|
let record = await PayRecord.findById(merchantOrderNo)
|
|
if (!record) {
|
|
logger.info(`alchemy callback record not found`)
|
|
throw new ZError(12, 'alchemy callback record not found')
|
|
}
|
|
if (record.status !== PayStatus.PENDING && record.status !== PayStatus.TRANSFERING) {
|
|
logger.info(`alchemy callback record status error`)
|
|
throw new ZError(13, 'alchemy callback record status error')
|
|
}
|
|
if (!checkPayResultSign(req.params)) {
|
|
logger.info(`alchemy callback sign error`)
|
|
record.status = PayStatus.FAIL
|
|
await record.save()
|
|
throw new ZError(14, 'alchemy callback sign error')
|
|
}
|
|
|
|
record.outOrderId = orderNo
|
|
record.network = network
|
|
record.crypto = crypto
|
|
record.outData = req.params
|
|
record.status = status == 'PAY_SUCCESS' ? PayStatus.SUCCESS : PayStatus.FAIL
|
|
await record.save()
|
|
return {}
|
|
}
|
|
|
|
/**
|
|
* 向商户查询币价
|
|
* TODO::
|
|
*/
|
|
@role(ROLE_ANON)
|
|
@router('get /pay/out/alchemy/queryprice')
|
|
async queryToken(req, res) {
|
|
const { crypto } = req.params
|
|
const { appId, timestamp, sign } = req.headers
|
|
if (!crypto) {
|
|
return errorRes('params mismatch')
|
|
}
|
|
if (!appId || !timestamp || !sign) {
|
|
return errorRes('headers mismatch')
|
|
}
|
|
if (!checkSimpleSign(req.headers)) {
|
|
return errorRes('sign error')
|
|
}
|
|
let result = {
|
|
direct: 1,
|
|
data: {
|
|
price: '1.0',
|
|
networkList: [
|
|
{
|
|
network: 'ETH',
|
|
networkFee: '1.21',
|
|
},
|
|
],
|
|
},
|
|
success: true,
|
|
returnCode: '0000', // false: 9999
|
|
returnMsg: 'in amet',
|
|
}
|
|
return result
|
|
}
|
|
|
|
/**
|
|
* 通知商户打币
|
|
* TODO::
|
|
*/
|
|
@role(ROLE_ANON)
|
|
@router('post /pay/out/alchemy/distribute')
|
|
async distributeToken(req, res) {
|
|
const { orderNo, crypto, network, address, cryptoAmount, cryptoPrice, usdtAmount } = req.params
|
|
const { appId, timestamp, sign } = req.headers
|
|
if (!orderNo || !crypto || !network || !address || !cryptoAmount || !cryptoPrice || !usdtAmount) {
|
|
return errorRes('params mismatch')
|
|
}
|
|
if (!appId || !timestamp || !sign) {
|
|
return errorRes('headers mismatch')
|
|
}
|
|
if (!checkSimpleSign(req.headers)) {
|
|
return errorRes('sign error')
|
|
}
|
|
|
|
let record = await PayRecord.findByRecordId(orderNo)
|
|
if (!record) {
|
|
return errorRes('orderNo not found')
|
|
}
|
|
if (record.crypto != crypto || record.network != network || record.address != address) {
|
|
return errorRes('params mismatch')
|
|
}
|
|
record.cryptoAmount = cryptoAmount
|
|
record.cryptoPrice = cryptoPrice
|
|
record.usdtAdmount = usdtAmount
|
|
await record.save()
|
|
new TransferQueue().addTask(record)
|
|
let result = {
|
|
direct: 1,
|
|
data: null,
|
|
success: true,
|
|
returnCode: '0000', // false: 9999
|
|
returnMsg: 'in amet',
|
|
}
|
|
res.send(result)
|
|
}
|
|
}
|