DigitalConsumer.FixMyGlass/src/layouts/payment/payment.vue
2023-10-25 16:44:16 -04:00

392 lines
17 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" />
</div>
</div>
<div class="row justify-content-center">
<div class="col-md-6 col-xl-4 p-0">
<div id="card-container">
<iframe
ref="paymentFrame"
class="hop-iframe payment-iframe"
name="card-frame"
id="card-frame"
seamless
scrolling="no">
</iframe>
</div>
<navbar
cmsWidgetName="FunnelFooterWidget"
isForwardActionDisabled="true"
:isBackButtonHidden="shouldHideBackButton"
isSubmitHidden="true"
@back-clicked="backButtonAction" />
</div>
</div>
</div>
</Form>
<form
ref="myForm"
id="card-data"
:target="paypalPayment ? '_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="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 { 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 baseMixin from "@/mixins/base-mixin.js";
// Validation
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: this.getPiaLineItems(),
paypalPayment: this.isPaypal(),
};
},
async beforeRouteEnter(to, from, next) {
// Call APIs
const cmsContentPromise = fetchCmsContentForPage(to.query.fmgPage);
const signaturePromise = baseMixin.methods.dispatchStoreActionWithLogging(
storeActions.GET_SIGNATURE,
null,
"payment"
);
// TODO: Data fetching Promise declarations
const promiseResultMap = [
{
resultKey: "cmsContent",
promise: cmsContentPromise,
},
{
resultKey: "signature",
promise: signaturePromise,
},
];
const resultMap = await settleAllPromises(promiseResultMap);
// Call the "next" function to complete the transition to this page.
next(async (vm) => {
vm.setCmsContent(resultMap.cmsContent);
vm.fetchSignatureInfo(resultMap.signature);
});
},
computed: {
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 "";
},
},
methods: {
arePagePrerequisitesValid() {
// TODO
return true;
},
getWOrkOrderNumber() {
if (store.getters.order.workOrderNumber) {
const items = store.getters.order.workOrderNumber.split("-");
return items[1];
}
// no work order, set pia error and return
this.dispatchStoreAction(storeActions.SAVE_PIA_ERROR_CODE, "NO WORK ORDER", false);
this.backButtonAction();
},
getInvoiceNumber() {
if (store.getters.order.workOrderNumber) {
return store.getters.order.workOrderNumber.replace("-", "");
}
// no work order, set pia error and return
this.dispatchStoreAction(storeActions.SAVE_PIA_ERROR_CODE, "NO WORK ORDER", false);
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() {
let itemsForPia = "";
const glassParts = store.getters.order.lineItems.glassParts;
const supportingItems = store.getters.order.lineItems.supportingItems;
const vaps = store.getters.order.lineItems.vaps;
const items = [...(glassParts ?? []), ...(supportingItems ?? []), ...(vaps ?? [])];
for (let i = 0; i < items.length; i++) {
const amount = items[i].laborAmount + items[i].sellingPrice;
itemsForPia += items[i].partType + "|" + amount + "|1|";
}
return itemsForPia;
},
getAmountDue() {
return 1600;
//return baseMixin.methods.getAmountDue(store.getters.order.lineItems);
},
getDisplayAmountDue() {
return "$1600.00";
//return baseMixin.methods.getDisplayAmountDue(store.getters.order.lineItems);
},
isPaypal() {
if (this.getPaymentType() == "pp") {
return true;
}
return false;
},
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);
},
async fetchSignatureInfo(signatureInfo) {
if (this.isPaypal()) {
this.$refs.loadingModal.showModal();
}
this.authToken = signatureInfo.token;
this.authSignature = signatureInfo.signature;
this.authSignatureStart = signatureInfo.startDate;
this.$nextTick(() => {
this.$refs.myForm.submit();
if (this.paymentType == "ap") {
const iframe = this.$refs.paymentFrame;
if (iframe) {
iframe.onload = () => {
if (iframe.contentWindow) {
iframe.contentWindow.postMessage("afterpay", "*");
}
};
}
}
});
},
},
components: {
funnelHeader,
navbar,
loadingModal,
},
};
</script>
<style lang="scss">
.hop-iframe {
position: relative;
min-height: 1320px;
width: 100%;
border: 0 none;
}
</style>