时里院子市集
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

5.8 KiB

支付逻辑重构指南

概述

本文档描述了支付逻辑的重构过程,将原本分散的支付代码统一整合,提高了代码的可维护性和复用性。

重构前后对比

重构前的问题

  1. 代码重复:每个支付方式都有重复的订单构建逻辑
  2. 维护困难:支付逻辑分散在多个方法中
  3. 扩展性差:添加新的支付方式需要修改多处代码

重构后的优势

  1. 统一入口:所有支付都通过 onPay 方法处理
  2. 代码复用:订单构建逻辑统一封装
  3. 易于扩展:新增支付方式只需在工具类中添加
  4. 错误处理统一:所有支付的错误处理逻辑一致

核心改进

1. 统一的支付工具类

文件: src/utils/payment.ts

// 支付类型枚举
export enum PaymentType {
  BALANCE = 0,  // 余额支付
  WECHAT = 1,   // 微信支付
  ALIPAY = 3,   // 支付宝支付
}

// 统一支付处理类
export class PaymentHandler {
  static async pay(
    orderData: OrderCreateRequest, 
    paymentType: PaymentType,
    callback?: PaymentCallback
  ): Promise<void> {
    // 统一的支付处理逻辑
  }
}

2. 订单数据构建函数

// 单商品订单
export function buildSingleGoodsOrder(
  goodsId: number,
  quantity: number = 1,
  addressId?: number,
  options?: {
    comments?: string;
    deliveryType?: number;
    couponId?: number;
  }
): OrderCreateRequest

// 购物车订单
export function buildCartOrder(
  cartItems: Array<{ goodsId: number; quantity: number }>,
  addressId?: number,
  options?: { ... }
): OrderCreateRequest

3. 简化的支付入口

重构前:

const onWxPay = async (goods: ShopGoods) => {
  // 校验逻辑
  // 构建订单数据
  // 调用创建订单API
  // 处理微信支付
  // 错误处理
}

const onBalancePay = async (goods: ShopGoods) => {
  // 重复的校验逻辑
  // 重复的订单构建逻辑
  // 处理余额支付
  // 重复的错误处理
}

const onPay = async (goods: ShopGoods) => {
  if (payment?.type == 0) {
    await onBalancePay(goods)
  }
  if (payment?.type == 1) {
    await onWxPay(goods)
  }
}

重构后:

const onPay = async (goods: ShopGoods) => {
  // 基础校验
  if (!address || !payment) {
    // 错误提示
    return;
  }

  // 构建订单数据
  const orderData = buildSingleGoodsOrder(
    goods.goodsId!,
    1,
    address.id,
    { comments: goods.name }
  );

  // 选择支付类型
  const paymentType = payment.type === 0 ? PaymentType.BALANCE : PaymentType.WECHAT;

  // 执行支付
  await PaymentHandler.pay(orderData, paymentType);
};

使用示例

1. 单商品下单

// 在 orderConfirm/index.tsx 中
const onPay = async (goods: ShopGoods) => {
  if (!address || !payment) return;

  const orderData = buildSingleGoodsOrder(
    goods.goodsId!,
    1,
    address.id,
    {
      comments: goods.name,
      deliveryType: 0
    }
  );

  const paymentType = payment.type === 0 ? PaymentType.BALANCE : PaymentType.WECHAT;
  await PaymentHandler.pay(orderData, paymentType);
};

2. 购物车批量下单

// 在 orderConfirmCart/index.tsx 中
const onPay = async () => {
  if (!address || !cartItems?.length) return;

  const orderData = buildCartOrder(
    cartItems.map(item => ({
      goodsId: item.goodsId!,
      quantity: item.quantity || 1
    })),
    address.id,
    {
      comments: '购物车下单',
      deliveryType: 0
    }
  );

  const paymentType = payment?.type === 0 ? PaymentType.BALANCE : PaymentType.WECHAT;
  await PaymentHandler.pay(orderData, paymentType);
};

3. 使用优惠券下单

const onPayWithCoupon = async (goods: ShopGoods, couponId: number) => {
  const orderData = buildSingleGoodsOrder(
    goods.goodsId!,
    1,
    address.id,
    {
      comments: `使用优惠券购买${goods.name}`,
      couponId: couponId
    }
  );

  await PaymentHandler.pay(orderData, PaymentType.WECHAT);
};

4. 自提订单

const onSelfPickupOrder = async (goods: ShopGoods, merchantId: number) => {
  const orderData = buildSingleGoodsOrder(
    goods.goodsId!,
    1,
    address.id,
    {
      comments: `自提订单 - ${goods.name}`,
      deliveryType: 1,
      selfTakeMerchantId: merchantId
    }
  );

  await PaymentHandler.pay(orderData, PaymentType.WECHAT);
};

扩展新的支付方式

1. 添加支付类型

// 在 PaymentType 枚举中添加
export enum PaymentType {
  BALANCE = 0,
  WECHAT = 1,
  ALIPAY = 3,
  UNIONPAY = 4,  // 新增银联支付
}

2. 实现支付处理方法

// 在 PaymentHandler 类中添加
private static async handleUnionPay(result: any): Promise<void> {
  // 银联支付逻辑
}

3. 在支付分发中添加

// 在 PaymentHandler.pay 方法中添加
switch (paymentType) {
  case PaymentType.WECHAT:
    await this.handleWechatPay(result);
    break;
  case PaymentType.BALANCE:
    await this.handleBalancePay(result);
    break;
  case PaymentType.UNIONPAY:  // 新增
    await this.handleUnionPay(result);
    break;
  // ...
}

优势总结

  1. 代码简洁:支付入口方法从 50+ 行减少到 20+ 行
  2. 逻辑清晰:订单构建、支付处理、错误处理分离
  3. 易于测试:每个功能模块独立,便于单元测试
  4. 维护性强:修改支付逻辑只需在工具类中修改
  5. 扩展性好:新增支付方式无需修改业务代码

注意事项

  1. 向后兼容:确保重构后的接口与原有调用方式兼容
  2. 错误处理:统一的错误处理机制,确保用户体验一致
  3. 类型安全:使用 TypeScript 枚举确保支付类型的类型安全
  4. 测试覆盖:对重构后的代码进行充分的测试