@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
|
@@ -1,195 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
import { asBool } from "../stripe-twin.js";
|
|
4
|
-
import { at, at_, created, fail, newest, refundDestination } from "./shared.js";
|
|
5
|
-
// the reasons a caller may give; `expired_uncaptured_charge` is Stripe's own
|
|
6
|
-
const REFUND_REASONS = new Set(['duplicate', 'fraudulent', 'requested_by_customer']);
|
|
7
|
-
/**
|
|
8
|
-
* Create a refund and land it on its charge. An omitted amount is the whole remaining balance. The
|
|
9
|
-
* charge's write records `charge.refunded`, the event Stripe sends carrying the charge's new totals;
|
|
10
|
-
* `refunded` is true only at the full amount.
|
|
11
|
-
*/
|
|
12
|
-
/** A reason Stripe does not take (docs.stripe.com/api/refunds/create#create_refund-reason). */
|
|
13
|
-
function badReason(ctx) {
|
|
14
|
-
return fail(ctx, `Invalid refund reason: must be one of ${[...REFUND_REASONS].join(', ')}.`, 400, 'parameter_invalid_string_enum');
|
|
15
|
-
}
|
|
16
|
-
/** A bank-transfer payment refunded with origin=customer_balance goes back to the cash balance
|
|
17
|
-
* (docs.stripe.com/payments/customer-balance/refunding). */
|
|
18
|
-
async function backToCashBalance(ctx, customer, currency, amount, refundId) {
|
|
19
|
-
const before = ctx.rows('customer_cash_balance_transaction').filter((t) => t.customer === customer && String(t.currency) === currency).reduce((n, t) => n + (Number(t.net_amount) || 0), 0);
|
|
20
|
-
await created(ctx, 'customer_cash_balance_transaction', { customer }, { currency, type: 'refunded_from_payment', net_amount: amount, ending_balance: before + amount, refunded_from_payment: { refund: refundId }, livemode: false });
|
|
21
|
-
}
|
|
22
|
-
/** A capture=false charge's refund, which releases its whole authorization (see the header). */
|
|
23
|
-
async function refundUncaptured(ctx, charge, amount, remaining, params) {
|
|
24
|
-
if (amount < remaining)
|
|
25
|
-
return fail(ctx, `Charge ${String(charge.id)} is uncaptured: refunding it releases the whole authorization (${remaining}).`, 400, 'amount_too_small');
|
|
26
|
-
const { reason, metadata } = params;
|
|
27
|
-
return ctx.reply(await releaseAuthorization(ctx, charge, ctx.call.operation.id, { ...(reason !== undefined ? { reason } : {}), ...(metadata !== undefined ? { metadata } : {}) }));
|
|
28
|
-
}
|
|
29
|
-
export async function refundCharge(ctx, charge, params) {
|
|
30
|
-
const chargeId = String(charge.id);
|
|
31
|
-
const total = Number(charge.amount) || 0;
|
|
32
|
-
const already = Number(charge.amount_refunded) || 0;
|
|
33
|
-
const remaining = Math.max(0, total - already);
|
|
34
|
-
const amount = params.amount === undefined ? remaining : Math.trunc(Number(params.amount));
|
|
35
|
-
if (!Number.isFinite(amount) || amount <= 0)
|
|
36
|
-
return fail(ctx, 'Invalid integer: amount must be a positive integer.', 400, 'parameter_invalid_integer');
|
|
37
|
-
if (amount > remaining)
|
|
38
|
-
return fail(ctx, `Refund amount (${amount}) is greater than unrefunded amount on charge (${remaining}).`, 400, 'amount_too_large');
|
|
39
|
-
if (params.reason !== undefined && !REFUND_REASONS.has(String(params.reason)))
|
|
40
|
-
return badReason(ctx);
|
|
41
|
-
// an authorization is released, never refunded out of the balance: a PaymentIntent's by cancelling the intent, a
|
|
42
|
-
// capture=false charge's by its refund (refundUncaptured)
|
|
43
|
-
if (charge.captured === false && typeof charge.payment_intent === 'string')
|
|
44
|
-
return fail(ctx, `Charge ${chargeId} is uncaptured and can't be refunded directly; cancel its PaymentIntent (${charge.payment_intent}) to release the authorization.`, 400, 'payment_intent_unexpected_state');
|
|
45
|
-
if (charge.captured === false)
|
|
46
|
-
return refundUncaptured(ctx, charge, amount, remaining, params);
|
|
47
|
-
const refunded = already + amount;
|
|
48
|
-
// the refund that takes the rest refunds the charge: the charge machine's move under this operation
|
|
49
|
-
if (refunded >= total && charge.refunded !== true) {
|
|
50
|
-
const refused = ctx.legal('charge', 'refunded', ctx.call.operation.id, 'false', 'true', chargeId);
|
|
51
|
-
if (refused)
|
|
52
|
-
return ctx.refuse(refused);
|
|
53
|
-
}
|
|
54
|
-
// a refund has no `livemode` field; it debits the balance at once
|
|
55
|
-
const refundId = ctx.mint('refund');
|
|
56
|
-
const currency = String(charge.currency ?? 'usd');
|
|
57
|
-
const pi = typeof charge.payment_intent === 'string' ? ctx.get('payment_intent', charge.payment_intent) : undefined;
|
|
58
|
-
const byTransfer = (pi?.payment_method_types ?? []).includes('customer_balance');
|
|
59
|
-
const toCashBalance = byTransfer && params.origin === 'customer_balance';
|
|
60
|
-
const awaitsBank = byTransfer && !toCashBalance;
|
|
61
|
-
const now = Number(ctx.now());
|
|
62
|
-
const customer = typeof charge.customer === 'string' ? charge.customer : typeof pi?.customer === 'string' ? pi.customer : undefined;
|
|
63
|
-
const emailTo = typeof params.instructions_email === 'string' ? params.instructions_email : (customer ? ctx.get('customer', customer)?.email : undefined) ?? null;
|
|
64
|
-
// "Refunds use your available Stripe balance (not including pending amounts). If your available balance doesn't
|
|
65
|
-
// cover the amount of the refund, Stripe holds the refund as pending for card transactions ... until your Stripe
|
|
66
|
-
// balance becomes sufficient" (docs.stripe.com/refunds): the refund waits, moving no money, until the balance covers
|
|
67
|
-
// it (settleHeldRefunds). Where the documentation stops and the twin decides: a refund of another payment method
|
|
68
|
-
// short of balance is not modelled (Stripe fails it); the twin makes it as a card's.
|
|
69
|
-
const account = actingAccount(ctx);
|
|
70
|
-
const isCard = charge.payment_method_details?.type === 'card';
|
|
71
|
-
const held = !awaitsBank && !toCashBalance && isCard && availableAt(ctx, account, currency, now) < amount;
|
|
72
|
-
if (held)
|
|
73
|
-
ctx.legal('refund', 'status', ctx.call.operation.id, 'succeeded', 'pending', refundId);
|
|
74
|
-
const bt = awaitsBank || held ? null : await settleRefund(ctx, refundId, amount, currency);
|
|
75
|
-
if (toCashBalance && customer)
|
|
76
|
-
await backToCashBalance(ctx, customer, currency, amount, refundId);
|
|
77
|
-
const { reverse_transfer: reverseTransfer, refund_application_fee: refundFee, instructions_email: _email, origin: _origin, ...stored } = params;
|
|
78
|
-
const share = (whole) => Math.round((whole * amount) / (total || 1));
|
|
79
|
-
let transferReversal = null;
|
|
80
|
-
const transfer = typeof charge.transfer === 'string' ? ctx.get('transfer', charge.transfer) : undefined;
|
|
81
|
-
if (reverseTransfer !== undefined && asBool(reverseTransfer) && transfer) {
|
|
82
|
-
const back = Math.min(share(Number(transfer.amount) || 0), (Number(transfer.amount) || 0) - (Number(transfer.amount_reversed) || 0));
|
|
83
|
-
const trr = await created(ctx, 'transfer_reversal', { amount: back, currency, transfer: transfer.id }, { balance_transaction: null, destination_payment_refund: null, source_refund: refundId, metadata: {} });
|
|
84
|
-
const trrBt = await settleTransferReversal(ctx, String(trr.id), back, currency, String(transfer.destination));
|
|
85
|
-
const reversal = await ctx.write('transfer_reversal', String(trr.id), { balance_transaction: trrBt }, 'transfer_reversal.updated');
|
|
86
|
-
const reversed = (Number(transfer.amount_reversed) || 0) + back;
|
|
87
|
-
const list = transfer.reversals ?? { object: 'list', data: [], has_more: false, total_count: 0 };
|
|
88
|
-
const data = [...((list.data ?? [])), reversal];
|
|
89
|
-
await ctx.write('transfer', String(transfer.id), { amount_reversed: reversed, reversed: reversed >= (Number(transfer.amount) || 0), reversals: { ...list, data, total_count: data.length, url: `/v1/transfers/${String(transfer.id)}/reversals` } }, 'transfer.reversed');
|
|
90
|
-
transferReversal = String(trr.id);
|
|
91
|
-
}
|
|
92
|
-
const fee = typeof charge.application_fee === 'string' ? ctx.get('application_fee', charge.application_fee) : undefined;
|
|
93
|
-
if (refundFee !== undefined && asBool(refundFee) && fee) {
|
|
94
|
-
const feeTotal = Number(fee.amount) || 0;
|
|
95
|
-
const back = Math.min(share(feeTotal), feeTotal - (Number(fee.amount_refunded) || 0));
|
|
96
|
-
const done = (Number(fee.amount_refunded) || 0) + back;
|
|
97
|
-
if (!(done >= feeTotal && fee.refunded !== true && ctx.legal('application_fee', 'refunded', ctx.call.operation.id, 'false', 'true', String(fee.id)))) {
|
|
98
|
-
const fr = await created(ctx, 'fee_refund', { amount: back, currency, fee: fee.id }, { balance_transaction: null, metadata: {} });
|
|
99
|
-
const list = fee.refunds ?? { object: 'list', data: [], has_more: false, total_count: 0 };
|
|
100
|
-
const data = [...((list.data ?? [])), fr];
|
|
101
|
-
await ctx.write('application_fee', String(fee.id), { amount_refunded: done, refunded: done >= feeTotal, refunds: { ...list, data, total_count: data.length, url: `/v1/application_fees/${String(fee.id)}/refunds` } }, 'application_fee.refunded');
|
|
102
|
-
}
|
|
103
|
-
}
|
|
104
|
-
const body = await created(ctx, 'refund', {
|
|
105
|
-
...stored, id: refundId, charge: chargeId, amount, currency, transfer_reversal: transferReversal,
|
|
106
|
-
...(typeof charge.payment_intent === 'string' ? { payment_intent: charge.payment_intent } : {}),
|
|
107
|
-
}, {
|
|
108
|
-
status: awaitsBank ? 'requires_action' : held ? 'pending' : 'succeeded', metadata: {}, reason: null, receipt_number: null,
|
|
109
|
-
...(held ? { pending_reason: 'insufficient_funds', _account: account ?? null } : {}),
|
|
110
|
-
balance_transaction: bt, source_transfer_reversal: null,
|
|
111
|
-
// a bank transfer's refund goes to the customer's bank (a us_bank_transfer) or back to its cash balance
|
|
112
|
-
// (customer_cash_balance): "If this is a `us_bank_transfer` refund, this hash contains the transaction specific details",
|
|
113
|
-
// "If this is a `customer_cash_balance` refund ..." (docs.stripe.com/api/refunds/object, destination_details)
|
|
114
|
-
...(byTransfer
|
|
115
|
-
? { destination_details: toCashBalance ? { type: 'customer_cash_balance', customer_cash_balance: {} } : { type: 'us_bank_transfer', us_bank_transfer: { reference: null, reference_status: null } } }
|
|
116
|
-
: refundDestination(charge, 'refund')),
|
|
117
|
-
...(awaitsBank ? { next_action: { type: 'display_details', display_details: { email_sent: { email_sent_at: now, email_sent_to: emailTo }, expires_at: now + 30 * 86_400 } } } : {}),
|
|
118
|
-
});
|
|
119
|
-
await ctx.write('charge', chargeId, { amount_refunded: refunded, refunded: refunded >= total }, 'charge.refunded');
|
|
120
|
-
return ctx.reply(body);
|
|
121
|
-
}
|
|
122
|
-
/** Time's settling of held refunds, caught up to the World's clock: each refund held for want of balance, oldest first,
|
|
123
|
-
* is made at the first moment the account's available balance covers it (the funds that come due then), its debit
|
|
124
|
-
* written then, as `refund.updated`. Where the documentation stops and the twin decides: a held refund is made the
|
|
125
|
-
* moment the balance covers it. */
|
|
126
|
-
export async function settleHeldRefunds(ctx) {
|
|
127
|
-
const now = Number(ctx.now());
|
|
128
|
-
const heldRefunds = ctx.rowsRaw('refund').filter((r) => r.status === 'pending' && r.pending_reason === 'insufficient_funds').sort((a, b) => Number(a.created) - Number(b.created));
|
|
129
|
-
for (const r of heldRefunds) {
|
|
130
|
-
const account = typeof r._account === 'string' ? r._account : undefined;
|
|
131
|
-
const currency = String(r.currency ?? 'usd');
|
|
132
|
-
const amount = Number(r.amount) || 0;
|
|
133
|
-
const when = [Number(r.created), ...fundsDueBetween(ctx, account, currency, Number(r.created), now)].find((t) => availableAt(ctx, account, currency, t) >= amount);
|
|
134
|
-
if (when === undefined)
|
|
135
|
-
continue;
|
|
136
|
-
const c = await at_(ctx)(when);
|
|
137
|
-
c.legal('refund', 'status', ctx.call.operation.id, 'pending', 'succeeded', String(r.id), 'vendor');
|
|
138
|
-
const bt = await settleRefund(c, String(r.id), amount, currency, account ?? null);
|
|
139
|
-
await c.write('refund', String(r.id), { status: 'succeeded', pending_reason: null, balance_transaction: bt }, 'refund.updated');
|
|
140
|
-
}
|
|
141
|
-
}
|
|
142
|
-
/** The charge a refund aims at: named directly, or reached through its PaymentIntent. */
|
|
143
|
-
function target(ctx) {
|
|
144
|
-
const chargeId = typeof ctx.params.charge === 'string' ? ctx.params.charge : '';
|
|
145
|
-
const piId = typeof ctx.params.payment_intent === 'string' ? ctx.params.payment_intent : '';
|
|
146
|
-
if (!chargeId && !piId)
|
|
147
|
-
return fail(ctx, 'One of `charge` or `payment_intent` is required.', 400, 'parameter_missing');
|
|
148
|
-
if (chargeId)
|
|
149
|
-
return ctx.get('charge', chargeId) ?? fail(ctx, `No such charge: '${chargeId}'`, 404, 'resource_missing');
|
|
150
|
-
const pi = ctx.get('payment_intent', piId);
|
|
151
|
-
if (!pi)
|
|
152
|
-
return fail(ctx, `No such payment_intent: '${piId}'`, 404, 'resource_missing');
|
|
153
|
-
const latest = typeof pi.latest_charge === 'string' ? pi.latest_charge : undefined;
|
|
154
|
-
const ch = (latest ? ctx.get('charge', latest) : undefined) ?? newest(ctx, 'charge').find((c) => c.payment_intent === piId);
|
|
155
|
-
return ch ?? fail(ctx, `This PaymentIntent does not have a successful charge to refund. Its status is ${String(pi.status)}.`, 400, 'payment_intent_unexpected_state');
|
|
156
|
-
}
|
|
157
|
-
const create = async (ctx) => {
|
|
1
|
+
import { refundCharge, target } from "./shared.js";
|
|
2
|
+
export async function PostRefunds(ctx) {
|
|
158
3
|
const ch = target(ctx);
|
|
159
4
|
return ch instanceof Response ? ch : refundCharge(ctx, ch, ctx.params);
|
|
160
|
-
}
|
|
161
|
-
const refundMissing = (ctx, id) => fail(ctx, `No such refund: '${id}'`, 404, 'resource_missing');
|
|
162
|
-
const retrieve = async (ctx) => {
|
|
163
|
-
const r = ctx.get('refund', at(ctx, 'refund'));
|
|
164
|
-
return r ? ctx.reply(r) : refundMissing(ctx, at(ctx, 'refund'));
|
|
165
|
-
};
|
|
166
|
-
// a canceled pending refund gives its money back to the charge: pending funds were already taken out
|
|
167
|
-
const cancel = async (ctx) => {
|
|
168
|
-
const id = at(ctx, 'refund');
|
|
169
|
-
const r = ctx.get('refund', id);
|
|
170
|
-
if (!r)
|
|
171
|
-
return refundMissing(ctx, id);
|
|
172
|
-
const refused = ctx.legal('refund', 'status', 'PostRefundsRefundCancel', r.status, undefined, id);
|
|
173
|
-
if (refused)
|
|
174
|
-
return ctx.refuse(refused);
|
|
175
|
-
// next_action says what a refund "needs to continue processing" "If the refund has a status of requires_action"
|
|
176
|
-
// (docs.stripe.com/api/refunds/object): a canceled one needs nothing
|
|
177
|
-
const canceled = await ctx.write('refund', id, { status: 'canceled', next_action: null }, 'refund.updated');
|
|
178
|
-
const chargeId = typeof r.charge === 'string' ? r.charge : '';
|
|
179
|
-
const ch = chargeId ? ctx.get('charge', chargeId) : undefined;
|
|
180
|
-
if (ch) {
|
|
181
|
-
const total = Number(ch.amount) || 0;
|
|
182
|
-
const back = Math.max(0, (Number(ch.amount_refunded) || 0) - (Number(r.amount) || 0));
|
|
183
|
-
const refunded = back > 0 && back >= total;
|
|
184
|
-
// a charge the canceled refund had fully refunded is no longer refunded
|
|
185
|
-
if (refunded !== (ch.refunded === true))
|
|
186
|
-
ctx.legal('charge', 'refunded', 'PostRefundsRefundCancel', String(ch.refunded === true), String(refunded), chargeId);
|
|
187
|
-
await ctx.write('charge', chargeId, { amount_refunded: back, refunded }, 'charge.update');
|
|
188
|
-
}
|
|
189
|
-
return ctx.reply(canceled);
|
|
190
|
-
};
|
|
191
|
-
export const refunds = {
|
|
192
|
-
PostRefunds: create,
|
|
193
|
-
GetRefundsRefund: retrieve,
|
|
194
|
-
PostRefundsRefundCancel: cancel,
|
|
195
|
-
};
|
|
5
|
+
}
|