mirror of
https://github.com/woocommerce/woocommerce-paypal-payments.git
synced 2025-09-04 08:47:23 +08:00
Merge pull request #1832 from woocommerce/PCP-2158-apple-pay-use-checkout-form-data-to-update-shipping-and-billing
ApplePay use checkout form data to update shipping and billing (2158)
This commit is contained in:
commit
aec5e6431c
10 changed files with 421 additions and 212 deletions
|
@ -163,7 +163,7 @@ return array(
|
|||
),
|
||||
),
|
||||
'applepay_button_domain_registration' => array(
|
||||
'title' => str_repeat( ' ', 6 ) . __( 'Domain Registration', 'woocommerce-paypal-payments' ),
|
||||
'title' => __( 'Domain Registration', 'woocommerce-paypal-payments' ),
|
||||
'type' => 'ppcp-text',
|
||||
'text' =>
|
||||
'<a href="' . $domain_registration_url . '" class="button" target="_blank">'
|
||||
|
@ -177,13 +177,14 @@ return array(
|
|||
'Registering the website domain on the PayPal site is mandated by Apple. Payments will fail if the Apple Pay button is used on an unregistered domain.',
|
||||
'woocommerce-paypal-payments'
|
||||
),
|
||||
'classes' => array( 'ppcp-field-indent' ),
|
||||
'class' => array(),
|
||||
'screens' => array( State::STATE_ONBOARDED ),
|
||||
'gateway' => 'paypal',
|
||||
'requirements' => array(),
|
||||
),
|
||||
'applepay_button_domain_validation' => array(
|
||||
'title' => str_repeat( ' ', 6 ) . __( 'Domain Validation', 'woocommerce-paypal-payments' ),
|
||||
'title' => __( 'Domain Validation', 'woocommerce-paypal-payments' ),
|
||||
'type' => 'ppcp-text',
|
||||
'text' => $domain_validation_text
|
||||
. '<p class="description">'
|
||||
|
@ -199,13 +200,14 @@ return array(
|
|||
'Apple requires the website domain to be registered and validated. PayPal Payments automatically presents your domain association file for Apple to validate the manually registered domain.',
|
||||
'woocommerce-paypal-payments'
|
||||
),
|
||||
'classes' => array( 'ppcp-field-indent' ),
|
||||
'class' => array(),
|
||||
'screens' => array( State::STATE_ONBOARDED ),
|
||||
'gateway' => 'paypal',
|
||||
'requirements' => array(),
|
||||
),
|
||||
'applepay_button_device_eligibility' => array(
|
||||
'title' => str_repeat( ' ', 6 ) . __( 'Device Eligibility', 'woocommerce-paypal-payments' ),
|
||||
'title' => __( 'Device Eligibility', 'woocommerce-paypal-payments' ),
|
||||
'type' => 'ppcp-text',
|
||||
'text' => $device_eligibility_text
|
||||
. '<p class="description">'
|
||||
|
@ -216,19 +218,21 @@ return array(
|
|||
'Apple Pay demands certain Apple devices for secure payment execution. This helps determine if your current device is compliant.',
|
||||
'woocommerce-paypal-payments'
|
||||
),
|
||||
'classes' => array( 'ppcp-field-indent' ),
|
||||
'class' => array(),
|
||||
'screens' => array( State::STATE_ONBOARDED ),
|
||||
'gateway' => 'paypal',
|
||||
'requirements' => array(),
|
||||
),
|
||||
'applepay_button_type' => array(
|
||||
'title' => str_repeat( ' ', 6 ) . __( 'Button Label', 'woocommerce-paypal-payments' ),
|
||||
'title' => __( 'Button Label', 'woocommerce-paypal-payments' ),
|
||||
'type' => 'select',
|
||||
'desc_tip' => true,
|
||||
'description' => __(
|
||||
'This controls the label of the Apple Pay button.',
|
||||
'woocommerce-paypal-payments'
|
||||
),
|
||||
'classes' => array( 'ppcp-field-indent' ),
|
||||
'class' => array(),
|
||||
'input_class' => array( 'wc-enhanced-select' ),
|
||||
'default' => 'pay',
|
||||
|
@ -238,7 +242,7 @@ return array(
|
|||
'requirements' => array(),
|
||||
),
|
||||
'applepay_button_color' => array(
|
||||
'title' => str_repeat( ' ', 6 ) . __( 'Button Color', 'woocommerce-paypal-payments' ),
|
||||
'title' => __( 'Button Color', 'woocommerce-paypal-payments' ),
|
||||
'type' => 'select',
|
||||
'desc_tip' => true,
|
||||
'description' => __(
|
||||
|
@ -247,6 +251,7 @@ return array(
|
|||
),
|
||||
'label' => '',
|
||||
'input_class' => array( 'wc-enhanced-select' ),
|
||||
'classes' => array( 'ppcp-field-indent' ),
|
||||
'class' => array(),
|
||||
'default' => 'black',
|
||||
'options' => PropertiesDictionary::button_colors(),
|
||||
|
@ -255,13 +260,14 @@ return array(
|
|||
'requirements' => array(),
|
||||
),
|
||||
'applepay_button_language' => array(
|
||||
'title' => str_repeat( ' ', 6 ) . __( 'Button Language', 'woocommerce-paypal-payments' ),
|
||||
'title' => __( 'Button Language', 'woocommerce-paypal-payments' ),
|
||||
'type' => 'select',
|
||||
'desc_tip' => true,
|
||||
'description' => __(
|
||||
'The language and region used for the displayed Apple Pay button. The default value is the current language and region setting in a browser.',
|
||||
'woocommerce-paypal-payments'
|
||||
),
|
||||
'classes' => array( 'ppcp-field-indent' ),
|
||||
'class' => array(),
|
||||
'input_class' => array( 'wc-enhanced-select' ),
|
||||
'default' => 'en',
|
||||
|
@ -270,6 +276,20 @@ return array(
|
|||
'gateway' => 'paypal',
|
||||
'requirements' => array(),
|
||||
),
|
||||
'applepay_checkout_data_mode' => array(
|
||||
'title' => __( 'Send checkout billing and shipping data to Apple Pay', 'woocommerce-paypal-payments' ),
|
||||
'type' => 'select',
|
||||
'classes' => array( 'ppcp-field-indent' ),
|
||||
'class' => array(),
|
||||
'input_class' => array( 'wc-enhanced-select' ),
|
||||
'desc_tip' => true,
|
||||
'description' => __( 'Using the WC form data increases convenience for the customers, but can cause issues if Apple Pay details do not match the billing and shipping data in the checkout form.', 'woocommerce-paypal-payments' ),
|
||||
'default' => PropertiesDictionary::BILLING_DATA_MODE_DEFAULT,
|
||||
'options' => PropertiesDictionary::billing_data_modes(),
|
||||
'screens' => array( State::STATE_ONBOARDED ),
|
||||
'gateway' => 'paypal',
|
||||
'requirements' => array(),
|
||||
),
|
||||
)
|
||||
);
|
||||
},
|
||||
|
|
|
@ -16,7 +16,7 @@ class ApplepayButton {
|
|||
this.buttonConfig = buttonConfig;
|
||||
this.ppcpConfig = ppcpConfig;
|
||||
this.paymentsClient = null;
|
||||
this.form_saved = false;
|
||||
this.formData = null;
|
||||
|
||||
this.contextHandler = ContextHandlerFactory.create(
|
||||
this.context,
|
||||
|
@ -24,10 +24,13 @@ class ApplepayButton {
|
|||
this.ppcpConfig
|
||||
);
|
||||
|
||||
this.updated_contact_info = []
|
||||
this.updatedContactInfo = []
|
||||
this.selectedShippingMethod = []
|
||||
this.nonce = document.getElementById('woocommerce-process-checkout-nonce')?.value || buttonConfig.nonce
|
||||
|
||||
// Stores initialization data sent to the button.
|
||||
this.initialPaymentRequest = null;
|
||||
|
||||
this.log = function() {
|
||||
if ( this.buttonConfig.is_debug ) {
|
||||
console.log('[ApplePayButton]', ...arguments);
|
||||
|
@ -35,6 +38,13 @@ class ApplepayButton {
|
|||
}
|
||||
|
||||
this.refreshContextData();
|
||||
|
||||
// Debug helpers
|
||||
jQuery(document).on('ppcp-applepay-debug', () => {
|
||||
console.log('ApplePayButton', this.context, this);
|
||||
});
|
||||
document.ppcpApplepayButtons = document.ppcpApplepayButtons || {};
|
||||
document.ppcpApplepayButtons[this.context] = this;
|
||||
}
|
||||
|
||||
init(config) {
|
||||
|
@ -51,6 +61,7 @@ class ApplepayButton {
|
|||
this.isInitialized = true;
|
||||
this.applePayConfig = config;
|
||||
const isEligible = this.applePayConfig.isEligible;
|
||||
|
||||
if (isEligible) {
|
||||
this.fetchTransactionInfo().then(() => {
|
||||
const isSubscriptionProduct = this.ppcpConfig?.data_client_id?.has_subscriptions === true;
|
||||
|
@ -72,11 +83,6 @@ class ApplepayButton {
|
|||
this.onButtonClick();
|
||||
});
|
||||
}
|
||||
|
||||
// Listen for changes on any input within the WooCommerce checkout form
|
||||
jQuery('form.checkout').on('change', 'input, select, textarea', () => {
|
||||
this.fetchTransactionInfo();
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -93,6 +99,7 @@ class ApplepayButton {
|
|||
async fetchTransactionInfo() {
|
||||
this.transactionInfo = await this.contextHandler.transactionInfo();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns configurations relative to this button context.
|
||||
*/
|
||||
|
@ -117,6 +124,7 @@ class ApplepayButton {
|
|||
|
||||
return config;
|
||||
}
|
||||
|
||||
initEventHandlers() {
|
||||
const { wrapper, ppcpButtonWrapper } = this.contextConfig();
|
||||
const wrapper_id = '#' + wrapper;
|
||||
|
@ -136,22 +144,25 @@ class ApplepayButton {
|
|||
syncButtonVisibility();
|
||||
}
|
||||
|
||||
/**
|
||||
* Starts an ApplePay session.
|
||||
*/
|
||||
applePaySession(paymentRequest) {
|
||||
this.log('applePaySession', paymentRequest);
|
||||
const session = new ApplePaySession(4, paymentRequest)
|
||||
session.begin()
|
||||
const session = new ApplePaySession(4, paymentRequest);
|
||||
session.begin();
|
||||
|
||||
if (this.buttonConfig.product.needShipping) {
|
||||
session.onshippingmethodselected = this.onshippingmethodselected(session)
|
||||
session.onshippingcontactselected = this.onshippingcontactselected(session)
|
||||
if (this.shouldRequireShippingInButton()) {
|
||||
session.onshippingmethodselected = this.onShippingMethodSelected(session);
|
||||
session.onshippingcontactselected = this.onShippingContactSelected(session);
|
||||
}
|
||||
session.onvalidatemerchant = this.onvalidatemerchant(session);
|
||||
session.onpaymentauthorized = this.onpaymentauthorized(session);
|
||||
session.onvalidatemerchant = this.onValidateMerchant(session);
|
||||
session.onpaymentauthorized = this.onPaymentAuthorized(session);
|
||||
return session;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a Apple Pay purchase button
|
||||
* Adds an Apple Pay purchase button.
|
||||
*/
|
||||
addButton() {
|
||||
this.log('addButton', this.context);
|
||||
|
@ -188,8 +199,9 @@ class ApplepayButton {
|
|||
async onButtonClick() {
|
||||
this.log('onButtonClick', this.context);
|
||||
|
||||
const paymentDataRequest = this.paymentDataRequest();
|
||||
// trigger woocommerce validation if we are in the checkout page
|
||||
const paymentRequest = this.paymentRequest();
|
||||
|
||||
// Trigger woocommerce validation if we are in the checkout page.
|
||||
if (this.context === 'checkout') {
|
||||
const checkoutFormSelector = 'form.woocommerce-checkout';
|
||||
const errorHandler = new ErrorHandler(
|
||||
|
@ -198,13 +210,16 @@ class ApplepayButton {
|
|||
);
|
||||
try {
|
||||
const formData = new FormData(document.querySelector(checkoutFormSelector));
|
||||
this.form_saved = Object.fromEntries(formData.entries());
|
||||
// This line should be reviewed, the widgetBuilder.paypal.Applepay().confirmOrder fails if we add it.
|
||||
//this.update_request_data_with_form(paymentDataRequest);
|
||||
this.formData = Object.fromEntries(formData.entries());
|
||||
|
||||
this.updateRequestDataWithForm(paymentRequest);
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
}
|
||||
const session = this.applePaySession(paymentDataRequest)
|
||||
|
||||
this.log('=== paymentRequest', paymentRequest);
|
||||
|
||||
const session = this.applePaySession(paymentRequest);
|
||||
const formValidator = PayPalCommerceGateway.early_checkout_validation_enabled ?
|
||||
new FormValidator(
|
||||
PayPalCommerceGateway.ajax.validate_checkout.endpoint,
|
||||
|
@ -225,19 +240,115 @@ class ApplepayButton {
|
|||
}
|
||||
return;
|
||||
}
|
||||
this.applePaySession(paymentDataRequest)
|
||||
|
||||
// Default session initialization.
|
||||
this.applePaySession(paymentRequest);
|
||||
}
|
||||
|
||||
update_request_data_with_form(paymentDataRequest) {
|
||||
paymentDataRequest.billingContact = this.fill_billing_contact(this.form_saved);
|
||||
paymentDataRequest.applicationData = this.fill_application_data(this.form_saved);
|
||||
if (!this.buttonConfig.product.needShipping) {
|
||||
/**
|
||||
* If the button should show the shipping fields.
|
||||
*
|
||||
* @returns {false|*}
|
||||
*/
|
||||
shouldRequireShippingInButton() {
|
||||
return this.contextHandler.shippingAllowed()
|
||||
&& this.buttonConfig.product.needShipping
|
||||
&& (this.context !== 'checkout' || this.shouldUpdateButtonWithFormData());
|
||||
}
|
||||
|
||||
/**
|
||||
* If the button should be updated with the form addresses.
|
||||
*
|
||||
* @returns {boolean}
|
||||
*/
|
||||
shouldUpdateButtonWithFormData() {
|
||||
if (this.context !== 'checkout') {
|
||||
return false;
|
||||
}
|
||||
return this.buttonConfig?.preferences?.checkout_data_mode === 'use_applepay';
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates how payment completion should be handled if with the context handler default actions.
|
||||
* Or with ApplePay module specific completion.
|
||||
*
|
||||
* @returns {boolean}
|
||||
*/
|
||||
shouldCompletePaymentWithContextHandler() {
|
||||
// Data already handled, ex: PayNow
|
||||
if (!this.contextHandler.shippingAllowed()) {
|
||||
return true;
|
||||
}
|
||||
// Use WC form data mode in Checkout.
|
||||
if (this.context === 'checkout' && !this.shouldUpdateButtonWithFormData()) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates ApplePay paymentRequest with form data.
|
||||
*/
|
||||
updateRequestDataWithForm(paymentRequest) {
|
||||
if (!this.shouldUpdateButtonWithFormData()) {
|
||||
return;
|
||||
}
|
||||
paymentDataRequest.shippingContact = this.fill_shipping_contact(this.form_saved);
|
||||
|
||||
// Add billing address.
|
||||
paymentRequest.billingContact = this.fillBillingContact(this.formData);
|
||||
|
||||
// Add custom data.
|
||||
// "applicationData" is originating a "PayPalApplePayError: An internal server error has occurred" on paypal.Applepay().confirmOrder().
|
||||
// paymentRequest.applicationData = this.fillApplicationData(this.formData);
|
||||
|
||||
if (!this.shouldRequireShippingInButton()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Add shipping address.
|
||||
paymentRequest.shippingContact = this.fillShippingContact(this.formData);
|
||||
|
||||
// Get shipping methods.
|
||||
const rate = this.transactionInfo.chosenShippingMethods[0];
|
||||
paymentRequest.shippingMethods = [];
|
||||
|
||||
// Add selected shipping method.
|
||||
for (const shippingPackage of this.transactionInfo.shippingPackages) {
|
||||
if (rate === shippingPackage.id) {
|
||||
const shippingMethod = {
|
||||
'label' : shippingPackage.label,
|
||||
'detail' : '',
|
||||
'amount' : shippingPackage.cost_str,
|
||||
'identifier' : shippingPackage.id,
|
||||
};
|
||||
|
||||
// Remember this shipping method as the selected one.
|
||||
this.selectedShippingMethod = shippingMethod;
|
||||
|
||||
paymentRequest.shippingMethods.push(shippingMethod);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Add other shipping methods.
|
||||
for (const shippingPackage of this.transactionInfo.shippingPackages) {
|
||||
if (rate !== shippingPackage.id) {
|
||||
paymentRequest.shippingMethods.push({
|
||||
'label' : shippingPackage.label,
|
||||
'detail' : '',
|
||||
'amount' : shippingPackage.cost_str,
|
||||
'identifier' : shippingPackage.id,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// Store for reuse in case this data is not provided by ApplePay on authorization.
|
||||
this.initialPaymentRequest = paymentRequest;
|
||||
|
||||
this.log('=== paymentRequest.shippingMethods', paymentRequest.shippingMethods);
|
||||
}
|
||||
|
||||
paymentDataRequest() {
|
||||
paymentRequest() {
|
||||
const applepayConfig = this.applePayConfig
|
||||
const buttonConfig = this.buttonConfig
|
||||
let baseRequest = {
|
||||
|
@ -245,22 +356,28 @@ class ApplepayButton {
|
|||
merchantCapabilities: applepayConfig.merchantCapabilities,
|
||||
supportedNetworks: applepayConfig.supportedNetworks,
|
||||
requiredShippingContactFields: ["postalAddress", "email", "phone"],
|
||||
requiredBillingContactFields: ["postalAddress", "email", "phone"],
|
||||
requiredBillingContactFields: ["postalAddress"], // ApplePay does not implement billing email and phone fields.
|
||||
}
|
||||
|
||||
if (!this.contextHandler.shippingAllowed()) {
|
||||
baseRequest.requiredShippingContactFields = [];
|
||||
if (!this.shouldRequireShippingInButton()) {
|
||||
if (this.shouldCompletePaymentWithContextHandler()) {
|
||||
// Data needs handled externally.
|
||||
baseRequest.requiredShippingContactFields = [];
|
||||
} else {
|
||||
// Minimum data required for order creation.
|
||||
baseRequest.requiredShippingContactFields = ["email", "phone"];
|
||||
}
|
||||
}
|
||||
|
||||
const paymentDataRequest = Object.assign({}, baseRequest);
|
||||
paymentDataRequest.currencyCode = buttonConfig.shop.currencyCode;
|
||||
paymentDataRequest.total = {
|
||||
const paymentRequest = Object.assign({}, baseRequest);
|
||||
paymentRequest.currencyCode = buttonConfig.shop.currencyCode;
|
||||
paymentRequest.total = {
|
||||
label: buttonConfig.shop.totalLabel,
|
||||
type: "final",
|
||||
amount: this.transactionInfo.totalPrice,
|
||||
}
|
||||
|
||||
return paymentDataRequest
|
||||
return paymentRequest;
|
||||
}
|
||||
|
||||
refreshContextData() {
|
||||
|
@ -278,7 +395,7 @@ class ApplepayButton {
|
|||
// Payment process
|
||||
//------------------------
|
||||
|
||||
onvalidatemerchant(session) {
|
||||
onValidateMerchant(session) {
|
||||
this.log('onvalidatemerchant', this.buttonConfig.ajax_url);
|
||||
return (applePayValidateMerchantEvent) => {
|
||||
this.log('onvalidatemerchant call');
|
||||
|
@ -312,83 +429,90 @@ class ApplepayButton {
|
|||
validation: false,
|
||||
'woocommerce-process-checkout-nonce': this.nonce,
|
||||
}
|
||||
})
|
||||
});
|
||||
this.log('onvalidatemerchant session abort');
|
||||
session.abort();
|
||||
});
|
||||
};
|
||||
}
|
||||
onshippingmethodselected(session) {
|
||||
|
||||
onShippingMethodSelected(session) {
|
||||
this.log('onshippingmethodselected', this.buttonConfig.ajax_url);
|
||||
const ajax_url = this.buttonConfig.ajax_url
|
||||
const ajax_url = this.buttonConfig.ajax_url;
|
||||
return (event) => {
|
||||
this.log('onshippingmethodselected call');
|
||||
|
||||
const data = this.getShippingMethodData(event);
|
||||
|
||||
jQuery.ajax({
|
||||
url: ajax_url,
|
||||
method: 'POST',
|
||||
data: data,
|
||||
success: (applePayShippingMethodUpdate, textStatus, jqXHR) => {
|
||||
this.log('onshippingmethodselected ok');
|
||||
let response = applePayShippingMethodUpdate.data
|
||||
let response = applePayShippingMethodUpdate.data;
|
||||
if (applePayShippingMethodUpdate.success === false) {
|
||||
response.errors = createAppleErrors(response.errors)
|
||||
response.errors = createAppleErrors(response.errors);
|
||||
}
|
||||
this.selectedShippingMethod = event.shippingMethod
|
||||
//order the response shipping methods, so that the selected shipping method is the first one
|
||||
let orderedShippingMethods = response.newShippingMethods.sort((a, b) => {
|
||||
this.selectedShippingMethod = event.shippingMethod;
|
||||
|
||||
// Sort the response shipping methods, so that the selected shipping method is the first one.
|
||||
response.newShippingMethods = response.newShippingMethods.sort((a, b) => {
|
||||
if (a.label === this.selectedShippingMethod.label) {
|
||||
return -1
|
||||
return -1;
|
||||
}
|
||||
return 1
|
||||
})
|
||||
//update the response.newShippingMethods with the ordered shipping methods
|
||||
response.newShippingMethods = orderedShippingMethods
|
||||
return 1;
|
||||
});
|
||||
|
||||
if (applePayShippingMethodUpdate.success === false) {
|
||||
response.errors = createAppleErrors(response.errors)
|
||||
response.errors = createAppleErrors(response.errors);
|
||||
}
|
||||
session.completeShippingMethodSelection(response)
|
||||
session.completeShippingMethodSelection(response);
|
||||
},
|
||||
error: (jqXHR, textStatus, errorThrown) => {
|
||||
this.log('onshippingmethodselected error', textStatus);
|
||||
console.warn(textStatus, errorThrown)
|
||||
session.abort()
|
||||
console.warn(textStatus, errorThrown);
|
||||
session.abort();
|
||||
},
|
||||
})
|
||||
});
|
||||
};
|
||||
}
|
||||
onshippingcontactselected(session) {
|
||||
|
||||
onShippingContactSelected(session) {
|
||||
this.log('onshippingcontactselected', this.buttonConfig.ajax_url);
|
||||
const ajax_url = this.buttonConfig.ajax_url
|
||||
|
||||
const ajax_url = this.buttonConfig.ajax_url;
|
||||
|
||||
return (event) => {
|
||||
this.log('onshippingcontactselected call');
|
||||
|
||||
const data = this.getShippingContactData(event);
|
||||
|
||||
jQuery.ajax({
|
||||
url: ajax_url,
|
||||
method: 'POST',
|
||||
data: data,
|
||||
success: (applePayShippingContactUpdate, textStatus, jqXHR) => {
|
||||
this.log('onshippingcontactselected ok');
|
||||
let response = applePayShippingContactUpdate.data
|
||||
this.updated_contact_info = event.shippingContact
|
||||
let response = applePayShippingContactUpdate.data;
|
||||
this.updatedContactInfo = event.shippingContact;
|
||||
if (applePayShippingContactUpdate.success === false) {
|
||||
response.errors = createAppleErrors(response.errors)
|
||||
response.errors = createAppleErrors(response.errors);
|
||||
}
|
||||
if (response.newShippingMethods) {
|
||||
this.selectedShippingMethod = response.newShippingMethods[0]
|
||||
this.selectedShippingMethod = response.newShippingMethods[0];
|
||||
}
|
||||
session.completeShippingContactSelection(response)
|
||||
session.completeShippingContactSelection(response);
|
||||
},
|
||||
error: (jqXHR, textStatus, errorThrown) => {
|
||||
this.log('onshippingcontactselected error', textStatus);
|
||||
console.warn(textStatus, errorThrown)
|
||||
session.abort()
|
||||
console.warn(textStatus, errorThrown);
|
||||
session.abort();
|
||||
},
|
||||
})
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
getShippingContactData(event) {
|
||||
const product_id = this.buttonConfig.product.id;
|
||||
|
||||
|
@ -403,7 +527,7 @@ class ApplepayButton {
|
|||
caller_page: 'productDetail',
|
||||
product_quantity: this.productQuantity,
|
||||
simplified_contact: event.shippingContact,
|
||||
need_shipping: this.buttonConfig.product.needShipping,
|
||||
need_shipping: this.shouldRequireShippingInButton(),
|
||||
'woocommerce-process-checkout-nonce': this.nonce,
|
||||
};
|
||||
case 'cart':
|
||||
|
@ -415,11 +539,12 @@ class ApplepayButton {
|
|||
action: 'ppcp_update_shipping_contact',
|
||||
simplified_contact: event.shippingContact,
|
||||
caller_page: 'cart',
|
||||
need_shipping: this.buttonConfig.product.needShipping,
|
||||
need_shipping: this.shouldRequireShippingInButton(),
|
||||
'woocommerce-process-checkout-nonce': this.nonce,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
getShippingMethodData(event) {
|
||||
const product_id = this.buttonConfig.product.id;
|
||||
|
||||
|
@ -429,11 +554,11 @@ class ApplepayButton {
|
|||
case 'product': return {
|
||||
action: 'ppcp_update_shipping_method',
|
||||
shipping_method: event.shippingMethod,
|
||||
simplified_contact: this.updatedContactInfo || this.initialPaymentRequest.shippingContact || this.initialPaymentRequest.billingContact,
|
||||
product_id: product_id,
|
||||
products: JSON.stringify(this.products),
|
||||
caller_page: 'productDetail',
|
||||
product_quantity: this.productQuantity,
|
||||
simplified_contact: this.updated_contact_info,
|
||||
'woocommerce-process-checkout-nonce': this.nonce,
|
||||
}
|
||||
case 'cart':
|
||||
|
@ -444,14 +569,14 @@ class ApplepayButton {
|
|||
return {
|
||||
action: 'ppcp_update_shipping_method',
|
||||
shipping_method: event.shippingMethod,
|
||||
simplified_contact: this.updatedContactInfo || this.initialPaymentRequest.shippingContact || this.initialPaymentRequest.billingContact,
|
||||
caller_page: 'cart',
|
||||
simplified_contact: this.updated_contact_info,
|
||||
'woocommerce-process-checkout-nonce': this.nonce,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
onpaymentauthorized(session) {
|
||||
onPaymentAuthorized(session) {
|
||||
this.log('onpaymentauthorized');
|
||||
return async (event) => {
|
||||
this.log('onpaymentauthorized call');
|
||||
|
@ -462,8 +587,10 @@ class ApplepayButton {
|
|||
const processInWooAndCapture = async (data) => {
|
||||
return new Promise((resolve, reject) => {
|
||||
try {
|
||||
const billingContact = data.billing_contact
|
||||
const shippingContact = data.shipping_contact
|
||||
const billingContact = data.billing_contact || this.initialPaymentRequest.billingContact;
|
||||
const shippingContact = data.shipping_contact || this.initialPaymentRequest.shippingContact;
|
||||
const shippingMethod = this.selectedShippingMethod || (this.initialPaymentRequest.shippingMethods || [])[0];
|
||||
|
||||
let request_data = {
|
||||
action: 'ppcp_create_order',
|
||||
'caller_page': this.context,
|
||||
|
@ -473,7 +600,7 @@ class ApplepayButton {
|
|||
'shipping_contact': shippingContact,
|
||||
'billing_contact': billingContact,
|
||||
'token': event.payment.token,
|
||||
'shipping_method': this.selectedShippingMethod,
|
||||
'shipping_method': shippingMethod,
|
||||
'woocommerce-process-checkout-nonce': this.nonce,
|
||||
'funding_source': 'applepay',
|
||||
'_wp_http_referer': '/?wc-ajax=update_order_review',
|
||||
|
@ -491,16 +618,16 @@ class ApplepayButton {
|
|||
},
|
||||
success: (authorizationResult, textStatus, jqXHR) => {
|
||||
this.log('onpaymentauthorized ok');
|
||||
resolve(authorizationResult)
|
||||
resolve(authorizationResult);
|
||||
},
|
||||
error: (jqXHR, textStatus, errorThrown) => {
|
||||
this.log('onpaymentauthorized error', textStatus);
|
||||
reject(new Error(errorThrown));
|
||||
},
|
||||
})
|
||||
});
|
||||
} catch (error) {
|
||||
this.log('onpaymentauthorized catch', error);
|
||||
console.log(error) // handle error
|
||||
console.log(error); // handle error
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -522,8 +649,8 @@ class ApplepayButton {
|
|||
if (confirmOrderResponse.approveApplePayPayment.status === "APPROVED") {
|
||||
try {
|
||||
|
||||
if (!this.contextHandler.shippingAllowed()) {
|
||||
// No shipping, expect immediate capture, ex: PayNow.
|
||||
if (this.shouldCompletePaymentWithContextHandler()) {
|
||||
// No shipping, expect immediate capture, ex: PayNow, Checkout with form data.
|
||||
|
||||
let approveFailed = false;
|
||||
await this.contextHandler.approveOrder({
|
||||
|
@ -546,7 +673,7 @@ class ApplepayButton {
|
|||
} else {
|
||||
this.log('onpaymentauthorized approveOrder FAIL');
|
||||
session.completePayment(ApplePaySession.STATUS_FAILURE);
|
||||
session.abort()
|
||||
session.abort();
|
||||
console.error(error);
|
||||
}
|
||||
|
||||
|
@ -560,17 +687,17 @@ class ApplepayButton {
|
|||
};
|
||||
let authorizationResult = await processInWooAndCapture(data);
|
||||
if (authorizationResult.result === "success") {
|
||||
session.completePayment(ApplePaySession.STATUS_SUCCESS)
|
||||
window.location.href = authorizationResult.redirect
|
||||
session.completePayment(ApplePaySession.STATUS_SUCCESS);
|
||||
window.location.href = authorizationResult.redirect;
|
||||
} else {
|
||||
session.completePayment(ApplePaySession.STATUS_FAILURE)
|
||||
session.completePayment(ApplePaySession.STATUS_FAILURE);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
} catch (error) {
|
||||
session.completePayment(ApplePaySession.STATUS_FAILURE);
|
||||
session.abort()
|
||||
session.abort();
|
||||
console.error(error);
|
||||
}
|
||||
} else {
|
||||
|
@ -584,43 +711,44 @@ class ApplepayButton {
|
|||
} catch (error) {
|
||||
console.error('Error confirming order with applepay token', error);
|
||||
session.completePayment(ApplePaySession.STATUS_FAILURE);
|
||||
session.abort()
|
||||
session.abort();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
fill_billing_contact(form_saved) {
|
||||
fillBillingContact(data) {
|
||||
return {
|
||||
givenName: form_saved.billing_first_name ?? '',
|
||||
familyName: form_saved.billing_last_name ?? '',
|
||||
emailAddress: form_saved.billing_email ?? '',
|
||||
phoneNumber: form_saved.billing_phone ?? '',
|
||||
addressLines: [form_saved.billing_address_1, form_saved.billing_address_2],
|
||||
locality: form_saved.billing_city ?? '',
|
||||
postalCode: form_saved.billing_postcode ?? '',
|
||||
countryCode: form_saved.billing_country ?? '',
|
||||
administrativeArea: form_saved.billing_state ?? '',
|
||||
}
|
||||
}
|
||||
fill_shipping_contact(form_saved) {
|
||||
if (form_saved.shipping_first_name === "") {
|
||||
return this.fill_billing_contact(form_saved)
|
||||
}
|
||||
return {
|
||||
givenName: (form_saved?.shipping_first_name && form_saved.shipping_first_name !== "") ? form_saved.shipping_first_name : form_saved?.billing_first_name,
|
||||
familyName: (form_saved?.shipping_last_name && form_saved.shipping_last_name !== "") ? form_saved.shipping_last_name : form_saved?.billing_last_name,
|
||||
emailAddress: (form_saved?.shipping_email && form_saved.shipping_email !== "") ? form_saved.shipping_email : form_saved?.billing_email,
|
||||
phoneNumber: (form_saved?.shipping_phone && form_saved.shipping_phone !== "") ? form_saved.shipping_phone : form_saved?.billing_phone,
|
||||
addressLines: [form_saved.shipping_address_1 ?? '', form_saved.shipping_address_2 ?? ''],
|
||||
locality: (form_saved?.shipping_city && form_saved.shipping_city !== "") ? form_saved.shipping_city : form_saved?.billing_city,
|
||||
postalCode: (form_saved?.shipping_postcode && form_saved.shipping_postcode !== "") ? form_saved.shipping_postcode : form_saved?.billing_postcode,
|
||||
countryCode: (form_saved?.shipping_country && form_saved.shipping_country !== "") ? form_saved.shipping_country : form_saved?.billing_country,
|
||||
administrativeArea: (form_saved?.shipping_state && form_saved.shipping_state !== "") ? form_saved.shipping_state : form_saved?.billing_state,
|
||||
givenName: data.billing_first_name ?? '',
|
||||
familyName: data.billing_last_name ?? '',
|
||||
emailAddress: data.billing_email ?? '',
|
||||
phoneNumber: data.billing_phone ?? '',
|
||||
addressLines: [data.billing_address_1, data.billing_address_2],
|
||||
locality: data.billing_city ?? '',
|
||||
postalCode: data.billing_postcode ?? '',
|
||||
countryCode: data.billing_country ?? '',
|
||||
administrativeArea: data.billing_state ?? '',
|
||||
}
|
||||
}
|
||||
|
||||
fill_application_data(form_saved) {
|
||||
const jsonString = JSON.stringify(form_saved);
|
||||
fillShippingContact(data) {
|
||||
if (data.shipping_first_name === "") {
|
||||
return this.fillBillingContact(data);
|
||||
}
|
||||
return {
|
||||
givenName: (data?.shipping_first_name && data.shipping_first_name !== "") ? data.shipping_first_name : data?.billing_first_name,
|
||||
familyName: (data?.shipping_last_name && data.shipping_last_name !== "") ? data.shipping_last_name : data?.billing_last_name,
|
||||
emailAddress: (data?.shipping_email && data.shipping_email !== "") ? data.shipping_email : data?.billing_email,
|
||||
phoneNumber: (data?.shipping_phone && data.shipping_phone !== "") ? data.shipping_phone : data?.billing_phone,
|
||||
addressLines: [data.shipping_address_1 ?? '', data.shipping_address_2 ?? ''],
|
||||
locality: (data?.shipping_city && data.shipping_city !== "") ? data.shipping_city : data?.billing_city,
|
||||
postalCode: (data?.shipping_postcode && data.shipping_postcode !== "") ? data.shipping_postcode : data?.billing_postcode,
|
||||
countryCode: (data?.shipping_country && data.shipping_country !== "") ? data.shipping_country : data?.billing_country,
|
||||
administrativeArea: (data?.shipping_state && data.shipping_state !== "") ? data.shipping_state : data?.billing_state,
|
||||
}
|
||||
}
|
||||
|
||||
fillApplicationData(data) {
|
||||
const jsonString = JSON.stringify(data);
|
||||
let utf8Str = encodeURIComponent(jsonString).replace(/%([0-9A-F]{2})/g, (match, p1) => {
|
||||
return String.fromCharCode('0x' + p1);
|
||||
});
|
||||
|
|
|
@ -22,12 +22,14 @@ class BaseHandler {
|
|||
|
||||
transactionInfo() {
|
||||
return new Promise((resolve, reject) => {
|
||||
const endpoint = this.ppcpConfig.ajax.cart_script_params.endpoint;
|
||||
const separator = (endpoint.indexOf('?') !== -1) ? '&' : '?';
|
||||
|
||||
fetch(
|
||||
this.ppcpConfig.ajax.cart_script_params.endpoint,
|
||||
endpoint + separator + 'shipping=1',
|
||||
{
|
||||
method: 'GET',
|
||||
credentials: 'same-origin',
|
||||
credentials: 'same-origin'
|
||||
}
|
||||
)
|
||||
.then(result => result.json())
|
||||
|
@ -43,7 +45,9 @@ class BaseHandler {
|
|||
countryCode: data.country_code,
|
||||
currencyCode: data.currency_code,
|
||||
totalPriceStatus: 'FINAL',
|
||||
totalPrice: data.total_str
|
||||
totalPrice: data.total_str,
|
||||
chosenShippingMethods: data.chosen_shipping_methods || null,
|
||||
shippingPackages: data.shipping_packages || null,
|
||||
});
|
||||
|
||||
});
|
||||
|
|
|
@ -1,28 +1,17 @@
|
|||
import Spinner from "../../../../ppcp-button/resources/js/modules/Helper/Spinner";
|
||||
import CheckoutActionHandler
|
||||
from "../../../../ppcp-button/resources/js/modules/ActionHandler/CheckoutActionHandler";
|
||||
import ErrorHandler from "../../../../ppcp-button/resources/js/modules/ErrorHandler";
|
||||
import BaseHandler from "./BaseHandler";
|
||||
|
||||
class CheckoutHandler extends BaseHandler {
|
||||
|
||||
createOrder() {
|
||||
const errorHandler = new ErrorHandler(
|
||||
this.ppcpConfig.labels.error.generic,
|
||||
document.querySelector('.woocommerce-notices-wrapper')
|
||||
);
|
||||
|
||||
const spinner = new Spinner();
|
||||
|
||||
const actionHandler = new CheckoutActionHandler(
|
||||
actionHandler() {
|
||||
return new CheckoutActionHandler(
|
||||
this.ppcpConfig,
|
||||
errorHandler,
|
||||
spinner
|
||||
this.errorHandler(),
|
||||
new Spinner()
|
||||
);
|
||||
|
||||
return actionHandler.configuration().createOrder(null, null);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default CheckoutHandler;
|
||||
|
|
|
@ -312,7 +312,6 @@ class ApplePayButton implements ButtonInterface {
|
|||
$user_country,
|
||||
$allowed_shipping_countries
|
||||
);
|
||||
$product_need_shipping = $applepay_request_data_object->need_shipping();
|
||||
|
||||
if ( ! $is_allowed_selling_country ) {
|
||||
$this->response_templates->response_with_data_errors(
|
||||
|
@ -320,7 +319,7 @@ class ApplePayButton implements ButtonInterface {
|
|||
);
|
||||
return;
|
||||
}
|
||||
if ( $product_need_shipping && ! $is_allowed_shipping_country ) {
|
||||
if ( $applepay_request_data_object->need_shipping() && ! $is_allowed_shipping_country ) {
|
||||
$this->response_templates->response_with_data_errors(
|
||||
array( array( 'errorCode' => 'addressUnserviceable' ) )
|
||||
);
|
||||
|
@ -405,6 +404,7 @@ class ApplePayButton implements ButtonInterface {
|
|||
public function create_wc_order(): void {
|
||||
$applepay_request_data_object = $this->applepay_data_object_http();
|
||||
//phpcs:disable WordPress.Security.NonceVerification
|
||||
|
||||
$context = wc_clean( wp_unslash( $_POST['caller_page'] ?? '' ) );
|
||||
if ( ! is_string( $context ) ) {
|
||||
$this->response_templates->response_with_data_errors(
|
||||
|
@ -418,6 +418,7 @@ class ApplePayButton implements ButtonInterface {
|
|||
return;
|
||||
}
|
||||
$applepay_request_data_object->order_data( $context );
|
||||
|
||||
$this->update_posted_data( $applepay_request_data_object );
|
||||
if ( $context === 'product' ) {
|
||||
$cart_item_key = $this->prepare_cart( $applepay_request_data_object );
|
||||
|
@ -451,7 +452,7 @@ class ApplePayButton implements ButtonInterface {
|
|||
}
|
||||
);
|
||||
}
|
||||
$this->add_addresses_to_order( $applepay_request_data_object );
|
||||
|
||||
WC()->checkout()->process_checkout();
|
||||
}
|
||||
|
||||
|
@ -596,10 +597,10 @@ class ApplePayButton implements ButtonInterface {
|
|||
$address['country'] ?? $shop_country_code
|
||||
);
|
||||
WC()->customer->set_shipping_postcode(
|
||||
$address['postcode'] ?? $shop_country_code
|
||||
$address['postcode'] ?? ''
|
||||
);
|
||||
WC()->customer->set_shipping_city(
|
||||
$address['city'] ?? $shop_country_code
|
||||
$address['city'] ?? ''
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -765,32 +766,6 @@ class ApplePayButton implements ButtonInterface {
|
|||
return $results;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add address billing and shipping data to order
|
||||
*
|
||||
* @param ApplePayDataObjectHttp $applepay_request_data_object ApplePayDataObjectHttp.
|
||||
*/
|
||||
protected function add_addresses_to_order(
|
||||
ApplePayDataObjectHttp $applepay_request_data_object
|
||||
): void {
|
||||
add_action(
|
||||
'woocommerce_checkout_create_order',
|
||||
static function ( WC_Order $order, array $data ) use ( $applepay_request_data_object ) {
|
||||
if ( ! empty( $applepay_request_data_object->shipping_method() ) ) {
|
||||
$billing_address = $applepay_request_data_object->billing_address();
|
||||
$shipping_address = $applepay_request_data_object->shipping_address();
|
||||
// apple puts email in shipping_address while we get it from WC's billing_address.
|
||||
$billing_address['email'] = $shipping_address['email'];
|
||||
$billing_address['phone'] = $shipping_address['phone'];
|
||||
|
||||
$order->set_address( $billing_address, 'billing' );
|
||||
$order->set_address( $shipping_address, 'shipping' );
|
||||
}
|
||||
},
|
||||
10,
|
||||
2
|
||||
);
|
||||
}
|
||||
/**
|
||||
* Empty the cart to use for calculations
|
||||
* while saving its contents in a field
|
||||
|
@ -867,10 +842,11 @@ class ApplePayButton implements ButtonInterface {
|
|||
* @param ApplePayDataObjectHttp $applepay_request_data_object The Apple Pay request data.
|
||||
*/
|
||||
protected function update_posted_data( $applepay_request_data_object ): void {
|
||||
// TODO : get checkout form data in here to fill more fields like: ensure billing email and phone are filled.
|
||||
|
||||
add_filter(
|
||||
'woocommerce_checkout_posted_data',
|
||||
function ( array $data ) use ( $applepay_request_data_object ): array {
|
||||
|
||||
$data['payment_method'] = 'ppcp-gateway';
|
||||
$data['shipping_method'] = $applepay_request_data_object->shipping_method();
|
||||
$data['billing_first_name'] = $applepay_request_data_object->billing_address()['first_name'] ?? '';
|
||||
|
@ -882,10 +858,18 @@ class ApplePayButton implements ButtonInterface {
|
|||
$data['billing_city'] = $applepay_request_data_object->billing_address()['city'] ?? '';
|
||||
$data['billing_state'] = $applepay_request_data_object->billing_address()['state'] ?? '';
|
||||
$data['billing_postcode'] = $applepay_request_data_object->billing_address()['postcode'] ?? '';
|
||||
$data['billing_email'] = $applepay_request_data_object->billing_address()['email'] ?? '';
|
||||
$data['billing_phone'] = $applepay_request_data_object->billing_address()['phone'] ?? '';
|
||||
|
||||
// ApplePay doesn't send us a billing email or phone, use the shipping contacts instead.
|
||||
if ( ! ( $data['billing_email'] ?? false ) ) {
|
||||
$data['billing_email'] = $applepay_request_data_object->shipping_address()['email'] ?? '';
|
||||
}
|
||||
if ( ! ( $data['billing_phone'] ?? false ) ) {
|
||||
$data['billing_phone'] = $applepay_request_data_object->shipping_address()['phone'] ?? '';
|
||||
}
|
||||
|
||||
if ( ! empty( $applepay_request_data_object->shipping_method() ) ) {
|
||||
$data['billing_email'] = $applepay_request_data_object->shipping_address()['email'] ?? '';
|
||||
$data['billing_phone'] = $applepay_request_data_object->shipping_address()['phone'] ?? '';
|
||||
$data['shipping_first_name'] = $applepay_request_data_object->shipping_address()['first_name'] ?? '';
|
||||
$data['shipping_last_name'] = $applepay_request_data_object->shipping_address()['last_name'] ?? '';
|
||||
$data['shipping_company'] = $applepay_request_data_object->shipping_address()['company'] ?? '';
|
||||
|
|
|
@ -144,31 +144,35 @@ class DataToAppleButtonScripts {
|
|||
$type = $this->settings->has( 'applepay_button_type' ) ? $this->settings->get( 'applepay_button_type' ) : '';
|
||||
$color = $this->settings->has( 'applepay_button_color' ) ? $this->settings->get( 'applepay_button_color' ) : '';
|
||||
$lang = $this->settings->has( 'applepay_button_language' ) ? $this->settings->get( 'applepay_button_language' ) : '';
|
||||
$checkout_data_mode = $this->settings->has( 'applepay_checkout_data_mode' ) ? $this->settings->get( 'applepay_checkout_data_mode' ) : PropertiesDictionary::BILLING_DATA_MODE_DEFAULT;
|
||||
|
||||
return array(
|
||||
'sdk_url' => $this->sdk_url,
|
||||
'is_debug' => defined( 'WP_DEBUG' ) && WP_DEBUG ? true : false,
|
||||
'button' => array(
|
||||
'sdk_url' => $this->sdk_url,
|
||||
'is_debug' => defined( 'WP_DEBUG' ) && WP_DEBUG ? true : false,
|
||||
'preferences' => array(
|
||||
'checkout_data_mode' => $checkout_data_mode,
|
||||
),
|
||||
'button' => array(
|
||||
'wrapper' => 'applepay-container',
|
||||
'mini_cart_wrapper' => 'applepay-container-minicart',
|
||||
'type' => $type,
|
||||
'color' => $color,
|
||||
'lang' => $lang,
|
||||
),
|
||||
'product' => array(
|
||||
'product' => array(
|
||||
'needShipping' => $product_need_shipping,
|
||||
'id' => $product_id,
|
||||
'price' => $product_price,
|
||||
'isVariation' => $is_variation,
|
||||
'stock' => $product_stock,
|
||||
),
|
||||
'shop' => array(
|
||||
'shop' => array(
|
||||
'countryCode' => $shop_country_code,
|
||||
'currencyCode' => $currency_code,
|
||||
'totalLabel' => $total_label,
|
||||
),
|
||||
'ajax_url' => admin_url( 'admin-ajax.php' ),
|
||||
'nonce' => wp_create_nonce( 'woocommerce-process_checkout' ),
|
||||
'ajax_url' => admin_url( 'admin-ajax.php' ),
|
||||
'nonce' => wp_create_nonce( 'woocommerce-process_checkout' ),
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -191,32 +195,36 @@ class DataToAppleButtonScripts {
|
|||
return array();
|
||||
}
|
||||
|
||||
$type = $this->settings->has( 'applepay_button_type' ) ? $this->settings->get( 'applepay_button_type' ) : '';
|
||||
$color = $this->settings->has( 'applepay_button_color' ) ? $this->settings->get( 'applepay_button_color' ) : '';
|
||||
$lang = $this->settings->has( 'applepay_button_language' ) ? $this->settings->get( 'applepay_button_language' ) : '';
|
||||
$lang = apply_filters( 'woocommerce_paypal_payments_applepay_button_language', $lang );
|
||||
$type = $this->settings->has( 'applepay_button_type' ) ? $this->settings->get( 'applepay_button_type' ) : '';
|
||||
$color = $this->settings->has( 'applepay_button_color' ) ? $this->settings->get( 'applepay_button_color' ) : '';
|
||||
$lang = $this->settings->has( 'applepay_button_language' ) ? $this->settings->get( 'applepay_button_language' ) : '';
|
||||
$lang = apply_filters( 'woocommerce_paypal_payments_applepay_button_language', $lang );
|
||||
$checkout_data_mode = $this->settings->has( 'applepay_checkout_data_mode' ) ? $this->settings->get( 'applepay_checkout_data_mode' ) : PropertiesDictionary::BILLING_DATA_MODE_DEFAULT;
|
||||
|
||||
return array(
|
||||
'sdk_url' => $this->sdk_url,
|
||||
'is_debug' => defined( 'WP_DEBUG' ) && WP_DEBUG ? true : false,
|
||||
'button' => array(
|
||||
'sdk_url' => $this->sdk_url,
|
||||
'is_debug' => defined( 'WP_DEBUG' ) && WP_DEBUG ? true : false,
|
||||
'preferences' => array(
|
||||
'checkout_data_mode' => $checkout_data_mode,
|
||||
),
|
||||
'button' => array(
|
||||
'wrapper' => 'applepay-container',
|
||||
'mini_cart_wrapper' => 'applepay-container-minicart',
|
||||
'type' => $type,
|
||||
'color' => $color,
|
||||
'lang' => $lang,
|
||||
),
|
||||
'product' => array(
|
||||
'product' => array(
|
||||
'needShipping' => $cart->needs_shipping(),
|
||||
'subtotal' => $cart->get_subtotal(),
|
||||
),
|
||||
'shop' => array(
|
||||
'shop' => array(
|
||||
'countryCode' => $shop_country_code,
|
||||
'currencyCode' => $currency_code,
|
||||
'totalLabel' => $total_label,
|
||||
),
|
||||
'ajax_url' => admin_url( 'admin-ajax.php' ),
|
||||
'nonce' => wp_create_nonce( 'woocommerce-process_checkout' ),
|
||||
'ajax_url' => admin_url( 'admin-ajax.php' ),
|
||||
'nonce' => wp_create_nonce( 'woocommerce-process_checkout' ),
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -235,31 +243,35 @@ class DataToAppleButtonScripts {
|
|||
$currency_code,
|
||||
$total_label
|
||||
) {
|
||||
$type = $this->settings->has( 'applepay_button_type' ) ? $this->settings->get( 'applepay_button_type' ) : '';
|
||||
$color = $this->settings->has( 'applepay_button_color' ) ? $this->settings->get( 'applepay_button_color' ) : '';
|
||||
$lang = $this->settings->has( 'applepay_button_language' ) ? $this->settings->get( 'applepay_button_language' ) : '';
|
||||
$lang = apply_filters( 'woocommerce_paypal_payments_applepay_button_language', $lang );
|
||||
$type = $this->settings->has( 'applepay_button_type' ) ? $this->settings->get( 'applepay_button_type' ) : '';
|
||||
$color = $this->settings->has( 'applepay_button_color' ) ? $this->settings->get( 'applepay_button_color' ) : '';
|
||||
$lang = $this->settings->has( 'applepay_button_language' ) ? $this->settings->get( 'applepay_button_language' ) : '';
|
||||
$lang = apply_filters( 'woocommerce_paypal_payments_applepay_button_language', $lang );
|
||||
$checkout_data_mode = $this->settings->has( 'applepay_checkout_data_mode' ) ? $this->settings->get( 'applepay_checkout_data_mode' ) : PropertiesDictionary::BILLING_DATA_MODE_DEFAULT;
|
||||
|
||||
return array(
|
||||
'sdk_url' => $this->sdk_url,
|
||||
'is_debug' => defined( 'WP_DEBUG' ) && WP_DEBUG ? true : false,
|
||||
'button' => array(
|
||||
'sdk_url' => $this->sdk_url,
|
||||
'is_debug' => defined( 'WP_DEBUG' ) && WP_DEBUG ? true : false,
|
||||
'preferences' => array(
|
||||
'checkout_data_mode' => $checkout_data_mode,
|
||||
),
|
||||
'button' => array(
|
||||
'wrapper' => 'applepay-container',
|
||||
'mini_cart_wrapper' => 'applepay-container-minicart',
|
||||
'type' => $type,
|
||||
'color' => $color,
|
||||
'lang' => $lang,
|
||||
),
|
||||
'product' => array(
|
||||
'product' => array(
|
||||
'needShipping' => false,
|
||||
'subtotal' => 0,
|
||||
),
|
||||
'shop' => array(
|
||||
'shop' => array(
|
||||
'countryCode' => $shop_country_code,
|
||||
'currencyCode' => $currency_code,
|
||||
'totalLabel' => $total_label,
|
||||
),
|
||||
'ajax_url' => admin_url( 'admin-ajax.php' ),
|
||||
'ajax_url' => admin_url( 'admin-ajax.php' ),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,6 +17,10 @@ class PropertiesDictionary {
|
|||
|
||||
public const BILLING_CONTACT_INVALID = 'billing Contact Invalid';
|
||||
|
||||
public const BILLING_DATA_MODE_USE_WC = 'use_wc';
|
||||
public const BILLING_DATA_MODE_USE_APPLEPAY = 'use_applepay';
|
||||
public const BILLING_DATA_MODE_DEFAULT = self::BILLING_DATA_MODE_USE_WC;
|
||||
|
||||
public const CREATE_ORDER_SINGLE_PROD_REQUIRED_FIELDS =
|
||||
array(
|
||||
self::WCNONCE,
|
||||
|
@ -186,4 +190,16 @@ class PropertiesDictionary {
|
|||
'zh-TW' => __( 'Chinese (Traditional)', 'woocommerce-paypal-payments' ),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the possible list of billing data modes.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public static function billing_data_modes(): array {
|
||||
return array(
|
||||
self::BILLING_DATA_MODE_USE_WC => __( 'Use WC checkout form data (do not show shipping address fields)', 'woocommerce-paypal-payments' ),
|
||||
self::BILLING_DATA_MODE_USE_APPLEPAY => __( 'Do not use WC checkout form data (request billing and shipping addresses on Apple Pay)', 'woocommerce-paypal-payments' ),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -70,6 +70,8 @@ class CartScriptParamsEndpoint implements EndpointInterface {
|
|||
wc_maybe_define_constant( 'WOOCOMMERCE_CART', true );
|
||||
}
|
||||
|
||||
$include_shipping = (bool) wc_clean( wp_unslash( $_GET['shipping'] ?? '' ) ); // phpcs:ignore WordPress.Security.NonceVerification.Recommended
|
||||
|
||||
$script_data = $this->smart_button->script_data();
|
||||
|
||||
$total = (float) WC()->cart->get_total( 'numeric' );
|
||||
|
@ -79,20 +81,23 @@ class CartScriptParamsEndpoint implements EndpointInterface {
|
|||
$shop_country_code = $base_location['country'] ?? '';
|
||||
$currency_code = get_woocommerce_currency();
|
||||
|
||||
wp_send_json_success(
|
||||
array(
|
||||
'url_params' => $script_data['url_params'],
|
||||
'button' => $script_data['button'],
|
||||
'messages' => $script_data['messages'],
|
||||
'amount' => WC()->cart->get_total( 'raw' ),
|
||||
$response = array(
|
||||
'url_params' => $script_data['url_params'],
|
||||
'button' => $script_data['button'],
|
||||
'messages' => $script_data['messages'],
|
||||
'amount' => WC()->cart->get_total( 'raw' ),
|
||||
|
||||
'total' => $total,
|
||||
'total_str' => ( new Money( $total, $currency_code ) )->value_str(),
|
||||
'currency_code' => $currency_code,
|
||||
'country_code' => $shop_country_code,
|
||||
)
|
||||
'total' => $total,
|
||||
'total_str' => ( new Money( $total, $currency_code ) )->value_str(),
|
||||
'currency_code' => $currency_code,
|
||||
'country_code' => $shop_country_code,
|
||||
);
|
||||
|
||||
if ( $include_shipping ) {
|
||||
$response = $this->append_shipping_data( $response, $currency_code );
|
||||
}
|
||||
|
||||
wp_send_json_success( $response );
|
||||
return true;
|
||||
} catch ( Throwable $error ) {
|
||||
$this->logger->error( "CartScriptParamsEndpoint execution failed. {$error->getMessage()} {$error->getFile()}:{$error->getLine()}" );
|
||||
|
@ -101,4 +106,45 @@ class CartScriptParamsEndpoint implements EndpointInterface {
|
|||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Appends shipping data to response.
|
||||
*
|
||||
* @param array $response The response array.
|
||||
* @param string $currency_code The currency code.
|
||||
* @return array
|
||||
*/
|
||||
private function append_shipping_data( array $response, string $currency_code ): array {
|
||||
$calculated_packages = WC()->shipping->calculate_shipping(
|
||||
WC()->cart->get_shipping_packages()
|
||||
);
|
||||
|
||||
$shipping_packages = array();
|
||||
|
||||
foreach ( $calculated_packages[0]['rates'] as $rate ) {
|
||||
$rate_cost = $rate->get_cost();
|
||||
|
||||
/**
|
||||
* The shipping rate.
|
||||
*
|
||||
* @var \WC_Shipping_Rate $rate
|
||||
*/
|
||||
$shipping_packages[] = array(
|
||||
'id' => $rate->get_id(),
|
||||
'label' => $rate->get_label(),
|
||||
'cost' => (float) $rate_cost,
|
||||
'cost_str' => ( new Money( (float) $rate_cost, $currency_code ) )->value_str(),
|
||||
'description' => html_entity_decode(
|
||||
wp_strip_all_tags(
|
||||
wc_price( (float) $rate->get_cost(), array( 'currency' => get_woocommerce_currency() ) )
|
||||
)
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
$response['chosen_shipping_methods'] = WC()->session->get( 'chosen_shipping_methods' );
|
||||
$response['shipping_packages'] = $shipping_packages;
|
||||
|
||||
return $response;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -135,13 +135,14 @@ return array(
|
|||
),
|
||||
),
|
||||
'googlepay_button_type' => array(
|
||||
'title' => str_repeat( ' ', 6 ) . __( 'Button Label', 'woocommerce-paypal-payments' ),
|
||||
'title' => __( 'Button Label', 'woocommerce-paypal-payments' ),
|
||||
'type' => 'select',
|
||||
'desc_tip' => true,
|
||||
'description' => __(
|
||||
'This controls the label of the Google Pay button.',
|
||||
'woocommerce-paypal-payments'
|
||||
),
|
||||
'classes' => array( 'ppcp-field-indent' ),
|
||||
'class' => array(),
|
||||
'input_class' => array( 'wc-enhanced-select' ),
|
||||
'default' => 'pay',
|
||||
|
@ -151,7 +152,7 @@ return array(
|
|||
'requirements' => array(),
|
||||
),
|
||||
'googlepay_button_color' => array(
|
||||
'title' => str_repeat( ' ', 6 ) . __( 'Button Color', 'woocommerce-paypal-payments' ),
|
||||
'title' => __( 'Button Color', 'woocommerce-paypal-payments' ),
|
||||
'type' => 'select',
|
||||
'desc_tip' => true,
|
||||
'description' => __(
|
||||
|
@ -160,6 +161,7 @@ return array(
|
|||
),
|
||||
'label' => '',
|
||||
'input_class' => array( 'wc-enhanced-select' ),
|
||||
'classes' => array( 'ppcp-field-indent' ),
|
||||
'class' => array(),
|
||||
'default' => 'black',
|
||||
'options' => PropertiesDictionary::button_colors(),
|
||||
|
@ -168,13 +170,14 @@ return array(
|
|||
'requirements' => array(),
|
||||
),
|
||||
'googlepay_button_language' => array(
|
||||
'title' => str_repeat( ' ', 6 ) . __( 'Button Language', 'woocommerce-paypal-payments' ),
|
||||
'title' => __( 'Button Language', 'woocommerce-paypal-payments' ),
|
||||
'type' => 'select',
|
||||
'desc_tip' => true,
|
||||
'description' => __(
|
||||
'The language and region used for the displayed Google Pay button. The default value is the current language and region setting in a browser.',
|
||||
'woocommerce-paypal-payments'
|
||||
),
|
||||
'classes' => array( 'ppcp-field-indent' ),
|
||||
'class' => array(),
|
||||
'input_class' => array( 'wc-enhanced-select' ),
|
||||
'default' => 'en',
|
||||
|
@ -184,13 +187,14 @@ return array(
|
|||
'requirements' => array(),
|
||||
),
|
||||
'googlepay_button_shipping_enabled' => array(
|
||||
'title' => str_repeat( ' ', 6 ) . __( 'Shipping Callback', 'woocommerce-paypal-payments' ),
|
||||
'title' => __( 'Shipping Callback', 'woocommerce-paypal-payments' ),
|
||||
'type' => 'checkbox',
|
||||
'desc_tip' => true,
|
||||
'description' => __(
|
||||
'Synchronizes your available shipping options with Google Pay. Enabling this may impact the buyer experience.',
|
||||
'woocommerce-paypal-payments'
|
||||
),
|
||||
'classes' => array( 'ppcp-field-indent' ),
|
||||
'label' => __( 'Enable Google Pay shipping callback', 'woocommerce-paypal-payments' ),
|
||||
'default' => 'no',
|
||||
'screens' => array( State::STATE_ONBOARDED ),
|
||||
|
|
|
@ -9,3 +9,9 @@
|
|||
filter: grayscale(100%);
|
||||
opacity: 0.5;
|
||||
}
|
||||
|
||||
.ppcp-field-indent {
|
||||
th {
|
||||
padding-left: 20px;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue