Merge pull request #3006 from Safelite/feature/CASH-1722

Adyen - Update Error Scenarios
This commit is contained in:
chloeherdsafelite 2026-01-13 12:41:08 -05:00 committed by GitHub
commit 6c845aaaa5
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 143 additions and 40 deletions

View file

@ -4,6 +4,16 @@
<div class="container">
<div class="row">
<div class="col-12">
<div>
<alert
ref="piaErrorAlert"
class="my-4"
v-if="hasPaymentFailureError"
cmsWidgetName="PIAErrorAlertWidget"
alertClass="alert-danger"
@textLinkClicked="paymentFailedPayLater"
v-bind:isDismissible="false" />
</div>
<div id="card-container">
<div id="payment-container">
<funnelSubHeader class="py-5" cmsWidgetName="FunnelSubHeaderWidget" />
@ -45,6 +55,7 @@ import Form from "vee-validate";
import funnelHeader from "@/fmg-components/funnel-header/funnel-header";
import navbar from "@/fmg-components/nav-bar/nav-bar";
import funnelSubHeader from "@/fmg-components/funnel-sub-header/funnel-sub-header";
import alert from "@/ux-components/alert/alert";
import { fetchCmsContentForPage } from "@/helpers/cms-content-helper";
import { settleAllPromises } from "@/helpers/layout-helper";
@ -75,6 +86,8 @@ export default {
data() {
return {
sessionId: String,
dropinComponent: null,
hasPaymentFailureError: false,
};
},
@ -92,9 +105,15 @@ export default {
const resultMap = await settleAllPromises(promiseResultMap);
const hasExistingPiaError = to.query?.piaFailure;
// Hydrate page with results
next(async (vm) => {
vm.setCmsContent(resultMap.cmsContent);
if (hasExistingPiaError) {
vm.hasPaymentFailureError = true;
}
});
},
@ -184,9 +203,9 @@ export default {
debugLog("providerLocation.city:", providerLocation.city, !preReqResult);
debugLog("providerLocation.state:", providerLocation.state, !preReqResult);
debugLog("providerLocation.zipCode:", providerLocation.zipCode, !preReqResult);
debugLog("", null, !preReqResult);
debugLog("isInsuranceSet:", isInsuranceSet, !preReqResult);
debugLog("", null, !preReqResult);
@ -197,7 +216,7 @@ export default {
debugLog("schedule.endTime:", schedule.endTime, !preReqResult);
debugLog("schedule.jobMaxMinutes:", schedule.jobMaxMinutes, !preReqResult);
debugLog("schedule.jobMinMinutes:", schedule.jobMinMinutes, !preReqResult);
debugLog("", null, !preReqResult);
debugLog("customerReqs:", customerReqs, !preReqResult);
@ -205,7 +224,7 @@ export default {
debugLog("customer.lastName:", customer.lastName, !preReqResult);
debugLog("customer.phoneNumber:", customer.phoneNumber, !preReqResult);
debugLog("customer.emailAddress:", customer.emailAddress, !preReqResult);
debugLog("", null, !preReqResult);
debugLog("paymentMethodReqs:", paymentMethodReqs, !preReqResult);
@ -292,7 +311,11 @@ export default {
name: "Credit or debit card",
},
},
}).mount("#adyen-container");
});
this.dropinComponent = dropin;
dropin.mount("#adyen-container");
},
async handleCompletedPayment(result) {
@ -382,33 +405,33 @@ export default {
console.log(`Result =`);
console.log(result);
// Fetch session info
const paymentSessionRequest = {
zipCodeCtu: this.locationInfo.zipCodeCtu,
workOrderNumber: this.workOrderNumberLastSixDigits,
sourceSystem: this.sourceSystem,
sessionId: this.sessionId,
sessionResult: result?.sessionResult,
};
const wasPaymentCancelled = result?.resultCode === "Cancelled";
console.log(`Get session payload =`);
console.log(paymentSessionRequest);
if (!wasPaymentCancelled) {
const stringToLog = `ADYEN PAYMENT NOT AUTHORIZED. Code = ${result?.resultCode}. Id = ${this.sessionId}`;
try {
const response = await globalMethods.callHttpClient({
method: endpoints.GetAdyenSessionResult.method,
endpoint: endpoints.GetAdyenSessionResult.url,
payload: paymentSessionRequest,
logApiCall: true,
pageNameToLog: "payment-adyen",
});
await global.$logger.logError(stringToLog);
console.log(response);
} catch (error) {
console.log(`Error getting session info after failure.`);
this.hasPaymentFailureError = true;
}
this.dropinComponent?.update();
},
async handleError(error) {
console.log(error);
const wasPaymentCancelled = error?.name === "CANCEL";
if (!wasPaymentCancelled) {
const stringToLog = `ADYEN ERROR. Name = ${error?.name}. Details = ${error?.message}.`;
await global.$logger.logError(stringToLog);
this.hasPaymentFailureError = true;
}
this.dropinComponent?.update();
},
handleError(error) {},
async saveAndSubmitWorkOrder() {
// Work order submission after successful payment.
@ -421,15 +444,10 @@ export default {
} catch (error) {
console.log(`error: response from submit work order: ${error.message}`);
// navigate to error page
const errorPayload = {
cause: `Error while submitting work order after Adyen payment.`,
currentPage: this.pageName,
sessionId: this.sessionId,
idempotencyKey: this.idempotencyKey,
};
this.$router.handleSoftError(errorPayload);
this.$router.navigateWithoutSaving(
this.navigationScenarios.PIA_ERROR,
this.pageName
);
return;
}
@ -441,6 +459,37 @@ export default {
this.pageName
);
},
async paymentFailedPayLater() {
console.log(`Doing final work order submission...`);
showFmgLoadingModal(true);
await this.dispatchStoreAction(
storeActions.SAVE_PAYMENT_METHOD_CHOICE,
paymentMethods.PAY_LATER,
false
);
await this.dispatchStoreAction(storeActions.RESET_SAVE_SESSION_PROMISE);
try {
await submitWorkOrder({
pageNameToLog: this.pageName,
submitAfterSave: true,
});
await baseMixin.methods.dispatchStoreAction(storeActions.CREATE_SUBMITTED_STATE);
this.$router.navigateWithoutSaving(
this.navigationScenarios.CLICKED_FORWARD,
this.pageName
);
} catch (error) {
console.log(`Final submission failed after failed payment.`);
this.$router.handleSoftError();
return;
}
},
},
computed: {
@ -581,6 +630,7 @@ export default {
funnelSubHeader,
navbar,
cart,
alert,
},
};
</script>

View file

@ -578,6 +578,13 @@ const routingTable = function () {
scenario: navigationScenarios.CLICKED_FORWARD,
destinationPageData: routeData.CONFIRMATION,
},
{
scenario: navigationScenarios.PIA_ERROR,
destinationPageData: routeData.PAYMENT_METHOD,
params: {
piaError: "true",
},
},
],
},
{

View file

@ -15,7 +15,30 @@ export async function adyenReturnBeforeEnter(to, from) {
const redirectResult = to?.query?.redirectResult;
if (sessionId && redirectResult) {
const result = await finalizeAdyenPayment(sessionId, redirectResult);
let result = null;
try {
result = await finalizeAdyenPayment(sessionId, redirectResult);
} catch (unexpectedResult) {
// If user cancelled payment, handle without error message
if (unexpectedResult.code === "Cancelled" || unexpectedResult.code === "CANCEL") {
return {
name: routeData.PAYMENT_ADYEN.name,
replace: true,
};
}
// Otherwise, failure scenario.
// Payment fails, so return user to payment-adyen screen to try again or pay later.
return {
name: routeData.PAYMENT_ADYEN.name,
query: {
piaFailure: true,
},
replace: true,
};
}
console.log(`Out of promise`);
console.log(result);
@ -59,7 +82,10 @@ export async function adyenReturnBeforeEnter(to, from) {
} catch (error) {
console.log(error);
return {
name: routeData.ERROR.name,
name: routeData.PAYMENT_METHOD.name,
query: {
piaError: "true",
},
replace: true,
};
}
@ -93,12 +119,32 @@ function finalizeAdyenPayment(sessionId, redirectResult) {
onPaymentFailed: (result, component) => {
console.log(`Payment failed`);
console.log(result);
reject("Payment failed from Adyen");
if (result?.resultCode !== "Cancelled") {
const stringToLog = `ADYEN PAYMENT NOT AUTHORIZED. Code = ${result?.resultCode}. Id = ${sessionId}`;
global.$logger.logError(stringToLog);
}
reject({
code: result?.resultCode,
message: "Payment failed from Adyen",
});
},
onError: (error, component) => {
console.log(`Error occured`);
console.log(error);
reject("Error from Adyen");
if (error?.name !== "CANCEL") {
const stringToLog = `ADYEN ERROR. Name = ${error?.name}. Details = ${error?.message}.`;
global.$logger.logError(stringToLog);
}
reject({
code: error?.name,
message: "Error from Adyen",
});
},
},
options: {},