forked from gxwebsoft/mp-10550
265 lines
5.8 KiB
Markdown
265 lines
5.8 KiB
Markdown
# 支付逻辑重构指南
|
|
|
|
## 概述
|
|
|
|
本文档描述了支付逻辑的重构过程,将原本分散的支付代码统一整合,提高了代码的可维护性和复用性。
|
|
|
|
## 重构前后对比
|
|
|
|
### 重构前的问题
|
|
|
|
1. **代码重复**:每个支付方式都有重复的订单构建逻辑
|
|
2. **维护困难**:支付逻辑分散在多个方法中
|
|
3. **扩展性差**:添加新的支付方式需要修改多处代码
|
|
|
|
### 重构后的优势
|
|
|
|
1. **统一入口**:所有支付都通过 `onPay` 方法处理
|
|
2. **代码复用**:订单构建逻辑统一封装
|
|
3. **易于扩展**:新增支付方式只需在工具类中添加
|
|
4. **错误处理统一**:所有支付的错误处理逻辑一致
|
|
|
|
## 核心改进
|
|
|
|
### 1. 统一的支付工具类
|
|
|
|
**文件:** `src/utils/payment.ts`
|
|
|
|
```typescript
|
|
// 支付类型枚举
|
|
export enum PaymentType {
|
|
BALANCE = 0, // 余额支付
|
|
WECHAT = 1, // 微信支付
|
|
ALIPAY = 3, // 支付宝支付
|
|
}
|
|
|
|
// 统一支付处理类
|
|
export class PaymentHandler {
|
|
static async pay(
|
|
orderData: OrderCreateRequest,
|
|
paymentType: PaymentType,
|
|
callback?: PaymentCallback
|
|
): Promise<void> {
|
|
// 统一的支付处理逻辑
|
|
}
|
|
}
|
|
```
|
|
|
|
### 2. 订单数据构建函数
|
|
|
|
```typescript
|
|
// 单商品订单
|
|
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. 简化的支付入口
|
|
|
|
**重构前:**
|
|
```typescript
|
|
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)
|
|
}
|
|
}
|
|
```
|
|
|
|
**重构后:**
|
|
```typescript
|
|
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. 单商品下单
|
|
|
|
```typescript
|
|
// 在 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. 购物车批量下单
|
|
|
|
```typescript
|
|
// 在 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. 使用优惠券下单
|
|
|
|
```typescript
|
|
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. 自提订单
|
|
|
|
```typescript
|
|
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. 添加支付类型
|
|
|
|
```typescript
|
|
// 在 PaymentType 枚举中添加
|
|
export enum PaymentType {
|
|
BALANCE = 0,
|
|
WECHAT = 1,
|
|
ALIPAY = 3,
|
|
UNIONPAY = 4, // 新增银联支付
|
|
}
|
|
```
|
|
|
|
### 2. 实现支付处理方法
|
|
|
|
```typescript
|
|
// 在 PaymentHandler 类中添加
|
|
private static async handleUnionPay(result: any): Promise<void> {
|
|
// 银联支付逻辑
|
|
}
|
|
```
|
|
|
|
### 3. 在支付分发中添加
|
|
|
|
```typescript
|
|
// 在 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. **测试覆盖**:对重构后的代码进行充分的测试
|