@lightspeed/online-payments-sdk 1.7.3 → 1.9.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 +37 -0
- package/dist/cjs/index.js +4 -1
- package/dist/cjs/v1/EventBroadcaster.js +1 -0
- package/dist/cjs/v1/adyen/terms.js +16 -0
- package/dist/cjs/v1/adyen/widget.js +216 -9
- package/dist/cjs/v1/index.js +1 -0
- package/dist/cjs/v1/stripe/localizedText.js +32 -0
- package/dist/cjs/v1/stripe/session.js +9 -0
- package/dist/cjs/v1/stripe/shared.js +55 -14
- package/dist/cjs/v1/stripe/terms.js +1 -1
- package/dist/cjs/v1/stripe/themes.js +2 -2
- package/dist/cjs/v1/stripe/widget.js +64 -25
- package/dist/cjs/v1/stripe/widgets/deferredMoto.js +203 -0
- package/dist/cjs/v1/widget.js +83 -2
- package/dist/cjs/version.js +1 -1
- package/dist/index.d.ts +3 -0
- package/dist/index.js +3 -0
- package/dist/v1/EventBroadcaster.d.ts +18 -1
- package/dist/v1/EventBroadcaster.js +1 -0
- package/dist/v1/adyen/session.d.ts +6 -3
- package/dist/v1/adyen/terms.d.ts +5 -0
- package/dist/v1/adyen/terms.js +12 -0
- package/dist/v1/adyen/widget.d.ts +9 -2
- package/dist/v1/adyen/widget.js +216 -9
- package/dist/v1/common.d.ts +30 -2
- package/dist/v1/index.d.ts +12 -3
- package/dist/v1/index.js +2 -1
- package/dist/v1/stripe/localizedText.d.ts +3 -0
- package/dist/v1/stripe/localizedText.js +28 -0
- package/dist/v1/stripe/session.d.ts +29 -6
- package/dist/v1/stripe/session.js +7 -1
- package/dist/v1/stripe/shared.d.ts +8 -5
- package/dist/v1/stripe/shared.js +55 -15
- package/dist/v1/stripe/terms.d.ts +1 -1
- package/dist/v1/stripe/terms.js +1 -1
- package/dist/v1/stripe/themes.js +2 -2
- package/dist/v1/stripe/widget.js +62 -23
- package/dist/v1/stripe/widgets/deferredMoto.d.ts +5 -0
- package/dist/v1/stripe/widgets/deferredMoto.js +200 -0
- package/dist/v1/stripe/widgets/moto.d.ts +2 -2
- package/dist/v1/stripe/widgets/payment.d.ts +2 -2
- package/dist/v1/widget.d.ts +8 -1
- package/dist/v1/widget.js +82 -2
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +8 -3
- package/styles/lightspeed-global-styles.css +81 -1
package/README.md
CHANGED
|
@@ -31,6 +31,7 @@ Mount the widget with the payment session from your integration:
|
|
|
31
31
|
|
|
32
32
|
```ts
|
|
33
33
|
import {LightspeedPayments} from '@lightspeed/online-payments-sdk';
|
|
34
|
+
import '@lightspeed/online-payments-sdk/styles/lightspeed-global-styles.css';
|
|
34
35
|
|
|
35
36
|
const mountPoint = document.getElementById('payment-widget');
|
|
36
37
|
|
|
@@ -109,6 +110,23 @@ submitButton.addEventListener('click', async () => {
|
|
|
109
110
|
controller.unmount();
|
|
110
111
|
```
|
|
111
112
|
|
|
113
|
+
`submit()` returns `Promise<WidgetSubmitResult>`. Existing intent-bound Stripe
|
|
114
|
+
and Adyen sessions retain their runtime behavior, but TypeScript integrations
|
|
115
|
+
that explicitly treat the submit result as `Event` must first handle or exclude
|
|
116
|
+
the new `RequiresFinalization` status. Listener callbacks are unchanged and
|
|
117
|
+
continue to receive only `Event`.
|
|
118
|
+
|
|
119
|
+
### Deferred MOTO payments
|
|
120
|
+
|
|
121
|
+
Deferred Stripe `moto` and `moto-with-save` sessions return a
|
|
122
|
+
`RequiresFinalization` result for backend finalization instead of reporting
|
|
123
|
+
payment success. Integrations opting into this mode must forward the returned
|
|
124
|
+
artifact unchanged and handle definitive declines through
|
|
125
|
+
`reportFinalizationDecline`.
|
|
126
|
+
|
|
127
|
+
The complete [deferred Stripe MOTO integration guide](https://github.com/lightspeed-payments/lsp-online-payments-sdk/blob/main/packages/lsp-online-payments-sdk/docs/deferred-stripe-moto.md)
|
|
128
|
+
is maintained in the GitHub repository and is not included in the npm package.
|
|
129
|
+
|
|
112
130
|
## Theming
|
|
113
131
|
|
|
114
132
|
Use `theme` to select a widget appearance:
|
|
@@ -133,3 +151,22 @@ import {THEME_COLORS} from '@lightspeed/online-payments-sdk';
|
|
|
133
151
|
wrapper.style.backgroundColor = THEME_COLORS.DARK.BACKGROUND;
|
|
134
152
|
wrapper.style.color = THEME_COLORS.DARK.TEXT;
|
|
135
153
|
```
|
|
154
|
+
|
|
155
|
+
## Checking the SDK version
|
|
156
|
+
|
|
157
|
+
The running SDK version is available at runtime, matching the version published to npm:
|
|
158
|
+
|
|
159
|
+
```ts
|
|
160
|
+
import {LightspeedPayments, SDK_VERSION} from '@lightspeed/online-payments-sdk';
|
|
161
|
+
|
|
162
|
+
console.log(LightspeedPayments.version); // e.g. "1.8.0"
|
|
163
|
+
console.log(SDK_VERSION); // e.g. "1.8.0"
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
While a widget is mounted, its mount element also carries a `data-lightspeed-payments-sdk-version` attribute, so the running version can be inspected directly in browser devtools without any application code:
|
|
167
|
+
|
|
168
|
+
```html
|
|
169
|
+
<div id="payment-widget" data-lightspeed-payments-sdk-version="1.8.0"></div>
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
The attribute is removed when `controller.unmount()` is called.
|
package/dist/cjs/index.js
CHANGED
|
@@ -1,9 +1,12 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.LightspeedPayments = exports.THEME_COLORS = void 0;
|
|
3
|
+
exports.LightspeedPayments = exports.SDK_VERSION = exports.THEME_COLORS = void 0;
|
|
4
4
|
var v1_1 = require("./v1");
|
|
5
|
+
var version_1 = require("./version");
|
|
6
|
+
Object.defineProperty(exports, "SDK_VERSION", { enumerable: true, get: function () { return version_1.SDK_VERSION; } });
|
|
5
7
|
var v1_2 = require("./v1");
|
|
6
8
|
Object.defineProperty(exports, "THEME_COLORS", { enumerable: true, get: function () { return v1_2.THEME_COLORS; } });
|
|
7
9
|
exports.LightspeedPayments = {
|
|
8
10
|
v1: v1_1.v1,
|
|
11
|
+
version: version_1.SDK_VERSION,
|
|
9
12
|
};
|
|
@@ -66,6 +66,7 @@ var EventBroadcaster = /** @class */ (function () {
|
|
|
66
66
|
var processedEvent = this.applyMiddlewares(event);
|
|
67
67
|
var eventListener = this.listenersRegistry[event.status];
|
|
68
68
|
eventListener(processedEvent);
|
|
69
|
+
return processedEvent;
|
|
69
70
|
};
|
|
70
71
|
return EventBroadcaster;
|
|
71
72
|
}());
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.NO_SHOW_CONSENT_REASON = exports.NO_SHOW_CONSENT_TEXT = void 0;
|
|
4
|
+
exports.buildNoShowConsentText = buildNoShowConsentText;
|
|
5
|
+
// SDK-owned consent copy for the card-save (no-show) flow — the SDK owns the
|
|
6
|
+
// wording rather than taking free-form text from the backend (mirrors
|
|
7
|
+
// `PARTNER_CARD_CONSENT_TEXT` in `stripe/terms.ts`). Plain constants, so they can
|
|
8
|
+
// be extracted for Transifex later. `{business}`/`{reason}` interpolated at render.
|
|
9
|
+
exports.NO_SHOW_CONSENT_TEXT = {
|
|
10
|
+
MANDATORY_TEMPLATE: 'By providing your card information, you authorize {business} to charge your card for {reason} in accordance with their terms.',
|
|
11
|
+
};
|
|
12
|
+
// Hardcoded for now; may become a per-session input from the backend later.
|
|
13
|
+
exports.NO_SHOW_CONSENT_REASON = 'a no-show fee if you do not honor your reservation';
|
|
14
|
+
function buildNoShowConsentText(businessName) {
|
|
15
|
+
return exports.NO_SHOW_CONSENT_TEXT.MANDATORY_TEMPLATE.replace(/\{business\}/g, function () { return businessName; }).replace(/\{reason\}/g, function () { return exports.NO_SHOW_CONSENT_REASON; });
|
|
16
|
+
}
|
|
@@ -39,13 +39,31 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
39
39
|
exports.AdyenWidget = void 0;
|
|
40
40
|
var adyen_web_1 = require("@adyen/adyen-web");
|
|
41
41
|
var ResultBuilder_1 = require("./ResultBuilder");
|
|
42
|
+
var terms_1 = require("./terms");
|
|
42
43
|
function mount(mountElement, session, eventBroadcaster) {
|
|
44
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
45
|
+
return __generator(this, function (_a) {
|
|
46
|
+
return [2 /*return*/, mountSessionsFlow(mountElement, session.context, eventBroadcaster)];
|
|
47
|
+
});
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
// Entry for the multi-step contract (v1.mountMultiStepWidget). Kept separate
|
|
51
|
+
// from `mount` so the event-based Sessions flow keeps its WidgetController shape.
|
|
52
|
+
function mountMultiStep(mountElement, session, eventBroadcaster, onRequiresFinalization) {
|
|
53
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
54
|
+
return __generator(this, function (_a) {
|
|
55
|
+
return [2 /*return*/, mountAdvancedFlow(mountElement, session.context, eventBroadcaster, onRequiresFinalization)];
|
|
56
|
+
});
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
function mountSessionsFlow(mountElement, context, eventBroadcaster) {
|
|
43
60
|
return __awaiter(this, void 0, void 0, function () {
|
|
44
61
|
var checkoutConfig, checkout, dropinConfiguration, dropIn;
|
|
45
62
|
return __generator(this, function (_a) {
|
|
46
63
|
switch (_a.label) {
|
|
47
64
|
case 0:
|
|
48
|
-
|
|
65
|
+
injectAdyenCssModuleFix();
|
|
66
|
+
checkoutConfig = createSessionsConfiguration(context, eventBroadcaster);
|
|
49
67
|
return [4 /*yield*/, (0, adyen_web_1.AdyenCheckout)(checkoutConfig)];
|
|
50
68
|
case 1:
|
|
51
69
|
checkout = _a.sent();
|
|
@@ -66,7 +84,163 @@ function mount(mountElement, session, eventBroadcaster) {
|
|
|
66
84
|
});
|
|
67
85
|
});
|
|
68
86
|
}
|
|
69
|
-
|
|
87
|
+
// Multi-step Advanced flow: submit() surfaces the encrypted payment data for
|
|
88
|
+
// the host to POST; handleNextAction() feeds the server response back to drive
|
|
89
|
+
// native 3DS2. See MultiStepController in common.ts.
|
|
90
|
+
function mountAdvancedFlow(mountElement, context, eventBroadcaster, onRequiresFinalization) {
|
|
91
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
92
|
+
var stashedActions, pendingResolve, isValid, checkoutConfig, checkout, dropinConfiguration, dropIn;
|
|
93
|
+
var _a;
|
|
94
|
+
return __generator(this, function (_b) {
|
|
95
|
+
switch (_b.label) {
|
|
96
|
+
case 0:
|
|
97
|
+
isValid = false;
|
|
98
|
+
checkoutConfig = {
|
|
99
|
+
clientKey: context.clientKey,
|
|
100
|
+
environment: context.env,
|
|
101
|
+
countryCode: context.countryCode,
|
|
102
|
+
locale: context.locale,
|
|
103
|
+
amount: { value: (_a = context.amount) !== null && _a !== void 0 ? _a : 0, currency: context.currency },
|
|
104
|
+
paymentMethodsResponse: context.paymentMethods,
|
|
105
|
+
analytics: { enabled: false },
|
|
106
|
+
onSubmit: function (state, _component, actions) {
|
|
107
|
+
stashedActions = actions;
|
|
108
|
+
var result = {
|
|
109
|
+
status: 'RequiresFinalization',
|
|
110
|
+
paymentData: {
|
|
111
|
+
paymentMethod: state.data.paymentMethod,
|
|
112
|
+
browserInfo: state.data.browserInfo,
|
|
113
|
+
origin: window.location.origin,
|
|
114
|
+
},
|
|
115
|
+
saveSessionId: context.saveSessionId,
|
|
116
|
+
};
|
|
117
|
+
if (pendingResolve) {
|
|
118
|
+
pendingResolve(result);
|
|
119
|
+
pendingResolve = undefined;
|
|
120
|
+
}
|
|
121
|
+
else {
|
|
122
|
+
// Express methods (Google Pay / Apple Pay) fire onSubmit from their own
|
|
123
|
+
// button with no submit() pending — hand the result to the host instead.
|
|
124
|
+
onRequiresFinalization === null || onRequiresFinalization === void 0 ? void 0 : onRequiresFinalization(result);
|
|
125
|
+
}
|
|
126
|
+
},
|
|
127
|
+
onAdditionalDetails: function (state, _component, actions) {
|
|
128
|
+
stashedActions = actions;
|
|
129
|
+
pendingResolve === null || pendingResolve === void 0 ? void 0 : pendingResolve({
|
|
130
|
+
status: 'RequiresAction',
|
|
131
|
+
paymentData: {
|
|
132
|
+
details: state.data.details,
|
|
133
|
+
paymentData: state.data.paymentData,
|
|
134
|
+
},
|
|
135
|
+
saveSessionId: context.saveSessionId,
|
|
136
|
+
});
|
|
137
|
+
pendingResolve = undefined;
|
|
138
|
+
},
|
|
139
|
+
onError: function (error) {
|
|
140
|
+
// Resolve a waiting submit()/handleNextAction() so the host doesn't hang.
|
|
141
|
+
if (pendingResolve) {
|
|
142
|
+
pendingResolve({ status: 'Error', error: error });
|
|
143
|
+
pendingResolve = undefined;
|
|
144
|
+
return;
|
|
145
|
+
}
|
|
146
|
+
eventBroadcaster.publish({
|
|
147
|
+
status: 'Error',
|
|
148
|
+
code: 'Processing',
|
|
149
|
+
loggingEnrichment: error,
|
|
150
|
+
});
|
|
151
|
+
},
|
|
152
|
+
// Surface form validity so the host can gate its own submit button; onSubmit
|
|
153
|
+
// never fires for an invalid form, so this is the host's only validity signal.
|
|
154
|
+
onChange: function (state) {
|
|
155
|
+
var _a;
|
|
156
|
+
isValid = state.isValid;
|
|
157
|
+
var paymentMethodType = (_a = state.data.paymentMethod) === null || _a === void 0 ? void 0 : _a.type;
|
|
158
|
+
eventBroadcaster.publish({
|
|
159
|
+
status: 'Change',
|
|
160
|
+
code: isValid ? 'Complete' : 'Incomplete',
|
|
161
|
+
paymentMethodType: typeof paymentMethodType === 'string' ? paymentMethodType : undefined,
|
|
162
|
+
});
|
|
163
|
+
},
|
|
164
|
+
};
|
|
165
|
+
injectAdyenCssModuleFix();
|
|
166
|
+
return [4 /*yield*/, (0, adyen_web_1.AdyenCheckout)(checkoutConfig)];
|
|
167
|
+
case 1:
|
|
168
|
+
checkout = _b.sent();
|
|
169
|
+
dropinConfiguration = {
|
|
170
|
+
paymentMethodComponents: [adyen_web_1.Card, adyen_web_1.ApplePay, adyen_web_1.GooglePay, adyen_web_1.Bancontact],
|
|
171
|
+
showStoredPaymentMethods: false,
|
|
172
|
+
paymentMethodsConfiguration: {
|
|
173
|
+
card: {
|
|
174
|
+
// Hide the card's built-in button (host renders its own submit). In
|
|
175
|
+
// adyen-web v6 showPayButton is per-component, not Dropin-level. Express
|
|
176
|
+
// wallets keep their native buttons.
|
|
177
|
+
showPayButton: false,
|
|
178
|
+
// Suppress Click to Pay in a zero-value card-save. `_disableClickToPay`
|
|
179
|
+
// is an internal adyen-web flag; replace on the next upgrade.
|
|
180
|
+
_disableClickToPay: true,
|
|
181
|
+
},
|
|
182
|
+
},
|
|
183
|
+
// Render the consent copy only once the Drop-in has finished loading, so it
|
|
184
|
+
// doesn't flash on its own before the card/wallet options appear.
|
|
185
|
+
onReady: function () { return renderConsentDisclosure(mountElement, context.businessName); },
|
|
186
|
+
};
|
|
187
|
+
dropIn = new adyen_web_1.Dropin(checkout, dropinConfiguration).mount(mountElement);
|
|
188
|
+
return [2 /*return*/, {
|
|
189
|
+
unmount: function () {
|
|
190
|
+
dropIn.unmount();
|
|
191
|
+
removeConsentDisclosure(mountElement);
|
|
192
|
+
},
|
|
193
|
+
submit: function () {
|
|
194
|
+
return new Promise(function (resolve) {
|
|
195
|
+
// adyen-web renders inline field errors but never calls onSubmit for an
|
|
196
|
+
// invalid form, so waiting on pendingResolve would hang the host. Trigger
|
|
197
|
+
// the field errors and settle deterministically instead.
|
|
198
|
+
if (!isValid) {
|
|
199
|
+
dropIn.submit();
|
|
200
|
+
resolve({ status: 'Invalid' });
|
|
201
|
+
return;
|
|
202
|
+
}
|
|
203
|
+
pendingResolve = resolve;
|
|
204
|
+
dropIn.submit();
|
|
205
|
+
});
|
|
206
|
+
},
|
|
207
|
+
handleNextAction: function (serverResponse) {
|
|
208
|
+
return new Promise(function (resolve) {
|
|
209
|
+
var _a;
|
|
210
|
+
var response = (serverResponse !== null && serverResponse !== void 0 ? serverResponse : {});
|
|
211
|
+
if (response.action) {
|
|
212
|
+
// 3DS1 (redirect) is out of scope: surface as an error so the host can
|
|
213
|
+
// ask the shopper for a different card.
|
|
214
|
+
if (response.action.type === 'redirect') {
|
|
215
|
+
resolve({
|
|
216
|
+
status: 'Error',
|
|
217
|
+
error: { code: 'RedirectNotSupported', resultCode: response.resultCode },
|
|
218
|
+
});
|
|
219
|
+
return;
|
|
220
|
+
}
|
|
221
|
+
// Native 3DS2 step: let the component perform it, then resolve once
|
|
222
|
+
// onAdditionalDetails hands us the next payload for the host to POST.
|
|
223
|
+
pendingResolve = resolve;
|
|
224
|
+
stashedActions === null || stashedActions === void 0 ? void 0 : stashedActions.resolve(response);
|
|
225
|
+
return;
|
|
226
|
+
}
|
|
227
|
+
// Terminal response: let the component finalize its UI (its own result
|
|
228
|
+
// screen), drop the now-stale pre-submission consent, report Complete.
|
|
229
|
+
stashedActions === null || stashedActions === void 0 ? void 0 : stashedActions.resolve(response);
|
|
230
|
+
removeConsentDisclosure(mountElement);
|
|
231
|
+
resolve({ status: 'Complete', resultCode: (_a = response.resultCode) !== null && _a !== void 0 ? _a : 'Unknown' });
|
|
232
|
+
});
|
|
233
|
+
},
|
|
234
|
+
}];
|
|
235
|
+
}
|
|
236
|
+
});
|
|
237
|
+
});
|
|
238
|
+
}
|
|
239
|
+
function createSessionsConfiguration(context, eventBroadcaster) {
|
|
240
|
+
var _a;
|
|
241
|
+
if (!context.sessionId || !context.sessionData) {
|
|
242
|
+
throw new Error('Sessions flow requires sessionId and sessionData; received an advanced-flow session.');
|
|
243
|
+
}
|
|
70
244
|
return {
|
|
71
245
|
clientKey: context.clientKey,
|
|
72
246
|
session: {
|
|
@@ -74,15 +248,10 @@ function createAdyenConfiguration(context, eventBroadcaster) {
|
|
|
74
248
|
sessionData: context.sessionData,
|
|
75
249
|
},
|
|
76
250
|
countryCode: context.countryCode,
|
|
77
|
-
amount: {
|
|
78
|
-
value: context.amount,
|
|
79
|
-
currency: context.currency,
|
|
80
|
-
},
|
|
251
|
+
amount: { value: (_a = context.amount) !== null && _a !== void 0 ? _a : 0, currency: context.currency },
|
|
81
252
|
locale: context.locale,
|
|
82
253
|
environment: context.env,
|
|
83
|
-
analytics: {
|
|
84
|
-
enabled: false,
|
|
85
|
-
},
|
|
254
|
+
analytics: { enabled: false },
|
|
86
255
|
onPaymentCompleted: function (data) {
|
|
87
256
|
eventBroadcaster.publish(ResultBuilder_1.ResultBuilder.fromPaymentCompletedData(data));
|
|
88
257
|
},
|
|
@@ -99,6 +268,43 @@ function createAdyenConfiguration(context, eventBroadcaster) {
|
|
|
99
268
|
paymentMethodsResponse: context.paymentMethods,
|
|
100
269
|
};
|
|
101
270
|
}
|
|
271
|
+
// Appends the SDK-owned no-show consent copy under the Drop-in. Idempotent, so
|
|
272
|
+
// a repeated onReady never duplicates it; a no-op when no business name is set.
|
|
273
|
+
function renderConsentDisclosure(mountElement, businessName) {
|
|
274
|
+
if (!businessName)
|
|
275
|
+
return;
|
|
276
|
+
if (mountElement.querySelector('[data-lspay="consent-disclosure"]'))
|
|
277
|
+
return;
|
|
278
|
+
var disclosure = document.createElement('p');
|
|
279
|
+
disclosure.setAttribute('data-lspay', 'consent-disclosure');
|
|
280
|
+
disclosure.style.marginTop = '16px';
|
|
281
|
+
disclosure.textContent = (0, terms_1.buildNoShowConsentText)(businessName);
|
|
282
|
+
mountElement.appendChild(disclosure);
|
|
283
|
+
}
|
|
284
|
+
// Removes the consent copy once the flow finalizes or unmounts, so it doesn't
|
|
285
|
+
// linger on the Drop-in's result screen (it only applies pre-submission).
|
|
286
|
+
function removeConsentDisclosure(mountElement) {
|
|
287
|
+
var _a;
|
|
288
|
+
(_a = mountElement.querySelector('[data-lspay="consent-disclosure"]')) === null || _a === void 0 ? void 0 : _a.remove();
|
|
289
|
+
}
|
|
290
|
+
// Adyen's Drop-in CSS uses hashed class names (e.g. .loading-input__spinner--abc123),
|
|
291
|
+
// but when the host app's bundler processes the CSS as modules it rehashes them,
|
|
292
|
+
// causing a mismatch with the unhashed class names Adyen writes to the DOM.
|
|
293
|
+
// We inject plain (unhashed) rules so the spinner/loading states render correctly.
|
|
294
|
+
var adyenCssFixInjected = false;
|
|
295
|
+
function injectAdyenCssModuleFix() {
|
|
296
|
+
if (adyenCssFixInjected)
|
|
297
|
+
return;
|
|
298
|
+
adyenCssFixInjected = true;
|
|
299
|
+
var style = document.createElement('style');
|
|
300
|
+
style.setAttribute('data-lspay', 'adyen-css-module-fix');
|
|
301
|
+
style.textContent = [
|
|
302
|
+
".loading-input__spinner { z-index: 1; width: 100%; height: 100%; display: none; position: absolute; top: 0; left: 0; }",
|
|
303
|
+
".loading-input__spinner--active { display: flex; align-items: center; justify-content: center; }",
|
|
304
|
+
".loading-input__form--loading { opacity: 0; }",
|
|
305
|
+
].join('\n');
|
|
306
|
+
document.head.appendChild(style);
|
|
307
|
+
}
|
|
102
308
|
function createDropinConfiguration() {
|
|
103
309
|
return {
|
|
104
310
|
paymentMethodComponents: [adyen_web_1.Card, adyen_web_1.ApplePay, adyen_web_1.Bancontact, adyen_web_1.GooglePay, adyen_web_1.Redirect, adyen_web_1.Twint],
|
|
@@ -106,4 +312,5 @@ function createDropinConfiguration() {
|
|
|
106
312
|
}
|
|
107
313
|
exports.AdyenWidget = {
|
|
108
314
|
mount: mount,
|
|
315
|
+
mountMultiStep: mountMultiStep,
|
|
109
316
|
};
|
package/dist/cjs/v1/index.js
CHANGED
|
@@ -17,4 +17,5 @@ var themes_1 = require("./stripe/themes");
|
|
|
17
17
|
Object.defineProperty(exports, "THEME_COLORS", { enumerable: true, get: function () { return themes_1.THEME_COLORS; } });
|
|
18
18
|
exports.v1 = {
|
|
19
19
|
mountPaymentWidget: widget_1.mountPaymentWidget,
|
|
20
|
+
mountMultiStepWidget: widget_1.mountMultiStepWidget,
|
|
20
21
|
};
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/** Locale-selected UI text rendered alongside Stripe Elements. */
|
|
3
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
|
+
exports.getSavePaymentMethodText = getSavePaymentMethodText;
|
|
5
|
+
exports.getCardDeclinedText = getCardDeclinedText;
|
|
6
|
+
var SAVE_PAYMENT_METHOD_TEXT = {
|
|
7
|
+
de: 'Zahlungsinformationen für zukünftige Einkäufe speichern',
|
|
8
|
+
en: 'Save payment details for future purchases',
|
|
9
|
+
fr: 'Enregistrer les informations de paiement pour vos prochains achats',
|
|
10
|
+
nl: 'Betaalgegevens opslaan voor toekomstige aankopen',
|
|
11
|
+
};
|
|
12
|
+
var CARD_DECLINED_TEXT = {
|
|
13
|
+
de: 'Ihre Karte wurde abgelehnt.',
|
|
14
|
+
en: 'Your card was declined.',
|
|
15
|
+
fr: 'Votre carte a été refusée.',
|
|
16
|
+
nl: 'Uw kaart is geweigerd.',
|
|
17
|
+
};
|
|
18
|
+
function getLanguage(locale) {
|
|
19
|
+
var _a;
|
|
20
|
+
var resolvedLocale = !locale || locale === 'auto'
|
|
21
|
+
? ((_a = globalThis.navigator) === null || _a === void 0 ? void 0 : _a.language) || 'en'
|
|
22
|
+
: locale;
|
|
23
|
+
return resolvedLocale.toLowerCase().split('-')[0];
|
|
24
|
+
}
|
|
25
|
+
function getSavePaymentMethodText(locale) {
|
|
26
|
+
var language = getLanguage(locale);
|
|
27
|
+
return SAVE_PAYMENT_METHOD_TEXT[language] || SAVE_PAYMENT_METHOD_TEXT.en;
|
|
28
|
+
}
|
|
29
|
+
function getCardDeclinedText(locale) {
|
|
30
|
+
var language = getLanguage(locale);
|
|
31
|
+
return CARD_DECLINED_TEXT[language] || CARD_DECLINED_TEXT.en;
|
|
32
|
+
}
|
|
@@ -1,2 +1,11 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.isDeferredStripeSession = isDeferredStripeSession;
|
|
4
|
+
exports.isIntentBoundStripeSession = isIntentBoundStripeSession;
|
|
5
|
+
function isDeferredStripeSession(session) {
|
|
6
|
+
return session.context.intentMode === 'deferred';
|
|
7
|
+
}
|
|
8
|
+
function isIntentBoundStripeSession(session) {
|
|
9
|
+
return (session.context.intentMode === undefined ||
|
|
10
|
+
session.context.intentMode === 'intent-bound');
|
|
11
|
+
}
|
|
@@ -52,6 +52,7 @@ exports.createPaymentElementOptions = createPaymentElementOptions;
|
|
|
52
52
|
exports.createAddressElementOptions = createAddressElementOptions;
|
|
53
53
|
exports.buildCardConsentText = buildCardConsentText;
|
|
54
54
|
exports.createCardConsentElement = createCardConsentElement;
|
|
55
|
+
exports.createSavePaymentMethodElement = createSavePaymentMethodElement;
|
|
55
56
|
exports.createPaymentElement = createPaymentElement;
|
|
56
57
|
exports.setupChangeEventHandler = setupChangeEventHandler;
|
|
57
58
|
exports.createAddressElement = createAddressElement;
|
|
@@ -64,16 +65,17 @@ var ResultBuilder_1 = require("./ResultBuilder");
|
|
|
64
65
|
var error_1 = require("../error");
|
|
65
66
|
var themes_1 = require("./themes");
|
|
66
67
|
var terms_1 = require("./terms");
|
|
68
|
+
var localizedText_1 = require("./localizedText");
|
|
67
69
|
/**
|
|
68
70
|
* Initialize Stripe with the given context
|
|
69
71
|
*/
|
|
70
72
|
function initStripe(context, theme) {
|
|
71
73
|
return __awaiter(this, void 0, void 0, function () {
|
|
72
|
-
var publishableKey,
|
|
74
|
+
var publishableKey, loadedStripe, stripe, themeConfig, sharedElementsOptions, elements, elementsOptions, elementsOptions;
|
|
73
75
|
return __generator(this, function (_a) {
|
|
74
76
|
switch (_a.label) {
|
|
75
77
|
case 0:
|
|
76
|
-
publishableKey = context.publishableKey
|
|
78
|
+
publishableKey = context.publishableKey;
|
|
77
79
|
return [4 /*yield*/, (0, stripe_js_1.loadStripe)(publishableKey)];
|
|
78
80
|
case 1:
|
|
79
81
|
loadedStripe = _a.sent();
|
|
@@ -82,8 +84,15 @@ function initStripe(context, theme) {
|
|
|
82
84
|
}
|
|
83
85
|
stripe = loadedStripe;
|
|
84
86
|
themeConfig = (0, themes_1.getThemeConfig)(theme);
|
|
85
|
-
|
|
86
|
-
|
|
87
|
+
sharedElementsOptions = __assign(__assign(__assign({}, (context.locale && { locale: context.locale })), (themeConfig && { appearance: themeConfig.appearance })), (themeConfig && { fonts: themeConfig.fonts }));
|
|
88
|
+
if (context.intentMode === 'deferred') {
|
|
89
|
+
elementsOptions = __assign(__assign(__assign({}, sharedElementsOptions), { mode: 'payment', amount: context.amount, currency: context.currency.toLowerCase(), paymentMethodTypes: context.paymentMethodTypes, paymentMethodCreation: 'manual' }), (context.onBehalfOf && { onBehalfOf: context.onBehalfOf }));
|
|
90
|
+
elements = stripe.elements(elementsOptions);
|
|
91
|
+
}
|
|
92
|
+
else {
|
|
93
|
+
elementsOptions = __assign(__assign({}, sharedElementsOptions), { clientSecret: context.clientSecret, customerSessionClientSecret: context.customerSessionClientSecret });
|
|
94
|
+
elements = stripe.elements(elementsOptions);
|
|
95
|
+
}
|
|
87
96
|
return [2 /*return*/, { stripe: stripe, elements: elements }];
|
|
88
97
|
}
|
|
89
98
|
});
|
|
@@ -220,6 +229,24 @@ function createCardConsentElement(consentText) {
|
|
|
220
229
|
container.appendChild(text);
|
|
221
230
|
return container;
|
|
222
231
|
}
|
|
232
|
+
function createSavePaymentMethodElement(mountElement, onChange, locale) {
|
|
233
|
+
var label = document.createElement('label');
|
|
234
|
+
label.className = 'stripe-save-payment-method-container';
|
|
235
|
+
var checkbox = document.createElement('input');
|
|
236
|
+
checkbox.type = 'checkbox';
|
|
237
|
+
checkbox.className = 'stripe-save-payment-method-checkbox';
|
|
238
|
+
checkbox.dataset.testid = 'save-payment-method-checkbox';
|
|
239
|
+
var text = document.createElement('span');
|
|
240
|
+
text.className = 'stripe-save-payment-method-text';
|
|
241
|
+
text.textContent = (0, localizedText_1.getSavePaymentMethodText)(locale);
|
|
242
|
+
label.appendChild(checkbox);
|
|
243
|
+
label.appendChild(text);
|
|
244
|
+
mountElement.appendChild(label);
|
|
245
|
+
// The label must remain clickable, but its consent text is not selectable.
|
|
246
|
+
label.addEventListener('selectstart', function (event) { return event.preventDefault(); });
|
|
247
|
+
checkbox.addEventListener('change', function () { return onChange(checkbox.checked); });
|
|
248
|
+
return label;
|
|
249
|
+
}
|
|
223
250
|
/**
|
|
224
251
|
* Create and mount payment element
|
|
225
252
|
*/
|
|
@@ -259,12 +286,12 @@ function createPaymentElement(elements, options, mountElement, eventBroadcaster)
|
|
|
259
286
|
* Also includes the current save-payment-method checkbox state (when present) on every Change event,
|
|
260
287
|
* and emits a Change event when that checkbox state changes.
|
|
261
288
|
*/
|
|
262
|
-
function setupChangeEventHandler(paymentElement, eventBroadcaster, addressElement) {
|
|
289
|
+
function setupChangeEventHandler(paymentElement, eventBroadcaster, addressElement, onPaymentValueChange, initialSaveCheckboxState) {
|
|
263
290
|
var paymentComplete = false;
|
|
264
291
|
var addressComplete = !addressElement; // If no address element, consider it complete
|
|
265
292
|
var previousComplete = null;
|
|
266
293
|
var previousMethodType;
|
|
267
|
-
var previousSaveCheckboxState
|
|
294
|
+
var previousSaveCheckboxState = initialSaveCheckboxState;
|
|
268
295
|
var emitChangeEvent = function () {
|
|
269
296
|
var complete = paymentComplete && addressComplete;
|
|
270
297
|
previousComplete = complete;
|
|
@@ -275,23 +302,30 @@ function setupChangeEventHandler(paymentElement, eventBroadcaster, addressElemen
|
|
|
275
302
|
})));
|
|
276
303
|
};
|
|
277
304
|
paymentElement.on('change', function (event) {
|
|
278
|
-
var _a, _b;
|
|
305
|
+
var _a, _b, _c;
|
|
279
306
|
paymentComplete = event.complete;
|
|
307
|
+
onPaymentValueChange === null || onPaymentValueChange === void 0 ? void 0 : onPaymentValueChange({
|
|
308
|
+
savePaymentMethod: (_a = event.value) === null || _a === void 0 ? void 0 : _a.savePaymentMethod,
|
|
309
|
+
});
|
|
280
310
|
var completenessChanged = (paymentComplete && addressComplete) !== previousComplete;
|
|
281
|
-
var methodType = (
|
|
311
|
+
var methodType = (_b = event.value) === null || _b === void 0 ? void 0 : _b.type;
|
|
282
312
|
var methodTypeChanged = methodType !== undefined && methodType !== previousMethodType;
|
|
283
313
|
if (methodType !== undefined) {
|
|
284
314
|
previousMethodType = methodType;
|
|
285
315
|
}
|
|
286
316
|
// `savePaymentMethod` reflects the "save for future use" checkbox; it is only
|
|
287
317
|
// present on the change event when the element renders that checkbox.
|
|
288
|
-
var
|
|
289
|
-
var
|
|
290
|
-
if (
|
|
291
|
-
|
|
292
|
-
|
|
318
|
+
var stripeSaveCheckboxChanged = false;
|
|
319
|
+
var stripeSaveCheckboxState = (_c = event.value) === null || _c === void 0 ? void 0 : _c.savePaymentMethod;
|
|
320
|
+
if (initialSaveCheckboxState === undefined &&
|
|
321
|
+
stripeSaveCheckboxState !== undefined) {
|
|
322
|
+
stripeSaveCheckboxChanged =
|
|
323
|
+
previousSaveCheckboxState !== stripeSaveCheckboxState;
|
|
324
|
+
previousSaveCheckboxState = stripeSaveCheckboxState;
|
|
293
325
|
}
|
|
294
|
-
if (completenessChanged ||
|
|
326
|
+
if (completenessChanged ||
|
|
327
|
+
methodTypeChanged ||
|
|
328
|
+
stripeSaveCheckboxChanged) {
|
|
295
329
|
emitChangeEvent();
|
|
296
330
|
}
|
|
297
331
|
});
|
|
@@ -304,6 +338,13 @@ function setupChangeEventHandler(paymentElement, eventBroadcaster, addressElemen
|
|
|
304
338
|
}
|
|
305
339
|
});
|
|
306
340
|
}
|
|
341
|
+
return function (saveCheckboxChecked) {
|
|
342
|
+
if (previousSaveCheckboxState === saveCheckboxChecked) {
|
|
343
|
+
return;
|
|
344
|
+
}
|
|
345
|
+
previousSaveCheckboxState = saveCheckboxChecked;
|
|
346
|
+
emitChangeEvent();
|
|
347
|
+
};
|
|
307
348
|
}
|
|
308
349
|
/**
|
|
309
350
|
* Create and mount address element
|
|
@@ -53,7 +53,7 @@ function ensureThemeStylesheet() {
|
|
|
53
53
|
}
|
|
54
54
|
var styleElement = document.createElement('style');
|
|
55
55
|
styleElement.id = THEME_STYLESHEET_ID;
|
|
56
|
-
styleElement.textContent = "\n /* Dark theme styles for the mount element */\n .lsp-theme-dark {\n background-color: ".concat(exports.THEME_COLORS.DARK.BACKGROUND, " !important;\n color: ").concat(exports.THEME_COLORS.DARK.TEXT, " !important;\n }\n /* Dark theme styles for Stripe custom terms elements */\n .lsp-theme-dark .stripe-terms-chevron-icon {\n color: ").concat(exports.THEME_COLORS.DARK.TEXT, " !important;\n }\n .lsp-theme-dark .stripe-custom-terms-text {\n color: ").concat(exports.THEME_COLORS.DARK.TEXT, " !important;\n }\n .lsp-theme-dark .stripe-expandable-terms-content p {\n color: ").concat(exports.THEME_COLORS.DARK.TEXT, " !important;\n }\n ");
|
|
56
|
+
styleElement.textContent = "\n /* Dark theme styles for the mount element */\n .lsp-theme-dark {\n background-color: ".concat(exports.THEME_COLORS.DARK.BACKGROUND, " !important;\n color: ").concat(exports.THEME_COLORS.DARK.TEXT, " !important;\n }\n /* Dark theme styles for Stripe custom terms elements */\n .lsp-theme-dark .stripe-terms-chevron-icon {\n color: ").concat(exports.THEME_COLORS.DARK.TEXT, " !important;\n }\n .lsp-theme-dark .stripe-custom-terms-text {\n color: ").concat(exports.THEME_COLORS.DARK.TEXT, " !important;\n }\n .lsp-theme-dark .stripe-expandable-terms-content p {\n color: ").concat(exports.THEME_COLORS.DARK.TEXT, " !important;\n }\n .lsp-theme-dark .stripe-save-payment-method-container {\n color: ").concat(exports.THEME_COLORS.DARK.TEXT, " !important;\n }\n .lsp-theme-dark .stripe-finalization-error {\n color: #ff8a8a !important;\n }\n .lsp-theme-dark .stripe-save-payment-method-checkbox {\n border-color: #697386;\n background-color: #30313d;\n }\n .lsp-theme-dark .stripe-save-payment-method-checkbox:checked {\n border-color: #007ea3;\n background-color: #007ea3;\n }\n .lsp-theme-dark .stripe-save-payment-method-checkbox:focus-visible {\n border-color: #00d4ff;\n box-shadow: 0 0 0 3px rgba(0, 212, 255, 0.25);\n }\n ");
|
|
57
57
|
document.head.appendChild(styleElement);
|
|
58
58
|
}
|
|
59
59
|
/**
|
|
@@ -77,7 +77,7 @@ function ensureInvoicingDarkStylesheet() {
|
|
|
77
77
|
}
|
|
78
78
|
var styleElement = document.createElement('style');
|
|
79
79
|
styleElement.id = INVOICING_DARK_STYLESHEET_ID;
|
|
80
|
-
styleElement.textContent = "\n /*\n * Mirror the non-colour .lsp-theme-invoicing rules from\n * lightspeed-global-styles.css. Class selectors match whole tokens, so an\n * element carrying the class lsp-theme-invoicing-dark is never matched by\n * the selector .lsp-theme-invoicing; without these the terms text would\n * fall back to the system font while the Elements iframe renders Inter.\n */\n .lsp-theme-invoicing-dark {\n color: #e3e4e9;\n padding-bottom: 0 !important;\n }\n .lsp-theme-invoicing-dark .stripe-custom-terms-text,\n .lsp-theme-invoicing-dark .stripe-expandable-terms-content p {\n color: #e3e4e9;\n font-family: 'Inter', system-ui, sans-serif;\n }\n /*\n * Links and the expand toggle. lightspeed-global-styles.css colours these\n * #635bff, which is close to unreadable on a dark surface, so they take the\n * consumer dark interactive colour instead. The chevron inherits from its\n * toggle so the two can never drift apart.\n */\n .lsp-theme-invoicing-dark .stripe-custom-terms-text a,\n .lsp-theme-invoicing-dark .stripe-expandable-terms-content a,\n .lsp-theme-invoicing-dark .stripe-expandable-terms-toggle {\n color: #6cb5fb;\n }\n .lsp-theme-invoicing-dark .stripe-terms-chevron-icon {\n color: inherit;\n }\n ";
|
|
80
|
+
styleElement.textContent = "\n /*\n * Mirror the non-colour .lsp-theme-invoicing rules from\n * lightspeed-global-styles.css. Class selectors match whole tokens, so an\n * element carrying the class lsp-theme-invoicing-dark is never matched by\n * the selector .lsp-theme-invoicing; without these the terms text would\n * fall back to the system font while the Elements iframe renders Inter.\n */\n .lsp-theme-invoicing-dark {\n color: #e3e4e9;\n padding-bottom: 0 !important;\n }\n .lsp-theme-invoicing-dark .stripe-custom-terms-text,\n .lsp-theme-invoicing-dark .stripe-expandable-terms-content p,\n .lsp-theme-invoicing-dark .stripe-save-payment-method-container,\n .lsp-theme-invoicing-dark .stripe-finalization-error {\n color: #e3e4e9;\n font-family: 'Inter', system-ui, sans-serif;\n }\n .lsp-theme-invoicing-dark .stripe-finalization-error {\n color: #ffa597;\n }\n .lsp-theme-invoicing-dark .stripe-save-payment-method-checkbox {\n border-color: #525256;\n background-color: #242427;\n }\n .lsp-theme-invoicing-dark .stripe-save-payment-method-checkbox:checked {\n border-color: #286ea8;\n background-color: #286ea8;\n }\n .lsp-theme-invoicing-dark .stripe-save-payment-method-checkbox:focus-visible {\n border-color: #6cb5fb;\n box-shadow: 0 0 0 3px rgba(108, 181, 251, 0.25);\n }\n /*\n * Links and the expand toggle. lightspeed-global-styles.css colours these\n * #635bff, which is close to unreadable on a dark surface, so they take the\n * consumer dark interactive colour instead. The chevron inherits from its\n * toggle so the two can never drift apart.\n */\n .lsp-theme-invoicing-dark .stripe-custom-terms-text a,\n .lsp-theme-invoicing-dark .stripe-expandable-terms-content a,\n .lsp-theme-invoicing-dark .stripe-expandable-terms-toggle {\n color: #6cb5fb;\n }\n .lsp-theme-invoicing-dark .stripe-terms-chevron-icon {\n color: inherit;\n }\n ";
|
|
81
81
|
document.head.appendChild(styleElement);
|
|
82
82
|
}
|
|
83
83
|
/**
|