mirror of
https://github.com/woocommerce/woocommerce-paypal-payments.git
synced 2025-09-01 07:02:48 +08:00
Refactor axo module
This commit is contained in:
parent
b7d43d3c5b
commit
039cc53f40
6 changed files with 581 additions and 51 deletions
|
@ -2,6 +2,7 @@ import Fastlane from "./Entity/Fastlane";
|
|||
import MockData from "./Helper/MockData";
|
||||
import {log} from "./Helper/Debug";
|
||||
import {hide, show} from '../../../ppcp-button/resources/js/modules/Helper/Hiding';
|
||||
import FormFieldGroup from "./Helper/FormFieldGroup";
|
||||
|
||||
class AxoManager {
|
||||
|
||||
|
@ -13,6 +14,15 @@ class AxoManager {
|
|||
this.fastlane = new Fastlane();
|
||||
this.$ = jQuery;
|
||||
|
||||
this.isConnectProfile = false;
|
||||
this.hideGatewaySelection = false;
|
||||
|
||||
this.data = {
|
||||
billing: null,
|
||||
shipping: null,
|
||||
card: null,
|
||||
}
|
||||
|
||||
this.elements = {
|
||||
gatewayRadioButton: {
|
||||
selector: '#payment_method_ppcp-axo-gateway',
|
||||
|
@ -35,11 +45,24 @@ class AxoManager {
|
|||
selector: '#ppcp-axo-email-widget',
|
||||
className: 'ppcp-axo-email-widget'
|
||||
},
|
||||
shippingAddressContainer: {
|
||||
id: 'ppcp-axo-shipping-address-container',
|
||||
selector: '#ppcp-axo-shipping-address-container',
|
||||
className: 'ppcp-axo-shipping-address-container',
|
||||
anchorSelector: '.woocommerce-shipping-fields'
|
||||
},
|
||||
billingAddressContainer: {
|
||||
id: 'ppcp-axo-billing-address-container',
|
||||
selector: '#ppcp-axo-billing-address-container',
|
||||
className: 'ppcp-axo-billing-address-container',
|
||||
anchorSelector: '.woocommerce-billing-fields__field-wrapper'
|
||||
},
|
||||
fieldBillingEmail: {
|
||||
selector: '#billing_email_field'
|
||||
},
|
||||
submitButtonContainer: {
|
||||
selector: '#ppcp-axo-submit-button-container'
|
||||
selector: '#ppcp-axo-submit-button-container',
|
||||
buttonSelector: '#ppcp-axo-submit-button-container button'
|
||||
},
|
||||
}
|
||||
|
||||
|
@ -51,6 +74,226 @@ class AxoManager {
|
|||
|
||||
this.locale = 'en_us';
|
||||
|
||||
this.registerEventHandlers();
|
||||
|
||||
this.shippingFormFields = new FormFieldGroup({
|
||||
baseSelector: '.woocommerce-checkout',
|
||||
contentSelector: this.elements.shippingAddressContainer.selector,
|
||||
template: (data) => {
|
||||
const valueOfSelect = (selectSelector, key) => {
|
||||
const selectElement = document.querySelector(selectSelector);
|
||||
const option = selectElement.querySelector(`option[value="${key}"]`);
|
||||
return option ? option.textContent : key;
|
||||
}
|
||||
|
||||
if (data.isEditing()) {
|
||||
return `
|
||||
<div style="margin-bottom: 20px;">
|
||||
<h3>Shipping details <a href="javascript:void(0)" data-ppcp-axo-save-shipping-address style="margin-left: 20px;">Save</a></h3>
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
if (data.isEmpty()) {
|
||||
return `
|
||||
<div style="margin-bottom: 20px;">
|
||||
<h3>Shipping details <a href="javascript:void(0)" data-ppcp-axo-change-shipping-address style="margin-left: 20px;">Edit</a></h3>
|
||||
<div>Please fill in your shipping details.</div>
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
return `
|
||||
<div style="margin-bottom: 20px;">
|
||||
<h3>Shipping details <a href="javascript:void(0)" data-ppcp-axo-change-shipping-address style="margin-left: 20px;">Edit</a></h3>
|
||||
<div>${data.value('company')}</div>
|
||||
<div>${data.value('firstName')} ${data.value('lastName')}</div>
|
||||
<div>${data.value('street1')}</div>
|
||||
<div>${data.value('street2')}</div>
|
||||
<div>${data.value('postCode')} ${data.value('city')}</div>
|
||||
<div>${valueOfSelect('#shipping_state', data.value('stateCode'))}</div>
|
||||
<div>${valueOfSelect('#shipping_country', data.value('countryCode'))}</div>
|
||||
</div>
|
||||
`;
|
||||
},
|
||||
fields: {
|
||||
firstName: {
|
||||
'key': 'firstName',
|
||||
'selector': '#shipping_first_name_field',
|
||||
'valuePath': 'shipping.name.firstName',
|
||||
},
|
||||
lastName: {
|
||||
'selector': '#shipping_last_name_field',
|
||||
'valuePath': 'shipping.name.lastName',
|
||||
},
|
||||
street1: {
|
||||
'selector': '#shipping_address_1_field',
|
||||
'valuePath': 'shipping.address.addressLine1',
|
||||
},
|
||||
street2: {
|
||||
'selector': '#shipping_address_2_field',
|
||||
'valuePath': null
|
||||
},
|
||||
postCode: {
|
||||
'selector': '#shipping_postcode_field',
|
||||
'valuePath': 'shipping.address.postalCode',
|
||||
},
|
||||
city: {
|
||||
'selector': '#shipping_city_field',
|
||||
'valuePath': 'shipping.address.adminArea2',
|
||||
},
|
||||
stateCode: {
|
||||
'selector': '#shipping_state_field',
|
||||
'valuePath': 'shipping.address.adminArea1',
|
||||
},
|
||||
countryCode: {
|
||||
'selector': '#shipping_country_field',
|
||||
'valuePath': 'shipping.address.countryCode',
|
||||
},
|
||||
company: {
|
||||
'selector': '#shipping_company_field',
|
||||
'valuePath': null,
|
||||
},
|
||||
shipDifferentAddress: {
|
||||
'selector': '#ship-to-different-address',
|
||||
'valuePath': null,
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
this.billingFormFields = new FormFieldGroup({
|
||||
baseSelector: '.woocommerce-checkout',
|
||||
contentSelector: this.elements.billingAddressContainer.selector,
|
||||
template: (data) => {
|
||||
const valueOfSelect = (selectSelector, key) => {
|
||||
const selectElement = document.querySelector(selectSelector);
|
||||
const option = selectElement.querySelector(`option[value="${key}"]`);
|
||||
return option ? option.textContent : key;
|
||||
}
|
||||
|
||||
if (data.isEditing()) {
|
||||
return `
|
||||
<div style="margin-bottom: 20px;">
|
||||
<h4><a href="javascript:void(0)" data-ppcp-axo-save-billing-address>Save</a></h4>
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
if (data.isEmpty()) {
|
||||
return `
|
||||
<div style="margin-bottom: 20px;">
|
||||
<div>Please fill in your billing details.</div>
|
||||
<h4><a href="javascript:void(0)" data-ppcp-axo-change-billing-address>Edit</a></h4>
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
return `
|
||||
<div style="margin-bottom: 20px;">
|
||||
<h4>Billing address</h4>
|
||||
<div>${data.value('company')}</div>
|
||||
<div>${data.value('firstName')} ${data.value('lastName')}</div>
|
||||
<div>${data.value('street1')}</div>
|
||||
<div>${data.value('street2')}</div>
|
||||
<div>${data.value('postCode')} ${data.value('city')}</div>
|
||||
<div>${valueOfSelect('#billing_state', data.value('stateCode'))}</div>
|
||||
<div>${valueOfSelect('#billing_country', data.value('countryCode'))}</div>
|
||||
<div>${data.value('phone')}</div>
|
||||
<h4><a href="javascript:void(0)" data-ppcp-axo-change-billing-address>Edit</a></h4>
|
||||
</div>
|
||||
`;
|
||||
},
|
||||
fields: {
|
||||
firstName: {
|
||||
'selector': '#billing_first_name_field',
|
||||
'valuePath': 'billing.name.firstName',
|
||||
},
|
||||
lastName: {
|
||||
'selector': '#billing_last_name_field',
|
||||
'valuePath': 'billing.name.lastName',
|
||||
},
|
||||
street1: {
|
||||
'selector': '#billing_address_1_field',
|
||||
'valuePath': 'billing.address.addressLine1',
|
||||
},
|
||||
street2: {
|
||||
'selector': '#billing_address_2_field',
|
||||
'valuePath': null
|
||||
},
|
||||
postCode: {
|
||||
'selector': '#billing_postcode_field',
|
||||
'valuePath': 'billing.address.postalCode',
|
||||
},
|
||||
city: {
|
||||
'selector': '#billing_city_field',
|
||||
'valuePath': 'billing.address.adminArea2',
|
||||
},
|
||||
stateCode: {
|
||||
'selector': '#billing_state_field',
|
||||
'valuePath': 'billing.address.adminArea1',
|
||||
},
|
||||
countryCode: {
|
||||
'selector': '#billing_country_field',
|
||||
'valuePath': 'billing.address.countryCode',
|
||||
},
|
||||
company: {
|
||||
'selector': '#billing_company_field',
|
||||
'valuePath': null,
|
||||
},
|
||||
phone: {
|
||||
'selector': '#billing_phone_field',
|
||||
'valuePath': null,
|
||||
},
|
||||
}
|
||||
});
|
||||
|
||||
this.cardFormFields = new FormFieldGroup({
|
||||
baseSelector: '.ppcp-axo-payment-container',
|
||||
contentSelector: this.elements.paymentContainer.selector,
|
||||
template: (data) => {
|
||||
const selectOtherPaymentMethod = () => {
|
||||
if (!this.hideGatewaySelection) {
|
||||
return '';
|
||||
}
|
||||
return `<p style="margin-top: 40px; text-align: center;"><a href="javascript:void(0)" data-ppcp-axo-show-gateway-selection>Select other payment method</a></p>`;
|
||||
};
|
||||
|
||||
if (data.isEmpty()) {
|
||||
return `
|
||||
<div style="margin-bottom: 20px; text-align: center;">
|
||||
<div>Please fill in your card details.</div>
|
||||
<h4><a href="javascript:void(0)" data-ppcp-axo-change-card>Edit</a></h4>
|
||||
${selectOtherPaymentMethod()}
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
return `
|
||||
<div style="margin-bottom: 20px;">
|
||||
<h3>Card Details <a href="javascript:void(0)" data-ppcp-axo-change-card>Edit</a></h3>
|
||||
<div>${data.value('name')}</div>
|
||||
<div>${data.value('brand')}</div>
|
||||
<div>${data.value('lastDigits') ? '************' + data.value('lastDigits'): ''}</div>
|
||||
<div>${data.value('expiry')}</div>
|
||||
${selectOtherPaymentMethod()}
|
||||
</div>
|
||||
`;
|
||||
},
|
||||
fields: {
|
||||
brand: {
|
||||
'valuePath': 'card.paymentSource.card.brand',
|
||||
},
|
||||
expiry: {
|
||||
'valuePath': 'card.paymentSource.card.expiry',
|
||||
},
|
||||
lastDigits: {
|
||||
'valuePath': 'card.paymentSource.card.lastDigits',
|
||||
},
|
||||
name: {
|
||||
'valuePath': 'card.paymentSource.card.name',
|
||||
},
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
registerEventHandlers() {
|
||||
|
||||
// Listen to Gateway Radio button changes.
|
||||
this.$(document).on('change', this.elements.gatewayRadioButton.selector, (ev) => {
|
||||
if (ev.target.checked) {
|
||||
|
@ -64,16 +307,86 @@ class AxoManager {
|
|||
this.triggerGatewayChange();
|
||||
});
|
||||
|
||||
this.$(document).on('click', this.elements.submitButtonContainer.selector + ' button', () => {
|
||||
// On checkout form submitted.
|
||||
this.$(document).on('click', this.elements.submitButtonContainer.buttonSelector, () => {
|
||||
this.onClickSubmitButton();
|
||||
return false;
|
||||
});
|
||||
|
||||
// Click change shipping address link.
|
||||
this.$(document).on('click', '*[data-ppcp-axo-change-shipping-address]', async () => {
|
||||
|
||||
if (this.isConnectProfile) {
|
||||
console.log('profile', this.fastlane.profile);
|
||||
|
||||
//this.shippingFormFields.deactivate();
|
||||
|
||||
const { selectionChanged, selectedAddress } = await this.fastlane.profile.showShippingAddressSelector();
|
||||
|
||||
console.log('selectedAddress', selectedAddress);
|
||||
|
||||
if (selectionChanged) {
|
||||
this.setShipping(selectedAddress);
|
||||
this.shippingFormFields.activate();
|
||||
}
|
||||
} else {
|
||||
let checkbox = document.querySelector('#ship-to-different-address-checkbox');
|
||||
if (checkbox && !checkbox.checked) {
|
||||
jQuery(checkbox).trigger('click');
|
||||
}
|
||||
this.shippingFormFields.deactivate();
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
this.$(document).on('click', '*[data-ppcp-axo-save-shipping-address]', async () => {
|
||||
this.shippingFormFields.activate();
|
||||
});
|
||||
|
||||
// Click change billing address link.
|
||||
this.$(document).on('click', '*[data-ppcp-axo-change-billing-address]', async () => {
|
||||
if (this.isConnectProfile) {
|
||||
this.$('*[data-ppcp-axo-change-card]').trigger('click');
|
||||
} else {
|
||||
this.billingFormFields.deactivate();
|
||||
}
|
||||
});
|
||||
|
||||
this.$(document).on('click', '*[data-ppcp-axo-save-billing-address]', async () => {
|
||||
this.billingFormFields.activate();
|
||||
});
|
||||
|
||||
// Click change card link.
|
||||
this.$(document).on('click', '*[data-ppcp-axo-change-card]', async () => {
|
||||
console.log('profile', this.fastlane.profile);
|
||||
|
||||
const response = await this.fastlane.profile.showCardSelector();
|
||||
|
||||
console.log('card response', response);
|
||||
|
||||
if (response.selectionChanged) {
|
||||
this.setCard(response.selectedCard);
|
||||
this.setBilling({
|
||||
address: response.selectedCard.paymentSource.card.billingAddress
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
// Cancel "continuation" mode.
|
||||
this.$(document).on('click', '*[data-ppcp-axo-show-gateway-selection]', async () => {
|
||||
this.hideGatewaySelection = false;
|
||||
this.$('.wc_payment_methods label').show();
|
||||
this.cardFormFields.refresh();
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
showAxo() {
|
||||
this.initEmail();
|
||||
this.init();
|
||||
this.initPlacements();
|
||||
this.initFastlane();
|
||||
|
||||
this.shippingFormFields.activate();
|
||||
this.billingFormFields.activate();
|
||||
|
||||
show(this.elements.emailWidgetContainer.selector);
|
||||
show(this.elements.watermarkContainer.selector);
|
||||
|
@ -87,6 +400,9 @@ class AxoManager {
|
|||
}
|
||||
|
||||
hideAxo() {
|
||||
this.shippingFormFields.deactivate();
|
||||
this.billingFormFields.deactivate();
|
||||
|
||||
hide(this.elements.emailWidgetContainer.selector);
|
||||
hide(this.elements.watermarkContainer.selector);
|
||||
hide(this.elements.paymentContainer.selector);
|
||||
|
@ -98,15 +414,31 @@ class AxoManager {
|
|||
}
|
||||
}
|
||||
|
||||
initEmail() {
|
||||
initPlacements() {
|
||||
let emailRow = document.querySelector(this.elements.fieldBillingEmail.selector);
|
||||
|
||||
const bc = this.elements.billingAddressContainer;
|
||||
const sc = this.elements.shippingAddressContainer;
|
||||
const ec = this.elements.emailWidgetContainer;
|
||||
|
||||
if (!document.querySelector(bc.selector)) {
|
||||
document.querySelector(bc.anchorSelector).insertAdjacentHTML('beforeend', `
|
||||
<div id="${bc.id}" class="${bc.className}"></div>
|
||||
`);
|
||||
}
|
||||
|
||||
if (!document.querySelector(sc.selector)) {
|
||||
document.querySelector(sc.anchorSelector).insertAdjacentHTML('afterbegin', `
|
||||
<div id="${sc.id}" class="${sc.className}"></div>
|
||||
`);
|
||||
}
|
||||
|
||||
if (this.useEmailWidget()) {
|
||||
|
||||
// Display email widget.
|
||||
if (!document.querySelector(this.elements.emailWidgetContainer.selector)) {
|
||||
if (!document.querySelector(ec.selector)) {
|
||||
emailRow.parentNode.insertAdjacentHTML('afterbegin', `
|
||||
<div id="${this.elements.emailWidgetContainer.id}" class="${this.elements.emailWidgetContainer.className}">
|
||||
<div id="${ec.id}" class="${ec.className}">
|
||||
--- EMAIL WIDGET PLACEHOLDER ---
|
||||
</div>
|
||||
`);
|
||||
|
@ -120,7 +452,7 @@ class AxoManager {
|
|||
}
|
||||
}
|
||||
|
||||
async init() {
|
||||
async initFastlane() {
|
||||
if (this.initialized) {
|
||||
return;
|
||||
}
|
||||
|
@ -188,30 +520,79 @@ class AxoManager {
|
|||
async onChangeEmail () {
|
||||
log('Email changed: ' + this.emailInput.value);
|
||||
|
||||
this.isConnectProfile = false;
|
||||
this.hideGatewaySelection = false;
|
||||
|
||||
if (!this.emailInput.checkValidity()) {
|
||||
log('The email address is not valid.');
|
||||
return;
|
||||
}
|
||||
|
||||
const { customerContextId } = await this.fastlane.identity.lookupCustomerByEmail(this.emailInput.value);
|
||||
const lookupResponse = await this.fastlane.identity.lookupCustomerByEmail(this.emailInput.value);
|
||||
|
||||
if (customerContextId) {
|
||||
show(this.elements.paymentContainer.selector);
|
||||
|
||||
if (lookupResponse.customerContextId) {
|
||||
// Email is associated with a Connect profile or a PayPal member.
|
||||
// Authenticate the customer to get access to their profile.
|
||||
log('Email is associated with a Connect profile or a PayPal member');
|
||||
|
||||
// TODO : enter hideOtherGateways mode
|
||||
|
||||
const authResponse = await this.fastlane.identity.triggerAuthenticationFlow(lookupResponse.customerContextId);
|
||||
|
||||
log('AuthResponse', authResponse);
|
||||
|
||||
if (authResponse.authenticationState === 'succeeded') {
|
||||
log(JSON.stringify(authResponse));
|
||||
|
||||
// document.querySelector(this.elements.paymentContainer.selector).innerHTML =
|
||||
// '<a href="javascript:void(0)" data-ppcp-axo-change-card>Change card</a>';
|
||||
|
||||
// Add addresses
|
||||
this.setShipping(authResponse.profileData.shippingAddress);
|
||||
// TODO : set billing
|
||||
this.setCard(authResponse.profileData.card);
|
||||
|
||||
this.isConnectProfile = true;
|
||||
this.hideGatewaySelection = true;
|
||||
this.$('.wc_payment_methods label').hide();
|
||||
|
||||
this.shippingFormFields.activate();
|
||||
this.billingFormFields.activate();
|
||||
this.cardFormFields.activate();
|
||||
|
||||
} else {
|
||||
// authentication failed or canceled by the customer
|
||||
log("Authentication Failed")
|
||||
}
|
||||
|
||||
} else {
|
||||
// No profile found with this email address.
|
||||
// This is a guest customer.
|
||||
log('No profile found with this email address.');
|
||||
|
||||
document.querySelector(this.elements.paymentContainer.selector)?.classList.remove('hidden');
|
||||
|
||||
this.cardComponent = await this.fastlane
|
||||
.FastlaneCardComponent(MockData.cardComponent())
|
||||
.render(this.elements.paymentContainer.selector);
|
||||
}
|
||||
}
|
||||
|
||||
setShipping(shipping) {
|
||||
this.data.shipping = shipping;
|
||||
this.shippingFormFields.setData(this.data);
|
||||
}
|
||||
|
||||
setBilling(billing) {
|
||||
this.data.billing = billing;
|
||||
this.billingFormFields.setData(this.data);
|
||||
}
|
||||
|
||||
setCard(card) {
|
||||
this.data.card = card;
|
||||
this.cardFormFields.setData(this.data);
|
||||
}
|
||||
|
||||
onClickSubmitButton() {
|
||||
try {
|
||||
this.cardComponent.tokenize(MockData.cardComponentTokenize()).then((response) => {
|
||||
|
@ -227,29 +608,6 @@ class AxoManager {
|
|||
log('nonce: ' + nonce);
|
||||
alert('nonce: ' + nonce);
|
||||
|
||||
// fetch('submit.php', {
|
||||
// method: 'POST',
|
||||
// headers: {
|
||||
// 'Content-Type': 'application/json',
|
||||
// },
|
||||
// body: JSON.stringify({
|
||||
// nonce: nonce
|
||||
// }),
|
||||
// })
|
||||
// .then(response => {
|
||||
// if (!response.ok) {
|
||||
// throw new Error('Network response was not ok');
|
||||
// }
|
||||
// return response.json();
|
||||
// })
|
||||
// .then(data => {
|
||||
// log('Submit response', data);
|
||||
// log(JSON.stringify(data));
|
||||
// })
|
||||
// .catch(error => {
|
||||
// console.error('There has been a problem with your fetch operation:', error);
|
||||
// });
|
||||
|
||||
// Submit form.
|
||||
document.querySelector(this.elements.defaultSubmitButton.selector).click();
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue