收口审计治理与套餐任务进展

Constraint: 在线热修前必须保存当前迭代分支全部有效代码进展
Confidence: medium
Scope-risk: broad
Directive: 后续修改需保持审计事件与业务事务边界一致
Tested: git diff --cached --check
Not-tested: 未运行全量测试,提交用于切换分支前保存既有工作
This commit is contained in:
2026-08-05 14:30:54 +08:00
parent b3499adfca
commit 5e552d99bc
178 changed files with 16797 additions and 5674 deletions

View File

@@ -2,8 +2,10 @@ package recharge_order
import (
"context"
"strconv"
"time"
"github.com/break/junhong_cmp_fiber/internal/infrastructure/audit"
"github.com/break/junhong_cmp_fiber/internal/model"
"github.com/break/junhong_cmp_fiber/internal/store/postgres"
"github.com/break/junhong_cmp_fiber/internal/task"
@@ -28,6 +30,12 @@ type Service struct {
commissionRecordStore *postgres.CommissionRecordStore
queueClient *queue.Client
logger *zap.Logger
auditWriter *audit.Writer
}
// SetPaymentAudit 注入充值支付统一审计 Writer。
func (s *Service) SetPaymentAudit(writer *audit.Writer) {
s.auditWriter = writer
}
func New(
@@ -157,8 +165,60 @@ func (s *Service) HandlePaymentCallback(ctx context.Context, paymentNo string, p
if err := s.triggerOneTimeCommissionIfNeededInTx(ctx, tx, rechargeOrder, rechargeOrder.Amount); err != nil {
return err
}
return nil
if s.auditWriter == nil {
return errors.New(errors.CodeInvalidStatus, "充值支付统一审计接缝未配置")
}
afterPayment := *payment
afterPayment.Status = model.PaymentRecordStatusPaid
afterPayment.ThirdPartyTradeNo = transactionID
afterPayment.PaidAt = &now
paymentResource := audit.PaymentResource(&afterPayment, constants.AuditResourceRelationPrimary, constants.AuditResourceRolePaymentTarget,
map[string]any{"status": payment.Status, "third_party_trade_no": payment.ThirdPartyTradeNo, "paid_at": payment.PaidAt},
map[string]any{"status": afterPayment.Status, "third_party_trade_no": afterPayment.ThirdPartyTradeNo, "paid_at": afterPayment.PaidAt})
rechargeID := strconv.FormatUint(uint64(rechargeOrder.ID), 10)
rechargeResource := audit.ResourceInput{
Type: constants.AuditResourceRechargeOrder, ID: &rechargeID, Key: rechargeOrder.RechargeOrderNo, DisplayName: rechargeOrder.RechargeOrderNo,
Relation: constants.AuditResourceRelationAffected, Role: constants.AuditResourceRolePaymentBusinessOrder,
IdentitySnapshot: map[string]any{
"id": rechargeOrder.ID, "recharge_order_no": rechargeOrder.RechargeOrderNo, "user_id": rechargeOrder.UserID,
"asset_wallet_id": rechargeOrder.AssetWalletID, "resource_type": rechargeOrder.ResourceType,
"resource_id": rechargeOrder.ResourceID, "amount": rechargeOrder.Amount, "status": model.RechargeOrderStatusPaid,
},
BeforeData: map[string]any{"status": rechargeOrder.Status}, AfterData: map[string]any{"status": model.RechargeOrderStatusPaid},
SubjectVisibility: constants.AuditSubjectResult, SubjectSummary: "充值支付已到账",
}
transactionIDValue := strconv.FormatUint(uint64(transaction.ID), 10)
transactionResource := audit.ResourceInput{
Type: constants.AuditResourceAssetWalletTransaction, ID: &transactionIDValue, Key: transactionIDValue, DisplayName: "资产钱包流水 " + transactionIDValue,
Relation: constants.AuditResourceRelationAffected, Role: constants.AuditResourceRolePaymentWalletTransaction,
IdentitySnapshot: map[string]any{
"id": transaction.ID, "asset_wallet_id": transaction.AssetWalletID, "resource_type": transaction.ResourceType,
"resource_id": transaction.ResourceID, "transaction_type": transaction.TransactionType,
"reference_type": transaction.ReferenceType, "reference_no": transaction.ReferenceNo, "status": transaction.Status,
},
AfterData: map[string]any{"amount": transaction.Amount, "balance_before": transaction.BalanceBefore, "balance_after": transaction.BalanceAfter},
}
resources := []audit.ResourceInput{paymentResource, rechargeResource, transactionResource}
references, err := audit.AssetRechargeReferences(ctx, tx, rechargeOrder)
if err != nil {
return err
}
for i := range references {
if references[i].Type != constants.AuditResourceAssetWallet {
continue
}
references[i].Relation = constants.AuditResourceRelationAffected
references[i].BeforeData = map[string]any{"balance": balanceBefore}
references[i].AfterData = map[string]any{"balance": balanceBefore + rechargeOrder.Amount}
references[i].SubjectVisibility = constants.AuditSubjectResult
references[i].SubjectSummary = "充值支付已到账"
}
resources = append(resources, references...)
return s.auditWriter.Append(ctx, tx, audit.AppendInput{
ActionCode: constants.AuditActionPaymentConfirmed, Summary: "第三方支付确认资产充值已到账",
ScopeType: constants.AuditScopePlatform, Result: constants.AuditResultSuccess,
CorrelationID: payment.PaymentNo, Resources: resources,
})
})
if err != nil {