充值修复

This commit is contained in:
zhx 2026-05-28 15:11:37 +08:00
parent c93f46b191
commit 1fdb2b3152
2 changed files with 81 additions and 2 deletions

View File

@ -565,7 +565,7 @@ func (s *Service) ConfirmGooglePayment(ctx context.Context, command ledger.Googl
if product.Platform != ledger.RechargeProductPlatformAndroid || product.Channel != ledger.RechargeChannelGoogle {
return ledger.GooglePaymentReceipt{}, xerr.New(xerr.InvalidArgument, "recharge product is not google play product")
}
if command.ProductCode != "" && command.ProductCode != product.ProductCode {
if command.ProductCode != "" && command.ProductCode != product.ProductName {
return ledger.GooglePaymentReceipt{}, xerr.New(xerr.Conflict, "product_code does not match")
}
if !rechargeProductSupportsRegion(product, command.RegionID) {
@ -585,7 +585,7 @@ func (s *Service) ConfirmGooglePayment(ctx context.Context, command ledger.Googl
if purchase.PurchaseState != ledger.GooglePurchaseStatePurchased {
return ledger.GooglePaymentReceipt{}, xerr.New(xerr.Conflict, "google purchase is not purchased")
}
if purchase.ProductID != "" && purchase.ProductID != product.ProductCode {
if purchase.ProductID != "" && purchase.ProductID != product.ProductName {
return ledger.GooglePaymentReceipt{}, xerr.New(xerr.Conflict, "google product_id does not match recharge product")
}
if command.OrderID != "" && purchase.OrderID != "" && command.OrderID != purchase.OrderID {

View File

@ -2134,6 +2134,63 @@ func TestRechargeProductsAreConfiguredByPlatformRegionAndStatus(t *testing.T) {
}
}
// TestConfirmGooglePaymentUsesProductNameAsGoogleProductID 锁定后台 product_name 作为 Google Play 商品 ID。
func TestConfirmGooglePaymentUsesProductNameAsGoogleProductID(t *testing.T) {
repository := mysqltest.NewRepository(t)
svc := walletservice.New(repository)
const googleProductID = "coins_1500_google"
product, err := svc.CreateRechargeProduct(context.Background(), ledger.RechargeProductCommand{
AppCode: "lalu",
AmountMicro: 1500000,
CoinAmount: 1500,
ProductName: googleProductID,
Description: "google coin pack",
Platform: ledger.RechargeProductPlatformAndroid,
RegionIDs: []int64{1001},
Enabled: true,
OperatorUserID: 90001,
})
if err != nil {
t.Fatalf("CreateRechargeProduct failed: %v", err)
}
if product.ProductCode == googleProductID {
t.Fatalf("test requires internal product_code to differ from Google product ID: %+v", product)
}
svc.SetGooglePlayClient(&fakeGooglePlayClient{
purchase: ledger.GooglePlayPurchase{
ProductID: googleProductID,
OrderID: "GPA.1",
PurchaseState: ledger.GooglePurchaseStatePurchased,
ConsumptionState: "CONSUMPTION_STATE_YET_TO_BE_CONSUMED",
AcknowledgementState: "ACKNOWLEDGEMENT_STATE_ACKNOWLEDGED",
},
})
receipt, err := svc.ConfirmGooglePayment(context.Background(), ledger.GooglePaymentCommand{
AppCode: "lalu",
CommandID: "google-pay-product-name",
UserID: 53001,
RegionID: 1001,
ProductID: product.ProductID,
ProductCode: googleProductID,
PackageName: "com.org.laluparty",
PurchaseToken: "purchase-token-product-name",
OrderID: "GPA.1",
})
if err != nil {
t.Fatalf("ConfirmGooglePayment failed: %v", err)
}
if receipt.Status != ledger.PaymentStatusCredited || receipt.CoinAmount != 1500 || receipt.ProductCode != product.ProductCode {
t.Fatalf("google payment receipt mismatch: %+v", receipt)
}
if got := repository.CountRows("payment_orders", "product_id = ? AND product_code = ?", product.ProductID, product.ProductCode); got != 1 {
t.Fatalf("google payment should write one payment order with internal product_code, got %d", got)
}
if got := repository.CountRows("wallet_entries", "transaction_id = ?", receipt.TransactionID); got != 1 {
t.Fatalf("google payment should write one wallet entry, got %d", got)
}
}
func TestApplyGameCoinChangeDebitCreditAndIdempotency(t *testing.T) {
repository := mysqltest.NewRepository(t)
repository.SetBalance(88001, 500)
@ -2283,3 +2340,25 @@ func (f *fakeActivityBadgeClient) ConsumeAchievementEvent(_ context.Context, req
}
return &activityv1.ConsumeAchievementEventResponse{EventId: req.GetEventId(), Status: status}, nil
}
type fakeGooglePlayClient struct {
purchase ledger.GooglePlayPurchase
err error
consumed []string
}
func (f *fakeGooglePlayClient) GetProductPurchase(_ context.Context, packageName string, purchaseToken string) (ledger.GooglePlayPurchase, error) {
if f.err != nil {
return ledger.GooglePlayPurchase{}, f.err
}
purchase := f.purchase
if purchase.PackageName == "" {
purchase.PackageName = packageName
}
return purchase, nil
}
func (f *fakeGooglePlayClient) ConsumeProduct(_ context.Context, _ string, productID string, _ string) error {
f.consumed = append(f.consumed, productID)
return nil
}