修改交易流程
This commit is contained in:
parent
e5dc33970c
commit
0913368456
@ -17,10 +17,10 @@ EMAIL_SERVER='http://127.0.0.1:3087'
|
||||
|
||||
ALCHEMY_APPID="f83Is2y7L425rxl8"
|
||||
ALCHEMY_APP_SECRET="4Yn8RkxDXN71Q3p0"
|
||||
ALCHEMY_API_BASE="https://openapi-test.alchemypay.org"
|
||||
ALCHEMY_PAGE_BASE="https://ramptest.alchemypay.org"
|
||||
# ALCHEMY_API_BASE="http://127.0.0.1:3009"
|
||||
# ALCHEMY_PAGE_BASE="http://127.0.0.1:3009/pay_page"
|
||||
# ALCHEMY_API_BASE="https://openapi-test.alchemypay.org"
|
||||
# ALCHEMY_PAGE_BASE="https://ramptest.alchemypay.org"
|
||||
ALCHEMY_API_BASE="http://127.0.0.1:3009"
|
||||
ALCHEMY_PAGE_BASE="http://127.0.0.1:3009/pay_page"
|
||||
|
||||
ALCHEMY_PAY_CB_URL="https://wallet.cebggame.com"
|
||||
|
||||
|
@ -94,59 +94,6 @@ class AlchemyController extends BaseController {
|
||||
}
|
||||
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) {
|
||||
|
@ -21,53 +21,69 @@ let errorRes = function (msg: string) {
|
||||
}
|
||||
}
|
||||
/**
|
||||
* for Alchemy call
|
||||
* for Alchemy call,
|
||||
*/
|
||||
class AlchemyOutController extends BaseController {
|
||||
// 购买回调
|
||||
@role(ROLE_ANON)
|
||||
@router('post /pay/out/alchemy/buycb')
|
||||
async alchemyCallback(req, res) {
|
||||
@router('post /pay/out/alchemy/result')
|
||||
async buyresult(req, res) {
|
||||
let { orderNo, status, crypto, network, merchantOrderNo } = req.params
|
||||
logger.info(`alchemy callback: ${orderNo}, ${status}, ${crypto}, ${network}, ${merchantOrderNo}`)
|
||||
if (!merchantOrderNo) {
|
||||
logger.info(`alchemy callback merchantOrderNo not found`)
|
||||
logger.info(`alchemy callback merchantOrderNo not found, ordreNo: ${orderNo}`)
|
||||
throw new ZError(11, 'alchemy callback merchantOrderNo not found')
|
||||
}
|
||||
|
||||
let record = await PayRecord.findById(merchantOrderNo)
|
||||
if (!record) {
|
||||
logger.info(`alchemy callback record not found`)
|
||||
logger.info(`alchemy callback record not found, ordreNo: ${orderNo}`)
|
||||
throw new ZError(12, 'alchemy callback record not found')
|
||||
}
|
||||
if (
|
||||
record.status !== PayStatus.PENDING &&
|
||||
record.status !== PayStatus.TRANSFERING &&
|
||||
record.status !== PayStatus.TRANSFERED
|
||||
) {
|
||||
logger.info(`alchemy callback record status error`)
|
||||
if (record.status !== PayStatus.PENDING && record.status !== PayStatus.PAYED) {
|
||||
logger.info(`alchemy callback record status error, ordreNo: ${orderNo}`)
|
||||
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')
|
||||
logger.info(`alchemy callback sign error: ${orderNo}`)
|
||||
throw new ZError(14, `alchemy callback sign error: orderNo: ${orderNo}`)
|
||||
}
|
||||
let transferRecord = await TransferRecord.findByRecordId(record.id)
|
||||
if (transferRecord) {
|
||||
transferRecord.status = 9
|
||||
await transferRecord.save()
|
||||
if (status === 'FINISHED') {
|
||||
let transferRecord = await TransferRecord.findByRecordId(record.id)
|
||||
if (transferRecord) {
|
||||
transferRecord.status = 9
|
||||
await transferRecord.save()
|
||||
}
|
||||
}
|
||||
record.outOrderId = orderNo
|
||||
record.network = network
|
||||
record.crypto = crypto
|
||||
record.outData = req.params
|
||||
record.status = status == 'PAY_SUCCESS' ? PayStatus.SUCCESS : PayStatus.FAIL
|
||||
record.outDatas.push(req.params)
|
||||
if (req.params.payTime) {
|
||||
record.payTime = req.params.payTime
|
||||
}
|
||||
if (status === 'PAY_SUCCESS') {
|
||||
record.status = PayStatus.PAYED
|
||||
} else if (status === 'FINISHED') {
|
||||
record.status = PayStatus.SUCCESS
|
||||
} else {
|
||||
record.status = PayStatus.FAIL
|
||||
}
|
||||
await record.save()
|
||||
setImmediate(() => {
|
||||
reportPayResult(record)
|
||||
})
|
||||
logger.info(`alchemy callback success, pay finished`)
|
||||
if (status === 'FINISHED') {
|
||||
setImmediate(async () => {
|
||||
try {
|
||||
await reportPayResult(record)
|
||||
record.reportStatus = 1
|
||||
await record.save()
|
||||
} catch (err) {
|
||||
logger.info(`report pay result:: ${record.outOrderId} error: ${err.message}`)
|
||||
record.reportStatus = 99
|
||||
await record.save()
|
||||
}
|
||||
})
|
||||
}
|
||||
logger.info(`alchemy callback success, status: ${status} orderNo: ${orderNo} `)
|
||||
return {}
|
||||
}
|
||||
|
||||
@ -93,7 +109,7 @@ class AlchemyOutController extends BaseController {
|
||||
return errorRes('sign error')
|
||||
}
|
||||
let gas = 36000 * 0.0000000001
|
||||
let price = await new PriceSvr().fetchPrice({ crypto: 'ETH', network: 'ARBITRUM' })
|
||||
let price = await new PriceSvr().fetchPrice({ crypto: 'ETH', network: 'ARBITRUM', fiat: 'USD' })
|
||||
let networkFee = gas * parseFloat(price)
|
||||
let result = {
|
||||
direct: 1,
|
||||
@ -145,6 +161,8 @@ class AlchemyOutController extends BaseController {
|
||||
new OrderCacheSvr().removeOrder(orderNo)
|
||||
return errorRes('orderNo not found')
|
||||
}
|
||||
record.outDatas.push(req.params)
|
||||
await record.save()
|
||||
if (record.crypto != crypto || record.network != network || record.address != address) {
|
||||
new OrderCacheSvr().removeOrder(orderNo)
|
||||
return errorRes('params mismatch')
|
||||
@ -161,7 +179,6 @@ class AlchemyOutController extends BaseController {
|
||||
record.network.toLowerCase() === 'agor' && record.crypto.toLowerCase() === 'agor' ? '0.001' : cryptoAmount
|
||||
record.cryptoPrice = cryptoPrice
|
||||
record.usdtAdmount = usdtAmount
|
||||
record.status = PayStatus.TRANSFERING
|
||||
await record.save()
|
||||
new TransferQueue().addTask(record)
|
||||
let result = {
|
||||
|
@ -24,11 +24,11 @@ const notify = async function (record: DocumentType<PayRecordClass>, subTask: Do
|
||||
network: record.network, // 用户购买的数字货币对应的网络
|
||||
// networkFee: record.networkFee, // 网络费用/USDT
|
||||
address: record.address, // 用户的提币地址
|
||||
status: record.status === PayStatus.TRANSFERED ? 'SUCCESS' : 'FAIL', // SUCCESS/FAIL
|
||||
status: record.tranStatus === 2 ? 'SUCCESS' : 'FAIL', // SUCCESS/FAIL
|
||||
}
|
||||
try {
|
||||
let price = await new PriceSvr().fetchPrice({ crypto: 'ETH', network: 'ARBITRUM' })
|
||||
data.networkFee = parseFloat(subTask.gas) * parseFloat(subTask.gasPrice) * parseFloat(price) + ''
|
||||
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) {
|
||||
@ -71,10 +71,10 @@ export default class InternalController extends BaseController {
|
||||
record.gasPrice = gasPrice
|
||||
record.hashList = hashList
|
||||
task.txHash = hashList[0]
|
||||
task.status = PayStatus.TRANSFERED
|
||||
task.tranStatus = 2
|
||||
} else {
|
||||
record.status = 10
|
||||
task.status = PayStatus.TRANSFER_FAIL
|
||||
task.tranStatus = 99
|
||||
}
|
||||
await record.save()
|
||||
await task.save()
|
||||
|
@ -13,10 +13,9 @@ export enum PayType {
|
||||
|
||||
export enum PayStatus {
|
||||
PENDING = 0, // 默认状态, 未支付
|
||||
TRANSFERING = 1, //只有国库模式才会有该状态
|
||||
TRANSFERED = 2, //只有国库模式才会有该状态
|
||||
PAYED = 3, // 已支付
|
||||
SUCCESS = 9,
|
||||
TRANSFER_FAIL = 98, // 转账错误
|
||||
PAY_FAIL = 97, // 用户支付失败, 国库模式
|
||||
FAIL = 99, // 交易失败
|
||||
}
|
||||
|
||||
@ -58,6 +57,7 @@ export class PayRecordClass extends BaseModule {
|
||||
// 加密货币数量, 实际转账金额
|
||||
@prop()
|
||||
public cryptoAmount?: string
|
||||
|
||||
// 开始创建记录时, 估算的可获取加密货币数量
|
||||
@prop()
|
||||
public cryptoAmountEstimate: string
|
||||
@ -74,10 +74,18 @@ export class PayRecordClass extends BaseModule {
|
||||
// 交易状态
|
||||
@prop({ required: true, default: PayStatus.PENDING })
|
||||
public status: PayStatus
|
||||
|
||||
// 渠道返回的原始资料
|
||||
@prop({ type: mongoose.Schema.Types.Mixed })
|
||||
public outData: any
|
||||
|
||||
@prop({ type: () => [mongoose.Schema.Types.Mixed] })
|
||||
public outDatas: any[]
|
||||
|
||||
// 支付时间, 由alchemy提供
|
||||
@prop()
|
||||
public payTime: string
|
||||
|
||||
// 渠道返回的订单id
|
||||
@prop()
|
||||
public outOrderId: string
|
||||
@ -89,6 +97,24 @@ export class PayRecordClass extends BaseModule {
|
||||
public gameAccountId: string
|
||||
@prop()
|
||||
public gameOrderId: string
|
||||
/**
|
||||
* 国库模式转账状态
|
||||
* 0: 未转账
|
||||
* 1: 提交转账成功
|
||||
* 2: 转账成功
|
||||
* 99: 转账失败
|
||||
*/
|
||||
@prop({ default: 0 })
|
||||
public tranStatus: number
|
||||
|
||||
/**
|
||||
* 上报游戏服状态
|
||||
* 0: 未上报
|
||||
* 1: 上报成功
|
||||
* 99: 上报失败
|
||||
*/
|
||||
@prop({ default: 0 })
|
||||
public reportStatus: number
|
||||
|
||||
public static async findByRecordId(this: ReturnModelType<typeof PayRecordClass>, outOrderId: string) {
|
||||
return this.findOne({ outOrderId }).exec()
|
||||
|
@ -91,9 +91,11 @@ export class TransferQueue {
|
||||
cb: process.env.PAY_TRANSFER_CB_URL,
|
||||
}
|
||||
await pushTaskToChain(reqData)
|
||||
|
||||
task.tranStatus = 1
|
||||
await task.save()
|
||||
} catch (err) {
|
||||
task.tranStatus = 99
|
||||
await task.save()
|
||||
logger.error('error add chain task: ')
|
||||
logger.error(err)
|
||||
}
|
||||
|
@ -40,8 +40,9 @@ export function createSha1Sign() {
|
||||
* @returns true if the sign is valid, false otherwise
|
||||
*/
|
||||
export function checkPayResultSign(data: any) {
|
||||
const { appId, orderNo, crypto, network, address, signature } = data
|
||||
const sign = sha1(appId + process.env.ALCHEMY_APP_SECRET + appId + orderNo + crypto + network + address)
|
||||
const { appId, appid, orderNo, crypto, network, address, signature } = data
|
||||
const appIdReal = appId || appid
|
||||
const sign = sha1(appIdReal + process.env.ALCHEMY_APP_SECRET + appIdReal + orderNo + crypto + network + address)
|
||||
return sign === signature
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user