增加显式C2C充值校验渠道

This commit is contained in:
zhx 2026-07-14 16:33:15 +08:00
parent 7609509f7f
commit 3210db25c4
6 changed files with 95 additions and 25 deletions

View File

@ -850,6 +850,8 @@ func normalizeRechargeProvider(providerCode string, chain string) (string, strin
return "usdt", "TRON", nil return "usdt", "TRON", nil
case "usdt_bep20", "bep20", "bsc", "bnb": case "usdt_bep20", "bep20", "bsc", "bnb":
return "usdt", "BSC", nil return "usdt", "BSC", nil
case "usdt_c2c", "c2c":
return "usdt", "C2C", nil
default: default:
return "", "", errors.New("充值方式不正确") return "", "", errors.New("充值方式不正确")
} }
@ -865,6 +867,8 @@ func normalizeRechargeChain(chain string) string {
return "TRON" return "TRON"
case "bsc", "bnb", "bep20", "usdt_bep20": case "bsc", "bnb", "bep20", "usdt_bep20":
return "BSC" return "BSC"
case "c2c", "usdt_c2c":
return "C2C"
default: default:
return "" return ""
} }
@ -879,6 +883,8 @@ func receiptProviderCode(order model.CoinSellerRechargeOrder) string {
return "usdt_trc20" return "usdt_trc20"
case "BSC": case "BSC":
return "usdt_bep20" return "usdt_bep20"
case "C2C":
return "usdt_c2c"
default: default:
return "usdt" return "usdt"
} }
@ -903,6 +909,8 @@ func receiptChain(order model.CoinSellerRechargeOrder) string {
return "trc20" return "trc20"
case "BSC": case "BSC":
return "bep20" return "bep20"
case "C2C":
return "c2c"
default: default:
return "" return ""
} }

View File

@ -79,7 +79,7 @@ func (c *Client) FindUSDTTransfer(ctx context.Context, req ports.BinanceTransfer
req.Coin = strings.ToUpper(strings.TrimSpace(req.Coin)) req.Coin = strings.ToUpper(strings.TrimSpace(req.Coin))
req.Network = strings.ToUpper(strings.TrimSpace(req.Network)) req.Network = strings.ToUpper(strings.TrimSpace(req.Network))
req.ToAddress = strings.TrimSpace(req.ToAddress) req.ToAddress = strings.TrimSpace(req.ToAddress)
if req.ExternalID == "" || req.Coin == "" || req.Network == "" || req.ToAddress == "" || req.AmountMinor <= 0 { if req.ExternalID == "" || req.Coin == "" || req.Network == "" || req.AmountMinor <= 0 {
return ports.BinanceTransferRecord{}, xerr.New(xerr.InvalidArgument, "binance transfer verification request is incomplete") return ports.BinanceTransferRecord{}, xerr.New(xerr.InvalidArgument, "binance transfer verification request is incomplete")
} }
serverTimeMS, err := c.serverTime(ctx) serverTimeMS, err := c.serverTime(ctx)
@ -260,7 +260,8 @@ func matchDepositRecord(req ports.BinanceTransferLookupRequest, records []deposi
if candidate.Status != 1 { if candidate.Status != 1 {
return ports.BinanceTransferRecord{}, xerr.New(xerr.Conflict, "binance deposit status is not successful") return ports.BinanceTransferRecord{}, xerr.New(xerr.Conflict, "binance deposit status is not successful")
} }
if !strings.EqualFold(strings.TrimSpace(candidate.Address), strings.TrimSpace(req.ToAddress)) { // Deposit History 属于具体链上入账,必须有预先配置的收款地址;允许空地址仅服务于随后独立校验的 Pay C2C 事实源。
if strings.TrimSpace(req.ToAddress) == "" || !strings.EqualFold(strings.TrimSpace(candidate.Address), strings.TrimSpace(req.ToAddress)) {
return ports.BinanceTransferRecord{}, xerr.New(xerr.Conflict, "binance deposit address mismatch") return ports.BinanceTransferRecord{}, xerr.New(xerr.Conflict, "binance deposit address mismatch")
} }
amountMinor, err := parseUSDTAmountMinor(candidate.Amount) amountMinor, err := parseUSDTAmountMinor(candidate.Amount)

View File

@ -68,6 +68,8 @@ const (
PaymentProviderUSDTTRC20 = "usdt_trc20" PaymentProviderUSDTTRC20 = "usdt_trc20"
// PaymentProviderUSDTBEP20 是用户提交 BSC BEP20 链上交易哈希的 USDT 充值渠道。 // PaymentProviderUSDTBEP20 是用户提交 BSC BEP20 链上交易哈希的 USDT 充值渠道。
PaymentProviderUSDTBEP20 = "usdt_bep20" PaymentProviderUSDTBEP20 = "usdt_bep20"
// PaymentProviderUSDTC2C 是 Binance Pay C2C 收款订单;它不绑定公链,也不要求链上收款地址。
PaymentProviderUSDTC2C = "usdt_c2c"
// ThirdPartyPaymentStatusActive 表示渠道或支付方式可用于 H5 下单。 // ThirdPartyPaymentStatusActive 表示渠道或支付方式可用于 H5 下单。
ThirdPartyPaymentStatusActive = "active" ThirdPartyPaymentStatusActive = "active"
// ThirdPartyPaymentStatusDisabled 表示渠道或支付方式已被后台关闭。 // ThirdPartyPaymentStatusDisabled 表示渠道或支付方式已被后台关闭。

View File

@ -416,6 +416,8 @@ func NormalizePaymentProvider(provider string) string {
return PaymentProviderUSDTTRC20 return PaymentProviderUSDTTRC20
case PaymentProviderUSDTBEP20: case PaymentProviderUSDTBEP20:
return PaymentProviderUSDTBEP20 return PaymentProviderUSDTBEP20
case PaymentProviderUSDTC2C:
return PaymentProviderUSDTC2C
case PaymentProviderGooglePlay: case PaymentProviderGooglePlay:
return PaymentProviderGooglePlay return PaymentProviderGooglePlay
default: default:

View File

@ -33,6 +33,9 @@ func (s *Service) VerifyCoinSellerRechargeReceipt(ctx context.Context, command l
return s.verifyUSDTRechargeReceipt(ctx, command, "trc20", s.externalRecharge.USDTTRC20Enabled, s.externalRecharge.usdtTRC20AddressForApp(command.AppCode), s.tronUSDT) return s.verifyUSDTRechargeReceipt(ctx, command, "trc20", s.externalRecharge.USDTTRC20Enabled, s.externalRecharge.usdtTRC20AddressForApp(command.AppCode), s.tronUSDT)
case ledger.PaymentProviderUSDTBEP20: case ledger.PaymentProviderUSDTBEP20:
return s.verifyUSDTRechargeReceipt(ctx, command, "bep20", s.externalRecharge.USDTBEP20Enabled, s.externalRecharge.usdtBEP20AddressForApp(command.AppCode), s.bscUSDT) return s.verifyUSDTRechargeReceipt(ctx, command, "bep20", s.externalRecharge.USDTBEP20Enabled, s.externalRecharge.usdtBEP20AddressForApp(command.AppCode), s.bscUSDT)
case ledger.PaymentProviderUSDTC2C:
// C2C 是 Binance 账户内收款事实,不属于 TRON/BSC空地址和关闭的链上开关不影响只读查单。
return s.verifyUSDTRechargeReceipt(ctx, command, "c2c", false, "", nil)
default: default:
return ledger.CoinSellerRechargeReceiptVerification{}, xerr.New(xerr.InvalidArgument, "receipt provider is invalid") return ledger.CoinSellerRechargeReceiptVerification{}, xerr.New(xerr.InvalidArgument, "receipt provider is invalid")
} }
@ -333,20 +336,23 @@ type receiptUSDTClient interface {
} }
func (s *Service) verifyUSDTRechargeReceipt(ctx context.Context, command ledger.VerifyCoinSellerRechargeReceiptCommand, chain string, enabled bool, receiveAddress string, client receiptUSDTClient) (ledger.CoinSellerRechargeReceiptVerification, error) { func (s *Service) verifyUSDTRechargeReceipt(ctx context.Context, command ledger.VerifyCoinSellerRechargeReceiptCommand, chain string, enabled bool, receiveAddress string, client receiptUSDTClient) (ledger.CoinSellerRechargeReceiptVerification, error) {
if !enabled || strings.TrimSpace(receiveAddress) == "" {
return ledger.CoinSellerRechargeReceiptVerification{}, xerr.New(xerr.Unavailable, "usdt "+chain+" receipt verification is not configured")
}
snapshot := s.receiptSnapshot(command) snapshot := s.receiptSnapshot(command)
snapshot.Chain = chain snapshot.Chain = chain
snapshot.CurrencyCode = ledger.PaidCurrencyUSDT snapshot.CurrencyCode = ledger.PaidCurrencyUSDT
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 !isLikelyChainTransactionHash(command.ExternalOrderNo) { if chain == "c2c" {
// Binance Pay C2C 订单号不属于某条公链;后台选择 TRC20 或 BEP20 只表示运营记录的支付币种。 // 查单来源由运营显式选择C2C 只读取 Binance 账户事实,绝不从 TRON/BSC 隐式降级或猜测。
// 因此所有非链上哈希都必须先走 Binance 账户入账事实,不能把 BEP20 的 C2C 订单号误送给 BSC 链上客户端。
return s.verifyBinanceTransferReceipt(ctx, command, snapshot, binanceNetworkForReceiptChain(chain)) return s.verifyBinanceTransferReceipt(ctx, command, snapshot, binanceNetworkForReceiptChain(chain))
} }
if !enabled || snapshot.ReceiveAddress == "" {
return ledger.CoinSellerRechargeReceiptVerification{}, xerr.New(xerr.Unavailable, "usdt "+chain+" receipt verification is not configured")
}
if !isLikelyChainTransactionHash(command.ExternalOrderNo) {
// TRON/BSC 只接受标准交易哈希;非链上编号必须由运营明确改选 C2C避免跨事实源误校验。
return ledger.CoinSellerRechargeReceiptVerification{}, xerr.New(xerr.InvalidArgument, "usdt "+chain+" receipt requires transaction hash")
}
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")
} }
@ -387,7 +393,7 @@ func (s *Service) verifyBinanceTransferReceipt(ctx context.Context, command ledg
snapshot.ProviderOrderID = record.TxID snapshot.ProviderOrderID = record.TxID
snapshot.ProviderAmountMinor = record.AmountMinor snapshot.ProviderAmountMinor = record.AmountMinor
// Pay C2C 没有链上收款地址;只有 Deposit History 命中时才用 Binance 返回地址覆盖配置快照。 // Pay C2C 没有链上收款地址;只有 Deposit History 命中时才用 Binance 返回地址覆盖配置快照。
if strings.TrimSpace(record.Address) != "" { if snapshot.Chain != "c2c" && strings.TrimSpace(record.Address) != "" {
snapshot.ReceiveAddress = record.Address snapshot.ReceiveAddress = record.Address
} }
snapshot.RawJSON = strings.TrimSpace(record.RawJSON) snapshot.RawJSON = strings.TrimSpace(record.RawJSON)
@ -400,6 +406,8 @@ func binanceNetworkForReceiptChain(chain string) string {
switch strings.ToLower(strings.TrimSpace(chain)) { switch strings.ToLower(strings.TrimSpace(chain)) {
case "bep20": case "bep20":
return "BSC" return "BSC"
case "c2c":
return "C2C"
default: default:
return "TRX" return "TRX"
} }

View File

@ -529,7 +529,25 @@ func TestVerifyCoinSellerRechargeReceiptUSDTTRC20HashUsesTronGrid(t *testing.T)
} }
} }
func TestVerifyCoinSellerRechargeReceiptUSDTTRC20OffchainUsesBinance(t *testing.T) { func TestVerifyCoinSellerRechargeReceiptUSDTTRC20RejectsC2COrderNumber(t *testing.T) {
svc := walletservice.New(nil)
svc.SetTronUSDTClient(&fakeTronUSDTClient{})
svc.SetExternalRechargeConfig(walletservice.ExternalRechargeConfig{
USDTTRC20Enabled: true,
USDTTRC20Address: "TPlatformReceiveAddress",
})
_, err := svc.VerifyCoinSellerRechargeReceipt(context.Background(), ledger.VerifyCoinSellerRechargeReceiptCommand{
AppCode: "lalu",
ProviderCode: ledger.PaymentProviderUSDTTRC20,
ExternalOrderNo: "440537037787594752",
USDMinorAmount: 20000,
})
if !xerr.IsCode(err, xerr.InvalidArgument) || !strings.Contains(err.Error(), "requires transaction hash") {
t.Fatalf("TRC20 must reject C2C order number without fallback: %v", err)
}
}
func TestVerifyCoinSellerRechargeReceiptUSDTC2CUsesBinance(t *testing.T) {
tron := &fakeTronUSDTClient{err: xerr.New(xerr.Internal, "tron should not be called")} tron := &fakeTronUSDTClient{err: xerr.New(xerr.Internal, "tron should not be called")}
binance := &fakeBinanceClient{record: walletservice.BinanceTransferRecord{ binance := &fakeBinanceClient{record: walletservice.BinanceTransferRecord{
TxID: "Off-chain transfer 388611987194", TxID: "Off-chain transfer 388611987194",
@ -553,7 +571,7 @@ func TestVerifyCoinSellerRechargeReceiptUSDTTRC20OffchainUsesBinance(t *testing.
}) })
receipt, err := svc.VerifyCoinSellerRechargeReceipt(context.Background(), ledger.VerifyCoinSellerRechargeReceiptCommand{ receipt, err := svc.VerifyCoinSellerRechargeReceipt(context.Background(), ledger.VerifyCoinSellerRechargeReceiptCommand{
AppCode: "aslan", AppCode: "aslan",
ProviderCode: ledger.PaymentProviderUSDTTRC20, ProviderCode: ledger.PaymentProviderUSDTC2C,
ExternalOrderNo: "388611987194", ExternalOrderNo: "388611987194",
USDMinorAmount: 50000, USDMinorAmount: 50000,
OrderDateMS: 1783344000000, OrderDateMS: 1783344000000,
@ -561,10 +579,10 @@ func TestVerifyCoinSellerRechargeReceiptUSDTTRC20OffchainUsesBinance(t *testing.
if err != nil { if err != nil {
t.Fatalf("VerifyCoinSellerRechargeReceipt binance offchain failed: %v", err) t.Fatalf("VerifyCoinSellerRechargeReceipt binance offchain failed: %v", err)
} }
if !receipt.Verified || receipt.Status != "confirmed" || receipt.ProviderOrderID != "Off-chain transfer 388611987194" || receipt.ProviderAmountMinor != 50000 || receipt.ReceiveAddress != "TNwqCkF8cnM4XiwjnbbKTfdZvFDqVoa1TN" { if !receipt.Verified || receipt.Status != "confirmed" || receipt.ProviderOrderID != "Off-chain transfer 388611987194" || receipt.ProviderAmountMinor != 50000 || receipt.ReceiveAddress != "" {
t.Fatalf("binance offchain receipt snapshot mismatch: %+v", receipt) t.Fatalf("binance offchain receipt snapshot mismatch: %+v", receipt)
} }
if binance.calls != 1 || binance.req.AppCode != "aslan" || binance.req.ExternalID != "388611987194" || binance.req.Network != "TRX" || binance.req.ToAddress != "TNwqCkF8cnM4XiwjnbbKTfdZvFDqVoa1TN" || binance.req.AmountMinor != 50000 || binance.req.OrderTimeMS != 1783344000000 { if binance.calls != 1 || binance.req.AppCode != "aslan" || binance.req.ExternalID != "388611987194" || binance.req.Network != "C2C" || binance.req.ToAddress != "" || binance.req.AmountMinor != 50000 || binance.req.OrderTimeMS != 1783344000000 {
t.Fatalf("binance offchain request mismatch: calls=%d req=%+v", binance.calls, binance.req) t.Fatalf("binance offchain request mismatch: calls=%d req=%+v", binance.calls, binance.req)
} }
if tron.lastTxHash != "" { if tron.lastTxHash != "" {
@ -572,7 +590,7 @@ func TestVerifyCoinSellerRechargeReceiptUSDTTRC20OffchainUsesBinance(t *testing.
} }
} }
func TestVerifyCoinSellerRechargeReceiptUSDTTRC20PayKeepsConfiguredAddress(t *testing.T) { func TestVerifyCoinSellerRechargeReceiptUSDTC2CPayKeepsNoChainAddress(t *testing.T) {
binance := &fakeBinanceClient{record: walletservice.BinanceTransferRecord{ binance := &fakeBinanceClient{record: walletservice.BinanceTransferRecord{
Source: "pay_history", Source: "pay_history",
ID: "433527303245463552", ID: "433527303245463552",
@ -593,7 +611,7 @@ func TestVerifyCoinSellerRechargeReceiptUSDTTRC20PayKeepsConfiguredAddress(t *te
}) })
receipt, err := svc.VerifyCoinSellerRechargeReceipt(context.Background(), ledger.VerifyCoinSellerRechargeReceiptCommand{ receipt, err := svc.VerifyCoinSellerRechargeReceipt(context.Background(), ledger.VerifyCoinSellerRechargeReceiptCommand{
AppCode: "yumi", AppCode: "yumi",
ProviderCode: ledger.PaymentProviderUSDTTRC20, ProviderCode: ledger.PaymentProviderUSDTC2C,
ExternalOrderNo: "433527303245463552", ExternalOrderNo: "433527303245463552",
USDMinorAmount: 10000, USDMinorAmount: 10000,
OrderDateMS: 1779713682799, OrderDateMS: 1779713682799,
@ -604,15 +622,15 @@ func TestVerifyCoinSellerRechargeReceiptUSDTTRC20PayKeepsConfiguredAddress(t *te
if !receipt.Verified || receipt.Status != "confirmed" || receipt.ProviderOrderID != "P_A223BU5M4Y171116" || receipt.ProviderAmountMinor != 10000 { if !receipt.Verified || receipt.Status != "confirmed" || receipt.ProviderOrderID != "P_A223BU5M4Y171116" || receipt.ProviderAmountMinor != 10000 {
t.Fatalf("Pay C2C receipt snapshot mismatch: %+v", receipt) t.Fatalf("Pay C2C receipt snapshot mismatch: %+v", receipt)
} }
if receipt.ReceiveAddress != "TYumiConfiguredChainAddress" { if receipt.ReceiveAddress != "" {
t.Fatalf("Pay C2C must not erase configured chain address: %+v", receipt) t.Fatalf("Pay C2C must not inherit an unrelated chain address: %+v", receipt)
} }
if binance.req.OrderTimeMS != 1779713682799 { if binance.req.OrderTimeMS != 1779713682799 {
t.Fatalf("coin seller order time must bound Pay History query: %+v", binance.req) t.Fatalf("coin seller order time must bound Pay History query: %+v", binance.req)
} }
} }
func TestVerifyCoinSellerRechargeReceiptUSDTBEP20PayUsesBinance(t *testing.T) { func TestVerifyCoinSellerRechargeReceiptUSDTC2CPayUsesBinance(t *testing.T) {
bsc := &fakeTronUSDTClient{err: xerr.New(xerr.Internal, "bsc chain client should not be called")} bsc := &fakeTronUSDTClient{err: xerr.New(xerr.Internal, "bsc chain client should not be called")}
binance := &fakeBinanceClient{record: walletservice.BinanceTransferRecord{ binance := &fakeBinanceClient{record: walletservice.BinanceTransferRecord{
Source: "pay_history", Source: "pay_history",
@ -635,7 +653,7 @@ func TestVerifyCoinSellerRechargeReceiptUSDTBEP20PayUsesBinance(t *testing.T) {
}) })
receipt, err := svc.VerifyCoinSellerRechargeReceipt(context.Background(), ledger.VerifyCoinSellerRechargeReceiptCommand{ receipt, err := svc.VerifyCoinSellerRechargeReceipt(context.Background(), ledger.VerifyCoinSellerRechargeReceiptCommand{
AppCode: "yumi", AppCode: "yumi",
ProviderCode: ledger.PaymentProviderUSDTBEP20, ProviderCode: ledger.PaymentProviderUSDTC2C,
ExternalOrderNo: "440537037787594752", ExternalOrderNo: "440537037787594752",
USDMinorAmount: 20000, USDMinorAmount: 20000,
OrderDateMS: 1784017140000, OrderDateMS: 1784017140000,
@ -646,18 +664,49 @@ func TestVerifyCoinSellerRechargeReceiptUSDTBEP20PayUsesBinance(t *testing.T) {
if !receipt.Verified || receipt.Status != "confirmed" || receipt.ProviderOrderID != "P_C2C_BEP20_RECEIPT" || receipt.ProviderAmountMinor != 20000 { 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) t.Fatalf("BEP20 Pay C2C receipt snapshot mismatch: %+v", receipt)
} }
if receipt.ReceiveAddress != "0xYumiConfiguredBSCAddress" { if receipt.ReceiveAddress != "" {
t.Fatalf("BEP20 Pay C2C must keep configured chain address: %+v", receipt) t.Fatalf("C2C must not persist an unrelated chain address: %+v", receipt)
} }
if binance.calls != 1 || binance.req.Network != "BSC" || binance.req.ExternalID != "440537037787594752" || binance.req.AmountMinor != 20000 { if binance.calls != 1 || binance.req.Network != "C2C" || 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) t.Fatalf("C2C must use Binance transfer lookup: calls=%d req=%+v", binance.calls, binance.req)
} }
if bsc.lastTxHash != "" { if bsc.lastTxHash != "" {
t.Fatalf("BEP20 Pay C2C order id must not call BSC chain client: %+v", bsc) t.Fatalf("BEP20 Pay C2C order id must not call BSC chain client: %+v", bsc)
} }
} }
func TestVerifyCoinSellerRechargeReceiptUSDTTRC20OffchainMissingBinanceAccount(t *testing.T) { func TestVerifyCoinSellerRechargeReceiptUSDTC2CDoesNotRequireChainConfig(t *testing.T) {
binance := &fakeBinanceClient{record: walletservice.BinanceTransferRecord{
Source: "pay_history",
TxID: "P_C2C_LALU_RECEIPT",
Coin: ledger.PaidCurrencyUSDT,
Status: 1,
Amount: "200.00000000",
AmountMinor: 20000,
}}
svc := walletservice.New(nil)
svc.SetBinanceClient(binance)
// Lalu 只校验 Binance C2C 收款事实时不需要开启 BSC RPC也不需要伪造一个链上收款地址。
svc.SetExternalRechargeConfig(walletservice.ExternalRechargeConfig{})
receipt, err := svc.VerifyCoinSellerRechargeReceipt(context.Background(), ledger.VerifyCoinSellerRechargeReceiptCommand{
AppCode: "lalu",
ProviderCode: ledger.PaymentProviderUSDTC2C,
ExternalOrderNo: "440537037787594752",
USDMinorAmount: 20000,
OrderDateMS: 1784017620000,
})
if err != nil {
t.Fatalf("BEP20 Pay C2C must not require chain config: %v", err)
}
if !receipt.Verified || receipt.ProviderOrderID != "P_C2C_LALU_RECEIPT" {
t.Fatalf("BEP20 Pay C2C receipt mismatch without chain config: %+v", receipt)
}
if binance.calls != 1 || binance.req.ToAddress != "" || binance.req.Network != "C2C" {
t.Fatalf("BEP20 Pay C2C lookup mismatch without chain config: calls=%d req=%+v", binance.calls, binance.req)
}
}
func TestVerifyCoinSellerRechargeReceiptUSDTC2CMissingBinanceAccount(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)
svc.SetBinanceClient(binance) svc.SetBinanceClient(binance)
@ -667,7 +716,7 @@ func TestVerifyCoinSellerRechargeReceiptUSDTTRC20OffchainMissingBinanceAccount(t
}) })
receipt, err := svc.VerifyCoinSellerRechargeReceipt(context.Background(), ledger.VerifyCoinSellerRechargeReceiptCommand{ receipt, err := svc.VerifyCoinSellerRechargeReceipt(context.Background(), ledger.VerifyCoinSellerRechargeReceiptCommand{
AppCode: "yumi", AppCode: "yumi",
ProviderCode: ledger.PaymentProviderUSDTTRC20, ProviderCode: ledger.PaymentProviderUSDTC2C,
ExternalOrderNo: "388611987194", ExternalOrderNo: "388611987194",
USDMinorAmount: 50000, USDMinorAmount: 50000,
}) })