orderopia-ordering-api-client-vue 0.0.4 → 0.0.6
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/dist/index.cjs +34 -4
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +34 -4
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/index.cjs
CHANGED
|
@@ -55,6 +55,7 @@ function useBasket() {
|
|
|
55
55
|
var import_vue2 = require("vue");
|
|
56
56
|
|
|
57
57
|
// src/opayo/opayo3dsManager.ts
|
|
58
|
+
var import_orderopia_ordering_api_client2 = require("orderopia-ordering-api-client");
|
|
58
59
|
function isBrowser() {
|
|
59
60
|
return typeof window !== "undefined" && typeof document !== "undefined";
|
|
60
61
|
}
|
|
@@ -126,6 +127,9 @@ function hiddenInput(name, value) {
|
|
|
126
127
|
inp.value = value == null ? "" : String(value);
|
|
127
128
|
return inp;
|
|
128
129
|
}
|
|
130
|
+
function getChallengeRedirectUri() {
|
|
131
|
+
return (0, import_orderopia_ordering_api_client2.isOrderopiaDevMode)() ? "https://api-test.orderopia.com/Transactions/3ds/Challenge" : "https://api.orderopia.com/Transactions/3ds/Challenge";
|
|
132
|
+
}
|
|
129
133
|
var onOpayoCancelled;
|
|
130
134
|
function initializeIframe(responseType, acsUrl, pReq, cReq, redirectUri, transactionId) {
|
|
131
135
|
if (!isBrowser()) return;
|
|
@@ -177,8 +181,9 @@ function initializeIframe(responseType, acsUrl, pReq, cReq, redirectUri, transac
|
|
|
177
181
|
form.appendChild(hiddenInput("threeDSSessionData", transactionId));
|
|
178
182
|
}
|
|
179
183
|
} else {
|
|
184
|
+
const termUrl = redirectUri || "";
|
|
180
185
|
form.appendChild(hiddenInput("PaReq", pReq || ""));
|
|
181
|
-
form.appendChild(hiddenInput("TermUrl",
|
|
186
|
+
form.appendChild(hiddenInput("TermUrl", termUrl));
|
|
182
187
|
form.appendChild(hiddenInput("MD", transactionId || ""));
|
|
183
188
|
}
|
|
184
189
|
form.submit();
|
|
@@ -187,7 +192,7 @@ function initializeIframe(responseType, acsUrl, pReq, cReq, redirectUri, transac
|
|
|
187
192
|
document.body.removeChild(form);
|
|
188
193
|
} catch {
|
|
189
194
|
}
|
|
190
|
-
},
|
|
195
|
+
}, 1e6);
|
|
191
196
|
}
|
|
192
197
|
function closeOpayoIframe() {
|
|
193
198
|
if (!isBrowser()) return;
|
|
@@ -213,11 +218,33 @@ function run3DSecure(args) {
|
|
|
213
218
|
onOpened,
|
|
214
219
|
onClosed
|
|
215
220
|
} = args;
|
|
216
|
-
|
|
221
|
+
console.log("[3DS] run3DSecure called", {
|
|
222
|
+
responseType,
|
|
223
|
+
acsUrl,
|
|
224
|
+
transactionId,
|
|
225
|
+
redirectUriProvided: !!redirectUri,
|
|
226
|
+
redirectUriFinal: redirectUri ?? getChallengeRedirectUri(),
|
|
227
|
+
cReqType: typeof cReq,
|
|
228
|
+
cReqPreview: typeof cReq === "string" ? cReq.slice(0, 80) : cReq && typeof cReq === "object" ? JSON.stringify(cReq).slice(0, 120) : cReq
|
|
229
|
+
});
|
|
230
|
+
onOpayoCancelled = () => {
|
|
231
|
+
console.log("[3DS] onOpayoCancelled fired");
|
|
232
|
+
try {
|
|
233
|
+
onCancelled?.();
|
|
234
|
+
} catch {
|
|
235
|
+
}
|
|
236
|
+
};
|
|
217
237
|
return new Promise((resolve) => {
|
|
218
238
|
const handleMessage = (event) => {
|
|
219
239
|
const msg = String(event.data || "");
|
|
240
|
+
console.log("[3DS] message received", {
|
|
241
|
+
msg,
|
|
242
|
+
origin: event.origin,
|
|
243
|
+
sourceIsWindow: event.source === window,
|
|
244
|
+
sourceIsTop: event.source === window.top
|
|
245
|
+
});
|
|
220
246
|
if (msg === "OPAYO_CALLBACK_SUCCESS") {
|
|
247
|
+
console.log("[3DS] SUCCESS -> closing + resolve(true)");
|
|
221
248
|
closeOpayoIframe();
|
|
222
249
|
window.removeEventListener("message", handleMessage);
|
|
223
250
|
try {
|
|
@@ -226,6 +253,7 @@ function run3DSecure(args) {
|
|
|
226
253
|
}
|
|
227
254
|
resolve(true);
|
|
228
255
|
} else if (msg === "OPAYO_CALLBACK_FAILED") {
|
|
256
|
+
console.log("[3DS] FAILED -> closing + resolve(false)");
|
|
229
257
|
closeOpayoIframe();
|
|
230
258
|
window.removeEventListener("message", handleMessage);
|
|
231
259
|
try {
|
|
@@ -240,7 +268,9 @@ function run3DSecure(args) {
|
|
|
240
268
|
onOpened?.();
|
|
241
269
|
} catch {
|
|
242
270
|
}
|
|
243
|
-
|
|
271
|
+
const termUrl = redirectUri ?? getChallengeRedirectUri();
|
|
272
|
+
console.log("[3DS] initializing iframe", { termUrl });
|
|
273
|
+
initializeIframe(responseType, acsUrl, pReq, cReq, termUrl, transactionId);
|
|
244
274
|
});
|
|
245
275
|
}
|
|
246
276
|
function receiveOpayoResponse(message) {
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/composables/useBasket.ts","../src/composables/useOpayo3ds.ts","../src/opayo/opayo3dsManager.ts","../src/install.ts"],"sourcesContent":["// src/index.ts\r\nexport { useBasket } from './composables/useBasket'\r\nexport { useOpayo3ds } from './composables/useOpayo3ds'\r\nexport { receiveOpayoResponse } from './opayo/opayo3dsManager'\r\nexport { OrderopiaVuePlugin } from './install'\r\n","// src/composables/useBasket.ts\r\nimport { ref, computed, onScopeDispose } from 'vue'\r\nimport {\r\n basketManager,\r\n type BasketState\r\n} from 'orderopia-ordering-api-client'\r\n\r\nexport function useBasket() {\r\n // Start with current basket immediately\r\n const basket = ref<BasketState>(basketManager.getBasket())\r\n\r\n // Subscribe immediately (NOT in onMounted)\r\n const unsubscribe = basketManager.subscribe(state => {\r\n basket.value = state\r\n })\r\n\r\n // Auto-cleanup when the component/composable scope is destroyed\r\n onScopeDispose(() => {\r\n unsubscribe()\r\n })\r\n\r\n const totalQuantity = computed(() =>\r\n basket.value.items.reduce((sum, i) => sum + (i.quantity ?? 0), 0)\r\n )\r\n\r\n return {\r\n basket,\r\n totalQuantity,\r\n\r\n // pass-through helpers (nice DX)\r\n addToBasket: basketManager.addToBasket.bind(basketManager),\r\n removeFromBasket: basketManager.removeFromBasket.bind(basketManager),\r\n clearBasket: basketManager.clearBasket.bind(basketManager)\r\n }\r\n}\r\n","// src/composables/useOpayo3ds.ts\r\nimport { ref, onScopeDispose } from 'vue'\r\nimport { run3DSecure, closeOpayoIframe, type Run3DSecureArgs } from '../opayo/opayo3dsManager'\r\n\r\nexport function useOpayo3ds() {\r\n const isOpen = ref(false)\r\n const isRunning = ref(false)\r\n\r\n let disposed = false\r\n\r\n onScopeDispose(() => {\r\n disposed = true\r\n isOpen.value = false\r\n isRunning.value = false\r\n closeOpayoIframe()\r\n })\r\n\r\n async function run(args: Run3DSecureArgs) {\r\n if (disposed) return false\r\n\r\n isOpen.value = true\r\n isRunning.value = true\r\n\r\n try {\r\n const result = await run3DSecure({\r\n ...args,\r\n onOpened: () => {\r\n if (disposed) return\r\n isOpen.value = true\r\n args.onOpened?.()\r\n },\r\n onClosed: () => {\r\n if (disposed) return\r\n isOpen.value = false\r\n args.onClosed?.()\r\n },\r\n onCancelled: () => {\r\n if (disposed) return\r\n isOpen.value = false\r\n args.onCancelled?.()\r\n }\r\n })\r\n\r\n return result\r\n } finally {\r\n if (!disposed) {\r\n isRunning.value = false\r\n }\r\n }\r\n }\r\n\r\n function close() {\r\n isOpen.value = false\r\n isRunning.value = false\r\n closeOpayoIframe()\r\n }\r\n\r\n return {\r\n isOpen,\r\n isRunning,\r\n run,\r\n close\r\n }\r\n}\r\n","// src/opayo/opayo3dsManager.ts\r\ntype ResponseType = 'CHALLENGE' | 'FALLBACK'\r\n\r\nfunction isBrowser() {\r\n return typeof window !== 'undefined' && typeof document !== 'undefined'\r\n}\r\n\r\nfunction ensureThreedsContainer() {\r\n if (!isBrowser()) return null\r\n\r\n let el = document.getElementById('threeds-container') as HTMLDivElement | null\r\n if (!el) {\r\n el = document.createElement('div')\r\n el.id = 'threeds-container'\r\n el.style.position = 'fixed'\r\n el.style.inset = '0'\r\n el.style.display = 'none'\r\n el.style.background = 'rgba(0,0,0,0.35)'\r\n el.style.zIndex = '99999'\r\n document.body.appendChild(el)\r\n }\r\n return el\r\n}\r\n\r\n// UTF-8 -> Base64URL (no padding)\r\nfunction utf8ToBase64Url(str: string) {\r\n const bytes = new TextEncoder().encode(str)\r\n let bin = ''\r\n for (let i = 0; i < bytes.length; i++) bin += String.fromCharCode(bytes[i])\r\n const b64 = btoa(bin)\r\n return b64.replace(/\\+/g, '-').replace(/\\//g, '_').replace(/=+$/g, '')\r\n}\r\n\r\n// Base64URL -> Base64 (and add padding)\r\nfunction toStdBase64(b64url: string) {\r\n let s = b64url.replace(/-/g, '+').replace(/_/g, '/')\r\n const pad = s.length % 4\r\n if (pad) s += '==='.slice(pad - 1)\r\n return s\r\n}\r\n\r\nfunction safeAtobMaybeJson(b64ish: string) {\r\n try {\r\n return atob(toStdBase64(b64ish))\r\n } catch {\r\n return null\r\n }\r\n}\r\n\r\n// Normalize creq to Base64URL without padding.\r\nfunction normalizeCreq(input: unknown) {\r\n if (input == null) return ''\r\n\r\n // Object -> JSON\r\n if (typeof input === 'object') {\r\n try {\r\n return utf8ToBase64Url(JSON.stringify(input))\r\n } catch {\r\n // ignore\r\n }\r\n }\r\n\r\n let creq = String(input).trim()\r\n\r\n // If obviously JSON text\r\n if (/^\\s*\\{[\\s\\S]*\\}\\s*$/.test(creq)) {\r\n return utf8ToBase64Url(creq)\r\n }\r\n\r\n // If it looks URL-encoded, attempt a decode\r\n if (/%[0-9A-Fa-f]{2}/.test(creq) || creq.includes('%')) {\r\n try {\r\n creq = decodeURIComponent(creq)\r\n } catch {\r\n // ignore\r\n }\r\n }\r\n\r\n // Remove whitespace, convert spaces to '+'\r\n creq = creq.replace(/\\s+/g, '').replace(/ /g, '+')\r\n\r\n // If decodes to JSON, re-encode properly as UTF-8 base64url\r\n const maybe = safeAtobMaybeJson(creq)\r\n if (maybe && maybe.charCodeAt(0) === 123 /* '{' */) {\r\n return utf8ToBase64Url(maybe)\r\n }\r\n\r\n // Otherwise normalize to base64url and strip padding\r\n creq = creq.replace(/\\+/g, '-').replace(/\\//g, '_').replace(/=+$/g, '')\r\n return creq\r\n}\r\n\r\nfunction hiddenInput(name: string, value: unknown) {\r\n const inp = document.createElement('input')\r\n inp.type = 'hidden'\r\n inp.name = name\r\n inp.value = value == null ? '' : String(value)\r\n return inp\r\n}\r\n\r\nexport type Run3DSecureArgs = {\r\n responseType: ResponseType\r\n acsUrl: string\r\n pReq?: string | null\r\n cReq?: unknown\r\n redirectUri?: string | null\r\n transactionId?: string | null\r\n\r\n onCancelled?: () => void\r\n onOpened?: () => void\r\n onClosed?: () => void\r\n}\r\n\r\nlet onOpayoCancelled: (() => void) | undefined\r\n\r\nfunction initializeIframe(\r\n responseType: ResponseType,\r\n acsUrl: string,\r\n pReq?: string | null,\r\n cReq?: unknown,\r\n redirectUri?: string | null,\r\n transactionId?: string | null\r\n) {\r\n if (!isBrowser()) return\r\n\r\n const container = ensureThreedsContainer()\r\n if (!container) return\r\n\r\n container.style.display = 'block'\r\n container.textContent = ''\r\n\r\n const panel = document.createElement('div')\r\n panel.style.position = 'absolute'\r\n panel.style.top = '50%'\r\n panel.style.left = '50%'\r\n panel.style.transform = 'translate(-50%, -50%)'\r\n panel.style.width = 'min(100%, 500px)'\r\n panel.style.height = 'min(100%, 600px)'\r\n panel.style.background = 'var(--background, #fff)'\r\n panel.style.borderRadius = '10px'\r\n panel.style.boxShadow = '0 10px 30px rgba(0,0,0,0.2)'\r\n panel.style.display = 'flex'\r\n panel.style.flexDirection = 'column'\r\n panel.style.overflow = 'hidden'\r\n container.appendChild(panel)\r\n\r\n const msg = document.createElement('div')\r\n msg.style.padding = '16px'\r\n msg.style.fontFamily = 'sans-serif'\r\n msg.style.textAlign = 'center'\r\n msg.innerHTML =\r\n '<div style=\"font-weight:600;\">We’re redirecting you to your bank to complete the payment.</div>' +\r\n '<div style=\"margin-top:6px;\">This will only take a moment. Please <u>do not</u> refresh the page.</div>'\r\n panel.appendChild(msg)\r\n\r\n const iframeWrap = document.createElement('div')\r\n iframeWrap.style.flex = '1'\r\n iframeWrap.style.borderTop = '1px solid rgba(0,0,0,0.06)'\r\n panel.appendChild(iframeWrap)\r\n\r\n const iframeName = 'threeds_frame_' + Math.random().toString(36).slice(2)\r\n const iframe = document.createElement('iframe')\r\n iframe.name = iframeName\r\n iframe.title = '3-D Secure Authentication'\r\n iframe.style.width = '100%'\r\n iframe.style.height = '100%'\r\n iframe.style.border = '0'\r\n iframeWrap.appendChild(iframe)\r\n\r\n const form = document.createElement('form')\r\n form.style.display = 'none'\r\n form.method = 'POST'\r\n form.action = acsUrl\r\n form.target = iframeName\r\n document.body.appendChild(form)\r\n\r\n if (responseType === 'CHALLENGE') {\r\n // 3DS v2\r\n form.appendChild(hiddenInput('creq', normalizeCreq(cReq)))\r\n if (transactionId) {\r\n // Optional echo field (send as-is)\r\n form.appendChild(hiddenInput('threeDSSessionData', transactionId))\r\n }\r\n } else {\r\n // 3DS v1 fallback\r\n form.appendChild(hiddenInput('PaReq', pReq || ''))\r\n form.appendChild(hiddenInput('TermUrl', redirectUri || ''))\r\n form.appendChild(hiddenInput('MD', transactionId || ''))\r\n }\r\n\r\n form.submit()\r\n\r\n setTimeout(() => {\r\n try {\r\n document.body.removeChild(form)\r\n } catch {\r\n // ignore\r\n }\r\n }, 1000)\r\n}\r\n\r\nexport function closeOpayoIframe() {\r\n if (!isBrowser()) return\r\n const container = document.getElementById('threeds-container') as HTMLDivElement | null\r\n if (!container) return\r\n\r\n container.innerHTML = ''\r\n container.style.display = 'none'\r\n\r\n try {\r\n onOpayoCancelled?.()\r\n } catch {\r\n // ignore\r\n }\r\n}\r\n\r\nexport function run3DSecure(args: Run3DSecureArgs) {\r\n if (!isBrowser()) return Promise.resolve(false)\r\n\r\n const {\r\n responseType,\r\n acsUrl,\r\n pReq,\r\n cReq,\r\n redirectUri,\r\n transactionId,\r\n onCancelled,\r\n onOpened,\r\n onClosed\r\n } = args\r\n\r\n onOpayoCancelled = onCancelled\r\n\r\n return new Promise<boolean>((resolve) => {\r\n const handleMessage = (event: MessageEvent) => {\r\n const msg = String((event as any).data || '')\r\n\r\n if (msg === 'OPAYO_CALLBACK_SUCCESS') {\r\n closeOpayoIframe()\r\n window.removeEventListener('message', handleMessage)\r\n try {\r\n onClosed?.()\r\n } catch {\r\n // ignore\r\n }\r\n resolve(true)\r\n } else if (msg === 'OPAYO_CALLBACK_FAILED') {\r\n closeOpayoIframe()\r\n window.removeEventListener('message', handleMessage)\r\n try {\r\n onClosed?.()\r\n } catch {\r\n // ignore\r\n }\r\n resolve(false)\r\n }\r\n }\r\n\r\n window.addEventListener('message', handleMessage)\r\n\r\n try {\r\n onOpened?.()\r\n } catch {\r\n // ignore\r\n }\r\n\r\n initializeIframe(responseType, acsUrl, pReq, cReq, redirectUri, transactionId)\r\n })\r\n}\r\n\r\n// Call this from your callback/return page.\r\n// It posts a signal back to the parent checkout window.\r\nexport function receiveOpayoResponse(message: unknown) {\r\n if (!isBrowser()) return\r\n\r\n const m = String(message || '')\r\n if (m === 'OPAYO_CALLBACK_FAILED' || m === 'OPAYO_CALLBACK_SUCCESS') {\r\n try {\r\n window.top?.postMessage(m, '*')\r\n } catch {\r\n // ignore\r\n }\r\n\r\n try {\r\n onOpayoCancelled?.()\r\n } catch {\r\n // ignore\r\n }\r\n }\r\n}\r\n","// src/install.ts\r\nimport type { App } from 'vue'\r\n\r\nexport function OrderopiaVuePlugin() {\r\n return {\r\n install(app: App) {\r\n // nothing yet, but future-proof\r\n }\r\n }\r\n}\r\n"],"mappings":"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","names":["import_vue"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/composables/useBasket.ts","../src/composables/useOpayo3ds.ts","../src/opayo/opayo3dsManager.ts","../src/install.ts"],"sourcesContent":["// src/index.ts\r\nexport { useBasket } from './composables/useBasket'\r\nexport { useOpayo3ds } from './composables/useOpayo3ds'\r\nexport { receiveOpayoResponse } from './opayo/opayo3dsManager'\r\nexport { OrderopiaVuePlugin } from './install'\r\n","// src/composables/useBasket.ts\r\nimport { ref, computed, onScopeDispose } from 'vue'\r\nimport {\r\n basketManager,\r\n type BasketState\r\n} from 'orderopia-ordering-api-client'\r\n\r\nexport function useBasket() {\r\n // Start with current basket immediately\r\n const basket = ref<BasketState>(basketManager.getBasket())\r\n\r\n // Subscribe immediately (NOT in onMounted)\r\n const unsubscribe = basketManager.subscribe(state => {\r\n basket.value = state\r\n })\r\n\r\n // Auto-cleanup when the component/composable scope is destroyed\r\n onScopeDispose(() => {\r\n unsubscribe()\r\n })\r\n\r\n const totalQuantity = computed(() =>\r\n basket.value.items.reduce((sum, i) => sum + (i.quantity ?? 0), 0)\r\n )\r\n\r\n return {\r\n basket,\r\n totalQuantity,\r\n\r\n // pass-through helpers (nice DX)\r\n addToBasket: basketManager.addToBasket.bind(basketManager),\r\n removeFromBasket: basketManager.removeFromBasket.bind(basketManager),\r\n clearBasket: basketManager.clearBasket.bind(basketManager)\r\n }\r\n}\r\n","// src/composables/useOpayo3ds.ts\r\nimport { ref, onScopeDispose } from 'vue'\r\nimport { run3DSecure, closeOpayoIframe, type Run3DSecureArgs } from '../opayo/opayo3dsManager'\r\n\r\nexport function useOpayo3ds() {\r\n const isOpen = ref(false)\r\n const isRunning = ref(false)\r\n\r\n let disposed = false\r\n\r\n onScopeDispose(() => {\r\n disposed = true\r\n isOpen.value = false\r\n isRunning.value = false\r\n closeOpayoIframe()\r\n })\r\n\r\n async function run(args: Run3DSecureArgs) {\r\n if (disposed) return false\r\n\r\n isOpen.value = true\r\n isRunning.value = true\r\n\r\n try {\r\n const result = await run3DSecure({\r\n ...args,\r\n onOpened: () => {\r\n if (disposed) return\r\n isOpen.value = true\r\n args.onOpened?.()\r\n },\r\n onClosed: () => {\r\n if (disposed) return\r\n isOpen.value = false\r\n args.onClosed?.()\r\n },\r\n onCancelled: () => {\r\n if (disposed) return\r\n isOpen.value = false\r\n args.onCancelled?.()\r\n }\r\n })\r\n\r\n return result\r\n } finally {\r\n if (!disposed) {\r\n isRunning.value = false\r\n }\r\n }\r\n }\r\n\r\n function close() {\r\n isOpen.value = false\r\n isRunning.value = false\r\n closeOpayoIframe()\r\n }\r\n\r\n return {\r\n isOpen,\r\n isRunning,\r\n run,\r\n close\r\n }\r\n}\r\n","// src/opayo/opayo3dsManager.ts\r\n\r\ntype ResponseType = 'CHALLENGE' | 'FALLBACK'\r\n\r\nfunction isBrowser() {\r\n return typeof window !== 'undefined' && typeof document !== 'undefined'\r\n}\r\n\r\nfunction ensureThreedsContainer() {\r\n if (!isBrowser()) return null\r\n\r\n let el = document.getElementById('threeds-container') as HTMLDivElement | null\r\n if (!el) {\r\n el = document.createElement('div')\r\n el.id = 'threeds-container'\r\n el.style.position = 'fixed'\r\n el.style.inset = '0'\r\n el.style.display = 'none'\r\n el.style.background = 'rgba(0,0,0,0.35)'\r\n el.style.zIndex = '99999'\r\n document.body.appendChild(el)\r\n }\r\n return el\r\n}\r\n\r\n// UTF-8 -> Base64URL (no padding)\r\nfunction utf8ToBase64Url(str: string) {\r\n const bytes = new TextEncoder().encode(str)\r\n let bin = ''\r\n for (let i = 0; i < bytes.length; i++) bin += String.fromCharCode(bytes[i])\r\n const b64 = btoa(bin)\r\n return b64.replace(/\\+/g, '-').replace(/\\//g, '_').replace(/=+$/g, '')\r\n}\r\n\r\n// Base64URL -> Base64 (and add padding)\r\nfunction toStdBase64(b64url: string) {\r\n let s = b64url.replace(/-/g, '+').replace(/_/g, '/')\r\n const pad = s.length % 4\r\n if (pad) s += '==='.slice(pad - 1)\r\n return s\r\n}\r\n\r\nfunction safeAtobMaybeJson(b64ish: string) {\r\n try {\r\n return atob(toStdBase64(b64ish))\r\n } catch {\r\n return null\r\n }\r\n}\r\n\r\n// Normalize creq to Base64URL without padding.\r\nfunction normalizeCreq(input: unknown) {\r\n if (input == null) return ''\r\n\r\n // Object -> JSON\r\n if (typeof input === 'object') {\r\n try {\r\n return utf8ToBase64Url(JSON.stringify(input))\r\n } catch {\r\n // ignore\r\n }\r\n }\r\n\r\n let creq = String(input).trim()\r\n\r\n // If obviously JSON text\r\n if (/^\\s*\\{[\\s\\S]*\\}\\s*$/.test(creq)) {\r\n return utf8ToBase64Url(creq)\r\n }\r\n\r\n // If it looks URL-encoded, attempt a decode\r\n if (/%[0-9A-Fa-f]{2}/.test(creq) || creq.includes('%')) {\r\n try {\r\n creq = decodeURIComponent(creq)\r\n } catch {\r\n // ignore\r\n }\r\n }\r\n\r\n // Remove whitespace, convert spaces to '+'\r\n creq = creq.replace(/\\s+/g, '').replace(/ /g, '+')\r\n\r\n // If decodes to JSON, re-encode properly as UTF-8 base64url\r\n const maybe = safeAtobMaybeJson(creq)\r\n if (maybe && maybe.charCodeAt(0) === 123 /* '{' */) {\r\n return utf8ToBase64Url(maybe)\r\n }\r\n\r\n // Otherwise normalize to base64url and strip padding\r\n creq = creq.replace(/\\+/g, '-').replace(/\\//g, '_').replace(/=+$/g, '')\r\n return creq\r\n}\r\n\r\nfunction hiddenInput(name: string, value: unknown) {\r\n const inp = document.createElement('input')\r\n inp.type = 'hidden'\r\n inp.name = name\r\n inp.value = value == null ? '' : String(value)\r\n return inp\r\n}\r\n\r\n/**\r\n * ✅ Pull env from the core client (prod/dev toggle you built)\r\n * NOTE: Adjust the import path to whatever you export publicly from the client package.\r\n */\r\nimport { isOrderopiaDevMode } from 'orderopia-ordering-api-client'\r\n\r\nfunction getChallengeRedirectUri(): string {\r\n // TEMP values for now (your ask) — but environment-aware.\r\n // Replace these when you confirm the final endpoint paths.\r\n return isOrderopiaDevMode()\r\n ? 'https://api-test.orderopia.com/Transactions/3ds/Challenge'\r\n : 'https://api.orderopia.com/Transactions/3ds/Challenge'\r\n}\r\n\r\nexport type Run3DSecureArgs = {\r\n responseType: ResponseType\r\n acsUrl: string\r\n pReq?: string | null\r\n cReq?: unknown\r\n redirectUri?: string | null\r\n transactionId?: string | null\r\n\r\n onCancelled?: () => void\r\n onOpened?: () => void\r\n onClosed?: () => void\r\n}\r\n\r\nlet onOpayoCancelled: (() => void) | undefined\r\n\r\nfunction initializeIframe(\r\n responseType: ResponseType,\r\n acsUrl: string,\r\n pReq?: string | null,\r\n cReq?: unknown,\r\n redirectUri?: string | null,\r\n transactionId?: string | null\r\n) {\r\n if (!isBrowser()) return\r\n\r\n const container = ensureThreedsContainer()\r\n if (!container) return\r\n\r\n container.style.display = 'block'\r\n container.textContent = ''\r\n\r\n const panel = document.createElement('div')\r\n panel.style.position = 'absolute'\r\n panel.style.top = '50%'\r\n panel.style.left = '50%'\r\n panel.style.transform = 'translate(-50%, -50%)'\r\n panel.style.width = 'min(100%, 500px)'\r\n panel.style.height = 'min(100%, 600px)'\r\n panel.style.background = 'var(--background, #fff)'\r\n panel.style.borderRadius = '10px'\r\n panel.style.boxShadow = '0 10px 30px rgba(0,0,0,0.2)'\r\n panel.style.display = 'flex'\r\n panel.style.flexDirection = 'column'\r\n panel.style.overflow = 'hidden'\r\n container.appendChild(panel)\r\n\r\n const msg = document.createElement('div')\r\n msg.style.padding = '16px'\r\n msg.style.fontFamily = 'sans-serif'\r\n msg.style.textAlign = 'center'\r\n msg.innerHTML =\r\n '<div style=\"font-weight:600;\">We’re redirecting you to your bank to complete the payment.</div>' +\r\n '<div style=\"margin-top:6px;\">This will only take a moment. Please <u>do not</u> refresh the page.</div>'\r\n panel.appendChild(msg)\r\n\r\n const iframeWrap = document.createElement('div')\r\n iframeWrap.style.flex = '1'\r\n iframeWrap.style.borderTop = '1px solid rgba(0,0,0,0.06)'\r\n panel.appendChild(iframeWrap)\r\n\r\n const iframeName = 'threeds_frame_' + Math.random().toString(36).slice(2)\r\n const iframe = document.createElement('iframe')\r\n iframe.name = iframeName\r\n iframe.title = '3-D Secure Authentication'\r\n iframe.style.width = '100%'\r\n iframe.style.height = '100%'\r\n iframe.style.border = '0'\r\n iframeWrap.appendChild(iframe)\r\n\r\n const form = document.createElement('form')\r\n form.style.display = 'none'\r\n form.method = 'POST'\r\n form.action = acsUrl\r\n form.target = iframeName\r\n document.body.appendChild(form)\r\n\r\n if (responseType === 'CHALLENGE') {\r\n // 3DS v2\r\n form.appendChild(hiddenInput('creq', normalizeCreq(cReq)))\r\n if (transactionId) {\r\n // Optional echo field (send as-is)\r\n form.appendChild(hiddenInput('threeDSSessionData', transactionId))\r\n }\r\n } else {\r\n // 3DS v1 fallback\r\n const termUrl = redirectUri || ''\r\n form.appendChild(hiddenInput('PaReq', pReq || ''))\r\n form.appendChild(hiddenInput('TermUrl', termUrl))\r\n form.appendChild(hiddenInput('MD', transactionId || ''))\r\n }\r\n\r\n form.submit()\r\n\r\n setTimeout(() => {\r\n try {\r\n document.body.removeChild(form)\r\n } catch {\r\n // ignore\r\n }\r\n }, 1000000)\r\n}\r\n\r\nexport function closeOpayoIframe() {\r\n if (!isBrowser()) return\r\n const container = document.getElementById('threeds-container') as HTMLDivElement | null\r\n if (!container) return\r\n\r\n container.innerHTML = ''\r\n container.style.display = 'none'\r\n\r\n try {\r\n onOpayoCancelled?.()\r\n } catch {\r\n // ignore\r\n }\r\n}\r\n\r\nexport function run3DSecure(args: Run3DSecureArgs) {\r\n if (!isBrowser()) return Promise.resolve(false)\r\n\r\n const {\r\n responseType,\r\n acsUrl,\r\n pReq,\r\n cReq,\r\n redirectUri,\r\n transactionId,\r\n onCancelled,\r\n onOpened,\r\n onClosed\r\n } = args\r\n\r\n console.log('[3DS] run3DSecure called', {\r\n responseType,\r\n acsUrl,\r\n transactionId,\r\n redirectUriProvided: !!redirectUri,\r\n redirectUriFinal: redirectUri ?? getChallengeRedirectUri(),\r\n cReqType: typeof cReq,\r\n cReqPreview:\r\n typeof cReq === 'string'\r\n ? cReq.slice(0, 80)\r\n : cReq && typeof cReq === 'object'\r\n ? JSON.stringify(cReq).slice(0, 120)\r\n : cReq\r\n })\r\n\r\n onOpayoCancelled = () => {\r\n console.log('[3DS] onOpayoCancelled fired')\r\n try {\r\n onCancelled?.()\r\n } catch {\r\n // ignore\r\n }\r\n }\r\n\r\n return new Promise<boolean>((resolve) => {\r\n const handleMessage = (event: MessageEvent) => {\r\n const msg = String((event as any).data || '')\r\n console.log('[3DS] message received', {\r\n msg,\r\n origin: event.origin,\r\n sourceIsWindow: event.source === window,\r\n sourceIsTop: event.source === window.top\r\n })\r\n\r\n if (msg === 'OPAYO_CALLBACK_SUCCESS') {\r\n console.log('[3DS] SUCCESS -> closing + resolve(true)')\r\n closeOpayoIframe()\r\n window.removeEventListener('message', handleMessage)\r\n try {\r\n onClosed?.()\r\n } catch {}\r\n resolve(true)\r\n } else if (msg === 'OPAYO_CALLBACK_FAILED') {\r\n console.log('[3DS] FAILED -> closing + resolve(false)')\r\n closeOpayoIframe()\r\n window.removeEventListener('message', handleMessage)\r\n try {\r\n onClosed?.()\r\n } catch {}\r\n resolve(false)\r\n }\r\n }\r\n\r\n window.addEventListener('message', handleMessage)\r\n\r\n try {\r\n onOpened?.()\r\n } catch {}\r\n\r\n const termUrl = redirectUri ?? getChallengeRedirectUri()\r\n console.log('[3DS] initializing iframe', { termUrl })\r\n\r\n initializeIframe(responseType, acsUrl, pReq, cReq, termUrl, transactionId)\r\n })\r\n}\r\n\r\n// Call this from your callback/return page.\r\n// It posts a signal back to the parent checkout window.\r\nexport function receiveOpayoResponse(message: unknown) {\r\n if (!isBrowser()) return\r\n\r\n const m = String(message || '')\r\n if (m === 'OPAYO_CALLBACK_FAILED' || m === 'OPAYO_CALLBACK_SUCCESS') {\r\n try {\r\n window.top?.postMessage(m, '*')\r\n } catch {\r\n // ignore\r\n }\r\n\r\n try {\r\n onOpayoCancelled?.()\r\n } catch {\r\n // ignore\r\n }\r\n }\r\n}\r\n","// src/install.ts\r\nimport type { App } from 'vue'\r\n\r\nexport function OrderopiaVuePlugin() {\r\n return {\r\n install(app: App) {\r\n // nothing yet, but future-proof\r\n }\r\n }\r\n}\r\n"],"mappings":"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","names":["import_vue","import_orderopia_ordering_api_client"]}
|
package/dist/index.js
CHANGED
|
@@ -28,6 +28,7 @@ function useBasket() {
|
|
|
28
28
|
import { ref as ref2, onScopeDispose as onScopeDispose2 } from "vue";
|
|
29
29
|
|
|
30
30
|
// src/opayo/opayo3dsManager.ts
|
|
31
|
+
import { isOrderopiaDevMode } from "orderopia-ordering-api-client";
|
|
31
32
|
function isBrowser() {
|
|
32
33
|
return typeof window !== "undefined" && typeof document !== "undefined";
|
|
33
34
|
}
|
|
@@ -99,6 +100,9 @@ function hiddenInput(name, value) {
|
|
|
99
100
|
inp.value = value == null ? "" : String(value);
|
|
100
101
|
return inp;
|
|
101
102
|
}
|
|
103
|
+
function getChallengeRedirectUri() {
|
|
104
|
+
return isOrderopiaDevMode() ? "https://api-test.orderopia.com/Transactions/3ds/Challenge" : "https://api.orderopia.com/Transactions/3ds/Challenge";
|
|
105
|
+
}
|
|
102
106
|
var onOpayoCancelled;
|
|
103
107
|
function initializeIframe(responseType, acsUrl, pReq, cReq, redirectUri, transactionId) {
|
|
104
108
|
if (!isBrowser()) return;
|
|
@@ -150,8 +154,9 @@ function initializeIframe(responseType, acsUrl, pReq, cReq, redirectUri, transac
|
|
|
150
154
|
form.appendChild(hiddenInput("threeDSSessionData", transactionId));
|
|
151
155
|
}
|
|
152
156
|
} else {
|
|
157
|
+
const termUrl = redirectUri || "";
|
|
153
158
|
form.appendChild(hiddenInput("PaReq", pReq || ""));
|
|
154
|
-
form.appendChild(hiddenInput("TermUrl",
|
|
159
|
+
form.appendChild(hiddenInput("TermUrl", termUrl));
|
|
155
160
|
form.appendChild(hiddenInput("MD", transactionId || ""));
|
|
156
161
|
}
|
|
157
162
|
form.submit();
|
|
@@ -160,7 +165,7 @@ function initializeIframe(responseType, acsUrl, pReq, cReq, redirectUri, transac
|
|
|
160
165
|
document.body.removeChild(form);
|
|
161
166
|
} catch {
|
|
162
167
|
}
|
|
163
|
-
},
|
|
168
|
+
}, 1e6);
|
|
164
169
|
}
|
|
165
170
|
function closeOpayoIframe() {
|
|
166
171
|
if (!isBrowser()) return;
|
|
@@ -186,11 +191,33 @@ function run3DSecure(args) {
|
|
|
186
191
|
onOpened,
|
|
187
192
|
onClosed
|
|
188
193
|
} = args;
|
|
189
|
-
|
|
194
|
+
console.log("[3DS] run3DSecure called", {
|
|
195
|
+
responseType,
|
|
196
|
+
acsUrl,
|
|
197
|
+
transactionId,
|
|
198
|
+
redirectUriProvided: !!redirectUri,
|
|
199
|
+
redirectUriFinal: redirectUri ?? getChallengeRedirectUri(),
|
|
200
|
+
cReqType: typeof cReq,
|
|
201
|
+
cReqPreview: typeof cReq === "string" ? cReq.slice(0, 80) : cReq && typeof cReq === "object" ? JSON.stringify(cReq).slice(0, 120) : cReq
|
|
202
|
+
});
|
|
203
|
+
onOpayoCancelled = () => {
|
|
204
|
+
console.log("[3DS] onOpayoCancelled fired");
|
|
205
|
+
try {
|
|
206
|
+
onCancelled?.();
|
|
207
|
+
} catch {
|
|
208
|
+
}
|
|
209
|
+
};
|
|
190
210
|
return new Promise((resolve) => {
|
|
191
211
|
const handleMessage = (event) => {
|
|
192
212
|
const msg = String(event.data || "");
|
|
213
|
+
console.log("[3DS] message received", {
|
|
214
|
+
msg,
|
|
215
|
+
origin: event.origin,
|
|
216
|
+
sourceIsWindow: event.source === window,
|
|
217
|
+
sourceIsTop: event.source === window.top
|
|
218
|
+
});
|
|
193
219
|
if (msg === "OPAYO_CALLBACK_SUCCESS") {
|
|
220
|
+
console.log("[3DS] SUCCESS -> closing + resolve(true)");
|
|
194
221
|
closeOpayoIframe();
|
|
195
222
|
window.removeEventListener("message", handleMessage);
|
|
196
223
|
try {
|
|
@@ -199,6 +226,7 @@ function run3DSecure(args) {
|
|
|
199
226
|
}
|
|
200
227
|
resolve(true);
|
|
201
228
|
} else if (msg === "OPAYO_CALLBACK_FAILED") {
|
|
229
|
+
console.log("[3DS] FAILED -> closing + resolve(false)");
|
|
202
230
|
closeOpayoIframe();
|
|
203
231
|
window.removeEventListener("message", handleMessage);
|
|
204
232
|
try {
|
|
@@ -213,7 +241,9 @@ function run3DSecure(args) {
|
|
|
213
241
|
onOpened?.();
|
|
214
242
|
} catch {
|
|
215
243
|
}
|
|
216
|
-
|
|
244
|
+
const termUrl = redirectUri ?? getChallengeRedirectUri();
|
|
245
|
+
console.log("[3DS] initializing iframe", { termUrl });
|
|
246
|
+
initializeIframe(responseType, acsUrl, pReq, cReq, termUrl, transactionId);
|
|
217
247
|
});
|
|
218
248
|
}
|
|
219
249
|
function receiveOpayoResponse(message) {
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/composables/useBasket.ts","../src/composables/useOpayo3ds.ts","../src/opayo/opayo3dsManager.ts","../src/install.ts"],"sourcesContent":["// src/composables/useBasket.ts\r\nimport { ref, computed, onScopeDispose } from 'vue'\r\nimport {\r\n basketManager,\r\n type BasketState\r\n} from 'orderopia-ordering-api-client'\r\n\r\nexport function useBasket() {\r\n // Start with current basket immediately\r\n const basket = ref<BasketState>(basketManager.getBasket())\r\n\r\n // Subscribe immediately (NOT in onMounted)\r\n const unsubscribe = basketManager.subscribe(state => {\r\n basket.value = state\r\n })\r\n\r\n // Auto-cleanup when the component/composable scope is destroyed\r\n onScopeDispose(() => {\r\n unsubscribe()\r\n })\r\n\r\n const totalQuantity = computed(() =>\r\n basket.value.items.reduce((sum, i) => sum + (i.quantity ?? 0), 0)\r\n )\r\n\r\n return {\r\n basket,\r\n totalQuantity,\r\n\r\n // pass-through helpers (nice DX)\r\n addToBasket: basketManager.addToBasket.bind(basketManager),\r\n removeFromBasket: basketManager.removeFromBasket.bind(basketManager),\r\n clearBasket: basketManager.clearBasket.bind(basketManager)\r\n }\r\n}\r\n","// src/composables/useOpayo3ds.ts\r\nimport { ref, onScopeDispose } from 'vue'\r\nimport { run3DSecure, closeOpayoIframe, type Run3DSecureArgs } from '../opayo/opayo3dsManager'\r\n\r\nexport function useOpayo3ds() {\r\n const isOpen = ref(false)\r\n const isRunning = ref(false)\r\n\r\n let disposed = false\r\n\r\n onScopeDispose(() => {\r\n disposed = true\r\n isOpen.value = false\r\n isRunning.value = false\r\n closeOpayoIframe()\r\n })\r\n\r\n async function run(args: Run3DSecureArgs) {\r\n if (disposed) return false\r\n\r\n isOpen.value = true\r\n isRunning.value = true\r\n\r\n try {\r\n const result = await run3DSecure({\r\n ...args,\r\n onOpened: () => {\r\n if (disposed) return\r\n isOpen.value = true\r\n args.onOpened?.()\r\n },\r\n onClosed: () => {\r\n if (disposed) return\r\n isOpen.value = false\r\n args.onClosed?.()\r\n },\r\n onCancelled: () => {\r\n if (disposed) return\r\n isOpen.value = false\r\n args.onCancelled?.()\r\n }\r\n })\r\n\r\n return result\r\n } finally {\r\n if (!disposed) {\r\n isRunning.value = false\r\n }\r\n }\r\n }\r\n\r\n function close() {\r\n isOpen.value = false\r\n isRunning.value = false\r\n closeOpayoIframe()\r\n }\r\n\r\n return {\r\n isOpen,\r\n isRunning,\r\n run,\r\n close\r\n }\r\n}\r\n","// src/opayo/opayo3dsManager.ts\r\ntype ResponseType = 'CHALLENGE' | 'FALLBACK'\r\n\r\nfunction isBrowser() {\r\n return typeof window !== 'undefined' && typeof document !== 'undefined'\r\n}\r\n\r\nfunction ensureThreedsContainer() {\r\n if (!isBrowser()) return null\r\n\r\n let el = document.getElementById('threeds-container') as HTMLDivElement | null\r\n if (!el) {\r\n el = document.createElement('div')\r\n el.id = 'threeds-container'\r\n el.style.position = 'fixed'\r\n el.style.inset = '0'\r\n el.style.display = 'none'\r\n el.style.background = 'rgba(0,0,0,0.35)'\r\n el.style.zIndex = '99999'\r\n document.body.appendChild(el)\r\n }\r\n return el\r\n}\r\n\r\n// UTF-8 -> Base64URL (no padding)\r\nfunction utf8ToBase64Url(str: string) {\r\n const bytes = new TextEncoder().encode(str)\r\n let bin = ''\r\n for (let i = 0; i < bytes.length; i++) bin += String.fromCharCode(bytes[i])\r\n const b64 = btoa(bin)\r\n return b64.replace(/\\+/g, '-').replace(/\\//g, '_').replace(/=+$/g, '')\r\n}\r\n\r\n// Base64URL -> Base64 (and add padding)\r\nfunction toStdBase64(b64url: string) {\r\n let s = b64url.replace(/-/g, '+').replace(/_/g, '/')\r\n const pad = s.length % 4\r\n if (pad) s += '==='.slice(pad - 1)\r\n return s\r\n}\r\n\r\nfunction safeAtobMaybeJson(b64ish: string) {\r\n try {\r\n return atob(toStdBase64(b64ish))\r\n } catch {\r\n return null\r\n }\r\n}\r\n\r\n// Normalize creq to Base64URL without padding.\r\nfunction normalizeCreq(input: unknown) {\r\n if (input == null) return ''\r\n\r\n // Object -> JSON\r\n if (typeof input === 'object') {\r\n try {\r\n return utf8ToBase64Url(JSON.stringify(input))\r\n } catch {\r\n // ignore\r\n }\r\n }\r\n\r\n let creq = String(input).trim()\r\n\r\n // If obviously JSON text\r\n if (/^\\s*\\{[\\s\\S]*\\}\\s*$/.test(creq)) {\r\n return utf8ToBase64Url(creq)\r\n }\r\n\r\n // If it looks URL-encoded, attempt a decode\r\n if (/%[0-9A-Fa-f]{2}/.test(creq) || creq.includes('%')) {\r\n try {\r\n creq = decodeURIComponent(creq)\r\n } catch {\r\n // ignore\r\n }\r\n }\r\n\r\n // Remove whitespace, convert spaces to '+'\r\n creq = creq.replace(/\\s+/g, '').replace(/ /g, '+')\r\n\r\n // If decodes to JSON, re-encode properly as UTF-8 base64url\r\n const maybe = safeAtobMaybeJson(creq)\r\n if (maybe && maybe.charCodeAt(0) === 123 /* '{' */) {\r\n return utf8ToBase64Url(maybe)\r\n }\r\n\r\n // Otherwise normalize to base64url and strip padding\r\n creq = creq.replace(/\\+/g, '-').replace(/\\//g, '_').replace(/=+$/g, '')\r\n return creq\r\n}\r\n\r\nfunction hiddenInput(name: string, value: unknown) {\r\n const inp = document.createElement('input')\r\n inp.type = 'hidden'\r\n inp.name = name\r\n inp.value = value == null ? '' : String(value)\r\n return inp\r\n}\r\n\r\nexport type Run3DSecureArgs = {\r\n responseType: ResponseType\r\n acsUrl: string\r\n pReq?: string | null\r\n cReq?: unknown\r\n redirectUri?: string | null\r\n transactionId?: string | null\r\n\r\n onCancelled?: () => void\r\n onOpened?: () => void\r\n onClosed?: () => void\r\n}\r\n\r\nlet onOpayoCancelled: (() => void) | undefined\r\n\r\nfunction initializeIframe(\r\n responseType: ResponseType,\r\n acsUrl: string,\r\n pReq?: string | null,\r\n cReq?: unknown,\r\n redirectUri?: string | null,\r\n transactionId?: string | null\r\n) {\r\n if (!isBrowser()) return\r\n\r\n const container = ensureThreedsContainer()\r\n if (!container) return\r\n\r\n container.style.display = 'block'\r\n container.textContent = ''\r\n\r\n const panel = document.createElement('div')\r\n panel.style.position = 'absolute'\r\n panel.style.top = '50%'\r\n panel.style.left = '50%'\r\n panel.style.transform = 'translate(-50%, -50%)'\r\n panel.style.width = 'min(100%, 500px)'\r\n panel.style.height = 'min(100%, 600px)'\r\n panel.style.background = 'var(--background, #fff)'\r\n panel.style.borderRadius = '10px'\r\n panel.style.boxShadow = '0 10px 30px rgba(0,0,0,0.2)'\r\n panel.style.display = 'flex'\r\n panel.style.flexDirection = 'column'\r\n panel.style.overflow = 'hidden'\r\n container.appendChild(panel)\r\n\r\n const msg = document.createElement('div')\r\n msg.style.padding = '16px'\r\n msg.style.fontFamily = 'sans-serif'\r\n msg.style.textAlign = 'center'\r\n msg.innerHTML =\r\n '<div style=\"font-weight:600;\">We’re redirecting you to your bank to complete the payment.</div>' +\r\n '<div style=\"margin-top:6px;\">This will only take a moment. Please <u>do not</u> refresh the page.</div>'\r\n panel.appendChild(msg)\r\n\r\n const iframeWrap = document.createElement('div')\r\n iframeWrap.style.flex = '1'\r\n iframeWrap.style.borderTop = '1px solid rgba(0,0,0,0.06)'\r\n panel.appendChild(iframeWrap)\r\n\r\n const iframeName = 'threeds_frame_' + Math.random().toString(36).slice(2)\r\n const iframe = document.createElement('iframe')\r\n iframe.name = iframeName\r\n iframe.title = '3-D Secure Authentication'\r\n iframe.style.width = '100%'\r\n iframe.style.height = '100%'\r\n iframe.style.border = '0'\r\n iframeWrap.appendChild(iframe)\r\n\r\n const form = document.createElement('form')\r\n form.style.display = 'none'\r\n form.method = 'POST'\r\n form.action = acsUrl\r\n form.target = iframeName\r\n document.body.appendChild(form)\r\n\r\n if (responseType === 'CHALLENGE') {\r\n // 3DS v2\r\n form.appendChild(hiddenInput('creq', normalizeCreq(cReq)))\r\n if (transactionId) {\r\n // Optional echo field (send as-is)\r\n form.appendChild(hiddenInput('threeDSSessionData', transactionId))\r\n }\r\n } else {\r\n // 3DS v1 fallback\r\n form.appendChild(hiddenInput('PaReq', pReq || ''))\r\n form.appendChild(hiddenInput('TermUrl', redirectUri || ''))\r\n form.appendChild(hiddenInput('MD', transactionId || ''))\r\n }\r\n\r\n form.submit()\r\n\r\n setTimeout(() => {\r\n try {\r\n document.body.removeChild(form)\r\n } catch {\r\n // ignore\r\n }\r\n }, 1000)\r\n}\r\n\r\nexport function closeOpayoIframe() {\r\n if (!isBrowser()) return\r\n const container = document.getElementById('threeds-container') as HTMLDivElement | null\r\n if (!container) return\r\n\r\n container.innerHTML = ''\r\n container.style.display = 'none'\r\n\r\n try {\r\n onOpayoCancelled?.()\r\n } catch {\r\n // ignore\r\n }\r\n}\r\n\r\nexport function run3DSecure(args: Run3DSecureArgs) {\r\n if (!isBrowser()) return Promise.resolve(false)\r\n\r\n const {\r\n responseType,\r\n acsUrl,\r\n pReq,\r\n cReq,\r\n redirectUri,\r\n transactionId,\r\n onCancelled,\r\n onOpened,\r\n onClosed\r\n } = args\r\n\r\n onOpayoCancelled = onCancelled\r\n\r\n return new Promise<boolean>((resolve) => {\r\n const handleMessage = (event: MessageEvent) => {\r\n const msg = String((event as any).data || '')\r\n\r\n if (msg === 'OPAYO_CALLBACK_SUCCESS') {\r\n closeOpayoIframe()\r\n window.removeEventListener('message', handleMessage)\r\n try {\r\n onClosed?.()\r\n } catch {\r\n // ignore\r\n }\r\n resolve(true)\r\n } else if (msg === 'OPAYO_CALLBACK_FAILED') {\r\n closeOpayoIframe()\r\n window.removeEventListener('message', handleMessage)\r\n try {\r\n onClosed?.()\r\n } catch {\r\n // ignore\r\n }\r\n resolve(false)\r\n }\r\n }\r\n\r\n window.addEventListener('message', handleMessage)\r\n\r\n try {\r\n onOpened?.()\r\n } catch {\r\n // ignore\r\n }\r\n\r\n initializeIframe(responseType, acsUrl, pReq, cReq, redirectUri, transactionId)\r\n })\r\n}\r\n\r\n// Call this from your callback/return page.\r\n// It posts a signal back to the parent checkout window.\r\nexport function receiveOpayoResponse(message: unknown) {\r\n if (!isBrowser()) return\r\n\r\n const m = String(message || '')\r\n if (m === 'OPAYO_CALLBACK_FAILED' || m === 'OPAYO_CALLBACK_SUCCESS') {\r\n try {\r\n window.top?.postMessage(m, '*')\r\n } catch {\r\n // ignore\r\n }\r\n\r\n try {\r\n onOpayoCancelled?.()\r\n } catch {\r\n // ignore\r\n }\r\n }\r\n}\r\n","// src/install.ts\r\nimport type { App } from 'vue'\r\n\r\nexport function OrderopiaVuePlugin() {\r\n return {\r\n install(app: App) {\r\n // nothing yet, but future-proof\r\n }\r\n }\r\n}\r\n"],"mappings":"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","names":["ref","onScopeDispose","ref","onScopeDispose"]}
|
|
1
|
+
{"version":3,"sources":["../src/composables/useBasket.ts","../src/composables/useOpayo3ds.ts","../src/opayo/opayo3dsManager.ts","../src/install.ts"],"sourcesContent":["// src/composables/useBasket.ts\r\nimport { ref, computed, onScopeDispose } from 'vue'\r\nimport {\r\n basketManager,\r\n type BasketState\r\n} from 'orderopia-ordering-api-client'\r\n\r\nexport function useBasket() {\r\n // Start with current basket immediately\r\n const basket = ref<BasketState>(basketManager.getBasket())\r\n\r\n // Subscribe immediately (NOT in onMounted)\r\n const unsubscribe = basketManager.subscribe(state => {\r\n basket.value = state\r\n })\r\n\r\n // Auto-cleanup when the component/composable scope is destroyed\r\n onScopeDispose(() => {\r\n unsubscribe()\r\n })\r\n\r\n const totalQuantity = computed(() =>\r\n basket.value.items.reduce((sum, i) => sum + (i.quantity ?? 0), 0)\r\n )\r\n\r\n return {\r\n basket,\r\n totalQuantity,\r\n\r\n // pass-through helpers (nice DX)\r\n addToBasket: basketManager.addToBasket.bind(basketManager),\r\n removeFromBasket: basketManager.removeFromBasket.bind(basketManager),\r\n clearBasket: basketManager.clearBasket.bind(basketManager)\r\n }\r\n}\r\n","// src/composables/useOpayo3ds.ts\r\nimport { ref, onScopeDispose } from 'vue'\r\nimport { run3DSecure, closeOpayoIframe, type Run3DSecureArgs } from '../opayo/opayo3dsManager'\r\n\r\nexport function useOpayo3ds() {\r\n const isOpen = ref(false)\r\n const isRunning = ref(false)\r\n\r\n let disposed = false\r\n\r\n onScopeDispose(() => {\r\n disposed = true\r\n isOpen.value = false\r\n isRunning.value = false\r\n closeOpayoIframe()\r\n })\r\n\r\n async function run(args: Run3DSecureArgs) {\r\n if (disposed) return false\r\n\r\n isOpen.value = true\r\n isRunning.value = true\r\n\r\n try {\r\n const result = await run3DSecure({\r\n ...args,\r\n onOpened: () => {\r\n if (disposed) return\r\n isOpen.value = true\r\n args.onOpened?.()\r\n },\r\n onClosed: () => {\r\n if (disposed) return\r\n isOpen.value = false\r\n args.onClosed?.()\r\n },\r\n onCancelled: () => {\r\n if (disposed) return\r\n isOpen.value = false\r\n args.onCancelled?.()\r\n }\r\n })\r\n\r\n return result\r\n } finally {\r\n if (!disposed) {\r\n isRunning.value = false\r\n }\r\n }\r\n }\r\n\r\n function close() {\r\n isOpen.value = false\r\n isRunning.value = false\r\n closeOpayoIframe()\r\n }\r\n\r\n return {\r\n isOpen,\r\n isRunning,\r\n run,\r\n close\r\n }\r\n}\r\n","// src/opayo/opayo3dsManager.ts\r\n\r\ntype ResponseType = 'CHALLENGE' | 'FALLBACK'\r\n\r\nfunction isBrowser() {\r\n return typeof window !== 'undefined' && typeof document !== 'undefined'\r\n}\r\n\r\nfunction ensureThreedsContainer() {\r\n if (!isBrowser()) return null\r\n\r\n let el = document.getElementById('threeds-container') as HTMLDivElement | null\r\n if (!el) {\r\n el = document.createElement('div')\r\n el.id = 'threeds-container'\r\n el.style.position = 'fixed'\r\n el.style.inset = '0'\r\n el.style.display = 'none'\r\n el.style.background = 'rgba(0,0,0,0.35)'\r\n el.style.zIndex = '99999'\r\n document.body.appendChild(el)\r\n }\r\n return el\r\n}\r\n\r\n// UTF-8 -> Base64URL (no padding)\r\nfunction utf8ToBase64Url(str: string) {\r\n const bytes = new TextEncoder().encode(str)\r\n let bin = ''\r\n for (let i = 0; i < bytes.length; i++) bin += String.fromCharCode(bytes[i])\r\n const b64 = btoa(bin)\r\n return b64.replace(/\\+/g, '-').replace(/\\//g, '_').replace(/=+$/g, '')\r\n}\r\n\r\n// Base64URL -> Base64 (and add padding)\r\nfunction toStdBase64(b64url: string) {\r\n let s = b64url.replace(/-/g, '+').replace(/_/g, '/')\r\n const pad = s.length % 4\r\n if (pad) s += '==='.slice(pad - 1)\r\n return s\r\n}\r\n\r\nfunction safeAtobMaybeJson(b64ish: string) {\r\n try {\r\n return atob(toStdBase64(b64ish))\r\n } catch {\r\n return null\r\n }\r\n}\r\n\r\n// Normalize creq to Base64URL without padding.\r\nfunction normalizeCreq(input: unknown) {\r\n if (input == null) return ''\r\n\r\n // Object -> JSON\r\n if (typeof input === 'object') {\r\n try {\r\n return utf8ToBase64Url(JSON.stringify(input))\r\n } catch {\r\n // ignore\r\n }\r\n }\r\n\r\n let creq = String(input).trim()\r\n\r\n // If obviously JSON text\r\n if (/^\\s*\\{[\\s\\S]*\\}\\s*$/.test(creq)) {\r\n return utf8ToBase64Url(creq)\r\n }\r\n\r\n // If it looks URL-encoded, attempt a decode\r\n if (/%[0-9A-Fa-f]{2}/.test(creq) || creq.includes('%')) {\r\n try {\r\n creq = decodeURIComponent(creq)\r\n } catch {\r\n // ignore\r\n }\r\n }\r\n\r\n // Remove whitespace, convert spaces to '+'\r\n creq = creq.replace(/\\s+/g, '').replace(/ /g, '+')\r\n\r\n // If decodes to JSON, re-encode properly as UTF-8 base64url\r\n const maybe = safeAtobMaybeJson(creq)\r\n if (maybe && maybe.charCodeAt(0) === 123 /* '{' */) {\r\n return utf8ToBase64Url(maybe)\r\n }\r\n\r\n // Otherwise normalize to base64url and strip padding\r\n creq = creq.replace(/\\+/g, '-').replace(/\\//g, '_').replace(/=+$/g, '')\r\n return creq\r\n}\r\n\r\nfunction hiddenInput(name: string, value: unknown) {\r\n const inp = document.createElement('input')\r\n inp.type = 'hidden'\r\n inp.name = name\r\n inp.value = value == null ? '' : String(value)\r\n return inp\r\n}\r\n\r\n/**\r\n * ✅ Pull env from the core client (prod/dev toggle you built)\r\n * NOTE: Adjust the import path to whatever you export publicly from the client package.\r\n */\r\nimport { isOrderopiaDevMode } from 'orderopia-ordering-api-client'\r\n\r\nfunction getChallengeRedirectUri(): string {\r\n // TEMP values for now (your ask) — but environment-aware.\r\n // Replace these when you confirm the final endpoint paths.\r\n return isOrderopiaDevMode()\r\n ? 'https://api-test.orderopia.com/Transactions/3ds/Challenge'\r\n : 'https://api.orderopia.com/Transactions/3ds/Challenge'\r\n}\r\n\r\nexport type Run3DSecureArgs = {\r\n responseType: ResponseType\r\n acsUrl: string\r\n pReq?: string | null\r\n cReq?: unknown\r\n redirectUri?: string | null\r\n transactionId?: string | null\r\n\r\n onCancelled?: () => void\r\n onOpened?: () => void\r\n onClosed?: () => void\r\n}\r\n\r\nlet onOpayoCancelled: (() => void) | undefined\r\n\r\nfunction initializeIframe(\r\n responseType: ResponseType,\r\n acsUrl: string,\r\n pReq?: string | null,\r\n cReq?: unknown,\r\n redirectUri?: string | null,\r\n transactionId?: string | null\r\n) {\r\n if (!isBrowser()) return\r\n\r\n const container = ensureThreedsContainer()\r\n if (!container) return\r\n\r\n container.style.display = 'block'\r\n container.textContent = ''\r\n\r\n const panel = document.createElement('div')\r\n panel.style.position = 'absolute'\r\n panel.style.top = '50%'\r\n panel.style.left = '50%'\r\n panel.style.transform = 'translate(-50%, -50%)'\r\n panel.style.width = 'min(100%, 500px)'\r\n panel.style.height = 'min(100%, 600px)'\r\n panel.style.background = 'var(--background, #fff)'\r\n panel.style.borderRadius = '10px'\r\n panel.style.boxShadow = '0 10px 30px rgba(0,0,0,0.2)'\r\n panel.style.display = 'flex'\r\n panel.style.flexDirection = 'column'\r\n panel.style.overflow = 'hidden'\r\n container.appendChild(panel)\r\n\r\n const msg = document.createElement('div')\r\n msg.style.padding = '16px'\r\n msg.style.fontFamily = 'sans-serif'\r\n msg.style.textAlign = 'center'\r\n msg.innerHTML =\r\n '<div style=\"font-weight:600;\">We’re redirecting you to your bank to complete the payment.</div>' +\r\n '<div style=\"margin-top:6px;\">This will only take a moment. Please <u>do not</u> refresh the page.</div>'\r\n panel.appendChild(msg)\r\n\r\n const iframeWrap = document.createElement('div')\r\n iframeWrap.style.flex = '1'\r\n iframeWrap.style.borderTop = '1px solid rgba(0,0,0,0.06)'\r\n panel.appendChild(iframeWrap)\r\n\r\n const iframeName = 'threeds_frame_' + Math.random().toString(36).slice(2)\r\n const iframe = document.createElement('iframe')\r\n iframe.name = iframeName\r\n iframe.title = '3-D Secure Authentication'\r\n iframe.style.width = '100%'\r\n iframe.style.height = '100%'\r\n iframe.style.border = '0'\r\n iframeWrap.appendChild(iframe)\r\n\r\n const form = document.createElement('form')\r\n form.style.display = 'none'\r\n form.method = 'POST'\r\n form.action = acsUrl\r\n form.target = iframeName\r\n document.body.appendChild(form)\r\n\r\n if (responseType === 'CHALLENGE') {\r\n // 3DS v2\r\n form.appendChild(hiddenInput('creq', normalizeCreq(cReq)))\r\n if (transactionId) {\r\n // Optional echo field (send as-is)\r\n form.appendChild(hiddenInput('threeDSSessionData', transactionId))\r\n }\r\n } else {\r\n // 3DS v1 fallback\r\n const termUrl = redirectUri || ''\r\n form.appendChild(hiddenInput('PaReq', pReq || ''))\r\n form.appendChild(hiddenInput('TermUrl', termUrl))\r\n form.appendChild(hiddenInput('MD', transactionId || ''))\r\n }\r\n\r\n form.submit()\r\n\r\n setTimeout(() => {\r\n try {\r\n document.body.removeChild(form)\r\n } catch {\r\n // ignore\r\n }\r\n }, 1000000)\r\n}\r\n\r\nexport function closeOpayoIframe() {\r\n if (!isBrowser()) return\r\n const container = document.getElementById('threeds-container') as HTMLDivElement | null\r\n if (!container) return\r\n\r\n container.innerHTML = ''\r\n container.style.display = 'none'\r\n\r\n try {\r\n onOpayoCancelled?.()\r\n } catch {\r\n // ignore\r\n }\r\n}\r\n\r\nexport function run3DSecure(args: Run3DSecureArgs) {\r\n if (!isBrowser()) return Promise.resolve(false)\r\n\r\n const {\r\n responseType,\r\n acsUrl,\r\n pReq,\r\n cReq,\r\n redirectUri,\r\n transactionId,\r\n onCancelled,\r\n onOpened,\r\n onClosed\r\n } = args\r\n\r\n console.log('[3DS] run3DSecure called', {\r\n responseType,\r\n acsUrl,\r\n transactionId,\r\n redirectUriProvided: !!redirectUri,\r\n redirectUriFinal: redirectUri ?? getChallengeRedirectUri(),\r\n cReqType: typeof cReq,\r\n cReqPreview:\r\n typeof cReq === 'string'\r\n ? cReq.slice(0, 80)\r\n : cReq && typeof cReq === 'object'\r\n ? JSON.stringify(cReq).slice(0, 120)\r\n : cReq\r\n })\r\n\r\n onOpayoCancelled = () => {\r\n console.log('[3DS] onOpayoCancelled fired')\r\n try {\r\n onCancelled?.()\r\n } catch {\r\n // ignore\r\n }\r\n }\r\n\r\n return new Promise<boolean>((resolve) => {\r\n const handleMessage = (event: MessageEvent) => {\r\n const msg = String((event as any).data || '')\r\n console.log('[3DS] message received', {\r\n msg,\r\n origin: event.origin,\r\n sourceIsWindow: event.source === window,\r\n sourceIsTop: event.source === window.top\r\n })\r\n\r\n if (msg === 'OPAYO_CALLBACK_SUCCESS') {\r\n console.log('[3DS] SUCCESS -> closing + resolve(true)')\r\n closeOpayoIframe()\r\n window.removeEventListener('message', handleMessage)\r\n try {\r\n onClosed?.()\r\n } catch {}\r\n resolve(true)\r\n } else if (msg === 'OPAYO_CALLBACK_FAILED') {\r\n console.log('[3DS] FAILED -> closing + resolve(false)')\r\n closeOpayoIframe()\r\n window.removeEventListener('message', handleMessage)\r\n try {\r\n onClosed?.()\r\n } catch {}\r\n resolve(false)\r\n }\r\n }\r\n\r\n window.addEventListener('message', handleMessage)\r\n\r\n try {\r\n onOpened?.()\r\n } catch {}\r\n\r\n const termUrl = redirectUri ?? getChallengeRedirectUri()\r\n console.log('[3DS] initializing iframe', { termUrl })\r\n\r\n initializeIframe(responseType, acsUrl, pReq, cReq, termUrl, transactionId)\r\n })\r\n}\r\n\r\n// Call this from your callback/return page.\r\n// It posts a signal back to the parent checkout window.\r\nexport function receiveOpayoResponse(message: unknown) {\r\n if (!isBrowser()) return\r\n\r\n const m = String(message || '')\r\n if (m === 'OPAYO_CALLBACK_FAILED' || m === 'OPAYO_CALLBACK_SUCCESS') {\r\n try {\r\n window.top?.postMessage(m, '*')\r\n } catch {\r\n // ignore\r\n }\r\n\r\n try {\r\n onOpayoCancelled?.()\r\n } catch {\r\n // ignore\r\n }\r\n }\r\n}\r\n","// src/install.ts\r\nimport type { App } from 'vue'\r\n\r\nexport function OrderopiaVuePlugin() {\r\n return {\r\n install(app: App) {\r\n // nothing yet, but future-proof\r\n }\r\n }\r\n}\r\n"],"mappings":";AACA,SAAS,KAAK,UAAU,sBAAsB;AAC9C;AAAA,EACE;AAAA,OAEK;AAEA,SAAS,YAAY;AAE1B,QAAM,SAAS,IAAiB,cAAc,UAAU,CAAC;AAGzD,QAAM,cAAc,cAAc,UAAU,WAAS;AACnD,WAAO,QAAQ;AAAA,EACjB,CAAC;AAGD,iBAAe,MAAM;AACnB,gBAAY;AAAA,EACd,CAAC;AAED,QAAM,gBAAgB;AAAA,IAAS,MAC7B,OAAO,MAAM,MAAM,OAAO,CAAC,KAAK,MAAM,OAAO,EAAE,YAAY,IAAI,CAAC;AAAA,EAClE;AAEA,SAAO;AAAA,IACL;AAAA,IACA;AAAA;AAAA,IAGA,aAAa,cAAc,YAAY,KAAK,aAAa;AAAA,IACzD,kBAAkB,cAAc,iBAAiB,KAAK,aAAa;AAAA,IACnE,aAAa,cAAc,YAAY,KAAK,aAAa;AAAA,EAC3D;AACF;;;ACjCA,SAAS,OAAAA,MAAK,kBAAAC,uBAAsB;;;ACwGpC,SAAS,0BAA0B;AArGnC,SAAS,YAAY;AACnB,SAAO,OAAO,WAAW,eAAe,OAAO,aAAa;AAC9D;AAEA,SAAS,yBAAyB;AAChC,MAAI,CAAC,UAAU,EAAG,QAAO;AAEzB,MAAI,KAAK,SAAS,eAAe,mBAAmB;AACpD,MAAI,CAAC,IAAI;AACP,SAAK,SAAS,cAAc,KAAK;AACjC,OAAG,KAAK;AACR,OAAG,MAAM,WAAW;AACpB,OAAG,MAAM,QAAQ;AACjB,OAAG,MAAM,UAAU;AACnB,OAAG,MAAM,aAAa;AACtB,OAAG,MAAM,SAAS;AAClB,aAAS,KAAK,YAAY,EAAE;AAAA,EAC9B;AACA,SAAO;AACT;AAGA,SAAS,gBAAgB,KAAa;AACpC,QAAM,QAAQ,IAAI,YAAY,EAAE,OAAO,GAAG;AAC1C,MAAI,MAAM;AACV,WAAS,IAAI,GAAG,IAAI,MAAM,QAAQ,IAAK,QAAO,OAAO,aAAa,MAAM,CAAC,CAAC;AAC1E,QAAM,MAAM,KAAK,GAAG;AACpB,SAAO,IAAI,QAAQ,OAAO,GAAG,EAAE,QAAQ,OAAO,GAAG,EAAE,QAAQ,QAAQ,EAAE;AACvE;AAGA,SAAS,YAAY,QAAgB;AACnC,MAAI,IAAI,OAAO,QAAQ,MAAM,GAAG,EAAE,QAAQ,MAAM,GAAG;AACnD,QAAM,MAAM,EAAE,SAAS;AACvB,MAAI,IAAK,MAAK,MAAM,MAAM,MAAM,CAAC;AACjC,SAAO;AACT;AAEA,SAAS,kBAAkB,QAAgB;AACzC,MAAI;AACF,WAAO,KAAK,YAAY,MAAM,CAAC;AAAA,EACjC,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAGA,SAAS,cAAc,OAAgB;AACrC,MAAI,SAAS,KAAM,QAAO;AAG1B,MAAI,OAAO,UAAU,UAAU;AAC7B,QAAI;AACF,aAAO,gBAAgB,KAAK,UAAU,KAAK,CAAC;AAAA,IAC9C,QAAQ;AAAA,IAER;AAAA,EACF;AAEA,MAAI,OAAO,OAAO,KAAK,EAAE,KAAK;AAG9B,MAAI,sBAAsB,KAAK,IAAI,GAAG;AACpC,WAAO,gBAAgB,IAAI;AAAA,EAC7B;AAGA,MAAI,kBAAkB,KAAK,IAAI,KAAK,KAAK,SAAS,GAAG,GAAG;AACtD,QAAI;AACF,aAAO,mBAAmB,IAAI;AAAA,IAChC,QAAQ;AAAA,IAER;AAAA,EACF;AAGA,SAAO,KAAK,QAAQ,QAAQ,EAAE,EAAE,QAAQ,MAAM,GAAG;AAGjD,QAAM,QAAQ,kBAAkB,IAAI;AACpC,MAAI,SAAS,MAAM,WAAW,CAAC,MAAM,KAAe;AAClD,WAAO,gBAAgB,KAAK;AAAA,EAC9B;AAGA,SAAO,KAAK,QAAQ,OAAO,GAAG,EAAE,QAAQ,OAAO,GAAG,EAAE,QAAQ,QAAQ,EAAE;AACtE,SAAO;AACT;AAEA,SAAS,YAAY,MAAc,OAAgB;AACjD,QAAM,MAAM,SAAS,cAAc,OAAO;AAC1C,MAAI,OAAO;AACX,MAAI,OAAO;AACX,MAAI,QAAQ,SAAS,OAAO,KAAK,OAAO,KAAK;AAC7C,SAAO;AACT;AAQA,SAAS,0BAAkC;AAGzC,SAAO,mBAAmB,IACtB,8DACA;AACN;AAeA,IAAI;AAEJ,SAAS,iBACP,cACA,QACA,MACA,MACA,aACA,eACA;AACA,MAAI,CAAC,UAAU,EAAG;AAElB,QAAM,YAAY,uBAAuB;AACzC,MAAI,CAAC,UAAW;AAEhB,YAAU,MAAM,UAAU;AAC1B,YAAU,cAAc;AAExB,QAAM,QAAQ,SAAS,cAAc,KAAK;AAC1C,QAAM,MAAM,WAAW;AACvB,QAAM,MAAM,MAAM;AAClB,QAAM,MAAM,OAAO;AACnB,QAAM,MAAM,YAAY;AACxB,QAAM,MAAM,QAAQ;AACpB,QAAM,MAAM,SAAS;AACrB,QAAM,MAAM,aAAa;AACzB,QAAM,MAAM,eAAe;AAC3B,QAAM,MAAM,YAAY;AACxB,QAAM,MAAM,UAAU;AACtB,QAAM,MAAM,gBAAgB;AAC5B,QAAM,MAAM,WAAW;AACvB,YAAU,YAAY,KAAK;AAE3B,QAAM,MAAM,SAAS,cAAc,KAAK;AACxC,MAAI,MAAM,UAAU;AACpB,MAAI,MAAM,aAAa;AACvB,MAAI,MAAM,YAAY;AACtB,MAAI,YACF;AAEF,QAAM,YAAY,GAAG;AAErB,QAAM,aAAa,SAAS,cAAc,KAAK;AAC/C,aAAW,MAAM,OAAO;AACxB,aAAW,MAAM,YAAY;AAC7B,QAAM,YAAY,UAAU;AAE5B,QAAM,aAAa,mBAAmB,KAAK,OAAO,EAAE,SAAS,EAAE,EAAE,MAAM,CAAC;AACxE,QAAM,SAAS,SAAS,cAAc,QAAQ;AAC9C,SAAO,OAAO;AACd,SAAO,QAAQ;AACf,SAAO,MAAM,QAAQ;AACrB,SAAO,MAAM,SAAS;AACtB,SAAO,MAAM,SAAS;AACtB,aAAW,YAAY,MAAM;AAE7B,QAAM,OAAO,SAAS,cAAc,MAAM;AAC1C,OAAK,MAAM,UAAU;AACrB,OAAK,SAAS;AACd,OAAK,SAAS;AACd,OAAK,SAAS;AACd,WAAS,KAAK,YAAY,IAAI;AAE9B,MAAI,iBAAiB,aAAa;AAEhC,SAAK,YAAY,YAAY,QAAQ,cAAc,IAAI,CAAC,CAAC;AACzD,QAAI,eAAe;AAEjB,WAAK,YAAY,YAAY,sBAAsB,aAAa,CAAC;AAAA,IACnE;AAAA,EACF,OAAO;AAEL,UAAM,UAAU,eAAe;AAC/B,SAAK,YAAY,YAAY,SAAS,QAAQ,EAAE,CAAC;AACjD,SAAK,YAAY,YAAY,WAAW,OAAO,CAAC;AAChD,SAAK,YAAY,YAAY,MAAM,iBAAiB,EAAE,CAAC;AAAA,EACzD;AAEA,OAAK,OAAO;AAEZ,aAAW,MAAM;AACf,QAAI;AACF,eAAS,KAAK,YAAY,IAAI;AAAA,IAChC,QAAQ;AAAA,IAER;AAAA,EACF,GAAG,GAAO;AACZ;AAEO,SAAS,mBAAmB;AACjC,MAAI,CAAC,UAAU,EAAG;AAClB,QAAM,YAAY,SAAS,eAAe,mBAAmB;AAC7D,MAAI,CAAC,UAAW;AAEhB,YAAU,YAAY;AACtB,YAAU,MAAM,UAAU;AAE1B,MAAI;AACF,uBAAmB;AAAA,EACrB,QAAQ;AAAA,EAER;AACF;AAEO,SAAS,YAAY,MAAuB;AACjD,MAAI,CAAC,UAAU,EAAG,QAAO,QAAQ,QAAQ,KAAK;AAE9C,QAAM;AAAA,IACJ;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,IAAI;AAEJ,UAAQ,IAAI,4BAA4B;AAAA,IACtC;AAAA,IACA;AAAA,IACA;AAAA,IACA,qBAAqB,CAAC,CAAC;AAAA,IACvB,kBAAkB,eAAe,wBAAwB;AAAA,IACzD,UAAU,OAAO;AAAA,IACjB,aACE,OAAO,SAAS,WACZ,KAAK,MAAM,GAAG,EAAE,IAChB,QAAQ,OAAO,SAAS,WACtB,KAAK,UAAU,IAAI,EAAE,MAAM,GAAG,GAAG,IACjC;AAAA,EACV,CAAC;AAED,qBAAmB,MAAM;AACvB,YAAQ,IAAI,8BAA8B;AAC1C,QAAI;AACF,oBAAc;AAAA,IAChB,QAAQ;AAAA,IAER;AAAA,EACF;AAEA,SAAO,IAAI,QAAiB,CAAC,YAAY;AACvC,UAAM,gBAAgB,CAAC,UAAwB;AAC7C,YAAM,MAAM,OAAQ,MAAc,QAAQ,EAAE;AAC5C,cAAQ,IAAI,0BAA0B;AAAA,QACpC;AAAA,QACA,QAAQ,MAAM;AAAA,QACd,gBAAgB,MAAM,WAAW;AAAA,QACjC,aAAa,MAAM,WAAW,OAAO;AAAA,MACvC,CAAC;AAED,UAAI,QAAQ,0BAA0B;AACpC,gBAAQ,IAAI,0CAA0C;AACtD,yBAAiB;AACjB,eAAO,oBAAoB,WAAW,aAAa;AACnD,YAAI;AACF,qBAAW;AAAA,QACb,QAAQ;AAAA,QAAC;AACT,gBAAQ,IAAI;AAAA,MACd,WAAW,QAAQ,yBAAyB;AAC1C,gBAAQ,IAAI,0CAA0C;AACtD,yBAAiB;AACjB,eAAO,oBAAoB,WAAW,aAAa;AACnD,YAAI;AACF,qBAAW;AAAA,QACb,QAAQ;AAAA,QAAC;AACT,gBAAQ,KAAK;AAAA,MACf;AAAA,IACF;AAEA,WAAO,iBAAiB,WAAW,aAAa;AAEhD,QAAI;AACF,iBAAW;AAAA,IACb,QAAQ;AAAA,IAAC;AAET,UAAM,UAAU,eAAe,wBAAwB;AACvD,YAAQ,IAAI,6BAA6B,EAAE,QAAQ,CAAC;AAEpD,qBAAiB,cAAc,QAAQ,MAAM,MAAM,SAAS,aAAa;AAAA,EAC3E,CAAC;AACH;AAIO,SAAS,qBAAqB,SAAkB;AACrD,MAAI,CAAC,UAAU,EAAG;AAElB,QAAM,IAAI,OAAO,WAAW,EAAE;AAC9B,MAAI,MAAM,2BAA2B,MAAM,0BAA0B;AACnE,QAAI;AACF,aAAO,KAAK,YAAY,GAAG,GAAG;AAAA,IAChC,QAAQ;AAAA,IAER;AAEA,QAAI;AACF,yBAAmB;AAAA,IACrB,QAAQ;AAAA,IAER;AAAA,EACF;AACF;;;ADxUO,SAAS,cAAc;AAC5B,QAAM,SAASC,KAAI,KAAK;AACxB,QAAM,YAAYA,KAAI,KAAK;AAE3B,MAAI,WAAW;AAEf,EAAAC,gBAAe,MAAM;AACnB,eAAW;AACX,WAAO,QAAQ;AACf,cAAU,QAAQ;AAClB,qBAAiB;AAAA,EACnB,CAAC;AAED,iBAAe,IAAI,MAAuB;AACxC,QAAI,SAAU,QAAO;AAErB,WAAO,QAAQ;AACf,cAAU,QAAQ;AAElB,QAAI;AACF,YAAM,SAAS,MAAM,YAAY;AAAA,QAC/B,GAAG;AAAA,QACH,UAAU,MAAM;AACd,cAAI,SAAU;AACd,iBAAO,QAAQ;AACf,eAAK,WAAW;AAAA,QAClB;AAAA,QACA,UAAU,MAAM;AACd,cAAI,SAAU;AACd,iBAAO,QAAQ;AACf,eAAK,WAAW;AAAA,QAClB;AAAA,QACA,aAAa,MAAM;AACjB,cAAI,SAAU;AACd,iBAAO,QAAQ;AACf,eAAK,cAAc;AAAA,QACrB;AAAA,MACF,CAAC;AAED,aAAO;AAAA,IACT,UAAE;AACA,UAAI,CAAC,UAAU;AACb,kBAAU,QAAQ;AAAA,MACpB;AAAA,IACF;AAAA,EACF;AAEA,WAAS,QAAQ;AACf,WAAO,QAAQ;AACf,cAAU,QAAQ;AAClB,qBAAiB;AAAA,EACnB;AAEA,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;;;AE5DO,SAAS,qBAAqB;AACnC,SAAO;AAAA,IACL,QAAQ,KAAU;AAAA,IAElB;AAAA,EACF;AACF;","names":["ref","onScopeDispose","ref","onScopeDispose"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "orderopia-ordering-api-client-vue",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.6",
|
|
4
4
|
"description": "Vue bindings for Orderopia Ordering API Client",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -33,6 +33,6 @@
|
|
|
33
33
|
"vue": "^3.3.0"
|
|
34
34
|
},
|
|
35
35
|
"dependencies": {
|
|
36
|
-
"orderopia-ordering-api-client": "^0.1.
|
|
36
|
+
"orderopia-ordering-api-client": "^0.1.6"
|
|
37
37
|
}
|
|
38
38
|
}
|