Add my account payment method for PayPal payment

This commit is contained in:
Emili Castells Guasch 2023-10-27 12:25:42 +02:00
parent 34cc1bffe4
commit 48c5773ecd
7 changed files with 298 additions and 91 deletions

View file

@ -16,25 +16,61 @@ use WooCommerce\PayPalCommerce\ApiClient\Entity\PaymentSource;
use WooCommerce\PayPalCommerce\ApiClient\Exception\PayPalApiException;
use WooCommerce\PayPalCommerce\ApiClient\Exception\RuntimeException;
/**
* Class PaymentMethodTokensEndpoint
*/
class PaymentMethodTokensEndpoint {
use RequestTrait;
private string $host;
private Bearer $bearer;
private LoggerInterface $logger;
/**
* The host.
*
* @var string
*/
private $host;
public function __construct(string $host, Bearer $bearer, LoggerInterface $logger)
{
/**
* The bearer.
*
* @var Bearer
*/
private $bearer;
/**
* The logger.
*
* @var LoggerInterface
*/
private $logger;
/**
* PaymentMethodTokensEndpoint constructor.
*
* @param string $host The host.
* @param Bearer $bearer The bearer.
* @param LoggerInterface $logger The logger.
*/
public function __construct( string $host, Bearer $bearer, LoggerInterface $logger ) {
$this->host = $host;
$this->bearer = $bearer;
$this->logger = $logger;
}
public function setup_tokens(PaymentSource $payment_source): stdClass {
/**
* Creates a setup token.
*
* @param PaymentSource $payment_source The payment source.
*
* @return stdClass
*
* @throws RuntimeException When something when wrong with the request.
* @throws PayPalApiException When something when wrong setting up the token.
*/
public function setup_tokens( PaymentSource $payment_source ): stdClass {
$data = array(
'payment_source' => array(
$payment_source->name() => $payment_source->properties()
$payment_source->name() => $payment_source->properties(),
),
);
@ -69,10 +105,20 @@ class PaymentMethodTokensEndpoint {
return $json;
}
public function payment_tokens(PaymentSource $payment_source) {
/**
* Creates a payment token for the given payment source.
*
* @param PaymentSource $payment_source The payment source.
*
* @return stdClass
*
* @throws RuntimeException When something when wrong with the request.
* @throws PayPalApiException When something when wrong setting up the token.
*/
public function payment_tokens( PaymentSource $payment_source ): stdClass {
$data = array(
'payment_source' => array(
$payment_source->name() => $payment_source->properties()
$payment_source->name() => $payment_source->properties(),
),
);

View file

@ -54,16 +54,24 @@ return array(
dirname( realpath( __FILE__ ), 3 ) . '/woocommerce-paypal-payments.php'
);
},
'save-payment-methods.endpoint.create-setup-token' => static function (ContainerInterface $container): CreateSetupToken {
'save-payment-methods.endpoint.create-setup-token' => static function ( ContainerInterface $container ): CreateSetupToken {
return new CreateSetupToken(
$container->get( 'button.request-data' ),
$container->get('api.endpoint.payment-method-tokens')
$container->get( 'api.endpoint.payment-method-tokens' )
);
},
'save-payment-methods.endpoint.create-payment-token' => static function (ContainerInterface $container): CreatePaymentToken {
return new CreatePaymentToken(
$container->get('button.request-data'),
$container->get('api.endpoint.payment-method-tokens')
'save-payment-methods.wc-payment-tokens' => static function( ContainerInterface $container ): WooCommercePaymentTokens {
return new WooCommercePaymentTokens(
$container->get( 'vaulting.payment-token-helper' ),
$container->get( 'vaulting.payment-token-factory' ),
$container->get( 'woocommerce.logger.woocommerce' )
);
}
},
'save-payment-methods.endpoint.create-payment-token' => static function ( ContainerInterface $container ): CreatePaymentToken {
return new CreatePaymentToken(
$container->get( 'button.request-data' ),
$container->get( 'api.endpoint.payment-method-tokens' ),
$container->get( 'save-payment-methods.wc-payment-tokens' )
);
},
);

View file

@ -1,4 +1,11 @@
<?php
/**
* The Create Payment Token endpoint.
*
* @package WooCommerce\PayPalCommerce\ApiClient\Endpoint
*/
declare(strict_types=1);
namespace WooCommerce\PayPalCommerce\SavePaymentMethods\Endpoint;
@ -7,20 +14,51 @@ use WooCommerce\PayPalCommerce\ApiClient\Endpoint\PaymentMethodTokensEndpoint;
use WooCommerce\PayPalCommerce\ApiClient\Entity\PaymentSource;
use WooCommerce\PayPalCommerce\Button\Endpoint\EndpointInterface;
use WooCommerce\PayPalCommerce\Button\Endpoint\RequestData;
use WooCommerce\PayPalCommerce\SavePaymentMethods\WooCommercePaymentTokens;
/**
* Class CreatePaymentToken
*/
class CreatePaymentToken implements EndpointInterface {
const ENDPOINT = 'ppc-create-payment-token';
private RequestData $request_data;
private PaymentMethodTokensEndpoint $payment_method_tokens_endpoint;
/**
* The request data.
*
* @var RequestData
*/
private $request_data;
/**
* The payment method tokens endpoint.
*
* @var PaymentMethodTokensEndpoint
*/
private $payment_method_tokens_endpoint;
/**
* The WC payment tokens.
*
* @var WooCommercePaymentTokens
*/
private $wc_payment_tokens;
/**
* CreatePaymentToken constructor.
*
* @param RequestData $request_data The request data.
* @param PaymentMethodTokensEndpoint $payment_method_tokens_endpoint The payment method tokens endpoint.
* @param WooCommercePaymentTokens $wc_payment_tokens The WC payment tokens.
*/
public function __construct(
RequestData $request_data,
PaymentMethodTokensEndpoint $payment_method_tokens_endpoint
PaymentMethodTokensEndpoint $payment_method_tokens_endpoint,
WooCommercePaymentTokens $wc_payment_tokens
) {
$this->request_data = $request_data;
$this->payment_method_tokens_endpoint = $payment_method_tokens_endpoint;
$this->wc_payment_tokens = $wc_payment_tokens;
}
/**
@ -46,11 +84,27 @@ class CreatePaymentToken implements EndpointInterface {
'token',
(object) array(
'id' => $data['vault_setup_token'],
'type' => 'SETUP-TOKEN',
'type' => 'SETUP_TOKEN',
)
);
$result = $this->payment_method_tokens_endpoint->payment_tokens( $payment_source );
if ( is_user_logged_in() && isset( $result->customer->id ) ) {
update_user_meta( get_current_user_id(), '_ppcp_target_customer_id', $result->customer->id );
$email = '';
if ( isset( $result->payment_source->paypal->email_address ) ) {
$email = $result->payment_source->paypal->email_address;
}
$this->wc_payment_tokens->create_payment_token_paypal(
get_current_user_id(),
$result->id,
$email
);
}
wp_send_json_success( $result );
return true;
} catch ( Exception $exception ) {

View file

@ -1,4 +1,11 @@
<?php
/**
* The Create Setup Token endpoint.
*
* @package WooCommerce\PayPalCommerce\ApiClient\Endpoint
*/
declare(strict_types=1);
namespace WooCommerce\PayPalCommerce\SavePaymentMethods\Endpoint;
@ -8,29 +15,37 @@ use WooCommerce\PayPalCommerce\ApiClient\Entity\PaymentSource;
use WooCommerce\PayPalCommerce\Button\Endpoint\EndpointInterface;
use WooCommerce\PayPalCommerce\Button\Endpoint\RequestData;
class CreateSetupToken implements EndpointInterface
{
/**
* Class CreateSetupToken
*/
class CreateSetupToken implements EndpointInterface {
const ENDPOINT = 'ppc-create-setup-token';
/**
* * The request data helper.
* The request data helper.
*
* @var RequestData
*/
private RequestData $request_data;
private $request_data;
/**
* Payment Method Tokens endpoint.
*
* @var PaymentMethodTokensEndpoint
*/
private PaymentMethodTokensEndpoint $payment_method_tokens_endpoint;
private $payment_method_tokens_endpoint;
/**
* CreateSetupToken constructor.
*
* @param RequestData $request_data The request data helper.
* @param PaymentMethodTokensEndpoint $payment_method_tokens_endpoint Payment Method Tokens endpoint.
*/
public function __construct(
RequestData $request_data,
PaymentMethodTokensEndpoint $payment_method_tokens_endpoint
)
{
) {
$this->request_data = $request_data;
$this->payment_method_tokens_endpoint = $payment_method_tokens_endpoint;
}
@ -40,8 +55,7 @@ class CreateSetupToken implements EndpointInterface
*
* @return string
*/
public static function nonce(): string
{
public static function nonce(): string {
return self::ENDPOINT;
}
@ -51,8 +65,7 @@ class CreateSetupToken implements EndpointInterface
* @return bool
* @throws Exception On Error.
*/
public function handle_request(): bool
{
public function handle_request(): bool {
try {
$this->request_data->read_request( $this->nonce() );
@ -63,15 +76,15 @@ class CreateSetupToken implements EndpointInterface
'experience_context' => (object) array(
'return_url' => esc_url( wc_get_account_endpoint_url( 'payment-methods' ) ),
'cancel_url' => esc_url( wc_get_account_endpoint_url( 'add-payment-method' ) ),
)
),
)
);
$result = $this->payment_method_tokens_endpoint->setup_tokens($payment_source);
$result = $this->payment_method_tokens_endpoint->setup_tokens( $payment_source );
wp_send_json_success($result);
wp_send_json_success( $result );
return true;
} catch (Exception $exception) {
} catch ( Exception $exception ) {
wp_send_json_error();
return false;
}

View file

@ -11,6 +11,7 @@ namespace WooCommerce\PayPalCommerce\SavePaymentMethods;
use Exception;
use Psr\Log\LoggerInterface;
use stdClass;
use WC_Order;
use WC_Payment_Tokens;
use WooCommerce\PayPalCommerce\ApiClient\Authentication\UserIdToken;
@ -116,37 +117,21 @@ class SavePaymentMethodsModule implements ModuleInterface {
$payment_token_helper = $c->get( 'vaulting.payment-token-helper' );
assert( $payment_token_helper instanceof PaymentTokenHelper );
$wc_tokens = WC_Payment_Tokens::get_customer_tokens( $wc_order->get_customer_id(), PayPalGateway::ID );
if ( $payment_token_helper->token_exist( $wc_tokens, $payment_vault_attributes->id ) ) {
return;
}
$payment_token_factory = $c->get( 'vaulting.payment-token-factory' );
assert( $payment_token_factory instanceof PaymentTokenFactory );
$payment_token_paypal = $payment_token_factory->create( 'paypal' );
assert( $payment_token_paypal instanceof PaymentTokenPayPal );
$payment_token_paypal->set_token( $payment_vault_attributes->id );
$payment_token_paypal->set_user_id( $wc_order->get_customer_id() );
$payment_token_paypal->set_gateway_id( PayPalGateway::ID );
$email = $order->payment_source()->properties()->email_address ?? '';
if ( $email && is_email( $email ) ) {
$payment_token_paypal->set_email( $email );
}
try {
$payment_token_paypal->save();
} catch ( Exception $exception ) {
$logger = $c->get( 'woocommerce.logger.woocommerce' );
assert( $logger instanceof LoggerInterface );
$logger->error(
"Could not save WC payment token PayPal for order #{$wc_order->get_id()}. " . $exception->getMessage()
$wc_payment_tokens = $c->get( 'save-payment-methods.wc-payment-tokens' );
assert( $wc_payment_tokens instanceof WooCommercePaymentTokens );
$wc_payment_tokens->create_payment_token_paypal(
$wc_order->get_customer_id(),
$payment_vault_attributes->id,
$order->payment_source()->properties()->email_address ?? ''
);
}
}
},
10,
2
@ -170,16 +155,16 @@ class SavePaymentMethodsModule implements ModuleInterface {
true
);
$api = $c->get('api.user-id-token');
assert($api instanceof UserIdToken);
$api = $c->get( 'api.user-id-token' );
assert( $api instanceof UserIdToken );
try {
$target_customer_id = '';
if (is_user_logged_in()) {
$target_customer_id = get_user_meta(get_current_user_id(), '_ppcp_target_customer_id', true);
if ( is_user_logged_in() ) {
$target_customer_id = get_user_meta( get_current_user_id(), '_ppcp_target_customer_id', true );
}
$id_token = $api->id_token($target_customer_id);
$id_token = $api->id_token( $target_customer_id );
wp_localize_script(
'ppcp-add-payment-method',
@ -200,16 +185,16 @@ class SavePaymentMethodsModule implements ModuleInterface {
),
)
);
} catch (RuntimeException $exception) {
$logger = $c->get('woocommerce.logger.woocommerce');
assert($logger instanceof LoggerInterface);
} catch ( RuntimeException $exception ) {
$logger = $c->get( 'woocommerce.logger.woocommerce' );
assert( $logger instanceof LoggerInterface );
$error = $exception->getMessage();
if (is_a($exception, PayPalApiException::class)) {
$error = $exception->get_details($error);
if ( is_a( $exception, PayPalApiException::class ) ) {
$error = $exception->get_details( $error );
}
$logger->error($error);
$logger->error( $error );
}
}
);
@ -221,7 +206,7 @@ class SavePaymentMethodsModule implements ModuleInterface {
return;
}
echo '<div id="ppc-button-' . PayPalGateway::ID . '-save-payment-method"></div>';
echo '<div id="ppc-button-' . esc_attr( PayPalGateway::ID ) . '-save-payment-method"></div>';
}
);
@ -229,7 +214,7 @@ class SavePaymentMethodsModule implements ModuleInterface {
'wc_ajax_' . CreateSetupToken::ENDPOINT,
static function () use ( $c ) {
$endpoint = $c->get( 'save-payment-methods.endpoint.create-setup-token' );
assert($endpoint instanceof CreateSetupToken);
assert( $endpoint instanceof CreateSetupToken );
$endpoint->handle_request();
}
@ -239,7 +224,7 @@ class SavePaymentMethodsModule implements ModuleInterface {
'wc_ajax_' . CreatePaymentToken::ENDPOINT,
static function () use ( $c ) {
$endpoint = $c->get( 'save-payment-methods.endpoint.create-payment-token' );
assert($endpoint instanceof CreatePaymentToken);
assert( $endpoint instanceof CreatePaymentToken );
$endpoint->handle_request();
}

View file

@ -0,0 +1,102 @@
<?php
/**
* Service to create WC Payment Tokens.
*
* @package WooCommerce\PayPalCommerce\Applepay
*/
declare(strict_types=1);
namespace WooCommerce\PayPalCommerce\SavePaymentMethods;
use Exception;
use Psr\Log\LoggerInterface;
use WC_Payment_Tokens;
use WooCommerce\PayPalCommerce\Vaulting\PaymentTokenFactory;
use WooCommerce\PayPalCommerce\Vaulting\PaymentTokenHelper;
use WooCommerce\PayPalCommerce\Vaulting\PaymentTokenPayPal;
use WooCommerce\PayPalCommerce\WcGateway\Gateway\PayPalGateway;
/**
* Class WooCommercePaymentTokens
*/
class WooCommercePaymentTokens {
/**
* The payment token helper.
*
* @var PaymentTokenHelper
*/
private $payment_token_helper;
/**
* The payment token factory.
*
* @var PaymentTokenFactory
*/
private $payment_token_factory;
/**
* The logger.
*
* @var LoggerInterface
*/
private $logger;
/**
* WooCommercePaymentTokens constructor.
*
* @param PaymentTokenHelper $payment_token_helper The payment token helper.
* @param PaymentTokenFactory $payment_token_factory The payment token factory.
* @param LoggerInterface $logger The logger.
*/
public function __construct(
PaymentTokenHelper $payment_token_helper,
PaymentTokenFactory $payment_token_factory,
LoggerInterface $logger
) {
$this->payment_token_helper = $payment_token_helper;
$this->payment_token_factory = $payment_token_factory;
$this->logger = $logger;
}
/**
* 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.
*
* @return void
*/
public function create_payment_token_paypal(
int $customer_id,
string $token,
string $email
): void {
$wc_tokens = WC_Payment_Tokens::get_customer_tokens( $customer_id, PayPalGateway::ID );
if ( $this->payment_token_helper->token_exist( $wc_tokens, $token ) ) {
return;
}
$payment_token_paypal = $this->payment_token_factory->create( 'paypal' );
assert( $payment_token_paypal instanceof PaymentTokenPayPal );
$payment_token_paypal->set_token( $token );
$payment_token_paypal->set_user_id( $customer_id );
$payment_token_paypal->set_gateway_id( PayPalGateway::ID );
if ( $email && is_email( $email ) ) {
$payment_token_paypal->set_email( $email );
}
try {
$payment_token_paypal->save();
} catch ( Exception $exception ) {
$this->logger->error(
"Could not create WC payment token PayPal for customer {$customer_id}. " . $exception->getMessage()
);
}
}
}

View file

@ -60,7 +60,6 @@ return array(
$source
);
},
'wcgateway.settings.fields' => function ( ContainerInterface $container, array $fields ): array {
$path_to_settings_fields = __DIR__ . '/src/Settings/Fields';