fix(wallet): share lalu payment country configs
This commit is contained in:
parent
d66799b312
commit
bb5efebabd
@ -55,7 +55,7 @@ func (s *Service) createMifaPayRechargeOrder(ctx context.Context, command ledger
|
||||
if s.mifaPay == nil {
|
||||
return ledger.ExternalRechargeOrder{}, xerr.New(xerr.Unavailable, "mifapay client is not configured")
|
||||
}
|
||||
method, err := s.repository.GetThirdPartyPaymentMethod(ctx, command.AppCode, command.PaymentMethodID)
|
||||
method, err := s.sharedPaymentMethod(ctx, command.AppCode, ledger.PaymentProviderMifaPay, command.PaymentMethodID)
|
||||
if err != nil {
|
||||
return ledger.ExternalRechargeOrder{}, err
|
||||
}
|
||||
@ -106,7 +106,7 @@ func (s *Service) createV5PayRechargeOrder(ctx context.Context, command ledger.C
|
||||
if s.v5Pay == nil {
|
||||
return ledger.ExternalRechargeOrder{}, xerr.New(xerr.Unavailable, "v5pay client is not configured")
|
||||
}
|
||||
method, err := s.repository.GetThirdPartyPaymentMethod(ctx, command.AppCode, command.PaymentMethodID)
|
||||
method, err := s.sharedPaymentMethod(ctx, command.AppCode, ledger.PaymentProviderV5Pay, command.PaymentMethodID)
|
||||
if err != nil {
|
||||
return ledger.ExternalRechargeOrder{}, err
|
||||
}
|
||||
|
||||
@ -8,6 +8,20 @@ import (
|
||||
"strings"
|
||||
)
|
||||
|
||||
// sharedPaymentConfigAppCode 是三方收单方式的唯一国家/币种配置 owner。
|
||||
// Yumi、Aslan 等 App 可以有自己的商品和用户区域,但不能复制一套 V5Pay/MiFaPay
|
||||
// 国家、币种或汇率配置,否则人工收款与 H5 下单会因配置漂移得到不同的支付结果。
|
||||
const sharedPaymentConfigAppCode = appcode.Default
|
||||
|
||||
func usesSharedPaymentConfig(providerCode string) bool {
|
||||
switch ledger.NormalizePaymentProvider(providerCode) {
|
||||
case ledger.PaymentProviderMifaPay, ledger.PaymentProviderV5Pay:
|
||||
return true
|
||||
default:
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
// ListThirdPartyPaymentChannels 返回后台三方支付管理页需要的渠道、国家和方式树。
|
||||
func (s *Service) ListThirdPartyPaymentChannels(ctx context.Context, query ledger.ListThirdPartyPaymentChannelsQuery) ([]ledger.ThirdPartyPaymentChannel, error) {
|
||||
if s.repository == nil {
|
||||
@ -20,8 +34,49 @@ func (s *Service) ListThirdPartyPaymentChannels(ctx context.Context, query ledge
|
||||
return nil, xerr.New(xerr.InvalidArgument, "status is invalid")
|
||||
}
|
||||
}
|
||||
// 指定渠道时,V5Pay/MiFaPay 的国家和币种统一由 Lalu 维护。读取端始终切到
|
||||
// 该配置 owner,避免某个 App 没有复制支付方式时,临时链接和人工查单退化为无候选可用。
|
||||
if usesSharedPaymentConfig(query.ProviderCode) {
|
||||
query.AppCode = sharedPaymentConfigAppCode
|
||||
ctx = appcode.WithContext(ctx, query.AppCode)
|
||||
return s.repository.ListThirdPartyPaymentChannels(ctx, query)
|
||||
}
|
||||
ctx = appcode.WithContext(ctx, query.AppCode)
|
||||
return s.repository.ListThirdPartyPaymentChannels(ctx, query)
|
||||
channels, err := s.repository.ListThirdPartyPaymentChannels(ctx, query)
|
||||
if err != nil || query.AppCode == sharedPaymentConfigAppCode || query.ProviderCode != "" {
|
||||
return channels, err
|
||||
}
|
||||
|
||||
// 未指定渠道的临时收款页面仍要同时展示两个共享渠道。保留当前 App 的非共享渠道,
|
||||
// 但移除其历史副本,确保 UI 不会把同一国家/币种配置展示为两套来源。
|
||||
filtered := make([]ledger.ThirdPartyPaymentChannel, 0, len(channels)+2)
|
||||
for _, channel := range channels {
|
||||
if !usesSharedPaymentConfig(channel.ProviderCode) {
|
||||
filtered = append(filtered, channel)
|
||||
}
|
||||
}
|
||||
for _, providerCode := range []string{ledger.PaymentProviderMifaPay, ledger.PaymentProviderV5Pay} {
|
||||
sharedQuery := query
|
||||
sharedQuery.AppCode = sharedPaymentConfigAppCode
|
||||
sharedQuery.ProviderCode = providerCode
|
||||
sharedCtx := appcode.WithContext(ctx, sharedPaymentConfigAppCode)
|
||||
sharedChannels, err := s.repository.ListThirdPartyPaymentChannels(sharedCtx, sharedQuery)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
filtered = append(filtered, sharedChannels...)
|
||||
}
|
||||
return filtered, nil
|
||||
}
|
||||
|
||||
// sharedPaymentMethod 返回支付配置 owner 的方式。订单本身仍按 command.AppCode 落库,
|
||||
// 因此只共享国家/币种、产品类型和汇率,不会把 Yumi/Aslan 的账务事实写入 Lalu。
|
||||
func (s *Service) sharedPaymentMethod(ctx context.Context, appCode string, providerCode string, methodID int64) (ledger.ThirdPartyPaymentMethod, error) {
|
||||
configAppCode := appcode.Normalize(appCode)
|
||||
if usesSharedPaymentConfig(providerCode) {
|
||||
configAppCode = sharedPaymentConfigAppCode
|
||||
}
|
||||
return s.repository.GetThirdPartyPaymentMethod(ctx, configAppCode, methodID)
|
||||
}
|
||||
|
||||
func (s *Service) SetThirdPartyPaymentMethodStatus(ctx context.Context, command ledger.ThirdPartyPaymentMethodStatusCommand) (ledger.ThirdPartyPaymentMethod, error) {
|
||||
|
||||
@ -282,7 +282,7 @@ func (s *Service) v5PayReceiptQueryCandidates(ctx context.Context, command ledge
|
||||
if s.repository == nil {
|
||||
return candidates, nil
|
||||
}
|
||||
channels, err := s.repository.ListThirdPartyPaymentChannels(ctx, ledger.ListThirdPartyPaymentChannelsQuery{
|
||||
channels, err := s.ListThirdPartyPaymentChannels(ctx, ledger.ListThirdPartyPaymentChannelsQuery{
|
||||
AppCode: command.AppCode,
|
||||
ProviderCode: ledger.PaymentProviderV5Pay,
|
||||
Status: ledger.ThirdPartyPaymentStatusActive,
|
||||
|
||||
@ -427,6 +427,45 @@ func TestVerifyCoinSellerRechargeReceiptV5PayWithoutCountryCurrencyUsesEnabledCa
|
||||
}
|
||||
}
|
||||
|
||||
func TestVerifyCoinSellerRechargeReceiptV5PayUsesLaluCountryCurrencyConfig(t *testing.T) {
|
||||
repository := &fakeReceiptRepository{channels: []ledger.ThirdPartyPaymentChannel{{
|
||||
AppCode: "lalu",
|
||||
ProviderCode: ledger.PaymentProviderV5Pay,
|
||||
Status: ledger.ThirdPartyPaymentStatusActive,
|
||||
Methods: []ledger.ThirdPartyPaymentMethod{{
|
||||
ProviderCode: ledger.PaymentProviderV5Pay,
|
||||
CountryCode: "TR",
|
||||
CurrencyCode: "TRY",
|
||||
Status: ledger.ThirdPartyPaymentStatusActive,
|
||||
}},
|
||||
}}}
|
||||
v5Pay := &fakeV5PayClient{queryResp: walletservice.V5PayQueryOrderResponse{
|
||||
OrderID: "receipt-v5-yumi-shared-config",
|
||||
ProviderOrderID: "tx_receipt_v5_yumi_shared_config",
|
||||
Status: "2",
|
||||
Amount: "48.00",
|
||||
Currency: "TRY",
|
||||
ProductType: "BANK_TRANSFER",
|
||||
RawJSON: `{"status":"2"}`,
|
||||
}}
|
||||
svc := walletservice.New(repository)
|
||||
svc.SetV5PayClient(v5Pay)
|
||||
receipt, err := svc.VerifyCoinSellerRechargeReceipt(context.Background(), ledger.VerifyCoinSellerRechargeReceiptCommand{
|
||||
AppCode: "yumi",
|
||||
ProviderCode: ledger.PaymentProviderV5Pay,
|
||||
ExternalOrderNo: "receipt-v5-yumi-shared-config",
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatalf("VerifyCoinSellerRechargeReceipt v5pay shared config failed: %v", err)
|
||||
}
|
||||
if !receipt.Verified || repository.query.AppCode != "lalu" {
|
||||
t.Fatalf("V5Pay receipt must query Lalu country/currency config, receipt=%+v query=%+v", receipt, repository.query)
|
||||
}
|
||||
if len(v5Pay.queryReqs) != 1 || v5Pay.queryReqs[0].CountryCode != "TR" || v5Pay.queryReqs[0].CurrencyCode != "TRY" {
|
||||
t.Fatalf("V5Pay receipt must use the Lalu candidate, got %+v", v5Pay.queryReqs)
|
||||
}
|
||||
}
|
||||
|
||||
func TestVerifyCoinSellerRechargeReceiptV5PayWithoutCountryCurrencyNotFound(t *testing.T) {
|
||||
repository := &fakeReceiptRepository{channels: []ledger.ThirdPartyPaymentChannel{{
|
||||
AppCode: "lalu",
|
||||
|
||||
@ -35,7 +35,7 @@ func (s *Service) createTemporaryMifaPayRechargeOrder(ctx context.Context, comma
|
||||
if s.mifaPay == nil {
|
||||
return ledger.ExternalRechargeOrder{}, xerr.New(xerr.Unavailable, "mifapay client is not configured")
|
||||
}
|
||||
method, err := s.repository.GetThirdPartyPaymentMethod(ctx, command.AppCode, command.PaymentMethodID)
|
||||
method, err := s.sharedPaymentMethod(ctx, command.AppCode, ledger.PaymentProviderMifaPay, command.PaymentMethodID)
|
||||
if err != nil {
|
||||
return ledger.ExternalRechargeOrder{}, err
|
||||
}
|
||||
@ -89,7 +89,7 @@ func (s *Service) createTemporaryV5PayRechargeOrder(ctx context.Context, command
|
||||
if s.v5Pay == nil {
|
||||
return ledger.ExternalRechargeOrder{}, xerr.New(xerr.Unavailable, "v5pay client is not configured")
|
||||
}
|
||||
method, err := s.repository.GetThirdPartyPaymentMethod(ctx, command.AppCode, command.PaymentMethodID)
|
||||
method, err := s.sharedPaymentMethod(ctx, command.AppCode, ledger.PaymentProviderV5Pay, command.PaymentMethodID)
|
||||
if err != nil {
|
||||
return ledger.ExternalRechargeOrder{}, err
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user