Use stored token id for subscription renewals

This commit is contained in:
Emili Castells Guasch 2023-10-31 14:22:17 +01:00
parent 5ff6c7be71
commit 4dbc6630b0
3 changed files with 86 additions and 31 deletions

View file

@ -178,7 +178,7 @@ class OrderEndpoint {
* @param string $shipping_preference One of ApplicationContext::SHIPPING_PREFERENCE_ values. * @param string $shipping_preference One of ApplicationContext::SHIPPING_PREFERENCE_ values.
* @param Payer|null $payer The payer off the order. * @param Payer|null $payer The payer off the order.
* @param PaymentToken|null $payment_token The payment token. * @param PaymentToken|null $payment_token The payment token.
* @param string $paypal_request_id The paypal request id. * @param string $paypal_request_id The PayPal request id.
* @param string $user_action The user action. * @param string $user_action The user action.
* *
* @return Order * @return Order

View file

@ -11,6 +11,7 @@ namespace WooCommerce\PayPalCommerce\SavePaymentMethods;
use Psr\Log\LoggerInterface; use Psr\Log\LoggerInterface;
use WC_Order; use WC_Order;
use WC_Payment_Tokens;
use WooCommerce\PayPalCommerce\ApiClient\Authentication\UserIdToken; use WooCommerce\PayPalCommerce\ApiClient\Authentication\UserIdToken;
use WooCommerce\PayPalCommerce\ApiClient\Entity\Order; use WooCommerce\PayPalCommerce\ApiClient\Entity\Order;
use WooCommerce\PayPalCommerce\ApiClient\Entity\PaymentSource; use WooCommerce\PayPalCommerce\ApiClient\Entity\PaymentSource;
@ -89,6 +90,27 @@ class SavePaymentMethodsModule implements ModuleInterface {
add_filter( add_filter(
'ppcp_create_order_request_body_data', 'ppcp_create_order_request_body_data',
function( array $data ): array { function( array $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;
}
}
}
$data['payment_source'] = array( $data['payment_source'] = array(
'paypal' => array( 'paypal' => array(
'attributes' => array( 'attributes' => array(
@ -139,6 +161,8 @@ class SavePaymentMethodsModule implements ModuleInterface {
add_filter( 'woocommerce_paypal_payments_disable_add_payment_method', '__return_false' ); 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_action( add_action(
'wp_enqueue_scripts', 'wp_enqueue_scripts',
function() use ( $c ) { function() use ( $c ) {

View file

@ -181,13 +181,8 @@ class RenewalHandler {
* @throws \Exception If customer cannot be read/found. * @throws \Exception If customer cannot be read/found.
*/ */
private function process_order( \WC_Order $wc_order ): void { private function process_order( \WC_Order $wc_order ): void {
$user_id = (int) $wc_order->get_customer_id(); $user_id = (int) $wc_order->get_customer_id();
$customer = new \WC_Customer( $user_id ); $customer = new \WC_Customer( $user_id );
$token = $this->get_token_for_customer( $customer, $wc_order );
if ( ! $token ) {
return;
}
$purchase_unit = $this->purchase_unit_factory->from_wc_order( $wc_order ); $purchase_unit = $this->purchase_unit_factory->from_wc_order( $wc_order );
$payer = $this->payer_factory->from_customer( $customer ); $payer = $this->payer_factory->from_customer( $customer );
@ -196,6 +191,8 @@ class RenewalHandler {
'renewal' 'renewal'
); );
$token = $this->get_token_for_customer( $customer, $wc_order );
if ( $token ) {
$order = $this->order_endpoint->create( $order = $this->order_endpoint->create(
array( $purchase_unit ), array( $purchase_unit ),
$shipping_preference, $shipping_preference,
@ -203,29 +200,29 @@ class RenewalHandler {
$token $token
); );
$this->add_paypal_meta( $wc_order, $order, $this->environment ); $this->handle_paypal_order( $wc_order, $order );
if ( $order->intent() === 'AUTHORIZE' ) { $this->logger->info(
$order = $this->order_endpoint->authorize( $order ); sprintf(
$wc_order->update_meta_data( AuthorizedPaymentsProcessor::CAPTURED_META_KEY, 'false' ); 'Renewal for order %d is completed.',
$wc_order->get_id()
)
);
return;
} }
$transaction_id = $this->get_paypal_order_transaction_id( $order ); if ( apply_filters( 'woocommerce_paypal_payments_subscription_renewal_return_before_create_order_without_token', true ) ) {
if ( $transaction_id ) { return;
$this->update_transaction_id( $transaction_id, $wc_order );
$subscriptions = wcs_get_subscriptions_for_order( $wc_order->get_id(), array( 'order_type' => 'any' ) );
foreach ( $subscriptions as $id => $subscription ) {
$subscription->update_meta_data( 'ppcp_previous_transaction_reference', $transaction_id );
$subscription->save();
}
} }
$this->handle_new_order_status( $order, $wc_order ); $order = $this->order_endpoint->create(
array( $purchase_unit ),
$shipping_preference,
$payer
);
if ( $this->capture_authorized_downloads( $order ) ) { $this->handle_paypal_order( $wc_order, $order );
$this->authorized_payments_processor->capture_authorized_payment( $wc_order );
}
$this->logger->info( $this->logger->info(
sprintf( sprintf(
@ -317,4 +314,38 @@ class RenewalHandler {
} }
return true; return true;
} }
/**
* Handles PayPal order creation and updates WC order accordingly.
*
* @param \WC_Order $wc_order WC order.
* @param Order $order PayPal order.
* @return void
* @throws NotFoundException When something goes wrong while handling the order.
*/
private function handle_paypal_order( \WC_Order $wc_order, Order $order ): void {
$this->add_paypal_meta( $wc_order, $order, $this->environment );
if ( $order->intent() === 'AUTHORIZE' ) {
$order = $this->order_endpoint->authorize( $order );
$wc_order->update_meta_data( AuthorizedPaymentsProcessor::CAPTURED_META_KEY, 'false' );
}
$transaction_id = $this->get_paypal_order_transaction_id( $order );
if ( $transaction_id ) {
$this->update_transaction_id( $transaction_id, $wc_order );
$subscriptions = wcs_get_subscriptions_for_order( $wc_order->get_id(), array( 'order_type' => 'any' ) );
foreach ( $subscriptions as $id => $subscription ) {
$subscription->update_meta_data( 'ppcp_previous_transaction_reference', $transaction_id );
$subscription->save();
}
}
$this->handle_new_order_status( $order, $wc_order );
if ( $this->capture_authorized_downloads( $order ) ) {
$this->authorized_payments_processor->capture_authorized_payment( $wc_order );
}
}
} }