@thepayulink/checkout 2.1.2 → 2.1.4
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/payulink-checkout.cjs +21 -21
- package/dist/payulink-checkout.esm.js +21 -21
- package/dist/payulink-checkout.umd.js +21 -21
- package/package.json +1 -1
- package/src/index.js +11 -1
- package/src/modal.js +5 -1
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
var
|
|
1
|
+
var E=Object.defineProperty;var ee=Object.getOwnPropertyDescriptor;var le=Object.getOwnPropertyNames;var ae=Object.prototype.hasOwnProperty;var te=(a,o)=>{for(var r in o)E(a,r,{get:o[r],enumerable:!0})},re=(a,o,r,y)=>{if(o&&typeof o=="object"||typeof o=="function")for(let h of le(o))!ae.call(a,h)&&h!==r&&E(a,h,{get:()=>o[h],enumerable:!(y=ee(o,h))||y.enumerable});return a};var ie=a=>re(E({},"__esModule",{value:!0}),a);var de={};te(de,{default:()=>w});module.exports=ie(de);var oe=`
|
|
2
2
|
#pl-overlay * { box-sizing: border-box; margin: 0; padding: 0; }
|
|
3
3
|
#pl-overlay { --pl-blue:#3395ff; --pl-blue-dark:#1f86f5; --pl-brand:#0b3068; --pl-ink:#1a2a44; --pl-mut:#6b7c93; --pl-line:#eceff4;
|
|
4
4
|
position: fixed; inset: 0; z-index: 2147483000; font-family: 'Inter', system-ui, -apple-system, BlinkMacSystemFont, sans-serif;
|
|
@@ -237,7 +237,7 @@ var j=Object.defineProperty;var ee=Object.getOwnPropertyDescriptor;var le=Object
|
|
|
237
237
|
#pl-overlay .pl-approw { justify-content: center; }
|
|
238
238
|
#pl-overlay .pl-validrow { margin: 0 auto; }
|
|
239
239
|
}
|
|
240
|
-
`,
|
|
240
|
+
`,U=!1;function O(a=document){if(U&&a.getElementById("pl-checkout-styles"))return;let o=a.createElement("style");o.id="pl-checkout-styles",o.textContent=oe,a.head.appendChild(o),U=!0}var ne=a=>"\u20B9"+Number(a||0).toLocaleString("en-IN",{maximumFractionDigits:2}),pe=a=>`${Math.floor(a/60)}:${a%60<10?"0":""}${a%60}`,f=a=>String(a==null?"":a).replace(/[&<>"]/g,o=>({"&":"&","<":"<",">":">",'"':"""})[o]),m=a=>`<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">${a}</svg>`,b={qr:m('<rect width="5" height="5" x="3" y="3" rx="1"/><rect width="5" height="5" x="16" y="3" rx="1"/><rect width="5" height="5" x="3" y="16" rx="1"/><path d="M21 16h-3a2 2 0 0 0-2 2v3"/><path d="M21 21v.01"/><path d="M12 7v3a2 2 0 0 1-2 2H7"/><path d="M3 12h.01"/><path d="M12 3h.01"/><path d="M12 16v.01"/><path d="M16 12h1"/><path d="M21 12v.01"/><path d="M12 21v-1"/>'),card:m('<rect width="20" height="14" x="2" y="5" rx="2"/><line x1="2" x2="22" y1="10" y2="10"/>'),netbanking:m('<path d="M10 18v-7"/><path d="M11.119 2.205a2 2 0 0 1 1.762 0l7.84 3.846A.5.5 0 0 1 20.5 7h-17a.5.5 0 0 1-.22-.949z"/><path d="M14 18v-7"/><path d="M18 18v-7"/><path d="M3 22h18"/><path d="M6 18v-7"/>'),wallet:m('<path d="M19 7V4a1 1 0 0 0-1-1H5a2 2 0 0 0 0 4h15a1 1 0 0 1 1 1v4h-3a2 2 0 0 0 0 4h3a1 1 0 0 0 1-1v-2a1 1 0 0 0-1-1"/><path d="M3 5v14a2 2 0 0 0 2 2h15a1 1 0 0 0 1-1v-4"/>'),emi:m('<path d="M16 14v2.2l1.6 1"/><path d="M16 2v4"/><path d="M21 7.5V6a2 2 0 0 0-2-2H5a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h3.5"/><path d="M3 10h5"/><path d="M8 2v4"/><circle cx="16" cy="16" r="6"/>'),back:m('<path d="M15 18l-6-6 6-6"/>'),mail:m('<rect x="2" y="4" width="20" height="16" rx="2"/><path d="m22 7-10 5L2 7"/>'),arrow:m('<path d="M5 12h14M13 6l6 6-6 6"/>'),verified:m('<path d="M9 12l2 2 4-4"/><circle cx="12" cy="12" r="10"/>'),lock:m('<rect width="18" height="11" x="3" y="11" rx="2"/><path d="M7 11V7a5 5 0 0 1 10 0v4"/>')},R='<svg width="13" height="13" viewBox="0 0 24 24" fill="currentColor"><path d="M12 1l9 4v6c0 5.5-3.8 10.7-9 12-5.2-1.3-9-6.5-9-12V5l9-4z"/></svg>',se=[{m:"card",t:"Cards",s:"Visa, Mastercard & RuPay",ic:"card"},{m:"netbanking",t:"Netbanking",s:"All Indian banks",ic:"netbanking"},{m:"wallet",t:"Wallet",s:"Paytm, PhonePe & more",ic:"wallet"},{m:"emi",t:"EMI",s:"EMI via cards & more",ic:"emi"}];function A(a){O(),a=Object.assign({name:"Payment",description:"",amount:0,assetBase:"/assets",logo:"/assets/payulink-logo.png",prefill:{},apiBase:""},a);let o=String(a.apiBase||"").replace(/\/$/,""),r=ne(a.amount),y=["gpay","phonepe","paytm","bhim","amazonpay"].reduce((e,t)=>(e[t]=`${a.assetBase}/upi/${t}.png`,e),{}),h=["phonepe","gpay","paytm","bhim","amazonpay"],l={screen:"loader",order:null,customer:null,timer:null,stop:null,done:!1,utr:null,expiryMs:null},p=document.createElement("div");p.id="pl-overlay",a.brandColor&&p.style.setProperty("--pl-brand",a.brandColor),p.innerHTML=`
|
|
241
241
|
<div class="pl-modal" role="dialog" aria-modal="true">
|
|
242
242
|
<div class="pl-splash" id="pl-splash">
|
|
243
243
|
<div class="pl-shield">
|
|
@@ -246,25 +246,25 @@ var j=Object.defineProperty;var ee=Object.getOwnPropertyDescriptor;var le=Object
|
|
|
246
246
|
<path d="M60 3 L113 25 V70 C113 105 90 128 60 137 C30 128 7 105 7 70 V25 Z" fill="url(#pl-shgrad)"/>
|
|
247
247
|
</svg>
|
|
248
248
|
<span class="pl-shield-shine"></span>
|
|
249
|
-
<img class="pl-shield-logo" src="${
|
|
249
|
+
<img class="pl-shield-logo" src="${f(a.assetBase)}/payulink-logo.png" alt="payulink">
|
|
250
250
|
</div>
|
|
251
|
-
<div class="pl-splash-foot">Secured By <span class="pl-pb"><img src="${
|
|
251
|
+
<div class="pl-splash-foot">Secured By <span class="pl-pb"><img src="${f(a.assetBase)}/payulink-logo.png" alt=""><strong>payulink</strong></span></div>
|
|
252
252
|
</div>
|
|
253
253
|
<aside class="pl-left">
|
|
254
254
|
<div class="pl-brandrow">
|
|
255
|
-
<div class="pl-logo"><img src="${
|
|
255
|
+
<div class="pl-logo"><img src="${f(a.logo)}" alt=""></div>
|
|
256
256
|
<div class="pl-bmeta">
|
|
257
|
-
<div class="pl-bname">${
|
|
257
|
+
<div class="pl-bname">${f(a.name)}</div>
|
|
258
258
|
<div class="pl-btrust">${b.verified}<span>Trusted Business</span></div>
|
|
259
259
|
</div>
|
|
260
260
|
</div>
|
|
261
261
|
<div class="pl-summary">
|
|
262
262
|
<div class="pl-sl">Price Summary</div>
|
|
263
263
|
<div class="pl-samt">${r}</div>
|
|
264
|
-
<div class="pl-snote">${
|
|
264
|
+
<div class="pl-snote">${f(a.note||"Paying for "+(a.description||a.name))}</div>
|
|
265
265
|
</div>
|
|
266
266
|
<svg class="pl-illus" viewBox="0 0 230 150" fill="none"><rect x="20" y="70" width="58" height="68" rx="5" fill="#fff" fill-opacity=".92"/><path d="M33 70c0-10 5-16 16-16s16 6 16 16" stroke="#fff" stroke-width="3.5"/><rect x="88" y="55" width="68" height="83" rx="5" fill="#fff"/><path d="M104 55c0-12 6-19 18-19s18 7 18 19" stroke="#fff" stroke-width="3.5"/><rect x="150" y="92" width="52" height="46" rx="4" fill="#fff" fill-opacity=".92"/><circle cx="178" cy="40" r="18" fill="#fff"/><path d="M178 30v20M168 40h20" stroke="currentColor" stroke-width="3.5" opacity=".5"/></svg>
|
|
267
|
-
<div class="pl-secured">${
|
|
267
|
+
<div class="pl-secured">${R}Secured by <span class="pl-pb"><img src="${f(a.assetBase)}/payulink-logo.png" alt=""><strong>payulink</strong></span></div>
|
|
268
268
|
</aside>
|
|
269
269
|
<section class="pl-main">
|
|
270
270
|
<header class="pl-head">
|
|
@@ -276,21 +276,21 @@ var j=Object.defineProperty;var ee=Object.getOwnPropertyDescriptor;var le=Object
|
|
|
276
276
|
<div class="pl-vp"><div class="pl-screen pl-active" id="pl-screen"></div></div>
|
|
277
277
|
<footer class="pl-foot">${b.lock}<span>Encrypted & secure payments</span></footer>
|
|
278
278
|
</section>
|
|
279
|
-
</div>`,document.body.appendChild(
|
|
279
|
+
</div>`,document.body.appendChild(p);let x=document.body.style.overflow;document.body.style.overflow="hidden";let S=p.querySelector(".pl-vp"),I=p.querySelector("#pl-title"),z=p.querySelector("#pl-back");function k(){d(),a.onDismiss&&a.onDismiss()}function d(){if(l.stop)try{l.stop()}catch{}clearInterval(l.timer),p.classList.add("pl-closing"),document.body.style.overflow=x,setTimeout(()=>p.remove(),240)}p.querySelector("#pl-close").onclick=k,p.addEventListener("mousedown",e=>{e.target.id==="pl-overlay"&&k()}),z.onclick=()=>{l.screen==="contact"||l.screen==="success"||i("options")};let u={loader:"Payment Options",contact:"Contact Details",options:"Payment Options",success:"Payment Successful"};function i(e){l.screen=e,I.textContent=u[e]||"Payment",z.classList.toggle("pl-show",e==="options"),clearInterval(l.timer);let t=document.createElement("div");t.className="pl-screen pl-active"+(e==="options"?" pl-screen-options":""),t.innerHTML=c[e]?c[e]():"",S.replaceChildren(t),N(e,t)}let g=h.slice(0,4).map(e=>`<img src="${y[e]}" alt="">`).join(""),_=h.map(e=>`<a class="pl-uapp" data-app="${e}" title="${e}"><img src="${y[e]}" alt="${e}"></a>`).join(""),c={loader:()=>`<div class="pl-loader"><div class="pl-bload"><img src="${f(a.logo)}" alt=""><span class="pl-bring"></span><span class="pl-bripple"></span><span class="pl-bripple pl-bripple2"></span></div><p>Securely loading payment options\u2026</p></div>`,contact:()=>`
|
|
280
280
|
<div class="pl-pad">
|
|
281
281
|
<div class="pl-h1">Contact details</div>
|
|
282
282
|
<div class="pl-sub">Enter your details to continue the payment</div>
|
|
283
283
|
<div class="pl-field"><label>Full Name</label>
|
|
284
|
-
<input class="pl-input" id="pl-name" type="text" placeholder="Enter your name" value="${
|
|
284
|
+
<input class="pl-input" id="pl-name" type="text" placeholder="Enter your name" value="${f(a.prefill.name||"")}"></div>
|
|
285
285
|
<div class="pl-field"><label>Mobile Number</label>
|
|
286
286
|
<div class="pl-phone"><div class="pl-cc">+91</div>
|
|
287
|
-
<input class="pl-input" id="pl-mobile" type="tel" maxlength="10" placeholder="Enter mobile number" value="${
|
|
287
|
+
<input class="pl-input" id="pl-mobile" type="tel" maxlength="10" placeholder="Enter mobile number" value="${f(a.prefill.contact||"")}"></div></div>
|
|
288
288
|
<div class="pl-field"><label>Email Address <span class="pl-opt">(optional)</span></label>
|
|
289
289
|
<div class="pl-inwrap"><span class="pl-inicon">${b.mail}</span>
|
|
290
|
-
<input class="pl-input pl-padleft" id="pl-email" type="email" placeholder="Enter email address" value="${
|
|
290
|
+
<input class="pl-input pl-padleft" id="pl-email" type="email" placeholder="Enter email address" value="${f(a.prefill.email||"")}"></div></div>
|
|
291
291
|
<button class="pl-cta" id="pl-continue">Continue <span class="pl-cta-arr">${b.arrow}</span></button>
|
|
292
292
|
<div class="pl-err" id="pl-cerr"></div>
|
|
293
|
-
<div class="pl-trust">${
|
|
293
|
+
<div class="pl-trust">${R}100% secure payments</div>
|
|
294
294
|
</div>`,options:()=>`
|
|
295
295
|
<div class="pl-options">
|
|
296
296
|
<div class="pl-nav" id="pl-nav">
|
|
@@ -308,25 +308,25 @@ var j=Object.defineProperty;var ee=Object.getOwnPropertyDescriptor;var le=Object
|
|
|
308
308
|
<span class="pl-soon">Coming soon</span>
|
|
309
309
|
</div>`).join("")}
|
|
310
310
|
</div>
|
|
311
|
-
<div class="pl-pane" id="pl-pane">${
|
|
311
|
+
<div class="pl-pane" id="pl-pane">${M()}</div>
|
|
312
312
|
</div>`,success:()=>{let e=["#00c060","#3395ff","#ffb020","#ff5a5f","#7a52d8","#19c3c3"];return`
|
|
313
313
|
<div class="pl-success">
|
|
314
314
|
<div class="pl-burst">
|
|
315
|
-
${Array.from({length:18},(
|
|
315
|
+
${Array.from({length:18},(n,s)=>{let v=s/18*Math.PI*2+(s%2?.22:-.22),q=60+s*13%40,F=Math.round(Math.cos(v)*q),G=Math.round(Math.sin(v)*q),W=e[s%e.length],Z=(s%2?1:-1)*(140+s*14),J=s%3===0?6:8,K=s%4===0?6:12;return`<i class="pl-confetti" style="--tx:${F}px;--ty:${G}px;--c:${W};--r:${Z}deg;width:${J}px;height:${K}px;border-radius:${s%4===0?"50%":"2px"};animation-delay:${(.15+s*.024).toFixed(3)}s"></i>`}).join("")}
|
|
316
316
|
<span class="pl-ripple"></span><span class="pl-ripple pl-ripple2"></span>
|
|
317
317
|
<div class="pl-check"><svg viewBox="0 0 24 24"><path d="M5 13l4 4L19 7"/></svg></div>
|
|
318
318
|
</div>
|
|
319
319
|
<h2>Payment Successful</h2>
|
|
320
|
-
<p>${r} paid${a.name?" to "+
|
|
321
|
-
<div class="pl-pid" id="pl-pid">${
|
|
322
|
-
${l.utr?`<div class="pl-pid pl-utr">UTR ${
|
|
323
|
-
</div>`}};function
|
|
320
|
+
<p>${r} paid${a.name?" to "+f(a.name):""}</p>
|
|
321
|
+
<div class="pl-pid" id="pl-pid">${f(l.order&&l.order.merchant_order_no||"")}</div>
|
|
322
|
+
${l.utr?`<div class="pl-pid pl-utr">UTR ${f(l.utr)}</div>`:""}
|
|
323
|
+
</div>`}};function M(){return`
|
|
324
324
|
<div class="pl-paneh">UPI QR</div>
|
|
325
325
|
<div class="pl-qrcard">
|
|
326
326
|
<div class="pl-qrbox" id="pl-qr"><div class="pl-qrloading"></div></div>
|
|
327
327
|
<div class="pl-qrside">
|
|
328
328
|
<div class="pl-scan">Scan the QR using any UPI App</div>
|
|
329
|
-
<div class="pl-approw" id="pl-applist">${
|
|
329
|
+
<div class="pl-approw" id="pl-applist">${_}</div>
|
|
330
330
|
<div class="pl-validrow"><span class="pl-dot"></span><span id="pl-timer">Valid 5:00</span></div>
|
|
331
331
|
</div>
|
|
332
332
|
</div>
|
|
@@ -335,4 +335,4 @@ var j=Object.defineProperty;var ee=Object.getOwnPropertyDescriptor;var le=Object
|
|
|
335
335
|
<input class="pl-vpa" id="pl-vpa" placeholder="example@okhdfcbank" autocomplete="off" spellcheck="false">
|
|
336
336
|
<button class="pl-verify" id="pl-verify">Verify and Pay</button>
|
|
337
337
|
</div>
|
|
338
|
-
<div id="pl-status" class="pl-pendrow"><span class="pl-mini-spin"></span> Waiting for payment\u2026</div>`}function N(e,t){if(e==="contact")t.querySelector("#pl-continue").onclick=()=>{let
|
|
338
|
+
<div id="pl-status" class="pl-pendrow"><span class="pl-mini-spin"></span> Waiting for payment\u2026</div>`}function N(e,t){if(e==="contact")t.querySelector("#pl-continue").onclick=()=>{let n=t.querySelector("#pl-name").value.trim(),s=t.querySelector("#pl-mobile").value.replace(/\D/g,""),v=t.querySelector("#pl-email").value.trim(),q=t.querySelector("#pl-cerr");if(n.length<2)return q.textContent="Please enter your name";if(s.length!==10)return q.textContent="Enter a valid 10-digit mobile number";l.customer={name:n,mobile:s,email:v},i("options")};else if(e==="options"){t.querySelectorAll(".pl-navitem").forEach(s=>s.onclick=()=>{s.dataset.m!=="upi"&&C("Coming soon \u2014 please pay via UPI / QR for now")});let n=t.querySelector("#pl-verify");n&&(n.onclick=()=>{let s=(t.querySelector("#pl-vpa").value||"").trim();if(!/^[\w.\-]{2,}@[a-zA-Z]{2,}$/.test(s))return t.querySelector("#pl-vpa").focus(),C("Enter a valid UPI ID, e.g. name@okhdfcbank");let v=l.order&&(l.order.upi_intent_url||l.order.payment_link);v&&/Android|iPhone|iPad|Mobile/i.test(navigator.userAgent)?location.href=v:C("Scan the QR with your phone\u2019s UPI app to complete the payment.")}),B(),P(!0)}}let $=!1;async function P(e){if(e||i("options"),l.order){L();return}if(!$){$=!0;try{l.customer||(l.customer={name:a.prefill.name||"Customer",mobile:(a.prefill.contact||"").replace(/\D/g,""),email:a.prefill.email||""}),l.order=await a.createOrder(l.customer),L(),V()}catch(t){let n=p.querySelector("#pl-qr");if(n){n.innerHTML=`<div class="pl-qrerr"><span>${f(t.message||"Could not start payment")}</span><button class="pl-retry" id="pl-retry">Try again</button></div>`;let s=n.querySelector("#pl-retry");s&&(s.onclick=()=>{$=!1,n.innerHTML='<div class="pl-qrloading"></div>',P(!0)})}}finally{$=!1}}}function L(){let e=l.order;if(!e)return;Y(e);let t=p.querySelector("#pl-qr");t&&(e.qr_data_url?t.innerHTML=`<img src="${e.qr_data_url}" alt="UPI QR">`:t.innerHTML=`<div class="pl-qrerr"><span>${f(e.qr_unavailable_reason||"QR unavailable \u2014 use a UPI app below")}</span></div>`);let n=e.upi_intent_url||e.payment_link||"#",s=p.querySelector("#pl-applist");s&&s.querySelectorAll(".pl-uapp").forEach(v=>{v.setAttribute("href",n),v.setAttribute("target","_blank"),v.setAttribute("rel","noopener")}),B()}function Y(e){e&&e.expires_at&&e.server_now?l.expiryMs=Date.now()+Math.max(0,e.expires_at-e.server_now):l.expiryMs||(l.expiryMs=Date.now()+5*60*1e3)}function T(){if(l.done)return;let e=p.querySelector("#pl-qr");e&&(e.innerHTML='<div class="pl-qrerr"><span>QR code expired</span><button class="pl-retry" id="pl-regen">Generate new QR</button></div>');let t=p.querySelector("#pl-regen");t&&(t.onclick=H);let n=p.querySelector("#pl-timer");n&&(n.textContent="Expired");let s=p.querySelector(".pl-validrow");s&&s.classList.add("pl-expired")}function H(){if(l.stop){try{l.stop()}catch{}l.stop=null}l.order=null,l.expiryMs=null,$=!1;let e=p.querySelector(".pl-validrow");e&&e.classList.remove("pl-expired");let t=p.querySelector("#pl-qr");t&&(t.innerHTML='<div class="pl-qrloading"></div>'),P(!0)}function V(){!l.order||l.stop||(l.stop=a.watchOrder(l.order.merchant_order_no,e=>{!e||typeof e.status!="number"||(e.status===0?(l.utr=e.utr||l.utr,Q()):e.status===3?(clearInterval(l.timer),l.expiryMs=Date.now(),T(),j("failed","QR expired \u2014 generate a new one")):[1,4].includes(e.status)?j("failed","Payment "+(e.status_label||"failed").toLowerCase()):e.status===6&&j("pending","Processing payment\u2026"))}))}function j(e,t){let n=p.querySelector("#pl-status");n&&(n.className=e==="failed"?"pl-pendrow pl-fail":"pl-pendrow",n.innerHTML=(e==="pending"?'<span class="pl-mini-spin"></span> ':"")+f(t))}function Q(){l.done||(l.done=!0,clearInterval(l.timer),i("success"),a.onSuccess&&a.onSuccess({merchant_order_no:l.order.merchant_order_no,utr:l.utr,amount:a.amount}),l.utr||X())}async function X(){for(let e=0;e<10&&!l.utr;e++){await new Promise(t=>setTimeout(t,4e3));try{let t=await fetch(`${o}/api/order/${l.order.merchant_order_no}`).then(n=>n.json());if(t.utr){l.utr=t.utr;let n=p.querySelector("#pl-pid");n&&l.screen==="success"&&n.insertAdjacentHTML("afterend",`<div class="pl-pid pl-utr">UTR ${f(t.utr)}</div>`);break}}catch{}}}function B(){clearInterval(l.timer);let e=()=>{let t=p.querySelector("#pl-timer");if(!t)return;if(!l.expiryMs){t.textContent="Valid 5:00";return}let n=Math.max(0,Math.round((l.expiryMs-Date.now())/1e3));t.textContent=n>0?"Valid "+pe(n):"Expired",n<=0&&(clearInterval(l.timer),T())};e(),l.timer=setInterval(e,1e3)}function C(e){let t=document.getElementById("pl-toast");t||(t=document.createElement("div"),t.id="pl-toast",document.body.appendChild(t)),t.textContent=e,t.classList.add("pl-show"),clearTimeout(t._t),t._t=setTimeout(()=>t.classList.remove("pl-show"),2600)}return i("loader"),setTimeout(()=>{let e=a.prefill||{};e.name&&(e.contact||"").replace(/\D/g,"").length===10?(l.customer={name:e.name,mobile:e.contact.replace(/\D/g,""),email:e.email||""},i("options")):i("contact");let t=p.querySelector("#pl-splash");t&&(t.classList.add("pl-splash-hide"),setTimeout(()=>t.remove(),450))},1600),{close:d}}var D={apiBase:"https://payulink.io/api",assetBase:"https://assetcdn.payulink.io/checkout/v1/assets",name:null,logo:null,brandColor:null,pollMs:2500},w=class a{constructor(o={}){if(typeof window=="undefined"||typeof document=="undefined")throw new Error("PayuLink checkout runs in the browser only. On React Native use @thepayulink/checkout-react-native; on a server use @thepayulink/server.");let r=o.key||o.keyId||o.key_id;if(!r)throw new Error("PayuLink: `key` (your publishable pl_live_\u2026 / pl_test_\u2026 key) is required");if(/^pl_(live|test)_/.test(r)||console.warn("PayuLink: `key` should look like pl_live_\u2026 or pl_test_\u2026"),o.keySecret||o.key_secret)throw new Error("PayuLink: never pass a key_secret to the browser SDK. It belongs on your server only.");this.options=Object.assign({},D,o,{key:r})}open(o={}){let r=Object.assign({},this.options,o),y=String(r.apiBase||"").replace(/\/$/,""),h=String(r.assetBase||`${y}/assets`).replace(/\/$/,""),l=r.order_id||r.orderId;if(!l)throw new Error("PayuLink: `order_id` is required. Create it on your server with POST /v1/orders.");let p=d=>{typeof r.onError=="function"?r.onError(d):console.error("PayuLink:",d.message||d)},x=null,S=null,I=async d=>{var g,_,c;let u=await fetch(`${y}/v1/checkout/session`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({key_id:r.key,order_id:l,customer:d?{name:d.name,contact:d.mobile||d.contact,email:d.email}:void 0})}),i=await u.json().catch(()=>({}));if(!u.ok){let M=new Error(((g=i==null?void 0:i.error)==null?void 0:g.description)||`Could not start payment (HTTP ${u.status})`);throw M.code=(_=i==null?void 0:i.error)==null?void 0:_.code,M.retriable=((c=i==null?void 0:i.error)==null?void 0:c.code)==="GATEWAY_BUSY",M}return x=i,{merchant_order_no:i.order_id,amount:i.amount/100,upi_intent_url:i.upi_intent_url,payment_link:i.payment_link,qr_data_url:i.qr_data_url||null,qr_unavailable_reason:i.qr_unavailable_reason||null,qr_retriable:i.qr_retriable===!0,expires_at:i.expires_at?i.expires_at*1e3:null,server_now:Date.now()}},z=(d,u)=>{let i=async()=>{if(x!=null&&x.session_token)try{let c=await(await fetch(`${y}/v1/checkout/session/${encodeURIComponent(x.session_token)}`)).json().catch(()=>({}));c.status==="paid"&&c.payulink_signature&&(S={payulink_order_id:c.payulink_order_id,payulink_payment_id:c.payulink_payment_id,payulink_signature:c.payulink_signature,utr:c.utr||null,amount:c.amount}),u({status:c.status==="paid"?0:c.status==="failed"?1:c.status==="expired"?3:2,status_label:String(c.status||"pending").toUpperCase(),utr:c.utr||null})}catch{}},g=setInterval(i,r.pollMs||D.pollMs);return i(),()=>clearInterval(g)},k={_inner:null,close(){var d;(d=this._inner)==null||d.close()}};return fetch(`${y}/v1/checkout/order/${encodeURIComponent(l)}?key_id=${encodeURIComponent(r.key)}`).then(async d=>{var i;let u=await d.json().catch(()=>({}));if(!d.ok)throw new Error(((i=u==null?void 0:u.error)==null?void 0:i.description)||"Unknown or expired order");k._inner=A(Object.assign({},{apiBase:y,assetBase:h,name:r.name||u.merchant_name,logo:r.logo||`${h}/payulink-logo.png`,brandColor:r.brandColor,note:r.note,prefill:r.prefill||{},amount:u.amount/100,description:r.description||r.item||u.merchant_name,createOrder:I,watchOrder:z,onSuccess:()=>{let g=S||{payulink_order_id:(x==null?void 0:x.order_id)||l,payulink_payment_id:null,payulink_signature:null};typeof r.handler=="function"&&r.handler(g),typeof r.onSuccess=="function"&&r.onSuccess(g)},onDismiss:()=>{typeof r.onDismiss=="function"&&r.onDismiss()},onError:p}))}).catch(p),k}static open(o={}){return new a(o).open(o)}};typeof window!="undefined"&&(window.PayuLink=w,window.PayulinkCheckout=w);
|
|
@@ -237,7 +237,7 @@ var K=`
|
|
|
237
237
|
#pl-overlay .pl-approw { justify-content: center; }
|
|
238
238
|
#pl-overlay .pl-validrow { margin: 0 auto; }
|
|
239
239
|
}
|
|
240
|
-
`,
|
|
240
|
+
`,B=!1;function U(t=document){if(B&&t.getElementById("pl-checkout-styles"))return;let s=t.createElement("style");s.id="pl-checkout-styles",s.textContent=K,t.head.appendChild(s),B=!0}var ee=t=>"\u20B9"+Number(t||0).toLocaleString("en-IN",{maximumFractionDigits:2}),le=t=>`${Math.floor(t/60)}:${t%60<10?"0":""}${t%60}`,f=t=>String(t==null?"":t).replace(/[&<>"]/g,s=>({"&":"&","<":"<",">":">",'"':"""})[s]),h=t=>`<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">${t}</svg>`,g={qr:h('<rect width="5" height="5" x="3" y="3" rx="1"/><rect width="5" height="5" x="16" y="3" rx="1"/><rect width="5" height="5" x="3" y="16" rx="1"/><path d="M21 16h-3a2 2 0 0 0-2 2v3"/><path d="M21 21v.01"/><path d="M12 7v3a2 2 0 0 1-2 2H7"/><path d="M3 12h.01"/><path d="M12 3h.01"/><path d="M12 16v.01"/><path d="M16 12h1"/><path d="M21 12v.01"/><path d="M12 21v-1"/>'),card:h('<rect width="20" height="14" x="2" y="5" rx="2"/><line x1="2" x2="22" y1="10" y2="10"/>'),netbanking:h('<path d="M10 18v-7"/><path d="M11.119 2.205a2 2 0 0 1 1.762 0l7.84 3.846A.5.5 0 0 1 20.5 7h-17a.5.5 0 0 1-.22-.949z"/><path d="M14 18v-7"/><path d="M18 18v-7"/><path d="M3 22h18"/><path d="M6 18v-7"/>'),wallet:h('<path d="M19 7V4a1 1 0 0 0-1-1H5a2 2 0 0 0 0 4h15a1 1 0 0 1 1 1v4h-3a2 2 0 0 0 0 4h3a1 1 0 0 0 1-1v-2a1 1 0 0 0-1-1"/><path d="M3 5v14a2 2 0 0 0 2 2h15a1 1 0 0 0 1-1v-4"/>'),emi:h('<path d="M16 14v2.2l1.6 1"/><path d="M16 2v4"/><path d="M21 7.5V6a2 2 0 0 0-2-2H5a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h3.5"/><path d="M3 10h5"/><path d="M8 2v4"/><circle cx="16" cy="16" r="6"/>'),back:h('<path d="M15 18l-6-6 6-6"/>'),mail:h('<rect x="2" y="4" width="20" height="16" rx="2"/><path d="m22 7-10 5L2 7"/>'),arrow:h('<path d="M5 12h14M13 6l6 6-6 6"/>'),verified:h('<path d="M9 12l2 2 4-4"/><circle cx="12" cy="12" r="10"/>'),lock:h('<rect width="18" height="11" x="3" y="11" rx="2"/><path d="M7 11V7a5 5 0 0 1 10 0v4"/>')},O='<svg width="13" height="13" viewBox="0 0 24 24" fill="currentColor"><path d="M12 1l9 4v6c0 5.5-3.8 10.7-9 12-5.2-1.3-9-6.5-9-12V5l9-4z"/></svg>',ae=[{m:"card",t:"Cards",s:"Visa, Mastercard & RuPay",ic:"card"},{m:"netbanking",t:"Netbanking",s:"All Indian banks",ic:"netbanking"},{m:"wallet",t:"Wallet",s:"Paytm, PhonePe & more",ic:"wallet"},{m:"emi",t:"EMI",s:"EMI via cards & more",ic:"emi"}];function R(t){U(),t=Object.assign({name:"Payment",description:"",amount:0,assetBase:"/assets",logo:"/assets/payulink-logo.png",prefill:{},apiBase:""},t);let s=String(t.apiBase||"").replace(/\/$/,""),i=ee(t.amount),m=["gpay","phonepe","paytm","bhim","amazonpay"].reduce((e,a)=>(e[a]=`${t.assetBase}/upi/${a}.png`,e),{}),b=["phonepe","gpay","paytm","bhim","amazonpay"],l={screen:"loader",order:null,customer:null,timer:null,stop:null,done:!1,utr:null,expiryMs:null},n=document.createElement("div");n.id="pl-overlay",t.brandColor&&n.style.setProperty("--pl-brand",t.brandColor),n.innerHTML=`
|
|
241
241
|
<div class="pl-modal" role="dialog" aria-modal="true">
|
|
242
242
|
<div class="pl-splash" id="pl-splash">
|
|
243
243
|
<div class="pl-shield">
|
|
@@ -246,25 +246,25 @@ var K=`
|
|
|
246
246
|
<path d="M60 3 L113 25 V70 C113 105 90 128 60 137 C30 128 7 105 7 70 V25 Z" fill="url(#pl-shgrad)"/>
|
|
247
247
|
</svg>
|
|
248
248
|
<span class="pl-shield-shine"></span>
|
|
249
|
-
<img class="pl-shield-logo" src="${
|
|
249
|
+
<img class="pl-shield-logo" src="${f(t.assetBase)}/payulink-logo.png" alt="payulink">
|
|
250
250
|
</div>
|
|
251
|
-
<div class="pl-splash-foot">Secured By <span class="pl-pb"><img src="${
|
|
251
|
+
<div class="pl-splash-foot">Secured By <span class="pl-pb"><img src="${f(t.assetBase)}/payulink-logo.png" alt=""><strong>payulink</strong></span></div>
|
|
252
252
|
</div>
|
|
253
253
|
<aside class="pl-left">
|
|
254
254
|
<div class="pl-brandrow">
|
|
255
|
-
<div class="pl-logo"><img src="${
|
|
255
|
+
<div class="pl-logo"><img src="${f(t.logo)}" alt=""></div>
|
|
256
256
|
<div class="pl-bmeta">
|
|
257
|
-
<div class="pl-bname">${
|
|
257
|
+
<div class="pl-bname">${f(t.name)}</div>
|
|
258
258
|
<div class="pl-btrust">${g.verified}<span>Trusted Business</span></div>
|
|
259
259
|
</div>
|
|
260
260
|
</div>
|
|
261
261
|
<div class="pl-summary">
|
|
262
262
|
<div class="pl-sl">Price Summary</div>
|
|
263
|
-
<div class="pl-samt">${
|
|
264
|
-
<div class="pl-snote">${
|
|
263
|
+
<div class="pl-samt">${i}</div>
|
|
264
|
+
<div class="pl-snote">${f(t.note||"Paying for "+(t.description||t.name))}</div>
|
|
265
265
|
</div>
|
|
266
266
|
<svg class="pl-illus" viewBox="0 0 230 150" fill="none"><rect x="20" y="70" width="58" height="68" rx="5" fill="#fff" fill-opacity=".92"/><path d="M33 70c0-10 5-16 16-16s16 6 16 16" stroke="#fff" stroke-width="3.5"/><rect x="88" y="55" width="68" height="83" rx="5" fill="#fff"/><path d="M104 55c0-12 6-19 18-19s18 7 18 19" stroke="#fff" stroke-width="3.5"/><rect x="150" y="92" width="52" height="46" rx="4" fill="#fff" fill-opacity=".92"/><circle cx="178" cy="40" r="18" fill="#fff"/><path d="M178 30v20M168 40h20" stroke="currentColor" stroke-width="3.5" opacity=".5"/></svg>
|
|
267
|
-
<div class="pl-secured">${
|
|
267
|
+
<div class="pl-secured">${O}Secured by <span class="pl-pb"><img src="${f(t.assetBase)}/payulink-logo.png" alt=""><strong>payulink</strong></span></div>
|
|
268
268
|
</aside>
|
|
269
269
|
<section class="pl-main">
|
|
270
270
|
<header class="pl-head">
|
|
@@ -276,21 +276,21 @@ var K=`
|
|
|
276
276
|
<div class="pl-vp"><div class="pl-screen pl-active" id="pl-screen"></div></div>
|
|
277
277
|
<footer class="pl-foot">${g.lock}<span>Encrypted & secure payments</span></footer>
|
|
278
278
|
</section>
|
|
279
|
-
</div>`,document.body.appendChild(
|
|
279
|
+
</div>`,document.body.appendChild(n);let y=document.body.style.overflow;document.body.style.overflow="hidden";let S=n.querySelector(".pl-vp"),I=n.querySelector("#pl-title"),z=n.querySelector("#pl-back");function w(){d(),t.onDismiss&&t.onDismiss()}function d(){if(l.stop)try{l.stop()}catch{}clearInterval(l.timer),n.classList.add("pl-closing"),document.body.style.overflow=y,setTimeout(()=>n.remove(),240)}n.querySelector("#pl-close").onclick=w,n.addEventListener("mousedown",e=>{e.target.id==="pl-overlay"&&w()}),z.onclick=()=>{l.screen==="contact"||l.screen==="success"||r("options")};let u={loader:"Payment Options",contact:"Contact Details",options:"Payment Options",success:"Payment Successful"};function r(e){l.screen=e,I.textContent=u[e]||"Payment",z.classList.toggle("pl-show",e==="options"),clearInterval(l.timer);let a=document.createElement("div");a.className="pl-screen pl-active"+(e==="options"?" pl-screen-options":""),a.innerHTML=c[e]?c[e]():"",S.replaceChildren(a),D(e,a)}let x=b.slice(0,4).map(e=>`<img src="${m[e]}" alt="">`).join(""),k=b.map(e=>`<a class="pl-uapp" data-app="${e}" title="${e}"><img src="${m[e]}" alt="${e}"></a>`).join(""),c={loader:()=>`<div class="pl-loader"><div class="pl-bload"><img src="${f(t.logo)}" alt=""><span class="pl-bring"></span><span class="pl-bripple"></span><span class="pl-bripple pl-bripple2"></span></div><p>Securely loading payment options\u2026</p></div>`,contact:()=>`
|
|
280
280
|
<div class="pl-pad">
|
|
281
281
|
<div class="pl-h1">Contact details</div>
|
|
282
282
|
<div class="pl-sub">Enter your details to continue the payment</div>
|
|
283
283
|
<div class="pl-field"><label>Full Name</label>
|
|
284
|
-
<input class="pl-input" id="pl-name" type="text" placeholder="Enter your name" value="${
|
|
284
|
+
<input class="pl-input" id="pl-name" type="text" placeholder="Enter your name" value="${f(t.prefill.name||"")}"></div>
|
|
285
285
|
<div class="pl-field"><label>Mobile Number</label>
|
|
286
286
|
<div class="pl-phone"><div class="pl-cc">+91</div>
|
|
287
|
-
<input class="pl-input" id="pl-mobile" type="tel" maxlength="10" placeholder="Enter mobile number" value="${
|
|
287
|
+
<input class="pl-input" id="pl-mobile" type="tel" maxlength="10" placeholder="Enter mobile number" value="${f(t.prefill.contact||"")}"></div></div>
|
|
288
288
|
<div class="pl-field"><label>Email Address <span class="pl-opt">(optional)</span></label>
|
|
289
289
|
<div class="pl-inwrap"><span class="pl-inicon">${g.mail}</span>
|
|
290
|
-
<input class="pl-input pl-padleft" id="pl-email" type="email" placeholder="Enter email address" value="${
|
|
290
|
+
<input class="pl-input pl-padleft" id="pl-email" type="email" placeholder="Enter email address" value="${f(t.prefill.email||"")}"></div></div>
|
|
291
291
|
<button class="pl-cta" id="pl-continue">Continue <span class="pl-cta-arr">${g.arrow}</span></button>
|
|
292
292
|
<div class="pl-err" id="pl-cerr"></div>
|
|
293
|
-
<div class="pl-trust">${
|
|
293
|
+
<div class="pl-trust">${O}100% secure payments</div>
|
|
294
294
|
</div>`,options:()=>`
|
|
295
295
|
<div class="pl-options">
|
|
296
296
|
<div class="pl-nav" id="pl-nav">
|
|
@@ -308,25 +308,25 @@ var K=`
|
|
|
308
308
|
<span class="pl-soon">Coming soon</span>
|
|
309
309
|
</div>`).join("")}
|
|
310
310
|
</div>
|
|
311
|
-
<div class="pl-pane" id="pl-pane">${
|
|
311
|
+
<div class="pl-pane" id="pl-pane">${_()}</div>
|
|
312
312
|
</div>`,success:()=>{let e=["#00c060","#3395ff","#ffb020","#ff5a5f","#7a52d8","#19c3c3"];return`
|
|
313
313
|
<div class="pl-success">
|
|
314
314
|
<div class="pl-burst">
|
|
315
|
-
${Array.from({length:18},(
|
|
315
|
+
${Array.from({length:18},(o,p)=>{let v=p/18*Math.PI*2+(p%2?.22:-.22),$=60+p*13%40,X=Math.round(Math.cos(v)*$),F=Math.round(Math.sin(v)*$),G=e[p%e.length],W=(p%2?1:-1)*(140+p*14),Z=p%3===0?6:8,J=p%4===0?6:12;return`<i class="pl-confetti" style="--tx:${X}px;--ty:${F}px;--c:${G};--r:${W}deg;width:${Z}px;height:${J}px;border-radius:${p%4===0?"50%":"2px"};animation-delay:${(.15+p*.024).toFixed(3)}s"></i>`}).join("")}
|
|
316
316
|
<span class="pl-ripple"></span><span class="pl-ripple pl-ripple2"></span>
|
|
317
317
|
<div class="pl-check"><svg viewBox="0 0 24 24"><path d="M5 13l4 4L19 7"/></svg></div>
|
|
318
318
|
</div>
|
|
319
319
|
<h2>Payment Successful</h2>
|
|
320
|
-
<p>${
|
|
321
|
-
<div class="pl-pid" id="pl-pid">${
|
|
322
|
-
${l.utr?`<div class="pl-pid pl-utr">UTR ${
|
|
323
|
-
</div>`}};function
|
|
320
|
+
<p>${i} paid${t.name?" to "+f(t.name):""}</p>
|
|
321
|
+
<div class="pl-pid" id="pl-pid">${f(l.order&&l.order.merchant_order_no||"")}</div>
|
|
322
|
+
${l.utr?`<div class="pl-pid pl-utr">UTR ${f(l.utr)}</div>`:""}
|
|
323
|
+
</div>`}};function _(){return`
|
|
324
324
|
<div class="pl-paneh">UPI QR</div>
|
|
325
325
|
<div class="pl-qrcard">
|
|
326
326
|
<div class="pl-qrbox" id="pl-qr"><div class="pl-qrloading"></div></div>
|
|
327
327
|
<div class="pl-qrside">
|
|
328
328
|
<div class="pl-scan">Scan the QR using any UPI App</div>
|
|
329
|
-
<div class="pl-approw" id="pl-applist">${
|
|
329
|
+
<div class="pl-approw" id="pl-applist">${k}</div>
|
|
330
330
|
<div class="pl-validrow"><span class="pl-dot"></span><span id="pl-timer">Valid 5:00</span></div>
|
|
331
331
|
</div>
|
|
332
332
|
</div>
|
|
@@ -335,4 +335,4 @@ var K=`
|
|
|
335
335
|
<input class="pl-vpa" id="pl-vpa" placeholder="example@okhdfcbank" autocomplete="off" spellcheck="false">
|
|
336
336
|
<button class="pl-verify" id="pl-verify">Verify and Pay</button>
|
|
337
337
|
</div>
|
|
338
|
-
<div id="pl-status" class="pl-pendrow"><span class="pl-mini-spin"></span> Waiting for payment\u2026</div>`}function
|
|
338
|
+
<div id="pl-status" class="pl-pendrow"><span class="pl-mini-spin"></span> Waiting for payment\u2026</div>`}function D(e,a){if(e==="contact")a.querySelector("#pl-continue").onclick=()=>{let o=a.querySelector("#pl-name").value.trim(),p=a.querySelector("#pl-mobile").value.replace(/\D/g,""),v=a.querySelector("#pl-email").value.trim(),$=a.querySelector("#pl-cerr");if(o.length<2)return $.textContent="Please enter your name";if(p.length!==10)return $.textContent="Enter a valid 10-digit mobile number";l.customer={name:o,mobile:p,email:v},r("options")};else if(e==="options"){a.querySelectorAll(".pl-navitem").forEach(p=>p.onclick=()=>{p.dataset.m!=="upi"&&C("Coming soon \u2014 please pay via UPI / QR for now")});let o=a.querySelector("#pl-verify");o&&(o.onclick=()=>{let p=(a.querySelector("#pl-vpa").value||"").trim();if(!/^[\w.\-]{2,}@[a-zA-Z]{2,}$/.test(p))return a.querySelector("#pl-vpa").focus(),C("Enter a valid UPI ID, e.g. name@okhdfcbank");let v=l.order&&(l.order.upi_intent_url||l.order.payment_link);v&&/Android|iPhone|iPad|Mobile/i.test(navigator.userAgent)?location.href=v:C("Scan the QR with your phone\u2019s UPI app to complete the payment.")}),T(),P(!0)}}let M=!1;async function P(e){if(e||r("options"),l.order){E();return}if(!M){M=!0;try{l.customer||(l.customer={name:t.prefill.name||"Customer",mobile:(t.prefill.contact||"").replace(/\D/g,""),email:t.prefill.email||""}),l.order=await t.createOrder(l.customer),E(),H()}catch(a){let o=n.querySelector("#pl-qr");if(o){o.innerHTML=`<div class="pl-qrerr"><span>${f(a.message||"Could not start payment")}</span><button class="pl-retry" id="pl-retry">Try again</button></div>`;let p=o.querySelector("#pl-retry");p&&(p.onclick=()=>{M=!1,o.innerHTML='<div class="pl-qrloading"></div>',P(!0)})}}finally{M=!1}}}function E(){let e=l.order;if(!e)return;N(e);let a=n.querySelector("#pl-qr");a&&(e.qr_data_url?a.innerHTML=`<img src="${e.qr_data_url}" alt="UPI QR">`:a.innerHTML=`<div class="pl-qrerr"><span>${f(e.qr_unavailable_reason||"QR unavailable \u2014 use a UPI app below")}</span></div>`);let o=e.upi_intent_url||e.payment_link||"#",p=n.querySelector("#pl-applist");p&&p.querySelectorAll(".pl-uapp").forEach(v=>{v.setAttribute("href",o),v.setAttribute("target","_blank"),v.setAttribute("rel","noopener")}),T()}function N(e){e&&e.expires_at&&e.server_now?l.expiryMs=Date.now()+Math.max(0,e.expires_at-e.server_now):l.expiryMs||(l.expiryMs=Date.now()+5*60*1e3)}function L(){if(l.done)return;let e=n.querySelector("#pl-qr");e&&(e.innerHTML='<div class="pl-qrerr"><span>QR code expired</span><button class="pl-retry" id="pl-regen">Generate new QR</button></div>');let a=n.querySelector("#pl-regen");a&&(a.onclick=Y);let o=n.querySelector("#pl-timer");o&&(o.textContent="Expired");let p=n.querySelector(".pl-validrow");p&&p.classList.add("pl-expired")}function Y(){if(l.stop){try{l.stop()}catch{}l.stop=null}l.order=null,l.expiryMs=null,M=!1;let e=n.querySelector(".pl-validrow");e&&e.classList.remove("pl-expired");let a=n.querySelector("#pl-qr");a&&(a.innerHTML='<div class="pl-qrloading"></div>'),P(!0)}function H(){!l.order||l.stop||(l.stop=t.watchOrder(l.order.merchant_order_no,e=>{!e||typeof e.status!="number"||(e.status===0?(l.utr=e.utr||l.utr,V()):e.status===3?(clearInterval(l.timer),l.expiryMs=Date.now(),L(),j("failed","QR expired \u2014 generate a new one")):[1,4].includes(e.status)?j("failed","Payment "+(e.status_label||"failed").toLowerCase()):e.status===6&&j("pending","Processing payment\u2026"))}))}function j(e,a){let o=n.querySelector("#pl-status");o&&(o.className=e==="failed"?"pl-pendrow pl-fail":"pl-pendrow",o.innerHTML=(e==="pending"?'<span class="pl-mini-spin"></span> ':"")+f(a))}function V(){l.done||(l.done=!0,clearInterval(l.timer),r("success"),t.onSuccess&&t.onSuccess({merchant_order_no:l.order.merchant_order_no,utr:l.utr,amount:t.amount}),l.utr||Q())}async function Q(){for(let e=0;e<10&&!l.utr;e++){await new Promise(a=>setTimeout(a,4e3));try{let a=await fetch(`${s}/api/order/${l.order.merchant_order_no}`).then(o=>o.json());if(a.utr){l.utr=a.utr;let o=n.querySelector("#pl-pid");o&&l.screen==="success"&&o.insertAdjacentHTML("afterend",`<div class="pl-pid pl-utr">UTR ${f(a.utr)}</div>`);break}}catch{}}}function T(){clearInterval(l.timer);let e=()=>{let a=n.querySelector("#pl-timer");if(!a)return;if(!l.expiryMs){a.textContent="Valid 5:00";return}let o=Math.max(0,Math.round((l.expiryMs-Date.now())/1e3));a.textContent=o>0?"Valid "+le(o):"Expired",o<=0&&(clearInterval(l.timer),L())};e(),l.timer=setInterval(e,1e3)}function C(e){let a=document.getElementById("pl-toast");a||(a=document.createElement("div"),a.id="pl-toast",document.body.appendChild(a)),a.textContent=e,a.classList.add("pl-show"),clearTimeout(a._t),a._t=setTimeout(()=>a.classList.remove("pl-show"),2600)}return r("loader"),setTimeout(()=>{let e=t.prefill||{};e.name&&(e.contact||"").replace(/\D/g,"").length===10?(l.customer={name:e.name,mobile:e.contact.replace(/\D/g,""),email:e.email||""},r("options")):r("contact");let a=n.querySelector("#pl-splash");a&&(a.classList.add("pl-splash-hide"),setTimeout(()=>a.remove(),450))},1600),{close:d}}var A={apiBase:"https://payulink.io/api",assetBase:"https://assetcdn.payulink.io/checkout/v1/assets",name:null,logo:null,brandColor:null,pollMs:2500},q=class t{constructor(s={}){if(typeof window=="undefined"||typeof document=="undefined")throw new Error("PayuLink checkout runs in the browser only. On React Native use @thepayulink/checkout-react-native; on a server use @thepayulink/server.");let i=s.key||s.keyId||s.key_id;if(!i)throw new Error("PayuLink: `key` (your publishable pl_live_\u2026 / pl_test_\u2026 key) is required");if(/^pl_(live|test)_/.test(i)||console.warn("PayuLink: `key` should look like pl_live_\u2026 or pl_test_\u2026"),s.keySecret||s.key_secret)throw new Error("PayuLink: never pass a key_secret to the browser SDK. It belongs on your server only.");this.options=Object.assign({},A,s,{key:i})}open(s={}){let i=Object.assign({},this.options,s),m=String(i.apiBase||"").replace(/\/$/,""),b=String(i.assetBase||`${m}/assets`).replace(/\/$/,""),l=i.order_id||i.orderId;if(!l)throw new Error("PayuLink: `order_id` is required. Create it on your server with POST /v1/orders.");let n=d=>{typeof i.onError=="function"?i.onError(d):console.error("PayuLink:",d.message||d)},y=null,S=null,I=async d=>{var x,k,c;let u=await fetch(`${m}/v1/checkout/session`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({key_id:i.key,order_id:l,customer:d?{name:d.name,contact:d.mobile||d.contact,email:d.email}:void 0})}),r=await u.json().catch(()=>({}));if(!u.ok){let _=new Error(((x=r==null?void 0:r.error)==null?void 0:x.description)||`Could not start payment (HTTP ${u.status})`);throw _.code=(k=r==null?void 0:r.error)==null?void 0:k.code,_.retriable=((c=r==null?void 0:r.error)==null?void 0:c.code)==="GATEWAY_BUSY",_}return y=r,{merchant_order_no:r.order_id,amount:r.amount/100,upi_intent_url:r.upi_intent_url,payment_link:r.payment_link,qr_data_url:r.qr_data_url||null,qr_unavailable_reason:r.qr_unavailable_reason||null,qr_retriable:r.qr_retriable===!0,expires_at:r.expires_at?r.expires_at*1e3:null,server_now:Date.now()}},z=(d,u)=>{let r=async()=>{if(y!=null&&y.session_token)try{let c=await(await fetch(`${m}/v1/checkout/session/${encodeURIComponent(y.session_token)}`)).json().catch(()=>({}));c.status==="paid"&&c.payulink_signature&&(S={payulink_order_id:c.payulink_order_id,payulink_payment_id:c.payulink_payment_id,payulink_signature:c.payulink_signature,utr:c.utr||null,amount:c.amount}),u({status:c.status==="paid"?0:c.status==="failed"?1:c.status==="expired"?3:2,status_label:String(c.status||"pending").toUpperCase(),utr:c.utr||null})}catch{}},x=setInterval(r,i.pollMs||A.pollMs);return r(),()=>clearInterval(x)},w={_inner:null,close(){var d;(d=this._inner)==null||d.close()}};return fetch(`${m}/v1/checkout/order/${encodeURIComponent(l)}?key_id=${encodeURIComponent(i.key)}`).then(async d=>{var r;let u=await d.json().catch(()=>({}));if(!d.ok)throw new Error(((r=u==null?void 0:u.error)==null?void 0:r.description)||"Unknown or expired order");w._inner=R(Object.assign({},{apiBase:m,assetBase:b,name:i.name||u.merchant_name,logo:i.logo||`${b}/payulink-logo.png`,brandColor:i.brandColor,note:i.note,prefill:i.prefill||{},amount:u.amount/100,description:i.description||i.item||u.merchant_name,createOrder:I,watchOrder:z,onSuccess:()=>{let x=S||{payulink_order_id:(y==null?void 0:y.order_id)||l,payulink_payment_id:null,payulink_signature:null};typeof i.handler=="function"&&i.handler(x),typeof i.onSuccess=="function"&&i.onSuccess(x)},onDismiss:()=>{typeof i.onDismiss=="function"&&i.onDismiss()},onError:n}))}).catch(n),w}static open(s={}){return new t(s).open(s)}};typeof window!="undefined"&&(window.PayuLink=q,window.PayulinkCheckout=q);export{q as default};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
var PayulinkCheckoutNS=(()=>{var
|
|
1
|
+
var PayulinkCheckoutNS=(()=>{var E=Object.defineProperty;var ee=Object.getOwnPropertyDescriptor;var le=Object.getOwnPropertyNames;var ae=Object.prototype.hasOwnProperty;var te=(a,o)=>{for(var r in o)E(a,r,{get:o[r],enumerable:!0})},re=(a,o,r,y)=>{if(o&&typeof o=="object"||typeof o=="function")for(let h of le(o))!ae.call(a,h)&&h!==r&&E(a,h,{get:()=>o[h],enumerable:!(y=ee(o,h))||y.enumerable});return a};var ie=a=>re(E({},"__esModule",{value:!0}),a);var de={};te(de,{default:()=>w});var oe=`
|
|
2
2
|
#pl-overlay * { box-sizing: border-box; margin: 0; padding: 0; }
|
|
3
3
|
#pl-overlay { --pl-blue:#3395ff; --pl-blue-dark:#1f86f5; --pl-brand:#0b3068; --pl-ink:#1a2a44; --pl-mut:#6b7c93; --pl-line:#eceff4;
|
|
4
4
|
position: fixed; inset: 0; z-index: 2147483000; font-family: 'Inter', system-ui, -apple-system, BlinkMacSystemFont, sans-serif;
|
|
@@ -237,7 +237,7 @@ var PayulinkCheckoutNS=(()=>{var j=Object.defineProperty;var ee=Object.getOwnPro
|
|
|
237
237
|
#pl-overlay .pl-approw { justify-content: center; }
|
|
238
238
|
#pl-overlay .pl-validrow { margin: 0 auto; }
|
|
239
239
|
}
|
|
240
|
-
`,
|
|
240
|
+
`,U=!1;function O(a=document){if(U&&a.getElementById("pl-checkout-styles"))return;let o=a.createElement("style");o.id="pl-checkout-styles",o.textContent=oe,a.head.appendChild(o),U=!0}var ne=a=>"\u20B9"+Number(a||0).toLocaleString("en-IN",{maximumFractionDigits:2}),pe=a=>`${Math.floor(a/60)}:${a%60<10?"0":""}${a%60}`,f=a=>String(a==null?"":a).replace(/[&<>"]/g,o=>({"&":"&","<":"<",">":">",'"':"""})[o]),m=a=>`<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">${a}</svg>`,b={qr:m('<rect width="5" height="5" x="3" y="3" rx="1"/><rect width="5" height="5" x="16" y="3" rx="1"/><rect width="5" height="5" x="3" y="16" rx="1"/><path d="M21 16h-3a2 2 0 0 0-2 2v3"/><path d="M21 21v.01"/><path d="M12 7v3a2 2 0 0 1-2 2H7"/><path d="M3 12h.01"/><path d="M12 3h.01"/><path d="M12 16v.01"/><path d="M16 12h1"/><path d="M21 12v.01"/><path d="M12 21v-1"/>'),card:m('<rect width="20" height="14" x="2" y="5" rx="2"/><line x1="2" x2="22" y1="10" y2="10"/>'),netbanking:m('<path d="M10 18v-7"/><path d="M11.119 2.205a2 2 0 0 1 1.762 0l7.84 3.846A.5.5 0 0 1 20.5 7h-17a.5.5 0 0 1-.22-.949z"/><path d="M14 18v-7"/><path d="M18 18v-7"/><path d="M3 22h18"/><path d="M6 18v-7"/>'),wallet:m('<path d="M19 7V4a1 1 0 0 0-1-1H5a2 2 0 0 0 0 4h15a1 1 0 0 1 1 1v4h-3a2 2 0 0 0 0 4h3a1 1 0 0 0 1-1v-2a1 1 0 0 0-1-1"/><path d="M3 5v14a2 2 0 0 0 2 2h15a1 1 0 0 0 1-1v-4"/>'),emi:m('<path d="M16 14v2.2l1.6 1"/><path d="M16 2v4"/><path d="M21 7.5V6a2 2 0 0 0-2-2H5a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h3.5"/><path d="M3 10h5"/><path d="M8 2v4"/><circle cx="16" cy="16" r="6"/>'),back:m('<path d="M15 18l-6-6 6-6"/>'),mail:m('<rect x="2" y="4" width="20" height="16" rx="2"/><path d="m22 7-10 5L2 7"/>'),arrow:m('<path d="M5 12h14M13 6l6 6-6 6"/>'),verified:m('<path d="M9 12l2 2 4-4"/><circle cx="12" cy="12" r="10"/>'),lock:m('<rect width="18" height="11" x="3" y="11" rx="2"/><path d="M7 11V7a5 5 0 0 1 10 0v4"/>')},R='<svg width="13" height="13" viewBox="0 0 24 24" fill="currentColor"><path d="M12 1l9 4v6c0 5.5-3.8 10.7-9 12-5.2-1.3-9-6.5-9-12V5l9-4z"/></svg>',se=[{m:"card",t:"Cards",s:"Visa, Mastercard & RuPay",ic:"card"},{m:"netbanking",t:"Netbanking",s:"All Indian banks",ic:"netbanking"},{m:"wallet",t:"Wallet",s:"Paytm, PhonePe & more",ic:"wallet"},{m:"emi",t:"EMI",s:"EMI via cards & more",ic:"emi"}];function A(a){O(),a=Object.assign({name:"Payment",description:"",amount:0,assetBase:"/assets",logo:"/assets/payulink-logo.png",prefill:{},apiBase:""},a);let o=String(a.apiBase||"").replace(/\/$/,""),r=ne(a.amount),y=["gpay","phonepe","paytm","bhim","amazonpay"].reduce((e,t)=>(e[t]=`${a.assetBase}/upi/${t}.png`,e),{}),h=["phonepe","gpay","paytm","bhim","amazonpay"],l={screen:"loader",order:null,customer:null,timer:null,stop:null,done:!1,utr:null,expiryMs:null},p=document.createElement("div");p.id="pl-overlay",a.brandColor&&p.style.setProperty("--pl-brand",a.brandColor),p.innerHTML=`
|
|
241
241
|
<div class="pl-modal" role="dialog" aria-modal="true">
|
|
242
242
|
<div class="pl-splash" id="pl-splash">
|
|
243
243
|
<div class="pl-shield">
|
|
@@ -246,25 +246,25 @@ var PayulinkCheckoutNS=(()=>{var j=Object.defineProperty;var ee=Object.getOwnPro
|
|
|
246
246
|
<path d="M60 3 L113 25 V70 C113 105 90 128 60 137 C30 128 7 105 7 70 V25 Z" fill="url(#pl-shgrad)"/>
|
|
247
247
|
</svg>
|
|
248
248
|
<span class="pl-shield-shine"></span>
|
|
249
|
-
<img class="pl-shield-logo" src="${
|
|
249
|
+
<img class="pl-shield-logo" src="${f(a.assetBase)}/payulink-logo.png" alt="payulink">
|
|
250
250
|
</div>
|
|
251
|
-
<div class="pl-splash-foot">Secured By <span class="pl-pb"><img src="${
|
|
251
|
+
<div class="pl-splash-foot">Secured By <span class="pl-pb"><img src="${f(a.assetBase)}/payulink-logo.png" alt=""><strong>payulink</strong></span></div>
|
|
252
252
|
</div>
|
|
253
253
|
<aside class="pl-left">
|
|
254
254
|
<div class="pl-brandrow">
|
|
255
|
-
<div class="pl-logo"><img src="${
|
|
255
|
+
<div class="pl-logo"><img src="${f(a.logo)}" alt=""></div>
|
|
256
256
|
<div class="pl-bmeta">
|
|
257
|
-
<div class="pl-bname">${
|
|
257
|
+
<div class="pl-bname">${f(a.name)}</div>
|
|
258
258
|
<div class="pl-btrust">${b.verified}<span>Trusted Business</span></div>
|
|
259
259
|
</div>
|
|
260
260
|
</div>
|
|
261
261
|
<div class="pl-summary">
|
|
262
262
|
<div class="pl-sl">Price Summary</div>
|
|
263
263
|
<div class="pl-samt">${r}</div>
|
|
264
|
-
<div class="pl-snote">${
|
|
264
|
+
<div class="pl-snote">${f(a.note||"Paying for "+(a.description||a.name))}</div>
|
|
265
265
|
</div>
|
|
266
266
|
<svg class="pl-illus" viewBox="0 0 230 150" fill="none"><rect x="20" y="70" width="58" height="68" rx="5" fill="#fff" fill-opacity=".92"/><path d="M33 70c0-10 5-16 16-16s16 6 16 16" stroke="#fff" stroke-width="3.5"/><rect x="88" y="55" width="68" height="83" rx="5" fill="#fff"/><path d="M104 55c0-12 6-19 18-19s18 7 18 19" stroke="#fff" stroke-width="3.5"/><rect x="150" y="92" width="52" height="46" rx="4" fill="#fff" fill-opacity=".92"/><circle cx="178" cy="40" r="18" fill="#fff"/><path d="M178 30v20M168 40h20" stroke="currentColor" stroke-width="3.5" opacity=".5"/></svg>
|
|
267
|
-
<div class="pl-secured">${
|
|
267
|
+
<div class="pl-secured">${R}Secured by <span class="pl-pb"><img src="${f(a.assetBase)}/payulink-logo.png" alt=""><strong>payulink</strong></span></div>
|
|
268
268
|
</aside>
|
|
269
269
|
<section class="pl-main">
|
|
270
270
|
<header class="pl-head">
|
|
@@ -276,21 +276,21 @@ var PayulinkCheckoutNS=(()=>{var j=Object.defineProperty;var ee=Object.getOwnPro
|
|
|
276
276
|
<div class="pl-vp"><div class="pl-screen pl-active" id="pl-screen"></div></div>
|
|
277
277
|
<footer class="pl-foot">${b.lock}<span>Encrypted & secure payments</span></footer>
|
|
278
278
|
</section>
|
|
279
|
-
</div>`,document.body.appendChild(
|
|
279
|
+
</div>`,document.body.appendChild(p);let x=document.body.style.overflow;document.body.style.overflow="hidden";let S=p.querySelector(".pl-vp"),I=p.querySelector("#pl-title"),z=p.querySelector("#pl-back");function k(){d(),a.onDismiss&&a.onDismiss()}function d(){if(l.stop)try{l.stop()}catch{}clearInterval(l.timer),p.classList.add("pl-closing"),document.body.style.overflow=x,setTimeout(()=>p.remove(),240)}p.querySelector("#pl-close").onclick=k,p.addEventListener("mousedown",e=>{e.target.id==="pl-overlay"&&k()}),z.onclick=()=>{l.screen==="contact"||l.screen==="success"||i("options")};let u={loader:"Payment Options",contact:"Contact Details",options:"Payment Options",success:"Payment Successful"};function i(e){l.screen=e,I.textContent=u[e]||"Payment",z.classList.toggle("pl-show",e==="options"),clearInterval(l.timer);let t=document.createElement("div");t.className="pl-screen pl-active"+(e==="options"?" pl-screen-options":""),t.innerHTML=c[e]?c[e]():"",S.replaceChildren(t),N(e,t)}let g=h.slice(0,4).map(e=>`<img src="${y[e]}" alt="">`).join(""),_=h.map(e=>`<a class="pl-uapp" data-app="${e}" title="${e}"><img src="${y[e]}" alt="${e}"></a>`).join(""),c={loader:()=>`<div class="pl-loader"><div class="pl-bload"><img src="${f(a.logo)}" alt=""><span class="pl-bring"></span><span class="pl-bripple"></span><span class="pl-bripple pl-bripple2"></span></div><p>Securely loading payment options\u2026</p></div>`,contact:()=>`
|
|
280
280
|
<div class="pl-pad">
|
|
281
281
|
<div class="pl-h1">Contact details</div>
|
|
282
282
|
<div class="pl-sub">Enter your details to continue the payment</div>
|
|
283
283
|
<div class="pl-field"><label>Full Name</label>
|
|
284
|
-
<input class="pl-input" id="pl-name" type="text" placeholder="Enter your name" value="${
|
|
284
|
+
<input class="pl-input" id="pl-name" type="text" placeholder="Enter your name" value="${f(a.prefill.name||"")}"></div>
|
|
285
285
|
<div class="pl-field"><label>Mobile Number</label>
|
|
286
286
|
<div class="pl-phone"><div class="pl-cc">+91</div>
|
|
287
|
-
<input class="pl-input" id="pl-mobile" type="tel" maxlength="10" placeholder="Enter mobile number" value="${
|
|
287
|
+
<input class="pl-input" id="pl-mobile" type="tel" maxlength="10" placeholder="Enter mobile number" value="${f(a.prefill.contact||"")}"></div></div>
|
|
288
288
|
<div class="pl-field"><label>Email Address <span class="pl-opt">(optional)</span></label>
|
|
289
289
|
<div class="pl-inwrap"><span class="pl-inicon">${b.mail}</span>
|
|
290
|
-
<input class="pl-input pl-padleft" id="pl-email" type="email" placeholder="Enter email address" value="${
|
|
290
|
+
<input class="pl-input pl-padleft" id="pl-email" type="email" placeholder="Enter email address" value="${f(a.prefill.email||"")}"></div></div>
|
|
291
291
|
<button class="pl-cta" id="pl-continue">Continue <span class="pl-cta-arr">${b.arrow}</span></button>
|
|
292
292
|
<div class="pl-err" id="pl-cerr"></div>
|
|
293
|
-
<div class="pl-trust">${
|
|
293
|
+
<div class="pl-trust">${R}100% secure payments</div>
|
|
294
294
|
</div>`,options:()=>`
|
|
295
295
|
<div class="pl-options">
|
|
296
296
|
<div class="pl-nav" id="pl-nav">
|
|
@@ -308,25 +308,25 @@ var PayulinkCheckoutNS=(()=>{var j=Object.defineProperty;var ee=Object.getOwnPro
|
|
|
308
308
|
<span class="pl-soon">Coming soon</span>
|
|
309
309
|
</div>`).join("")}
|
|
310
310
|
</div>
|
|
311
|
-
<div class="pl-pane" id="pl-pane">${
|
|
311
|
+
<div class="pl-pane" id="pl-pane">${M()}</div>
|
|
312
312
|
</div>`,success:()=>{let e=["#00c060","#3395ff","#ffb020","#ff5a5f","#7a52d8","#19c3c3"];return`
|
|
313
313
|
<div class="pl-success">
|
|
314
314
|
<div class="pl-burst">
|
|
315
|
-
${Array.from({length:18},(
|
|
315
|
+
${Array.from({length:18},(n,s)=>{let v=s/18*Math.PI*2+(s%2?.22:-.22),q=60+s*13%40,F=Math.round(Math.cos(v)*q),G=Math.round(Math.sin(v)*q),W=e[s%e.length],Z=(s%2?1:-1)*(140+s*14),J=s%3===0?6:8,K=s%4===0?6:12;return`<i class="pl-confetti" style="--tx:${F}px;--ty:${G}px;--c:${W};--r:${Z}deg;width:${J}px;height:${K}px;border-radius:${s%4===0?"50%":"2px"};animation-delay:${(.15+s*.024).toFixed(3)}s"></i>`}).join("")}
|
|
316
316
|
<span class="pl-ripple"></span><span class="pl-ripple pl-ripple2"></span>
|
|
317
317
|
<div class="pl-check"><svg viewBox="0 0 24 24"><path d="M5 13l4 4L19 7"/></svg></div>
|
|
318
318
|
</div>
|
|
319
319
|
<h2>Payment Successful</h2>
|
|
320
|
-
<p>${r} paid${a.name?" to "+
|
|
321
|
-
<div class="pl-pid" id="pl-pid">${
|
|
322
|
-
${l.utr?`<div class="pl-pid pl-utr">UTR ${
|
|
323
|
-
</div>`}};function
|
|
320
|
+
<p>${r} paid${a.name?" to "+f(a.name):""}</p>
|
|
321
|
+
<div class="pl-pid" id="pl-pid">${f(l.order&&l.order.merchant_order_no||"")}</div>
|
|
322
|
+
${l.utr?`<div class="pl-pid pl-utr">UTR ${f(l.utr)}</div>`:""}
|
|
323
|
+
</div>`}};function M(){return`
|
|
324
324
|
<div class="pl-paneh">UPI QR</div>
|
|
325
325
|
<div class="pl-qrcard">
|
|
326
326
|
<div class="pl-qrbox" id="pl-qr"><div class="pl-qrloading"></div></div>
|
|
327
327
|
<div class="pl-qrside">
|
|
328
328
|
<div class="pl-scan">Scan the QR using any UPI App</div>
|
|
329
|
-
<div class="pl-approw" id="pl-applist">${
|
|
329
|
+
<div class="pl-approw" id="pl-applist">${_}</div>
|
|
330
330
|
<div class="pl-validrow"><span class="pl-dot"></span><span id="pl-timer">Valid 5:00</span></div>
|
|
331
331
|
</div>
|
|
332
332
|
</div>
|
|
@@ -335,5 +335,5 @@ var PayulinkCheckoutNS=(()=>{var j=Object.defineProperty;var ee=Object.getOwnPro
|
|
|
335
335
|
<input class="pl-vpa" id="pl-vpa" placeholder="example@okhdfcbank" autocomplete="off" spellcheck="false">
|
|
336
336
|
<button class="pl-verify" id="pl-verify">Verify and Pay</button>
|
|
337
337
|
</div>
|
|
338
|
-
<div id="pl-status" class="pl-pendrow"><span class="pl-mini-spin"></span> Waiting for payment\u2026</div>`}function N(e,t){if(e==="contact")t.querySelector("#pl-continue").onclick=()=>{let
|
|
338
|
+
<div id="pl-status" class="pl-pendrow"><span class="pl-mini-spin"></span> Waiting for payment\u2026</div>`}function N(e,t){if(e==="contact")t.querySelector("#pl-continue").onclick=()=>{let n=t.querySelector("#pl-name").value.trim(),s=t.querySelector("#pl-mobile").value.replace(/\D/g,""),v=t.querySelector("#pl-email").value.trim(),q=t.querySelector("#pl-cerr");if(n.length<2)return q.textContent="Please enter your name";if(s.length!==10)return q.textContent="Enter a valid 10-digit mobile number";l.customer={name:n,mobile:s,email:v},i("options")};else if(e==="options"){t.querySelectorAll(".pl-navitem").forEach(s=>s.onclick=()=>{s.dataset.m!=="upi"&&C("Coming soon \u2014 please pay via UPI / QR for now")});let n=t.querySelector("#pl-verify");n&&(n.onclick=()=>{let s=(t.querySelector("#pl-vpa").value||"").trim();if(!/^[\w.\-]{2,}@[a-zA-Z]{2,}$/.test(s))return t.querySelector("#pl-vpa").focus(),C("Enter a valid UPI ID, e.g. name@okhdfcbank");let v=l.order&&(l.order.upi_intent_url||l.order.payment_link);v&&/Android|iPhone|iPad|Mobile/i.test(navigator.userAgent)?location.href=v:C("Scan the QR with your phone\u2019s UPI app to complete the payment.")}),B(),P(!0)}}let $=!1;async function P(e){if(e||i("options"),l.order){L();return}if(!$){$=!0;try{l.customer||(l.customer={name:a.prefill.name||"Customer",mobile:(a.prefill.contact||"").replace(/\D/g,""),email:a.prefill.email||""}),l.order=await a.createOrder(l.customer),L(),V()}catch(t){let n=p.querySelector("#pl-qr");if(n){n.innerHTML=`<div class="pl-qrerr"><span>${f(t.message||"Could not start payment")}</span><button class="pl-retry" id="pl-retry">Try again</button></div>`;let s=n.querySelector("#pl-retry");s&&(s.onclick=()=>{$=!1,n.innerHTML='<div class="pl-qrloading"></div>',P(!0)})}}finally{$=!1}}}function L(){let e=l.order;if(!e)return;Y(e);let t=p.querySelector("#pl-qr");t&&(e.qr_data_url?t.innerHTML=`<img src="${e.qr_data_url}" alt="UPI QR">`:t.innerHTML=`<div class="pl-qrerr"><span>${f(e.qr_unavailable_reason||"QR unavailable \u2014 use a UPI app below")}</span></div>`);let n=e.upi_intent_url||e.payment_link||"#",s=p.querySelector("#pl-applist");s&&s.querySelectorAll(".pl-uapp").forEach(v=>{v.setAttribute("href",n),v.setAttribute("target","_blank"),v.setAttribute("rel","noopener")}),B()}function Y(e){e&&e.expires_at&&e.server_now?l.expiryMs=Date.now()+Math.max(0,e.expires_at-e.server_now):l.expiryMs||(l.expiryMs=Date.now()+5*60*1e3)}function T(){if(l.done)return;let e=p.querySelector("#pl-qr");e&&(e.innerHTML='<div class="pl-qrerr"><span>QR code expired</span><button class="pl-retry" id="pl-regen">Generate new QR</button></div>');let t=p.querySelector("#pl-regen");t&&(t.onclick=H);let n=p.querySelector("#pl-timer");n&&(n.textContent="Expired");let s=p.querySelector(".pl-validrow");s&&s.classList.add("pl-expired")}function H(){if(l.stop){try{l.stop()}catch{}l.stop=null}l.order=null,l.expiryMs=null,$=!1;let e=p.querySelector(".pl-validrow");e&&e.classList.remove("pl-expired");let t=p.querySelector("#pl-qr");t&&(t.innerHTML='<div class="pl-qrloading"></div>'),P(!0)}function V(){!l.order||l.stop||(l.stop=a.watchOrder(l.order.merchant_order_no,e=>{!e||typeof e.status!="number"||(e.status===0?(l.utr=e.utr||l.utr,Q()):e.status===3?(clearInterval(l.timer),l.expiryMs=Date.now(),T(),j("failed","QR expired \u2014 generate a new one")):[1,4].includes(e.status)?j("failed","Payment "+(e.status_label||"failed").toLowerCase()):e.status===6&&j("pending","Processing payment\u2026"))}))}function j(e,t){let n=p.querySelector("#pl-status");n&&(n.className=e==="failed"?"pl-pendrow pl-fail":"pl-pendrow",n.innerHTML=(e==="pending"?'<span class="pl-mini-spin"></span> ':"")+f(t))}function Q(){l.done||(l.done=!0,clearInterval(l.timer),i("success"),a.onSuccess&&a.onSuccess({merchant_order_no:l.order.merchant_order_no,utr:l.utr,amount:a.amount}),l.utr||X())}async function X(){for(let e=0;e<10&&!l.utr;e++){await new Promise(t=>setTimeout(t,4e3));try{let t=await fetch(`${o}/api/order/${l.order.merchant_order_no}`).then(n=>n.json());if(t.utr){l.utr=t.utr;let n=p.querySelector("#pl-pid");n&&l.screen==="success"&&n.insertAdjacentHTML("afterend",`<div class="pl-pid pl-utr">UTR ${f(t.utr)}</div>`);break}}catch{}}}function B(){clearInterval(l.timer);let e=()=>{let t=p.querySelector("#pl-timer");if(!t)return;if(!l.expiryMs){t.textContent="Valid 5:00";return}let n=Math.max(0,Math.round((l.expiryMs-Date.now())/1e3));t.textContent=n>0?"Valid "+pe(n):"Expired",n<=0&&(clearInterval(l.timer),T())};e(),l.timer=setInterval(e,1e3)}function C(e){let t=document.getElementById("pl-toast");t||(t=document.createElement("div"),t.id="pl-toast",document.body.appendChild(t)),t.textContent=e,t.classList.add("pl-show"),clearTimeout(t._t),t._t=setTimeout(()=>t.classList.remove("pl-show"),2600)}return i("loader"),setTimeout(()=>{let e=a.prefill||{};e.name&&(e.contact||"").replace(/\D/g,"").length===10?(l.customer={name:e.name,mobile:e.contact.replace(/\D/g,""),email:e.email||""},i("options")):i("contact");let t=p.querySelector("#pl-splash");t&&(t.classList.add("pl-splash-hide"),setTimeout(()=>t.remove(),450))},1600),{close:d}}var D={apiBase:"https://payulink.io/api",assetBase:"https://assetcdn.payulink.io/checkout/v1/assets",name:null,logo:null,brandColor:null,pollMs:2500},w=class a{constructor(o={}){if(typeof window=="undefined"||typeof document=="undefined")throw new Error("PayuLink checkout runs in the browser only. On React Native use @thepayulink/checkout-react-native; on a server use @thepayulink/server.");let r=o.key||o.keyId||o.key_id;if(!r)throw new Error("PayuLink: `key` (your publishable pl_live_\u2026 / pl_test_\u2026 key) is required");if(/^pl_(live|test)_/.test(r)||console.warn("PayuLink: `key` should look like pl_live_\u2026 or pl_test_\u2026"),o.keySecret||o.key_secret)throw new Error("PayuLink: never pass a key_secret to the browser SDK. It belongs on your server only.");this.options=Object.assign({},D,o,{key:r})}open(o={}){let r=Object.assign({},this.options,o),y=String(r.apiBase||"").replace(/\/$/,""),h=String(r.assetBase||`${y}/assets`).replace(/\/$/,""),l=r.order_id||r.orderId;if(!l)throw new Error("PayuLink: `order_id` is required. Create it on your server with POST /v1/orders.");let p=d=>{typeof r.onError=="function"?r.onError(d):console.error("PayuLink:",d.message||d)},x=null,S=null,I=async d=>{var g,_,c;let u=await fetch(`${y}/v1/checkout/session`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({key_id:r.key,order_id:l,customer:d?{name:d.name,contact:d.mobile||d.contact,email:d.email}:void 0})}),i=await u.json().catch(()=>({}));if(!u.ok){let M=new Error(((g=i==null?void 0:i.error)==null?void 0:g.description)||`Could not start payment (HTTP ${u.status})`);throw M.code=(_=i==null?void 0:i.error)==null?void 0:_.code,M.retriable=((c=i==null?void 0:i.error)==null?void 0:c.code)==="GATEWAY_BUSY",M}return x=i,{merchant_order_no:i.order_id,amount:i.amount/100,upi_intent_url:i.upi_intent_url,payment_link:i.payment_link,qr_data_url:i.qr_data_url||null,qr_unavailable_reason:i.qr_unavailable_reason||null,qr_retriable:i.qr_retriable===!0,expires_at:i.expires_at?i.expires_at*1e3:null,server_now:Date.now()}},z=(d,u)=>{let i=async()=>{if(x!=null&&x.session_token)try{let c=await(await fetch(`${y}/v1/checkout/session/${encodeURIComponent(x.session_token)}`)).json().catch(()=>({}));c.status==="paid"&&c.payulink_signature&&(S={payulink_order_id:c.payulink_order_id,payulink_payment_id:c.payulink_payment_id,payulink_signature:c.payulink_signature,utr:c.utr||null,amount:c.amount}),u({status:c.status==="paid"?0:c.status==="failed"?1:c.status==="expired"?3:2,status_label:String(c.status||"pending").toUpperCase(),utr:c.utr||null})}catch{}},g=setInterval(i,r.pollMs||D.pollMs);return i(),()=>clearInterval(g)},k={_inner:null,close(){var d;(d=this._inner)==null||d.close()}};return fetch(`${y}/v1/checkout/order/${encodeURIComponent(l)}?key_id=${encodeURIComponent(r.key)}`).then(async d=>{var i;let u=await d.json().catch(()=>({}));if(!d.ok)throw new Error(((i=u==null?void 0:u.error)==null?void 0:i.description)||"Unknown or expired order");k._inner=A(Object.assign({},{apiBase:y,assetBase:h,name:r.name||u.merchant_name,logo:r.logo||`${h}/payulink-logo.png`,brandColor:r.brandColor,note:r.note,prefill:r.prefill||{},amount:u.amount/100,description:r.description||r.item||u.merchant_name,createOrder:I,watchOrder:z,onSuccess:()=>{let g=S||{payulink_order_id:(x==null?void 0:x.order_id)||l,payulink_payment_id:null,payulink_signature:null};typeof r.handler=="function"&&r.handler(g),typeof r.onSuccess=="function"&&r.onSuccess(g)},onDismiss:()=>{typeof r.onDismiss=="function"&&r.onDismiss()},onError:p}))}).catch(p),k}static open(o={}){return new a(o).open(o)}};typeof window!="undefined"&&(window.PayuLink=w,window.PayulinkCheckout=w);return ie(de);})();
|
|
339
339
|
window.PayulinkCheckout=PayulinkCheckoutNS.default||PayulinkCheckoutNS;
|
package/package.json
CHANGED
package/src/index.js
CHANGED
|
@@ -86,7 +86,12 @@ export default class PayuLink {
|
|
|
86
86
|
}),
|
|
87
87
|
});
|
|
88
88
|
const s = await res.json().catch(() => ({}));
|
|
89
|
-
if (!res.ok)
|
|
89
|
+
if (!res.ok) {
|
|
90
|
+
const err = new Error(s?.error?.description || `Could not start payment (HTTP ${res.status})`);
|
|
91
|
+
err.code = s?.error?.code; // e.g. GATEWAY_BUSY — retriable, not a bug
|
|
92
|
+
err.retriable = s?.error?.code === 'GATEWAY_BUSY';
|
|
93
|
+
throw err;
|
|
94
|
+
}
|
|
90
95
|
session = s;
|
|
91
96
|
|
|
92
97
|
return {
|
|
@@ -101,6 +106,11 @@ export default class PayuLink {
|
|
|
101
106
|
// intent: the static fallback carries an identical note on every order, which
|
|
102
107
|
// silently defeats auto-detection.
|
|
103
108
|
qr_data_url: s.qr_data_url || null,
|
|
109
|
+
// When the provider didn't return a QR, pass the REASON through so the modal
|
|
110
|
+
// can say why and that it's retriable — rather than a bare "QR unavailable"
|
|
111
|
+
// that covered two unrelated causes (provider timeout vs no liquidity).
|
|
112
|
+
qr_unavailable_reason: s.qr_unavailable_reason || null,
|
|
113
|
+
qr_retriable: s.qr_retriable === true,
|
|
104
114
|
// UNITS: modal.js does `Date.now() + (expires_at - server_now)`, and
|
|
105
115
|
// Date.now() is MILLISECONDS — so the delta must be ms too, not just
|
|
106
116
|
// "the same unit as each other". /v1 returns expires_at in epoch
|
package/src/modal.js
CHANGED
|
@@ -263,7 +263,11 @@ export function openModal(o) {
|
|
|
263
263
|
const q = root.querySelector('#pl-qr');
|
|
264
264
|
if (q) {
|
|
265
265
|
if (ord.qr_data_url) q.innerHTML = `<img src="${ord.qr_data_url}" alt="UPI QR">`;
|
|
266
|
-
|
|
266
|
+
// Say WHY there's no QR. "QR unavailable" covered two unrelated causes
|
|
267
|
+
// (provider timeout vs no liquidity) and told the customer nothing actionable.
|
|
268
|
+
// The order is still payable via the UPI-app button below.
|
|
269
|
+
else q.innerHTML = `<div class="pl-qrerr"><span>${esc(ord.qr_unavailable_reason
|
|
270
|
+
|| 'QR unavailable — use a UPI app below')}</span></div>`;
|
|
267
271
|
}
|
|
268
272
|
const intent = ord.upi_intent_url || ord.payment_link || '#';
|
|
269
273
|
const list = root.querySelector('#pl-applist');
|