const FUNNEL_STATES = JSON.parse('{"OFFER_TAPPED":"OFFER_TAPPED","PAYMENT_INFO_COMPLETE":"PAYMENT_INFO_COMPLETE","PRODUCT_OPTION_SELECTED":"PRODUCT_OPTION_SELECTED","APPOINTMENT_INFO_COMPLETED":"APPOINTMENT_INFO_COMPLETED","SHIPPING_ADDRESS_COMPLETED":"SHIPPING_ADDRESS_COMPLETED","PAYMENT_WENT_THROUGH":"PAYMENT_WENT_THROUGH","PAYMENT_DECLINED":"PAYMENT_DECLINED","CANCELED_APPOINTMENT_OPTIONS":"CANCELED_APPOINTMENT_OPTIONS","CANCELED_SHIPPING_OPTIONS":"CANCELED_SHIPPING_OPTIONS","CANCELED_CONFIRMATION_SCREEN":"CANCELED_CONFIRMATION_SCREEN","PAYMENT_REQUESTED_BY_CUSTOMER":"PAYMENT_REQUESTED_BY_CUSTOMER"}'); const PAYMENT_METHOD_CHARGE_FUNCTIONS = {}; const PAYMENT_METHOD_FURTHER_ACTION_FUNCTIONS = {}; const PAYMENT_METHOD_AUX_FUNCTIONS = {}; const DONE_ACTIONS = {}; const request = window.superagent; var iPhone = true; selectedDoneAction = null; var latestFunnelState = null; var orderId = null; function updateCustomer(dataToInclude) { if (singleProductCheckout) { var data = { customerId: customerId, socialId: replaceSocialIdForPhoneNumberWhenItIsNotDedined(), label: label, selectedPaymentMethod: selectedPaymentMethod }; } else { var Firstlabel = getFirstLabelFromShoppingCart(); var data = { customerId: customerId, socialId: replaceSocialIdForPhoneNumberWhenItIsNotDedined(), label: Firstlabel, selectedPaymentMethod: selectedPaymentMethod, }; } if (dataToInclude) { Object.keys(dataToInclude).forEach(key => { data[key] = dataToInclude[key]; }); } try { console.log('updateCustomer(): updating the customer ' + customerId + ' with data ' + JSON.stringify(dataToInclude, null, 2)); return request .post('/beta/customer/update') .set('X-Request-ID', correlationId) .send(data) } catch(e) { console.log('updateCustomer(): the request failed because of ' + e); } } function updateCustomerWithToken(cardToken) { var dataToInclude = { payments: cardToken }; updateCustomer(dataToInclude).end(); } function updateFunnelState(label, customerId, funnelState) { console.log('updateFunnelState(): updating customer ' + customerId + ' funnelState ' + funnelState + ' in label ' + label); latestFunnelState = funnelState; var interactionInstant = new Date(); var updateFunnelRequest = { customerId: customerId, label: label, funnelState: funnelState, time: Date.now(), timezone: interactionInstant.getTimezoneOffset() }; try { console.log('updateFunnelState(): setting funnel for ' + customerId + ' to ' + funnelState); return request .post('/beta/funnel/update') .set('X-Request-ID', correlationId) .send(updateFunnelRequest) } catch(e) { console.log('updateFunnelState(): the request failed because of ' + e); } } function updateMultiFunnelState(customerId, funnelState) { try { console.log('updateMultiFunnelState(): updating customer ' + customerId + ' funnelState ' + funnelState ); latestFunnelState = funnelState; productRows = window.parent.shoppingCart.getCart().productRows; Object.entries(productRows).forEach(([key, productRow]) => { labelInRow = productRow.label; count = productRow.count; for (i = 1; i <= count; i++) { updateFunnelState(labelInRow, customerId, funnelState).end(); } }); return true; } catch(e) { console.log('updateMultiFunnelState(): the request failed because of ' + e); return false; } } function pay(params) { if (!parent.IS_CHIRINGO_CART) { // Old stuff if (singleProductCheckout) { updateFunnelState(label, customerId, FUNNEL_STATES.PAYMENT_REQUESTED_BY_CUSTOMER).end(); } else { updateMultiFunnelState(customerId, FUNNEL_STATES.PAYMENT_REQUESTED_BY_CUSTOMER); } } console.log('pay(): charging with payment method ' + selectedPaymentMethod); PAYMENT_METHOD_CHARGE_FUNCTIONS[selectedPaymentMethod](params) .then(paymentSuccessResponse => { orderId = paymentSuccessResponse.body.orderId; if (paymentSuccessResponse.body.furtherActionRequired) { console.log('pay(): payment requires further action: ' + paymentSuccessResponse.body.furtherActionDescription); PAYMENT_METHOD_FURTHER_ACTION_FUNCTIONS[selectedPaymentMethod](paymentSuccessResponse, label, customerId, FUNNEL_STATES); return; } if (paymentSuccessResponse.body.success) { console.log('pay(): payment succeeded!'); slideToNext(); // Chiringo cart if (parent.IS_CHIRINGO_CART) { // Done with the cart, let's empty it parent.initializeCart(); // Now sliding all the purchased product images for the Done screen var allProductImageSpans = parent.document.getElementById('cartItems').querySelectorAll('span'); var allProductImages = []; for (const theSpan of allProductImageSpans) { if (theSpan.style.backgroundImage.split('"')[1] == undefined) continue; allProductImages.push(theSpan.style.backgroundImage.split('"')[1]); } console.log(allProductImages); var backgroundImageIndex = 0; document.getElementById('purchaseDoneProductImage').style.backgroundImage = 'url(' + allProductImages[backgroundImageIndex++] + ')'; setInterval(() => { document.getElementById('purchaseDoneProductImage').style.backgroundImage = 'url(' + allProductImages[backgroundImageIndex++] + ')'; backgroundImageIndex = (backgroundImageIndex % allProductImages.length); console.log('pay(): the background index is ' + backgroundImageIndex); }, 2000); return; } // 1-click and old cart if (singleProductCheckout) { updateFunnelState(label, customerId, FUNNEL_STATES.PAYMENT_WENT_THROUGH).end(); } else { updateMultiFunnelState(customerId, FUNNEL_STATES.PAYMENT_WENT_THROUGH); } return; } }) .catch(paymentErrorResponse => { console.log('pay(): payment failed! ' + JSON.stringify(paymentErrorResponse, null, 2)); if (singleProductCheckout) { updateFunnelState(label, customerId, FUNNEL_STATES.PAYMENT_DECLINED).end(); } else { updateMultiFunnelState(customerId, FUNNEL_STATES.PAYMENT_DECLINED); } // TODO: showPaymentFailedAlert(null); resetVisualElements(); // 2) Where to go? // 3) Inform the user, how about provoking error conditions??????????? }); } function resetVisualElements() { unsetButtonAsLoading('confirmButton'); unsetButtonAsLoading('shippingWithOptionsButton'); if(PAYMENT_METHOD_CHARGE_FUNCTIONS['STRIPE']) { unsetButtonAsLoading('paybutton'); }; if(PAYMENT_METHOD_CHARGE_FUNCTIONS['PAYPAL']) { $('#paypal-button-container').show(); } if(PAYMENT_METHOD_CHARGE_FUNCTIONS['POD']) { unsetButtonAsLoading('podPaybutton'); } if(PAYMENT_METHOD_CHARGE_FUNCTIONS['COMNPAY']) { unsetButtonAsLoading('comnpayButton'); } if(PAYMENT_METHOD_CHARGE_FUNCTIONS['EBANXPAY']) { unsetButtonAsLoading('ebanxButton'); } if(PAYMENT_METHOD_CHARGE_FUNCTIONS['MOBILEMONEY']) { unsetButtonAsLoading('mobileMoneybutton'); } // After placing payment details at the end of the flow, hiding the overlay is not needed anymore // invokeOverlayOff(); } function closeWebView() { console.log('closeWebView(): trying to close the webview'); try { MessengerExtensions.requestCloseBrowser( function success() { console.log('closeWebView(): webview closed, end of the flow.'); }, function error(err) { // Messenger extensions not SUPPORTED or eventual error happened showCloseWindowAlert(); hideDoneButton(); } ); } catch(e) { // Messenger extensions not LOADED or eventual error happened console.log('closeWebView(): MessengerExtensions failed! Details are ' + e); showCloseWindowAlert(); hideDoneButton(); } } function closeOnIntermediateStep(cancellingFunnelStep) { console.log('closeOnIntermediateStep(): closing at funnel state ' + cancellingFunnelStep); // 1) Update the funnel if (singleProductCheckout) { updateFunnelState(label, customerId, cancellingFunnelStep).end(); // 2) Send "nothing was charged message" //sendMessageStackToUser(customerId, label, 'cancel'); // 3) Hide the form and the payment options invokeOverlayOff(); hidePaymentMethods(); // 4) Invoke closeWebView closeWebView(); } else { updateMultiFunnelState(customerId, cancellingFunnelStep); // 2) Send "nothing was charged message" //sendMessageStackToUser(customerId, label, 'cancel'); // 3) Hide the form and the payment options invokeOverlayOff(); hidePaymentMethods(); // 4) Invoke closeWebView closeWebView(); } } function done() { if(!selectedDoneAction) { if (appointmentproduct) { document.getElementById('appointmentIframe').contentWindow.document.getElementById('submit_button_identifier').click(); //execute the submit on the calendy } DONE_ACTIONS['default'](); } // Other actions can come here if they get to exist } $(document).ready(function() { ensureWindowCorrectSize(); if (error != 0) { console.log('Tried to load non existing quickoffer.'); handleError(); return; } // updateCustomer().end(); // Initially create the user + register tap on QO if (singleProductCheckout) { updateFunnelState(label, customerId, FUNNEL_STATES.OFFER_TAPPED).end(); registerSliderEvents(); //ensureProductImageInPlace(); } else { updateMultiFunnelState(customerId, FUNNEL_STATES.OFFER_TAPPED); registerSliderEvents(); } // doCorrectiveInitialScroll(); }); function assignOrderId(theOrderId) { orderId = theOrdeId; console.log('assignOrderId(): the orderId now is ' + orderId); } function createLabelObject() { var labelArrayObject = []; if (singleProductCheckout) { var noteObject = (notes) ? {"question": JSON.parse(notes).question, "answer": noteAnswer } : null; labelArrayObject.push({label:label, count:1, productOption: selectedProductOption, note: noteObject }); } else { console.log('createLabelObject(): the cart ' + parent.getCart()); for (const product of parent.getCart()) { labelArrayObject.push({ label: product.label, productOption: product.productOption, shippingOption: product.shippingOption }); } // productRows = window.parent.shoppingCart.getCart().productRows; // Object.entries(productRows).forEach(([key, productRow]) => { // if ( productRow.accountId === window.parent.shoppingCart.accountId) {//maybe it is better to get accountId from quickoffer page // var labelInRow = productRow.label; // var count = productRow.count; // var productOption = productRow.productOption; // var noteObject = productRow.note; // labelArrayObject.push({label:labelInRow, count:count, productOption:productOption, note: noteObject}); // } // }); } return labelArrayObject; } function getFirstLabelFromShoppingCart() { productRows = window.parent.shoppingCart.getCart().productRows; var currentAccountId = window.parent.shoppingCart.accountId; var Firstlabel = null; Object.entries(productRows).forEach(([key, productRow]) => { if ( productRow.accountId === currentAccountId ) { Firstlabel = productRow.label; } }); return Firstlabel; } function replaceSocialIdForPhoneNumberWhenItIsNotDedined() { if ( socialId ) { return socialId; } else { var shippingObject = getShippingAddressDatastructure(); if (( shippingObject ) && ( shippingObject.shippingAddress ) && ( shippingObject.shippingAddress.phone )) { return shippingObject.shippingAddress.phone; } else { return socialId; } } } // For Chiringo function buildShippingAddress() { return { "firstName": document.getElementById('firstName').value, "lastName": document.getElementById('lastName').value, "address1": document.getElementById('address1').value, "address2": document.getElementById('address2').value, "city": document.getElementById('city').value, "state": document.getElementById('state').value, "country": document.getElementById('country').value, "email": document.getElementById('email').value, // Parameter 0 as per https://github.com/jackocnr/intl-tel-input/blob/c398e8ca17d848107109e044437796a6c8ff272a/src/js/utils.js#L104 "phone": phoneInstance.getNumber(0), "zipcode": document.getElementById('zipcode').value }; }