@paybyrd/threedsecure-service
Advanced tools
| <!DOCTYPE html> | ||
| <html lang="en"> | ||
| <head> | ||
| <meta charset="UTF-8"> | ||
| <meta http-equiv="X-UA-Compatible" content="IE=edge"> | ||
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> | ||
| <title>Document</title> | ||
| <style> | ||
| html, | ||
| body { | ||
| width: 100%; | ||
| height: 100vh; | ||
| padding: 0; | ||
| margin: 0; | ||
| } | ||
| .container { | ||
| width: 90%; | ||
| height: inherit; | ||
| margin: 0 auto; | ||
| background-color: gray; | ||
| } | ||
| * { | ||
| box-sizing: border-box; | ||
| } | ||
| html { | ||
| font-family: "Arial", sans-serif; | ||
| } | ||
| iframe { | ||
| width: 100%; | ||
| height: 100%; | ||
| } | ||
| form { | ||
| width: 100%; | ||
| max-width: 500px; | ||
| } | ||
| label { | ||
| margin-bottom: 8px; | ||
| display: block; | ||
| color: #40545F; | ||
| font-size: 14px; | ||
| font-weight: 700; | ||
| } | ||
| .field-wrapper { | ||
| margin-bottom: 16px; | ||
| width: 100%; | ||
| height: 40px; | ||
| padding-top: 6px; | ||
| padding-right: 12px; | ||
| padding-bottom: 6px; | ||
| padding-left: 12px; | ||
| box-shadow: 0px 0px 3px rgba(23, 31, 39, 0.3); | ||
| border-width: 1px; | ||
| border-color: transparent; | ||
| border-style: solid; | ||
| border-radius: 4px; | ||
| } | ||
| </style> | ||
| </head> | ||
| <body> | ||
| <form id="form"> | ||
| <div> | ||
| <label>API Key:</label> | ||
| <input type="text" id="api_key" class="field-wrapper"> | ||
| </div> | ||
| <div> | ||
| <label>Cardholder Name:</label> | ||
| <input type="text" id="holder" class="field-wrapper"> | ||
| </div> | ||
| <div> | ||
| <label>Card number:</label> | ||
| <input type="text" id="number" class="field-wrapper"> | ||
| </div> | ||
| <div> | ||
| <label>Expiration Date:</label> | ||
| <input type="text" id="expiration" class="field-wrapper"> | ||
| </div> | ||
| <div> | ||
| <label>Card Security Code:</label> | ||
| <input type="text" id="cvv" class="field-wrapper"> | ||
| </div> | ||
| <button id="send" type="submit">Submit</button> | ||
| <pre id="response"></pre> | ||
| </form> | ||
| <div class="container"> | ||
| </div> | ||
| <script type="text/javascript" src="https://js.verygoodvault.com/vgs-collect/2.13.0/vgs-collect.js"></script> | ||
| <script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script> | ||
| <script type="module"> | ||
| const apiKey = document.getElementById('api_key'); | ||
| const cardNumber = document.getElementById('number'); | ||
| const holderName = document.getElementById('holder'); | ||
| const expiration = document.getElementById('expiration'); | ||
| const cvv = document.getElementById('cvv'); | ||
| const container = document.getElementsByClassName('container')[0]; | ||
| const response = document.getElementById('response'); | ||
| import ThreeDSecureService from '../src/threedsecure-service.js'; | ||
| const exec = async () => { | ||
| const gatewayClient = axios.create({ | ||
| baseURL: 'https://gateway.paybyrd.com', | ||
| headers: { | ||
| 'content-type': 'application/json', | ||
| 'x-api-key': apiKey.value | ||
| } | ||
| }); | ||
| const threeDSecureService = new ThreeDSecureService({ | ||
| container, | ||
| threeDSecureUrl: 'https://threedsecure.paybyrd.com', | ||
| maxAttempts: 20, | ||
| attemptDelay: 2000, | ||
| culture: 'pt-BR', | ||
| onProgressFn: (event) => console.log(event) | ||
| }); | ||
| /* CREATE ORDER - Start */ | ||
| const createOrderRequest = { | ||
| amount: '0.01', | ||
| currency: 'EUR', | ||
| orderRef: '3ds-flow-test' | ||
| } | ||
| const orderResponse = await gatewayClient.post('/api/v2/orders', createOrderRequest); | ||
| if (orderResponse.status >= 300) { | ||
| response.innerText = JSON.stringify(orderResponse.data); | ||
| return; | ||
| } | ||
| const { checkoutKey } = orderResponse.data; | ||
| /* CREATE ORDER - End */ | ||
| /* EXECUTE 3DS - Start */ | ||
| const threeDSRequest = { | ||
| cardNumber: cardNumber.value, | ||
| cardHolder: holderName.value, | ||
| cardExpiration: expiration.value, | ||
| merchantId: 10, | ||
| purchaseAmount: 1, | ||
| purchaseCurrency: 'EUR' | ||
| }; | ||
| const threeDSResponse = await threeDSecureService.createAndExecute( | ||
| threeDSRequest); | ||
| /* EXECUTE 3DS - End */ | ||
| /* CREATE PAYMENT - Start */ | ||
| const createPaymentRequest = { | ||
| type: 'Card', | ||
| card: { | ||
| number: cardNumber.value, | ||
| holder: holderName.value, | ||
| expiration: expiration.value, | ||
| cvv: cvv.value, | ||
| threeDSVersion: threeDSResponse.version, | ||
| aav: threeDSResponse.authenticationValue, | ||
| caav_algorithm: threeDSResponse.authenticationValueAlgorithm, | ||
| dsTransactionId: threeDSResponse.dsTransactionId, | ||
| eci: threeDSResponse.eci, | ||
| xid: threeDSResponse.xid, | ||
| verificationMethod: threeDSResponse.verificationMethod | ||
| } | ||
| }; | ||
| const createPaymentResponse = await gatewayClient.post( | ||
| `/api/v2/payment?checkoutKey=${checkoutKey}`, | ||
| createPaymentRequest, | ||
| { | ||
| headers: { | ||
| correlationId: threeDSResponse.correlationId | ||
| } | ||
| }); | ||
| /* CREATE PAYMENT - End */ | ||
| response.innerHTML = JSON.stringify(createPaymentResponse); | ||
| } | ||
| const form = document.getElementById('form'); | ||
| form.addEventListener('submit', async (event) => { | ||
| event.preventDefault(); | ||
| await exec(); | ||
| }); | ||
| </script> | ||
| </body> | ||
| </html> |
@@ -1,1 +0,1 @@ | ||
| class ThreeDSecureService{constructor({threeDSecureUrl,container,maxAttempts,attemptDelay,culture,onProgressFn,onIFrameCreatedFn,onContainerCreatedFn}){this._onProgressFn=onProgressFn,this._maxAttempts=maxAttempts||50,this._attemptDelay=attemptDelay||2e3,this._threeDSecureUrl=threeDSecureUrl||"https://threedsecure.paybyrd.com",this._culture=culture||"en-US",this._container=container||document.body,this._onIFrameCreatedFn=onIFrameCreatedFn,this._onContainerCreatedFn=onContainerCreatedFn,this.IFRAME_DSMETHOD_NAME="threeDSMethodIframe",this.FORM_DSMETHOD_NAME="threeDSMethodForm",this.IFRAME_CHALLENGE_NAME="challengeIframe",this.FORM_CHALLENGE_NAME="challengeForm",this._fixContainer()}createAndExecute(initiatePayment,correlationId=crypto.randomUUID()){return this.create(initiatePayment,correlationId).then(createResponse=>this.preAuth(createResponse,correlationId)).then(preAuthResponse=>this.auth(preAuthResponse,correlationId)).then(authResponse=>this.postAuth(authResponse,correlationId)).then(postAuthResponse=>({...postAuthResponse,correlationId:correlationId})).catch(error=>Promise.reject({...error,correlationId:correlationId})).finally(this._destroy.bind(this))}create(initiatePayment,correlationId){return this._retry(this._isTransientStatusCode,()=>this._sendRequest({path:"/api/v1",method:"POST",payload:{...initiatePayment,browser:this._getBrowserData()},correlationId:correlationId}),"event:create")}preAuth(preAuthRequest,correlationId){return this._retry(this._isTransientStatusCode,()=>this._sendRequest({path:`/api/v1/${preAuthRequest.id}/preauth`,method:"POST",correlationId:correlationId}),"event:preAuth").then(preAuthResponse=>preAuthResponse.isDsMethodRequired?this._executeDsMethod(preAuthResponse).then(()=>preAuthResponse):preAuthResponse)}auth(authRequest,correlationId){return this._retry(this._isTransientStatusCode,()=>this._sendRequest({path:`/api/v1/${authRequest.id}/auth`,method:"POST",correlationId:correlationId}),"event:auth").then(authResponse=>authResponse.isChallengeRequired?("1.0.0"===authResponse.challengeVersion?this._executeChallengeV1(authResponse):this._executeChallengeV2(authResponse)).then(()=>authResponse):authResponse)}postAuth(postAuthRequest,correlationId){return this._retry(this._isTransientStatusCode,()=>this._sendRequest({path:`/api/v1/${postAuthRequest.id}/postAuth`,method:"POST",correlationId:correlationId}),"event:postAuth")}_executeDsMethod(preAuthResponse){return new Promise((resolve,reject)=>{try{this._onProgress({type:"event:dsMethod:start"});var iframeName=this.IFRAME_DSMETHOD_NAME,formName=this.FORM_DSMETHOD_NAME;this._createIFrame(iframeName,!1);const form=this._createForm(formName,preAuthResponse.dsMethodUrl,iframeName),threeDSMethodDataInput=this._createInput(form,"threeDSMethodData","hidden");var threeDSMethodData={threeDSServerTransID:preAuthResponse.processId,threeDSMethodNotificationURL:preAuthResponse.notificationUrl};threeDSMethodDataInput.value=this._convertToBase64UriJson(threeDSMethodData),form.submit(),this._onProgress({type:"event:dsMethod:success"}),resolve()}catch(error){return this._onProgress({type:"event:dsMethod:fail"}),reject({message:error.toString()})}})}_executeChallengeV1(authResponse){return new Promise((resolve,reject)=>{try{this._onProgress({type:"event:challenge:v1:start"});var iframeName=this.IFRAME_CHALLENGE_NAME,formName=this.FORM_CHALLENGE_NAME;this._createIFrame(iframeName);const form=this._createForm(formName,authResponse.challengeUrl,iframeName,"post"),paReqInput=this._createInput(form,"PaReq","hidden"),termUrlInput=this._createInput(form,"TermUrl","hidden");paReqInput.value=authResponse.preAuthRequest,termUrlInput.value=authResponse.notificationUrl,form.submit(),resolve(),this._onProgress({type:"event:challenge:v1:success"})}catch(error){return this._onProgress({type:"event:challenge:v1:fail",error:error}),reject({message:error.toString()})}})}_executeChallengeV2(authResponse){return new Promise((resolve,reject)=>{try{this._onProgress({type:"event:challenge:v2:start"});var iframeName=this.IFRAME_CHALLENGE_NAME,formName=this.FORM_CHALLENGE_NAME;this._createIFrame(iframeName);const form=this._createForm(formName,authResponse.challengeUrl,iframeName,"post"),threeDSRequestInput=(this._createInput(form,"threeDSSessionData","hidden"),this._createInput(form,"creq","hidden"));var cReq={threeDSServerTransID:authResponse.processId,acsTransID:authResponse.challengeId,messageVersion:authResponse.challengeVersion,messageType:"CReq",challengeWindowSize:"01"};threeDSRequestInput.value=this._convertToBase64UriJson(cReq),form.submit(),resolve(),this._onProgress({type:"event:challenge:v2:success"})}catch(error){return this._onProgress({type:"event:challenge:v2:fail",error:error}),reject({message:error.toString()})}})}_delay(timeout){return this._onProgress({type:"event:delay:start",data:{timeout:timeout}}),new Promise((resolve,_)=>{setTimeout(()=>{this._onProgress({type:"event:delay:end",data:{timeout:timeout}}),resolve()},timeout)})}_fixContainer(){this._onContainerCreatedFn?this._onContainerCreatedFn(this._container):this._container.setAttribute("style","position: relative; overflow: hidden;")}_createForm(name,action,target,method="POST"){const form=document.createElement("form");return form.id=name,form.name=name,form.action=action,form.target=target,form.method=method,this._container.appendChild(form),form}_createInput(form,name,type){const input=document.createElement("input");return input.id=name,input.name=name,input.type=type,form.appendChild(input),input}_createIFrame(name,visible=!0){const iframe=document.createElement("iframe");return iframe.id=name,iframe.name=name,this._onIFrameCreatedFn?(this._onIFrameCreatedFn(iframe),iframe.style.opacity=visible?1:0):iframe.setAttribute("style","border: none;position: absolute; top: 0; left: 0; bottom: 0; right: 0; width: 100%; height: 100%;opacity: "+(visible?"1":"0")),this._container.appendChild(iframe),iframe}_getBrowserData(){var colorDepth=[48,32,24,16,15,8,4,1].find(x=>x<=screen.colorDepth);return{javaEnabled:navigator.javaEnabled(),javascriptEnabled:!0,language:navigator.language,userAgent:navigator.userAgent,screenWidth:window.screen.width,screenHeight:window.screen.height,timezoneOffset:(new Date).getTimezoneOffset(),colorDepth:colorDepth,acceptHeader:"text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9"}}_retry(conditionFn,executeFn,eventType){return new Promise(async(resolve,reject)=>{let response=null,attempts=this._maxAttempts;do{this._onProgress({type:eventType+":start",data:{attempt:this._maxAttempts-attempts+1}});try{response=await executeFn()}catch(error){this._onProgress({type:eventType+":error",error:error.data?.error,data:{statusCode:error.status}}),response=error}if(200<=response.status&&response.status<300)return this._onProgress({type:eventType+":success",data:response.data.data}),void resolve(response.data.data)}while(attempts--,await this._delay(this._attemptDelay),0<attempts&&conditionFn(response));this._onProgress({type:eventType+":fail",error:response.data?.error}),reject(response.data?.error??{message:"Unhandled error"})})}_onProgress(event){try{this._onProgressFn?.call(null,event)}catch{}}_isTransientStatusCode(response){return 409===response.status||424===response.status||504===response.status}_convertToBase64UriJson(data){data=JSON.stringify(data);const base64Json=btoa(data);return base64Json.replace(/=/g,"").replace(/\+/g,"-").replace(/\//g,"_")}_sendRequest({path,method,payload,correlationId}){const tryParse=json=>{if(""===json)return null;try{return JSON.parse(json)}catch{return null}};return new Promise((resolve,reject)=>{let xhr=new XMLHttpRequest;const url=new URL(path,this._threeDSecureUrl);xhr.open(method,url.toString());xhr.timeout=3e4,xhr.setRequestHeader("Accept","application/json"),xhr.setRequestHeader("Accept-Language",this._culture),xhr.setRequestHeader("Content-Type","application/json"),xhr.setRequestHeader("CorrelationId",correlationId),xhr.onload=()=>{(200<=xhr.status&&xhr.status<300?resolve:reject)({status:xhr.status,data:tryParse(xhr.responseText)})},xhr.onerror=()=>{reject({status:xhr.status,data:tryParse(xhr.responseText)})},xhr.send(JSON.stringify(payload))})}_destroy(){document.getElementById(this.IFRAME_DSMETHOD_NAME)?.remove(),document.getElementById(this.FORM_DSMETHOD_NAME)?.remove(),document.getElementById(this.IFRAME_CHALLENGE_NAME)?.remove(),document.getElementById(this.FORM_CHALLENGE_NAME)?.remove()}}export default ThreeDSecureService; | ||
| export default class ThreeDSecureService{constructor({threeDSecureUrl,container,maxAttempts,attemptDelay,culture,onProgressFn,onIFrameCreatedFn,onContainerCreatedFn}){this._onProgressFn=onProgressFn,this._maxAttempts=maxAttempts||50,this._attemptDelay=attemptDelay||2e3,this._threeDSecureUrl=threeDSecureUrl||"https://threedsecure.paybyrd.com",this._culture=culture||"en-US",this._container=container||document.body,this._onIFrameCreatedFn=onIFrameCreatedFn,this._onContainerCreatedFn=onContainerCreatedFn,this.IFRAME_DSMETHOD_NAME="threeDSMethodIframe",this.FORM_DSMETHOD_NAME="threeDSMethodForm",this.IFRAME_CHALLENGE_NAME="challengeIframe",this.FORM_CHALLENGE_NAME="challengeForm",this._fixContainer()}createAndExecute(initiatePayment,correlationId=crypto.randomUUID()){return this.create(initiatePayment,correlationId).then(createResponse=>this.preAuth(createResponse,correlationId)).then(preAuthResponse=>this.auth(preAuthResponse,correlationId)).then(authResponse=>this.postAuth(authResponse,correlationId)).then(postAuthResponse=>({...postAuthResponse,correlationId:correlationId})).catch(error=>Promise.reject({...error,correlationId:correlationId})).finally(this._destroy.bind(this))}create(initiatePayment,correlationId){return this._retry(this._isTransientStatusCode.bind(this),()=>this._sendRequest({path:"/api/v1",method:"POST",payload:{...initiatePayment,browser:this._getBrowserData()},correlationId:correlationId}),"event:create")}preAuth(preAuthRequest,correlationId){return this._retry(this._isTransientStatusCode.bind(this),()=>this._sendRequest({path:`/api/v1/${preAuthRequest.id}/preauth`,method:"POST",correlationId:correlationId}),"event:preAuth").then(preAuthResponse=>preAuthResponse.isDsMethodRequired?this._executeDsMethod(preAuthResponse).then(()=>preAuthResponse):preAuthResponse)}auth(authRequest,correlationId){return this._retry(this._isTransientStatusCode.bind(this),()=>this._sendRequest({path:`/api/v1/${authRequest.id}/auth`,method:"POST",correlationId:correlationId}),"event:auth").then(authResponse=>authResponse.isChallengeRequired?("1.0.0"===authResponse.challengeVersion?this._executeChallengeV1(authResponse):this._executeChallengeV2(authResponse)).then(()=>authResponse):authResponse)}postAuth(postAuthRequest,correlationId){return this._retry(this._isTransientStatusCode.bind(this),()=>this._sendRequest({path:`/api/v1/${postAuthRequest.id}/postAuth`,method:"POST",correlationId:correlationId}),"event:postAuth")}_executeDsMethod(preAuthResponse){return new Promise((resolve,reject)=>{try{this._onProgress({type:"event:dsMethod:start"});var iframeName=this.IFRAME_DSMETHOD_NAME,formName=this.FORM_DSMETHOD_NAME;this._createIFrame(iframeName,!1);const form=this._createForm(formName,preAuthResponse.dsMethodUrl,iframeName),threeDSMethodDataInput=this._createInput(form,"threeDSMethodData","hidden");var threeDSMethodData={threeDSServerTransID:preAuthResponse.processId,threeDSMethodNotificationURL:preAuthResponse.notificationUrl};threeDSMethodDataInput.value=this._convertToBase64UriJson(threeDSMethodData),form.submit(),this._onProgress({type:"event:dsMethod:success"}),resolve()}catch(error){return this._onProgress({type:"event:dsMethod:fail"}),reject({message:error.toString()})}})}_executeChallengeV1(authResponse){return new Promise((resolve,reject)=>{try{this._onProgress({type:"event:challenge:v1:start"});var iframeName=this.IFRAME_CHALLENGE_NAME,formName=this.FORM_CHALLENGE_NAME;this._createIFrame(iframeName);const form=this._createForm(formName,authResponse.challengeUrl,iframeName,"post"),paReqInput=this._createInput(form,"PaReq","hidden"),termUrlInput=this._createInput(form,"TermUrl","hidden");paReqInput.value=authResponse.preAuthRequest,termUrlInput.value=authResponse.notificationUrl,form.submit(),resolve(),this._onProgress({type:"event:challenge:v1:success"})}catch(error){return this._onProgress({type:"event:challenge:v1:fail",error:error}),reject({message:error.toString()})}})}_executeChallengeV2(authResponse){return new Promise((resolve,reject)=>{try{this._onProgress({type:"event:challenge:v2:start"});var iframeName=this.IFRAME_CHALLENGE_NAME,formName=this.FORM_CHALLENGE_NAME;this._createIFrame(iframeName);const form=this._createForm(formName,authResponse.challengeUrl,iframeName,"post"),threeDSRequestInput=(this._createInput(form,"threeDSSessionData","hidden"),this._createInput(form,"creq","hidden"));var cReq={threeDSServerTransID:authResponse.processId,acsTransID:authResponse.challengeId,messageVersion:authResponse.challengeVersion,messageType:"CReq",challengeWindowSize:"01"};threeDSRequestInput.value=this._convertToBase64UriJson(cReq),form.submit(),resolve(),this._onProgress({type:"event:challenge:v2:success"})}catch(error){return this._onProgress({type:"event:challenge:v2:fail",error:error}),reject({message:error.toString()})}})}_delay(timeout){return this._onProgress({type:"event:delay:start",data:{timeout:timeout}}),new Promise((resolve,_)=>{setTimeout(()=>{this._onProgress({type:"event:delay:end",data:{timeout:timeout}}),resolve()},timeout)})}_fixContainer(){this._onContainerCreatedFn?this._onContainerCreatedFn(this._container):this._container.setAttribute("style","position: relative; overflow: hidden;")}_createForm(name,action,target,method="POST"){const form=document.createElement("form");return form.id=name,form.name=name,form.action=action,form.target=target,form.method=method,this._container.appendChild(form),form}_createInput(form,name,type){const input=document.createElement("input");return input.id=name,input.name=name,input.type=type,form.appendChild(input),input}_createIFrame(name,visible=!0){const iframe=document.createElement("iframe");return iframe.id=name,iframe.name=name,this._onIFrameCreatedFn?(this._onIFrameCreatedFn(iframe),iframe.style.opacity=visible?1:0):iframe.setAttribute("style","border: none;position: absolute; top: 0; left: 0; bottom: 0; right: 0; width: 100%; height: 100%;opacity: "+(visible?"1":"0")),this._container.appendChild(iframe),iframe}_getBrowserData(){var colorDepth=[48,32,24,16,15,8,4,1].find(x=>x<=screen.colorDepth);return{javaEnabled:navigator.javaEnabled(),javascriptEnabled:!0,language:navigator.language,userAgent:navigator.userAgent,screenWidth:window.screen.width,screenHeight:window.screen.height,timezoneOffset:(new Date).getTimezoneOffset(),colorDepth:colorDepth,acceptHeader:"text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9"}}_retry(conditionFn,executeFn,eventType){return new Promise(async(resolve,reject)=>{let response=null,attempts=this._maxAttempts;do{this._onProgress({type:eventType+":start",data:{attempt:this._maxAttempts-attempts+1}});try{response=await executeFn()}catch(error){this._onProgress({type:eventType+":error",error:error.data?.error,data:{statusCode:error.status}}),response=error}if(200<=response.status&&response.status<300)return this._onProgress({type:eventType+":success",data:response.data.data}),void resolve(response.data.data)}while(attempts--,await this._delay(this._attemptDelay),0<attempts&&conditionFn(response));this._onProgress({type:eventType+":fail",error:response.data?.error}),reject(response.data?.error??{message:"Unhandled error"})})}_onProgress(event){this._safeExecute(()=>this._onProgressFn?.call(null,event))}_isTransientStatusCode(response){return this._safeExecute(()=>500==response.status||409===response.status||424===response.status||504===response.status,!0)}_convertToBase64UriJson(data){data=JSON.stringify(data);const base64Json=btoa(data);return base64Json.replace(/=/g,"").replace(/\+/g,"-").replace(/\//g,"_")}_sendRequest({path,method,payload,correlationId}){const tryParse=json=>""===json?null:this._safeExecute(()=>JSON.parse(json),null);return new Promise((resolve,reject)=>{let xhr=new XMLHttpRequest;const url=new URL(path,this._threeDSecureUrl);xhr.open(method,url.toString());xhr.timeout=3e4,xhr.setRequestHeader("Accept","application/json"),xhr.setRequestHeader("Accept-Language",this._culture),xhr.setRequestHeader("Content-Type","application/json"),xhr.setRequestHeader("CorrelationId",correlationId),xhr.onload=()=>{try{if(200<=xhr.status&&xhr.status<300)return void resolve({status:xhr.status,data:tryParse(xhr.responseText)});reject({status:xhr.status,data:tryParse(xhr.responseText)})}catch(error){console.log(error),reject({status:500,data:{message:error.toString()}})}},xhr.onerror=()=>{reject({status:xhr.status,data:tryParse(xhr.responseText)})};var json=this._safeExecute(()=>JSON.stringify(payload),"{}");xhr.send(json)})}_destroy(){this._safeExecute(()=>document.getElementById(this.IFRAME_DSMETHOD_NAME)?.remove()),this._safeExecute(()=>document.getElementById(this.FORM_DSMETHOD_NAME)?.remove()),this._safeExecute(()=>document.getElementById(this.IFRAME_CHALLENGE_NAME)?.remove()),this._safeExecute(()=>document.getElementById(this.FORM_CHALLENGE_NAME)?.remove())}_safeExecute(action,defaultResult){try{return action()}catch(error){return console.log(error),defaultResult}}} |
+5
-3
| { | ||
| "name": "@paybyrd/threedsecure-service", | ||
| "version": "1.2.0", | ||
| "version": "1.2.1", | ||
| "description": "JS service implementation to control the 3DS flow over Paybyrd API", | ||
@@ -11,3 +11,4 @@ "main": "dist/threedsecure-service.min.js", | ||
| "scripts": { | ||
| "prepublish": "uglifyjs src/threedsecure-service.js -c -o dist/threedsecure-service.min.js" | ||
| "prepublish": "uglifyjs src/threedsecure-service.js -c -o dist/threedsecure-service.min.js", | ||
| "samples": "live-server --open=./samples" | ||
| }, | ||
@@ -29,4 +30,5 @@ "keywords": [ | ||
| "devDependencies": { | ||
| "uglify-js": "^3.16.2" | ||
| "uglify-js": "^3.16.2", | ||
| "live-server": "1.2.2" | ||
| } | ||
| } |
@@ -1,2 +0,2 @@ | ||
| class ThreeDSecureService { | ||
| export default class ThreeDSecureService { | ||
| constructor({ | ||
@@ -51,3 +51,3 @@ threeDSecureUrl, | ||
| return this._retry( | ||
| this._isTransientStatusCode, | ||
| this._isTransientStatusCode.bind(this), | ||
| () => this._sendRequest({ | ||
@@ -67,3 +67,3 @@ path: '/api/v1', | ||
| return this._retry( | ||
| this._isTransientStatusCode, | ||
| this._isTransientStatusCode.bind(this), | ||
| () => this._sendRequest({ | ||
@@ -87,3 +87,3 @@ path: `/api/v1/${preAuthRequest.id}/preauth`, | ||
| return this._retry( | ||
| this._isTransientStatusCode, | ||
| this._isTransientStatusCode.bind(this), | ||
| () => this._sendRequest({ | ||
@@ -110,3 +110,3 @@ path: `/api/v1/${authRequest.id}/auth`, | ||
| return this._retry( | ||
| this._isTransientStatusCode, | ||
| this._isTransientStatusCode.bind(this), | ||
| () => this._sendRequest({ | ||
@@ -408,13 +408,7 @@ path: `/api/v1/${postAuthRequest.id}/postAuth`, | ||
| _onProgress(event) { | ||
| try { | ||
| this._onProgressFn?.call(null, event); | ||
| } catch | ||
| { | ||
| // do nothing | ||
| } | ||
| this._safeExecute(() => this._onProgressFn?.call(null, event)); | ||
| } | ||
| _isTransientStatusCode(response) { | ||
| return response.status === 409 || response.status === 424 || response.status === 504; | ||
| return this._safeExecute(() => response.status == 500 || response.status === 409 || response.status === 424 || response.status === 504, true); | ||
| } | ||
@@ -437,7 +431,3 @@ | ||
| } | ||
| try { | ||
| return JSON.parse(json); | ||
| } catch { | ||
| return null; | ||
| } | ||
| return this._safeExecute(() => JSON.parse(json), null); | ||
| } | ||
@@ -449,3 +439,2 @@ | ||
| xhr.open(method, url.toString()); | ||
@@ -462,13 +451,24 @@ | ||
| xhr.onload = () => { | ||
| if (xhr.status >= 200 && xhr.status < 300) { | ||
| resolve({ | ||
| try { | ||
| if (xhr.status >= 200 && xhr.status < 300) { | ||
| resolve({ | ||
| status: xhr.status, | ||
| data: tryParse(xhr.responseText) | ||
| }); | ||
| return; | ||
| } | ||
| reject({ | ||
| status: xhr.status, | ||
| data: tryParse(xhr.responseText) | ||
| }); | ||
| return; | ||
| } | ||
| reject({ | ||
| status: xhr.status, | ||
| data: tryParse(xhr.responseText) | ||
| }); | ||
| catch (error) { | ||
| console.log(error); | ||
| reject({ | ||
| status: 500, | ||
| data: { | ||
| message: error.toString() | ||
| } | ||
| }); | ||
| } | ||
| }; | ||
@@ -482,3 +482,5 @@ xhr.onerror = () => { | ||
| xhr.send(JSON.stringify(payload)); | ||
| const json = this._safeExecute(() => JSON.stringify(payload), '{}'); | ||
| xhr.send(json); | ||
| }); | ||
@@ -488,9 +490,16 @@ } | ||
| _destroy() { | ||
| document.getElementById(this.IFRAME_DSMETHOD_NAME)?.remove(); | ||
| document.getElementById(this.FORM_DSMETHOD_NAME)?.remove(); | ||
| document.getElementById(this.IFRAME_CHALLENGE_NAME)?.remove(); | ||
| document.getElementById(this.FORM_CHALLENGE_NAME)?.remove(); | ||
| this._safeExecute(() => document.getElementById(this.IFRAME_DSMETHOD_NAME)?.remove()); | ||
| this._safeExecute(() => document.getElementById(this.FORM_DSMETHOD_NAME)?.remove()); | ||
| this._safeExecute(() => document.getElementById(this.IFRAME_CHALLENGE_NAME)?.remove()); | ||
| this._safeExecute(() => document.getElementById(this.FORM_CHALLENGE_NAME)?.remove()); | ||
| } | ||
| } | ||
| export default ThreeDSecureService; | ||
| _safeExecute(action, defaultResult) { | ||
| try { | ||
| return action(); | ||
| } catch (error) { | ||
| console.log(error); | ||
| return defaultResult; | ||
| } | ||
| } | ||
| } |
63525
13.7%7
16.67%437
2.34%2
100%