CSR-1072 insurance orders will remove line items depending on the company. mobile fee, recycle fee, etc. So we can return from heritage with nothing in supporting items causing exceptions when lineItems is no longer required.
703 lines
28 KiB
Vue
703 lines
28 KiB
Vue
<template>
|
|
<Form>
|
|
<loadingModal notFullScreen ref="loadingModal" />
|
|
<div class="container-fluid">
|
|
<div class="row justify-content-center">
|
|
<div class="col-md-6">
|
|
<funnelHeader cmsWidgetName="FunnelHeaderWidget" ref="funnelHeader" />
|
|
</div>
|
|
</div>
|
|
|
|
<div class="row justify-content-center">
|
|
<div class="col-md-6 col-xl-4 p-0">
|
|
<div>
|
|
<alert
|
|
ref="piaCCErrorAlert"
|
|
class="my-4"
|
|
v-if="shouldDisplayPiaCCAlert"
|
|
cmsWidgetName="PIACCErrorAlertWidget"
|
|
alertClass="alert-danger"
|
|
@textLinkClicked="paymentFailedPayLater"
|
|
v-bind:isDismissible="false" />
|
|
</div>
|
|
|
|
<div>
|
|
<alert
|
|
ref="piaAPErrorAlert"
|
|
class="my-4"
|
|
v-if="shouldDisplayPiaAPAlert"
|
|
cmsWidgetName="PIAAPErrorAlertWidget"
|
|
alertClass="alert-danger"
|
|
@textLinkClicked="paymentFailedPayLater"
|
|
v-bind:isDismissible="false" />
|
|
</div>
|
|
|
|
<div id="card-container">
|
|
<iframe
|
|
v-resize
|
|
ref="paymentFrame"
|
|
class="hop-iframe payment-iframe"
|
|
name="card-frame"
|
|
id="card-frame"
|
|
seamless
|
|
scrolling="no">
|
|
</iframe>
|
|
</div>
|
|
|
|
<hr />
|
|
|
|
<cart
|
|
ref="cart"
|
|
:damage="damageInfo"
|
|
:availableVaps="availableVaps"
|
|
:allowItemRemoval="false"
|
|
v-model="lineItems"
|
|
servicePackageOptionsCmsName="ServicePackageTitle"
|
|
recyclingModalCmsWidgetName="RecycleModal" />
|
|
|
|
<hr class="mb-5" />
|
|
|
|
<navbar
|
|
cmsWidgetName="FunnelFooterWidget"
|
|
isForwardActionDisabled="true"
|
|
:isBackButtonHidden="shouldHideBackButton"
|
|
isSubmitHidden="true"
|
|
@back-clicked="backButtonAction" />
|
|
</div>
|
|
</div>
|
|
|
|
<div v-if="shouldBlockInteraction" class="ui-block" @click="supressClick"></div>
|
|
</div>
|
|
</Form>
|
|
|
|
<form
|
|
ref="hopForm"
|
|
id="card-data"
|
|
:target="isPaypal ? '_top' : 'card-frame'"
|
|
method="POST"
|
|
:action="checkoutUrl">
|
|
<input type="hidden" name="paymentType" :value="paymentType" />
|
|
<input type="hidden" name="sgSessionId" :value="authToken" />
|
|
<input type="hidden" name="sgAuthToken" :value="authToken" />
|
|
<input type="hidden" name="sgSignaturePublic" :value="authSignature" />
|
|
<input type="hidden" name="sgSignatureStartDate" :value="authSignatureStart" />
|
|
<input type="hidden" name="referralSeqNum" :value="referralSequenceNumber" />
|
|
|
|
<input type="hidden" name="sge_commerce_indicator_isinternet" value="true" />
|
|
<input type="hidden" name="sghopsource" value="Safelite.com" />
|
|
<input type="hidden" name="sgHtmlStyle" value="ResourceSafeliteHtml" />
|
|
<input type="hidden" name="sgErrorMessagesEmbedded" value="true" />
|
|
|
|
<input type="hidden" name="sgNoKeystrokeProcessing" value="false" />
|
|
|
|
<input type="hidden" name="maskCharacter" value="*" />
|
|
<input type="hidden" name="styleSheetCode" :value="dynamicCSSUrl" />
|
|
<input type="hidden" name="styleSheetCode2" :value="dynamicHopCSSUrl" />
|
|
|
|
<input type="hidden" name="sgReceiptResponseURL" :value="piaResponseUrl" />
|
|
<input type="hidden" name="sgDeclineResponseURL" :value="piaResponseUrl" />
|
|
<input type="hidden" name="sgErrorResponseURL" :value="piaResponseUrl" />
|
|
|
|
<input type="hidden" name="sgheaderline1" :value="getHeaderLine1" />
|
|
<input type="hidden" name="sgHeader1subtitle" value="" />
|
|
<input type="hidden" name="sgheaderline2" :value="getHeaderLine2" />
|
|
<input type="hidden" name="sgheaderline3" value="" />
|
|
<input type="hidden" name="sgheaderline4" value="" />
|
|
<input type="hidden" name="sgheaderline5" value="*Required information" />
|
|
|
|
<input type="hidden" name="billTo_firstName" :value="firstName" />
|
|
<input type="hidden" name="billTo_firstNameShow" value="true" />
|
|
<input type="hidden" name="sghopmiddleInitialShow" value="false" />
|
|
<input type="hidden" name="billTo_lastName" :value="lastName" />
|
|
<input type="hidden" name="billTo_lastNameShow" value="true" />
|
|
|
|
<input type="hidden" name="billTo_street1" value="" />
|
|
<input type="hidden" name="billTo_street2" value="" />
|
|
<input type="hidden" name="billTo_city" value="" />
|
|
<input type="hidden" name="billTo_state" value="" />
|
|
|
|
<input type="hidden" name="billTo_postalCode" value="" />
|
|
<input type="hidden" name="billTo_postalCodeShow" value="true" />
|
|
<input type="hidden" name="billTo_postalCodeEnable" value="true" />
|
|
<input type="hidden" name="sgLabelPostalCode" value="Billing ZIP" />
|
|
|
|
<input type="hidden" name="sgtotalamount" :value="displayAmount" />
|
|
<input type="hidden" name="totalAmountDecimal" :value="totalAmount" />
|
|
<input type="hidden" name="lineItems" :value="piaLineItems" />
|
|
|
|
<input type="hidden" name="sgdiscountstrikethruamount" value="" />
|
|
|
|
<input type="hidden" name="callerDisplayText" value="" />
|
|
|
|
<input
|
|
type="hidden"
|
|
name="sgtermsofusedisplaytext"
|
|
value="By selecting submit, I agree to Safelite's" />
|
|
<input type="hidden" name="sgtermsofuseurl" value="http://www.safelite.com/terms-of-use/" />
|
|
<input type="hidden" name="sgtermsofuselinkdisplaytext" value="terms of use" />
|
|
<input type="hidden" name="sgtermsofcancelrefunddisplaytext" value="and" />
|
|
<input
|
|
type="hidden"
|
|
name="sgtermsofcancelrefundlinkdisplaytext"
|
|
value="cancellation and refund policy" />
|
|
<input
|
|
type="hidden"
|
|
name="sgtermsofcancelrefundurl"
|
|
value="http://www.safelite.com/cancellation-refund-policy" />
|
|
|
|
<input
|
|
type="hidden"
|
|
name="sgErrorMessageCardVerification"
|
|
value="Credit card could not be processed" />
|
|
<input
|
|
type="hidden"
|
|
name="sgErrorMessageTimeOut"
|
|
value="For your security, this transaction has been timed out." />
|
|
|
|
<input type="hidden" name="sgLabelCardNumber" value="" />
|
|
<input type="hidden" name="sgLabelAddressLine1" :value="address1" />
|
|
<input type="hidden" name="sgLabelAddressLine2" :value="address2" />
|
|
<input type="hidden" name="sgLabelCity" :value="city" />
|
|
<input type="hidden" name="sgLabelState" :value="state" />
|
|
|
|
<input type="hidden" name="sgCtu" :value="ctu" />
|
|
<input type="hidden" name="sgWorkOrder" :value="workOrderNumber" />
|
|
<input type="hidden" name="sgEmailAddress" :value="emailAddress" />
|
|
<input type="hidden" name="paypalInvoiceNumber" :value="invoiceNumber" />
|
|
<input type="hidden" name="paypalSuccessUrl" :value="piaResponseUrl" />
|
|
<input type="hidden" name="paypalCancelUrl" :value="piaCancelUrl" />
|
|
|
|
<input type="hidden" name="sgCCDeclineURL" :value="piaCancelUrl" />
|
|
<input type="hidden" name="sgCCTimeoutURL" :value="piaCancelUrl" />
|
|
|
|
<input type="hidden" name="sgTransactionType" value="authorization" />
|
|
<input type="hidden" name="amount" :value="totalAmount" />
|
|
<input type="hidden" name="ctu" :value="ctu" />
|
|
<input type="hidden" name="orderNumber" :value="workOrderNumber" />
|
|
|
|
<input type="hidden" name="billTo_email" :value="emailAddress" />
|
|
<input type="hidden" name="useDecisionManager" value="True" />
|
|
<input type="hidden" name="correlationId" :value="referralCorrelationId" />
|
|
<input type="hidden" name="sgErrorMessageCard_CVN" value="Please enter a valid CVV" />
|
|
|
|
<input type="hidden" name="ship_to_address_line1" :value="address1" />
|
|
<input type="hidden" name="ship_to_address_line2" :value="address2" />
|
|
<input type="hidden" name="ship_to_address_city" :value="city" />
|
|
<input type="hidden" name="ship_to_address_state" :value="state" />
|
|
<input type="hidden" name="ship_to_address_country" value="US" />
|
|
<input type="hidden" name="ship_to_address_postal_code" :value="zipCode" />
|
|
<input type="hidden" name="ship_to_phone" :value="phoneNumber" />
|
|
|
|
<input type="hidden" name="calling_application" value="NextGen" />
|
|
</form>
|
|
</template>
|
|
|
|
<script>
|
|
// Components
|
|
import funnelHeader from "@/fmg-components/funnel-header/funnel-header";
|
|
import navbar from "@/fmg-components/nav-bar/nav-bar";
|
|
import loadingModal from "@/fmg-components/loading-modal/loading-modal.vue";
|
|
import cart from "@/fmg-components/cart/cart";
|
|
import alert from "@/ux-components/alert/alert";
|
|
|
|
import { storeActions } from "@/constants/store-actions";
|
|
import store from "@/store";
|
|
import { externalUrls } from "@/router/router-constants/externalUrl-values";
|
|
import { fetchCmsContentForPage } from "@/helpers/cms-content-helper";
|
|
import { settleAllPromises } from "@/helpers/layout-helper";
|
|
import { applicationConfig } from "@/constants/application-config";
|
|
import { paymentMethods } from "@/constants/payment-method-constants";
|
|
import { AppointmentTypeStrings } from "@/constants/schedule-constants";
|
|
import baseMixin from "@/mixins/base-mixin.js";
|
|
import { mapTaxedLineItemsToStoreFormat } from "../../store";
|
|
import {
|
|
revalidatePromosAndValidateQueryStringPromo,
|
|
getAddableVapsFromAvailableLineItems,
|
|
getVapsThatNeedToBeAddedToSatisfyPromos,
|
|
} from "@/helpers/promotions-helper";
|
|
import { queryStrings } from "@/constants/query-strings";
|
|
import { getQuerystringParameter } from "@/helpers/querystring-helper";
|
|
import { deepClone } from "@/helpers/object-helper";
|
|
import { submitWorkOrder } from "@/helpers/heritage-integration/order-helper.js";
|
|
|
|
import iframeResize from "../../../node_modules/iframe-resizer/js/iframeResizer.js";
|
|
import { routerParams } from "@/router/router-constants/router-params";
|
|
|
|
export default {
|
|
name: "payment",
|
|
data() {
|
|
return {
|
|
checkoutUrl: externalUrls.SAFELITE_HOP,
|
|
piaResponseUrl: applicationConfig.PIA_RESPONSE_URL,
|
|
piaCancelUrl: applicationConfig.PIA_CANCEL_URL,
|
|
paymentType: this.getPaymentType(),
|
|
authToken: "",
|
|
authSignature: "",
|
|
authSignatureStart: "",
|
|
referralSequenceNumber: store.getters.order.referralSequenceNumber,
|
|
emailAddress: store.getters.order.customer.emailAddress,
|
|
address1: this.getAddress1(),
|
|
address2: this.getAddress2(),
|
|
city: this.getCity(),
|
|
state: this.getState(),
|
|
zipCode: this.getZipCode(),
|
|
firstName: store.getters.order.customer.firstName,
|
|
lastName: store.getters.order.customer.lastName,
|
|
phoneNumber: store.getters.order.customer.phoneNumber,
|
|
ctu: store.getters.order.serviceLocation.zipCodeCtu,
|
|
referralCorrelationId: store.getters.order.referralCorrelationId,
|
|
workOrderNumber: this.getWOrkOrderNumber(),
|
|
invoiceNumber: this.getInvoiceNumber(),
|
|
totalAmount: this.getAmountDue(),
|
|
displayAmount: this.getDisplayAmountDue(),
|
|
piaLineItems: "",
|
|
lineItems: [],
|
|
availableVaps: [],
|
|
|
|
shouldBlockInteraction: false,
|
|
};
|
|
},
|
|
directives: {
|
|
resize: {
|
|
mounted: function (el) {
|
|
el.addEventListener("load", () => {
|
|
iframeResize({ checkOrigin: false }, el);
|
|
});
|
|
},
|
|
unmounted: function (el) {
|
|
el.iFrameResizer.removeListeners();
|
|
},
|
|
},
|
|
},
|
|
async beforeRouteEnter(to, from, next) {
|
|
// Call APIs
|
|
const cmsContentPromise = fetchCmsContentForPage(to.query.fmgPage);
|
|
|
|
const signaturePromise = baseMixin.methods.dispatchStoreActionWithLogging(
|
|
storeActions.GET_SIGNATURE,
|
|
null,
|
|
"payment"
|
|
);
|
|
|
|
const wipersPromise = baseMixin.methods.dispatchStoreActionWithLogging(
|
|
storeActions.GET_WIPERS,
|
|
{
|
|
serviceZipCode: store.getters.order.serviceLocation.zipCode,
|
|
carId: store.getters.vehicle.carId,
|
|
},
|
|
"payment"
|
|
);
|
|
|
|
const rainDefensePromise = baseMixin.methods.dispatchStoreActionWithLogging(
|
|
storeActions.GET_RAIN_DEFENSE,
|
|
null,
|
|
"payment"
|
|
);
|
|
|
|
const promiseResultMap = [
|
|
{
|
|
resultKey: "cmsContent",
|
|
promise: cmsContentPromise,
|
|
},
|
|
{
|
|
resultKey: "signature",
|
|
promise: signaturePromise,
|
|
},
|
|
{
|
|
resultKey: "wipers",
|
|
promise: wipersPromise,
|
|
},
|
|
{
|
|
resultKey: "rainDefense",
|
|
promise: rainDefensePromise,
|
|
},
|
|
];
|
|
|
|
const resultMap = await settleAllPromises(promiseResultMap);
|
|
const lineItemsFromStore = deepClone(store.getters.order.lineItems);
|
|
const glassParts = lineItemsFromStore.glassParts ?? [];
|
|
const supportingItems = lineItemsFromStore.supportingItems ?? [];
|
|
|
|
const lineItemsToTax = [
|
|
resultMap.rainDefense,
|
|
...supportingItems,
|
|
...resultMap.wipers,
|
|
...glassParts,
|
|
];
|
|
const availableVaps = [resultMap.rainDefense, ...resultMap.wipers];
|
|
|
|
const pricedLineItemsToTax = await baseMixin.methods.dispatchStoreActionWithLogging(
|
|
storeActions.PRICE_ORDER_ITEMS_AND_SAVE_SERVER_DATA,
|
|
{
|
|
availableLineItems: lineItemsToTax,
|
|
},
|
|
"payment",
|
|
false
|
|
);
|
|
|
|
// Promo logic
|
|
const promoCodeFromQueryString = getQuerystringParameter(queryStrings.PROMO);
|
|
|
|
const { validatePromoResponse, revalidatePromoResponse } =
|
|
await revalidatePromosAndValidateQueryStringPromo(
|
|
promoCodeFromQueryString,
|
|
pricedLineItemsToTax,
|
|
"payment"
|
|
);
|
|
|
|
const newValidatedPromos = validatePromoResponse?.orderPromos ?? [];
|
|
newValidatedPromos.push(
|
|
...(revalidatePromoResponse ? revalidatePromoResponse.promoLineItems : [])
|
|
);
|
|
|
|
pricedLineItemsToTax.push(...newValidatedPromos);
|
|
// End of promo logic
|
|
|
|
const taxedLineItems = await baseMixin.methods.dispatchStoreActionWithLogging(
|
|
storeActions.TAX_ORDER_ITEMS_AND_SAVE_SERVER_DATA,
|
|
{
|
|
billToAccountNumber: store.getters.payment.billToAccountNumber,
|
|
providerNumber: store.getters.order.serviceLocation.provider.providerNumber,
|
|
appointmentType: store.getters.order.serviceLocation.appointmentType,
|
|
serviceLocationCity: store.getters.order.serviceLocation.city,
|
|
serviceLocationState: store.getters.order.serviceLocation.state,
|
|
serviceLocationZipCode: store.getters.order.serviceLocation.zipCode,
|
|
pricedLineItems: pricedLineItemsToTax,
|
|
},
|
|
"payment",
|
|
false
|
|
);
|
|
|
|
// Match all line items to the line items as they are in the store
|
|
// and rebuild the original structure.
|
|
const lineItems = mapTaxedLineItemsToStoreFormat(taxedLineItems, lineItemsFromStore);
|
|
const taxedVaps = mapTaxedLineItemsToStoreFormat(taxedLineItems, availableVaps);
|
|
|
|
// Add items that were not in the store yet but added via query string promo validation
|
|
//newValidatedPromos contains both validated and revalidated promos.
|
|
lineItems.promos = Array.from(newValidatedPromos);
|
|
const vapsToAddToCart = getVapsThatNeedToBeAddedToSatisfyPromos(
|
|
newValidatedPromos,
|
|
taxedVaps,
|
|
lineItems
|
|
);
|
|
lineItems.vaps = lineItems.vaps ?? [];
|
|
lineItems.vaps.push(...vapsToAddToCart);
|
|
|
|
// Call the "next" function to complete the transition to this page.
|
|
next(async (vm) => {
|
|
vm.setCmsContent(resultMap.cmsContent);
|
|
vm.availableVaps = taxedVaps;
|
|
vm.lineItems = lineItems;
|
|
|
|
vm.$nextTick(() => {
|
|
if (vm.$refs.cart) {
|
|
const cartItems = vm.$refs.cart.cartItems;
|
|
vm.getPiaLineItems(cartItems);
|
|
}
|
|
|
|
vm.fetchSignatureInfo(resultMap.signature);
|
|
vm.setIFrameListener();
|
|
});
|
|
});
|
|
},
|
|
computed: {
|
|
dynamicCSSUrl() {
|
|
const { protocol, hostname, port } = window.location;
|
|
return `${protocol}//${hostname}:${port}/fmg/css/site-2020Styling.css`;
|
|
},
|
|
dynamicHopCSSUrl() {
|
|
const { protocol, hostname, port } = window.location;
|
|
return `${protocol}//${hostname}:${port}/fmg/css/hop-styling.css`;
|
|
},
|
|
getHeaderLine1() {
|
|
if (!this.isPaypal) {
|
|
return this.getCmsContent("PIAHeaderLine1", "Text");
|
|
}
|
|
return "";
|
|
},
|
|
getHeaderLine2() {
|
|
if (!this.isPaypal) {
|
|
return this.getCmsContent("PIAHeaderLine2", "Text");
|
|
}
|
|
return "";
|
|
},
|
|
damageInfo() {
|
|
return this.$store.getters.damage;
|
|
},
|
|
isPaypal() {
|
|
if (this.paymentType == "pp") {
|
|
return true;
|
|
}
|
|
return false;
|
|
},
|
|
shouldDisplayPiaCCAlert() {
|
|
return this.shouldDisplayPiaAlert(paymentMethods.CREDIT_CARD);
|
|
},
|
|
shouldDisplayPiaAPAlert() {
|
|
return this.shouldDisplayPiaAlert(paymentMethods.AFTERPAY);
|
|
},
|
|
},
|
|
methods: {
|
|
arePagePrerequisitesValid() {
|
|
// Service Location
|
|
const serviceLocation = store.getters.order.serviceLocation;
|
|
const mobileReqs = !!(
|
|
serviceLocation.address &&
|
|
serviceLocation.city &&
|
|
serviceLocation.state &&
|
|
serviceLocation.zipCode
|
|
);
|
|
|
|
const providerLocation = serviceLocation.provider.address;
|
|
const dropOffInshopReqs = !!(
|
|
providerLocation.streetAddress &&
|
|
providerLocation.city &&
|
|
providerLocation.state &&
|
|
providerLocation.zipCode
|
|
);
|
|
|
|
const isMobile = serviceLocation.appointmentType === AppointmentTypeStrings.MOBILE;
|
|
|
|
const serviceLocationReqs =
|
|
(isMobile && mobileReqs) || (!isMobile && dropOffInshopReqs);
|
|
|
|
// Insurance
|
|
const isInsuranceSet = store.getters.order.payment.isInsurance !== null;
|
|
|
|
// Schedule
|
|
const schedule = store.getters.order.schedule;
|
|
const scheduleReqs = !!(
|
|
schedule.date &&
|
|
schedule.startTime &&
|
|
schedule.endTime &&
|
|
schedule.jobMaxMinutes &&
|
|
schedule.jobMinMinutes
|
|
);
|
|
|
|
// Customer
|
|
const customer = store.getters.order.customer;
|
|
const customerReqs = !!(
|
|
customer.firstName &&
|
|
customer.lastName &&
|
|
customer.phoneNumber &&
|
|
customer.emailAddress
|
|
);
|
|
|
|
const paymentMethodReqs =
|
|
store.getters.order.payment.isPia !== null &&
|
|
(store.getters.order.payment.isPia || !!store.getters.order.payment.piaType);
|
|
|
|
return (
|
|
serviceLocationReqs &&
|
|
isInsuranceSet &&
|
|
scheduleReqs &&
|
|
customerReqs &&
|
|
paymentMethodReqs
|
|
);
|
|
},
|
|
getWOrkOrderNumber() {
|
|
if (store.getters.order.workOrderNumber) {
|
|
const items = store.getters.order.workOrderNumber.split("-");
|
|
return items[1];
|
|
}
|
|
|
|
this.backButtonAction();
|
|
},
|
|
getInvoiceNumber() {
|
|
if (store.getters.order.workOrderNumber) {
|
|
return store.getters.order.workOrderNumber.replace("-", "");
|
|
}
|
|
|
|
this.backButtonAction();
|
|
},
|
|
getAddress1() {
|
|
return store.getters.order.serviceLocation.address
|
|
? store.getters.order.serviceLocation.address
|
|
: store.getters.order.serviceLocation.provider.address.streetAddress;
|
|
},
|
|
getAddress2() {
|
|
return store.getters.order.serviceLocation.address2
|
|
? store.getters.order.serviceLocation.address2
|
|
: null;
|
|
},
|
|
getCity() {
|
|
return store.getters.order.serviceLocation.city
|
|
? store.getters.order.serviceLocation.city
|
|
: store.getters.order.serviceLocation.provider.address.city;
|
|
},
|
|
getState() {
|
|
return store.getters.order.serviceLocation.state
|
|
? store.getters.order.serviceLocation.state
|
|
: store.getters.order.serviceLocation.provider.address.state;
|
|
},
|
|
getZipCode() {
|
|
return store.getters.order.serviceLocation.zipCode
|
|
? store.getters.order.serviceLocation.zipCode
|
|
: store.getters.order.serviceLocation.provider.address.zipCode;
|
|
},
|
|
getPaymentType() {
|
|
switch (store.getters.order.payment.piaType) {
|
|
case paymentMethods.AFTERPAY:
|
|
return "ap";
|
|
case paymentMethods.CREDIT_CARD:
|
|
return "cc";
|
|
case paymentMethods.PAYPAL:
|
|
return "pp";
|
|
default:
|
|
return store.getters.payment.piaType;
|
|
}
|
|
},
|
|
getPiaLineItems(cartItems) {
|
|
const glassParts = store.getters.order.lineItems.glassParts;
|
|
let lineItems = [];
|
|
|
|
if (glassParts === null) {
|
|
lineItems = ["Labor|0|1", "Repair supplies|0|1"];
|
|
} else {
|
|
lineItems = ["Parts and labor|0|1"];
|
|
}
|
|
|
|
cartItems.forEach((item) => {
|
|
if (item.name !== null && item.category != "promos") {
|
|
lineItems.push(`${item.name}|${(item.salesTax + item.subTotal).toFixed(2)}|1`);
|
|
}
|
|
});
|
|
|
|
this.piaLineItems = lineItems.join("||");
|
|
},
|
|
getAmountDue() {
|
|
return baseMixin.methods.getAmountDue(store.getters.order.lineItems);
|
|
},
|
|
getDisplayAmountDue() {
|
|
return baseMixin.methods.getDisplayAmountDue(store.getters.order.lineItems);
|
|
},
|
|
async paymentFailedPayLater() {
|
|
this.$refs.loadingModal.isModalVisible = true;
|
|
|
|
await this.dispatchStoreAction(
|
|
storeActions.SAVE_PAYMENT_METHOD_CHOICE,
|
|
paymentMethods.LATER,
|
|
false
|
|
);
|
|
|
|
await this.dispatchStoreAction(storeActions.RESET_SAVE_SESSION_PROMISE);
|
|
try {
|
|
await submitWorkOrder({
|
|
pageNameToLog: "payment",
|
|
submitAfterSave: true,
|
|
});
|
|
|
|
await baseMixin.methods.dispatchStoreAction(storeActions.CREATE_SUBMITTED_ORDER);
|
|
window.location = applicationConfig.CONFIRMATION_URL;
|
|
} catch (error) {
|
|
console.log("error: response from submit work order(payment pg):" + error.message);
|
|
this.$router.navigateWithoutSaving(
|
|
this.navigationScenarios.PIA_ERROR,
|
|
this.$route,
|
|
{},
|
|
{ [routerParams.DISPLAY_PIA_ALERT]: true }
|
|
);
|
|
this.$refs.loadingModal.isModalVisible = false;
|
|
return;
|
|
}
|
|
},
|
|
backButtonAction() {
|
|
// The only way I could figure out how to get navigation to work on a page with the iframe.
|
|
// This is also how a cancel from Paypal would work. Just a redirect to the payment-method page.
|
|
// The normal navigation sort of works but the page does not render. The "next" callback function does not get
|
|
// invoked in payment-method's beforeroute enter. I also spotted an error in vue-router.esm-bundler.js when this
|
|
// happens but was unable to ignore it with a try catch. The navigation guard error is:
|
|
// Error: Redirected from "/?fmgPage=payment-method" to "{ params: {isSavingNation: "false"}, query: "fmgPage: "payment-method"}"
|
|
// I don't know if the navigation guard thinks the to and from are the same page.
|
|
// Also tried overriding with a $router.push
|
|
window.location = applicationConfig.PIA_CANCEL_URL;
|
|
//this.$router.navigateWithoutSaving(this.navigationScenarios.CLICKED_BACK, this.$route);
|
|
},
|
|
submitHopForm() {
|
|
this.$nextTick(() => {
|
|
this.$refs.hopForm.submit();
|
|
|
|
const iframe = this.$refs.paymentFrame;
|
|
if (iframe) {
|
|
iframe.onload = () => {
|
|
if (iframe.contentWindow) {
|
|
if (this.paymentType == "cc") {
|
|
iframe.contentWindow.postMessage("CreditCardChosen", "*");
|
|
} else if (this.paymentType == "ap") {
|
|
iframe.contentWindow.postMessage("afterpay", "*");
|
|
}
|
|
}
|
|
};
|
|
}
|
|
});
|
|
},
|
|
async fetchSignatureInfo(signatureInfo) {
|
|
if (this.isPaypal) {
|
|
this.$refs.loadingModal.showModal();
|
|
}
|
|
|
|
this.authToken = signatureInfo.token;
|
|
this.authSignature = signatureInfo.signature;
|
|
this.authSignatureStart = signatureInfo.startDate;
|
|
|
|
this.submitHopForm();
|
|
},
|
|
handleIFrameContentWindwMessage(event) {
|
|
if (event.data.indexOf("afterpayClosed") > -1) {
|
|
this.backButtonAction();
|
|
}
|
|
if (event.data.indexOf("creditCardSubmit") > -1) {
|
|
this.setUIBlock(true);
|
|
}
|
|
},
|
|
setIFrameListener() {
|
|
window.addEventListener("message", (event) =>
|
|
this.handleIFrameContentWindwMessage(event)
|
|
);
|
|
},
|
|
setUIBlock(val) {
|
|
this.shouldBlockInteraction = val;
|
|
},
|
|
supressClick(event) {
|
|
if (this.shouldBlockInteraction) {
|
|
event.stopPropagation();
|
|
}
|
|
},
|
|
shouldDisplayPiaAlert(payMethod) {
|
|
return (
|
|
this.$route.query[queryStrings.DISPLAY_PIA_ALERT] === payMethod ||
|
|
this.$route.params[routerParams.DISPLAY_PIA_ALERT] === payMethod
|
|
);
|
|
},
|
|
},
|
|
components: {
|
|
funnelHeader,
|
|
navbar,
|
|
loadingModal,
|
|
cart,
|
|
alert,
|
|
},
|
|
};
|
|
</script>
|
|
|
|
<style lang="scss">
|
|
.hop-iframe {
|
|
position: relative;
|
|
min-height: 650px;
|
|
width: 100%;
|
|
border: 0 none;
|
|
}
|
|
#pageLoadingModal {
|
|
background-color: red;
|
|
}
|
|
|
|
.ui-block {
|
|
position: fixed;
|
|
top: 0;
|
|
bottom: 0;
|
|
left: 0;
|
|
right: 0;
|
|
z-index: 9999;
|
|
}
|
|
</style>
|