@lightspeed/online-payments-sdk 1.7.1 → 1.7.3

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
@@ -1,6 +1,11 @@
1
1
  # Lightspeed Online Payments SDK
2
2
 
3
- `@lightspeed/online-payments-sdk` is a browser SDK for mounting Lightspeed Payments widgets (Stripe and Adyen) in web applications.
3
+ `@lightspeed/online-payments-sdk` is a browser SDK for displaying Lightspeed Payments widgets in your web application.
4
+
5
+ This is intended for partners who wish to add payments functionality to an integration with a Lightspeed product.
6
+
7
+ For onboarding questions, account configuration, or production enablement: contact your Lightspeed
8
+ representative.
4
9
 
5
10
  ## Installation
6
11
 
@@ -8,94 +13,123 @@
8
13
  npm install @lightspeed/online-payments-sdk
9
14
  ```
10
15
 
11
- ## Quick start
12
-
13
- ```ts
14
- import {LightspeedPayments} from '@lightspeed/online-payments-sdk';
15
-
16
- const controller = await LightspeedPayments.v1.mountPaymentWidget(sessionToken, {
17
- mountPoint: document.getElementById('payment-widget')!,
18
- });
16
+ ## Requirements
19
17
 
20
- controller.unmount();
21
- ```
18
+ - A browser environment with `window` and `document`
19
+ - A payment session obtained from your Lightspeed Payments integration
20
+ - An HTML element where the payment widget can be mounted
22
21
 
23
- ## Compatibility
24
-
25
- - TypeScript/JavaScript
26
- - Browser runtime (requires `window`)
27
-
28
- ## Theming
22
+ ## Quick start
29
23
 
30
- The SDK supports custom themes. If no theme is specified, Stripe defaults are used.
24
+ Add a mount element to your page:
31
25
 
32
- ### Available themes
26
+ ```html
27
+ <div id="payment-widget"></div>
28
+ ```
33
29
 
34
- - default (no `theme` value)
35
- - `invoicing`
36
- - `dark`
30
+ Mount the widget with the payment session from your integration:
37
31
 
38
32
  ```ts
39
33
  import {LightspeedPayments} from '@lightspeed/online-payments-sdk';
40
34
 
41
- await LightspeedPayments.v1.mountPaymentWidget(paymentSession, {
42
- mountPoint: document.getElementById('payment-widget')!,
43
- theme: 'dark',
35
+ const mountPoint = document.getElementById('payment-widget');
36
+
37
+ if (!mountPoint) {
38
+ throw new Error('Payment widget mount point was not found');
39
+ }
40
+
41
+ const controller = await LightspeedPayments.v1.mountPaymentWidget(session, {
42
+ mountPoint,
44
43
  });
45
44
  ```
46
45
 
47
- ### Container styling
46
+ Keep the returned controller to submit the widget or remove it when the containing page or component is no longer needed.
47
+
48
+ ## Configuration
48
49
 
49
- For dark mode, the SDK styles the mount element you pass in `mountPoint`. If you style a parent wrapper, use `THEME_COLORS`.
50
+ `mountPaymentWidget(session, configuration)` accepts a payment session and the following configuration:
51
+
52
+ | Option | Description |
53
+ | --------------- | ---------------------------------------------------------------- |
54
+ | `mountPoint` | Required `HTMLElement` where the SDK renders the payment widget. |
55
+ | `defaultValues` | Optional initial address values: `country` and `postalCode`. |
56
+ | `listeners` | Optional callbacks for widget lifecycle and payment events. |
57
+ | `theme` | Optional visual theme: `dark`. |
50
58
 
51
59
  ```ts
52
- import {THEME_COLORS} from '@lightspeed/online-payments-sdk';
60
+ const controller = await LightspeedPayments.v1.mountPaymentWidget(session, {
61
+ mountPoint,
62
+ defaultValues: {
63
+ country: 'CA',
64
+ postalCode: 'H1H1H1',
65
+ },
66
+ listeners: {
67
+ onReady: () => {
68
+ // The widget is ready for payer input.
69
+ },
70
+ onChange: event => {
71
+ submitButton.disabled = event.code !== 'Complete';
72
+ },
73
+ onSucceeded: () => {
74
+ // Continue after a successful payment or payment-method save.
75
+ },
76
+ onDeclined: event => {
77
+ // Show a decline message appropriate for event.code.
78
+ },
79
+ onError: event => {
80
+ // Handle a widget or processing error.
81
+ },
82
+ },
83
+ });
53
84
  ```
54
85
 
55
- ## Documentation
86
+ ### Events
56
87
 
57
- - Datadog logging reference: `packages/lsp-online-payments-sdk/docs/DATADOG_LOGGING.md`
58
- - Sandbox releases (testing unreleased builds in a real app): `packages/lsp-online-payments-sdk/docs/sandbox-releases.md`
88
+ Listeners receive an event with a `status` and `code`. Available listener names are `onReady`, `onChange`, `onSucceeded`, `onPending`, `onDeclined`, and `onError`.
59
89
 
60
- ## Development
90
+ | Status | Codes |
91
+ | ----------- | -------------------------------------------------------------------------------------------------------------- |
92
+ | `Ready` | `Ready` |
93
+ | `Change` | `Complete`, `Incomplete` |
94
+ | `Succeeded` | `Authorized` |
95
+ | `Pending` | `Processing` |
96
+ | `Declined` | `CardValidation`, `Generic`, `PaymentMethodNotSupported` |
97
+ | `Error` | `Unexpected`, `InvalidSession`, `InvalidSessionPayload`, `UnsupportedLocation`, `Processing`, `FormValidation` |
61
98
 
62
- Run SDK checks (same order as CI):
99
+ ## Submit and unmount
63
100
 
64
- ```sh
65
- npm run lint --workspace @lightspeed/online-payments-sdk
66
- npm run typecheck --workspace @lightspeed/online-payments-sdk
67
- npm run test --workspace @lightspeed/online-payments-sdk
68
- ```
101
+ Call `submit()` in response to your application's payment action. Call `unmount()` before removing or replacing the mount element.
69
102
 
70
- Build package:
103
+ ```ts
104
+ submitButton.addEventListener('click', async () => {
105
+ await controller.submit();
106
+ });
71
107
 
72
- ```sh
73
- npm run build --workspace @lightspeed/online-payments-sdk
108
+ // For example, during page or component cleanup.
109
+ controller.unmount();
74
110
  ```
75
111
 
76
- Inspect publish contents:
112
+ ## Theming
77
113
 
78
- ```sh
79
- npm pack --dry-run
80
- ```
114
+ Use `theme` to select a widget appearance:
81
115
 
82
- ## Publishing and release flow
116
+ - Omit `theme` to use the default appearance.
117
+ - `dark` uses a dark appearance and styles the mount element with a dark background.
83
118
 
84
- Publishing is handled by CircleCI (not manual local publish).
119
+ Custom themes can be used with support from the Lightspeed Payments team.
85
120
 
86
- - Release path runs on `main` and `release/*`.
87
- - CircleCI runs quality gates (`lint`, `typecheck`, unit tests, build, e2e).
88
- - `verify_package_version` compares local `package.json` version with npm.
89
- - If local version is not higher, publish is skipped.
90
- - If local version is higher, the workflow pauses at manual approval (`pause_workflow`).
91
- - A human must approve before the `release` job runs `npm publish`.
121
+ ```ts
122
+ await LightspeedPayments.v1.mountPaymentWidget(session, {
123
+ mountPoint,
124
+ theme: 'dark',
125
+ });
126
+ ```
92
127
 
93
- In practice: bump `version` in `packages/lsp-online-payments-sdk/package.json`, merge to `main`, then approve the release hold in CircleCI.
128
+ For a wrapper around a widget using the `dark` theme, use `THEME_COLORS` to match the SDK's dark container colors:
94
129
 
95
- ### Sandbox releases
130
+ ```ts
131
+ import {THEME_COLORS} from '@lightspeed/online-payments-sdk';
96
132
 
97
- To test unreleased SDK changes inside a real app without touching the production
98
- package on public npm, publish a **sandbox** build to GitHub Packages: push a
99
- `sandbox/*` branch and approve the `hold_sandbox` step in CircleCI. Consuming an
100
- app requires no `import` changes — just an `.npmrc` scope + a `package.json`
101
- alias. See `docs/sandbox-releases.md` for the full publish and consume steps.
133
+ wrapper.style.backgroundColor = THEME_COLORS.DARK.BACKGROUND;
134
+ wrapper.style.color = THEME_COLORS.DARK.TEXT;
135
+ ```
@@ -0,0 +1,39 @@
1
+ "use strict";
2
+ /**
3
+ * Helpers for identifying partner-initiated sessions from the session
4
+ * metadata `product` value.
5
+ *
6
+ * The processing service encodes the product as
7
+ * `partner:{grantor}::{applicationId}` for integrator (partner) sessions
8
+ * (see `formatPartnerProductValue` in lsp-processing-service). We only need to
9
+ * read the grantor segment here to branch on partner-specific behavior such as
10
+ * custom card consent text.
11
+ */
12
+ Object.defineProperty(exports, "__esModule", { value: true });
13
+ exports.getPartnerGrantor = getPartnerGrantor;
14
+ var PARTNER_PRODUCT_PREFIX = 'partner:';
15
+ var PARTNER_PRODUCT_SEGMENT_SEPARATOR = '::';
16
+ /**
17
+ * Parse the grantor segment out of a partner product value.
18
+ * Returns `undefined` for non-partner or malformed product values.
19
+ */
20
+ function getPartnerGrantor(product) {
21
+ if (typeof product !== 'string') {
22
+ return undefined;
23
+ }
24
+ if (!product.startsWith(PARTNER_PRODUCT_PREFIX)) {
25
+ return undefined;
26
+ }
27
+ var suffix = product.slice(PARTNER_PRODUCT_PREFIX.length);
28
+ var separatorIndex = suffix.indexOf(PARTNER_PRODUCT_SEGMENT_SEPARATOR);
29
+ if (separatorIndex <= 0) {
30
+ return undefined;
31
+ }
32
+ var grantor = suffix.slice(0, separatorIndex);
33
+ var applicationId = suffix.slice(separatorIndex + PARTNER_PRODUCT_SEGMENT_SEPARATOR.length);
34
+ // Require both segments: `partner:golf::` (empty applicationId) is malformed.
35
+ if (grantor.length === 0 || applicationId.length === 0) {
36
+ return undefined;
37
+ }
38
+ return grantor;
39
+ }
@@ -50,6 +50,8 @@ Object.defineProperty(exports, "__esModule", { value: true });
50
50
  exports.initStripe = initStripe;
51
51
  exports.createPaymentElementOptions = createPaymentElementOptions;
52
52
  exports.createAddressElementOptions = createAddressElementOptions;
53
+ exports.buildCardConsentText = buildCardConsentText;
54
+ exports.createCardConsentElement = createCardConsentElement;
53
55
  exports.createPaymentElement = createPaymentElement;
54
56
  exports.setupChangeEventHandler = setupChangeEventHandler;
55
57
  exports.createAddressElement = createAddressElement;
@@ -93,11 +95,10 @@ function initStripe(context, theme) {
93
95
  * @param theme - Theme configuration
94
96
  * @param hideNameField - Whether to hide the billing details name field (used when address element is present to avoid duplicates with ACH)
95
97
  * @param businessName - Overrides the merchant name Stripe renders in mandate text (passed to `business.name`)
96
- * @param showCardMandate - Forces Stripe to render its card mandate text (which includes `business.name`). Used for partner payment-with-save flows where Stripe would otherwise not show terms.
98
+ * @param cardMandate - Maps directly to Stripe's `terms.card`: `'always'` forces Stripe's card mandate (with `business.name`), `'never'` hides it (used when the SDK renders its own consent text). Omit to leave Stripe's `'auto'` default.
97
99
  */
98
- function createPaymentElementOptions(defaultValues, theme, hideNameField, businessName, showCardMandate) {
100
+ function createPaymentElementOptions(defaultValues, theme, hideNameField, businessName, cardMandate) {
99
101
  if (hideNameField === void 0) { hideNameField = false; }
100
- if (showCardMandate === void 0) { showCardMandate = false; }
101
102
  var options = __assign(__assign(__assign({ wallets: {
102
103
  applePay: 'never',
103
104
  googlePay: 'never',
@@ -108,7 +109,7 @@ function createPaymentElementOptions(defaultValues, theme, hideNameField, busine
108
109
  name: 'never', // prevent duplicate Name field on the form when using ACH (only when address element is present)
109
110
  },
110
111
  },
111
- })), { terms: __assign({ usBankAccount: 'never' }, (showCardMandate && businessName && { card: 'always' })) }), (businessName && { business: { name: businessName } }));
112
+ })), { terms: __assign({ usBankAccount: 'never' }, (cardMandate && { card: cardMandate })) }), (businessName && { business: { name: businessName } }));
112
113
  if (defaultValues) {
113
114
  options.defaultValues = {
114
115
  billingDetails: {
@@ -186,6 +187,39 @@ function createCustomTermsElement() {
186
187
  }
187
188
  return termsContainer;
188
189
  }
190
+ /**
191
+ * Build a card consent sentence by interpolating the business name and reason
192
+ * into the flow-specific template.
193
+ * @param variant - 'mandatory' for the save-card flow (consent by providing card
194
+ * details), 'checkbox' for the pay-and-save flow (consent by checking the box).
195
+ */
196
+ function buildCardConsentText(businessName, reason, variant) {
197
+ var template = variant === 'checkbox'
198
+ ? terms_1.PARTNER_CARD_CONSENT_TEXT.CHECKBOX_TEMPLATE
199
+ : terms_1.PARTNER_CARD_CONSENT_TEXT.MANDATORY_TEMPLATE;
200
+ return template
201
+ .replace(/\{business\}/g, function () { return businessName; })
202
+ .replace(/\{reason\}/g, function () { return reason; });
203
+ }
204
+ /**
205
+ * Render a card consent element that replaces Stripe's built-in card mandate
206
+ * (suppressed via `terms.card: 'never'`) with the given copy. Pure render
207
+ * primitive — the caller composes the sentence (e.g. via `buildCardConsentText`)
208
+ * so this makes no assumption about the wording. Uses dedicated
209
+ * `.stripe-card-consent-*` classes whose styling mirrors the ACH custom-terms
210
+ * text.
211
+ */
212
+ function createCardConsentElement(consentText) {
213
+ var container = document.createElement('div');
214
+ container.className = 'stripe-card-consent-container';
215
+ var text = document.createElement('p');
216
+ text.className = 'stripe-card-consent-text';
217
+ // Plain text (no links) — use textContent to avoid injecting the composed
218
+ // business name as HTML.
219
+ text.textContent = consentText;
220
+ container.appendChild(text);
221
+ return container;
222
+ }
189
223
  /**
190
224
  * Create and mount payment element
191
225
  */
@@ -285,7 +319,7 @@ function createAddressElement(elements, options, mountElement) {
285
319
  /**
286
320
  * Clean up elements and containers
287
321
  */
288
- function cleanupElements(paymentElement, addressElement, paymentContainer, addressContainer, customTermsContainer) {
322
+ function cleanupElements(paymentElement, addressElement, paymentContainer, addressContainer, customTermsContainer, cardConsentContainer) {
289
323
  paymentElement.unmount();
290
324
  if (addressElement) {
291
325
  addressElement.unmount();
@@ -300,6 +334,9 @@ function cleanupElements(paymentElement, addressElement, paymentContainer, addre
300
334
  if (customTermsContainer) {
301
335
  customTermsContainer.remove();
302
336
  }
337
+ if (cardConsentContainer) {
338
+ cardConsentContainer.remove();
339
+ }
303
340
  }
304
341
  /**
305
342
  * Handle save card operation
@@ -8,7 +8,8 @@
8
8
  * - Replace with translated versions based on locale
9
9
  */
10
10
  Object.defineProperty(exports, "__esModule", { value: true });
11
- exports.ACH_TERMS_URL = exports.ACH_TERMS_TEXT = void 0;
11
+ exports.ACH_TERMS_URL = exports.PARTNER_CARD_CONSENT_TEXT = exports.ACH_TERMS_TEXT = void 0;
12
+ exports.getPartnerCardConsentReason = getPartnerCardConsentReason;
12
13
  exports.ACH_TERMS_TEXT = {
13
14
  /**
14
15
  * Main terms text displayed for US Bank Account payments.
@@ -37,6 +38,45 @@ exports.ACH_TERMS_TEXT = {
37
38
  EXPANDED_TERMS_PRIVACY_PREFIX: 'Lightspeed may collect or access certain payment-related information as described in the platform agreement and',
38
39
  PRIVACY_POLICY_LINK_TEXT: 'Privacy Policy',
39
40
  };
41
+ /**
42
+ * Partner card consent text — replaces Stripe's built-in card mandate (whose
43
+ * wording is fixed by Stripe and cannot be customized) with copy the SDK renders
44
+ * itself for partner card payments. `{business}` and `{reason}` are interpolated
45
+ * at render time (reason supplied by the caller, e.g. via
46
+ * `getPartnerCardConsentReason`).
47
+ *
48
+ * NOTE: The SDK does not translate these strings at runtime — they render in
49
+ * English regardless of the session `locale` (which only localizes Stripe's own
50
+ * Element UI). Like the ACH strings above, they are kept as plain constants so
51
+ * they *could* be extracted for Transifex later, but no runtime i18n exists
52
+ * today.
53
+ */
54
+ exports.PARTNER_CARD_CONSENT_TEXT = {
55
+ // save-card flow: consent given by providing card details.
56
+ MANDATORY_TEMPLATE: 'By providing your card information, you authorize {business} to charge your card for {reason} in accordance with their terms.',
57
+ // pay-and-save flow: consent tied to the save checkbox.
58
+ CHECKBOX_TEMPLATE: 'By checking the box above, you authorize {business} to charge your card for {reason} in accordance with their terms.',
59
+ };
60
+ /**
61
+ * Consent reason per partner grantor — what the saved card may be charged for,
62
+ * keyed by the grantor segment of the product (`partner:{grantor}::...`). Add an
63
+ * entry to offer custom card consent to another partner. Hardcoded for now; may
64
+ * become a per-session input from Processing Service later.
65
+ */
66
+ var PARTNER_CARD_CONSENT_REASONS = {
67
+ golf: 'future payments towards charges related to tee-time bookings and/or house accounts as applicable',
68
+ };
69
+ /**
70
+ * The configured consent reason for a partner grantor, or `undefined` if the
71
+ * partner has none (in which case no custom card consent is rendered).
72
+ */
73
+ function getPartnerCardConsentReason(grantor) {
74
+ if (grantor &&
75
+ Object.prototype.hasOwnProperty.call(PARTNER_CARD_CONSENT_REASONS, grantor)) {
76
+ return PARTNER_CARD_CONSENT_REASONS[grantor];
77
+ }
78
+ return undefined;
79
+ }
40
80
  exports.ACH_TERMS_URL = {
41
81
  STRIPE_ACH_AUTHORIZATION: 'https://stripe.com/legal/ach-payments/authorization',
42
82
  PRIVACY_POLICY: 'https://www.lightspeedhq.com/legal/privacy-policy/',
@@ -38,25 +38,39 @@ var __generator = (this && this.__generator) || function (thisArg, body) {
38
38
  Object.defineProperty(exports, "__esModule", { value: true });
39
39
  exports.mountMotoWidget = mountMotoWidget;
40
40
  var shared_1 = require("../shared");
41
+ var partnerProduct_1 = require("../partnerProduct");
42
+ var terms_1 = require("../terms");
41
43
  /**
42
44
  * Mount MOTO widget for moto and moto-with-save session types
43
45
  * MOTO (Mail Order/Telephone Order) forms don't require address collection
44
46
  */
45
47
  function mountMotoWidget(mountElement, session, eventBroadcaster, defaultValues, theme) {
46
48
  return __awaiter(this, void 0, void 0, function () {
47
- var _a, stripe, elements, paymentOptions, _b, paymentElement, paymentContainer, customTermsContainer;
49
+ var _a, stripe, elements, businessName, consentReason, renderPartnerConsent, cardMandate, paymentOptions, _b, paymentElement, paymentContainer, customTermsContainer, cardConsentContainer;
48
50
  return __generator(this, function (_c) {
49
51
  switch (_c.label) {
50
52
  case 0: return [4 /*yield*/, (0, shared_1.initStripe)(session.context, theme)];
51
53
  case 1:
52
54
  _a = _c.sent(), stripe = _a.stripe, elements = _a.elements;
53
- paymentOptions = (0, shared_1.createPaymentElementOptions)(defaultValues, theme, false, session.context.businessName);
55
+ businessName = session.context.businessName;
56
+ consentReason = (0, terms_1.getPartnerCardConsentReason)((0, partnerProduct_1.getPartnerGrantor)(session.metadata.product));
57
+ renderPartnerConsent = session.metadata.sessionType === 'save' &&
58
+ !!businessName &&
59
+ !!consentReason;
60
+ cardMandate = renderPartnerConsent
61
+ ? 'never'
62
+ : undefined;
63
+ paymentOptions = (0, shared_1.createPaymentElementOptions)(defaultValues, theme, false, businessName, cardMandate);
54
64
  _b = (0, shared_1.createPaymentElement)(elements, paymentOptions, mountElement, eventBroadcaster), paymentElement = _b.element, paymentContainer = _b.container, customTermsContainer = _b.customTermsContainer;
65
+ if (renderPartnerConsent) {
66
+ cardConsentContainer = (0, shared_1.createCardConsentElement)((0, shared_1.buildCardConsentText)(businessName, consentReason, 'mandatory'));
67
+ mountElement.appendChild(cardConsentContainer);
68
+ }
55
69
  // Setup change handler for payment element only (MOTO forms don't have address element)
56
70
  (0, shared_1.setupChangeEventHandler)(paymentElement, eventBroadcaster);
57
71
  return [2 /*return*/, {
58
72
  unmount: function () {
59
- (0, shared_1.cleanupElements)(paymentElement, null, paymentContainer, null, customTermsContainer);
73
+ (0, shared_1.cleanupElements)(paymentElement, null, paymentContainer, null, customTermsContainer, cardConsentContainer);
60
74
  },
61
75
  submit: (0, shared_1.createSubmitHandler)(stripe, elements, session, eventBroadcaster, null),
62
76
  }];
@@ -38,17 +38,21 @@ var __generator = (this && this.__generator) || function (thisArg, body) {
38
38
  Object.defineProperty(exports, "__esModule", { value: true });
39
39
  exports.mountPaymentWidget = mountPaymentWidget;
40
40
  var shared_1 = require("../shared");
41
+ var partnerProduct_1 = require("../partnerProduct");
42
+ var terms_1 = require("../terms");
41
43
  /**
42
44
  * Mount payment widget for payment and payment-with-save session types
43
45
  */
44
46
  function mountPaymentWidget(mountElement, session, eventBroadcaster, defaultValues, theme) {
45
47
  return __awaiter(this, void 0, void 0, function () {
46
- var _a, stripe, elements, productMetadata, isPartnerProduct, addressElement, addressContainer, addressOptions, created, showCardMandate, paymentOptions, _b, paymentElement, paymentContainer, customTermsContainer;
48
+ var _a, stripe, elements, businessName, isPayWithSave, productMetadata, isPartnerProduct, addressElement, addressContainer, addressOptions, created, consentReason, renderPartnerConsent, cardMandate, paymentOptions, _b, paymentElement, paymentContainer, customTermsContainer, cardConsentContainer;
47
49
  return __generator(this, function (_c) {
48
50
  switch (_c.label) {
49
51
  case 0: return [4 /*yield*/, (0, shared_1.initStripe)(session.context, theme)];
50
52
  case 1:
51
53
  _a = _c.sent(), stripe = _a.stripe, elements = _a.elements;
54
+ businessName = session.context.businessName;
55
+ isPayWithSave = session.metadata.sessionType === 'payment-with-save';
52
56
  productMetadata = session.metadata.product;
53
57
  isPartnerProduct = typeof productMetadata === 'string' &&
54
58
  productMetadata.startsWith('partner:');
@@ -60,16 +64,24 @@ function mountPaymentWidget(mountElement, session, eventBroadcaster, defaultValu
60
64
  addressElement = created.element;
61
65
  addressContainer = created.container;
62
66
  }
63
- showCardMandate = session.metadata.sessionType === 'payment-with-save' &&
64
- !!session.context.businessName &&
65
- isPartnerProduct;
66
- paymentOptions = (0, shared_1.createPaymentElementOptions)(defaultValues, theme, !!addressElement, session.context.businessName, showCardMandate);
67
+ consentReason = (0, terms_1.getPartnerCardConsentReason)((0, partnerProduct_1.getPartnerGrantor)(productMetadata));
68
+ renderPartnerConsent = isPayWithSave && !!businessName && !!consentReason;
69
+ cardMandate = renderPartnerConsent
70
+ ? 'never'
71
+ : isPayWithSave && !!businessName && isPartnerProduct
72
+ ? 'always'
73
+ : undefined;
74
+ paymentOptions = (0, shared_1.createPaymentElementOptions)(defaultValues, theme, !!addressElement, businessName, cardMandate);
67
75
  _b = (0, shared_1.createPaymentElement)(elements, paymentOptions, mountElement, eventBroadcaster), paymentElement = _b.element, paymentContainer = _b.container, customTermsContainer = _b.customTermsContainer;
76
+ if (renderPartnerConsent) {
77
+ cardConsentContainer = (0, shared_1.createCardConsentElement)((0, shared_1.buildCardConsentText)(businessName, consentReason, 'checkbox'));
78
+ mountElement.appendChild(cardConsentContainer);
79
+ }
68
80
  // Setup change handler that emits Complete only when both elements are complete
69
81
  (0, shared_1.setupChangeEventHandler)(paymentElement, eventBroadcaster, addressElement);
70
82
  return [2 /*return*/, {
71
83
  unmount: function () {
72
- (0, shared_1.cleanupElements)(paymentElement, addressElement, paymentContainer, addressContainer, customTermsContainer);
84
+ (0, shared_1.cleanupElements)(paymentElement, addressElement, paymentContainer, addressContainer, customTermsContainer, cardConsentContainer);
73
85
  },
74
86
  submit: (0, shared_1.createSubmitHandler)(stripe, elements, session, eventBroadcaster, addressElement),
75
87
  }];
@@ -3,4 +3,4 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.SDK_VERSION = void 0;
4
4
  // This file is auto-generated during the build process
5
5
  // DO NOT EDIT MANUALLY - Version is extracted from package.json
6
- exports.SDK_VERSION = '1.7.1';
6
+ exports.SDK_VERSION = '1.7.3';
@@ -0,0 +1,15 @@
1
+ /**
2
+ * Helpers for identifying partner-initiated sessions from the session
3
+ * metadata `product` value.
4
+ *
5
+ * The processing service encodes the product as
6
+ * `partner:{grantor}::{applicationId}` for integrator (partner) sessions
7
+ * (see `formatPartnerProductValue` in lsp-processing-service). We only need to
8
+ * read the grantor segment here to branch on partner-specific behavior such as
9
+ * custom card consent text.
10
+ */
11
+ /**
12
+ * Parse the grantor segment out of a partner product value.
13
+ * Returns `undefined` for non-partner or malformed product values.
14
+ */
15
+ export declare function getPartnerGrantor(product?: string): string | undefined;
@@ -0,0 +1,36 @@
1
+ /**
2
+ * Helpers for identifying partner-initiated sessions from the session
3
+ * metadata `product` value.
4
+ *
5
+ * The processing service encodes the product as
6
+ * `partner:{grantor}::{applicationId}` for integrator (partner) sessions
7
+ * (see `formatPartnerProductValue` in lsp-processing-service). We only need to
8
+ * read the grantor segment here to branch on partner-specific behavior such as
9
+ * custom card consent text.
10
+ */
11
+ var PARTNER_PRODUCT_PREFIX = 'partner:';
12
+ var PARTNER_PRODUCT_SEGMENT_SEPARATOR = '::';
13
+ /**
14
+ * Parse the grantor segment out of a partner product value.
15
+ * Returns `undefined` for non-partner or malformed product values.
16
+ */
17
+ export function getPartnerGrantor(product) {
18
+ if (typeof product !== 'string') {
19
+ return undefined;
20
+ }
21
+ if (!product.startsWith(PARTNER_PRODUCT_PREFIX)) {
22
+ return undefined;
23
+ }
24
+ var suffix = product.slice(PARTNER_PRODUCT_PREFIX.length);
25
+ var separatorIndex = suffix.indexOf(PARTNER_PRODUCT_SEGMENT_SEPARATOR);
26
+ if (separatorIndex <= 0) {
27
+ return undefined;
28
+ }
29
+ var grantor = suffix.slice(0, separatorIndex);
30
+ var applicationId = suffix.slice(separatorIndex + PARTNER_PRODUCT_SEGMENT_SEPARATOR.length);
31
+ // Require both segments: `partner:golf::` (empty applicationId) is malformed.
32
+ if (grantor.length === 0 || applicationId.length === 0) {
33
+ return undefined;
34
+ }
35
+ return grantor;
36
+ }
@@ -22,13 +22,29 @@ export declare function initStripe(context: StripeContext, theme?: PaymentWidget
22
22
  * @param theme - Theme configuration
23
23
  * @param hideNameField - Whether to hide the billing details name field (used when address element is present to avoid duplicates with ACH)
24
24
  * @param businessName - Overrides the merchant name Stripe renders in mandate text (passed to `business.name`)
25
- * @param showCardMandate - Forces Stripe to render its card mandate text (which includes `business.name`). Used for partner payment-with-save flows where Stripe would otherwise not show terms.
25
+ * @param cardMandate - Maps directly to Stripe's `terms.card`: `'always'` forces Stripe's card mandate (with `business.name`), `'never'` hides it (used when the SDK renders its own consent text). Omit to leave Stripe's `'auto'` default.
26
26
  */
27
- export declare function createPaymentElementOptions(defaultValues?: DefaultValues, theme?: PaymentWidgetTheme, hideNameField?: boolean, businessName?: string, showCardMandate?: boolean): StripePaymentElementOptions;
27
+ export declare function createPaymentElementOptions(defaultValues?: DefaultValues, theme?: PaymentWidgetTheme, hideNameField?: boolean, businessName?: string, cardMandate?: 'always' | 'never'): StripePaymentElementOptions;
28
28
  /**
29
29
  * Create address element options
30
30
  */
31
31
  export declare function createAddressElementOptions(defaultValues?: DefaultValues): StripeAddressElementOptions;
32
+ /**
33
+ * Build a card consent sentence by interpolating the business name and reason
34
+ * into the flow-specific template.
35
+ * @param variant - 'mandatory' for the save-card flow (consent by providing card
36
+ * details), 'checkbox' for the pay-and-save flow (consent by checking the box).
37
+ */
38
+ export declare function buildCardConsentText(businessName: string, reason: string, variant: 'mandatory' | 'checkbox'): string;
39
+ /**
40
+ * Render a card consent element that replaces Stripe's built-in card mandate
41
+ * (suppressed via `terms.card: 'never'`) with the given copy. Pure render
42
+ * primitive — the caller composes the sentence (e.g. via `buildCardConsentText`)
43
+ * so this makes no assumption about the wording. Uses dedicated
44
+ * `.stripe-card-consent-*` classes whose styling mirrors the ACH custom-terms
45
+ * text.
46
+ */
47
+ export declare function createCardConsentElement(consentText: string): HTMLElement;
32
48
  /**
33
49
  * Create and mount payment element
34
50
  */
@@ -56,7 +72,7 @@ export declare function createAddressElement(elements: StripeElements, options:
56
72
  /**
57
73
  * Clean up elements and containers
58
74
  */
59
- export declare function cleanupElements(paymentElement: StripePaymentElement, addressElement: StripeAddressElement | null, paymentContainer: HTMLElement, addressContainer: HTMLElement | null, customTermsContainer?: HTMLElement): void;
75
+ export declare function cleanupElements(paymentElement: StripePaymentElement, addressElement: StripeAddressElement | null, paymentContainer: HTMLElement, addressContainer: HTMLElement | null, customTermsContainer?: HTMLElement, cardConsentContainer?: HTMLElement): void;
60
76
  /**
61
77
  * Handle save card operation
62
78
  */
@@ -49,7 +49,7 @@ import { loadStripe, } from '@stripe/stripe-js';
49
49
  import { EventBuilder } from './ResultBuilder';
50
50
  import { InvalidSessionPayloadError, ProcessingError } from '../error';
51
51
  import { getThemeConfig } from './themes';
52
- import { ACH_TERMS_TEXT, ACH_TERMS_URL } from './terms';
52
+ import { ACH_TERMS_TEXT, ACH_TERMS_URL, PARTNER_CARD_CONSENT_TEXT } from './terms';
53
53
  /**
54
54
  * Initialize Stripe with the given context
55
55
  */
@@ -81,11 +81,10 @@ export function initStripe(context, theme) {
81
81
  * @param theme - Theme configuration
82
82
  * @param hideNameField - Whether to hide the billing details name field (used when address element is present to avoid duplicates with ACH)
83
83
  * @param businessName - Overrides the merchant name Stripe renders in mandate text (passed to `business.name`)
84
- * @param showCardMandate - Forces Stripe to render its card mandate text (which includes `business.name`). Used for partner payment-with-save flows where Stripe would otherwise not show terms.
84
+ * @param cardMandate - Maps directly to Stripe's `terms.card`: `'always'` forces Stripe's card mandate (with `business.name`), `'never'` hides it (used when the SDK renders its own consent text). Omit to leave Stripe's `'auto'` default.
85
85
  */
86
- export function createPaymentElementOptions(defaultValues, theme, hideNameField, businessName, showCardMandate) {
86
+ export function createPaymentElementOptions(defaultValues, theme, hideNameField, businessName, cardMandate) {
87
87
  if (hideNameField === void 0) { hideNameField = false; }
88
- if (showCardMandate === void 0) { showCardMandate = false; }
89
88
  var options = __assign(__assign(__assign({ wallets: {
90
89
  applePay: 'never',
91
90
  googlePay: 'never',
@@ -96,7 +95,7 @@ export function createPaymentElementOptions(defaultValues, theme, hideNameField,
96
95
  name: 'never', // prevent duplicate Name field on the form when using ACH (only when address element is present)
97
96
  },
98
97
  },
99
- })), { terms: __assign({ usBankAccount: 'never' }, (showCardMandate && businessName && { card: 'always' })) }), (businessName && { business: { name: businessName } }));
98
+ })), { terms: __assign({ usBankAccount: 'never' }, (cardMandate && { card: cardMandate })) }), (businessName && { business: { name: businessName } }));
100
99
  if (defaultValues) {
101
100
  options.defaultValues = {
102
101
  billingDetails: {
@@ -174,6 +173,39 @@ function createCustomTermsElement() {
174
173
  }
175
174
  return termsContainer;
176
175
  }
176
+ /**
177
+ * Build a card consent sentence by interpolating the business name and reason
178
+ * into the flow-specific template.
179
+ * @param variant - 'mandatory' for the save-card flow (consent by providing card
180
+ * details), 'checkbox' for the pay-and-save flow (consent by checking the box).
181
+ */
182
+ export function buildCardConsentText(businessName, reason, variant) {
183
+ var template = variant === 'checkbox'
184
+ ? PARTNER_CARD_CONSENT_TEXT.CHECKBOX_TEMPLATE
185
+ : PARTNER_CARD_CONSENT_TEXT.MANDATORY_TEMPLATE;
186
+ return template
187
+ .replace(/\{business\}/g, function () { return businessName; })
188
+ .replace(/\{reason\}/g, function () { return reason; });
189
+ }
190
+ /**
191
+ * Render a card consent element that replaces Stripe's built-in card mandate
192
+ * (suppressed via `terms.card: 'never'`) with the given copy. Pure render
193
+ * primitive — the caller composes the sentence (e.g. via `buildCardConsentText`)
194
+ * so this makes no assumption about the wording. Uses dedicated
195
+ * `.stripe-card-consent-*` classes whose styling mirrors the ACH custom-terms
196
+ * text.
197
+ */
198
+ export function createCardConsentElement(consentText) {
199
+ var container = document.createElement('div');
200
+ container.className = 'stripe-card-consent-container';
201
+ var text = document.createElement('p');
202
+ text.className = 'stripe-card-consent-text';
203
+ // Plain text (no links) — use textContent to avoid injecting the composed
204
+ // business name as HTML.
205
+ text.textContent = consentText;
206
+ container.appendChild(text);
207
+ return container;
208
+ }
177
209
  /**
178
210
  * Create and mount payment element
179
211
  */
@@ -273,7 +305,7 @@ export function createAddressElement(elements, options, mountElement) {
273
305
  /**
274
306
  * Clean up elements and containers
275
307
  */
276
- export function cleanupElements(paymentElement, addressElement, paymentContainer, addressContainer, customTermsContainer) {
308
+ export function cleanupElements(paymentElement, addressElement, paymentContainer, addressContainer, customTermsContainer, cardConsentContainer) {
277
309
  paymentElement.unmount();
278
310
  if (addressElement) {
279
311
  addressElement.unmount();
@@ -288,6 +320,9 @@ export function cleanupElements(paymentElement, addressElement, paymentContainer
288
320
  if (customTermsContainer) {
289
321
  customTermsContainer.remove();
290
322
  }
323
+ if (cardConsentContainer) {
324
+ cardConsentContainer.remove();
325
+ }
291
326
  }
292
327
  /**
293
328
  * Handle save card operation
@@ -29,6 +29,28 @@ export declare const ACH_TERMS_TEXT: {
29
29
  readonly EXPANDED_TERMS_PRIVACY_PREFIX: "Lightspeed may collect or access certain payment-related information as described in the platform agreement and";
30
30
  readonly PRIVACY_POLICY_LINK_TEXT: "Privacy Policy";
31
31
  };
32
+ /**
33
+ * Partner card consent text — replaces Stripe's built-in card mandate (whose
34
+ * wording is fixed by Stripe and cannot be customized) with copy the SDK renders
35
+ * itself for partner card payments. `{business}` and `{reason}` are interpolated
36
+ * at render time (reason supplied by the caller, e.g. via
37
+ * `getPartnerCardConsentReason`).
38
+ *
39
+ * NOTE: The SDK does not translate these strings at runtime — they render in
40
+ * English regardless of the session `locale` (which only localizes Stripe's own
41
+ * Element UI). Like the ACH strings above, they are kept as plain constants so
42
+ * they *could* be extracted for Transifex later, but no runtime i18n exists
43
+ * today.
44
+ */
45
+ export declare const PARTNER_CARD_CONSENT_TEXT: {
46
+ readonly MANDATORY_TEMPLATE: "By providing your card information, you authorize {business} to charge your card for {reason} in accordance with their terms.";
47
+ readonly CHECKBOX_TEMPLATE: "By checking the box above, you authorize {business} to charge your card for {reason} in accordance with their terms.";
48
+ };
49
+ /**
50
+ * The configured consent reason for a partner grantor, or `undefined` if the
51
+ * partner has none (in which case no custom card consent is rendered).
52
+ */
53
+ export declare function getPartnerCardConsentReason(grantor?: string): string | undefined;
32
54
  export declare const ACH_TERMS_URL: {
33
55
  readonly STRIPE_ACH_AUTHORIZATION: "https://stripe.com/legal/ach-payments/authorization";
34
56
  readonly PRIVACY_POLICY: "https://www.lightspeedhq.com/legal/privacy-policy/";
@@ -34,6 +34,45 @@ export var ACH_TERMS_TEXT = {
34
34
  EXPANDED_TERMS_PRIVACY_PREFIX: 'Lightspeed may collect or access certain payment-related information as described in the platform agreement and',
35
35
  PRIVACY_POLICY_LINK_TEXT: 'Privacy Policy',
36
36
  };
37
+ /**
38
+ * Partner card consent text — replaces Stripe's built-in card mandate (whose
39
+ * wording is fixed by Stripe and cannot be customized) with copy the SDK renders
40
+ * itself for partner card payments. `{business}` and `{reason}` are interpolated
41
+ * at render time (reason supplied by the caller, e.g. via
42
+ * `getPartnerCardConsentReason`).
43
+ *
44
+ * NOTE: The SDK does not translate these strings at runtime — they render in
45
+ * English regardless of the session `locale` (which only localizes Stripe's own
46
+ * Element UI). Like the ACH strings above, they are kept as plain constants so
47
+ * they *could* be extracted for Transifex later, but no runtime i18n exists
48
+ * today.
49
+ */
50
+ export var PARTNER_CARD_CONSENT_TEXT = {
51
+ // save-card flow: consent given by providing card details.
52
+ MANDATORY_TEMPLATE: 'By providing your card information, you authorize {business} to charge your card for {reason} in accordance with their terms.',
53
+ // pay-and-save flow: consent tied to the save checkbox.
54
+ CHECKBOX_TEMPLATE: 'By checking the box above, you authorize {business} to charge your card for {reason} in accordance with their terms.',
55
+ };
56
+ /**
57
+ * Consent reason per partner grantor — what the saved card may be charged for,
58
+ * keyed by the grantor segment of the product (`partner:{grantor}::...`). Add an
59
+ * entry to offer custom card consent to another partner. Hardcoded for now; may
60
+ * become a per-session input from Processing Service later.
61
+ */
62
+ var PARTNER_CARD_CONSENT_REASONS = {
63
+ golf: 'future payments towards charges related to tee-time bookings and/or house accounts as applicable',
64
+ };
65
+ /**
66
+ * The configured consent reason for a partner grantor, or `undefined` if the
67
+ * partner has none (in which case no custom card consent is rendered).
68
+ */
69
+ export function getPartnerCardConsentReason(grantor) {
70
+ if (grantor &&
71
+ Object.prototype.hasOwnProperty.call(PARTNER_CARD_CONSENT_REASONS, grantor)) {
72
+ return PARTNER_CARD_CONSENT_REASONS[grantor];
73
+ }
74
+ return undefined;
75
+ }
37
76
  export var ACH_TERMS_URL = {
38
77
  STRIPE_ACH_AUTHORIZATION: 'https://stripe.com/legal/ach-payments/authorization',
39
78
  PRIVACY_POLICY: 'https://www.lightspeedhq.com/legal/privacy-policy/',
@@ -34,26 +34,40 @@ var __generator = (this && this.__generator) || function (thisArg, body) {
34
34
  if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
35
35
  }
36
36
  };
37
- import { initStripe, createPaymentElementOptions, createPaymentElement, cleanupElements, createSubmitHandler, setupChangeEventHandler, } from '../shared';
37
+ import { initStripe, createPaymentElementOptions, createPaymentElement, buildCardConsentText, createCardConsentElement, cleanupElements, createSubmitHandler, setupChangeEventHandler, } from '../shared';
38
+ import { getPartnerGrantor } from '../partnerProduct';
39
+ import { getPartnerCardConsentReason } from '../terms';
38
40
  /**
39
41
  * Mount MOTO widget for moto and moto-with-save session types
40
42
  * MOTO (Mail Order/Telephone Order) forms don't require address collection
41
43
  */
42
44
  export function mountMotoWidget(mountElement, session, eventBroadcaster, defaultValues, theme) {
43
45
  return __awaiter(this, void 0, void 0, function () {
44
- var _a, stripe, elements, paymentOptions, _b, paymentElement, paymentContainer, customTermsContainer;
46
+ var _a, stripe, elements, businessName, consentReason, renderPartnerConsent, cardMandate, paymentOptions, _b, paymentElement, paymentContainer, customTermsContainer, cardConsentContainer;
45
47
  return __generator(this, function (_c) {
46
48
  switch (_c.label) {
47
49
  case 0: return [4 /*yield*/, initStripe(session.context, theme)];
48
50
  case 1:
49
51
  _a = _c.sent(), stripe = _a.stripe, elements = _a.elements;
50
- paymentOptions = createPaymentElementOptions(defaultValues, theme, false, session.context.businessName);
52
+ businessName = session.context.businessName;
53
+ consentReason = getPartnerCardConsentReason(getPartnerGrantor(session.metadata.product));
54
+ renderPartnerConsent = session.metadata.sessionType === 'save' &&
55
+ !!businessName &&
56
+ !!consentReason;
57
+ cardMandate = renderPartnerConsent
58
+ ? 'never'
59
+ : undefined;
60
+ paymentOptions = createPaymentElementOptions(defaultValues, theme, false, businessName, cardMandate);
51
61
  _b = createPaymentElement(elements, paymentOptions, mountElement, eventBroadcaster), paymentElement = _b.element, paymentContainer = _b.container, customTermsContainer = _b.customTermsContainer;
62
+ if (renderPartnerConsent) {
63
+ cardConsentContainer = createCardConsentElement(buildCardConsentText(businessName, consentReason, 'mandatory'));
64
+ mountElement.appendChild(cardConsentContainer);
65
+ }
52
66
  // Setup change handler for payment element only (MOTO forms don't have address element)
53
67
  setupChangeEventHandler(paymentElement, eventBroadcaster);
54
68
  return [2 /*return*/, {
55
69
  unmount: function () {
56
- cleanupElements(paymentElement, null, paymentContainer, null, customTermsContainer);
70
+ cleanupElements(paymentElement, null, paymentContainer, null, customTermsContainer, cardConsentContainer);
57
71
  },
58
72
  submit: createSubmitHandler(stripe, elements, session, eventBroadcaster, null),
59
73
  }];
@@ -34,18 +34,22 @@ var __generator = (this && this.__generator) || function (thisArg, body) {
34
34
  if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
35
35
  }
36
36
  };
37
- import { initStripe, createPaymentElementOptions, createAddressElementOptions, createPaymentElement, createAddressElement, cleanupElements, createSubmitHandler, setupChangeEventHandler, } from '../shared';
37
+ import { initStripe, createPaymentElementOptions, createAddressElementOptions, createPaymentElement, createAddressElement, buildCardConsentText, createCardConsentElement, cleanupElements, createSubmitHandler, setupChangeEventHandler, } from '../shared';
38
+ import { getPartnerGrantor } from '../partnerProduct';
39
+ import { getPartnerCardConsentReason } from '../terms';
38
40
  /**
39
41
  * Mount payment widget for payment and payment-with-save session types
40
42
  */
41
43
  export function mountPaymentWidget(mountElement, session, eventBroadcaster, defaultValues, theme) {
42
44
  return __awaiter(this, void 0, void 0, function () {
43
- var _a, stripe, elements, productMetadata, isPartnerProduct, addressElement, addressContainer, addressOptions, created, showCardMandate, paymentOptions, _b, paymentElement, paymentContainer, customTermsContainer;
45
+ var _a, stripe, elements, businessName, isPayWithSave, productMetadata, isPartnerProduct, addressElement, addressContainer, addressOptions, created, consentReason, renderPartnerConsent, cardMandate, paymentOptions, _b, paymentElement, paymentContainer, customTermsContainer, cardConsentContainer;
44
46
  return __generator(this, function (_c) {
45
47
  switch (_c.label) {
46
48
  case 0: return [4 /*yield*/, initStripe(session.context, theme)];
47
49
  case 1:
48
50
  _a = _c.sent(), stripe = _a.stripe, elements = _a.elements;
51
+ businessName = session.context.businessName;
52
+ isPayWithSave = session.metadata.sessionType === 'payment-with-save';
49
53
  productMetadata = session.metadata.product;
50
54
  isPartnerProduct = typeof productMetadata === 'string' &&
51
55
  productMetadata.startsWith('partner:');
@@ -57,16 +61,24 @@ export function mountPaymentWidget(mountElement, session, eventBroadcaster, defa
57
61
  addressElement = created.element;
58
62
  addressContainer = created.container;
59
63
  }
60
- showCardMandate = session.metadata.sessionType === 'payment-with-save' &&
61
- !!session.context.businessName &&
62
- isPartnerProduct;
63
- paymentOptions = createPaymentElementOptions(defaultValues, theme, !!addressElement, session.context.businessName, showCardMandate);
64
+ consentReason = getPartnerCardConsentReason(getPartnerGrantor(productMetadata));
65
+ renderPartnerConsent = isPayWithSave && !!businessName && !!consentReason;
66
+ cardMandate = renderPartnerConsent
67
+ ? 'never'
68
+ : isPayWithSave && !!businessName && isPartnerProduct
69
+ ? 'always'
70
+ : undefined;
71
+ paymentOptions = createPaymentElementOptions(defaultValues, theme, !!addressElement, businessName, cardMandate);
64
72
  _b = createPaymentElement(elements, paymentOptions, mountElement, eventBroadcaster), paymentElement = _b.element, paymentContainer = _b.container, customTermsContainer = _b.customTermsContainer;
73
+ if (renderPartnerConsent) {
74
+ cardConsentContainer = createCardConsentElement(buildCardConsentText(businessName, consentReason, 'checkbox'));
75
+ mountElement.appendChild(cardConsentContainer);
76
+ }
65
77
  // Setup change handler that emits Complete only when both elements are complete
66
78
  setupChangeEventHandler(paymentElement, eventBroadcaster, addressElement);
67
79
  return [2 /*return*/, {
68
80
  unmount: function () {
69
- cleanupElements(paymentElement, addressElement, paymentContainer, addressContainer, customTermsContainer);
81
+ cleanupElements(paymentElement, addressElement, paymentContainer, addressContainer, customTermsContainer, cardConsentContainer);
70
82
  },
71
83
  submit: createSubmitHandler(stripe, elements, session, eventBroadcaster, addressElement),
72
84
  }];
package/dist/version.d.ts CHANGED
@@ -1 +1 @@
1
- export declare const SDK_VERSION = "1.7.1";
1
+ export declare const SDK_VERSION = "1.7.3";
package/dist/version.js CHANGED
@@ -1,3 +1,3 @@
1
1
  // This file is auto-generated during the build process
2
2
  // DO NOT EDIT MANUALLY - Version is extracted from package.json
3
- export var SDK_VERSION = '1.7.1';
3
+ export var SDK_VERSION = '1.7.3';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lightspeed/online-payments-sdk",
3
- "version": "1.7.1",
3
+ "version": "1.7.3",
4
4
  "description": "Process online-payments with Lightspeed Payments",
5
5
  "author": "Lightspeed Commerce Inc.",
6
6
  "license": "SEE LICENSE IN LICENSE.md",
@@ -66,6 +66,24 @@
66
66
  margin-bottom: 0;
67
67
  }
68
68
 
69
+ /* Custom card consent text for partner card payments. Replaces Stripe's
70
+ built-in card mandate (suppressed via terms.card: 'never'). Typography matches
71
+ the ACH custom terms text above. */
72
+
73
+ .stripe-card-consent-container {
74
+ padding: 0;
75
+ }
76
+
77
+ .stripe-card-consent-text {
78
+ margin: 16px 0 0 0;
79
+ font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen,
80
+ Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif;
81
+ font-size: 0.93rem;
82
+ font-weight: 400;
83
+ line-height: 1.5;
84
+ color: #30313d;
85
+ }
86
+
69
87
  /* Invoicing theme: only override font-family to match the Inter font
70
88
  passed to Stripe Elements via the invoicing theme config. */
71
89
 
@@ -74,7 +92,8 @@
74
92
  }
75
93
 
76
94
  .lsp-theme-invoicing .stripe-custom-terms-text,
77
- .lsp-theme-invoicing .stripe-expandable-terms-content p {
95
+ .lsp-theme-invoicing .stripe-expandable-terms-content p,
96
+ .lsp-theme-invoicing .stripe-card-consent-text {
78
97
  font-family: 'Inter', system-ui, sans-serif;
79
98
  }
80
99