@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/dist/v1/adyen/widget.js
CHANGED
|
@@ -36,13 +36,31 @@ var __generator = (this && this.__generator) || function (thisArg, body) {
|
|
|
36
36
|
};
|
|
37
37
|
import { AdyenCheckout, Dropin, ApplePay, Bancontact, Card, GooglePay, Redirect, Twint, } from '@adyen/adyen-web';
|
|
38
38
|
import { ResultBuilder } from './ResultBuilder';
|
|
39
|
+
import { buildNoShowConsentText } from './terms';
|
|
39
40
|
function mount(mountElement, session, eventBroadcaster) {
|
|
41
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
42
|
+
return __generator(this, function (_a) {
|
|
43
|
+
return [2 /*return*/, mountSessionsFlow(mountElement, session.context, eventBroadcaster)];
|
|
44
|
+
});
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
// Entry for the multi-step contract (v1.mountMultiStepWidget). Kept separate
|
|
48
|
+
// from `mount` so the event-based Sessions flow keeps its WidgetController shape.
|
|
49
|
+
function mountMultiStep(mountElement, session, eventBroadcaster, onRequiresFinalization) {
|
|
50
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
51
|
+
return __generator(this, function (_a) {
|
|
52
|
+
return [2 /*return*/, mountAdvancedFlow(mountElement, session.context, eventBroadcaster, onRequiresFinalization)];
|
|
53
|
+
});
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
function mountSessionsFlow(mountElement, context, eventBroadcaster) {
|
|
40
57
|
return __awaiter(this, void 0, void 0, function () {
|
|
41
58
|
var checkoutConfig, checkout, dropinConfiguration, dropIn;
|
|
42
59
|
return __generator(this, function (_a) {
|
|
43
60
|
switch (_a.label) {
|
|
44
61
|
case 0:
|
|
45
|
-
|
|
62
|
+
injectAdyenCssModuleFix();
|
|
63
|
+
checkoutConfig = createSessionsConfiguration(context, eventBroadcaster);
|
|
46
64
|
return [4 /*yield*/, AdyenCheckout(checkoutConfig)];
|
|
47
65
|
case 1:
|
|
48
66
|
checkout = _a.sent();
|
|
@@ -63,7 +81,163 @@ function mount(mountElement, session, eventBroadcaster) {
|
|
|
63
81
|
});
|
|
64
82
|
});
|
|
65
83
|
}
|
|
66
|
-
|
|
84
|
+
// Multi-step Advanced flow: submit() surfaces the encrypted payment data for
|
|
85
|
+
// the host to POST; handleNextAction() feeds the server response back to drive
|
|
86
|
+
// native 3DS2. See MultiStepController in common.ts.
|
|
87
|
+
function mountAdvancedFlow(mountElement, context, eventBroadcaster, onRequiresFinalization) {
|
|
88
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
89
|
+
var stashedActions, pendingResolve, isValid, checkoutConfig, checkout, dropinConfiguration, dropIn;
|
|
90
|
+
var _a;
|
|
91
|
+
return __generator(this, function (_b) {
|
|
92
|
+
switch (_b.label) {
|
|
93
|
+
case 0:
|
|
94
|
+
isValid = false;
|
|
95
|
+
checkoutConfig = {
|
|
96
|
+
clientKey: context.clientKey,
|
|
97
|
+
environment: context.env,
|
|
98
|
+
countryCode: context.countryCode,
|
|
99
|
+
locale: context.locale,
|
|
100
|
+
amount: { value: (_a = context.amount) !== null && _a !== void 0 ? _a : 0, currency: context.currency },
|
|
101
|
+
paymentMethodsResponse: context.paymentMethods,
|
|
102
|
+
analytics: { enabled: false },
|
|
103
|
+
onSubmit: function (state, _component, actions) {
|
|
104
|
+
stashedActions = actions;
|
|
105
|
+
var result = {
|
|
106
|
+
status: 'RequiresFinalization',
|
|
107
|
+
paymentData: {
|
|
108
|
+
paymentMethod: state.data.paymentMethod,
|
|
109
|
+
browserInfo: state.data.browserInfo,
|
|
110
|
+
origin: window.location.origin,
|
|
111
|
+
},
|
|
112
|
+
saveSessionId: context.saveSessionId,
|
|
113
|
+
};
|
|
114
|
+
if (pendingResolve) {
|
|
115
|
+
pendingResolve(result);
|
|
116
|
+
pendingResolve = undefined;
|
|
117
|
+
}
|
|
118
|
+
else {
|
|
119
|
+
// Express methods (Google Pay / Apple Pay) fire onSubmit from their own
|
|
120
|
+
// button with no submit() pending — hand the result to the host instead.
|
|
121
|
+
onRequiresFinalization === null || onRequiresFinalization === void 0 ? void 0 : onRequiresFinalization(result);
|
|
122
|
+
}
|
|
123
|
+
},
|
|
124
|
+
onAdditionalDetails: function (state, _component, actions) {
|
|
125
|
+
stashedActions = actions;
|
|
126
|
+
pendingResolve === null || pendingResolve === void 0 ? void 0 : pendingResolve({
|
|
127
|
+
status: 'RequiresAction',
|
|
128
|
+
paymentData: {
|
|
129
|
+
details: state.data.details,
|
|
130
|
+
paymentData: state.data.paymentData,
|
|
131
|
+
},
|
|
132
|
+
saveSessionId: context.saveSessionId,
|
|
133
|
+
});
|
|
134
|
+
pendingResolve = undefined;
|
|
135
|
+
},
|
|
136
|
+
onError: function (error) {
|
|
137
|
+
// Resolve a waiting submit()/handleNextAction() so the host doesn't hang.
|
|
138
|
+
if (pendingResolve) {
|
|
139
|
+
pendingResolve({ status: 'Error', error: error });
|
|
140
|
+
pendingResolve = undefined;
|
|
141
|
+
return;
|
|
142
|
+
}
|
|
143
|
+
eventBroadcaster.publish({
|
|
144
|
+
status: 'Error',
|
|
145
|
+
code: 'Processing',
|
|
146
|
+
loggingEnrichment: error,
|
|
147
|
+
});
|
|
148
|
+
},
|
|
149
|
+
// Surface form validity so the host can gate its own submit button; onSubmit
|
|
150
|
+
// never fires for an invalid form, so this is the host's only validity signal.
|
|
151
|
+
onChange: function (state) {
|
|
152
|
+
var _a;
|
|
153
|
+
isValid = state.isValid;
|
|
154
|
+
var paymentMethodType = (_a = state.data.paymentMethod) === null || _a === void 0 ? void 0 : _a.type;
|
|
155
|
+
eventBroadcaster.publish({
|
|
156
|
+
status: 'Change',
|
|
157
|
+
code: isValid ? 'Complete' : 'Incomplete',
|
|
158
|
+
paymentMethodType: typeof paymentMethodType === 'string' ? paymentMethodType : undefined,
|
|
159
|
+
});
|
|
160
|
+
},
|
|
161
|
+
};
|
|
162
|
+
injectAdyenCssModuleFix();
|
|
163
|
+
return [4 /*yield*/, AdyenCheckout(checkoutConfig)];
|
|
164
|
+
case 1:
|
|
165
|
+
checkout = _b.sent();
|
|
166
|
+
dropinConfiguration = {
|
|
167
|
+
paymentMethodComponents: [Card, ApplePay, GooglePay, Bancontact],
|
|
168
|
+
showStoredPaymentMethods: false,
|
|
169
|
+
paymentMethodsConfiguration: {
|
|
170
|
+
card: {
|
|
171
|
+
// Hide the card's built-in button (host renders its own submit). In
|
|
172
|
+
// adyen-web v6 showPayButton is per-component, not Dropin-level. Express
|
|
173
|
+
// wallets keep their native buttons.
|
|
174
|
+
showPayButton: false,
|
|
175
|
+
// Suppress Click to Pay in a zero-value card-save. `_disableClickToPay`
|
|
176
|
+
// is an internal adyen-web flag; replace on the next upgrade.
|
|
177
|
+
_disableClickToPay: true,
|
|
178
|
+
},
|
|
179
|
+
},
|
|
180
|
+
// Render the consent copy only once the Drop-in has finished loading, so it
|
|
181
|
+
// doesn't flash on its own before the card/wallet options appear.
|
|
182
|
+
onReady: function () { return renderConsentDisclosure(mountElement, context.businessName); },
|
|
183
|
+
};
|
|
184
|
+
dropIn = new Dropin(checkout, dropinConfiguration).mount(mountElement);
|
|
185
|
+
return [2 /*return*/, {
|
|
186
|
+
unmount: function () {
|
|
187
|
+
dropIn.unmount();
|
|
188
|
+
removeConsentDisclosure(mountElement);
|
|
189
|
+
},
|
|
190
|
+
submit: function () {
|
|
191
|
+
return new Promise(function (resolve) {
|
|
192
|
+
// adyen-web renders inline field errors but never calls onSubmit for an
|
|
193
|
+
// invalid form, so waiting on pendingResolve would hang the host. Trigger
|
|
194
|
+
// the field errors and settle deterministically instead.
|
|
195
|
+
if (!isValid) {
|
|
196
|
+
dropIn.submit();
|
|
197
|
+
resolve({ status: 'Invalid' });
|
|
198
|
+
return;
|
|
199
|
+
}
|
|
200
|
+
pendingResolve = resolve;
|
|
201
|
+
dropIn.submit();
|
|
202
|
+
});
|
|
203
|
+
},
|
|
204
|
+
handleNextAction: function (serverResponse) {
|
|
205
|
+
return new Promise(function (resolve) {
|
|
206
|
+
var _a;
|
|
207
|
+
var response = (serverResponse !== null && serverResponse !== void 0 ? serverResponse : {});
|
|
208
|
+
if (response.action) {
|
|
209
|
+
// 3DS1 (redirect) is out of scope: surface as an error so the host can
|
|
210
|
+
// ask the shopper for a different card.
|
|
211
|
+
if (response.action.type === 'redirect') {
|
|
212
|
+
resolve({
|
|
213
|
+
status: 'Error',
|
|
214
|
+
error: { code: 'RedirectNotSupported', resultCode: response.resultCode },
|
|
215
|
+
});
|
|
216
|
+
return;
|
|
217
|
+
}
|
|
218
|
+
// Native 3DS2 step: let the component perform it, then resolve once
|
|
219
|
+
// onAdditionalDetails hands us the next payload for the host to POST.
|
|
220
|
+
pendingResolve = resolve;
|
|
221
|
+
stashedActions === null || stashedActions === void 0 ? void 0 : stashedActions.resolve(response);
|
|
222
|
+
return;
|
|
223
|
+
}
|
|
224
|
+
// Terminal response: let the component finalize its UI (its own result
|
|
225
|
+
// screen), drop the now-stale pre-submission consent, report Complete.
|
|
226
|
+
stashedActions === null || stashedActions === void 0 ? void 0 : stashedActions.resolve(response);
|
|
227
|
+
removeConsentDisclosure(mountElement);
|
|
228
|
+
resolve({ status: 'Complete', resultCode: (_a = response.resultCode) !== null && _a !== void 0 ? _a : 'Unknown' });
|
|
229
|
+
});
|
|
230
|
+
},
|
|
231
|
+
}];
|
|
232
|
+
}
|
|
233
|
+
});
|
|
234
|
+
});
|
|
235
|
+
}
|
|
236
|
+
function createSessionsConfiguration(context, eventBroadcaster) {
|
|
237
|
+
var _a;
|
|
238
|
+
if (!context.sessionId || !context.sessionData) {
|
|
239
|
+
throw new Error('Sessions flow requires sessionId and sessionData; received an advanced-flow session.');
|
|
240
|
+
}
|
|
67
241
|
return {
|
|
68
242
|
clientKey: context.clientKey,
|
|
69
243
|
session: {
|
|
@@ -71,15 +245,10 @@ function createAdyenConfiguration(context, eventBroadcaster) {
|
|
|
71
245
|
sessionData: context.sessionData,
|
|
72
246
|
},
|
|
73
247
|
countryCode: context.countryCode,
|
|
74
|
-
amount: {
|
|
75
|
-
value: context.amount,
|
|
76
|
-
currency: context.currency,
|
|
77
|
-
},
|
|
248
|
+
amount: { value: (_a = context.amount) !== null && _a !== void 0 ? _a : 0, currency: context.currency },
|
|
78
249
|
locale: context.locale,
|
|
79
250
|
environment: context.env,
|
|
80
|
-
analytics: {
|
|
81
|
-
enabled: false,
|
|
82
|
-
},
|
|
251
|
+
analytics: { enabled: false },
|
|
83
252
|
onPaymentCompleted: function (data) {
|
|
84
253
|
eventBroadcaster.publish(ResultBuilder.fromPaymentCompletedData(data));
|
|
85
254
|
},
|
|
@@ -96,6 +265,43 @@ function createAdyenConfiguration(context, eventBroadcaster) {
|
|
|
96
265
|
paymentMethodsResponse: context.paymentMethods,
|
|
97
266
|
};
|
|
98
267
|
}
|
|
268
|
+
// Appends the SDK-owned no-show consent copy under the Drop-in. Idempotent, so
|
|
269
|
+
// a repeated onReady never duplicates it; a no-op when no business name is set.
|
|
270
|
+
function renderConsentDisclosure(mountElement, businessName) {
|
|
271
|
+
if (!businessName)
|
|
272
|
+
return;
|
|
273
|
+
if (mountElement.querySelector('[data-lspay="consent-disclosure"]'))
|
|
274
|
+
return;
|
|
275
|
+
var disclosure = document.createElement('p');
|
|
276
|
+
disclosure.setAttribute('data-lspay', 'consent-disclosure');
|
|
277
|
+
disclosure.style.marginTop = '16px';
|
|
278
|
+
disclosure.textContent = buildNoShowConsentText(businessName);
|
|
279
|
+
mountElement.appendChild(disclosure);
|
|
280
|
+
}
|
|
281
|
+
// Removes the consent copy once the flow finalizes or unmounts, so it doesn't
|
|
282
|
+
// linger on the Drop-in's result screen (it only applies pre-submission).
|
|
283
|
+
function removeConsentDisclosure(mountElement) {
|
|
284
|
+
var _a;
|
|
285
|
+
(_a = mountElement.querySelector('[data-lspay="consent-disclosure"]')) === null || _a === void 0 ? void 0 : _a.remove();
|
|
286
|
+
}
|
|
287
|
+
// Adyen's Drop-in CSS uses hashed class names (e.g. .loading-input__spinner--abc123),
|
|
288
|
+
// but when the host app's bundler processes the CSS as modules it rehashes them,
|
|
289
|
+
// causing a mismatch with the unhashed class names Adyen writes to the DOM.
|
|
290
|
+
// We inject plain (unhashed) rules so the spinner/loading states render correctly.
|
|
291
|
+
var adyenCssFixInjected = false;
|
|
292
|
+
function injectAdyenCssModuleFix() {
|
|
293
|
+
if (adyenCssFixInjected)
|
|
294
|
+
return;
|
|
295
|
+
adyenCssFixInjected = true;
|
|
296
|
+
var style = document.createElement('style');
|
|
297
|
+
style.setAttribute('data-lspay', 'adyen-css-module-fix');
|
|
298
|
+
style.textContent = [
|
|
299
|
+
".loading-input__spinner { z-index: 1; width: 100%; height: 100%; display: none; position: absolute; top: 0; left: 0; }",
|
|
300
|
+
".loading-input__spinner--active { display: flex; align-items: center; justify-content: center; }",
|
|
301
|
+
".loading-input__form--loading { opacity: 0; }",
|
|
302
|
+
].join('\n');
|
|
303
|
+
document.head.appendChild(style);
|
|
304
|
+
}
|
|
99
305
|
function createDropinConfiguration() {
|
|
100
306
|
return {
|
|
101
307
|
paymentMethodComponents: [Card, ApplePay, Bancontact, GooglePay, Redirect, Twint],
|
|
@@ -103,4 +309,5 @@ function createDropinConfiguration() {
|
|
|
103
309
|
}
|
|
104
310
|
export var AdyenWidget = {
|
|
105
311
|
mount: mount,
|
|
312
|
+
mountMultiStep: mountMultiStep,
|
|
106
313
|
};
|
package/dist/v1/common.d.ts
CHANGED
|
@@ -1,10 +1,38 @@
|
|
|
1
|
-
import { EventBroadcaster, Event } from './EventBroadcaster';
|
|
1
|
+
import { EventBroadcaster, Event, RequiresFinalizationResult } from './EventBroadcaster';
|
|
2
2
|
import { Session } from './session';
|
|
3
3
|
import { PaymentWidgetTheme } from './widget';
|
|
4
4
|
export type SessionType = 'payment' | 'payment-with-save' | 'moto' | 'moto-with-save' | 'save';
|
|
5
|
+
export type WidgetSubmitResult = Event | RequiresFinalizationResult;
|
|
5
6
|
export type WidgetController = {
|
|
6
7
|
unmount: () => void;
|
|
7
|
-
submit: () => Promise<
|
|
8
|
+
submit: () => Promise<WidgetSubmitResult>;
|
|
9
|
+
/**
|
|
10
|
+
* Deferred MOTO only. Reports a definitive backend decline so the widget can
|
|
11
|
+
* present it and collect a fresh PaymentMethod on the next submission.
|
|
12
|
+
*/
|
|
13
|
+
reportFinalizationDecline?: (result: RequiresFinalizationResult, message: string) => void;
|
|
14
|
+
};
|
|
15
|
+
export type MultiStepResult = {
|
|
16
|
+
status: 'RequiresFinalization';
|
|
17
|
+
paymentData: unknown;
|
|
18
|
+
saveSessionId?: string;
|
|
19
|
+
} | {
|
|
20
|
+
status: 'RequiresAction';
|
|
21
|
+
paymentData: unknown;
|
|
22
|
+
saveSessionId?: string;
|
|
23
|
+
} | {
|
|
24
|
+
status: 'Complete';
|
|
25
|
+
resultCode: string;
|
|
26
|
+
} | {
|
|
27
|
+
status: 'Invalid';
|
|
28
|
+
} | {
|
|
29
|
+
status: 'Error';
|
|
30
|
+
error: unknown;
|
|
31
|
+
};
|
|
32
|
+
export type MultiStepController = {
|
|
33
|
+
unmount: () => void;
|
|
34
|
+
submit: () => Promise<MultiStepResult>;
|
|
35
|
+
handleNextAction: (serverResponse: unknown) => Promise<MultiStepResult>;
|
|
8
36
|
};
|
|
9
37
|
export type DefaultValues = {
|
|
10
38
|
country?: string;
|
package/dist/v1/index.d.ts
CHANGED
|
@@ -4,10 +4,10 @@
|
|
|
4
4
|
* and handling errors related to payment sessions.
|
|
5
5
|
* Don't use * for exports. Be specific to prevent leaking internal APIs.
|
|
6
6
|
*/
|
|
7
|
-
import { WidgetController } from './common';
|
|
7
|
+
import { WidgetController, MultiStepController } from './common';
|
|
8
8
|
import { PaymentWidgetConfiguration } from './widget';
|
|
9
|
-
export type { WidgetController, SessionType, DefaultValues } from './common';
|
|
10
|
-
export type { Event } from './EventBroadcaster';
|
|
9
|
+
export type { WidgetController, MultiStepController, MultiStepResult, SessionType, DefaultValues, WidgetSubmitResult, } from './common';
|
|
10
|
+
export type { Event, RequiresFinalizationResult } from './EventBroadcaster';
|
|
11
11
|
export { UnsupportedLocationError, InvalidSessionPayloadError, InvalidSessionError, ProcessingError, } from './error';
|
|
12
12
|
export type { PaymentWidgetConfiguration, PaymentWidgetTheme } from './widget';
|
|
13
13
|
export { THEME_COLORS } from './stripe/themes';
|
|
@@ -19,5 +19,14 @@ export type LightspeedPaymentsV1 = {
|
|
|
19
19
|
* @param {PaymentWidgetConfiguration} config - The configuration options for the payment widget.
|
|
20
20
|
*/
|
|
21
21
|
mountPaymentWidget(session: string, config: PaymentWidgetConfiguration): Promise<WidgetController>;
|
|
22
|
+
/**
|
|
23
|
+
* Mounts the payment widget using the multi-step contract, where the host
|
|
24
|
+
* owns HTTP transport. Returns a controller whose `submit()` yields the opaque
|
|
25
|
+
* payment data to POST and whose `handleNextAction()` drives the 3DS2 loop.
|
|
26
|
+
* @function mountMultiStepWidget
|
|
27
|
+
* @param {string} session - The base64-encoded session payload from the create-session API.
|
|
28
|
+
* @param {PaymentWidgetConfiguration} config - The configuration options for the payment widget.
|
|
29
|
+
*/
|
|
30
|
+
mountMultiStepWidget(session: string, config: PaymentWidgetConfiguration): Promise<MultiStepController>;
|
|
22
31
|
};
|
|
23
32
|
export declare const v1: LightspeedPaymentsV1;
|
package/dist/v1/index.js
CHANGED
|
@@ -4,9 +4,10 @@
|
|
|
4
4
|
* and handling errors related to payment sessions.
|
|
5
5
|
* Don't use * for exports. Be specific to prevent leaking internal APIs.
|
|
6
6
|
*/
|
|
7
|
-
import { mountPaymentWidget } from './widget';
|
|
7
|
+
import { mountPaymentWidget, mountMultiStepWidget, } from './widget';
|
|
8
8
|
export { UnsupportedLocationError, InvalidSessionPayloadError, InvalidSessionError, ProcessingError, } from './error';
|
|
9
9
|
export { THEME_COLORS } from './stripe/themes';
|
|
10
10
|
export var v1 = {
|
|
11
11
|
mountPaymentWidget: mountPaymentWidget,
|
|
12
|
+
mountMultiStepWidget: mountMultiStepWidget,
|
|
12
13
|
};
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/** Locale-selected UI text rendered alongside Stripe Elements. */
|
|
2
|
+
var SAVE_PAYMENT_METHOD_TEXT = {
|
|
3
|
+
de: 'Zahlungsinformationen für zukünftige Einkäufe speichern',
|
|
4
|
+
en: 'Save payment details for future purchases',
|
|
5
|
+
fr: 'Enregistrer les informations de paiement pour vos prochains achats',
|
|
6
|
+
nl: 'Betaalgegevens opslaan voor toekomstige aankopen',
|
|
7
|
+
};
|
|
8
|
+
var CARD_DECLINED_TEXT = {
|
|
9
|
+
de: 'Ihre Karte wurde abgelehnt.',
|
|
10
|
+
en: 'Your card was declined.',
|
|
11
|
+
fr: 'Votre carte a été refusée.',
|
|
12
|
+
nl: 'Uw kaart is geweigerd.',
|
|
13
|
+
};
|
|
14
|
+
function getLanguage(locale) {
|
|
15
|
+
var _a;
|
|
16
|
+
var resolvedLocale = !locale || locale === 'auto'
|
|
17
|
+
? ((_a = globalThis.navigator) === null || _a === void 0 ? void 0 : _a.language) || 'en'
|
|
18
|
+
: locale;
|
|
19
|
+
return resolvedLocale.toLowerCase().split('-')[0];
|
|
20
|
+
}
|
|
21
|
+
export function getSavePaymentMethodText(locale) {
|
|
22
|
+
var language = getLanguage(locale);
|
|
23
|
+
return SAVE_PAYMENT_METHOD_TEXT[language] || SAVE_PAYMENT_METHOD_TEXT.en;
|
|
24
|
+
}
|
|
25
|
+
export function getCardDeclinedText(locale) {
|
|
26
|
+
var language = getLanguage(locale);
|
|
27
|
+
return CARD_DECLINED_TEXT[language] || CARD_DECLINED_TEXT.en;
|
|
28
|
+
}
|
|
@@ -1,15 +1,38 @@
|
|
|
1
1
|
import { StripeElementLocale } from '@stripe/stripe-js';
|
|
2
2
|
import { BaseSession } from '../session';
|
|
3
|
-
export type
|
|
3
|
+
export type StripeBaseSession = BaseSession & {
|
|
4
4
|
psp: 'STRIPE';
|
|
5
|
-
context: StripeContext;
|
|
6
5
|
};
|
|
7
|
-
|
|
8
|
-
clientSecret: string;
|
|
6
|
+
type StripeContextBase = {
|
|
9
7
|
publishableKey: string;
|
|
8
|
+
locale?: StripeElementLocale;
|
|
9
|
+
businessName?: string;
|
|
10
|
+
};
|
|
11
|
+
export type IntentBoundStripeContext = StripeContextBase & {
|
|
12
|
+
intentMode?: 'intent-bound';
|
|
13
|
+
clientSecret: string;
|
|
10
14
|
customerSessionClientSecret?: string;
|
|
11
15
|
intent: 'save-card' | 'payment';
|
|
12
|
-
locale?: StripeElementLocale;
|
|
13
16
|
redirectUrl?: string;
|
|
14
|
-
businessName?: string;
|
|
15
17
|
};
|
|
18
|
+
export type DeferredStripeContext = StripeContextBase & {
|
|
19
|
+
intentMode: 'deferred';
|
|
20
|
+
intent: 'payment';
|
|
21
|
+
amount: number;
|
|
22
|
+
currency: string;
|
|
23
|
+
paymentMethodTypes: string[];
|
|
24
|
+
onBehalfOf: string;
|
|
25
|
+
clientSecret?: never;
|
|
26
|
+
customerSessionClientSecret?: never;
|
|
27
|
+
};
|
|
28
|
+
export type StripeContext = IntentBoundStripeContext | DeferredStripeContext;
|
|
29
|
+
export type IntentBoundStripeSession = StripeBaseSession & {
|
|
30
|
+
context: IntentBoundStripeContext;
|
|
31
|
+
};
|
|
32
|
+
export type DeferredStripeSession = StripeBaseSession & {
|
|
33
|
+
context: DeferredStripeContext;
|
|
34
|
+
};
|
|
35
|
+
export type StripeSession = IntentBoundStripeSession | DeferredStripeSession;
|
|
36
|
+
export declare function isDeferredStripeSession(session: StripeSession): session is DeferredStripeSession;
|
|
37
|
+
export declare function isIntentBoundStripeSession(session: StripeSession): session is IntentBoundStripeSession;
|
|
38
|
+
export {};
|
|
@@ -1 +1,7 @@
|
|
|
1
|
-
export {
|
|
1
|
+
export function isDeferredStripeSession(session) {
|
|
2
|
+
return session.context.intentMode === 'deferred';
|
|
3
|
+
}
|
|
4
|
+
export function isIntentBoundStripeSession(session) {
|
|
5
|
+
return (session.context.intentMode === undefined ||
|
|
6
|
+
session.context.intentMode === 'intent-bound');
|
|
7
|
+
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { StripePaymentElementOptions, StripeAddressElementOptions } from '@stripe/stripe-js';
|
|
2
2
|
import type { StripeElements, Stripe, StripeAddressElement, StripePaymentElement } from '@stripe/stripe-js';
|
|
3
|
-
import {
|
|
3
|
+
import { IntentBoundStripeSession, StripeContext } from './session';
|
|
4
4
|
import { DefaultValues } from '../common';
|
|
5
5
|
import { EventBroadcaster } from '../EventBroadcaster';
|
|
6
6
|
import { PaymentWidgetTheme } from '../widget';
|
|
@@ -45,6 +45,7 @@ export declare function buildCardConsentText(businessName: string, reason: strin
|
|
|
45
45
|
* text.
|
|
46
46
|
*/
|
|
47
47
|
export declare function createCardConsentElement(consentText: string): HTMLElement;
|
|
48
|
+
export declare function createSavePaymentMethodElement(mountElement: HTMLElement, onChange: (checked: boolean) => void, locale?: string): HTMLElement;
|
|
48
49
|
/**
|
|
49
50
|
* Create and mount payment element
|
|
50
51
|
*/
|
|
@@ -61,7 +62,9 @@ export declare function createPaymentElement(elements: StripeElements, options:
|
|
|
61
62
|
* Also includes the current save-payment-method checkbox state (when present) on every Change event,
|
|
62
63
|
* and emits a Change event when that checkbox state changes.
|
|
63
64
|
*/
|
|
64
|
-
export declare function setupChangeEventHandler(paymentElement: StripePaymentElement, eventBroadcaster: EventBroadcaster, addressElement?: StripeAddressElement | null
|
|
65
|
+
export declare function setupChangeEventHandler(paymentElement: StripePaymentElement, eventBroadcaster: EventBroadcaster, addressElement?: StripeAddressElement | null, onPaymentValueChange?: (value: {
|
|
66
|
+
savePaymentMethod?: boolean;
|
|
67
|
+
}) => void, initialSaveCheckboxState?: boolean): (saveCheckboxChecked: boolean) => void;
|
|
65
68
|
/**
|
|
66
69
|
* Create and mount address element
|
|
67
70
|
*/
|
|
@@ -76,12 +79,12 @@ export declare function cleanupElements(paymentElement: StripePaymentElement, ad
|
|
|
76
79
|
/**
|
|
77
80
|
* Handle save card operation
|
|
78
81
|
*/
|
|
79
|
-
export declare function handleSaveCard(stripe: Stripe, elements: StripeElements, session:
|
|
82
|
+
export declare function handleSaveCard(stripe: Stripe, elements: StripeElements, session: IntentBoundStripeSession, addressElement?: StripeAddressElement | null): Promise<import("../EventBroadcaster").SucceededResultEvent | import("../EventBroadcaster").PendingResultEvent | import("../EventBroadcaster").DeclinedResultEvent | import("../EventBroadcaster").ErrorResultEvent>;
|
|
80
83
|
/**
|
|
81
84
|
* Handle payment operation
|
|
82
85
|
*/
|
|
83
|
-
export declare function handlePayment(stripe: Stripe, elements: StripeElements, session:
|
|
86
|
+
export declare function handlePayment(stripe: Stripe, elements: StripeElements, session: IntentBoundStripeSession, addressElement?: StripeAddressElement | null): Promise<import("../EventBroadcaster").SucceededResultEvent | import("../EventBroadcaster").PendingResultEvent | import("../EventBroadcaster").DeclinedResultEvent | import("../EventBroadcaster").ErrorResultEvent>;
|
|
84
87
|
/**
|
|
85
88
|
* Create common submit handler for widgets
|
|
86
89
|
*/
|
|
87
|
-
export declare function createSubmitHandler(stripe: Stripe, elements: StripeElements, session:
|
|
90
|
+
export declare function createSubmitHandler(stripe: Stripe, elements: StripeElements, session: IntentBoundStripeSession, eventBroadcaster: EventBroadcaster, addressElement?: StripeAddressElement | null): () => Promise<import("../EventBroadcaster").SucceededResultEvent | import("../EventBroadcaster").PendingResultEvent | import("../EventBroadcaster").DeclinedResultEvent | import("../EventBroadcaster").ErrorResultEvent>;
|
package/dist/v1/stripe/shared.js
CHANGED
|
@@ -49,17 +49,18 @@ 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, PARTNER_CARD_CONSENT_TEXT } from './terms';
|
|
52
|
+
import { ACH_TERMS_TEXT, ACH_TERMS_URL, PARTNER_CARD_CONSENT_TEXT, } from './terms';
|
|
53
|
+
import { getSavePaymentMethodText } from './localizedText';
|
|
53
54
|
/**
|
|
54
55
|
* Initialize Stripe with the given context
|
|
55
56
|
*/
|
|
56
57
|
export function initStripe(context, theme) {
|
|
57
58
|
return __awaiter(this, void 0, void 0, function () {
|
|
58
|
-
var publishableKey,
|
|
59
|
+
var publishableKey, loadedStripe, stripe, themeConfig, sharedElementsOptions, elements, elementsOptions, elementsOptions;
|
|
59
60
|
return __generator(this, function (_a) {
|
|
60
61
|
switch (_a.label) {
|
|
61
62
|
case 0:
|
|
62
|
-
publishableKey = context.publishableKey
|
|
63
|
+
publishableKey = context.publishableKey;
|
|
63
64
|
return [4 /*yield*/, loadStripe(publishableKey)];
|
|
64
65
|
case 1:
|
|
65
66
|
loadedStripe = _a.sent();
|
|
@@ -68,8 +69,15 @@ export function initStripe(context, theme) {
|
|
|
68
69
|
}
|
|
69
70
|
stripe = loadedStripe;
|
|
70
71
|
themeConfig = getThemeConfig(theme);
|
|
71
|
-
|
|
72
|
-
|
|
72
|
+
sharedElementsOptions = __assign(__assign(__assign({}, (context.locale && { locale: context.locale })), (themeConfig && { appearance: themeConfig.appearance })), (themeConfig && { fonts: themeConfig.fonts }));
|
|
73
|
+
if (context.intentMode === 'deferred') {
|
|
74
|
+
elementsOptions = __assign(__assign(__assign({}, sharedElementsOptions), { mode: 'payment', amount: context.amount, currency: context.currency.toLowerCase(), paymentMethodTypes: context.paymentMethodTypes, paymentMethodCreation: 'manual' }), (context.onBehalfOf && { onBehalfOf: context.onBehalfOf }));
|
|
75
|
+
elements = stripe.elements(elementsOptions);
|
|
76
|
+
}
|
|
77
|
+
else {
|
|
78
|
+
elementsOptions = __assign(__assign({}, sharedElementsOptions), { clientSecret: context.clientSecret, customerSessionClientSecret: context.customerSessionClientSecret });
|
|
79
|
+
elements = stripe.elements(elementsOptions);
|
|
80
|
+
}
|
|
73
81
|
return [2 /*return*/, { stripe: stripe, elements: elements }];
|
|
74
82
|
}
|
|
75
83
|
});
|
|
@@ -206,6 +214,24 @@ export function createCardConsentElement(consentText) {
|
|
|
206
214
|
container.appendChild(text);
|
|
207
215
|
return container;
|
|
208
216
|
}
|
|
217
|
+
export function createSavePaymentMethodElement(mountElement, onChange, locale) {
|
|
218
|
+
var label = document.createElement('label');
|
|
219
|
+
label.className = 'stripe-save-payment-method-container';
|
|
220
|
+
var checkbox = document.createElement('input');
|
|
221
|
+
checkbox.type = 'checkbox';
|
|
222
|
+
checkbox.className = 'stripe-save-payment-method-checkbox';
|
|
223
|
+
checkbox.dataset.testid = 'save-payment-method-checkbox';
|
|
224
|
+
var text = document.createElement('span');
|
|
225
|
+
text.className = 'stripe-save-payment-method-text';
|
|
226
|
+
text.textContent = getSavePaymentMethodText(locale);
|
|
227
|
+
label.appendChild(checkbox);
|
|
228
|
+
label.appendChild(text);
|
|
229
|
+
mountElement.appendChild(label);
|
|
230
|
+
// The label must remain clickable, but its consent text is not selectable.
|
|
231
|
+
label.addEventListener('selectstart', function (event) { return event.preventDefault(); });
|
|
232
|
+
checkbox.addEventListener('change', function () { return onChange(checkbox.checked); });
|
|
233
|
+
return label;
|
|
234
|
+
}
|
|
209
235
|
/**
|
|
210
236
|
* Create and mount payment element
|
|
211
237
|
*/
|
|
@@ -245,12 +271,12 @@ export function createPaymentElement(elements, options, mountElement, eventBroad
|
|
|
245
271
|
* Also includes the current save-payment-method checkbox state (when present) on every Change event,
|
|
246
272
|
* and emits a Change event when that checkbox state changes.
|
|
247
273
|
*/
|
|
248
|
-
export function setupChangeEventHandler(paymentElement, eventBroadcaster, addressElement) {
|
|
274
|
+
export function setupChangeEventHandler(paymentElement, eventBroadcaster, addressElement, onPaymentValueChange, initialSaveCheckboxState) {
|
|
249
275
|
var paymentComplete = false;
|
|
250
276
|
var addressComplete = !addressElement; // If no address element, consider it complete
|
|
251
277
|
var previousComplete = null;
|
|
252
278
|
var previousMethodType;
|
|
253
|
-
var previousSaveCheckboxState
|
|
279
|
+
var previousSaveCheckboxState = initialSaveCheckboxState;
|
|
254
280
|
var emitChangeEvent = function () {
|
|
255
281
|
var complete = paymentComplete && addressComplete;
|
|
256
282
|
previousComplete = complete;
|
|
@@ -261,23 +287,30 @@ export function setupChangeEventHandler(paymentElement, eventBroadcaster, addres
|
|
|
261
287
|
})));
|
|
262
288
|
};
|
|
263
289
|
paymentElement.on('change', function (event) {
|
|
264
|
-
var _a, _b;
|
|
290
|
+
var _a, _b, _c;
|
|
265
291
|
paymentComplete = event.complete;
|
|
292
|
+
onPaymentValueChange === null || onPaymentValueChange === void 0 ? void 0 : onPaymentValueChange({
|
|
293
|
+
savePaymentMethod: (_a = event.value) === null || _a === void 0 ? void 0 : _a.savePaymentMethod,
|
|
294
|
+
});
|
|
266
295
|
var completenessChanged = (paymentComplete && addressComplete) !== previousComplete;
|
|
267
|
-
var methodType = (
|
|
296
|
+
var methodType = (_b = event.value) === null || _b === void 0 ? void 0 : _b.type;
|
|
268
297
|
var methodTypeChanged = methodType !== undefined && methodType !== previousMethodType;
|
|
269
298
|
if (methodType !== undefined) {
|
|
270
299
|
previousMethodType = methodType;
|
|
271
300
|
}
|
|
272
301
|
// `savePaymentMethod` reflects the "save for future use" checkbox; it is only
|
|
273
302
|
// present on the change event when the element renders that checkbox.
|
|
274
|
-
var
|
|
275
|
-
var
|
|
276
|
-
if (
|
|
277
|
-
|
|
278
|
-
|
|
303
|
+
var stripeSaveCheckboxChanged = false;
|
|
304
|
+
var stripeSaveCheckboxState = (_c = event.value) === null || _c === void 0 ? void 0 : _c.savePaymentMethod;
|
|
305
|
+
if (initialSaveCheckboxState === undefined &&
|
|
306
|
+
stripeSaveCheckboxState !== undefined) {
|
|
307
|
+
stripeSaveCheckboxChanged =
|
|
308
|
+
previousSaveCheckboxState !== stripeSaveCheckboxState;
|
|
309
|
+
previousSaveCheckboxState = stripeSaveCheckboxState;
|
|
279
310
|
}
|
|
280
|
-
if (completenessChanged ||
|
|
311
|
+
if (completenessChanged ||
|
|
312
|
+
methodTypeChanged ||
|
|
313
|
+
stripeSaveCheckboxChanged) {
|
|
281
314
|
emitChangeEvent();
|
|
282
315
|
}
|
|
283
316
|
});
|
|
@@ -290,6 +323,13 @@ export function setupChangeEventHandler(paymentElement, eventBroadcaster, addres
|
|
|
290
323
|
}
|
|
291
324
|
});
|
|
292
325
|
}
|
|
326
|
+
return function (saveCheckboxChecked) {
|
|
327
|
+
if (previousSaveCheckboxState === saveCheckboxChecked) {
|
|
328
|
+
return;
|
|
329
|
+
}
|
|
330
|
+
previousSaveCheckboxState = saveCheckboxChecked;
|
|
331
|
+
emitChangeEvent();
|
|
332
|
+
};
|
|
293
333
|
}
|
|
294
334
|
/**
|
|
295
335
|
* Create and mount address element
|
package/dist/v1/stripe/terms.js
CHANGED