7 changed files with 256 additions and 154 deletions
@ -0,0 +1,56 @@ |
|||||||
|
/** |
||||||
|
* 订单/支付相关 API |
||||||
|
*/ |
||||||
|
import { get, post } from '../services/request' |
||||||
|
import { PaymentResult, QueryPaymentRequest, CloseOrderDto } from '../types/order' |
||||||
|
|
||||||
|
/** |
||||||
|
* 查询支付结果(通用,通过 outTradeNo 或 tradeNo 查询) |
||||||
|
* @param dto 查询参数 |
||||||
|
*/ |
||||||
|
export const queryPaymentResult = (dto: QueryPaymentRequest) => { |
||||||
|
return post<PaymentResult>('/Order/query', dto) |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 关闭支付订单(用户取消或支付失败时调用,避免产生悬挂订单) |
||||||
|
* @param outTradeNo 商户订单号 |
||||||
|
*/ |
||||||
|
export const closeOrder = (outTradeNo: string) => { |
||||||
|
return post<boolean>('/Order/close', { outTradeNo } as CloseOrderDto) |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 查询第三方支付结果(通过消费记录ID查询,适用于开台/续费/关灯重开等场景) |
||||||
|
* @param consumptionId 消费记录ID(来自 startDevice 响应) |
||||||
|
*/ |
||||||
|
export const queryPaymentByConsumptionId = (consumptionId: number) => { |
||||||
|
return get<PaymentResult>(`/Order/query/${consumptionId}`) |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 轮询支付结果,直到确认成功或超时 |
||||||
|
* 判断依据:data.success === true 或 data.tradeState === 'SUCCESS' |
||||||
|
* @param consumptionId 消费记录ID |
||||||
|
* @param maxRetries 最大轮询次数(默认 5 次) |
||||||
|
* @param intervalMs 每次间隔毫秒(默认 2000ms) |
||||||
|
* @returns 是否支付成功 |
||||||
|
*/ |
||||||
|
export const pollTablePaymentStatus = async ( |
||||||
|
consumptionId: number, |
||||||
|
maxRetries = 5, |
||||||
|
intervalMs = 2000 |
||||||
|
): Promise<boolean> => { |
||||||
|
for (let i = 0; i < maxRetries; i++) { |
||||||
|
await new Promise(resolve => setTimeout(resolve, intervalMs)) |
||||||
|
try { |
||||||
|
const res = await queryPaymentByConsumptionId(consumptionId) |
||||||
|
if (res.data?.success || res.data?.tradeState === 'SUCCESS') { |
||||||
|
return true |
||||||
|
} |
||||||
|
} catch (e) { |
||||||
|
console.warn(`查询支付状态第${i + 1}次异常:`, e) |
||||||
|
} |
||||||
|
} |
||||||
|
return false |
||||||
|
} |
||||||
@ -0,0 +1,63 @@ |
|||||||
|
/** |
||||||
|
* 订单/支付相关类型定义 |
||||||
|
*/ |
||||||
|
|
||||||
|
/** |
||||||
|
* 支付渠道 |
||||||
|
*/ |
||||||
|
export type PaymentChannel = 'WechatPay' | 'Alipay' | 'UnionPay' | 'Balance' | 'BankCard' |
||||||
|
|
||||||
|
/** |
||||||
|
* 支付查询结果 |
||||||
|
*/ |
||||||
|
export interface PaymentResult { |
||||||
|
/** 是否成功 */ |
||||||
|
success: boolean |
||||||
|
/** 消息 */ |
||||||
|
message: string |
||||||
|
/** 商户订单号 */ |
||||||
|
outTradeNo: string |
||||||
|
/** 支付渠道订单号 */ |
||||||
|
tradeNo: string |
||||||
|
/** 支付金额 */ |
||||||
|
amount: number |
||||||
|
/** 支付时间 */ |
||||||
|
payTime: string |
||||||
|
/** 支付渠道 */ |
||||||
|
channel: PaymentChannel |
||||||
|
/** 前端调起支付所需参数 */ |
||||||
|
payParameters: unknown |
||||||
|
/** 支付URL(扫码支付等) */ |
||||||
|
payUrl: string |
||||||
|
/** H5支付URL */ |
||||||
|
mwebUrl: string |
||||||
|
/** 预支付ID(小程序/JSAPI支付) */ |
||||||
|
prepayId: string |
||||||
|
/** |
||||||
|
* 交易状态 |
||||||
|
* 微信标准值:SUCCESS-成功 / REFUND-退款 / NOTPAY-未支付 / CLOSED-关闭 / REVOKED-撤销 / USERPAYING-支付中 / PAYERROR-支付失败 |
||||||
|
*/ |
||||||
|
tradeState: string |
||||||
|
/** 原始响应数据 */ |
||||||
|
rawResponse: unknown |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 查询支付结果请求参数(POST /Order/query) |
||||||
|
*/ |
||||||
|
export interface QueryPaymentRequest { |
||||||
|
/** 商户订单号 */ |
||||||
|
outTradeNo?: string |
||||||
|
/** 微信支付订单号 */ |
||||||
|
tradeNo?: string |
||||||
|
/** 支付渠道 */ |
||||||
|
channel?: PaymentChannel |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 关闭支付订单请求参数(POST /Order/close) |
||||||
|
*/ |
||||||
|
export interface CloseOrderDto { |
||||||
|
/** 商户订单号 */ |
||||||
|
outTradeNo: string |
||||||
|
} |
||||||
Loading…
Reference in new issue