@adonis-agora/payments 0.2.0 → 0.4.0
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/CHANGELOG.md +2375 -0
- package/dist/assets/spa/assets/index-B7rU8eIL.css +2 -0
- package/dist/assets/spa/assets/index-BcM2VH5k.js +10 -0
- package/dist/assets/spa/assets/index-BcM2VH5k.js.map +1 -0
- package/dist/assets/spa/index.html +20 -0
- package/dist/commands/main.d.ts +4 -3
- package/dist/commands/main.d.ts.map +1 -1
- package/dist/commands/main.js +9 -2
- package/dist/commands/main.js.map +1 -1
- package/dist/commands/make_billable.d.ts.map +1 -1
- package/dist/commands/make_billable.js +1 -1
- package/dist/commands/make_billable.js.map +1 -1
- package/dist/commands/make_webhook_handler.d.ts.map +1 -1
- package/dist/commands/make_webhook_handler.js +1 -1
- package/dist/commands/make_webhook_handler.js.map +1 -1
- package/dist/commands/payments_health.d.ts +31 -0
- package/dist/commands/payments_health.d.ts.map +1 -0
- package/dist/commands/payments_health.js +113 -0
- package/dist/commands/payments_health.js.map +1 -0
- package/dist/commands/payments_sync.d.ts +18 -4
- package/dist/commands/payments_sync.d.ts.map +1 -1
- package/dist/commands/payments_sync.js +136 -40
- package/dist/commands/payments_sync.js.map +1 -1
- package/dist/commands/payments_webhook.d.ts.map +1 -1
- package/dist/commands/payments_webhook.js.map +1 -1
- package/dist/configure.d.ts +12 -5
- package/dist/configure.d.ts.map +1 -1
- package/dist/configure.js +18 -5
- package/dist/configure.js.map +1 -1
- package/dist/providers/dashboard_provider.d.ts +97 -0
- package/dist/providers/dashboard_provider.d.ts.map +1 -0
- package/dist/providers/dashboard_provider.js +430 -0
- package/dist/providers/dashboard_provider.js.map +1 -0
- package/dist/providers/payments_client_provider.d.ts +41 -0
- package/dist/providers/payments_client_provider.d.ts.map +1 -0
- package/dist/providers/payments_client_provider.js +95 -0
- package/dist/providers/payments_client_provider.js.map +1 -0
- package/dist/providers/payments_provider.d.ts +35 -0
- package/dist/providers/payments_provider.d.ts.map +1 -1
- package/dist/providers/payments_provider.js +250 -36
- package/dist/providers/payments_provider.js.map +1 -1
- package/dist/src/billing/billing_health.d.ts +85 -0
- package/dist/src/billing/billing_health.d.ts.map +1 -0
- package/dist/src/billing/billing_health.js +155 -0
- package/dist/src/billing/billing_health.js.map +1 -0
- package/dist/src/billing/billing_overview.d.ts +4 -3
- package/dist/src/billing/billing_overview.d.ts.map +1 -1
- package/dist/src/billing/billing_overview.js +14 -5
- package/dist/src/billing/billing_overview.js.map +1 -1
- package/dist/src/billing/billing_store.d.ts +634 -5
- package/dist/src/billing/billing_store.d.ts.map +1 -1
- package/dist/src/billing/billing_store.js +18 -1
- package/dist/src/billing/billing_store.js.map +1 -1
- package/dist/src/billing/index.d.ts +4 -3
- package/dist/src/billing/index.d.ts.map +1 -1
- package/dist/src/billing/index.js +2 -1
- package/dist/src/billing/index.js.map +1 -1
- package/dist/src/billing/list_query.d.ts +16 -0
- package/dist/src/billing/list_query.d.ts.map +1 -0
- package/dist/src/billing/list_query.js +28 -0
- package/dist/src/billing/list_query.js.map +1 -0
- package/dist/src/billing/lucid_billing_store.d.ts +122 -4
- package/dist/src/billing/lucid_billing_store.d.ts.map +1 -1
- package/dist/src/billing/lucid_billing_store.js +811 -13
- package/dist/src/billing/lucid_billing_store.js.map +1 -1
- package/dist/src/billing/mixins/index.d.ts +5 -2
- package/dist/src/billing/mixins/index.d.ts.map +1 -1
- package/dist/src/billing/mixins/index.js +5 -2
- package/dist/src/billing/mixins/index.js.map +1 -1
- package/dist/src/billing/mixins/with_audit_event.d.ts +48 -0
- package/dist/src/billing/mixins/with_audit_event.d.ts.map +1 -0
- package/dist/src/billing/mixins/with_audit_event.js +77 -0
- package/dist/src/billing/mixins/with_audit_event.js.map +1 -0
- package/dist/src/billing/mixins/with_billable.d.ts.map +1 -1
- package/dist/src/billing/mixins/with_customer.d.ts +39 -0
- package/dist/src/billing/mixins/with_customer.d.ts.map +1 -0
- package/dist/src/billing/mixins/with_customer.js +68 -0
- package/dist/src/billing/mixins/with_customer.js.map +1 -0
- package/dist/src/billing/mixins/with_dispute.d.ts +68 -0
- package/dist/src/billing/mixins/with_dispute.d.ts.map +1 -0
- package/dist/src/billing/mixins/with_dispute.js +83 -0
- package/dist/src/billing/mixins/with_dispute.js.map +1 -0
- package/dist/src/billing/mixins/with_payment.d.ts +42 -0
- package/dist/src/billing/mixins/with_payment.d.ts.map +1 -1
- package/dist/src/billing/mixins/with_payment.js +29 -3
- package/dist/src/billing/mixins/with_payment.js.map +1 -1
- package/dist/src/billing/mixins/with_subscription.d.ts +7 -0
- package/dist/src/billing/mixins/with_subscription.d.ts.map +1 -1
- package/dist/src/billing/mixins/with_subscription.js +15 -1
- package/dist/src/billing/mixins/with_subscription.js.map +1 -1
- package/dist/src/billing/mixins/with_usage_event.d.ts +7 -0
- package/dist/src/billing/mixins/with_usage_event.d.ts.map +1 -1
- package/dist/src/billing/mixins/with_usage_event.js +15 -1
- package/dist/src/billing/mixins/with_usage_event.js.map +1 -1
- package/dist/src/billing/mixins/with_webhook_event.d.ts +18 -0
- package/dist/src/billing/mixins/with_webhook_event.d.ts.map +1 -1
- package/dist/src/billing/mixins/with_webhook_event.js +18 -1
- package/dist/src/billing/mixins/with_webhook_event.js.map +1 -1
- package/dist/src/billing/resolve_dispatch.d.ts +22 -0
- package/dist/src/billing/resolve_dispatch.d.ts.map +1 -0
- package/dist/src/billing/resolve_dispatch.js +44 -0
- package/dist/src/billing/resolve_dispatch.js.map +1 -0
- package/dist/src/billing/resolve_store.d.ts +18 -0
- package/dist/src/billing/resolve_store.d.ts.map +1 -0
- package/dist/src/billing/resolve_store.js +35 -0
- package/dist/src/billing/resolve_store.js.map +1 -0
- package/dist/src/billing/schema.d.ts +108 -0
- package/dist/src/billing/schema.d.ts.map +1 -0
- package/dist/src/billing/schema.js +350 -0
- package/dist/src/billing/schema.js.map +1 -0
- package/dist/src/billing/webhook_dispatcher.d.ts +95 -16
- package/dist/src/billing/webhook_dispatcher.d.ts.map +1 -1
- package/dist/src/billing/webhook_dispatcher.js +186 -33
- package/dist/src/billing/webhook_dispatcher.js.map +1 -1
- package/dist/src/billing/webhook_events.d.ts +67 -1
- package/dist/src/billing/webhook_events.d.ts.map +1 -1
- package/dist/src/billing/webhook_events.js +15 -0
- package/dist/src/billing/webhook_events.js.map +1 -1
- package/dist/src/billing/webhook_processor.d.ts.map +1 -1
- package/dist/src/billing/webhook_processor.js +325 -5
- package/dist/src/billing/webhook_processor.js.map +1 -1
- package/dist/src/client/define_config.d.ts +150 -0
- package/dist/src/client/define_config.d.ts.map +1 -0
- package/dist/src/client/define_config.js +98 -0
- package/dist/src/client/define_config.js.map +1 -0
- package/dist/src/client/handlers.d.ts +71 -0
- package/dist/src/client/handlers.d.ts.map +1 -0
- package/dist/src/client/handlers.js +119 -0
- package/dist/src/client/handlers.js.map +1 -0
- package/dist/src/client/index.d.ts +15 -0
- package/dist/src/client/index.d.ts.map +1 -0
- package/dist/src/client/index.js +12 -0
- package/dist/src/client/index.js.map +1 -0
- package/dist/src/client/statuses.d.ts +38 -0
- package/dist/src/client/statuses.d.ts.map +1 -0
- package/dist/src/client/statuses.js +42 -0
- package/dist/src/client/statuses.js.map +1 -0
- package/dist/src/dashboard/actions.d.ts +143 -0
- package/dist/src/dashboard/actions.d.ts.map +1 -0
- package/dist/src/dashboard/actions.js +112 -0
- package/dist/src/dashboard/actions.js.map +1 -0
- package/dist/src/dashboard/auth.d.ts +136 -0
- package/dist/src/dashboard/auth.d.ts.map +1 -0
- package/dist/src/dashboard/auth.js +152 -0
- package/dist/src/dashboard/auth.js.map +1 -0
- package/dist/src/dashboard/define_config.d.ts +80 -0
- package/dist/src/dashboard/define_config.d.ts.map +1 -0
- package/dist/src/dashboard/define_config.js +83 -0
- package/dist/src/dashboard/define_config.js.map +1 -0
- package/dist/src/dashboard/handlers.d.ts +281 -0
- package/dist/src/dashboard/handlers.d.ts.map +1 -0
- package/dist/src/dashboard/handlers.js +960 -0
- package/dist/src/dashboard/handlers.js.map +1 -0
- package/dist/src/dashboard/index.d.ts +17 -0
- package/dist/src/dashboard/index.d.ts.map +1 -0
- package/dist/src/dashboard/index.js +13 -0
- package/dist/src/dashboard/index.js.map +1 -0
- package/dist/src/dashboard/login_page.d.ts +23 -0
- package/dist/src/dashboard/login_page.d.ts.map +1 -0
- package/dist/src/dashboard/login_page.js +170 -0
- package/dist/src/dashboard/login_page.js.map +1 -0
- package/dist/src/dashboard/period.d.ts +31 -0
- package/dist/src/dashboard/period.d.ts.map +1 -0
- package/dist/src/dashboard/period.js +44 -0
- package/dist/src/dashboard/period.js.map +1 -0
- package/dist/src/dashboard/session_cookie.d.ts +42 -0
- package/dist/src/dashboard/session_cookie.d.ts.map +1 -0
- package/dist/src/dashboard/session_cookie.js +97 -0
- package/dist/src/dashboard/session_cookie.js.map +1 -0
- package/dist/src/dashboard/spa.d.ts +24 -0
- package/dist/src/dashboard/spa.d.ts.map +1 -0
- package/dist/src/dashboard/spa.js +52 -0
- package/dist/src/dashboard/spa.js.map +1 -0
- package/dist/src/define_config.d.ts +245 -10
- package/dist/src/define_config.d.ts.map +1 -1
- package/dist/src/define_config.js +97 -1
- package/dist/src/define_config.js.map +1 -1
- package/dist/src/diagnostics.d.ts +287 -7
- package/dist/src/diagnostics.d.ts.map +1 -1
- package/dist/src/diagnostics.js +317 -1
- package/dist/src/diagnostics.js.map +1 -1
- package/dist/src/driver.d.ts +139 -5
- package/dist/src/driver.d.ts.map +1 -1
- package/dist/src/drivers/abacate.d.ts +13 -3
- package/dist/src/drivers/abacate.d.ts.map +1 -1
- package/dist/src/drivers/abacate.js +112 -19
- package/dist/src/drivers/abacate.js.map +1 -1
- package/dist/src/drivers/adyen.d.ts +164 -0
- package/dist/src/drivers/adyen.d.ts.map +1 -0
- package/dist/src/drivers/adyen.js +678 -0
- package/dist/src/drivers/adyen.js.map +1 -0
- package/dist/src/drivers/asaas.d.ts +53 -3
- package/dist/src/drivers/asaas.d.ts.map +1 -1
- package/dist/src/drivers/asaas.js +364 -29
- package/dist/src/drivers/asaas.js.map +1 -1
- package/dist/src/drivers/dodo.d.ts +135 -0
- package/dist/src/drivers/dodo.d.ts.map +1 -0
- package/dist/src/drivers/dodo.js +864 -0
- package/dist/src/drivers/dodo.js.map +1 -0
- package/dist/src/drivers/efi.d.ts +98 -0
- package/dist/src/drivers/efi.d.ts.map +1 -0
- package/dist/src/drivers/efi.js +628 -0
- package/dist/src/drivers/efi.js.map +1 -0
- package/dist/src/drivers/infinitepay.d.ts +156 -0
- package/dist/src/drivers/infinitepay.d.ts.map +1 -0
- package/dist/src/drivers/infinitepay.js +321 -0
- package/dist/src/drivers/infinitepay.js.map +1 -0
- package/dist/src/drivers/lemonsqueezy.d.ts +125 -0
- package/dist/src/drivers/lemonsqueezy.d.ts.map +1 -0
- package/dist/src/drivers/lemonsqueezy.js +632 -0
- package/dist/src/drivers/lemonsqueezy.js.map +1 -0
- package/dist/src/drivers/mercadopago.d.ts +97 -0
- package/dist/src/drivers/mercadopago.d.ts.map +1 -0
- package/dist/src/drivers/mercadopago.js +844 -0
- package/dist/src/drivers/mercadopago.js.map +1 -0
- package/dist/src/drivers/mollie.d.ts +125 -0
- package/dist/src/drivers/mollie.d.ts.map +1 -0
- package/dist/src/drivers/mollie.js +812 -0
- package/dist/src/drivers/mollie.js.map +1 -0
- package/dist/src/drivers/paddle.d.ts +148 -0
- package/dist/src/drivers/paddle.d.ts.map +1 -0
- package/dist/src/drivers/paddle.js +738 -0
- package/dist/src/drivers/paddle.js.map +1 -0
- package/dist/src/drivers/pagarme.d.ts +97 -0
- package/dist/src/drivers/pagarme.d.ts.map +1 -0
- package/dist/src/drivers/pagarme.js +829 -0
- package/dist/src/drivers/pagarme.js.map +1 -0
- package/dist/src/drivers/pagbank.d.ts +57 -0
- package/dist/src/drivers/pagbank.d.ts.map +1 -0
- package/dist/src/drivers/pagbank.js +499 -0
- package/dist/src/drivers/pagbank.js.map +1 -0
- package/dist/src/drivers/paypal.d.ts +120 -0
- package/dist/src/drivers/paypal.d.ts.map +1 -0
- package/dist/src/drivers/paypal.js +891 -0
- package/dist/src/drivers/paypal.js.map +1 -0
- package/dist/src/drivers/polar.d.ts +118 -0
- package/dist/src/drivers/polar.d.ts.map +1 -0
- package/dist/src/drivers/polar.js +604 -0
- package/dist/src/drivers/polar.js.map +1 -0
- package/dist/src/drivers/razorpay.d.ts +103 -0
- package/dist/src/drivers/razorpay.d.ts.map +1 -0
- package/dist/src/drivers/razorpay.js +867 -0
- package/dist/src/drivers/razorpay.js.map +1 -0
- package/dist/src/drivers/shared.d.ts +33 -0
- package/dist/src/drivers/shared.d.ts.map +1 -0
- package/dist/src/drivers/shared.js +37 -0
- package/dist/src/drivers/shared.js.map +1 -0
- package/dist/src/drivers/square.d.ts +133 -0
- package/dist/src/drivers/square.d.ts.map +1 -0
- package/dist/src/drivers/square.js +905 -0
- package/dist/src/drivers/square.js.map +1 -0
- package/dist/src/drivers/stripe.d.ts +41 -4
- package/dist/src/drivers/stripe.d.ts.map +1 -1
- package/dist/src/drivers/stripe.js +823 -26
- package/dist/src/drivers/stripe.js.map +1 -1
- package/dist/src/drivers/woovi.d.ts +11 -4
- package/dist/src/drivers/woovi.d.ts.map +1 -1
- package/dist/src/drivers/woovi.js +162 -29
- package/dist/src/drivers/woovi.js.map +1 -1
- package/dist/src/ensure_customer.d.ts +34 -1
- package/dist/src/ensure_customer.d.ts.map +1 -1
- package/dist/src/ensure_customer.js +29 -4
- package/dist/src/ensure_customer.js.map +1 -1
- package/dist/src/hooks/webhook_handlers.d.ts.map +1 -1
- package/dist/src/hooks/webhook_handlers.js.map +1 -1
- package/dist/src/http.d.ts +37 -3
- package/dist/src/http.d.ts.map +1 -1
- package/dist/src/http.js +69 -5
- package/dist/src/http.js.map +1 -1
- package/dist/src/index.d.ts +54 -26
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +29 -12
- package/dist/src/index.js.map +1 -1
- package/dist/src/invoice/drivers/asaas.d.ts.map +1 -1
- package/dist/src/invoice/drivers/asaas.js.map +1 -1
- package/dist/src/invoice/drivers/enotas.d.ts.map +1 -1
- package/dist/src/invoice/drivers/enotas.js.map +1 -1
- package/dist/src/invoice/drivers/focus.d.ts.map +1 -1
- package/dist/src/invoice/drivers/focus.js.map +1 -1
- package/dist/src/invoice/drivers/plugnotas.d.ts.map +1 -1
- package/dist/src/invoice/drivers/plugnotas.js.map +1 -1
- package/dist/src/invoice/drivers/tecnospeed.d.ts.map +1 -1
- package/dist/src/invoice/drivers/tecnospeed.js.map +1 -1
- package/dist/src/invoice/emit_invoice.d.ts.map +1 -1
- package/dist/src/invoice/emit_invoice.js +31 -11
- package/dist/src/invoice/emit_invoice.js.map +1 -1
- package/dist/src/invoice/invoice_manager.d.ts.map +1 -1
- package/dist/src/money.d.ts +23 -5
- package/dist/src/money.d.ts.map +1 -1
- package/dist/src/money.js +72 -7
- package/dist/src/money.js.map +1 -1
- package/dist/src/payments_manager.d.ts +8 -1
- package/dist/src/payments_manager.d.ts.map +1 -1
- package/dist/src/payments_manager.js +168 -6
- package/dist/src/payments_manager.js.map +1 -1
- package/dist/src/services/main.d.ts +38 -0
- package/dist/src/services/main.d.ts.map +1 -1
- package/dist/src/services/main.js +130 -0
- package/dist/src/services/main.js.map +1 -1
- package/dist/src/telescope/index.d.ts +2 -0
- package/dist/src/telescope/index.d.ts.map +1 -1
- package/dist/src/telescope/index.js +1 -0
- package/dist/src/telescope/index.js.map +1 -1
- package/dist/src/telescope/payments_watcher.d.ts +10 -4
- package/dist/src/telescope/payments_watcher.d.ts.map +1 -1
- package/dist/src/telescope/payments_watcher.js +66 -14
- package/dist/src/telescope/payments_watcher.js.map +1 -1
- package/dist/src/telescope/register.d.ts +62 -0
- package/dist/src/telescope/register.d.ts.map +1 -0
- package/dist/src/telescope/register.js +48 -0
- package/dist/src/telescope/register.js.map +1 -0
- package/dist/src/testing/fake_payments.d.ts +62 -0
- package/dist/src/testing/fake_payments.d.ts.map +1 -0
- package/dist/src/testing/fake_payments.js +82 -0
- package/dist/src/testing/fake_payments.js.map +1 -0
- package/dist/src/testing/fake_payments_driver.d.ts +1 -1
- package/dist/src/testing/fake_payments_driver.d.ts.map +1 -1
- package/dist/src/testing/fake_payments_driver.js.map +1 -1
- package/dist/src/testing/in_memory_billing_store.d.ts +151 -2
- package/dist/src/testing/in_memory_billing_store.d.ts.map +1 -1
- package/dist/src/testing/in_memory_billing_store.js +517 -4
- package/dist/src/testing/in_memory_billing_store.js.map +1 -1
- package/dist/src/testing/index.d.ts +3 -2
- package/dist/src/testing/index.d.ts.map +1 -1
- package/dist/src/testing/index.js +1 -0
- package/dist/src/testing/index.js.map +1 -1
- package/dist/src/testing/mutable_clock.d.ts.map +1 -1
- package/dist/src/types.d.ts +161 -5
- package/dist/src/types.d.ts.map +1 -1
- package/dist/src/types.js +30 -1
- package/dist/src/types.js.map +1 -1
- package/dist/src/webhook_handlers.d.ts +96 -2
- package/dist/src/webhook_handlers.d.ts.map +1 -1
- package/dist/src/webhook_handlers.js +91 -10
- package/dist/src/webhook_handlers.js.map +1 -1
- package/dist/src/webhook_security.d.ts +94 -3
- package/dist/src/webhook_security.d.ts.map +1 -1
- package/dist/src/webhook_security.js +173 -9
- package/dist/src/webhook_security.js.map +1 -1
- package/dist/stubs/config/payments.stub +13 -0
- package/dist/stubs/config/payments_client.stub +42 -0
- package/dist/stubs/config/payments_dashboard.stub +38 -0
- package/dist/stubs/database/migrations/create_billing_tables.stub +35 -77
- package/dist/stubs/main.js.map +1 -1
- package/dist/stubs/make/webhook_handler/main.stub +29 -11
- package/package.json +67 -32
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The user behind a request, or `null`.
|
|
3
|
+
*
|
|
4
|
+
* A throwing `getUser()` (some guards throw rather than return `null` for an anonymous
|
|
5
|
+
* request) is a denial, not a `500`.
|
|
6
|
+
*/
|
|
7
|
+
export async function resolveRequestUser(ctx) {
|
|
8
|
+
const auth = ctx?.auth;
|
|
9
|
+
if (!auth)
|
|
10
|
+
return null;
|
|
11
|
+
try {
|
|
12
|
+
return (await auth.getUser?.()) ?? auth.user ?? null;
|
|
13
|
+
}
|
|
14
|
+
catch {
|
|
15
|
+
return null;
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
/** The default {@link PaymentsClientConfig.authorize}: there must be a resolved user. */
|
|
19
|
+
export async function defaultAuthorize(ctx) {
|
|
20
|
+
return (await resolveRequestUser(ctx)) !== null;
|
|
21
|
+
}
|
|
22
|
+
/** The default {@link PaymentsClientConfig.owner}: `{ type: 'User', id: String(user.id) }`. */
|
|
23
|
+
export async function defaultOwner(ctx) {
|
|
24
|
+
const user = (await resolveRequestUser(ctx));
|
|
25
|
+
const id = user?.id;
|
|
26
|
+
if (id === undefined || id === null || id === '')
|
|
27
|
+
return null;
|
|
28
|
+
return { type: 'User', id: String(id) };
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* The default ownership check: the payment's gateway customer must be the one this owner
|
|
32
|
+
* holds at that gateway, per `billing_customers`.
|
|
33
|
+
*
|
|
34
|
+
* Every branch that cannot PROVE ownership denies. In particular an app that never called
|
|
35
|
+
* `ensureCustomer({ store, owner })` has an empty registry, and an empty registry means
|
|
36
|
+
* "unknown", not "allowed" — the failure mode of the opposite choice is that every
|
|
37
|
+
* authenticated user can read every payment by guessing a reference.
|
|
38
|
+
*/
|
|
39
|
+
export const registryReferenceGuard = async ({ payment, owner, store }) => {
|
|
40
|
+
if (!payment.customerId) {
|
|
41
|
+
return {
|
|
42
|
+
allowed: false,
|
|
43
|
+
reason: `[payments] Payment ${payment.gatewayId} has no customer recorded, so no owner can be proven for it. Charge through a gateway customer, or supply your own \`authorizeReference\` in config/payments_client.ts.`,
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
const mapping = (await store.findCustomerByOwner(owner.type, owner.id, payment.provider));
|
|
47
|
+
const heldGatewayId = typeof mapping?.gatewayId === 'string' ? mapping.gatewayId : null;
|
|
48
|
+
if (!heldGatewayId) {
|
|
49
|
+
return {
|
|
50
|
+
allowed: false,
|
|
51
|
+
reason: `[payments] No billing_customers mapping for ${owner.type}:${owner.id} at "${payment.provider}", so ownership of this payment cannot be proven and the request was denied. Record the mapping with \`ensureCustomer(driver, id, input, { store, owner })\`, or supply your own \`authorizeReference\` in config/payments_client.ts.`,
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
if (heldGatewayId !== payment.customerId) {
|
|
55
|
+
return {
|
|
56
|
+
allowed: false,
|
|
57
|
+
reason: `[payments] ${owner.type}:${owner.id} holds customer ${heldGatewayId} at "${payment.provider}", but payment ${payment.gatewayId} belongs to ${payment.customerId}.`,
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
return { allowed: true };
|
|
61
|
+
};
|
|
62
|
+
/**
|
|
63
|
+
* Adapt an app-supplied `authorizeReference` into the internal {@link ReferenceGuard}.
|
|
64
|
+
*
|
|
65
|
+
* The hook only ever sees `(ctx, reference)` — the payment stays behind this adapter.
|
|
66
|
+
*/
|
|
67
|
+
function adaptAuthorizeReference(hook) {
|
|
68
|
+
return async ({ ctx, reference }) => {
|
|
69
|
+
if (await hook(ctx, reference))
|
|
70
|
+
return { allowed: true };
|
|
71
|
+
return {
|
|
72
|
+
allowed: false,
|
|
73
|
+
reason: `[payments] authorizeReference denied reference "${reference}".`,
|
|
74
|
+
};
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
/** Apply defaults to a partial config, producing a fully-resolved one. */
|
|
78
|
+
export function resolveConfig(config = {}) {
|
|
79
|
+
const rawPath = config.path ?? '/payments/client';
|
|
80
|
+
// Normalize: a single leading slash, no trailing slash (root collapses to '').
|
|
81
|
+
const trimmed = `/${rawPath.replace(/^\/+/, '').replace(/\/+$/, '')}`;
|
|
82
|
+
return {
|
|
83
|
+
// Opt-in, unlike the dashboard: this one is reachable by every logged-in browser.
|
|
84
|
+
enabled: config.enabled ?? false,
|
|
85
|
+
path: trimmed === '/' ? '' : trimmed,
|
|
86
|
+
authorize: config.authorize ?? defaultAuthorize,
|
|
87
|
+
owner: config.owner ?? defaultOwner,
|
|
88
|
+
resolveReference: config.resolveReference ?? null,
|
|
89
|
+
guard: config.authorizeReference
|
|
90
|
+
? adaptAuthorizeReference(config.authorizeReference)
|
|
91
|
+
: registryReferenceGuard,
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
/** Identity helper giving `config/payments_client.ts` full type-checking. */
|
|
95
|
+
export function defineConfig(config = {}) {
|
|
96
|
+
return config;
|
|
97
|
+
}
|
|
98
|
+
//# sourceMappingURL=define_config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"define_config.js","sourceRoot":"","sources":["../../../src/client/define_config.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import type { HttpContext } from '@adonisjs/core/http';
|
|
2
|
+
import type { BillingStore } from '../billing/billing_store.js';
|
|
3
|
+
import type { ClientPayment, ResolvedPaymentsClientConfig } from './define_config.js';
|
|
4
|
+
/**
|
|
5
|
+
* The one framework-light handler behind `GET <path>/status`.
|
|
6
|
+
*
|
|
7
|
+
* It answers exactly one question — "where does the payment behind this reference stand" —
|
|
8
|
+
* for a caller that has been proven to own it, and it is built so the unsafe shape of that
|
|
9
|
+
* answer is not expressible:
|
|
10
|
+
*
|
|
11
|
+
* 1. the caller is resolved BEFORE the reference is looked at (`authorize`, then `owner`);
|
|
12
|
+
* 2. the payment is loaded, but the response is only ever constructed AFTER the ownership
|
|
13
|
+
* guard has returned `allowed`, inside this function — there is no branch that reaches
|
|
14
|
+
* a body without passing it;
|
|
15
|
+
* 3. the body is assembled from four NAMED fields. Nothing spreads the row, so a column
|
|
16
|
+
* added to `billing_payments` later (a payload, a customer, a gateway id) cannot start
|
|
17
|
+
* appearing in a browser because somebody forgot to exclude it.
|
|
18
|
+
*
|
|
19
|
+
* Reads one indexed row (`billing_payments_external_reference_idx`, then the unique
|
|
20
|
+
* `billing_payments.gateway_id` when nothing carries that reference) plus, for the default
|
|
21
|
+
* guard, one more (`billing_customers_owner_idx`). It never calls a gateway: this endpoint
|
|
22
|
+
* is polled, and a gateway call per poll is a rate-limit incident waiting for its first
|
|
23
|
+
* busy afternoon.
|
|
24
|
+
*/
|
|
25
|
+
/** What the handler needs to answer a request. */
|
|
26
|
+
export interface PaymentStatusDeps {
|
|
27
|
+
store: BillingStore;
|
|
28
|
+
config: ResolvedPaymentsClientConfig;
|
|
29
|
+
/**
|
|
30
|
+
* Called with the developer-facing reason a reference was refused. The browser gets a
|
|
31
|
+
* bare `403` either way — this is how "you never recorded a customer mapping" reaches a
|
|
32
|
+
* log instead of dying silently.
|
|
33
|
+
*/
|
|
34
|
+
onDeny?: (reason: string) => void;
|
|
35
|
+
}
|
|
36
|
+
/** A plain JSON response: an HTTP status and a serializable body. */
|
|
37
|
+
export interface ClientApiResponse {
|
|
38
|
+
status: number;
|
|
39
|
+
body: unknown;
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* The entire success body. Deliberately four fields.
|
|
43
|
+
*
|
|
44
|
+
* Not the payload, not the customer, not the gateway ids: even the rightful owner's browser
|
|
45
|
+
* has no business holding a raw gateway payload, and a body this small cannot leak a field
|
|
46
|
+
* somebody adds to the row later without thinking.
|
|
47
|
+
*
|
|
48
|
+
* `amount` is integer minor units, as stored. Format at the edge.
|
|
49
|
+
*/
|
|
50
|
+
export interface PaymentStatusBody {
|
|
51
|
+
status: string;
|
|
52
|
+
amount: number;
|
|
53
|
+
currency: string;
|
|
54
|
+
/** ISO 8601, or `null` while the payment has not settled. */
|
|
55
|
+
paidAt: string | null;
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Read a store row into {@link ClientPayment} by NAMED column.
|
|
59
|
+
*
|
|
60
|
+
* The store is generic over its row type — a Lucid model instance in one implementation, a
|
|
61
|
+
* plain object in the other — so this reads structurally, exactly as `listPayments` does.
|
|
62
|
+
* `amount` goes through `Number` because Postgres hands `bigint` back as a string.
|
|
63
|
+
*/
|
|
64
|
+
export declare function normalizePayment(row: unknown): ClientPayment | null;
|
|
65
|
+
/**
|
|
66
|
+
* `GET <path>/status?reference=<reference>`.
|
|
67
|
+
*
|
|
68
|
+
* See the module note above for the order the guards run in and why.
|
|
69
|
+
*/
|
|
70
|
+
export declare function paymentStatus(deps: PaymentStatusDeps, ctx: HttpContext, reference: string | undefined): Promise<ClientApiResponse>;
|
|
71
|
+
//# sourceMappingURL=handlers.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"handlers.d.ts","sourceRoot":"","sources":["../../../src/client/handlers.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AACvD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAC;AAChE,OAAO,KAAK,EAAE,aAAa,EAAE,4BAA4B,EAAE,MAAM,oBAAoB,CAAC;AAEtF;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH,kDAAkD;AAClD,MAAM,WAAW,iBAAiB;IAChC,KAAK,EAAE,YAAY,CAAC;IACpB,MAAM,EAAE,4BAA4B,CAAC;IACrC;;;;OAIG;IACH,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC;CACnC;AAED,qEAAqE;AACrE,MAAM,WAAW,iBAAiB;IAChC,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,OAAO,CAAC;CACf;AAED;;;;;;;;GAQG;AACH,MAAM,WAAW,iBAAiB;IAChC,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,6DAA6D;IAC7D,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;CACvB;AAyBD;;;;;;GAMG;AACH,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,OAAO,GAAG,aAAa,GAAG,IAAI,CAwBnE;AAmCD;;;;GAIG;AACH,wBAAsB,aAAa,CACjC,IAAI,EAAE,iBAAiB,EACvB,GAAG,EAAE,WAAW,EAChB,SAAS,EAAE,MAAM,GAAG,SAAS,GAC5B,OAAO,CAAC,iBAAiB,CAAC,CA+B5B"}
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
const badRequest = (message) => ({
|
|
2
|
+
status: 400,
|
|
3
|
+
body: { error: message },
|
|
4
|
+
});
|
|
5
|
+
/** No caller could be resolved. Terminal for the browser — retrying will not grow a user. */
|
|
6
|
+
const unauthorized = () => ({ status: 401, body: { error: 'unauthorized' } });
|
|
7
|
+
/** A caller was resolved and does not own this reference. Also terminal. */
|
|
8
|
+
const forbidden = () => ({ status: 403, body: { error: 'forbidden' } });
|
|
9
|
+
/**
|
|
10
|
+
* No payment row for that reference — which is the NORMAL state of a Pix charge that has
|
|
11
|
+
* not been paid yet: `billing_payments` is written by the webhook, so nothing exists until
|
|
12
|
+
* the gateway calls. The browser keeps polling on this one.
|
|
13
|
+
*/
|
|
14
|
+
const notFound = () => ({ status: 404, body: { error: 'unknown reference' } });
|
|
15
|
+
/** `Date`, Luxon `DateTime` (Lucid) or nothing → a `Date` or `null`. */
|
|
16
|
+
function toDate(value) {
|
|
17
|
+
if (value instanceof Date)
|
|
18
|
+
return value;
|
|
19
|
+
const asLuxon = value;
|
|
20
|
+
if (asLuxon && typeof asLuxon.toJSDate === 'function')
|
|
21
|
+
return asLuxon.toJSDate();
|
|
22
|
+
return null;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Read a store row into {@link ClientPayment} by NAMED column.
|
|
26
|
+
*
|
|
27
|
+
* The store is generic over its row type — a Lucid model instance in one implementation, a
|
|
28
|
+
* plain object in the other — so this reads structurally, exactly as `listPayments` does.
|
|
29
|
+
* `amount` goes through `Number` because Postgres hands `bigint` back as a string.
|
|
30
|
+
*/
|
|
31
|
+
export function normalizePayment(row) {
|
|
32
|
+
const record = row;
|
|
33
|
+
if (!record)
|
|
34
|
+
return null;
|
|
35
|
+
const gatewayId = record.gatewayId;
|
|
36
|
+
const provider = record.provider;
|
|
37
|
+
const status = record.status;
|
|
38
|
+
const currency = record.currency;
|
|
39
|
+
if (typeof gatewayId !== 'string' ||
|
|
40
|
+
typeof provider !== 'string' ||
|
|
41
|
+
typeof status !== 'string' ||
|
|
42
|
+
typeof currency !== 'string') {
|
|
43
|
+
return null;
|
|
44
|
+
}
|
|
45
|
+
return {
|
|
46
|
+
gatewayId,
|
|
47
|
+
provider,
|
|
48
|
+
status,
|
|
49
|
+
amount: Number(record.amount ?? 0),
|
|
50
|
+
currency,
|
|
51
|
+
customerId: typeof record.customerId === 'string' ? record.customerId : null,
|
|
52
|
+
paidAt: toDate(record.paidAt),
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* The payment behind the reference the browser sent.
|
|
57
|
+
*
|
|
58
|
+
* Two lookups, in this order, and both indexed:
|
|
59
|
+
*
|
|
60
|
+
* 1. `external_reference` — the app's OWN id for the charge. This is the routing key: a
|
|
61
|
+
* checkout page polls for `order-1042`, not for `pi_3Qx...`, and the column exists so it
|
|
62
|
+
* can. Answers `null` for every row an install wrote before it ran the
|
|
63
|
+
* an earlier schema migration, which is exactly why (2) is still here.
|
|
64
|
+
* 2. `gateway_id` — the old behaviour, kept because several Pix gateways make the two equal
|
|
65
|
+
* (Woovi's `correlationID`, Efí's `txid`) and because a not-yet-migrated install has
|
|
66
|
+
* nothing else to match on.
|
|
67
|
+
*
|
|
68
|
+
* An app-supplied `resolveReference` REPLACES both: it says "my reference is neither of
|
|
69
|
+
* those, here is the gateway id", and second-guessing that with a fallback would be the
|
|
70
|
+
* endpoint quietly answering a question the app already said it owns.
|
|
71
|
+
*/
|
|
72
|
+
async function findPayment(store, config, ctx, reference) {
|
|
73
|
+
if (config.resolveReference) {
|
|
74
|
+
const gatewayId = await config.resolveReference(ctx, reference);
|
|
75
|
+
if (typeof gatewayId !== 'string' || gatewayId === '')
|
|
76
|
+
return null;
|
|
77
|
+
return normalizePayment(await store.findPaymentByGatewayId(gatewayId));
|
|
78
|
+
}
|
|
79
|
+
const byReference = normalizePayment(await store.findPaymentByExternalReference(reference));
|
|
80
|
+
if (byReference)
|
|
81
|
+
return byReference;
|
|
82
|
+
return normalizePayment(await store.findPaymentByGatewayId(reference));
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* `GET <path>/status?reference=<reference>`.
|
|
86
|
+
*
|
|
87
|
+
* See the module note above for the order the guards run in and why.
|
|
88
|
+
*/
|
|
89
|
+
export async function paymentStatus(deps, ctx, reference) {
|
|
90
|
+
const { store, config } = deps;
|
|
91
|
+
if (typeof reference !== 'string' || reference.trim() === '') {
|
|
92
|
+
return badRequest('reference is required');
|
|
93
|
+
}
|
|
94
|
+
const trimmed = reference.trim();
|
|
95
|
+
// ── 1. The caller, before the reference. ───────────────────────────────────────────
|
|
96
|
+
if (!(await config.authorize(ctx)))
|
|
97
|
+
return unauthorized();
|
|
98
|
+
const owner = await config.owner(ctx);
|
|
99
|
+
if (!owner)
|
|
100
|
+
return unauthorized();
|
|
101
|
+
// ── 2. The payment. ────────────────────────────────────────────────────────────────
|
|
102
|
+
const payment = await findPayment(store, config, ctx, trimmed);
|
|
103
|
+
if (!payment)
|
|
104
|
+
return notFound();
|
|
105
|
+
// ── 3. Ownership. Nothing below this line is reachable without it. ─────────────────
|
|
106
|
+
const outcome = await config.guard({ ctx, reference: trimmed, payment, owner, store });
|
|
107
|
+
if (!outcome.allowed) {
|
|
108
|
+
deps.onDeny?.(outcome.reason);
|
|
109
|
+
return forbidden();
|
|
110
|
+
}
|
|
111
|
+
const body = {
|
|
112
|
+
status: payment.status,
|
|
113
|
+
amount: payment.amount,
|
|
114
|
+
currency: payment.currency,
|
|
115
|
+
paidAt: payment.paidAt ? payment.paidAt.toISOString() : null,
|
|
116
|
+
};
|
|
117
|
+
return { status: 200, body };
|
|
118
|
+
}
|
|
119
|
+
//# sourceMappingURL=handlers.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"handlers.js","sourceRoot":"","sources":["../../../src/client/handlers.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The browser-facing half of `@adonis-agora/payments`: one polled, opt-in endpoint that
|
|
3
|
+
* answers "has this payment settled yet" for a caller proven to own it.
|
|
4
|
+
*
|
|
5
|
+
* Mounted by `@adonis-agora/payments/payments_client_provider` from
|
|
6
|
+
* `config/payments_client.ts`. The React hook that polls it lives in
|
|
7
|
+
* `@adonis-agora/payments-react`.
|
|
8
|
+
*/
|
|
9
|
+
export type { ClientAuthorizeHook, ClientAuthorizeReferenceHook, ClientOwnerHook, ClientPayment, ClientResolveReferenceHook, PaymentOwner, PaymentsClientConfig, ReferenceDenied, ReferenceGuard, ReferenceGuardRequest, ReferenceOutcome, ResolvedPaymentsClientConfig, } from './define_config.js';
|
|
10
|
+
export { defaultAuthorize, defaultOwner, defineConfig, registryReferenceGuard, resolveConfig, resolveRequestUser, } from './define_config.js';
|
|
11
|
+
export type { ClientApiResponse, PaymentStatusBody, PaymentStatusDeps } from './handlers.js';
|
|
12
|
+
export { normalizePayment, paymentStatus } from './handlers.js';
|
|
13
|
+
export type { PaymentStatus, PaymentStatusesAreExhaustive, TerminalPaymentStatus, } from './statuses.js';
|
|
14
|
+
export { isTerminalPaymentStatus, PAYMENT_STATUSES, PAYMENT_STATUSES_ARE_EXHAUSTIVE, TERMINAL_PAYMENT_STATUSES, } from './statuses.js';
|
|
15
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/client/index.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,YAAY,EACV,mBAAmB,EACnB,4BAA4B,EAC5B,eAAe,EACf,aAAa,EACb,0BAA0B,EAC1B,YAAY,EACZ,oBAAoB,EACpB,eAAe,EACf,cAAc,EACd,qBAAqB,EACrB,gBAAgB,EAChB,4BAA4B,GAC7B,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EACL,gBAAgB,EAChB,YAAY,EACZ,YAAY,EACZ,sBAAsB,EACtB,aAAa,EACb,kBAAkB,GACnB,MAAM,oBAAoB,CAAC;AAC5B,YAAY,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AAC7F,OAAO,EAAE,gBAAgB,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAChE,YAAY,EACV,aAAa,EACb,4BAA4B,EAC5B,qBAAqB,GACtB,MAAM,eAAe,CAAC;AACvB,OAAO,EACL,uBAAuB,EACvB,gBAAgB,EAChB,+BAA+B,EAC/B,yBAAyB,GAC1B,MAAM,eAAe,CAAC"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The browser-facing half of `@adonis-agora/payments`: one polled, opt-in endpoint that
|
|
3
|
+
* answers "has this payment settled yet" for a caller proven to own it.
|
|
4
|
+
*
|
|
5
|
+
* Mounted by `@adonis-agora/payments/payments_client_provider` from
|
|
6
|
+
* `config/payments_client.ts`. The React hook that polls it lives in
|
|
7
|
+
* `@adonis-agora/payments-react`.
|
|
8
|
+
*/
|
|
9
|
+
export { defaultAuthorize, defaultOwner, defineConfig, registryReferenceGuard, resolveConfig, resolveRequestUser, } from './define_config.js';
|
|
10
|
+
export { normalizePayment, paymentStatus } from './handlers.js';
|
|
11
|
+
export { isTerminalPaymentStatus, PAYMENT_STATUSES, PAYMENT_STATUSES_ARE_EXHAUSTIVE, TERMINAL_PAYMENT_STATUSES, } from './statuses.js';
|
|
12
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/client/index.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAgBH,OAAO,EACL,gBAAgB,EAChB,YAAY,EACZ,YAAY,EACZ,sBAAsB,EACtB,aAAa,EACb,kBAAkB,GACnB,MAAM,oBAAoB,CAAC;AAE5B,OAAO,EAAE,gBAAgB,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAMhE,OAAO,EACL,uBAAuB,EACvB,gBAAgB,EAChB,+BAA+B,EAC/B,yBAAyB,GAC1B,MAAM,eAAe,CAAC"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import type { BillingStatus } from '../types.js';
|
|
2
|
+
/**
|
|
3
|
+
* The payment statuses the client endpoint can report, in the order a payment moves
|
|
4
|
+
* through them.
|
|
5
|
+
*
|
|
6
|
+
* This is the canonical {@link BillingStatus} union restated as a VALUE, because the
|
|
7
|
+
* browser half of this feature (`@adonis-agora/payments-react`) needs the same set at
|
|
8
|
+
* runtime and cannot import a server package to get it. `test/client/status_parity.spec.ts`
|
|
9
|
+
* asserts the two lists are still the same list.
|
|
10
|
+
*/
|
|
11
|
+
export declare const PAYMENT_STATUSES: readonly ["pending", "authorized", "paid", "failed", "refunded", "canceled", "disputed"];
|
|
12
|
+
export type PaymentStatus = (typeof PAYMENT_STATUSES)[number];
|
|
13
|
+
/**
|
|
14
|
+
* `true` only while {@link PAYMENT_STATUSES} lists every member of {@link BillingStatus}.
|
|
15
|
+
*
|
|
16
|
+
* `as const satisfies readonly BillingStatus[]` above proves each listed status is real; it
|
|
17
|
+
* cannot prove none is MISSING. A status added to `BillingStatus` and forgotten here would
|
|
18
|
+
* reach a consumer's exhaustive `switch` as a string outside the union — so the omission is
|
|
19
|
+
* made a compile error instead.
|
|
20
|
+
*/
|
|
21
|
+
export type PaymentStatusesAreExhaustive = [Exclude<BillingStatus, PaymentStatus>] extends [never] ? true : never;
|
|
22
|
+
/** Exported so the assertion above is a real reference rather than dead code. */
|
|
23
|
+
export declare const PAYMENT_STATUSES_ARE_EXHAUSTIVE: PaymentStatusesAreExhaustive;
|
|
24
|
+
/**
|
|
25
|
+
* The statuses a payment does not move out of — where the browser stops asking.
|
|
26
|
+
*
|
|
27
|
+
* `pending` and `authorized` are deliberately absent: a Pix that has not been paid is
|
|
28
|
+
* `pending`, and authorized card money is held, not captured. Both can still change.
|
|
29
|
+
*/
|
|
30
|
+
export declare const TERMINAL_PAYMENT_STATUSES: readonly ["paid", "failed", "refunded", "canceled", "disputed"];
|
|
31
|
+
export type TerminalPaymentStatus = (typeof TERMINAL_PAYMENT_STATUSES)[number];
|
|
32
|
+
/**
|
|
33
|
+
* Whether a status is terminal. Takes a plain `string` on purpose: the store's `status`
|
|
34
|
+
* column is a free string (a gateway may write its own), so an unrecognized value must
|
|
35
|
+
* answer "not terminal" rather than fail a narrowing.
|
|
36
|
+
*/
|
|
37
|
+
export declare function isTerminalPaymentStatus(status: string): status is TerminalPaymentStatus;
|
|
38
|
+
//# sourceMappingURL=statuses.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"statuses.d.ts","sourceRoot":"","sources":["../../../src/client/statuses.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAEjD;;;;;;;;GAQG;AACH,eAAO,MAAM,gBAAgB,0FAQgB,CAAC;AAE9C,MAAM,MAAM,aAAa,GAAG,CAAC,OAAO,gBAAgB,CAAC,CAAC,MAAM,CAAC,CAAC;AAE9D;;;;;;;GAOG;AACH,MAAM,MAAM,4BAA4B,GAAG,CAAC,OAAO,CAAC,aAAa,EAAE,aAAa,CAAC,CAAC,SAAS,CAAC,KAAK,CAAC,GAC9F,IAAI,GACJ,KAAK,CAAC;AAEV,iFAAiF;AACjF,eAAO,MAAM,+BAA+B,EAAE,4BAAmC,CAAC;AAElF;;;;;GAKG;AACH,eAAO,MAAM,yBAAyB,iEAMO,CAAC;AAE9C,MAAM,MAAM,qBAAqB,GAAG,CAAC,OAAO,yBAAyB,CAAC,CAAC,MAAM,CAAC,CAAC;AAE/E;;;;GAIG;AACH,wBAAgB,uBAAuB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,IAAI,qBAAqB,CAEvF"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The payment statuses the client endpoint can report, in the order a payment moves
|
|
3
|
+
* through them.
|
|
4
|
+
*
|
|
5
|
+
* This is the canonical {@link BillingStatus} union restated as a VALUE, because the
|
|
6
|
+
* browser half of this feature (`@adonis-agora/payments-react`) needs the same set at
|
|
7
|
+
* runtime and cannot import a server package to get it. `test/client/status_parity.spec.ts`
|
|
8
|
+
* asserts the two lists are still the same list.
|
|
9
|
+
*/
|
|
10
|
+
export const PAYMENT_STATUSES = [
|
|
11
|
+
'pending',
|
|
12
|
+
'authorized',
|
|
13
|
+
'paid',
|
|
14
|
+
'failed',
|
|
15
|
+
'refunded',
|
|
16
|
+
'canceled',
|
|
17
|
+
'disputed',
|
|
18
|
+
];
|
|
19
|
+
/** Exported so the assertion above is a real reference rather than dead code. */
|
|
20
|
+
export const PAYMENT_STATUSES_ARE_EXHAUSTIVE = true;
|
|
21
|
+
/**
|
|
22
|
+
* The statuses a payment does not move out of — where the browser stops asking.
|
|
23
|
+
*
|
|
24
|
+
* `pending` and `authorized` are deliberately absent: a Pix that has not been paid is
|
|
25
|
+
* `pending`, and authorized card money is held, not captured. Both can still change.
|
|
26
|
+
*/
|
|
27
|
+
export const TERMINAL_PAYMENT_STATUSES = [
|
|
28
|
+
'paid',
|
|
29
|
+
'failed',
|
|
30
|
+
'refunded',
|
|
31
|
+
'canceled',
|
|
32
|
+
'disputed',
|
|
33
|
+
];
|
|
34
|
+
/**
|
|
35
|
+
* Whether a status is terminal. Takes a plain `string` on purpose: the store's `status`
|
|
36
|
+
* column is a free string (a gateway may write its own), so an unrecognized value must
|
|
37
|
+
* answer "not terminal" rather than fail a narrowing.
|
|
38
|
+
*/
|
|
39
|
+
export function isTerminalPaymentStatus(status) {
|
|
40
|
+
return TERMINAL_PAYMENT_STATUSES.includes(status);
|
|
41
|
+
}
|
|
42
|
+
//# sourceMappingURL=statuses.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"statuses.js","sourceRoot":"","sources":["../../../src/client/statuses.ts"],"names":[],"mappings":"AAEA;;;;;;;;GAQG;AACH,MAAM,CAAC,MAAM,gBAAgB,GAAG;IAC9B,SAAS;IACT,YAAY;IACZ,MAAM;IACN,QAAQ;IACR,UAAU;IACV,UAAU;IACV,UAAU;CACiC,CAAC;AAgB9C,iFAAiF;AACjF,MAAM,CAAC,MAAM,+BAA+B,GAAiC,IAAI,CAAC;AAElF;;;;;GAKG;AACH,MAAM,CAAC,MAAM,yBAAyB,GAAG;IACvC,MAAM;IACN,QAAQ;IACR,UAAU;IACV,UAAU;IACV,UAAU;CACiC,CAAC;AAI9C;;;;GAIG;AACH,MAAM,UAAU,uBAAuB,CAAC,MAAc;IACpD,OAAQ,yBAA+C,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;AAC3E,CAAC"}
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
import type { BillingStore } from '../billing/billing_store.js';
|
|
2
|
+
/**
|
|
3
|
+
* The dashboard's two WRITE actions, as framework-light ports.
|
|
4
|
+
*
|
|
5
|
+
* Everything else this console does is a store read. These two are not: a refund moves money at
|
|
6
|
+
* the gateway, and a retry re-runs an app's webhook handlers. Both need things the handlers
|
|
7
|
+
* deliberately do not know about (a `PaymentsDriver`, a `WebhookProcessor`), so they cross the
|
|
8
|
+
* boundary as narrow function types the provider supplies and a test can fake — the same shape
|
|
9
|
+
* `@adonis-agora/durable`'s dashboard uses for its engine port.
|
|
10
|
+
*
|
|
11
|
+
* Every failure mode is a VALUE here, never a thrown error: an operator who clicks "Refund" and
|
|
12
|
+
* gets nothing back has no way to tell "the gateway said no" from "the button is broken", so each
|
|
13
|
+
* outcome carries the message that names which one happened.
|
|
14
|
+
*/
|
|
15
|
+
/** The slice of `PaymentsDriver` a refund needs. Structural on purpose: the real driver satisfies
|
|
16
|
+
* it, and a test can hand over eight lines instead of a gateway. */
|
|
17
|
+
export interface RefundCapableDriver {
|
|
18
|
+
readonly provider: string;
|
|
19
|
+
readonly capabilities?: {
|
|
20
|
+
refunds?: boolean;
|
|
21
|
+
};
|
|
22
|
+
refund(paymentGatewayId: string, amount?: number, options?: {
|
|
23
|
+
idempotencyKey?: string;
|
|
24
|
+
}): Promise<{
|
|
25
|
+
gatewayId: string;
|
|
26
|
+
provider: string;
|
|
27
|
+
amount: {
|
|
28
|
+
amount: number;
|
|
29
|
+
currency: string;
|
|
30
|
+
};
|
|
31
|
+
status: string;
|
|
32
|
+
createdAt: string;
|
|
33
|
+
}>;
|
|
34
|
+
}
|
|
35
|
+
/** What the operator gets back from the refund button. */
|
|
36
|
+
export type RefundOutcome = {
|
|
37
|
+
kind: 'ok';
|
|
38
|
+
/** Integer minor units, as the gateway reported them back. */
|
|
39
|
+
refund: {
|
|
40
|
+
gatewayId: string;
|
|
41
|
+
amount: number;
|
|
42
|
+
currency: string;
|
|
43
|
+
status: string;
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
/** The provider that took this payment is not in `config/payments.ts` any more, or the app has
|
|
47
|
+
* no manager at all. Nothing was attempted. */
|
|
48
|
+
| {
|
|
49
|
+
kind: 'unavailable';
|
|
50
|
+
message: string;
|
|
51
|
+
}
|
|
52
|
+
/** The gateway has no refund API (Woovi/OpenPix). Nothing was attempted. */
|
|
53
|
+
| {
|
|
54
|
+
kind: 'unsupported';
|
|
55
|
+
message: string;
|
|
56
|
+
}
|
|
57
|
+
/** The gateway refused. `message` is ITS message, verbatim — a silent failure here is worse
|
|
58
|
+
* than no button. */
|
|
59
|
+
| {
|
|
60
|
+
kind: 'gateway-error';
|
|
61
|
+
message: string;
|
|
62
|
+
};
|
|
63
|
+
export type RefundAction = (input: {
|
|
64
|
+
provider: string;
|
|
65
|
+
gatewayId: string;
|
|
66
|
+
/** Integer minor units. Omitted = refund the whole payment. */
|
|
67
|
+
amount?: number;
|
|
68
|
+
}) => Promise<RefundOutcome>;
|
|
69
|
+
/**
|
|
70
|
+
* Build the refund action over a driver resolver (the app's `PaymentsManager.driver`).
|
|
71
|
+
*
|
|
72
|
+
* The capability check happens BEFORE the call, matching `PaymentsManager.assertCapability`: a
|
|
73
|
+
* driver that declares `refunds: false` implements `refund()` only to throw, and discovering that
|
|
74
|
+
* from a gateway round-trip reads to the operator like a network failure.
|
|
75
|
+
*/
|
|
76
|
+
export declare function createRefundAction(resolveDriver: (provider: string) => RefundCapableDriver | Promise<RefundCapableDriver>): RefundAction;
|
|
77
|
+
/** The normalized webhook event the replay rebuilds and re-runs. Structurally `WebhookEvent`. */
|
|
78
|
+
export interface ReplayableWebhookEvent {
|
|
79
|
+
id: string;
|
|
80
|
+
provider: string;
|
|
81
|
+
type: string;
|
|
82
|
+
data: unknown;
|
|
83
|
+
raw: Record<string, unknown>;
|
|
84
|
+
}
|
|
85
|
+
/** What the operator gets back from the retry button. */
|
|
86
|
+
export type ReplayOutcome =
|
|
87
|
+
/** The handlers ran to completion; the ledger row is `processed`. */
|
|
88
|
+
{
|
|
89
|
+
kind: 'processed';
|
|
90
|
+
}
|
|
91
|
+
/** Something else claimed the row between the read and the write — it is no longer `failed`. */
|
|
92
|
+
| {
|
|
93
|
+
kind: 'conflict';
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* The ledger row carries no normalized event, so there is nothing to replay. That means the
|
|
97
|
+
* row was written before this install ran the `the schema this package now creates itself` migration —
|
|
98
|
+
* the raw payload alone is not replayable, because turning it back into an event would mean
|
|
99
|
+
* calling `parseWebhook`, which re-verifies a signature computed from headers the ledger
|
|
100
|
+
* never kept. The row is put back exactly as it was, original error and all.
|
|
101
|
+
*/
|
|
102
|
+
| {
|
|
103
|
+
kind: 'undeliverable';
|
|
104
|
+
message: string;
|
|
105
|
+
}
|
|
106
|
+
/** The handlers threw again. The ledger row carries the NEW error (the processor wrote it). */
|
|
107
|
+
| {
|
|
108
|
+
kind: 'failed';
|
|
109
|
+
message: string;
|
|
110
|
+
};
|
|
111
|
+
export type ReplayAction = (input: {
|
|
112
|
+
gatewayEventId: string;
|
|
113
|
+
provider: string;
|
|
114
|
+
type: string;
|
|
115
|
+
/** The error the row carried before we touched it, so a driver refusal can restore it verbatim. */
|
|
116
|
+
previousError: string | null;
|
|
117
|
+
}) => Promise<ReplayOutcome>;
|
|
118
|
+
/**
|
|
119
|
+
* Build the retry action over the store plus the app's webhook processor.
|
|
120
|
+
*
|
|
121
|
+
* The ledger dance is the fiddly part and it lives here, once:
|
|
122
|
+
*
|
|
123
|
+
* 1. `recordWebhookEvent` re-claims a `failed` row and hands the ORIGINAL delivery back — both
|
|
124
|
+
* the raw payload and the NORMALIZED event recorded beside it. That is the only way to read
|
|
125
|
+
* a stored delivery through the `BillingStore` contract.
|
|
126
|
+
* 2. The event is rebuilt from those two columns. It is NEVER re-parsed: `parseWebhook`
|
|
127
|
+
* re-verifies a signature computed over headers the ledger does not keep, so rebuilding that
|
|
128
|
+
* way answered `422` on Stripe, Adyen and every other gateway that signs — a retry that
|
|
129
|
+
* worked for a minority of gateways, and only for the ones an attacker would not need to
|
|
130
|
+
* forge. A row with no `normalized` (written before the migration) is `undeliverable`,
|
|
131
|
+
* stated plainly, rather than half-replayed.
|
|
132
|
+
* 3. The row is put BACK to `failed` before `process` runs, because `WebhookProcessor.process`
|
|
133
|
+
* claims through `recordWebhookEvent` itself, and a row sitting at `received` reads to it as
|
|
134
|
+
* "in flight" — it would return `false` and run nothing at all. This is the one place that
|
|
135
|
+
* subtlety is written down.
|
|
136
|
+
* 4. `process` claims it properly and marks it `processed` or `failed` with the real reason.
|
|
137
|
+
*/
|
|
138
|
+
export declare function createReplayAction(deps: {
|
|
139
|
+
store: BillingStore;
|
|
140
|
+
/** Run it through the app's `WebhookProcessor` (built-in sync + the app's own handlers). */
|
|
141
|
+
process: (event: ReplayableWebhookEvent) => Promise<unknown>;
|
|
142
|
+
}): ReplayAction;
|
|
143
|
+
//# sourceMappingURL=actions.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"actions.d.ts","sourceRoot":"","sources":["../../../src/dashboard/actions.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAC;AAEhE;;;;;;;;;;;;GAYG;AAEH;qEACqE;AACrE,MAAM,WAAW,mBAAmB;IAClC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,YAAY,CAAC,EAAE;QAAE,OAAO,CAAC,EAAE,OAAO,CAAA;KAAE,CAAC;IAC9C,MAAM,CACJ,gBAAgB,EAAE,MAAM,EACxB,MAAM,CAAC,EAAE,MAAM,EACf,OAAO,CAAC,EAAE;QAAE,cAAc,CAAC,EAAE,MAAM,CAAA;KAAE,GACpC,OAAO,CAAC;QACT,SAAS,EAAE,MAAM,CAAC;QAClB,QAAQ,EAAE,MAAM,CAAC;QACjB,MAAM,EAAE;YAAE,MAAM,EAAE,MAAM,CAAC;YAAC,QAAQ,EAAE,MAAM,CAAA;SAAE,CAAC;QAC7C,MAAM,EAAE,MAAM,CAAC;QACf,SAAS,EAAE,MAAM,CAAC;KACnB,CAAC,CAAC;CACJ;AAED,0DAA0D;AAC1D,MAAM,MAAM,aAAa,GACrB;IACE,IAAI,EAAE,IAAI,CAAC;IACX,8DAA8D;IAC9D,MAAM,EAAE;QAAE,SAAS,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC;CACjF;AACH;gDACgD;GAC9C;IAAE,IAAI,EAAE,aAAa,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE;AAC1C,4EAA4E;GAC1E;IAAE,IAAI,EAAE,aAAa,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE;AAC1C;sBACsB;GACpB;IAAE,IAAI,EAAE,eAAe,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC;AAE/C,MAAM,MAAM,YAAY,GAAG,CAAC,KAAK,EAAE;IACjC,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,+DAA+D;IAC/D,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB,KAAK,OAAO,CAAC,aAAa,CAAC,CAAC;AAE7B;;;;;;GAMG;AACH,wBAAgB,kBAAkB,CAChC,aAAa,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,mBAAmB,GAAG,OAAO,CAAC,mBAAmB,CAAC,GACtF,YAAY,CA+Bd;AAED,iGAAiG;AACjG,MAAM,WAAW,sBAAsB;IACrC,EAAE,EAAE,MAAM,CAAC;IACX,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,OAAO,CAAC;IACd,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAC9B;AAED,yDAAyD;AACzD,MAAM,MAAM,aAAa;AACvB,qEAAqE;AACnE;IAAE,IAAI,EAAE,WAAW,CAAA;CAAE;AACvB,gGAAgG;GAC9F;IAAE,IAAI,EAAE,UAAU,CAAA;CAAE;AACtB;;;;;;GAMG;GACD;IAAE,IAAI,EAAE,eAAe,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE;AAC5C,+FAA+F;GAC7F;IAAE,IAAI,EAAE,QAAQ,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC;AAExC,MAAM,MAAM,YAAY,GAAG,CAAC,KAAK,EAAE;IACjC,cAAc,EAAE,MAAM,CAAC;IACvB,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,mGAAmG;IACnG,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;CAC9B,KAAK,OAAO,CAAC,aAAa,CAAC,CAAC;AAE7B;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE;IACvC,KAAK,EAAE,YAAY,CAAC;IACpB,4FAA4F;IAC5F,OAAO,EAAE,CAAC,KAAK,EAAE,sBAAsB,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;CAC9D,GAAG,YAAY,CAgDf"}
|