Skip to content

Commit

Permalink
Merge pull request #1920 from woocommerce/vault-v3-wc-subscriptions
Browse files Browse the repository at this point in the history
Vault v3 WC Subscriptions integration (2481)
  • Loading branch information
Dinamiko authored Jan 5, 2024
2 parents 1e1cae5 + 004fb68 commit 843bee6
Show file tree
Hide file tree
Showing 4 changed files with 121 additions and 262 deletions.
33 changes: 10 additions & 23 deletions modules/ppcp-save-payment-methods/src/SavePaymentMethodsModule.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@

use Psr\Log\LoggerInterface;
use WC_Order;
use WC_Payment_Tokens;
use WooCommerce\PayPalCommerce\ApiClient\Authentication\UserIdToken;
use WooCommerce\PayPalCommerce\ApiClient\Endpoint\PaymentTokensEndpoint;
use WooCommerce\PayPalCommerce\ApiClient\Entity\Order;
Expand Down Expand Up @@ -79,27 +78,6 @@ function( array $localized_script_data ) use ( $c ) {
add_filter(
'ppcp_create_order_request_body_data',
function( array $data, string $payment_method, array $request_data ): array {
// phpcs:ignore WordPress.Security.NonceVerification.Missing
$wc_order_action = wc_clean( wp_unslash( $_POST['wc_order_action'] ?? '' ) );
if ( $wc_order_action === 'wcs_process_renewal' ) {
// phpcs:ignore WordPress.Security.NonceVerification.Missing
$subscription_id = wc_clean( wp_unslash( $_POST['post_ID'] ?? '' ) );
$subscription = wcs_get_subscription( (int) $subscription_id );
if ( $subscription ) {
$customer_id = $subscription->get_customer_id();
$wc_tokens = WC_Payment_Tokens::get_customer_tokens( $customer_id, PayPalGateway::ID );
foreach ( $wc_tokens as $token ) {
$data['payment_source'] = array(
'paypal' => array(
'vault_id' => $token->get_token(),
),
);

return $data;
}
}
}

if ( $payment_method === CreditCardGateway::ID ) {
$save_payment_method = $request_data['save_payment_method'] ?? false;
if ( $save_payment_method ) {
Expand All @@ -114,6 +92,10 @@ function( array $data, string $payment_method, array $request_data ): array {
);

$target_customer_id = get_user_meta( get_current_user_id(), '_ppcp_target_customer_id', true );
if ( ! $target_customer_id ) {
$target_customer_id = get_user_meta( get_current_user_id(), 'ppcp_customer_id', true );
}

if ( $target_customer_id ) {
$data['payment_source']['card']['attributes']['customer'] = array(
'id' => $target_customer_id,
Expand Down Expand Up @@ -189,7 +171,6 @@ function( WC_Order $wc_order, Order $order ) use ( $c ) {
);

add_filter( 'woocommerce_paypal_payments_disable_add_payment_method', '__return_false' );
add_filter( 'woocommerce_paypal_payments_subscription_renewal_return_before_create_order_without_token', '__return_false' );
add_filter( 'woocommerce_paypal_payments_should_render_card_custom_fields', '__return_false' );

add_action(
Expand All @@ -215,6 +196,9 @@ function() use ( $c ) {
$target_customer_id = '';
if ( is_user_logged_in() ) {
$target_customer_id = get_user_meta( get_current_user_id(), '_ppcp_target_customer_id', true );
if ( ! $target_customer_id ) {
$target_customer_id = get_user_meta( get_current_user_id(), 'ppcp_customer_id', true );
}
}

$id_token = $api->id_token( $target_customer_id );
Expand Down Expand Up @@ -354,6 +338,9 @@ private function add_id_token_to_script_data(
$target_customer_id = '';
if ( is_user_logged_in() ) {
$target_customer_id = get_user_meta( get_current_user_id(), '_ppcp_target_customer_id', true );
if ( ! $target_customer_id ) {
$target_customer_id = get_user_meta( get_current_user_id(), 'ppcp_customer_id', true );
}
}

$id_token = $api->id_token( $target_customer_id );
Expand Down
175 changes: 108 additions & 67 deletions modules/ppcp-wc-subscriptions/src/RenewalHandler.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,9 @@

namespace WooCommerce\PayPalCommerce\WcSubscriptions;

use WC_Order;
use WC_Subscription;
use WC_Payment_Tokens;
use WooCommerce\PayPalCommerce\ApiClient\Endpoint\OrderEndpoint;
use WooCommerce\PayPalCommerce\ApiClient\Entity\ApplicationContext;
use WooCommerce\PayPalCommerce\ApiClient\Entity\Order;
Expand All @@ -24,6 +26,7 @@
use Psr\Log\LoggerInterface;
use WooCommerce\PayPalCommerce\WcGateway\Exception\NotFoundException;
use WooCommerce\PayPalCommerce\WcGateway\Gateway\CreditCardGateway;
use WooCommerce\PayPalCommerce\WcGateway\Gateway\PayPalGateway;
use WooCommerce\PayPalCommerce\WcGateway\Processor\AuthorizedPaymentsProcessor;
use WooCommerce\PayPalCommerce\WcGateway\Processor\OrderMetaTrait;
use WooCommerce\PayPalCommerce\WcGateway\Processor\PaymentsStatusHandlingTrait;
Expand Down Expand Up @@ -194,32 +197,60 @@ private function process_order( \WC_Order $wc_order ): void {
'renewal'
);

$token = $this->get_token_for_customer( $customer, $wc_order );
if ( $token ) {
if ( $wc_order->get_payment_method() === CreditCardGateway::ID ) {
$stored_credentials = array(
'payment_initiator' => 'MERCHANT',
'payment_type' => 'RECURRING',
'usage' => 'SUBSEQUENT',
);

$subscriptions = wcs_get_subscriptions_for_renewal_order( $wc_order );
foreach ( $subscriptions as $post_id => $subscription ) {
$previous_transaction_reference = $subscription->get_meta( 'ppcp_previous_transaction_reference' );
if ( $previous_transaction_reference ) {
$stored_credentials['previous_transaction_reference'] = $previous_transaction_reference;
break;
}
}

// Vault v3.
$payment_source = null;
if ( $wc_order->get_payment_method() === PayPalGateway::ID ) {
$wc_tokens = WC_Payment_Tokens::get_customer_tokens( $wc_order->get_customer_id(), PayPalGateway::ID );
foreach ( $wc_tokens as $token ) {
$payment_source = new PaymentSource(
'card',
'paypal',
(object) array(
'vault_id' => $token->id(),
'stored_credential' => $stored_credentials,
'vault_id' => $token->get_token(),
)
);

break;
}
}

if ( $wc_order->get_payment_method() === CreditCardGateway::ID ) {
$wc_tokens = WC_Payment_Tokens::get_customer_tokens( $wc_order->get_customer_id(), CreditCardGateway::ID );
foreach ( $wc_tokens as $token ) {
$payment_source = $this->card_payment_source( $token->get_token(), $wc_order );
}
}

if ( $payment_source ) {
$order = $this->order_endpoint->create(
array( $purchase_unit ),
$shipping_preference,
$payer,
null,
'',
ApplicationContext::USER_ACTION_CONTINUE,
'',
array(),
$payment_source
);

$this->handle_paypal_order( $wc_order, $order );

$this->logger->info(
sprintf(
'Renewal for order %d is completed.',
$wc_order->get_id()
)
);

return;
}

// Vault v2.
$token = $this->get_token_for_customer( $customer, $wc_order );
if ( $token ) {
if ( $wc_order->get_payment_method() === CreditCardGateway::ID ) {
$payment_source = $this->card_payment_source( $token->id(), $wc_order );

$order = $this->order_endpoint->create(
array( $purchase_unit ),
$shipping_preference,
Expand All @@ -244,43 +275,24 @@ private function process_order( \WC_Order $wc_order ): void {
return;
}

$order = $this->order_endpoint->create(
array( $purchase_unit ),
$shipping_preference,
$payer,
$token
);

$this->handle_paypal_order( $wc_order, $order );

$this->logger->info(
sprintf(
'Renewal for order %d is completed.',
$wc_order->get_id()
)
);
if ( $wc_order->get_payment_method() === PayPalGateway::ID ) {
$order = $this->order_endpoint->create(
array( $purchase_unit ),
$shipping_preference,
$payer,
$token
);

return;
}
$this->handle_paypal_order( $wc_order, $order );

if ( apply_filters( 'woocommerce_paypal_payments_subscription_renewal_return_before_create_order_without_token', true ) ) {
return;
$this->logger->info(
sprintf(
'Renewal for order %d is completed.',
$wc_order->get_id()
)
);
}
}

$order = $this->order_endpoint->create(
array( $purchase_unit ),
$shipping_preference,
$payer
);

$this->handle_paypal_order( $wc_order, $order );

$this->logger->info(
sprintf(
'Renewal for order %d is completed.',
$wc_order->get_id()
)
);
}

/**
Expand All @@ -302,18 +314,7 @@ private function get_token_for_customer( \WC_Customer $customer, \WC_Order $wc_o

$tokens = $this->repository->all_for_user_id( (int) $customer->get_id() );
if ( ! $tokens ) {

$error_message = sprintf(
'Payment failed. No payment tokens found for customer %d.',
$customer->get_id()
);

$wc_order->update_status(
'failed',
$error_message
);

$this->logger->error( $error_message );
return false;
}

$subscription = function_exists( 'wcs_get_subscription' ) ? wcs_get_subscription( $wc_order->get_meta( '_subscription_renewal' ) ) : null;
Expand Down Expand Up @@ -399,4 +400,44 @@ private function handle_paypal_order( \WC_Order $wc_order, Order $order ): void
$this->authorized_payments_processor->capture_authorized_payment( $wc_order );
}
}

/**
* Returns a Card payment source.
*
* @param string $token Vault token id.
* @param WC_Order $wc_order WC order.
* @return PaymentSource
* @throws NotFoundException If setting is not found.
*/
private function card_payment_source( string $token, WC_Order $wc_order ): PaymentSource {
$properties = array(
'vault_id' => $token,
);

if (
$this->settings->has( '3d_secure_contingency' )
&& ( $this->settings->get( '3d_secure_contingency' ) === 'SCA_ALWAYS' || $this->settings->get( '3d_secure_contingency' ) === 'SCA_WHEN_REQUIRED' )
) {
$stored_credentials = array(
'payment_initiator' => 'MERCHANT',
'payment_type' => 'RECURRING',
'usage' => 'SUBSEQUENT',
);

$subscriptions = wcs_get_subscriptions_for_renewal_order( $wc_order );
foreach ( $subscriptions as $post_id => $subscription ) {
$previous_transaction_reference = $subscription->get_meta( 'ppcp_previous_transaction_reference' );
if ( $previous_transaction_reference ) {
$stored_credentials['previous_transaction_reference'] = $previous_transaction_reference;
$properties['stored_credentials'] = $stored_credentials;
break;
}
}
}

return new PaymentSource(
'card',
(object) $properties
);
}
}
4 changes: 3 additions & 1 deletion modules/ppcp-wc-subscriptions/src/WcSubscriptionsModule.php
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,9 @@ function ( $subscription ) use ( $c ) {
$payment_token_repository = $c->get( 'vaulting.repository.payment-token' );
$logger = $c->get( 'woocommerce.logger.woocommerce' );

$this->add_payment_token_id( $subscription, $payment_token_repository, $logger );
if ( ! $c->has( 'save-payment-methods.eligible' ) || ! $c->get( 'save-payment-methods.eligible' ) ) {
$this->add_payment_token_id( $subscription, $payment_token_repository, $logger );
}

if ( count( $subscription->get_related_orders() ) === 1 ) {
$parent_order = $subscription->get_parent();
Expand Down
Loading

0 comments on commit 843bee6

Please sign in to comment.