Merge pull request #1789 from woocommerce/PCP-2136-apple-pay-payment-process-issues

Apple Pay payment process issues (2136)
This commit is contained in:
Emili Castells 2023-10-23 16:52:54 +02:00 committed by GitHub
commit df283218bd
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 91 additions and 45 deletions

View file

@ -24,9 +24,7 @@ class ApplepayButton {
);
//PRODUCT DETAIL PAGE
if(this.context === 'product') {
this.productQuantity = document.querySelector('input.qty').value
}
this.refreshContextData();
this.updated_contact_info = []
this.selectedShippingMethod = []
@ -43,6 +41,8 @@ class ApplepayButton {
if (this.isInitialized) {
return;
}
this.log('Init', this.context);
this.initEventHandlers();
this.isInitialized = true;
this.applePayConfig = config;
@ -76,6 +76,16 @@ class ApplepayButton {
});
}
}
reinit() {
if (!this.applePayConfig) {
return;
}
this.isInitialized = false;
this.init(this.applePayConfig);
}
async fetchTransactionInfo() {
this.transactionInfo = await this.contextHandler.transactionInfo();
}
@ -123,6 +133,7 @@ class ApplepayButton {
}
applePaySession(paymentRequest) {
this.log('applePaySession', paymentRequest);
const session = new ApplePaySession(4, paymentRequest)
session.begin()
@ -172,6 +183,8 @@ class ApplepayButton {
* Show Apple Pay payment sheet when Apple Pay payment button is clicked
*/
async onButtonClick() {
this.log('onButtonClick', this.context);
const paymentDataRequest = this.paymentDataRequest();
// trigger woocommerce validation if we are in the checkout page
if (this.context === 'checkout') {
@ -183,7 +196,8 @@ class ApplepayButton {
try {
const formData = new FormData(document.querySelector(checkoutFormSelector));
this.form_saved = Object.fromEntries(formData.entries());
this.update_request_data_with_form(paymentDataRequest);
// This line should be reviewed, the paypal.Applepay().confirmOrder fails if we add it.
//this.update_request_data_with_form(paymentDataRequest);
} catch (error) {
console.error(error);
}
@ -241,17 +255,29 @@ class ApplepayButton {
return paymentDataRequest
}
refreshContextData() {
switch (this.context) {
case 'product':
// Refresh product data that makes the price change.
this.productQuantity = document.querySelector('input.qty').value;
break;
}
}
//------------------------
// Payment process
//------------------------
onvalidatemerchant(session) {
this.log('onvalidatemerchant', this.buttonConfig.ajax_url);
return (applePayValidateMerchantEvent) => {
this.log('onvalidatemerchant call');
paypal.Applepay().validateMerchant({
validationUrl: applePayValidateMerchantEvent.validationURL
})
.then(validateResult => {
this.log('onvalidatemerchant ok');
session.completeMerchantValidation(validateResult.merchantSession);
//call backend to update validation to true
jQuery.ajax({
@ -265,6 +291,7 @@ class ApplepayButton {
})
})
.catch(validateError => {
this.log('onvalidatemerchant error', validateError);
console.error(validateError);
//call backend to update validation to false
jQuery.ajax({
@ -276,19 +303,24 @@ class ApplepayButton {
'woocommerce-process-checkout-nonce': this.nonce,
}
})
this.log('onvalidatemerchant session abort');
session.abort();
});
};
}
onshippingmethodselected(session) {
this.log('onshippingmethodselected', 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
if (applePayShippingMethodUpdate.success === false) {
response.errors = createAppleErrors(response.errors)
@ -309,6 +341,7 @@ class ApplepayButton {
session.completeShippingMethodSelection(response)
},
error: (jqXHR, textStatus, errorThrown) => {
this.log('onshippingmethodselected error', textStatus);
console.warn(textStatus, errorThrown)
session.abort()
},
@ -316,14 +349,18 @@ class ApplepayButton {
};
}
onshippingcontactselected(session) {
this.log('onshippingcontactselected', 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
if (applePayShippingContactUpdate.success === false) {
@ -335,6 +372,7 @@ class ApplepayButton {
session.completeShippingContactSelection(response)
},
error: (jqXHR, textStatus, errorThrown) => {
this.log('onshippingcontactselected error', textStatus);
console.warn(textStatus, errorThrown)
session.abort()
},
@ -344,6 +382,8 @@ class ApplepayButton {
getShippingContactData(event) {
const product_id = this.buttonConfig.product.id;
this.refreshContextData();
switch (this.context) {
case 'product':
return {
@ -371,6 +411,9 @@ class ApplepayButton {
}
getShippingMethodData(event) {
const product_id = this.buttonConfig.product.id;
this.refreshContextData();
switch (this.context) {
case 'product': return {
action: 'ppcp_update_shipping_method',
@ -397,7 +440,10 @@ class ApplepayButton {
}
onpaymentauthorized(session) {
this.log('onpaymentauthorized');
return async (event) => {
this.log('onpaymentauthorized call');
function form() {
return document.querySelector('form.cart');
}
@ -420,32 +466,45 @@ class ApplepayButton {
'_wp_http_referer': '/?wc-ajax=update_order_review',
'paypal_order_id': data.paypal_order_id,
};
this.log('onpaymentauthorized request', this.buttonConfig.ajax_url, data);
jQuery.ajax({
url: this.buttonConfig.ajax_url,
method: 'POST',
data: request_data,
complete: (jqXHR, textStatus) => {
this.log('onpaymentauthorized complete');
},
success: (authorizationResult, textStatus, jqXHR) => {
this.log('onpaymentauthorized ok');
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
}
});
}
let id = await this.contextHandler.createOrder();
this.log('onpaymentauthorized paypal order ID', id, event.payment.token, event.payment.billingContact);
try {
const confirmOrderResponse = await paypal.Applepay().confirmOrder({
orderId: id,
token: event.payment.token,
billingContact: event.payment.billingContact,
});
this.log('onpaymentauthorized confirmOrderResponse', confirmOrderResponse);
if (confirmOrderResponse && confirmOrderResponse.approveApplePayPayment) {
if (confirmOrderResponse.approveApplePayPayment.status === "APPROVED") {
try {

View file

@ -35,6 +35,12 @@ class ApplepayManager {
})();
}
reinit() {
for (const button of this.buttons) {
button.reinit();
}
}
/**
* Gets ApplePay configuration of the PayPal merchant.
* @returns {Promise<null>}

View file

@ -8,11 +8,19 @@ import ApplepayManager from "./ApplepayManager";
jQuery
}) {
let manager;
const bootstrap = function () {
const manager = new ApplepayManager(buttonConfig, ppcpConfig);
manager = new ApplepayManager(buttonConfig, ppcpConfig);
manager.init();
};
jQuery(document.body).on('updated_cart_totals updated_checkout', () => {
if (manager) {
manager.reinit();
}
});
document.addEventListener(
'DOMContentLoaded',
() => {

File diff suppressed because one or more lines are too long

View file

@ -12,23 +12,16 @@ namespace WooCommerce\PayPalCommerce\Applepay\Assets;
use Exception;
use Psr\Log\LoggerInterface;
use WC_Cart;
use WC_Checkout;
use WC_Order;
use WC_Session_Handler;
use WooCommerce\PayPalCommerce\ApiClient\Endpoint\OrderEndpoint;
use WooCommerce\PayPalCommerce\ApiClient\Entity\OrderStatus;
use WooCommerce\PayPalCommerce\Button\Assets\ButtonInterface;
use WooCommerce\PayPalCommerce\Session\MemoryWcSession;
use WooCommerce\PayPalCommerce\Session\SessionHandler;
use WooCommerce\PayPalCommerce\WcGateway\Exception\NotFoundException;
use WooCommerce\PayPalCommerce\WcGateway\Gateway\PayPalGateway;
use WooCommerce\PayPalCommerce\WcGateway\Helper\SettingsStatus;
use WooCommerce\PayPalCommerce\WcGateway\Processor\OrderProcessor;
use WooCommerce\PayPalCommerce\WcGateway\Settings\Settings;
use WooCommerce\PayPalCommerce\Webhooks\Handler\RequestHandlerTrait;
/**
* Class PayPalPaymentMethod
* Class ApplePayButton
*/
class ApplePayButton implements ButtonInterface {
use RequestHandlerTrait;
@ -178,21 +171,6 @@ class ApplePayButton implements ButtonInterface {
$data['products'][0] = 'PAYMENT_METHODS';
}
$data['capabilities'][] = 'APPLE_PAY';
$data['operations'][] = array(
'operation' => 'API_INTEGRATION',
'api_integration_preference' => array(
'rest_api_integration' => array(
'integration_method' => 'PAYPAL',
'integration_type' => 'THIRD_PARTY',
'third_party_details' => array(
'features' => array(
'PAYMENT',
'REFUND',
),
),
),
),
);
return $data;
}

View file

@ -300,6 +300,10 @@ class ApplePayDataObjectHttp {
*/
protected function assign_data_object_values( array $data ): void {
foreach ( $data as $key => $value ) {
// Null values may give origin to type errors. If necessary replace condition this with a specialized field filter.
if ( null === $value ) {
continue;
}
if ( $key === 'woocommerce-process-checkout-nonce' ) {
$key = 'nonce';
}

View file

@ -204,21 +204,6 @@ class Button implements ButtonInterface {
}
$data['capabilities'][] = 'GOOGLE_PAY';
$data['operations'][] = array(
'operation' => 'API_INTEGRATION',
'api_integration_preference' => array(
'rest_api_integration' => array(
'integration_method' => 'PAYPAL',
'integration_type' => 'THIRD_PARTY',
'third_party_details' => array(
'features' => array(
'PAYMENT',
'REFUND',
),
),
),
),
);
return $data;
}