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