- Add some missing semicolons - Better null checking for iframe - Better iOS check - Correct icon for successful dropdown input
973 lines
32 KiB
Vue
973 lines
32 KiB
Vue
<template>
|
|
<Form>
|
|
<div class="fade-on-route-transition">
|
|
<div class="justify-content-center">
|
|
<siteHeader cmsWidgetName="SiteHeaderWidget" />
|
|
</div>
|
|
<div class="iss-heritage-container-width payment-page-container">
|
|
<div id="card-container" class="row">
|
|
<div class="col-lg-8">
|
|
<alert
|
|
v-if="displayPayInAdvanceCreditCardAlert"
|
|
name="payInAdvanceCreditCardErrorAlert"
|
|
class="pay-in-advance-alert"
|
|
cmsWidgetName="PayInAdvanceCreditCardErrorAlertWidget"
|
|
alertClass="alert-danger"
|
|
:isDismissible="false"
|
|
:isCollapsible="true"
|
|
:preventDefaultOnClick="true"
|
|
@textLinkClicked="paymentFailedPayLater" />
|
|
<alert
|
|
v-if="displayPayInAdvanceAfterPayAlert"
|
|
name="payInAdvanceAfterPayErrorAlert"
|
|
class="pay-in-advance-alert"
|
|
cmsWidgetName="PayInAdvanceAfterpayErrorAlertWidget"
|
|
alertClass="alert-danger"
|
|
:isDismissible="false"
|
|
:isCollapsible="true"
|
|
:preventDefaultOnClick="true"
|
|
@textLinkClicked="paymentFailedPayLater" />
|
|
<iframe
|
|
id="card-frame"
|
|
ref="paymentFrame"
|
|
v-resize
|
|
class="hop-iframe payment-iframe"
|
|
name="card-frame"
|
|
seamless
|
|
scrolling="no"
|
|
allow="payment *; microphone *; geolocation *; loopback-network *;">
|
|
</iframe>
|
|
</div>
|
|
<div class="col-lg-4 col-md-10 col-xs-12">
|
|
<div class="order-summary-panel">
|
|
<div class="cart-title">{{ cartTitle }}</div>
|
|
<cartDropdown
|
|
ref="cart"
|
|
class="cart-dropdown-component"
|
|
:readOnly="true"
|
|
:showAsPaid="false"
|
|
recyclingModalCmsWidgetName="RecycleModal"
|
|
servicePackageTitleWidgetName="ServicePackageTitle" />
|
|
</div>
|
|
<div class="d-none d-lg-block">
|
|
<buttonMain
|
|
v-if="!afterpayModalOpen"
|
|
class="submit-payment-button"
|
|
variant="success"
|
|
:preventDefaultOnClick="true"
|
|
:buttonText="submitPaymentText"
|
|
@clickEvent="submitPaymentAction"
|
|
/>
|
|
</div>
|
|
<div
|
|
v-if="!afterpayModalOpen"
|
|
class="switch-payment-container">
|
|
<div class="switch-payment-text">{{ switchPaymentText }}</div>
|
|
<button
|
|
class="afterpay-button"
|
|
@click.prevent="switchToAfterPay">
|
|
{{ afterpayButtonText }}
|
|
<img
|
|
class="afterpay-logo"
|
|
:src="afterpayLogo"
|
|
alt="Afterpay Logo" />
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="col-xs-12">
|
|
<siteFooter
|
|
class="footer-component"
|
|
ref="siteFooter"
|
|
cmsWidgetName="SiteFooterWidget"
|
|
:isForwardActionDisabled="true"
|
|
:isForwardButtonHidden="true"
|
|
@ForwardClicked="forwardButtonAction"
|
|
@backClicked="backButtonAction" />
|
|
</div>
|
|
</div>
|
|
<div
|
|
v-if="shouldBlockInteraction"
|
|
class="ui-block"
|
|
@click="supressClick"></div>
|
|
</div>
|
|
</Form>
|
|
|
|
<form
|
|
id="card-data"
|
|
ref="hopForm"
|
|
: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="payInAdvanceResponseUrl" />
|
|
<input
|
|
type="hidden"
|
|
name="sgDeclineResponseURL"
|
|
:value="payInAdvanceResponseUrl" />
|
|
<input
|
|
type="hidden"
|
|
name="sgErrorResponseURL"
|
|
:value="payInAdvanceResponseUrl" />
|
|
<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="zipCode" />
|
|
<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="payInAdvanceLineItems" />
|
|
<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="payInAdvanceResponseUrl" />
|
|
<input
|
|
type="hidden"
|
|
name="paypalCancelUrl"
|
|
:value="payInAdvanceCancelUrl" />
|
|
<input
|
|
type="hidden"
|
|
name="sgCCDeclineURL"
|
|
:value="payInAdvanceCancelUrl" />
|
|
<input
|
|
type="hidden"
|
|
name="sgCCTimeoutURL"
|
|
:value="payInAdvanceCancelUrl" />
|
|
<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="ISSNextGen" />
|
|
|
|
<input
|
|
type="hidden"
|
|
name="parentdomainname"
|
|
:value="parentDomainName" />
|
|
</form>
|
|
</template>
|
|
<script>
|
|
// Components
|
|
import siteHeader from '@/iss-components/site-header/site-header.vue';
|
|
import siteFooter from '@/iss-components/site-footer/site-footer.vue';
|
|
|
|
// Supporting files
|
|
import issPageValues from '@/router/router-constants/issPage-values.js';
|
|
import { fetchCmsContentForPage } from '@/helpers/cms-content-helper';
|
|
import settleAllPromises from '@/helpers/layout-helper';
|
|
import { Form } from 'vee-validate';
|
|
import BaseFormMixin from '@/mixins/base-form-mixin.js';
|
|
import { getCartTotal } from '@/helpers/cart-helper';
|
|
import { useMainStore } from '@/store';
|
|
import iframeResize from 'iframe-resizer/js/iframeResizer.js';
|
|
import externalUrls from '@/router/router-constants/externalUrl-values.js';
|
|
import widgetFields from '@/constants/cms-widget-fields.js';
|
|
import { paymentMethods } from '@/constants/payment-method-constants.js';
|
|
import { AppointmentTypeStrings } from '@/constants/schedule-constants.js';
|
|
import queryStrings from '@/constants/query-strings';
|
|
import alert from '@/ux-components/alert/alert.vue';
|
|
import cartDropdown from '@/iss-components/cart-dropdown/cart-dropdown.vue';
|
|
import { formatAmountInDollars } from '@/helpers/text-helper';
|
|
import showIssLoadingModal from '@/helpers/loading-modal-helper';
|
|
import { supportsApplePay } from '@/helpers/browser-helper';
|
|
import buttonMain from '@/ux-components/button-main/button-main.vue';
|
|
import { submitWorkOrder } from '@/helpers/order-helper';
|
|
import submitType from '@/constants/submit-type';
|
|
|
|
export default {
|
|
name: 'payment-page',
|
|
components: {
|
|
cartDropdown,
|
|
siteHeader,
|
|
siteFooter,
|
|
Form,
|
|
alert,
|
|
buttonMain
|
|
},
|
|
directives: {
|
|
resize: {
|
|
mounted(el) {
|
|
el.addEventListener('load', () => {
|
|
iframeResize({ checkOrigin: false }, el);
|
|
});
|
|
},
|
|
unmounted(el) {
|
|
el.iFrameResizer.removeListeners();
|
|
}
|
|
}
|
|
},
|
|
mixins: [BaseFormMixin],
|
|
async beforeRouteEnter(to, from, next) {
|
|
const paymentType = useMainStore().order.payment.paymentMethod;
|
|
const alertToDisplay = to.query[queryStrings.DISPLAY_PAY_IN_ADVANCE_ALERT];
|
|
if (paymentType === paymentMethods.PAYPAL || alertToDisplay) {
|
|
useMainStore().savePaymentMethodChoice(paymentMethods.CREDIT_CARD);
|
|
}
|
|
|
|
// Call APIs
|
|
const cmsContentPromise = fetchCmsContentForPage(to.query.issPage);
|
|
|
|
const paymentSignaturePromise = await useMainStore().getPaymentSignature();
|
|
|
|
// Settle promises and get results
|
|
const promiseResultMap = [
|
|
{
|
|
resultKey: 'cmsContent',
|
|
promise: cmsContentPromise
|
|
},
|
|
{
|
|
resultKey: 'paymentSignature',
|
|
promise: paymentSignaturePromise
|
|
}
|
|
];
|
|
|
|
// use resultMap to populate layout content.
|
|
const resultMap = await settleAllPromises(promiseResultMap);
|
|
|
|
next((vm) => {
|
|
vm.setCmsContent(resultMap.cmsContent);
|
|
vm.$nextTick(() => {
|
|
if (vm.$refs.cart) {
|
|
const cartItems = vm.$refs.cart.cartItems;
|
|
vm.getPayInAdvanceLineItems(cartItems);
|
|
}
|
|
|
|
vm.fetchSignatureInfo(resultMap.paymentSignature);
|
|
vm.setIFrameListener();
|
|
});
|
|
});
|
|
},
|
|
setup() {
|
|
const mainStore = useMainStore();
|
|
return { mainStore };
|
|
},
|
|
data() {
|
|
return {
|
|
checkoutUrl: externalUrls.SAFELITE_HOP,
|
|
paymentType: useMainStore().order.payment.paymentMethod,
|
|
authToken: '',
|
|
authSignature: '',
|
|
authSignatureStart: '',
|
|
referralSequenceNumber: useMainStore().order.referralSequenceNumber,
|
|
emailAddress: useMainStore().contactInfo.emailAddress,
|
|
address1: this.getAddress1(),
|
|
address2: this.getAddress2(),
|
|
city: this.getCity(),
|
|
state: this.getState(),
|
|
zipCode: this.getZipCode(),
|
|
firstName: useMainStore().contactInfo.firstName,
|
|
lastName: useMainStore().contactInfo.lastName,
|
|
phoneNumber: useMainStore().contactInfo.servicePhone,
|
|
ctu: useMainStore().order.serviceLocation.provider?.address?.zipCodeCtu ?? useMainStore().order.serviceLocation.zipCodeCtu,
|
|
referralCorrelationId: useMainStore().order.referralCorrelationId,
|
|
workOrderNumber: this.getWorkOrderNumber(),
|
|
invoiceNumber: this.getInvoiceNumber(),
|
|
totalAmount: this.getAmountDue(),
|
|
displayAmount: this.getDisplayAmountDue(),
|
|
payInAdvanceLineItems: '',
|
|
shouldBlockInteraction: false,
|
|
afterpayModalOpen: false
|
|
};
|
|
},
|
|
computed: {
|
|
parentDomainName() {
|
|
return window.location.hostname;
|
|
},
|
|
payInAdvanceResponseUrl() {
|
|
const { protocol, host } = window.location;
|
|
return `${protocol}//${host}/?issPage=${issPageValues.PAYMENT_RETURN}&src=iss-nextgen`;
|
|
},
|
|
payInAdvanceCancelUrl() {
|
|
const { protocol, host } = window.location;
|
|
return `${protocol}//${host}/?issPage=${issPageValues.PAYMENT_METHOD}&src=iss-nextgen`;
|
|
},
|
|
dynamicCSSUrl() {
|
|
const { protocol, hostname, port } = window.location;
|
|
return `${protocol}//${hostname}:${port}/css/site-2020Styling.css`;
|
|
},
|
|
dynamicHopCSSUrl() {
|
|
const { protocol, hostname, port } = window.location;
|
|
return `${protocol}//${hostname}:${port}/css/hop-styling.css`;
|
|
},
|
|
getHeaderLine1() {
|
|
if (!this.isPaypal) {
|
|
return this.getCmsContent('PayInAdvanceHeaderLine1', widgetFields.TEXT_BLOCK_WIDGET.TEXT);
|
|
}
|
|
return '';
|
|
},
|
|
getHeaderLine2() {
|
|
if (!this.isPaypal) {
|
|
return this.getCmsContent(
|
|
'PayInAdvanceHeaderLine2',
|
|
widgetFields.TEXT_BLOCK_WIDGET.TEXT
|
|
);
|
|
}
|
|
return '';
|
|
},
|
|
cartTitle() {
|
|
return this.getCmsContent('OrderSummaryTextWidget', widgetFields.TEXT_BLOCK_WIDGET.TEXT);
|
|
},
|
|
switchPaymentText() {
|
|
return this.getCmsContent('SwitchPaymentTextWidget', widgetFields.TEXT_BLOCK_WIDGET.TEXT);
|
|
},
|
|
submitPaymentText() {
|
|
return this.getCmsContent('SiteFooterWidget', widgetFields.FOOTER_WIDGET.FORWARD_BUTTON_TEXT);
|
|
},
|
|
afterpayButtonText() {
|
|
return this.getCmsContent('AfterpayButtonWidget', widgetFields.CONTENT_GROUP_WIDGET.HEADER_TEXT);
|
|
},
|
|
afterpayLogo() {
|
|
return this.getCmsContent('AfterpayButtonWidget', widgetFields.CONTENT_GROUP_WIDGET.IMAGE);
|
|
},
|
|
isPaypal() {
|
|
return this.paymentType === paymentMethods.PAYPAL;
|
|
},
|
|
isCreditCard() {
|
|
return this.paymentType === paymentMethods.CREDIT_CARD;
|
|
},
|
|
isAfterPay() {
|
|
return this.paymentType === paymentMethods.AFTERPAY;
|
|
},
|
|
isPayNow() {
|
|
return this.paymentType === paymentMethods.PayNow;
|
|
},
|
|
displayPayInAdvanceCreditCardAlert() {
|
|
return this.displayPayInAdvanceAlert(paymentMethods.CREDIT_CARD);
|
|
},
|
|
displayPayInAdvanceAfterPayAlert() {
|
|
return this.displayPayInAdvanceAlert(paymentMethods.AFTERPAY);
|
|
}
|
|
},
|
|
methods: {
|
|
arePagePrerequisitesValid() {
|
|
// Line Items
|
|
const packageReqs =
|
|
!!useMainStore().order.lineItems.supportingItems;
|
|
|
|
// Service Location
|
|
const { serviceLocation } = useMainStore().order;
|
|
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
|
|
|| serviceLocation.appointmentType === AppointmentTypeStrings.MOBILE_NOT_ITAC_AND_NOT_NOCOMP;
|
|
|
|
const serviceLocationReqs =
|
|
(isMobile && mobileReqs) || (!isMobile && dropOffInshopReqs);
|
|
|
|
// Insurance
|
|
const isInsuranceSet =
|
|
useMainStore().order.payment.isInsurance !== null;
|
|
|
|
// Schedule
|
|
const { schedule } = useMainStore().order;
|
|
const scheduleReqs = !!(
|
|
schedule.date
|
|
&& schedule.startTime
|
|
&& schedule.endTime
|
|
&& schedule.jobMaxMinutes
|
|
&& schedule.jobMinMinutes
|
|
);
|
|
|
|
// Contact Info
|
|
const { contactInfo } = useMainStore();
|
|
const contactInfoReqs = !!(
|
|
contactInfo.firstName
|
|
&& contactInfo.lastName
|
|
&& contactInfo.servicePhone
|
|
&& contactInfo.emailAddress
|
|
);
|
|
|
|
const paymentMethodReqs = useMainStore().isPayInAdvance;
|
|
|
|
return (
|
|
packageReqs
|
|
&& serviceLocationReqs
|
|
&& isInsuranceSet
|
|
&& scheduleReqs
|
|
&& contactInfoReqs
|
|
&& paymentMethodReqs
|
|
);
|
|
},
|
|
getWorkOrderNumber() {
|
|
const { workOrderNumber } = useMainStore().order;
|
|
if (workOrderNumber) {
|
|
const items = workOrderNumber.split('-');
|
|
if (items.length > 1) {
|
|
return items[1];
|
|
}
|
|
}
|
|
return undefined;
|
|
},
|
|
getInvoiceNumber() {
|
|
const { workOrderNumber } = useMainStore().order;
|
|
if (workOrderNumber) {
|
|
return workOrderNumber.replace('-', '');
|
|
}
|
|
return undefined;
|
|
},
|
|
getAddress1() {
|
|
return (
|
|
useMainStore().order.serviceLocation.address
|
|
?? useMainStore().order.serviceLocation.provider.address
|
|
.streetAddress
|
|
);
|
|
},
|
|
getAddress2() {
|
|
return useMainStore().order.serviceLocation.address2;
|
|
},
|
|
getCity() {
|
|
return (
|
|
useMainStore().order.serviceLocation.city
|
|
?? useMainStore().order.serviceLocation.provider.address.city
|
|
);
|
|
},
|
|
getState() {
|
|
return (
|
|
useMainStore().order.serviceLocation.state
|
|
?? useMainStore().order.serviceLocation.provider.address.state
|
|
);
|
|
},
|
|
getZipCode() {
|
|
return (
|
|
useMainStore().order.customer.address.zipCode
|
|
?? useMainStore().order.serviceLocation.zipCode
|
|
?? useMainStore().order.serviceLocation.provider.address.zipCode
|
|
);
|
|
},
|
|
getPayInAdvanceLineItems(cartItems) {
|
|
const { glassParts } = useMainStore().order.lineItems;
|
|
const lineItems =
|
|
glassParts === null
|
|
? [
|
|
this.getPayInAdvanceFormattedLineItem('Labor', 0, 1),
|
|
this.getPayInAdvanceFormattedLineItem('Repair supplies', 0, 1)
|
|
]
|
|
: [
|
|
this.getPayInAdvanceFormattedLineItem('Parts and labor', 0, 1)
|
|
];
|
|
|
|
cartItems.forEach((item) => {
|
|
if (item.name !== null && item.category !== 'promos') {
|
|
lineItems.push(this.getPayInAdvanceFormattedLineItem(
|
|
item.name,
|
|
(item.salesTax + item.subTotal).toFixed(2),
|
|
1
|
|
));
|
|
}
|
|
});
|
|
|
|
this.payInAdvanceLineItems = lineItems.join('||');
|
|
},
|
|
getPayInAdvanceFormattedLineItem(itemName, price, quantity) {
|
|
return `${itemName}|${price}|${quantity}`;
|
|
},
|
|
getAmountDue() {
|
|
return getCartTotal(useMainStore().order);
|
|
},
|
|
getDisplayAmountDue() {
|
|
return formatAmountInDollars(this.getAmountDue());
|
|
},
|
|
fetchSignatureInfo(signatureInfo) {
|
|
this.authToken = signatureInfo.token;
|
|
this.authSignature = signatureInfo.signature;
|
|
this.authSignatureStart = signatureInfo.startDate;
|
|
|
|
this.submitHopForm();
|
|
},
|
|
submitHopForm() {
|
|
this.$nextTick(() => {
|
|
this.$refs.hopForm.submit();
|
|
|
|
const iframe = this.$refs.paymentFrame;
|
|
if (iframe) {
|
|
iframe.onload = () => {
|
|
if (iframe.contentWindow) {
|
|
if (supportsApplePay()) {
|
|
iframe.contentWindow.postMessage("hybrid-with-applepay", "*");
|
|
} else {
|
|
iframe.contentWindow.postMessage('hybrid', '*');
|
|
}
|
|
|
|
if (this.isAfterPay) {
|
|
this.afterpayModalOpen = true;
|
|
iframe.contentWindow.postMessage('afterpay', '*');
|
|
} else {
|
|
iframe.contentWindow.postMessage('CreditCardChosen', '*');
|
|
}
|
|
}
|
|
};
|
|
}
|
|
});
|
|
},
|
|
handleIFrameContentWindowMessage(event) {
|
|
const iframe = this.$refs.paymentFrame;
|
|
if (typeof event.data !== 'string') {
|
|
return;
|
|
}
|
|
|
|
if (event.data.includes('afterpayClosed')) {
|
|
if (this.isAfterPay) {
|
|
this.backButtonAction();
|
|
} else {
|
|
iframe.contentWindow.postMessage('CreditCardChosen', '*');
|
|
this.afterpayModalOpen = false;
|
|
}
|
|
}
|
|
|
|
if (useMainStore().order.payment.paymentMethod !== paymentMethods.PayNow) {
|
|
return;
|
|
}
|
|
|
|
if (event.data.includes('creditCardSubmit')) {
|
|
this.showIssLoadingModal(true);
|
|
useMainStore().savePaymentMethodChoice(paymentMethods.CREDIT_CARD);
|
|
this.setUIBlock(true);
|
|
}
|
|
if (event.data.includes('afterpayPaymentReceived')) {
|
|
this.showIssLoadingModal(true);
|
|
useMainStore().savePaymentMethodChoice(paymentMethods.AFTERPAY);
|
|
}
|
|
if (event.data.includes('applepayOpened')) {
|
|
this.showIssLoadingModal(true);
|
|
useMainStore().savePaymentMethodChoice(paymentMethods.APPLEPAY);
|
|
}
|
|
if (event.data.includes('showLoaderForPaypal')) {
|
|
this.showIssLoadingModal(true);
|
|
useMainStore().savePaymentMethodChoice(paymentMethods.PAYPAL);
|
|
}
|
|
},
|
|
setIFrameListener() {
|
|
window.addEventListener('message', this.handleIFrameContentWindowMessage);
|
|
},
|
|
setUIBlock(val) {
|
|
this.shouldBlockInteraction = val;
|
|
},
|
|
supressClick(event) {
|
|
if (this.shouldBlockInteraction) {
|
|
event.stopPropagation();
|
|
}
|
|
},
|
|
displayPayInAdvanceAlert(payMethod) {
|
|
return (
|
|
this.$route.query[queryStrings.DISPLAY_PAY_IN_ADVANCE_ALERT] === payMethod
|
|
);
|
|
},
|
|
async paymentFailedPayLater() {
|
|
this.showIssLoadingModal(true);
|
|
this.mainStore.savePaymentMethodChoice(paymentMethods.PAY_AT_TIME_OF_SERVICE);
|
|
await submitWorkOrder({ submitType: submitType.SAFELITE });
|
|
this.$router.navigate(
|
|
this.navigationScenarios.CLICKED_FORWARD,
|
|
this.$route
|
|
);
|
|
},
|
|
backButtonAction() {
|
|
// page will not render with normal navigation due to navigating from the iframe
|
|
window.location = this.payInAdvanceCancelUrl;
|
|
},
|
|
forwardButtonAction() {
|
|
this.$router.navigate(
|
|
this.navigationScenarios.CLICKED_FORWARD,
|
|
this.$route
|
|
);
|
|
},
|
|
submitPaymentAction() {
|
|
const iframe = this.$refs.paymentFrame;
|
|
if (iframe && iframe.contentWindow) {
|
|
iframe.contentWindow.postMessage('submitPayment', '*');
|
|
}
|
|
},
|
|
switchToAfterPay() {
|
|
const iframe = this.$refs.paymentFrame;
|
|
if (iframe && iframe.contentWindow) {
|
|
this.afterpayModalOpen = true;
|
|
iframe.contentWindow.postMessage('afterpay-switch', '*');
|
|
}
|
|
},
|
|
showIssLoadingModal
|
|
}
|
|
};
|
|
</script>
|
|
<style lang="scss" scoped>
|
|
.iss-heritage-container-width.payment-page-container {
|
|
padding: 0 .9375rem;
|
|
|
|
#card-container {
|
|
padding-top: 1.375rem;
|
|
margin: 0;
|
|
> * {
|
|
padding: 0 .9375rem;
|
|
}
|
|
}
|
|
|
|
.order-summary-panel {
|
|
margin-bottom: 1.375rem;
|
|
}
|
|
|
|
.cart-title {
|
|
font-size: 1rem;
|
|
font-weight: 500;
|
|
margin-top: 1.25rem;
|
|
margin-bottom: .625rem;
|
|
}
|
|
|
|
.cart-dropdown-component.cart-table {
|
|
font-size: .8125rem;
|
|
}
|
|
|
|
.submit-payment-button {
|
|
width: 100%;
|
|
font-weight: $font-weight-normal;
|
|
}
|
|
|
|
.switch-payment-container {
|
|
@include media-breakpoint-up(lg) {
|
|
padding-top: 1.25rem;
|
|
}
|
|
}
|
|
|
|
.switch-payment-text {
|
|
padding-top: 1rem;
|
|
padding-bottom: .625rem;
|
|
border-top: 1px solid #f0f1f2;
|
|
}
|
|
|
|
.footer-component:deep(.footer) {
|
|
margin: 1.25rem 0 0 0;
|
|
}
|
|
|
|
.afterpay-button {
|
|
width: 100%;
|
|
height: 2.875rem;
|
|
border: solid 1px #cacbcc;
|
|
border-radius: 1.375rem;
|
|
background-color: white;
|
|
box-shadow: 0 1px 5px 0 rgba(0, 0, 0, 0.2);
|
|
color: $darker-gray;
|
|
font-weight: 400;
|
|
margin-bottom: 1.25rem;
|
|
padding: .5rem 1rem;
|
|
|
|
&:focus {
|
|
background: $background-color-selected;
|
|
}
|
|
&:active {
|
|
box-shadow: inset 0 3px 5px rgba(0, 0, 0, .125);
|
|
}
|
|
}
|
|
|
|
.pay-in-advance-alert {
|
|
width: 80%;
|
|
|
|
@media (max-width: 35rem) {
|
|
width: 100%;
|
|
}
|
|
}
|
|
}
|
|
|
|
.fade-on-route-transition {
|
|
height: unset;
|
|
}
|
|
|
|
.payment p {
|
|
margin-bottom: 0.75rem;
|
|
}
|
|
|
|
.hop-iframe {
|
|
position: relative;
|
|
min-height: 40.625rem;
|
|
width: 100%;
|
|
border: 0 none;
|
|
}
|
|
|
|
.ui-block {
|
|
position: fixed;
|
|
top: 0;
|
|
bottom: 0;
|
|
left: 0;
|
|
right: 0;
|
|
z-index: 9999;
|
|
}
|
|
</style>
|