package client_order 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/auditcontext" "github.com/break/junhong_cmp_fiber/pkg/constants" "github.com/break/junhong_cmp_fiber/pkg/errors" ) func (s *Service) appendPaymentCreatedAudit(ctx context.Context, tx *gorm.DB, payment *model.Payment, order *model.Order, recharge *model.RechargeOrder) error { if s.auditWriter == nil { return errors.New(errors.CodeInvalidStatus, "支付统一审计接缝未配置") } resources := []audit.ResourceInput{audit.PaymentResource(payment, constants.AuditResourceRelationPrimary, constants.AuditResourceRolePaymentTarget, nil, map[string]any{"status": payment.Status})} if order != nil { resources = append(resources, audit.OrderResource(order, constants.AuditResourceRelationReference, constants.AuditResourceRolePaymentBusinessOrder)) } if recharge != nil { id := strconv.FormatUint(uint64(recharge.ID), 10) resources = append(resources, audit.ResourceInput{ Type: constants.AuditResourceRechargeOrder, ID: &id, 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, }, }) } return s.auditWriter.Append(ctx, tx, audit.AppendInput{ ActionCode: constants.AuditActionPaymentCreated, Summary: "创建第三方支付记录", ScopeType: constants.AuditScopePlatform, Result: constants.AuditResultSuccess, CorrelationID: payment.PaymentNo, Resources: resources, }) } func (s *Service) startPaymentAttempt(ctx context.Context, payment *model.Payment, provider, scene string) (*model.IntegrationLog, time.Time, error) { if s.paymentIntegration == nil { return nil, time.Time{}, errors.New(errors.CodeInvalidStatus, "支付 Integration Log 接缝未配置") } resourceID := strconv.FormatUint(uint64(payment.ID), 10) resourceKey, series, correlationID := payment.PaymentNo, "payment:"+resourceID+":"+constants.IntegrationOperationPaymentPreCreate, payment.PaymentNo triggerSource, triggerScene := auditcontext.From(ctx).Source, scene log, err := s.paymentIntegration.Start(ctx, integrationlog.Attempt{ Provider: provider, Direction: constants.IntegrationDirectionOutbound, Operation: constants.IntegrationOperationPaymentPreCreate, ResourceType: constants.IntegrationResourceTypePayment, ResourceID: &resourceID, ResourceKey: &resourceKey, ExternalID: &resourceKey, TriggerSource: &triggerSource, TriggerScene: &triggerScene, TriggerSeries: &series, CorrelationID: &correlationID, RequestSummary: map[string]any{"payment_config_id": payment.PaymentConfigID, "amount": payment.Amount}, }) return log, time.Now(), err } func (s *Service) completePaymentAttempt(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 := s.paymentIntegration.Complete(ctx, log.IntegrationID, completion) return err } func paymentIntegrationProvider(config *model.WechatConfig) string { if config != nil && config.ProviderType == model.ProviderTypeFuiou { return constants.IntegrationProviderFuiou } return constants.IntegrationProviderWechatPay } func (s *Service) markPaymentFailed(ctx context.Context, payment *model.Payment, summary string) error { return s.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 s.auditWriter.Append(ctx, tx, audit.AppendInput{ ActionCode: constants.AuditActionPaymentFailed, Summary: 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})}, }) }) }