@bloque/payments-core 0.0.12 → 0.1.1
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 +32 -2
- package/dist/assets/mc-id-check-logo-data-uri.d.ts +2 -0
- package/dist/checkout.d.ts +12 -0
- package/dist/index.cjs +134 -6
- package/dist/index.d.ts +1 -1
- package/dist/index.js +134 -6
- package/dist/types/payment.d.ts +7 -3
- package/dist/types.d.ts +25 -5
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -8,15 +8,26 @@ Core JavaScript library for integrating Bloque hosted checkout into any web appl
|
|
|
8
8
|
pnpm install @bloque/payments-core
|
|
9
9
|
```
|
|
10
10
|
|
|
11
|
+
## Authentication
|
|
12
|
+
|
|
13
|
+
The checkout component accepts two browser-safe credentials:
|
|
14
|
+
|
|
15
|
+
| Option | Required | Description |
|
|
16
|
+
|--------|----------|-------------|
|
|
17
|
+
| `publishableKey` | Yes | Your `pk_test_*` / `pk_live_*` key — identifies the merchant |
|
|
18
|
+
| `clientSecret` | Recommended | A scoped JWT from `bloque.checkout.create()` — authorizes payment execution |
|
|
19
|
+
|
|
20
|
+
> `publicApiKey` is still accepted for backward compatibility but is deprecated in favor of `publishableKey`.
|
|
21
|
+
|
|
11
22
|
## Quick Start
|
|
12
23
|
|
|
13
24
|
```javascript
|
|
14
25
|
import { createCheckout } from '@bloque/payments-core';
|
|
15
26
|
|
|
16
|
-
// First, create a payment intent using @bloque/payments on your backend
|
|
17
|
-
// Then use the checkout_id to mount the checkout
|
|
18
27
|
const checkout = createCheckout({
|
|
19
28
|
checkoutId: 'checkout_123abc',
|
|
29
|
+
publishableKey: 'pk_test_...',
|
|
30
|
+
clientSecret: 'eyJ...', // from your backend
|
|
20
31
|
container: '#checkout-container',
|
|
21
32
|
onSuccess: (data) => {
|
|
22
33
|
console.log('Payment successful!', data);
|
|
@@ -30,6 +41,25 @@ const checkout = createCheckout({
|
|
|
30
41
|
checkout.destroy();
|
|
31
42
|
```
|
|
32
43
|
|
|
44
|
+
## 3D Secure
|
|
45
|
+
|
|
46
|
+
When the hosted checkout triggers a 3DS challenge, the overlay is rendered at the **parent page** level (not inside the checkout iframe) via `postMessage`:
|
|
47
|
+
|
|
48
|
+
```javascript
|
|
49
|
+
const checkout = createCheckout({
|
|
50
|
+
checkoutId: 'checkout_123abc',
|
|
51
|
+
publishableKey: 'pk_test_...',
|
|
52
|
+
clientSecret: 'eyJ...',
|
|
53
|
+
container: '#checkout-container',
|
|
54
|
+
threeDsAuthType: 'challenge_v2', // sandbox only
|
|
55
|
+
onThreeDSChallenge: () => {
|
|
56
|
+
console.log('3DS challenge overlay is visible');
|
|
57
|
+
},
|
|
58
|
+
onSuccess: (data) => console.log('ok', data),
|
|
59
|
+
onError: (err) => console.error(err),
|
|
60
|
+
});
|
|
61
|
+
```
|
|
62
|
+
|
|
33
63
|
## Documentation
|
|
34
64
|
|
|
35
65
|
For complete documentation, examples, and API reference, visit:
|
package/dist/checkout.d.ts
CHANGED
|
@@ -5,6 +5,11 @@ export declare class BloqueCheckout {
|
|
|
5
5
|
private options;
|
|
6
6
|
private messageListener;
|
|
7
7
|
private isReady;
|
|
8
|
+
/** Full-screen 3DS overlay mounted on document.body (avoids nested iframes). */
|
|
9
|
+
private threeDsOverlay;
|
|
10
|
+
private threeDsTimers;
|
|
11
|
+
private threeDsContentEl;
|
|
12
|
+
private threeDsStatusEl;
|
|
8
13
|
/**
|
|
9
14
|
* Initialize global configuration for all BloqueCheckout instances
|
|
10
15
|
* This allows you to set publicApiKey and mode once instead of passing them to every checkout
|
|
@@ -24,7 +29,14 @@ export declare class BloqueCheckout {
|
|
|
24
29
|
mount(container: HTMLElement | string): void;
|
|
25
30
|
private setupMessageListener;
|
|
26
31
|
private handleCheckoutReady;
|
|
32
|
+
private clearThreeDsTimers;
|
|
33
|
+
private removeThreeDsOverlay;
|
|
34
|
+
private setThreeDsStatus;
|
|
35
|
+
private showMcLogoInContent;
|
|
36
|
+
private handleThreeDSChallenge;
|
|
27
37
|
private handlePaymentResult;
|
|
38
|
+
private finishThreeDsThenDispatch;
|
|
39
|
+
private dispatchPaymentResult;
|
|
28
40
|
private handlePaymentError;
|
|
29
41
|
isCheckoutReady(): boolean;
|
|
30
42
|
getIframe(): HTMLIFrameElement | null;
|
package/dist/index.cjs
CHANGED
|
@@ -28,13 +28,26 @@ __webpack_require__.d(__webpack_exports__, {
|
|
|
28
28
|
createCheckout: ()=>createCheckout,
|
|
29
29
|
init: ()=>init
|
|
30
30
|
});
|
|
31
|
+
const MC_ID_CHECK_LOGO_DATA_URI = 'data:image/svg+xml;charset=utf-8,' + encodeURIComponent('<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 504.16287 144"><rect width="504.16287" height="144" fill="none"/><rect x="78.4951" y="43.6968" width="31.5" height="56.6064" fill="#ff5f00"/><path d="M224.41386,306a35.9375,35.9375,0,0,1,13.7499-28.3032,36,36,0,1,0,0,56.6064A35.938,35.938,0,0,1,224.41386,306Z" transform="translate(-143.91856 -234)" fill="#eb001b"/><path d="M296.409,306a35.99867,35.99867,0,0,1-58.24521,28.3032,36.00518,36.00518,0,0,0,0-56.6064A35.99867,35.99867,0,0,1,296.409,306Z" transform="translate(-143.91856 -234)" fill="#f79e1b"/><path d="M292.97436,328.3077v-1.1589h.4673v-.2361h-1.1901v.2361h.4675v1.1589Zm2.3105,0v-1.3973h-.3648l-.4196.9611-.4197-.9611h-.365v1.3973h.2576v-1.054l.3935.9087h.26711l.39349-.911v1.0563Z" transform="translate(-143.91856 -234)" fill="#f79e1b"/><polygon points="189.157 108.202 187.824 108.202 187.824 96.055 187.824 71.759 187.824 47.463 187.824 35.316 189.157 35.316 189.157 59.611 189.157 83.907 189.157 108.202"/><path d="M369.97109,328.30869h-3.74122V285.37558h3.74122Zm27.293-42.93311a29.13247,29.13247,0,0,1,9.66016,1.50244,20.54648,20.54648,0,0,1,7.29883,4.29346,18.82,18.82,0,0,1,4.62988,6.76172,25.2182,25.2182,0,0,1,0,17.81738,18.81762,18.81762,0,0,1-4.62988,6.76221,20.53928,20.53928,0,0,1-7.29883,4.29346,29.11984,29.11984,0,0,1-9.66016,1.50244H381.59316V285.37558Zm-11.92968,3.55713v35.81885h11.92968a24.72126,24.72126,0,0,0,8.28028-1.27295,16.77648,16.77648,0,0,0,6.041-3.603,15.0198,15.0198,0,0,0,3.71094-5.64306,22.35805,22.35805,0,0,0,0-14.78125,15.15681,15.15681,0,0,0-3.71094-5.65772,16.49932,16.49932,0,0,0-6.041-3.60351,25.01066,25.01066,0,0,0-8.28028-1.25733Zm78.6289-4.04785a22.97654,22.97654,0,0,1,5.33692.61328,21.59063,21.59063,0,0,1,4.8291,1.76319,19.26143,19.26143,0,0,1,4.0791,2.77539,17.01572,17.01572,0,0,1,3.1123,3.68017l-3.12793,2.085a15.116,15.116,0,0,0-2.62207-3.03564,16.4616,16.4616,0,0,0-3.34277-2.3003,17.16135,17.16135,0,0,0-3.9248-1.45654,18.46749,18.46749,0,0,0-4.33985-.50586,19.03537,19.03537,0,0,0-7.12988,1.31836,16.99574,16.99574,0,0,0-5.73438,3.7417,17.48439,17.48439,0,0,0-3.833,5.7959,20.75862,20.75862,0,0,0,0,14.96533,17.47928,17.47928,0,0,0,3.833,5.7959,16.98717,16.98717,0,0,0,5.73438,3.74121,19.01623,19.01623,0,0,0,7.12988,1.31885,18.82191,18.82191,0,0,0,4.32422-.49072,16.68442,16.68442,0,0,0,3.91016-1.44141,16.42818,16.42818,0,0,0,3.34277-2.2998,14.76727,14.76727,0,0,0,2.62207-3.0669l3.06641,2.23877a18.18515,18.18515,0,0,1-3.17383,3.61865,19.8084,19.8084,0,0,1-4.04785,2.72949,21.03046,21.03046,0,0,1-4.76856,1.73243,23.97561,23.97561,0,0,1-14-1.02735,21.025,21.025,0,0,1-6.97656-4.52343,20.74492,20.74492,0,0,1-4.61523-6.93067,24.37931,24.37931,0,0,1,0-17.74023,20.719,20.719,0,0,1,4.61523-6.94629,21.03249,21.03249,0,0,1,6.97656-4.52344A23.13114,23.13114,0,0,1,463.96327,284.88486Zm28.85742,19.56494a11.0293,11.0293,0,0,1,2.00879-2.45312,10.72962,10.72962,0,0,1,2.499-1.70215,12.47653,12.47653,0,0,1,2.82129-.981,13.73243,13.73243,0,0,1,2.94433-.32226,14.39955,14.39955,0,0,1,4.9375.8125,11.13893,11.13893,0,0,1,3.84863,2.31543,10.13945,10.13945,0,0,1,2.48438,3.66455,12.79658,12.79658,0,0,1,.874,4.83007v17.69483h-3.49609v-16.6211a11.82475,11.82475,0,0,0-.61328-3.92578,7.84633,7.84633,0,0,0-1.80957-2.959,7.9592,7.9592,0,0,0-2.91309-1.85547,11.13969,11.13969,0,0,0-3.92578-.644,10.2964,10.2964,0,0,0-3.78711.68994,9.05794,9.05794,0,0,0-3.0664,1.96289,9.23828,9.23828,0,0,0-2.05469,3.03564,9.78042,9.78042,0,0,0-.752,3.8794v16.4375H489.3246V284.14853h3.49609Zm43.21-5.45849a13.11521,13.11521,0,0,1,5.35058,1.08886,12.68765,12.68765,0,0,1,4.2627,3.03565,14.43555,14.43555,0,0,1,2.83691,4.66162,16.863,16.863,0,0,1,1.07324,5.93408c0,.26563-.00488.5166-.01465.751q-.01611.353-.04589.69043H525.29726a12.40913,12.40913,0,0,0,1.11914,4.477,10.56862,10.56862,0,0,0,2.43847,3.32715,10.27766,10.27766,0,0,0,3.44922,2.07031,12.11186,12.11186,0,0,0,4.15528.70508,12.80778,12.80778,0,0,0,5.42871-1.104,15.199,15.199,0,0,0,4.32324-3.00537l1.87109,2.39209a17.14471,17.14471,0,0,1-2.80566,2.30029,14.98357,14.98357,0,0,1-2.91406,1.47168,14.37333,14.37333,0,0,1-3.02051.76661,22.32086,22.32086,0,0,1-3.09668.21484,15.28005,15.28005,0,0,1-5.82715-1.08887,13.5515,13.5515,0,0,1-4.59961-3.05127,13.79423,13.79423,0,0,1-3.00586-4.69189,16.37017,16.37017,0,0,1-1.07324-6.04151A16.12411,16.12411,0,0,1,522.82851,307.9a14.25392,14.25392,0,0,1,3.00488-4.72266,13.57607,13.57607,0,0,1,4.53906-3.082A14.43287,14.43287,0,0,1,536.03066,298.99131Zm-.06153,3.09716a10.50706,10.50706,0,0,0-4.0332.75147,10.10774,10.10774,0,0,0-3.2041,2.08545,10.81339,10.81339,0,0,0-2.25391,3.17383,12.58891,12.58891,0,0,0-1.11914,4.04834h20.63867a12.478,12.478,0,0,0-1.01269-4.09424,10.31139,10.31139,0,0,0-2.16211-3.17383,9.61078,9.61078,0,0,0-6.85352-2.791Zm33.70117-3.09716a15.28282,15.28282,0,0,1,5.96485,1.1499,12.75921,12.75921,0,0,1,4.67676,3.32763l-2.26954,2.36133a12.53947,12.53947,0,0,0-3.78711-2.62207,11.37194,11.37194,0,0,0-4.67675-.93554,11.053,11.053,0,0,0-4.40039.874,10.80754,10.80754,0,0,0-3.542,2.42285,11.07186,11.07186,0,0,0-2.34668,3.67969,13.22753,13.22753,0,0,0,0,9.292,10.74991,10.74991,0,0,0,5.88868,6.07227,11.053,11.053,0,0,0,4.40039.874,11.31977,11.31977,0,0,0,4.73828-.98145,13.16026,13.16026,0,0,0,3.81738-2.60644l2.17774,2.39209a13.07136,13.07136,0,0,1-4.69239,3.32715,16.10337,16.10337,0,0,1-11.91406.01513,13.92431,13.92431,0,0,1-7.72754-7.835,16.58924,16.58924,0,0,1,0-11.82226,13.88959,13.88959,0,0,1,7.72754-7.85059A15.3168,15.3168,0,0,1,569.6703,298.99131Zm21.15918,12.63476h4.69239l12.14355-12.1748h4.416l-13.73828,13.61621,13.98339,15.24121h-4.44629l-12.35839-13.52393h-4.69239v13.52393h-3.49609V284.14853h3.49609Z" transform="translate(-143.91856 -234)"/></svg>');
|
|
31
32
|
const DEFAULT_CHECKOUT_URL = 'https://payments.bloque.app/checkout';
|
|
33
|
+
function isUrl(s) {
|
|
34
|
+
return /^https?:\/\//i.test(s.trim());
|
|
35
|
+
}
|
|
36
|
+
function decodeHtmlEntities(encoded) {
|
|
37
|
+
const textarea = document.createElement('textarea');
|
|
38
|
+
textarea.innerHTML = encoded;
|
|
39
|
+
return textarea.value;
|
|
40
|
+
}
|
|
32
41
|
class BloqueCheckout {
|
|
33
42
|
static globalConfig = null;
|
|
34
43
|
iframe = null;
|
|
35
44
|
options;
|
|
36
45
|
messageListener = null;
|
|
37
46
|
isReady = false;
|
|
47
|
+
threeDsOverlay = null;
|
|
48
|
+
threeDsTimers = [];
|
|
49
|
+
threeDsContentEl = null;
|
|
50
|
+
threeDsStatusEl = null;
|
|
38
51
|
static init(config) {
|
|
39
52
|
BloqueCheckout.globalConfig = config;
|
|
40
53
|
}
|
|
@@ -43,13 +56,15 @@ class BloqueCheckout {
|
|
|
43
56
|
}
|
|
44
57
|
constructor(options){
|
|
45
58
|
if (!options.checkoutId) throw new Error('[BloqueCheckout] checkoutId is required');
|
|
46
|
-
const
|
|
59
|
+
const publishableKey = options.publishableKey || options.publicApiKey || BloqueCheckout.globalConfig?.publishableKey || BloqueCheckout.globalConfig?.publicApiKey;
|
|
47
60
|
const mode = options.mode || BloqueCheckout.globalConfig?.mode || 'production';
|
|
48
61
|
const checkoutUrl = options.checkoutUrl || BloqueCheckout.globalConfig?.checkoutUrl || DEFAULT_CHECKOUT_URL;
|
|
49
|
-
if (!
|
|
62
|
+
if (!publishableKey) throw new Error('[BloqueCheckout] publishableKey (or publicApiKey) is required. Either pass it as an option or call BloqueCheckout.init() first.');
|
|
50
63
|
this.options = {
|
|
51
64
|
checkoutId: options.checkoutId,
|
|
52
|
-
|
|
65
|
+
clientSecret: options.clientSecret,
|
|
66
|
+
publishableKey,
|
|
67
|
+
publicApiKey: publishableKey,
|
|
53
68
|
mode,
|
|
54
69
|
checkoutUrl,
|
|
55
70
|
appearance: options.appearance,
|
|
@@ -61,7 +76,9 @@ class BloqueCheckout {
|
|
|
61
76
|
onSuccess: options.onSuccess,
|
|
62
77
|
onError: options.onError,
|
|
63
78
|
onPending: options.onPending,
|
|
64
|
-
iframeStyles: options.iframeStyles
|
|
79
|
+
iframeStyles: options.iframeStyles,
|
|
80
|
+
three_ds_auth_type: options.three_ds_auth_type,
|
|
81
|
+
onThreeDSChallenge: options.onThreeDSChallenge
|
|
65
82
|
};
|
|
66
83
|
}
|
|
67
84
|
createIframe() {
|
|
@@ -104,11 +121,14 @@ class BloqueCheckout {
|
|
|
104
121
|
}
|
|
105
122
|
setupMessageListener() {
|
|
106
123
|
this.messageListener = (event)=>{
|
|
107
|
-
const { type, data, error } = event.data || {};
|
|
124
|
+
const { type, data, error, threeDsData } = event.data || {};
|
|
108
125
|
switch(type){
|
|
109
126
|
case 'checkout-ready':
|
|
110
127
|
this.handleCheckoutReady();
|
|
111
128
|
break;
|
|
129
|
+
case '3ds-challenge':
|
|
130
|
+
this.handleThreeDSChallenge(threeDsData);
|
|
131
|
+
break;
|
|
112
132
|
case 'payment-result':
|
|
113
133
|
if (data) this.handlePaymentResult(data);
|
|
114
134
|
break;
|
|
@@ -126,17 +146,124 @@ class BloqueCheckout {
|
|
|
126
146
|
if (this.iframe?.contentWindow) this.iframe.contentWindow.postMessage({
|
|
127
147
|
type: 'checkout-init',
|
|
128
148
|
checkoutId: this.options.checkoutId,
|
|
149
|
+
clientSecret: this.options.clientSecret,
|
|
150
|
+
publishableKey: this.options.publishableKey,
|
|
129
151
|
publicApiKey: this.options.publicApiKey,
|
|
130
|
-
mode: this.options.mode
|
|
152
|
+
mode: this.options.mode,
|
|
153
|
+
...void 0 !== this.options.three_ds_auth_type ? {
|
|
154
|
+
three_ds_auth_type: this.options.three_ds_auth_type
|
|
155
|
+
} : {}
|
|
131
156
|
}, '*');
|
|
132
157
|
this.options.onReady?.();
|
|
133
158
|
}
|
|
159
|
+
clearThreeDsTimers() {
|
|
160
|
+
for (const t of this.threeDsTimers)clearTimeout(t);
|
|
161
|
+
this.threeDsTimers = [];
|
|
162
|
+
}
|
|
163
|
+
removeThreeDsOverlay() {
|
|
164
|
+
this.clearThreeDsTimers();
|
|
165
|
+
this.threeDsContentEl = null;
|
|
166
|
+
this.threeDsStatusEl = null;
|
|
167
|
+
if (this.threeDsOverlay?.parentNode) this.threeDsOverlay.parentNode.removeChild(this.threeDsOverlay);
|
|
168
|
+
this.threeDsOverlay = null;
|
|
169
|
+
}
|
|
170
|
+
setThreeDsStatus(text) {
|
|
171
|
+
if (this.threeDsStatusEl) this.threeDsStatusEl.textContent = text;
|
|
172
|
+
}
|
|
173
|
+
showMcLogoInContent() {
|
|
174
|
+
if (!this.threeDsContentEl) return;
|
|
175
|
+
this.threeDsContentEl.replaceChildren();
|
|
176
|
+
const wrap = document.createElement('div');
|
|
177
|
+
wrap.style.cssText = 'display:flex;align-items:center;justify-content:center;width:100%;min-height:400px;background:#fff;';
|
|
178
|
+
const img = document.createElement('img');
|
|
179
|
+
img.src = MC_ID_CHECK_LOGO_DATA_URI;
|
|
180
|
+
img.alt = 'Mastercard Identity Check';
|
|
181
|
+
img.style.cssText = 'width:256px;max-width:80%;height:auto;';
|
|
182
|
+
wrap.appendChild(img);
|
|
183
|
+
this.threeDsContentEl.appendChild(wrap);
|
|
184
|
+
}
|
|
185
|
+
handleThreeDSChallenge(data) {
|
|
186
|
+
if (!data?.iframe || "u" < typeof document) return;
|
|
187
|
+
this.options.onThreeDSChallenge?.();
|
|
188
|
+
this.removeThreeDsOverlay();
|
|
189
|
+
const root = document.createElement('div');
|
|
190
|
+
root.className = 'bloque-3ds-overlay';
|
|
191
|
+
root.style.cssText = 'position:fixed;inset:0;z-index:99999;background:rgba(0,0,0,0.5);display:flex;flex-direction:column;font-family:system-ui,sans-serif;';
|
|
192
|
+
const panel = document.createElement('div');
|
|
193
|
+
panel.style.cssText = 'margin:auto;width:min(480px,96vw);max-height:90vh;display:flex;flex-direction:column;background:#fff;border-radius:12px;overflow:hidden;box-shadow:0 25px 50px -12px rgba(0,0,0,0.25);';
|
|
194
|
+
const header = document.createElement('div');
|
|
195
|
+
header.style.cssText = 'display:flex;align-items:center;justify-content:space-between;padding:12px 16px;border-bottom:1px solid #e5e7eb;';
|
|
196
|
+
const title = document.createElement('span');
|
|
197
|
+
title.textContent = 'Verificación segura';
|
|
198
|
+
title.style.cssText = 'font-weight:600;font-size:15px;color:#111827;';
|
|
199
|
+
const closeBtn = document.createElement('button');
|
|
200
|
+
closeBtn.type = 'button';
|
|
201
|
+
closeBtn.setAttribute('aria-label', 'Cerrar');
|
|
202
|
+
closeBtn.textContent = '✕';
|
|
203
|
+
closeBtn.style.cssText = 'border:none;background:transparent;font-size:20px;line-height:1;cursor:pointer;color:#6b7280;padding:4px 8px;';
|
|
204
|
+
closeBtn.addEventListener('click', ()=>{
|
|
205
|
+
this.removeThreeDsOverlay();
|
|
206
|
+
this.options.onError?.('3D Secure verification was cancelled');
|
|
207
|
+
});
|
|
208
|
+
header.appendChild(title);
|
|
209
|
+
header.appendChild(closeBtn);
|
|
210
|
+
const statusEl = document.createElement('div');
|
|
211
|
+
statusEl.style.cssText = 'padding:8px 16px;font-size:13px;color:#4b5563;text-align:center;';
|
|
212
|
+
statusEl.textContent = 'Iniciando verificación segura...';
|
|
213
|
+
const contentEl = document.createElement('div');
|
|
214
|
+
contentEl.style.cssText = 'flex:1;min-height:400px;border-top:1px solid #e5e7eb;';
|
|
215
|
+
panel.appendChild(header);
|
|
216
|
+
panel.appendChild(statusEl);
|
|
217
|
+
panel.appendChild(contentEl);
|
|
218
|
+
root.appendChild(panel);
|
|
219
|
+
document.body.appendChild(root);
|
|
220
|
+
this.threeDsOverlay = root;
|
|
221
|
+
this.threeDsStatusEl = statusEl;
|
|
222
|
+
this.threeDsContentEl = contentEl;
|
|
223
|
+
this.showMcLogoInContent();
|
|
224
|
+
const decoded = decodeHtmlEntities(data.iframe);
|
|
225
|
+
const splashTimer = setTimeout(()=>{
|
|
226
|
+
this.setThreeDsStatus('Complete la verificación de su banco para continuar');
|
|
227
|
+
if (!this.threeDsContentEl) return;
|
|
228
|
+
this.threeDsContentEl.replaceChildren();
|
|
229
|
+
const frameWrap = document.createElement('div');
|
|
230
|
+
frameWrap.style.cssText = 'width:100%;min-height:400px;background:#fff;';
|
|
231
|
+
const iframeEl = document.createElement('iframe');
|
|
232
|
+
iframeEl.title = '3D Secure verification';
|
|
233
|
+
iframeEl.style.cssText = 'width:100%;height:400px;border:0;display:block;';
|
|
234
|
+
if (isUrl(decoded)) {
|
|
235
|
+
iframeEl.src = decoded.trim();
|
|
236
|
+
iframeEl.setAttribute('sandbox', "allow-scripts allow-forms allow-popups allow-same-origin");
|
|
237
|
+
} else {
|
|
238
|
+
iframeEl.srcdoc = decoded;
|
|
239
|
+
iframeEl.setAttribute('sandbox', "allow-scripts allow-forms allow-popups");
|
|
240
|
+
}
|
|
241
|
+
frameWrap.appendChild(iframeEl);
|
|
242
|
+
this.threeDsContentEl.appendChild(frameWrap);
|
|
243
|
+
}, 3000);
|
|
244
|
+
this.threeDsTimers.push(splashTimer);
|
|
245
|
+
}
|
|
134
246
|
handlePaymentResult(data) {
|
|
247
|
+
if (this.threeDsOverlay) return void this.finishThreeDsThenDispatch(data);
|
|
248
|
+
this.dispatchPaymentResult(data);
|
|
249
|
+
}
|
|
250
|
+
finishThreeDsThenDispatch(data) {
|
|
251
|
+
this.clearThreeDsTimers();
|
|
252
|
+
this.setThreeDsStatus('Autenticación completada, redirigiendo...');
|
|
253
|
+
this.showMcLogoInContent();
|
|
254
|
+
const t = setTimeout(()=>{
|
|
255
|
+
this.removeThreeDsOverlay();
|
|
256
|
+
this.dispatchPaymentResult(data);
|
|
257
|
+
}, 2000);
|
|
258
|
+
this.threeDsTimers.push(t);
|
|
259
|
+
}
|
|
260
|
+
dispatchPaymentResult(data) {
|
|
135
261
|
if ('approved' === data.status) this.options.onSuccess?.(data);
|
|
136
262
|
else if ('pending' === data.status) this.options.onPending?.(data);
|
|
137
263
|
else if ('rejected' === data.status) this.options.onError?.(data.message || 'Payment was rejected');
|
|
138
264
|
}
|
|
139
265
|
handlePaymentError(error) {
|
|
266
|
+
if (this.threeDsOverlay) this.removeThreeDsOverlay();
|
|
140
267
|
this.options.onError?.(error);
|
|
141
268
|
}
|
|
142
269
|
isCheckoutReady() {
|
|
@@ -154,6 +281,7 @@ class BloqueCheckout {
|
|
|
154
281
|
};
|
|
155
282
|
}
|
|
156
283
|
destroy() {
|
|
284
|
+
this.removeThreeDsOverlay();
|
|
157
285
|
if (this.iframe) {
|
|
158
286
|
this.iframe.remove();
|
|
159
287
|
this.iframe = null;
|
package/dist/index.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
export { BloqueCheckout, createCheckout, init } from './checkout';
|
|
2
|
-
export type { AppearanceConfig, BloqueCheckoutOptions, BloqueInitOptions, CheckoutMessage, CheckoutMessageType, PaymentMethod, PaymentResult, } from './types';
|
|
2
|
+
export type { AppearanceConfig, BloqueCheckoutOptions, BloqueInitOptions, CheckoutMessage, CheckoutMessageType, PaymentMethod, PaymentResult, ThreeDSChallengeData, } from './types';
|
package/dist/index.js
CHANGED
|
@@ -1,10 +1,23 @@
|
|
|
1
|
+
const MC_ID_CHECK_LOGO_DATA_URI = 'data:image/svg+xml;charset=utf-8,' + encodeURIComponent('<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 504.16287 144"><rect width="504.16287" height="144" fill="none"/><rect x="78.4951" y="43.6968" width="31.5" height="56.6064" fill="#ff5f00"/><path d="M224.41386,306a35.9375,35.9375,0,0,1,13.7499-28.3032,36,36,0,1,0,0,56.6064A35.938,35.938,0,0,1,224.41386,306Z" transform="translate(-143.91856 -234)" fill="#eb001b"/><path d="M296.409,306a35.99867,35.99867,0,0,1-58.24521,28.3032,36.00518,36.00518,0,0,0,0-56.6064A35.99867,35.99867,0,0,1,296.409,306Z" transform="translate(-143.91856 -234)" fill="#f79e1b"/><path d="M292.97436,328.3077v-1.1589h.4673v-.2361h-1.1901v.2361h.4675v1.1589Zm2.3105,0v-1.3973h-.3648l-.4196.9611-.4197-.9611h-.365v1.3973h.2576v-1.054l.3935.9087h.26711l.39349-.911v1.0563Z" transform="translate(-143.91856 -234)" fill="#f79e1b"/><polygon points="189.157 108.202 187.824 108.202 187.824 96.055 187.824 71.759 187.824 47.463 187.824 35.316 189.157 35.316 189.157 59.611 189.157 83.907 189.157 108.202"/><path d="M369.97109,328.30869h-3.74122V285.37558h3.74122Zm27.293-42.93311a29.13247,29.13247,0,0,1,9.66016,1.50244,20.54648,20.54648,0,0,1,7.29883,4.29346,18.82,18.82,0,0,1,4.62988,6.76172,25.2182,25.2182,0,0,1,0,17.81738,18.81762,18.81762,0,0,1-4.62988,6.76221,20.53928,20.53928,0,0,1-7.29883,4.29346,29.11984,29.11984,0,0,1-9.66016,1.50244H381.59316V285.37558Zm-11.92968,3.55713v35.81885h11.92968a24.72126,24.72126,0,0,0,8.28028-1.27295,16.77648,16.77648,0,0,0,6.041-3.603,15.0198,15.0198,0,0,0,3.71094-5.64306,22.35805,22.35805,0,0,0,0-14.78125,15.15681,15.15681,0,0,0-3.71094-5.65772,16.49932,16.49932,0,0,0-6.041-3.60351,25.01066,25.01066,0,0,0-8.28028-1.25733Zm78.6289-4.04785a22.97654,22.97654,0,0,1,5.33692.61328,21.59063,21.59063,0,0,1,4.8291,1.76319,19.26143,19.26143,0,0,1,4.0791,2.77539,17.01572,17.01572,0,0,1,3.1123,3.68017l-3.12793,2.085a15.116,15.116,0,0,0-2.62207-3.03564,16.4616,16.4616,0,0,0-3.34277-2.3003,17.16135,17.16135,0,0,0-3.9248-1.45654,18.46749,18.46749,0,0,0-4.33985-.50586,19.03537,19.03537,0,0,0-7.12988,1.31836,16.99574,16.99574,0,0,0-5.73438,3.7417,17.48439,17.48439,0,0,0-3.833,5.7959,20.75862,20.75862,0,0,0,0,14.96533,17.47928,17.47928,0,0,0,3.833,5.7959,16.98717,16.98717,0,0,0,5.73438,3.74121,19.01623,19.01623,0,0,0,7.12988,1.31885,18.82191,18.82191,0,0,0,4.32422-.49072,16.68442,16.68442,0,0,0,3.91016-1.44141,16.42818,16.42818,0,0,0,3.34277-2.2998,14.76727,14.76727,0,0,0,2.62207-3.0669l3.06641,2.23877a18.18515,18.18515,0,0,1-3.17383,3.61865,19.8084,19.8084,0,0,1-4.04785,2.72949,21.03046,21.03046,0,0,1-4.76856,1.73243,23.97561,23.97561,0,0,1-14-1.02735,21.025,21.025,0,0,1-6.97656-4.52343,20.74492,20.74492,0,0,1-4.61523-6.93067,24.37931,24.37931,0,0,1,0-17.74023,20.719,20.719,0,0,1,4.61523-6.94629,21.03249,21.03249,0,0,1,6.97656-4.52344A23.13114,23.13114,0,0,1,463.96327,284.88486Zm28.85742,19.56494a11.0293,11.0293,0,0,1,2.00879-2.45312,10.72962,10.72962,0,0,1,2.499-1.70215,12.47653,12.47653,0,0,1,2.82129-.981,13.73243,13.73243,0,0,1,2.94433-.32226,14.39955,14.39955,0,0,1,4.9375.8125,11.13893,11.13893,0,0,1,3.84863,2.31543,10.13945,10.13945,0,0,1,2.48438,3.66455,12.79658,12.79658,0,0,1,.874,4.83007v17.69483h-3.49609v-16.6211a11.82475,11.82475,0,0,0-.61328-3.92578,7.84633,7.84633,0,0,0-1.80957-2.959,7.9592,7.9592,0,0,0-2.91309-1.85547,11.13969,11.13969,0,0,0-3.92578-.644,10.2964,10.2964,0,0,0-3.78711.68994,9.05794,9.05794,0,0,0-3.0664,1.96289,9.23828,9.23828,0,0,0-2.05469,3.03564,9.78042,9.78042,0,0,0-.752,3.8794v16.4375H489.3246V284.14853h3.49609Zm43.21-5.45849a13.11521,13.11521,0,0,1,5.35058,1.08886,12.68765,12.68765,0,0,1,4.2627,3.03565,14.43555,14.43555,0,0,1,2.83691,4.66162,16.863,16.863,0,0,1,1.07324,5.93408c0,.26563-.00488.5166-.01465.751q-.01611.353-.04589.69043H525.29726a12.40913,12.40913,0,0,0,1.11914,4.477,10.56862,10.56862,0,0,0,2.43847,3.32715,10.27766,10.27766,0,0,0,3.44922,2.07031,12.11186,12.11186,0,0,0,4.15528.70508,12.80778,12.80778,0,0,0,5.42871-1.104,15.199,15.199,0,0,0,4.32324-3.00537l1.87109,2.39209a17.14471,17.14471,0,0,1-2.80566,2.30029,14.98357,14.98357,0,0,1-2.91406,1.47168,14.37333,14.37333,0,0,1-3.02051.76661,22.32086,22.32086,0,0,1-3.09668.21484,15.28005,15.28005,0,0,1-5.82715-1.08887,13.5515,13.5515,0,0,1-4.59961-3.05127,13.79423,13.79423,0,0,1-3.00586-4.69189,16.37017,16.37017,0,0,1-1.07324-6.04151A16.12411,16.12411,0,0,1,522.82851,307.9a14.25392,14.25392,0,0,1,3.00488-4.72266,13.57607,13.57607,0,0,1,4.53906-3.082A14.43287,14.43287,0,0,1,536.03066,298.99131Zm-.06153,3.09716a10.50706,10.50706,0,0,0-4.0332.75147,10.10774,10.10774,0,0,0-3.2041,2.08545,10.81339,10.81339,0,0,0-2.25391,3.17383,12.58891,12.58891,0,0,0-1.11914,4.04834h20.63867a12.478,12.478,0,0,0-1.01269-4.09424,10.31139,10.31139,0,0,0-2.16211-3.17383,9.61078,9.61078,0,0,0-6.85352-2.791Zm33.70117-3.09716a15.28282,15.28282,0,0,1,5.96485,1.1499,12.75921,12.75921,0,0,1,4.67676,3.32763l-2.26954,2.36133a12.53947,12.53947,0,0,0-3.78711-2.62207,11.37194,11.37194,0,0,0-4.67675-.93554,11.053,11.053,0,0,0-4.40039.874,10.80754,10.80754,0,0,0-3.542,2.42285,11.07186,11.07186,0,0,0-2.34668,3.67969,13.22753,13.22753,0,0,0,0,9.292,10.74991,10.74991,0,0,0,5.88868,6.07227,11.053,11.053,0,0,0,4.40039.874,11.31977,11.31977,0,0,0,4.73828-.98145,13.16026,13.16026,0,0,0,3.81738-2.60644l2.17774,2.39209a13.07136,13.07136,0,0,1-4.69239,3.32715,16.10337,16.10337,0,0,1-11.91406.01513,13.92431,13.92431,0,0,1-7.72754-7.835,16.58924,16.58924,0,0,1,0-11.82226,13.88959,13.88959,0,0,1,7.72754-7.85059A15.3168,15.3168,0,0,1,569.6703,298.99131Zm21.15918,12.63476h4.69239l12.14355-12.1748h4.416l-13.73828,13.61621,13.98339,15.24121h-4.44629l-12.35839-13.52393h-4.69239v13.52393h-3.49609V284.14853h3.49609Z" transform="translate(-143.91856 -234)"/></svg>');
|
|
1
2
|
const DEFAULT_CHECKOUT_URL = 'https://payments.bloque.app/checkout';
|
|
3
|
+
function isUrl(s) {
|
|
4
|
+
return /^https?:\/\//i.test(s.trim());
|
|
5
|
+
}
|
|
6
|
+
function decodeHtmlEntities(encoded) {
|
|
7
|
+
const textarea = document.createElement('textarea');
|
|
8
|
+
textarea.innerHTML = encoded;
|
|
9
|
+
return textarea.value;
|
|
10
|
+
}
|
|
2
11
|
class BloqueCheckout {
|
|
3
12
|
static globalConfig = null;
|
|
4
13
|
iframe = null;
|
|
5
14
|
options;
|
|
6
15
|
messageListener = null;
|
|
7
16
|
isReady = false;
|
|
17
|
+
threeDsOverlay = null;
|
|
18
|
+
threeDsTimers = [];
|
|
19
|
+
threeDsContentEl = null;
|
|
20
|
+
threeDsStatusEl = null;
|
|
8
21
|
static init(config) {
|
|
9
22
|
BloqueCheckout.globalConfig = config;
|
|
10
23
|
}
|
|
@@ -13,13 +26,15 @@ class BloqueCheckout {
|
|
|
13
26
|
}
|
|
14
27
|
constructor(options){
|
|
15
28
|
if (!options.checkoutId) throw new Error('[BloqueCheckout] checkoutId is required');
|
|
16
|
-
const
|
|
29
|
+
const publishableKey = options.publishableKey || options.publicApiKey || BloqueCheckout.globalConfig?.publishableKey || BloqueCheckout.globalConfig?.publicApiKey;
|
|
17
30
|
const mode = options.mode || BloqueCheckout.globalConfig?.mode || 'production';
|
|
18
31
|
const checkoutUrl = options.checkoutUrl || BloqueCheckout.globalConfig?.checkoutUrl || DEFAULT_CHECKOUT_URL;
|
|
19
|
-
if (!
|
|
32
|
+
if (!publishableKey) throw new Error('[BloqueCheckout] publishableKey (or publicApiKey) is required. Either pass it as an option or call BloqueCheckout.init() first.');
|
|
20
33
|
this.options = {
|
|
21
34
|
checkoutId: options.checkoutId,
|
|
22
|
-
|
|
35
|
+
clientSecret: options.clientSecret,
|
|
36
|
+
publishableKey,
|
|
37
|
+
publicApiKey: publishableKey,
|
|
23
38
|
mode,
|
|
24
39
|
checkoutUrl,
|
|
25
40
|
appearance: options.appearance,
|
|
@@ -31,7 +46,9 @@ class BloqueCheckout {
|
|
|
31
46
|
onSuccess: options.onSuccess,
|
|
32
47
|
onError: options.onError,
|
|
33
48
|
onPending: options.onPending,
|
|
34
|
-
iframeStyles: options.iframeStyles
|
|
49
|
+
iframeStyles: options.iframeStyles,
|
|
50
|
+
three_ds_auth_type: options.three_ds_auth_type,
|
|
51
|
+
onThreeDSChallenge: options.onThreeDSChallenge
|
|
35
52
|
};
|
|
36
53
|
}
|
|
37
54
|
createIframe() {
|
|
@@ -74,11 +91,14 @@ class BloqueCheckout {
|
|
|
74
91
|
}
|
|
75
92
|
setupMessageListener() {
|
|
76
93
|
this.messageListener = (event)=>{
|
|
77
|
-
const { type, data, error } = event.data || {};
|
|
94
|
+
const { type, data, error, threeDsData } = event.data || {};
|
|
78
95
|
switch(type){
|
|
79
96
|
case 'checkout-ready':
|
|
80
97
|
this.handleCheckoutReady();
|
|
81
98
|
break;
|
|
99
|
+
case '3ds-challenge':
|
|
100
|
+
this.handleThreeDSChallenge(threeDsData);
|
|
101
|
+
break;
|
|
82
102
|
case 'payment-result':
|
|
83
103
|
if (data) this.handlePaymentResult(data);
|
|
84
104
|
break;
|
|
@@ -96,17 +116,124 @@ class BloqueCheckout {
|
|
|
96
116
|
if (this.iframe?.contentWindow) this.iframe.contentWindow.postMessage({
|
|
97
117
|
type: 'checkout-init',
|
|
98
118
|
checkoutId: this.options.checkoutId,
|
|
119
|
+
clientSecret: this.options.clientSecret,
|
|
120
|
+
publishableKey: this.options.publishableKey,
|
|
99
121
|
publicApiKey: this.options.publicApiKey,
|
|
100
|
-
mode: this.options.mode
|
|
122
|
+
mode: this.options.mode,
|
|
123
|
+
...void 0 !== this.options.three_ds_auth_type ? {
|
|
124
|
+
three_ds_auth_type: this.options.three_ds_auth_type
|
|
125
|
+
} : {}
|
|
101
126
|
}, '*');
|
|
102
127
|
this.options.onReady?.();
|
|
103
128
|
}
|
|
129
|
+
clearThreeDsTimers() {
|
|
130
|
+
for (const t of this.threeDsTimers)clearTimeout(t);
|
|
131
|
+
this.threeDsTimers = [];
|
|
132
|
+
}
|
|
133
|
+
removeThreeDsOverlay() {
|
|
134
|
+
this.clearThreeDsTimers();
|
|
135
|
+
this.threeDsContentEl = null;
|
|
136
|
+
this.threeDsStatusEl = null;
|
|
137
|
+
if (this.threeDsOverlay?.parentNode) this.threeDsOverlay.parentNode.removeChild(this.threeDsOverlay);
|
|
138
|
+
this.threeDsOverlay = null;
|
|
139
|
+
}
|
|
140
|
+
setThreeDsStatus(text) {
|
|
141
|
+
if (this.threeDsStatusEl) this.threeDsStatusEl.textContent = text;
|
|
142
|
+
}
|
|
143
|
+
showMcLogoInContent() {
|
|
144
|
+
if (!this.threeDsContentEl) return;
|
|
145
|
+
this.threeDsContentEl.replaceChildren();
|
|
146
|
+
const wrap = document.createElement('div');
|
|
147
|
+
wrap.style.cssText = 'display:flex;align-items:center;justify-content:center;width:100%;min-height:400px;background:#fff;';
|
|
148
|
+
const img = document.createElement('img');
|
|
149
|
+
img.src = MC_ID_CHECK_LOGO_DATA_URI;
|
|
150
|
+
img.alt = 'Mastercard Identity Check';
|
|
151
|
+
img.style.cssText = 'width:256px;max-width:80%;height:auto;';
|
|
152
|
+
wrap.appendChild(img);
|
|
153
|
+
this.threeDsContentEl.appendChild(wrap);
|
|
154
|
+
}
|
|
155
|
+
handleThreeDSChallenge(data) {
|
|
156
|
+
if (!data?.iframe || "u" < typeof document) return;
|
|
157
|
+
this.options.onThreeDSChallenge?.();
|
|
158
|
+
this.removeThreeDsOverlay();
|
|
159
|
+
const root = document.createElement('div');
|
|
160
|
+
root.className = 'bloque-3ds-overlay';
|
|
161
|
+
root.style.cssText = 'position:fixed;inset:0;z-index:99999;background:rgba(0,0,0,0.5);display:flex;flex-direction:column;font-family:system-ui,sans-serif;';
|
|
162
|
+
const panel = document.createElement('div');
|
|
163
|
+
panel.style.cssText = 'margin:auto;width:min(480px,96vw);max-height:90vh;display:flex;flex-direction:column;background:#fff;border-radius:12px;overflow:hidden;box-shadow:0 25px 50px -12px rgba(0,0,0,0.25);';
|
|
164
|
+
const header = document.createElement('div');
|
|
165
|
+
header.style.cssText = 'display:flex;align-items:center;justify-content:space-between;padding:12px 16px;border-bottom:1px solid #e5e7eb;';
|
|
166
|
+
const title = document.createElement('span');
|
|
167
|
+
title.textContent = 'Verificación segura';
|
|
168
|
+
title.style.cssText = 'font-weight:600;font-size:15px;color:#111827;';
|
|
169
|
+
const closeBtn = document.createElement('button');
|
|
170
|
+
closeBtn.type = 'button';
|
|
171
|
+
closeBtn.setAttribute('aria-label', 'Cerrar');
|
|
172
|
+
closeBtn.textContent = '✕';
|
|
173
|
+
closeBtn.style.cssText = 'border:none;background:transparent;font-size:20px;line-height:1;cursor:pointer;color:#6b7280;padding:4px 8px;';
|
|
174
|
+
closeBtn.addEventListener('click', ()=>{
|
|
175
|
+
this.removeThreeDsOverlay();
|
|
176
|
+
this.options.onError?.('3D Secure verification was cancelled');
|
|
177
|
+
});
|
|
178
|
+
header.appendChild(title);
|
|
179
|
+
header.appendChild(closeBtn);
|
|
180
|
+
const statusEl = document.createElement('div');
|
|
181
|
+
statusEl.style.cssText = 'padding:8px 16px;font-size:13px;color:#4b5563;text-align:center;';
|
|
182
|
+
statusEl.textContent = 'Iniciando verificación segura...';
|
|
183
|
+
const contentEl = document.createElement('div');
|
|
184
|
+
contentEl.style.cssText = 'flex:1;min-height:400px;border-top:1px solid #e5e7eb;';
|
|
185
|
+
panel.appendChild(header);
|
|
186
|
+
panel.appendChild(statusEl);
|
|
187
|
+
panel.appendChild(contentEl);
|
|
188
|
+
root.appendChild(panel);
|
|
189
|
+
document.body.appendChild(root);
|
|
190
|
+
this.threeDsOverlay = root;
|
|
191
|
+
this.threeDsStatusEl = statusEl;
|
|
192
|
+
this.threeDsContentEl = contentEl;
|
|
193
|
+
this.showMcLogoInContent();
|
|
194
|
+
const decoded = decodeHtmlEntities(data.iframe);
|
|
195
|
+
const splashTimer = setTimeout(()=>{
|
|
196
|
+
this.setThreeDsStatus('Complete la verificación de su banco para continuar');
|
|
197
|
+
if (!this.threeDsContentEl) return;
|
|
198
|
+
this.threeDsContentEl.replaceChildren();
|
|
199
|
+
const frameWrap = document.createElement('div');
|
|
200
|
+
frameWrap.style.cssText = 'width:100%;min-height:400px;background:#fff;';
|
|
201
|
+
const iframeEl = document.createElement('iframe');
|
|
202
|
+
iframeEl.title = '3D Secure verification';
|
|
203
|
+
iframeEl.style.cssText = 'width:100%;height:400px;border:0;display:block;';
|
|
204
|
+
if (isUrl(decoded)) {
|
|
205
|
+
iframeEl.src = decoded.trim();
|
|
206
|
+
iframeEl.setAttribute('sandbox', "allow-scripts allow-forms allow-popups allow-same-origin");
|
|
207
|
+
} else {
|
|
208
|
+
iframeEl.srcdoc = decoded;
|
|
209
|
+
iframeEl.setAttribute('sandbox', "allow-scripts allow-forms allow-popups");
|
|
210
|
+
}
|
|
211
|
+
frameWrap.appendChild(iframeEl);
|
|
212
|
+
this.threeDsContentEl.appendChild(frameWrap);
|
|
213
|
+
}, 3000);
|
|
214
|
+
this.threeDsTimers.push(splashTimer);
|
|
215
|
+
}
|
|
104
216
|
handlePaymentResult(data) {
|
|
217
|
+
if (this.threeDsOverlay) return void this.finishThreeDsThenDispatch(data);
|
|
218
|
+
this.dispatchPaymentResult(data);
|
|
219
|
+
}
|
|
220
|
+
finishThreeDsThenDispatch(data) {
|
|
221
|
+
this.clearThreeDsTimers();
|
|
222
|
+
this.setThreeDsStatus('Autenticación completada, redirigiendo...');
|
|
223
|
+
this.showMcLogoInContent();
|
|
224
|
+
const t = setTimeout(()=>{
|
|
225
|
+
this.removeThreeDsOverlay();
|
|
226
|
+
this.dispatchPaymentResult(data);
|
|
227
|
+
}, 2000);
|
|
228
|
+
this.threeDsTimers.push(t);
|
|
229
|
+
}
|
|
230
|
+
dispatchPaymentResult(data) {
|
|
105
231
|
if ('approved' === data.status) this.options.onSuccess?.(data);
|
|
106
232
|
else if ('pending' === data.status) this.options.onPending?.(data);
|
|
107
233
|
else if ('rejected' === data.status) this.options.onError?.(data.message || 'Payment was rejected');
|
|
108
234
|
}
|
|
109
235
|
handlePaymentError(error) {
|
|
236
|
+
if (this.threeDsOverlay) this.removeThreeDsOverlay();
|
|
110
237
|
this.options.onError?.(error);
|
|
111
238
|
}
|
|
112
239
|
isCheckoutReady() {
|
|
@@ -124,6 +251,7 @@ class BloqueCheckout {
|
|
|
124
251
|
};
|
|
125
252
|
}
|
|
126
253
|
destroy() {
|
|
254
|
+
this.removeThreeDsOverlay();
|
|
127
255
|
if (this.iframe) {
|
|
128
256
|
this.iframe.remove();
|
|
129
257
|
this.iframe = null;
|
package/dist/types/payment.d.ts
CHANGED
|
@@ -1,15 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Internal reference types. NOT exported from the @bloque/payments-core barrel.
|
|
3
|
+
* The canonical versions live in @bloque/payments.
|
|
4
|
+
*/
|
|
1
5
|
import type { PaymentSubmitPayload } from './payment-submit';
|
|
2
6
|
export type PaymentMethodType = 'card' | 'pse' | 'cash';
|
|
3
7
|
export interface CreatePaymentParams {
|
|
4
|
-
|
|
8
|
+
paymentUrn: string;
|
|
5
9
|
payment: PaymentSubmitPayload;
|
|
6
10
|
}
|
|
7
11
|
export interface PaymentResponse {
|
|
8
12
|
id: string;
|
|
9
13
|
object: 'payment';
|
|
10
|
-
status: '
|
|
14
|
+
status: 'approved' | 'rejected' | 'pending';
|
|
15
|
+
message: string;
|
|
11
16
|
amount: number;
|
|
12
17
|
currency: string;
|
|
13
18
|
created_at: string;
|
|
14
|
-
updated_at: string;
|
|
15
19
|
}
|
package/dist/types.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export type PaymentMethod = 'card' | 'pse';
|
|
1
|
+
export type PaymentMethod = 'card' | 'pse' | 'cash';
|
|
2
2
|
export interface AppearanceConfig {
|
|
3
3
|
/**
|
|
4
4
|
* Primary color for buttons and accents
|
|
@@ -18,9 +18,11 @@ export interface AppearanceConfig {
|
|
|
18
18
|
}
|
|
19
19
|
export interface BloqueInitOptions {
|
|
20
20
|
/**
|
|
21
|
-
* Your Bloque
|
|
21
|
+
* Your Bloque publishable API key (pk_live_... or pk_test_...)
|
|
22
22
|
*/
|
|
23
|
-
|
|
23
|
+
publishableKey?: string;
|
|
24
|
+
/** @deprecated Use publishableKey instead */
|
|
25
|
+
publicApiKey?: string;
|
|
24
26
|
/**
|
|
25
27
|
* Operation mode
|
|
26
28
|
* @default 'production'
|
|
@@ -38,8 +40,14 @@ export interface BloqueCheckoutOptions {
|
|
|
38
40
|
*/
|
|
39
41
|
checkoutId: string;
|
|
40
42
|
/**
|
|
41
|
-
*
|
|
43
|
+
* Checkout-scoped JWT returned from the create checkout API
|
|
44
|
+
*/
|
|
45
|
+
clientSecret?: string;
|
|
46
|
+
/**
|
|
47
|
+
* Your Bloque publishable key (pk_live_... or pk_test_...)
|
|
42
48
|
*/
|
|
49
|
+
publishableKey?: string;
|
|
50
|
+
/** @deprecated Use publishableKey instead */
|
|
43
51
|
publicApiKey?: string;
|
|
44
52
|
/**
|
|
45
53
|
* Operation mode (optional if you called BloqueCheckout.init())
|
|
@@ -88,6 +96,14 @@ export interface BloqueCheckoutOptions {
|
|
|
88
96
|
* Custom CSS styles to apply to the iframe
|
|
89
97
|
*/
|
|
90
98
|
iframeStyles?: Record<string, string>;
|
|
99
|
+
/**
|
|
100
|
+
* Sandbox-only Wompi 3DS scenario (e.g. challenge_v2). Forwarded to hosted checkout via checkout-init.
|
|
101
|
+
*/
|
|
102
|
+
three_ds_auth_type?: string;
|
|
103
|
+
/**
|
|
104
|
+
* Called when the hosted checkout starts a 3DS challenge (overlay is shown in the parent page).
|
|
105
|
+
*/
|
|
106
|
+
onThreeDSChallenge?: () => void;
|
|
91
107
|
}
|
|
92
108
|
export interface PaymentResult {
|
|
93
109
|
payment_id: string;
|
|
@@ -98,10 +114,14 @@ export interface PaymentResult {
|
|
|
98
114
|
reference: string;
|
|
99
115
|
created_at: string;
|
|
100
116
|
}
|
|
101
|
-
export type CheckoutMessageType = 'checkout-ready' | 'checkout-init' | 'payment-result' | 'payment-error';
|
|
117
|
+
export type CheckoutMessageType = 'checkout-ready' | 'checkout-init' | 'payment-result' | 'payment-error' | '3ds-challenge';
|
|
118
|
+
export interface ThreeDSChallengeData {
|
|
119
|
+
iframe: string;
|
|
120
|
+
}
|
|
102
121
|
export interface CheckoutMessage {
|
|
103
122
|
type: CheckoutMessageType;
|
|
104
123
|
checkoutId?: string;
|
|
105
124
|
data?: PaymentResult;
|
|
106
125
|
error?: string;
|
|
126
|
+
threeDsData?: ThreeDSChallengeData;
|
|
107
127
|
}
|