@downcity/services 0.1.67 → 0.1.71

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.
Files changed (79) hide show
  1. package/bin/accounts/index.d.ts +1 -5
  2. package/bin/accounts/index.d.ts.map +1 -1
  3. package/bin/accounts/index.js +1 -4
  4. package/bin/accounts/index.js.map +1 -1
  5. package/bin/balance/index.d.ts +3 -3
  6. package/bin/balance/index.d.ts.map +1 -1
  7. package/bin/balance/index.js +2 -2
  8. package/bin/balance/index.js.map +1 -1
  9. package/bin/balance/routes.d.ts.map +1 -1
  10. package/bin/balance/routes.js +36 -0
  11. package/bin/balance/routes.js.map +1 -1
  12. package/bin/balance/schema.d.ts +161 -0
  13. package/bin/balance/schema.d.ts.map +1 -1
  14. package/bin/balance/schema.js +38 -0
  15. package/bin/balance/schema.js.map +1 -1
  16. package/bin/balance/service.d.ts +171 -5
  17. package/bin/balance/service.d.ts.map +1 -1
  18. package/bin/balance/service.js +77 -11
  19. package/bin/balance/service.js.map +1 -1
  20. package/bin/balance/types.d.ts +81 -1
  21. package/bin/balance/types.d.ts.map +1 -1
  22. package/bin/balance/utils.d.ts +5 -1
  23. package/bin/balance/utils.d.ts.map +1 -1
  24. package/bin/balance/utils.js +17 -0
  25. package/bin/balance/utils.js.map +1 -1
  26. package/bin/index.d.ts +8 -10
  27. package/bin/index.d.ts.map +1 -1
  28. package/bin/index.js +6 -7
  29. package/bin/index.js.map +1 -1
  30. package/bin/payment/helpers.d.ts +68 -0
  31. package/bin/payment/helpers.d.ts.map +1 -0
  32. package/bin/payment/helpers.js +148 -0
  33. package/bin/payment/helpers.js.map +1 -0
  34. package/bin/payment/index.d.ts +10 -28
  35. package/bin/payment/index.d.ts.map +1 -1
  36. package/bin/payment/index.js +9 -890
  37. package/bin/payment/index.js.map +1 -1
  38. package/bin/payment/providers.d.ts +25 -0
  39. package/bin/payment/providers.d.ts.map +1 -0
  40. package/bin/payment/providers.js +415 -0
  41. package/bin/payment/providers.js.map +1 -0
  42. package/bin/payment/routes.d.ts +29 -0
  43. package/bin/payment/routes.d.ts.map +1 -0
  44. package/bin/payment/routes.js +394 -0
  45. package/bin/payment/routes.js.map +1 -0
  46. package/bin/{billing → payment}/service.d.ts +99 -278
  47. package/bin/payment/service.d.ts.map +1 -0
  48. package/bin/payment/service.js +72 -0
  49. package/bin/payment/service.js.map +1 -0
  50. package/bin/payment/types.d.ts +11 -18
  51. package/bin/payment/types.d.ts.map +1 -1
  52. package/bin/usage/index.d.ts +3 -174
  53. package/bin/usage/index.d.ts.map +1 -1
  54. package/bin/usage/index.js +2 -117
  55. package/bin/usage/index.js.map +1 -1
  56. package/bin/usage/service.d.ts +353 -0
  57. package/bin/usage/service.d.ts.map +1 -0
  58. package/bin/usage/service.js +140 -0
  59. package/bin/usage/service.js.map +1 -0
  60. package/package.json +2 -2
  61. package/bin/billing/index.d.ts +0 -7
  62. package/bin/billing/index.d.ts.map +0 -1
  63. package/bin/billing/index.js +0 -6
  64. package/bin/billing/index.js.map +0 -1
  65. package/bin/billing/routes.d.ts +0 -14
  66. package/bin/billing/routes.d.ts.map +0 -1
  67. package/bin/billing/routes.js +0 -61
  68. package/bin/billing/routes.js.map +0 -1
  69. package/bin/billing/schema.d.ts +0 -582
  70. package/bin/billing/schema.d.ts.map +0 -1
  71. package/bin/billing/schema.js +0 -81
  72. package/bin/billing/schema.js.map +0 -1
  73. package/bin/billing/service.d.ts.map +0 -1
  74. package/bin/billing/service.js +0 -492
  75. package/bin/billing/service.js.map +0 -1
  76. package/bin/billing/types.d.ts +0 -226
  77. package/bin/billing/types.d.ts.map +0 -1
  78. package/bin/billing/types.js +0 -10
  79. package/bin/billing/types.js.map +0 -1
@@ -1,28 +1,28 @@
1
1
  /**
2
- * Downcity 官方 Billing 服务实现。
2
+ * Downcity 官方 Payment 统一服务。
3
3
  *
4
- * 设计边界:
5
- * - usage 负责记录事实,billing 负责把事实换算成 charge
6
- * - balance 负责真正的钱包扣减与流水
7
- * - pricing rule 使用 microcredits,1 credit = 1 USD = 1_000_000 microcredits
4
+ * 关键点(中文)
5
+ * - payment 是唯一支付服务,Stripe / Creem / Dodo / Waffo 都只是 provider。
6
+ * - 统一负责 checkout、本地支付记录、webhook 幂等、状态同步和 balance 入账。
7
+ * - 所有 provider 共用 `/v1/payment/*` 路由和统一 payments/events 表。
8
8
  */
9
- import { InstallableService, type Context, type ServiceInstallContext } from "@downcity/city";
10
- import type { BillingCharge, BillingChargeInput, BillingChargeQuery, BillingPricingRule, BillingPricingRuleInput, BillingPricingRuleQuery, BillingServiceOptions } from "./types.js";
9
+ import { InstallableService, type ServiceInstallContext } from "@downcity/city";
10
+ import type { PaymentProvider, PaymentServiceOptions } from "./types.js";
11
11
  /**
12
- * Billing 服务实例。
12
+ * 统一 Payment 服务。
13
13
  */
14
- export declare class BillingService extends InstallableService {
15
- readonly id = "billing";
16
- readonly name = "Billing";
17
- readonly version = "0.1.0";
14
+ export declare class PaymentService extends InstallableService {
15
+ readonly id = "payment";
16
+ readonly name = "Payment";
17
+ readonly version = "0.2.0";
18
18
  readonly schema: {
19
- pricing_rules: import("drizzle-orm/sqlite-core").SQLiteTableWithColumns<{
20
- name: "service_billing_pricing_rules";
19
+ payments: import("drizzle-orm/sqlite-core").SQLiteTableWithColumns<{
20
+ name: "service_payment_payments";
21
21
  schema: undefined;
22
22
  columns: {
23
- rule_id: import("drizzle-orm/sqlite-core").SQLiteColumn<{
24
- name: "rule_id";
25
- tableName: "service_billing_pricing_rules";
23
+ payment_id: import("drizzle-orm/sqlite-core").SQLiteColumn<{
24
+ name: "payment_id";
25
+ tableName: "service_payment_payments";
26
26
  dataType: "string";
27
27
  columnType: "SQLiteText";
28
28
  data: string;
@@ -39,9 +39,9 @@ export declare class BillingService extends InstallableService {
39
39
  }, {}, {
40
40
  length: number | undefined;
41
41
  }>;
42
- service_id: import("drizzle-orm/sqlite-core").SQLiteColumn<{
43
- name: "service_id";
44
- tableName: "service_billing_pricing_rules";
42
+ provider: import("drizzle-orm/sqlite-core").SQLiteColumn<{
43
+ name: "provider";
44
+ tableName: "service_payment_payments";
45
45
  dataType: "string";
46
46
  columnType: "SQLiteText";
47
47
  data: string;
@@ -58,9 +58,9 @@ export declare class BillingService extends InstallableService {
58
58
  }, {}, {
59
59
  length: number | undefined;
60
60
  }>;
61
- action_id: import("drizzle-orm/sqlite-core").SQLiteColumn<{
62
- name: "action_id";
63
- tableName: "service_billing_pricing_rules";
61
+ topup_id: import("drizzle-orm/sqlite-core").SQLiteColumn<{
62
+ name: "topup_id";
63
+ tableName: "service_payment_payments";
64
64
  dataType: "string";
65
65
  columnType: "SQLiteText";
66
66
  data: string;
@@ -77,9 +77,9 @@ export declare class BillingService extends InstallableService {
77
77
  }, {}, {
78
78
  length: number | undefined;
79
79
  }>;
80
- model_id: import("drizzle-orm/sqlite-core").SQLiteColumn<{
81
- name: "model_id";
82
- tableName: "service_billing_pricing_rules";
80
+ user_id: import("drizzle-orm/sqlite-core").SQLiteColumn<{
81
+ name: "user_id";
82
+ tableName: "service_payment_payments";
83
83
  dataType: "string";
84
84
  columnType: "SQLiteText";
85
85
  data: string;
@@ -96,9 +96,9 @@ export declare class BillingService extends InstallableService {
96
96
  }, {}, {
97
97
  length: number | undefined;
98
98
  }>;
99
- provider_id: import("drizzle-orm/sqlite-core").SQLiteColumn<{
100
- name: "provider_id";
101
- tableName: "service_billing_pricing_rules";
99
+ provider_session_id: import("drizzle-orm/sqlite-core").SQLiteColumn<{
100
+ name: "provider_session_id";
101
+ tableName: "service_payment_payments";
102
102
  dataType: "string";
103
103
  columnType: "SQLiteText";
104
104
  data: string;
@@ -115,145 +115,9 @@ export declare class BillingService extends InstallableService {
115
115
  }, {}, {
116
116
  length: number | undefined;
117
117
  }>;
118
- request_microcredits: import("drizzle-orm/sqlite-core").SQLiteColumn<{
119
- name: "request_microcredits";
120
- tableName: "service_billing_pricing_rules";
121
- dataType: "number";
122
- columnType: "SQLiteInteger";
123
- data: number;
124
- driverParam: number;
125
- notNull: true;
126
- hasDefault: false;
127
- isPrimaryKey: false;
128
- isAutoincrement: false;
129
- hasRuntimeDefault: false;
130
- enumValues: undefined;
131
- baseColumn: never;
132
- identity: undefined;
133
- generated: undefined;
134
- }, {}, {}>;
135
- input_token_microcredits: import("drizzle-orm/sqlite-core").SQLiteColumn<{
136
- name: "input_token_microcredits";
137
- tableName: "service_billing_pricing_rules";
138
- dataType: "number";
139
- columnType: "SQLiteInteger";
140
- data: number;
141
- driverParam: number;
142
- notNull: true;
143
- hasDefault: false;
144
- isPrimaryKey: false;
145
- isAutoincrement: false;
146
- hasRuntimeDefault: false;
147
- enumValues: undefined;
148
- baseColumn: never;
149
- identity: undefined;
150
- generated: undefined;
151
- }, {}, {}>;
152
- input_mtoken_microcredits: import("drizzle-orm/sqlite-core").SQLiteColumn<{
153
- name: "input_mtoken_microcredits";
154
- tableName: "service_billing_pricing_rules";
155
- dataType: "number";
156
- columnType: "SQLiteInteger";
157
- data: number;
158
- driverParam: number;
159
- notNull: true;
160
- hasDefault: false;
161
- isPrimaryKey: false;
162
- isAutoincrement: false;
163
- hasRuntimeDefault: false;
164
- enumValues: undefined;
165
- baseColumn: never;
166
- identity: undefined;
167
- generated: undefined;
168
- }, {}, {}>;
169
- output_token_microcredits: import("drizzle-orm/sqlite-core").SQLiteColumn<{
170
- name: "output_token_microcredits";
171
- tableName: "service_billing_pricing_rules";
172
- dataType: "number";
173
- columnType: "SQLiteInteger";
174
- data: number;
175
- driverParam: number;
176
- notNull: true;
177
- hasDefault: false;
178
- isPrimaryKey: false;
179
- isAutoincrement: false;
180
- hasRuntimeDefault: false;
181
- enumValues: undefined;
182
- baseColumn: never;
183
- identity: undefined;
184
- generated: undefined;
185
- }, {}, {}>;
186
- output_mtoken_microcredits: import("drizzle-orm/sqlite-core").SQLiteColumn<{
187
- name: "output_mtoken_microcredits";
188
- tableName: "service_billing_pricing_rules";
189
- dataType: "number";
190
- columnType: "SQLiteInteger";
191
- data: number;
192
- driverParam: number;
193
- notNull: true;
194
- hasDefault: false;
195
- isPrimaryKey: false;
196
- isAutoincrement: false;
197
- hasRuntimeDefault: false;
198
- enumValues: undefined;
199
- baseColumn: never;
200
- identity: undefined;
201
- generated: undefined;
202
- }, {}, {}>;
203
- cached_token_microcredits: import("drizzle-orm/sqlite-core").SQLiteColumn<{
204
- name: "cached_token_microcredits";
205
- tableName: "service_billing_pricing_rules";
206
- dataType: "number";
207
- columnType: "SQLiteInteger";
208
- data: number;
209
- driverParam: number;
210
- notNull: true;
211
- hasDefault: false;
212
- isPrimaryKey: false;
213
- isAutoincrement: false;
214
- hasRuntimeDefault: false;
215
- enumValues: undefined;
216
- baseColumn: never;
217
- identity: undefined;
218
- generated: undefined;
219
- }, {}, {}>;
220
- cached_mtoken_microcredits: import("drizzle-orm/sqlite-core").SQLiteColumn<{
221
- name: "cached_mtoken_microcredits";
222
- tableName: "service_billing_pricing_rules";
223
- dataType: "number";
224
- columnType: "SQLiteInteger";
225
- data: number;
226
- driverParam: number;
227
- notNull: true;
228
- hasDefault: false;
229
- isPrimaryKey: false;
230
- isAutoincrement: false;
231
- hasRuntimeDefault: false;
232
- enumValues: undefined;
233
- baseColumn: never;
234
- identity: undefined;
235
- generated: undefined;
236
- }, {}, {}>;
237
- image_microcredits: import("drizzle-orm/sqlite-core").SQLiteColumn<{
238
- name: "image_microcredits";
239
- tableName: "service_billing_pricing_rules";
240
- dataType: "number";
241
- columnType: "SQLiteInteger";
242
- data: number;
243
- driverParam: number;
244
- notNull: true;
245
- hasDefault: false;
246
- isPrimaryKey: false;
247
- isAutoincrement: false;
248
- hasRuntimeDefault: false;
249
- enumValues: undefined;
250
- baseColumn: never;
251
- identity: undefined;
252
- generated: undefined;
253
- }, {}, {}>;
254
- status: import("drizzle-orm/sqlite-core").SQLiteColumn<{
255
- name: "status";
256
- tableName: "service_billing_pricing_rules";
118
+ provider_payment_id: import("drizzle-orm/sqlite-core").SQLiteColumn<{
119
+ name: "provider_payment_id";
120
+ tableName: "service_payment_payments";
257
121
  dataType: "string";
258
122
  columnType: "SQLiteText";
259
123
  data: string;
@@ -270,9 +134,9 @@ export declare class BillingService extends InstallableService {
270
134
  }, {}, {
271
135
  length: number | undefined;
272
136
  }>;
273
- note: import("drizzle-orm/sqlite-core").SQLiteColumn<{
274
- name: "note";
275
- tableName: "service_billing_pricing_rules";
137
+ provider_order_id: import("drizzle-orm/sqlite-core").SQLiteColumn<{
138
+ name: "provider_order_id";
139
+ tableName: "service_payment_payments";
276
140
  dataType: "string";
277
141
  columnType: "SQLiteText";
278
142
  data: string;
@@ -289,28 +153,26 @@ export declare class BillingService extends InstallableService {
289
153
  }, {}, {
290
154
  length: number | undefined;
291
155
  }>;
292
- created_at: import("drizzle-orm/sqlite-core").SQLiteColumn<{
293
- name: "created_at";
294
- tableName: "service_billing_pricing_rules";
295
- dataType: "string";
296
- columnType: "SQLiteText";
297
- data: string;
298
- driverParam: string;
156
+ amount: import("drizzle-orm/sqlite-core").SQLiteColumn<{
157
+ name: "amount";
158
+ tableName: "service_payment_payments";
159
+ dataType: "number";
160
+ columnType: "SQLiteInteger";
161
+ data: number;
162
+ driverParam: number;
299
163
  notNull: true;
300
164
  hasDefault: false;
301
165
  isPrimaryKey: false;
302
166
  isAutoincrement: false;
303
167
  hasRuntimeDefault: false;
304
- enumValues: [string, ...string[]];
168
+ enumValues: undefined;
305
169
  baseColumn: never;
306
170
  identity: undefined;
307
171
  generated: undefined;
308
- }, {}, {
309
- length: number | undefined;
310
- }>;
311
- updated_at: import("drizzle-orm/sqlite-core").SQLiteColumn<{
312
- name: "updated_at";
313
- tableName: "service_billing_pricing_rules";
172
+ }, {}, {}>;
173
+ currency: import("drizzle-orm/sqlite-core").SQLiteColumn<{
174
+ name: "currency";
175
+ tableName: "service_payment_payments";
314
176
  dataType: "string";
315
177
  columnType: "SQLiteText";
316
178
  data: string;
@@ -327,23 +189,16 @@ export declare class BillingService extends InstallableService {
327
189
  }, {}, {
328
190
  length: number | undefined;
329
191
  }>;
330
- };
331
- dialect: "sqlite";
332
- }>;
333
- charges: import("drizzle-orm/sqlite-core").SQLiteTableWithColumns<{
334
- name: "service_billing_charges";
335
- schema: undefined;
336
- columns: {
337
- charge_id: import("drizzle-orm/sqlite-core").SQLiteColumn<{
338
- name: "charge_id";
339
- tableName: "service_billing_charges";
192
+ status: import("drizzle-orm/sqlite-core").SQLiteColumn<{
193
+ name: "status";
194
+ tableName: "service_payment_payments";
340
195
  dataType: "string";
341
196
  columnType: "SQLiteText";
342
197
  data: string;
343
198
  driverParam: string;
344
199
  notNull: true;
345
200
  hasDefault: false;
346
- isPrimaryKey: true;
201
+ isPrimaryKey: false;
347
202
  isAutoincrement: false;
348
203
  hasRuntimeDefault: false;
349
204
  enumValues: [string, ...string[]];
@@ -353,9 +208,9 @@ export declare class BillingService extends InstallableService {
353
208
  }, {}, {
354
209
  length: number | undefined;
355
210
  }>;
356
- user_id: import("drizzle-orm/sqlite-core").SQLiteColumn<{
357
- name: "user_id";
358
- tableName: "service_billing_charges";
211
+ checkout_url: import("drizzle-orm/sqlite-core").SQLiteColumn<{
212
+ name: "checkout_url";
213
+ tableName: "service_payment_payments";
359
214
  dataType: "string";
360
215
  columnType: "SQLiteText";
361
216
  data: string;
@@ -372,9 +227,9 @@ export declare class BillingService extends InstallableService {
372
227
  }, {}, {
373
228
  length: number | undefined;
374
229
  }>;
375
- town_id: import("drizzle-orm/sqlite-core").SQLiteColumn<{
376
- name: "town_id";
377
- tableName: "service_billing_charges";
230
+ metadata_json: import("drizzle-orm/sqlite-core").SQLiteColumn<{
231
+ name: "metadata_json";
232
+ tableName: "service_payment_payments";
378
233
  dataType: "string";
379
234
  columnType: "SQLiteText";
380
235
  data: string;
@@ -391,9 +246,9 @@ export declare class BillingService extends InstallableService {
391
246
  }, {}, {
392
247
  length: number | undefined;
393
248
  }>;
394
- service_id: import("drizzle-orm/sqlite-core").SQLiteColumn<{
395
- name: "service_id";
396
- tableName: "service_billing_charges";
249
+ created_at: import("drizzle-orm/sqlite-core").SQLiteColumn<{
250
+ name: "created_at";
251
+ tableName: "service_payment_payments";
397
252
  dataType: "string";
398
253
  columnType: "SQLiteText";
399
254
  data: string;
@@ -410,9 +265,9 @@ export declare class BillingService extends InstallableService {
410
265
  }, {}, {
411
266
  length: number | undefined;
412
267
  }>;
413
- action_id: import("drizzle-orm/sqlite-core").SQLiteColumn<{
414
- name: "action_id";
415
- tableName: "service_billing_charges";
268
+ updated_at: import("drizzle-orm/sqlite-core").SQLiteColumn<{
269
+ name: "updated_at";
270
+ tableName: "service_payment_payments";
416
271
  dataType: "string";
417
272
  columnType: "SQLiteText";
418
273
  data: string;
@@ -429,16 +284,23 @@ export declare class BillingService extends InstallableService {
429
284
  }, {}, {
430
285
  length: number | undefined;
431
286
  }>;
432
- model_id: import("drizzle-orm/sqlite-core").SQLiteColumn<{
433
- name: "model_id";
434
- tableName: "service_billing_charges";
287
+ };
288
+ dialect: "sqlite";
289
+ }>;
290
+ events: import("drizzle-orm/sqlite-core").SQLiteTableWithColumns<{
291
+ name: "service_payment_events";
292
+ schema: undefined;
293
+ columns: {
294
+ event_id: import("drizzle-orm/sqlite-core").SQLiteColumn<{
295
+ name: "event_id";
296
+ tableName: "service_payment_events";
435
297
  dataType: "string";
436
298
  columnType: "SQLiteText";
437
299
  data: string;
438
300
  driverParam: string;
439
301
  notNull: true;
440
302
  hasDefault: false;
441
- isPrimaryKey: false;
303
+ isPrimaryKey: true;
442
304
  isAutoincrement: false;
443
305
  hasRuntimeDefault: false;
444
306
  enumValues: [string, ...string[]];
@@ -448,9 +310,9 @@ export declare class BillingService extends InstallableService {
448
310
  }, {}, {
449
311
  length: number | undefined;
450
312
  }>;
451
- provider_id: import("drizzle-orm/sqlite-core").SQLiteColumn<{
452
- name: "provider_id";
453
- tableName: "service_billing_charges";
313
+ provider: import("drizzle-orm/sqlite-core").SQLiteColumn<{
314
+ name: "provider";
315
+ tableName: "service_payment_events";
454
316
  dataType: "string";
455
317
  columnType: "SQLiteText";
456
318
  data: string;
@@ -467,9 +329,9 @@ export declare class BillingService extends InstallableService {
467
329
  }, {}, {
468
330
  length: number | undefined;
469
331
  }>;
470
- rule_id: import("drizzle-orm/sqlite-core").SQLiteColumn<{
471
- name: "rule_id";
472
- tableName: "service_billing_charges";
332
+ type: import("drizzle-orm/sqlite-core").SQLiteColumn<{
333
+ name: "type";
334
+ tableName: "service_payment_events";
473
335
  dataType: "string";
474
336
  columnType: "SQLiteText";
475
337
  data: string;
@@ -486,26 +348,9 @@ export declare class BillingService extends InstallableService {
486
348
  }, {}, {
487
349
  length: number | undefined;
488
350
  }>;
489
- amount_microcredits: import("drizzle-orm/sqlite-core").SQLiteColumn<{
490
- name: "amount_microcredits";
491
- tableName: "service_billing_charges";
492
- dataType: "number";
493
- columnType: "SQLiteInteger";
494
- data: number;
495
- driverParam: number;
496
- notNull: true;
497
- hasDefault: false;
498
- isPrimaryKey: false;
499
- isAutoincrement: false;
500
- hasRuntimeDefault: false;
501
- enumValues: undefined;
502
- baseColumn: never;
503
- identity: undefined;
504
- generated: undefined;
505
- }, {}, {}>;
506
- status: import("drizzle-orm/sqlite-core").SQLiteColumn<{
507
- name: "status";
508
- tableName: "service_billing_charges";
351
+ payload_json: import("drizzle-orm/sqlite-core").SQLiteColumn<{
352
+ name: "payload_json";
353
+ tableName: "service_payment_events";
509
354
  dataType: "string";
510
355
  columnType: "SQLiteText";
511
356
  data: string;
@@ -522,9 +367,9 @@ export declare class BillingService extends InstallableService {
522
367
  }, {}, {
523
368
  length: number | undefined;
524
369
  }>;
525
- note: import("drizzle-orm/sqlite-core").SQLiteColumn<{
526
- name: "note";
527
- tableName: "service_billing_charges";
370
+ sync_status: import("drizzle-orm/sqlite-core").SQLiteColumn<{
371
+ name: "sync_status";
372
+ tableName: "service_payment_events";
528
373
  dataType: "string";
529
374
  columnType: "SQLiteText";
530
375
  data: string;
@@ -541,9 +386,9 @@ export declare class BillingService extends InstallableService {
541
386
  }, {}, {
542
387
  length: number | undefined;
543
388
  }>;
544
- metadata_json: import("drizzle-orm/sqlite-core").SQLiteColumn<{
545
- name: "metadata_json";
546
- tableName: "service_billing_charges";
389
+ sync_error: import("drizzle-orm/sqlite-core").SQLiteColumn<{
390
+ name: "sync_error";
391
+ tableName: "service_payment_events";
547
392
  dataType: "string";
548
393
  columnType: "SQLiteText";
549
394
  data: string;
@@ -562,7 +407,7 @@ export declare class BillingService extends InstallableService {
562
407
  }>;
563
408
  created_at: import("drizzle-orm/sqlite-core").SQLiteColumn<{
564
409
  name: "created_at";
565
- tableName: "service_billing_charges";
410
+ tableName: "service_payment_events";
566
411
  dataType: "string";
567
412
  columnType: "SQLiteText";
568
413
  data: string;
@@ -583,45 +428,21 @@ export declare class BillingService extends InstallableService {
583
428
  dialect: "sqlite";
584
429
  }>;
585
430
  };
586
- private readonly balance;
587
- private readonly initialRules;
588
- private readonly requireBeforeCall;
589
- constructor(options: BillingServiceOptions);
590
- _onInit(): Promise<void>;
431
+ private readonly options;
432
+ private readonly providers;
433
+ constructor(options: PaymentServiceOptions);
591
434
  install(ctx: ServiceInstallContext): void;
592
435
  /**
593
- * 新增或更新 pricing rule。
436
+ * 读取充值单。
594
437
  */
595
- upsertPricingRule(input: BillingPricingRuleInput): Promise<BillingPricingRule>;
438
+ readTopup(topup_id: string): Promise<import("./types.js").PaymentTopupRecord>;
596
439
  /**
597
- * 列出 pricing rules。
440
+ * 完成充值并入账。
598
441
  */
599
- listPricingRules(query?: BillingPricingRuleQuery): Promise<BillingPricingRule[]>;
442
+ finishTopup(topup_id: string, extra?: Record<string, unknown>): Promise<import("./types.js").PaymentTopupRecord>;
600
443
  /**
601
- * 列出 charge。
444
+ * 获取已挂载的 provider 列表。
602
445
  */
603
- listCharges(query?: BillingChargeQuery): Promise<BillingCharge[]>;
604
- /**
605
- * 对当前 service 调用执行结算。
606
- */
607
- settle(ctx: Context): Promise<BillingCharge | undefined>;
608
- /**
609
- * 显式扣费。
610
- *
611
- * 关键说明(中文)
612
- * - AI Provider 可以自行完成 usage 与价格换算,然后通过 AIService 调用这里。
613
- * - Billing 只负责扣余额和记录账单,不理解 provider 内部 usage 结构。
614
- */
615
- charge(input: BillingChargeInput): Promise<BillingCharge | undefined>;
616
- private createCharge;
617
- private resolvePricingRule;
618
- private readPricingRule;
619
- private readPricingRuleRequired;
620
- private ensurePricingRuleColumns;
621
- private resolveRaw;
446
+ getProviders(): PaymentProvider[];
622
447
  }
623
- /**
624
- * 创建 Billing 服务实例。
625
- */
626
- export declare function billingService(options: BillingServiceOptions): BillingService;
627
448
  //# sourceMappingURL=service.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"service.d.ts","sourceRoot":"","sources":["../../src/payment/service.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAE,kBAAkB,EAAuB,KAAK,qBAAqB,EAAE,MAAM,gBAAgB,CAAC;AAIrG,OAAO,KAAK,EAAE,eAAe,EAAE,qBAAqB,EAAE,MAAM,YAAY,CAAC;AAazE;;GAEG;AACH,qBAAa,cAAe,SAAQ,kBAAkB;IACpD,QAAQ,CAAC,EAAE,aAAa;IACxB,QAAQ,CAAC,IAAI,aAAa;IAC1B,QAAQ,CAAC,OAAO,WAAW;IAC3B,QAAQ,CAAC,MAAM;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;MAGb;IAEF,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAwB;IAChD,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAoB;gBAElC,OAAO,EAAE,qBAAqB;IAe1C,OAAO,CAAC,GAAG,EAAE,qBAAqB,GAAG,IAAI;IAIzC;;OAEG;IACH,SAAS,CAAC,QAAQ,EAAE,MAAM;IAI1B;;OAEG;IACH,WAAW,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;IAI7D;;OAEG;IACH,YAAY,IAAI,eAAe,EAAE;CAGlC"}
@@ -0,0 +1,72 @@
1
+ /**
2
+ * Downcity 官方 Payment 统一服务。
3
+ *
4
+ * 关键点(中文)
5
+ * - payment 是唯一支付服务,Stripe / Creem / Dodo / Waffo 都只是 provider。
6
+ * - 统一负责 checkout、本地支付记录、webhook 幂等、状态同步和 balance 入账。
7
+ * - 所有 provider 共用 `/v1/payment/*` 路由和统一 payments/events 表。
8
+ */
9
+ import { InstallableService } from "@downcity/city";
10
+ import { paymentEvents, paymentPayments } from "./schema.js";
11
+ import { mergeEnvRequirements, normalizeProviders } from "./helpers.js";
12
+ import { installPaymentRoutes } from "./routes.js";
13
+ /**
14
+ * Payment 服务自身 env。
15
+ */
16
+ const paymentEnv = [
17
+ {
18
+ key: "DOWNCITY_CITY_BASE_URL",
19
+ description: "City 对外访问地址;用于自动生成统一 payment 结果页地址",
20
+ required: false,
21
+ },
22
+ ];
23
+ /**
24
+ * 统一 Payment 服务。
25
+ */
26
+ export class PaymentService extends InstallableService {
27
+ id = "payment";
28
+ name = "Payment";
29
+ version = "0.2.0";
30
+ schema = {
31
+ payments: paymentPayments,
32
+ events: paymentEvents,
33
+ };
34
+ options;
35
+ providers;
36
+ constructor(options) {
37
+ const providers = normalizeProviders(options.providers);
38
+ super(mergeEnvRequirements([
39
+ ...paymentEnv,
40
+ ...providers.flatMap((provider) => provider.env),
41
+ ]));
42
+ this.options = options;
43
+ this.providers = providers;
44
+ this.instruction = [
45
+ "统一支付服务。Stripe、Creem、Dodo、Waffo 都作为 provider 挂载。",
46
+ "前端先读取 /methods,再通过 /checkout/create 创建对应 provider 的 checkout。",
47
+ "所有 provider 共用 /webhook、/payments、/events 和统一 payment 表。",
48
+ ].join("\n");
49
+ }
50
+ install(ctx) {
51
+ installPaymentRoutes(this, ctx);
52
+ }
53
+ /**
54
+ * 读取充值单。
55
+ */
56
+ readTopup(topup_id) {
57
+ return this.options.readTopup(topup_id);
58
+ }
59
+ /**
60
+ * 完成充值并入账。
61
+ */
62
+ finishTopup(topup_id, extra) {
63
+ return this.options.finishTopup(topup_id, extra);
64
+ }
65
+ /**
66
+ * 获取已挂载的 provider 列表。
67
+ */
68
+ getProviders() {
69
+ return this.providers;
70
+ }
71
+ }
72
+ //# sourceMappingURL=service.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"service.js","sourceRoot":"","sources":["../../src/payment/service.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAE,kBAAkB,EAAmD,MAAM,gBAAgB,CAAC;AACrG,OAAO,EAAE,aAAa,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAC7D,OAAO,EAAE,oBAAoB,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC;AACxE,OAAO,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC;AAGnD;;GAEG;AACH,MAAM,UAAU,GAAqB;IACnC;QACE,GAAG,EAAE,wBAAwB;QAC7B,WAAW,EAAE,oCAAoC;QACjD,QAAQ,EAAE,KAAK;KAChB;CACF,CAAC;AAEF;;GAEG;AACH,MAAM,OAAO,cAAe,SAAQ,kBAAkB;IAC3C,EAAE,GAAG,SAAS,CAAC;IACf,IAAI,GAAG,SAAS,CAAC;IACjB,OAAO,GAAG,OAAO,CAAC;IAClB,MAAM,GAAG;QAChB,QAAQ,EAAE,eAAe;QACzB,MAAM,EAAE,aAAa;KACtB,CAAC;IAEe,OAAO,CAAwB;IAC/B,SAAS,CAAoB;IAE9C,YAAY,OAA8B;QACxC,MAAM,SAAS,GAAG,kBAAkB,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;QACxD,KAAK,CAAC,oBAAoB,CAAC;YACzB,GAAG,UAAU;YACb,GAAG,SAAS,CAAC,OAAO,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,QAAQ,CAAC,GAAG,CAAC;SACjD,CAAC,CAAC,CAAC;QACJ,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;QACvB,IAAI,CAAC,SAAS,GAAG,SAAS,CAAC;QAC3B,IAAI,CAAC,WAAW,GAAG;YACjB,iDAAiD;YACjD,+DAA+D;YAC/D,0DAA0D;SAC3D,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACf,CAAC;IAED,OAAO,CAAC,GAA0B;QAChC,oBAAoB,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;IAClC,CAAC;IAED;;OAEG;IACH,SAAS,CAAC,QAAgB;QACxB,OAAO,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC;IAC1C,CAAC;IAED;;OAEG;IACH,WAAW,CAAC,QAAgB,EAAE,KAA+B;QAC3D,OAAO,IAAI,CAAC,OAAO,CAAC,WAAW,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAC;IACnD,CAAC;IAED;;OAEG;IACH,YAAY;QACV,OAAO,IAAI,CAAC,SAAS,CAAC;IACxB,CAAC;CACF"}