@volter/twin-stripe 2.0.38 → 3.0.1
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/README.md +112 -207
- package/dist/generated/pack-facts.json +94 -0
- package/dist/journeys/coverage.json +596 -0
- package/dist/journeys/customer-life.json +6108 -0
- package/dist/journeys/customer-life.outline.md +371 -0
- package/dist/journeys/decisions.json +677 -0
- package/dist/journeys/demand.json +706 -0
- package/dist/journeys/score.json +853 -0
- package/dist/journeys/unreachable.json +102 -0
- package/dist/journeys/vendor-examples.json +8010 -0
- package/dist/spec/SOURCE.md +18 -0
- package/dist/spec/doc-examples.json +445 -0
- package/dist/spec/fixtures3.json.gz +0 -0
- package/dist/spec/openapi.json.gz +0 -0
- package/dist/spec/patches.json +34 -0
- package/dist/spec/sources.json +306 -0
- package/dist/src/cli.d.ts +0 -1
- package/dist/src/cli.js +11 -31
- package/dist/src/engine/after-payment.d.ts +8 -0
- package/dist/src/engine/after-payment.js +27 -0
- package/dist/src/engine/apps-secrets.d.ts +1 -0
- package/dist/src/engine/apps-secrets.js +3 -0
- package/dist/src/engine/balance.d.ts +5 -0
- package/dist/src/engine/balance.js +15 -0
- package/dist/src/engine/checkout.d.ts +24 -0
- package/dist/src/engine/checkout.js +30 -0
- package/dist/src/engine/common.d.ts +19 -0
- package/dist/src/engine/common.js +34 -0
- package/dist/src/engine/connect.d.ts +45 -0
- package/dist/src/engine/connect.js +108 -0
- package/dist/src/engine/customers.d.ts +4 -0
- package/dist/src/engine/customers.js +8 -0
- package/dist/src/engine/display.d.ts +11 -0
- package/dist/src/engine/display.js +13 -0
- package/dist/src/engine/files.d.ts +11 -0
- package/dist/src/engine/files.js +23 -0
- package/dist/src/engine/invoices.d.ts +21 -0
- package/dist/src/engine/invoices.js +84 -0
- package/dist/src/engine/issuing.d.ts +33 -0
- package/dist/src/engine/issuing.js +54 -0
- package/dist/src/engine/ledger.d.ts +8 -0
- package/dist/src/engine/ledger.js +8 -0
- package/dist/src/engine/oauth.d.ts +4 -0
- package/dist/src/engine/oauth.js +24 -0
- package/dist/src/engine/onboarding.d.ts +13 -0
- package/dist/src/engine/onboarding.js +42 -0
- package/dist/src/{stripe-params.d.ts → engine/params.d.ts} +20 -3
- package/dist/src/{stripe-params.js → engine/params.js} +7 -60
- package/dist/src/engine/payment-intents.d.ts +10 -0
- package/dist/src/engine/payment-intents.js +27 -0
- package/dist/src/engine/payment-methods.d.ts +16 -0
- package/dist/src/engine/payment-methods.js +22 -0
- package/dist/src/engine/radar.d.ts +2 -0
- package/dist/src/engine/radar.js +5 -0
- package/dist/src/engine/refunds.d.ts +1 -0
- package/dist/src/engine/refunds.js +3 -0
- package/dist/src/engine/renewals.d.ts +36 -0
- package/dist/src/engine/renewals.js +65 -0
- package/dist/src/{stripe-twin.d.ts → engine/stripe.d.ts} +12 -45
- package/dist/src/{stripe-twin.js → engine/stripe.js} +53 -387
- package/dist/src/engine/subscriptions.d.ts +11 -0
- package/dist/src/engine/subscriptions.js +30 -0
- package/dist/src/engine/transfers.d.ts +2 -0
- package/dist/src/engine/transfers.js +1 -0
- package/dist/src/{stripe-version.d.ts → engine/version.d.ts} +0 -2
- package/dist/src/{stripe-version.js → engine/version.js} +21 -9
- package/dist/src/engine/webhook-endpoints.d.ts +1 -0
- package/dist/src/engine/webhook-endpoints.js +12 -0
- package/dist/src/engine/webhooks.d.ts +31 -0
- package/dist/src/engine/webhooks.js +68 -0
- package/dist/src/fetch.d.ts +2 -0
- package/dist/src/fetch.js +26 -0
- package/dist/src/generated/surface.gen.json +1 -1
- package/dist/src/generated/ui.gen.json +1 -1
- package/dist/src/index.d.ts +5 -14
- package/dist/src/index.js +10 -75
- package/dist/src/manifest.js +478 -876
- package/dist/src/screens/billing-portal.d.ts +3 -0
- package/dist/src/screens/{portal.js → billing-portal.js} +32 -58
- package/dist/src/screens/checkout-js.d.ts +2 -0
- package/dist/src/screens/checkout-js.js +84 -0
- package/dist/src/screens/checkout.d.ts +2 -31
- package/dist/src/screens/checkout.js +32 -121
- package/dist/src/screens/connect-onboarding.d.ts +3 -0
- package/dist/src/screens/{onboarding.js → connect-onboarding.js} +38 -104
- package/dist/src/screens/dashboard.d.ts +3 -0
- package/dist/src/screens/dashboard.js +116 -0
- package/dist/src/screens/shared.d.ts +27 -0
- package/dist/src/screens/shared.js +87 -0
- package/dist/src/screens/stripe-js.d.ts +3 -0
- package/dist/src/screens/stripe-js.js +95 -0
- package/dist/src/semantics/account.d.ts +2 -0
- package/dist/src/semantics/account.js +8 -0
- package/dist/src/semantics/account_links.d.ts +2 -0
- package/dist/src/semantics/account_links.js +22 -0
- package/dist/src/semantics/accounts.d.ts +4 -0
- package/dist/src/semantics/accounts.js +40 -0
- package/dist/src/semantics/apps.d.ts +4 -0
- package/dist/src/semantics/{apps-secrets.js → apps.js} +14 -26
- package/dist/src/semantics/around.d.ts +2 -0
- package/dist/src/semantics/around.js +13 -0
- package/dist/src/semantics/balance.d.ts +2 -11
- package/dist/src/semantics/balance.js +3 -194
- package/dist/src/semantics/balance_transactions.d.ts +2 -0
- package/dist/src/semantics/balance_transactions.js +15 -0
- package/dist/src/semantics/billing_portal.d.ts +4 -0
- package/dist/src/semantics/billing_portal.js +36 -0
- package/dist/src/semantics/charges.d.ts +3 -28
- package/dist/src/semantics/charges.js +5 -202
- package/dist/src/semantics/checkout.d.ts +3 -20
- package/dist/src/semantics/checkout.js +21 -271
- package/dist/src/semantics/clock.d.ts +2 -0
- package/dist/src/semantics/clock.js +15 -0
- package/dist/src/semantics/coupons.d.ts +2 -6
- package/dist/src/semantics/coupons.js +2 -60
- package/dist/src/semantics/customers.d.ts +5 -6
- package/dist/src/semantics/customers.js +47 -413
- package/dist/src/semantics/doors.d.ts +23 -0
- package/dist/src/semantics/doors.js +73 -0
- package/dist/src/semantics/entitlements.d.ts +0 -2
- package/dist/src/semantics/entitlements.js +4 -95
- package/dist/src/semantics/events.d.ts +11 -0
- package/dist/src/semantics/events.js +31 -0
- package/dist/src/semantics/index.d.ts +2 -0
- package/dist/src/semantics/index.js +85 -0
- package/dist/src/semantics/invoice_payments.d.ts +2 -0
- package/dist/src/semantics/invoice_payments.js +12 -0
- package/dist/src/semantics/invoices.d.ts +11 -18
- package/dist/src/semantics/invoices.js +121 -440
- package/dist/src/semantics/issuing.d.ts +6 -13
- package/dist/src/semantics/issuing.js +58 -556
- package/dist/src/semantics/payment_intents.d.ts +3 -0
- package/dist/src/semantics/payment_intents.js +71 -0
- package/dist/src/semantics/payment_methods.d.ts +3 -0
- package/dist/src/semantics/payment_methods.js +15 -0
- package/dist/src/semantics/payouts.d.ts +3 -0
- package/dist/src/semantics/payouts.js +28 -0
- package/dist/src/semantics/prices.d.ts +4 -0
- package/dist/src/semantics/prices.js +37 -0
- package/dist/src/semantics/products.d.ts +4 -2
- package/dist/src/semantics/products.js +12 -138
- package/dist/src/semantics/promotion_codes.d.ts +3 -0
- package/dist/src/semantics/promotion_codes.js +35 -0
- package/dist/src/semantics/radar.d.ts +2 -2
- package/dist/src/semantics/radar.js +5 -74
- package/dist/src/semantics/refunds.d.ts +2 -9
- package/dist/src/semantics/refunds.js +3 -193
- package/dist/src/semantics/shared.d.ts +558 -55
- package/dist/src/semantics/shared.js +2070 -114
- package/dist/src/semantics/states.d.ts +462 -0
- package/dist/src/semantics/states.js +634 -0
- package/dist/src/semantics/subscriptions.d.ts +6 -11
- package/dist/src/semantics/subscriptions.js +37 -530
- package/dist/src/semantics/test_helpers.d.ts +3 -0
- package/dist/src/semantics/test_helpers.js +125 -0
- package/dist/src/semantics/transfers.d.ts +2 -2
- package/dist/src/semantics/transfers.js +6 -101
- package/dist/src/semantics/webhook_endpoints.d.ts +2 -0
- package/dist/src/semantics/webhook_endpoints.js +26 -0
- package/dist/src/server.d.ts +7 -0
- package/dist/src/server.js +7 -0
- package/generated/pack-facts.json +94 -0
- package/journeys/coverage.json +596 -0
- package/journeys/customer-life.json +6108 -0
- package/journeys/customer-life.outline.md +371 -0
- package/journeys/decisions.json +677 -0
- package/journeys/demand.json +706 -0
- package/journeys/score.json +853 -0
- package/journeys/unreachable.json +102 -0
- package/journeys/vendor-examples.json +8010 -0
- package/package.json +11 -20
- package/spec/SOURCE.md +18 -0
- package/spec/doc-examples.json +445 -0
- package/spec/fixtures3.json.gz +0 -0
- package/spec/openapi.json.gz +0 -0
- package/spec/patches.json +34 -0
- package/spec/sources.json +306 -0
- package/src/cli.ts +11 -28
- package/src/engine/after-payment.ts +29 -0
- package/src/engine/apps-secrets.ts +4 -0
- package/src/engine/balance.ts +32 -0
- package/src/engine/checkout.ts +39 -0
- package/src/engine/common.ts +49 -0
- package/src/engine/connect.ts +106 -0
- package/src/engine/customers.ts +10 -0
- package/src/engine/display.ts +18 -0
- package/src/engine/files.ts +28 -0
- package/src/engine/invoices.ts +102 -0
- package/src/engine/issuing.ts +66 -0
- package/src/engine/ledger.ts +48 -0
- package/src/engine/oauth.ts +18 -0
- package/src/engine/onboarding.ts +53 -0
- package/src/{stripe-params.ts → engine/params.ts} +7 -56
- package/src/engine/payment-intents.ts +32 -0
- package/src/engine/payment-methods.ts +24 -0
- package/src/engine/radar.ts +6 -0
- package/src/engine/refunds.ts +3 -0
- package/src/engine/renewals.ts +72 -0
- package/src/{stripe-twin.ts → engine/stripe.ts} +57 -400
- package/src/engine/subscriptions.ts +37 -0
- package/src/engine/transfers.ts +22 -0
- package/src/{stripe-version.ts → engine/version.ts} +19 -10
- package/src/engine/webhook-endpoints.ts +14 -0
- package/src/engine/webhooks.ts +70 -0
- package/src/fetch.ts +27 -0
- package/src/generated/surface.gen.json +1 -1
- package/src/generated/ui.gen.json +1 -1
- package/src/index.ts +10 -116
- package/src/manifest.ts +480 -904
- package/src/screens/{portal.tsx → billing-portal.tsx} +35 -42
- package/src/screens/checkout-js.ts +80 -0
- package/src/screens/checkout.tsx +32 -96
- package/src/screens/{onboarding.tsx → connect-onboarding.tsx} +39 -85
- package/src/screens/dashboard.tsx +178 -0
- package/src/screens/shared.tsx +84 -0
- package/src/screens/stripe-js.ts +102 -0
- package/src/semantics/account.ts +10 -0
- package/src/semantics/account_links.ts +20 -0
- package/src/semantics/accounts.ts +44 -0
- package/src/semantics/{apps-secrets.ts → apps.ts} +17 -33
- package/src/semantics/around.ts +17 -0
- package/src/semantics/balance.ts +6 -208
- package/src/semantics/balance_transactions.ts +18 -0
- package/src/semantics/billing_portal.ts +45 -0
- package/src/semantics/charges.ts +8 -212
- package/src/semantics/checkout.ts +25 -276
- package/src/semantics/clock.ts +19 -0
- package/src/semantics/coupons.ts +5 -68
- package/src/semantics/customers.ts +48 -414
- package/src/semantics/doors.ts +79 -0
- package/src/semantics/entitlements.ts +3 -94
- package/src/semantics/events.ts +37 -0
- package/src/semantics/index.ts +89 -0
- package/src/semantics/invoice_payments.ts +16 -0
- package/src/semantics/invoices.ts +112 -441
- package/src/semantics/issuing.ts +57 -573
- package/src/semantics/payment_intents.ts +76 -0
- package/src/semantics/payment_methods.ts +20 -0
- package/src/semantics/payouts.ts +29 -0
- package/src/semantics/prices.ts +41 -0
- package/src/semantics/products.ts +12 -146
- package/src/semantics/promotion_codes.ts +38 -0
- package/src/semantics/radar.ts +8 -79
- package/src/semantics/refunds.ts +4 -216
- package/src/semantics/shared.ts +2089 -135
- package/src/semantics/states.ts +662 -0
- package/src/semantics/subscriptions.ts +39 -542
- package/src/semantics/test_helpers.ts +119 -0
- package/src/semantics/transfers.ts +10 -132
- package/src/semantics/webhook_endpoints.ts +27 -0
- package/src/server.ts +7 -0
- package/client/dashboard-api.ts +0 -286
- package/client/stripe-mirror.css +0 -277
- package/client/stripe-mirror.tsx +0 -1559
- package/dist/client/dashboard-api.d.ts +0 -107
- package/dist/client/dashboard-api.js +0 -238
- package/dist/client/dashboard-api.ts +0 -286
- package/dist/client/stripe-mirror.bundle.js +0 -236
- package/dist/client/stripe-mirror.css +0 -277
- package/dist/client/stripe-mirror.d.ts +0 -134
- package/dist/client/stripe-mirror.js +0 -859
- package/dist/client/stripe-mirror.tsx +0 -1559
- package/dist/src/screens/connect-oauth.d.ts +0 -27
- package/dist/src/screens/connect-oauth.js +0 -414
- package/dist/src/screens/connect-settings.d.ts +0 -22
- package/dist/src/screens/connect-settings.js +0 -103
- package/dist/src/screens/consent-skin.d.ts +0 -4
- package/dist/src/screens/consent-skin.js +0 -18
- package/dist/src/screens/financial-connections.d.ts +0 -5
- package/dist/src/screens/financial-connections.js +0 -90
- package/dist/src/screens/identity.d.ts +0 -5
- package/dist/src/screens/identity.js +0 -86
- package/dist/src/screens/onboarding.d.ts +0 -13
- package/dist/src/screens/portal.d.ts +0 -5
- package/dist/src/screens/public-details.d.ts +0 -5
- package/dist/src/screens/public-details.js +0 -90
- package/dist/src/semantics/after-payment.d.ts +0 -22
- package/dist/src/semantics/after-payment.js +0 -99
- package/dist/src/semantics/apps-secrets.d.ts +0 -2
- package/dist/src/semantics/billing.d.ts +0 -2
- package/dist/src/semantics/billing.js +0 -220
- package/dist/src/semantics/connect.d.ts +0 -5
- package/dist/src/semantics/connect.js +0 -493
- package/dist/src/semantics/credit-notes.d.ts +0 -2
- package/dist/src/semantics/credit-notes.js +0 -172
- package/dist/src/semantics/disputes.d.ts +0 -2
- package/dist/src/semantics/disputes.js +0 -51
- package/dist/src/semantics/ephemeral-keys.d.ts +0 -2
- package/dist/src/semantics/ephemeral-keys.js +0 -34
- package/dist/src/semantics/files.d.ts +0 -2
- package/dist/src/semantics/files.js +0 -125
- package/dist/src/semantics/ledger.d.ts +0 -59
- package/dist/src/semantics/ledger.js +0 -200
- package/dist/src/semantics/payment-intents.d.ts +0 -18
- package/dist/src/semantics/payment-intents.js +0 -452
- package/dist/src/semantics/payment-links.d.ts +0 -2
- package/dist/src/semantics/payment-links.js +0 -133
- package/dist/src/semantics/payment-methods.d.ts +0 -20
- package/dist/src/semantics/payment-methods.js +0 -140
- package/dist/src/semantics/plans.d.ts +0 -5
- package/dist/src/semantics/plans.js +0 -121
- package/dist/src/semantics/platform.d.ts +0 -9
- package/dist/src/semantics/platform.js +0 -206
- package/dist/src/semantics/renewals.d.ts +0 -47
- package/dist/src/semantics/renewals.js +0 -281
- package/dist/src/semantics/setup-intents.d.ts +0 -2
- package/dist/src/semantics/setup-intents.js +0 -84
- package/dist/src/semantics/subscription-schedules.d.ts +0 -2
- package/dist/src/semantics/subscription-schedules.js +0 -119
- package/dist/src/semantics/tax.d.ts +0 -2
- package/dist/src/semantics/tax.js +0 -197
- package/dist/src/semantics/terminal.d.ts +0 -5
- package/dist/src/semantics/terminal.js +0 -182
- package/dist/src/semantics/test-clocks.d.ts +0 -6
- package/dist/src/semantics/test-clocks.js +0 -73
- package/dist/src/semantics/tokens.d.ts +0 -4
- package/dist/src/semantics/tokens.js +0 -44
- package/dist/src/semantics/treasury.d.ts +0 -2
- package/dist/src/semantics/treasury.js +0 -377
- package/dist/src/semantics/webhook-endpoints.d.ts +0 -3
- package/dist/src/semantics/webhook-endpoints.js +0 -85
- package/dist/src/stripe-budget.d.ts +0 -55
- package/dist/src/stripe-budget.js +0 -155
- package/dist/src/stripe-capabilities.d.ts +0 -3
- package/dist/src/stripe-capabilities.js +0 -5836
- package/dist/src/stripe-conformance.d.ts +0 -43
- package/dist/src/stripe-conformance.js +0 -105
- package/dist/src/stripe-connector.d.ts +0 -161
- package/dist/src/stripe-connector.js +0 -414
- package/dist/src/stripe-emit.d.ts +0 -2
- package/dist/src/stripe-emit.js +0 -145
- package/dist/src/stripe-events.d.ts +0 -93
- package/dist/src/stripe-events.js +0 -392
- package/dist/src/stripe-js.d.ts +0 -4
- package/dist/src/stripe-js.js +0 -70
- package/dist/src/stripe-mirror-ui.d.ts +0 -15
- package/dist/src/stripe-mirror-ui.js +0 -87
- package/dist/src/stripe-perform-harness.d.ts +0 -9
- package/dist/src/stripe-perform-harness.js +0 -26
- package/dist/src/stripe-server.d.ts +0 -33
- package/dist/src/stripe-server.js +0 -429
- package/dist/src/stripe-shared.d.ts +0 -109
- package/dist/src/stripe-shared.js +0 -276
- package/dist/src/stripe-ui-conformance.d.ts +0 -5
- package/dist/src/stripe-ui-conformance.js +0 -79
- package/dist/src/stripe-ui-structure.d.ts +0 -3
- package/dist/src/stripe-ui-structure.js +0 -168
- package/dist/test-fixtures/stripe-known-deviations.json +0 -110
- package/dist/test-fixtures/stripe-openapi-operations.SOURCE.md +0 -14
- package/dist/test-fixtures/stripe-openapi-operations.json +0 -4717
- package/dist/test-fixtures/stripe-schemas.SOURCE.md +0 -35
- package/dist/test-fixtures/stripe-schemas.json +0 -3813
- package/src/screens/connect-oauth.tsx +0 -400
- package/src/screens/connect-settings.tsx +0 -121
- package/src/screens/consent-skin.ts +0 -20
- package/src/screens/financial-connections.tsx +0 -101
- package/src/screens/identity.tsx +0 -96
- package/src/screens/public-details.tsx +0 -105
- package/src/semantics/after-payment.ts +0 -118
- package/src/semantics/billing.ts +0 -216
- package/src/semantics/connect.ts +0 -487
- package/src/semantics/credit-notes.ts +0 -168
- package/src/semantics/disputes.ts +0 -62
- package/src/semantics/ephemeral-keys.ts +0 -34
- package/src/semantics/files.ts +0 -143
- package/src/semantics/ledger.ts +0 -253
- package/src/semantics/payment-intents.ts +0 -463
- package/src/semantics/payment-links.ts +0 -148
- package/src/semantics/payment-methods.ts +0 -145
- package/src/semantics/plans.ts +0 -131
- package/src/semantics/platform.ts +0 -220
- package/src/semantics/renewals.ts +0 -279
- package/src/semantics/setup-intents.ts +0 -87
- package/src/semantics/subscription-schedules.ts +0 -129
- package/src/semantics/tax.ts +0 -220
- package/src/semantics/terminal.ts +0 -195
- package/src/semantics/test-clocks.ts +0 -77
- package/src/semantics/tokens.ts +0 -52
- package/src/semantics/treasury.ts +0 -383
- package/src/semantics/webhook-endpoints.ts +0 -87
- package/src/stripe-budget.ts +0 -181
- package/src/stripe-capabilities.ts +0 -5651
- package/src/stripe-conformance.ts +0 -124
- package/src/stripe-connector.ts +0 -462
- package/src/stripe-emit.ts +0 -157
- package/src/stripe-events.ts +0 -434
- package/src/stripe-js.ts +0 -70
- package/src/stripe-mirror-ui.ts +0 -90
- package/src/stripe-perform-harness.ts +0 -29
- package/src/stripe-server.ts +0 -393
- package/src/stripe-shared.ts +0 -297
- package/src/stripe-ui-conformance.ts +0 -88
- package/src/stripe-ui-structure.ts +0 -182
- package/test-fixtures/stripe-known-deviations.json +0 -110
- package/test-fixtures/stripe-openapi-operations.json +0 -4717
- package/test-fixtures/stripe-schemas.json +0 -3813
- /package/dist/src/{screens → engine}/industries.d.ts +0 -0
- /package/dist/src/{screens → engine}/industries.js +0 -0
- /package/dist/src/{semantics → engine}/test-cards.d.ts +0 -0
- /package/dist/src/{semantics → engine}/test-cards.js +0 -0
- /package/src/{screens → engine}/industries.ts +0 -0
- /package/src/{semantics → engine}/test-cards.ts +0 -0
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
// Connect semantics: connected accounts (and the platform's own account), their persons,
|
|
2
|
+
// capabilities, external (payout) accounts, login links, onboarding links and embedded-component
|
|
3
|
+
// sessions. A new connected account is not yet active: charges and payouts are off and its
|
|
4
|
+
// requirements are outstanding, as on Stripe before onboarding. Account retrieve and delete and
|
|
5
|
+
// the person list are the derived core's.
|
|
6
|
+
import { accountRequirements, accountSettings, PLATFORM_ACCOUNT_ID } from "./stripe.js";
|
|
7
|
+
import { currentlyDue, kindOf } from "./onboarding.js";
|
|
8
|
+
import { externalList } from "./common.js";
|
|
9
|
+
// the platform's own account: stored once it is written, otherwise Stripe's default. It "controls itself" (controller
|
|
10
|
+
// type `account`, docs.stripe.com/api/accounts/object), is fully onboarded with nothing due, and takes card payments
|
|
11
|
+
// and transfers. Where the documentation stops and the twin decides: it was created as the World began (2026-01-01),
|
|
12
|
+
// and its bank account, which its automatic payouts reach, is not modelled, so it lists none.
|
|
13
|
+
export const PLATFORM_CREATED = 1_767_225_600;
|
|
14
|
+
/** The platform's own account as Stripe's default has it, before anything is written to it. */
|
|
15
|
+
export const platformAccountDefault = () => ({
|
|
16
|
+
object: 'account', id: PLATFORM_ACCOUNT_ID, type: 'standard', country: 'US', default_currency: 'usd', created: PLATFORM_CREATED,
|
|
17
|
+
charges_enabled: true, payouts_enabled: true, details_submitted: true, email: null, metadata: {},
|
|
18
|
+
capabilities: { card_payments: 'active', transfers: 'active' }, controller: { type: 'account' },
|
|
19
|
+
requirements: { alternatives: [], current_deadline: null, currently_due: [], disabled_reason: null, errors: [], eventually_due: [], past_due: [], pending_verification: [] },
|
|
20
|
+
future_requirements: { alternatives: [], current_deadline: null, currently_due: [], disabled_reason: null, errors: [], eventually_due: [], past_due: [], pending_verification: [] },
|
|
21
|
+
external_accounts: externalList(PLATFORM_ACCOUNT_ID, []), tos_acceptance: { date: null, ip: null, user_agent: null }, business_profile: {},
|
|
22
|
+
settings: accountSettings(undefined), livemode: false,
|
|
23
|
+
});
|
|
24
|
+
/** A new Express account owes what its hosted onboarding will ask for (screens/connect-onboarding.tsx; the US sets
|
|
25
|
+
* docs.stripe.com/connect/required-verification-information lists), or, where the twin does not model the set, the
|
|
26
|
+
* generic list. */
|
|
27
|
+
export function expressRequirements(params) {
|
|
28
|
+
const kind = kindOf({ country: params.country ?? 'US', business_type: params.business_type ?? 'individual' });
|
|
29
|
+
const base = accountRequirements();
|
|
30
|
+
return kind ? { ...base, currently_due: currentlyDue(kind), eventually_due: currentlyDue(kind) } : base;
|
|
31
|
+
}
|
|
32
|
+
/** The controller an account made with a `type` has: "Each of the three account types maps to values in the
|
|
33
|
+
* `controller` hash", Standard to losses.payments `stripe`, fees.payer `account`, requirement_collection `stripe` and
|
|
34
|
+
* a `full` dashboard, Express to `application`, `application_express`, `stripe` and `express`, Custom to
|
|
35
|
+
* `application`, `application_custom`, `application` and `none`; each "type": "application", "is_controller": true
|
|
36
|
+
* (docs.stripe.com/connect/migrate-to-controller-properties). */
|
|
37
|
+
export function controllerOf(type) {
|
|
38
|
+
const [losses, payer, collection, dashboard] = type === 'express' ? ['application', 'application_express', 'stripe', 'express']
|
|
39
|
+
: type === 'custom' ? ['application', 'application_custom', 'application', 'none'] : ['stripe', 'account', 'stripe', 'full'];
|
|
40
|
+
return { type: 'application', is_controller: true, losses: { payments: losses }, fees: { payer }, requirement_collection: collection, stripe_dashboard: { type: dashboard } };
|
|
41
|
+
}
|
|
42
|
+
/** What a Custom account still owes, from what the platform has given for it, as Stripe's requirements endpoint lists it
|
|
43
|
+
* for a US account with no Stripe Dashboard and the full service agreement
|
|
44
|
+
* (docs.stripe.com/_endpoint/get-requirements-for-setups, the data behind
|
|
45
|
+
* docs.stripe.com/connect/required-verification-information). With transfers alone, a company owes business_profile.url,
|
|
46
|
+
* company.name, an external account and tos_acceptance.date and .ip at once (capability_limit_amount -1: paused until
|
|
47
|
+
* given) and company.tax_id before $3,000 of payouts (payout_limit_amount 300000); an individual owes the url, its
|
|
48
|
+
* first and last name, the bank account and the terms at once, and its date of birth and ssn_last_4 before $3,000 of
|
|
49
|
+
* payouts. Requesting card_payments adds business_profile.mcc and the entity's address at once (and an individual's
|
|
50
|
+
* email and ssn_last_4). A company with card_payments owes, at once, business_profile.mcc, its address, that its owners
|
|
51
|
+
* are provided, each owner's name and email, and its representative's name, email, address, title and ssn_last_4; and
|
|
52
|
+
* in time its phone, its statement descriptor and its representative's date of birth and phone (the endpoint's answer
|
|
53
|
+
* for US / dashboard none / full terms / company / card_payments and transfers, saved in scratch as
|
|
54
|
+
* req-custom-company-cards-transfers.json: capability_limit_amount -1 for the first, none for the second). The
|
|
55
|
+
* representative and the owners are the account's persons (relationship.representative, relationship.owner).
|
|
56
|
+
* Where the documentation stops and the twin decides: what has no limit, or is owed before $3,000 of payouts, is
|
|
57
|
+
* eventually_due and blocks nothing (the twin keeps no payout total against it); an owner field is met when every
|
|
58
|
+
* person marked owner has it (none marked: met). */
|
|
59
|
+
export const at_path = (a, path) => path.split('.').reduce((v, k) => (v && typeof v === 'object' ? v[k] : undefined), a);
|
|
60
|
+
export const CARD_COMPANY_NOW = ['business_profile.mcc', 'company.address.line1', 'company.address.city', 'company.address.state', 'company.address.postal_code', 'company.owners_provided', 'owners.first_name', 'owners.last_name', 'owners.email', 'representative.first_name', 'representative.last_name', 'representative.email', 'representative.address.line1', 'representative.address.city', 'representative.address.state', 'representative.address.postal_code', 'representative.relationship.title', 'representative.ssn_last_4'];
|
|
61
|
+
export const CARD_COMPANY_LATER = ['company.phone', 'settings.payments.statement_descriptor', 'representative.dob.day', 'representative.dob.month', 'representative.dob.year', 'representative.phone'];
|
|
62
|
+
export const CARD_INDIVIDUAL_NOW = ['business_profile.mcc', 'individual.address.line1', 'individual.address.city', 'individual.address.state', 'individual.address.postal_code', 'individual.email', 'individual.ssn_last_4'];
|
|
63
|
+
export const personHas = (p, field) => {
|
|
64
|
+
if (field === 'ssn_last_4')
|
|
65
|
+
return p.ssn_last_4_provided === true;
|
|
66
|
+
const v = at_path(p, field);
|
|
67
|
+
return v !== undefined && v !== null && v !== '';
|
|
68
|
+
};
|
|
69
|
+
export const met = (a, bank, field, persons = []) => {
|
|
70
|
+
if (field === 'external_account')
|
|
71
|
+
return bank;
|
|
72
|
+
if (field.startsWith('representative.')) {
|
|
73
|
+
const rep = persons.find((p) => p.relationship?.representative === true);
|
|
74
|
+
return !!rep && personHas(rep, field.slice('representative.'.length));
|
|
75
|
+
}
|
|
76
|
+
if (field.startsWith('owners.'))
|
|
77
|
+
return persons.filter((p) => p.relationship?.owner === true).every((p) => personHas(p, field.slice('owners.'.length)));
|
|
78
|
+
if (field === 'company.tax_id')
|
|
79
|
+
return at_path(a, 'company.tax_id_provided') === true;
|
|
80
|
+
if (field === 'individual.ssn_last_4')
|
|
81
|
+
return at_path(a, 'individual.ssn_last_4_provided') === true;
|
|
82
|
+
const v = at_path(a, field);
|
|
83
|
+
return v !== undefined && v !== null && v !== '';
|
|
84
|
+
};
|
|
85
|
+
export function customRequirements(a, bank, persons = []) {
|
|
86
|
+
const company = a.business_type === 'company';
|
|
87
|
+
const cards = Object.keys(a.capabilities ?? {}).includes('card_payments');
|
|
88
|
+
const now = ['business_profile.url', ...(company ? ['company.name'] : ['individual.first_name', 'individual.last_name']), 'external_account', 'tos_acceptance.date', 'tos_acceptance.ip'];
|
|
89
|
+
if (cards)
|
|
90
|
+
now.push(...(company ? CARD_COMPANY_NOW : CARD_INDIVIDUAL_NOW));
|
|
91
|
+
const later = [...(company ? ['company.tax_id'] : ['individual.dob.day', 'individual.dob.month', 'individual.dob.year', 'individual.ssn_last_4']), ...(cards && company ? CARD_COMPANY_LATER : [])].filter((f) => !now.includes(f));
|
|
92
|
+
return { now: now.filter((f) => !met(a, bank, f, persons)), later: later.filter((f) => !met(a, bank, f, persons)) };
|
|
93
|
+
}
|
|
94
|
+
/** A request's company or individual as Stripe keeps it: a tax id or SSN given is kept only as provided (the Account
|
|
95
|
+
* object answers company.tax_id_provided and individual.ssn_last_4_provided, never the numbers;
|
|
96
|
+
* docs.stripe.com/api/accounts/object). */
|
|
97
|
+
export function keptKyc(params) {
|
|
98
|
+
const out = { ...params };
|
|
99
|
+
if (params.company && typeof params.company === 'object') {
|
|
100
|
+
const { tax_id, ...company } = params.company;
|
|
101
|
+
out.company = { ...company, ...(tax_id !== undefined && tax_id !== '' ? { tax_id_provided: true } : {}) };
|
|
102
|
+
}
|
|
103
|
+
if (params.individual && typeof params.individual === 'object') {
|
|
104
|
+
const { ssn_last_4, id_number, ...individual } = params.individual;
|
|
105
|
+
out.individual = { ...individual, ...(ssn_last_4 !== undefined && ssn_last_4 !== '' ? { ssn_last_4_provided: true } : {}), ...(id_number !== undefined && id_number !== '' ? { id_number_provided: true } : {}) };
|
|
106
|
+
}
|
|
107
|
+
return out;
|
|
108
|
+
}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { Row } from './common.js';
|
|
2
|
+
/** What a new customer answers before any invoice: its invoice_prefix and a next_invoice_sequence of 1, a zero balance,
|
|
3
|
+
* no metadata (docs.stripe.com/api/customers/object). */
|
|
4
|
+
export declare const newCustomer: (id: string) => Row;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
// Customer semantics: the customer and what hangs off it (tax ids, the credit-balance ledger, the
|
|
2
|
+
// cash balance, legacy sources, attached payment methods) and the top-level Source object. List,
|
|
3
|
+
// update and delete of a customer, retrieve of a Source and the flat tax-id list are the derived core's.
|
|
4
|
+
import { invoicePrefix } from "./invoices.js";
|
|
5
|
+
/** What a new customer answers before any invoice: its invoice_prefix and a next_invoice_sequence of 1, a zero balance,
|
|
6
|
+
* no metadata (docs.stripe.com/api/customers/object). */
|
|
7
|
+
export const newCustomer = (id) => ({ invoice_prefix: invoicePrefix(id), next_invoice_sequence: 1, balance: 0, metadata: {}, invoice_settings: {} });
|
|
8
|
+
// ── tax ids: a customer's, keyed under it; `type` and `value` are required ──
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
type Row = Record<string, any>;
|
|
2
|
+
/** The name an account shows its customers (Checkout, the customer portal): its public business name,
|
|
3
|
+
* `business_profile.name` ("The customer-facing business name", docs.stripe.com/api/accounts/object), which the
|
|
4
|
+
* operator sets on the Dashboard ("You can change a Checkout page's name by modifying the Business name field",
|
|
5
|
+
* docs.stripe.com/payments/checkout/customization/appearance). Where the documentation stops and the twin decides:
|
|
6
|
+
* with none set it falls back to the Dashboard's account name, `settings.dashboard.display_name` ("used on the Stripe
|
|
7
|
+
* Dashboard to differentiate between accounts", the same object page), and with neither to "Twin Inc.", the name the
|
|
8
|
+
* twin has always given the World's own account. */
|
|
9
|
+
export declare const PLATFORM_DEFAULT_NAME = "Twin Inc.";
|
|
10
|
+
export declare function publicBusinessName(account: Row | undefined): string;
|
|
11
|
+
export {};
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
// What Stripe's pages show of an account, and where its Connect OAuth connections are kept.
|
|
2
|
+
/** The name an account shows its customers (Checkout, the customer portal): its public business name,
|
|
3
|
+
* `business_profile.name` ("The customer-facing business name", docs.stripe.com/api/accounts/object), which the
|
|
4
|
+
* operator sets on the Dashboard ("You can change a Checkout page's name by modifying the Business name field",
|
|
5
|
+
* docs.stripe.com/payments/checkout/customization/appearance). Where the documentation stops and the twin decides:
|
|
6
|
+
* with none set it falls back to the Dashboard's account name, `settings.dashboard.display_name` ("used on the Stripe
|
|
7
|
+
* Dashboard to differentiate between accounts", the same object page), and with neither to "Twin Inc.", the name the
|
|
8
|
+
* twin has always given the World's own account. */
|
|
9
|
+
export const PLATFORM_DEFAULT_NAME = 'Twin Inc.';
|
|
10
|
+
export function publicBusinessName(account) {
|
|
11
|
+
const named = (v) => (typeof v === 'string' && v.trim() ? v : undefined);
|
|
12
|
+
return named(account?.business_profile?.name) ?? named(account?.settings?.dashboard?.display_name) ?? PLATFORM_DEFAULT_NAME;
|
|
13
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { Row } from './common.js';
|
|
2
|
+
export declare const PBC = "billing_portal.configuration";
|
|
3
|
+
/** A portal configuration's features, each filled where the request leaves it: every feature is answered (the served
|
|
4
|
+
* spec requires all five), as the create page's example answers a request that sets only customer_update and
|
|
5
|
+
* invoice_history: payment_method_update disabled, subscription_cancel disabled at_period_end with proration_behavior
|
|
6
|
+
* none and its five default reasons, subscription_update disabled with no allowed updates and proration_behavior none
|
|
7
|
+
* (docs.stripe.com/api/customer_portal/configurations/create); trial_update_behavior "Defaults to a value of
|
|
8
|
+
* `end_trial` if you don't set it during creation" (the served spec). Where the documentation stops and the twin
|
|
9
|
+
* decides: a feature the request leaves out is disabled, and schedule_at_period_end has no conditions. */
|
|
10
|
+
export declare const PORTAL_FEATURES: Row;
|
|
11
|
+
export declare const filled: (base: unknown, given: unknown) => unknown;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
export const PBC = 'billing_portal.configuration';
|
|
2
|
+
/** A portal configuration's features, each filled where the request leaves it: every feature is answered (the served
|
|
3
|
+
* spec requires all five), as the create page's example answers a request that sets only customer_update and
|
|
4
|
+
* invoice_history: payment_method_update disabled, subscription_cancel disabled at_period_end with proration_behavior
|
|
5
|
+
* none and its five default reasons, subscription_update disabled with no allowed updates and proration_behavior none
|
|
6
|
+
* (docs.stripe.com/api/customer_portal/configurations/create); trial_update_behavior "Defaults to a value of
|
|
7
|
+
* `end_trial` if you don't set it during creation" (the served spec). Where the documentation stops and the twin
|
|
8
|
+
* decides: a feature the request leaves out is disabled, and schedule_at_period_end has no conditions. */
|
|
9
|
+
export const PORTAL_FEATURES = {
|
|
10
|
+
customer_update: { allowed_updates: [], enabled: false },
|
|
11
|
+
invoice_history: { enabled: false },
|
|
12
|
+
payment_method_update: { enabled: false, payment_method_configuration: null },
|
|
13
|
+
subscription_cancel: { cancellation_reason: { enabled: false, options: ['too_expensive', 'missing_features', 'switched_service', 'unused', 'other'] }, enabled: false, mode: 'at_period_end', proration_behavior: 'none' },
|
|
14
|
+
subscription_update: { default_allowed_updates: [], enabled: false, proration_behavior: 'none', schedule_at_period_end: { conditions: [] }, trial_update_behavior: 'end_trial' },
|
|
15
|
+
};
|
|
16
|
+
export const filled = (base, given) => {
|
|
17
|
+
if (!given || typeof given !== 'object' || Array.isArray(given) || !base || typeof base !== 'object' || Array.isArray(base))
|
|
18
|
+
return given === undefined ? base : given;
|
|
19
|
+
const out = { ...base };
|
|
20
|
+
for (const [k, v] of Object.entries(given))
|
|
21
|
+
out[k] = filled(base[k], v);
|
|
22
|
+
return out;
|
|
23
|
+
};
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { Row } from './common.js';
|
|
2
|
+
export declare const INV = "invoice";
|
|
3
|
+
/** Whether leaving draft mints a PaymentIntent: only a charge_automatically invoice with a balance. */
|
|
4
|
+
export declare const collectsThroughIntent: (inv: Row) => boolean;
|
|
5
|
+
export declare const transitions: (inv: Row) => object;
|
|
6
|
+
/** What finalizing assigns: the invoice's `number`, the customer's invoice_prefix and a sequence
|
|
7
|
+
* (https://docs.stripe.com/api/invoices/object#invoice_object-number), and for send_invoice a
|
|
8
|
+
* `due_date` days_until_due after finalization (#invoice_object-due_date). */
|
|
9
|
+
/** A customer's invoice_prefix, "The prefix for the customer used to generate unique invoice numbers"
|
|
10
|
+
* (docs.stripe.com/api/customers/object): the twin's, from the customer's id. */
|
|
11
|
+
export declare const invoicePrefix: (customerId: string) => string;
|
|
12
|
+
/** An invoice's payment as Stripe answers it (docs.stripe.com/api/invoice-payment/object): the PaymentIntent that
|
|
13
|
+
* collects the invoice, open until the invoice is paid. Where the documentation stops and the twin decides: an
|
|
14
|
+
* invoice has one payment, its default, and the payment's id is the invoice's with `inpay_`. */
|
|
15
|
+
export declare function invoicePayment(inv: Row): Row | undefined;
|
|
16
|
+
export declare const linesOf: (inv: Row) => Row[];
|
|
17
|
+
export declare const sumLines: (lines: Row[]) => number;
|
|
18
|
+
/** Credit the previous price and debit the replacement for the same remaining service time. */
|
|
19
|
+
export declare function prorationLines(before: Row[], after: Row[], time: number, start: number, end: number, coupon: Row | undefined): Row[];
|
|
20
|
+
/** A draft invoice's fields before anything is on it: what a new invoice and a preview start from. */
|
|
21
|
+
export declare const draft: (now: number) => Row;
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import { applyCouponDiscount } from "./stripe.js";
|
|
2
|
+
export const INV = 'invoice';
|
|
3
|
+
/** Whether leaving draft mints a PaymentIntent: only a charge_automatically invoice with a balance. */
|
|
4
|
+
// "Finalizing an invoice does the following: ... It creates an incomplete payment intent for the invoice"
|
|
5
|
+
// (docs.stripe.com/invoicing/integration/workflow-transitions), whichever its collection method
|
|
6
|
+
export const collectsThroughIntent = (inv) => inv.status === 'draft' && (Number(inv.amount_due) || 0) > 0;
|
|
7
|
+
export const transitions = (inv) => inv.status_transitions ?? {};
|
|
8
|
+
/** What finalizing assigns: the invoice's `number`, the customer's invoice_prefix and a sequence
|
|
9
|
+
* (https://docs.stripe.com/api/invoices/object#invoice_object-number), and for send_invoice a
|
|
10
|
+
* `due_date` days_until_due after finalization (#invoice_object-due_date). */
|
|
11
|
+
/** A customer's invoice_prefix, "The prefix for the customer used to generate unique invoice numbers"
|
|
12
|
+
* (docs.stripe.com/api/customers/object): the twin's, from the customer's id. */
|
|
13
|
+
export const invoicePrefix = (customerId) => customerId.replace(/[^a-z0-9]/gi, '').slice(-8).toUpperCase() || 'TWIN';
|
|
14
|
+
/** An invoice's payment as Stripe answers it (docs.stripe.com/api/invoice-payment/object): the PaymentIntent that
|
|
15
|
+
* collects the invoice, open until the invoice is paid. Where the documentation stops and the twin decides: an
|
|
16
|
+
* invoice has one payment, its default, and the payment's id is the invoice's with `inpay_`. */
|
|
17
|
+
export function invoicePayment(inv) {
|
|
18
|
+
if (typeof inv.payment_intent !== 'string')
|
|
19
|
+
return undefined;
|
|
20
|
+
const paid = inv.status === 'paid';
|
|
21
|
+
const transitions = inv.status_transitions ?? {};
|
|
22
|
+
return {
|
|
23
|
+
id: `inpay_${String(inv.id).replace(/^in_/, '')}`, object: 'invoice_payment', invoice: inv.id, is_default: true, livemode: false,
|
|
24
|
+
amount_requested: Number(inv.amount_due ?? 0), amount_paid: paid ? Number(inv.amount_paid ?? inv.amount_due ?? 0) : null, currency: inv.currency,
|
|
25
|
+
created: inv.created, payment: { type: 'payment_intent', payment_intent: inv.payment_intent },
|
|
26
|
+
status: paid ? 'paid' : inv.status === 'void' ? 'canceled' : 'open',
|
|
27
|
+
status_transitions: { paid_at: paid ? (transitions.paid_at ?? null) : null, canceled_at: inv.status === 'void' ? (transitions.voided_at ?? null) : null },
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
export const linesOf = (inv) => inv.lines?.data ?? [];
|
|
31
|
+
export const sumLines = (lines) => lines.reduce((s, l) => s + (Number(l.amount) || 0), 0);
|
|
32
|
+
/** Credit the previous price and debit the replacement for the same remaining service time. */
|
|
33
|
+
// source: https://docs.stripe.com/billing/subscriptions/prorations "Unused time on original 10 USD plan (credit)"
|
|
34
|
+
// source: https://docs.stripe.com/billing/subscriptions/prorations "Remaining time on new 20 USD plan (debit)"
|
|
35
|
+
// source: https://docs.stripe.com/billing/subscriptions/prorations "The current billing period’s start and end times are used to calculate the cost of the subscription before and after the change."
|
|
36
|
+
// source: https://docs.stripe.com/billing/subscriptions/prorations "By default, Stripe calculates prorations down to the second."
|
|
37
|
+
export function prorationLines(before, after, time, start, end, coupon) {
|
|
38
|
+
const out = [];
|
|
39
|
+
const discounted = (line, lines) => {
|
|
40
|
+
const total = sumLines(lines);
|
|
41
|
+
// source: https://docs.stripe.com/billing/subscriptions/prorations "When calculating proration credits or debits, Stripe uses the subscription’s discounted price, not the original price."
|
|
42
|
+
return Number(line.amount) - (total > 0 ? applyCouponDiscount(total, coupon) * Number(line.amount) / total : 0);
|
|
43
|
+
};
|
|
44
|
+
const priceId = (line) => typeof line.price === 'object' ? line.price.id : line.price;
|
|
45
|
+
const append = (line, lines, credit) => {
|
|
46
|
+
const billingPeriod = line.period;
|
|
47
|
+
const periodStart = Number(billingPeriod.start ?? start), periodEnd = Number(billingPeriod.end ?? end);
|
|
48
|
+
const fraction = Math.max(0, Math.min(1, (periodEnd - time) / Math.max(1, periodEnd - periodStart)));
|
|
49
|
+
const amount = Math.round(discounted(line, lines) * fraction) * (credit ? -1 : 1);
|
|
50
|
+
if (!amount)
|
|
51
|
+
return;
|
|
52
|
+
out.push({ ...line, id: `${line.id}_${credit ? 'unused' : 'remaining'}`, amount, proration: true, discountable: false,
|
|
53
|
+
period: { start: time, end: periodEnd }, description: `${credit ? 'Unused' : 'Remaining'} time on ${String(line.price?.nickname ?? priceId(line))}` });
|
|
54
|
+
};
|
|
55
|
+
for (const old of before) {
|
|
56
|
+
const replacement = after.find(line => line.subscription_item === old.subscription_item);
|
|
57
|
+
if (replacement && priceId(replacement) === priceId(old) && replacement.quantity === old.quantity)
|
|
58
|
+
continue;
|
|
59
|
+
append(old, before, true);
|
|
60
|
+
}
|
|
61
|
+
for (const next of after) {
|
|
62
|
+
const previous = before.find(line => line.subscription_item && line.subscription_item === next.subscription_item);
|
|
63
|
+
if (previous && priceId(previous) === priceId(next) && previous.quantity === next.quantity)
|
|
64
|
+
continue;
|
|
65
|
+
append(next, after, false);
|
|
66
|
+
}
|
|
67
|
+
return out;
|
|
68
|
+
}
|
|
69
|
+
// ── invoices ──
|
|
70
|
+
/** A draft invoice's fields before anything is on it: what a new invoice and a preview start from. */
|
|
71
|
+
export const draft = (now) => ({
|
|
72
|
+
status: 'draft', livemode: false, currency: 'usd', collection_method: 'charge_automatically',
|
|
73
|
+
auto_advance: false, attempt_count: 0, attempted: false,
|
|
74
|
+
amount_due: 0, amount_paid: 0, amount_remaining: 0, amount_overpaid: 0, amount_paid_off_stripe: 0, amount_shipping: 0,
|
|
75
|
+
subtotal: 0, total: 0, starting_balance: 0, post_payment_credit_notes_amount: 0, pre_payment_credit_notes_amount: 0,
|
|
76
|
+
period_start: now, period_end: now, default_tax_rates: [], discounts: [],
|
|
77
|
+
lines: { object: 'list', data: [], has_more: false, total_count: 0 },
|
|
78
|
+
automatic_tax: { enabled: false, liability: null, status: null },
|
|
79
|
+
status_transitions: { finalized_at: null, marked_uncollectible_at: null, paid_at: null, voided_at: null },
|
|
80
|
+
issuer: { type: 'self' },
|
|
81
|
+
payment_settings: { default_mandate: null, payment_method_options: null, payment_method_types: null },
|
|
82
|
+
// a draft has no PaymentIntent: finalize mints it
|
|
83
|
+
payment_intent: null,
|
|
84
|
+
});
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import type { Row } from './common.js';
|
|
2
|
+
export declare const CH = "issuing.cardholder";
|
|
3
|
+
/** The id of a card's cardholder: the card answers the cardholder in full (the served spec's issuing.card.cardholder is
|
|
4
|
+
* the Cardholder object, not an id); its id is read from it for filtering and for the objects that name it by id. */
|
|
5
|
+
export declare const holderId: (c: Row) => string;
|
|
6
|
+
export declare const CARD = "issuing.card";
|
|
7
|
+
export declare const AUTH = "issuing.authorization";
|
|
8
|
+
export declare const TXN = "issuing.transaction";
|
|
9
|
+
/** One request_history entry; the authorization code is derived from the request time (Stripe's is not unique either). */
|
|
10
|
+
export declare function historyEntry(o: {
|
|
11
|
+
amount: number;
|
|
12
|
+
currency: string;
|
|
13
|
+
approved: boolean;
|
|
14
|
+
reason: string;
|
|
15
|
+
reasonMessage: string | null;
|
|
16
|
+
createdSec: number;
|
|
17
|
+
merchantAmount: number;
|
|
18
|
+
merchantCurrency: string;
|
|
19
|
+
}): Row;
|
|
20
|
+
/** The test helper's default merchant, under any merchant_data the caller gives. */
|
|
21
|
+
export declare function merchantData(param: unknown): Row;
|
|
22
|
+
/** The card's stored id (an embedded card answers with its id). */
|
|
23
|
+
export declare const cardId: (auth: Row) => unknown;
|
|
24
|
+
/** The real-time window: "If Stripe doesn't receive your approve or decline response within 2 seconds, the
|
|
25
|
+
* Authorization is automatically approved or declined based on your timeout settings"
|
|
26
|
+
* (docs.stripe.com/issuing/controls/real-time-authorizations). */
|
|
27
|
+
export declare const REALTIME_WINDOW_SECONDS = 2;
|
|
28
|
+
/** A virtual card's number, drawn from the World: a 16-digit Visa number ("The brand of the card": the twin issues
|
|
29
|
+
* Visa) whose last digit is the Luhn check digit every card number carries. Where the documentation stops and the twin
|
|
30
|
+
* decides: the digits are the World's draw, Stripe's are the issuer's. */
|
|
31
|
+
export declare function cardNumberOf(drawn: string): string;
|
|
32
|
+
/** A virtual card's CVC, drawn from the World: three digits. */
|
|
33
|
+
export declare const cvcOf: (drawn: string) => string;
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
export const CH = 'issuing.cardholder';
|
|
2
|
+
/** The id of a card's cardholder: the card answers the cardholder in full (the served spec's issuing.card.cardholder is
|
|
3
|
+
* the Cardholder object, not an id); its id is read from it for filtering and for the objects that name it by id. */
|
|
4
|
+
export const holderId = (c) => (typeof c.cardholder === 'string' ? c.cardholder : String(c.cardholder?.id ?? ''));
|
|
5
|
+
export const CARD = 'issuing.card';
|
|
6
|
+
export const AUTH = 'issuing.authorization';
|
|
7
|
+
export const TXN = 'issuing.transaction';
|
|
8
|
+
/** One request_history entry; the authorization code is derived from the request time (Stripe's is not unique either). */
|
|
9
|
+
export function historyEntry(o) {
|
|
10
|
+
return {
|
|
11
|
+
amount: o.amount, amount_details: null, approved: o.approved,
|
|
12
|
+
authorization_code: o.approved ? `S${String(100000 + (o.createdSec % 900000))}` : null,
|
|
13
|
+
created: o.createdSec, currency: o.currency,
|
|
14
|
+
merchant_amount: o.merchantAmount, merchant_currency: o.merchantCurrency,
|
|
15
|
+
network_risk_score: null, reason: o.reason, reason_message: o.reasonMessage,
|
|
16
|
+
requested_at: o.createdSec,
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
/** The test helper's default merchant, under any merchant_data the caller gives. */
|
|
20
|
+
export function merchantData(param) {
|
|
21
|
+
const base = {
|
|
22
|
+
category: 'general', category_code: '5399', city: 'San Francisco', country: 'US',
|
|
23
|
+
name: 'Twin Test Merchant', network_id: '1234567890', postal_code: '94103', state: 'CA',
|
|
24
|
+
tax_id: null, terminal_id: null, url: null,
|
|
25
|
+
};
|
|
26
|
+
if (param && typeof param === 'object' && !Array.isArray(param))
|
|
27
|
+
Object.assign(base, param);
|
|
28
|
+
return base;
|
|
29
|
+
}
|
|
30
|
+
/** The card's stored id (an embedded card answers with its id). */
|
|
31
|
+
export const cardId = (auth) => (auth.card && typeof auth.card === 'object' ? auth.card.id : auth.card);
|
|
32
|
+
/** The real-time window: "If Stripe doesn't receive your approve or decline response within 2 seconds, the
|
|
33
|
+
* Authorization is automatically approved or declined based on your timeout settings"
|
|
34
|
+
* (docs.stripe.com/issuing/controls/real-time-authorizations). */
|
|
35
|
+
export const REALTIME_WINDOW_SECONDS = 2;
|
|
36
|
+
/** A virtual card's number, drawn from the World: a 16-digit Visa number ("The brand of the card": the twin issues
|
|
37
|
+
* Visa) whose last digit is the Luhn check digit every card number carries. Where the documentation stops and the twin
|
|
38
|
+
* decides: the digits are the World's draw, Stripe's are the issuer's. */
|
|
39
|
+
export function cardNumberOf(drawn) {
|
|
40
|
+
const body = `4${[...drawn].map((ch) => String(ch.charCodeAt(0) % 10)).join('').padEnd(14, '0').slice(0, 14)}`;
|
|
41
|
+
let sum = 0;
|
|
42
|
+
for (let i = 0; i < body.length; i++) {
|
|
43
|
+
let d = Number(body[body.length - 1 - i]);
|
|
44
|
+
if (i % 2 === 0) {
|
|
45
|
+
d *= 2;
|
|
46
|
+
if (d > 9)
|
|
47
|
+
d -= 9;
|
|
48
|
+
}
|
|
49
|
+
sum += d;
|
|
50
|
+
}
|
|
51
|
+
return `${body}${(10 - (sum % 10)) % 10}`;
|
|
52
|
+
}
|
|
53
|
+
/** A virtual card's CVC, drawn from the World: three digits. */
|
|
54
|
+
export const cvcOf = (drawn) => [...drawn].map((ch) => String(ch.charCodeAt(0) % 10)).join('').padEnd(3, '0').slice(0, 3);
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { Row } from './common.js';
|
|
2
|
+
export declare const BT = "balance_transaction";
|
|
3
|
+
/** A ledger entry's mark: available at once, its balance.available not yet sent (settleDueEntries). */
|
|
4
|
+
export declare const UNSENT = "_availableUnsent";
|
|
5
|
+
export declare const BYPASS_NUMBERS: Set<string>;
|
|
6
|
+
export declare const feeOf: (amount: number) => number;
|
|
7
|
+
/** Whether a stored ledger entry is on this account's balance (undefined: the platform's). */
|
|
8
|
+
export declare const onAccount: (t: Row, account: string | undefined) => boolean;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { BYPASS_PENDING_CARDS } from "./test-cards.js";
|
|
2
|
+
export const BT = 'balance_transaction';
|
|
3
|
+
/** A ledger entry's mark: available at once, its balance.available not yet sent (settleDueEntries). */
|
|
4
|
+
export const UNSENT = '_availableUnsent';
|
|
5
|
+
export const BYPASS_NUMBERS = new Set(Object.values(BYPASS_PENDING_CARDS).map((c) => c.number));
|
|
6
|
+
export const feeOf = (amount) => (amount > 0 ? Math.round(amount * 0.029) + 30 : 0);
|
|
7
|
+
/** Whether a stored ledger entry is on this account's balance (undefined: the platform's). */
|
|
8
|
+
export const onAccount = (t, account) => (typeof t._account === 'string' ? t._account : undefined) === account;
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
/** A key shown the way Stripe's errors show one: its prefix and its last four. */
|
|
2
|
+
export declare const redactKey: (key: string) => string;
|
|
3
|
+
/** The API key a request carries: Bearer, or Basic's user (`curl -u sk_…:`, docs.stripe.com/api/authentication). */
|
|
4
|
+
export declare function requestKey(request: Request): string;
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
// Stripe API key parsing and error redaction, from the API authentication documentation.
|
|
2
|
+
/** A key shown the way Stripe's errors show one: its prefix and its last four. */
|
|
3
|
+
export const redactKey = (key) => {
|
|
4
|
+
const prefix = /^(sk|rk|pk)_(test|live)_/.exec(key)?.[0] ?? '';
|
|
5
|
+
const rest = key.slice(prefix.length);
|
|
6
|
+
return rest.length > 4 ? `${prefix}${'*'.repeat(rest.length - 4)}${rest.slice(-4)}` : `${prefix}${'*'.repeat(rest.length)}`;
|
|
7
|
+
};
|
|
8
|
+
/** The API key a request carries: Bearer, or Basic's user (`curl -u sk_…:`, docs.stripe.com/api/authentication). */
|
|
9
|
+
export function requestKey(request) {
|
|
10
|
+
const header = request.headers.get('authorization') ?? '';
|
|
11
|
+
const bearer = /^bearer\s+(\S+)/i.exec(header)?.[1];
|
|
12
|
+
if (bearer)
|
|
13
|
+
return bearer;
|
|
14
|
+
const basic = /^basic\s+(\S+)/i.exec(header)?.[1];
|
|
15
|
+
if (basic) {
|
|
16
|
+
try {
|
|
17
|
+
return atob(basic).split(':')[0] ?? '';
|
|
18
|
+
}
|
|
19
|
+
catch {
|
|
20
|
+
return '';
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
return '';
|
|
24
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
type Row = Record<string, unknown>;
|
|
2
|
+
export declare const OFFERED: Set<string>;
|
|
3
|
+
export type Form = Record<string, string>;
|
|
4
|
+
export type Kind = 'company' | 'individual';
|
|
5
|
+
export declare const has: (v: Form, k: string) => boolean;
|
|
6
|
+
export declare const dobPart: (v: Form, i: number) => boolean;
|
|
7
|
+
/** Each requirement Stripe names, the form's answer that meets it, and which of the two sets it belongs to. */
|
|
8
|
+
export declare const REQUIREMENTS: Array<[string, (v: Form) => boolean, Kind[]]>;
|
|
9
|
+
/** The set an account onboards against: the two US sets the twin models, or none. */
|
|
10
|
+
export declare function kindOf(account: Row): Kind | undefined;
|
|
11
|
+
/** What an account of this kind still owes, given the form's answers (none: all of it). */
|
|
12
|
+
export declare function currentlyDue(kind: Kind, v?: Form): string[];
|
|
13
|
+
export {};
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
// What a connected account owes Stripe before it can take payments (the requirements its onboarding collects,
|
|
2
|
+
// ../screens/connect-onboarding.tsx), as the Accounts API reports them (`requirements.currently_due`): the two US sets the twin
|
|
3
|
+
// models, a company's and an individual's.
|
|
4
|
+
import { INDUSTRIES as MCCS } from "./industries.js";
|
|
5
|
+
export const OFFERED = new Set(MCCS.map(([mcc]) => mcc));
|
|
6
|
+
export const has = (v, k) => (v[k] ?? '').trim() !== '';
|
|
7
|
+
export const dobPart = (v, i) => /^\d{4}-\d{2}-\d{2}$/.test(v.dob ?? '') && Number((v.dob ?? '').split('-')[i]) > 0;
|
|
8
|
+
/** Each requirement Stripe names, the form's answer that meets it, and which of the two sets it belongs to. */
|
|
9
|
+
export const REQUIREMENTS = [
|
|
10
|
+
['business_profile.mcc', (v) => OFFERED.has((v.mcc ?? '').trim()), ['company', 'individual']],
|
|
11
|
+
['business_profile.url', (v) => has(v, 'url'), ['company', 'individual']],
|
|
12
|
+
['settings.payments.statement_descriptor', (v) => has(v, 'statement_descriptor'), ['company', 'individual']],
|
|
13
|
+
['company.name', (v) => has(v, 'company_name'), ['company']],
|
|
14
|
+
['company.tax_id', (v) => has(v, 'company_tax_id'), ['company']],
|
|
15
|
+
['company.phone', (v) => has(v, 'company_phone'), ['company']],
|
|
16
|
+
['company.address.line1', (v) => has(v, 'company_line1'), ['company']],
|
|
17
|
+
['company.address.city', (v) => has(v, 'company_city'), ['company']],
|
|
18
|
+
['company.address.state', (v) => has(v, 'company_state'), ['company']],
|
|
19
|
+
['company.address.postal_code', (v) => has(v, 'company_postal_code'), ['company']],
|
|
20
|
+
['company.owners_provided', (v) => v.owners_provided === 'provided', ['company']],
|
|
21
|
+
['owners.first_name', (v) => has(v, 'owner_first_name'), ['company']],
|
|
22
|
+
['owners.last_name', (v) => has(v, 'owner_last_name'), ['company']],
|
|
23
|
+
['owners.email', (v) => has(v, 'owner_email'), ['company']],
|
|
24
|
+
...['first_name', 'last_name', 'email', 'phone'].flatMap((f) => [[`representative.${f}`, (v) => has(v, f), ['company']], [`individual.${f}`, (v) => has(v, f), ['individual']]]),
|
|
25
|
+
...['day', 'month', 'year'].flatMap((f, i) => [[`representative.dob.${f}`, (v) => dobPart(v, 2 - i), ['company']], [`individual.dob.${f}`, (v) => dobPart(v, 2 - i), ['individual']]]),
|
|
26
|
+
...['line1', 'city', 'state', 'postal_code'].flatMap((f) => [[`representative.address.${f}`, (v) => has(v, f), ['company']], [`individual.address.${f}`, (v) => has(v, f), ['individual']]]),
|
|
27
|
+
['representative.relationship.title', (v) => has(v, 'title'), ['company']],
|
|
28
|
+
['representative.ssn_last_4', (v) => /^\d{4}$/.test(v.ssn_last_4 ?? ''), ['company']],
|
|
29
|
+
['individual.ssn_last_4', (v) => /^\d{4}$/.test(v.ssn_last_4 ?? ''), ['individual']],
|
|
30
|
+
['tos_acceptance.date', (v) => v.tos === 'accepted', ['company', 'individual']],
|
|
31
|
+
['tos_acceptance.ip', (v) => v.tos === 'accepted', ['company', 'individual']],
|
|
32
|
+
['external_account', (v) => has(v, 'routing_number') && has(v, 'account_number'), ['company', 'individual']],
|
|
33
|
+
];
|
|
34
|
+
/** The set an account onboards against: the two US sets the twin models, or none. */
|
|
35
|
+
export function kindOf(account) {
|
|
36
|
+
const type = account.business_type ?? 'individual';
|
|
37
|
+
return (account.country ?? 'US') === 'US' && (type === 'company' || type === 'individual') ? type : undefined;
|
|
38
|
+
}
|
|
39
|
+
/** What an account of this kind still owes, given the form's answers (none: all of it). */
|
|
40
|
+
export function currentlyDue(kind, v = {}) {
|
|
41
|
+
return REQUIREMENTS.filter(([, met, kinds]) => kinds.includes(kind) && !met(v)).map(([req]) => req);
|
|
42
|
+
}
|
|
@@ -1,8 +1,22 @@
|
|
|
1
|
-
|
|
1
|
+
type Param = {
|
|
2
|
+
name: string;
|
|
3
|
+
required?: boolean;
|
|
4
|
+
};
|
|
5
|
+
type Op = {
|
|
6
|
+
id: string;
|
|
7
|
+
method: string;
|
|
8
|
+
query?: Param[];
|
|
9
|
+
body?: Param[];
|
|
10
|
+
};
|
|
11
|
+
export declare const OPS: Map<string, Op>;
|
|
12
|
+
/** Parameters Stripe documents outside its published spec, each with the page that documents it. */
|
|
13
|
+
export declare const DOCUMENTED: Record<string, string[]>;
|
|
2
14
|
/** The version that removed payment_method_types from the intents: a caller pinned to it or later is refused. */
|
|
3
15
|
export declare const METHOD_TYPES_REMOVED_IN = "2026-08-26.preview";
|
|
4
16
|
/** Whether a pinned version is at or after the removal: versions order by their date (YYYY-MM-DD). */
|
|
5
17
|
export declare const methodTypesRemoved: (pinned: string) => boolean;
|
|
18
|
+
export declare const REMOVED_TYPES: Set<string>;
|
|
19
|
+
export declare const TYPED: Set<string>;
|
|
6
20
|
/** The payment method types there are: the PaymentMethod object's `type` in the served spec. */
|
|
7
21
|
export declare const PAYMENT_METHOD_TYPES: readonly string[];
|
|
8
22
|
/** The payment method types a Checkout Session takes: the vendored spec's (2026-09-30.endive) PostCheckoutSessions
|
|
@@ -10,5 +24,8 @@ export declare const PAYMENT_METHOD_TYPES: readonly string[];
|
|
|
10
24
|
* payment methods (e.g., `card`) this Checkout Session can accept"). It holds no in-person type (card_present,
|
|
11
25
|
* interac_present) and no `custom`. The surface keeps no request enums, so it is copied here. */
|
|
12
26
|
export declare const CHECKOUT_METHOD_TYPES: readonly string[];
|
|
13
|
-
/**
|
|
14
|
-
export declare
|
|
27
|
+
/** The create page each intent's refusal links to. */
|
|
28
|
+
export declare const TYPES_DOC: Record<string, string>;
|
|
29
|
+
/** An enum's values as Stripe lists them in a refusal: "a, b, or c". */
|
|
30
|
+
export declare const oneOf: (values: readonly string[]) => string;
|
|
31
|
+
export {};
|