131 lines
4.4 KiB
Go
131 lines
4.4 KiB
Go
package wallet
|
|
|
|
import (
|
|
"context"
|
|
"hyapp/pkg/appcode"
|
|
"hyapp/pkg/xerr"
|
|
"hyapp/services/wallet-service/internal/domain/ledger"
|
|
"strings"
|
|
)
|
|
|
|
func (s *Service) ReconcileExternalRechargeOrders(ctx context.Context, appCode string, limit int) (int, error) {
|
|
if s.repository == nil {
|
|
return 0, xerr.New(xerr.Unavailable, "wallet repository is not configured")
|
|
}
|
|
if limit <= 0 {
|
|
return 0, nil
|
|
}
|
|
ctx = appcode.WithContext(ctx, appcode.Normalize(appCode))
|
|
orders, err := s.repository.ListExternalRechargeOrdersForReconcile(ctx, appcode.FromContext(ctx), limit)
|
|
if err != nil {
|
|
return 0, err
|
|
}
|
|
processed := 0
|
|
for _, order := range orders {
|
|
|
|
if _, err := s.refreshMifaPayRechargeOrder(ctx, order); err != nil {
|
|
processed++
|
|
continue
|
|
}
|
|
if _, err := s.refreshV5PayRechargeOrder(ctx, order); err != nil {
|
|
processed++
|
|
continue
|
|
}
|
|
processed++
|
|
}
|
|
return processed, nil
|
|
}
|
|
|
|
func (s *Service) refreshMifaPayRechargeOrder(ctx context.Context, order ledger.ExternalRechargeOrder) (ledger.ExternalRechargeOrder, error) {
|
|
if s.mifaPay == nil || order.ProviderCode != ledger.PaymentProviderMifaPay || isExternalRechargeTerminalStatus(order.Status) {
|
|
return order, nil
|
|
}
|
|
query, err := s.mifaPay.QueryOrder(ctx, MifaPayQueryOrderRequest{
|
|
OrderID: order.OrderID,
|
|
ProviderOrderID: order.ProviderOrderID,
|
|
OrderCreatedAtMS: order.CreatedAtMS,
|
|
})
|
|
if err != nil {
|
|
|
|
return order, err
|
|
}
|
|
providerOrderID := firstNonEmpty(query.ProviderOrderID, order.ProviderOrderID)
|
|
data := MifaPayNotifyData{
|
|
OrderID: firstNonEmpty(query.OrderID, order.OrderID),
|
|
ProviderOrderID: providerOrderID,
|
|
Amount: query.Amount,
|
|
Currency: query.Currency,
|
|
PayType: query.PayType,
|
|
RawJSON: query.RawJSON,
|
|
}
|
|
switch strings.TrimSpace(query.Status) {
|
|
case "1":
|
|
if !mifaPayQueryMatchesOrder(data, order) {
|
|
|
|
return s.repository.MarkExternalRechargeOrderFailed(ctx, order.AppCode, order.OrderID, "mifapay query order data mismatch", query.RawJSON)
|
|
}
|
|
if isTemporaryExternalRechargeOrder(order) {
|
|
return s.repository.MarkExternalRechargeOrderPaid(ctx, order.AppCode, order.OrderID, providerOrderID, query.RawJSON)
|
|
}
|
|
return s.repository.CreditExternalRechargeOrder(ctx, order.AppCode, order.OrderID, providerOrderID, "", query.RawJSON)
|
|
case "4":
|
|
return s.repository.MarkExternalRechargeOrderFailed(ctx, order.AppCode, order.OrderID, "mifapay order status 4", query.RawJSON)
|
|
case "0", "5", "":
|
|
return order, nil
|
|
default:
|
|
return order, nil
|
|
}
|
|
}
|
|
|
|
func (s *Service) refreshV5PayRechargeOrder(ctx context.Context, order ledger.ExternalRechargeOrder) (ledger.ExternalRechargeOrder, error) {
|
|
if s.v5Pay == nil || order.ProviderCode != ledger.PaymentProviderV5Pay || isExternalRechargeTerminalStatus(order.Status) {
|
|
return order, nil
|
|
}
|
|
query, err := s.v5Pay.QueryOrder(ctx, V5PayQueryOrderRequest{
|
|
OrderID: order.OrderID,
|
|
ProviderOrderID: order.ProviderOrderID,
|
|
CountryCode: order.CountryCode,
|
|
CurrencyCode: order.CurrencyCode,
|
|
})
|
|
if err != nil {
|
|
|
|
return order, err
|
|
}
|
|
providerOrderID := firstNonEmpty(query.ProviderOrderID, order.ProviderOrderID)
|
|
data := V5PayNotifyData{
|
|
OrderID: firstNonEmpty(query.OrderID, order.OrderID),
|
|
ProviderOrderID: providerOrderID,
|
|
OrderStatus: query.Status,
|
|
Amount: query.Amount,
|
|
Currency: query.Currency,
|
|
ProductType: query.ProductType,
|
|
RawJSON: query.RawJSON,
|
|
}
|
|
switch strings.TrimSpace(query.Status) {
|
|
case "2":
|
|
if !v5PayOrderDataMatchesOrder(data, order) {
|
|
|
|
return s.repository.MarkExternalRechargeOrderFailed(ctx, order.AppCode, order.OrderID, "v5pay query order data mismatch", query.RawJSON)
|
|
}
|
|
if isTemporaryExternalRechargeOrder(order) {
|
|
return s.repository.MarkExternalRechargeOrderPaid(ctx, order.AppCode, order.OrderID, providerOrderID, query.RawJSON)
|
|
}
|
|
return s.repository.CreditExternalRechargeOrder(ctx, order.AppCode, order.OrderID, providerOrderID, "", query.RawJSON)
|
|
case "3", "5", "6":
|
|
return s.repository.MarkExternalRechargeOrderFailed(ctx, order.AppCode, order.OrderID, "v5pay order status "+query.Status, query.RawJSON)
|
|
case "0", "1", "":
|
|
return order, nil
|
|
default:
|
|
return order, nil
|
|
}
|
|
}
|
|
|
|
func isExternalRechargeTerminalStatus(status string) bool {
|
|
switch strings.TrimSpace(status) {
|
|
case ledger.ExternalRechargeStatusCredited, ledger.ExternalRechargeStatusPaid, ledger.ExternalRechargeStatusFailed:
|
|
return true
|
|
default:
|
|
return false
|
|
}
|
|
}
|