@adonis-agora/payments 0.2.0 → 0.3.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 +2347 -0
- package/dist/assets/spa/assets/index-CT5Zon6P.css +1 -0
- package/dist/assets/spa/assets/index-CvEbJEnq.js +41 -0
- package/dist/assets/spa/assets/index-CvEbJEnq.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/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/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 +2 -1
- package/dist/src/billing/index.d.ts.map +1 -1
- package/dist/src/billing/index.js +1 -0
- 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 +3 -0
- package/dist/src/billing/mixins/index.d.ts.map +1 -1
- package/dist/src/billing/mixins/index.js +3 -0
- 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_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 +16 -0
- package/dist/src/client/index.d.ts.map +1 -0
- package/dist/src/client/index.js +13 -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 +18 -0
- package/dist/src/dashboard/index.d.ts.map +1 -0
- package/dist/src/dashboard/index.js +14 -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 +244 -9
- 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 +12 -2
- 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 +52 -2
- 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 +40 -3
- package/dist/src/drivers/stripe.d.ts.map +1 -1
- package/dist/src/drivers/stripe.js +806 -25
- package/dist/src/drivers/stripe.js.map +1 -1
- package/dist/src/drivers/woovi.d.ts +10 -3
- 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/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 +40 -10
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +22 -4
- package/dist/src/index.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/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 +65 -13
- 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/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 +2 -1
- 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/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/make/webhook_handler/main.stub +29 -11
- package/package.json +60 -25
|
@@ -0,0 +1,604 @@
|
|
|
1
|
+
import { publishRefundDiagnostics, publishSubscriptionDiagnostics, } from '../diagnostics.js';
|
|
2
|
+
import { headerValue, httpRequest, isNotFound } from '../http.js';
|
|
3
|
+
import { verifyStandardWebhookSignature } from '../webhook_security.js';
|
|
4
|
+
import { requireCredential, requireCurrency } from './shared.js';
|
|
5
|
+
/**
|
|
6
|
+
* The API version this driver is written against, pinned on every request via
|
|
7
|
+
* `Polar-Version`. Polar defaults to `2026-04` when the header is absent, so omitting it
|
|
8
|
+
* would silently follow whatever Polar promotes to default next.
|
|
9
|
+
*/
|
|
10
|
+
const POLAR_API_VERSION = '2026-04';
|
|
11
|
+
/**
|
|
12
|
+
* Polar driver — merchant-of-record billing for software (polar.sh), written against the
|
|
13
|
+
* REST API (`https://api.polar.sh`, spec version `2026-04`) with `fetch`; the
|
|
14
|
+
* `@polar-sh/sdk` peer dependency is deliberately not used.
|
|
15
|
+
*
|
|
16
|
+
* Polar sells on your behalf: it is the legal seller of record and handles sales tax/VAT
|
|
17
|
+
* registration, calculation and remittance. That is a business arrangement the library
|
|
18
|
+
* does not model — it only changes which driver you configure.
|
|
19
|
+
*
|
|
20
|
+
* The shape of the API follows from that. There is no "charge a card for an amount"
|
|
21
|
+
* endpoint: everything starts from a **product** you created in Polar, and money moves
|
|
22
|
+
* through a hosted checkout. So {@link PolarDriver.charge} refuses, and
|
|
23
|
+
* {@link PolarDriver.createCheckout} is the way in.
|
|
24
|
+
*/
|
|
25
|
+
export class PolarDriver {
|
|
26
|
+
provider = 'polar';
|
|
27
|
+
/**
|
|
28
|
+
* Polar's checkout takes cards (plus the local methods it enables per country); the API
|
|
29
|
+
* has no field to request one, so the driver can only say "a card checkout" and let
|
|
30
|
+
* Polar present what it supports. Pix and boleto are not offered — nothing in the API
|
|
31
|
+
* reference produces either.
|
|
32
|
+
*/
|
|
33
|
+
supportedMethods = ['credit_card', 'undefined'];
|
|
34
|
+
/**
|
|
35
|
+
* `disputes: false`. Polar has no dispute API and no dispute webhook — see
|
|
36
|
+
* `#mapWebhookType`. As merchant of record Polar manages chargebacks end to end, so
|
|
37
|
+
* there is nothing here to read and nothing to submit.
|
|
38
|
+
*/
|
|
39
|
+
capabilities = { refunds: true, invoices: true, subscriptions: true, disputes: false };
|
|
40
|
+
#baseUrl;
|
|
41
|
+
#bearerToken;
|
|
42
|
+
#currency;
|
|
43
|
+
#webhookSecret;
|
|
44
|
+
#invoiceCtx;
|
|
45
|
+
constructor(ctx, config) {
|
|
46
|
+
this.#invoiceCtx = ctx;
|
|
47
|
+
this.#bearerToken = requireCredential({
|
|
48
|
+
driver: 'polar',
|
|
49
|
+
option: 'accessToken',
|
|
50
|
+
env: 'POLAR_ACCESS_TOKEN',
|
|
51
|
+
value: config.accessToken,
|
|
52
|
+
});
|
|
53
|
+
this.#currency = requireCurrency('polar', config.currency);
|
|
54
|
+
const sandbox = config.sandbox ?? process.env.NODE_ENV !== 'production';
|
|
55
|
+
this.#baseUrl = sandbox ? 'https://sandbox-api.polar.sh' : 'https://api.polar.sh';
|
|
56
|
+
this.#webhookSecret = config.webhookSecret ?? process.env.POLAR_WEBHOOK_SECRET;
|
|
57
|
+
}
|
|
58
|
+
// ── Customers ────────────────────────────────────────────────────────────────────────
|
|
59
|
+
async createCustomer(input) {
|
|
60
|
+
if (!input.email) {
|
|
61
|
+
throw new Error('[payments] Polar requires an email to create a customer — it is the identity Polar deduplicates on.');
|
|
62
|
+
}
|
|
63
|
+
const data = await this.#request('/v1/customers/', {
|
|
64
|
+
method: 'POST',
|
|
65
|
+
...(input.idempotencyKey !== undefined ? { idempotencyKey: input.idempotencyKey } : {}),
|
|
66
|
+
body: {
|
|
67
|
+
email: input.email,
|
|
68
|
+
...(input.name !== undefined ? { name: input.name } : {}),
|
|
69
|
+
...(input.taxId !== undefined ? { tax_id: input.taxId } : {}),
|
|
70
|
+
...(input.metadata !== undefined ? { metadata: input.metadata } : {}),
|
|
71
|
+
},
|
|
72
|
+
});
|
|
73
|
+
return this.#mapCustomer(data);
|
|
74
|
+
}
|
|
75
|
+
async findCustomer(customerId) {
|
|
76
|
+
try {
|
|
77
|
+
const data = await this.#request(`/v1/customers/${encodeURIComponent(customerId)}`);
|
|
78
|
+
return this.#mapCustomer(data);
|
|
79
|
+
}
|
|
80
|
+
catch (error) {
|
|
81
|
+
if (isNotFound(error))
|
|
82
|
+
return null;
|
|
83
|
+
throw error;
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
async updateCustomer(customerId, input) {
|
|
87
|
+
const data = await this.#request(`/v1/customers/${encodeURIComponent(customerId)}`, {
|
|
88
|
+
method: 'PATCH',
|
|
89
|
+
body: {
|
|
90
|
+
...(input.email !== undefined ? { email: input.email } : {}),
|
|
91
|
+
...(input.name !== undefined ? { name: input.name } : {}),
|
|
92
|
+
...(input.taxId !== undefined ? { tax_id: input.taxId } : {}),
|
|
93
|
+
...(input.metadata !== undefined ? { metadata: input.metadata } : {}),
|
|
94
|
+
},
|
|
95
|
+
});
|
|
96
|
+
return this.#mapCustomer(data);
|
|
97
|
+
}
|
|
98
|
+
// ── Payments ─────────────────────────────────────────────────────────────────────────
|
|
99
|
+
/**
|
|
100
|
+
* Polar has no endpoint that charges an amount. `POST /v1/orders/` exists but creates a
|
|
101
|
+
* *draft* order for an off-session charge against a saved payment method, needs a second
|
|
102
|
+
* `POST /v1/orders/{id}/finalize` call, and is gated behind the
|
|
103
|
+
* `off_session_charges_enabled` feature flag — nothing a driver can rely on. Faking a
|
|
104
|
+
* charge by opening a checkout and returning it as a settled `Payment` would report money
|
|
105
|
+
* that has not moved, so this refuses instead.
|
|
106
|
+
*/
|
|
107
|
+
async charge(_input) {
|
|
108
|
+
throw new Error('[payments] Polar does not expose a direct charge endpoint — as a merchant of record it sells through its own checkout. ' +
|
|
109
|
+
'Use `createCheckout({ planId: <polar product id>, successUrl })` and read the resulting order from the `order.paid` webhook.');
|
|
110
|
+
}
|
|
111
|
+
async findPayment(gatewayId) {
|
|
112
|
+
try {
|
|
113
|
+
const data = await this.#request(`/v1/orders/${encodeURIComponent(gatewayId)}`);
|
|
114
|
+
return this.#mapPayment(data);
|
|
115
|
+
}
|
|
116
|
+
catch (error) {
|
|
117
|
+
if (isNotFound(error))
|
|
118
|
+
return null;
|
|
119
|
+
throw error;
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* Refund an order. `paymentGatewayId` is a Polar **order** id, because an order is what
|
|
124
|
+
* this driver maps onto `Payment`.
|
|
125
|
+
*
|
|
126
|
+
* `options.idempotencyKey` goes out as Polar's `Idempotency-Key` header, which is where
|
|
127
|
+
* Polar actually deduplicates — a retry with the same key returns the first refund
|
|
128
|
+
* instead of issuing a second one.
|
|
129
|
+
*/
|
|
130
|
+
async refund(paymentGatewayId, amount, options) {
|
|
131
|
+
// `amount` is required by `POST /v1/refunds/` — a full refund has to name the figure,
|
|
132
|
+
// so an omitted amount is resolved from the order's own `refundable_amount` rather
|
|
133
|
+
// than guessed. Note it is the NET figure: Polar refunds the tax alongside it (in
|
|
134
|
+
// full, or prorated for a partial refund), so this is not `total_amount`.
|
|
135
|
+
let value = amount;
|
|
136
|
+
if (value === undefined) {
|
|
137
|
+
const order = await this.#request(`/v1/orders/${encodeURIComponent(paymentGatewayId)}`);
|
|
138
|
+
value = order.refundable_amount;
|
|
139
|
+
}
|
|
140
|
+
const data = await this.#request('/v1/refunds/', {
|
|
141
|
+
method: 'POST',
|
|
142
|
+
...(options?.idempotencyKey !== undefined ? { idempotencyKey: options.idempotencyKey } : {}),
|
|
143
|
+
body: {
|
|
144
|
+
order_id: paymentGatewayId,
|
|
145
|
+
amount: value,
|
|
146
|
+
// The driver is not told why the refund is happening, and Polar's enum has no
|
|
147
|
+
// "merchant initiated" member, so `other` is the only honest choice.
|
|
148
|
+
reason: 'other',
|
|
149
|
+
revoke_benefits: false,
|
|
150
|
+
},
|
|
151
|
+
});
|
|
152
|
+
const refund = {
|
|
153
|
+
id: data.id,
|
|
154
|
+
gatewayId: data.id,
|
|
155
|
+
provider: this.provider,
|
|
156
|
+
amount: { amount: data.amount, currency: data.currency.toLowerCase() },
|
|
157
|
+
status: data.status === 'succeeded'
|
|
158
|
+
? 'succeeded'
|
|
159
|
+
: data.status === 'pending'
|
|
160
|
+
? 'pending'
|
|
161
|
+
: 'failed',
|
|
162
|
+
createdAt: data.created_at,
|
|
163
|
+
};
|
|
164
|
+
publishRefundDiagnostics(refund);
|
|
165
|
+
return refund;
|
|
166
|
+
}
|
|
167
|
+
// ── Checkout ─────────────────────────────────────────────────────────────────────────
|
|
168
|
+
async createCheckout(input) {
|
|
169
|
+
const productId = input.planId ?? input.metadata?.productId;
|
|
170
|
+
if (!productId) {
|
|
171
|
+
throw new Error('[payments] Polar checkout needs a product — pass the Polar product id as `planId` (or `metadata.productId`). ' +
|
|
172
|
+
'Polar prices live on the product; there is no ad-hoc line item.');
|
|
173
|
+
}
|
|
174
|
+
const metadata = this.#metadataWithReference(this.#withoutDriverKeys(input.metadata), input.externalReference);
|
|
175
|
+
const data = await this.#request('/v1/checkouts/', {
|
|
176
|
+
method: 'POST',
|
|
177
|
+
...(input.idempotencyKey !== undefined ? { idempotencyKey: input.idempotencyKey } : {}),
|
|
178
|
+
body: {
|
|
179
|
+
products: [productId],
|
|
180
|
+
success_url: input.successUrl,
|
|
181
|
+
// Polar has no cancel URL. `return_url` is the closest thing it offers: it puts a
|
|
182
|
+
// back button on the checkout page pointing here.
|
|
183
|
+
...(input.cancelUrl !== undefined ? { return_url: input.cancelUrl } : {}),
|
|
184
|
+
// "Amount in cents, before discounts and taxes. Only useful for custom prices,
|
|
185
|
+
// it'll be ignored for fixed and free prices." — so this is safe to always send,
|
|
186
|
+
// but it does NOT override a fixed product price.
|
|
187
|
+
amount: input.amount,
|
|
188
|
+
...(input.currency !== undefined
|
|
189
|
+
? { currency: input.currency }
|
|
190
|
+
: { currency: this.#currency }),
|
|
191
|
+
...(input.customerId !== undefined ? { customer_id: input.customerId } : {}),
|
|
192
|
+
...(input.trialDays !== undefined
|
|
193
|
+
? { trial_interval: 'day', trial_interval_count: input.trialDays }
|
|
194
|
+
: {}),
|
|
195
|
+
...(Object.keys(metadata).length > 0 ? { metadata } : {}),
|
|
196
|
+
},
|
|
197
|
+
});
|
|
198
|
+
return {
|
|
199
|
+
id: data.id,
|
|
200
|
+
gatewayId: data.id,
|
|
201
|
+
provider: this.provider,
|
|
202
|
+
url: data.url,
|
|
203
|
+
status: this.#mapCheckoutStatus(data.status),
|
|
204
|
+
amount: { amount: data.total_amount, currency: data.currency.toLowerCase() },
|
|
205
|
+
...(data.customer_id ? { customerId: data.customer_id } : {}),
|
|
206
|
+
...(data.subscription_id ? { subscriptionId: data.subscription_id } : {}),
|
|
207
|
+
};
|
|
208
|
+
}
|
|
209
|
+
// ── Subscriptions ────────────────────────────────────────────────────────────────────
|
|
210
|
+
/**
|
|
211
|
+
* `POST /v1/subscriptions/` — Polar's own words: "This endpoint only allows to create
|
|
212
|
+
* subscription on free products. For paid products, use the checkout flow." Anything the
|
|
213
|
+
* contract carries that Polar cannot honor here is refused rather than dropped, because
|
|
214
|
+
* a dropped `amount` is a subscription billing a price nobody chose.
|
|
215
|
+
*/
|
|
216
|
+
async createSubscription(input) {
|
|
217
|
+
if (input.amount !== undefined) {
|
|
218
|
+
throw new Error('[payments] Polar takes the subscription price from the product, so `amount` cannot be set on a subscription. ' +
|
|
219
|
+
'Create the product with the price you want and pass its id as `planId`.');
|
|
220
|
+
}
|
|
221
|
+
if (input.cycle !== undefined) {
|
|
222
|
+
throw new Error('[payments] Polar takes the billing interval from the product, so `cycle` cannot be set on a subscription. ' +
|
|
223
|
+
'Create a product with the interval you want and pass its id as `planId`.');
|
|
224
|
+
}
|
|
225
|
+
if (input.trialDays !== undefined) {
|
|
226
|
+
throw new Error('[payments] Polar sets trials on the checkout, not on `POST /v1/subscriptions/`. ' +
|
|
227
|
+
'Pass `trialDays` to `createCheckout()` instead.');
|
|
228
|
+
}
|
|
229
|
+
if (input.card !== undefined) {
|
|
230
|
+
throw new Error('[payments] Polar has no tokenized-card input — as a merchant of record it collects the card on its own checkout. ' +
|
|
231
|
+
'Use `createCheckout({ planId })`.');
|
|
232
|
+
}
|
|
233
|
+
const data = await this.#request('/v1/subscriptions/', {
|
|
234
|
+
method: 'POST',
|
|
235
|
+
...(input.idempotencyKey !== undefined ? { idempotencyKey: input.idempotencyKey } : {}),
|
|
236
|
+
body: {
|
|
237
|
+
product_id: input.planId,
|
|
238
|
+
customer_id: input.customerId,
|
|
239
|
+
metadata: this.#metadataWithReference(input.metadata, input.externalReference),
|
|
240
|
+
},
|
|
241
|
+
});
|
|
242
|
+
const subscription = this.#mapSubscription(data);
|
|
243
|
+
publishSubscriptionDiagnostics(subscription, 'subscription.created');
|
|
244
|
+
return subscription;
|
|
245
|
+
}
|
|
246
|
+
async cancelSubscription(subscriptionGatewayId, options) {
|
|
247
|
+
const id = encodeURIComponent(subscriptionGatewayId);
|
|
248
|
+
// Polar splits the two: PATCH `cancel_at_period_end` schedules the cancellation for
|
|
249
|
+
// the end of the paid period; DELETE revokes access immediately.
|
|
250
|
+
const data = options?.atPeriodEnd === false
|
|
251
|
+
? await this.#request(`/v1/subscriptions/${id}`, { method: 'DELETE' })
|
|
252
|
+
: await this.#request(`/v1/subscriptions/${id}`, {
|
|
253
|
+
method: 'PATCH',
|
|
254
|
+
body: { cancel_at_period_end: true },
|
|
255
|
+
});
|
|
256
|
+
const subscription = this.#mapSubscription(data);
|
|
257
|
+
publishSubscriptionDiagnostics(subscription, 'subscription.canceled');
|
|
258
|
+
return subscription;
|
|
259
|
+
}
|
|
260
|
+
/**
|
|
261
|
+
* The only thing `PATCH /v1/subscriptions/{id}` can change about what a customer pays is
|
|
262
|
+
* *which product* they are on — Polar has no price field on a subscription. So a plan
|
|
263
|
+
* change is expressed as `metadata.productId`, and an `amount` is refused rather than
|
|
264
|
+
* silently discarded.
|
|
265
|
+
*/
|
|
266
|
+
async updateSubscription(subscriptionGatewayId, input) {
|
|
267
|
+
if (input.amount !== undefined) {
|
|
268
|
+
throw new Error('[payments] Polar has no subscription amount to update — the price belongs to the product. ' +
|
|
269
|
+
'Switch plans with `updateSubscription(id, { metadata: { productId: <new polar product id> } })`.');
|
|
270
|
+
}
|
|
271
|
+
if (input.description !== undefined) {
|
|
272
|
+
throw new Error('[payments] Polar subscriptions carry no description — the product supplies the name shown to the customer.');
|
|
273
|
+
}
|
|
274
|
+
const productId = input.metadata?.productId;
|
|
275
|
+
const prorationBehavior = input.metadata?.prorationBehavior;
|
|
276
|
+
if (productId === undefined) {
|
|
277
|
+
throw new Error('[payments] Nothing to update on a Polar subscription. The only supported change is the plan: ' +
|
|
278
|
+
'pass `metadata.productId` (optionally `metadata.prorationBehavior`).');
|
|
279
|
+
}
|
|
280
|
+
const data = await this.#request(`/v1/subscriptions/${encodeURIComponent(subscriptionGatewayId)}`, {
|
|
281
|
+
method: 'PATCH',
|
|
282
|
+
...(input.idempotencyKey !== undefined ? { idempotencyKey: input.idempotencyKey } : {}),
|
|
283
|
+
body: {
|
|
284
|
+
product_id: productId,
|
|
285
|
+
...(prorationBehavior !== undefined ? { proration_behavior: prorationBehavior } : {}),
|
|
286
|
+
},
|
|
287
|
+
});
|
|
288
|
+
return this.#mapSubscription(data);
|
|
289
|
+
}
|
|
290
|
+
async findSubscription(gatewayId) {
|
|
291
|
+
try {
|
|
292
|
+
const data = await this.#request(`/v1/subscriptions/${encodeURIComponent(gatewayId)}`);
|
|
293
|
+
return this.#mapSubscription(data);
|
|
294
|
+
}
|
|
295
|
+
catch (error) {
|
|
296
|
+
if (isNotFound(error))
|
|
297
|
+
return null;
|
|
298
|
+
throw error;
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
// ── Invoices ─────────────────────────────────────────────────────────────────────────
|
|
302
|
+
/**
|
|
303
|
+
* Polar's orders are its invoices — `invoice_number` is on the order itself. The PDF
|
|
304
|
+
* lives behind a per-order `GET /v1/orders/{id}/invoice`, so `hostedPdfUrl` is left
|
|
305
|
+
* unset here rather than firing one request per row.
|
|
306
|
+
*/
|
|
307
|
+
async listInvoices(customerId) {
|
|
308
|
+
const data = await this.#request(`/v1/orders/?customer_id=${encodeURIComponent(customerId)}&limit=100`);
|
|
309
|
+
return (data.items ?? []).map((order) => ({
|
|
310
|
+
id: order.id,
|
|
311
|
+
gatewayId: order.id,
|
|
312
|
+
provider: this.provider,
|
|
313
|
+
customerId: order.customer_id,
|
|
314
|
+
...(order.subscription_id ? { subscriptionId: order.subscription_id } : {}),
|
|
315
|
+
status: this.#mapInvoiceStatus(order.status),
|
|
316
|
+
amount: { amount: order.total_amount, currency: order.currency.toLowerCase() },
|
|
317
|
+
createdAt: order.created_at,
|
|
318
|
+
...(order.invoice_number ? { number: order.invoice_number } : {}),
|
|
319
|
+
payload: order,
|
|
320
|
+
}));
|
|
321
|
+
}
|
|
322
|
+
// ── Webhooks ─────────────────────────────────────────────────────────────────────────
|
|
323
|
+
/**
|
|
324
|
+
* Whether a delivery to `POST /payments/webhook/:provider` can be authenticated.
|
|
325
|
+
*
|
|
326
|
+
* `parseWebhook` already refuses without the secret — declaring it moves the refusal to boot.
|
|
327
|
+
*/
|
|
328
|
+
get webhookVerification() {
|
|
329
|
+
return this.#webhookSecret !== undefined ? 'configured' : 'unconfigured';
|
|
330
|
+
}
|
|
331
|
+
parseWebhook(rawBody, headers) {
|
|
332
|
+
if (!this.#webhookSecret) {
|
|
333
|
+
throw new Error('[payments] Polar webhook processing requires a webhook secret. Set `POLAR_WEBHOOK_SECRET` env or pass `webhookSecret` to `payments.polar()`.');
|
|
334
|
+
}
|
|
335
|
+
// Polar signs with Standard Webhooks, but its key derivation is NOT the spec default:
|
|
336
|
+
// `@polar-sh/sdk` base64-*encodes* the secret before handing it to the reference
|
|
337
|
+
// library, which base64-decodes it again — so the HMAC key is the secret's raw UTF-8
|
|
338
|
+
// bytes, `whsec_` prefix and all. Decoding it as base64 (what Dodo and Svix do) would
|
|
339
|
+
// reject every genuine Polar delivery.
|
|
340
|
+
const id = this.#verifiedEventId(rawBody, headers, this.#webhookSecret);
|
|
341
|
+
const payload = JSON.parse(rawBody);
|
|
342
|
+
const data = payload.data ?? {};
|
|
343
|
+
return {
|
|
344
|
+
id,
|
|
345
|
+
provider: this.provider,
|
|
346
|
+
type: this.#mapWebhookType(payload.type),
|
|
347
|
+
createdAt: payload.timestamp ?? new Date().toISOString(),
|
|
348
|
+
data: this.#mapWebhookData(payload.type, data),
|
|
349
|
+
raw: payload,
|
|
350
|
+
};
|
|
351
|
+
}
|
|
352
|
+
/**
|
|
353
|
+
* Verify the delivery and return the event id, which for Standard Webhooks lives in the
|
|
354
|
+
* `webhook-id` header rather than the body — it is what the idempotency ledger
|
|
355
|
+
* deduplicates on.
|
|
356
|
+
*
|
|
357
|
+
* `keyEncoding: 'raw'` is the Polar-specific half: the HMAC key is the secret's UTF-8
|
|
358
|
+
* bytes verbatim, `whsec_` prefix included, NOT the spec's base64-decoded default.
|
|
359
|
+
*/
|
|
360
|
+
#verifiedEventId(rawBody, headers, secret) {
|
|
361
|
+
const id = headerValue(headers, 'webhook-id');
|
|
362
|
+
if (id === undefined ||
|
|
363
|
+
headerValue(headers, 'webhook-timestamp') === undefined ||
|
|
364
|
+
headerValue(headers, 'webhook-signature') === undefined) {
|
|
365
|
+
throw new Error('[payments] Missing Standard Webhooks headers on Polar request (webhook-id, webhook-timestamp, webhook-signature).');
|
|
366
|
+
}
|
|
367
|
+
if (!verifyStandardWebhookSignature({ rawBody, headers, secret, keyEncoding: 'raw' })) {
|
|
368
|
+
throw new Error('[payments] Invalid Polar webhook signature.');
|
|
369
|
+
}
|
|
370
|
+
return id;
|
|
371
|
+
}
|
|
372
|
+
// ── Mappers ──────────────────────────────────────────────────────────────────────────
|
|
373
|
+
#mapCustomer(data) {
|
|
374
|
+
// Polar answers `tax_id` as a `[number, type]` pair; the contract wants the number.
|
|
375
|
+
const taxId = Array.isArray(data.tax_id) ? data.tax_id[0] : data.tax_id;
|
|
376
|
+
return {
|
|
377
|
+
id: data.id,
|
|
378
|
+
email: data.email,
|
|
379
|
+
...(data.name ? { name: data.name } : {}),
|
|
380
|
+
...(taxId ? { taxId } : {}),
|
|
381
|
+
...(data.metadata !== undefined && Object.keys(data.metadata).length > 0
|
|
382
|
+
? { metadata: data.metadata }
|
|
383
|
+
: {}),
|
|
384
|
+
};
|
|
385
|
+
}
|
|
386
|
+
#mapPayment(data) {
|
|
387
|
+
const statusMap = {
|
|
388
|
+
draft: 'pending',
|
|
389
|
+
pending: 'pending',
|
|
390
|
+
paid: 'paid',
|
|
391
|
+
// A partial refund leaves the order settled; only a full one flips it to refunded.
|
|
392
|
+
partially_refunded: 'paid',
|
|
393
|
+
refunded: 'refunded',
|
|
394
|
+
void: 'canceled',
|
|
395
|
+
};
|
|
396
|
+
const result = {
|
|
397
|
+
id: data.id,
|
|
398
|
+
gatewayId: data.id,
|
|
399
|
+
provider: this.provider,
|
|
400
|
+
amount: { amount: data.total_amount, currency: data.currency.toLowerCase() },
|
|
401
|
+
status: statusMap[data.status] ?? 'pending',
|
|
402
|
+
customerId: data.customer_id,
|
|
403
|
+
payload: data,
|
|
404
|
+
createdAt: data.created_at,
|
|
405
|
+
};
|
|
406
|
+
if (data.subscription_id)
|
|
407
|
+
result.subscriptionId = data.subscription_id;
|
|
408
|
+
// Polar exposes no settlement timestamp on the order, so a paid order dates its
|
|
409
|
+
// payment from when the order was created rather than inventing a moment.
|
|
410
|
+
if (data.paid)
|
|
411
|
+
result.paidAt = data.created_at;
|
|
412
|
+
return result;
|
|
413
|
+
}
|
|
414
|
+
#mapSubscription(data) {
|
|
415
|
+
const statusMap = {
|
|
416
|
+
incomplete: 'incomplete',
|
|
417
|
+
incomplete_expired: 'ended',
|
|
418
|
+
trialing: 'trialing',
|
|
419
|
+
active: 'active',
|
|
420
|
+
past_due: 'past_due',
|
|
421
|
+
canceled: 'canceled',
|
|
422
|
+
unpaid: 'past_due',
|
|
423
|
+
// A paused Polar subscription still exists and will bill again — but it is not
|
|
424
|
+
// billing NOW, so reporting it as `active` entitled a subscriber who is not paying.
|
|
425
|
+
paused: 'paused',
|
|
426
|
+
};
|
|
427
|
+
return {
|
|
428
|
+
id: data.id,
|
|
429
|
+
gatewayId: data.id,
|
|
430
|
+
provider: this.provider,
|
|
431
|
+
customerId: data.customer_id,
|
|
432
|
+
status: statusMap[data.status] ?? 'active',
|
|
433
|
+
planId: data.product_id,
|
|
434
|
+
amount: { amount: data.amount, currency: data.currency.toLowerCase() },
|
|
435
|
+
...(data.trial_end ? { trialEndsAt: data.trial_end } : {}),
|
|
436
|
+
...((data.ends_at ?? data.ended_at)
|
|
437
|
+
? { endsAt: (data.ends_at ?? data.ended_at) }
|
|
438
|
+
: {}),
|
|
439
|
+
...(data.current_period_start ? { currentPeriodStart: data.current_period_start } : {}),
|
|
440
|
+
...(data.current_period_end ? { currentPeriodEnd: data.current_period_end } : {}),
|
|
441
|
+
payload: data,
|
|
442
|
+
createdAt: data.created_at,
|
|
443
|
+
};
|
|
444
|
+
}
|
|
445
|
+
#mapCheckoutStatus(status) {
|
|
446
|
+
switch (status) {
|
|
447
|
+
case 'succeeded':
|
|
448
|
+
return 'complete';
|
|
449
|
+
case 'expired':
|
|
450
|
+
case 'failed':
|
|
451
|
+
return 'expired';
|
|
452
|
+
default:
|
|
453
|
+
// `confirmed` means the payment is being processed — the session is not settled yet.
|
|
454
|
+
return 'open';
|
|
455
|
+
}
|
|
456
|
+
}
|
|
457
|
+
#mapInvoiceStatus(status) {
|
|
458
|
+
switch (status) {
|
|
459
|
+
case 'paid':
|
|
460
|
+
case 'partially_refunded':
|
|
461
|
+
case 'refunded':
|
|
462
|
+
return 'paid';
|
|
463
|
+
case 'pending':
|
|
464
|
+
return 'pending';
|
|
465
|
+
case 'void':
|
|
466
|
+
return 'void';
|
|
467
|
+
default:
|
|
468
|
+
return 'draft';
|
|
469
|
+
}
|
|
470
|
+
}
|
|
471
|
+
#mapWebhookType(event) {
|
|
472
|
+
switch (event) {
|
|
473
|
+
case 'order.paid':
|
|
474
|
+
return 'payment.succeeded';
|
|
475
|
+
case 'order.refunded':
|
|
476
|
+
case 'refund.created':
|
|
477
|
+
return 'payment.refunded';
|
|
478
|
+
case 'order.created':
|
|
479
|
+
case 'order.updated':
|
|
480
|
+
case 'refund.updated':
|
|
481
|
+
return 'payment.updated';
|
|
482
|
+
case 'subscription.created':
|
|
483
|
+
return 'subscription.created';
|
|
484
|
+
case 'subscription.active':
|
|
485
|
+
case 'subscription.updated':
|
|
486
|
+
case 'subscription.uncanceled':
|
|
487
|
+
case 'subscription.past_due':
|
|
488
|
+
// `cycled` is the renewal event, and it fires whether or not the renewal payment
|
|
489
|
+
// succeeded — before the renewal order exists. It is a subscription state change,
|
|
490
|
+
// not a payment.
|
|
491
|
+
case 'subscription.cycled':
|
|
492
|
+
case 'subscription.paused':
|
|
493
|
+
case 'subscription.resumed':
|
|
494
|
+
return 'subscription.updated';
|
|
495
|
+
case 'subscription.canceled':
|
|
496
|
+
case 'subscription.revoked':
|
|
497
|
+
return 'subscription.canceled';
|
|
498
|
+
default:
|
|
499
|
+
// checkout.*, customer.*, benefit*.*, product.*, organization.* — passed through so
|
|
500
|
+
// an app handler can subscribe to them by their Polar name.
|
|
501
|
+
//
|
|
502
|
+
// There is deliberately no dispute type here: **Polar's event catalogue has NO
|
|
503
|
+
// dispute or chargeback event** — no warning, no chargeback, no resolution. Nor is
|
|
504
|
+
// there a dispute status: an Order is `pending`, `paid`, `refunded`,
|
|
505
|
+
// `partially_refunded` or `void`, and none of those means charged back.
|
|
506
|
+
//
|
|
507
|
+
// That is the merchant-of-record bargain rather than an oversight: Polar is the
|
|
508
|
+
// seller on the buyer's statement, so the chargeback is raised against Polar, Polar
|
|
509
|
+
// runs the dispute (including Rapid Dispute Resolution, whose auto-refunds arrive
|
|
510
|
+
// as an ordinary `refund.created`), and the $15 network fee is deducted from the
|
|
511
|
+
// balance whatever the outcome. There is no deadline that belongs to you and no
|
|
512
|
+
// evidence you can file. Forcing an unrelated event into `payment.disputed` would
|
|
513
|
+
// invent a notification that does not exist.
|
|
514
|
+
return event;
|
|
515
|
+
}
|
|
516
|
+
}
|
|
517
|
+
/**
|
|
518
|
+
* Normalize the event body onto the shapes the billing layer's built-in sync expects.
|
|
519
|
+
* `externalReference` comes back out of `metadata.external_reference`, which Polar copies
|
|
520
|
+
* from the checkout onto the resulting order and subscription.
|
|
521
|
+
*/
|
|
522
|
+
#mapWebhookData(event, data) {
|
|
523
|
+
if (event.startsWith('order.')) {
|
|
524
|
+
const order = data;
|
|
525
|
+
return {
|
|
526
|
+
gatewayId: order.id,
|
|
527
|
+
amount: order.total_amount,
|
|
528
|
+
currency: (order.currency ?? this.#currency).toLowerCase(),
|
|
529
|
+
customerId: order.customer_id,
|
|
530
|
+
...(order.subscription_id ? { subscriptionId: order.subscription_id } : {}),
|
|
531
|
+
...this.#referenceFrom(order.metadata),
|
|
532
|
+
};
|
|
533
|
+
}
|
|
534
|
+
if (event.startsWith('refund.')) {
|
|
535
|
+
const refund = data;
|
|
536
|
+
// Keyed by the ORDER, not the refund: the order is what this driver reports as the
|
|
537
|
+
// payment, so it is the row an app handler has to find.
|
|
538
|
+
return {
|
|
539
|
+
gatewayId: refund.order_id,
|
|
540
|
+
amount: refund.amount,
|
|
541
|
+
currency: (refund.currency ?? this.#currency).toLowerCase(),
|
|
542
|
+
customerId: refund.customer_id,
|
|
543
|
+
...(refund.subscription_id ? { subscriptionId: refund.subscription_id } : {}),
|
|
544
|
+
};
|
|
545
|
+
}
|
|
546
|
+
if (event.startsWith('subscription.')) {
|
|
547
|
+
const subscription = data;
|
|
548
|
+
const mapped = this.#mapSubscription(subscription);
|
|
549
|
+
return {
|
|
550
|
+
gatewayId: mapped.gatewayId,
|
|
551
|
+
customerId: mapped.customerId,
|
|
552
|
+
status: mapped.status,
|
|
553
|
+
planId: mapped.planId,
|
|
554
|
+
...(mapped.trialEndsAt !== undefined ? { trialEndsAt: mapped.trialEndsAt } : {}),
|
|
555
|
+
...(mapped.endsAt !== undefined ? { endsAt: mapped.endsAt } : {}),
|
|
556
|
+
...this.#referenceFrom(subscription.metadata),
|
|
557
|
+
};
|
|
558
|
+
}
|
|
559
|
+
return data;
|
|
560
|
+
}
|
|
561
|
+
#referenceFrom(metadata) {
|
|
562
|
+
const reference = metadata?.external_reference;
|
|
563
|
+
return {
|
|
564
|
+
...(typeof reference === 'string' ? { externalReference: reference } : {}),
|
|
565
|
+
...(metadata !== undefined && Object.keys(metadata).length > 0 ? { metadata } : {}),
|
|
566
|
+
};
|
|
567
|
+
}
|
|
568
|
+
/**
|
|
569
|
+
* Polar echoes checkout/subscription `metadata` on the order and subscription it
|
|
570
|
+
* produces, which makes it the only place `externalReference` can survive the round
|
|
571
|
+
* trip to a webhook.
|
|
572
|
+
*/
|
|
573
|
+
#metadataWithReference(metadata, externalReference) {
|
|
574
|
+
return {
|
|
575
|
+
...(metadata ?? {}),
|
|
576
|
+
...(externalReference !== undefined ? { external_reference: externalReference } : {}),
|
|
577
|
+
};
|
|
578
|
+
}
|
|
579
|
+
/** Drop the keys this driver reads as arguments, so they don't leak into Polar metadata. */
|
|
580
|
+
#withoutDriverKeys(metadata) {
|
|
581
|
+
const { productId: _productId, ...rest } = metadata ?? {};
|
|
582
|
+
return rest;
|
|
583
|
+
}
|
|
584
|
+
/**
|
|
585
|
+
* `idempotencyKey` goes out as Polar's `Idempotency-Key` header — Polar documents it for
|
|
586
|
+
* mutating requests (POST, PATCH, DELETE) and deduplicates on nothing else, so a key
|
|
587
|
+
* written into `metadata` would be echoed back and protect nothing.
|
|
588
|
+
*/
|
|
589
|
+
async #request(path, options = {}) {
|
|
590
|
+
return httpRequest(path, {
|
|
591
|
+
baseUrl: this.#baseUrl,
|
|
592
|
+
...(options.method !== undefined ? { method: options.method } : {}),
|
|
593
|
+
...(options.body !== undefined ? { body: options.body } : {}),
|
|
594
|
+
bearerToken: this.#bearerToken,
|
|
595
|
+
headers: {
|
|
596
|
+
'Polar-Version': POLAR_API_VERSION,
|
|
597
|
+
...(options.idempotencyKey !== undefined
|
|
598
|
+
? { 'Idempotency-Key': options.idempotencyKey }
|
|
599
|
+
: {}),
|
|
600
|
+
},
|
|
601
|
+
});
|
|
602
|
+
}
|
|
603
|
+
}
|
|
604
|
+
//# sourceMappingURL=polar.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"polar.js","sourceRoot":"","sources":["../../../src/drivers/polar.ts"],"names":[],"mappings":"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"}
|