mirror of
https://github.com/woocommerce/woocommerce-paypal-payments.git
synced 2025-09-04 08:47:23 +08:00
Merge branch 'trunk' into PCP-1968-subscriptions-api-renewals
This commit is contained in:
commit
250172a2ad
25 changed files with 301 additions and 68 deletions
|
@ -43,6 +43,20 @@ class ApiModule implements ModuleInterface {
|
|||
WC()->session->set( 'ppcp_fees', $fees );
|
||||
}
|
||||
);
|
||||
add_filter(
|
||||
'ppcp_create_order_request_body_data',
|
||||
function( array $data ) use ( $c ) {
|
||||
|
||||
foreach ( $data['purchase_units'] as $purchase_unit_index => $purchase_unit ) {
|
||||
foreach ( $purchase_unit['items'] as $item_index => $item ) {
|
||||
$data['purchase_units'][ $purchase_unit_index ]['items'][ $item_index ]['name'] =
|
||||
apply_filters( 'woocommerce_paypal_payments_cart_line_item_name', $item['name'], $item['cart_item_key'] );
|
||||
}
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
);
|
||||
add_action(
|
||||
'woocommerce_paypal_payments_paypal_order_created',
|
||||
function ( Order $order ) use ( $c ) {
|
||||
|
|
|
@ -121,7 +121,7 @@ class BillingAgreementsEndpoint {
|
|||
*/
|
||||
public function reference_transaction_enabled(): bool {
|
||||
try {
|
||||
if ( get_transient( 'ppcp_reference_transaction_enabled' ) === true ) {
|
||||
if ( wc_string_to_bool( get_transient( 'ppcp_reference_transaction_enabled' ) ) === true ) {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -135,7 +135,7 @@ class BillingAgreementsEndpoint {
|
|||
);
|
||||
} finally {
|
||||
$this->is_request_logging_enabled = true;
|
||||
set_transient( 'ppcp_reference_transaction_enabled', true, 3 * MONTH_IN_SECONDS );
|
||||
set_transient( 'ppcp_reference_transaction_enabled', true, MONTH_IN_SECONDS );
|
||||
}
|
||||
|
||||
return true;
|
||||
|
|
|
@ -202,7 +202,15 @@ class WebhookEndpoint {
|
|||
|
||||
$status_code = (int) wp_remote_retrieve_response_code( $response );
|
||||
if ( 204 !== $status_code ) {
|
||||
$json = json_decode( $response['body'] ) ?? null;
|
||||
$json = null;
|
||||
/**
|
||||
* Use in array as consistency check.
|
||||
*
|
||||
* @psalm-suppress RedundantConditionGivenDocblockType
|
||||
*/
|
||||
if ( is_array( $response ) ) {
|
||||
$json = json_decode( $response['body'] );
|
||||
}
|
||||
throw new PayPalApiException(
|
||||
$json,
|
||||
$status_code
|
||||
|
|
|
@ -249,9 +249,12 @@ class Item {
|
|||
'sku' => $this->sku(),
|
||||
'category' => $this->category(),
|
||||
'url' => $this->url(),
|
||||
'image_url' => $this->image_url(),
|
||||
);
|
||||
|
||||
if ( $this->image_url() ) {
|
||||
$item['image_url'] = $this->image_url();
|
||||
}
|
||||
|
||||
if ( $this->tax() ) {
|
||||
$item['tax'] = $this->tax()->to_array();
|
||||
}
|
||||
|
|
|
@ -98,7 +98,7 @@ class PPECHelper {
|
|||
set_transient(
|
||||
'ppcp_has_ppec_subscriptions',
|
||||
! empty( $result ) ? 'true' : 'false',
|
||||
3 * MONTH_IN_SECONDS
|
||||
MONTH_IN_SECONDS
|
||||
);
|
||||
|
||||
return ! empty( $result );
|
||||
|
|
|
@ -64,7 +64,7 @@ class OnboardingUrl {
|
|||
*
|
||||
* @var int
|
||||
*/
|
||||
private $cache_ttl = 3 * MONTH_IN_SECONDS;
|
||||
private $cache_ttl = MONTH_IN_SECONDS;
|
||||
|
||||
/**
|
||||
* The TTL for the previous token cache.
|
||||
|
|
|
@ -241,7 +241,7 @@ class RenewalHandler {
|
|||
* @param \WC_Customer $customer The customer.
|
||||
* @param \WC_Order $wc_order The current WooCommerce order we want to process.
|
||||
*
|
||||
* @return PaymentToken|null
|
||||
* @return PaymentToken|null|false
|
||||
*/
|
||||
private function get_token_for_customer( \WC_Customer $customer, \WC_Order $wc_order ) {
|
||||
/**
|
||||
|
|
|
@ -45,6 +45,12 @@ return array(
|
|||
);
|
||||
},
|
||||
|
||||
'uninstall.ppcp-all-action-names' => function( ContainerInterface $container ) : array {
|
||||
return array(
|
||||
'woocommerce_paypal_payments_uninstall',
|
||||
);
|
||||
},
|
||||
|
||||
'uninstall.clear-db-endpoint' => function( ContainerInterface $container ) : string {
|
||||
return 'ppcp-clear-db';
|
||||
},
|
||||
|
|
|
@ -31,4 +31,13 @@ class ClearDatabase implements ClearDatabaseInterface {
|
|||
as_unschedule_action( $action_name );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function clear_actions( array $action_names ): void {
|
||||
foreach ( $action_names as $action_name ) {
|
||||
do_action( $action_name );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -29,4 +29,12 @@ interface ClearDatabaseInterface {
|
|||
*/
|
||||
public function clear_scheduled_actions( array $action_names ): void;
|
||||
|
||||
/**
|
||||
* Clears the given actions.
|
||||
*
|
||||
* @param string[] $action_names The list of action names.
|
||||
* @throws RuntimeException If problem clearing.
|
||||
*/
|
||||
public function clear_actions( array $action_names ): void;
|
||||
|
||||
}
|
||||
|
|
|
@ -47,8 +47,9 @@ class UninstallModule implements ModuleInterface {
|
|||
$clear_db_endpoint = $container->get( 'uninstall.clear-db-endpoint' );
|
||||
$option_names = $container->get( 'uninstall.ppcp-all-option-names' );
|
||||
$scheduled_action_names = $container->get( 'uninstall.ppcp-all-scheduled-action-names' );
|
||||
$action_names = $container->get( 'uninstall.ppcp-all-action-names' );
|
||||
|
||||
$this->handleClearDbAjaxRequest( $request_data, $clear_db, $clear_db_endpoint, $option_names, $scheduled_action_names );
|
||||
$this->handleClearDbAjaxRequest( $request_data, $clear_db, $clear_db_endpoint, $option_names, $scheduled_action_names, $action_names );
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -69,17 +70,19 @@ class UninstallModule implements ModuleInterface {
|
|||
* @param string $nonce The nonce.
|
||||
* @param string[] $option_names The list of option names.
|
||||
* @param string[] $scheduled_action_names The list of scheduled action names.
|
||||
* @param string[] $action_names The list of action names.
|
||||
*/
|
||||
protected function handleClearDbAjaxRequest(
|
||||
RequestData $request_data,
|
||||
ClearDatabaseInterface $clear_db,
|
||||
string $nonce,
|
||||
array $option_names,
|
||||
array $scheduled_action_names
|
||||
array $scheduled_action_names,
|
||||
array $action_names
|
||||
): void {
|
||||
add_action(
|
||||
"wc_ajax_{$nonce}",
|
||||
static function () use ( $request_data, $clear_db, $nonce, $option_names, $scheduled_action_names ) {
|
||||
static function () use ( $request_data, $clear_db, $nonce, $option_names, $scheduled_action_names, $action_names ) {
|
||||
try {
|
||||
if ( ! current_user_can( 'manage_woocommerce' ) ) {
|
||||
wp_send_json_error( 'Not admin.', 403 );
|
||||
|
@ -91,6 +94,7 @@ class UninstallModule implements ModuleInterface {
|
|||
|
||||
$clear_db->delete_options( $option_names );
|
||||
$clear_db->clear_scheduled_actions( $scheduled_action_names );
|
||||
$clear_db->clear_actions( $action_names );
|
||||
|
||||
wp_send_json_success();
|
||||
return true;
|
||||
|
|
|
@ -56,10 +56,14 @@ return array(
|
|||
'vaulting.payment-token-factory' => function( ContainerInterface $container ): PaymentTokenFactory {
|
||||
return new PaymentTokenFactory();
|
||||
},
|
||||
'vaulting.payment-token-helper' => function( ContainerInterface $container ): PaymentTokenHelper {
|
||||
return new PaymentTokenHelper();
|
||||
},
|
||||
'vaulting.payment-tokens-migration' => function( ContainerInterface $container ): PaymentTokensMigration {
|
||||
return new PaymentTokensMigration(
|
||||
$container->get( 'vaulting.payment-token-factory' ),
|
||||
$container->get( 'vaulting.repository.payment-token' ),
|
||||
$container->get( 'vaulting.payment-token-helper' ),
|
||||
$container->get( 'woocommerce.logger.woocommerce' )
|
||||
);
|
||||
},
|
||||
|
|
35
modules/ppcp-vaulting/src/PaymentTokenHelper.php
Normal file
35
modules/ppcp-vaulting/src/PaymentTokenHelper.php
Normal file
|
@ -0,0 +1,35 @@
|
|||
<?php
|
||||
/**
|
||||
* Payment Tokens helper methods.
|
||||
*
|
||||
* @package WooCommerce\PayPalCommerce\Vaulting
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace WooCommerce\PayPalCommerce\Vaulting;
|
||||
|
||||
use WC_Payment_Token;
|
||||
|
||||
/**
|
||||
* Class PaymentTokenHelper
|
||||
*/
|
||||
class PaymentTokenHelper {
|
||||
|
||||
/**
|
||||
* Checks if given token exist as WC Payment Token.
|
||||
*
|
||||
* @param WC_Payment_Token[] $wc_tokens WC Payment Tokens.
|
||||
* @param string $token_id Payment Token ID.
|
||||
* @return bool
|
||||
*/
|
||||
public function token_exist( array $wc_tokens, string $token_id ): bool {
|
||||
foreach ( $wc_tokens as $wc_token ) {
|
||||
if ( $wc_token->get_token() === $token_id ) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
|
@ -35,6 +35,13 @@ class PaymentTokensMigration {
|
|||
*/
|
||||
private $payment_token_repository;
|
||||
|
||||
/**
|
||||
* The payment token helper.
|
||||
*
|
||||
* @var PaymentTokenHelper
|
||||
*/
|
||||
private $payment_token_helper;
|
||||
|
||||
/**
|
||||
* The logger.
|
||||
*
|
||||
|
@ -47,16 +54,19 @@ class PaymentTokensMigration {
|
|||
*
|
||||
* @param PaymentTokenFactory $payment_token_factory The payment token factory.
|
||||
* @param PaymentTokenRepository $payment_token_repository The payment token repository.
|
||||
* @param PaymentTokenHelper $payment_token_helper The payment token helper.
|
||||
* @param LoggerInterface $logger The logger.
|
||||
*/
|
||||
public function __construct(
|
||||
PaymentTokenFactory $payment_token_factory,
|
||||
PaymentTokenRepository $payment_token_repository,
|
||||
PaymentTokenHelper $payment_token_helper,
|
||||
LoggerInterface $logger
|
||||
) {
|
||||
$this->payment_token_factory = $payment_token_factory;
|
||||
$this->payment_token_repository = $payment_token_repository;
|
||||
$this->logger = $logger;
|
||||
$this->payment_token_helper = $payment_token_helper;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -72,7 +82,7 @@ class PaymentTokensMigration {
|
|||
foreach ( $tokens as $token ) {
|
||||
if ( isset( $token->source()->card ) ) {
|
||||
$wc_tokens = WC_Payment_Tokens::get_customer_tokens( $id, CreditCardGateway::ID );
|
||||
if ( $this->token_exist( $wc_tokens, $token ) ) {
|
||||
if ( $this->payment_token_helper->token_exist( $wc_tokens, $token->id() ) ) {
|
||||
$this->logger->info( 'Token already exist for user ' . (string) $id );
|
||||
continue;
|
||||
}
|
||||
|
@ -97,7 +107,7 @@ class PaymentTokensMigration {
|
|||
}
|
||||
} elseif ( $token->source()->paypal ) {
|
||||
$wc_tokens = WC_Payment_Tokens::get_customer_tokens( $id, PayPalGateway::ID );
|
||||
if ( $this->token_exist( $wc_tokens, $token ) ) {
|
||||
if ( $this->payment_token_helper->token_exist( $wc_tokens, $token->id() ) ) {
|
||||
$this->logger->info( 'Token already exist for user ' . (string) $id );
|
||||
continue;
|
||||
}
|
||||
|
@ -126,21 +136,4 @@ class PaymentTokensMigration {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if given PayPal token exist as WC Payment Token.
|
||||
*
|
||||
* @param array $wc_tokens WC Payment Tokens.
|
||||
* @param PaymentToken $token PayPal Token ID.
|
||||
* @return bool
|
||||
*/
|
||||
private function token_exist( array $wc_tokens, PaymentToken $token ): bool {
|
||||
foreach ( $wc_tokens as $wc_token ) {
|
||||
if ( $wc_token->get_token() === $token->id() ) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -44,4 +44,14 @@ class GatewayRepository {
|
|||
}
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates if a given gateway ID is registered.
|
||||
*
|
||||
* @param string $gateway_id The gateway ID.
|
||||
* @return bool
|
||||
*/
|
||||
public function exists( string $gateway_id ): bool {
|
||||
return in_array( $gateway_id, $this->ppcp_gateway_ids, true );
|
||||
}
|
||||
}
|
||||
|
|
|
@ -227,7 +227,6 @@ class PayPalGateway extends \WC_Payment_Gateway {
|
|||
|
||||
if (
|
||||
( $this->config->has( 'vault_enabled' ) && $this->config->get( 'vault_enabled' ) )
|
||||
|| ( $this->config->has( 'vault_enabled_dcc' ) && $this->config->get( 'vault_enabled_dcc' ) )
|
||||
|| ( $this->config->has( 'subscriptions_mode' ) && $this->config->get( 'subscriptions_mode' ) === 'subscriptions_api' )
|
||||
) {
|
||||
array_push(
|
||||
|
@ -244,6 +243,8 @@ class PayPalGateway extends \WC_Payment_Gateway {
|
|||
'subscription_payment_method_change_admin',
|
||||
'multiple_subscriptions'
|
||||
);
|
||||
} elseif ( $this->config->has( 'vault_enabled_dcc' ) && $this->config->get( 'vault_enabled_dcc' ) ) {
|
||||
$this->supports[] = 'tokenization';
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -135,12 +135,12 @@ class DCCProductStatus {
|
|||
$this->settings->set( 'products_dcc_enabled', true );
|
||||
$this->settings->persist();
|
||||
$this->current_status_cache = true;
|
||||
$this->cache->set( self::DCC_STATUS_CACHE_KEY, 'true', 3 * MONTH_IN_SECONDS );
|
||||
$this->cache->set( self::DCC_STATUS_CACHE_KEY, 'true', MONTH_IN_SECONDS );
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
$expiration = 3 * MONTH_IN_SECONDS;
|
||||
$expiration = MONTH_IN_SECONDS;
|
||||
if ( $this->dcc_applies->for_country_currency() ) {
|
||||
$expiration = 3 * HOUR_IN_SECONDS;
|
||||
}
|
||||
|
|
|
@ -127,11 +127,11 @@ class PayUponInvoiceProductStatus {
|
|||
$this->settings->set( 'products_pui_enabled', true );
|
||||
$this->settings->persist();
|
||||
$this->current_status_cache = true;
|
||||
$this->cache->set( self::PUI_STATUS_CACHE_KEY, 'true', 3 * MONTH_IN_SECONDS );
|
||||
$this->cache->set( self::PUI_STATUS_CACHE_KEY, 'true', MONTH_IN_SECONDS );
|
||||
return true;
|
||||
}
|
||||
}
|
||||
$this->cache->set( self::PUI_STATUS_CACHE_KEY, 'false', 3 * MONTH_IN_SECONDS );
|
||||
$this->cache->set( self::PUI_STATUS_CACHE_KEY, 'false', MONTH_IN_SECONDS );
|
||||
|
||||
$this->current_status_cache = false;
|
||||
return false;
|
||||
|
|
|
@ -116,6 +116,13 @@ class OrderProcessor {
|
|||
*/
|
||||
private $order_helper;
|
||||
|
||||
/**
|
||||
* Array to store temporary order data changes to restore after processing.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
private $restore_order_data = array();
|
||||
|
||||
/**
|
||||
* OrderProcessor constructor.
|
||||
*
|
||||
|
@ -292,8 +299,12 @@ class OrderProcessor {
|
|||
* @return Order
|
||||
*/
|
||||
public function patch_order( \WC_Order $wc_order, Order $order ): Order {
|
||||
$this->apply_outbound_order_filters( $wc_order );
|
||||
$updated_order = $this->order_factory->from_wc_order( $wc_order, $order );
|
||||
$order = $this->order_endpoint->patch_order_with( $order, $updated_order );
|
||||
$this->restore_order_from_filters( $wc_order );
|
||||
|
||||
$order = $this->order_endpoint->patch_order_with( $order, $updated_order );
|
||||
|
||||
return $order;
|
||||
}
|
||||
|
||||
|
@ -323,4 +334,48 @@ class OrderProcessor {
|
|||
true
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Applies filters to the WC_Order, so they are reflected only on PayPal Order.
|
||||
*
|
||||
* @param WC_Order $wc_order The WoocOmmerce Order.
|
||||
* @return void
|
||||
*/
|
||||
private function apply_outbound_order_filters( WC_Order $wc_order ): void {
|
||||
$items = $wc_order->get_items();
|
||||
|
||||
$this->restore_order_data['names'] = array();
|
||||
|
||||
foreach ( $items as $item ) {
|
||||
if ( ! $item instanceof \WC_Order_Item ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$original_name = $item->get_name();
|
||||
$new_name = apply_filters( 'woocommerce_paypal_payments_order_line_item_name', $original_name, $item->get_id(), $wc_order->get_id() );
|
||||
|
||||
if ( $new_name !== $original_name ) {
|
||||
$this->restore_order_data['names'][ $item->get_id() ] = $original_name;
|
||||
$item->set_name( $new_name );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Restores the WC_Order to it's state before filters.
|
||||
*
|
||||
* @param WC_Order $wc_order The WooCommerce Order.
|
||||
* @return void
|
||||
*/
|
||||
private function restore_order_from_filters( WC_Order $wc_order ): void {
|
||||
if ( is_array( $this->restore_order_data['names'] ?? null ) ) {
|
||||
foreach ( $this->restore_order_data['names'] as $wc_item_id => $original_name ) {
|
||||
$wc_item = $wc_order->get_item( $wc_item_id, false );
|
||||
|
||||
if ( $wc_item ) {
|
||||
$wc_item->set_name( $original_name );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -211,7 +211,7 @@ class SettingsListener {
|
|||
}
|
||||
|
||||
$merchant_id = sanitize_text_field( wp_unslash( $_GET['merchantIdInPayPal'] ) );
|
||||
$merchant_email = sanitize_text_field( wp_unslash( $_GET['merchantId'] ) );
|
||||
$merchant_email = $this->sanitize_onboarding_email( sanitize_text_field( wp_unslash( $_GET['merchantId'] ) ) );
|
||||
$onboarding_token = sanitize_text_field( wp_unslash( $_GET['ppcpToken'] ) );
|
||||
$retry_count = isset( $_GET['ppcpRetry'] ) ? ( (int) sanitize_text_field( wp_unslash( $_GET['ppcpRetry'] ) ) ) : 0;
|
||||
// phpcs:enable WordPress.Security.NonceVerification.Missing
|
||||
|
@ -278,6 +278,16 @@ class SettingsListener {
|
|||
$this->onboarding_redirect();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sanitizes the onboarding email.
|
||||
*
|
||||
* @param string $email The onboarding email.
|
||||
* @return string
|
||||
*/
|
||||
private function sanitize_onboarding_email( string $email ): string {
|
||||
return str_replace( ' ', '+', $email );
|
||||
}
|
||||
|
||||
/**
|
||||
* Redirect to the onboarding URL.
|
||||
*
|
||||
|
@ -401,9 +411,7 @@ class SettingsListener {
|
|||
$this->webhook_registrar->unregister();
|
||||
|
||||
foreach ( $this->signup_link_ids as $key ) {
|
||||
if ( $this->signup_link_cache->has( $key ) ) {
|
||||
$this->signup_link_cache->delete( $key );
|
||||
}
|
||||
( new OnboardingUrl( $this->signup_link_cache, $key, get_current_user_id() ) )->delete();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -613,4 +621,40 @@ class SettingsListener {
|
|||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prevent enabling tracking if it is not enabled for merchant account.
|
||||
*
|
||||
* @throws RuntimeException When API request fails.
|
||||
*/
|
||||
public function listen_for_tracking_enabled(): void {
|
||||
if ( State::STATE_ONBOARDED !== $this->state->current_state() ) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
$token = $this->bearer->bearer();
|
||||
if ( ! $token->is_tracking_available() ) {
|
||||
$this->settings->set( 'tracking_enabled', false );
|
||||
$this->settings->persist();
|
||||
return;
|
||||
}
|
||||
} catch ( RuntimeException $exception ) {
|
||||
$this->settings->set( 'tracking_enabled', false );
|
||||
$this->settings->persist();
|
||||
|
||||
throw $exception;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles onboarding URLs deletion
|
||||
*/
|
||||
public function listen_for_uninstall(): void {
|
||||
// Clear onboarding links from cache.
|
||||
foreach ( $this->signup_link_ids as $key ) {
|
||||
( new OnboardingUrl( $this->signup_link_cache, $key, get_current_user_id() ) )->delete();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -33,6 +33,7 @@ use WooCommerce\PayPalCommerce\WcGateway\Checkout\DisableGateways;
|
|||
use WooCommerce\PayPalCommerce\WcGateway\Endpoint\ReturnUrlEndpoint;
|
||||
use WooCommerce\PayPalCommerce\WcGateway\Exception\NotFoundException;
|
||||
use WooCommerce\PayPalCommerce\WcGateway\Gateway\CreditCardGateway;
|
||||
use WooCommerce\PayPalCommerce\WcGateway\Gateway\GatewayRepository;
|
||||
use WooCommerce\PayPalCommerce\WcGateway\Gateway\PayPalGateway;
|
||||
use WooCommerce\PayPalCommerce\WcGateway\Helper\DCCProductStatus;
|
||||
use WooCommerce\PayPalCommerce\WcGateway\Helper\PayUponInvoiceProductStatus;
|
||||
|
@ -356,6 +357,14 @@ class WCGatewayModule implements ModuleInterface {
|
|||
return;
|
||||
}
|
||||
|
||||
$gateway_repository = $c->get( 'wcgateway.gateway-repository' );
|
||||
assert( $gateway_repository instanceof GatewayRepository );
|
||||
|
||||
// Only allow to proceed if the payment method is one of our Gateways.
|
||||
if ( ! $gateway_repository->exists( $wc_order->get_payment_method() ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$intent = strtoupper( (string) $wc_order->get_meta( PayPalGateway::INTENT_META_KEY ) );
|
||||
$captured = wc_string_to_bool( $wc_order->get_meta( AuthorizedPaymentsProcessor::CAPTURED_META_KEY ) );
|
||||
if ( $intent !== 'AUTHORIZE' || $captured ) {
|
||||
|
@ -392,6 +401,16 @@ class WCGatewayModule implements ModuleInterface {
|
|||
3
|
||||
);
|
||||
|
||||
add_action(
|
||||
'woocommerce_paypal_payments_uninstall',
|
||||
static function () use ( $c ) {
|
||||
$listener = $c->get( 'wcgateway.settings.listener' );
|
||||
assert( $listener instanceof SettingsListener );
|
||||
|
||||
$listener->listen_for_uninstall();
|
||||
}
|
||||
);
|
||||
|
||||
if ( defined( 'WP_CLI' ) && WP_CLI ) {
|
||||
\WP_CLI::add_command(
|
||||
'pcp settings',
|
||||
|
|
|
@ -80,6 +80,7 @@ return array(
|
|||
$order_endpoint = $container->get( 'api.endpoint.order' );
|
||||
$authorized_payments_processor = $container->get( 'wcgateway.processor.authorized-payments' );
|
||||
$payment_token_factory = $container->get( 'vaulting.payment-token-factory' );
|
||||
$payment_token_helper = $container->get( 'vaulting.payment-token-helper' );
|
||||
$refund_fees_updater = $container->get( 'wcgateway.helper.refund-fees-updater' );
|
||||
|
||||
return array(
|
||||
|
@ -95,7 +96,7 @@ return array(
|
|||
new PaymentCaptureRefunded( $logger, $refund_fees_updater ),
|
||||
new PaymentCaptureReversed( $logger ),
|
||||
new PaymentCaptureCompleted( $logger, $order_endpoint ),
|
||||
new VaultPaymentTokenCreated( $logger, $prefix, $authorized_payments_processor, $payment_token_factory ),
|
||||
new VaultPaymentTokenCreated( $logger, $prefix, $authorized_payments_processor, $payment_token_factory, $payment_token_helper ),
|
||||
new VaultPaymentTokenDeleted( $logger ),
|
||||
new PaymentCapturePending( $logger ),
|
||||
new PaymentSaleCompleted( $logger ),
|
||||
|
|
|
@ -13,6 +13,7 @@ use Psr\Log\LoggerInterface;
|
|||
use WC_Payment_Token_CC;
|
||||
use WC_Payment_Tokens;
|
||||
use WooCommerce\PayPalCommerce\Vaulting\PaymentTokenFactory;
|
||||
use WooCommerce\PayPalCommerce\Vaulting\PaymentTokenHelper;
|
||||
use WooCommerce\PayPalCommerce\Vaulting\PaymentTokenPayPal;
|
||||
use WooCommerce\PayPalCommerce\WcGateway\Gateway\CreditCardGateway;
|
||||
use WooCommerce\PayPalCommerce\WcGateway\Gateway\PayPalGateway;
|
||||
|
@ -54,6 +55,13 @@ class VaultPaymentTokenCreated implements RequestHandler {
|
|||
*/
|
||||
protected $payment_token_factory;
|
||||
|
||||
/**
|
||||
* The payment token helper.
|
||||
*
|
||||
* @var PaymentTokenHelper
|
||||
*/
|
||||
private $payment_token_helper;
|
||||
|
||||
/**
|
||||
* VaultPaymentTokenCreated constructor.
|
||||
*
|
||||
|
@ -61,17 +69,20 @@ class VaultPaymentTokenCreated implements RequestHandler {
|
|||
* @param string $prefix The prefix.
|
||||
* @param AuthorizedPaymentsProcessor $authorized_payments_processor The authorized payment processor.
|
||||
* @param PaymentTokenFactory $payment_token_factory The payment token factory.
|
||||
* @param PaymentTokenHelper $payment_token_helper The payment token helper.
|
||||
*/
|
||||
public function __construct(
|
||||
LoggerInterface $logger,
|
||||
string $prefix,
|
||||
AuthorizedPaymentsProcessor $authorized_payments_processor,
|
||||
PaymentTokenFactory $payment_token_factory
|
||||
PaymentTokenFactory $payment_token_factory,
|
||||
PaymentTokenHelper $payment_token_helper
|
||||
) {
|
||||
$this->logger = $logger;
|
||||
$this->prefix = $prefix;
|
||||
$this->authorized_payments_processor = $authorized_payments_processor;
|
||||
$this->payment_token_factory = $payment_token_factory;
|
||||
$this->payment_token_helper = $payment_token_helper;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -123,33 +134,39 @@ class VaultPaymentTokenCreated implements RequestHandler {
|
|||
|
||||
if ( ! is_null( $request['resource'] ) && isset( $request['resource']['id'] ) ) {
|
||||
if ( ! is_null( $request['resource']['source'] ) && isset( $request['resource']['source']['card'] ) ) {
|
||||
$token = new WC_Payment_Token_CC();
|
||||
$token->set_token( $request['resource']['id'] );
|
||||
$token->set_user_id( $wc_customer_id );
|
||||
$token->set_gateway_id( CreditCardGateway::ID );
|
||||
$wc_tokens = WC_Payment_Tokens::get_customer_tokens( $wc_customer_id, CreditCardGateway::ID );
|
||||
if ( ! $this->payment_token_helper->token_exist( $wc_tokens, $request['resource']['id'] ) ) {
|
||||
$token = new WC_Payment_Token_CC();
|
||||
$token->set_token( $request['resource']['id'] );
|
||||
$token->set_user_id( $wc_customer_id );
|
||||
$token->set_gateway_id( CreditCardGateway::ID );
|
||||
|
||||
$token->set_last4( $request['resource']['source']['card']['last_digits'] ?? '' );
|
||||
$expiry = explode( '-', $request['resource']['source']['card']['expiry'] ?? '' );
|
||||
$token->set_expiry_year( $expiry[0] ?? '' );
|
||||
$token->set_expiry_month( $expiry[1] ?? '' );
|
||||
$token->set_card_type( $request['resource']['source']['card']['brand'] ?? '' );
|
||||
$token->save();
|
||||
WC_Payment_Tokens::set_users_default( $wc_customer_id, $token->get_id() );
|
||||
} elseif ( isset( $request['resource']['source']['paypal'] ) ) {
|
||||
$payment_token_paypal = $this->payment_token_factory->create( 'paypal' );
|
||||
assert( $payment_token_paypal instanceof PaymentTokenPayPal );
|
||||
|
||||
$payment_token_paypal->set_token( $request['resource']['id'] );
|
||||
$payment_token_paypal->set_user_id( $wc_customer_id );
|
||||
$payment_token_paypal->set_gateway_id( PayPalGateway::ID );
|
||||
|
||||
$email = $request['resource']['source']['paypal']['payer']['email_address'] ?? '';
|
||||
if ( $email && is_email( $email ) ) {
|
||||
$payment_token_paypal->set_email( $email );
|
||||
$token->set_last4( $request['resource']['source']['card']['last_digits'] ?? '' );
|
||||
$expiry = explode( '-', $request['resource']['source']['card']['expiry'] ?? '' );
|
||||
$token->set_expiry_year( $expiry[0] ?? '' );
|
||||
$token->set_expiry_month( $expiry[1] ?? '' );
|
||||
$token->set_card_type( $request['resource']['source']['card']['brand'] ?? '' );
|
||||
$token->save();
|
||||
WC_Payment_Tokens::set_users_default( $wc_customer_id, $token->get_id() );
|
||||
}
|
||||
} elseif ( isset( $request['resource']['source']['paypal'] ) ) {
|
||||
$wc_tokens = WC_Payment_Tokens::get_customer_tokens( $wc_customer_id, PayPalGateway::ID );
|
||||
if ( ! $this->payment_token_helper->token_exist( $wc_tokens, $request['resource']['id'] ) ) {
|
||||
$payment_token_paypal = $this->payment_token_factory->create( 'paypal' );
|
||||
assert( $payment_token_paypal instanceof PaymentTokenPayPal );
|
||||
|
||||
$payment_token_paypal->save();
|
||||
WC_Payment_Tokens::set_users_default( $wc_customer_id, $payment_token_paypal->get_id() );
|
||||
$payment_token_paypal->set_token( $request['resource']['id'] );
|
||||
$payment_token_paypal->set_user_id( $wc_customer_id );
|
||||
$payment_token_paypal->set_gateway_id( PayPalGateway::ID );
|
||||
|
||||
$email = $request['resource']['source']['paypal']['payer']['email_address'] ?? '';
|
||||
if ( $email && is_email( $email ) ) {
|
||||
$payment_token_paypal->set_email( $email );
|
||||
}
|
||||
|
||||
$payment_token_paypal->save();
|
||||
WC_Payment_Tokens::set_users_default( $wc_customer_id, $payment_token_paypal->get_id() );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -3,7 +3,7 @@ declare(strict_types=1);
|
|||
|
||||
namespace WooCommerce\PayPalCommerce\Onboarding\Helper;
|
||||
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use WooCommerce\PayPalCommerce\TestCase;
|
||||
use WooCommerce\PayPalCommerce\ApiClient\Helper\Cache;
|
||||
use RuntimeException;
|
||||
use function Brain\Monkey\Functions\when;
|
||||
|
@ -15,7 +15,7 @@ class OnboardingUrlTest extends TestCase
|
|||
private $user_id = 123;
|
||||
private $onboardingUrl;
|
||||
|
||||
protected function setUp(): void
|
||||
public function setUp(): void
|
||||
{
|
||||
parent::setUp();
|
||||
|
||||
|
|
|
@ -57,6 +57,7 @@ class OrderProcessorTest extends TestCase
|
|||
->andReturn($payments);
|
||||
|
||||
$wcOrder = Mockery::mock(\WC_Order::class);
|
||||
$wcOrder->expects('get_items')->andReturn([]);
|
||||
$wcOrder->expects('update_meta_data')
|
||||
->with(PayPalGateway::ORDER_PAYMENT_MODE_META_KEY, 'live');
|
||||
$wcOrder->shouldReceive('get_id')->andReturn(1);
|
||||
|
@ -193,7 +194,8 @@ class OrderProcessorTest extends TestCase
|
|||
->andReturn($payments);
|
||||
|
||||
$wcOrder = Mockery::mock(\WC_Order::class);
|
||||
$orderStatus = Mockery::mock(OrderStatus::class);
|
||||
$wcOrder->expects('get_items')->andReturn([]);
|
||||
$orderStatus = Mockery::mock(OrderStatus::class);
|
||||
$orderStatus
|
||||
->shouldReceive('is')
|
||||
->with(OrderStatus::APPROVED)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue