修复BSC币商C2C凭证校验
This commit is contained in:
parent
aac2b4dc76
commit
7609509f7f
@ -342,8 +342,10 @@ func (s *Service) verifyUSDTRechargeReceipt(ctx context.Context, command ledger.
|
|||||||
snapshot.ProviderAmountMinor = command.USDMinorAmount
|
snapshot.ProviderAmountMinor = command.USDMinorAmount
|
||||||
snapshot.ProviderOrderID = command.ExternalOrderNo
|
snapshot.ProviderOrderID = command.ExternalOrderNo
|
||||||
snapshot.ReceiveAddress = strings.TrimSpace(receiveAddress)
|
snapshot.ReceiveAddress = strings.TrimSpace(receiveAddress)
|
||||||
if chain == "trc20" && !isLikelyChainTransactionHash(command.ExternalOrderNo) {
|
if !isLikelyChainTransactionHash(command.ExternalOrderNo) {
|
||||||
return s.verifyBinanceTRXDepositReceipt(ctx, command, snapshot)
|
// Binance Pay C2C 订单号不属于某条公链;后台选择 TRC20 或 BEP20 只表示运营记录的支付币种。
|
||||||
|
// 因此所有非链上哈希都必须先走 Binance 账户入账事实,不能把 BEP20 的 C2C 订单号误送给 BSC 链上客户端。
|
||||||
|
return s.verifyBinanceTransferReceipt(ctx, command, snapshot, binanceNetworkForReceiptChain(chain))
|
||||||
}
|
}
|
||||||
if client == nil {
|
if client == nil {
|
||||||
return ledger.CoinSellerRechargeReceiptVerification{}, xerr.New(xerr.Unavailable, "usdt "+chain+" client is not configured")
|
return ledger.CoinSellerRechargeReceiptVerification{}, xerr.New(xerr.Unavailable, "usdt "+chain+" client is not configured")
|
||||||
@ -360,7 +362,7 @@ func (s *Service) verifyUSDTRechargeReceipt(ctx context.Context, command ledger.
|
|||||||
return snapshot, nil
|
return snapshot, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Service) verifyBinanceTRXDepositReceipt(ctx context.Context, command ledger.VerifyCoinSellerRechargeReceiptCommand, snapshot ledger.CoinSellerRechargeReceiptVerification) (ledger.CoinSellerRechargeReceiptVerification, error) {
|
func (s *Service) verifyBinanceTransferReceipt(ctx context.Context, command ledger.VerifyCoinSellerRechargeReceiptCommand, snapshot ledger.CoinSellerRechargeReceiptVerification, network string) (ledger.CoinSellerRechargeReceiptVerification, error) {
|
||||||
if s.binance == nil {
|
if s.binance == nil {
|
||||||
return ledger.CoinSellerRechargeReceiptVerification{}, xerr.New(xerr.Unavailable, "binance client is not configured")
|
return ledger.CoinSellerRechargeReceiptVerification{}, xerr.New(xerr.Unavailable, "binance client is not configured")
|
||||||
}
|
}
|
||||||
@ -370,7 +372,7 @@ func (s *Service) verifyBinanceTRXDepositReceipt(ctx context.Context, command le
|
|||||||
AppCode: command.AppCode,
|
AppCode: command.AppCode,
|
||||||
ExternalID: command.ExternalOrderNo,
|
ExternalID: command.ExternalOrderNo,
|
||||||
Coin: ledger.PaidCurrencyUSDT,
|
Coin: ledger.PaidCurrencyUSDT,
|
||||||
Network: "TRX",
|
Network: network,
|
||||||
ToAddress: snapshot.ReceiveAddress,
|
ToAddress: snapshot.ReceiveAddress,
|
||||||
AmountMinor: command.USDMinorAmount,
|
AmountMinor: command.USDMinorAmount,
|
||||||
OrderTimeMS: command.OrderDateMS,
|
OrderTimeMS: command.OrderDateMS,
|
||||||
@ -392,6 +394,17 @@ func (s *Service) verifyBinanceTRXDepositReceipt(ctx context.Context, command le
|
|||||||
return snapshot, nil
|
return snapshot, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func binanceNetworkForReceiptChain(chain string) string {
|
||||||
|
// Binance Deposit History 使用交易所网络代码而不是后台 provider 名称;Pay C2C 不校验网络,
|
||||||
|
// 但同一个入口也支持 off-chain Deposit History,因此这里必须保留准确映射。
|
||||||
|
switch strings.ToLower(strings.TrimSpace(chain)) {
|
||||||
|
case "bep20":
|
||||||
|
return "BSC"
|
||||||
|
default:
|
||||||
|
return "TRX"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func (s *Service) receiptSnapshot(command ledger.VerifyCoinSellerRechargeReceiptCommand) ledger.CoinSellerRechargeReceiptVerification {
|
func (s *Service) receiptSnapshot(command ledger.VerifyCoinSellerRechargeReceiptCommand) ledger.CoinSellerRechargeReceiptVerification {
|
||||||
return ledger.CoinSellerRechargeReceiptVerification{
|
return ledger.CoinSellerRechargeReceiptVerification{
|
||||||
ProviderCode: command.ProviderCode,
|
ProviderCode: command.ProviderCode,
|
||||||
|
|||||||
@ -467,10 +467,11 @@ func TestVerifyCoinSellerRechargeReceiptUSDTBEP20UsesReadOnlyClient(t *testing.T
|
|||||||
USDTBEP20Enabled: true,
|
USDTBEP20Enabled: true,
|
||||||
USDTBEP20Address: "0xPlatformBEP20ReceiveAddress",
|
USDTBEP20Address: "0xPlatformBEP20ReceiveAddress",
|
||||||
})
|
})
|
||||||
|
txHash := "0x0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef"
|
||||||
receipt, err := svc.VerifyCoinSellerRechargeReceipt(context.Background(), ledger.VerifyCoinSellerRechargeReceiptCommand{
|
receipt, err := svc.VerifyCoinSellerRechargeReceipt(context.Background(), ledger.VerifyCoinSellerRechargeReceiptCommand{
|
||||||
AppCode: "lalu",
|
AppCode: "lalu",
|
||||||
ProviderCode: ledger.PaymentProviderUSDTBEP20,
|
ProviderCode: ledger.PaymentProviderUSDTBEP20,
|
||||||
ExternalOrderNo: "0xreceiptbep20",
|
ExternalOrderNo: txHash,
|
||||||
USDMinorAmount: 150,
|
USDMinorAmount: 150,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -479,7 +480,7 @@ func TestVerifyCoinSellerRechargeReceiptUSDTBEP20UsesReadOnlyClient(t *testing.T
|
|||||||
if !receipt.Verified || receipt.Status != "confirmed" || receipt.Chain != "bep20" || receipt.ProviderAmountMinor != 150 || receipt.ReceiveAddress != "0xPlatformBEP20ReceiveAddress" {
|
if !receipt.Verified || receipt.Status != "confirmed" || receipt.Chain != "bep20" || receipt.ProviderAmountMinor != 150 || receipt.ReceiveAddress != "0xPlatformBEP20ReceiveAddress" {
|
||||||
t.Fatalf("bep20 receipt snapshot mismatch: %+v", receipt)
|
t.Fatalf("bep20 receipt snapshot mismatch: %+v", receipt)
|
||||||
}
|
}
|
||||||
if bsc.lastTxHash != "0xreceiptbep20" || bsc.lastToAddress != "0xPlatformBEP20ReceiveAddress" || bsc.lastAmountMinor != 150 {
|
if bsc.lastTxHash != txHash || bsc.lastToAddress != "0xPlatformBEP20ReceiveAddress" || bsc.lastAmountMinor != 150 {
|
||||||
t.Fatalf("bep20 client request mismatch: %+v", bsc)
|
t.Fatalf("bep20 client request mismatch: %+v", bsc)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -611,6 +612,51 @@ func TestVerifyCoinSellerRechargeReceiptUSDTTRC20PayKeepsConfiguredAddress(t *te
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestVerifyCoinSellerRechargeReceiptUSDTBEP20PayUsesBinance(t *testing.T) {
|
||||||
|
bsc := &fakeTronUSDTClient{err: xerr.New(xerr.Internal, "bsc chain client should not be called")}
|
||||||
|
binance := &fakeBinanceClient{record: walletservice.BinanceTransferRecord{
|
||||||
|
Source: "pay_history",
|
||||||
|
ID: "440537037787594752",
|
||||||
|
TxID: "P_C2C_BEP20_RECEIPT",
|
||||||
|
Coin: ledger.PaidCurrencyUSDT,
|
||||||
|
Status: 1,
|
||||||
|
Amount: "200.00000000",
|
||||||
|
AmountMinor: 20000,
|
||||||
|
RawJSON: `{"orderType":"C2C","orderId":"440537037787594752","amount":"200.00000000","currency":"USDT"}`,
|
||||||
|
}}
|
||||||
|
svc := walletservice.New(nil)
|
||||||
|
svc.SetBSCUSDTClient(bsc)
|
||||||
|
svc.SetBinanceClient(binance)
|
||||||
|
svc.SetExternalRechargeConfig(walletservice.ExternalRechargeConfig{
|
||||||
|
USDTBEP20Enabled: true,
|
||||||
|
USDTBEP20Addresses: map[string]string{
|
||||||
|
"yumi": "0xYumiConfiguredBSCAddress",
|
||||||
|
},
|
||||||
|
})
|
||||||
|
receipt, err := svc.VerifyCoinSellerRechargeReceipt(context.Background(), ledger.VerifyCoinSellerRechargeReceiptCommand{
|
||||||
|
AppCode: "yumi",
|
||||||
|
ProviderCode: ledger.PaymentProviderUSDTBEP20,
|
||||||
|
ExternalOrderNo: "440537037787594752",
|
||||||
|
USDMinorAmount: 20000,
|
||||||
|
OrderDateMS: 1784017140000,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("VerifyCoinSellerRechargeReceipt BEP20 Pay C2C failed: %v", err)
|
||||||
|
}
|
||||||
|
if !receipt.Verified || receipt.Status != "confirmed" || receipt.ProviderOrderID != "P_C2C_BEP20_RECEIPT" || receipt.ProviderAmountMinor != 20000 {
|
||||||
|
t.Fatalf("BEP20 Pay C2C receipt snapshot mismatch: %+v", receipt)
|
||||||
|
}
|
||||||
|
if receipt.ReceiveAddress != "0xYumiConfiguredBSCAddress" {
|
||||||
|
t.Fatalf("BEP20 Pay C2C must keep configured chain address: %+v", receipt)
|
||||||
|
}
|
||||||
|
if binance.calls != 1 || binance.req.Network != "BSC" || binance.req.ExternalID != "440537037787594752" || binance.req.AmountMinor != 20000 {
|
||||||
|
t.Fatalf("BEP20 Pay C2C must use Binance transfer lookup: calls=%d req=%+v", binance.calls, binance.req)
|
||||||
|
}
|
||||||
|
if bsc.lastTxHash != "" {
|
||||||
|
t.Fatalf("BEP20 Pay C2C order id must not call BSC chain client: %+v", bsc)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestVerifyCoinSellerRechargeReceiptUSDTTRC20OffchainMissingBinanceAccount(t *testing.T) {
|
func TestVerifyCoinSellerRechargeReceiptUSDTTRC20OffchainMissingBinanceAccount(t *testing.T) {
|
||||||
binance := &fakeBinanceClient{err: xerr.New(xerr.Unavailable, "binance account is not configured")}
|
binance := &fakeBinanceClient{err: xerr.New(xerr.Unavailable, "binance account is not configured")}
|
||||||
svc := walletservice.New(nil)
|
svc := walletservice.New(nil)
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user