@reevit/vue 0.4.0 → 0.4.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/bridges/loaders.d.ts +1 -0
- package/dist/index.js +2 -2
- package/dist/index.mjs +256 -255
- package/package.json +2 -2
|
@@ -102,6 +102,7 @@ export interface HubtelConfig {
|
|
|
102
102
|
callbackUrl?: string;
|
|
103
103
|
customerPhone?: string;
|
|
104
104
|
customerEmail?: string;
|
|
105
|
+
hubtelSessionToken?: string;
|
|
105
106
|
basicAuth?: string;
|
|
106
107
|
onSuccess: (response: Record<string, unknown>) => void;
|
|
107
108
|
onClose: () => void;
|
package/dist/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("vue"),v=require("@reevit/core");function Q(n){const o=n.toLowerCase();return o.includes("paystack")?"paystack":o.includes("hubtel")?"hubtel":o.includes("flutterwave")?"flutterwave":o.includes("stripe")?"stripe":o.includes("monnify")?"monnify":o.includes("mpesa")||o.includes("m-pesa")?"mpesa":"paystack"}function X(n,o){return{id:n.id,clientSecret:n.client_secret,pspPublicKey:n.psp_public_key,pspCredentials:n.psp_credentials,amount:n.amount,currency:n.currency,status:n.status,recommendedPsp:Q(n.provider),availableMethods:o.paymentMethods||["card","mobile_money"],reference:n.reference||o.reference,connectionId:n.connection_id,provider:n.provider,feeAmount:n.fee_amount,feeCurrency:n.fee_currency,netAmount:n.net_amount,metadata:o.metadata}}function L(n){const{config:o,onSuccess:t,onError:l,onClose:r,onStateChange:m,apiBaseUrl:d}=n,i=e.ref(v.createInitialState());if(o.initialPaymentIntent){const c=o.initialPaymentIntent;i.value={...i.value,status:"ready",paymentIntent:c,selectedMethod:c.availableMethods?.length===1?c.availableMethods[0]:null}}const p=new v.ReevitAPIClient({publicKey:o.publicKey,baseUrl:d}),u=c=>{i.value=v.reevitReducer(i.value,c)};e.watch(()=>i.value.status,c=>{m?.(c)});const a=async c=>{u({type:"INIT_START"});try{const s=o.reference||v.generateReference(),y=v.detectCountryFromCurrency(o.currency),f=c||o.paymentMethods?.[0]||"card",{data:k,error:x}=await p.createPaymentIntent({...o,reference:s},f,y);if(x){u({type:"INIT_ERROR",payload:x}),l?.(x);return}if(!k){const $={code:"INIT_FAILED",message:"No data received from API",recoverable:!0};u({type:"INIT_ERROR",payload:$}),l?.($);return}const J=X(k,{...o,reference:s});u({type:"INIT_SUCCESS",payload:J})}catch(s){const y={code:"INIT_FAILED",message:s instanceof Error?s.message:"Failed to initialize checkout",recoverable:!0,originalError:s};u({type:"INIT_ERROR",payload:y}),l?.(y)}},h=c=>{u({type:"SELECT_METHOD",payload:c})},E=async c=>{if(!(!i.value.paymentIntent||!i.value.selectedMethod)){u({type:"PROCESS_START"});try{let s;if(i.value.paymentIntent.clientSecret){const{data:f,error:k}=await p.confirmPaymentIntent(i.value.paymentIntent.id,i.value.paymentIntent.clientSecret);if(k){u({type:"PROCESS_ERROR",payload:k}),l?.(k);return}s=f}else{const{data:f,error:k}=await p.confirmPayment(i.value.paymentIntent.id);if(k){u({type:"PROCESS_ERROR",payload:k}),l?.(k);return}s=f}const y={paymentId:i.value.paymentIntent.id,reference:c.reference||i.value.paymentIntent.reference||i.value.paymentIntent.metadata?.reference||"",amount:i.value.paymentIntent.amount,currency:i.value.paymentIntent.currency,paymentMethod:i.value.selectedMethod,psp:i.value.paymentIntent.recommendedPsp,pspReference:c.pspReference||s?.provider_ref_id||"",status:"success",metadata:c};u({type:"PROCESS_SUCCESS",payload:y}),t?.(y)}catch(s){const y={code:"PAYMENT_FAILED",message:s instanceof Error?s.message:"Payment failed",recoverable:!0,originalError:s};u({type:"PROCESS_ERROR",payload:y}),l?.(y)}}},P=async c=>{await E(c)},R=c=>{u({type:"PROCESS_ERROR",payload:c}),l?.(c)},w=()=>{u({type:"RESET"})},I=async()=>{if(i.value.paymentIntent&&i.value.status!=="success")try{await p.cancelPaymentIntent(i.value.paymentIntent.id)}catch{}u({type:"CLOSE"}),r?.()},C=e.computed(()=>i.value.status),V=e.computed(()=>i.value.paymentIntent),S=e.computed(()=>i.value.selectedMethod),B=e.computed(()=>i.value.error),b=e.computed(()=>i.value.result),N=e.computed(()=>i.value.status==="loading"||i.value.status==="processing"),_=e.computed(()=>i.value.status==="ready"||i.value.status==="method_selected"||i.value.status==="processing"),g=e.computed(()=>i.value.status==="success"),T=e.computed(()=>i.value.error?.recoverable??!1);return{status:e.readonly(C),paymentIntent:e.readonly(V),selectedMethod:e.readonly(S),error:e.readonly(B),result:e.readonly(b),initialize:a,selectMethod:h,processPayment:E,handlePspSuccess:P,handlePspError:R,reset:w,close:I,isLoading:e.readonly(N),isReady:e.readonly(_),isComplete:e.readonly(g),canRetry:e.readonly(T)}}const Z={class:"reevit-method-selector"},ee={class:"reevit-amount-display"},te={class:"reevit-methods-grid"},ne=["onClick"],oe={class:"reevit-method-icon"},re={class:"reevit-method-info"},ae={class:"reevit-method-name"},se={class:"reevit-method-description"},ie={class:"reevit-method-radio"},le={key:0,class:"reevit-radio-inner"},D=e.defineComponent({__name:"PaymentMethodSelector",props:{methods:{},selected:{},amount:{},currency:{},provider:{}},emits:["select"],setup(n,{emit:o}){const t=n,l=o,r={hubtel:"Hubtel",paystack:"Paystack",flutterwave:"Flutterwave",monnify:"Monnify",mpesa:"M-Pesa",stripe:"Stripe"},m=p=>t.provider?.toLowerCase().includes("hubtel")&&p==="mobile_money"?`Pay with ${r[t.provider.toLowerCase()]||"Hubtel"}`:{card:"Card",mobile_money:"Mobile Money",bank_transfer:"Bank Transfer"}[p],d=p=>t.provider?.toLowerCase().includes("hubtel")?"Card, Mobile Money, and Bank Transfer":{card:"Visa, Mastercard, Maestro",mobile_money:"MTN, Vodafone, AirtelTigo",bank_transfer:"Transfer directly from your bank"}[p],i=e.computed(()=>[{id:"card",name:m("card"),description:d("card"),icon:"💳"},{id:"mobile_money",name:m("mobile_money"),description:d("mobile_money"),icon:"📱"},{id:"bank_transfer",name:m("bank_transfer"),description:d("bank_transfer"),icon:"🏦"}].filter(p=>t.methods.includes(p.id)));return(p,u)=>(e.openBlock(),e.createElementBlock("div",Z,[u[0]||(u[0]=e.createElementVNode("h3",{class:"reevit-section-title"},"Select Payment Method",-1)),e.createElementVNode("p",ee," Pay "+e.toDisplayString(e.unref(v.formatAmount)(n.amount,n.currency)),1),e.createElementVNode("div",te,[(e.openBlock(!0),e.createElementBlock(e.Fragment,null,e.renderList(i.value,a=>(e.openBlock(),e.createElementBlock("button",{key:a.id,type:"button",class:e.normalizeClass(e.unref(v.cn)("reevit-method-card",n.selected===a.id&&"reevit-method-card--selected")),onClick:h=>l("select",a.id)},[e.createElementVNode("span",oe,e.toDisplayString(a.icon),1),e.createElementVNode("div",re,[e.createElementVNode("span",ae,e.toDisplayString(a.name),1),e.createElementVNode("span",se,e.toDisplayString(a.description),1)]),e.createElementVNode("div",ie,[n.selected===a.id?(e.openBlock(),e.createElementBlock("div",le)):e.createCommentVNode("",!0)])],10,ne))),128))])]))}}),ce={class:"reevit-form-group"},de=["disabled"],ue={class:"reevit-network-selector"},me={class:"reevit-networks-grid"},pe=["onClick","disabled"],ye={key:0,class:"reevit-error-message"},ve=["disabled"],he={key:0,class:"reevit-spinner"},fe={key:1},U=e.defineComponent({__name:"MobileMoneyForm",props:{initialPhone:{},loading:{type:Boolean}},emits:["submit"],setup(n,{emit:o}){const t=n,l=o,r=e.ref(t.initialPhone||""),m=e.ref(null),d=e.ref(null);e.watch(r,u=>{const a=v.detectNetwork(u);a&&(m.value=a),d.value&&(d.value=null)});const i=()=>{if(!v.validatePhone(r.value)){d.value="Please enter a valid phone number";return}if(!m.value){d.value="Please select your mobile network";return}l("submit",{phone:r.value,network:m.value})},p=[{id:"mtn",name:"MTN",color:"#FFCC00"},{id:"vodafone",name:"Vodafone",color:"#E60000"},{id:"airteltigo",name:"AirtelTigo",color:"#005596"}];return(u,a)=>(e.openBlock(),e.createElementBlock("form",{class:"reevit-momo-form",onSubmit:e.withModifiers(i,["prevent"])},[e.createElementVNode("div",ce,[a[1]||(a[1]=e.createElementVNode("label",{class:"reevit-label",for:"reevit-phone"},"Phone Number",-1)),e.withDirectives(e.createElementVNode("input",{id:"reevit-phone","onUpdate:modelValue":a[0]||(a[0]=h=>r.value=h),type:"tel",class:e.normalizeClass(["reevit-input",{"reevit-input--error":d.value&&!e.unref(v.validatePhone)(r.value)}]),placeholder:"e.g. 024 123 4567",disabled:n.loading,autocomplete:"tel"},null,10,de),[[e.vModelText,r.value]])]),e.createElementVNode("div",ue,[a[2]||(a[2]=e.createElementVNode("label",{class:"reevit-label"},"Select Network",-1)),e.createElementVNode("div",me,[(e.openBlock(),e.createElementBlock(e.Fragment,null,e.renderList(p,h=>e.createElementVNode("button",{key:h.id,type:"button",class:e.normalizeClass(e.unref(v.cn)("reevit-network-btn",m.value===h.id&&"reevit-network-btn--selected")),onClick:E=>m.value=h.id,disabled:n.loading},[e.createElementVNode("div",{class:"reevit-network-dot",style:e.normalizeStyle({backgroundColor:h.color})},null,4),e.createTextVNode(" "+e.toDisplayString(h.name),1)],10,pe)),64))])]),d.value?(e.openBlock(),e.createElementBlock("p",ye,e.toDisplayString(d.value),1)):e.createCommentVNode("",!0),e.createElementVNode("button",{type:"submit",class:"reevit-submit-btn",disabled:n.loading||!r.value},[n.loading?(e.openBlock(),e.createElementBlock("span",he)):(e.openBlock(),e.createElementBlock("span",fe,"Continue"))],8,ve),a[3]||(a[3]=e.createElementVNode("p",{class:"reevit-secure-text"}," 🔒 Secure mobile money payment via Reevit ",-1))],32))}});class be{constructor(o){this.baseUrl="https://unified-pay.hubtel.com",this.messageHandler=null,this.stylesInjected=!1,o&&(this.baseUrl=o)}redirect({purchaseInfo:o,config:t}){const l=this.createCheckoutUrl(o,t),r=window.open(l);if(!r||r.closed||typeof r.closed>"u")throw new Error("Popup was blocked by the browser. Please allow popups for this site.")}initIframe({purchaseInfo:o,callBacks:t,config:l,iframeStyle:r}){var m,d,i;this.registerEvents(t);const p=document.getElementById("hubtel-checkout-iframe");if(!p)throw new Error('Container element with id "hubtel-checkout-iframe" not found in the DOM.');p.innerHTML="";const u=document.createElement("div");u.textContent="Loading...",p.appendChild(u);const a=document.createElement("iframe");a.setAttribute("id","hubtel-iframe-element"),a.src=this.createCheckoutUrl(o,l),a.style.display="none",a.style.width=(m=r?.width)!==null&&m!==void 0?m:"100%",a.style.height=(d=r?.height)!==null&&d!==void 0?d:"100%",a.style.minHeight=r?.minHeight||"400px",a.style.border=(i=r?.border)!==null&&i!==void 0?i:"none",a.onload=()=>{var h;p.removeChild(u),a.style.display="block",(h=t.onLoad)===null||h===void 0||h.call(t)},p.appendChild(a)}openModal({purchaseInfo:o,callBacks:t,config:l}){this.injectStyles(),this.createIframe(),this.handleBackButton(),this.registerEvents(t),this.renderWebpageInPopup(this.createCheckoutUrl(o,l),t.onClose,t.onLoad)}createCheckoutUrl(o,t){const l=Object.assign(Object.assign({},o),t),r=Object.keys(l).reduce((u,a)=>(l[a]!==null&&l[a]!==void 0&&(u[a]=l[a]),u),{}),m=Object.keys(r).map(u=>`${u}=${encodeURIComponent(r[u])}`).join("&"),d=this.encodeBase64(m),i=encodeURIComponent(d);return`${r?.branding==="disabled"?`${this.baseUrl}/pay/direct`:`${this.baseUrl}/pay`}?p=${i}`}encodeBase64(o){return btoa(unescape(encodeURIComponent(o)))}handleBackButton(){window.addEventListener("popstate",()=>{this.closePopUp()})}createIframe(){const o=document.createElement("div");o.setAttribute("id","backdrop"),o.classList.add("backdrop");const t=document.createElement("span");t.classList.add("checkout-loader"),o.appendChild(t),document.body.appendChild(o)}registerEvents(o){this.messageHandler&&window.removeEventListener("message",this.messageHandler,!1);const t=l=>{var r,m,d,i,p,u;if(l.origin!==this.baseUrl)return;const{data:a}=l;if(a.success===!0)(r=o.onPaymentSuccess)===null||r===void 0||r.call(o,a);else if(a.success===!1)(m=o.onPaymentFailure)===null||m===void 0||m.call(o,a);else if(a.initialized)(d=o.init)===null||d===void 0||d.call(o,a),(i=o.onInit)===null||i===void 0||i.call(o,a);else if(a.feesChanged)(p=o.onFeesChanged)===null||p===void 0||p.call(o,a.fees);else if(a.resize){const h=document.getElementById("hubtel-iframe-element");h&&(h.style.height=a.height+"px"),(u=o?.onResize)===null||u===void 0||u.call(o,a)}};this.messageHandler=t,window.addEventListener("message",t,!1)}destroy(){this.messageHandler&&(window.removeEventListener("message",this.messageHandler,!1),this.messageHandler=null)}renderWebpageInPopup(o,t,l){const r=document.createElement("div");r.classList.add("checkout-modal");const m=document.createElement("div");m.setAttribute("id","checkout-close-icon"),m.innerHTML="×",m.classList.add("close-icon"),m.addEventListener("click",()=>{this.closePopUp(),t?.()}),r.appendChild(m);const d=document.createElement("iframe");d.src=o,history.pushState({modalOpen:!0},""),d.classList.add("iframe"),r.appendChild(d),document.body.appendChild(r),r.style.opacity="0",d.addEventListener("load",()=>{r.style.opacity="1",l?.()})}closePopUp(){const o=document.querySelector(".backdrop"),t=document.querySelector(".checkout-modal");o&&document.body.removeChild(o),t&&document.body.removeChild(t),history.replaceState(null,""),window.removeEventListener("popstate",this.closePopUp)}injectStyles(){if(this.stylesInjected)return;const o=document.createElement("style");o.type="text/css",o.setAttribute("data-hubtel-checkout","true"),o.innerHTML=`
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("vue"),v=require("@reevit/core");function Q(t){const o=t.toLowerCase();return o.includes("paystack")?"paystack":o.includes("hubtel")?"hubtel":o.includes("flutterwave")?"flutterwave":o.includes("stripe")?"stripe":o.includes("monnify")?"monnify":o.includes("mpesa")||o.includes("m-pesa")?"mpesa":"paystack"}function X(t,o){return{id:t.id,clientSecret:t.client_secret,pspPublicKey:t.psp_public_key,pspCredentials:t.psp_credentials,amount:t.amount,currency:t.currency,status:t.status,recommendedPsp:Q(t.provider),availableMethods:o.paymentMethods||["card","mobile_money"],reference:t.reference||o.reference,connectionId:t.connection_id,provider:t.provider,feeAmount:t.fee_amount,feeCurrency:t.fee_currency,netAmount:t.net_amount,metadata:o.metadata}}function L(t){const{config:o,onSuccess:n,onError:l,onClose:r,onStateChange:d,apiBaseUrl:u}=t,i=e.ref(v.createInitialState());if(o.initialPaymentIntent){const c=o.initialPaymentIntent;i.value={...i.value,status:"ready",paymentIntent:c,selectedMethod:c.availableMethods?.length===1?c.availableMethods[0]:null}}const p=new v.ReevitAPIClient({publicKey:o.publicKey,baseUrl:u}),m=c=>{i.value=v.reevitReducer(i.value,c)};e.watch(()=>i.value.status,c=>{d?.(c)});const a=async c=>{m({type:"INIT_START"});try{const s=o.reference||v.generateReference(),y=v.detectCountryFromCurrency(o.currency),f=c||o.paymentMethods?.[0]||"card",{data:k,error:x}=await p.createPaymentIntent({...o,reference:s},f,y);if(x){m({type:"INIT_ERROR",payload:x}),l?.(x);return}if(!k){const $={code:"INIT_FAILED",message:"No data received from API",recoverable:!0};m({type:"INIT_ERROR",payload:$}),l?.($);return}const J=X(k,{...o,reference:s});m({type:"INIT_SUCCESS",payload:J})}catch(s){const y={code:"INIT_FAILED",message:s instanceof Error?s.message:"Failed to initialize checkout",recoverable:!0,originalError:s};m({type:"INIT_ERROR",payload:y}),l?.(y)}},h=c=>{m({type:"SELECT_METHOD",payload:c})},E=async c=>{if(!(!i.value.paymentIntent||!i.value.selectedMethod)){m({type:"PROCESS_START"});try{let s;if(i.value.paymentIntent.clientSecret){const{data:f,error:k}=await p.confirmPaymentIntent(i.value.paymentIntent.id,i.value.paymentIntent.clientSecret);if(k){m({type:"PROCESS_ERROR",payload:k}),l?.(k);return}s=f}else{const{data:f,error:k}=await p.confirmPayment(i.value.paymentIntent.id);if(k){m({type:"PROCESS_ERROR",payload:k}),l?.(k);return}s=f}const y={paymentId:i.value.paymentIntent.id,reference:c.reference||i.value.paymentIntent.reference||i.value.paymentIntent.metadata?.reference||"",amount:i.value.paymentIntent.amount,currency:i.value.paymentIntent.currency,paymentMethod:i.value.selectedMethod,psp:i.value.paymentIntent.recommendedPsp,pspReference:c.pspReference||s?.provider_ref_id||"",status:"success",metadata:c};m({type:"PROCESS_SUCCESS",payload:y}),n?.(y)}catch(s){const y={code:"PAYMENT_FAILED",message:s instanceof Error?s.message:"Payment failed",recoverable:!0,originalError:s};m({type:"PROCESS_ERROR",payload:y}),l?.(y)}}},P=async c=>{await E(c)},R=c=>{m({type:"PROCESS_ERROR",payload:c}),l?.(c)},w=()=>{m({type:"RESET"})},I=async()=>{if(i.value.paymentIntent&&i.value.status!=="success")try{await p.cancelPaymentIntent(i.value.paymentIntent.id)}catch{}m({type:"CLOSE"}),r?.()},C=e.computed(()=>i.value.status),V=e.computed(()=>i.value.paymentIntent),S=e.computed(()=>i.value.selectedMethod),B=e.computed(()=>i.value.error),b=e.computed(()=>i.value.result),N=e.computed(()=>i.value.status==="loading"||i.value.status==="processing"),_=e.computed(()=>i.value.status==="ready"||i.value.status==="method_selected"||i.value.status==="processing"),g=e.computed(()=>i.value.status==="success"),T=e.computed(()=>i.value.error?.recoverable??!1);return{status:e.readonly(C),paymentIntent:e.readonly(V),selectedMethod:e.readonly(S),error:e.readonly(B),result:e.readonly(b),initialize:a,selectMethod:h,processPayment:E,handlePspSuccess:P,handlePspError:R,reset:w,close:I,isLoading:e.readonly(N),isReady:e.readonly(_),isComplete:e.readonly(g),canRetry:e.readonly(T)}}const Z={class:"reevit-method-selector"},ee={class:"reevit-amount-display"},te={class:"reevit-methods-grid"},ne=["onClick"],oe={class:"reevit-method-icon"},re={class:"reevit-method-info"},ae={class:"reevit-method-name"},se={class:"reevit-method-description"},ie={class:"reevit-method-radio"},le={key:0,class:"reevit-radio-inner"},D=e.defineComponent({__name:"PaymentMethodSelector",props:{methods:{},selected:{},amount:{},currency:{},provider:{}},emits:["select"],setup(t,{emit:o}){const n=t,l=o,r={hubtel:"Hubtel",paystack:"Paystack",flutterwave:"Flutterwave",monnify:"Monnify",mpesa:"M-Pesa",stripe:"Stripe"},d=p=>n.provider?.toLowerCase().includes("hubtel")&&p==="mobile_money"?`Pay with ${r[n.provider.toLowerCase()]||"Hubtel"}`:{card:"Card",mobile_money:"Mobile Money",bank_transfer:"Bank Transfer"}[p],u=p=>n.provider?.toLowerCase().includes("hubtel")?"Card, Mobile Money, and Bank Transfer":{card:"Visa, Mastercard, Maestro",mobile_money:"MTN, Vodafone, AirtelTigo",bank_transfer:"Transfer directly from your bank"}[p],i=e.computed(()=>[{id:"card",name:d("card"),description:u("card"),icon:"💳"},{id:"mobile_money",name:d("mobile_money"),description:u("mobile_money"),icon:"📱"},{id:"bank_transfer",name:d("bank_transfer"),description:u("bank_transfer"),icon:"🏦"}].filter(p=>n.methods.includes(p.id)));return(p,m)=>(e.openBlock(),e.createElementBlock("div",Z,[m[0]||(m[0]=e.createElementVNode("h3",{class:"reevit-section-title"},"Select Payment Method",-1)),e.createElementVNode("p",ee," Pay "+e.toDisplayString(e.unref(v.formatAmount)(t.amount,t.currency)),1),e.createElementVNode("div",te,[(e.openBlock(!0),e.createElementBlock(e.Fragment,null,e.renderList(i.value,a=>(e.openBlock(),e.createElementBlock("button",{key:a.id,type:"button",class:e.normalizeClass(e.unref(v.cn)("reevit-method-card",t.selected===a.id&&"reevit-method-card--selected")),onClick:h=>l("select",a.id)},[e.createElementVNode("span",oe,e.toDisplayString(a.icon),1),e.createElementVNode("div",re,[e.createElementVNode("span",ae,e.toDisplayString(a.name),1),e.createElementVNode("span",se,e.toDisplayString(a.description),1)]),e.createElementVNode("div",ie,[t.selected===a.id?(e.openBlock(),e.createElementBlock("div",le)):e.createCommentVNode("",!0)])],10,ne))),128))])]))}}),ce={class:"reevit-form-group"},de=["disabled"],ue={class:"reevit-network-selector"},me={class:"reevit-networks-grid"},pe=["onClick","disabled"],ye={key:0,class:"reevit-error-message"},ve=["disabled"],he={key:0,class:"reevit-spinner"},fe={key:1},U=e.defineComponent({__name:"MobileMoneyForm",props:{initialPhone:{},loading:{type:Boolean}},emits:["submit"],setup(t,{emit:o}){const n=t,l=o,r=e.ref(n.initialPhone||""),d=e.ref(null),u=e.ref(null);e.watch(r,m=>{const a=v.detectNetwork(m);a&&(d.value=a),u.value&&(u.value=null)});const i=()=>{if(!v.validatePhone(r.value)){u.value="Please enter a valid phone number";return}if(!d.value){u.value="Please select your mobile network";return}l("submit",{phone:r.value,network:d.value})},p=[{id:"mtn",name:"MTN",color:"#FFCC00"},{id:"vodafone",name:"Vodafone",color:"#E60000"},{id:"airteltigo",name:"AirtelTigo",color:"#005596"}];return(m,a)=>(e.openBlock(),e.createElementBlock("form",{class:"reevit-momo-form",onSubmit:e.withModifiers(i,["prevent"])},[e.createElementVNode("div",ce,[a[1]||(a[1]=e.createElementVNode("label",{class:"reevit-label",for:"reevit-phone"},"Phone Number",-1)),e.withDirectives(e.createElementVNode("input",{id:"reevit-phone","onUpdate:modelValue":a[0]||(a[0]=h=>r.value=h),type:"tel",class:e.normalizeClass(["reevit-input",{"reevit-input--error":u.value&&!e.unref(v.validatePhone)(r.value)}]),placeholder:"e.g. 024 123 4567",disabled:t.loading,autocomplete:"tel"},null,10,de),[[e.vModelText,r.value]])]),e.createElementVNode("div",ue,[a[2]||(a[2]=e.createElementVNode("label",{class:"reevit-label"},"Select Network",-1)),e.createElementVNode("div",me,[(e.openBlock(),e.createElementBlock(e.Fragment,null,e.renderList(p,h=>e.createElementVNode("button",{key:h.id,type:"button",class:e.normalizeClass(e.unref(v.cn)("reevit-network-btn",d.value===h.id&&"reevit-network-btn--selected")),onClick:E=>d.value=h.id,disabled:t.loading},[e.createElementVNode("div",{class:"reevit-network-dot",style:e.normalizeStyle({backgroundColor:h.color})},null,4),e.createTextVNode(" "+e.toDisplayString(h.name),1)],10,pe)),64))])]),u.value?(e.openBlock(),e.createElementBlock("p",ye,e.toDisplayString(u.value),1)):e.createCommentVNode("",!0),e.createElementVNode("button",{type:"submit",class:"reevit-submit-btn",disabled:t.loading||!r.value},[t.loading?(e.openBlock(),e.createElementBlock("span",he)):(e.openBlock(),e.createElementBlock("span",fe,"Continue"))],8,ve),a[3]||(a[3]=e.createElementVNode("p",{class:"reevit-secure-text"}," 🔒 Secure mobile money payment via Reevit ",-1))],32))}});class be{constructor(o){this.baseUrl="https://unified-pay.hubtel.com",this.messageHandler=null,this.stylesInjected=!1,o&&(this.baseUrl=o)}redirect({purchaseInfo:o,config:n}){const l=this.createCheckoutUrl(o,n),r=window.open(l);if(!r||r.closed||typeof r.closed>"u")throw new Error("Popup was blocked by the browser. Please allow popups for this site.")}initIframe({purchaseInfo:o,callBacks:n,config:l,iframeStyle:r}){var d,u,i;this.registerEvents(n);const p=document.getElementById("hubtel-checkout-iframe");if(!p)throw new Error('Container element with id "hubtel-checkout-iframe" not found in the DOM.');p.innerHTML="";const m=document.createElement("div");m.textContent="Loading...",p.appendChild(m);const a=document.createElement("iframe");a.setAttribute("id","hubtel-iframe-element"),a.src=this.createCheckoutUrl(o,l),a.style.display="none",a.style.width=(d=r?.width)!==null&&d!==void 0?d:"100%",a.style.height=(u=r?.height)!==null&&u!==void 0?u:"100%",a.style.minHeight=r?.minHeight||"400px",a.style.border=(i=r?.border)!==null&&i!==void 0?i:"none",a.onload=()=>{var h;p.removeChild(m),a.style.display="block",(h=n.onLoad)===null||h===void 0||h.call(n)},p.appendChild(a)}openModal({purchaseInfo:o,callBacks:n,config:l}){this.injectStyles(),this.createIframe(),this.handleBackButton(),this.registerEvents(n),this.renderWebpageInPopup(this.createCheckoutUrl(o,l),n.onClose,n.onLoad)}createCheckoutUrl(o,n){const l=Object.assign(Object.assign({},o),n),r=Object.keys(l).reduce((m,a)=>(l[a]!==null&&l[a]!==void 0&&(m[a]=l[a]),m),{}),d=Object.keys(r).map(m=>`${m}=${encodeURIComponent(r[m])}`).join("&"),u=this.encodeBase64(d),i=encodeURIComponent(u);return`${r?.branding==="disabled"?`${this.baseUrl}/pay/direct`:`${this.baseUrl}/pay`}?p=${i}`}encodeBase64(o){return btoa(unescape(encodeURIComponent(o)))}handleBackButton(){window.addEventListener("popstate",()=>{this.closePopUp()})}createIframe(){const o=document.createElement("div");o.setAttribute("id","backdrop"),o.classList.add("backdrop");const n=document.createElement("span");n.classList.add("checkout-loader"),o.appendChild(n),document.body.appendChild(o)}registerEvents(o){this.messageHandler&&window.removeEventListener("message",this.messageHandler,!1);const n=l=>{var r,d,u,i,p,m;if(l.origin!==this.baseUrl)return;const{data:a}=l;if(a.success===!0)(r=o.onPaymentSuccess)===null||r===void 0||r.call(o,a);else if(a.success===!1)(d=o.onPaymentFailure)===null||d===void 0||d.call(o,a);else if(a.initialized)(u=o.init)===null||u===void 0||u.call(o,a),(i=o.onInit)===null||i===void 0||i.call(o,a);else if(a.feesChanged)(p=o.onFeesChanged)===null||p===void 0||p.call(o,a.fees);else if(a.resize){const h=document.getElementById("hubtel-iframe-element");h&&(h.style.height=a.height+"px"),(m=o?.onResize)===null||m===void 0||m.call(o,a)}};this.messageHandler=n,window.addEventListener("message",n,!1)}destroy(){this.messageHandler&&(window.removeEventListener("message",this.messageHandler,!1),this.messageHandler=null)}renderWebpageInPopup(o,n,l){const r=document.createElement("div");r.classList.add("checkout-modal");const d=document.createElement("div");d.setAttribute("id","checkout-close-icon"),d.innerHTML="×",d.classList.add("close-icon"),d.addEventListener("click",()=>{this.closePopUp(),n?.()}),r.appendChild(d);const u=document.createElement("iframe");u.src=o,history.pushState({modalOpen:!0},""),u.classList.add("iframe"),r.appendChild(u),document.body.appendChild(r),r.style.opacity="0",u.addEventListener("load",()=>{r.style.opacity="1",l?.()})}closePopUp(){const o=document.querySelector(".backdrop"),n=document.querySelector(".checkout-modal");o&&document.body.removeChild(o),n&&document.body.removeChild(n),history.replaceState(null,""),window.removeEventListener("popstate",this.closePopUp)}injectStyles(){if(this.stylesInjected)return;const o=document.createElement("style");o.type="text/css",o.setAttribute("data-hubtel-checkout","true"),o.innerHTML=`
|
|
2
2
|
.backdrop {
|
|
3
3
|
position: fixed;
|
|
4
4
|
left: 0;
|
|
@@ -98,4 +98,4 @@
|
|
|
98
98
|
|
|
99
99
|
}
|
|
100
100
|
}
|
|
101
|
-
`,document.head.appendChild(o),this.stylesInjected=!0}}const O=new Map;function M(n,o){const t=O.get(o);if(t)return t;const l=new Promise((r,m)=>{if(document.getElementById(o)){r();return}const d=document.createElement("script");d.id=o,d.src=n,d.async=!0,d.onload=()=>r(),d.onerror=()=>m(new Error(`Failed to load ${o} script`)),document.head.appendChild(d)});return O.set(o,l),l}function F(){return M("https://js.paystack.co/v1/inline.js","paystack-script")}function ke(){return Promise.resolve()}function j(){return M("https://checkout.flutterwave.com/v3.js","flutterwave-script")}function A(){return M("https://js.stripe.com/v3/","stripe-script")}function z(){return M("https://sdk.monnify.com/plugin/monnify.js","monnify-script")}async function K(n){if(await F(),!window.PaystackPop)throw new Error("Paystack script not loaded");window.PaystackPop.setup({key:n.key,email:n.email,amount:n.amount,currency:n.currency,ref:n.ref,metadata:n.metadata,callback:n.onSuccess,onClose:n.onClose}).openIframe()}async function H(n){const o=new be,t={amount:n.amount,purchaseDescription:n.purchaseDescription,customerPhoneNumber:n.customerPhone||"",clientReference:`hubtel_${Date.now()}`},l={branding:"enabled",callbackUrl:n.callbackUrl||(typeof window<"u"?window.location.href:""),merchantAccount:typeof n.clientId=="string"?parseInt(n.clientId,10):n.clientId,basicAuth:n.basicAuth||""};o.openModal({purchaseInfo:t,config:l,callBacks:{onPaymentSuccess:r=>{n.onSuccess(r),o.closePopUp()},onPaymentFailure:()=>{n.onClose()},onClose:()=>{n.onClose()}}})}async function q(n){if(await j(),!window.FlutterwaveCheckout)throw new Error("Flutterwave script not loaded");window.FlutterwaveCheckout({public_key:n.public_key,tx_ref:n.tx_ref,amount:n.amount,currency:n.currency,customer:n.customer,payment_options:n.payment_options,customizations:n.customizations,callback:n.callback,onclose:n.onclose})}async function Y(n){if(await A(),!window.Stripe)throw new Error("Stripe.js not loaded");return window.Stripe(n)}async function Ee(n){const t=await(await Y(n.publishableKey)).confirmPayment({elements:n.elements,clientSecret:n.clientSecret,redirect:"if_required"});t.error?n.onError({message:t.error.message||"Payment failed"}):t.paymentIntent&&n.onSuccess({paymentIntentId:t.paymentIntent.id,status:t.paymentIntent.status})}async function W(n){if(await z(),!window.MonnifySDK)throw new Error("Monnify SDK not loaded");window.MonnifySDK.initialize({amount:n.amount,currency:n.currency,reference:n.reference,customerName:n.customerName,customerEmail:n.customerEmail,customerMobileNumber:n.customerPhone,apiKey:n.apiKey,contractCode:n.contractCode,paymentDescription:n.paymentDescription||"Payment",isTestMode:n.isTestMode??!1,metadata:n.metadata,onComplete:o=>{o.status==="SUCCESS"?n.onSuccess({transactionReference:o.transactionReference,paymentReference:o.paymentReference,...o}):n.onError?.({message:o.message||"Payment failed"})},onClose:n.onClose})}async function G(n,o){n.onInitiated();try{const t=await fetch(o,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({phone_number:n.phoneNumber,amount:n.amount,reference:n.reference,description:n.description})});if(!t.ok){const m=(await t.json().catch(()=>({}))).message||"Failed to initiate M-Pesa payment";return n.onError({message:m}),{status:"failed",message:m}}const l=await t.json();return{status:"initiated",message:"Please check your phone and enter your M-Pesa PIN to complete the payment.",transactionId:l.checkout_request_id||l.transaction_id}}catch(t){const l=t instanceof Error?t.message:"Network error";return n.onError({message:l}),{status:"failed",message:l}}}const we=["disabled"],Pe={key:0,class:"reevit-spinner"},Ce={class:"reevit-modal-body"},Se={key:0,class:"reevit-loading-state"},_e={key:1,class:"reevit-error-state"},ge={key:2,class:"reevit-success-state"},Ie={key:1,class:"reevit-method-form-container"},Ne={key:2,class:"reevit-card-info"},Me=["disabled"],Re={key:0,class:"reevit-spinner"},Ve={key:1},Be=e.defineComponent({__name:"ReevitCheckout",props:{publicKey:{},amount:{},currency:{},email:{},phone:{},reference:{},metadata:{},paymentMethods:{},theme:{},isOpen:{type:Boolean},apiBaseUrl:{},initialPaymentIntent:{}},emits:["success","error","close"],setup(n,{emit:o}){const t=n,l=o,{status:r,paymentIntent:m,selectedMethod:d,error:i,isLoading:p,isReady:u,initialize:a,selectMethod:h,handlePspSuccess:E,handlePspError:P,close:R}=L({config:{publicKey:t.publicKey,amount:t.amount,currency:t.currency,email:t.email,phone:t.phone,reference:t.reference,metadata:t.metadata,paymentMethods:t.paymentMethods,initialPaymentIntent:t.initialPaymentIntent},apiBaseUrl:t.apiBaseUrl,onSuccess:c=>l("success",c),onError:c=>l("error",c),onClose:()=>l("close")}),w=e.ref(t.isOpen??!1);e.watch(()=>t.isOpen,c=>{c!==void 0&&(w.value=c)});const I=()=>{w.value=!0,!m.value&&r.value==="idle"&&a()};e.watch([w,m,d],([c,s,y])=>{c&&s&&y&&y==="card"&&S(null)});const C=()=>{w.value=!1,R()},V=c=>{h(c)},S=async c=>{const s=m.value;if(!s)return;const y=s.recommendedPsp;try{if(y==="paystack")await K({key:t.publicKey,email:t.email||"",amount:t.amount,currency:t.currency,ref:s.id,onSuccess:f=>E(f),onClose:()=>{}});else if(y==="hubtel")await H({clientId:s.pspCredentials?.merchantAccount||t.publicKey,purchaseDescription:`Payment for ${t.amount} ${t.currency}`,amount:t.amount,customerPhone:c?.phone||t.phone,customerEmail:t.email,basicAuth:s.pspCredentials?.basicAuth,onSuccess:f=>E(f),onClose:()=>{}});else if(y==="flutterwave")await q({public_key:t.publicKey,tx_ref:s.id,amount:t.amount,currency:t.currency,customer:{email:t.email||"",phone_number:c?.phone||t.phone},callback:f=>E(f),onclose:()=>{}});else if(y==="monnify")await W({apiKey:s.pspPublicKey||t.publicKey,contractCode:t.metadata?.contract_code||t.publicKey,amount:t.amount,currency:t.currency,reference:s.reference||s.id,customerName:t.metadata?.customer_name||t.email||"",customerEmail:t.email||"",customerPhone:c?.phone||t.phone,metadata:t.metadata,onSuccess:f=>E(f),onClose:()=>{}});else if(y==="mpesa"){const f=`${t.apiBaseUrl||"https://api.reevit.io"}/v1/payments/${s.id}/mpesa`;await G({phoneNumber:c?.phone||t.phone||"",amount:t.amount,reference:s.reference||s.id,description:`Payment ${s.reference||""}`,onInitiated:()=>{},onSuccess:k=>E(k),onError:k=>P({code:"MPESA_ERROR",message:k.message})},f)}else P(y==="stripe"?{code:"STRIPE_NOT_IMPLEMENTED",message:"Stripe integration requires custom Elements setup. Please use the React SDK or implement custom Stripe Elements."}:{code:"UNSUPPORTED_PSP",message:`Payment provider "${y}" is not supported in this checkout.`})}catch(f){P({code:"BRIDGE_ERROR",message:f instanceof Error?f.message:"Failed to open payment gateway"})}},B=e.computed(()=>v.createThemeVariables(t.theme||{}));e.watch(w,c=>{c?document.body.style.overflow="hidden":document.body.style.overflow=""}),e.onUnmounted(()=>{document.body.style.overflow=""});const b=e.computed(()=>r.value),N=e.computed(()=>i.value),_=e.computed(()=>d.value),g=e.computed(()=>p.value),T=e.computed(()=>u.value);return(c,s)=>(e.openBlock(),e.createElementBlock("div",{class:"reevit-sdk-container",style:e.normalizeStyle(B.value)},[e.renderSlot(c.$slots,"default",{open:I,isLoading:g.value},()=>[e.createElementVNode("button",{type:"button",class:"reevit-pay-button",onClick:I,disabled:g.value},[g.value?(e.openBlock(),e.createElementBlock("span",Pe)):e.renderSlot(c.$slots,"button-text",{key:1},()=>[s[1]||(s[1]=e.createTextVNode("Pay Now",-1))])],8,we)]),(e.openBlock(),e.createBlock(e.Teleport,{to:"body"},[w.value?(e.openBlock(),e.createElementBlock("div",{key:0,class:"reevit-modal-overlay",onClick:e.withModifiers(C,["self"])},[e.createElementVNode("div",{class:e.normalizeClass(["reevit-modal-content",{"reevit-modal--dark":t.theme?.darkMode}])},[e.createElementVNode("button",{class:"reevit-modal-close",onClick:C,"aria-label":"Close"}," × "),s[9]||(s[9]=e.createElementVNode("div",{class:"reevit-modal-header"},[e.createElementVNode("img",{src:"https://i.imgur.com/bzUR5Lm.png",alt:"Reevit",class:"reevit-modal__logo"})],-1)),e.createElementVNode("div",Ce,[b.value==="loading"?(e.openBlock(),e.createElementBlock("div",Se,[...s[2]||(s[2]=[e.createElementVNode("div",{class:"reevit-spinner reevit-spinner--large"},null,-1),e.createElementVNode("p",null,"Initializing payment...",-1)])])):b.value==="failed"&&N.value?(e.openBlock(),e.createElementBlock("div",_e,[s[3]||(s[3]=e.createElementVNode("div",{class:"reevit-error-icon"},"⚠️",-1)),s[4]||(s[4]=e.createElementVNode("h3",null,"Payment Failed",-1)),e.createElementVNode("p",null,e.toDisplayString(N.value.message),1),e.createElementVNode("button",{class:"reevit-retry-btn",onClick:s[0]||(s[0]=y=>e.unref(a)())},"Retry")])):b.value==="success"?(e.openBlock(),e.createElementBlock("div",ge,[s[5]||(s[5]=e.createElementVNode("div",{class:"reevit-success-icon"},"✅",-1)),s[6]||(s[6]=e.createElementVNode("h3",null,"Payment Successful",-1)),s[7]||(s[7]=e.createElementVNode("p",null,"Thank you for your payment.",-1)),e.createElementVNode("button",{class:"reevit-done-btn",onClick:C},"Done")])):T.value?(e.openBlock(),e.createElementBlock(e.Fragment,{key:3},[b.value==="ready"||b.value==="method_selected"||b.value==="processing"?(e.openBlock(),e.createBlock(D,{key:0,methods:t.paymentMethods||["card","mobile_money"],selected:_.value,amount:t.amount,currency:t.currency,provider:c.psp,onSelect:V},null,8,["methods","selected","amount","currency","provider"])):e.createCommentVNode("",!0),(b.value==="method_selected"||b.value==="processing")&&_.value==="mobile_money"?(e.openBlock(),e.createElementBlock("div",Ie,[e.createVNode(U,{"initial-phone":t.phone,loading:b.value==="processing",onSubmit:S},null,8,["initial-phone","loading"])])):e.createCommentVNode("",!0),(b.value==="method_selected"||b.value==="processing")&&_.value==="card"?(e.openBlock(),e.createElementBlock("div",Ne,[s[8]||(s[8]=e.createElementVNode("p",{class:"reevit-info-text"},"You will be redirected to our secure payment partner to complete your card payment.",-1)),e.createElementVNode("button",{class:"reevit-submit-btn",onClick:S,disabled:b.value==="processing"},[b.value==="processing"?(e.openBlock(),e.createElementBlock("span",Re)):(e.openBlock(),e.createElementBlock("span",Ve,"Proceed to Card Payment"))],8,Me)])):e.createCommentVNode("",!0)],64)):e.createCommentVNode("",!0)]),s[10]||(s[10]=e.createElementVNode("div",{class:"reevit-modal-footer"},[e.createElementVNode("div",{class:"reevit-trust-badges"},[e.createElementVNode("span",null,"PCI DSS Compliant"),e.createElementVNode("span",null,"•"),e.createElementVNode("span",null,"SSL Secure")])],-1))],2)])):e.createCommentVNode("",!0)]))],4))}});Object.defineProperty(exports,"ReevitAPIClient",{enumerable:!0,get:()=>v.ReevitAPIClient});Object.defineProperty(exports,"cn",{enumerable:!0,get:()=>v.cn});Object.defineProperty(exports,"createReevitClient",{enumerable:!0,get:()=>v.createReevitClient});Object.defineProperty(exports,"detectCountryFromCurrency",{enumerable:!0,get:()=>v.detectCountryFromCurrency});Object.defineProperty(exports,"detectNetwork",{enumerable:!0,get:()=>v.detectNetwork});Object.defineProperty(exports,"formatAmount",{enumerable:!0,get:()=>v.formatAmount});Object.defineProperty(exports,"formatPhone",{enumerable:!0,get:()=>v.formatPhone});Object.defineProperty(exports,"validatePhone",{enumerable:!0,get:()=>v.validatePhone});exports.MobileMoneyForm=U;exports.PaymentMethodSelector=D;exports.ReevitCheckout=Be;exports.confirmStripePayment=Ee;exports.createStripeInstance=Y;exports.initiateMPesaSTKPush=G;exports.loadFlutterwaveScript=j;exports.loadHubtelScript=ke;exports.loadMonnifyScript=z;exports.loadPaystackScript=F;exports.loadStripeScript=A;exports.openFlutterwaveModal=q;exports.openHubtelPopup=H;exports.openMonnifyModal=W;exports.openPaystackPopup=K;exports.useReevit=L;
|
|
101
|
+
`,document.head.appendChild(o),this.stylesInjected=!0}}const O=new Map;function M(t,o){const n=O.get(o);if(n)return n;const l=new Promise((r,d)=>{if(document.getElementById(o)){r();return}const u=document.createElement("script");u.id=o,u.src=t,u.async=!0,u.onload=()=>r(),u.onerror=()=>d(new Error(`Failed to load ${o} script`)),document.head.appendChild(u)});return O.set(o,l),l}function F(){return M("https://js.paystack.co/v1/inline.js","paystack-script")}function ke(){return Promise.resolve()}function j(){return M("https://checkout.flutterwave.com/v3.js","flutterwave-script")}function A(){return M("https://js.stripe.com/v3/","stripe-script")}function z(){return M("https://sdk.monnify.com/plugin/monnify.js","monnify-script")}async function K(t){if(await F(),!window.PaystackPop)throw new Error("Paystack script not loaded");window.PaystackPop.setup({key:t.key,email:t.email,amount:t.amount,currency:t.currency,ref:t.ref,metadata:t.metadata,callback:t.onSuccess,onClose:t.onClose}).openIframe()}async function H(t){const o=new be,n={amount:t.amount,purchaseDescription:t.purchaseDescription,customerPhoneNumber:t.customerPhone||"",clientReference:`hubtel_${Date.now()}`},l=t.hubtelSessionToken||t.basicAuth||"",r={branding:"enabled",callbackUrl:t.callbackUrl||(typeof window<"u"?window.location.href:""),merchantAccount:typeof t.clientId=="string"?parseInt(t.clientId,10):t.clientId,basicAuth:l};o.openModal({purchaseInfo:n,config:r,callBacks:{onPaymentSuccess:d=>{t.onSuccess(d),o.closePopUp()},onPaymentFailure:()=>{t.onClose()},onClose:()=>{t.onClose()}}})}async function q(t){if(await j(),!window.FlutterwaveCheckout)throw new Error("Flutterwave script not loaded");window.FlutterwaveCheckout({public_key:t.public_key,tx_ref:t.tx_ref,amount:t.amount,currency:t.currency,customer:t.customer,payment_options:t.payment_options,customizations:t.customizations,callback:t.callback,onclose:t.onclose})}async function Y(t){if(await A(),!window.Stripe)throw new Error("Stripe.js not loaded");return window.Stripe(t)}async function Ee(t){const n=await(await Y(t.publishableKey)).confirmPayment({elements:t.elements,clientSecret:t.clientSecret,redirect:"if_required"});n.error?t.onError({message:n.error.message||"Payment failed"}):n.paymentIntent&&t.onSuccess({paymentIntentId:n.paymentIntent.id,status:n.paymentIntent.status})}async function W(t){if(await z(),!window.MonnifySDK)throw new Error("Monnify SDK not loaded");window.MonnifySDK.initialize({amount:t.amount,currency:t.currency,reference:t.reference,customerName:t.customerName,customerEmail:t.customerEmail,customerMobileNumber:t.customerPhone,apiKey:t.apiKey,contractCode:t.contractCode,paymentDescription:t.paymentDescription||"Payment",isTestMode:t.isTestMode??!1,metadata:t.metadata,onComplete:o=>{o.status==="SUCCESS"?t.onSuccess({transactionReference:o.transactionReference,paymentReference:o.paymentReference,...o}):t.onError?.({message:o.message||"Payment failed"})},onClose:t.onClose})}async function G(t,o){t.onInitiated();try{const n=await fetch(o,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({phone_number:t.phoneNumber,amount:t.amount,reference:t.reference,description:t.description})});if(!n.ok){const d=(await n.json().catch(()=>({}))).message||"Failed to initiate M-Pesa payment";return t.onError({message:d}),{status:"failed",message:d}}const l=await n.json();return{status:"initiated",message:"Please check your phone and enter your M-Pesa PIN to complete the payment.",transactionId:l.checkout_request_id||l.transaction_id}}catch(n){const l=n instanceof Error?n.message:"Network error";return t.onError({message:l}),{status:"failed",message:l}}}const we=["disabled"],Pe={key:0,class:"reevit-spinner"},Ce={class:"reevit-modal-body"},Se={key:0,class:"reevit-loading-state"},_e={key:1,class:"reevit-error-state"},ge={key:2,class:"reevit-success-state"},Ie={key:1,class:"reevit-method-form-container"},Ne={key:2,class:"reevit-card-info"},Me=["disabled"],Re={key:0,class:"reevit-spinner"},Ve={key:1},Be=e.defineComponent({__name:"ReevitCheckout",props:{publicKey:{},amount:{},currency:{},email:{},phone:{},reference:{},metadata:{},paymentMethods:{},theme:{},isOpen:{type:Boolean},apiBaseUrl:{},initialPaymentIntent:{}},emits:["success","error","close"],setup(t,{emit:o}){const n=t,l=o,{status:r,paymentIntent:d,selectedMethod:u,error:i,isLoading:p,isReady:m,initialize:a,selectMethod:h,handlePspSuccess:E,handlePspError:P,close:R}=L({config:{publicKey:n.publicKey,amount:n.amount,currency:n.currency,email:n.email,phone:n.phone,reference:n.reference,metadata:n.metadata,paymentMethods:n.paymentMethods,initialPaymentIntent:n.initialPaymentIntent},apiBaseUrl:n.apiBaseUrl,onSuccess:c=>l("success",c),onError:c=>l("error",c),onClose:()=>l("close")}),w=e.ref(n.isOpen??!1);e.watch(()=>n.isOpen,c=>{c!==void 0&&(w.value=c)});const I=()=>{w.value=!0,!d.value&&r.value==="idle"&&a()};e.watch([w,d,u],([c,s,y])=>{c&&s&&y&&y==="card"&&S(null)});const C=()=>{w.value=!1,R()},V=c=>{h(c)},S=async c=>{const s=d.value;if(!s)return;const y=s.recommendedPsp;try{if(y==="paystack")await K({key:n.publicKey,email:n.email||"",amount:n.amount,currency:n.currency,ref:s.id,onSuccess:f=>E(f),onClose:()=>{}});else if(y==="hubtel")await H({clientId:s.pspCredentials?.merchantAccount||n.publicKey,purchaseDescription:`Payment for ${n.amount} ${n.currency}`,amount:n.amount,customerPhone:c?.phone||n.phone,customerEmail:n.email,hubtelSessionToken:s.id,onSuccess:f=>E(f),onClose:()=>{}});else if(y==="flutterwave")await q({public_key:n.publicKey,tx_ref:s.id,amount:n.amount,currency:n.currency,customer:{email:n.email||"",phone_number:c?.phone||n.phone},callback:f=>E(f),onclose:()=>{}});else if(y==="monnify")await W({apiKey:s.pspPublicKey||n.publicKey,contractCode:n.metadata?.contract_code||n.publicKey,amount:n.amount,currency:n.currency,reference:s.reference||s.id,customerName:n.metadata?.customer_name||n.email||"",customerEmail:n.email||"",customerPhone:c?.phone||n.phone,metadata:n.metadata,onSuccess:f=>E(f),onClose:()=>{}});else if(y==="mpesa"){const f=`${n.apiBaseUrl||"https://api.reevit.io"}/v1/payments/${s.id}/mpesa`;await G({phoneNumber:c?.phone||n.phone||"",amount:n.amount,reference:s.reference||s.id,description:`Payment ${s.reference||""}`,onInitiated:()=>{},onSuccess:k=>E(k),onError:k=>P({code:"MPESA_ERROR",message:k.message})},f)}else P(y==="stripe"?{code:"STRIPE_NOT_IMPLEMENTED",message:"Stripe integration requires custom Elements setup. Please use the React SDK or implement custom Stripe Elements."}:{code:"UNSUPPORTED_PSP",message:`Payment provider "${y}" is not supported in this checkout.`})}catch(f){P({code:"BRIDGE_ERROR",message:f instanceof Error?f.message:"Failed to open payment gateway"})}},B=e.computed(()=>v.createThemeVariables(n.theme||{}));e.watch(w,c=>{c?document.body.style.overflow="hidden":document.body.style.overflow=""}),e.onUnmounted(()=>{document.body.style.overflow=""});const b=e.computed(()=>r.value),N=e.computed(()=>i.value),_=e.computed(()=>u.value),g=e.computed(()=>p.value),T=e.computed(()=>m.value);return(c,s)=>(e.openBlock(),e.createElementBlock("div",{class:"reevit-sdk-container",style:e.normalizeStyle(B.value)},[e.renderSlot(c.$slots,"default",{open:I,isLoading:g.value},()=>[e.createElementVNode("button",{type:"button",class:"reevit-pay-button",onClick:I,disabled:g.value},[g.value?(e.openBlock(),e.createElementBlock("span",Pe)):e.renderSlot(c.$slots,"button-text",{key:1},()=>[s[1]||(s[1]=e.createTextVNode("Pay Now",-1))])],8,we)]),(e.openBlock(),e.createBlock(e.Teleport,{to:"body"},[w.value?(e.openBlock(),e.createElementBlock("div",{key:0,class:"reevit-modal-overlay",onClick:e.withModifiers(C,["self"])},[e.createElementVNode("div",{class:e.normalizeClass(["reevit-modal-content",{"reevit-modal--dark":n.theme?.darkMode}])},[e.createElementVNode("button",{class:"reevit-modal-close",onClick:C,"aria-label":"Close"}," × "),s[9]||(s[9]=e.createElementVNode("div",{class:"reevit-modal-header"},[e.createElementVNode("img",{src:"https://i.imgur.com/bzUR5Lm.png",alt:"Reevit",class:"reevit-modal__logo"})],-1)),e.createElementVNode("div",Ce,[b.value==="loading"?(e.openBlock(),e.createElementBlock("div",Se,[...s[2]||(s[2]=[e.createElementVNode("div",{class:"reevit-spinner reevit-spinner--large"},null,-1),e.createElementVNode("p",null,"Initializing payment...",-1)])])):b.value==="failed"&&N.value?(e.openBlock(),e.createElementBlock("div",_e,[s[3]||(s[3]=e.createElementVNode("div",{class:"reevit-error-icon"},"⚠️",-1)),s[4]||(s[4]=e.createElementVNode("h3",null,"Payment Failed",-1)),e.createElementVNode("p",null,e.toDisplayString(N.value.message),1),e.createElementVNode("button",{class:"reevit-retry-btn",onClick:s[0]||(s[0]=y=>e.unref(a)())},"Retry")])):b.value==="success"?(e.openBlock(),e.createElementBlock("div",ge,[s[5]||(s[5]=e.createElementVNode("div",{class:"reevit-success-icon"},"✅",-1)),s[6]||(s[6]=e.createElementVNode("h3",null,"Payment Successful",-1)),s[7]||(s[7]=e.createElementVNode("p",null,"Thank you for your payment.",-1)),e.createElementVNode("button",{class:"reevit-done-btn",onClick:C},"Done")])):T.value?(e.openBlock(),e.createElementBlock(e.Fragment,{key:3},[b.value==="ready"||b.value==="method_selected"||b.value==="processing"?(e.openBlock(),e.createBlock(D,{key:0,methods:n.paymentMethods||["card","mobile_money"],selected:_.value,amount:n.amount,currency:n.currency,provider:c.psp,onSelect:V},null,8,["methods","selected","amount","currency","provider"])):e.createCommentVNode("",!0),(b.value==="method_selected"||b.value==="processing")&&_.value==="mobile_money"?(e.openBlock(),e.createElementBlock("div",Ie,[e.createVNode(U,{"initial-phone":n.phone,loading:b.value==="processing",onSubmit:S},null,8,["initial-phone","loading"])])):e.createCommentVNode("",!0),(b.value==="method_selected"||b.value==="processing")&&_.value==="card"?(e.openBlock(),e.createElementBlock("div",Ne,[s[8]||(s[8]=e.createElementVNode("p",{class:"reevit-info-text"},"You will be redirected to our secure payment partner to complete your card payment.",-1)),e.createElementVNode("button",{class:"reevit-submit-btn",onClick:S,disabled:b.value==="processing"},[b.value==="processing"?(e.openBlock(),e.createElementBlock("span",Re)):(e.openBlock(),e.createElementBlock("span",Ve,"Proceed to Card Payment"))],8,Me)])):e.createCommentVNode("",!0)],64)):e.createCommentVNode("",!0)]),s[10]||(s[10]=e.createElementVNode("div",{class:"reevit-modal-footer"},[e.createElementVNode("div",{class:"reevit-trust-badges"},[e.createElementVNode("span",null,"PCI DSS Compliant"),e.createElementVNode("span",null,"•"),e.createElementVNode("span",null,"SSL Secure")])],-1))],2)])):e.createCommentVNode("",!0)]))],4))}});Object.defineProperty(exports,"ReevitAPIClient",{enumerable:!0,get:()=>v.ReevitAPIClient});Object.defineProperty(exports,"cn",{enumerable:!0,get:()=>v.cn});Object.defineProperty(exports,"createReevitClient",{enumerable:!0,get:()=>v.createReevitClient});Object.defineProperty(exports,"detectCountryFromCurrency",{enumerable:!0,get:()=>v.detectCountryFromCurrency});Object.defineProperty(exports,"detectNetwork",{enumerable:!0,get:()=>v.detectNetwork});Object.defineProperty(exports,"formatAmount",{enumerable:!0,get:()=>v.formatAmount});Object.defineProperty(exports,"formatPhone",{enumerable:!0,get:()=>v.formatPhone});Object.defineProperty(exports,"validatePhone",{enumerable:!0,get:()=>v.validatePhone});exports.MobileMoneyForm=U;exports.PaymentMethodSelector=D;exports.ReevitCheckout=Be;exports.confirmStripePayment=Ee;exports.createStripeInstance=Y;exports.initiateMPesaSTKPush=G;exports.loadFlutterwaveScript=j;exports.loadHubtelScript=ke;exports.loadMonnifyScript=z;exports.loadPaystackScript=F;exports.loadStripeScript=A;exports.openFlutterwaveModal=q;exports.openHubtelPopup=H;exports.openMonnifyModal=W;exports.openPaystackPopup=K;exports.useReevit=L;
|
package/dist/index.mjs
CHANGED
|
@@ -1,32 +1,32 @@
|
|
|
1
|
-
import { ref as $, watch as N, computed as w, readonly as
|
|
1
|
+
import { ref as $, watch as N, computed as w, readonly as C, defineComponent as V, createElementBlock as h, openBlock as v, createElementVNode as c, toDisplayString as I, unref as L, Fragment as q, renderList as Q, normalizeClass as D, createCommentVNode as E, withModifiers as X, withDirectives as oe, vModelText as ae, createTextVNode as Z, normalizeStyle as ee, onUnmounted as re, renderSlot as Y, createBlock as W, Teleport as se, createVNode as ie } from "vue";
|
|
2
2
|
import { createInitialState as le, ReevitAPIClient as ce, generateReference as de, detectCountryFromCurrency as ue, reevitReducer as me, formatAmount as pe, cn as te, detectNetwork as ye, validatePhone as G, createThemeVariables as ve } from "@reevit/core";
|
|
3
|
-
import { ReevitAPIClient as vt, cn as ht, createReevitClient as ft, detectCountryFromCurrency as bt, detectNetwork as wt, formatAmount as kt, formatPhone as Pt, validatePhone as
|
|
4
|
-
function he(
|
|
5
|
-
const n =
|
|
3
|
+
import { ReevitAPIClient as vt, cn as ht, createReevitClient as ft, detectCountryFromCurrency as bt, detectNetwork as wt, formatAmount as kt, formatPhone as Pt, validatePhone as _t } from "@reevit/core";
|
|
4
|
+
function he(e) {
|
|
5
|
+
const n = e.toLowerCase();
|
|
6
6
|
return n.includes("paystack") ? "paystack" : n.includes("hubtel") ? "hubtel" : n.includes("flutterwave") ? "flutterwave" : n.includes("stripe") ? "stripe" : n.includes("monnify") ? "monnify" : n.includes("mpesa") || n.includes("m-pesa") ? "mpesa" : "paystack";
|
|
7
7
|
}
|
|
8
|
-
function fe(
|
|
8
|
+
function fe(e, n) {
|
|
9
9
|
return {
|
|
10
|
-
id:
|
|
11
|
-
clientSecret:
|
|
12
|
-
pspPublicKey:
|
|
13
|
-
pspCredentials:
|
|
14
|
-
amount:
|
|
15
|
-
currency:
|
|
16
|
-
status:
|
|
17
|
-
recommendedPsp: he(
|
|
10
|
+
id: e.id,
|
|
11
|
+
clientSecret: e.client_secret,
|
|
12
|
+
pspPublicKey: e.psp_public_key,
|
|
13
|
+
pspCredentials: e.psp_credentials,
|
|
14
|
+
amount: e.amount,
|
|
15
|
+
currency: e.currency,
|
|
16
|
+
status: e.status,
|
|
17
|
+
recommendedPsp: he(e.provider),
|
|
18
18
|
availableMethods: n.paymentMethods || ["card", "mobile_money"],
|
|
19
|
-
reference:
|
|
20
|
-
connectionId:
|
|
21
|
-
provider:
|
|
22
|
-
feeAmount:
|
|
23
|
-
feeCurrency:
|
|
24
|
-
netAmount:
|
|
19
|
+
reference: e.reference || n.reference,
|
|
20
|
+
connectionId: e.connection_id,
|
|
21
|
+
provider: e.provider,
|
|
22
|
+
feeAmount: e.fee_amount,
|
|
23
|
+
feeCurrency: e.fee_currency,
|
|
24
|
+
netAmount: e.net_amount,
|
|
25
25
|
metadata: n.metadata
|
|
26
26
|
};
|
|
27
27
|
}
|
|
28
|
-
function be(
|
|
29
|
-
const { config: n, onSuccess:
|
|
28
|
+
function be(e) {
|
|
29
|
+
const { config: n, onSuccess: t, onError: i, onClose: o, onStateChange: d, apiBaseUrl: u } = e, s = $(le());
|
|
30
30
|
if (n.initialPaymentIntent) {
|
|
31
31
|
const l = n.initialPaymentIntent;
|
|
32
32
|
s.value = {
|
|
@@ -38,18 +38,18 @@ function be(t) {
|
|
|
38
38
|
}
|
|
39
39
|
const p = new ce({
|
|
40
40
|
publicKey: n.publicKey,
|
|
41
|
-
baseUrl:
|
|
42
|
-
}),
|
|
41
|
+
baseUrl: u
|
|
42
|
+
}), m = (l) => {
|
|
43
43
|
s.value = me(s.value, l);
|
|
44
44
|
};
|
|
45
45
|
N(
|
|
46
46
|
() => s.value.status,
|
|
47
47
|
(l) => {
|
|
48
|
-
|
|
48
|
+
d?.(l);
|
|
49
49
|
}
|
|
50
50
|
);
|
|
51
51
|
const a = async (l) => {
|
|
52
|
-
|
|
52
|
+
m({ type: "INIT_START" });
|
|
53
53
|
try {
|
|
54
54
|
const r = n.reference || de(), y = ue(n.currency), b = l || n.paymentMethods?.[0] || "card", { data: P, error: H } = await p.createPaymentIntent(
|
|
55
55
|
{ ...n, reference: r },
|
|
@@ -57,7 +57,7 @@ function be(t) {
|
|
|
57
57
|
y
|
|
58
58
|
);
|
|
59
59
|
if (H) {
|
|
60
|
-
|
|
60
|
+
m({ type: "INIT_ERROR", payload: H }), i?.(H);
|
|
61
61
|
return;
|
|
62
62
|
}
|
|
63
63
|
if (!P) {
|
|
@@ -66,11 +66,11 @@ function be(t) {
|
|
|
66
66
|
message: "No data received from API",
|
|
67
67
|
recoverable: !0
|
|
68
68
|
};
|
|
69
|
-
|
|
69
|
+
m({ type: "INIT_ERROR", payload: B }), i?.(B);
|
|
70
70
|
return;
|
|
71
71
|
}
|
|
72
72
|
const ne = fe(P, { ...n, reference: r });
|
|
73
|
-
|
|
73
|
+
m({ type: "INIT_SUCCESS", payload: ne });
|
|
74
74
|
} catch (r) {
|
|
75
75
|
const y = {
|
|
76
76
|
code: "INIT_FAILED",
|
|
@@ -78,13 +78,13 @@ function be(t) {
|
|
|
78
78
|
recoverable: !0,
|
|
79
79
|
originalError: r
|
|
80
80
|
};
|
|
81
|
-
|
|
81
|
+
m({ type: "INIT_ERROR", payload: y }), i?.(y);
|
|
82
82
|
}
|
|
83
83
|
}, f = (l) => {
|
|
84
|
-
|
|
85
|
-
},
|
|
84
|
+
m({ type: "SELECT_METHOD", payload: l });
|
|
85
|
+
}, _ = async (l) => {
|
|
86
86
|
if (!(!s.value.paymentIntent || !s.value.selectedMethod)) {
|
|
87
|
-
|
|
87
|
+
m({ type: "PROCESS_START" });
|
|
88
88
|
try {
|
|
89
89
|
let r;
|
|
90
90
|
if (s.value.paymentIntent.clientSecret) {
|
|
@@ -93,14 +93,14 @@ function be(t) {
|
|
|
93
93
|
s.value.paymentIntent.clientSecret
|
|
94
94
|
);
|
|
95
95
|
if (P) {
|
|
96
|
-
|
|
96
|
+
m({ type: "PROCESS_ERROR", payload: P }), i?.(P);
|
|
97
97
|
return;
|
|
98
98
|
}
|
|
99
99
|
r = b;
|
|
100
100
|
} else {
|
|
101
101
|
const { data: b, error: P } = await p.confirmPayment(s.value.paymentIntent.id);
|
|
102
102
|
if (P) {
|
|
103
|
-
|
|
103
|
+
m({ type: "PROCESS_ERROR", payload: P }), i?.(P);
|
|
104
104
|
return;
|
|
105
105
|
}
|
|
106
106
|
r = b;
|
|
@@ -116,7 +116,7 @@ function be(t) {
|
|
|
116
116
|
status: "success",
|
|
117
117
|
metadata: l
|
|
118
118
|
};
|
|
119
|
-
|
|
119
|
+
m({ type: "PROCESS_SUCCESS", payload: y }), t?.(y);
|
|
120
120
|
} catch (r) {
|
|
121
121
|
const y = {
|
|
122
122
|
code: "PAYMENT_FAILED",
|
|
@@ -124,22 +124,22 @@ function be(t) {
|
|
|
124
124
|
recoverable: !0,
|
|
125
125
|
originalError: r
|
|
126
126
|
};
|
|
127
|
-
|
|
127
|
+
m({ type: "PROCESS_ERROR", payload: y }), i?.(y);
|
|
128
128
|
}
|
|
129
129
|
}
|
|
130
130
|
}, g = async (l) => {
|
|
131
|
-
await
|
|
131
|
+
await _(l);
|
|
132
132
|
}, A = (l) => {
|
|
133
|
-
|
|
133
|
+
m({ type: "PROCESS_ERROR", payload: l }), i?.(l);
|
|
134
134
|
}, S = () => {
|
|
135
|
-
|
|
135
|
+
m({ type: "RESET" });
|
|
136
136
|
}, U = async () => {
|
|
137
137
|
if (s.value.paymentIntent && s.value.status !== "success")
|
|
138
138
|
try {
|
|
139
139
|
await p.cancelPaymentIntent(s.value.paymentIntent.id);
|
|
140
140
|
} catch {
|
|
141
141
|
}
|
|
142
|
-
|
|
142
|
+
m({ type: "CLOSE" }), o?.();
|
|
143
143
|
}, M = w(() => s.value.status), K = w(() => s.value.paymentIntent), R = w(() => s.value.selectedMethod), j = w(() => s.value.error), k = w(() => s.value.result), O = w(
|
|
144
144
|
() => s.value.status === "loading" || s.value.status === "processing"
|
|
145
145
|
), x = w(
|
|
@@ -147,27 +147,27 @@ function be(t) {
|
|
|
147
147
|
), T = w(() => s.value.status === "success"), z = w(() => s.value.error?.recoverable ?? !1);
|
|
148
148
|
return {
|
|
149
149
|
// State (readonly refs)
|
|
150
|
-
status:
|
|
151
|
-
paymentIntent:
|
|
152
|
-
selectedMethod:
|
|
153
|
-
error:
|
|
154
|
-
result:
|
|
150
|
+
status: C(M),
|
|
151
|
+
paymentIntent: C(K),
|
|
152
|
+
selectedMethod: C(R),
|
|
153
|
+
error: C(j),
|
|
154
|
+
result: C(k),
|
|
155
155
|
// Actions
|
|
156
156
|
initialize: a,
|
|
157
157
|
selectMethod: f,
|
|
158
|
-
processPayment:
|
|
158
|
+
processPayment: _,
|
|
159
159
|
handlePspSuccess: g,
|
|
160
160
|
handlePspError: A,
|
|
161
161
|
reset: S,
|
|
162
162
|
close: U,
|
|
163
163
|
// Computed
|
|
164
|
-
isLoading:
|
|
165
|
-
isReady:
|
|
166
|
-
isComplete:
|
|
167
|
-
canRetry:
|
|
164
|
+
isLoading: C(O),
|
|
165
|
+
isReady: C(x),
|
|
166
|
+
isComplete: C(T),
|
|
167
|
+
canRetry: C(z)
|
|
168
168
|
};
|
|
169
169
|
}
|
|
170
|
-
const we = { class: "reevit-method-selector" }, ke = { class: "reevit-amount-display" }, Pe = { class: "reevit-methods-grid" },
|
|
170
|
+
const we = { class: "reevit-method-selector" }, ke = { class: "reevit-amount-display" }, Pe = { class: "reevit-methods-grid" }, _e = ["onClick"], Ce = { class: "reevit-method-icon" }, Se = { class: "reevit-method-info" }, Ee = { class: "reevit-method-name" }, Ie = { class: "reevit-method-description" }, ge = { class: "reevit-method-radio" }, Me = {
|
|
171
171
|
key: 0,
|
|
172
172
|
class: "reevit-radio-inner"
|
|
173
173
|
}, Re = /* @__PURE__ */ V({
|
|
@@ -180,61 +180,61 @@ const we = { class: "reevit-method-selector" }, ke = { class: "reevit-amount-dis
|
|
|
180
180
|
provider: {}
|
|
181
181
|
},
|
|
182
182
|
emits: ["select"],
|
|
183
|
-
setup(
|
|
184
|
-
const
|
|
183
|
+
setup(e, { emit: n }) {
|
|
184
|
+
const t = e, i = n, o = {
|
|
185
185
|
hubtel: "Hubtel",
|
|
186
186
|
paystack: "Paystack",
|
|
187
187
|
flutterwave: "Flutterwave",
|
|
188
188
|
monnify: "Monnify",
|
|
189
189
|
mpesa: "M-Pesa",
|
|
190
190
|
stripe: "Stripe"
|
|
191
|
-
},
|
|
191
|
+
}, d = (p) => t.provider?.toLowerCase().includes("hubtel") && p === "mobile_money" ? `Pay with ${o[t.provider.toLowerCase()] || "Hubtel"}` : {
|
|
192
192
|
card: "Card",
|
|
193
193
|
mobile_money: "Mobile Money",
|
|
194
194
|
bank_transfer: "Bank Transfer"
|
|
195
|
-
}[p],
|
|
195
|
+
}[p], u = (p) => t.provider?.toLowerCase().includes("hubtel") ? "Card, Mobile Money, and Bank Transfer" : {
|
|
196
196
|
card: "Visa, Mastercard, Maestro",
|
|
197
197
|
mobile_money: "MTN, Vodafone, AirtelTigo",
|
|
198
198
|
bank_transfer: "Transfer directly from your bank"
|
|
199
199
|
}[p], s = w(() => [
|
|
200
200
|
{
|
|
201
201
|
id: "card",
|
|
202
|
-
name:
|
|
203
|
-
description:
|
|
202
|
+
name: d("card"),
|
|
203
|
+
description: u("card"),
|
|
204
204
|
icon: "💳"
|
|
205
205
|
},
|
|
206
206
|
{
|
|
207
207
|
id: "mobile_money",
|
|
208
|
-
name:
|
|
209
|
-
description:
|
|
208
|
+
name: d("mobile_money"),
|
|
209
|
+
description: u("mobile_money"),
|
|
210
210
|
icon: "📱"
|
|
211
211
|
},
|
|
212
212
|
{
|
|
213
213
|
id: "bank_transfer",
|
|
214
|
-
name:
|
|
215
|
-
description:
|
|
214
|
+
name: d("bank_transfer"),
|
|
215
|
+
description: u("bank_transfer"),
|
|
216
216
|
icon: "🏦"
|
|
217
217
|
}
|
|
218
|
-
].filter((p) =>
|
|
219
|
-
return (p,
|
|
220
|
-
|
|
221
|
-
c("p", ke, " Pay " + I(L(pe)(
|
|
218
|
+
].filter((p) => t.methods.includes(p.id)));
|
|
219
|
+
return (p, m) => (v(), h("div", we, [
|
|
220
|
+
m[0] || (m[0] = c("h3", { class: "reevit-section-title" }, "Select Payment Method", -1)),
|
|
221
|
+
c("p", ke, " Pay " + I(L(pe)(e.amount, e.currency)), 1),
|
|
222
222
|
c("div", Pe, [
|
|
223
223
|
(v(!0), h(q, null, Q(s.value, (a) => (v(), h("button", {
|
|
224
224
|
key: a.id,
|
|
225
225
|
type: "button",
|
|
226
|
-
class: D(L(te)("reevit-method-card",
|
|
226
|
+
class: D(L(te)("reevit-method-card", e.selected === a.id && "reevit-method-card--selected")),
|
|
227
227
|
onClick: (f) => i("select", a.id)
|
|
228
228
|
}, [
|
|
229
|
-
c("span",
|
|
229
|
+
c("span", Ce, I(a.icon), 1),
|
|
230
230
|
c("div", Se, [
|
|
231
231
|
c("span", Ee, I(a.name), 1),
|
|
232
232
|
c("span", Ie, I(a.description), 1)
|
|
233
233
|
]),
|
|
234
234
|
c("div", ge, [
|
|
235
|
-
|
|
235
|
+
e.selected === a.id ? (v(), h("div", Me)) : E("", !0)
|
|
236
236
|
])
|
|
237
|
-
], 10,
|
|
237
|
+
], 10, _e))), 128))
|
|
238
238
|
])
|
|
239
239
|
]));
|
|
240
240
|
}
|
|
@@ -251,31 +251,31 @@ const we = { class: "reevit-method-selector" }, ke = { class: "reevit-amount-dis
|
|
|
251
251
|
loading: { type: Boolean }
|
|
252
252
|
},
|
|
253
253
|
emits: ["submit"],
|
|
254
|
-
setup(
|
|
255
|
-
const
|
|
256
|
-
N(o, (
|
|
257
|
-
const a = ye(
|
|
258
|
-
a && (
|
|
254
|
+
setup(e, { emit: n }) {
|
|
255
|
+
const t = e, i = n, o = $(t.initialPhone || ""), d = $(null), u = $(null);
|
|
256
|
+
N(o, (m) => {
|
|
257
|
+
const a = ye(m);
|
|
258
|
+
a && (d.value = a), u.value && (u.value = null);
|
|
259
259
|
});
|
|
260
260
|
const s = () => {
|
|
261
261
|
if (!G(o.value)) {
|
|
262
|
-
|
|
262
|
+
u.value = "Please enter a valid phone number";
|
|
263
263
|
return;
|
|
264
264
|
}
|
|
265
|
-
if (!
|
|
266
|
-
|
|
265
|
+
if (!d.value) {
|
|
266
|
+
u.value = "Please select your mobile network";
|
|
267
267
|
return;
|
|
268
268
|
}
|
|
269
269
|
i("submit", {
|
|
270
270
|
phone: o.value,
|
|
271
|
-
network:
|
|
271
|
+
network: d.value
|
|
272
272
|
});
|
|
273
273
|
}, p = [
|
|
274
274
|
{ id: "mtn", name: "MTN", color: "#FFCC00" },
|
|
275
275
|
{ id: "vodafone", name: "Vodafone", color: "#E60000" },
|
|
276
276
|
{ id: "airteltigo", name: "AirtelTigo", color: "#005596" }
|
|
277
277
|
];
|
|
278
|
-
return (
|
|
278
|
+
return (m, a) => (v(), h("form", {
|
|
279
279
|
class: "reevit-momo-form",
|
|
280
280
|
onSubmit: X(s, ["prevent"])
|
|
281
281
|
}, [
|
|
@@ -288,9 +288,9 @@ const we = { class: "reevit-method-selector" }, ke = { class: "reevit-amount-dis
|
|
|
288
288
|
id: "reevit-phone",
|
|
289
289
|
"onUpdate:modelValue": a[0] || (a[0] = (f) => o.value = f),
|
|
290
290
|
type: "tel",
|
|
291
|
-
class: D(["reevit-input", { "reevit-input--error":
|
|
291
|
+
class: D(["reevit-input", { "reevit-input--error": u.value && !L(G)(o.value) }]),
|
|
292
292
|
placeholder: "e.g. 024 123 4567",
|
|
293
|
-
disabled:
|
|
293
|
+
disabled: e.loading,
|
|
294
294
|
autocomplete: "tel"
|
|
295
295
|
}, null, 10, Te), [
|
|
296
296
|
[ae, o.value]
|
|
@@ -302,9 +302,9 @@ const we = { class: "reevit-method-selector" }, ke = { class: "reevit-amount-dis
|
|
|
302
302
|
(v(), h(q, null, Q(p, (f) => c("button", {
|
|
303
303
|
key: f.id,
|
|
304
304
|
type: "button",
|
|
305
|
-
class: D(L(te)("reevit-network-btn",
|
|
306
|
-
onClick: (
|
|
307
|
-
disabled:
|
|
305
|
+
class: D(L(te)("reevit-network-btn", d.value === f.id && "reevit-network-btn--selected")),
|
|
306
|
+
onClick: (_) => d.value = f.id,
|
|
307
|
+
disabled: e.loading
|
|
308
308
|
}, [
|
|
309
309
|
c("div", {
|
|
310
310
|
class: "reevit-network-dot",
|
|
@@ -314,13 +314,13 @@ const we = { class: "reevit-method-selector" }, ke = { class: "reevit-amount-dis
|
|
|
314
314
|
], 10, Le)), 64))
|
|
315
315
|
])
|
|
316
316
|
]),
|
|
317
|
-
|
|
317
|
+
u.value ? (v(), h("p", Ue, I(u.value), 1)) : E("", !0),
|
|
318
318
|
c("button", {
|
|
319
319
|
type: "submit",
|
|
320
320
|
class: "reevit-submit-btn",
|
|
321
|
-
disabled:
|
|
321
|
+
disabled: e.loading || !o.value
|
|
322
322
|
}, [
|
|
323
|
-
|
|
323
|
+
e.loading ? (v(), h("span", De)) : (v(), h("span", Fe, "Continue"))
|
|
324
324
|
], 8, Oe),
|
|
325
325
|
a[3] || (a[3] = c("p", { class: "reevit-secure-text" }, " 🔒 Secure mobile money payment via Reevit ", -1))
|
|
326
326
|
], 32));
|
|
@@ -336,8 +336,8 @@ class Ke {
|
|
|
336
336
|
* @param config - The configuration.
|
|
337
337
|
* @throws {Error} If the popup is blocked by the browser.
|
|
338
338
|
*/
|
|
339
|
-
redirect({ purchaseInfo: n, config:
|
|
340
|
-
const i = this.createCheckoutUrl(n,
|
|
339
|
+
redirect({ purchaseInfo: n, config: t }) {
|
|
340
|
+
const i = this.createCheckoutUrl(n, t), o = window.open(i);
|
|
341
341
|
if (!o || o.closed || typeof o.closed > "u")
|
|
342
342
|
throw new Error("Popup was blocked by the browser. Please allow popups for this site.");
|
|
343
343
|
}
|
|
@@ -350,26 +350,26 @@ class Ke {
|
|
|
350
350
|
* @param iframeStyle - The style options for the iframe (optional).
|
|
351
351
|
* @throws {Error} If the container element with id "hubtel-checkout-iframe" is not found.
|
|
352
352
|
*/
|
|
353
|
-
initIframe({ purchaseInfo: n, callBacks:
|
|
354
|
-
var
|
|
355
|
-
this.registerEvents(
|
|
353
|
+
initIframe({ purchaseInfo: n, callBacks: t, config: i, iframeStyle: o }) {
|
|
354
|
+
var d, u, s;
|
|
355
|
+
this.registerEvents(t);
|
|
356
356
|
const p = document.getElementById("hubtel-checkout-iframe");
|
|
357
357
|
if (!p)
|
|
358
358
|
throw new Error('Container element with id "hubtel-checkout-iframe" not found in the DOM.');
|
|
359
359
|
p.innerHTML = "";
|
|
360
|
-
const
|
|
361
|
-
|
|
360
|
+
const m = document.createElement("div");
|
|
361
|
+
m.textContent = "Loading...", p.appendChild(m);
|
|
362
362
|
const a = document.createElement("iframe");
|
|
363
|
-
a.setAttribute("id", "hubtel-iframe-element"), a.src = this.createCheckoutUrl(n, i), a.style.display = "none", a.style.width = (
|
|
363
|
+
a.setAttribute("id", "hubtel-iframe-element"), a.src = this.createCheckoutUrl(n, i), a.style.display = "none", a.style.width = (d = o?.width) !== null && d !== void 0 ? d : "100%", a.style.height = (u = o?.height) !== null && u !== void 0 ? u : "100%", a.style.minHeight = o?.minHeight || "400px", a.style.border = (s = o?.border) !== null && s !== void 0 ? s : "none", a.onload = () => {
|
|
364
364
|
var f;
|
|
365
|
-
p.removeChild(
|
|
365
|
+
p.removeChild(m), a.style.display = "block", (f = t.onLoad) === null || f === void 0 || f.call(t);
|
|
366
366
|
}, p.appendChild(a);
|
|
367
367
|
}
|
|
368
|
-
openModal({ purchaseInfo: n, callBacks:
|
|
369
|
-
this.injectStyles(), this.createIframe(), this.handleBackButton(), this.registerEvents(
|
|
368
|
+
openModal({ purchaseInfo: n, callBacks: t, config: i }) {
|
|
369
|
+
this.injectStyles(), this.createIframe(), this.handleBackButton(), this.registerEvents(t), this.renderWebpageInPopup(this.createCheckoutUrl(n, i), t.onClose, t.onLoad);
|
|
370
370
|
}
|
|
371
|
-
createCheckoutUrl(n,
|
|
372
|
-
const i = Object.assign(Object.assign({}, n),
|
|
371
|
+
createCheckoutUrl(n, t) {
|
|
372
|
+
const i = Object.assign(Object.assign({}, n), t), o = Object.keys(i).reduce((m, a) => (i[a] !== null && i[a] !== void 0 && (m[a] = i[a]), m), {}), d = Object.keys(o).map((m) => `${m}=${encodeURIComponent(o[m])}`).join("&"), u = this.encodeBase64(d), s = encodeURIComponent(u);
|
|
373
373
|
return `${o?.branding === "disabled" ? `${this.baseUrl}/pay/direct` : `${this.baseUrl}/pay`}?p=${s}`;
|
|
374
374
|
}
|
|
375
375
|
encodeBase64(n) {
|
|
@@ -383,30 +383,30 @@ class Ke {
|
|
|
383
383
|
createIframe() {
|
|
384
384
|
const n = document.createElement("div");
|
|
385
385
|
n.setAttribute("id", "backdrop"), n.classList.add("backdrop");
|
|
386
|
-
const
|
|
387
|
-
|
|
386
|
+
const t = document.createElement("span");
|
|
387
|
+
t.classList.add("checkout-loader"), n.appendChild(t), document.body.appendChild(n);
|
|
388
388
|
}
|
|
389
389
|
registerEvents(n) {
|
|
390
390
|
this.messageHandler && window.removeEventListener("message", this.messageHandler, !1);
|
|
391
|
-
const
|
|
392
|
-
var o,
|
|
391
|
+
const t = (i) => {
|
|
392
|
+
var o, d, u, s, p, m;
|
|
393
393
|
if (i.origin !== this.baseUrl)
|
|
394
394
|
return;
|
|
395
395
|
const { data: a } = i;
|
|
396
396
|
if (a.success === !0)
|
|
397
397
|
(o = n.onPaymentSuccess) === null || o === void 0 || o.call(n, a);
|
|
398
398
|
else if (a.success === !1)
|
|
399
|
-
(
|
|
399
|
+
(d = n.onPaymentFailure) === null || d === void 0 || d.call(n, a);
|
|
400
400
|
else if (a.initialized)
|
|
401
|
-
(
|
|
401
|
+
(u = n.init) === null || u === void 0 || u.call(n, a), (s = n.onInit) === null || s === void 0 || s.call(n, a);
|
|
402
402
|
else if (a.feesChanged)
|
|
403
403
|
(p = n.onFeesChanged) === null || p === void 0 || p.call(n, a.fees);
|
|
404
404
|
else if (a.resize) {
|
|
405
405
|
const f = document.getElementById("hubtel-iframe-element");
|
|
406
|
-
f && (f.style.height = a.height + "px"), (
|
|
406
|
+
f && (f.style.height = a.height + "px"), (m = n?.onResize) === null || m === void 0 || m.call(n, a);
|
|
407
407
|
}
|
|
408
408
|
};
|
|
409
|
-
this.messageHandler =
|
|
409
|
+
this.messageHandler = t, window.addEventListener("message", t, !1);
|
|
410
410
|
}
|
|
411
411
|
/**
|
|
412
412
|
* Removes the message event listener to prevent memory leaks.
|
|
@@ -415,21 +415,21 @@ class Ke {
|
|
|
415
415
|
destroy() {
|
|
416
416
|
this.messageHandler && (window.removeEventListener("message", this.messageHandler, !1), this.messageHandler = null);
|
|
417
417
|
}
|
|
418
|
-
renderWebpageInPopup(n,
|
|
418
|
+
renderWebpageInPopup(n, t, i) {
|
|
419
419
|
const o = document.createElement("div");
|
|
420
420
|
o.classList.add("checkout-modal");
|
|
421
|
-
const
|
|
422
|
-
|
|
423
|
-
this.closePopUp(),
|
|
424
|
-
}), o.appendChild(
|
|
425
|
-
const
|
|
426
|
-
|
|
421
|
+
const d = document.createElement("div");
|
|
422
|
+
d.setAttribute("id", "checkout-close-icon"), d.innerHTML = "×", d.classList.add("close-icon"), d.addEventListener("click", () => {
|
|
423
|
+
this.closePopUp(), t?.();
|
|
424
|
+
}), o.appendChild(d);
|
|
425
|
+
const u = document.createElement("iframe");
|
|
426
|
+
u.src = n, history.pushState({ modalOpen: !0 }, ""), u.classList.add("iframe"), o.appendChild(u), document.body.appendChild(o), o.style.opacity = "0", u.addEventListener("load", () => {
|
|
427
427
|
o.style.opacity = "1", i?.();
|
|
428
428
|
});
|
|
429
429
|
}
|
|
430
430
|
closePopUp() {
|
|
431
|
-
const n = document.querySelector(".backdrop"),
|
|
432
|
-
n && document.body.removeChild(n),
|
|
431
|
+
const n = document.querySelector(".backdrop"), t = document.querySelector(".checkout-modal");
|
|
432
|
+
n && document.body.removeChild(n), t && document.body.removeChild(t), history.replaceState(null, ""), window.removeEventListener("popstate", this.closePopUp);
|
|
433
433
|
}
|
|
434
434
|
injectStyles() {
|
|
435
435
|
if (this.stylesInjected)
|
|
@@ -539,16 +539,16 @@ class Ke {
|
|
|
539
539
|
}
|
|
540
540
|
}
|
|
541
541
|
const J = /* @__PURE__ */ new Map();
|
|
542
|
-
function F(
|
|
543
|
-
const
|
|
544
|
-
if (
|
|
545
|
-
const i = new Promise((o,
|
|
542
|
+
function F(e, n) {
|
|
543
|
+
const t = J.get(n);
|
|
544
|
+
if (t) return t;
|
|
545
|
+
const i = new Promise((o, d) => {
|
|
546
546
|
if (document.getElementById(n)) {
|
|
547
547
|
o();
|
|
548
548
|
return;
|
|
549
549
|
}
|
|
550
|
-
const
|
|
551
|
-
|
|
550
|
+
const u = document.createElement("script");
|
|
551
|
+
u.id = n, u.src = e, u.async = !0, u.onload = () => o(), u.onerror = () => d(new Error(`Failed to load ${n} script`)), document.head.appendChild(u);
|
|
552
552
|
});
|
|
553
553
|
return J.set(n, i), i;
|
|
554
554
|
}
|
|
@@ -567,130 +567,130 @@ function He() {
|
|
|
567
567
|
function Ve() {
|
|
568
568
|
return F("https://sdk.monnify.com/plugin/monnify.js", "monnify-script");
|
|
569
569
|
}
|
|
570
|
-
async function qe(
|
|
570
|
+
async function qe(e) {
|
|
571
571
|
if (await je(), !window.PaystackPop)
|
|
572
572
|
throw new Error("Paystack script not loaded");
|
|
573
573
|
window.PaystackPop.setup({
|
|
574
|
-
key:
|
|
575
|
-
email:
|
|
576
|
-
amount:
|
|
577
|
-
currency:
|
|
578
|
-
ref:
|
|
579
|
-
metadata:
|
|
580
|
-
callback:
|
|
581
|
-
onClose:
|
|
574
|
+
key: e.key,
|
|
575
|
+
email: e.email,
|
|
576
|
+
amount: e.amount,
|
|
577
|
+
currency: e.currency,
|
|
578
|
+
ref: e.ref,
|
|
579
|
+
metadata: e.metadata,
|
|
580
|
+
callback: e.onSuccess,
|
|
581
|
+
onClose: e.onClose
|
|
582
582
|
}).openIframe();
|
|
583
583
|
}
|
|
584
|
-
async function Be(
|
|
585
|
-
const n = new Ke(),
|
|
586
|
-
amount:
|
|
587
|
-
purchaseDescription:
|
|
588
|
-
customerPhoneNumber:
|
|
584
|
+
async function Be(e) {
|
|
585
|
+
const n = new Ke(), t = {
|
|
586
|
+
amount: e.amount,
|
|
587
|
+
purchaseDescription: e.purchaseDescription,
|
|
588
|
+
customerPhoneNumber: e.customerPhone || "",
|
|
589
589
|
clientReference: `hubtel_${Date.now()}`
|
|
590
|
-
}, i = {
|
|
590
|
+
}, i = e.hubtelSessionToken || e.basicAuth || "", o = {
|
|
591
591
|
branding: "enabled",
|
|
592
|
-
callbackUrl:
|
|
593
|
-
merchantAccount: typeof
|
|
594
|
-
basicAuth:
|
|
592
|
+
callbackUrl: e.callbackUrl || (typeof window < "u" ? window.location.href : ""),
|
|
593
|
+
merchantAccount: typeof e.clientId == "string" ? parseInt(e.clientId, 10) : e.clientId,
|
|
594
|
+
basicAuth: i
|
|
595
595
|
};
|
|
596
596
|
n.openModal({
|
|
597
|
-
purchaseInfo:
|
|
598
|
-
config:
|
|
597
|
+
purchaseInfo: t,
|
|
598
|
+
config: o,
|
|
599
599
|
callBacks: {
|
|
600
|
-
onPaymentSuccess: (
|
|
601
|
-
|
|
600
|
+
onPaymentSuccess: (d) => {
|
|
601
|
+
e.onSuccess(d), n.closePopUp();
|
|
602
602
|
},
|
|
603
603
|
onPaymentFailure: () => {
|
|
604
|
-
|
|
604
|
+
e.onClose();
|
|
605
605
|
},
|
|
606
606
|
onClose: () => {
|
|
607
|
-
|
|
607
|
+
e.onClose();
|
|
608
608
|
}
|
|
609
609
|
}
|
|
610
610
|
});
|
|
611
611
|
}
|
|
612
|
-
async function Ye(
|
|
612
|
+
async function Ye(e) {
|
|
613
613
|
if (await ze(), !window.FlutterwaveCheckout)
|
|
614
614
|
throw new Error("Flutterwave script not loaded");
|
|
615
615
|
window.FlutterwaveCheckout({
|
|
616
|
-
public_key:
|
|
617
|
-
tx_ref:
|
|
618
|
-
amount:
|
|
619
|
-
currency:
|
|
620
|
-
customer:
|
|
621
|
-
payment_options:
|
|
622
|
-
customizations:
|
|
623
|
-
callback:
|
|
624
|
-
onclose:
|
|
616
|
+
public_key: e.public_key,
|
|
617
|
+
tx_ref: e.tx_ref,
|
|
618
|
+
amount: e.amount,
|
|
619
|
+
currency: e.currency,
|
|
620
|
+
customer: e.customer,
|
|
621
|
+
payment_options: e.payment_options,
|
|
622
|
+
customizations: e.customizations,
|
|
623
|
+
callback: e.callback,
|
|
624
|
+
onclose: e.onclose
|
|
625
625
|
});
|
|
626
626
|
}
|
|
627
|
-
async function We(
|
|
627
|
+
async function We(e) {
|
|
628
628
|
if (await He(), !window.Stripe)
|
|
629
629
|
throw new Error("Stripe.js not loaded");
|
|
630
|
-
return window.Stripe(
|
|
630
|
+
return window.Stripe(e);
|
|
631
631
|
}
|
|
632
|
-
async function ut(
|
|
633
|
-
const
|
|
634
|
-
elements:
|
|
635
|
-
clientSecret:
|
|
632
|
+
async function ut(e) {
|
|
633
|
+
const t = await (await We(e.publishableKey)).confirmPayment({
|
|
634
|
+
elements: e.elements,
|
|
635
|
+
clientSecret: e.clientSecret,
|
|
636
636
|
redirect: "if_required"
|
|
637
637
|
});
|
|
638
|
-
|
|
639
|
-
paymentIntentId:
|
|
640
|
-
status:
|
|
638
|
+
t.error ? e.onError({ message: t.error.message || "Payment failed" }) : t.paymentIntent && e.onSuccess({
|
|
639
|
+
paymentIntentId: t.paymentIntent.id,
|
|
640
|
+
status: t.paymentIntent.status
|
|
641
641
|
});
|
|
642
642
|
}
|
|
643
|
-
async function Ge(
|
|
643
|
+
async function Ge(e) {
|
|
644
644
|
if (await Ve(), !window.MonnifySDK)
|
|
645
645
|
throw new Error("Monnify SDK not loaded");
|
|
646
646
|
window.MonnifySDK.initialize({
|
|
647
|
-
amount:
|
|
648
|
-
currency:
|
|
649
|
-
reference:
|
|
650
|
-
customerName:
|
|
651
|
-
customerEmail:
|
|
652
|
-
customerMobileNumber:
|
|
653
|
-
apiKey:
|
|
654
|
-
contractCode:
|
|
655
|
-
paymentDescription:
|
|
656
|
-
isTestMode:
|
|
657
|
-
metadata:
|
|
647
|
+
amount: e.amount,
|
|
648
|
+
currency: e.currency,
|
|
649
|
+
reference: e.reference,
|
|
650
|
+
customerName: e.customerName,
|
|
651
|
+
customerEmail: e.customerEmail,
|
|
652
|
+
customerMobileNumber: e.customerPhone,
|
|
653
|
+
apiKey: e.apiKey,
|
|
654
|
+
contractCode: e.contractCode,
|
|
655
|
+
paymentDescription: e.paymentDescription || "Payment",
|
|
656
|
+
isTestMode: e.isTestMode ?? !1,
|
|
657
|
+
metadata: e.metadata,
|
|
658
658
|
onComplete: (n) => {
|
|
659
|
-
n.status === "SUCCESS" ?
|
|
659
|
+
n.status === "SUCCESS" ? e.onSuccess({
|
|
660
660
|
transactionReference: n.transactionReference,
|
|
661
661
|
paymentReference: n.paymentReference,
|
|
662
662
|
...n
|
|
663
|
-
}) :
|
|
663
|
+
}) : e.onError?.({ message: n.message || "Payment failed" });
|
|
664
664
|
},
|
|
665
|
-
onClose:
|
|
665
|
+
onClose: e.onClose
|
|
666
666
|
});
|
|
667
667
|
}
|
|
668
|
-
async function Je(
|
|
669
|
-
|
|
668
|
+
async function Je(e, n) {
|
|
669
|
+
e.onInitiated();
|
|
670
670
|
try {
|
|
671
|
-
const
|
|
671
|
+
const t = await fetch(n, {
|
|
672
672
|
method: "POST",
|
|
673
673
|
headers: { "Content-Type": "application/json" },
|
|
674
674
|
body: JSON.stringify({
|
|
675
|
-
phone_number:
|
|
676
|
-
amount:
|
|
677
|
-
reference:
|
|
678
|
-
description:
|
|
675
|
+
phone_number: e.phoneNumber,
|
|
676
|
+
amount: e.amount,
|
|
677
|
+
reference: e.reference,
|
|
678
|
+
description: e.description
|
|
679
679
|
})
|
|
680
680
|
});
|
|
681
|
-
if (!
|
|
682
|
-
const
|
|
683
|
-
return
|
|
681
|
+
if (!t.ok) {
|
|
682
|
+
const d = (await t.json().catch(() => ({}))).message || "Failed to initiate M-Pesa payment";
|
|
683
|
+
return e.onError({ message: d }), { status: "failed", message: d };
|
|
684
684
|
}
|
|
685
|
-
const i = await
|
|
685
|
+
const i = await t.json();
|
|
686
686
|
return {
|
|
687
687
|
status: "initiated",
|
|
688
688
|
message: "Please check your phone and enter your M-Pesa PIN to complete the payment.",
|
|
689
689
|
transactionId: i.checkout_request_id || i.transaction_id
|
|
690
690
|
};
|
|
691
|
-
} catch (
|
|
692
|
-
const i =
|
|
693
|
-
return
|
|
691
|
+
} catch (t) {
|
|
692
|
+
const i = t instanceof Error ? t.message : "Network error";
|
|
693
|
+
return e.onError({ message: i }), { status: "failed", message: i };
|
|
694
694
|
}
|
|
695
695
|
}
|
|
696
696
|
const Qe = ["disabled"], Xe = {
|
|
@@ -731,43 +731,43 @@ const Qe = ["disabled"], Xe = {
|
|
|
731
731
|
initialPaymentIntent: {}
|
|
732
732
|
},
|
|
733
733
|
emits: ["success", "error", "close"],
|
|
734
|
-
setup(
|
|
735
|
-
const
|
|
734
|
+
setup(e, { emit: n }) {
|
|
735
|
+
const t = e, i = n, {
|
|
736
736
|
status: o,
|
|
737
|
-
paymentIntent:
|
|
738
|
-
selectedMethod:
|
|
737
|
+
paymentIntent: d,
|
|
738
|
+
selectedMethod: u,
|
|
739
739
|
error: s,
|
|
740
740
|
isLoading: p,
|
|
741
|
-
isReady:
|
|
741
|
+
isReady: m,
|
|
742
742
|
initialize: a,
|
|
743
743
|
selectMethod: f,
|
|
744
|
-
handlePspSuccess:
|
|
744
|
+
handlePspSuccess: _,
|
|
745
745
|
handlePspError: g,
|
|
746
746
|
close: A
|
|
747
747
|
} = be({
|
|
748
748
|
config: {
|
|
749
|
-
publicKey:
|
|
750
|
-
amount:
|
|
751
|
-
currency:
|
|
752
|
-
email:
|
|
753
|
-
phone:
|
|
754
|
-
reference:
|
|
755
|
-
metadata:
|
|
756
|
-
paymentMethods:
|
|
757
|
-
initialPaymentIntent:
|
|
749
|
+
publicKey: t.publicKey,
|
|
750
|
+
amount: t.amount,
|
|
751
|
+
currency: t.currency,
|
|
752
|
+
email: t.email,
|
|
753
|
+
phone: t.phone,
|
|
754
|
+
reference: t.reference,
|
|
755
|
+
metadata: t.metadata,
|
|
756
|
+
paymentMethods: t.paymentMethods,
|
|
757
|
+
initialPaymentIntent: t.initialPaymentIntent
|
|
758
758
|
},
|
|
759
|
-
apiBaseUrl:
|
|
759
|
+
apiBaseUrl: t.apiBaseUrl,
|
|
760
760
|
onSuccess: (l) => i("success", l),
|
|
761
761
|
onError: (l) => i("error", l),
|
|
762
762
|
onClose: () => i("close")
|
|
763
|
-
}), S = $(
|
|
764
|
-
N(() =>
|
|
763
|
+
}), S = $(t.isOpen ?? !1);
|
|
764
|
+
N(() => t.isOpen, (l) => {
|
|
765
765
|
l !== void 0 && (S.value = l);
|
|
766
766
|
});
|
|
767
767
|
const U = () => {
|
|
768
|
-
S.value = !0, !
|
|
768
|
+
S.value = !0, !d.value && o.value === "idle" && a();
|
|
769
769
|
};
|
|
770
|
-
N([S,
|
|
770
|
+
N([S, d, u], ([l, r, y]) => {
|
|
771
771
|
l && r && y && y === "card" && R(null);
|
|
772
772
|
});
|
|
773
773
|
const M = () => {
|
|
@@ -775,72 +775,73 @@ const Qe = ["disabled"], Xe = {
|
|
|
775
775
|
}, K = (l) => {
|
|
776
776
|
f(l);
|
|
777
777
|
}, R = async (l) => {
|
|
778
|
-
const r =
|
|
778
|
+
const r = d.value;
|
|
779
779
|
if (!r) return;
|
|
780
780
|
const y = r.recommendedPsp;
|
|
781
781
|
try {
|
|
782
782
|
if (y === "paystack")
|
|
783
783
|
await qe({
|
|
784
|
-
key:
|
|
785
|
-
email:
|
|
786
|
-
amount:
|
|
787
|
-
currency:
|
|
784
|
+
key: t.publicKey,
|
|
785
|
+
email: t.email || "",
|
|
786
|
+
amount: t.amount,
|
|
787
|
+
currency: t.currency,
|
|
788
788
|
ref: r.id,
|
|
789
|
-
onSuccess: (b) =>
|
|
789
|
+
onSuccess: (b) => _(b),
|
|
790
790
|
onClose: () => {
|
|
791
791
|
}
|
|
792
792
|
});
|
|
793
793
|
else if (y === "hubtel")
|
|
794
794
|
await Be({
|
|
795
|
-
clientId: r.pspCredentials?.merchantAccount ||
|
|
796
|
-
purchaseDescription: `Payment for ${
|
|
797
|
-
amount:
|
|
798
|
-
customerPhone: l?.phone ||
|
|
799
|
-
customerEmail:
|
|
800
|
-
|
|
801
|
-
|
|
795
|
+
clientId: r.pspCredentials?.merchantAccount || t.publicKey,
|
|
796
|
+
purchaseDescription: `Payment for ${t.amount} ${t.currency}`,
|
|
797
|
+
amount: t.amount,
|
|
798
|
+
customerPhone: l?.phone || t.phone,
|
|
799
|
+
customerEmail: t.email,
|
|
800
|
+
hubtelSessionToken: r.id,
|
|
801
|
+
// Pass payment ID to fetch session token
|
|
802
|
+
onSuccess: (b) => _(b),
|
|
802
803
|
onClose: () => {
|
|
803
804
|
}
|
|
804
805
|
});
|
|
805
806
|
else if (y === "flutterwave")
|
|
806
807
|
await Ye({
|
|
807
|
-
public_key:
|
|
808
|
+
public_key: t.publicKey,
|
|
808
809
|
tx_ref: r.id,
|
|
809
|
-
amount:
|
|
810
|
-
currency:
|
|
810
|
+
amount: t.amount,
|
|
811
|
+
currency: t.currency,
|
|
811
812
|
customer: {
|
|
812
|
-
email:
|
|
813
|
-
phone_number: l?.phone ||
|
|
813
|
+
email: t.email || "",
|
|
814
|
+
phone_number: l?.phone || t.phone
|
|
814
815
|
},
|
|
815
|
-
callback: (b) =>
|
|
816
|
+
callback: (b) => _(b),
|
|
816
817
|
onclose: () => {
|
|
817
818
|
}
|
|
818
819
|
});
|
|
819
820
|
else if (y === "monnify")
|
|
820
821
|
await Ge({
|
|
821
|
-
apiKey: r.pspPublicKey ||
|
|
822
|
-
contractCode:
|
|
823
|
-
amount:
|
|
824
|
-
currency:
|
|
822
|
+
apiKey: r.pspPublicKey || t.publicKey,
|
|
823
|
+
contractCode: t.metadata?.contract_code || t.publicKey,
|
|
824
|
+
amount: t.amount,
|
|
825
|
+
currency: t.currency,
|
|
825
826
|
reference: r.reference || r.id,
|
|
826
|
-
customerName:
|
|
827
|
-
customerEmail:
|
|
828
|
-
customerPhone: l?.phone ||
|
|
829
|
-
metadata:
|
|
830
|
-
onSuccess: (b) =>
|
|
827
|
+
customerName: t.metadata?.customer_name || t.email || "",
|
|
828
|
+
customerEmail: t.email || "",
|
|
829
|
+
customerPhone: l?.phone || t.phone,
|
|
830
|
+
metadata: t.metadata,
|
|
831
|
+
onSuccess: (b) => _(b),
|
|
831
832
|
onClose: () => {
|
|
832
833
|
}
|
|
833
834
|
});
|
|
834
835
|
else if (y === "mpesa") {
|
|
835
|
-
const b = `${
|
|
836
|
+
const b = `${t.apiBaseUrl || "https://api.reevit.io"}/v1/payments/${r.id}/mpesa`;
|
|
836
837
|
await Je({
|
|
837
|
-
phoneNumber: l?.phone ||
|
|
838
|
-
amount:
|
|
838
|
+
phoneNumber: l?.phone || t.phone || "",
|
|
839
|
+
amount: t.amount,
|
|
839
840
|
reference: r.reference || r.id,
|
|
840
841
|
description: `Payment ${r.reference || ""}`,
|
|
841
842
|
onInitiated: () => {
|
|
842
843
|
},
|
|
843
|
-
onSuccess: (P) =>
|
|
844
|
+
onSuccess: (P) => _(P),
|
|
844
845
|
onError: (P) => g({ code: "MPESA_ERROR", message: P.message })
|
|
845
846
|
}, b);
|
|
846
847
|
} else g(y === "stripe" ? {
|
|
@@ -856,13 +857,13 @@ const Qe = ["disabled"], Xe = {
|
|
|
856
857
|
message: b instanceof Error ? b.message : "Failed to open payment gateway"
|
|
857
858
|
});
|
|
858
859
|
}
|
|
859
|
-
}, j = w(() => ve(
|
|
860
|
+
}, j = w(() => ve(t.theme || {}));
|
|
860
861
|
N(S, (l) => {
|
|
861
862
|
l ? document.body.style.overflow = "hidden" : document.body.style.overflow = "";
|
|
862
863
|
}), re(() => {
|
|
863
864
|
document.body.style.overflow = "";
|
|
864
865
|
});
|
|
865
|
-
const k = w(() => o.value), O = w(() => s.value), x = w(() =>
|
|
866
|
+
const k = w(() => o.value), O = w(() => s.value), x = w(() => u.value), T = w(() => p.value), z = w(() => m.value);
|
|
866
867
|
return (l, r) => (v(), h("div", {
|
|
867
868
|
class: "reevit-sdk-container",
|
|
868
869
|
style: ee(j.value)
|
|
@@ -889,7 +890,7 @@ const Qe = ["disabled"], Xe = {
|
|
|
889
890
|
onClick: X(M, ["self"])
|
|
890
891
|
}, [
|
|
891
892
|
c("div", {
|
|
892
|
-
class: D(["reevit-modal-content", { "reevit-modal--dark":
|
|
893
|
+
class: D(["reevit-modal-content", { "reevit-modal--dark": t.theme?.darkMode }])
|
|
893
894
|
}, [
|
|
894
895
|
c("button", {
|
|
895
896
|
class: "reevit-modal-close",
|
|
@@ -926,16 +927,16 @@ const Qe = ["disabled"], Xe = {
|
|
|
926
927
|
])) : z.value ? (v(), h(q, { key: 3 }, [
|
|
927
928
|
k.value === "ready" || k.value === "method_selected" || k.value === "processing" ? (v(), W(Re, {
|
|
928
929
|
key: 0,
|
|
929
|
-
methods:
|
|
930
|
+
methods: t.paymentMethods || ["card", "mobile_money"],
|
|
930
931
|
selected: x.value,
|
|
931
|
-
amount:
|
|
932
|
-
currency:
|
|
932
|
+
amount: t.amount,
|
|
933
|
+
currency: t.currency,
|
|
933
934
|
provider: l.psp,
|
|
934
935
|
onSelect: K
|
|
935
936
|
}, null, 8, ["methods", "selected", "amount", "currency", "provider"])) : E("", !0),
|
|
936
937
|
(k.value === "method_selected" || k.value === "processing") && x.value === "mobile_money" ? (v(), h("div", ot, [
|
|
937
938
|
ie(Ae, {
|
|
938
|
-
"initial-phone":
|
|
939
|
+
"initial-phone": t.phone,
|
|
939
940
|
loading: k.value === "processing",
|
|
940
941
|
onSubmit: R
|
|
941
942
|
}, null, 8, ["initial-phone", "loading"])
|
|
@@ -989,5 +990,5 @@ export {
|
|
|
989
990
|
Ge as openMonnifyModal,
|
|
990
991
|
qe as openPaystackPopup,
|
|
991
992
|
be as useReevit,
|
|
992
|
-
|
|
993
|
+
_t as validatePhone
|
|
993
994
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@reevit/vue",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.1",
|
|
4
4
|
"description": "Unified Payment Widget for Vue 3 Applications",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"module": "./dist/index.mjs",
|
|
@@ -44,7 +44,7 @@
|
|
|
44
44
|
"vue": "^3.3.0"
|
|
45
45
|
},
|
|
46
46
|
"dependencies": {
|
|
47
|
-
"@reevit/core": "^0.4.
|
|
47
|
+
"@reevit/core": "^0.4.1",
|
|
48
48
|
"@hubteljs/checkout": "^1.0.4"
|
|
49
49
|
},
|
|
50
50
|
"devDependencies": {
|