orderopia-ordering-api-client-vue 0.0.4 → 0.0.5

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 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", redirectUri || ""));
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
- }, 1e3);
195
+ }, 1e6);
191
196
  }
192
197
  function closeOpayoIframe() {
193
198
  if (!isBrowser()) return;
@@ -240,7 +245,8 @@ function run3DSecure(args) {
240
245
  onOpened?.();
241
246
  } catch {
242
247
  }
243
- initializeIframe(responseType, acsUrl, pReq, cReq, redirectUri, transactionId);
248
+ const termUrl = redirectUri ?? getChallengeRedirectUri();
249
+ initializeIframe(responseType, acsUrl, pReq, cReq, termUrl, transactionId);
244
250
  });
245
251
  }
246
252
  function receiveOpayoResponse(message) {
@@ -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 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 const termUrl = redirectUri ?? getChallengeRedirectUri()\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", redirectUri || ""));
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
- }, 1e3);
168
+ }, 1e6);
164
169
  }
165
170
  function closeOpayoIframe() {
166
171
  if (!isBrowser()) return;
@@ -213,7 +218,8 @@ function run3DSecure(args) {
213
218
  onOpened?.();
214
219
  } catch {
215
220
  }
216
- initializeIframe(responseType, acsUrl, pReq, cReq, redirectUri, transactionId);
221
+ const termUrl = redirectUri ?? getChallengeRedirectUri();
222
+ initializeIframe(responseType, acsUrl, pReq, cReq, termUrl, transactionId);
217
223
  });
218
224
  }
219
225
  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 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 const termUrl = redirectUri ?? getChallengeRedirectUri()\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":["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.4",
3
+ "version": "0.0.5",
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.2"
36
+ "orderopia-ordering-api-client": "^0.1.6"
37
37
  }
38
38
  }