@munchi_oy/payments 1.4.9 → 1.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +1 -1
- package/dist/index.mjs +1 -1
- package/dist/src/MunchiPaymentSDK.d.ts +1 -0
- package/dist/src/MunchiPaymentSDK.d.ts.map +1 -1
- package/dist/src/strategies/IPaymentStrategy.d.ts +5 -0
- package/dist/src/strategies/IPaymentStrategy.d.ts.map +1 -1
- package/dist/src/strategies/VivaAppToAppStrategy.d.ts +51 -0
- package/dist/src/strategies/VivaAppToAppStrategy.d.ts.map +1 -0
- package/dist/src/types/payment.d.ts +3 -1
- package/dist/src/types/payment.d.ts.map +1 -1
- package/dist/src/types/sdk.d.ts +13 -0
- package/dist/src/types/sdk.d.ts.map +1 -1
- package/dist/src/utils/parsing.d.ts +3 -0
- package/dist/src/utils/parsing.d.ts.map +1 -0
- package/dist/src/version.d.ts +1 -1
- package/package.json +1 -1
- package/src/MunchiPaymentSDK.ts +101 -14
- package/src/strategies/IPaymentStrategy.ts +6 -0
- package/src/strategies/VivaAppToAppStrategy.ts +810 -0
- package/src/types/payment.ts +3 -1
- package/src/types/sdk.ts +16 -0
- package/src/utils/parsing.ts +21 -0
- package/src/version.ts +1 -1
package/dist/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";var w=Object.defineProperty;var _=Object.getOwnPropertyDescriptor;var D=Object.getOwnPropertyNames;var L=Object.prototype.hasOwnProperty;var F=(u,t)=>{for(var r in t)w(u,r,{get:t[r],enumerable:!0})},M=(u,t,r,e)=>{if(t&&typeof t=="object"||typeof t=="function")for(let n of D(t))!L.call(u,n)&&n!==r&&w(u,n,{get:()=>t[n],enumerable:!(e=_(t,n))||e.enumerable});return u};var x=u=>M(w({},"__esModule",{value:!0}),u);var k={};F(k,{AppReaderStatus:()=>O,MunchiPaymentSDK:()=>b,PaymentInteractionState:()=>g,SdkPaymentStatus:()=>S});module.exports=x(k);var y=require("@munchi_oy/core");var v="1.4.9";var c=class u extends Error{code;rawError;constructor(t,r,e){super(r),this.name="PaymentSDKError",this.code=t,this.rawError=e,Object.setPrototypeOf(this,u.prototype)}};var h=require("@munchi_oy/core");var S=(s=>(s.PENDING="PENDING",s.SUCCESS="SUCCESS",s.APPROVED="APPROVED",s.FAILED="FAILED",s.CANCELLED="CANCELLED",s.ERROR="ERROR",s))(S||{}),g=(o=>(o.IDLE="IDLE",o.CONNECTING="CONNECTING",o.REQUIRES_INPUT="REQUIRES_INPUT",o.PROCESSING="PROCESSING",o.SUCCESS="SUCCESS",o.FAILED="FAILED",o.INTERNAL_ERROR="INTERNAL_ERROR",o.VERIFYING="VERIFYING",o))(g||{});var P=class{constructor(t,r,e){this.messaging=r;this.config=e;this.api=new h.PaymentApi(void 0,"",t)}api;abortController=null;currentRequestId=null;paymentProvider=h.PaymentProviderEnum.Nets;async processPayment(t,r){this.abortController=new AbortController,r("CONNECTING");let e={amount:t.amountCents,businessId:Number(this.config.storeId),referenceId:t.orderRef,currency:t.currency,displayId:t.displayId,options:{allowPinBypass:!0,transactionType:h.TransactionType.Purchase}};try{let{data:n}=await this.api.initiateNetsTerminalTransaction(e),i=n.connectCloudRequestId;if(!i)throw new Error("connectCloudRequestId is missing from response.");if(this.currentRequestId=i,this.abortController.signal.aborted)throw new Error("Aborted");r("REQUIRES_INPUT",{sessionId:i});let s=await this.waitForPaymentCompletion(i,t.orderRef,this.abortController.signal);return this.currentRequestId=null,s}catch(n){throw this.currentRequestId=null,n instanceof c?n:new c("TERMINAL_BUSY","Failed to create Nets Intent",n)}}async waitForPaymentCompletion(t,r,e){let n=`nets.requests.${t}`,i=h.PaymentEventType.StatusChanged;return new Promise((s,d)=>{let o=!1,a=()=>{o=!0,typeof m=="function"&&m(),clearTimeout(R)},l=()=>{a(),d(new c("CANCELLED","Transaction cancelled"))};e.addEventListener("abort",l);let m=this.messaging.subscribe(n,i,f=>{o||(a(),e.removeEventListener("abort",l),s(this.handleSuccess(f)))}),R=setTimeout(async()=>{if(!(o||e.aborted))try{let f=await this.pollOrderStatus(t,r,this.config.storeId,e);s(this.handleSuccess(f))}catch(f){d(new c("TIMEOUT","Payment timed out and polling failed",f))}finally{e.removeEventListener("abort",l),a()}},1e4)})}async pollOrderStatus(t,r,e,n){let o=Date.now()+12e4;for(;Date.now()<o;){if(n.aborted)throw new Error("Aborted");try{let{data:a}=await this.api.getPaymentStatus({businessId:Number(e),orderId:r,provider:this.paymentProvider,referenceId:t});if(n.aborted)throw new Error("Aborted");if(a.status!==h.SimplePaymentStatus.Pending)return a}catch(a){if(a instanceof Error&&a.message==="Aborted")throw a}await new Promise(a=>{let l=()=>{clearTimeout(m),a(void 0)};n.addEventListener("abort",l,{once:!0});let m=setTimeout(()=>{n.removeEventListener("abort",l),a(void 0)},2e3)})}throw new Error("Payment verification timed out.")}async cancelTransaction(t){if(!this.currentRequestId)return!1;let r={requestId:this.currentRequestId,businessId:Number(this.config.storeId)};try{return await this.api.cancelNetsTerminalTransaction(r),this.abortController?.abort(),this.currentRequestId=null,!0}catch{return!1}}async refundTransaction(t,r){try{this.abortController=new AbortController;let e={amount:t.amountCents,businessId:Number(this.config.storeId),currency:t.currency,displayId:this.config.kioskId,referenceId:t.orderRef,options:{allowPinBypass:!0,transactionType:h.TransactionType.ReturnOfGoods}},{data:n}=await this.api.initiateNetsTerminalTransaction(e),i=n.connectCloudRequestId;if(!i)throw new Error("connectCloudRequestId is missing from response.");if(this.currentRequestId=i,this.abortController.signal.aborted)throw new Error("Aborted");r("REQUIRES_INPUT",{sessionId:i});let s=await this.waitForPaymentCompletion(i,t.orderRef,this.abortController.signal);return this.currentRequestId=null,s}catch(e){throw this.currentRequestId=null,e instanceof c||e instanceof c?e:new c("NETWORK_ERROR","Failed to refund Nets transaction",e)}}async verifyFinalStatus(t,r){try{let{data:e}=await this.api.getPaymentStatus({businessId:Number(this.config.storeId),orderId:t.orderRef,provider:this.paymentProvider,referenceId:r});return this.handleSuccess(e)}catch(e){throw new c("NETWORK_ERROR","Failed to verify final Nets status",e)}}handleSuccess(t){let r=t.status===h.SimplePaymentStatus.Success,e={success:r,status:r?"SUCCESS":"FAILED",orderId:t.orderId,transaction:t.transaction};return t.transactionId&&(e.transactionId=t.transactionId),t.error?.code&&(e.errorCode=t.error.code),t.error?.message&&(e.errorMessage=t.error.message),e}abort(){this.abortController?.abort()}};var I=require("@munchi_oy/core");var T=class{constructor(t,r,e){this.messaging=r;this.config=e;this.api=new I.PaymentApi(void 0,"",t)}api;abortController=null;currentSessionId=null;paymentProvider=I.PaymentProviderEnum.Viva;async processPayment(t,r){this.abortController=new AbortController,r("CONNECTING");let e={amount:t.amountCents,referenceId:t.orderRef,businessId:parseInt(this.config.storeId),currency:t.currency,displayId:t.displayId,showReceipt:!0,showTransactionResult:!0};try{let{data:n}=await this.api.initiateTerminalTransaction(e);if(this.currentSessionId=n.sessionId,this.abortController.signal.aborted)throw new Error("Aborted");r("REQUIRES_INPUT",{sessionId:n.sessionId});let i=await this.waitForPaymentCompletion(n.sessionId,t.orderRef,this.abortController.signal);return this.currentSessionId=null,i}catch(n){throw this.currentSessionId=null,n instanceof c?n:new c("NETWORK_ERROR","Failed to create Viva Intent",n)}}async waitForPaymentCompletion(t,r,e){let i=`viva.${this.config.channel.toLowerCase()}.requests.${t}`,s="payment:status-changed";return new Promise((d,o)=>{let a=!1,l=()=>{a=!0,typeof R=="function"&&R(),clearTimeout(f)},m=()=>{l(),o(new Error("Aborted"))};e.addEventListener("abort",m);let R=this.messaging.subscribe(i,s,E=>{a||E.status!==I.SimplePaymentStatus.Pending&&(l(),e.removeEventListener("abort",m),d(this.handleSuccess(E)))}),f=setTimeout(async()=>{if(!(a||e.aborted))try{let E=await this.pollOrderStatus(t,r,this.config.storeId,e);d(this.handleSuccess(E))}catch(E){o(new c("TIMEOUT","Payment timed out and polling failed",E))}finally{e.removeEventListener("abort",m),l()}},1e4)})}async pollOrderStatus(t,r,e,n){let o=Date.now()+12e4;for(;Date.now()<o;){if(n.aborted)throw new Error("Aborted");try{let{data:a}=await this.api.getPaymentStatus({businessId:Number(e),orderId:r,provider:this.paymentProvider,referenceId:t});if(n.aborted)throw new Error("Aborted");if(a.status!==I.SimplePaymentStatus.Pending)return a}catch(a){if(a instanceof Error&&a.message==="Aborted")throw a}await new Promise(a=>{let l=()=>{clearTimeout(m),a(void 0)};n.addEventListener("abort",l,{once:!0});let m=setTimeout(()=>{n.removeEventListener("abort",l),a(void 0)},2e3)})}throw new Error("Payment verification timed out.")}handleSuccess(t){let r=t.status===I.SimplePaymentStatus.Success,e={success:r,status:r?"SUCCESS":"FAILED",orderId:t.orderId,errorCode:t.error?.code||(r?"":I.PaymentFailureCode.SystemUnknown),errorMessage:t.error?.message||(r?"":"Transaction failed without error details")};return t.transactionId&&(e.transactionId=t.transactionId),t.error?.referenceError&&(e.errorReference=t.error.referenceError),t.transaction&&(e.transaction=t.transaction),e}async cancelTransaction(t){if(!this.currentSessionId)return!1;try{let r=this.currentSessionId;return this.currentSessionId=null,await this.api.cancelVivaTransactionV2({cashRegisterId:this.config.storeId,sessionId:r}),this.abortController?.abort(),!0}catch(r){throw this.currentSessionId=null,new c("NETWORK_ERROR","Failed to cancel Viva transaction",r)}}async verifyFinalStatus(t,r){try{let{data:e}=await this.api.getPaymentStatus({businessId:Number(this.config.storeId),orderId:t.orderRef,provider:this.paymentProvider,referenceId:r}),n=e.status===I.SimplePaymentStatus.Success,i=e.status===I.SimplePaymentStatus.Pending,s={success:n,status:n?"SUCCESS":i?"PENDING":"FAILED",orderId:e.orderId,errorCode:e.error?.code||(n||i?"":I.PaymentFailureCode.SystemUnknown),errorMessage:e.error?.message||(n||i?"":"Transaction failed without error details")};return e.transactionId&&(s.transactionId=e.transactionId),e.error?.referenceError&&(s.errorReference=e.error.referenceError),e.transaction&&(s.transaction=e.transaction),s}catch(e){throw new c("NETWORK_ERROR","Failed to verify final transaction status",e)}}async refundTransaction(t,r){try{let e={amount:t.amountCents,businessId:Number(this.config.storeId),displayId:this.config.kioskId,currency:t.currency,orderReferenceId:t.orderRef,referenceId:t.originalTransactionId},{data:n}=await this.api.refundSingleVivaTransaction(e),i=n.success;return{success:i,status:i?"SUCCESS":"FAILED",orderId:t.orderRef,transactionId:n.sessionId}}catch(e){throw new c("NETWORK_ERROR","Failed to refund Viva transaction",e)}}abort(){this.abortController?.abort()}};var p=require("@munchi_oy/core"),A=require("axios");var C=class{constructor(t,r,e){this.messaging=r;this.config=e;this.paymentApi=new p.PaymentApi(void 0,"",t),this.worldlineApi=new p.WorldlineApi(void 0,"",t)}paymentApi;worldlineApi;abortController=null;currentOperationId=null;paymentProvider=p.PaymentProviderEnum.Worldline;async processPayment(t,r){this.abortController=new AbortController,r("CONNECTING");let e={amount:t.amountCents,businessId:Number(this.config.storeId),currency:t.currency,displayId:t.displayId,referenceId:t.orderRef,showReceipt:!0,showTransactionResult:!0,...t.options&&"tipAmount"in t.options&&typeof t.options.tipAmount=="number"?{tipAmount:t.options.tipAmount}:{}};try{let n=await this.worldlineApi.createPayment(e),i=this.extractOperationId(n.data);if(this.currentOperationId=i,this.abortController.signal.aborted)throw new Error("Aborted");r("REQUIRES_INPUT",{sessionId:i});let s=await this.waitForPaymentCompletion(i,t.orderRef,p.PaymentEventType.StatusChanged,this.abortController.signal);return this.currentOperationId=null,s}catch(n){throw this.currentOperationId=null,n instanceof c?n:this.mapWorldlineRequestError(n,"Failed to create Worldline payment")}}async cancelTransaction(t){if(!this.currentOperationId)return!1;let r={businessId:Number(this.config.storeId),targetOperationId:this.currentOperationId};try{return await this.worldlineApi.cancelPayment(r),!0}catch(e){throw this.mapWorldlineRequestError(e,"Failed to cancel Worldline transaction")}}async refundTransaction(t,r){this.abortController=new AbortController,r("CONNECTING");let e={amount:t.amountCents,businessId:Number(this.config.storeId),currency:t.currency,displayId:t.displayId,orderReferenceId:t.orderRef,referenceId:t.originalTransactionId};try{let n=await this.worldlineApi.createRefund(e),i=this.extractOperationId(n.data);if(this.currentOperationId=i,this.abortController.signal.aborted)throw new Error("Aborted");r("REQUIRES_INPUT",{sessionId:i});let s=await this.waitForPaymentCompletion(i,t.orderRef,p.PaymentEventType.RefundStatusChanged,this.abortController.signal);return this.currentOperationId=null,s}catch(n){throw this.currentOperationId=null,n instanceof c?n:this.mapWorldlineRequestError(n,"Failed to refund Worldline transaction")}}async verifyFinalStatus(t,r){try{let{data:e}=await this.paymentApi.getPaymentStatus({businessId:Number(this.config.storeId),orderId:t.orderRef,provider:this.paymentProvider,referenceId:r});return this.handlePaymentStatus(e)}catch(e){throw this.mapWorldlineRequestError(e,"Failed to verify final Worldline status")}}abort(){this.abortController?.abort()}async waitForPaymentCompletion(t,r,e,n){let i=`worldline.requests.${t}`;return new Promise((s,d)=>{let o=!1,a=()=>{o=!0,typeof m=="function"&&m(),clearTimeout(R)},l=()=>{a(),d(new c("CANCELLED","Transaction cancelled"))};n.addEventListener("abort",l);let m=this.messaging.subscribe(i,e,f=>{o||f.status===p.SimplePaymentStatus.Pending||(a(),n.removeEventListener("abort",l),s(this.handlePaymentStatus(f)))}),R=setTimeout(async()=>{if(!(o||n.aborted))try{let f=await this.pollOrderStatus(t,r,this.config.storeId,n);s(this.handlePaymentStatus(f))}catch(f){d(new c("TIMEOUT","Payment timed out and polling failed",f))}finally{n.removeEventListener("abort",l),a()}},1e4)})}async pollOrderStatus(t,r,e,n){let d=Date.now()+12e4;for(;Date.now()<d;){if(n.aborted)throw new Error("Aborted");try{let{data:o}=await this.paymentApi.getPaymentStatus({businessId:Number(e),orderId:r,provider:this.paymentProvider,referenceId:t});if(n.aborted)throw new Error("Aborted");if(o.status!==p.SimplePaymentStatus.Pending)return o}catch(o){if(o instanceof Error&&o.message==="Aborted")throw o}await new Promise(o=>{let a=()=>{clearTimeout(l),o(void 0)};n.addEventListener("abort",a,{once:!0});let l=setTimeout(()=>{n.removeEventListener("abort",a),o(void 0)},2e3)})}throw new Error("Payment verification timed out.")}handlePaymentStatus(t){let r=t.status===p.SimplePaymentStatus.Success,e=t.status===p.SimplePaymentStatus.Pending,n={success:r,status:r?"SUCCESS":e?"PENDING":"FAILED",orderId:t.orderId,errorCode:t.error?.code||(r||e?"":p.PaymentFailureCode.SystemUnknown),errorMessage:t.error?.message||(r||e?"":"Transaction failed without error details")};return t.transactionId&&(n.transactionId=t.transactionId),t.error?.referenceError&&(n.errorReference=t.error.referenceError),t.transaction&&(n.transaction=t.transaction),n}extractOperationId(t){let r=typeof t=="object"&&t!==null&&"operationId"in t&&typeof t.operationId=="string"?t.operationId:null;if(!r)throw new Error("operationId is missing from response.");return r}mapWorldlineRequestError(t,r){if((0,A.isAxiosError)(t)){if(t.response?.status===400||t.response?.status===409)return new c("TERMINAL_BUSY",r,t);if(t.response?.status===404)return new c("TERMINAL_OFFLINE",r,t)}return new c("NETWORK_ERROR",r,t)}};var b=class u{strategy;axios;messaging;timeoutMs;logger;_currentState="IDLE";_listeners=[];_cancellationIntent=!1;_currentSessionId;_autoResetTimer;autoResetOptions;static TERMINAL_STATES=["SUCCESS","FAILED","INTERNAL_ERROR"];static RESTING_STATES=["IDLE",...u.TERMINAL_STATES];constructor(t,r,e,n={},i){this.axios=t,this.messaging=r,this.logger=n.logger,this.timeoutMs=n.timeoutMs||3e4,this.autoResetOptions=n.autoResetOnPaymentComplete,this.strategy=i??this.resolveStrategy(e)}get version(){return v}get currentState(){return this._currentState}generateErrorResult(t,r,e){return{success:!1,status:"ERROR",errorCode:this.normalizeErrorCode(r),errorMessage:e,orderId:t}}normalizeErrorCode(t){return t?t.includes(".")?t:{CANCELLED:y.PaymentFailureCode.PaymentCancelledByUser,DECLINED:y.PaymentFailureCode.PaymentDeclined,TERMINAL_BUSY:y.PaymentFailureCode.TerminalBusy,TERMINAL_OFFLINE:y.PaymentFailureCode.TerminalOffline,TIMEOUT:y.PaymentFailureCode.TerminalTimeout,NETWORK_ERROR:y.PaymentFailureCode.SystemProviderError,STRATEGY_ERROR:y.PaymentFailureCode.SystemProviderError,MISSING_CONFIG:y.PaymentFailureCode.SystemUnknown,INVALID_AMOUNT:y.PaymentFailureCode.SystemUnknown,UNKNOWN:y.PaymentFailureCode.SystemUnknown}[t]??y.PaymentFailureCode.SystemUnknown:y.PaymentFailureCode.SystemUnknown}subscribe=t=>(this._listeners.push(t),t(this._currentState),()=>{this._listeners=this._listeners.filter(r=>r!==t)});transitionTo(t){if(this._currentState===t)return;if(t==="IDLE"){this.cancelAutoReset(),this._currentState=t,this._listeners.forEach(e=>e(t));return}if(u.TERMINAL_STATES.includes(this._currentState)){let e=`Invalid State Transition: Attempted to move from terminal state ${this._currentState} to ${t}`;throw this.logger?.error(e),this._currentState!=="INTERNAL_ERROR"&&(this._currentState="INTERNAL_ERROR",this._listeners.forEach(n=>n(this._currentState))),new c("UNKNOWN",e)}this._currentState=t,u.TERMINAL_STATES.includes(t)&&this.scheduleAutoReset(t),this._listeners.forEach(e=>e(t))}_resetScheduledAt;get nextAutoResetAt(){return this._resetScheduledAt}cancelAutoReset(){this._autoResetTimer&&(clearTimeout(this._autoResetTimer),this._autoResetTimer=void 0),this._resetScheduledAt=void 0}scheduleAutoReset(t){if(!this.autoResetOptions)return;let e=t==="SUCCESS"?this.autoResetOptions.successDelayMs??5e3:this.autoResetOptions.failureDelayMs??5e3;this.logger?.info(`Scheduling auto-reset to IDLE in ${e}ms`),this._resetScheduledAt=Date.now()+e,this._autoResetTimer=setTimeout(()=>{this.logger?.info("Auto-reset triggered"),this.reset()},e)}resolveStrategy(t){switch(t.provider){case y.PaymentProvider.Nets:return new P(this.axios,this.messaging,t);case y.PaymentProvider.Worldline:return new C(this.axios,this.messaging,t);default:return new T(this.axios,this.messaging,t)}}initiateTransaction=async(t,r)=>{let e=r??{},n=t.orderRef;if(!u.RESTING_STATES.includes(this._currentState))return this.generateErrorResult(t.orderRef,"UNKNOWN","A transaction is already in progress");let s=Date.now();if(this._cancellationIntent=!1,this._currentSessionId=void 0,this.transitionTo("IDLE"),t.amountCents<=0)return this.generateErrorResult(t.orderRef,"INVALID_AMOUNT","Amount must be greater than 0");try{let d=(m,R)=>{R?.sessionId&&(this._currentSessionId=R.sessionId),m!=="FAILED"&&(this.transitionTo(m),this.fireStateCallback(m,e,n))},o=this.strategy.processPayment(t,d),a=new Promise((m,R)=>{setTimeout(()=>{R(new c("TIMEOUT","Transaction timed out"))},this.timeoutMs)}),l=await Promise.race([o,a]);if(l.success)this.transitionTo("SUCCESS"),this.safeFireCallback(()=>e.onSuccess?.(l));else{if(this._cancellationIntent)return await this.handleTransactionError(t,new Error("Aborted after resolution"),e);this.transitionTo("FAILED"),this.safeFireCallback(()=>e.onError?.(l))}return this.logger?.info("Transaction completed successfully",{orderId:t.orderRef,durationMs:Date.now()-s}),l}catch(d){return this.logger?.warn("Transaction interrupted. Handling final status...",{error:d}),await this.handleTransactionError(t,d,e)}};async handleTransactionError(t,r,e={}){let n=r instanceof c&&r.code==="TIMEOUT";if(!this._cancellationIntent&&!n&&(this.transitionTo("VERIFYING"),this.safeFireCallback(()=>e.onVerifying?.({orderRef:t.orderRef,refPaymentId:this._currentSessionId}))),this._cancellationIntent){try{if(this._currentSessionId){let s=await this.verifyWithRetry(t,this._currentSessionId);if(s.success)return this.transitionTo("SUCCESS"),this.safeFireCallback(()=>e.onSuccess?.(s)),s}}catch(s){this.logger?.warn("Final status verification failed during cancellation",{err:s})}return this.transitionTo("FAILED"),this.safeFireCallback(()=>e.onCancelled?.({orderRef:t.orderRef,refPaymentId:this._currentSessionId})),{success:!1,status:"CANCELLED",errorCode:this.normalizeErrorCode("CANCELLED"),orderId:t.orderRef,...this._currentSessionId?{transactionId:this._currentSessionId}:{}}}let i;if(this.strategy.abort(),this._currentSessionId)try{let s=await this.verifyWithRetry(t,this._currentSessionId);if(s.success)return this.transitionTo("SUCCESS"),this.safeFireCallback(()=>e.onSuccess?.(s)),s;i=s}catch(s){this.logger?.warn("Failed to get detailed error from verifyFinalStatus",{verifyErr:s}),i=this.buildErrorResultFromException(t.orderRef,s)}else i=this.buildErrorResultFromException(t.orderRef,r);return this.transitionTo("FAILED"),this.safeFireCallback(()=>e.onError?.(i)),i}static VERIFY_TIMEOUT_MS=1e4;static VERIFY_MAX_RETRIES=3;static VERIFY_RETRY_DELAY_MS=1500;async verifyWithRetry(t,r){let e,n=!0;for(let d=1;d<=u.VERIFY_MAX_RETRIES;d++)try{let o=await Promise.race([this.strategy.verifyFinalStatus(t,r),new Promise((a,l)=>setTimeout(()=>l(new Error("Verify timed out")),u.VERIFY_TIMEOUT_MS))]);if(o.status==="PENDING"){e=new Error("Verify returned pending status"),this.logger?.warn(`verifyFinalStatus attempt ${d}/${u.VERIFY_MAX_RETRIES} returned pending status`),d<u.VERIFY_MAX_RETRIES&&await new Promise(a=>setTimeout(a,u.VERIFY_RETRY_DELAY_MS));continue}return o}catch(o){e=o,o instanceof Error&&o.message==="Verify timed out"||(n=!1),this.logger?.warn(`verifyFinalStatus attempt ${d}/${u.VERIFY_MAX_RETRIES} failed`,{err:o}),d<u.VERIFY_MAX_RETRIES&&await new Promise(l=>setTimeout(l,u.VERIFY_RETRY_DELAY_MS))}let i=e instanceof Error?e.message:"Verify retries exhausted",s=n?y.PaymentFailureCode.PaymentTimeout:y.PaymentFailureCode.PaymentUnknown;throw new c(s,i)}buildErrorResultFromException(t,r){return r instanceof c?this.generateErrorResult(t,r.code,r.message):this.generateErrorResult(t,"UNKNOWN",r instanceof Error?r.message:"Unknown fatal error")}fireStateCallback(t,r,e){let n={orderRef:e,refPaymentId:this._currentSessionId};switch(t){case"CONNECTING":this.safeFireCallback(()=>r.onConnecting?.(n));break;case"REQUIRES_INPUT":this.safeFireCallback(()=>r.onRequiresInput?.(n));break;case"PROCESSING":this.safeFireCallback(()=>r.onProcessing?.(n));break}}safeFireCallback(t){try{t()}catch(r){this.logger?.warn("Callback execution failed",{error:r})}}cancel=async()=>{if(this.logger?.info("Attempting cancellation"),u.TERMINAL_STATES.includes(this._currentState))return this.logger?.warn("Cannot cancel: Transaction already in terminal state",{state:this._currentState}),!1;if(!this._currentSessionId&&this._currentState==="IDLE")return this.logger?.warn("Cannot cancel: No active session to cancel",{state:this._currentState}),!1;this._cancellationIntent=!0,this.transitionTo("VERIFYING");try{return await this.strategy.cancelTransaction(r=>this.transitionTo(r))}catch(t){return this.logger?.error("Cancellation command failed",t),!1}};reset=()=>{u.TERMINAL_STATES.includes(this._currentState)&&(this._currentSessionId=void 0,this._cancellationIntent=!1,this.transitionTo("IDLE"))};refund=async(t,r)=>{let e=r??{};if(this.logger?.info("Initiating refund",{orderRef:t.orderRef}),this._currentSessionId=void 0,!u.RESTING_STATES.includes(this._currentState))return this.generateErrorResult(t.orderRef,"UNKNOWN","A transaction is already in progress");this.transitionTo("IDLE");try{let i=(d,o)=>{o?.sessionId&&(this._currentSessionId=o.sessionId),d!=="FAILED"&&(this.transitionTo(d),this.fireStateCallback(d,e,t.orderRef))},s=await this.strategy.refundTransaction(t,i);return s.success?(this.transitionTo("SUCCESS"),this.safeFireCallback(()=>e.onSuccess?.(s))):(this.transitionTo("FAILED"),this.safeFireCallback(()=>e.onError?.(s))),this.logger?.info("Refund completed",{success:s.success,orderRef:t.orderRef}),s}catch(i){this.logger?.error("Refund failed",i),this.transitionTo("FAILED");let s=this.generateErrorResult(t.orderRef,"UNKNOWN",i instanceof Error?i.message:"Refund failed");return this.safeFireCallback(()=>e.onError?.(s)),s}}};var O=(n=>(n.CONNECTING="CONNECTING",n.CONNECTED="CONNECTED",n.OFFLINE="OFFLINE",n.DISCONNECTED="DISCONNECTED",n))(O||{});0&&(module.exports={AppReaderStatus,MunchiPaymentSDK,PaymentInteractionState,SdkPaymentStatus});
|
|
1
|
+
"use strict";var N=Object.defineProperty;var M=Object.getOwnPropertyDescriptor;var U=Object.getOwnPropertyNames;var k=Object.prototype.hasOwnProperty;var V=(u,e)=>{for(var r in e)N(u,r,{get:e[r],enumerable:!0})},W=(u,e,r,t)=>{if(e&&typeof e=="object"||typeof e=="function")for(let n of U(e))!k.call(u,n)&&n!==r&&N(u,n,{get:()=>e[n],enumerable:!(t=M(e,n))||t.enumerable});return u};var G=u=>W(N({},"__esModule",{value:!0}),u);var J={};V(J,{AppReaderStatus:()=>x,MunchiPaymentSDK:()=>w,PaymentInteractionState:()=>C,SdkPaymentStatus:()=>T});module.exports=G(J);var y=require("@munchi_oy/core");var D="1.5.0";var l=class u extends Error{code;rawError;constructor(e,r,t){super(r),this.name="PaymentSDKError",this.code=e,this.rawError=t,Object.setPrototypeOf(this,u.prototype)}};var g=require("@munchi_oy/core");var T=(s=>(s.PENDING="PENDING",s.SUCCESS="SUCCESS",s.APPROVED="APPROVED",s.FAILED="FAILED",s.CANCELLED="CANCELLED",s.ERROR="ERROR",s))(T||{}),C=(o=>(o.IDLE="IDLE",o.CONNECTING="CONNECTING",o.REQUIRES_INPUT="REQUIRES_INPUT",o.PROCESSING="PROCESSING",o.SUCCESS="SUCCESS",o.FAILED="FAILED",o.INTERNAL_ERROR="INTERNAL_ERROR",o.VERIFYING="VERIFYING",o))(C||{});var S=class{constructor(e,r,t){this.messaging=r;this.config=t;this.api=new g.PaymentApi(void 0,"",e)}api;abortController=null;currentRequestId=null;paymentProvider=g.PaymentProviderEnum.Nets;async processPayment(e,r){this.abortController=new AbortController,r("CONNECTING");let t={amount:e.amountCents,businessId:Number(this.config.storeId),referenceId:e.orderRef,currency:e.currency,displayId:e.displayId,options:{allowPinBypass:!0,transactionType:g.TransactionType.Purchase}};try{let{data:n}=await this.api.initiateNetsTerminalTransaction(t),i=n.connectCloudRequestId;if(!i)throw new Error("connectCloudRequestId is missing from response.");if(this.currentRequestId=i,this.abortController.signal.aborted)throw new Error("Aborted");r("REQUIRES_INPUT",{sessionId:i});let s=await this.waitForPaymentCompletion(i,e.orderRef,this.abortController.signal);return this.currentRequestId=null,s}catch(n){throw this.currentRequestId=null,n instanceof l?n:new l("TERMINAL_BUSY","Failed to create Nets Intent",n)}}async waitForPaymentCompletion(e,r,t){let n=`nets.requests.${e}`,i=g.PaymentEventType.StatusChanged;return new Promise((s,a)=>{let o=!1,c=()=>{o=!0,typeof m=="function"&&m(),clearTimeout(f)},d=()=>{c(),a(new l("CANCELLED","Transaction cancelled"))};t.addEventListener("abort",d);let m=this.messaging.subscribe(n,i,I=>{o||(c(),t.removeEventListener("abort",d),s(this.handleSuccess(I)))}),f=setTimeout(async()=>{if(!(o||t.aborted))try{let I=await this.pollOrderStatus(e,r,this.config.storeId,t);s(this.handleSuccess(I))}catch(I){a(new l("TIMEOUT","Payment timed out and polling failed",I))}finally{t.removeEventListener("abort",d),c()}},1e4)})}async pollOrderStatus(e,r,t,n){let o=Date.now()+12e4;for(;Date.now()<o;){if(n.aborted)throw new Error("Aborted");try{let{data:c}=await this.api.getPaymentStatus({businessId:Number(t),orderId:r,provider:this.paymentProvider,referenceId:e});if(n.aborted)throw new Error("Aborted");if(c.status!==g.SimplePaymentStatus.Pending)return c}catch(c){if(c instanceof Error&&c.message==="Aborted")throw c}await new Promise(c=>{let d=()=>{clearTimeout(m),c(void 0)};n.addEventListener("abort",d,{once:!0});let m=setTimeout(()=>{n.removeEventListener("abort",d),c(void 0)},2e3)})}throw new Error("Payment verification timed out.")}async cancelTransaction(e){if(!this.currentRequestId)return!1;let r={requestId:this.currentRequestId,businessId:Number(this.config.storeId)};try{return await this.api.cancelNetsTerminalTransaction(r),this.abortController?.abort(),this.currentRequestId=null,!0}catch{return!1}}async refundTransaction(e,r){try{this.abortController=new AbortController;let t={amount:e.amountCents,businessId:Number(this.config.storeId),currency:e.currency,displayId:this.config.kioskId,referenceId:e.orderRef,options:{allowPinBypass:!0,transactionType:g.TransactionType.ReturnOfGoods}},{data:n}=await this.api.initiateNetsTerminalTransaction(t),i=n.connectCloudRequestId;if(!i)throw new Error("connectCloudRequestId is missing from response.");if(this.currentRequestId=i,this.abortController.signal.aborted)throw new Error("Aborted");r("REQUIRES_INPUT",{sessionId:i});let s=await this.waitForPaymentCompletion(i,e.orderRef,this.abortController.signal);return this.currentRequestId=null,s}catch(t){throw this.currentRequestId=null,t instanceof l||t instanceof l?t:new l("NETWORK_ERROR","Failed to refund Nets transaction",t)}}async verifyFinalStatus(e,r){try{let{data:t}=await this.api.getPaymentStatus({businessId:Number(this.config.storeId),orderId:e.orderRef,provider:this.paymentProvider,referenceId:r});return this.handleSuccess(t)}catch(t){throw new l("NETWORK_ERROR","Failed to verify final Nets status",t)}}handleSuccess(e){let r=e.status===g.SimplePaymentStatus.Success,t={success:r,status:r?"SUCCESS":"FAILED",orderId:e.orderId,transaction:e.transaction};return e.transactionId&&(t.transactionId=e.transactionId),e.error?.code&&(t.errorCode=e.error.code),e.error?.message&&(t.errorMessage=e.error.message),t}abort(){this.abortController?.abort()}};var p=require("@munchi_oy/core");var O=u=>{if(!u)return 0;let e=Number.parseInt(u,10);return Number.isFinite(e)?e:0},_=u=>{if(!u)return new Date().toISOString();let e=new Date(u);return Number.isNaN(e.getTime())?new Date().toISOString():e.toISOString()};var Y="vivapayclient://pay/v1",B="abort",$="cancel",j="sale",L="transactionDetails",Q=4e3,X="534287",z="493591",H=["CREDIT","PREPAID","CORPORATE"],v=class{constructor(e,r,t,n){this.config=t;this.appToAppConfig=n;this.api=new p.VivaApi(void 0,"",e),this.paymentApi=new p.PaymentApi(void 0,"",e),this.paymentApiWithReference=this.paymentApi}api;paymentApi;abortController=null;currentClientTransactionId=null;currentIsvClientTransactionId=null;currentCurrency=null;currentOrderRef=null;currentSourceTerminalId=null;latestResult=null;paymentApiWithReference;wasCancelled=!1;getExecutionMode(){return"callback_driven"}async processPayment(e,r){if(!this.appToAppConfig.enabled)throw new l("STRATEGY_ERROR","Viva app-to-app is not enabled");r("CONNECTING");try{let{data:t}=await this.api.createVivaAppToAppPayment(this.buildCreatePaymentPayload(e));return await this.runAction(j,this.buildLaunchParams(t),e,r)}catch(t){throw new l("NETWORK_ERROR","Failed to create Viva app-to-app payment",t)}}async cancelTransaction(e){if(!this.currentClientTransactionId)return!1;let r=await this.lookupTransactionDetails();if(r)return this.latestResult=r,this.wasCancelled=r.status==="CANCELLED",this.abortController?.abort(),!0;try{await this.appToAppConfig.adapter.openUrl(this.buildActionUrl(B,{}))}catch(t){throw this.abortController?.abort(),new l("NETWORK_ERROR","Failed to launch Viva abort flow",t)}return this.wasCancelled=!0,this.abortController?.abort(),!0}async refundTransaction(e,r){r("CONNECTING");let t=await this.fetchPaymentReference(e),n=this.buildRefundLaunchParams(e,t);return this.runAction($,n,e,r)}async verifyFinalStatus(e,r){return this.latestResult?this.latestResult:this.wasCancelled?{success:!1,status:"CANCELLED",orderId:this.currentOrderRef??r,errorCode:p.PaymentFailureCode.PaymentCancelledByUser,errorMessage:"Transaction was cancelled",transactionId:r}:{success:!1,status:"PENDING",orderId:this.currentOrderRef??r,transactionId:r}}abort(){this.abortController?.abort()}async runAction(e,r,t,n){if(!this.appToAppConfig.enabled)throw new l("STRATEGY_ERROR","Viva app-to-app is not enabled");this.abortController=new AbortController,this.latestResult=null,this.wasCancelled=!1,this.currentCurrency=t.currency,this.currentOrderRef=t.orderRef,this.currentSourceTerminalId=r.sourceTerminalId??r.tid??null,this.currentClientTransactionId=r.clientTransactionId??null,this.currentIsvClientTransactionId=r.ISV_clientTransactionId??null;let i=this.currentClientTransactionId?{sessionId:this.currentClientTransactionId}:void 0;return new Promise((s,a)=>{let o=(m,f)=>{m?.(),this.abortController?.signal.removeEventListener("abort",f)},c=()=>{o(d,c),a(new Error("Aborted"))},d=this.appToAppConfig.adapter.subscribe(m=>{if(this.abortController?.signal.aborted)return;let f=this.parseCallbackUrl(m);f&&this.matchesKnownTransactionId(f.rawParams)&&(this.latestResult=f.result,this.wasCancelled=f.result.status==="CANCELLED",this.currentClientTransactionId=null,this.currentIsvClientTransactionId=null,this.currentCurrency=null,this.currentOrderRef=null,this.currentSourceTerminalId=null,o(d,c),s(f.result))});this.abortController?.signal.addEventListener("abort",c),n("REQUIRES_INPUT",i),this.appToAppConfig.adapter.openUrl(this.buildActionUrl(e,r)).then(()=>{this.abortController?.signal.aborted}).catch(m=>{o(d,c),this.currentClientTransactionId=null,this.currentIsvClientTransactionId=null,this.currentCurrency=null,this.currentOrderRef=null,this.currentSourceTerminalId=null,a(new l("NETWORK_ERROR","Failed to launch Viva app",m))})})}buildCreatePaymentPayload(e){let r=e.options??{},t={amount:e.amountCents,referenceId:e.orderRef,businessId:Number(this.config.storeId),currency:e.currency,displayId:e.displayId,showReceipt:!0,showTransactionResult:!0};return r.tipAmount!==void 0&&(t.tipAmount=r.tipAmount),t}buildLaunchParams(e){let r={};return Object.entries(e).forEach(([t,n])=>{n!==void 0&&(r[t]=String(n))}),r}buildRefundLaunchParams(e,r){let t=e.options??{},n=r?.originalTransactionId?.trim()||e.originalTransactionId.trim(),i={amount:String(e.amountCents),clientTransactionId:n,show_receipt:"true",show_transaction_result:"true"};if(t.sourceCode&&(i.sourceCode=t.sourceCode),r?.referenceCode&&(i.orderCode=r.referenceCode),r?.shortReferenceCode&&(i.shortOrderCode=r.shortReferenceCode),r?.receiptNumber&&(i.referenceNumber=r.receiptNumber),r?.terminalId&&(i.tid=r.terminalId),r?.referenceCode||r?.shortReferenceCode||r?.receiptNumber)return i;let s=n;return/^\d+$/.test(s)&&(s.length===16?i.orderCode=s:s.length===10?i.shortOrderCode=s:i.referenceNumber=s),i}async fetchPaymentReference(e){try{let{data:r}=await this.paymentApiWithReference.getPaymentReference({orderId:e.orderRef,provider:p.PaymentProvider.Viva,transactionId:e.originalTransactionId});return this.extractPaymentReferenceContext(r)}catch{return}}extractPaymentReferenceContext(e){if(!e)return;let r=e.references;if(!r||typeof r!="object"||Array.isArray(r))return{originalTransactionId:e.originalTransactionId};let t=r,n={originalTransactionId:this.readReferenceValue(t.originalTransactionId)??this.readReferenceValue(t.clientTransactionId)??e.originalTransactionId},i=this.readReferenceValue(t.receiptNumber)??this.readReferenceValue(t.referenceNumber),s=this.readReferenceValue(t.referenceCode)??this.readReferenceValue(t.orderCode),a=this.readReferenceValue(t.shortReferenceCode)??this.readReferenceValue(t.shortOrderCode),o=this.readReferenceValue(t.terminalId)??this.readReferenceValue(t.tid);return i&&(n.receiptNumber=i),s&&(n.referenceCode=s),a&&(n.shortReferenceCode=a),o&&(n.terminalId=o),n}readReferenceValue(e){if(typeof e!="string")return;let r=e.trim();return r.length>0?r:void 0}buildActionUrl(e,r){let t=new URLSearchParams({action:e,appId:this.appToAppConfig.appId,callback:this.appToAppConfig.callbackUrl});return Object.entries(r).forEach(([n,i])=>{t.set(n,i)}),`${Y}?${t.toString()}`}parseCallbackUrl(e){if(!this.matchesCallbackBase(e))return null;let r=new URL(e),t=Object.fromEntries(r.searchParams.entries()),n=this.isSuccessfulCallback(t),i=this.isCancelledCallback(t),s=this.resolveFailureCode(t,i),a={success:n,status:n?"SUCCESS":i?"CANCELLED":"FAILED",orderId:this.currentOrderRef??t.clientTransactionId??"unknown",errorCode:n?"":s,errorMessage:n?"":t.message??"Transaction failed without error details"};n&&(a.transaction=this.mapCallbackToTransaction(t));let o=t.transactionId??t.orderCode??t.clientTransactionId,c=t.errorCode??this.extractErrorReferenceFromMessage(t.message)??t.referenceNumber??t.tid??t.rrn;return o&&(a.transactionId=o),c&&(a.errorReference=c),{rawParams:t,result:a}}matchesCallbackBase(e){let r=new URL(e),t=new URL(this.appToAppConfig.callbackUrl);return r.protocol===t.protocol&&r.hostname===t.hostname&&r.pathname===t.pathname}matchesKnownTransactionId(e){let r=[this.currentClientTransactionId,this.currentIsvClientTransactionId].filter(n=>!!n);if(r.length===0)return!0;let t=[e.clientTransactionId,e.ISV_clientTransactionId].filter(n=>!!n);return t.length===0?!0:t.some(n=>r.includes(n))}resolveFailureCode(e,r){if(r)return p.PaymentFailureCode.PaymentCancelledByUser;let t=e.errorCode;if(t?.includes("."))return t;if(this.isTransactionDetailsAction(e)&&(e.transactionType??"").toLowerCase().includes("abort"))return p.PaymentFailureCode.SystemUnknown;let n=(e.message??"").toLowerCase(),i=(e.status??"").toLowerCase();return n.includes("declined")||i==="declined"||i==="fail"||i==="failed"?p.PaymentFailureCode.PaymentDeclined:p.PaymentFailureCode.SystemUnknown}isSuccessfulCallback(e){let r=(e.status??"").toLowerCase();return this.isTransactionDetailsAction(e)?r!=="success"?!1:!(e.transactionType??"").toLowerCase().includes("abort"):r==="success"}isTransactionDetailsAction(e){return(e.action??"").toLowerCase()===L.toLowerCase()}isCancelledCallback(e){let r=(e.status??"").toLowerCase(),t=(e.message??"").toLowerCase(),n=(e.errorCode??"").toLowerCase();return r==="cancelled"||r==="canceled"||t.includes("user_cancel")||t.includes("user cancel")||n.includes("user_cancel")||n.includes("user cancel")}extractErrorReferenceFromMessage(e){return e?e.match(/\((-?\d+)\)/)?.[1]:void 0}mapCallbackToTransaction(e){let r=e.transactionId??e.orderCode??e.clientTransactionId??"unknown",t=_(e.transactionDate),n=O(e.amount),i=O(e.tipAmount);return{amount:n,cardDetail:{aid:e.aid??null,applicationLabel:e.applicationLabel??null,cardNumber:e.accountNumber??"N/A",cardType:e.cardType??"N/A",issuer:e.bankId??null,orderCode:e.orderCode??null,timestamp:t,transactionId:r},createdAt:t,fees:this.buildFeesFromTip(i),id:r,label:null,provider:p.PaymentProvider.Viva,rawData:e,referenceId:e.clientTransactionId??null,roundingDifference:0,type:this.getVivaPaymentMethodType(e)}}getVivaPaymentMethodType(e){let r=(e.applicationLabel??"").toUpperCase().trim(),n=(e.accountNumber??"").substring(0,6);return n===X?p.PaymentMethod.Edenred:n===z?p.PaymentMethod.WoltBenefit:H.some(i=>r.includes(i))?p.PaymentMethod.Credit:p.PaymentMethod.Debit}buildFeesFromTip(e){return!e||!this.currentCurrency?null:{parts:[{taxAmount:0,total:{amount:e,currency:this.currentCurrency},type:p.FeeType.TipAmount,vatPercentage:0}]}}async lookupTransactionDetails(){if(!this.currentClientTransactionId||!this.currentSourceTerminalId)return null;let e={clientTransactionId:this.currentClientTransactionId,sourceTerminalId:this.currentSourceTerminalId};return new Promise(r=>{let t=!1,n=setTimeout(()=>{t||(t=!0,i(),r(null))},Q),i=this.appToAppConfig.adapter.subscribe(s=>{if(t)return;let a=this.parseCallbackUrl(s);a&&this.matchesKnownTransactionId(a.rawParams)&&(t=!0,clearTimeout(n),i(),r(a.result))});this.appToAppConfig.adapter.openUrl(this.buildActionUrl(L,e)).catch(()=>{t||(t=!0,clearTimeout(n),i(),r(null))})})}};var R=require("@munchi_oy/core");var P=class{constructor(e,r,t){this.messaging=r;this.config=t;this.api=new R.PaymentApi(void 0,"",e)}api;abortController=null;currentSessionId=null;paymentProvider=R.PaymentProviderEnum.Viva;async processPayment(e,r){this.abortController=new AbortController,r("CONNECTING");let t={amount:e.amountCents,referenceId:e.orderRef,businessId:parseInt(this.config.storeId),currency:e.currency,displayId:e.displayId,showReceipt:!0,showTransactionResult:!0};try{let{data:n}=await this.api.initiateTerminalTransaction(t);if(this.currentSessionId=n.sessionId,this.abortController.signal.aborted)throw new Error("Aborted");r("REQUIRES_INPUT",{sessionId:n.sessionId});let i=await this.waitForPaymentCompletion(n.sessionId,e.orderRef,this.abortController.signal);return this.currentSessionId=null,i}catch(n){throw this.currentSessionId=null,n instanceof l?n:new l("NETWORK_ERROR","Failed to create Viva Intent",n)}}async waitForPaymentCompletion(e,r,t){let i=`viva.${this.config.channel.toLowerCase()}.requests.${e}`,s="payment:status-changed";return new Promise((a,o)=>{let c=!1,d=()=>{c=!0,typeof f=="function"&&f(),clearTimeout(I)},m=()=>{d(),o(new Error("Aborted"))};t.addEventListener("abort",m);let f=this.messaging.subscribe(i,s,E=>{c||E.status!==R.SimplePaymentStatus.Pending&&(d(),t.removeEventListener("abort",m),a(this.handleSuccess(E)))}),I=setTimeout(async()=>{if(!(c||t.aborted))try{let E=await this.pollOrderStatus(e,r,this.config.storeId,t);a(this.handleSuccess(E))}catch(E){o(new l("TIMEOUT","Payment timed out and polling failed",E))}finally{t.removeEventListener("abort",m),d()}},1e4)})}async pollOrderStatus(e,r,t,n){let o=Date.now()+12e4;for(;Date.now()<o;){if(n.aborted)throw new Error("Aborted");try{let{data:c}=await this.api.getPaymentStatus({businessId:Number(t),orderId:r,provider:this.paymentProvider,referenceId:e});if(n.aborted)throw new Error("Aborted");if(c.status!==R.SimplePaymentStatus.Pending)return c}catch(c){if(c instanceof Error&&c.message==="Aborted")throw c}await new Promise(c=>{let d=()=>{clearTimeout(m),c(void 0)};n.addEventListener("abort",d,{once:!0});let m=setTimeout(()=>{n.removeEventListener("abort",d),c(void 0)},2e3)})}throw new Error("Payment verification timed out.")}handleSuccess(e){let r=e.status===R.SimplePaymentStatus.Success,t={success:r,status:r?"SUCCESS":"FAILED",orderId:e.orderId,errorCode:e.error?.code||(r?"":R.PaymentFailureCode.SystemUnknown),errorMessage:e.error?.message||(r?"":"Transaction failed without error details")};return e.transactionId&&(t.transactionId=e.transactionId),e.error?.referenceError&&(t.errorReference=e.error.referenceError),e.transaction&&(t.transaction=e.transaction),t}async cancelTransaction(e){if(!this.currentSessionId)return!1;try{let r=this.currentSessionId;return this.currentSessionId=null,await this.api.cancelVivaTransactionV2({cashRegisterId:this.config.storeId,sessionId:r}),this.abortController?.abort(),!0}catch(r){throw this.currentSessionId=null,new l("NETWORK_ERROR","Failed to cancel Viva transaction",r)}}async verifyFinalStatus(e,r){try{let{data:t}=await this.api.getPaymentStatus({businessId:Number(this.config.storeId),orderId:e.orderRef,provider:this.paymentProvider,referenceId:r}),n=t.status===R.SimplePaymentStatus.Success,i=t.status===R.SimplePaymentStatus.Pending,s={success:n,status:n?"SUCCESS":i?"PENDING":"FAILED",orderId:t.orderId,errorCode:t.error?.code||(n||i?"":R.PaymentFailureCode.SystemUnknown),errorMessage:t.error?.message||(n||i?"":"Transaction failed without error details")};return t.transactionId&&(s.transactionId=t.transactionId),t.error?.referenceError&&(s.errorReference=t.error.referenceError),t.transaction&&(s.transaction=t.transaction),s}catch(t){throw new l("NETWORK_ERROR","Failed to verify final transaction status",t)}}async refundTransaction(e,r){try{let t={amount:e.amountCents,businessId:Number(this.config.storeId),displayId:this.config.kioskId,currency:e.currency,orderReferenceId:e.orderRef,referenceId:e.originalTransactionId},{data:n}=await this.api.refundSingleVivaTransaction(t),i=n.success;return{success:i,status:i?"SUCCESS":"FAILED",orderId:e.orderRef,transactionId:n.sessionId}}catch(t){throw new l("NETWORK_ERROR","Failed to refund Viva transaction",t)}}abort(){this.abortController?.abort()}};var h=require("@munchi_oy/core"),F=require("axios");var A=class{constructor(e,r,t){this.messaging=r;this.config=t;this.paymentApi=new h.PaymentApi(void 0,"",e),this.worldlineApi=new h.WorldlineApi(void 0,"",e)}paymentApi;worldlineApi;abortController=null;currentOperationId=null;paymentProvider=h.PaymentProviderEnum.Worldline;async processPayment(e,r){this.abortController=new AbortController,r("CONNECTING");let t={amount:e.amountCents,businessId:Number(this.config.storeId),currency:e.currency,displayId:e.displayId,referenceId:e.orderRef,showReceipt:!0,showTransactionResult:!0,...e.options&&"tipAmount"in e.options&&typeof e.options.tipAmount=="number"?{tipAmount:e.options.tipAmount}:{}};try{let n=await this.worldlineApi.createPayment(t),i=this.extractOperationId(n.data);if(this.currentOperationId=i,this.abortController.signal.aborted)throw new Error("Aborted");r("REQUIRES_INPUT",{sessionId:i});let s=await this.waitForPaymentCompletion(i,e.orderRef,h.PaymentEventType.StatusChanged,this.abortController.signal);return this.currentOperationId=null,s}catch(n){throw this.currentOperationId=null,n instanceof l?n:this.mapWorldlineRequestError(n,"Failed to create Worldline payment")}}async cancelTransaction(e){if(!this.currentOperationId)return!1;let r={businessId:Number(this.config.storeId),targetOperationId:this.currentOperationId};try{return await this.worldlineApi.cancelPayment(r),!0}catch(t){throw this.mapWorldlineRequestError(t,"Failed to cancel Worldline transaction")}}async refundTransaction(e,r){this.abortController=new AbortController,r("CONNECTING");let t={amount:e.amountCents,businessId:Number(this.config.storeId),currency:e.currency,displayId:e.displayId,orderReferenceId:e.orderRef,referenceId:e.originalTransactionId};try{let n=await this.worldlineApi.createRefund(t),i=this.extractOperationId(n.data);if(this.currentOperationId=i,this.abortController.signal.aborted)throw new Error("Aborted");r("REQUIRES_INPUT",{sessionId:i});let s=await this.waitForPaymentCompletion(i,e.orderRef,h.PaymentEventType.RefundStatusChanged,this.abortController.signal);return this.currentOperationId=null,s}catch(n){throw this.currentOperationId=null,n instanceof l?n:this.mapWorldlineRequestError(n,"Failed to refund Worldline transaction")}}async verifyFinalStatus(e,r){try{let{data:t}=await this.paymentApi.getPaymentStatus({businessId:Number(this.config.storeId),orderId:e.orderRef,provider:this.paymentProvider,referenceId:r});return this.handlePaymentStatus(t)}catch(t){throw this.mapWorldlineRequestError(t,"Failed to verify final Worldline status")}}abort(){this.abortController?.abort()}async waitForPaymentCompletion(e,r,t,n){let i=`worldline.requests.${e}`;return new Promise((s,a)=>{let o=!1,c=()=>{o=!0,typeof m=="function"&&m(),clearTimeout(f)},d=()=>{c(),a(new l("CANCELLED","Transaction cancelled"))};n.addEventListener("abort",d);let m=this.messaging.subscribe(i,t,I=>{o||I.status===h.SimplePaymentStatus.Pending||(c(),n.removeEventListener("abort",d),s(this.handlePaymentStatus(I)))}),f=setTimeout(async()=>{if(!(o||n.aborted))try{let I=await this.pollOrderStatus(e,r,this.config.storeId,n);s(this.handlePaymentStatus(I))}catch(I){a(new l("TIMEOUT","Payment timed out and polling failed",I))}finally{n.removeEventListener("abort",d),c()}},1e4)})}async pollOrderStatus(e,r,t,n){let a=Date.now()+12e4;for(;Date.now()<a;){if(n.aborted)throw new Error("Aborted");try{let{data:o}=await this.paymentApi.getPaymentStatus({businessId:Number(t),orderId:r,provider:this.paymentProvider,referenceId:e});if(n.aborted)throw new Error("Aborted");if(o.status!==h.SimplePaymentStatus.Pending)return o}catch(o){if(o instanceof Error&&o.message==="Aborted")throw o}await new Promise(o=>{let c=()=>{clearTimeout(d),o(void 0)};n.addEventListener("abort",c,{once:!0});let d=setTimeout(()=>{n.removeEventListener("abort",c),o(void 0)},2e3)})}throw new Error("Payment verification timed out.")}handlePaymentStatus(e){let r=e.status===h.SimplePaymentStatus.Success,t=e.status===h.SimplePaymentStatus.Pending,n={success:r,status:r?"SUCCESS":t?"PENDING":"FAILED",orderId:e.orderId,errorCode:e.error?.code||(r||t?"":h.PaymentFailureCode.SystemUnknown),errorMessage:e.error?.message||(r||t?"":"Transaction failed without error details")};return e.transactionId&&(n.transactionId=e.transactionId),e.error?.referenceError&&(n.errorReference=e.error.referenceError),e.transaction&&(n.transaction=e.transaction),n}extractOperationId(e){let r=typeof e=="object"&&e!==null&&"operationId"in e&&typeof e.operationId=="string"?e.operationId:null;if(!r)throw new Error("operationId is missing from response.");return r}mapWorldlineRequestError(e,r){if((0,F.isAxiosError)(e)){if(e.response?.status===400||e.response?.status===409)return new l("TERMINAL_BUSY",r,e);if(e.response?.status===404)return new l("TERMINAL_OFFLINE",r,e)}return new l("NETWORK_ERROR",r,e)}};var w=class u{strategy;axios;messaging;timeoutMs;logger;_currentState="IDLE";_listeners=[];_cancellationIntent=!1;_currentSessionId;_autoResetTimer;autoResetOptions;appToAppConfig;static TERMINAL_STATES=["SUCCESS","FAILED","INTERNAL_ERROR"];static RESTING_STATES=["IDLE",...u.TERMINAL_STATES];constructor(e,r,t,n={},i){this.axios=e,this.messaging=r,this.logger=n.logger,this.timeoutMs=n.timeoutMs||3e4,this.autoResetOptions=n.autoResetOnPaymentComplete,this.appToAppConfig=n.appToApp,this.strategy=i??this.resolveStrategy(t)}get version(){return D}get currentState(){return this._currentState}generateErrorResult(e,r,t){return{success:!1,status:"ERROR",errorCode:this.normalizeErrorCode(r),errorMessage:t,orderId:e}}normalizeErrorCode(e){return e?e.includes(".")?e:{CANCELLED:y.PaymentFailureCode.PaymentCancelledByUser,DECLINED:y.PaymentFailureCode.PaymentDeclined,TERMINAL_BUSY:y.PaymentFailureCode.TerminalBusy,TERMINAL_OFFLINE:y.PaymentFailureCode.TerminalOffline,TIMEOUT:y.PaymentFailureCode.TerminalTimeout,NETWORK_ERROR:y.PaymentFailureCode.SystemProviderError,STRATEGY_ERROR:y.PaymentFailureCode.SystemProviderError,MISSING_CONFIG:y.PaymentFailureCode.SystemUnknown,INVALID_AMOUNT:y.PaymentFailureCode.SystemUnknown,UNKNOWN:y.PaymentFailureCode.SystemUnknown}[e]??y.PaymentFailureCode.SystemUnknown:y.PaymentFailureCode.SystemUnknown}subscribe=e=>(this._listeners.push(e),e(this._currentState),()=>{this._listeners=this._listeners.filter(r=>r!==e)});transitionTo(e){if(this._currentState===e)return;if(e==="IDLE"){this.cancelAutoReset(),this._currentState=e,this._listeners.forEach(t=>t(e));return}if(u.TERMINAL_STATES.includes(this._currentState)){let t=`Invalid State Transition: Attempted to move from terminal state ${this._currentState} to ${e}`;throw this.logger?.error(t),this._currentState!=="INTERNAL_ERROR"&&(this._currentState="INTERNAL_ERROR",this._listeners.forEach(n=>n(this._currentState))),new l("UNKNOWN",t)}this._currentState=e,u.TERMINAL_STATES.includes(e)&&this.scheduleAutoReset(e),this._listeners.forEach(t=>t(e))}_resetScheduledAt;get nextAutoResetAt(){return this._resetScheduledAt}cancelAutoReset(){this._autoResetTimer&&(clearTimeout(this._autoResetTimer),this._autoResetTimer=void 0),this._resetScheduledAt=void 0}scheduleAutoReset(e){if(!this.autoResetOptions)return;let t=e==="SUCCESS"?this.autoResetOptions.successDelayMs??5e3:this.autoResetOptions.failureDelayMs??5e3;this.logger?.info(`Scheduling auto-reset to IDLE in ${t}ms`),this._resetScheduledAt=Date.now()+t,this._autoResetTimer=setTimeout(()=>{this.logger?.info("Auto-reset triggered"),this.reset()},t)}resolveStrategy(e){switch(e.provider){case y.PaymentProvider.Nets:return new S(this.axios,this.messaging,e);case y.PaymentProvider.Worldline:return new A(this.axios,this.messaging,e);case y.PaymentProvider.Viva:return this.appToAppConfig?.enabled?new v(this.axios,this.messaging,e,this.appToAppConfig):new P(this.axios,this.messaging,e);default:return new P(this.axios,this.messaging,e)}}initiateTransaction=async(e,r)=>{let t=r??{},n=e.orderRef;if(!u.RESTING_STATES.includes(this._currentState))return this.generateErrorResult(e.orderRef,"UNKNOWN","A transaction is already in progress");let s=Date.now();if(this._cancellationIntent=!1,this._currentSessionId=void 0,this.transitionTo("IDLE"),e.amountCents<=0)return this.generateErrorResult(e.orderRef,"INVALID_AMOUNT","Amount must be greater than 0");try{let a=(m,f)=>{f?.sessionId&&(this._currentSessionId=f.sessionId),m!=="FAILED"&&(this.transitionTo(m),this.fireStateCallback(m,t,n))},o=this.strategy.processPayment(e,a),d=(this.strategy.getExecutionMode?.()??"managed")==="callback_driven"?await o:await Promise.race([o,new Promise((m,f)=>{setTimeout(()=>{f(new l("TIMEOUT","Transaction timed out"))},this.timeoutMs)})]);if(d.success)this.transitionTo("SUCCESS"),this.safeFireCallback(()=>t.onSuccess?.(d));else{if(this._cancellationIntent)return await this.handleTransactionError(e,new Error("Aborted after resolution"),t);this.transitionTo("FAILED"),this.safeFireCallback(()=>t.onError?.(d))}return this.logger?.info("Transaction completed successfully",{orderId:e.orderRef,durationMs:Date.now()-s}),d}catch(a){return this.logger?.warn("Transaction interrupted. Handling final status...",{error:a}),await this.handleTransactionError(e,a,t)}};async handleTransactionError(e,r,t={}){let n=r instanceof l&&r.code==="TIMEOUT";if(!this._cancellationIntent&&!n&&(this.transitionTo("VERIFYING"),this.safeFireCallback(()=>t.onVerifying?.({orderRef:e.orderRef,refPaymentId:this._currentSessionId}))),this._cancellationIntent){try{if(this._currentSessionId){let s=await this.verifyWithRetry(e,this._currentSessionId);if(s.success)return this.transitionTo("SUCCESS"),this.safeFireCallback(()=>t.onSuccess?.(s)),s}}catch(s){this.logger?.warn("Final status verification failed during cancellation",{err:s})}return this.transitionTo("FAILED"),this.safeFireCallback(()=>t.onCancelled?.({orderRef:e.orderRef,refPaymentId:this._currentSessionId})),{success:!1,status:"CANCELLED",errorCode:this.normalizeErrorCode("CANCELLED"),orderId:e.orderRef,...this._currentSessionId?{transactionId:this._currentSessionId}:{}}}let i;if(this.strategy.abort(),this._currentSessionId)try{let s=await this.verifyWithRetry(e,this._currentSessionId);if(s.success)return this.transitionTo("SUCCESS"),this.safeFireCallback(()=>t.onSuccess?.(s)),s;i=s}catch(s){this.logger?.warn("Failed to get detailed error from verifyFinalStatus",{verifyErr:s}),i=this.buildErrorResultFromException(e.orderRef,s)}else i=this.buildErrorResultFromException(e.orderRef,r);return this.transitionTo("FAILED"),this.safeFireCallback(()=>t.onError?.(i)),i}static VERIFY_TIMEOUT_MS=1e4;static VERIFY_MAX_RETRIES=3;static VERIFY_RETRY_DELAY_MS=1500;async verifyWithRetry(e,r){let t,n=!0;for(let a=1;a<=u.VERIFY_MAX_RETRIES;a++)try{let o=await Promise.race([this.strategy.verifyFinalStatus(e,r),new Promise((c,d)=>setTimeout(()=>d(new Error("Verify timed out")),u.VERIFY_TIMEOUT_MS))]);if(o.status==="PENDING"){t=new Error("Verify returned pending status"),this.logger?.warn(`verifyFinalStatus attempt ${a}/${u.VERIFY_MAX_RETRIES} returned pending status`),a<u.VERIFY_MAX_RETRIES&&await new Promise(c=>setTimeout(c,u.VERIFY_RETRY_DELAY_MS));continue}return o}catch(o){t=o,o instanceof Error&&o.message==="Verify timed out"||(n=!1),this.logger?.warn(`verifyFinalStatus attempt ${a}/${u.VERIFY_MAX_RETRIES} failed`,{err:o}),a<u.VERIFY_MAX_RETRIES&&await new Promise(d=>setTimeout(d,u.VERIFY_RETRY_DELAY_MS))}let i=t instanceof Error?t.message:"Verify retries exhausted",s=n?y.PaymentFailureCode.PaymentTimeout:y.PaymentFailureCode.PaymentUnknown;throw new l(s,i)}buildErrorResultFromException(e,r){return r instanceof l?this.generateErrorResult(e,r.code,r.message):this.generateErrorResult(e,"UNKNOWN",r instanceof Error?r.message:"Unknown fatal error")}fireStateCallback(e,r,t){let n={orderRef:t,refPaymentId:this._currentSessionId};switch(e){case"CONNECTING":this.safeFireCallback(()=>r.onConnecting?.(n));break;case"REQUIRES_INPUT":this.safeFireCallback(()=>r.onRequiresInput?.(n));break;case"PROCESSING":this.safeFireCallback(()=>r.onProcessing?.(n));break}}safeFireCallback(e){try{e()}catch(r){this.logger?.warn("Callback execution failed",{error:r})}}cancel=async()=>{if(this.logger?.info("Attempting cancellation"),u.TERMINAL_STATES.includes(this._currentState))return this.logger?.warn("Cannot cancel: Transaction already in terminal state",{state:this._currentState}),!1;if(!this._currentSessionId&&this._currentState==="IDLE")return this.logger?.warn("Cannot cancel: No active session to cancel",{state:this._currentState}),!1;this._cancellationIntent=!0,this.transitionTo("VERIFYING");try{return await this.strategy.cancelTransaction(r=>this.transitionTo(r))}catch(e){return this.logger?.error("Cancellation command failed",e),!1}};reset=()=>{u.TERMINAL_STATES.includes(this._currentState)&&(this._currentSessionId=void 0,this._cancellationIntent=!1,this.transitionTo("IDLE"))};refund=async(e,r)=>{let t=r??{};if(this.logger?.info("Initiating refund",{orderRef:e.orderRef}),this._currentSessionId=void 0,this._cancellationIntent=!1,!u.RESTING_STATES.includes(this._currentState))return this.generateErrorResult(e.orderRef,"UNKNOWN","A transaction is already in progress");this.transitionTo("IDLE");try{let i=(a,o)=>{o?.sessionId&&(this._currentSessionId=o.sessionId),a!=="FAILED"&&(this.transitionTo(a),this.fireStateCallback(a,t,e.orderRef))},s=await this.strategy.refundTransaction(e,i);return s.success?(this.transitionTo("SUCCESS"),this.safeFireCallback(()=>t.onSuccess?.(s))):this._cancellationIntent||s.status==="CANCELLED"?(this.transitionTo("FAILED"),this.safeFireCallback(()=>t.onCancelled?.({orderRef:e.orderRef,refPaymentId:this._currentSessionId}))):(this.transitionTo("FAILED"),this.safeFireCallback(()=>t.onError?.(s))),this.logger?.info("Refund completed",{success:s.success,orderRef:e.orderRef}),s}catch(i){if(this.logger?.error("Refund failed",i),this._cancellationIntent){try{if(this._currentSessionId){let a=await this.verifyWithRetry(e,this._currentSessionId);return a.success?(this.transitionTo("SUCCESS"),this.safeFireCallback(()=>t.onSuccess?.(a)),a):a.status==="CANCELLED"?(this.transitionTo("FAILED"),this.safeFireCallback(()=>t.onCancelled?.({orderRef:e.orderRef,refPaymentId:this._currentSessionId})),a):(this.transitionTo("FAILED"),this.safeFireCallback(()=>t.onError?.(a)),a)}}catch(a){this.logger?.warn("Refund final status verification failed",{verifyError:a})}return this.transitionTo("FAILED"),this.safeFireCallback(()=>t.onCancelled?.({orderRef:e.orderRef,refPaymentId:this._currentSessionId})),{success:!1,status:"CANCELLED",errorCode:this.normalizeErrorCode("CANCELLED"),orderId:e.orderRef,...this._currentSessionId?{transactionId:this._currentSessionId}:{}}}this.transitionTo("FAILED");let s=this.generateErrorResult(e.orderRef,"UNKNOWN",i instanceof Error?i.message:"Refund failed");return this.safeFireCallback(()=>t.onError?.(s)),s}}};var x=(n=>(n.CONNECTING="CONNECTING",n.CONNECTED="CONNECTED",n.OFFLINE="OFFLINE",n.DISCONNECTED="DISCONNECTED",n))(x||{});0&&(module.exports={AppReaderStatus,MunchiPaymentSDK,PaymentInteractionState,SdkPaymentStatus});
|
package/dist/index.mjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{PaymentFailureCode as p,PaymentProvider as _}from"@munchi_oy/core";var w="1.4.9";var c=class l extends Error{code;rawError;constructor(t,r,e){super(r),this.name="PaymentSDKError",this.code=t,this.rawError=e,Object.setPrototypeOf(this,l.prototype)}};import{PaymentApi as L,PaymentEventType as F,PaymentProviderEnum as M,SimplePaymentStatus as N,TransactionType as v}from"@munchi_oy/core";var h=(s=>(s.PENDING="PENDING",s.SUCCESS="SUCCESS",s.APPROVED="APPROVED",s.FAILED="FAILED",s.CANCELLED="CANCELLED",s.ERROR="ERROR",s))(h||{}),R=(o=>(o.IDLE="IDLE",o.CONNECTING="CONNECTING",o.REQUIRES_INPUT="REQUIRES_INPUT",o.PROCESSING="PROCESSING",o.SUCCESS="SUCCESS",o.FAILED="FAILED",o.INTERNAL_ERROR="INTERNAL_ERROR",o.VERIFYING="VERIFYING",o))(R||{});var S=class{constructor(t,r,e){this.messaging=r;this.config=e;this.api=new L(void 0,"",t)}api;abortController=null;currentRequestId=null;paymentProvider=M.Nets;async processPayment(t,r){this.abortController=new AbortController,r("CONNECTING");let e={amount:t.amountCents,businessId:Number(this.config.storeId),referenceId:t.orderRef,currency:t.currency,displayId:t.displayId,options:{allowPinBypass:!0,transactionType:v.Purchase}};try{let{data:n}=await this.api.initiateNetsTerminalTransaction(e),i=n.connectCloudRequestId;if(!i)throw new Error("connectCloudRequestId is missing from response.");if(this.currentRequestId=i,this.abortController.signal.aborted)throw new Error("Aborted");r("REQUIRES_INPUT",{sessionId:i});let s=await this.waitForPaymentCompletion(i,t.orderRef,this.abortController.signal);return this.currentRequestId=null,s}catch(n){throw this.currentRequestId=null,n instanceof c?n:new c("TERMINAL_BUSY","Failed to create Nets Intent",n)}}async waitForPaymentCompletion(t,r,e){let n=`nets.requests.${t}`,i=F.StatusChanged;return new Promise((s,u)=>{let o=!1,a=()=>{o=!0,typeof m=="function"&&m(),clearTimeout(f)},d=()=>{a(),u(new c("CANCELLED","Transaction cancelled"))};e.addEventListener("abort",d);let m=this.messaging.subscribe(n,i,y=>{o||(a(),e.removeEventListener("abort",d),s(this.handleSuccess(y)))}),f=setTimeout(async()=>{if(!(o||e.aborted))try{let y=await this.pollOrderStatus(t,r,this.config.storeId,e);s(this.handleSuccess(y))}catch(y){u(new c("TIMEOUT","Payment timed out and polling failed",y))}finally{e.removeEventListener("abort",d),a()}},1e4)})}async pollOrderStatus(t,r,e,n){let o=Date.now()+12e4;for(;Date.now()<o;){if(n.aborted)throw new Error("Aborted");try{let{data:a}=await this.api.getPaymentStatus({businessId:Number(e),orderId:r,provider:this.paymentProvider,referenceId:t});if(n.aborted)throw new Error("Aborted");if(a.status!==N.Pending)return a}catch(a){if(a instanceof Error&&a.message==="Aborted")throw a}await new Promise(a=>{let d=()=>{clearTimeout(m),a(void 0)};n.addEventListener("abort",d,{once:!0});let m=setTimeout(()=>{n.removeEventListener("abort",d),a(void 0)},2e3)})}throw new Error("Payment verification timed out.")}async cancelTransaction(t){if(!this.currentRequestId)return!1;let r={requestId:this.currentRequestId,businessId:Number(this.config.storeId)};try{return await this.api.cancelNetsTerminalTransaction(r),this.abortController?.abort(),this.currentRequestId=null,!0}catch{return!1}}async refundTransaction(t,r){try{this.abortController=new AbortController;let e={amount:t.amountCents,businessId:Number(this.config.storeId),currency:t.currency,displayId:this.config.kioskId,referenceId:t.orderRef,options:{allowPinBypass:!0,transactionType:v.ReturnOfGoods}},{data:n}=await this.api.initiateNetsTerminalTransaction(e),i=n.connectCloudRequestId;if(!i)throw new Error("connectCloudRequestId is missing from response.");if(this.currentRequestId=i,this.abortController.signal.aborted)throw new Error("Aborted");r("REQUIRES_INPUT",{sessionId:i});let s=await this.waitForPaymentCompletion(i,t.orderRef,this.abortController.signal);return this.currentRequestId=null,s}catch(e){throw this.currentRequestId=null,e instanceof c||e instanceof c?e:new c("NETWORK_ERROR","Failed to refund Nets transaction",e)}}async verifyFinalStatus(t,r){try{let{data:e}=await this.api.getPaymentStatus({businessId:Number(this.config.storeId),orderId:t.orderRef,provider:this.paymentProvider,referenceId:r});return this.handleSuccess(e)}catch(e){throw new c("NETWORK_ERROR","Failed to verify final Nets status",e)}}handleSuccess(t){let r=t.status===N.Success,e={success:r,status:r?"SUCCESS":"FAILED",orderId:t.orderId,transaction:t.transaction};return t.transactionId&&(e.transactionId=t.transactionId),t.error?.code&&(e.errorCode=t.error.code),t.error?.message&&(e.errorMessage=t.error.message),e}abort(){this.abortController?.abort()}};import{PaymentApi as x,PaymentFailureCode as A,PaymentProviderEnum as U,SimplePaymentStatus as E}from"@munchi_oy/core";var g=class{constructor(t,r,e){this.messaging=r;this.config=e;this.api=new x(void 0,"",t)}api;abortController=null;currentSessionId=null;paymentProvider=U.Viva;async processPayment(t,r){this.abortController=new AbortController,r("CONNECTING");let e={amount:t.amountCents,referenceId:t.orderRef,businessId:parseInt(this.config.storeId),currency:t.currency,displayId:t.displayId,showReceipt:!0,showTransactionResult:!0};try{let{data:n}=await this.api.initiateTerminalTransaction(e);if(this.currentSessionId=n.sessionId,this.abortController.signal.aborted)throw new Error("Aborted");r("REQUIRES_INPUT",{sessionId:n.sessionId});let i=await this.waitForPaymentCompletion(n.sessionId,t.orderRef,this.abortController.signal);return this.currentSessionId=null,i}catch(n){throw this.currentSessionId=null,n instanceof c?n:new c("NETWORK_ERROR","Failed to create Viva Intent",n)}}async waitForPaymentCompletion(t,r,e){let i=`viva.${this.config.channel.toLowerCase()}.requests.${t}`,s="payment:status-changed";return new Promise((u,o)=>{let a=!1,d=()=>{a=!0,typeof f=="function"&&f(),clearTimeout(y)},m=()=>{d(),o(new Error("Aborted"))};e.addEventListener("abort",m);let f=this.messaging.subscribe(i,s,I=>{a||I.status!==E.Pending&&(d(),e.removeEventListener("abort",m),u(this.handleSuccess(I)))}),y=setTimeout(async()=>{if(!(a||e.aborted))try{let I=await this.pollOrderStatus(t,r,this.config.storeId,e);u(this.handleSuccess(I))}catch(I){o(new c("TIMEOUT","Payment timed out and polling failed",I))}finally{e.removeEventListener("abort",m),d()}},1e4)})}async pollOrderStatus(t,r,e,n){let o=Date.now()+12e4;for(;Date.now()<o;){if(n.aborted)throw new Error("Aborted");try{let{data:a}=await this.api.getPaymentStatus({businessId:Number(e),orderId:r,provider:this.paymentProvider,referenceId:t});if(n.aborted)throw new Error("Aborted");if(a.status!==E.Pending)return a}catch(a){if(a instanceof Error&&a.message==="Aborted")throw a}await new Promise(a=>{let d=()=>{clearTimeout(m),a(void 0)};n.addEventListener("abort",d,{once:!0});let m=setTimeout(()=>{n.removeEventListener("abort",d),a(void 0)},2e3)})}throw new Error("Payment verification timed out.")}handleSuccess(t){let r=t.status===E.Success,e={success:r,status:r?"SUCCESS":"FAILED",orderId:t.orderId,errorCode:t.error?.code||(r?"":A.SystemUnknown),errorMessage:t.error?.message||(r?"":"Transaction failed without error details")};return t.transactionId&&(e.transactionId=t.transactionId),t.error?.referenceError&&(e.errorReference=t.error.referenceError),t.transaction&&(e.transaction=t.transaction),e}async cancelTransaction(t){if(!this.currentSessionId)return!1;try{let r=this.currentSessionId;return this.currentSessionId=null,await this.api.cancelVivaTransactionV2({cashRegisterId:this.config.storeId,sessionId:r}),this.abortController?.abort(),!0}catch(r){throw this.currentSessionId=null,new c("NETWORK_ERROR","Failed to cancel Viva transaction",r)}}async verifyFinalStatus(t,r){try{let{data:e}=await this.api.getPaymentStatus({businessId:Number(this.config.storeId),orderId:t.orderRef,provider:this.paymentProvider,referenceId:r}),n=e.status===E.Success,i=e.status===E.Pending,s={success:n,status:n?"SUCCESS":i?"PENDING":"FAILED",orderId:e.orderId,errorCode:e.error?.code||(n||i?"":A.SystemUnknown),errorMessage:e.error?.message||(n||i?"":"Transaction failed without error details")};return e.transactionId&&(s.transactionId=e.transactionId),e.error?.referenceError&&(s.errorReference=e.error.referenceError),e.transaction&&(s.transaction=e.transaction),s}catch(e){throw new c("NETWORK_ERROR","Failed to verify final transaction status",e)}}async refundTransaction(t,r){try{let e={amount:t.amountCents,businessId:Number(this.config.storeId),displayId:this.config.kioskId,currency:t.currency,orderReferenceId:t.orderRef,referenceId:t.originalTransactionId},{data:n}=await this.api.refundSingleVivaTransaction(e),i=n.success;return{success:i,status:i?"SUCCESS":"FAILED",orderId:t.orderRef,transactionId:n.sessionId}}catch(e){throw new c("NETWORK_ERROR","Failed to refund Viva transaction",e)}}abort(){this.abortController?.abort()}};import{PaymentApi as k,PaymentEventType as O,PaymentFailureCode as W,PaymentProviderEnum as V,SimplePaymentStatus as P,WorldlineApi as G}from"@munchi_oy/core";import{isAxiosError as K}from"axios";var T=class{constructor(t,r,e){this.messaging=r;this.config=e;this.paymentApi=new k(void 0,"",t),this.worldlineApi=new G(void 0,"",t)}paymentApi;worldlineApi;abortController=null;currentOperationId=null;paymentProvider=V.Worldline;async processPayment(t,r){this.abortController=new AbortController,r("CONNECTING");let e={amount:t.amountCents,businessId:Number(this.config.storeId),currency:t.currency,displayId:t.displayId,referenceId:t.orderRef,showReceipt:!0,showTransactionResult:!0,...t.options&&"tipAmount"in t.options&&typeof t.options.tipAmount=="number"?{tipAmount:t.options.tipAmount}:{}};try{let n=await this.worldlineApi.createPayment(e),i=this.extractOperationId(n.data);if(this.currentOperationId=i,this.abortController.signal.aborted)throw new Error("Aborted");r("REQUIRES_INPUT",{sessionId:i});let s=await this.waitForPaymentCompletion(i,t.orderRef,O.StatusChanged,this.abortController.signal);return this.currentOperationId=null,s}catch(n){throw this.currentOperationId=null,n instanceof c?n:this.mapWorldlineRequestError(n,"Failed to create Worldline payment")}}async cancelTransaction(t){if(!this.currentOperationId)return!1;let r={businessId:Number(this.config.storeId),targetOperationId:this.currentOperationId};try{return await this.worldlineApi.cancelPayment(r),!0}catch(e){throw this.mapWorldlineRequestError(e,"Failed to cancel Worldline transaction")}}async refundTransaction(t,r){this.abortController=new AbortController,r("CONNECTING");let e={amount:t.amountCents,businessId:Number(this.config.storeId),currency:t.currency,displayId:t.displayId,orderReferenceId:t.orderRef,referenceId:t.originalTransactionId};try{let n=await this.worldlineApi.createRefund(e),i=this.extractOperationId(n.data);if(this.currentOperationId=i,this.abortController.signal.aborted)throw new Error("Aborted");r("REQUIRES_INPUT",{sessionId:i});let s=await this.waitForPaymentCompletion(i,t.orderRef,O.RefundStatusChanged,this.abortController.signal);return this.currentOperationId=null,s}catch(n){throw this.currentOperationId=null,n instanceof c?n:this.mapWorldlineRequestError(n,"Failed to refund Worldline transaction")}}async verifyFinalStatus(t,r){try{let{data:e}=await this.paymentApi.getPaymentStatus({businessId:Number(this.config.storeId),orderId:t.orderRef,provider:this.paymentProvider,referenceId:r});return this.handlePaymentStatus(e)}catch(e){throw this.mapWorldlineRequestError(e,"Failed to verify final Worldline status")}}abort(){this.abortController?.abort()}async waitForPaymentCompletion(t,r,e,n){let i=`worldline.requests.${t}`;return new Promise((s,u)=>{let o=!1,a=()=>{o=!0,typeof m=="function"&&m(),clearTimeout(f)},d=()=>{a(),u(new c("CANCELLED","Transaction cancelled"))};n.addEventListener("abort",d);let m=this.messaging.subscribe(i,e,y=>{o||y.status===P.Pending||(a(),n.removeEventListener("abort",d),s(this.handlePaymentStatus(y)))}),f=setTimeout(async()=>{if(!(o||n.aborted))try{let y=await this.pollOrderStatus(t,r,this.config.storeId,n);s(this.handlePaymentStatus(y))}catch(y){u(new c("TIMEOUT","Payment timed out and polling failed",y))}finally{n.removeEventListener("abort",d),a()}},1e4)})}async pollOrderStatus(t,r,e,n){let u=Date.now()+12e4;for(;Date.now()<u;){if(n.aborted)throw new Error("Aborted");try{let{data:o}=await this.paymentApi.getPaymentStatus({businessId:Number(e),orderId:r,provider:this.paymentProvider,referenceId:t});if(n.aborted)throw new Error("Aborted");if(o.status!==P.Pending)return o}catch(o){if(o instanceof Error&&o.message==="Aborted")throw o}await new Promise(o=>{let a=()=>{clearTimeout(d),o(void 0)};n.addEventListener("abort",a,{once:!0});let d=setTimeout(()=>{n.removeEventListener("abort",a),o(void 0)},2e3)})}throw new Error("Payment verification timed out.")}handlePaymentStatus(t){let r=t.status===P.Success,e=t.status===P.Pending,n={success:r,status:r?"SUCCESS":e?"PENDING":"FAILED",orderId:t.orderId,errorCode:t.error?.code||(r||e?"":W.SystemUnknown),errorMessage:t.error?.message||(r||e?"":"Transaction failed without error details")};return t.transactionId&&(n.transactionId=t.transactionId),t.error?.referenceError&&(n.errorReference=t.error.referenceError),t.transaction&&(n.transaction=t.transaction),n}extractOperationId(t){let r=typeof t=="object"&&t!==null&&"operationId"in t&&typeof t.operationId=="string"?t.operationId:null;if(!r)throw new Error("operationId is missing from response.");return r}mapWorldlineRequestError(t,r){if(K(t)){if(t.response?.status===400||t.response?.status===409)return new c("TERMINAL_BUSY",r,t);if(t.response?.status===404)return new c("TERMINAL_OFFLINE",r,t)}return new c("NETWORK_ERROR",r,t)}};var b=class l{strategy;axios;messaging;timeoutMs;logger;_currentState="IDLE";_listeners=[];_cancellationIntent=!1;_currentSessionId;_autoResetTimer;autoResetOptions;static TERMINAL_STATES=["SUCCESS","FAILED","INTERNAL_ERROR"];static RESTING_STATES=["IDLE",...l.TERMINAL_STATES];constructor(t,r,e,n={},i){this.axios=t,this.messaging=r,this.logger=n.logger,this.timeoutMs=n.timeoutMs||3e4,this.autoResetOptions=n.autoResetOnPaymentComplete,this.strategy=i??this.resolveStrategy(e)}get version(){return w}get currentState(){return this._currentState}generateErrorResult(t,r,e){return{success:!1,status:"ERROR",errorCode:this.normalizeErrorCode(r),errorMessage:e,orderId:t}}normalizeErrorCode(t){return t?t.includes(".")?t:{CANCELLED:p.PaymentCancelledByUser,DECLINED:p.PaymentDeclined,TERMINAL_BUSY:p.TerminalBusy,TERMINAL_OFFLINE:p.TerminalOffline,TIMEOUT:p.TerminalTimeout,NETWORK_ERROR:p.SystemProviderError,STRATEGY_ERROR:p.SystemProviderError,MISSING_CONFIG:p.SystemUnknown,INVALID_AMOUNT:p.SystemUnknown,UNKNOWN:p.SystemUnknown}[t]??p.SystemUnknown:p.SystemUnknown}subscribe=t=>(this._listeners.push(t),t(this._currentState),()=>{this._listeners=this._listeners.filter(r=>r!==t)});transitionTo(t){if(this._currentState===t)return;if(t==="IDLE"){this.cancelAutoReset(),this._currentState=t,this._listeners.forEach(e=>e(t));return}if(l.TERMINAL_STATES.includes(this._currentState)){let e=`Invalid State Transition: Attempted to move from terminal state ${this._currentState} to ${t}`;throw this.logger?.error(e),this._currentState!=="INTERNAL_ERROR"&&(this._currentState="INTERNAL_ERROR",this._listeners.forEach(n=>n(this._currentState))),new c("UNKNOWN",e)}this._currentState=t,l.TERMINAL_STATES.includes(t)&&this.scheduleAutoReset(t),this._listeners.forEach(e=>e(t))}_resetScheduledAt;get nextAutoResetAt(){return this._resetScheduledAt}cancelAutoReset(){this._autoResetTimer&&(clearTimeout(this._autoResetTimer),this._autoResetTimer=void 0),this._resetScheduledAt=void 0}scheduleAutoReset(t){if(!this.autoResetOptions)return;let e=t==="SUCCESS"?this.autoResetOptions.successDelayMs??5e3:this.autoResetOptions.failureDelayMs??5e3;this.logger?.info(`Scheduling auto-reset to IDLE in ${e}ms`),this._resetScheduledAt=Date.now()+e,this._autoResetTimer=setTimeout(()=>{this.logger?.info("Auto-reset triggered"),this.reset()},e)}resolveStrategy(t){switch(t.provider){case _.Nets:return new S(this.axios,this.messaging,t);case _.Worldline:return new T(this.axios,this.messaging,t);default:return new g(this.axios,this.messaging,t)}}initiateTransaction=async(t,r)=>{let e=r??{},n=t.orderRef;if(!l.RESTING_STATES.includes(this._currentState))return this.generateErrorResult(t.orderRef,"UNKNOWN","A transaction is already in progress");let s=Date.now();if(this._cancellationIntent=!1,this._currentSessionId=void 0,this.transitionTo("IDLE"),t.amountCents<=0)return this.generateErrorResult(t.orderRef,"INVALID_AMOUNT","Amount must be greater than 0");try{let u=(m,f)=>{f?.sessionId&&(this._currentSessionId=f.sessionId),m!=="FAILED"&&(this.transitionTo(m),this.fireStateCallback(m,e,n))},o=this.strategy.processPayment(t,u),a=new Promise((m,f)=>{setTimeout(()=>{f(new c("TIMEOUT","Transaction timed out"))},this.timeoutMs)}),d=await Promise.race([o,a]);if(d.success)this.transitionTo("SUCCESS"),this.safeFireCallback(()=>e.onSuccess?.(d));else{if(this._cancellationIntent)return await this.handleTransactionError(t,new Error("Aborted after resolution"),e);this.transitionTo("FAILED"),this.safeFireCallback(()=>e.onError?.(d))}return this.logger?.info("Transaction completed successfully",{orderId:t.orderRef,durationMs:Date.now()-s}),d}catch(u){return this.logger?.warn("Transaction interrupted. Handling final status...",{error:u}),await this.handleTransactionError(t,u,e)}};async handleTransactionError(t,r,e={}){let n=r instanceof c&&r.code==="TIMEOUT";if(!this._cancellationIntent&&!n&&(this.transitionTo("VERIFYING"),this.safeFireCallback(()=>e.onVerifying?.({orderRef:t.orderRef,refPaymentId:this._currentSessionId}))),this._cancellationIntent){try{if(this._currentSessionId){let s=await this.verifyWithRetry(t,this._currentSessionId);if(s.success)return this.transitionTo("SUCCESS"),this.safeFireCallback(()=>e.onSuccess?.(s)),s}}catch(s){this.logger?.warn("Final status verification failed during cancellation",{err:s})}return this.transitionTo("FAILED"),this.safeFireCallback(()=>e.onCancelled?.({orderRef:t.orderRef,refPaymentId:this._currentSessionId})),{success:!1,status:"CANCELLED",errorCode:this.normalizeErrorCode("CANCELLED"),orderId:t.orderRef,...this._currentSessionId?{transactionId:this._currentSessionId}:{}}}let i;if(this.strategy.abort(),this._currentSessionId)try{let s=await this.verifyWithRetry(t,this._currentSessionId);if(s.success)return this.transitionTo("SUCCESS"),this.safeFireCallback(()=>e.onSuccess?.(s)),s;i=s}catch(s){this.logger?.warn("Failed to get detailed error from verifyFinalStatus",{verifyErr:s}),i=this.buildErrorResultFromException(t.orderRef,s)}else i=this.buildErrorResultFromException(t.orderRef,r);return this.transitionTo("FAILED"),this.safeFireCallback(()=>e.onError?.(i)),i}static VERIFY_TIMEOUT_MS=1e4;static VERIFY_MAX_RETRIES=3;static VERIFY_RETRY_DELAY_MS=1500;async verifyWithRetry(t,r){let e,n=!0;for(let u=1;u<=l.VERIFY_MAX_RETRIES;u++)try{let o=await Promise.race([this.strategy.verifyFinalStatus(t,r),new Promise((a,d)=>setTimeout(()=>d(new Error("Verify timed out")),l.VERIFY_TIMEOUT_MS))]);if(o.status==="PENDING"){e=new Error("Verify returned pending status"),this.logger?.warn(`verifyFinalStatus attempt ${u}/${l.VERIFY_MAX_RETRIES} returned pending status`),u<l.VERIFY_MAX_RETRIES&&await new Promise(a=>setTimeout(a,l.VERIFY_RETRY_DELAY_MS));continue}return o}catch(o){e=o,o instanceof Error&&o.message==="Verify timed out"||(n=!1),this.logger?.warn(`verifyFinalStatus attempt ${u}/${l.VERIFY_MAX_RETRIES} failed`,{err:o}),u<l.VERIFY_MAX_RETRIES&&await new Promise(d=>setTimeout(d,l.VERIFY_RETRY_DELAY_MS))}let i=e instanceof Error?e.message:"Verify retries exhausted",s=n?p.PaymentTimeout:p.PaymentUnknown;throw new c(s,i)}buildErrorResultFromException(t,r){return r instanceof c?this.generateErrorResult(t,r.code,r.message):this.generateErrorResult(t,"UNKNOWN",r instanceof Error?r.message:"Unknown fatal error")}fireStateCallback(t,r,e){let n={orderRef:e,refPaymentId:this._currentSessionId};switch(t){case"CONNECTING":this.safeFireCallback(()=>r.onConnecting?.(n));break;case"REQUIRES_INPUT":this.safeFireCallback(()=>r.onRequiresInput?.(n));break;case"PROCESSING":this.safeFireCallback(()=>r.onProcessing?.(n));break}}safeFireCallback(t){try{t()}catch(r){this.logger?.warn("Callback execution failed",{error:r})}}cancel=async()=>{if(this.logger?.info("Attempting cancellation"),l.TERMINAL_STATES.includes(this._currentState))return this.logger?.warn("Cannot cancel: Transaction already in terminal state",{state:this._currentState}),!1;if(!this._currentSessionId&&this._currentState==="IDLE")return this.logger?.warn("Cannot cancel: No active session to cancel",{state:this._currentState}),!1;this._cancellationIntent=!0,this.transitionTo("VERIFYING");try{return await this.strategy.cancelTransaction(r=>this.transitionTo(r))}catch(t){return this.logger?.error("Cancellation command failed",t),!1}};reset=()=>{l.TERMINAL_STATES.includes(this._currentState)&&(this._currentSessionId=void 0,this._cancellationIntent=!1,this.transitionTo("IDLE"))};refund=async(t,r)=>{let e=r??{};if(this.logger?.info("Initiating refund",{orderRef:t.orderRef}),this._currentSessionId=void 0,!l.RESTING_STATES.includes(this._currentState))return this.generateErrorResult(t.orderRef,"UNKNOWN","A transaction is already in progress");this.transitionTo("IDLE");try{let i=(u,o)=>{o?.sessionId&&(this._currentSessionId=o.sessionId),u!=="FAILED"&&(this.transitionTo(u),this.fireStateCallback(u,e,t.orderRef))},s=await this.strategy.refundTransaction(t,i);return s.success?(this.transitionTo("SUCCESS"),this.safeFireCallback(()=>e.onSuccess?.(s))):(this.transitionTo("FAILED"),this.safeFireCallback(()=>e.onError?.(s))),this.logger?.info("Refund completed",{success:s.success,orderRef:t.orderRef}),s}catch(i){this.logger?.error("Refund failed",i),this.transitionTo("FAILED");let s=this.generateErrorResult(t.orderRef,"UNKNOWN",i instanceof Error?i.message:"Refund failed");return this.safeFireCallback(()=>e.onError?.(s)),s}}};var Y=(n=>(n.CONNECTING="CONNECTING",n.CONNECTED="CONNECTED",n.OFFLINE="OFFLINE",n.DISCONNECTED="DISCONNECTED",n))(Y||{});export{Y as AppReaderStatus,b as MunchiPaymentSDK,R as PaymentInteractionState,h as SdkPaymentStatus};
|
|
1
|
+
import{PaymentFailureCode as y,PaymentProvider as N}from"@munchi_oy/core";var D="1.5.0";var l=class d extends Error{code;rawError;constructor(e,r,t){super(r),this.name="PaymentSDKError",this.code=e,this.rawError=t,Object.setPrototypeOf(this,d.prototype)}};import{PaymentApi as W,PaymentEventType as G,PaymentProviderEnum as q,SimplePaymentStatus as _,TransactionType as L}from"@munchi_oy/core";var I=(s=>(s.PENDING="PENDING",s.SUCCESS="SUCCESS",s.APPROVED="APPROVED",s.FAILED="FAILED",s.CANCELLED="CANCELLED",s.ERROR="ERROR",s))(I||{}),R=(o=>(o.IDLE="IDLE",o.CONNECTING="CONNECTING",o.REQUIRES_INPUT="REQUIRES_INPUT",o.PROCESSING="PROCESSING",o.SUCCESS="SUCCESS",o.FAILED="FAILED",o.INTERNAL_ERROR="INTERNAL_ERROR",o.VERIFYING="VERIFYING",o))(R||{});var E=class{constructor(e,r,t){this.messaging=r;this.config=t;this.api=new W(void 0,"",e)}api;abortController=null;currentRequestId=null;paymentProvider=q.Nets;async processPayment(e,r){this.abortController=new AbortController,r("CONNECTING");let t={amount:e.amountCents,businessId:Number(this.config.storeId),referenceId:e.orderRef,currency:e.currency,displayId:e.displayId,options:{allowPinBypass:!0,transactionType:L.Purchase}};try{let{data:n}=await this.api.initiateNetsTerminalTransaction(t),i=n.connectCloudRequestId;if(!i)throw new Error("connectCloudRequestId is missing from response.");if(this.currentRequestId=i,this.abortController.signal.aborted)throw new Error("Aborted");r("REQUIRES_INPUT",{sessionId:i});let s=await this.waitForPaymentCompletion(i,e.orderRef,this.abortController.signal);return this.currentRequestId=null,s}catch(n){throw this.currentRequestId=null,n instanceof l?n:new l("TERMINAL_BUSY","Failed to create Nets Intent",n)}}async waitForPaymentCompletion(e,r,t){let n=`nets.requests.${e}`,i=G.StatusChanged;return new Promise((s,a)=>{let o=!1,c=()=>{o=!0,typeof m=="function"&&m(),clearTimeout(p)},u=()=>{c(),a(new l("CANCELLED","Transaction cancelled"))};t.addEventListener("abort",u);let m=this.messaging.subscribe(n,i,f=>{o||(c(),t.removeEventListener("abort",u),s(this.handleSuccess(f)))}),p=setTimeout(async()=>{if(!(o||t.aborted))try{let f=await this.pollOrderStatus(e,r,this.config.storeId,t);s(this.handleSuccess(f))}catch(f){a(new l("TIMEOUT","Payment timed out and polling failed",f))}finally{t.removeEventListener("abort",u),c()}},1e4)})}async pollOrderStatus(e,r,t,n){let o=Date.now()+12e4;for(;Date.now()<o;){if(n.aborted)throw new Error("Aborted");try{let{data:c}=await this.api.getPaymentStatus({businessId:Number(t),orderId:r,provider:this.paymentProvider,referenceId:e});if(n.aborted)throw new Error("Aborted");if(c.status!==_.Pending)return c}catch(c){if(c instanceof Error&&c.message==="Aborted")throw c}await new Promise(c=>{let u=()=>{clearTimeout(m),c(void 0)};n.addEventListener("abort",u,{once:!0});let m=setTimeout(()=>{n.removeEventListener("abort",u),c(void 0)},2e3)})}throw new Error("Payment verification timed out.")}async cancelTransaction(e){if(!this.currentRequestId)return!1;let r={requestId:this.currentRequestId,businessId:Number(this.config.storeId)};try{return await this.api.cancelNetsTerminalTransaction(r),this.abortController?.abort(),this.currentRequestId=null,!0}catch{return!1}}async refundTransaction(e,r){try{this.abortController=new AbortController;let t={amount:e.amountCents,businessId:Number(this.config.storeId),currency:e.currency,displayId:this.config.kioskId,referenceId:e.orderRef,options:{allowPinBypass:!0,transactionType:L.ReturnOfGoods}},{data:n}=await this.api.initiateNetsTerminalTransaction(t),i=n.connectCloudRequestId;if(!i)throw new Error("connectCloudRequestId is missing from response.");if(this.currentRequestId=i,this.abortController.signal.aborted)throw new Error("Aborted");r("REQUIRES_INPUT",{sessionId:i});let s=await this.waitForPaymentCompletion(i,e.orderRef,this.abortController.signal);return this.currentRequestId=null,s}catch(t){throw this.currentRequestId=null,t instanceof l||t instanceof l?t:new l("NETWORK_ERROR","Failed to refund Nets transaction",t)}}async verifyFinalStatus(e,r){try{let{data:t}=await this.api.getPaymentStatus({businessId:Number(this.config.storeId),orderId:e.orderRef,provider:this.paymentProvider,referenceId:r});return this.handleSuccess(t)}catch(t){throw new l("NETWORK_ERROR","Failed to verify final Nets status",t)}}handleSuccess(e){let r=e.status===_.Success,t={success:r,status:r?"SUCCESS":"FAILED",orderId:e.orderId,transaction:e.transaction};return e.transactionId&&(t.transactionId=e.transactionId),e.error?.code&&(t.errorCode=e.error.code),e.error?.message&&(t.errorMessage=e.error.message),t}abort(){this.abortController?.abort()}};import{FeeType as Y,PaymentFailureCode as g,PaymentMethod as S,PaymentProvider as x,VivaApi as B,PaymentApi as $}from"@munchi_oy/core";var w=d=>{if(!d)return 0;let e=Number.parseInt(d,10);return Number.isFinite(e)?e:0},F=d=>{if(!d)return new Date().toISOString();let e=new Date(d);return Number.isNaN(e.getTime())?new Date().toISOString():e.toISOString()};var j="vivapayclient://pay/v1",Q="abort",X="cancel",z="sale",M="transactionDetails",H=4e3,J="534287",Z="493591",ee=["CREDIT","PREPAID","CORPORATE"],b=class{constructor(e,r,t,n){this.config=t;this.appToAppConfig=n;this.api=new B(void 0,"",e),this.paymentApi=new $(void 0,"",e),this.paymentApiWithReference=this.paymentApi}api;paymentApi;abortController=null;currentClientTransactionId=null;currentIsvClientTransactionId=null;currentCurrency=null;currentOrderRef=null;currentSourceTerminalId=null;latestResult=null;paymentApiWithReference;wasCancelled=!1;getExecutionMode(){return"callback_driven"}async processPayment(e,r){if(!this.appToAppConfig.enabled)throw new l("STRATEGY_ERROR","Viva app-to-app is not enabled");r("CONNECTING");try{let{data:t}=await this.api.createVivaAppToAppPayment(this.buildCreatePaymentPayload(e));return await this.runAction(z,this.buildLaunchParams(t),e,r)}catch(t){throw new l("NETWORK_ERROR","Failed to create Viva app-to-app payment",t)}}async cancelTransaction(e){if(!this.currentClientTransactionId)return!1;let r=await this.lookupTransactionDetails();if(r)return this.latestResult=r,this.wasCancelled=r.status==="CANCELLED",this.abortController?.abort(),!0;try{await this.appToAppConfig.adapter.openUrl(this.buildActionUrl(Q,{}))}catch(t){throw this.abortController?.abort(),new l("NETWORK_ERROR","Failed to launch Viva abort flow",t)}return this.wasCancelled=!0,this.abortController?.abort(),!0}async refundTransaction(e,r){r("CONNECTING");let t=await this.fetchPaymentReference(e),n=this.buildRefundLaunchParams(e,t);return this.runAction(X,n,e,r)}async verifyFinalStatus(e,r){return this.latestResult?this.latestResult:this.wasCancelled?{success:!1,status:"CANCELLED",orderId:this.currentOrderRef??r,errorCode:g.PaymentCancelledByUser,errorMessage:"Transaction was cancelled",transactionId:r}:{success:!1,status:"PENDING",orderId:this.currentOrderRef??r,transactionId:r}}abort(){this.abortController?.abort()}async runAction(e,r,t,n){if(!this.appToAppConfig.enabled)throw new l("STRATEGY_ERROR","Viva app-to-app is not enabled");this.abortController=new AbortController,this.latestResult=null,this.wasCancelled=!1,this.currentCurrency=t.currency,this.currentOrderRef=t.orderRef,this.currentSourceTerminalId=r.sourceTerminalId??r.tid??null,this.currentClientTransactionId=r.clientTransactionId??null,this.currentIsvClientTransactionId=r.ISV_clientTransactionId??null;let i=this.currentClientTransactionId?{sessionId:this.currentClientTransactionId}:void 0;return new Promise((s,a)=>{let o=(m,p)=>{m?.(),this.abortController?.signal.removeEventListener("abort",p)},c=()=>{o(u,c),a(new Error("Aborted"))},u=this.appToAppConfig.adapter.subscribe(m=>{if(this.abortController?.signal.aborted)return;let p=this.parseCallbackUrl(m);p&&this.matchesKnownTransactionId(p.rawParams)&&(this.latestResult=p.result,this.wasCancelled=p.result.status==="CANCELLED",this.currentClientTransactionId=null,this.currentIsvClientTransactionId=null,this.currentCurrency=null,this.currentOrderRef=null,this.currentSourceTerminalId=null,o(u,c),s(p.result))});this.abortController?.signal.addEventListener("abort",c),n("REQUIRES_INPUT",i),this.appToAppConfig.adapter.openUrl(this.buildActionUrl(e,r)).then(()=>{this.abortController?.signal.aborted}).catch(m=>{o(u,c),this.currentClientTransactionId=null,this.currentIsvClientTransactionId=null,this.currentCurrency=null,this.currentOrderRef=null,this.currentSourceTerminalId=null,a(new l("NETWORK_ERROR","Failed to launch Viva app",m))})})}buildCreatePaymentPayload(e){let r=e.options??{},t={amount:e.amountCents,referenceId:e.orderRef,businessId:Number(this.config.storeId),currency:e.currency,displayId:e.displayId,showReceipt:!0,showTransactionResult:!0};return r.tipAmount!==void 0&&(t.tipAmount=r.tipAmount),t}buildLaunchParams(e){let r={};return Object.entries(e).forEach(([t,n])=>{n!==void 0&&(r[t]=String(n))}),r}buildRefundLaunchParams(e,r){let t=e.options??{},n=r?.originalTransactionId?.trim()||e.originalTransactionId.trim(),i={amount:String(e.amountCents),clientTransactionId:n,show_receipt:"true",show_transaction_result:"true"};if(t.sourceCode&&(i.sourceCode=t.sourceCode),r?.referenceCode&&(i.orderCode=r.referenceCode),r?.shortReferenceCode&&(i.shortOrderCode=r.shortReferenceCode),r?.receiptNumber&&(i.referenceNumber=r.receiptNumber),r?.terminalId&&(i.tid=r.terminalId),r?.referenceCode||r?.shortReferenceCode||r?.receiptNumber)return i;let s=n;return/^\d+$/.test(s)&&(s.length===16?i.orderCode=s:s.length===10?i.shortOrderCode=s:i.referenceNumber=s),i}async fetchPaymentReference(e){try{let{data:r}=await this.paymentApiWithReference.getPaymentReference({orderId:e.orderRef,provider:x.Viva,transactionId:e.originalTransactionId});return this.extractPaymentReferenceContext(r)}catch{return}}extractPaymentReferenceContext(e){if(!e)return;let r=e.references;if(!r||typeof r!="object"||Array.isArray(r))return{originalTransactionId:e.originalTransactionId};let t=r,n={originalTransactionId:this.readReferenceValue(t.originalTransactionId)??this.readReferenceValue(t.clientTransactionId)??e.originalTransactionId},i=this.readReferenceValue(t.receiptNumber)??this.readReferenceValue(t.referenceNumber),s=this.readReferenceValue(t.referenceCode)??this.readReferenceValue(t.orderCode),a=this.readReferenceValue(t.shortReferenceCode)??this.readReferenceValue(t.shortOrderCode),o=this.readReferenceValue(t.terminalId)??this.readReferenceValue(t.tid);return i&&(n.receiptNumber=i),s&&(n.referenceCode=s),a&&(n.shortReferenceCode=a),o&&(n.terminalId=o),n}readReferenceValue(e){if(typeof e!="string")return;let r=e.trim();return r.length>0?r:void 0}buildActionUrl(e,r){let t=new URLSearchParams({action:e,appId:this.appToAppConfig.appId,callback:this.appToAppConfig.callbackUrl});return Object.entries(r).forEach(([n,i])=>{t.set(n,i)}),`${j}?${t.toString()}`}parseCallbackUrl(e){if(!this.matchesCallbackBase(e))return null;let r=new URL(e),t=Object.fromEntries(r.searchParams.entries()),n=this.isSuccessfulCallback(t),i=this.isCancelledCallback(t),s=this.resolveFailureCode(t,i),a={success:n,status:n?"SUCCESS":i?"CANCELLED":"FAILED",orderId:this.currentOrderRef??t.clientTransactionId??"unknown",errorCode:n?"":s,errorMessage:n?"":t.message??"Transaction failed without error details"};n&&(a.transaction=this.mapCallbackToTransaction(t));let o=t.transactionId??t.orderCode??t.clientTransactionId,c=t.errorCode??this.extractErrorReferenceFromMessage(t.message)??t.referenceNumber??t.tid??t.rrn;return o&&(a.transactionId=o),c&&(a.errorReference=c),{rawParams:t,result:a}}matchesCallbackBase(e){let r=new URL(e),t=new URL(this.appToAppConfig.callbackUrl);return r.protocol===t.protocol&&r.hostname===t.hostname&&r.pathname===t.pathname}matchesKnownTransactionId(e){let r=[this.currentClientTransactionId,this.currentIsvClientTransactionId].filter(n=>!!n);if(r.length===0)return!0;let t=[e.clientTransactionId,e.ISV_clientTransactionId].filter(n=>!!n);return t.length===0?!0:t.some(n=>r.includes(n))}resolveFailureCode(e,r){if(r)return g.PaymentCancelledByUser;let t=e.errorCode;if(t?.includes("."))return t;if(this.isTransactionDetailsAction(e)&&(e.transactionType??"").toLowerCase().includes("abort"))return g.SystemUnknown;let n=(e.message??"").toLowerCase(),i=(e.status??"").toLowerCase();return n.includes("declined")||i==="declined"||i==="fail"||i==="failed"?g.PaymentDeclined:g.SystemUnknown}isSuccessfulCallback(e){let r=(e.status??"").toLowerCase();return this.isTransactionDetailsAction(e)?r!=="success"?!1:!(e.transactionType??"").toLowerCase().includes("abort"):r==="success"}isTransactionDetailsAction(e){return(e.action??"").toLowerCase()===M.toLowerCase()}isCancelledCallback(e){let r=(e.status??"").toLowerCase(),t=(e.message??"").toLowerCase(),n=(e.errorCode??"").toLowerCase();return r==="cancelled"||r==="canceled"||t.includes("user_cancel")||t.includes("user cancel")||n.includes("user_cancel")||n.includes("user cancel")}extractErrorReferenceFromMessage(e){return e?e.match(/\((-?\d+)\)/)?.[1]:void 0}mapCallbackToTransaction(e){let r=e.transactionId??e.orderCode??e.clientTransactionId??"unknown",t=F(e.transactionDate),n=w(e.amount),i=w(e.tipAmount);return{amount:n,cardDetail:{aid:e.aid??null,applicationLabel:e.applicationLabel??null,cardNumber:e.accountNumber??"N/A",cardType:e.cardType??"N/A",issuer:e.bankId??null,orderCode:e.orderCode??null,timestamp:t,transactionId:r},createdAt:t,fees:this.buildFeesFromTip(i),id:r,label:null,provider:x.Viva,rawData:e,referenceId:e.clientTransactionId??null,roundingDifference:0,type:this.getVivaPaymentMethodType(e)}}getVivaPaymentMethodType(e){let r=(e.applicationLabel??"").toUpperCase().trim(),n=(e.accountNumber??"").substring(0,6);return n===J?S.Edenred:n===Z?S.WoltBenefit:ee.some(i=>r.includes(i))?S.Credit:S.Debit}buildFeesFromTip(e){return!e||!this.currentCurrency?null:{parts:[{taxAmount:0,total:{amount:e,currency:this.currentCurrency},type:Y.TipAmount,vatPercentage:0}]}}async lookupTransactionDetails(){if(!this.currentClientTransactionId||!this.currentSourceTerminalId)return null;let e={clientTransactionId:this.currentClientTransactionId,sourceTerminalId:this.currentSourceTerminalId};return new Promise(r=>{let t=!1,n=setTimeout(()=>{t||(t=!0,i(),r(null))},H),i=this.appToAppConfig.adapter.subscribe(s=>{if(t)return;let a=this.parseCallbackUrl(s);a&&this.matchesKnownTransactionId(a.rawParams)&&(t=!0,clearTimeout(n),i(),r(a.result))});this.appToAppConfig.adapter.openUrl(this.buildActionUrl(M,e)).catch(()=>{t||(t=!0,clearTimeout(n),i(),r(null))})})}};import{PaymentApi as te,PaymentFailureCode as U,PaymentProviderEnum as re,SimplePaymentStatus as T}from"@munchi_oy/core";var C=class{constructor(e,r,t){this.messaging=r;this.config=t;this.api=new te(void 0,"",e)}api;abortController=null;currentSessionId=null;paymentProvider=re.Viva;async processPayment(e,r){this.abortController=new AbortController,r("CONNECTING");let t={amount:e.amountCents,referenceId:e.orderRef,businessId:parseInt(this.config.storeId),currency:e.currency,displayId:e.displayId,showReceipt:!0,showTransactionResult:!0};try{let{data:n}=await this.api.initiateTerminalTransaction(t);if(this.currentSessionId=n.sessionId,this.abortController.signal.aborted)throw new Error("Aborted");r("REQUIRES_INPUT",{sessionId:n.sessionId});let i=await this.waitForPaymentCompletion(n.sessionId,e.orderRef,this.abortController.signal);return this.currentSessionId=null,i}catch(n){throw this.currentSessionId=null,n instanceof l?n:new l("NETWORK_ERROR","Failed to create Viva Intent",n)}}async waitForPaymentCompletion(e,r,t){let i=`viva.${this.config.channel.toLowerCase()}.requests.${e}`,s="payment:status-changed";return new Promise((a,o)=>{let c=!1,u=()=>{c=!0,typeof p=="function"&&p(),clearTimeout(f)},m=()=>{u(),o(new Error("Aborted"))};t.addEventListener("abort",m);let p=this.messaging.subscribe(i,s,h=>{c||h.status!==T.Pending&&(u(),t.removeEventListener("abort",m),a(this.handleSuccess(h)))}),f=setTimeout(async()=>{if(!(c||t.aborted))try{let h=await this.pollOrderStatus(e,r,this.config.storeId,t);a(this.handleSuccess(h))}catch(h){o(new l("TIMEOUT","Payment timed out and polling failed",h))}finally{t.removeEventListener("abort",m),u()}},1e4)})}async pollOrderStatus(e,r,t,n){let o=Date.now()+12e4;for(;Date.now()<o;){if(n.aborted)throw new Error("Aborted");try{let{data:c}=await this.api.getPaymentStatus({businessId:Number(t),orderId:r,provider:this.paymentProvider,referenceId:e});if(n.aborted)throw new Error("Aborted");if(c.status!==T.Pending)return c}catch(c){if(c instanceof Error&&c.message==="Aborted")throw c}await new Promise(c=>{let u=()=>{clearTimeout(m),c(void 0)};n.addEventListener("abort",u,{once:!0});let m=setTimeout(()=>{n.removeEventListener("abort",u),c(void 0)},2e3)})}throw new Error("Payment verification timed out.")}handleSuccess(e){let r=e.status===T.Success,t={success:r,status:r?"SUCCESS":"FAILED",orderId:e.orderId,errorCode:e.error?.code||(r?"":U.SystemUnknown),errorMessage:e.error?.message||(r?"":"Transaction failed without error details")};return e.transactionId&&(t.transactionId=e.transactionId),e.error?.referenceError&&(t.errorReference=e.error.referenceError),e.transaction&&(t.transaction=e.transaction),t}async cancelTransaction(e){if(!this.currentSessionId)return!1;try{let r=this.currentSessionId;return this.currentSessionId=null,await this.api.cancelVivaTransactionV2({cashRegisterId:this.config.storeId,sessionId:r}),this.abortController?.abort(),!0}catch(r){throw this.currentSessionId=null,new l("NETWORK_ERROR","Failed to cancel Viva transaction",r)}}async verifyFinalStatus(e,r){try{let{data:t}=await this.api.getPaymentStatus({businessId:Number(this.config.storeId),orderId:e.orderRef,provider:this.paymentProvider,referenceId:r}),n=t.status===T.Success,i=t.status===T.Pending,s={success:n,status:n?"SUCCESS":i?"PENDING":"FAILED",orderId:t.orderId,errorCode:t.error?.code||(n||i?"":U.SystemUnknown),errorMessage:t.error?.message||(n||i?"":"Transaction failed without error details")};return t.transactionId&&(s.transactionId=t.transactionId),t.error?.referenceError&&(s.errorReference=t.error.referenceError),t.transaction&&(s.transaction=t.transaction),s}catch(t){throw new l("NETWORK_ERROR","Failed to verify final transaction status",t)}}async refundTransaction(e,r){try{let t={amount:e.amountCents,businessId:Number(this.config.storeId),displayId:this.config.kioskId,currency:e.currency,orderReferenceId:e.orderRef,referenceId:e.originalTransactionId},{data:n}=await this.api.refundSingleVivaTransaction(t),i=n.success;return{success:i,status:i?"SUCCESS":"FAILED",orderId:e.orderRef,transactionId:n.sessionId}}catch(t){throw new l("NETWORK_ERROR","Failed to refund Viva transaction",t)}}abort(){this.abortController?.abort()}};import{PaymentApi as ne,PaymentEventType as k,PaymentFailureCode as ie,PaymentProviderEnum as se,SimplePaymentStatus as v,WorldlineApi as oe}from"@munchi_oy/core";import{isAxiosError as ae}from"axios";var A=class{constructor(e,r,t){this.messaging=r;this.config=t;this.paymentApi=new ne(void 0,"",e),this.worldlineApi=new oe(void 0,"",e)}paymentApi;worldlineApi;abortController=null;currentOperationId=null;paymentProvider=se.Worldline;async processPayment(e,r){this.abortController=new AbortController,r("CONNECTING");let t={amount:e.amountCents,businessId:Number(this.config.storeId),currency:e.currency,displayId:e.displayId,referenceId:e.orderRef,showReceipt:!0,showTransactionResult:!0,...e.options&&"tipAmount"in e.options&&typeof e.options.tipAmount=="number"?{tipAmount:e.options.tipAmount}:{}};try{let n=await this.worldlineApi.createPayment(t),i=this.extractOperationId(n.data);if(this.currentOperationId=i,this.abortController.signal.aborted)throw new Error("Aborted");r("REQUIRES_INPUT",{sessionId:i});let s=await this.waitForPaymentCompletion(i,e.orderRef,k.StatusChanged,this.abortController.signal);return this.currentOperationId=null,s}catch(n){throw this.currentOperationId=null,n instanceof l?n:this.mapWorldlineRequestError(n,"Failed to create Worldline payment")}}async cancelTransaction(e){if(!this.currentOperationId)return!1;let r={businessId:Number(this.config.storeId),targetOperationId:this.currentOperationId};try{return await this.worldlineApi.cancelPayment(r),!0}catch(t){throw this.mapWorldlineRequestError(t,"Failed to cancel Worldline transaction")}}async refundTransaction(e,r){this.abortController=new AbortController,r("CONNECTING");let t={amount:e.amountCents,businessId:Number(this.config.storeId),currency:e.currency,displayId:e.displayId,orderReferenceId:e.orderRef,referenceId:e.originalTransactionId};try{let n=await this.worldlineApi.createRefund(t),i=this.extractOperationId(n.data);if(this.currentOperationId=i,this.abortController.signal.aborted)throw new Error("Aborted");r("REQUIRES_INPUT",{sessionId:i});let s=await this.waitForPaymentCompletion(i,e.orderRef,k.RefundStatusChanged,this.abortController.signal);return this.currentOperationId=null,s}catch(n){throw this.currentOperationId=null,n instanceof l?n:this.mapWorldlineRequestError(n,"Failed to refund Worldline transaction")}}async verifyFinalStatus(e,r){try{let{data:t}=await this.paymentApi.getPaymentStatus({businessId:Number(this.config.storeId),orderId:e.orderRef,provider:this.paymentProvider,referenceId:r});return this.handlePaymentStatus(t)}catch(t){throw this.mapWorldlineRequestError(t,"Failed to verify final Worldline status")}}abort(){this.abortController?.abort()}async waitForPaymentCompletion(e,r,t,n){let i=`worldline.requests.${e}`;return new Promise((s,a)=>{let o=!1,c=()=>{o=!0,typeof m=="function"&&m(),clearTimeout(p)},u=()=>{c(),a(new l("CANCELLED","Transaction cancelled"))};n.addEventListener("abort",u);let m=this.messaging.subscribe(i,t,f=>{o||f.status===v.Pending||(c(),n.removeEventListener("abort",u),s(this.handlePaymentStatus(f)))}),p=setTimeout(async()=>{if(!(o||n.aborted))try{let f=await this.pollOrderStatus(e,r,this.config.storeId,n);s(this.handlePaymentStatus(f))}catch(f){a(new l("TIMEOUT","Payment timed out and polling failed",f))}finally{n.removeEventListener("abort",u),c()}},1e4)})}async pollOrderStatus(e,r,t,n){let a=Date.now()+12e4;for(;Date.now()<a;){if(n.aborted)throw new Error("Aborted");try{let{data:o}=await this.paymentApi.getPaymentStatus({businessId:Number(t),orderId:r,provider:this.paymentProvider,referenceId:e});if(n.aborted)throw new Error("Aborted");if(o.status!==v.Pending)return o}catch(o){if(o instanceof Error&&o.message==="Aborted")throw o}await new Promise(o=>{let c=()=>{clearTimeout(u),o(void 0)};n.addEventListener("abort",c,{once:!0});let u=setTimeout(()=>{n.removeEventListener("abort",c),o(void 0)},2e3)})}throw new Error("Payment verification timed out.")}handlePaymentStatus(e){let r=e.status===v.Success,t=e.status===v.Pending,n={success:r,status:r?"SUCCESS":t?"PENDING":"FAILED",orderId:e.orderId,errorCode:e.error?.code||(r||t?"":ie.SystemUnknown),errorMessage:e.error?.message||(r||t?"":"Transaction failed without error details")};return e.transactionId&&(n.transactionId=e.transactionId),e.error?.referenceError&&(n.errorReference=e.error.referenceError),e.transaction&&(n.transaction=e.transaction),n}extractOperationId(e){let r=typeof e=="object"&&e!==null&&"operationId"in e&&typeof e.operationId=="string"?e.operationId:null;if(!r)throw new Error("operationId is missing from response.");return r}mapWorldlineRequestError(e,r){if(ae(e)){if(e.response?.status===400||e.response?.status===409)return new l("TERMINAL_BUSY",r,e);if(e.response?.status===404)return new l("TERMINAL_OFFLINE",r,e)}return new l("NETWORK_ERROR",r,e)}};var O=class d{strategy;axios;messaging;timeoutMs;logger;_currentState="IDLE";_listeners=[];_cancellationIntent=!1;_currentSessionId;_autoResetTimer;autoResetOptions;appToAppConfig;static TERMINAL_STATES=["SUCCESS","FAILED","INTERNAL_ERROR"];static RESTING_STATES=["IDLE",...d.TERMINAL_STATES];constructor(e,r,t,n={},i){this.axios=e,this.messaging=r,this.logger=n.logger,this.timeoutMs=n.timeoutMs||3e4,this.autoResetOptions=n.autoResetOnPaymentComplete,this.appToAppConfig=n.appToApp,this.strategy=i??this.resolveStrategy(t)}get version(){return D}get currentState(){return this._currentState}generateErrorResult(e,r,t){return{success:!1,status:"ERROR",errorCode:this.normalizeErrorCode(r),errorMessage:t,orderId:e}}normalizeErrorCode(e){return e?e.includes(".")?e:{CANCELLED:y.PaymentCancelledByUser,DECLINED:y.PaymentDeclined,TERMINAL_BUSY:y.TerminalBusy,TERMINAL_OFFLINE:y.TerminalOffline,TIMEOUT:y.TerminalTimeout,NETWORK_ERROR:y.SystemProviderError,STRATEGY_ERROR:y.SystemProviderError,MISSING_CONFIG:y.SystemUnknown,INVALID_AMOUNT:y.SystemUnknown,UNKNOWN:y.SystemUnknown}[e]??y.SystemUnknown:y.SystemUnknown}subscribe=e=>(this._listeners.push(e),e(this._currentState),()=>{this._listeners=this._listeners.filter(r=>r!==e)});transitionTo(e){if(this._currentState===e)return;if(e==="IDLE"){this.cancelAutoReset(),this._currentState=e,this._listeners.forEach(t=>t(e));return}if(d.TERMINAL_STATES.includes(this._currentState)){let t=`Invalid State Transition: Attempted to move from terminal state ${this._currentState} to ${e}`;throw this.logger?.error(t),this._currentState!=="INTERNAL_ERROR"&&(this._currentState="INTERNAL_ERROR",this._listeners.forEach(n=>n(this._currentState))),new l("UNKNOWN",t)}this._currentState=e,d.TERMINAL_STATES.includes(e)&&this.scheduleAutoReset(e),this._listeners.forEach(t=>t(e))}_resetScheduledAt;get nextAutoResetAt(){return this._resetScheduledAt}cancelAutoReset(){this._autoResetTimer&&(clearTimeout(this._autoResetTimer),this._autoResetTimer=void 0),this._resetScheduledAt=void 0}scheduleAutoReset(e){if(!this.autoResetOptions)return;let t=e==="SUCCESS"?this.autoResetOptions.successDelayMs??5e3:this.autoResetOptions.failureDelayMs??5e3;this.logger?.info(`Scheduling auto-reset to IDLE in ${t}ms`),this._resetScheduledAt=Date.now()+t,this._autoResetTimer=setTimeout(()=>{this.logger?.info("Auto-reset triggered"),this.reset()},t)}resolveStrategy(e){switch(e.provider){case N.Nets:return new E(this.axios,this.messaging,e);case N.Worldline:return new A(this.axios,this.messaging,e);case N.Viva:return this.appToAppConfig?.enabled?new b(this.axios,this.messaging,e,this.appToAppConfig):new C(this.axios,this.messaging,e);default:return new C(this.axios,this.messaging,e)}}initiateTransaction=async(e,r)=>{let t=r??{},n=e.orderRef;if(!d.RESTING_STATES.includes(this._currentState))return this.generateErrorResult(e.orderRef,"UNKNOWN","A transaction is already in progress");let s=Date.now();if(this._cancellationIntent=!1,this._currentSessionId=void 0,this.transitionTo("IDLE"),e.amountCents<=0)return this.generateErrorResult(e.orderRef,"INVALID_AMOUNT","Amount must be greater than 0");try{let a=(m,p)=>{p?.sessionId&&(this._currentSessionId=p.sessionId),m!=="FAILED"&&(this.transitionTo(m),this.fireStateCallback(m,t,n))},o=this.strategy.processPayment(e,a),u=(this.strategy.getExecutionMode?.()??"managed")==="callback_driven"?await o:await Promise.race([o,new Promise((m,p)=>{setTimeout(()=>{p(new l("TIMEOUT","Transaction timed out"))},this.timeoutMs)})]);if(u.success)this.transitionTo("SUCCESS"),this.safeFireCallback(()=>t.onSuccess?.(u));else{if(this._cancellationIntent)return await this.handleTransactionError(e,new Error("Aborted after resolution"),t);this.transitionTo("FAILED"),this.safeFireCallback(()=>t.onError?.(u))}return this.logger?.info("Transaction completed successfully",{orderId:e.orderRef,durationMs:Date.now()-s}),u}catch(a){return this.logger?.warn("Transaction interrupted. Handling final status...",{error:a}),await this.handleTransactionError(e,a,t)}};async handleTransactionError(e,r,t={}){let n=r instanceof l&&r.code==="TIMEOUT";if(!this._cancellationIntent&&!n&&(this.transitionTo("VERIFYING"),this.safeFireCallback(()=>t.onVerifying?.({orderRef:e.orderRef,refPaymentId:this._currentSessionId}))),this._cancellationIntent){try{if(this._currentSessionId){let s=await this.verifyWithRetry(e,this._currentSessionId);if(s.success)return this.transitionTo("SUCCESS"),this.safeFireCallback(()=>t.onSuccess?.(s)),s}}catch(s){this.logger?.warn("Final status verification failed during cancellation",{err:s})}return this.transitionTo("FAILED"),this.safeFireCallback(()=>t.onCancelled?.({orderRef:e.orderRef,refPaymentId:this._currentSessionId})),{success:!1,status:"CANCELLED",errorCode:this.normalizeErrorCode("CANCELLED"),orderId:e.orderRef,...this._currentSessionId?{transactionId:this._currentSessionId}:{}}}let i;if(this.strategy.abort(),this._currentSessionId)try{let s=await this.verifyWithRetry(e,this._currentSessionId);if(s.success)return this.transitionTo("SUCCESS"),this.safeFireCallback(()=>t.onSuccess?.(s)),s;i=s}catch(s){this.logger?.warn("Failed to get detailed error from verifyFinalStatus",{verifyErr:s}),i=this.buildErrorResultFromException(e.orderRef,s)}else i=this.buildErrorResultFromException(e.orderRef,r);return this.transitionTo("FAILED"),this.safeFireCallback(()=>t.onError?.(i)),i}static VERIFY_TIMEOUT_MS=1e4;static VERIFY_MAX_RETRIES=3;static VERIFY_RETRY_DELAY_MS=1500;async verifyWithRetry(e,r){let t,n=!0;for(let a=1;a<=d.VERIFY_MAX_RETRIES;a++)try{let o=await Promise.race([this.strategy.verifyFinalStatus(e,r),new Promise((c,u)=>setTimeout(()=>u(new Error("Verify timed out")),d.VERIFY_TIMEOUT_MS))]);if(o.status==="PENDING"){t=new Error("Verify returned pending status"),this.logger?.warn(`verifyFinalStatus attempt ${a}/${d.VERIFY_MAX_RETRIES} returned pending status`),a<d.VERIFY_MAX_RETRIES&&await new Promise(c=>setTimeout(c,d.VERIFY_RETRY_DELAY_MS));continue}return o}catch(o){t=o,o instanceof Error&&o.message==="Verify timed out"||(n=!1),this.logger?.warn(`verifyFinalStatus attempt ${a}/${d.VERIFY_MAX_RETRIES} failed`,{err:o}),a<d.VERIFY_MAX_RETRIES&&await new Promise(u=>setTimeout(u,d.VERIFY_RETRY_DELAY_MS))}let i=t instanceof Error?t.message:"Verify retries exhausted",s=n?y.PaymentTimeout:y.PaymentUnknown;throw new l(s,i)}buildErrorResultFromException(e,r){return r instanceof l?this.generateErrorResult(e,r.code,r.message):this.generateErrorResult(e,"UNKNOWN",r instanceof Error?r.message:"Unknown fatal error")}fireStateCallback(e,r,t){let n={orderRef:t,refPaymentId:this._currentSessionId};switch(e){case"CONNECTING":this.safeFireCallback(()=>r.onConnecting?.(n));break;case"REQUIRES_INPUT":this.safeFireCallback(()=>r.onRequiresInput?.(n));break;case"PROCESSING":this.safeFireCallback(()=>r.onProcessing?.(n));break}}safeFireCallback(e){try{e()}catch(r){this.logger?.warn("Callback execution failed",{error:r})}}cancel=async()=>{if(this.logger?.info("Attempting cancellation"),d.TERMINAL_STATES.includes(this._currentState))return this.logger?.warn("Cannot cancel: Transaction already in terminal state",{state:this._currentState}),!1;if(!this._currentSessionId&&this._currentState==="IDLE")return this.logger?.warn("Cannot cancel: No active session to cancel",{state:this._currentState}),!1;this._cancellationIntent=!0,this.transitionTo("VERIFYING");try{return await this.strategy.cancelTransaction(r=>this.transitionTo(r))}catch(e){return this.logger?.error("Cancellation command failed",e),!1}};reset=()=>{d.TERMINAL_STATES.includes(this._currentState)&&(this._currentSessionId=void 0,this._cancellationIntent=!1,this.transitionTo("IDLE"))};refund=async(e,r)=>{let t=r??{};if(this.logger?.info("Initiating refund",{orderRef:e.orderRef}),this._currentSessionId=void 0,this._cancellationIntent=!1,!d.RESTING_STATES.includes(this._currentState))return this.generateErrorResult(e.orderRef,"UNKNOWN","A transaction is already in progress");this.transitionTo("IDLE");try{let i=(a,o)=>{o?.sessionId&&(this._currentSessionId=o.sessionId),a!=="FAILED"&&(this.transitionTo(a),this.fireStateCallback(a,t,e.orderRef))},s=await this.strategy.refundTransaction(e,i);return s.success?(this.transitionTo("SUCCESS"),this.safeFireCallback(()=>t.onSuccess?.(s))):this._cancellationIntent||s.status==="CANCELLED"?(this.transitionTo("FAILED"),this.safeFireCallback(()=>t.onCancelled?.({orderRef:e.orderRef,refPaymentId:this._currentSessionId}))):(this.transitionTo("FAILED"),this.safeFireCallback(()=>t.onError?.(s))),this.logger?.info("Refund completed",{success:s.success,orderRef:e.orderRef}),s}catch(i){if(this.logger?.error("Refund failed",i),this._cancellationIntent){try{if(this._currentSessionId){let a=await this.verifyWithRetry(e,this._currentSessionId);return a.success?(this.transitionTo("SUCCESS"),this.safeFireCallback(()=>t.onSuccess?.(a)),a):a.status==="CANCELLED"?(this.transitionTo("FAILED"),this.safeFireCallback(()=>t.onCancelled?.({orderRef:e.orderRef,refPaymentId:this._currentSessionId})),a):(this.transitionTo("FAILED"),this.safeFireCallback(()=>t.onError?.(a)),a)}}catch(a){this.logger?.warn("Refund final status verification failed",{verifyError:a})}return this.transitionTo("FAILED"),this.safeFireCallback(()=>t.onCancelled?.({orderRef:e.orderRef,refPaymentId:this._currentSessionId})),{success:!1,status:"CANCELLED",errorCode:this.normalizeErrorCode("CANCELLED"),orderId:e.orderRef,...this._currentSessionId?{transactionId:this._currentSessionId}:{}}}this.transitionTo("FAILED");let s=this.generateErrorResult(e.orderRef,"UNKNOWN",i instanceof Error?i.message:"Refund failed");return this.safeFireCallback(()=>t.onError?.(s)),s}}};var ce=(n=>(n.CONNECTING="CONNECTING",n.CONNECTED="CONNECTED",n.OFFLINE="OFFLINE",n.DISCONNECTED="DISCONNECTED",n))(ce||{});export{ce as AppReaderStatus,O as MunchiPaymentSDK,R as PaymentInteractionState,I as SdkPaymentStatus};
|
|
@@ -15,6 +15,7 @@ export declare class MunchiPaymentSDK implements IMunchiPaymentSDK {
|
|
|
15
15
|
private _currentSessionId;
|
|
16
16
|
private _autoResetTimer;
|
|
17
17
|
private autoResetOptions;
|
|
18
|
+
private appToAppConfig;
|
|
18
19
|
private static readonly TERMINAL_STATES;
|
|
19
20
|
private static readonly RESTING_STATES;
|
|
20
21
|
constructor(axios: AxiosInstance, messaging: IMessagingAdapter, config: PaymentTerminalConfig, options?: SDKOptions, strategy?: IPaymentStrategy);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MunchiPaymentSDK.d.ts","sourceRoot":"","sources":["../../src/MunchiPaymentSDK.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,OAAO,CAAC;AAG3C,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,+BAA+B,CAAC;
|
|
1
|
+
{"version":3,"file":"MunchiPaymentSDK.d.ts","sourceRoot":"","sources":["../../src/MunchiPaymentSDK.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,OAAO,CAAC;AAG3C,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,+BAA+B,CAAC;AAMtE,OAAO,EACL,KAAK,iBAAiB,EACtB,KAAK,iBAAiB,EACtB,uBAAuB,EACvB,KAAK,aAAa,EAClB,KAAK,qBAAqB,EAC1B,KAAK,aAAa,EAClB,KAAK,cAAc,IAAI,iBAAiB,EAExC,KAAK,kBAAkB,EACxB,MAAM,iBAAiB,CAAC;AACzB,OAAO,KAAK,EAA2B,UAAU,EAAE,MAAM,aAAa,CAAC;AAEvE,KAAK,aAAa,GAAG,CAAC,KAAK,EAAE,uBAAuB,KAAK,IAAI,CAAC;AAE9D,qBAAa,gBAAiB,YAAW,iBAAiB;IACxD,OAAO,CAAC,QAAQ,CAAmB;IACnC,OAAO,CAAC,KAAK,CAAgB;IAC7B,OAAO,CAAC,SAAS,CAAoB;IACrC,OAAO,CAAC,SAAS,CAAS;IAC1B,OAAO,CAAC,MAAM,CAAsB;IACpC,OAAO,CAAC,aAAa,CAAyD;IAC9E,OAAO,CAAC,UAAU,CAAuB;IACzC,OAAO,CAAC,mBAAmB,CAAS;IACpC,OAAO,CAAC,iBAAiB,CAAqB;IAC9C,OAAO,CAAC,eAAe,CAA4C;IACnE,OAAO,CAAC,gBAAgB,CAA2C;IACnE,OAAO,CAAC,cAAc,CAA6B;IAEnD,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,eAAe,CAIrC;IAEF,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,cAAc,CAGpC;gBAGA,KAAK,EAAE,aAAa,EACpB,SAAS,EAAE,iBAAiB,EAC5B,MAAM,EAAE,qBAAqB,EAC7B,OAAO,GAAE,UAAe,EACxB,QAAQ,CAAC,EAAE,gBAAgB;IAW7B,IAAW,OAAO,WAEjB;IAED,IAAW,YAAY,4BAEtB;IAED,OAAO,CAAC,mBAAmB;IAc3B,OAAO,CAAC,kBAAkB;IAoBnB,SAAS,GAAI,UAAU,aAAa,KAAG,CAAC,MAAM,IAAI,CAAC,CAOxD;IAEF,OAAO,CAAC,YAAY;IAmCpB,OAAO,CAAC,iBAAiB,CAAqB;IAE9C,IAAW,eAAe,IAAI,MAAM,GAAG,SAAS,CAE/C;IAED,OAAO,CAAC,eAAe;IAQvB,OAAO,CAAC,iBAAiB;IAqBzB,OAAO,CAAC,eAAe;IAsBhB,mBAAmB,GACxB,QAAQ,iBAAiB,EACzB,UAAU,kBAAkB,KAC3B,OAAO,CAAC,aAAa,CAAC,CAgGvB;YAEY,sBAAsB;IAqGpC,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,iBAAiB,CAAS;IAClD,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,kBAAkB,CAAK;IAC/C,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,qBAAqB,CAAQ;YAEvC,eAAe;IAwD7B,OAAO,CAAC,6BAA6B;IAarC,OAAO,CAAC,iBAAiB;IAsBzB,OAAO,CAAC,gBAAgB;IAQjB,MAAM,QAAa,OAAO,CAAC,OAAO,CAAC,CAyCxC;IAEK,KAAK,QAAO,IAAI,CAMrB;IAEK,MAAM,GACX,QAAQ,aAAa,EACrB,UAAU,kBAAkB,KAC3B,OAAO,CAAC,aAAa,CAAC,CAqIvB;CACH"}
|
|
@@ -1,5 +1,10 @@
|
|
|
1
1
|
import type { PaymentInteractionState, PaymentRequest, PaymentResult, RefundRequest } from "../types/payment";
|
|
2
|
+
export declare enum StrategyExecutionMode {
|
|
3
|
+
Managed = "managed",
|
|
4
|
+
CallbackDriven = "callback_driven"
|
|
5
|
+
}
|
|
2
6
|
export interface IPaymentStrategy {
|
|
7
|
+
getExecutionMode?(): StrategyExecutionMode;
|
|
3
8
|
processPayment(request: PaymentRequest, onStateChange: (state: PaymentInteractionState, detail?: {
|
|
4
9
|
sessionId?: string;
|
|
5
10
|
}) => void): Promise<PaymentResult>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"IPaymentStrategy.d.ts","sourceRoot":"","sources":["../../../src/strategies/IPaymentStrategy.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,uBAAuB,EACvB,cAAc,EACd,aAAa,EACb,aAAa,EACd,MAAM,kBAAkB,CAAC;AAE1B,MAAM,WAAW,gBAAgB;
|
|
1
|
+
{"version":3,"file":"IPaymentStrategy.d.ts","sourceRoot":"","sources":["../../../src/strategies/IPaymentStrategy.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,uBAAuB,EACvB,cAAc,EACd,aAAa,EACb,aAAa,EACd,MAAM,kBAAkB,CAAC;AAE1B,oBAAY,qBAAqB;IAC/B,OAAO,YAAY;IACnB,cAAc,oBAAoB;CACnC;AAED,MAAM,WAAW,gBAAgB;IAC/B,gBAAgB,CAAC,IAAI,qBAAqB,CAAC;IAE3C,cAAc,CACZ,OAAO,EAAE,cAAc,EACvB,aAAa,EAAE,CAAC,KAAK,EAAE,uBAAuB,EAAE,MAAM,CAAC,EAAE;QAAE,SAAS,CAAC,EAAE,MAAM,CAAA;KAAE,KAAK,IAAI,GACvF,OAAO,CAAC,aAAa,CAAC,CAAC;IAC1B,iBAAiB,CACf,aAAa,EAAE,CAAC,KAAK,EAAE,uBAAuB,KAAK,IAAI,GACtD,OAAO,CAAC,OAAO,CAAC,CAAC;IACpB,iBAAiB,CACf,OAAO,EAAE,aAAa,EACtB,aAAa,EAAE,CAAC,KAAK,EAAE,uBAAuB,EAAE,MAAM,CAAC,EAAE;QAAE,SAAS,CAAC,EAAE,MAAM,CAAA;KAAE,KAAK,IAAI,GACvF,OAAO,CAAC,aAAa,CAAC,CAAC;IAC1B,iBAAiB,CAAC,OAAO,EAAE,cAAc,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,CAAC,CAAC;IACtF,KAAK,IAAI,IAAI,CAAC;CACf"}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import type { AxiosInstance } from "axios";
|
|
2
|
+
import { PaymentInteractionState, type PaymentRequest, type PaymentResult, type PaymentTerminalConfig, type RefundRequest } from "../types/payment";
|
|
3
|
+
import type { AppToAppConfig } from "../types/sdk";
|
|
4
|
+
import { type IPaymentStrategy, StrategyExecutionMode } from "./IPaymentStrategy";
|
|
5
|
+
export declare class VivaAppToAppStrategy implements IPaymentStrategy {
|
|
6
|
+
private config;
|
|
7
|
+
private appToAppConfig;
|
|
8
|
+
private api;
|
|
9
|
+
private paymentApi;
|
|
10
|
+
private abortController;
|
|
11
|
+
private currentClientTransactionId;
|
|
12
|
+
private currentIsvClientTransactionId;
|
|
13
|
+
private currentCurrency;
|
|
14
|
+
private currentOrderRef;
|
|
15
|
+
private currentSourceTerminalId;
|
|
16
|
+
private latestResult;
|
|
17
|
+
private paymentApiWithReference;
|
|
18
|
+
private wasCancelled;
|
|
19
|
+
constructor(axios: AxiosInstance, _messaging: unknown, config: PaymentTerminalConfig, appToAppConfig: AppToAppConfig);
|
|
20
|
+
getExecutionMode(): StrategyExecutionMode;
|
|
21
|
+
processPayment(request: PaymentRequest, onStateChange: (state: PaymentInteractionState, detail?: {
|
|
22
|
+
sessionId?: string;
|
|
23
|
+
}) => void): Promise<PaymentResult>;
|
|
24
|
+
cancelTransaction(_onStateChange: (state: PaymentInteractionState) => void): Promise<boolean>;
|
|
25
|
+
refundTransaction(request: RefundRequest, onStateChange: (state: PaymentInteractionState, detail?: {
|
|
26
|
+
sessionId?: string;
|
|
27
|
+
}) => void): Promise<PaymentResult>;
|
|
28
|
+
verifyFinalStatus(_request: PaymentRequest, sessionId: string): Promise<PaymentResult>;
|
|
29
|
+
abort(): void;
|
|
30
|
+
private runAction;
|
|
31
|
+
private buildCreatePaymentPayload;
|
|
32
|
+
private buildLaunchParams;
|
|
33
|
+
private buildRefundLaunchParams;
|
|
34
|
+
private fetchPaymentReference;
|
|
35
|
+
private extractPaymentReferenceContext;
|
|
36
|
+
private readReferenceValue;
|
|
37
|
+
private buildActionUrl;
|
|
38
|
+
private parseCallbackUrl;
|
|
39
|
+
private matchesCallbackBase;
|
|
40
|
+
private matchesKnownTransactionId;
|
|
41
|
+
private resolveFailureCode;
|
|
42
|
+
private isSuccessfulCallback;
|
|
43
|
+
private isTransactionDetailsAction;
|
|
44
|
+
private isCancelledCallback;
|
|
45
|
+
private extractErrorReferenceFromMessage;
|
|
46
|
+
private mapCallbackToTransaction;
|
|
47
|
+
private getVivaPaymentMethodType;
|
|
48
|
+
private buildFeesFromTip;
|
|
49
|
+
private lookupTransactionDetails;
|
|
50
|
+
}
|
|
51
|
+
//# sourceMappingURL=VivaAppToAppStrategy.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"VivaAppToAppStrategy.d.ts","sourceRoot":"","sources":["../../../src/strategies/VivaAppToAppStrategy.ts"],"names":[],"mappings":"AAYA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,OAAO,CAAC;AAG3C,OAAO,EACL,uBAAuB,EACvB,KAAK,cAAc,EACnB,KAAK,aAAa,EAClB,KAAK,qBAAqB,EAC1B,KAAK,aAAa,EAGnB,MAAM,kBAAkB,CAAC;AAC1B,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAEnD,OAAO,EACL,KAAK,gBAAgB,EACrB,qBAAqB,EACtB,MAAM,oBAAoB,CAAC;AA+B5B,qBAAa,oBAAqB,YAAW,gBAAgB;IAoBzD,OAAO,CAAC,MAAM;IACd,OAAO,CAAC,cAAc;IApBxB,OAAO,CAAC,GAAG,CAAU;IACrB,OAAO,CAAC,UAAU,CAAa;IAC/B,OAAO,CAAC,eAAe,CAAgC;IACvD,OAAO,CAAC,0BAA0B,CAAuB;IACzD,OAAO,CAAC,6BAA6B,CAAuB;IAC5D,OAAO,CAAC,eAAe,CAA2C;IAClE,OAAO,CAAC,eAAe,CAAuB;IAC9C,OAAO,CAAC,uBAAuB,CAAuB;IACtD,OAAO,CAAC,YAAY,CAA8B;IAClD,OAAO,CAAC,uBAAuB,CAI7B;IACF,OAAO,CAAC,YAAY,CAAS;gBAG3B,KAAK,EAAE,aAAa,EACpB,UAAU,EAAE,OAAO,EACX,MAAM,EAAE,qBAAqB,EAC7B,cAAc,EAAE,cAAc;IAWxC,gBAAgB;IAIV,cAAc,CAClB,OAAO,EAAE,cAAc,EACvB,aAAa,EAAE,CACb,KAAK,EAAE,uBAAuB,EAC9B,MAAM,CAAC,EAAE;QAAE,SAAS,CAAC,EAAE,MAAM,CAAA;KAAE,KAC5B,IAAI,GACR,OAAO,CAAC,aAAa,CAAC;IA8BnB,iBAAiB,CACrB,cAAc,EAAE,CAAC,KAAK,EAAE,uBAAuB,KAAK,IAAI,GACvD,OAAO,CAAC,OAAO,CAAC;IAgCb,iBAAiB,CACrB,OAAO,EAAE,aAAa,EACtB,aAAa,EAAE,CACb,KAAK,EAAE,uBAAuB,EAC9B,MAAM,CAAC,EAAE;QAAE,SAAS,CAAC,EAAE,MAAM,CAAA;KAAE,KAC5B,IAAI,GACR,OAAO,CAAC,aAAa,CAAC;IAanB,iBAAiB,CACrB,QAAQ,EAAE,cAAc,EACxB,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,aAAa,CAAC;IAwBzB,KAAK,IAAI,IAAI;YAIC,SAAS;IAqGvB,OAAO,CAAC,yBAAyB;IAqBjC,OAAO,CAAC,iBAAiB;IAczB,OAAO,CAAC,uBAAuB;YAyDjB,qBAAqB;IAgBnC,OAAO,CAAC,8BAA8B;IAqDtC,OAAO,CAAC,kBAAkB;IAS1B,OAAO,CAAC,cAAc;IAiBtB,OAAO,CAAC,gBAAgB;IAyDxB,OAAO,CAAC,mBAAmB;IAW3B,OAAO,CAAC,yBAAyB;IAsBjC,OAAO,CAAC,kBAAkB;IAmC1B,OAAO,CAAC,oBAAoB;IAc5B,OAAO,CAAC,0BAA0B;IAKlC,OAAO,CAAC,mBAAmB;IAe3B,OAAO,CAAC,gCAAgC;IAWxC,OAAO,CAAC,wBAAwB;IAkChC,OAAO,CAAC,wBAAwB;IAsBhC,OAAO,CAAC,gBAAgB;YAoBV,wBAAwB;CA2DvC"}
|
|
@@ -52,7 +52,9 @@ export interface RefundRequest {
|
|
|
52
52
|
/**
|
|
53
53
|
* The ID of the original payment transaction.
|
|
54
54
|
* Maps to:
|
|
55
|
-
* - Viva:
|
|
55
|
+
* - Viva app-to-app: the original transaction referenceId / clientTransactionId.
|
|
56
|
+
* If available at a higher layer, provider-specific identifiers such as
|
|
57
|
+
* orderCode, shortOrderCode, or referenceNumber may produce a more direct referenced refund.
|
|
56
58
|
* - Nets: preAuthorizationInfo (or reference)
|
|
57
59
|
*/
|
|
58
60
|
originalTransactionId: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"payment.d.ts","sourceRoot":"","sources":["../../../src/types/payment.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACR,YAAY,EACZ,eAAe,EACf,YAAY,EACZ,cAAc,EACjB,MAAM,iBAAiB,CAAC;AAEzB,MAAM,MAAM,kBAAkB,GAAG,IAAI,CACnC,cAAc,EACd,IAAI,GAAG,WAAW,GAAG,UAAU,CAChC,CAAC;AAEF,oBAAY,gBAAgB;IAC1B,OAAO,YAAY;IACnB,OAAO,YAAY;IACnB,QAAQ,aAAa;IACrB,MAAM,WAAW;IACjB,SAAS,cAAc;IACvB,KAAK,UAAU;CAChB;AAED,oBAAY,uBAAuB;IACjC,IAAI,SAAS;IACb,UAAU,eAAe;IACzB,cAAc,mBAAmB;IACjC,UAAU,eAAe;IACzB,OAAO,YAAY;IACnB,MAAM,WAAW;IACjB,cAAc,mBAAmB;IACjC,SAAS,cAAc;CACxB;AAED,MAAM,WAAW,WAAW;IAC1B,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,WAAW;IAC1B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,gBAAgB;IAC/B,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,iBAAkB,SAAQ,WAAW;CAErD;AAED,MAAM,WAAW,iBAAkB,SAAQ,WAAW;IACpD,cAAc,CAAC,EAAE,OAAO,CAAC;CAC1B;AAED,MAAM,WAAW,sBAAuB,SAAQ,gBAAgB;CAE/D;AAED,MAAM,WAAW,cAAc;IAC7B,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,YAAY,CAAC;IACvB,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE,WAAW,GAAG,WAAW,GAAG,gBAAgB,CAAC;CACxD;AAED,MAAM,WAAW,aAAa;IAC5B,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,YAAY,CAAC;IACvB,SAAS,EAAE,MAAM,CAAC;IAClB
|
|
1
|
+
{"version":3,"file":"payment.d.ts","sourceRoot":"","sources":["../../../src/types/payment.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACR,YAAY,EACZ,eAAe,EACf,YAAY,EACZ,cAAc,EACjB,MAAM,iBAAiB,CAAC;AAEzB,MAAM,MAAM,kBAAkB,GAAG,IAAI,CACnC,cAAc,EACd,IAAI,GAAG,WAAW,GAAG,UAAU,CAChC,CAAC;AAEF,oBAAY,gBAAgB;IAC1B,OAAO,YAAY;IACnB,OAAO,YAAY;IACnB,QAAQ,aAAa;IACrB,MAAM,WAAW;IACjB,SAAS,cAAc;IACvB,KAAK,UAAU;CAChB;AAED,oBAAY,uBAAuB;IACjC,IAAI,SAAS;IACb,UAAU,eAAe;IACzB,cAAc,mBAAmB;IACjC,UAAU,eAAe;IACzB,OAAO,YAAY;IACnB,MAAM,WAAW;IACjB,cAAc,mBAAmB;IACjC,SAAS,cAAc;CACxB;AAED,MAAM,WAAW,WAAW;IAC1B,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,WAAW;IAC1B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,gBAAgB;IAC/B,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,iBAAkB,SAAQ,WAAW;CAErD;AAED,MAAM,WAAW,iBAAkB,SAAQ,WAAW;IACpD,cAAc,CAAC,EAAE,OAAO,CAAC;CAC1B;AAED,MAAM,WAAW,sBAAuB,SAAQ,gBAAgB;CAE/D;AAED,MAAM,WAAW,cAAc;IAC7B,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,YAAY,CAAC;IACvB,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE,WAAW,GAAG,WAAW,GAAG,gBAAgB,CAAC;CACxD;AAED,MAAM,WAAW,aAAa;IAC5B,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,YAAY,CAAC;IACvB,SAAS,EAAE,MAAM,CAAC;IAClB;;;;;;;OAOG;IACH,qBAAqB,EAAE,MAAM,CAAC;IAC9B,OAAO,CAAC,EAAE,iBAAiB,GAAG,iBAAiB,GAAG,sBAAsB,CAAC;CAC1E;AAED,MAAM,WAAW,qBAAqB;IACpC,OAAO,EAAE,YAAY,CAAC;IACtB,QAAQ,CAAC,EAAE,eAAe,GAAG,IAAI,CAAC;IAClC,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,aAAa;IAC5B,OAAO,EAAE,OAAO,CAAC;IACjB,MAAM,EAAE,gBAAgB,CAAC;IACzB,OAAO,EAAE,MAAM,CAAC;IAChB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,WAAW,CAAC,EAAE,cAAc,CAAC;CAC9B;AAED,MAAM,WAAW,kBAAkB;IACjC,YAAY,CAAC,EAAE,CAAC,GAAG,EAAE;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,YAAY,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;KAAE,KAAK,IAAI,CAAC;IACtF,eAAe,CAAC,EAAE,CAAC,GAAG,EAAE;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,YAAY,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;KAAE,KAAK,IAAI,CAAC;IACzF,YAAY,CAAC,EAAE,CAAC,GAAG,EAAE;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,YAAY,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;KAAE,KAAK,IAAI,CAAC;IACtF,WAAW,CAAC,EAAE,CAAC,GAAG,EAAE;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,YAAY,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;KAAE,KAAK,IAAI,CAAC;IACrF,SAAS,CAAC,EAAE,CAAC,MAAM,EAAE,aAAa,KAAK,IAAI,CAAC;IAC5C,OAAO,CAAC,EAAE,CAAC,MAAM,EAAE,aAAa,KAAK,IAAI,CAAC;IAC1C,WAAW,CAAC,EAAE,CAAC,GAAG,EAAE;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,YAAY,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;KAAE,KAAK,IAAI,CAAC;CACtF;AAED,MAAM,WAAW,iBAAiB;IAChC,SAAS,CAAC,CAAC,EACT,OAAO,EAAE,MAAM,EACf,KAAK,EAAE,MAAM,EACb,SAAS,EAAE,CAAC,IAAI,EAAE,CAAC,KAAK,IAAI,GAC3B,MAAM,IAAI,CAAC;CACf;AAED,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,YAAY,EAAE,uBAAuB,CAAC;IAC/C,QAAQ,CAAC,eAAe,EAAE,MAAM,GAAG,SAAS,CAAC;IAC7C,SAAS,CAAC,QAAQ,EAAE,CAAC,KAAK,EAAE,uBAAuB,KAAK,IAAI,GAAG,MAAM,IAAI,CAAC;IAC1E,mBAAmB,CACjB,MAAM,EAAE,cAAc,EACtB,OAAO,CAAC,EAAE,kBAAkB,GAC3B,OAAO,CAAC,aAAa,CAAC,CAAC;IAC1B,MAAM,IAAI,OAAO,CAAC,OAAO,CAAC,CAAC;IAC3B,MAAM,CAAC,MAAM,EAAE,aAAa,EAAE,OAAO,CAAC,EAAE,kBAAkB,GAAG,OAAO,CAAC,aAAa,CAAC,CAAC;IACpF,KAAK,IAAI,IAAI,CAAC;CACf"}
|
package/dist/src/types/sdk.d.ts
CHANGED
|
@@ -36,6 +36,18 @@ export interface AutoResetOptions {
|
|
|
36
36
|
*/
|
|
37
37
|
failureDelayMs?: number;
|
|
38
38
|
}
|
|
39
|
+
export type AppToAppScalar = boolean | number | string;
|
|
40
|
+
export interface AppToAppAdapter {
|
|
41
|
+
openUrl(url: string): Promise<void>;
|
|
42
|
+
subscribe(listener: (url: string) => void): () => void;
|
|
43
|
+
getInitialUrl?(): Promise<string | null>;
|
|
44
|
+
}
|
|
45
|
+
export interface AppToAppConfig {
|
|
46
|
+
enabled: boolean;
|
|
47
|
+
appId: string;
|
|
48
|
+
callbackUrl: string;
|
|
49
|
+
adapter: AppToAppAdapter;
|
|
50
|
+
}
|
|
39
51
|
export interface SDKOptions {
|
|
40
52
|
timeoutMs?: number;
|
|
41
53
|
logger?: ILogger;
|
|
@@ -44,5 +56,6 @@ export interface SDKOptions {
|
|
|
44
56
|
* If provided (even as an empty object), auto-reset is enabled.
|
|
45
57
|
*/
|
|
46
58
|
autoResetOnPaymentComplete?: AutoResetOptions;
|
|
59
|
+
appToApp?: AppToAppConfig;
|
|
47
60
|
}
|
|
48
61
|
//# sourceMappingURL=sdk.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sdk.d.ts","sourceRoot":"","sources":["../../../src/types/sdk.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,WAAW,CAAC;AAE/C,MAAM,WAAW,OAAO;IACtB,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;IAC7D,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;IAC5D,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,OAAO,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;IAC9E,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;CAC7D;AAED,MAAM,WAAW,gBAAgB;IAC/B,YAAY,CAAC,EAAE,CAAC,GAAG,EAAE;QAAE,QAAQ,EAAE,MAAM,CAAA;KAAE,KAAK,IAAI,CAAC;IACnD,eAAe,CAAC,EAAE,CAAC,GAAG,EAAE;QAAE,QAAQ,EAAE,MAAM,CAAA;KAAE,KAAK,IAAI,CAAC;IACtD,YAAY,CAAC,EAAE,CAAC,GAAG,EAAE;QAAE,QAAQ,EAAE,MAAM,CAAA;KAAE,KAAK,IAAI,CAAC;IACnD,WAAW,CAAC,EAAE,CAAC,GAAG,EAAE;QAAE,QAAQ,EAAE,MAAM,CAAA;KAAE,KAAK,IAAI,CAAC;IAClD,SAAS,CAAC,EAAE,CAAC,MAAM,EAAE,aAAa,KAAK,IAAI,CAAC;IAC5C,OAAO,CAAC,EAAE,CAAC,MAAM,EAAE,aAAa,KAAK,IAAI,CAAC;IAC1C,WAAW,CAAC,EAAE,CAAC,GAAG,EAAE;QAAE,QAAQ,EAAE,MAAM,CAAA;KAAE,KAAK,IAAI,CAAC;CACnD;AAED,MAAM,WAAW,gBAAgB;IAC/B;;;OAGG;IACH,cAAc,CAAC,EAAE,MAAM,CAAC;IAExB;;;OAGG;IACH,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAED,MAAM,WAAW,UAAU;IACzB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB;;;OAGG;IACH,0BAA0B,CAAC,EAAE,gBAAgB,CAAC;
|
|
1
|
+
{"version":3,"file":"sdk.d.ts","sourceRoot":"","sources":["../../../src/types/sdk.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,WAAW,CAAC;AAE/C,MAAM,WAAW,OAAO;IACtB,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;IAC7D,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;IAC5D,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,OAAO,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;IAC9E,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;CAC7D;AAED,MAAM,WAAW,gBAAgB;IAC/B,YAAY,CAAC,EAAE,CAAC,GAAG,EAAE;QAAE,QAAQ,EAAE,MAAM,CAAA;KAAE,KAAK,IAAI,CAAC;IACnD,eAAe,CAAC,EAAE,CAAC,GAAG,EAAE;QAAE,QAAQ,EAAE,MAAM,CAAA;KAAE,KAAK,IAAI,CAAC;IACtD,YAAY,CAAC,EAAE,CAAC,GAAG,EAAE;QAAE,QAAQ,EAAE,MAAM,CAAA;KAAE,KAAK,IAAI,CAAC;IACnD,WAAW,CAAC,EAAE,CAAC,GAAG,EAAE;QAAE,QAAQ,EAAE,MAAM,CAAA;KAAE,KAAK,IAAI,CAAC;IAClD,SAAS,CAAC,EAAE,CAAC,MAAM,EAAE,aAAa,KAAK,IAAI,CAAC;IAC5C,OAAO,CAAC,EAAE,CAAC,MAAM,EAAE,aAAa,KAAK,IAAI,CAAC;IAC1C,WAAW,CAAC,EAAE,CAAC,GAAG,EAAE;QAAE,QAAQ,EAAE,MAAM,CAAA;KAAE,KAAK,IAAI,CAAC;CACnD;AAED,MAAM,WAAW,gBAAgB;IAC/B;;;OAGG;IACH,cAAc,CAAC,EAAE,MAAM,CAAC;IAExB;;;OAGG;IACH,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAED,MAAM,MAAM,cAAc,GAAG,OAAO,GAAG,MAAM,GAAG,MAAM,CAAC;AAEvD,MAAM,WAAW,eAAe;IAC9B,OAAO,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACpC,SAAS,CAAC,QAAQ,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,GAAG,MAAM,IAAI,CAAC;IACvD,aAAa,CAAC,IAAI,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;CAC1C;AAED,MAAM,WAAW,cAAc;IAC7B,OAAO,EAAE,OAAO,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE,eAAe,CAAC;CAC1B;AAED,MAAM,WAAW,UAAU;IACzB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB;;;OAGG;IACH,0BAA0B,CAAC,EAAE,gBAAgB,CAAC;IAC9C,QAAQ,CAAC,EAAE,cAAc,CAAC;CAC3B"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"parsing.d.ts","sourceRoot":"","sources":["../../../src/utils/parsing.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,YAAY,GAAI,QAAQ,MAAM,KAAG,MAO7C,CAAC;AAEF,eAAO,MAAM,kBAAkB,GAAI,QAAQ,MAAM,KAAG,MAWnD,CAAC"}
|
package/dist/src/version.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export declare const VERSION = "1.
|
|
1
|
+
export declare const VERSION = "1.5.0";
|
|
2
2
|
//# sourceMappingURL=version.d.ts.map
|