@funnelfox/billing 0.8.0-beta.3 → 0.8.0-ffb-395.4

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 CHANGED
@@ -11,6 +11,7 @@ A modern TypeScript SDK for subscription payments with Primer Headless Checkout
11
11
  - 🔧 **Robust**: Built-in error handling, retries, and validation
12
12
  - 📦 **Lightweight**: Minimal dependencies, browser-optimized
13
13
  - 🎨 **Headless Checkout**: Full control over checkout UI with Primer Headless Checkout
14
+ - 💳 **Stripe Integration**: Native Stripe Elements card form and Apple Pay / Google Pay wallets
14
15
 
15
16
  ## Installation
16
17
 
@@ -711,6 +712,216 @@ const headlessCheckout = await Primer.createHeadless(session.clientToken, {
711
712
  await headlessCheckout.start();
712
713
  ```
713
714
 
715
+ ## Stripe Integration
716
+
717
+ The `Billing.stripe` namespace provides a Stripe-native checkout experience — no Primer dependency required. It supports card payments via Stripe Elements and native wallet payments (Apple Pay / Google Pay) via the Payment Request API.
718
+
719
+ > **Note:** `@primer-io/checkout-web` is **not** required for Stripe integration. Only `@funnelfox/billing` and a Stripe-enabled price in your Funnelfox account are needed.
720
+
721
+ ---
722
+
723
+ ### `Billing.stripe.createCardForm(element, params)`
724
+
725
+ Mounts a Stripe Elements payment form into a DOM element. Returns a `{ submit() }` handle — you control when payment is triggered (e.g. on your own button click).
726
+
727
+ ```javascript
728
+ const element = document.getElementById('card-form');
729
+
730
+ const cardForm = await Billing.stripe.createCardForm(element, {
731
+ // Required
732
+ priceId: 'price_123',
733
+ externalId: 'user_456',
734
+
735
+ // Optional
736
+ orgId: 'your-org-id',
737
+ email: 'user@example.com',
738
+ countryCode: 'US',
739
+ showWallets: false, // show Apple Pay / Google Pay inside the form
740
+ appearance: {
741
+ // Stripe Elements appearance API
742
+ theme: 'stripe',
743
+ },
744
+
745
+ // Callbacks
746
+ onRenderSuccess: () => {
747
+ document.getElementById('pay-button').disabled = false;
748
+ },
749
+ onLoaderChange: loading => {
750
+ document.getElementById('pay-button').disabled = loading;
751
+ },
752
+ onPaymentSuccess: (paymentMethod, orderId) => {
753
+ window.location.href = '/success?order=' + orderId;
754
+ },
755
+ onPaymentFail: error => {
756
+ console.error('Payment failed:', error.message);
757
+ },
758
+ });
759
+
760
+ // Wire up your own submit button
761
+ document.getElementById('pay-button').addEventListener('click', async () => {
762
+ await cardForm.submit();
763
+ });
764
+ ```
765
+
766
+ **Key parameters:**
767
+
768
+ | Parameter | Type | Description |
769
+ | ---------------- | -------- | --------------------------------------------------------------------------------- |
770
+ | `priceId` | string | Price identifier |
771
+ | `externalId` | string | Your user identifier |
772
+ | `email` | string? | Customer email |
773
+ | `orgId` | string? | Org ID (if not globally configured) |
774
+ | `showWallets` | boolean? | Show Apple Pay / Google Pay inside the Stripe form |
775
+ | `appearance` | object? | [Stripe Elements Appearance API](https://stripe.com/docs/elements/appearance-api) |
776
+ | `clientMetadata` | object? | Custom metadata attached to the order |
777
+
778
+ **Returns:** `Promise<{ submit: () => Promise<void> }>`
779
+
780
+ ---
781
+
782
+ ### `Billing.stripe.getAvailableWallet(params)`
783
+
784
+ Checks whether Apple Pay or Google Pay is available on the current device and browser. Use this to conditionally show a wallet button before attempting payment.
785
+
786
+ ```javascript
787
+ const wallet = await Billing.stripe.getAvailableWallet({
788
+ priceId: 'price_123',
789
+ externalId: 'user_456',
790
+ });
791
+
792
+ if (wallet === 'APPLE_PAY') {
793
+ document.getElementById('apple-pay-btn').style.display = 'block';
794
+ } else if (wallet === 'GOOGLE_PAY') {
795
+ document.getElementById('google-pay-btn').style.display = 'block';
796
+ } else {
797
+ // No wallet available — show card form only
798
+ }
799
+ ```
800
+
801
+ **Returns:** `Promise<'APPLE_PAY' | 'GOOGLE_PAY' | null>`
802
+
803
+ ---
804
+
805
+ ### `Billing.stripe.purchaseWallet(params)`
806
+
807
+ Triggers the native Apple Pay or Google Pay payment sheet. Call this on button click after confirming a wallet is available via `getAvailableWallet`.
808
+
809
+ ```javascript
810
+ document.getElementById('wallet-btn').addEventListener('click', async () => {
811
+ await Billing.stripe.purchaseWallet({
812
+ priceId: 'price_123',
813
+ externalId: 'user_456',
814
+ totalLabel: 'Premium Plan', // Label shown in the payment sheet
815
+
816
+ onPaymentSuccess: (paymentMethod, orderId) => {
817
+ window.location.href = '/success?order=' + orderId;
818
+ },
819
+ onPaymentFail: error => {
820
+ console.error('Wallet payment failed:', error.message);
821
+ },
822
+ onPaymentCancel: () => {
823
+ console.log('User cancelled');
824
+ },
825
+ onLoaderChange: loading => {
826
+ document.getElementById('wallet-btn').disabled = loading;
827
+ },
828
+ });
829
+ });
830
+ ```
831
+
832
+ **Key parameters:**
833
+
834
+ | Parameter | Type | Description |
835
+ | ---------------- | ------- | --------------------------------------------------- |
836
+ | `priceId` | string | Price identifier |
837
+ | `externalId` | string | Your user identifier |
838
+ | `totalLabel` | string? | Label shown next to the amount in the payment sheet |
839
+ | `email` | string? | Customer email |
840
+ | `clientMetadata` | object? | Custom metadata attached to the order |
841
+
842
+ ---
843
+
844
+ ### `Billing.stripe.getAvailablePaymentMethods(params)`
845
+
846
+ Returns all Stripe payment methods available for the current device. Always includes `PAYMENT_CARD`; also includes a wallet method if one is detected.
847
+
848
+ ```javascript
849
+ const methods = await Billing.stripe.getAvailablePaymentMethods({
850
+ priceId: 'price_123',
851
+ externalId: 'user_456',
852
+ });
853
+
854
+ // methods: ['PAYMENT_CARD', 'APPLE_PAY'] or ['PAYMENT_CARD'] etc.
855
+ console.log('Available:', methods);
856
+ ```
857
+
858
+ **Returns:** `Promise<PaymentMethod[]>` — always contains `PAYMENT_CARD`, optionally `APPLE_PAY` or `GOOGLE_PAY`
859
+
860
+ ---
861
+
862
+ ### Combined Example: Wallet Detection + Card Form Fallback
863
+
864
+ The recommended pattern — show a wallet button when available, always show the card form as fallback:
865
+
866
+ ```javascript
867
+ import { Billing } from '@funnelfox/billing';
868
+
869
+ Billing.configure({ orgId: 'your-org-id' });
870
+
871
+ const params = {
872
+ priceId: 'price_123',
873
+ externalId: 'user_456',
874
+ email: 'user@example.com',
875
+ };
876
+
877
+ async function initCheckout() {
878
+ // 1. Check for wallet availability
879
+ const wallet = await Billing.stripe.getAvailableWallet(params);
880
+
881
+ if (wallet) {
882
+ const walletBtn = document.getElementById('wallet-btn');
883
+ walletBtn.textContent =
884
+ wallet === 'APPLE_PAY' ? 'Pay with Apple Pay' : 'Pay with Google Pay';
885
+ walletBtn.style.display = 'block';
886
+
887
+ walletBtn.addEventListener('click', () => {
888
+ Billing.stripe.purchaseWallet({
889
+ ...params,
890
+ totalLabel: 'Premium Plan',
891
+ onPaymentSuccess: (_, orderId) => {
892
+ window.location.href = '/success?order=' + orderId;
893
+ },
894
+ onPaymentFail: err => alert(err.message),
895
+ onPaymentCancel: () => console.log('Cancelled'),
896
+ });
897
+ });
898
+ }
899
+
900
+ // 2. Always mount card form as fallback
901
+ const cardForm = await Billing.stripe.createCardForm(
902
+ document.getElementById('card-form'),
903
+ {
904
+ ...params,
905
+ onPaymentSuccess: (_, orderId) => {
906
+ window.location.href = '/success?order=' + orderId;
907
+ },
908
+ onPaymentFail: err => alert(err.message),
909
+ onLoaderChange: loading => {
910
+ document.getElementById('pay-btn').disabled = loading;
911
+ },
912
+ }
913
+ );
914
+
915
+ document.getElementById('pay-btn').addEventListener('click', () => {
916
+ cardForm.submit();
917
+ });
918
+ }
919
+
920
+ initCheckout();
921
+ ```
922
+
923
+ ---
924
+
714
925
  ## Browser Support
715
926
 
716
927
  - Chrome 60+
@@ -491,7 +491,7 @@ exports.PaymentMethod = void 0;
491
491
  /**
492
492
  * @fileoverview Constants for Funnefox SDK
493
493
  */
494
- const SDK_VERSION = '0.8.0-beta.3';
494
+ const SDK_VERSION = '0.9.0-beta.1';
495
495
  const DEFAULTS = {
496
496
  BASE_URL: 'https://billing.funnelfox.com',
497
497
  REGION: 'default',
@@ -530,6 +530,7 @@ const API_ENDPOINTS = {
530
530
  UPDATE_CLIENT_SESSION: '/v1/checkout/update_client_session',
531
531
  CREATE_PAYMENT: '/v1/checkout/create_payment',
532
532
  RESUME_PAYMENT: '/v1/checkout/resume_payment',
533
+ STRIPE_CREATE_PAYMENT: '/v1/stripe/create_payment',
533
534
  ONE_CLICK: '/v1/checkout/one_click',
534
535
  CREATE_SIMPLE_CLIENT_SESSION: '/v1/checkout/create_simple_client_session',
535
536
  };
@@ -1059,6 +1060,9 @@ class PrimerWrapper {
1059
1060
  }
1060
1061
  return element;
1061
1062
  }
1063
+ refreshClientSession() {
1064
+ return this.currentHeadless?.then(headless => headless.refreshClientSession());
1065
+ }
1062
1066
  }
1063
1067
  PrimerWrapper.headlessManager = new HeadlessManager();
1064
1068
 
@@ -1125,7 +1129,7 @@ class APIClient {
1125
1129
  async createClientSession(params) {
1126
1130
  const payload = {
1127
1131
  region: params.region || 'default',
1128
- integration_type: 'primer',
1132
+ integration_type: params.integration ?? 'primer',
1129
1133
  pp_ident: params.priceId,
1130
1134
  external_id: params.externalId,
1131
1135
  email_address: params.email,
@@ -1171,6 +1175,15 @@ class APIClient {
1171
1175
  body: JSON.stringify(payload),
1172
1176
  }));
1173
1177
  }
1178
+ async createStripePayment(params) {
1179
+ return (await this.request(API_ENDPOINTS.STRIPE_CREATE_PAYMENT, {
1180
+ method: 'POST',
1181
+ body: JSON.stringify({
1182
+ order_id: params.orderId,
1183
+ payment_method_id: params.paymentMethodId,
1184
+ }),
1185
+ }));
1186
+ }
1174
1187
  async resumePayment(params) {
1175
1188
  const payload = {
1176
1189
  order_id: params.orderId,
@@ -1261,6 +1274,45 @@ class APIClient {
1261
1274
  }
1262
1275
  }
1263
1276
 
1277
+ class SessionService {
1278
+ constructor() {
1279
+ this.cache = new Map();
1280
+ }
1281
+ buildCacheKey(p) {
1282
+ return [p.orgId, p.priceId, p.externalId, p.email, p.integration].join('-');
1283
+ }
1284
+ makeClient(orgId, baseUrl) {
1285
+ return new APIClient({
1286
+ baseUrl: baseUrl || DEFAULTS.BASE_URL,
1287
+ orgId,
1288
+ timeout: DEFAULTS.REQUEST_TIMEOUT,
1289
+ retryAttempts: DEFAULTS.RETRY_ATTEMPTS,
1290
+ });
1291
+ }
1292
+ createSession(p) {
1293
+ const key = this.buildCacheKey(p);
1294
+ const cached = this.cache.get(key);
1295
+ if (cached)
1296
+ return cached;
1297
+ const client = this.makeClient(p.orgId, p.baseUrl);
1298
+ const req = client.createClientSession({
1299
+ priceId: p.priceId,
1300
+ externalId: p.externalId,
1301
+ email: p.email,
1302
+ region: p.region || DEFAULTS.REGION,
1303
+ clientMetadata: p.clientMetadata,
1304
+ countryCode: p.countryCode,
1305
+ integration: p.integration,
1306
+ });
1307
+ this.cache.set(key, req);
1308
+ return req;
1309
+ }
1310
+ clearCache() {
1311
+ this.cache.clear();
1312
+ }
1313
+ }
1314
+ var sessionService = new SessionService();
1315
+
1264
1316
  var loaderHtml = "<div class=\"ff-sdk-loader-container\">\n <div class=\"ff-sdk-loader\"></div>\n</div>\n";
1265
1317
 
1266
1318
  if(typeof document!=="undefined")document.head.appendChild(document.createElement("style")).textContent=".ff-sdk-loader-container {\n position: absolute;\n top: 0;\n left: 0;\n width: 100%;\n height: 100%;\n display: flex;\n justify-content: center;\n align-items: center;\n background-color: rgba(255, 255, 255);\n z-index: 2;\n}\n\n.ff-sdk-loader {\n width: 24px;\n height: 24px;\n border: 4px solid #e32f41;\n border-top: 4px solid transparent;\n border-radius: 50%;\n animation: spin 1s linear infinite;\n}\n\n@keyframes spin {\n 0% {\n transform: rotate(0deg);\n }\n 100% {\n transform: rotate(360deg);\n }\n }";
@@ -1855,6 +1907,12 @@ class CheckoutInstance extends EventEmitter {
1855
1907
  this.cardEmailAddress = this.checkoutConfig.customer.email;
1856
1908
  this.shouldApplySessionCardholderNameConfig =
1857
1909
  this.checkoutConfig.card?.cardholderName?.required === undefined;
1910
+ this.apiClient = new APIClient({
1911
+ baseUrl: this.baseUrl || DEFAULTS.BASE_URL,
1912
+ orgId: this.orgId,
1913
+ timeout: DEFAULTS.REQUEST_TIMEOUT,
1914
+ retryAttempts: DEFAULTS.RETRY_ATTEMPTS,
1915
+ });
1858
1916
  this._setupCallbackBridges();
1859
1917
  }
1860
1918
  _setupCallbackBridges() {
@@ -1896,68 +1954,38 @@ class CheckoutInstance extends EventEmitter {
1896
1954
  }
1897
1955
  }
1898
1956
  async createSession() {
1899
- this.apiClient = new APIClient({
1900
- baseUrl: this.baseUrl || DEFAULTS.BASE_URL,
1957
+ const response = await sessionService.createSession({
1901
1958
  orgId: this.orgId,
1902
- timeout: DEFAULTS.REQUEST_TIMEOUT,
1903
- retryAttempts: DEFAULTS.RETRY_ATTEMPTS,
1904
- });
1905
- const sessionParams = {
1959
+ baseUrl: this.baseUrl,
1906
1960
  priceId: this.checkoutConfig.priceId,
1907
1961
  externalId: this.checkoutConfig.customer.externalId,
1908
1962
  email: this.checkoutConfig.customer.email,
1909
- region: this.region || DEFAULTS.REGION,
1963
+ region: this.region,
1910
1964
  clientMetadata: this.checkoutConfig.clientMetadata,
1911
1965
  countryCode: this.checkoutConfig.customer.countryCode,
1912
- };
1913
- const cacheKey = [
1914
- this.orgId,
1915
- this.checkoutConfig.priceId,
1916
- this.checkoutConfig.customer.externalId,
1917
- this.checkoutConfig.customer.email,
1918
- ].join('-');
1919
- let sessionResponse;
1920
- // Return cached response if payload hasn't changed
1921
- const cachedResponse = CheckoutInstance.sessionCache.get(cacheKey);
1922
- if (cachedResponse) {
1923
- sessionResponse = await cachedResponse;
1924
- }
1925
- else {
1926
- const sessionRequest = this.apiClient
1927
- .createClientSession(sessionParams)
1928
- .then((response) => {
1929
- const cachedResponse = response;
1930
- if (response.data?.stripe_public_key) {
1931
- const stripePublicKey = response.data.stripe_public_key;
1932
- cachedResponse.radarSessionId = loadStripe(stripePublicKey)
1933
- .then(stripe => stripe
1934
- ? stripe
1935
- .createRadarSession()
1936
- .then(session => session?.radarSession?.id || '')
1937
- .catch(() => '')
1938
- : '')
1939
- .catch(() => '');
1940
- }
1941
- // Initialize Airwallex device fingerprinting if enabled by backend
1942
- if (response.data?.airwallex_risk_enabled) {
1943
- const isLivemode = response.data?.is_livemode;
1944
- const deviceId = generateUUID();
1945
- cachedResponse.airwallexDeviceId = loadAirwallexDeviceFingerprint(deviceId, isLivemode)
1946
- .then(() => deviceId)
1947
- .catch(() => {
1948
- // Silently fail - return deviceId anyway
1949
- return deviceId;
1950
- });
1951
- }
1952
- return cachedResponse;
1953
- });
1954
- // Cache the successful response
1955
- CheckoutInstance.sessionCache.set(cacheKey, sessionRequest);
1956
- sessionResponse = await sessionRequest;
1966
+ integration: 'primer',
1967
+ });
1968
+ const sessionResponse = response;
1969
+ if (response.data?.stripe_public_key) {
1970
+ const stripePublicKey = response.data.stripe_public_key;
1971
+ sessionResponse.radarSessionId = loadStripe(stripePublicKey)
1972
+ .then(stripe => stripe
1973
+ ? stripe
1974
+ .createRadarSession()
1975
+ .then(session => session?.radarSession?.id || '')
1976
+ .catch(() => '')
1977
+ : '')
1978
+ .catch(() => '');
1979
+ }
1980
+ if (response.data?.airwallex_risk_enabled) {
1981
+ const isLivemode = response.data?.is_livemode;
1982
+ const deviceId = generateUUID();
1983
+ sessionResponse.airwallexDeviceId = loadAirwallexDeviceFingerprint(deviceId, isLivemode)
1984
+ .then(() => deviceId)
1985
+ .catch(() => deviceId);
1957
1986
  }
1958
1987
  this.cachedSessionResponse = sessionResponse;
1959
- this.isTelemetryEnabled =
1960
- !!sessionResponse.data?.sdk_telemetry_enabled || true;
1988
+ this.isTelemetryEnabled = !!sessionResponse.data?.sdk_telemetry_enabled;
1961
1989
  this.isCollectingApplePayEmail =
1962
1990
  !!sessionResponse.data?.collect_apple_pay_email;
1963
1991
  this.applySessionCardFieldConfig(sessionResponse);
@@ -2211,9 +2239,9 @@ class CheckoutInstance extends EventEmitter {
2211
2239
  throw new CheckoutError('Cannot update price while payment is processing');
2212
2240
  }
2213
2241
  try {
2242
+ this.onLoaderChangeWithRace(true);
2214
2243
  this._setState('updating');
2215
- // Invalidate session cache
2216
- CheckoutInstance.sessionCache.clear();
2244
+ sessionService.clearCache();
2217
2245
  await this.apiClient.updateClientSession({
2218
2246
  orderId: this.orderId,
2219
2247
  clientToken: this.clientToken,
@@ -2221,9 +2249,12 @@ class CheckoutInstance extends EventEmitter {
2221
2249
  clientMetadata,
2222
2250
  });
2223
2251
  this.checkoutConfig.priceId = newPriceId;
2252
+ await this.primerWrapper.refreshClientSession();
2253
+ this.onLoaderChangeWithRace(false);
2224
2254
  this._setState('ready');
2225
2255
  }
2226
2256
  catch (error) {
2257
+ this.onLoaderChangeWithRace(false);
2227
2258
  this._setState('error');
2228
2259
  this.emit(EVENTS.ERROR, error);
2229
2260
  throw error;
@@ -2243,7 +2274,7 @@ class CheckoutInstance extends EventEmitter {
2243
2274
  return;
2244
2275
  try {
2245
2276
  this.stopUnhandledTelemetry();
2246
- CheckoutInstance.sessionCache.clear();
2277
+ sessionService.clearCache();
2247
2278
  await this.primerWrapper.destroy();
2248
2279
  this._setState('destroyed');
2249
2280
  this.orderId = null;
@@ -2439,8 +2470,12 @@ class CheckoutInstance extends EventEmitter {
2439
2470
  baseUrl: this.baseUrl,
2440
2471
  enabled: this.isTelemetryEnabled,
2441
2472
  getContext: () => ({
2473
+ checkoutId: this.id,
2442
2474
  orderId: this.orderId,
2443
2475
  priceId: this.checkoutConfig.priceId,
2476
+ state: this.state,
2477
+ paymentMethod: this.telemetryPaymentMethod,
2478
+ reqId: this.cachedSessionResponse?.req_id,
2444
2479
  }),
2445
2480
  });
2446
2481
  }
@@ -2450,7 +2485,6 @@ class CheckoutInstance extends EventEmitter {
2450
2485
  this.telemetryPaymentMethod = undefined;
2451
2486
  }
2452
2487
  }
2453
- CheckoutInstance.sessionCache = new Map();
2454
2488
 
2455
2489
  /**
2456
2490
  * @fileoverview Public API with configuration and orchestration logic
@@ -2641,6 +2675,79 @@ async function getAvailablePaymentMethods(params) {
2641
2675
  throw error;
2642
2676
  }
2643
2677
  }
2678
+ async function createStripeCardForm(element, params) {
2679
+ const config = resolveConfig(params, 'createStripeCardForm');
2680
+ const [session, { mountStripeCardForm }] = await Promise.all([
2681
+ sessionService.createSession({
2682
+ orgId: config.orgId,
2683
+ baseUrl: config.baseUrl,
2684
+ region: config.region,
2685
+ priceId: params.priceId,
2686
+ externalId: params.externalId,
2687
+ email: params.email,
2688
+ clientMetadata: params.clientMetadata,
2689
+ countryCode: params.countryCode,
2690
+ integration: 'stripe',
2691
+ }),
2692
+ Promise.resolve().then(function () { return require('./chunk-stripe-card-form.cjs.js'); }),
2693
+ ]);
2694
+ const apiClient = new APIClient({
2695
+ orgId: config.orgId,
2696
+ baseUrl: config.baseUrl || DEFAULTS.BASE_URL,
2697
+ });
2698
+ return mountStripeCardForm(element, session, { ...params, apiClient });
2699
+ }
2700
+ async function purchaseStripeWallet(params) {
2701
+ const config = resolveConfig(params, 'purchaseStripeWallet');
2702
+ const [session, { purchaseWallet }] = await Promise.all([
2703
+ sessionService.createSession({
2704
+ orgId: config.orgId,
2705
+ baseUrl: config.baseUrl,
2706
+ region: config.region,
2707
+ priceId: params.priceId,
2708
+ externalId: params.externalId,
2709
+ email: params.email,
2710
+ clientMetadata: params.clientMetadata,
2711
+ countryCode: params.countryCode,
2712
+ integration: 'stripe',
2713
+ }),
2714
+ Promise.resolve().then(function () { return require('./chunk-stripe-wallet.cjs.js'); }),
2715
+ ]);
2716
+ const apiClient = new APIClient({
2717
+ orgId: config.orgId,
2718
+ baseUrl: config.baseUrl || DEFAULTS.BASE_URL,
2719
+ });
2720
+ return purchaseWallet(session, { ...params, apiClient });
2721
+ }
2722
+ async function getAvailableStripeWallet(params) {
2723
+ const config = resolveConfig(params, 'getAvailableStripeWallet');
2724
+ const [session, { getAvailableWallet }] = await Promise.all([
2725
+ sessionService.createSession({
2726
+ orgId: config.orgId,
2727
+ baseUrl: config.baseUrl,
2728
+ region: config.region,
2729
+ priceId: params.priceId,
2730
+ externalId: params.externalId,
2731
+ email: params.email,
2732
+ clientMetadata: params.clientMetadata,
2733
+ countryCode: params.countryCode,
2734
+ integration: 'stripe',
2735
+ }),
2736
+ Promise.resolve().then(function () { return require('./chunk-stripe-wallet.cjs.js'); }),
2737
+ ]);
2738
+ const result = await getAvailableWallet(session);
2739
+ if (result === 'APPLE_PAY')
2740
+ return exports.PaymentMethod.APPLE_PAY;
2741
+ if (result === 'GOOGLE_PAY')
2742
+ return exports.PaymentMethod.GOOGLE_PAY;
2743
+ return null;
2744
+ }
2745
+ async function getAvailableStripePaymentMethods(params) {
2746
+ const wallet = await getAvailableStripeWallet(params);
2747
+ return wallet
2748
+ ? [exports.PaymentMethod.PAYMENT_CARD, wallet]
2749
+ : [exports.PaymentMethod.PAYMENT_CARD];
2750
+ }
2644
2751
 
2645
2752
  /**
2646
2753
  * @fileoverview Main entry point for @funnelfox/billing
@@ -2652,6 +2759,12 @@ const Billing = {
2652
2759
  initMethod: initMethod,
2653
2760
  silentPurchase: silentPurchase,
2654
2761
  getAvailablePaymentMethods: getAvailablePaymentMethods,
2762
+ stripe: {
2763
+ createCardForm: createStripeCardForm,
2764
+ purchaseWallet: purchaseStripeWallet,
2765
+ getAvailableWallet: getAvailableStripeWallet,
2766
+ getAvailablePaymentMethods: getAvailableStripePaymentMethods,
2767
+ },
2655
2768
  };
2656
2769
  if (typeof window !== 'undefined') {
2657
2770
  window.Billing = Billing;
@@ -2675,3 +2788,4 @@ exports.configure = configure;
2675
2788
  exports.createCheckout = createCheckout;
2676
2789
  exports.createClientSession = createClientSession;
2677
2790
  exports.getAvailablePaymentMethods = getAvailablePaymentMethods;
2791
+ exports.loadStripe = loadStripe;