@whop/elements-react-native 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +179 -0
- package/android/build.gradle +64 -0
- package/android/consumer-rules.pro +3 -0
- package/android/gradle.properties +5 -0
- package/android/src/main/java/com/whop/elements/WhopAddressSuggestionsModule.kt +102 -0
- package/android/src/main/java/com/whop/elements/WhopAuthSessionModule.kt +126 -0
- package/android/src/main/java/com/whop/elements/WhopElementsPackage.kt +39 -0
- package/android/src/main/java/com/whop/elements/WhopPayButtonManager.kt +74 -0
- package/android/src/main/java/com/whop/elements/WhopPayButtonPressEvent.kt +17 -0
- package/android/src/main/java/com/whop/elements/WhopPayButtonView.kt +178 -0
- package/android/src/main/java/com/whop/elements/WhopPlatformPayModule.kt +212 -0
- package/assets/whop-wordmark-dark.png +0 -0
- package/assets/whop-wordmark-dark@2x.png +0 -0
- package/assets/whop-wordmark-dark@3x.png +0 -0
- package/assets/whop-wordmark-light.png +0 -0
- package/assets/whop-wordmark-light@2x.png +0 -0
- package/assets/whop-wordmark-light@3x.png +0 -0
- package/ios/Package.swift +59 -0
- package/ios/Sources/ElementsReactNative/WhopAddressSuggestionsImpl.swift +189 -0
- package/ios/Sources/ElementsReactNative/WhopAuthSessionImpl.swift +106 -0
- package/ios/Sources/ElementsReactNative/WhopPayButtonImpl.swift +89 -0
- package/ios/Sources/ElementsReactNative/WhopPlatformPayImpl.swift +181 -0
- package/ios/generated/WhopAddressSuggestionsModule.h +11 -0
- package/ios/generated/WhopAddressSuggestionsModule.mm +46 -0
- package/ios/generated/WhopAuthSessionModule.h +11 -0
- package/ios/generated/WhopAuthSessionModule.mm +45 -0
- package/ios/generated/WhopElementsShims.h +35 -0
- package/ios/generated/WhopPayButtonComponentView.h +12 -0
- package/ios/generated/WhopPayButtonComponentView.mm +82 -0
- package/ios/generated/WhopPlatformPayModule.h +11 -0
- package/ios/generated/WhopPlatformPayModule.mm +51 -0
- package/lib/module/api/client.js +139 -0
- package/lib/module/api/client.js.map +1 -0
- package/lib/module/api/client.test.js +137 -0
- package/lib/module/api/client.test.js.map +1 -0
- package/lib/module/api/types.js +2 -0
- package/lib/module/api/types.js.map +1 -0
- package/lib/module/controller/actions.js +148 -0
- package/lib/module/controller/actions.js.map +1 -0
- package/lib/module/controller/actions.test.js +102 -0
- package/lib/module/controller/actions.test.js.map +1 -0
- package/lib/module/controller/store.js +158 -0
- package/lib/module/controller/store.js.map +1 -0
- package/lib/module/core/address/country-data.js +1370 -0
- package/lib/module/core/address/country-data.js.map +1 -0
- package/lib/module/core/address/country-name.js +38 -0
- package/lib/module/core/address/country-name.js.map +1 -0
- package/lib/module/core/address/country-names.generated.js +249 -0
- package/lib/module/core/address/country-names.generated.js.map +1 -0
- package/lib/module/core/address/engine.js +245 -0
- package/lib/module/core/address/engine.js.map +1 -0
- package/lib/module/core/address/engine.test.js +216 -0
- package/lib/module/core/address/engine.test.js.map +1 -0
- package/lib/module/core/address/form-state.js +409 -0
- package/lib/module/core/address/form-state.js.map +1 -0
- package/lib/module/core/address/form-state.test.js +516 -0
- package/lib/module/core/address/form-state.test.js.map +1 -0
- package/lib/module/core/address/places.js +36 -0
- package/lib/module/core/address/places.js.map +1 -0
- package/lib/module/core/address/required-coverage.test.js +57 -0
- package/lib/module/core/address/required-coverage.test.js.map +1 -0
- package/lib/module/core/address/suggest.js +102 -0
- package/lib/module/core/address/suggest.js.map +1 -0
- package/lib/module/core/address/suggest.test.js +156 -0
- package/lib/module/core/address/suggest.test.js.map +1 -0
- package/lib/module/core/address/use-suggestions.js +33 -0
- package/lib/module/core/address/use-suggestions.js.map +1 -0
- package/lib/module/core/payments/address-change.js +91 -0
- package/lib/module/core/payments/address-change.js.map +1 -0
- package/lib/module/core/payments/billing-merge.js +62 -0
- package/lib/module/core/payments/billing-merge.js.map +1 -0
- package/lib/module/core/payments/browser-info.js +42 -0
- package/lib/module/core/payments/browser-info.js.map +1 -0
- package/lib/module/core/payments/bt.js +151 -0
- package/lib/module/core/payments/bt.js.map +1 -0
- package/lib/module/core/payments/bt.test.js +23 -0
- package/lib/module/core/payments/bt.test.js.map +1 -0
- package/lib/module/core/payments/currency.js +37 -0
- package/lib/module/core/payments/currency.js.map +1 -0
- package/lib/module/core/payments/detail.js +159 -0
- package/lib/module/core/payments/detail.js.map +1 -0
- package/lib/module/core/payments/detail.test.js +225 -0
- package/lib/module/core/payments/detail.test.js.map +1 -0
- package/lib/module/core/payments/errors.js +115 -0
- package/lib/module/core/payments/errors.js.map +1 -0
- package/lib/module/core/payments/mint.js +89 -0
- package/lib/module/core/payments/mint.js.map +1 -0
- package/lib/module/core/payments/plan.js +131 -0
- package/lib/module/core/payments/plan.js.map +1 -0
- package/lib/module/core/payments/refusals.js +17 -0
- package/lib/module/core/payments/refusals.js.map +1 -0
- package/lib/module/core/payments/secure-fields.js +87 -0
- package/lib/module/core/payments/secure-fields.js.map +1 -0
- package/lib/module/core/payments/tax-id-catalog.js +616 -0
- package/lib/module/core/payments/tax-id-catalog.js.map +1 -0
- package/lib/module/core/payments/wallet-contact.js +42 -0
- package/lib/module/core/payments/wallet-contact.js.map +1 -0
- package/lib/module/core/payments/wallet-contact.test.js +77 -0
- package/lib/module/core/payments/wallet-contact.test.js.map +1 -0
- package/lib/module/elements/address.js +467 -0
- package/lib/module/elements/address.js.map +1 -0
- package/lib/module/elements/branding.js +114 -0
- package/lib/module/elements/branding.js.map +1 -0
- package/lib/module/elements/card-fields/context.js +254 -0
- package/lib/module/elements/card-fields/context.js.map +1 -0
- package/lib/module/elements/card-fields/fields.js +309 -0
- package/lib/module/elements/card-fields/fields.js.map +1 -0
- package/lib/module/elements/card-fields/index.js +30 -0
- package/lib/module/elements/card-fields/index.js.map +1 -0
- package/lib/module/elements/card.js +107 -0
- package/lib/module/elements/card.js.map +1 -0
- package/lib/module/elements/email.js +84 -0
- package/lib/module/elements/email.js.map +1 -0
- package/lib/module/elements/payment/declared-fields.js +186 -0
- package/lib/module/elements/payment/declared-fields.js.map +1 -0
- package/lib/module/elements/payment/index.js +448 -0
- package/lib/module/elements/payment/index.js.map +1 -0
- package/lib/module/elements/payment/wallet.js +132 -0
- package/lib/module/elements/payment/wallet.js.map +1 -0
- package/lib/module/elements/tax-id.js +100 -0
- package/lib/module/elements/tax-id.js.map +1 -0
- package/lib/module/i18n/catalogs.js +103 -0
- package/lib/module/i18n/catalogs.js.map +1 -0
- package/lib/module/i18n/index.js +45 -0
- package/lib/module/i18n/index.js.map +1 -0
- package/lib/module/index.js +27 -0
- package/lib/module/index.js.map +1 -0
- package/lib/module/namespace.js +174 -0
- package/lib/module/namespace.js.map +1 -0
- package/lib/module/native/index.js +128 -0
- package/lib/module/native/index.js.map +1 -0
- package/lib/module/package.json +1 -0
- package/lib/module/provider.js +56 -0
- package/lib/module/provider.js.map +1 -0
- package/lib/module/specs/NativeWhopAddressSuggestions.js +6 -0
- package/lib/module/specs/NativeWhopAddressSuggestions.js.map +1 -0
- package/lib/module/specs/NativeWhopAuthSession.js +10 -0
- package/lib/module/specs/NativeWhopAuthSession.js.map +1 -0
- package/lib/module/specs/NativeWhopPlatformPay.js +10 -0
- package/lib/module/specs/NativeWhopPlatformPay.js.map +1 -0
- package/lib/module/specs/WhopPayButtonNativeComponent.ts +22 -0
- package/lib/module/theme/appearance.js +85 -0
- package/lib/module/theme/appearance.js.map +1 -0
- package/lib/module/theme/appearance.test.js +124 -0
- package/lib/module/theme/appearance.test.js.map +1 -0
- package/lib/module/theme/provider.js +25 -0
- package/lib/module/theme/provider.js.map +1 -0
- package/lib/module/theme/resolve.js +69 -0
- package/lib/module/theme/resolve.js.map +1 -0
- package/lib/module/theme/scales.generated.js +419 -0
- package/lib/module/theme/scales.generated.js.map +1 -0
- package/lib/module/ui/element-frame.js +83 -0
- package/lib/module/ui/element-frame.js.map +1 -0
- package/lib/module/ui/payment-method-icon.js +69 -0
- package/lib/module/ui/payment-method-icon.js.map +1 -0
- package/lib/module/ui/primitives.js +266 -0
- package/lib/module/ui/primitives.js.map +1 -0
- package/lib/module/ui/select.js +281 -0
- package/lib/module/ui/select.js.map +1 -0
- package/lib/module/ui/suggestions.js +71 -0
- package/lib/module/ui/suggestions.js.map +1 -0
- package/lib/module/ui/whop-logo.js +42 -0
- package/lib/module/ui/whop-logo.js.map +1 -0
- package/lib/typescript/package.json +1 -0
- package/lib/typescript/src/api/client.d.ts +87 -0
- package/lib/typescript/src/api/client.d.ts.map +1 -0
- package/lib/typescript/src/api/types.d.ts +175 -0
- package/lib/typescript/src/api/types.d.ts.map +1 -0
- package/lib/typescript/src/controller/actions.d.ts +42 -0
- package/lib/typescript/src/controller/actions.d.ts.map +1 -0
- package/lib/typescript/src/controller/store.d.ts +90 -0
- package/lib/typescript/src/controller/store.d.ts.map +1 -0
- package/lib/typescript/src/core/address/country-data.d.ts +4 -0
- package/lib/typescript/src/core/address/country-data.d.ts.map +1 -0
- package/lib/typescript/src/core/address/country-name.d.ts +2 -0
- package/lib/typescript/src/core/address/country-name.d.ts.map +1 -0
- package/lib/typescript/src/core/address/country-names.generated.d.ts +2 -0
- package/lib/typescript/src/core/address/country-names.generated.d.ts.map +1 -0
- package/lib/typescript/src/core/address/engine.d.ts +97 -0
- package/lib/typescript/src/core/address/engine.d.ts.map +1 -0
- package/lib/typescript/src/core/address/form-state.d.ts +144 -0
- package/lib/typescript/src/core/address/form-state.d.ts.map +1 -0
- package/lib/typescript/src/core/address/places.d.ts +23 -0
- package/lib/typescript/src/core/address/places.d.ts.map +1 -0
- package/lib/typescript/src/core/address/suggest.d.ts +47 -0
- package/lib/typescript/src/core/address/suggest.d.ts.map +1 -0
- package/lib/typescript/src/core/address/use-suggestions.d.ts +3 -0
- package/lib/typescript/src/core/address/use-suggestions.d.ts.map +1 -0
- package/lib/typescript/src/core/payments/address-change.d.ts +52 -0
- package/lib/typescript/src/core/payments/address-change.d.ts.map +1 -0
- package/lib/typescript/src/core/payments/billing-merge.d.ts +39 -0
- package/lib/typescript/src/core/payments/billing-merge.d.ts.map +1 -0
- package/lib/typescript/src/core/payments/browser-info.d.ts +12 -0
- package/lib/typescript/src/core/payments/browser-info.d.ts.map +1 -0
- package/lib/typescript/src/core/payments/bt.d.ts +55 -0
- package/lib/typescript/src/core/payments/bt.d.ts.map +1 -0
- package/lib/typescript/src/core/payments/currency.d.ts +7 -0
- package/lib/typescript/src/core/payments/currency.d.ts.map +1 -0
- package/lib/typescript/src/core/payments/detail.d.ts +53 -0
- package/lib/typescript/src/core/payments/detail.d.ts.map +1 -0
- package/lib/typescript/src/core/payments/errors.d.ts +62 -0
- package/lib/typescript/src/core/payments/errors.d.ts.map +1 -0
- package/lib/typescript/src/core/payments/mint.d.ts +74 -0
- package/lib/typescript/src/core/payments/mint.d.ts.map +1 -0
- package/lib/typescript/src/core/payments/plan.d.ts +69 -0
- package/lib/typescript/src/core/payments/plan.d.ts.map +1 -0
- package/lib/typescript/src/core/payments/refusals.d.ts +12 -0
- package/lib/typescript/src/core/payments/refusals.d.ts.map +1 -0
- package/lib/typescript/src/core/payments/secure-fields.d.ts +33 -0
- package/lib/typescript/src/core/payments/secure-fields.d.ts.map +1 -0
- package/lib/typescript/src/core/payments/tax-id-catalog.d.ts +481 -0
- package/lib/typescript/src/core/payments/tax-id-catalog.d.ts.map +1 -0
- package/lib/typescript/src/core/payments/wallet-contact.d.ts +40 -0
- package/lib/typescript/src/core/payments/wallet-contact.d.ts.map +1 -0
- package/lib/typescript/src/elements/address.d.ts +55 -0
- package/lib/typescript/src/elements/address.d.ts.map +1 -0
- package/lib/typescript/src/elements/branding.d.ts +18 -0
- package/lib/typescript/src/elements/branding.d.ts.map +1 -0
- package/lib/typescript/src/elements/card-fields/context.d.ts +67 -0
- package/lib/typescript/src/elements/card-fields/context.d.ts.map +1 -0
- package/lib/typescript/src/elements/card-fields/fields.d.ts +15 -0
- package/lib/typescript/src/elements/card-fields/fields.d.ts.map +1 -0
- package/lib/typescript/src/elements/card-fields/index.d.ts +21 -0
- package/lib/typescript/src/elements/card-fields/index.d.ts.map +1 -0
- package/lib/typescript/src/elements/card.d.ts +21 -0
- package/lib/typescript/src/elements/card.d.ts.map +1 -0
- package/lib/typescript/src/elements/email.d.ts +31 -0
- package/lib/typescript/src/elements/email.d.ts.map +1 -0
- package/lib/typescript/src/elements/payment/declared-fields.d.ts +43 -0
- package/lib/typescript/src/elements/payment/declared-fields.d.ts.map +1 -0
- package/lib/typescript/src/elements/payment/index.d.ts +37 -0
- package/lib/typescript/src/elements/payment/index.d.ts.map +1 -0
- package/lib/typescript/src/elements/payment/wallet.d.ts +39 -0
- package/lib/typescript/src/elements/payment/wallet.d.ts.map +1 -0
- package/lib/typescript/src/elements/tax-id.d.ts +41 -0
- package/lib/typescript/src/elements/tax-id.d.ts.map +1 -0
- package/lib/typescript/src/i18n/catalogs.d.ts +7 -0
- package/lib/typescript/src/i18n/catalogs.d.ts.map +1 -0
- package/lib/typescript/src/i18n/index.d.ts +17 -0
- package/lib/typescript/src/i18n/index.d.ts.map +1 -0
- package/lib/typescript/src/index.d.ts +42 -0
- package/lib/typescript/src/index.d.ts.map +1 -0
- package/lib/typescript/src/namespace.d.ts +36 -0
- package/lib/typescript/src/namespace.d.ts.map +1 -0
- package/lib/typescript/src/native/index.d.ts +62 -0
- package/lib/typescript/src/native/index.d.ts.map +1 -0
- package/lib/typescript/src/provider.d.ts +37 -0
- package/lib/typescript/src/provider.d.ts.map +1 -0
- package/lib/typescript/src/specs/NativeWhopAddressSuggestions.d.ts +13 -0
- package/lib/typescript/src/specs/NativeWhopAddressSuggestions.d.ts.map +1 -0
- package/lib/typescript/src/specs/NativeWhopAuthSession.d.ts +20 -0
- package/lib/typescript/src/specs/NativeWhopAuthSession.d.ts.map +1 -0
- package/lib/typescript/src/specs/NativeWhopPlatformPay.d.ts +24 -0
- package/lib/typescript/src/specs/NativeWhopPlatformPay.d.ts.map +1 -0
- package/lib/typescript/src/specs/WhopPayButtonNativeComponent.d.ts +21 -0
- package/lib/typescript/src/specs/WhopPayButtonNativeComponent.d.ts.map +1 -0
- package/lib/typescript/src/theme/appearance.d.ts +71 -0
- package/lib/typescript/src/theme/appearance.d.ts.map +1 -0
- package/lib/typescript/src/theme/provider.d.ts +11 -0
- package/lib/typescript/src/theme/provider.d.ts.map +1 -0
- package/lib/typescript/src/theme/resolve.d.ts +19 -0
- package/lib/typescript/src/theme/resolve.d.ts.map +1 -0
- package/lib/typescript/src/theme/scales.generated.d.ts +18 -0
- package/lib/typescript/src/theme/scales.generated.d.ts.map +1 -0
- package/lib/typescript/src/ui/element-frame.d.ts +32 -0
- package/lib/typescript/src/ui/element-frame.d.ts.map +1 -0
- package/lib/typescript/src/ui/payment-method-icon.d.ts +21 -0
- package/lib/typescript/src/ui/payment-method-icon.d.ts.map +1 -0
- package/lib/typescript/src/ui/primitives.d.ts +94 -0
- package/lib/typescript/src/ui/primitives.d.ts.map +1 -0
- package/lib/typescript/src/ui/select.d.ts +25 -0
- package/lib/typescript/src/ui/select.d.ts.map +1 -0
- package/lib/typescript/src/ui/suggestions.d.ts +15 -0
- package/lib/typescript/src/ui/suggestions.d.ts.map +1 -0
- package/lib/typescript/src/ui/whop-logo.d.ts +4 -0
- package/lib/typescript/src/ui/whop-logo.d.ts.map +1 -0
- package/package.json +121 -0
- package/scripts/check-swift.sh +27 -0
- package/scripts/codegen-shims.mjs +409 -0
- package/scripts/gen-country-names.mjs +58 -0
- package/scripts/gen-theme.mjs +124 -0
- package/scripts/gen-wordmark.mjs +68 -0
- package/scripts/mirror.mjs +112 -0
- package/src/api/client.ts +202 -0
- package/src/api/types.ts +166 -0
- package/src/controller/actions.ts +197 -0
- package/src/controller/store.ts +201 -0
- package/src/core/address/country-data.ts +927 -0
- package/src/core/address/country-name.ts +36 -0
- package/src/core/address/country-names.generated.ts +246 -0
- package/src/core/address/engine.ts +349 -0
- package/src/core/address/form-state.ts +479 -0
- package/src/core/address/places.ts +39 -0
- package/src/core/address/suggest.ts +153 -0
- package/src/core/address/use-suggestions.ts +37 -0
- package/src/core/payments/address-change.ts +121 -0
- package/src/core/payments/billing-merge.ts +91 -0
- package/src/core/payments/browser-info.ts +43 -0
- package/src/core/payments/bt.ts +176 -0
- package/src/core/payments/currency.ts +54 -0
- package/src/core/payments/detail.ts +204 -0
- package/src/core/payments/errors.ts +171 -0
- package/src/core/payments/mint.ts +130 -0
- package/src/core/payments/plan.ts +198 -0
- package/src/core/payments/refusals.ts +24 -0
- package/src/core/payments/secure-fields.ts +85 -0
- package/src/core/payments/tax-id-catalog.ts +320 -0
- package/src/core/payments/wallet-contact.ts +56 -0
- package/src/elements/address.tsx +570 -0
- package/src/elements/branding.tsx +87 -0
- package/src/elements/card-fields/context.tsx +310 -0
- package/src/elements/card-fields/fields.tsx +281 -0
- package/src/elements/card-fields/index.tsx +37 -0
- package/src/elements/card.tsx +101 -0
- package/src/elements/email.tsx +100 -0
- package/src/elements/payment/declared-fields.tsx +238 -0
- package/src/elements/payment/index.tsx +497 -0
- package/src/elements/payment/wallet.tsx +155 -0
- package/src/elements/tax-id.tsx +143 -0
- package/src/i18n/catalogs.ts +100 -0
- package/src/i18n/index.tsx +46 -0
- package/src/index.ts +68 -0
- package/src/namespace.tsx +231 -0
- package/src/native/index.ts +173 -0
- package/src/provider.tsx +76 -0
- package/src/specs/NativeWhopAddressSuggestions.ts +14 -0
- package/src/specs/NativeWhopAuthSession.ts +21 -0
- package/src/specs/NativeWhopPlatformPay.ts +25 -0
- package/src/specs/WhopPayButtonNativeComponent.ts +22 -0
- package/src/theme/appearance.ts +150 -0
- package/src/theme/provider.tsx +28 -0
- package/src/theme/resolve.ts +68 -0
- package/src/theme/scales.generated.ts +427 -0
- package/src/ui/element-frame.tsx +94 -0
- package/src/ui/payment-method-icon.tsx +55 -0
- package/src/ui/primitives.tsx +269 -0
- package/src/ui/select.tsx +255 -0
- package/src/ui/suggestions.tsx +69 -0
- package/src/ui/whop-logo.tsx +37 -0
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
import { sha256 } from '@noble/hashes/sha2';
|
|
4
|
+
import { bytesToHex } from '@noble/hashes/utils';
|
|
5
|
+
import { apiErrorMessage } from "./errors.js";
|
|
6
|
+
|
|
7
|
+
/** The package re-exports the hook but not its return type, so derive it rather than reach into a
|
|
8
|
+
* deep path that could move. */
|
|
9
|
+
|
|
10
|
+
/** The opaque handle a Basis Theory element hands out. It carries an id and a formatter, never the
|
|
11
|
+
* value the buyer typed — which is the whole isolation guarantee. */
|
|
12
|
+
|
|
13
|
+
const CARD_TOKEN_TTL_MS = 60 * 60 * 1000;
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Assemble one Basis Theory card token from the three field refs.
|
|
17
|
+
*
|
|
18
|
+
* This is the web ceremony (`card-fields/bt.ts`) with the frame hops removed: a BT session anchors
|
|
19
|
+
* a nonce-derived container, the number seeds an ephemeral token into it, the Whop backend
|
|
20
|
+
* authorizes the session for that container alone, and the remaining fields patch in under the
|
|
21
|
+
* session key. The web element splits these across three iframes and threads a serializable grant
|
|
22
|
+
* between them; here all three refs live in one realm, so the grant never leaves this function.
|
|
23
|
+
*
|
|
24
|
+
* The ceremony is kept rather than collapsed into a single create because it is what the
|
|
25
|
+
* card-assembly Basis Theory application is configured to permit: the backend authorizes
|
|
26
|
+
* `token:update` scoped to `starts_with` the derived container, for ten minutes.
|
|
27
|
+
*/
|
|
28
|
+
export async function tokenizeCard(bt, refs, command, sdk) {
|
|
29
|
+
if (!refs.number || !refs.expiryMonth || !refs.expiryYear || !refs.cvc) {
|
|
30
|
+
return {
|
|
31
|
+
ok: false,
|
|
32
|
+
code: 'card_fields_not_ready',
|
|
33
|
+
message: 'Card fields are not ready yet'
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
let session;
|
|
37
|
+
try {
|
|
38
|
+
session = await bt.sessions.create();
|
|
39
|
+
} catch (err) {
|
|
40
|
+
return collectFailure(err, 'card_tokenizer_session_failed', 'card_tokenizer_session_failed');
|
|
41
|
+
}
|
|
42
|
+
if (!session) {
|
|
43
|
+
return {
|
|
44
|
+
ok: false,
|
|
45
|
+
code: 'card_tokenizer_session_failed',
|
|
46
|
+
message: 'the tokenizer returned no session'
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
const container = `/card-assembly/${sha256Hex(session.nonce)}/`;
|
|
50
|
+
let tokenId;
|
|
51
|
+
try {
|
|
52
|
+
const token = await bt.tokens.create({
|
|
53
|
+
type: 'card',
|
|
54
|
+
data: {
|
|
55
|
+
number: refs.number
|
|
56
|
+
},
|
|
57
|
+
containers: [container],
|
|
58
|
+
expiresAt: new Date(Date.now() + CARD_TOKEN_TTL_MS).toISOString()
|
|
59
|
+
},
|
|
60
|
+
// The key is passed per call, never left to the client's config: Basis Theory's client
|
|
61
|
+
// is a module-level singleton whose first key wins for the whole process, so a second
|
|
62
|
+
// client built with a different application's key (a method's secure fields) would
|
|
63
|
+
// otherwise silently sign these calls.
|
|
64
|
+
{
|
|
65
|
+
apiKey: command.publicKey
|
|
66
|
+
});
|
|
67
|
+
if (!token?.id) {
|
|
68
|
+
return {
|
|
69
|
+
ok: false,
|
|
70
|
+
code: 'card_number_tokenization_failed',
|
|
71
|
+
message: 'the tokenizer returned no token'
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
tokenId = token.id;
|
|
75
|
+
} catch (err) {
|
|
76
|
+
return collectFailure(err, 'card_number_validation_failed', 'card_number_tokenization_failed');
|
|
77
|
+
}
|
|
78
|
+
try {
|
|
79
|
+
await sdk.paymentMethodTypes.createSession('card', {
|
|
80
|
+
account_id: command.accountId,
|
|
81
|
+
nonce: session.nonce
|
|
82
|
+
});
|
|
83
|
+
} catch (err) {
|
|
84
|
+
return {
|
|
85
|
+
ok: false,
|
|
86
|
+
code: 'card_session_authorization_failed',
|
|
87
|
+
message: apiErrorMessage(err, 'card session authorization failed')
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
try {
|
|
91
|
+
await bt.tokens.update(tokenId, {
|
|
92
|
+
data: {
|
|
93
|
+
expiration_month: refs.expiryMonth,
|
|
94
|
+
expiration_year: refs.expiryYear
|
|
95
|
+
}
|
|
96
|
+
}, {
|
|
97
|
+
apiKey: session.sessionKey
|
|
98
|
+
});
|
|
99
|
+
} catch (err) {
|
|
100
|
+
return collectFailure(err, 'card_expiry_validation_failed', 'card_expiry_tokenization_failed');
|
|
101
|
+
}
|
|
102
|
+
try {
|
|
103
|
+
await bt.tokens.update(tokenId, {
|
|
104
|
+
data: {
|
|
105
|
+
cvc: refs.cvc
|
|
106
|
+
}
|
|
107
|
+
}, {
|
|
108
|
+
apiKey: session.sessionKey
|
|
109
|
+
});
|
|
110
|
+
} catch (err) {
|
|
111
|
+
return collectFailure(err, 'card_cvc_validation_failed', 'card_cvc_tokenization_failed');
|
|
112
|
+
}
|
|
113
|
+
return {
|
|
114
|
+
ok: true,
|
|
115
|
+
token: tokenId
|
|
116
|
+
};
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
/**
|
|
120
|
+
* Must byte-match the backend's `Digest::SHA256.hexdigest` — lowercase hex, no separators.
|
|
121
|
+
*
|
|
122
|
+
* `@noble/hashes` UTF-8 encodes a string input itself, which is also why this does not reach for
|
|
123
|
+
* `TextEncoder`: React Native has no DOM and does not guarantee one.
|
|
124
|
+
*/
|
|
125
|
+
export function sha256Hex(value) {
|
|
126
|
+
return bytesToHex(sha256(value));
|
|
127
|
+
}
|
|
128
|
+
function collectFailure(err, validationCode, failureCode) {
|
|
129
|
+
const details = err instanceof Error && err.name === 'BasisTheoryValidationError' ? err.details?.data : undefined;
|
|
130
|
+
if (details) {
|
|
131
|
+
return {
|
|
132
|
+
ok: false,
|
|
133
|
+
code: validationCode,
|
|
134
|
+
message: 'Your card details are incomplete or invalid',
|
|
135
|
+
fields: {
|
|
136
|
+
number: fieldFailure(details.number),
|
|
137
|
+
cvc: fieldFailure(details.cvc),
|
|
138
|
+
expiry: fieldFailure(details.expiration_month) ?? fieldFailure(details.expiration_year)
|
|
139
|
+
}
|
|
140
|
+
};
|
|
141
|
+
}
|
|
142
|
+
return {
|
|
143
|
+
ok: false,
|
|
144
|
+
code: failureCode,
|
|
145
|
+
message: err instanceof Error ? err.message : 'Card tokenization failed'
|
|
146
|
+
};
|
|
147
|
+
}
|
|
148
|
+
function fieldFailure(detail) {
|
|
149
|
+
return detail?.type === 'invalid' || detail?.type === 'incomplete' ? detail.type : undefined;
|
|
150
|
+
}
|
|
151
|
+
//# sourceMappingURL=bt.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["sha256","bytesToHex","apiErrorMessage","CARD_TOKEN_TTL_MS","tokenizeCard","bt","refs","command","sdk","number","expiryMonth","expiryYear","cvc","ok","code","message","session","sessions","create","err","collectFailure","container","sha256Hex","nonce","tokenId","token","tokens","type","data","containers","expiresAt","Date","now","toISOString","apiKey","publicKey","id","paymentMethodTypes","createSession","account_id","accountId","update","expiration_month","expiration_year","sessionKey","value","validationCode","failureCode","details","Error","name","undefined","fields","fieldFailure","expiry","detail"],"sourceRoot":"../../../../src","sources":["core/payments/bt.ts"],"mappings":"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","ignoreList":[]}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
import { describe, expect, it } from 'vitest';
|
|
4
|
+
import { sha256Hex } from "./bt.js";
|
|
5
|
+
describe('sha256Hex', () => {
|
|
6
|
+
// The backend derives the card-assembly container as
|
|
7
|
+
// "/card-assembly/#{Digest::SHA256.hexdigest(nonce)}/". A mismatch here means every patch step
|
|
8
|
+
// 403s against a container the session was never authorized for, so this is pinned against
|
|
9
|
+
// known digests rather than against our own implementation.
|
|
10
|
+
it('matches Digest::SHA256.hexdigest for known inputs', () => {
|
|
11
|
+
expect(sha256Hex('')).toBe('e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855');
|
|
12
|
+
expect(sha256Hex('abc')).toBe('ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad');
|
|
13
|
+
expect(sha256Hex('nonce')).toBe('78377b525757b494427f89014f97d79928f3938d14eb51e20fb5dec9834eb304');
|
|
14
|
+
});
|
|
15
|
+
it('emits lowercase hex with no separators', () => {
|
|
16
|
+
const digest = sha256Hex('Whop');
|
|
17
|
+
expect(digest).toMatch(/^[0-9a-f]{64}$/);
|
|
18
|
+
});
|
|
19
|
+
it('is UTF-8 encoded, so a non-ASCII nonce agrees with the server', () => {
|
|
20
|
+
expect(sha256Hex('é')).toBe('4a99557e4033c3539de2eb65472017cad5f9557f7a0625a09f1c3f6e2ba69c4c');
|
|
21
|
+
});
|
|
22
|
+
});
|
|
23
|
+
//# sourceMappingURL=bt.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["describe","expect","it","sha256Hex","toBe","digest","toMatch"],"sourceRoot":"../../../../src","sources":["core/payments/bt.test.ts"],"mappings":";;AAAA,SAASA,QAAQ,EAAEC,MAAM,EAAEC,EAAE,QAAQ,QAAQ;AAE7C,SAASC,SAAS,QAAQ,SAAM;AAEhCH,QAAQ,CAAC,WAAW,EAAE,MAAM;EAC3B;EACA;EACA;EACA;EACAE,EAAE,CAAC,mDAAmD,EAAE,MAAM;IAC7DD,MAAM,CAACE,SAAS,CAAC,EAAE,CAAC,CAAC,CAACC,IAAI,CAAC,kEAAkE,CAAC;IAC9FH,MAAM,CAACE,SAAS,CAAC,KAAK,CAAC,CAAC,CAACC,IAAI,CAAC,kEAAkE,CAAC;IACjGH,MAAM,CAACE,SAAS,CAAC,OAAO,CAAC,CAAC,CAACC,IAAI,CAAC,kEAAkE,CAAC;EACpG,CAAC,CAAC;EAEFF,EAAE,CAAC,wCAAwC,EAAE,MAAM;IAClD,MAAMG,MAAM,GAAGF,SAAS,CAAC,MAAM,CAAC;IAChCF,MAAM,CAACI,MAAM,CAAC,CAACC,OAAO,CAAC,gBAAgB,CAAC;EACzC,CAAC,CAAC;EAEFJ,EAAE,CAAC,+DAA+D,EAAE,MAAM;IACzED,MAAM,CAACE,SAAS,CAAC,GAAG,CAAC,CAAC,CAACC,IAAI,CAAC,kEAAkE,CAAC;EAChG,CAAC,CAAC;AACH,CAAC,CAAC","ignoreList":[]}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
// ported verbatim from frontend/apps/web/src/elements/payments/lib/currency.ts — keep in sync when the web element changes
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* The minor-unit factor, mirroring the BACKEND's conversion exactly (Utils.amount_in_cents /
|
|
7
|
+
* stripe_factor_decimal over ZERO_DECIMAL_CURRENCIES + THREE_DECIMAL_CURRENCIES in
|
|
8
|
+
* backend/lib/application_constants.rb) — the backend is the authority on a currency's factor,
|
|
9
|
+
* NOT Intl/CLDR: several acceptable plan currencies (huf, cop, idr, pkr, all) are zero-decimal
|
|
10
|
+
* in CLDR but charged in 1/100ths by the backend, so an Intl-derived factor is 100× off for
|
|
11
|
+
* them. Keep these lists in lockstep with the backend constants.
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
const ZERO_DECIMAL_CURRENCIES = new Set(['bif', 'clp', 'djf', 'gnf', 'jpy', 'kmf', 'krw', 'mga', 'pyg', 'rwf', 'ugx', 'vnd', 'vuv', 'xaf', 'xof', 'xpf']);
|
|
15
|
+
const THREE_DECIMAL_CURRENCIES = new Set(['bhd', 'jod', 'kwd', 'omr', 'tnd']);
|
|
16
|
+
export function currencyMinorDigits(currency) {
|
|
17
|
+
const code = currency.toLowerCase();
|
|
18
|
+
if (ZERO_DECIMAL_CURRENCIES.has(code)) return 0;
|
|
19
|
+
if (THREE_DECIMAL_CURRENCIES.has(code)) return 3;
|
|
20
|
+
return 2;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/** Major-unit decimal (how money rides the wire) → the minor-unit integer a charge takes, on the
|
|
24
|
+
* backend's factor above — never Intl's. toFixed(4) first (kills float-scale artifacts like
|
|
25
|
+
* 29.99×100 → 2998.999…), then trunc (a genuinely sub-minor fraction never rounds the charge UP). */
|
|
26
|
+
export function toMinorUnits(majorAmount, currency) {
|
|
27
|
+
return Math.trunc(Number((majorAmount * 10 ** currencyMinorDigits(currency)).toFixed(4)));
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
// Charged in minor units but shown without them (PaymentsConstants::NO_MINOR_UNIT_CURRENCIES).
|
|
31
|
+
const NO_MINOR_UNIT_CURRENCIES = new Set(['cop']);
|
|
32
|
+
export function currencyDisplayDigits(currency) {
|
|
33
|
+
const code = currency.toLowerCase();
|
|
34
|
+
if (NO_MINOR_UNIT_CURRENCIES.has(code)) return 0;
|
|
35
|
+
return currencyMinorDigits(code);
|
|
36
|
+
}
|
|
37
|
+
//# sourceMappingURL=currency.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["ZERO_DECIMAL_CURRENCIES","Set","THREE_DECIMAL_CURRENCIES","currencyMinorDigits","currency","code","toLowerCase","has","toMinorUnits","majorAmount","Math","trunc","Number","toFixed","NO_MINOR_UNIT_CURRENCIES","currencyDisplayDigits"],"sourceRoot":"../../../../src","sources":["core/payments/currency.ts"],"mappings":";;AAAA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA,MAAMA,uBAAuB,GAAG,IAAIC,GAAG,CAAC,CACtC,KAAK,EACL,KAAK,EACL,KAAK,EACL,KAAK,EACL,KAAK,EACL,KAAK,EACL,KAAK,EACL,KAAK,EACL,KAAK,EACL,KAAK,EACL,KAAK,EACL,KAAK,EACL,KAAK,EACL,KAAK,EACL,KAAK,EACL,KAAK,CACN,CAAC;AAEF,MAAMC,wBAAwB,GAAG,IAAID,GAAG,CAAC,CAAC,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,CAAC,CAAC;AAE7E,OAAO,SAASE,mBAAmBA,CAACC,QAAgB,EAAU;EAC5D,MAAMC,IAAI,GAAGD,QAAQ,CAACE,WAAW,CAAC,CAAC;EACnC,IAAIN,uBAAuB,CAACO,GAAG,CAACF,IAAI,CAAC,EAAE,OAAO,CAAC;EAC/C,IAAIH,wBAAwB,CAACK,GAAG,CAACF,IAAI,CAAC,EAAE,OAAO,CAAC;EAChD,OAAO,CAAC;AACV;;AAEA;AACA;AACA;AACA,OAAO,SAASG,YAAYA,CAACC,WAAmB,EAAEL,QAAgB,EAAU;EAC1E,OAAOM,IAAI,CAACC,KAAK,CAACC,MAAM,CAAC,CAACH,WAAW,GAAG,EAAE,IAAIN,mBAAmB,CAACC,QAAQ,CAAC,EAAES,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC;AAC3F;;AAEA;AACA,MAAMC,wBAAwB,GAAG,IAAIb,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC;AAEjD,OAAO,SAASc,qBAAqBA,CAACX,QAAgB,EAAU;EAC9D,MAAMC,IAAI,GAAGD,QAAQ,CAACE,WAAW,CAAC,CAAC;EACnC,IAAIQ,wBAAwB,CAACP,GAAG,CAACF,IAAI,CAAC,EAAE,OAAO,CAAC;EAChD,OAAOF,mBAAmB,CAACE,IAAI,CAAC;AAClC","ignoreList":[]}
|
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
// gating rules ported from frontend/apps/web/src/elements/payments/lib/detail.tsx — keep in sync
|
|
4
|
+
|
|
5
|
+
import { currencyMinorDigits } from "./currency.js";
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Which checkout is asking. The matrix leaves out methods that do not serve the named surface, and
|
|
9
|
+
* the axis is who BUILT the checkout, not where it runs.
|
|
10
|
+
*
|
|
11
|
+
* A React Native mount is `direct_checkout`: it owns its own presentation the way a first-party
|
|
12
|
+
* whop.com document does, and unlike an iframe it can hand a full-page step to the system browser.
|
|
13
|
+
* Sending `external_checkout` would drop every `full_page`-only method from the list.
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
const TAB_OWNING_SURFACES = ['direct_checkout', 'modal_checkout'];
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* The categories this build can actually collect. An entry from a newer matrix in a category this
|
|
20
|
+
* build does not implement is a rail it cannot run, so it is skipped rather than rendered as a
|
|
21
|
+
* broken tile — the same gate web added in #25658 (apps/web/src/elements/payments/lib/detail.tsx).
|
|
22
|
+
*
|
|
23
|
+
* `balance` is web's list minus one: ledger-balance payment is not in this release (README), so
|
|
24
|
+
* claiming it here would render a tile that cannot complete.
|
|
25
|
+
*/
|
|
26
|
+
const IMPLEMENTED_CATEGORIES = ['card', 'wallet', 'bank_debit', 'bank_transfer', 'voucher', 'redirect', 'crypto'];
|
|
27
|
+
const TEMPLATES = ['redirect', 'bnpl_confirm', 'bank_connect', 'bank_wire', 'wallet_sheet', 'none'];
|
|
28
|
+
export function detailTemplate(entry) {
|
|
29
|
+
const declared = entry.detail?.template;
|
|
30
|
+
if (declared && TEMPLATES.includes(declared)) return declared;
|
|
31
|
+
// An unknown template is a newer matrix than this build; redirect copy is the safe read.
|
|
32
|
+
return 'redirect';
|
|
33
|
+
}
|
|
34
|
+
export function passesConfiguration(type, configuration, platformDefault) {
|
|
35
|
+
if (!configuration) return platformDefault ?? true;
|
|
36
|
+
const enabled = configuration.enabled ?? [];
|
|
37
|
+
if (!(configuration.include_platform_defaults ?? true)) return enabled.includes(type);
|
|
38
|
+
// (platform defaults − disabled + enabled): an off-by-default type needs an explicit enable,
|
|
39
|
+
// so "not disabled" alone is not an allow.
|
|
40
|
+
return (platformDefault ?? true) && !(configuration.disabled ?? []).includes(type) || enabled.includes(type);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/** The entry's category-keyed config block, read generically. */
|
|
44
|
+
export function methodConfigBlock(entry) {
|
|
45
|
+
const block = entry[entry.category];
|
|
46
|
+
return block && typeof block === 'object' ? block : {};
|
|
47
|
+
}
|
|
48
|
+
export function methodTokenizerKey(entry) {
|
|
49
|
+
const key = methodConfigBlock(entry).public_key;
|
|
50
|
+
return typeof key === 'string' ? key : undefined;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Whether the entry is offered for this charge on this surface.
|
|
55
|
+
*
|
|
56
|
+
* Amount-gated methods are excluded outright rather than rendered disabled, and every absent field
|
|
57
|
+
* reads as unrestricted so an older matrix keeps its behavior.
|
|
58
|
+
*/
|
|
59
|
+
export function presentMethod(entry, currency, amount, setupFutureUsage, walletAvailability, configuration, surface, country) {
|
|
60
|
+
// A category this build does not implement is a rail it cannot collect — an entry from a newer
|
|
61
|
+
// matrix must be skipped, never rendered as a broken tile.
|
|
62
|
+
if (!IMPLEMENTED_CATEGORIES.includes(entry.category)) return false;
|
|
63
|
+
if (!TAB_OWNING_SURFACES.includes(surface) && entry.next_action_render_modes && !entry.next_action_render_modes.includes('inline')) {
|
|
64
|
+
return false;
|
|
65
|
+
}
|
|
66
|
+
if (!passesConfiguration(entry.type, configuration, entry.platform_default)) return false;
|
|
67
|
+
if (!entry.usage?.one_time) return false;
|
|
68
|
+
if (setupFutureUsage === 'off_session' && !entry.usage?.off_session) return false;
|
|
69
|
+
if (setupFutureUsage === 'on_session' && !entry.usage?.on_session) return false;
|
|
70
|
+
if (entry.category === 'card' && !entry.card?.public_key) return false;
|
|
71
|
+
// A secure declared field tokenizes into the config block's key at collect time; without the key
|
|
72
|
+
// the method is broken at confirm, so it is never offered.
|
|
73
|
+
if ((entry.required_fields ?? []).some(field => field.secure) && !methodTokenizerKey(entry)) return false;
|
|
74
|
+
if (detailTemplate(entry) === 'wallet_sheet') {
|
|
75
|
+
if (entry.type === 'apple_pay' && !walletAvailability?.applePay) return false;
|
|
76
|
+
if (entry.type === 'google_pay' && !walletAvailability?.googlePay) return false;
|
|
77
|
+
}
|
|
78
|
+
const bounds = entry.currencies?.[currency.toLowerCase()];
|
|
79
|
+
if (!bounds) return false;
|
|
80
|
+
const {
|
|
81
|
+
min,
|
|
82
|
+
max
|
|
83
|
+
} = amountBounds(bounds, country);
|
|
84
|
+
if (min != null && amount < min) return false;
|
|
85
|
+
if (max != null && amount > max) return false;
|
|
86
|
+
return true;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* A currency's limits, narrowed to the billing country when the matrix publishes a row for it.
|
|
91
|
+
*
|
|
92
|
+
* Reading only the currency-level pair offered methods that the selected country cannot actually
|
|
93
|
+
* take at this amount, which the buyer discovers at confirm rather than in the list. Mirrors
|
|
94
|
+
* `amountBounds` in apps/web/src/elements/payments/lib/detail.tsx.
|
|
95
|
+
*/
|
|
96
|
+
function amountBounds(bounds, country) {
|
|
97
|
+
const code = country?.toLowerCase();
|
|
98
|
+
const row = code ? bounds.countries?.find(candidate => candidate.country?.toLowerCase() === code) : undefined;
|
|
99
|
+
if (!row) return {
|
|
100
|
+
min: bounds.min_amount,
|
|
101
|
+
max: bounds.max_amount
|
|
102
|
+
};
|
|
103
|
+
return {
|
|
104
|
+
min: row.min_amount,
|
|
105
|
+
max: row.max_amount
|
|
106
|
+
};
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
/** Listed types take their list position; unlisted types share the tail rank, so a stable sort
|
|
110
|
+
* preserves their incoming order. */
|
|
111
|
+
export function orderRank(type, order) {
|
|
112
|
+
const index = order.indexOf(type);
|
|
113
|
+
return index === -1 ? order.length : index;
|
|
114
|
+
}
|
|
115
|
+
export function formatMinorAmount(amount, currency, locale) {
|
|
116
|
+
// The divisor is the backend-mirrored factor; the display digits are Intl's. They disagree for
|
|
117
|
+
// currencies like huf, and the backend's answer is the one that priced the charge.
|
|
118
|
+
const major = amount / 10 ** currencyMinorDigits(currency);
|
|
119
|
+
try {
|
|
120
|
+
return new Intl.NumberFormat(locale, {
|
|
121
|
+
style: 'currency',
|
|
122
|
+
currency: currency.toUpperCase()
|
|
123
|
+
}).format(major);
|
|
124
|
+
} catch {
|
|
125
|
+
return `${major} ${currency.toUpperCase()}`;
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
export function fieldLabel(name) {
|
|
129
|
+
const spaced = name.replace(/_/g, ' ').replace(/\bid\b/gi, 'ID');
|
|
130
|
+
return spaced.charAt(0).toUpperCase() + spaced.slice(1);
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
/** A declared field's country-keyed pattern, `*` as the fallback. Never throws on a bad pattern. */
|
|
134
|
+
export function fieldMatches(formats, country, value) {
|
|
135
|
+
if (!formats) return true;
|
|
136
|
+
const trimmed = value.trim();
|
|
137
|
+
const patterns = [formats[(country ?? '').toLowerCase()], formats['*']].filter(p => typeof p === 'string');
|
|
138
|
+
return patterns.length === 0 || patterns.some(pattern => safeTest(pattern, trimmed));
|
|
139
|
+
}
|
|
140
|
+
function safeTest(pattern, value) {
|
|
141
|
+
try {
|
|
142
|
+
return new RegExp(pattern).test(value);
|
|
143
|
+
} catch {
|
|
144
|
+
return true;
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
/**
|
|
149
|
+
* The billing countries a method constrains the buyer to, or null when it constrains nothing.
|
|
150
|
+
*
|
|
151
|
+
* `*` anywhere in the entry's per-currency list means unrestricted, and so does an empty list — a
|
|
152
|
+
* method that names countries names ALL of the ones it serves. The address element intersects the
|
|
153
|
+
* result with the integrator's own `allowedCountries` rather than replacing it.
|
|
154
|
+
*/
|
|
155
|
+
export function methodBillingCountries(entry, currency) {
|
|
156
|
+
const codes = (entry?.currencies?.[currency]?.countries ?? []).map(row => row.country);
|
|
157
|
+
return codes.length === 0 || codes.includes('*') ? null : codes;
|
|
158
|
+
}
|
|
159
|
+
//# sourceMappingURL=detail.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["currencyMinorDigits","TAB_OWNING_SURFACES","IMPLEMENTED_CATEGORIES","TEMPLATES","detailTemplate","entry","declared","detail","template","includes","passesConfiguration","type","configuration","platformDefault","enabled","include_platform_defaults","disabled","methodConfigBlock","block","category","methodTokenizerKey","key","public_key","undefined","presentMethod","currency","amount","setupFutureUsage","walletAvailability","surface","country","next_action_render_modes","platform_default","usage","one_time","off_session","on_session","card","required_fields","some","field","secure","applePay","googlePay","bounds","currencies","toLowerCase","min","max","amountBounds","code","row","countries","find","candidate","min_amount","max_amount","orderRank","order","index","indexOf","length","formatMinorAmount","locale","major","Intl","NumberFormat","style","toUpperCase","format","fieldLabel","name","spaced","replace","charAt","slice","fieldMatches","formats","value","trimmed","trim","patterns","filter","p","pattern","safeTest","RegExp","test","methodBillingCountries","codes","map"],"sourceRoot":"../../../../src","sources":["core/payments/detail.ts"],"mappings":"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","ignoreList":[]}
|
|
@@ -0,0 +1,225 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
import { describe, expect, it } from 'vitest';
|
|
4
|
+
import { methodBillingCountries, orderRank, passesConfiguration, presentMethod } from "./detail.js";
|
|
5
|
+
function entry(overrides = {}) {
|
|
6
|
+
return {
|
|
7
|
+
object: 'payment_method_type',
|
|
8
|
+
type: 'card',
|
|
9
|
+
category: 'card',
|
|
10
|
+
display_name: 'Card',
|
|
11
|
+
detail: {
|
|
12
|
+
template: 'none'
|
|
13
|
+
},
|
|
14
|
+
usage: {
|
|
15
|
+
one_time: true,
|
|
16
|
+
off_session: true,
|
|
17
|
+
on_session: true
|
|
18
|
+
},
|
|
19
|
+
currencies: {
|
|
20
|
+
usd: {
|
|
21
|
+
min_amount: null,
|
|
22
|
+
max_amount: null,
|
|
23
|
+
countries: []
|
|
24
|
+
}
|
|
25
|
+
},
|
|
26
|
+
card: {
|
|
27
|
+
public_key: 'key_live'
|
|
28
|
+
},
|
|
29
|
+
...overrides
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
describe('presentMethod', () => {
|
|
33
|
+
const offer = (e, ...rest) => presentMethod(e, ...rest);
|
|
34
|
+
it('offers a card with a tokenizer key inside its currency bounds', () => {
|
|
35
|
+
expect(offer(entry(), 'usd', 1000, undefined, undefined, undefined, 'direct_checkout')).toBe(true);
|
|
36
|
+
});
|
|
37
|
+
it('refuses a card with no tokenizer key rather than rendering a broken tile', () => {
|
|
38
|
+
expect(offer(entry({
|
|
39
|
+
card: {
|
|
40
|
+
public_key: null
|
|
41
|
+
}
|
|
42
|
+
}), 'usd', 1000, undefined, undefined, undefined, 'direct_checkout')).toBe(false);
|
|
43
|
+
});
|
|
44
|
+
it('refuses a secure declared field with no tokenizer key', () => {
|
|
45
|
+
const sepa = entry({
|
|
46
|
+
type: 'sepa_debit',
|
|
47
|
+
category: 'bank_debit',
|
|
48
|
+
required_fields: [{
|
|
49
|
+
name: 'bank_account',
|
|
50
|
+
kind: 'payment_method',
|
|
51
|
+
secure: true
|
|
52
|
+
}]
|
|
53
|
+
});
|
|
54
|
+
expect(offer(sepa, 'usd', 1000, undefined, undefined, undefined, 'direct_checkout')).toBe(false);
|
|
55
|
+
});
|
|
56
|
+
it('excludes an amount outside the currency bounds outright', () => {
|
|
57
|
+
const bounded = entry({
|
|
58
|
+
currencies: {
|
|
59
|
+
usd: {
|
|
60
|
+
min_amount: 5000,
|
|
61
|
+
max_amount: null,
|
|
62
|
+
countries: []
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
});
|
|
66
|
+
expect(offer(bounded, 'usd', 1000, undefined, undefined, undefined, 'direct_checkout')).toBe(false);
|
|
67
|
+
expect(offer(bounded, 'usd', 5000, undefined, undefined, undefined, 'direct_checkout')).toBe(true);
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
// The currency-level pair was the only thing read, so a method the selected country cannot take
|
|
71
|
+
// at this amount was still offered and the buyer met the refusal at confirm instead of the list.
|
|
72
|
+
it('prefers the billing country row over the currency bounds', () => {
|
|
73
|
+
const bounded = entry({
|
|
74
|
+
currencies: {
|
|
75
|
+
usd: {
|
|
76
|
+
min_amount: 100,
|
|
77
|
+
max_amount: null,
|
|
78
|
+
countries: [{
|
|
79
|
+
country: 'GB',
|
|
80
|
+
min_amount: 5000,
|
|
81
|
+
max_amount: null
|
|
82
|
+
}]
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
});
|
|
86
|
+
expect(offer(bounded, 'usd', 1000, undefined, undefined, undefined, 'direct_checkout', 'GB')).toBe(false);
|
|
87
|
+
expect(offer(bounded, 'usd', 5000, undefined, undefined, undefined, 'direct_checkout', 'GB')).toBe(true);
|
|
88
|
+
});
|
|
89
|
+
it('falls back to the currency bounds for a country with no row', () => {
|
|
90
|
+
const bounded = entry({
|
|
91
|
+
currencies: {
|
|
92
|
+
usd: {
|
|
93
|
+
min_amount: 100,
|
|
94
|
+
max_amount: null,
|
|
95
|
+
countries: [{
|
|
96
|
+
country: 'GB',
|
|
97
|
+
min_amount: 5000,
|
|
98
|
+
max_amount: null
|
|
99
|
+
}]
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
});
|
|
103
|
+
expect(offer(bounded, 'usd', 1000, undefined, undefined, undefined, 'direct_checkout', 'US')).toBe(true);
|
|
104
|
+
expect(offer(bounded, 'usd', 1000, undefined, undefined, undefined, 'direct_checkout', undefined)).toBe(true);
|
|
105
|
+
});
|
|
106
|
+
it('matches the country case-insensitively, as the matrix publishes it', () => {
|
|
107
|
+
const bounded = entry({
|
|
108
|
+
currencies: {
|
|
109
|
+
usd: {
|
|
110
|
+
min_amount: 100,
|
|
111
|
+
max_amount: null,
|
|
112
|
+
countries: [{
|
|
113
|
+
country: 'gb',
|
|
114
|
+
min_amount: 5000,
|
|
115
|
+
max_amount: null
|
|
116
|
+
}]
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
});
|
|
120
|
+
expect(offer(bounded, 'usd', 1000, undefined, undefined, undefined, 'direct_checkout', 'GB')).toBe(false);
|
|
121
|
+
});
|
|
122
|
+
it('normalizes the currency the matrix keys lowercase', () => {
|
|
123
|
+
expect(offer(entry(), 'USD', 1000, undefined, undefined, undefined, 'direct_checkout')).toBe(true);
|
|
124
|
+
});
|
|
125
|
+
it('refuses a method that cannot vault when off_session save-consent is declared', () => {
|
|
126
|
+
const noVault = entry({
|
|
127
|
+
usage: {
|
|
128
|
+
one_time: true,
|
|
129
|
+
off_session: false,
|
|
130
|
+
on_session: true
|
|
131
|
+
}
|
|
132
|
+
});
|
|
133
|
+
expect(offer(noVault, 'usd', 1000, 'off_session', undefined, undefined, 'direct_checkout')).toBe(false);
|
|
134
|
+
});
|
|
135
|
+
it('hides a wallet until its probe lands true, without gating the rest', () => {
|
|
136
|
+
const wallet = entry({
|
|
137
|
+
type: 'apple_pay',
|
|
138
|
+
category: 'wallet',
|
|
139
|
+
detail: {
|
|
140
|
+
template: 'wallet_sheet'
|
|
141
|
+
},
|
|
142
|
+
card: null
|
|
143
|
+
});
|
|
144
|
+
expect(offer(wallet, 'usd', 1000, undefined, undefined, undefined, 'direct_checkout')).toBe(false);
|
|
145
|
+
expect(offer(wallet, 'usd', 1000, undefined, {
|
|
146
|
+
applePay: true
|
|
147
|
+
}, undefined, 'direct_checkout')).toBe(true);
|
|
148
|
+
});
|
|
149
|
+
it('keeps a full_page-only method on a tab-owning surface', () => {
|
|
150
|
+
const redirect = entry({
|
|
151
|
+
type: 'ideal',
|
|
152
|
+
category: 'redirect',
|
|
153
|
+
detail: {
|
|
154
|
+
template: 'redirect'
|
|
155
|
+
},
|
|
156
|
+
card: null,
|
|
157
|
+
next_action_render_modes: ['full_page']
|
|
158
|
+
});
|
|
159
|
+
// A React Native mount owns its presentation and can hand the step to the system browser.
|
|
160
|
+
expect(offer(redirect, 'usd', 1000, undefined, undefined, undefined, 'direct_checkout')).toBe(true);
|
|
161
|
+
expect(offer(redirect, 'usd', 1000, undefined, undefined, undefined, 'external_checkout')).toBe(false);
|
|
162
|
+
});
|
|
163
|
+
});
|
|
164
|
+
describe('passesConfiguration', () => {
|
|
165
|
+
it('treats an absent configuration as the platform default', () => {
|
|
166
|
+
expect(passesConfiguration('card', undefined, true)).toBe(true);
|
|
167
|
+
expect(passesConfiguration('card', undefined, false)).toBe(false);
|
|
168
|
+
});
|
|
169
|
+
it('needs an explicit enable for an off-by-default type', () => {
|
|
170
|
+
expect(passesConfiguration('pix', {
|
|
171
|
+
disabled: []
|
|
172
|
+
}, false)).toBe(false);
|
|
173
|
+
expect(passesConfiguration('pix', {
|
|
174
|
+
enabled: ['pix']
|
|
175
|
+
}, false)).toBe(true);
|
|
176
|
+
});
|
|
177
|
+
it('leaves only enabled types when platform defaults are excluded', () => {
|
|
178
|
+
expect(passesConfiguration('card', {
|
|
179
|
+
enabled: ['pix'],
|
|
180
|
+
include_platform_defaults: false
|
|
181
|
+
}, true)).toBe(false);
|
|
182
|
+
expect(passesConfiguration('pix', {
|
|
183
|
+
enabled: ['pix'],
|
|
184
|
+
include_platform_defaults: false
|
|
185
|
+
}, false)).toBe(true);
|
|
186
|
+
});
|
|
187
|
+
});
|
|
188
|
+
describe('orderRank', () => {
|
|
189
|
+
it('gives unlisted types a shared tail rank so a stable sort keeps their order', () => {
|
|
190
|
+
expect(orderRank('apple_pay', ['apple_pay', 'card'])).toBe(0);
|
|
191
|
+
expect(orderRank('card', ['apple_pay', 'card'])).toBe(1);
|
|
192
|
+
expect(orderRank('pix', ['apple_pay', 'card'])).toBe(2);
|
|
193
|
+
expect(orderRank('ideal', ['apple_pay', 'card'])).toBe(2);
|
|
194
|
+
});
|
|
195
|
+
});
|
|
196
|
+
describe('methodBillingCountries', () => {
|
|
197
|
+
const bound = (...codes) => ({
|
|
198
|
+
currencies: {
|
|
199
|
+
usd: {
|
|
200
|
+
min_amount: null,
|
|
201
|
+
max_amount: null,
|
|
202
|
+
countries: codes.map(country => ({
|
|
203
|
+
country,
|
|
204
|
+
min_amount: null,
|
|
205
|
+
max_amount: null
|
|
206
|
+
}))
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
});
|
|
210
|
+
it('returns the entry\'s countries for the charge currency', () => {
|
|
211
|
+
expect(methodBillingCountries(bound('DE', 'NL'), 'usd')).toEqual(['DE', 'NL']);
|
|
212
|
+
});
|
|
213
|
+
it('returns null when a wildcard is present', () => {
|
|
214
|
+
expect(methodBillingCountries(bound('*'), 'usd')).toBeNull();
|
|
215
|
+
expect(methodBillingCountries(bound('DE', '*'), 'usd')).toBeNull();
|
|
216
|
+
});
|
|
217
|
+
it('returns null when nothing is declared', () => {
|
|
218
|
+
expect(methodBillingCountries(bound(), 'usd')).toBeNull();
|
|
219
|
+
expect(methodBillingCountries(undefined, 'usd')).toBeNull();
|
|
220
|
+
});
|
|
221
|
+
it('is scoped to the charge currency, not the whole entry', () => {
|
|
222
|
+
expect(methodBillingCountries(bound('DE'), 'eur')).toBeNull();
|
|
223
|
+
});
|
|
224
|
+
});
|
|
225
|
+
//# sourceMappingURL=detail.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["describe","expect","it","methodBillingCountries","orderRank","passesConfiguration","presentMethod","entry","overrides","object","type","category","display_name","detail","template","usage","one_time","off_session","on_session","currencies","usd","min_amount","max_amount","countries","card","public_key","offer","e","rest","undefined","toBe","sepa","required_fields","name","kind","secure","bounded","country","noVault","wallet","applePay","redirect","next_action_render_modes","disabled","enabled","include_platform_defaults","bound","codes","map","toEqual","toBeNull"],"sourceRoot":"../../../../src","sources":["core/payments/detail.test.ts"],"mappings":"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","ignoreList":[]}
|