From 96b83c9d0d607f5efacab0392729520f24594235 Mon Sep 17 00:00:00 2001
From: Pedro Silva
Date: Wed, 24 Jan 2024 08:47:48 +0000
Subject: [PATCH] ApplePay Vaulting Integration
---
.../resources/js/ApplepayButton.js | 6 ++-
.../resources/js/checkout-block.js | 2 +-
.../js/modules/ButtonModuleWatcher.js | 1 -
.../src/SavePaymentMethodsModule.php | 7 +--
.../src/WooCommercePaymentTokens.php | 14 ++++--
.../ppcp-vaulting/src/PaymentTokenPayPal.php | 21 ++++++++-
modules/ppcp-vaulting/src/VaultingModule.php | 47 ++++++++++++++++++-
7 files changed, 86 insertions(+), 12 deletions(-)
diff --git a/modules/ppcp-applepay/resources/js/ApplepayButton.js b/modules/ppcp-applepay/resources/js/ApplepayButton.js
index 4484bba21..e9ec47bde 100644
--- a/modules/ppcp-applepay/resources/js/ApplepayButton.js
+++ b/modules/ppcp-applepay/resources/js/ApplepayButton.js
@@ -209,11 +209,15 @@ class ApplepayButton {
/**
* Show Apple Pay payment sheet when Apple Pay payment button is clicked
*/
- async onButtonClick() {
+ async onButtonClick(data, actions) {
+ console.log('data, actions', data, actions);
+
this.log('onButtonClick', this.context);
const paymentRequest = this.paymentRequest();
+ window.ppcpFundingSource = 'apple_pay'; // Do this on another place like on create order endpoint handler.
+
// Trigger woocommerce validation if we are in the checkout page.
if (this.context === 'checkout') {
const checkoutFormSelector = 'form.woocommerce-checkout';
diff --git a/modules/ppcp-blocks/resources/js/checkout-block.js b/modules/ppcp-blocks/resources/js/checkout-block.js
index 1662d7d89..d999efa80 100644
--- a/modules/ppcp-blocks/resources/js/checkout-block.js
+++ b/modules/ppcp-blocks/resources/js/checkout-block.js
@@ -87,7 +87,7 @@ const PayPalComponent = ({
bn_code: '',
context: config.scriptData.context,
payment_method: 'ppcp-gateway',
- funding_source: data.paymentSource,
+ funding_source: window.ppcpFundingSource ?? 'paypal',
createaccount: false
}),
});
diff --git a/modules/ppcp-button/resources/js/modules/ButtonModuleWatcher.js b/modules/ppcp-button/resources/js/modules/ButtonModuleWatcher.js
index c6165674a..3fccca178 100644
--- a/modules/ppcp-button/resources/js/modules/ButtonModuleWatcher.js
+++ b/modules/ppcp-button/resources/js/modules/ButtonModuleWatcher.js
@@ -7,7 +7,6 @@ class ButtonModuleWatcher {
}
watchContextBootstrap(callable) {
- console.log('ButtonModuleWatcher.js: watchContextBootstrap', this.contextBootstrapRegistry)
this.contextBootstrapWatchers.push(callable);
Object.values(this.contextBootstrapRegistry).forEach(callable);
}
diff --git a/modules/ppcp-save-payment-methods/src/SavePaymentMethodsModule.php b/modules/ppcp-save-payment-methods/src/SavePaymentMethodsModule.php
index 71441f562..e79ec11f6 100644
--- a/modules/ppcp-save-payment-methods/src/SavePaymentMethodsModule.php
+++ b/modules/ppcp-save-payment-methods/src/SavePaymentMethodsModule.php
@@ -119,14 +119,14 @@ class SavePaymentMethodsModule implements ModuleInterface {
),
),
);
- } else if ( $funding_source === 'apple_pay' ) {
+ } elseif ( $funding_source && $funding_source === 'apple_pay' ) {
$data['payment_source'] = array(
'apple_pay' => array(
'stored_credential' => array(
'payment_initiator' => 'CUSTOMER',
'payment_type' => 'RECURRING',
),
- 'attributes' => array(
+ 'attributes' => array(
'vault' => array(
'store_in_vault' => 'ON_SUCCESS',
),
@@ -191,7 +191,8 @@ class SavePaymentMethodsModule implements ModuleInterface {
$wc_payment_tokens->create_payment_token_paypal(
$wc_order->get_customer_id(),
$token_id,
- $payment_source->properties()->email_address ?? ''
+ $payment_source->properties()->email_address ?? '',
+ $payment_source->name()
);
}
}
diff --git a/modules/ppcp-save-payment-methods/src/WooCommercePaymentTokens.php b/modules/ppcp-save-payment-methods/src/WooCommercePaymentTokens.php
index 520099994..3e5f99b04 100644
--- a/modules/ppcp-save-payment-methods/src/WooCommercePaymentTokens.php
+++ b/modules/ppcp-save-payment-methods/src/WooCommercePaymentTokens.php
@@ -66,16 +66,18 @@ class WooCommercePaymentTokens {
/**
* Creates a WC Payment Token for PayPal payment.
*
- * @param int $customer_id The WC customer ID.
- * @param string $token The PayPal payment token.
- * @param string $email The PayPal customer email.
+ * @param int $customer_id The WC customer ID.
+ * @param string $token The PayPal payment token.
+ * @param string $email The PayPal customer email.
+ * @param string $payment_source The funding source.
*
* @return int
*/
public function create_payment_token_paypal(
int $customer_id,
string $token,
- string $email
+ string $email,
+ string $payment_source = ''
): int {
$wc_tokens = WC_Payment_Tokens::get_customer_tokens( $customer_id, PayPalGateway::ID );
@@ -94,6 +96,10 @@ class WooCommercePaymentTokens {
$payment_token_paypal->set_email( $email );
}
+ if ( $payment_source ) {
+ $payment_token_paypal->set_payment_source( $payment_source );
+ }
+
try {
$payment_token_paypal->save();
} catch ( Exception $exception ) {
diff --git a/modules/ppcp-vaulting/src/PaymentTokenPayPal.php b/modules/ppcp-vaulting/src/PaymentTokenPayPal.php
index 1a5858118..3b8eac849 100644
--- a/modules/ppcp-vaulting/src/PaymentTokenPayPal.php
+++ b/modules/ppcp-vaulting/src/PaymentTokenPayPal.php
@@ -28,7 +28,8 @@ class PaymentTokenPayPal extends WC_Payment_Token {
* @var string[]
*/
protected $extra_data = array(
- 'email' => '',
+ 'email' => '',
+ 'payment_source' => '',
);
/**
@@ -48,4 +49,22 @@ class PaymentTokenPayPal extends WC_Payment_Token {
public function set_email( $email ) {
$this->add_meta_data( 'email', $email, true );
}
+
+ /**
+ * Get the payment source.
+ *
+ * @return string The payment source.
+ */
+ public function get_payment_source() {
+ return $this->get_meta( 'payment_source' );
+ }
+
+ /**
+ * Set the payment source.
+ *
+ * @param string $payment_source The payment source.
+ */
+ public function set_payment_source( string $payment_source ) {
+ $this->add_meta_data( 'payment_source', $payment_source, true );
+ }
}
diff --git a/modules/ppcp-vaulting/src/VaultingModule.php b/modules/ppcp-vaulting/src/VaultingModule.php
index bba8e5464..1860a889d 100644
--- a/modules/ppcp-vaulting/src/VaultingModule.php
+++ b/modules/ppcp-vaulting/src/VaultingModule.php
@@ -86,6 +86,37 @@ class VaultingModule implements ModuleInterface {
}
);
+ add_filter(
+ 'woocommerce_get_customer_payment_tokens',
+ /**
+ * Filter available payment tokens depending on context.
+ *
+ * @psalm-suppress MissingClosureParamType
+ * @psalm-suppress MissingClosureReturnType
+ */
+ function( $tokens, $customer_id, $gateway_id ) {
+ if ( ! is_array( $tokens ) ) {
+ return $tokens;
+ }
+
+ // Exclude ApplePay tokens from payment pages.
+ if ( is_checkout() || is_cart() || is_product() ) {
+ foreach ( $tokens as $index => $token ) {
+ if (
+ $token instanceof PaymentTokenPayPal
+ && $token->get_payment_source() === 'apple_pay'
+ ) {
+ unset( $tokens[ $index ] );
+ }
+ }
+ }
+
+ return $tokens;
+ },
+ 10,
+ 3
+ );
+
add_filter(
'woocommerce_payment_methods_list_item',
/**
@@ -100,8 +131,22 @@ class VaultingModule implements ModuleInterface {
if ( strtolower( $payment_token->get_type() ) === 'paypal' ) {
assert( $payment_token instanceof PaymentTokenPayPal );
- $item['method']['brand'] = $payment_token->get_email();
+ $email = $payment_token->get_email();
+ $payment_source = $payment_token->get_payment_source();
+ $brand_parts = array();
+
+ if ( $payment_source !== 'paypal' ) {
+ $brand_parts[] = ucwords( $payment_source );
+ }
+
+ if ( $email ) {
+ $brand_parts[] = $email;
+ } else {
+ $brand_parts[] = '#' . ( (string) $payment_token->get_id() );
+ }
+
+ $item['method']['brand'] = implode( ' / ', array_filter( $brand_parts ) );
return $item;
}