支付相关
This commit is contained in:
@@ -6,41 +6,75 @@ import { PaymentApi } from "./PaymentApi";
|
||||
import proto from 'db://assets/Scripts/proto/proto.pb.js';
|
||||
|
||||
export interface PollOptions {
|
||||
maxDurationMs: number; // 轮询总时长(例如 2分钟)
|
||||
startIntervalMs: number; // 初始间隔(例如 2s)
|
||||
maxIntervalMs: number; // 最大间隔(例如 10s)
|
||||
jitter?: boolean; // 抖动
|
||||
maxDurationMs: number; // 最大轮询时长(超过就自动退出)(例如 2分钟)
|
||||
startIntervalMs: number; // 第一次轮询等待的间隔(例如 2s)
|
||||
maxIntervalMs: number; // 最大允许的间隔,防止指数增长过大(例如 10s)
|
||||
jitter?: boolean; // 是否启用抖动(让等待时间带点随机性,避免所有客户端同一时间请求服务器)
|
||||
}
|
||||
|
||||
export class PaymentPoller {
|
||||
private cancelled = false;
|
||||
private currentPollCount = 0; // 轮询次数
|
||||
|
||||
// 取消轮询
|
||||
cancel() { this.cancelled = true; }
|
||||
cancel() {
|
||||
this.cancelled = true;
|
||||
}
|
||||
|
||||
// 轮询订单
|
||||
async poll(orderId: string, opt: PollOptions, onTick?: (d: proto.cs.ICSQueryOrderRes) => void): Promise<proto.cs.ICSQueryOrderRes | null> {
|
||||
// 获取当前轮询次数
|
||||
public getCurrentPollCount(): number {
|
||||
return this.currentPollCount;
|
||||
}
|
||||
|
||||
/**
|
||||
* 轮询订单
|
||||
* @param orderId 要查询的订单 ID
|
||||
* @param opt 轮询配置(间隔、最大时长、是否抖动)
|
||||
* @param onTick 可选回调函数,每次轮询到结果时调用
|
||||
* @returns 最终查询到的订单结果 ICSQueryOrderRes,或者 null(超时/被取消)
|
||||
*/
|
||||
async poll(orderId: string, opt: PollOptions, onTick?: (d: proto.cs.ICSQueryOrderRes) => void): Promise<proto.cs.ICSQueryOrderRes> {
|
||||
const t0 = Date.now();
|
||||
let interval = opt.startIntervalMs;
|
||||
while (!this.cancelled) {
|
||||
// 增加轮询次数
|
||||
this.currentPollCount++;
|
||||
// 查询
|
||||
let reqData = {orderId: orderId};
|
||||
console.log("第 ", this.currentPollCount, " 次轮询订单的请求数据:", reqData);
|
||||
const r = await PaymentApi.I.queryOrder(reqData);
|
||||
console.log("第 ", this.currentPollCount, " 次轮询订单的响应数据:", r);
|
||||
if (r.code === proto.cs.EnmRetCode.SUCCESS && r.data) {
|
||||
// 回调
|
||||
onTick?.(r.data);
|
||||
// 订单状态,-1:失败,0:成功,1:处理中
|
||||
if ([-1, 0].indexOf(r.data.status) !== -1) {
|
||||
return r.data;
|
||||
}
|
||||
}
|
||||
// 退出条件
|
||||
if (Date.now() - t0 > opt.maxDurationMs) return null;
|
||||
// 轮询超时
|
||||
if (Date.now() - t0 > opt.maxDurationMs) {
|
||||
let resultData: proto.cs.ICSQueryOrderRes = {
|
||||
status: 92, // 自定义的状态,代表客户端轮询超时
|
||||
retCode: 0,
|
||||
balance: 0,
|
||||
vipExpire: 0,
|
||||
}
|
||||
return resultData;
|
||||
}
|
||||
// 等待
|
||||
await this.sleep(this.jitter(interval, opt));
|
||||
// 每次轮询后,interval 会按照 1.5 倍增长,直到达到最大间隔 maxIntervalMs,避免在短时间内重复请求
|
||||
interval = Math.min(interval * 1.5, opt.maxIntervalMs);
|
||||
}
|
||||
return null;
|
||||
// 至此,代表取消了轮询订单
|
||||
let resultData: proto.cs.ICSQueryOrderRes = {
|
||||
status: 90, // 自定义的状态,代表取消
|
||||
retCode: 0,
|
||||
balance: 0,
|
||||
vipExpire: 0,
|
||||
}
|
||||
return resultData;
|
||||
}
|
||||
|
||||
// 用来暂停一定的时间(ms 毫秒),并让轮询进入等待状态
|
||||
|
||||
Reference in New Issue
Block a user