进度: 50% (2/4 故事完成) 当前状态: Story 1 和 Story 2 已完成,支付回调和订单取消功能已实现并通过测试 下一步: 开始 Story 3 - 集成微信支付退款功能
跑通当前mini提交创建订单后,调用微信小程序支付,支付回调,更新订单状态。订单支付成功后,在min订单列表进入订单详情,点击取消订单后,可以取消订单并调用微信支付sdk退款,最后更新订单状态。
Current relevant functionality:
/pages/order-submit/index.tsx)- 支持订单创建,跳转到订单详情/pages/order-list/index.tsx)- 支持订单状态显示和筛选,有"去支付"按钮/pages/order-detail/index.tsx)- 支持取消订单和申请退款UI/utils/payment.ts)- 完整的微信支付工具类,包含支付调用、验证、重试、状态管理等Technology stack:
Integration points:
What's being added/changed:
/pages/payment/index.tsx)- 当前缺少支付页面How it integrates:
Success criteria:
✅ Story 1: 完善支付回调处理逻辑 - 确保支付回调正确更新订单状态,支持多租户隔离
packages/mini-payment-mt/src/services/payment.mt.service.ts - 修复TODO注释,实现订单状态更新packages/mini-payment-mt/src/routes/payment/callback.mt.ts - 支付回调接口✅ Story 2: 实现订单取消功能 - 支持已支付订单的取消和退款流程
packages/orders-module-mt/src/services/order.mt.service.ts - 添加cancelOrder方法packages/orders-module-mt/src/routes/user/orders.mt.ts - 添加取消订单APImini/src/pages/order-detail/index.tsx - 集成取消订单UIStory 3: 集成微信支付退款功能 - 调用微信支付SDK实现退款
packages/mini-payment-mt/src/services/payment.mt.service.ts - 添加refund方法packages/mini-payment-mt/src/routes/payment/create.mt.ts - 添加退款APIpackages/mini-payment-mt/src/entities/payment.mt.entity.ts - 可能扩展退款相关字段Story 4: Mini小程序前端支付页面和流程集成 - 创建支付页面并集成支付流程
mini/src/pages/payment/index.tsx - 创建支付页面mini/src/pages/order-submit/index.tsx - 集成支付页面跳转mini/src/pages/order-list/index.tsx - 集成"去支付"按钮功能mini/src/pages/order-detail/index.tsx - 集成取消订单功能Primary Risk: 退款功能可能影响现有支付流程的稳定性
Mitigation: 分阶段实施,先完善支付回调,再实现退款功能
Rollback Plan: 如果出现问题,可以暂时禁用退款功能,保持现有支付流程正常工作
// 支付回调接口 - 修复PaymentMtService中的TODO
class PaymentMtService {
async handlePaymentCallback(callbackData: any, headers: any, rawBody: string): Promise<void> {
// ... 现有验证逻辑 ...
// 根据回调结果更新支付状态
if (parsedData.trade_state === 'SUCCESS') {
payment.paymentStatus = PaymentStatus.PAID;
payment.wechatTransactionId = parsedData.transaction_id;
// TODO: 更新订单状态 - 需要实现
await this.updateOrderPaymentStatus(payment.tenantId, payment.externalOrderId, 2); // 支付成功
} else if (parsedData.trade_state === 'FAIL') {
payment.paymentStatus = PaymentStatus.FAILED;
await this.updateOrderPaymentStatus(payment.tenantId, payment.externalOrderId, 4); // 支付失败
} else if (parsedData.trade_state === 'REFUND') {
payment.paymentStatus = PaymentStatus.REFUNDED;
await this.updateOrderPaymentStatus(payment.tenantId, payment.externalOrderId, 3); // 已退款
}
await paymentRepository.save(payment);
}
}
// 订单取消服务 - 需要在OrderMtService中添加
class OrderMtService {
async cancelOrder(tenantId: number, orderId: number, reason: string, userId: number) {
const order = await this.repository.findOne({
where: { id: orderId, tenantId }
});
if (!order) {
throw new Error('订单不存在');
}
// 验证订单状态
if (order.payState !== 0 && order.payState !== 2) {
throw new Error('该订单状态不允许取消');
}
if (order.payState === 2) {
// 已支付订单,触发退款
const paymentService = new PaymentMtService(this.dataSource);
const refundResult = await paymentService.refund(
tenantId,
order.orderNo,
order.payAmount
);
// 创建退款记录
const refundService = new UserRefundsMtService(this.dataSource);
await refundService.createUserRefund({
orderNo: order.orderNo,
refundOrderNo: refundResult.refund_id,
refundAmount: order.payAmount,
state: 1 // 退款中
}, userId, tenantId);
}
// 更新订单状态
order.payState = 5; // 订单关闭
order.closeTime = new Date();
order.remark = `用户取消: ${reason}`;
order.updatedBy = userId;
await this.repository.save(order);
}
}
// 在PaymentMtService中添加退款功能
class PaymentMtService {
async refund(tenantId: number, orderNo: string, refundAmount: number): Promise<{
refund_id: string;
out_refund_no: string;
}> {
await this.initializeWxPay(tenantId);
const result = await this.wxPay.refund({
out_trade_no: orderNo,
out_refund_no: `REFUND_${orderNo}_${Date.now()}`,
amount: {
refund: refundAmount,
total: refundAmount,
currency: 'CNY'
}
});
return {
refund_id: result.refund_id,
out_refund_no: result.out_refund_no
};
}
}
sequenceDiagram
participant User as 用户
participant Mini as Mini小程序
participant OrderAPI as 订单API
participant PaymentAPI as 支付API
participant WechatPay as 微信支付
participant RefundAPI as 退款API
%% 支付流程
User->>Mini: 提交订单
Mini->>OrderAPI: 创建订单
OrderAPI-->>Mini: 返回订单ID
Mini->>PaymentAPI: 请求支付参数
PaymentAPI-->>Mini: 返回支付参数
Mini->>WechatPay: 调用微信支付
WechatPay-->>Mini: 支付结果
%% 支付回调
WechatPay->>PaymentAPI: 支付回调通知
PaymentAPI->>OrderAPI: 更新订单状态(已支付)
OrderAPI-->>PaymentAPI: 状态更新成功
PaymentAPI-->>WechatPay: 回调响应
%% 退款流程
User->>Mini: 取消订单
Mini->>OrderAPI: 请求取消订单
OrderAPI->>RefundAPI: 发起退款
RefundAPI->>WechatPay: 调用退款API
WechatPay-->>RefundAPI: 退款结果
RefundAPI->>OrderAPI: 更新订单状态(已退款)
OrderAPI-->>Mini: 取消成功
Mini-->>User: 显示取消结果
%% 退款回调
WechatPay->>RefundAPI: 退款回调通知
RefundAPI->>OrderAPI: 确认退款状态
OrderAPI-->>RefundAPI: 状态确认成功
RefundAPI-->>WechatPay: 回调响应
// 支付页面 - 需要创建 /pages/payment/index.tsx
class PaymentPage {
async handlePayment(orderId: number) {
// 1. 调用后端API获取支付参数
const paymentParams = await orderClient['create-payment']['$post']({
json: { orderId }
});
// 2. 使用现有支付工具函数调用微信支付
const result = await requestWechatPayment(paymentParams);
// 3. 处理支付结果
if (result.success) {
// 支付成功,跳转到支付成功页面
Taro.redirectTo({ url: '/pages/payment-success/index' });
} else {
// 支付失败,显示错误信息
Taro.showToast({ title: result.message, icon: 'none' });
}
}
}
// 订单详情页面 - 集成取消订单功能
class OrderDetailPage {
async handleCancelOrder(orderId: number, reason: string) {
try {
// 调用后端取消订单API
await orderClient['cancel-order']['$post']({
json: { orderId, reason }
});
Taro.showToast({ title: '订单取消成功', icon: 'success' });
// 刷新页面或返回订单列表
} catch (error) {
Taro.showToast({ title: error.message, icon: 'none' });
}
}
}
Story Manager Handoff:
"请为这个棕地史诗开发详细的用户故事。关键考虑因素:
mini/src/pages/order-submit/index.tsx)需要集成支付页面跳转mini/src/pages/order-list/index.tsx)的"去支付"按钮需要集成支付功能mini/src/pages/payment/index.tsx)mini/src/pages/order-detail/index.tsx)需要集成取消订单功能mini/src/utils/payment.ts)该史诗应在保持系统完整性的同时交付完整的支付退款流程功能。"