Files
junhong_cmp_fiber/internal/domain/agentrecharge/payment_confirmation.go
break 98c145fe70
Some checks failed
构建并部署到测试环境(无 SSH) / build-and-deploy (push) Failing after 3m55s
实现支付商户池与微信授权配置
新增收款商户、商户池轮询、微信授权配置独立管理;三类新支付
(C端套餐购买、C端资产钱包充值、代理在线预存款充值)无条件
经商户池选择并冻结路由,无旧综合配置回退。merchant_id 为空
历史支付继续按 payment_config_id 双读。凭证版本化加载与
ID+版本缓存保证轮换一致性。删除商户池新支付创建开关及全部
引用。
2026-09-09 18:13:04 +08:00

103 lines
4.4 KiB
Go

package agentrecharge
import (
"strings"
"github.com/break/junhong_cmp_fiber/internal/model"
"github.com/break/junhong_cmp_fiber/pkg/constants"
"github.com/break/junhong_cmp_fiber/pkg/errors"
)
// PaymentState 是支付单在确认用例中的领域状态。
type PaymentState int
const (
// PaymentStatePending 表示支付单仍待确认。
PaymentStatePending PaymentState = iota
// PaymentStatePaid 表示支付单已确认收款。
PaymentStatePaid
// PaymentStateFailed 表示支付单曾被明确关闭。
PaymentStateFailed
// PaymentStateRefunded 表示支付单已经退款。
PaymentStateRefunded
)
// PaymentConfirmationFacts 是支付确认所需的渠道与本地权威事实。
type PaymentConfirmationFacts struct {
OrderType string
ExpectedOrderType string
PaymentMethod string
RechargePaymentMethod string
RechargePaymentChannel string
PaymentConfigID uint
RechargePaymentConfigID uint
ConfirmedConfigID uint
FrozenMerchant bool
FrozenMerchantPaymentMethod string
FrozenMerchantProviderType string
MerchantIdentity string
ConfirmedMerchantIdentity string
PaymentAmount int64
RechargeAmount int64
ConfirmedAmount int64
PaymentOrderID uint
RechargeID uint
PaymentState PaymentState
RechargeStatus int
StoredTradeNo string
ConfirmedTradeNo string
}
// ValidatePaymentConfirmation 校验支付确认不变量,并返回是否属于完全一致的重复确认。
func ValidatePaymentConfirmation(facts PaymentConfirmationFacts) (bool, error) {
if facts.ExpectedOrderType == "" || facts.OrderType != facts.ExpectedOrderType ||
facts.RechargeID == 0 || facts.PaymentOrderID != facts.RechargeID {
return false, errors.New(errors.CodeConflict, "支付单与代理充值单关联不一致")
}
method := strings.TrimSpace(facts.PaymentMethod)
if method == "" || method != strings.TrimSpace(facts.RechargePaymentMethod) {
return false, errors.New(errors.CodeConflict, "支付渠道与代理充值单不一致")
}
channel := strings.TrimSpace(facts.RechargePaymentChannel)
if channel != method && !(method == constants.RechargeMethodWechat && channel == model.ProviderTypeFuiou) {
return false, errors.New(errors.CodeConflict, "支付渠道与代理充值单不一致")
}
identity := strings.TrimSpace(facts.MerchantIdentity)
if facts.FrozenMerchant {
frozenMethod := strings.TrimSpace(facts.FrozenMerchantPaymentMethod)
providerType := strings.TrimSpace(facts.FrozenMerchantProviderType)
if identity == "" || frozenMethod != method || providerType == "" {
return false, errors.New(errors.CodeConflict, "冻结商户支付事实不一致")
}
expectedChannel := method
if method == constants.RechargeMethodWechat && providerType == model.ProviderTypeFuiou {
expectedChannel = model.ProviderTypeFuiou
}
if channel != expectedChannel {
return false, errors.New(errors.CodeConflict, "支付渠道与冻结商户不一致")
}
} else if facts.PaymentConfigID == 0 || facts.PaymentConfigID != facts.RechargePaymentConfigID ||
facts.PaymentConfigID != facts.ConfirmedConfigID || identity == "" ||
identity != strings.TrimSpace(facts.ConfirmedMerchantIdentity) {
return false, errors.New(errors.CodeConflict, "支付配置身份与创建记录不一致")
}
tradeNo := strings.TrimSpace(facts.ConfirmedTradeNo)
if tradeNo == "" || facts.ConfirmedAmount <= 0 || facts.PaymentAmount != facts.RechargeAmount ||
facts.PaymentAmount != facts.ConfirmedAmount {
return false, errors.New(errors.CodeConflict, "支付金额或第三方交易号无效")
}
if facts.PaymentState == PaymentStatePaid {
if strings.TrimSpace(facts.StoredTradeNo) == tradeNo &&
(facts.RechargeStatus == constants.RechargeStatusPaid || facts.RechargeStatus == constants.RechargeStatusCompleted) {
return true, nil
}
return false, errors.New(errors.CodeConflict, "支付单已存在不一致的确认事实")
}
validPending := facts.PaymentState == PaymentStatePending && facts.RechargeStatus == constants.RechargeStatusPending
validLateSuccess := facts.PaymentState == PaymentStateFailed && facts.RechargeStatus == constants.RechargeStatusClosed
if !validPending && !validLateSuccess {
return false, errors.New(errors.CodeInvalidStatus, "代理充值单当前状态不可确认支付")
}
return false, nil
}