/** * ZPay 支付网关 SDK - 创建订单、查询状态,随时可调用 * 复制自 digital 项目 pay API */ import { getZPayConfig } from "../config"; const ZPAY_REQUIRED = [ "pid", "type", "out_trade_no", "notify_url", "return_url", "name", "money", "sign", "sign_type", ]; function escapeAttr(s: string): string { return String(s) .replace(/&/g, "&") .replace(/"/g, """) .replace(//g, ">"); } export interface CreateOrderOptions { user_id: string; return_url: string; total_fee?: number; type?: string; channel?: string; } export interface CreateOrderResult { params: Record; payUrl: string; } /** 创建支付订单 */ export async function createPayOrder(options: CreateOrderOptions): Promise { const config = getZPayConfig(); if (!config.apiUrl) throw new Error("未配置 PAYMENT_API_URL"); const { user_id, return_url, total_fee, type, channel = "alipay" } = options; const fee = total_fee ?? config.defaultAmount; const orderType = type ?? config.defaultType; const payload = { user_id, total_fee: Number(fee) || config.defaultAmount, type: orderType, channel, return_url, }; const controller = new AbortController(); const timeout = setTimeout(() => controller.abort(), 10000); const res = await fetch(`${config.apiUrl}/payh5`, { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify(payload), signal: controller.signal, }).finally(() => clearTimeout(timeout)); const data = await res.json().catch(() => ({})); if (!res.ok || data?.status !== "ok") { throw new Error(data?.detail || data?.msg || data?.message || "支付创建失败"); } let params = data.params || data.xorpay_params || {}; const payUrl = data.pay_url || data.xorpay_url || config.zpaySubmitUrl; if (!params || typeof params !== "object") { throw new Error("payjsapi 未返回支付参数"); } params = JSON.parse(JSON.stringify(params)); if (data.provider === "xorpay") { throw new Error("当前 payjsapi 使用 xorpay,请设置 PAYMENT_PROVIDER=zpay"); } return { params, payUrl }; } /** 查询订单支付状态 */ export async function getOrderStatus(orderId: string): Promise<{ paid: boolean }> { const config = getZPayConfig(); if (!config.apiUrl) throw new Error("未配置 PAYMENT_API_URL"); const res = await fetch( `${config.apiUrl}/zpay_order_status?out_trade_no=${encodeURIComponent(orderId)}`, { cache: "no-store" } ); const data = await res.json().catch(() => ({})); return { paid: !!data?.paid }; } /** 构建 ZPay 表单跳转 HTML */ export function buildPayHtml(payUrl: string, params: Record): string { const flat: Record = {}; for (const [k, v] of Object.entries(params)) { if (v == null) continue; const s = String(v).trim(); if (s === "") continue; flat[k] = s; } const inputs = Object.entries(flat) .map(([k, v]) => ``) .join("\n"); return ` 跳转支付...

正在跳转到支付页面...

${inputs}
`; } /** 获取 ZPay 必填参数列表(用于校验) */ export { ZPAY_REQUIRED };