电商支付系统设计与实现

2024/1/1

# 电商支付系统设计与实现

# 系统概述

支付系统是电商平台的核心组件,负责处理用户支付请求、对接第三方支付渠道、处理支付回调、管理支付流水等功能。一个完善的支付系统需要保证资金安全、支持多种支付方式、具备高可用性和强一致性。

# 支付架构设计

# 整体架构

┌─────────────────┐    ┌─────────────────┐    ┌─────────────────┐
│   用户端应用     │    │   商户管理后台   │    │   财务管理系统   │
└─────────────────┘    └─────────────────┘    └─────────────────┘
         │                       │                       │
         └───────────────────────┼───────────────────────┘
                                 │
         ┌─────────────────────────────────────────────────┐
         │              支付网关层                          │
         │  ┌─────────────┐  ┌─────────────┐  ┌─────────────┐ │
         │  │  路由选择   │  │  参数验证   │  │  签名验证   │ │
         │  └─────────────┘  └─────────────┘  └─────────────┘ │
         └─────────────────────────────────────────────────┘
                                 │
         ┌─────────────────────────────────────────────────┐
         │              支付核心服务                        │
         │  ┌─────────────┐  ┌─────────────┐  ┌─────────────┐ │
         │  │  订单管理   │  │  支付处理   │  │  对账服务   │ │
         │  └─────────────┘  └─────────────┘  └─────────────┘ │
         └─────────────────────────────────────────────────┘
                                 │
         ┌─────────────────────────────────────────────────┐
         │              第三方支付渠道                      │
         │  ┌─────────────┐  ┌─────────────┐  ┌─────────────┐ │
         │  │   微信支付   │  │  支付宝支付  │  │   银联支付   │ │
         │  └─────────────┘  └─────────────┘  └─────────────┘ │
         └─────────────────────────────────────────────────┘

# 核心实体设计

# 1. 支付订单

@Entity
@Table(name = "payment_orders")
public class PaymentOrder {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    
    @Column(unique = true, nullable = false, length = 32)
    private String paymentOrderNumber;
    
    @Column(nullable = false, length = 32)
    private String businessOrderNumber;
    
    @Enumerated(EnumType.STRING)
    @Column(nullable = false)
    private BusinessType businessType;
    
    @Column(nullable = false)
    private Long userId;
    
    @Column(nullable = false, precision = 10, scale = 2)
    private BigDecimal amount;
    
    @Enumerated(EnumType.STRING)
    @Column(nullable = false)
    private PaymentMethod paymentMethod;
    
    @Enumerated(EnumType.STRING)
    @Column(nullable = false)
    private PaymentChannel paymentChannel;
    
    @Enumerated(EnumType.STRING)
    @Column(nullable = false)
    private PaymentStatus status;
    
    @Column(length = 64)
    private String thirdPartyTransactionId;
    
    @Column(length = 500)
    private String subject;
    
    @Column(length = 1000)
    private String body;
    
    @Column(length = 200)
    private String notifyUrl;
    
    @Column(length = 200)
    private String returnUrl;
    
    @Column(columnDefinition = "TEXT")
    private String extendInfo;
    
    @CreationTimestamp
    private LocalDateTime createdAt;
    
    @UpdateTimestamp
    private LocalDateTime updatedAt;
    
    private LocalDateTime paidAt;
    private LocalDateTime expiredAt;
}

public enum PaymentStatus {
    PENDING,    // 待支付
    PAYING,     // 支付中
    SUCCESS,    // 支付成功
    FAILED,     // 支付失败
    CANCELLED,  // 已取消
    EXPIRED     // 已过期
}

public enum PaymentMethod {
    WECHAT_PAY,     // 微信支付
    ALIPAY,         // 支付宝
    UNION_PAY,      // 银联支付
    BALANCE,        // 余额支付
    CREDIT_CARD,    // 信用卡
    DEBIT_CARD      // 借记卡
}

public enum PaymentChannel {
    WECHAT_JSAPI,   // 微信公众号支付
    WECHAT_APP,     // 微信APP支付
    WECHAT_H5,      // 微信H5支付
    WECHAT_NATIVE,  // 微信扫码支付
    ALIPAY_APP,     // 支付宝APP支付
    ALIPAY_WEB,     // 支付宝网页支付
    ALIPAY_WAP      // 支付宝手机网站支付
}

public enum BusinessType {
    ORDER_PAYMENT,  // 订单支付
    RECHARGE,       // 账户充值
    REFUND          // 退款
}

# 2. 支付流水

@Entity
@Table(name = "payment_transactions")
public class PaymentTransaction {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    
    @Column(unique = true, nullable = false, length = 32)
    private String transactionNumber;
    
    @Column(nullable = false)
    private Long paymentOrderId;
    
    @Enumerated(EnumType.STRING)
    @Column(nullable = false)
    private TransactionType type;
    
    @Column(nullable = false, precision = 10, scale = 2)
    private BigDecimal amount;
    
    @Enumerated(EnumType.STRING)
    @Column(nullable = false)
    private TransactionStatus status;
    
    @Column(length = 64)
    private String thirdPartyTransactionId;
    
    @Column(columnDefinition = "TEXT")
    private String requestData;
    
    @Column(columnDefinition = "TEXT")
    private String responseData;
    
    @Column(length = 500)
    private String remark;
    
    @CreationTimestamp
    private LocalDateTime createdAt;
    
    @UpdateTimestamp
    private LocalDateTime updatedAt;
}

public enum TransactionType {
    PAYMENT,    // 支付
    REFUND,     // 退款
    TRANSFER    // 转账
}

public enum TransactionStatus {
    PROCESSING, // 处理中
    SUCCESS,    // 成功
    FAILED,     // 失败
    CANCELLED   // 已取消
}

# 支付服务实现

# 1. 支付网关服务

@Service
public class PaymentGatewayService {
    
    @Autowired
    private PaymentOrderService paymentOrderService;
    
    @Autowired
    private PaymentChannelFactory paymentChannelFactory;
    
    @Autowired
    private PaymentRouterService paymentRouterService;
    
    /**
     * 创建支付订单
     */
    public PaymentResult createPayment(PaymentRequest request) {
        // 1. 参数验证
        validatePaymentRequest(request);
        
        // 2. 选择支付渠道
        PaymentChannel channel = paymentRouterService.selectChannel(request);
        
        // 3. 创建支付订单
        PaymentOrder paymentOrder = paymentOrderService.createPaymentOrder(request, channel);
        
        // 4. 调用第三方支付接口
        PaymentChannelHandler handler = paymentChannelFactory.getHandler(channel);
        PaymentResult result = handler.createPayment(paymentOrder);
        
        // 5. 更新支付订单状态
        if (result.isSuccess()) {
            paymentOrderService.updateStatus(paymentOrder.getId(), PaymentStatus.PAYING);
        } else {
            paymentOrderService.updateStatus(paymentOrder.getId(), PaymentStatus.FAILED);
        }
        
        return result;
    }
    
    /**
     * 查询支付状态
     */
    public PaymentQueryResult queryPayment(String paymentOrderNumber) {
        PaymentOrder paymentOrder = paymentOrderService.findByOrderNumber(paymentOrderNumber);
        if (paymentOrder == null) {
            throw new BusinessException("支付订单不存在");
        }
        
        // 如果订单已经是最终状态,直接返回
        if (isFinalStatus(paymentOrder.getStatus())) {
            return PaymentQueryResult.of(paymentOrder);
        }
        
        // 查询第三方支付状态
        PaymentChannelHandler handler = paymentChannelFactory.getHandler(paymentOrder.getPaymentChannel());
        PaymentQueryResult result = handler.queryPayment(paymentOrder);
        
        // 更新本地状态
        if (result.getStatus() != paymentOrder.getStatus()) {
            paymentOrderService.updateStatus(paymentOrder.getId(), result.getStatus());
        }
        
        return result;
    }
}

# 2. 支付渠道路由

@Service
public class PaymentRouterService {
    
    @Autowired
    private PaymentChannelConfigService channelConfigService;
    
    /**
     * 选择支付渠道
     */
    public PaymentChannel selectChannel(PaymentRequest request) {
        PaymentMethod method = request.getPaymentMethod();
        String clientType = request.getClientType();
        BigDecimal amount = request.getAmount();
        
        // 获取可用的支付渠道
        List<PaymentChannelConfig> availableChannels = channelConfigService
            .getAvailableChannels(method, clientType);
        
        if (availableChannels.isEmpty()) {
            throw new BusinessException("暂无可用的支付渠道");
        }
        
        // 根据路由策略选择渠道
        return selectByStrategy(availableChannels, amount);
    }
    
    /**
     * 根据策略选择渠道
     */
    private PaymentChannel selectByStrategy(List<PaymentChannelConfig> channels, BigDecimal amount) {
        // 1. 按费率排序(费率低的优先)
        channels.sort(Comparator.comparing(PaymentChannelConfig::getFeeRate));
        
        // 2. 检查限额
        for (PaymentChannelConfig config : channels) {
            if (amount.compareTo(config.getMinAmount()) >= 0 && 
                amount.compareTo(config.getMaxAmount()) <= 0) {
                return config.getChannel();
            }
        }
        
        throw new BusinessException("支付金额超出限制");
    }
}

# 3. 微信支付实现

@Component
public class WechatPayHandler implements PaymentChannelHandler {
    
    @Autowired
    private WechatPayConfig wechatPayConfig;
    
    @Autowired
    private WechatPayClient wechatPayClient;
    
    @Override
    public PaymentResult createPayment(PaymentOrder paymentOrder) {
        try {
            WechatPayRequest request = buildWechatPayRequest(paymentOrder);
            WechatPayResponse response = wechatPayClient.unifiedOrder(request);
            
            if (response.isSuccess()) {
                return PaymentResult.success(response.getPrepayId(), response.getPayInfo());
            } else {
                return PaymentResult.failure(response.getErrorCode(), response.getErrorMsg());
            }
            
        } catch (Exception e) {
            log.error("微信支付创建失败", e);
            return PaymentResult.failure("SYSTEM_ERROR", "系统异常");
        }
    }
    
    @Override
    public PaymentQueryResult queryPayment(PaymentOrder paymentOrder) {
        try {
            WechatPayQueryRequest request = new WechatPayQueryRequest();
            request.setOutTradeNo(paymentOrder.getPaymentOrderNumber());
            
            WechatPayQueryResponse response = wechatPayClient.orderQuery(request);
            
            if (response.isSuccess()) {
                PaymentStatus status = convertWechatStatus(response.getTradeState());
                return PaymentQueryResult.success(status, response.getTransactionId());
            } else {
                return PaymentQueryResult.failure(response.getErrorCode(), response.getErrorMsg());
            }
            
        } catch (Exception e) {
            log.error("微信支付查询失败", e);
            return PaymentQueryResult.failure("SYSTEM_ERROR", "系统异常");
        }
    }
    
    /**
     * 构建微信支付请求
     */
    private WechatPayRequest buildWechatPayRequest(PaymentOrder paymentOrder) {
        WechatPayRequest request = new WechatPayRequest();
        request.setAppId(wechatPayConfig.getAppId());
        request.setMchId(wechatPayConfig.getMchId());
        request.setOutTradeNo(paymentOrder.getPaymentOrderNumber());
        request.setBody(paymentOrder.getSubject());
        request.setTotalFee(paymentOrder.getAmount().multiply(BigDecimal.valueOf(100)).intValue());
        request.setSpbillCreateIp(getClientIp());
        request.setNotifyUrl(paymentOrder.getNotifyUrl());
        request.setTradeType(getTradeType(paymentOrder.getPaymentChannel()));
        
        // 设置签名
        String sign = WechatPaySignUtil.sign(request, wechatPayConfig.getKey());
        request.setSign(sign);
        
        return request;
    }
    
    /**
     * 转换微信支付状态
     */
    private PaymentStatus convertWechatStatus(String tradeState) {
        switch (tradeState) {
            case "SUCCESS":
                return PaymentStatus.SUCCESS;
            case "REFUND":
                return PaymentStatus.SUCCESS; // 已退款但支付成功
            case "NOTPAY":
                return PaymentStatus.PENDING;
            case "CLOSED":
                return PaymentStatus.CANCELLED;
            case "REVOKED":
                return PaymentStatus.CANCELLED;
            case "USERPAYING":
                return PaymentStatus.PAYING;
            case "PAYERROR":
                return PaymentStatus.FAILED;
            default:
                return PaymentStatus.PENDING;
        }
    }
}

# 4. 支付回调处理

@RestController
@RequestMapping("/payment/notify")
public class PaymentNotifyController {
    
    @Autowired
    private PaymentNotifyService paymentNotifyService;
    
    /**
     * 微信支付回调
     */
    @PostMapping("/wechat")
    public String wechatNotify(HttpServletRequest request) {
        try {
            // 获取回调数据
            String xmlData = getRequestBody(request);
            
            // 验证签名
            if (!paymentNotifyService.verifyWechatSign(xmlData)) {
                log.warn("微信支付回调签名验证失败");
                return buildWechatFailResponse("签名验证失败");
            }
            
            // 解析回调数据
            WechatNotifyData notifyData = parseWechatNotifyData(xmlData);
            
            // 处理回调
            boolean success = paymentNotifyService.handleWechatNotify(notifyData);
            
            if (success) {
                return buildWechatSuccessResponse();
            } else {
                return buildWechatFailResponse("处理失败");
            }
            
        } catch (Exception e) {
            log.error("微信支付回调处理异常", e);
            return buildWechatFailResponse("系统异常");
        }
    }
    
    /**
     * 支付宝回调
     */
    @PostMapping("/alipay")
    public String alipayNotify(HttpServletRequest request) {
        try {
            // 获取回调参数
            Map<String, String> params = getRequestParams(request);
            
            // 验证签名
            if (!paymentNotifyService.verifyAlipaySign(params)) {
                log.warn("支付宝回调签名验证失败");
                return "failure";
            }
            
            // 处理回调
            boolean success = paymentNotifyService.handleAlipayNotify(params);
            
            return success ? "success" : "failure";
            
        } catch (Exception e) {
            log.error("支付宝回调处理异常", e);
            return "failure";
        }
    }
}

# 5. 回调处理服务

@Service
public class PaymentNotifyService {
    
    @Autowired
    private PaymentOrderService paymentOrderService;
    
    @Autowired
    private PaymentTransactionService transactionService;
    
    @Autowired
    private ApplicationEventPublisher eventPublisher;
    
    /**
     * 处理微信支付回调
     */
    @Transactional
    public boolean handleWechatNotify(WechatNotifyData notifyData) {
        String outTradeNo = notifyData.getOutTradeNo();
        String transactionId = notifyData.getTransactionId();
        String resultCode = notifyData.getResultCode();
        
        // 查找支付订单
        PaymentOrder paymentOrder = paymentOrderService.findByOrderNumber(outTradeNo);
        if (paymentOrder == null) {
            log.warn("微信支付回调:订单不存在,订单号:{}", outTradeNo);
            return false;
        }
        
        // 防重复处理
        if (paymentOrder.getStatus() == PaymentStatus.SUCCESS) {
            log.info("微信支付回调:订单已处理,订单号:{}", outTradeNo);
            return true;
        }
        
        // 记录交易流水
        PaymentTransaction transaction = new PaymentTransaction();
        transaction.setPaymentOrderId(paymentOrder.getId());
        transaction.setTransactionNumber(generateTransactionNumber());
        transaction.setType(TransactionType.PAYMENT);
        transaction.setAmount(paymentOrder.getAmount());
        transaction.setThirdPartyTransactionId(transactionId);
        transaction.setRequestData(JsonUtil.toJson(notifyData));
        
        if ("SUCCESS".equals(resultCode)) {
            // 支付成功
            paymentOrder.setStatus(PaymentStatus.SUCCESS);
            paymentOrder.setThirdPartyTransactionId(transactionId);
            paymentOrder.setPaidAt(LocalDateTime.now());
            
            transaction.setStatus(TransactionStatus.SUCCESS);
            
            // 发布支付成功事件
            eventPublisher.publishEvent(new PaymentSuccessEvent(this, paymentOrder));
            
        } else {
            // 支付失败
            paymentOrder.setStatus(PaymentStatus.FAILED);
            transaction.setStatus(TransactionStatus.FAILED);
            transaction.setRemark(notifyData.getErrCodeDes());
            
            // 发布支付失败事件
            eventPublisher.publishEvent(new PaymentFailureEvent(this, paymentOrder));
        }
        
        paymentOrderService.save(paymentOrder);
        transactionService.save(transaction);
        
        return true;
    }
    
    /**
     * 验证微信签名
     */
    public boolean verifyWechatSign(String xmlData) {
        try {
            Map<String, String> dataMap = XmlUtil.xmlToMap(xmlData);
            String sign = dataMap.remove("sign");
            String calculatedSign = WechatPaySignUtil.sign(dataMap, wechatPayConfig.getKey());
            return sign.equals(calculatedSign);
        } catch (Exception e) {
            log.error("微信签名验证异常", e);
            return false;
        }
    }
}

# 退款处理

# 1. 退款服务

@Service
public class RefundService {
    
    @Autowired
    private PaymentOrderService paymentOrderService;
    
    @Autowired
    private RefundOrderService refundOrderService;
    
    @Autowired
    private PaymentChannelFactory paymentChannelFactory;
    
    /**
     * 申请退款
     */
    @Transactional
    public RefundResult applyRefund(RefundRequest request) {
        // 1. 查找原支付订单
        PaymentOrder paymentOrder = paymentOrderService.findByOrderNumber(request.getPaymentOrderNumber());
        if (paymentOrder == null || paymentOrder.getStatus() != PaymentStatus.SUCCESS) {
            throw new BusinessException("原支付订单不存在或状态异常");
        }
        
        // 2. 验证退款金额
        if (request.getRefundAmount().compareTo(paymentOrder.getAmount()) > 0) {
            throw new BusinessException("退款金额不能大于支付金额");
        }
        
        // 3. 创建退款订单
        RefundOrder refundOrder = refundOrderService.createRefundOrder(request, paymentOrder);
        
        // 4. 调用第三方退款接口
        PaymentChannelHandler handler = paymentChannelFactory.getHandler(paymentOrder.getPaymentChannel());
        RefundResult result = handler.refund(refundOrder);
        
        // 5. 更新退款订单状态
        if (result.isSuccess()) {
            refundOrderService.updateStatus(refundOrder.getId(), RefundStatus.SUCCESS);
        } else {
            refundOrderService.updateStatus(refundOrder.getId(), RefundStatus.FAILED);
        }
        
        return result;
    }
}

# 对账服务

# 1. 对账实现

@Service
public class ReconciliationService {
    
    @Autowired
    private PaymentOrderService paymentOrderService;
    
    @Autowired
    private PaymentChannelFactory paymentChannelFactory;
    
    /**
     * 执行对账
     */
    @Scheduled(cron = "0 0 2 * * ?") // 每天凌晨2点执行
    public void executeReconciliation() {
        LocalDate yesterday = LocalDate.now().minusDays(1);
        
        // 获取所有支付渠道
        List<PaymentChannel> channels = Arrays.asList(PaymentChannel.values());
        
        for (PaymentChannel channel : channels) {
            try {
                reconcileChannel(channel, yesterday);
            } catch (Exception e) {
                log.error("渠道{}对账失败", channel, e);
            }
        }
    }
    
    /**
     * 渠道对账
     */
    private void reconcileChannel(PaymentChannel channel, LocalDate date) {
        // 1. 下载第三方对账单
        PaymentChannelHandler handler = paymentChannelFactory.getHandler(channel);
        List<ThirdPartyTransaction> thirdPartyTransactions = handler.downloadBill(date);
        
        // 2. 获取本地交易记录
        List<PaymentOrder> localOrders = paymentOrderService.findByChannelAndDate(channel, date);
        
        // 3. 执行对账
        ReconciliationResult result = doReconciliation(localOrders, thirdPartyTransactions);
        
        // 4. 处理差异
        handleReconciliationDifferences(result.getDifferences());
        
        // 5. 保存对账结果
        saveReconciliationResult(channel, date, result);
    }
    
    /**
     * 执行对账逻辑
     */
    private ReconciliationResult doReconciliation(List<PaymentOrder> localOrders, 
                                                 List<ThirdPartyTransaction> thirdPartyTransactions) {
        Map<String, PaymentOrder> localMap = localOrders.stream()
            .collect(Collectors.toMap(PaymentOrder::getPaymentOrderNumber, Function.identity()));
        
        Map<String, ThirdPartyTransaction> thirdPartyMap = thirdPartyTransactions.stream()
            .collect(Collectors.toMap(ThirdPartyTransaction::getOutTradeNo, Function.identity()));
        
        List<ReconciliationDifference> differences = new ArrayList<>();
        
        // 检查本地有但第三方没有的记录
        for (PaymentOrder localOrder : localOrders) {
            String orderNumber = localOrder.getPaymentOrderNumber();
            ThirdPartyTransaction thirdPartyTx = thirdPartyMap.get(orderNumber);
            
            if (thirdPartyTx == null) {
                differences.add(new ReconciliationDifference(
                    DifferenceType.LOCAL_ONLY, orderNumber, localOrder.getAmount(), null));
            } else {
                // 检查金额是否一致
                if (!localOrder.getAmount().equals(thirdPartyTx.getAmount())) {
                    differences.add(new ReconciliationDifference(
                        DifferenceType.AMOUNT_MISMATCH, orderNumber, 
                        localOrder.getAmount(), thirdPartyTx.getAmount()));
                }
            }
        }
        
        // 检查第三方有但本地没有的记录
        for (ThirdPartyTransaction thirdPartyTx : thirdPartyTransactions) {
            String orderNumber = thirdPartyTx.getOutTradeNo();
            if (!localMap.containsKey(orderNumber)) {
                differences.add(new ReconciliationDifference(
                    DifferenceType.THIRD_PARTY_ONLY, orderNumber, null, thirdPartyTx.getAmount()));
            }
        }
        
        return new ReconciliationResult(differences);
    }
}

# 安全机制

# 1. 签名验证

public class PaymentSignUtil {
    
    /**
     * 生成签名
     */
    public static String generateSign(Map<String, String> params, String key, String signType) {
        // 1. 过滤空值参数
        Map<String, String> filteredParams = params.entrySet().stream()
            .filter(entry -> StringUtils.hasText(entry.getValue()))
            .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
        
        // 2. 按key排序
        String sortedParams = filteredParams.entrySet().stream()
            .sorted(Map.Entry.comparingByKey())
            .map(entry -> entry.getKey() + "=" + entry.getValue())
            .collect(Collectors.joining("&"));
        
        // 3. 拼接密钥
        String stringToSign = sortedParams + "&key=" + key;
        
        // 4. 计算签名
        if ("MD5".equals(signType)) {
            return DigestUtils.md5Hex(stringToSign).toUpperCase();
        } else if ("HMAC-SHA256".equals(signType)) {
            return HmacUtils.hmacSha256Hex(key, stringToSign).toUpperCase();
        } else {
            throw new IllegalArgumentException("不支持的签名类型:" + signType);
        }
    }
    
    /**
     * 验证签名
     */
    public static boolean verifySign(Map<String, String> params, String key, String signType) {
        String sign = params.remove("sign");
        if (!StringUtils.hasText(sign)) {
            return false;
        }
        
        String calculatedSign = generateSign(params, key, signType);
        return sign.equals(calculatedSign);
    }
}

# 2. 幂等性保证

@Component
public class PaymentIdempotentHandler {
    
    @Autowired
    private RedisTemplate<String, Object> redisTemplate;
    
    private static final String IDEMPOTENT_KEY_PREFIX = "payment:idempotent:";
    private static final int EXPIRE_SECONDS = 300; // 5分钟
    
    /**
     * 检查幂等性
     */
    public boolean checkIdempotent(String idempotentKey) {
        String key = IDEMPOTENT_KEY_PREFIX + idempotentKey;
        Boolean success = redisTemplate.opsForValue().setIfAbsent(key, "1", EXPIRE_SECONDS, TimeUnit.SECONDS);
        return Boolean.TRUE.equals(success);
    }
    
    /**
     * 释放幂等锁
     */
    public void releaseIdempotent(String idempotentKey) {
        String key = IDEMPOTENT_KEY_PREFIX + idempotentKey;
        redisTemplate.delete(key);
    }
}

# 监控与告警

# 1. 支付监控

@Component
public class PaymentMonitor {
    
    @Autowired
    private MeterRegistry meterRegistry;
    
    /**
     * 记录支付指标
     */
    public void recordPaymentMetrics(PaymentOrder paymentOrder, PaymentStatus status) {
        // 支付次数
        Counter.builder("payment.count")
            .tag("channel", paymentOrder.getPaymentChannel().name())
            .tag("status", status.name())
            .register(meterRegistry)
            .increment();
        
        // 支付金额
        if (status == PaymentStatus.SUCCESS) {
            Gauge.builder("payment.amount")
                .tag("channel", paymentOrder.getPaymentChannel().name())
                .register(meterRegistry, paymentOrder.getAmount().doubleValue());
        }
        
        // 支付耗时
        if (paymentOrder.getPaidAt() != null) {
            Duration duration = Duration.between(paymentOrder.getCreatedAt(), paymentOrder.getPaidAt());
            Timer.builder("payment.duration")
                .tag("channel", paymentOrder.getPaymentChannel().name())
                .register(meterRegistry)
                .record(duration);
        }
    }
}

# 总结

支付系统的关键设计要点:

  1. 安全性:签名验证、HTTPS传输、敏感信息加密存储
  2. 可靠性:幂等性保证、事务一致性、异常处理和重试机制
  3. 扩展性:支持多种支付渠道、灵活的路由策略
  4. 监控性:完善的日志记录、指标监控、告警机制
  5. 对账机制:定时对账、差异处理、数据一致性保证
  6. 性能优化:异步处理、缓存策略、数据库优化

通过以上设计,可以构建一个安全、可靠、高性能的支付系统,满足电商平台的支付需求。