收口审计治理与套餐任务进展
Constraint: 在线热修前必须保存当前迭代分支全部有效代码进展 Confidence: medium Scope-risk: broad Directive: 后续修改需保持审计事件与业务事务边界一致 Tested: git diff --cached --check Not-tested: 未运行全量测试,提交用于切换分支前保存既有工作
This commit is contained in:
100
internal/handler/app/client_wallet_payment_audit.go
Normal file
100
internal/handler/app/client_wallet_payment_audit.go
Normal file
@@ -0,0 +1,100 @@
|
||||
package app
|
||||
|
||||
import (
|
||||
"context"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"gorm.io/gorm"
|
||||
|
||||
"github.com/break/junhong_cmp_fiber/internal/infrastructure/audit"
|
||||
"github.com/break/junhong_cmp_fiber/internal/infrastructure/integrationlog"
|
||||
"github.com/break/junhong_cmp_fiber/internal/model"
|
||||
"github.com/break/junhong_cmp_fiber/pkg/constants"
|
||||
"github.com/break/junhong_cmp_fiber/pkg/errors"
|
||||
)
|
||||
|
||||
func (h *ClientWalletHandler) appendRechargePaymentCreatedAudit(ctx context.Context, tx *gorm.DB, payment *model.Payment, recharge *model.RechargeOrder) error {
|
||||
if h.auditWriter == nil {
|
||||
return errors.New(errors.CodeInvalidStatus, "充值支付统一审计接缝未配置")
|
||||
}
|
||||
rechargeID := strconv.FormatUint(uint64(recharge.ID), 10)
|
||||
resources := []audit.ResourceInput{
|
||||
audit.PaymentResource(payment, constants.AuditResourceRelationPrimary, constants.AuditResourceRolePaymentTarget, nil, map[string]any{"status": payment.Status}),
|
||||
{
|
||||
Type: constants.AuditResourceRechargeOrder, ID: &rechargeID, Key: recharge.RechargeOrderNo, DisplayName: recharge.RechargeOrderNo,
|
||||
Relation: constants.AuditResourceRelationReference, Role: constants.AuditResourceRolePaymentBusinessOrder,
|
||||
IdentitySnapshot: map[string]any{
|
||||
"id": recharge.ID, "recharge_order_no": recharge.RechargeOrderNo, "user_id": recharge.UserID,
|
||||
"asset_wallet_id": recharge.AssetWalletID, "resource_type": recharge.ResourceType,
|
||||
"resource_id": recharge.ResourceID, "amount": recharge.Amount, "status": recharge.Status,
|
||||
},
|
||||
SubjectVisibility: constants.AuditSubjectResult, SubjectSummary: "资产充值支付已创建",
|
||||
},
|
||||
}
|
||||
references, err := audit.AssetRechargeReferences(ctx, tx, recharge)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
resources = append(resources, references...)
|
||||
return h.auditWriter.Append(ctx, tx, audit.AppendInput{
|
||||
ActionCode: constants.AuditActionPaymentCreated, Summary: "创建资产充值支付记录",
|
||||
ScopeType: constants.AuditScopePlatform, Result: constants.AuditResultSuccess,
|
||||
CorrelationID: payment.PaymentNo,
|
||||
Resources: resources,
|
||||
})
|
||||
}
|
||||
|
||||
func (h *ClientWalletHandler) startRechargePaymentAttempt(ctx context.Context, config *model.WechatConfig, paymentNo, rechargeNo string, amount int64) (*model.IntegrationLog, time.Time, error) {
|
||||
if h.paymentIntegration == nil {
|
||||
return nil, time.Time{}, errors.New(errors.CodeInvalidStatus, "充值支付 Integration Log 接缝未配置")
|
||||
}
|
||||
provider := constants.IntegrationProviderWechatPay
|
||||
if config.ProviderType == model.ProviderTypeFuiou {
|
||||
provider = constants.IntegrationProviderFuiou
|
||||
}
|
||||
series := "payment:" + paymentNo + ":" + constants.IntegrationOperationPaymentPreCreate
|
||||
log, err := h.paymentIntegration.Start(ctx, integrationlog.Attempt{
|
||||
Provider: provider, Direction: constants.IntegrationDirectionOutbound,
|
||||
Operation: constants.IntegrationOperationPaymentPreCreate,
|
||||
ResourceType: constants.IntegrationResourceTypePayment, ResourceKey: &paymentNo, ExternalID: &paymentNo,
|
||||
TriggerSeries: &series, CorrelationID: &rechargeNo,
|
||||
RequestSummary: map[string]any{"payment_config_id": config.ID, "amount": amount},
|
||||
})
|
||||
return log, time.Now(), err
|
||||
}
|
||||
|
||||
func (h *ClientWalletHandler) completeRechargePaymentAttempt(ctx context.Context, log *model.IntegrationLog, startedAt time.Time, result, providerCode, safeMessage string) error {
|
||||
completion := integrationlog.Completion{
|
||||
Result: result, ProviderCode: providerCode, SafeProviderMessage: safeMessage,
|
||||
ResponseSummary: map[string]any{"success": result == constants.IntegrationResultSuccess},
|
||||
DurationMS: time.Since(startedAt).Milliseconds(),
|
||||
}
|
||||
if result == constants.IntegrationResultUnknown {
|
||||
completion.RecoveryStrategy = "使用原支付单号向支付渠道查单,确认结果后再推进本地充值状态"
|
||||
}
|
||||
_, err := h.paymentIntegration.Complete(ctx, log.IntegrationID, completion)
|
||||
return err
|
||||
}
|
||||
|
||||
func (h *ClientWalletHandler) markRechargePaymentFailed(ctx context.Context, payment *model.Payment) error {
|
||||
return h.db.WithContext(ctx).Transaction(func(tx *gorm.DB) error {
|
||||
result := tx.Model(&model.Payment{}).Where("id = ? AND status = ?", payment.ID, model.PaymentRecordStatusPending).
|
||||
Update("status", model.PaymentRecordStatusFailed)
|
||||
if result.Error != nil {
|
||||
return errors.Wrap(errors.CodeDatabaseError, result.Error, "关闭失败支付记录失败")
|
||||
}
|
||||
if result.RowsAffected == 0 {
|
||||
return nil
|
||||
}
|
||||
after := *payment
|
||||
after.Status = model.PaymentRecordStatusFailed
|
||||
return h.auditWriter.Append(ctx, tx, audit.AppendInput{
|
||||
ActionCode: constants.AuditActionPaymentFailed, Summary: "支付宝支付链接生成失败,关闭支付记录",
|
||||
ScopeType: constants.AuditScopePlatform, Result: constants.AuditResultSuccess,
|
||||
CorrelationID: payment.PaymentNo,
|
||||
Resources: []audit.ResourceInput{audit.PaymentResource(&after, constants.AuditResourceRelationPrimary, constants.AuditResourceRolePaymentTarget,
|
||||
map[string]any{"status": payment.Status}, map[string]any{"status": after.Status})},
|
||||
})
|
||||
})
|
||||
}
|
||||
Reference in New Issue
Block a user