Some checks failed
构建并部署到测试环境(无 SSH) / build-and-deploy (push) Failing after 3m55s
新增收款商户、商户池轮询、微信授权配置独立管理;三类新支付 (C端套餐购买、C端资产钱包充值、代理在线预存款充值)无条件 经商户池选择并冻结路由,无旧综合配置回退。merchant_id 为空 历史支付继续按 payment_config_id 双读。凭证版本化加载与 ID+版本缓存保证轮换一致性。删除商户池新支付创建开关及全部 引用。
103 lines
4.4 KiB
Go
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
|
|
}
|