mirror of
https://github.com/woocommerce/woocommerce-paypal-payments.git
synced 2025-09-06 13:44:42 +08:00
Merge pull request #2152 from woocommerce/PCP-2768-zero-sum-subscriptions-cause-cannot-be-zero-or-negative-when-using-vault-v-3
Zero sum subscriptions cause CANNOT_BE_ZERO_OR_NEGATIVE when using Vault v3 (2768)
This commit is contained in:
commit
ffe3a0b958
17 changed files with 422 additions and 46 deletions
|
@ -103,7 +103,10 @@ return array(
|
|||
$api_shop_country,
|
||||
$container->get( 'api.endpoint.order' ),
|
||||
$container->get( 'api.factory.paypal-checkout-url' ),
|
||||
$container->get( 'wcgateway.place-order-button-text' )
|
||||
$container->get( 'wcgateway.place-order-button-text' ),
|
||||
$container->get( 'api.endpoint.payment-tokens' ),
|
||||
$container->get( 'vaulting.vault-v3-enabled' ),
|
||||
$container->get( 'vaulting.wc-payment-tokens' )
|
||||
);
|
||||
},
|
||||
'wcgateway.credit-card-gateway' => static function ( ContainerInterface $container ): CreditCardGateway {
|
||||
|
|
|
@ -33,6 +33,7 @@ use WooCommerce\PayPalCommerce\WcGateway\Processor\PaymentsStatusHandlingTrait;
|
|||
use WooCommerce\PayPalCommerce\WcGateway\Processor\RefundProcessor;
|
||||
use WooCommerce\PayPalCommerce\WcGateway\Processor\TransactionIdHandlingTrait;
|
||||
use WooCommerce\PayPalCommerce\WcGateway\Settings\SettingsRenderer;
|
||||
use WooCommerce\PayPalCommerce\WcSubscriptions\FreeTrialHandlerTrait;
|
||||
use WooCommerce\PayPalCommerce\WcSubscriptions\Helper\SubscriptionHelper;
|
||||
|
||||
/**
|
||||
|
@ -40,7 +41,7 @@ use WooCommerce\PayPalCommerce\WcSubscriptions\Helper\SubscriptionHelper;
|
|||
*/
|
||||
class CreditCardGateway extends \WC_Payment_Gateway_CC {
|
||||
|
||||
use ProcessPaymentTrait, GatewaySettingsRendererTrait, TransactionIdHandlingTrait, PaymentsStatusHandlingTrait;
|
||||
use ProcessPaymentTrait, GatewaySettingsRendererTrait, TransactionIdHandlingTrait, PaymentsStatusHandlingTrait, FreeTrialHandlerTrait;
|
||||
|
||||
const ID = 'ppcp-credit-card-gateway';
|
||||
|
||||
|
@ -454,6 +455,17 @@ class CreditCardGateway extends \WC_Payment_Gateway_CC {
|
|||
|
||||
// phpcs:ignore WordPress.Security.NonceVerification.Missing
|
||||
$card_payment_token_id = wc_clean( wp_unslash( $_POST['wc-ppcp-credit-card-gateway-payment-token'] ?? '' ) );
|
||||
|
||||
if ( $this->is_free_trial_order( $wc_order ) && $card_payment_token_id ) {
|
||||
$customer_tokens = $this->wc_payment_tokens->customer_tokens( get_current_user_id() );
|
||||
foreach ( $customer_tokens as $token ) {
|
||||
if ( $token['payment_source']->name() === 'card' ) {
|
||||
$wc_order->payment_complete();
|
||||
return $this->handle_payment_success( $wc_order );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( $card_payment_token_id ) {
|
||||
$customer_tokens = $this->wc_payment_tokens->customer_tokens( get_current_user_id() );
|
||||
|
||||
|
|
|
@ -14,12 +14,14 @@ use Psr\Log\LoggerInterface;
|
|||
use WC_Order;
|
||||
use WC_Payment_Tokens;
|
||||
use WooCommerce\PayPalCommerce\ApiClient\Endpoint\OrderEndpoint;
|
||||
use WooCommerce\PayPalCommerce\ApiClient\Endpoint\PaymentTokensEndpoint;
|
||||
use WooCommerce\PayPalCommerce\ApiClient\Entity\OrderStatus;
|
||||
use WooCommerce\PayPalCommerce\ApiClient\Entity\PaymentToken;
|
||||
use WooCommerce\PayPalCommerce\ApiClient\Exception\PayPalApiException;
|
||||
use WooCommerce\PayPalCommerce\Onboarding\Environment;
|
||||
use WooCommerce\PayPalCommerce\Onboarding\State;
|
||||
use WooCommerce\PayPalCommerce\Session\SessionHandler;
|
||||
use WooCommerce\PayPalCommerce\Vaulting\WooCommercePaymentTokens;
|
||||
use WooCommerce\PayPalCommerce\WcSubscriptions\FreeTrialHandlerTrait;
|
||||
use WooCommerce\PayPalCommerce\WcSubscriptions\Helper\SubscriptionHelper;
|
||||
use WooCommerce\PayPalCommerce\Vaulting\PaymentTokenRepository;
|
||||
|
@ -179,26 +181,50 @@ class PayPalGateway extends \WC_Payment_Gateway {
|
|||
*/
|
||||
private $paypal_checkout_url_factory;
|
||||
|
||||
/**
|
||||
* Payment tokens endpoint.
|
||||
*
|
||||
* @var PaymentTokensEndpoint
|
||||
*/
|
||||
private $payment_tokens_endpoint;
|
||||
|
||||
/**
|
||||
* Whether Vault v3 module is enabled.
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
private $vault_v3_enabled;
|
||||
|
||||
/**
|
||||
* WooCommerce payment tokens.
|
||||
*
|
||||
* @var WooCommercePaymentTokens
|
||||
*/
|
||||
private $wc_payment_tokens;
|
||||
|
||||
/**
|
||||
* PayPalGateway constructor.
|
||||
*
|
||||
* @param SettingsRenderer $settings_renderer The Settings Renderer.
|
||||
* @param FundingSourceRenderer $funding_source_renderer The funding source renderer.
|
||||
* @param OrderProcessor $order_processor The Order Processor.
|
||||
* @param ContainerInterface $config The settings.
|
||||
* @param SessionHandler $session_handler The Session Handler.
|
||||
* @param RefundProcessor $refund_processor The Refund Processor.
|
||||
* @param State $state The state.
|
||||
* @param TransactionUrlProvider $transaction_url_provider Service providing transaction view URL based on order.
|
||||
* @param SubscriptionHelper $subscription_helper The subscription helper.
|
||||
* @param string $page_id ID of the current PPCP gateway settings page, or empty if it is not such page.
|
||||
* @param Environment $environment The environment.
|
||||
* @param PaymentTokenRepository $payment_token_repository The payment token repository.
|
||||
* @param LoggerInterface $logger The logger.
|
||||
* @param string $api_shop_country The api shop country.
|
||||
* @param OrderEndpoint $order_endpoint The order endpoint.
|
||||
* @param callable(string):string $paypal_checkout_url_factory The function return the PayPal checkout URL for the given order ID.
|
||||
* @param string $place_order_button_text The text for the standard "Place order" button.
|
||||
* @param SettingsRenderer $settings_renderer The Settings Renderer.
|
||||
* @param FundingSourceRenderer $funding_source_renderer The funding source renderer.
|
||||
* @param OrderProcessor $order_processor The Order Processor.
|
||||
* @param ContainerInterface $config The settings.
|
||||
* @param SessionHandler $session_handler The Session Handler.
|
||||
* @param RefundProcessor $refund_processor The Refund Processor.
|
||||
* @param State $state The state.
|
||||
* @param TransactionUrlProvider $transaction_url_provider Service providing transaction view URL based on order.
|
||||
* @param SubscriptionHelper $subscription_helper The subscription helper.
|
||||
* @param string $page_id ID of the current PPCP gateway settings page, or empty if it is not such page.
|
||||
* @param Environment $environment The environment.
|
||||
* @param PaymentTokenRepository $payment_token_repository The payment token repository.
|
||||
* @param LoggerInterface $logger The logger.
|
||||
* @param string $api_shop_country The api shop country.
|
||||
* @param OrderEndpoint $order_endpoint The order endpoint.
|
||||
* @param callable(string):string $paypal_checkout_url_factory The function return the PayPal checkout URL for the given order ID.
|
||||
* @param string $place_order_button_text The text for the standard "Place order" button.
|
||||
* @param PaymentTokensEndpoint $payment_tokens_endpoint Payment tokens endpoint.
|
||||
* @param bool $vault_v3_enabled Whether Vault v3 module is enabled.
|
||||
* @param WooCommercePaymentTokens $wc_payment_tokens WooCommerce payment tokens.
|
||||
*/
|
||||
public function __construct(
|
||||
SettingsRenderer $settings_renderer,
|
||||
|
@ -217,7 +243,10 @@ class PayPalGateway extends \WC_Payment_Gateway {
|
|||
string $api_shop_country,
|
||||
OrderEndpoint $order_endpoint,
|
||||
callable $paypal_checkout_url_factory,
|
||||
string $place_order_button_text
|
||||
string $place_order_button_text,
|
||||
PaymentTokensEndpoint $payment_tokens_endpoint,
|
||||
bool $vault_v3_enabled,
|
||||
WooCommercePaymentTokens $wc_payment_tokens
|
||||
) {
|
||||
$this->id = self::ID;
|
||||
$this->settings_renderer = $settings_renderer;
|
||||
|
@ -237,6 +266,10 @@ class PayPalGateway extends \WC_Payment_Gateway {
|
|||
$this->api_shop_country = $api_shop_country;
|
||||
$this->paypal_checkout_url_factory = $paypal_checkout_url_factory;
|
||||
$this->order_button_text = $place_order_button_text;
|
||||
$this->order_endpoint = $order_endpoint;
|
||||
$this->payment_tokens_endpoint = $payment_tokens_endpoint;
|
||||
$this->vault_v3_enabled = $vault_v3_enabled;
|
||||
$this->wc_payment_tokens = $wc_payment_tokens;
|
||||
|
||||
if ( $this->onboarded ) {
|
||||
$this->supports = array( 'refunds', 'tokenization' );
|
||||
|
@ -299,8 +332,6 @@ class PayPalGateway extends \WC_Payment_Gateway {
|
|||
'process_admin_options',
|
||||
)
|
||||
);
|
||||
|
||||
$this->order_endpoint = $order_endpoint;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -500,7 +531,49 @@ class PayPalGateway extends \WC_Payment_Gateway {
|
|||
$wc_order->save();
|
||||
}
|
||||
|
||||
if ( 'card' !== $funding_source && $this->is_free_trial_order( $wc_order ) && ! $this->subscription_helper->paypal_subscription_id() ) {
|
||||
if (
|
||||
'card' !== $funding_source
|
||||
&& $this->is_free_trial_order( $wc_order )
|
||||
&& ! $this->subscription_helper->paypal_subscription_id()
|
||||
) {
|
||||
$ppcp_guest_payment_for_free_trial = WC()->session->get( 'ppcp_guest_payment_for_free_trial' ) ?? null;
|
||||
if ( $this->vault_v3_enabled && $ppcp_guest_payment_for_free_trial ) {
|
||||
$customer_id = $ppcp_guest_payment_for_free_trial->customer->id ?? '';
|
||||
if ( $customer_id ) {
|
||||
update_user_meta( $wc_order->get_customer_id(), '_ppcp_target_customer_id', $customer_id );
|
||||
}
|
||||
|
||||
if ( isset( $ppcp_guest_payment_for_free_trial->payment_source->paypal ) ) {
|
||||
$email = '';
|
||||
if ( isset( $ppcp_guest_payment_for_free_trial->payment_source->paypal->email_address ) ) {
|
||||
$email = $ppcp_guest_payment_for_free_trial->payment_source->paypal->email_address;
|
||||
}
|
||||
|
||||
$this->wc_payment_tokens->create_payment_token_paypal(
|
||||
$wc_order->get_customer_id(),
|
||||
$ppcp_guest_payment_for_free_trial->id,
|
||||
$email
|
||||
);
|
||||
}
|
||||
|
||||
WC()->session->set( 'ppcp_guest_payment_for_free_trial', null );
|
||||
|
||||
$wc_order->payment_complete();
|
||||
return $this->handle_payment_success( $wc_order );
|
||||
}
|
||||
|
||||
$customer_id = get_user_meta( $wc_order->get_customer_id(), '_ppcp_target_customer_id', true );
|
||||
if ( $customer_id ) {
|
||||
$customer_tokens = $this->payment_tokens_endpoint->payment_tokens_for_customer( $customer_id );
|
||||
foreach ( $customer_tokens as $token ) {
|
||||
$payment_source_name = $token['payment_source']->name() ?? '';
|
||||
if ( $payment_source_name === 'paypal' || $payment_source_name === 'venmo' ) {
|
||||
$wc_order->payment_complete();
|
||||
return $this->handle_payment_success( $wc_order );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$user_id = (int) $wc_order->get_customer_id();
|
||||
$tokens = $this->payment_token_repository->all_for_user_id( $user_id );
|
||||
if ( ! array_filter(
|
||||
|
@ -513,7 +586,6 @@ class PayPalGateway extends \WC_Payment_Gateway {
|
|||
}
|
||||
|
||||
$wc_order->payment_complete();
|
||||
|
||||
return $this->handle_payment_success( $wc_order );
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue