@downcity/services 0.1.98 → 0.1.101
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/payment/index.d.ts +6 -6
- package/bin/payment/index.d.ts.map +1 -1
- package/bin/payment/index.js +6 -6
- package/bin/payment/index.js.map +1 -1
- package/bin/{payment-creem/creem.d.ts → payment/providers/creem/client.d.ts} +7 -12
- package/bin/payment/providers/creem/client.d.ts.map +1 -0
- package/bin/{payment-creem/creem.js → payment/providers/creem/client.js} +29 -37
- package/bin/payment/providers/creem/client.js.map +1 -0
- package/bin/payment/providers/creem/index.d.ts +13 -0
- package/bin/payment/providers/creem/index.d.ts.map +1 -0
- package/bin/payment/providers/creem/index.js +94 -0
- package/bin/payment/providers/creem/index.js.map +1 -0
- package/bin/payment/providers/creem/types.d.ts +49 -0
- package/bin/payment/providers/creem/types.d.ts.map +1 -0
- package/bin/payment/providers/creem/types.js +9 -0
- package/bin/payment/providers/creem/types.js.map +1 -0
- package/bin/payment/providers/dodo/client.d.ts +48 -0
- package/bin/payment/providers/dodo/client.d.ts.map +1 -0
- package/bin/{payment-dodo/dodo.js → payment/providers/dodo/client.js} +18 -33
- package/bin/payment/providers/dodo/client.js.map +1 -0
- package/bin/payment/providers/dodo/index.d.ts +13 -0
- package/bin/payment/providers/dodo/index.d.ts.map +1 -0
- package/bin/payment/providers/dodo/index.js +109 -0
- package/bin/payment/providers/dodo/index.js.map +1 -0
- package/bin/payment/providers/dodo/types.d.ts +58 -0
- package/bin/payment/providers/dodo/types.d.ts.map +1 -0
- package/bin/payment/providers/dodo/types.js +9 -0
- package/bin/payment/providers/dodo/types.js.map +1 -0
- package/bin/payment/providers/index.d.ts +12 -0
- package/bin/payment/providers/index.d.ts.map +1 -0
- package/bin/payment/providers/index.js +12 -0
- package/bin/payment/providers/index.js.map +1 -0
- package/bin/{payment-stripe/stripe.d.ts → payment/providers/stripe/client.d.ts} +4 -12
- package/bin/payment/providers/stripe/client.d.ts.map +1 -0
- package/bin/{payment-stripe/stripe.js → payment/providers/stripe/client.js} +22 -38
- package/bin/payment/providers/stripe/client.js.map +1 -0
- package/bin/payment/providers/stripe/index.d.ts +13 -0
- package/bin/payment/providers/stripe/index.d.ts.map +1 -0
- package/bin/payment/providers/stripe/index.js +97 -0
- package/bin/payment/providers/stripe/index.js.map +1 -0
- package/bin/payment/providers/stripe/types.d.ts +51 -0
- package/bin/payment/providers/stripe/types.d.ts.map +1 -0
- package/bin/payment/providers/stripe/types.js +9 -0
- package/bin/payment/providers/stripe/types.js.map +1 -0
- package/bin/payment/providers/waffo/client.d.ts +56 -0
- package/bin/payment/providers/waffo/client.d.ts.map +1 -0
- package/bin/{payment-waffo/waffo.js → payment/providers/waffo/client.js} +54 -31
- package/bin/payment/providers/waffo/client.js.map +1 -0
- package/bin/payment/providers/waffo/index.d.ts +13 -0
- package/bin/payment/providers/waffo/index.d.ts.map +1 -0
- package/bin/payment/providers/waffo/index.js +105 -0
- package/bin/payment/providers/waffo/index.js.map +1 -0
- package/bin/payment/providers/waffo/types.d.ts +63 -0
- package/bin/payment/providers/waffo/types.d.ts.map +1 -0
- package/bin/payment/providers/waffo/types.js +9 -0
- package/bin/payment/providers/waffo/types.js.map +1 -0
- package/package.json +3 -3
- package/bin/payment/providers.d.ts +0 -25
- package/bin/payment/providers.d.ts.map +0 -1
- package/bin/payment/providers.js +0 -415
- package/bin/payment/providers.js.map +0 -1
- package/bin/payment-creem/creem.d.ts.map +0 -1
- package/bin/payment-creem/creem.js.map +0 -1
- package/bin/payment-creem/index.d.ts +0 -17
- package/bin/payment-creem/index.d.ts.map +0 -1
- package/bin/payment-creem/index.js +0 -569
- package/bin/payment-creem/index.js.map +0 -1
- package/bin/payment-creem/schema.d.ts +0 -378
- package/bin/payment-creem/schema.d.ts.map +0 -1
- package/bin/payment-creem/schema.js +0 -47
- package/bin/payment-creem/schema.js.map +0 -1
- package/bin/payment-creem/types.d.ts +0 -293
- package/bin/payment-creem/types.d.ts.map +0 -1
- package/bin/payment-creem/types.js +0 -10
- package/bin/payment-creem/types.js.map +0 -1
- package/bin/payment-dodo/dodo.d.ts +0 -119
- package/bin/payment-dodo/dodo.d.ts.map +0 -1
- package/bin/payment-dodo/dodo.js.map +0 -1
- package/bin/payment-dodo/index.d.ts +0 -17
- package/bin/payment-dodo/index.d.ts.map +0 -1
- package/bin/payment-dodo/index.js +0 -548
- package/bin/payment-dodo/index.js.map +0 -1
- package/bin/payment-dodo/schema.d.ts +0 -378
- package/bin/payment-dodo/schema.d.ts.map +0 -1
- package/bin/payment-dodo/schema.js +0 -47
- package/bin/payment-dodo/schema.js.map +0 -1
- package/bin/payment-dodo/types.d.ts +0 -257
- package/bin/payment-dodo/types.d.ts.map +0 -1
- package/bin/payment-dodo/types.js +0 -10
- package/bin/payment-dodo/types.js.map +0 -1
- package/bin/payment-stripe/index.d.ts +0 -17
- package/bin/payment-stripe/index.d.ts.map +0 -1
- package/bin/payment-stripe/index.js +0 -555
- package/bin/payment-stripe/index.js.map +0 -1
- package/bin/payment-stripe/schema.d.ts +0 -378
- package/bin/payment-stripe/schema.d.ts.map +0 -1
- package/bin/payment-stripe/schema.js +0 -47
- package/bin/payment-stripe/schema.js.map +0 -1
- package/bin/payment-stripe/stripe.d.ts.map +0 -1
- package/bin/payment-stripe/stripe.js.map +0 -1
- package/bin/payment-stripe/types.d.ts +0 -303
- package/bin/payment-stripe/types.d.ts.map +0 -1
- package/bin/payment-stripe/types.js +0 -10
- package/bin/payment-stripe/types.js.map +0 -1
- package/bin/payment-waffo/index.d.ts +0 -17
- package/bin/payment-waffo/index.d.ts.map +0 -1
- package/bin/payment-waffo/index.js +0 -549
- package/bin/payment-waffo/index.js.map +0 -1
- package/bin/payment-waffo/schema.d.ts +0 -388
- package/bin/payment-waffo/schema.d.ts.map +0 -1
- package/bin/payment-waffo/schema.js +0 -39
- package/bin/payment-waffo/schema.js.map +0 -1
- package/bin/payment-waffo/types.d.ts +0 -285
- package/bin/payment-waffo/types.d.ts.map +0 -1
- package/bin/payment-waffo/types.js +0 -10
- package/bin/payment-waffo/types.js.map +0 -1
- package/bin/payment-waffo/waffo.d.ts +0 -111
- package/bin/payment-waffo/waffo.d.ts.map +0 -1
- package/bin/payment-waffo/waffo.js.map +0 -1
|
@@ -1,549 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Downcity Waffo Pancake 一次性充值服务。
|
|
3
|
-
*
|
|
4
|
-
* 关键说明(中文)
|
|
5
|
-
* - 当前版本只处理 Waffo Checkout 一次性充值
|
|
6
|
-
* - 不处理 subscription,也不处理 refund ticket
|
|
7
|
-
* - 支付成功后统一调用 balance.finishTopup() 完成到账
|
|
8
|
-
*/
|
|
9
|
-
import { resolvePaymentRedirectURL } from "../payment/redirect.js";
|
|
10
|
-
import { waffoEvents, waffoPayments } from "./schema.js";
|
|
11
|
-
import { createWaffoCheckoutSession, createWaffoClient, normalizeOptionalText, normalizeRequired, normalizeWaffoEnvironment, parseWaffoWebhookEvent, readMetadata, } from "./waffo.js";
|
|
12
|
-
/**
|
|
13
|
-
* Waffo 服务对外暴露的运行时环境变量。
|
|
14
|
-
*/
|
|
15
|
-
const waffoPaymentEnv = [
|
|
16
|
-
{
|
|
17
|
-
key: "WAFFO_MERCHANT_ID",
|
|
18
|
-
description: "Waffo Merchant ID,例如 MER_xxx",
|
|
19
|
-
required: true,
|
|
20
|
-
},
|
|
21
|
-
{
|
|
22
|
-
key: "WAFFO_PRIVATE_KEY",
|
|
23
|
-
description: "Waffo API private key,用于 SDK 请求签名",
|
|
24
|
-
required: true,
|
|
25
|
-
},
|
|
26
|
-
{
|
|
27
|
-
key: "WAFFO_PRODUCT_ID",
|
|
28
|
-
description: "Waffo product_id,用于创建 Checkout Session",
|
|
29
|
-
required: true,
|
|
30
|
-
},
|
|
31
|
-
{
|
|
32
|
-
key: "WAFFO_WEBHOOK_PUBLIC_KEY",
|
|
33
|
-
description: "Waffo webhook public key,用于校验 x-waffo-signature",
|
|
34
|
-
required: false,
|
|
35
|
-
},
|
|
36
|
-
{
|
|
37
|
-
key: "WAFFO_ENVIRONMENT",
|
|
38
|
-
description: "Waffo 环境:test 或 prod;默认 test",
|
|
39
|
-
required: false,
|
|
40
|
-
},
|
|
41
|
-
{
|
|
42
|
-
key: "DOWNCITY_CITY_BASE_URL",
|
|
43
|
-
description: "City 对外访问地址;用于自动生成 Waffo 默认跳转页地址",
|
|
44
|
-
required: false,
|
|
45
|
-
},
|
|
46
|
-
{
|
|
47
|
-
key: "WAFFO_CURRENCY",
|
|
48
|
-
description: "默认结算币种,例如 usd",
|
|
49
|
-
required: false,
|
|
50
|
-
},
|
|
51
|
-
{
|
|
52
|
-
key: "WAFFO_API_BASE_URL",
|
|
53
|
-
description: "可选的 Waffo API 基础地址覆写,通常只用于测试环境",
|
|
54
|
-
required: false,
|
|
55
|
-
},
|
|
56
|
-
];
|
|
57
|
-
export { waffoEvents, waffoPayments } from "./schema.js";
|
|
58
|
-
/**
|
|
59
|
-
* 创建 Waffo Pancake 一次性充值服务。
|
|
60
|
-
*/
|
|
61
|
-
export function waffoPaymentService(options) {
|
|
62
|
-
const normalized = normalizeOptions(options);
|
|
63
|
-
return {
|
|
64
|
-
id: "payment.waffo",
|
|
65
|
-
name: "Waffo Pancake Payment",
|
|
66
|
-
version: "0.1.0",
|
|
67
|
-
env: waffoPaymentEnv,
|
|
68
|
-
schema: {
|
|
69
|
-
payments: waffoPayments,
|
|
70
|
-
events: waffoEvents,
|
|
71
|
-
},
|
|
72
|
-
instruction: [
|
|
73
|
-
"使用 Waffo Pancake 创建一次性充值 Checkout,并在 webhook 成功后完成 balance topup。",
|
|
74
|
-
"这个服务不处理 subscription,也不处理 refund ticket。",
|
|
75
|
-
"当 options 未显式传入时,会回退读取 WAFFO_MERCHANT_ID / WAFFO_PRIVATE_KEY / WAFFO_PRODUCT_ID。",
|
|
76
|
-
`currency=${normalized.currency},environment=${normalized.environment}。`,
|
|
77
|
-
"支付成功后统一通过 balance.finishTopup() 完成到账。",
|
|
78
|
-
].join("\n"),
|
|
79
|
-
install(ctx) {
|
|
80
|
-
const payments = ctx.table("payments");
|
|
81
|
-
const events = ctx.table("events");
|
|
82
|
-
const balance = normalized.balance;
|
|
83
|
-
ctx.route({
|
|
84
|
-
method: "POST",
|
|
85
|
-
path: "/checkout/create",
|
|
86
|
-
auth: ["user"],
|
|
87
|
-
async handler(requestCtx) {
|
|
88
|
-
const body = await requestCtx.json();
|
|
89
|
-
const userId = normalizeRequired(requestCtx.user?.user_id, "user_id");
|
|
90
|
-
const topup = await balance.readTopup(normalizeRequired(body.topup_id, "topup_id"));
|
|
91
|
-
if (topup.user_id !== userId) {
|
|
92
|
-
return requestCtx.jsonResponse({ error: "Topup does not belong to current user" }, 403);
|
|
93
|
-
}
|
|
94
|
-
if (topup.status !== "pending") {
|
|
95
|
-
return requestCtx.jsonResponse({ error: `Topup is already ${topup.status}` }, 409);
|
|
96
|
-
}
|
|
97
|
-
const existing = await findActivePaymentByTopup(payments, topup.topup_id);
|
|
98
|
-
if (existing)
|
|
99
|
-
return requestCtx.jsonResponse(toCheckoutResult(existing));
|
|
100
|
-
const merchantId = normalized.merchant_id ?? ctx.env("WAFFO_MERCHANT_ID");
|
|
101
|
-
if (!merchantId)
|
|
102
|
-
return requestCtx.jsonResponse({ error: "Waffo merchant id is not configured" }, 500);
|
|
103
|
-
const privateKey = normalized.private_key ?? ctx.env("WAFFO_PRIVATE_KEY");
|
|
104
|
-
if (!privateKey)
|
|
105
|
-
return requestCtx.jsonResponse({ error: "Waffo private key is not configured" }, 500);
|
|
106
|
-
const productId = normalized.product_id ?? ctx.env("WAFFO_PRODUCT_ID");
|
|
107
|
-
if (!productId)
|
|
108
|
-
return requestCtx.jsonResponse({ error: "Waffo product id is not configured" }, 500);
|
|
109
|
-
const paymentId = `pay_${randomId()}`;
|
|
110
|
-
const currency = resolveCurrency(normalized, ctx);
|
|
111
|
-
const client = createWaffoClient({
|
|
112
|
-
merchant_id: merchantId,
|
|
113
|
-
private_key: privateKey,
|
|
114
|
-
webhook_public_key: normalized.webhook_public_key ?? ctx.env("WAFFO_WEBHOOK_PUBLIC_KEY"),
|
|
115
|
-
api_base_url: normalized.api_base_url ?? ctx.env("WAFFO_API_BASE_URL"),
|
|
116
|
-
});
|
|
117
|
-
const created = await createWaffoCheckoutSession(client, {
|
|
118
|
-
payment_id: paymentId,
|
|
119
|
-
topup,
|
|
120
|
-
product_id: productId,
|
|
121
|
-
currency,
|
|
122
|
-
success_url: resolvePaymentRedirectURL({
|
|
123
|
-
path: "/v1/payment.waffo/redirect/success",
|
|
124
|
-
ctx,
|
|
125
|
-
request: requestCtx.request,
|
|
126
|
-
}),
|
|
127
|
-
});
|
|
128
|
-
const now = new Date().toISOString();
|
|
129
|
-
const row = {
|
|
130
|
-
payment_id: paymentId,
|
|
131
|
-
topup_id: topup.topup_id,
|
|
132
|
-
user_id: topup.user_id,
|
|
133
|
-
waffo_session_id: created.session_id,
|
|
134
|
-
waffo_order_id: "",
|
|
135
|
-
waffo_payment_id: "",
|
|
136
|
-
amount: topup.amount,
|
|
137
|
-
currency,
|
|
138
|
-
status: "pending",
|
|
139
|
-
checkout_url: created.checkout_url,
|
|
140
|
-
metadata_json: JSON.stringify({
|
|
141
|
-
note: topup.note,
|
|
142
|
-
product_id: productId,
|
|
143
|
-
}),
|
|
144
|
-
created_at: now,
|
|
145
|
-
updated_at: now,
|
|
146
|
-
};
|
|
147
|
-
await payments.insert(row);
|
|
148
|
-
return requestCtx.jsonResponse(toCheckoutResult(row));
|
|
149
|
-
},
|
|
150
|
-
});
|
|
151
|
-
ctx.route({
|
|
152
|
-
method: "GET",
|
|
153
|
-
path: "/payments/me",
|
|
154
|
-
auth: ["user"],
|
|
155
|
-
async handler(requestCtx) {
|
|
156
|
-
const userId = normalizeRequired(requestCtx.user?.user_id, "user_id");
|
|
157
|
-
return requestCtx.jsonResponse({ items: sortPayments(await payments.select({ user_id: userId })) });
|
|
158
|
-
},
|
|
159
|
-
});
|
|
160
|
-
ctx.route({
|
|
161
|
-
method: "GET",
|
|
162
|
-
path: "/payments",
|
|
163
|
-
auth: ["admin"],
|
|
164
|
-
async handler(requestCtx) {
|
|
165
|
-
return requestCtx.jsonResponse({ items: sortPayments(await payments.select()) });
|
|
166
|
-
},
|
|
167
|
-
});
|
|
168
|
-
ctx.route({
|
|
169
|
-
method: "GET",
|
|
170
|
-
path: "/events",
|
|
171
|
-
auth: ["admin"],
|
|
172
|
-
async handler(requestCtx) {
|
|
173
|
-
return requestCtx.jsonResponse({ items: sortEvents(await events.select()) });
|
|
174
|
-
},
|
|
175
|
-
});
|
|
176
|
-
ctx.route({
|
|
177
|
-
method: "POST",
|
|
178
|
-
path: "/webhook",
|
|
179
|
-
auth: [],
|
|
180
|
-
async handler(requestCtx) {
|
|
181
|
-
const raw = await requestCtx.text();
|
|
182
|
-
let event;
|
|
183
|
-
try {
|
|
184
|
-
const client = createWaffoClient({
|
|
185
|
-
merchant_id: normalized.merchant_id ?? ctx.env("WAFFO_MERCHANT_ID") ?? "MER_webhook",
|
|
186
|
-
private_key: normalized.private_key ?? ctx.env("WAFFO_PRIVATE_KEY") ?? fallbackPrivateKey(),
|
|
187
|
-
webhook_public_key: normalized.webhook_public_key ?? ctx.env("WAFFO_WEBHOOK_PUBLIC_KEY"),
|
|
188
|
-
api_base_url: normalized.api_base_url ?? ctx.env("WAFFO_API_BASE_URL"),
|
|
189
|
-
});
|
|
190
|
-
event = parseWaffoWebhookEvent({
|
|
191
|
-
client,
|
|
192
|
-
raw,
|
|
193
|
-
signature: requestCtx.request.headers.get("x-waffo-signature"),
|
|
194
|
-
environment: resolveEnvironment(normalized, ctx),
|
|
195
|
-
});
|
|
196
|
-
}
|
|
197
|
-
catch {
|
|
198
|
-
return requestCtx.jsonResponse({ error: "Invalid Waffo signature" }, 400);
|
|
199
|
-
}
|
|
200
|
-
const eventId = readEventId(event);
|
|
201
|
-
const eventType = readEventType(event);
|
|
202
|
-
const existing = (await events.select({ event_id: eventId }))[0];
|
|
203
|
-
if (existing) {
|
|
204
|
-
return requestCtx.jsonResponse({
|
|
205
|
-
received: true,
|
|
206
|
-
event_id: eventId,
|
|
207
|
-
sync_status: existing.sync_status,
|
|
208
|
-
});
|
|
209
|
-
}
|
|
210
|
-
const eventRow = {
|
|
211
|
-
event_id: eventId,
|
|
212
|
-
type: eventType,
|
|
213
|
-
payload_json: JSON.stringify(event),
|
|
214
|
-
sync_status: "pending",
|
|
215
|
-
sync_error: "",
|
|
216
|
-
created_at: new Date().toISOString(),
|
|
217
|
-
};
|
|
218
|
-
await events.insert(eventRow);
|
|
219
|
-
try {
|
|
220
|
-
const syncStatus = await syncWaffoEvent({ event, payments, balance });
|
|
221
|
-
await updateEvent(events, eventId, syncStatus, "");
|
|
222
|
-
return requestCtx.jsonResponse({
|
|
223
|
-
received: true,
|
|
224
|
-
event_id: eventId,
|
|
225
|
-
sync_status: syncStatus,
|
|
226
|
-
});
|
|
227
|
-
}
|
|
228
|
-
catch (error) {
|
|
229
|
-
const message = error instanceof Error ? error.message : String(error);
|
|
230
|
-
await updateEvent(events, eventId, "failed", message);
|
|
231
|
-
return requestCtx.jsonResponse({
|
|
232
|
-
received: true,
|
|
233
|
-
event_id: eventId,
|
|
234
|
-
sync_status: "failed",
|
|
235
|
-
error: message,
|
|
236
|
-
}, 500);
|
|
237
|
-
}
|
|
238
|
-
},
|
|
239
|
-
});
|
|
240
|
-
ctx.route({
|
|
241
|
-
method: "GET",
|
|
242
|
-
path: "/redirect/success",
|
|
243
|
-
auth: [],
|
|
244
|
-
handler(requestCtx) {
|
|
245
|
-
return htmlResponse(renderRedirectPage({
|
|
246
|
-
title: "Payment successful",
|
|
247
|
-
heading: "Payment completed",
|
|
248
|
-
description: "Your Waffo Pancake payment has been accepted. If the balance view has not refreshed yet, close this page and return to your app.",
|
|
249
|
-
request: requestCtx.request,
|
|
250
|
-
}));
|
|
251
|
-
},
|
|
252
|
-
});
|
|
253
|
-
ctx.route({
|
|
254
|
-
method: "GET",
|
|
255
|
-
path: "/redirect/cancel",
|
|
256
|
-
auth: [],
|
|
257
|
-
handler(requestCtx) {
|
|
258
|
-
return htmlResponse(renderRedirectPage({
|
|
259
|
-
title: "Payment canceled",
|
|
260
|
-
heading: "Payment canceled",
|
|
261
|
-
description: "No charge was completed. You can close this page and return to your app to try again later.",
|
|
262
|
-
request: requestCtx.request,
|
|
263
|
-
}));
|
|
264
|
-
},
|
|
265
|
-
});
|
|
266
|
-
},
|
|
267
|
-
};
|
|
268
|
-
}
|
|
269
|
-
/**
|
|
270
|
-
* 统一同步 Waffo webhook 事件。
|
|
271
|
-
*/
|
|
272
|
-
async function syncWaffoEvent(input) {
|
|
273
|
-
const { event, payments, balance } = input;
|
|
274
|
-
switch (readEventType(event)) {
|
|
275
|
-
case "order.completed":
|
|
276
|
-
return await syncOrderCompleted(event, payments, balance);
|
|
277
|
-
case "subscription.past_due":
|
|
278
|
-
case "refund.failed":
|
|
279
|
-
return "ignored";
|
|
280
|
-
default:
|
|
281
|
-
return "ignored";
|
|
282
|
-
}
|
|
283
|
-
}
|
|
284
|
-
/**
|
|
285
|
-
* 同步 `order.completed`。
|
|
286
|
-
*/
|
|
287
|
-
async function syncOrderCompleted(event, payments, balance) {
|
|
288
|
-
const data = readEventData(event);
|
|
289
|
-
const payment = await findPaymentByEventData(payments, data);
|
|
290
|
-
if (!payment)
|
|
291
|
-
return "ignored";
|
|
292
|
-
if (payment.status === "paid")
|
|
293
|
-
return "applied";
|
|
294
|
-
const orderId = normalizeOptionalText(data.orderId);
|
|
295
|
-
const waffoPaymentId = normalizeOptionalText(data.paymentId) || normalizeOptionalText(event.eventId);
|
|
296
|
-
const topup = await balance.readTopup(payment.topup_id);
|
|
297
|
-
if (topup.status === "pending") {
|
|
298
|
-
await balance.finishTopup(payment.topup_id, {
|
|
299
|
-
note: "waffo topup",
|
|
300
|
-
ref: waffoPaymentId || orderId || payment.waffo_session_id,
|
|
301
|
-
meta: {
|
|
302
|
-
waffo_event_id: readEventId(event),
|
|
303
|
-
waffo_order_id: orderId,
|
|
304
|
-
waffo_payment_id: waffoPaymentId,
|
|
305
|
-
waffo_service_payment_id: payment.payment_id,
|
|
306
|
-
},
|
|
307
|
-
});
|
|
308
|
-
}
|
|
309
|
-
await updatePayment(payments, payment.payment_id, {
|
|
310
|
-
status: "paid",
|
|
311
|
-
waffo_order_id: orderId || payment.waffo_order_id,
|
|
312
|
-
waffo_payment_id: waffoPaymentId || payment.waffo_payment_id,
|
|
313
|
-
});
|
|
314
|
-
return "applied";
|
|
315
|
-
}
|
|
316
|
-
/**
|
|
317
|
-
* 根据 webhook data 寻找支付记录。
|
|
318
|
-
*/
|
|
319
|
-
async function findPaymentByEventData(payments, data) {
|
|
320
|
-
const paymentId = normalizeOptionalText(data.orderMerchantExternalId);
|
|
321
|
-
if (paymentId) {
|
|
322
|
-
const record = (await payments.select({ payment_id: paymentId }))[0];
|
|
323
|
-
if (record)
|
|
324
|
-
return record;
|
|
325
|
-
}
|
|
326
|
-
const orderId = normalizeOptionalText(data.orderId);
|
|
327
|
-
if (orderId) {
|
|
328
|
-
const record = (await payments.select({ waffo_order_id: orderId }))[0];
|
|
329
|
-
if (record)
|
|
330
|
-
return record;
|
|
331
|
-
}
|
|
332
|
-
const waffoPaymentId = normalizeOptionalText(data.paymentId);
|
|
333
|
-
if (waffoPaymentId) {
|
|
334
|
-
const record = (await payments.select({ waffo_payment_id: waffoPaymentId }))[0];
|
|
335
|
-
if (record)
|
|
336
|
-
return record;
|
|
337
|
-
}
|
|
338
|
-
const metadata = readMetadata(data.orderMetadata);
|
|
339
|
-
const topupId = normalizeOptionalText(metadata.topup_id);
|
|
340
|
-
if (topupId)
|
|
341
|
-
return await findActivePaymentByTopup(payments, topupId);
|
|
342
|
-
return undefined;
|
|
343
|
-
}
|
|
344
|
-
/**
|
|
345
|
-
* 查询某个 topup 当前的活跃支付记录。
|
|
346
|
-
*/
|
|
347
|
-
async function findActivePaymentByTopup(payments, topupId) {
|
|
348
|
-
const rows = sortPayments(await payments.select({ topup_id: topupId }));
|
|
349
|
-
return rows.find((row) => row.status === "pending");
|
|
350
|
-
}
|
|
351
|
-
/**
|
|
352
|
-
* 更新支付记录。
|
|
353
|
-
*/
|
|
354
|
-
async function updatePayment(payments, paymentId, input) {
|
|
355
|
-
await payments.update({
|
|
356
|
-
where: { payment_id: paymentId },
|
|
357
|
-
values: {
|
|
358
|
-
status: input.status,
|
|
359
|
-
waffo_order_id: normalizeOptionalText(input.waffo_order_id),
|
|
360
|
-
waffo_payment_id: normalizeOptionalText(input.waffo_payment_id),
|
|
361
|
-
updated_at: new Date().toISOString(),
|
|
362
|
-
},
|
|
363
|
-
});
|
|
364
|
-
}
|
|
365
|
-
/**
|
|
366
|
-
* 更新 webhook 同步状态。
|
|
367
|
-
*/
|
|
368
|
-
async function updateEvent(events, eventId, syncStatus, syncError) {
|
|
369
|
-
await events.update({
|
|
370
|
-
where: { event_id: eventId },
|
|
371
|
-
values: {
|
|
372
|
-
sync_status: syncStatus,
|
|
373
|
-
sync_error: syncError.trim(),
|
|
374
|
-
},
|
|
375
|
-
});
|
|
376
|
-
}
|
|
377
|
-
/**
|
|
378
|
-
* 将支付记录裁剪为创建 Checkout 的返回结构。
|
|
379
|
-
*/
|
|
380
|
-
function toCheckoutResult(row) {
|
|
381
|
-
return {
|
|
382
|
-
payment_id: row.payment_id,
|
|
383
|
-
topup_id: row.topup_id,
|
|
384
|
-
waffo_session_id: row.waffo_session_id,
|
|
385
|
-
checkout_url: row.checkout_url,
|
|
386
|
-
status: row.status,
|
|
387
|
-
};
|
|
388
|
-
}
|
|
389
|
-
/**
|
|
390
|
-
* 统一排序支付记录。
|
|
391
|
-
*/
|
|
392
|
-
function sortPayments(rows) {
|
|
393
|
-
return [...rows].sort((left, right) => {
|
|
394
|
-
if (left.updated_at === right.updated_at)
|
|
395
|
-
return right.created_at.localeCompare(left.created_at);
|
|
396
|
-
return right.updated_at.localeCompare(left.updated_at);
|
|
397
|
-
});
|
|
398
|
-
}
|
|
399
|
-
/**
|
|
400
|
-
* 统一排序 webhook 事件记录。
|
|
401
|
-
*/
|
|
402
|
-
function sortEvents(rows) {
|
|
403
|
-
return [...rows].sort((left, right) => right.created_at.localeCompare(left.created_at));
|
|
404
|
-
}
|
|
405
|
-
/**
|
|
406
|
-
* 读取 webhook 事件 ID。
|
|
407
|
-
*/
|
|
408
|
-
function readEventId(event) {
|
|
409
|
-
return normalizeRequired(event.id || event.eventId || `evt_${randomId()}`, "waffo event id");
|
|
410
|
-
}
|
|
411
|
-
/**
|
|
412
|
-
* 读取 webhook 事件类型。
|
|
413
|
-
*/
|
|
414
|
-
function readEventType(event) {
|
|
415
|
-
return normalizeOptionalText(event.eventType) || "unknown";
|
|
416
|
-
}
|
|
417
|
-
/**
|
|
418
|
-
* 读取 webhook data。
|
|
419
|
-
*/
|
|
420
|
-
function readEventData(event) {
|
|
421
|
-
return readMetadata(event.data);
|
|
422
|
-
}
|
|
423
|
-
/**
|
|
424
|
-
* 规范化服务配置。
|
|
425
|
-
*/
|
|
426
|
-
function normalizeOptions(options) {
|
|
427
|
-
if (!options?.balance)
|
|
428
|
-
throw new TypeError("Waffo payment service requires a balance service instance");
|
|
429
|
-
return {
|
|
430
|
-
...options,
|
|
431
|
-
balance: options.balance,
|
|
432
|
-
environment: normalizeWaffoEnvironment(options.environment),
|
|
433
|
-
currency: normalizeCurrency(options.currency) || "usd",
|
|
434
|
-
};
|
|
435
|
-
}
|
|
436
|
-
/**
|
|
437
|
-
* 规范化币种。
|
|
438
|
-
*/
|
|
439
|
-
function normalizeCurrency(value) {
|
|
440
|
-
return normalizeOptionalText(value).toLowerCase();
|
|
441
|
-
}
|
|
442
|
-
/**
|
|
443
|
-
* 解析当前请求最终使用的币种。
|
|
444
|
-
*/
|
|
445
|
-
function resolveCurrency(options, ctx) {
|
|
446
|
-
return normalizeCurrency(ctx.env("WAFFO_CURRENCY")) || options.currency || "usd";
|
|
447
|
-
}
|
|
448
|
-
/**
|
|
449
|
-
* 解析当前请求最终使用的 Waffo 环境。
|
|
450
|
-
*/
|
|
451
|
-
function resolveEnvironment(options, ctx) {
|
|
452
|
-
return normalizeWaffoEnvironment(ctx.env("WAFFO_ENVIRONMENT") || options.environment);
|
|
453
|
-
}
|
|
454
|
-
/**
|
|
455
|
-
* 返回最小 HTML 页面,避免 Waffo 跳回后出现 404。
|
|
456
|
-
*/
|
|
457
|
-
function htmlResponse(html) {
|
|
458
|
-
return new Response(html, {
|
|
459
|
-
status: 200,
|
|
460
|
-
headers: { "content-type": "text/html; charset=utf-8" },
|
|
461
|
-
});
|
|
462
|
-
}
|
|
463
|
-
/**
|
|
464
|
-
* 渲染支付完成/取消结果页。
|
|
465
|
-
*/
|
|
466
|
-
function renderRedirectPage(input) {
|
|
467
|
-
const homeURL = escapeHTML(new URL("/", input.request.url).toString());
|
|
468
|
-
const title = escapeHTML(input.title);
|
|
469
|
-
const heading = escapeHTML(input.heading);
|
|
470
|
-
const description = escapeHTML(input.description);
|
|
471
|
-
return `<!doctype html>
|
|
472
|
-
<html lang="en">
|
|
473
|
-
<head>
|
|
474
|
-
<meta charset="utf-8" />
|
|
475
|
-
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
|
476
|
-
<title>${title}</title>
|
|
477
|
-
<style>
|
|
478
|
-
body { margin: 0; min-height: 100vh; display: grid; place-items: center; padding: 24px; background: #f5f7fb; color: #142033; font: 16px/1.5 -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif; }
|
|
479
|
-
main { width: min(100%, 560px); padding: 32px; border: 1px solid #d9e2f1; border-radius: 20px; background: #fff; box-shadow: 0 18px 60px rgba(16, 24, 40, 0.08); }
|
|
480
|
-
h1 { margin: 0 0 12px; font-size: 28px; line-height: 1.2; }
|
|
481
|
-
p { margin: 0; color: #5a6a85; }
|
|
482
|
-
a { display: inline-block; margin-top: 24px; color: #fff; background: #1f6feb; text-decoration: none; padding: 12px 16px; border-radius: 999px; font-weight: 600; }
|
|
483
|
-
</style>
|
|
484
|
-
</head>
|
|
485
|
-
<body>
|
|
486
|
-
<main>
|
|
487
|
-
<h1>${heading}</h1>
|
|
488
|
-
<p>${description}</p>
|
|
489
|
-
<a href="${homeURL}">Return to Downcity</a>
|
|
490
|
-
</main>
|
|
491
|
-
</body>
|
|
492
|
-
</html>`;
|
|
493
|
-
}
|
|
494
|
-
/**
|
|
495
|
-
* 最小 HTML 转义,避免文本直接拼进页面时破坏结构。
|
|
496
|
-
*/
|
|
497
|
-
function escapeHTML(value) {
|
|
498
|
-
return value
|
|
499
|
-
.replaceAll("&", "&")
|
|
500
|
-
.replaceAll("<", "<")
|
|
501
|
-
.replaceAll(">", ">")
|
|
502
|
-
.replaceAll('"', """)
|
|
503
|
-
.replaceAll("'", "'");
|
|
504
|
-
}
|
|
505
|
-
/**
|
|
506
|
-
* webhook-only client 兜底私钥。
|
|
507
|
-
*
|
|
508
|
-
* 关键说明(中文)
|
|
509
|
-
* - Waffo SDK 构造函数要求 privateKey
|
|
510
|
-
* - webhook 验签只需要 public key,这里只在未配置私钥且仅处理 webhook 时兜底
|
|
511
|
-
*/
|
|
512
|
-
function fallbackPrivateKey() {
|
|
513
|
-
return [
|
|
514
|
-
"-----BEGIN RSA PRIVATE KEY-----",
|
|
515
|
-
"MIIEpAIBAAKCAQEAtAqPA17F1sr9kylJy8LbcaHrim/UocR/ur3z5Vu7QQTUhuPO",
|
|
516
|
-
"pbsYnu1oFGwCsCjFhBBapI8/Huy9ARP3/Oxsp4kna9gEPLRSTMfUK5a0nPUnkHXv",
|
|
517
|
-
"DFgzIFYn1Yac/3FiA4zIA5BH+0ZUBu8cFZ1MvaPu7YFQvr165hOmwLnoJsypcY5V",
|
|
518
|
-
"Kjb8p+HjMXyiCy3gUId2DCJuUhjbtUo84gI3v4YAI6YD07pNUSm5wFDFKsYeymdV",
|
|
519
|
-
"QdtBhgPUx0RJDyhOKU1Vq8mge2b03ZiQK3O3gUmQgP0sAUpyyUrHaMjs/nAw9dqy",
|
|
520
|
-
"Wl0VyglAIcl79sRVUXTHgEHGf+j0pNcyVjIF2QIDAQABAoIBAAM1bPcSaVQ6qepF",
|
|
521
|
-
"ghsvjdmomRoOhCud5OjfGcmsqNmvzFnbFYO+oeGzOXejtSiOkXaZFAR6yRU0AupS",
|
|
522
|
-
"AMlxLT6PIzS41NqAHDdiGFXuiamCdQIOGASQTdj1sCAOFh43VxfZGnd1ytKfnj/B",
|
|
523
|
-
"Yy6/bu6yTT/OXjIIDnirQP2OUqTeWTHdf1xgQGkb+y20Oo3JgJ637j67HuLPrpzs",
|
|
524
|
-
"jIluqhRszKwVWhGlyTYJdK8nOv2sn+Kn8cEFybmbcytWk9Sxf128+IjTgsEFgEcy",
|
|
525
|
-
"RS6/UofjKfh9WY+4DK/L7mQgdYwawiRX4y4MkExCusmQxT72mDVGXnSbTYNp2qZl",
|
|
526
|
-
"WEgFeQECgYEA8cgKGrySiDFxJb900I5O/CL+1pIYXy6K4gDLk70luwjRSWU+ufZo",
|
|
527
|
-
"g/IRntgk0b0eC4vzP6539hQsh8rrO2swv0vBDG/cvyjP7ljHTx0pFtAjb/yJ9PXN",
|
|
528
|
-
"ca08G8qx6BX5mqdD46T56V4g5PtLT6cwn5Hth2/H+4MZ/5osP3CbU0UCgYEAvqEJ",
|
|
529
|
-
"OEOlKMRhxdfb7RnKMwiXUN2vZ0NuGgK0slqEC9FAv1E/XV8azcs40uINrDdieRmr",
|
|
530
|
-
"Oi+LBXC08FHiAKZOVuxg1DzKx8gDc/R6YGT5sKVhVhKgWsF9ysmCyyqdqnuvFMAd",
|
|
531
|
-
"7PgS4Nf01rO9jo+cqKBHTzFny0TWZTTAR6NzZ4UCgYEAzqcKs+V/XPbdXcUxg9xO",
|
|
532
|
-
"eEU1CZLfT+NJA3hoiAMAD8eukgv+PBX3KOeq1diqR7ZbysS4iTKHCAYgNYRj4Gpy",
|
|
533
|
-
"xN5rx0SJKb4pUvAAkoc7CmumDl6MT5oUGdhWau6pdtPpfpz+csEcdbFlbjG3IgKl",
|
|
534
|
-
"lY21tq/8/uUEQKq2rRaDO/0CgYAUgC0FqACzCauaI0S7kvJz2pCrWavrZw0ILxJP",
|
|
535
|
-
"u/xHaRGVgZ9W40t2pkxOIZFm2+3zKBeKAmLpCt3qmmO7vibeoj0nlgIYyiHU7o3a",
|
|
536
|
-
"oAFaRe7Z2tbz66sji9hNESAznWmOybpuKZ+eHptuG5ZfJoKqf9IrahzHd3e3Gp0z",
|
|
537
|
-
"FxjqIQKBgQDbHuXgZL8A7pQe+YFUVbXYjhzb+sTlVQD7C4KF0sdiKNKXcXhvcCxL",
|
|
538
|
-
"AfJu59vnIlhD4MUcxt5lWDBLX08dmcJOX2AryDMmNVC7knNu92IehJeboSaM1+t3",
|
|
539
|
-
"1V/8pTMTtzg5ANHzZICj6vn46UXCL78XUC3sqZdAm/+9kS+oAnWaIw==",
|
|
540
|
-
"-----END RSA PRIVATE KEY-----",
|
|
541
|
-
].join("\n");
|
|
542
|
-
}
|
|
543
|
-
/**
|
|
544
|
-
* 生成短随机 ID。
|
|
545
|
-
*/
|
|
546
|
-
function randomId() {
|
|
547
|
-
return crypto.randomUUID?.().replaceAll("-", "").slice(0, 16) || Math.random().toString(36).slice(2, 18);
|
|
548
|
-
}
|
|
549
|
-
//# sourceMappingURL=index.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/payment-waffo/index.ts"],"names":[],"mappings":"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"}
|