mirror of
https://github.com/woocommerce/woocommerce-paypal-payments.git
synced 2025-08-30 05:00:51 +08:00
Merge branch 'trunk' into pcp-157-blocks
This commit is contained in:
commit
b478d9adaa
25 changed files with 565 additions and 663 deletions
|
@ -197,6 +197,40 @@ class PaymentTokenEndpoint {
|
|||
return wp_remote_retrieve_response_code( $response ) === 204;
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes payment token by the given id.
|
||||
*
|
||||
* @param string $token_id Token id.
|
||||
* @return bool
|
||||
*
|
||||
* @throws RuntimeException If something goes wrong while deleting the token.
|
||||
*/
|
||||
public function delete_token_by_id( string $token_id ): bool {
|
||||
$bearer = $this->bearer->bearer();
|
||||
|
||||
$url = trailingslashit( $this->host ) . 'v2/vault/payment-tokens/' . $token_id;
|
||||
$args = array(
|
||||
'method' => 'DELETE',
|
||||
'headers' => array(
|
||||
'Authorization' => 'Bearer ' . $bearer->token(),
|
||||
'Content-Type' => 'application/json',
|
||||
),
|
||||
);
|
||||
|
||||
$response = $this->request( $url, $args );
|
||||
|
||||
if ( is_wp_error( $response ) ) {
|
||||
$error = new RuntimeException(
|
||||
__( 'Could not delete payment token.', 'woocommerce-paypal-payments' )
|
||||
);
|
||||
$this->logger->warning( $error->getMessage() );
|
||||
|
||||
throw $error;
|
||||
}
|
||||
|
||||
return wp_remote_retrieve_response_code( $response ) === 204;
|
||||
}
|
||||
|
||||
/**
|
||||
* Starts the process of PayPal account vaulting (without payment), returns the links for further actions.
|
||||
*
|
||||
|
|
|
@ -1,11 +0,0 @@
|
|||
{
|
||||
"presets": [
|
||||
[
|
||||
"@babel/preset-env",
|
||||
{
|
||||
"useBuiltIns": "usage",
|
||||
"corejs": "3.25.0"
|
||||
}
|
||||
]
|
||||
]
|
||||
}
|
2
modules/ppcp-vaulting/.gitignore
vendored
2
modules/ppcp-vaulting/.gitignore
vendored
|
@ -1,2 +0,0 @@
|
|||
node_modules
|
||||
/assets
|
3
modules/ppcp-vaulting/assets/js/myaccount-payments.js
Normal file
3
modules/ppcp-vaulting/assets/js/myaccount-payments.js
Normal file
File diff suppressed because one or more lines are too long
|
@ -0,0 +1 @@
|
|||
/*! regenerator-runtime -- Copyright (c) 2014-present, Facebook, Inc. -- license (MIT): https://github.com/facebook/regenerator/blob/main/LICENSE */
|
File diff suppressed because one or more lines are too long
|
@ -1,42 +0,0 @@
|
|||
document.addEventListener(
|
||||
'DOMContentLoaded',
|
||||
() => {
|
||||
jQuery('.ppcp-delete-payment-button').click(async (event) => {
|
||||
event.preventDefault();
|
||||
jQuery(this).prop('disabled', true);
|
||||
const token = event.target.id;
|
||||
|
||||
const response = await fetch(
|
||||
PayPalCommerceGatewayVaulting.delete.endpoint,
|
||||
{
|
||||
method: 'POST',
|
||||
credentials: 'same-origin',
|
||||
headers: {
|
||||
'content-type': 'application/json'
|
||||
},
|
||||
body: JSON.stringify(
|
||||
{
|
||||
nonce: PayPalCommerceGatewayVaulting.delete.nonce,
|
||||
token,
|
||||
}
|
||||
)
|
||||
}
|
||||
);
|
||||
|
||||
const reportError = error => {
|
||||
alert(error);
|
||||
}
|
||||
|
||||
if (!response.ok) {
|
||||
try {
|
||||
const result = await response.json();
|
||||
reportError(result.data);
|
||||
} catch (exc) {
|
||||
console.error(exc);
|
||||
reportError(response.status);
|
||||
}
|
||||
}
|
||||
|
||||
window.location.reload();
|
||||
});
|
||||
});
|
|
@ -10,8 +10,6 @@ declare(strict_types=1);
|
|||
namespace WooCommerce\PayPalCommerce\Vaulting;
|
||||
|
||||
use WooCommerce\PayPalCommerce\Vendor\Psr\Container\ContainerInterface;
|
||||
use WooCommerce\PayPalCommerce\Vaulting\Assets\MyAccountPaymentsAssets;
|
||||
use WooCommerce\PayPalCommerce\Vaulting\Endpoint\DeletePaymentTokenEndpoint;
|
||||
|
||||
return array(
|
||||
'vaulting.module-url' => static function ( ContainerInterface $container ): string {
|
||||
|
@ -20,27 +18,11 @@ return array(
|
|||
dirname( realpath( __FILE__ ), 3 ) . '/woocommerce-paypal-payments.php'
|
||||
);
|
||||
},
|
||||
'vaulting.assets.myaccount-payments' => function( ContainerInterface $container ) : MyAccountPaymentsAssets {
|
||||
return new MyAccountPaymentsAssets(
|
||||
$container->get( 'vaulting.module-url' ),
|
||||
$container->get( 'ppcp.asset-version' )
|
||||
);
|
||||
},
|
||||
'vaulting.payment-tokens-renderer' => static function (): PaymentTokensRenderer {
|
||||
return new PaymentTokensRenderer();
|
||||
},
|
||||
'vaulting.repository.payment-token' => static function ( ContainerInterface $container ): PaymentTokenRepository {
|
||||
$factory = $container->get( 'api.factory.payment-token' );
|
||||
$endpoint = $container->get( 'api.endpoint.payment-token' );
|
||||
return new PaymentTokenRepository( $factory, $endpoint );
|
||||
},
|
||||
'vaulting.endpoint.delete' => function( ContainerInterface $container ) : DeletePaymentTokenEndpoint {
|
||||
return new DeletePaymentTokenEndpoint(
|
||||
$container->get( 'vaulting.repository.payment-token' ),
|
||||
$container->get( 'button.request-data' ),
|
||||
$container->get( 'woocommerce.logger.woocommerce' )
|
||||
);
|
||||
},
|
||||
'vaulting.payment-token-checker' => function( ContainerInterface $container ) : PaymentTokenChecker {
|
||||
return new PaymentTokenChecker(
|
||||
$container->get( 'vaulting.repository.payment-token' ),
|
||||
|
@ -70,4 +52,14 @@ return array(
|
|||
$container->get( 'wcgateway.settings' )
|
||||
);
|
||||
},
|
||||
'vaulting.payment-token-factory' => function( ContainerInterface $container ): PaymentTokenFactory {
|
||||
return new PaymentTokenFactory();
|
||||
},
|
||||
'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( 'woocommerce.logger.woocommerce' )
|
||||
);
|
||||
},
|
||||
);
|
||||
|
|
|
@ -1,77 +0,0 @@
|
|||
<?php
|
||||
/**
|
||||
* Register and configure assets for My account PayPal payments page.
|
||||
*
|
||||
* @package WooCommerce\PayPalCommerce\Vaulting\Assets
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace WooCommerce\PayPalCommerce\Vaulting\Assets;
|
||||
|
||||
use WooCommerce\PayPalCommerce\Vaulting\Endpoint\DeletePaymentTokenEndpoint;
|
||||
|
||||
/**
|
||||
* Class MyAccountPaymentsAssets
|
||||
*/
|
||||
class MyAccountPaymentsAssets {
|
||||
|
||||
/**
|
||||
* The URL to the module.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $module_url;
|
||||
|
||||
/**
|
||||
* The assets version.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $version;
|
||||
|
||||
/**
|
||||
* MyAccountPaymentsAssets constructor.
|
||||
*
|
||||
* @param string $module_url The URL to the module.
|
||||
* @param string $version The assets version.
|
||||
*/
|
||||
public function __construct(
|
||||
string $module_url,
|
||||
string $version
|
||||
) {
|
||||
$this->module_url = untrailingslashit( $module_url );
|
||||
$this->version = $version;
|
||||
}
|
||||
|
||||
/**
|
||||
* Enqueues the necessary scripts.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function enqueue(): void {
|
||||
wp_enqueue_script(
|
||||
'ppcp-vaulting-myaccount-payments',
|
||||
untrailingslashit( $this->module_url ) . '/assets/js/myaccount-payments.js',
|
||||
array( 'jquery' ),
|
||||
$this->version,
|
||||
true
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Localize script.
|
||||
*/
|
||||
public function localize() {
|
||||
wp_localize_script(
|
||||
'ppcp-vaulting-myaccount-payments',
|
||||
'PayPalCommerceGatewayVaulting',
|
||||
array(
|
||||
'delete' => array(
|
||||
'endpoint' => \WC_AJAX::get_endpoint( DeletePaymentTokenEndpoint::ENDPOINT ),
|
||||
'nonce' => wp_create_nonce( DeletePaymentTokenEndpoint::nonce() ),
|
||||
),
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
|
@ -1,95 +0,0 @@
|
|||
<?php
|
||||
/**
|
||||
* The endpoint for deleting payment tokens.
|
||||
*
|
||||
* @package WooCommerce\PayPalCommerce\Vaulting\Endpoint
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace WooCommerce\PayPalCommerce\Vaulting\Endpoint;
|
||||
|
||||
use Exception;
|
||||
use Psr\Log\LoggerInterface;
|
||||
use WooCommerce\PayPalCommerce\Button\Endpoint\RequestData;
|
||||
use WooCommerce\PayPalCommerce\Vaulting\PaymentTokenRepository;
|
||||
|
||||
/**
|
||||
* Class DeletePayment
|
||||
*/
|
||||
class DeletePaymentTokenEndpoint {
|
||||
|
||||
const ENDPOINT = 'ppc-vaulting-delete';
|
||||
|
||||
/**
|
||||
* The repository.
|
||||
*
|
||||
* @var PaymentTokenRepository
|
||||
*/
|
||||
protected $repository;
|
||||
|
||||
/**
|
||||
* The request data.
|
||||
*
|
||||
* @var RequestData
|
||||
*/
|
||||
protected $request_data;
|
||||
|
||||
/**
|
||||
* The logger.
|
||||
*
|
||||
* @var LoggerInterface
|
||||
*/
|
||||
protected $logger;
|
||||
|
||||
/**
|
||||
* DeletePaymentTokenEndpoint constructor.
|
||||
*
|
||||
* @param PaymentTokenRepository $repository The repository.
|
||||
* @param RequestData $request_data The request data.
|
||||
* @param LoggerInterface $logger The logger.
|
||||
*/
|
||||
public function __construct( PaymentTokenRepository $repository, RequestData $request_data, LoggerInterface $logger ) {
|
||||
$this->repository = $repository;
|
||||
$this->request_data = $request_data;
|
||||
$this->logger = $logger;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the nonce for the endpoint.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function nonce(): string {
|
||||
return self::ENDPOINT;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles the incoming request.
|
||||
*/
|
||||
public function handle_request() {
|
||||
try {
|
||||
$data = $this->request_data->read_request( $this->nonce() );
|
||||
|
||||
$tokens = $this->repository->all_for_user_id( get_current_user_id() );
|
||||
if ( $tokens ) {
|
||||
foreach ( $tokens as $token ) {
|
||||
if ( isset( $data['token'] ) && $token->id() === $data['token'] ) {
|
||||
if ( $this->repository->delete_token( get_current_user_id(), $token ) ) {
|
||||
wp_send_json_success();
|
||||
return true;
|
||||
}
|
||||
|
||||
wp_send_json_error( 'Could not delete payment token.' );
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch ( Exception $error ) {
|
||||
$this->logger->error( 'Failed to delete payment: ' . $error->getMessage() );
|
||||
wp_send_json_error( $error->getMessage(), 403 );
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
72
modules/ppcp-vaulting/src/PaymentTokenACDC.php
Normal file
72
modules/ppcp-vaulting/src/PaymentTokenACDC.php
Normal file
|
@ -0,0 +1,72 @@
|
|||
<?php
|
||||
/**
|
||||
* WooCommerce Payment token for PayPal ACDC (Advanced Credit and Debit Card).
|
||||
*
|
||||
* @package WooCommerce\PayPalCommerce\Vaulting
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace WooCommerce\PayPalCommerce\Vaulting;
|
||||
|
||||
use WC_Payment_Token;
|
||||
|
||||
/**
|
||||
* Class PaymentTokenACDC
|
||||
*/
|
||||
class PaymentTokenACDC extends WC_Payment_Token {
|
||||
/**
|
||||
* Token Type String.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $type = 'ACDC';
|
||||
|
||||
/**
|
||||
* Stores Credit Card payment token data.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $extra_data = array(
|
||||
'last4' => '',
|
||||
'card_type' => '',
|
||||
);
|
||||
|
||||
/**
|
||||
* Returns the last four digits.
|
||||
*
|
||||
* @param string $context The context.
|
||||
* @return mixed|null
|
||||
*/
|
||||
public function get_last4( $context = 'view' ) {
|
||||
return $this->get_prop( 'last4', $context );
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the last four digits.
|
||||
*
|
||||
* @param string $last4 Last four digits.
|
||||
*/
|
||||
public function set_last4( $last4 ) {
|
||||
$this->set_prop( 'last4', $last4 );
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the card type (mastercard, visa, ...).
|
||||
*
|
||||
* @param string $context The context.
|
||||
* @return string Card type
|
||||
*/
|
||||
public function get_card_type( $context = 'view' ) {
|
||||
return $this->get_prop( 'card_type', $context );
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the card type (mastercard, visa, ...).
|
||||
*
|
||||
* @param string $type Credit card type (mastercard, visa, ...).
|
||||
*/
|
||||
public function set_card_type( $type ) {
|
||||
$this->set_prop( 'card_type', $type );
|
||||
}
|
||||
}
|
32
modules/ppcp-vaulting/src/PaymentTokenFactory.php
Normal file
32
modules/ppcp-vaulting/src/PaymentTokenFactory.php
Normal file
|
@ -0,0 +1,32 @@
|
|||
<?php
|
||||
/**
|
||||
* WooCommerce Payment token factory.
|
||||
*
|
||||
* @package WooCommerce\PayPalCommerce\Vaulting
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace WooCommerce\PayPalCommerce\Vaulting;
|
||||
|
||||
/**
|
||||
* Class PaymentTokenFactory
|
||||
*/
|
||||
class PaymentTokenFactory {
|
||||
|
||||
/**
|
||||
* Creates a new WC payment token instance of the given type.
|
||||
*
|
||||
* @param string $type The type of WC payment token.
|
||||
*
|
||||
* @return void|PaymentTokenACDC|PaymentTokenPayPal
|
||||
*/
|
||||
public function create( string $type ) {
|
||||
switch ( $type ) {
|
||||
case 'paypal':
|
||||
return new PaymentTokenPayPal();
|
||||
case 'acdc':
|
||||
return new PaymentTokenACDC();
|
||||
}
|
||||
}
|
||||
}
|
51
modules/ppcp-vaulting/src/PaymentTokenPayPal.php
Normal file
51
modules/ppcp-vaulting/src/PaymentTokenPayPal.php
Normal file
|
@ -0,0 +1,51 @@
|
|||
<?php
|
||||
/**
|
||||
* WooCommerce Payment token for PayPal.
|
||||
*
|
||||
* @package WooCommerce\PayPalCommerce\Vaulting
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace WooCommerce\PayPalCommerce\Vaulting;
|
||||
|
||||
use WC_Payment_Token;
|
||||
|
||||
/**
|
||||
* Class PaymentTokenPayPal
|
||||
*/
|
||||
class PaymentTokenPayPal extends WC_Payment_Token {
|
||||
/**
|
||||
* Token Type String.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $type = 'PayPal';
|
||||
|
||||
/**
|
||||
* Extra data.
|
||||
*
|
||||
* @var string[]
|
||||
*/
|
||||
protected $extra_data = array(
|
||||
'email' => '',
|
||||
);
|
||||
|
||||
/**
|
||||
* Get PayPal account email.
|
||||
*
|
||||
* @return string PayPal account email.
|
||||
*/
|
||||
public function get_email() {
|
||||
return $this->get_meta( 'email' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Set PayPal account email.
|
||||
*
|
||||
* @param string $email PayPal account email.
|
||||
*/
|
||||
public function set_email( $email ) {
|
||||
$this->add_meta_data( 'email', $email, true );
|
||||
}
|
||||
}
|
|
@ -20,8 +20,6 @@ use WooCommerce\PayPalCommerce\ApiClient\Factory\PaymentTokenFactory;
|
|||
class PaymentTokenRepository {
|
||||
|
||||
|
||||
const USER_META = 'ppcp-vault-token';
|
||||
|
||||
/**
|
||||
* The payment token factory.
|
||||
*
|
||||
|
@ -51,27 +49,6 @@ class PaymentTokenRepository {
|
|||
$this->endpoint = $endpoint;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a token for a user.
|
||||
*
|
||||
* @param int $id The user id.
|
||||
*
|
||||
* @return PaymentToken|null
|
||||
*/
|
||||
public function for_user_id( int $id ) {
|
||||
try {
|
||||
$token = (array) get_user_meta( $id, self::USER_META, true );
|
||||
if ( ! $token || ! isset( $token['id'] ) ) {
|
||||
return $this->fetch_for_user_id( $id );
|
||||
}
|
||||
|
||||
$token = $this->factory->from_array( $token );
|
||||
return $token;
|
||||
} catch ( RuntimeException $error ) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return all tokens for a user.
|
||||
*
|
||||
|
@ -81,7 +58,6 @@ class PaymentTokenRepository {
|
|||
public function all_for_user_id( int $id ) {
|
||||
try {
|
||||
$tokens = $this->endpoint->for_user( $id );
|
||||
update_user_meta( $id, self::USER_META, $tokens );
|
||||
return $tokens;
|
||||
} catch ( RuntimeException $exception ) {
|
||||
return array();
|
||||
|
@ -97,7 +73,6 @@ class PaymentTokenRepository {
|
|||
* @return bool
|
||||
*/
|
||||
public function delete_token( int $user_id, PaymentToken $token ): bool {
|
||||
delete_user_meta( $user_id, self::USER_META );
|
||||
return $this->endpoint->delete_token( $token );
|
||||
}
|
||||
|
||||
|
@ -121,21 +96,6 @@ class PaymentTokenRepository {
|
|||
return $this->token_contains_source( $tokens, 'paypal' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch PaymentToken from PayPal for a user.
|
||||
*
|
||||
* @param int $id The user id.
|
||||
* @return PaymentToken
|
||||
*/
|
||||
private function fetch_for_user_id( int $id ): PaymentToken {
|
||||
|
||||
$tokens = $this->endpoint->for_user( $id );
|
||||
$token = current( $tokens );
|
||||
$token_array = $token->to_array();
|
||||
update_user_meta( $id, self::USER_META, $token_array );
|
||||
return $token;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if tokens has the given source.
|
||||
*
|
||||
|
|
136
modules/ppcp-vaulting/src/PaymentTokensMigration.php
Normal file
136
modules/ppcp-vaulting/src/PaymentTokensMigration.php
Normal file
|
@ -0,0 +1,136 @@
|
|||
<?php
|
||||
/**
|
||||
* The payment tokens migration handler.
|
||||
*
|
||||
* @package WooCommerce\PayPalCommerce\Vaulting
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace WooCommerce\PayPalCommerce\Vaulting;
|
||||
|
||||
use Exception;
|
||||
use Psr\Log\LoggerInterface;
|
||||
use WC_Payment_Tokens;
|
||||
use WooCommerce\PayPalCommerce\ApiClient\Entity\PaymentToken;
|
||||
use WooCommerce\PayPalCommerce\WcGateway\Gateway\CreditCardGateway;
|
||||
use WooCommerce\PayPalCommerce\WcGateway\Gateway\PayPalGateway;
|
||||
|
||||
/**
|
||||
* Class PaymentTokensMigration
|
||||
*/
|
||||
class PaymentTokensMigration {
|
||||
/**
|
||||
* The payment token factory.
|
||||
*
|
||||
* @var PaymentTokenFactory
|
||||
*/
|
||||
private $payment_token_factory;
|
||||
|
||||
/**
|
||||
* The payment token repository.
|
||||
*
|
||||
* @var PaymentTokenRepository
|
||||
*/
|
||||
private $payment_token_repository;
|
||||
|
||||
/**
|
||||
* The logger.
|
||||
*
|
||||
* @var LoggerInterface
|
||||
*/
|
||||
private $logger;
|
||||
|
||||
/**
|
||||
* PaymentTokensMigration constructor.
|
||||
*
|
||||
* @param PaymentTokenFactory $payment_token_factory The payment token factory.
|
||||
* @param PaymentTokenRepository $payment_token_repository The payment token repository.
|
||||
* @param LoggerInterface $logger The logger.
|
||||
*/
|
||||
public function __construct(
|
||||
PaymentTokenFactory $payment_token_factory,
|
||||
PaymentTokenRepository $payment_token_repository,
|
||||
LoggerInterface $logger
|
||||
) {
|
||||
$this->payment_token_factory = $payment_token_factory;
|
||||
$this->payment_token_repository = $payment_token_repository;
|
||||
$this->logger = $logger;
|
||||
}
|
||||
|
||||
/**
|
||||
* Migrates user existing vaulted tokens into WC payment tokens API.
|
||||
*
|
||||
* @param int $id WooCommerce customer id.
|
||||
*/
|
||||
public function migrate_payment_tokens_for_user( int $id ):void {
|
||||
$tokens = $this->payment_token_repository->all_for_user_id( $id );
|
||||
$wc_tokens = WC_Payment_Tokens::get_customer_tokens( $id );
|
||||
|
||||
foreach ( $tokens as $token ) {
|
||||
if ( $this->token_exist( $wc_tokens, $token ) ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ( isset( $token->source()->card ) ) {
|
||||
$payment_token_acdc = $this->payment_token_factory->create( 'acdc' );
|
||||
assert( $payment_token_acdc instanceof PaymentTokenACDC );
|
||||
|
||||
$payment_token_acdc->set_token( $token->id() );
|
||||
$payment_token_acdc->set_user_id( $id );
|
||||
$payment_token_acdc->set_gateway_id( CreditCardGateway::ID );
|
||||
$payment_token_acdc->set_last4( $token->source()->card->last_digits );
|
||||
$payment_token_acdc->set_card_type( $token->source()->card->brand );
|
||||
|
||||
try {
|
||||
$payment_token_acdc->save();
|
||||
} catch ( Exception $exception ) {
|
||||
$this->logger->error(
|
||||
"Could not save WC payment token credit card {$token->id()} for user {$id}. "
|
||||
. $exception->getMessage()
|
||||
);
|
||||
continue;
|
||||
}
|
||||
} elseif ( $token->source()->paypal ) {
|
||||
$payment_token_paypal = $this->payment_token_factory->create( 'paypal' );
|
||||
assert( $payment_token_paypal instanceof PaymentTokenPayPal );
|
||||
|
||||
$payment_token_paypal->set_token( $token->id() );
|
||||
$payment_token_paypal->set_user_id( $id );
|
||||
$payment_token_paypal->set_gateway_id( PayPalGateway::ID );
|
||||
|
||||
$email = $token->source()->paypal->payer->email_address ?? '';
|
||||
if ( $email && is_email( $email ) ) {
|
||||
$payment_token_paypal->set_email( $email );
|
||||
}
|
||||
|
||||
try {
|
||||
$payment_token_paypal->save();
|
||||
} catch ( Exception $exception ) {
|
||||
$this->logger->error(
|
||||
"Could not save WC payment token PayPal {$token->id()} for user {$id}. "
|
||||
. $exception->getMessage()
|
||||
);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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;
|
||||
}
|
||||
}
|
|
@ -1,83 +0,0 @@
|
|||
<?php
|
||||
/**
|
||||
* The payment tokens renderer.
|
||||
*
|
||||
* @package WooCommerce\PayPalCommerce\Vaulting
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace WooCommerce\PayPalCommerce\Vaulting;
|
||||
|
||||
use WooCommerce\PayPalCommerce\ApiClient\Entity\PaymentToken;
|
||||
|
||||
/**
|
||||
* Class PaymentTokensRendered
|
||||
*/
|
||||
class PaymentTokensRenderer {
|
||||
|
||||
/**
|
||||
* Render payment tokens.
|
||||
*
|
||||
* @param PaymentToken[] $tokens The tokens.
|
||||
* @return false|string
|
||||
*/
|
||||
public function render( array $tokens ) {
|
||||
ob_start();
|
||||
?>
|
||||
<table class="shop_table shop_table_responsive">
|
||||
<thead>
|
||||
<tr>
|
||||
<th><?php echo esc_html__( 'Payment sources', 'woocommerce-paypal-payments' ); ?></th>
|
||||
<th></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php
|
||||
foreach ( $tokens as $token ) {
|
||||
$source = $token->source() ?? null;
|
||||
if ( $source && isset( $source->card ) ) {
|
||||
?>
|
||||
<tr>
|
||||
<td><?php echo esc_attr( $source->card->brand ) . ' ...' . esc_attr( $source->card->last_digits ); ?></td>
|
||||
<td>
|
||||
<a class="ppcp-delete-payment-button" id="<?php echo esc_attr( $token->id() ); ?>" href=""><?php echo esc_html__( 'Delete', 'woocommerce-paypal-payments' ); ?></a>
|
||||
</td>
|
||||
</tr>
|
||||
<?php
|
||||
}
|
||||
if ( $source && isset( $source->paypal ) ) {
|
||||
?>
|
||||
<tr>
|
||||
<td><?php echo esc_attr( $source->paypal->payer->email_address ); ?></td>
|
||||
<td>
|
||||
<a class="ppcp-delete-payment-button" id="<?php echo esc_attr( $token->id() ); ?>" href=""><?php echo esc_html__( 'Delete', 'woocommerce-paypal-payments' ); ?></a>
|
||||
</td>
|
||||
</tr>
|
||||
<?php
|
||||
}
|
||||
?>
|
||||
<?php
|
||||
}
|
||||
?>
|
||||
</tbody>
|
||||
</table>
|
||||
<?php
|
||||
return ob_get_clean();
|
||||
}
|
||||
|
||||
/**
|
||||
* Render no payments message.
|
||||
*
|
||||
* @return false|string
|
||||
*/
|
||||
public function render_no_tokens() {
|
||||
ob_start();
|
||||
?>
|
||||
<div class="woocommerce-Message woocommerce-Message--info woocommerce-info">
|
||||
<?php echo esc_html__( 'No payments available yet.', 'woocommerce-paypal-payments' ); ?>
|
||||
</div>
|
||||
<?php
|
||||
return ob_get_clean();
|
||||
}
|
||||
}
|
|
@ -9,6 +9,9 @@ declare(strict_types=1);
|
|||
|
||||
namespace WooCommerce\PayPalCommerce\Vaulting;
|
||||
|
||||
use RuntimeException;
|
||||
use WC_Payment_Token;
|
||||
use WC_Payment_Tokens;
|
||||
use WooCommerce\PayPalCommerce\Vendor\Dhii\Container\ServiceProvider;
|
||||
use WooCommerce\PayPalCommerce\Vendor\Dhii\Modular\Module\ModuleInterface;
|
||||
use WooCommerce\PayPalCommerce\Vendor\Interop\Container\ServiceProviderInterface;
|
||||
|
@ -16,9 +19,10 @@ use WooCommerce\PayPalCommerce\Vendor\Psr\Container\ContainerInterface;
|
|||
use Psr\Log\LoggerInterface;
|
||||
use WC_Order;
|
||||
use WooCommerce\PayPalCommerce\Subscription\Helper\SubscriptionHelper;
|
||||
use WooCommerce\PayPalCommerce\Vaulting\Endpoint\DeletePaymentTokenEndpoint;
|
||||
use WooCommerce\PayPalCommerce\WcGateway\Exception\NotFoundException;
|
||||
use WooCommerce\PayPalCommerce\WcGateway\Settings\Settings;
|
||||
use WooCommerce\PayPalCommerce\WcGateway\Gateway\CreditCardGateway;
|
||||
use WooCommerce\PayPalCommerce\WcGateway\Gateway\PayPalGateway;
|
||||
use WP_User_Query;
|
||||
|
||||
/**
|
||||
* Class StatusReportModule
|
||||
|
@ -43,7 +47,6 @@ class VaultingModule implements ModuleInterface {
|
|||
* @throws NotFoundException When service could not be found.
|
||||
*/
|
||||
public function run( ContainerInterface $container ): void {
|
||||
|
||||
$settings = $container->get( 'wcgateway.settings' );
|
||||
if ( ! $settings->has( 'vault_enabled' ) || ! $settings->get( 'vault_enabled' ) ) {
|
||||
return;
|
||||
|
@ -54,61 +57,6 @@ class VaultingModule implements ModuleInterface {
|
|||
|
||||
$listener->listen();
|
||||
|
||||
add_filter(
|
||||
'woocommerce_account_menu_items',
|
||||
function( $menu_links ) {
|
||||
$menu_links = array_slice( $menu_links, 0, 5, true )
|
||||
+ array( 'ppcp-paypal-payment-tokens' => __( 'PayPal payments', 'woocommerce-paypal-payments' ) )
|
||||
+ array_slice( $menu_links, 5, null, true );
|
||||
|
||||
return $menu_links;
|
||||
},
|
||||
40
|
||||
);
|
||||
|
||||
add_action(
|
||||
'init',
|
||||
function () {
|
||||
add_rewrite_endpoint( 'ppcp-paypal-payment-tokens', EP_PAGES );
|
||||
}
|
||||
);
|
||||
|
||||
add_action(
|
||||
'woocommerce_paypal_payments_gateway_migrate',
|
||||
function () {
|
||||
add_action(
|
||||
'init',
|
||||
function () {
|
||||
add_rewrite_endpoint( 'ppcp-paypal-payment-tokens', EP_PAGES );
|
||||
flush_rewrite_rules();
|
||||
}
|
||||
);
|
||||
}
|
||||
);
|
||||
|
||||
add_action(
|
||||
'woocommerce_paypal_payments_gateway_activate',
|
||||
function () {
|
||||
add_rewrite_endpoint( 'ppcp-paypal-payment-tokens', EP_PAGES );
|
||||
flush_rewrite_rules();
|
||||
}
|
||||
);
|
||||
|
||||
add_action(
|
||||
'woocommerce_account_ppcp-paypal-payment-tokens_endpoint',
|
||||
function () use ( $container ) {
|
||||
$payment_token_repository = $container->get( 'vaulting.repository.payment-token' );
|
||||
$renderer = $container->get( 'vaulting.payment-tokens-renderer' );
|
||||
|
||||
$tokens = $payment_token_repository->all_for_user_id( get_current_user_id() );
|
||||
if ( $tokens ) {
|
||||
echo wp_kses_post( $renderer->render( $tokens ) );
|
||||
} else {
|
||||
echo wp_kses_post( $renderer->render_no_tokens() );
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
$subscription_helper = $container->get( 'subscription.helper' );
|
||||
add_action(
|
||||
'woocommerce_created_customer',
|
||||
|
@ -124,27 +72,6 @@ class VaultingModule implements ModuleInterface {
|
|||
}
|
||||
);
|
||||
|
||||
$asset_loader = $container->get( 'vaulting.assets.myaccount-payments' );
|
||||
add_action(
|
||||
'wp_enqueue_scripts',
|
||||
function () use ( $asset_loader ) {
|
||||
if ( is_account_page() && $this->is_payments_page() ) {
|
||||
$asset_loader->enqueue();
|
||||
$asset_loader->localize();
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
add_action(
|
||||
'wc_ajax_' . DeletePaymentTokenEndpoint::ENDPOINT,
|
||||
static function () use ( $container ) {
|
||||
$endpoint = $container->get( 'vaulting.endpoint.delete' );
|
||||
assert( $endpoint instanceof DeletePaymentTokenEndpoint );
|
||||
|
||||
$endpoint->handle_request();
|
||||
}
|
||||
);
|
||||
|
||||
add_action(
|
||||
'woocommerce_paypal_payments_check_saved_payment',
|
||||
function ( int $order_id, int $customer_id, string $intent ) use ( $container ) {
|
||||
|
@ -156,6 +83,133 @@ class VaultingModule implements ModuleInterface {
|
|||
);
|
||||
|
||||
$this->filterFailedVaultingEmailsForSubscriptionOrders( $container );
|
||||
|
||||
add_filter(
|
||||
'woocommerce_payment_token_class',
|
||||
/**
|
||||
* Param types removed to avoid third-party issues.
|
||||
*
|
||||
* @psalm-suppress MissingClosureParamType
|
||||
*/
|
||||
function ( $type ) {
|
||||
if ( $type === 'WC_Payment_Token_ACDC' ) {
|
||||
return PaymentTokenACDC::class;
|
||||
}
|
||||
|
||||
if ( $type === 'WC_Payment_Token_PayPal' ) {
|
||||
return PaymentTokenPayPal::class;
|
||||
}
|
||||
|
||||
return $type;
|
||||
}
|
||||
);
|
||||
|
||||
add_filter(
|
||||
'woocommerce_payment_methods_list_item',
|
||||
/**
|
||||
* Param types removed to avoid third-party issues.
|
||||
*
|
||||
* @psalm-suppress MissingClosureParamType
|
||||
*/
|
||||
function( $item, $payment_token ) {
|
||||
if ( ! is_array( $item ) || ! is_a( $payment_token, WC_Payment_Token::class ) ) {
|
||||
return $item;
|
||||
}
|
||||
|
||||
if ( strtolower( $payment_token->get_type() ) === 'acdc' ) {
|
||||
assert( $payment_token instanceof PaymentTokenACDC );
|
||||
$item['method']['brand'] = $payment_token->get_card_type() . ' ...' . $payment_token->get_last4();
|
||||
|
||||
return $item;
|
||||
}
|
||||
|
||||
if ( strtolower( $payment_token->get_type() ) === 'paypal' ) {
|
||||
assert( $payment_token instanceof PaymentTokenPayPal );
|
||||
$item['method']['brand'] = $payment_token->get_email();
|
||||
|
||||
return $item;
|
||||
}
|
||||
|
||||
return $item;
|
||||
},
|
||||
10,
|
||||
2
|
||||
);
|
||||
|
||||
add_action(
|
||||
'wp',
|
||||
function() use ( $container ) {
|
||||
global $wp;
|
||||
|
||||
if ( isset( $wp->query_vars['delete-payment-method'] ) ) {
|
||||
$token_id = absint( $wp->query_vars['delete-payment-method'] );
|
||||
$token = WC_Payment_Tokens::get( $token_id );
|
||||
|
||||
if (
|
||||
is_null( $token )
|
||||
|| ( $token->get_gateway_id() !== PayPalGateway::ID && $token->get_gateway_id() !== CreditCardGateway::ID )
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
$wpnonce = wc_clean( wp_unslash( $_REQUEST['_wpnonce'] ?? '' ) );
|
||||
$token_id_string = (string) $token_id;
|
||||
$action = 'delete-payment-method-' . $token_id_string;
|
||||
if (
|
||||
$token->get_user_id() !== get_current_user_id()
|
||||
|| ! isset( $wpnonce ) || ! is_string( $wpnonce )
|
||||
|| wp_verify_nonce( $wpnonce, $action ) === false
|
||||
) {
|
||||
wc_add_notice( __( 'Invalid payment method.', 'woocommerce-paypal-payments' ), 'error' );
|
||||
wp_safe_redirect( wc_get_account_endpoint_url( 'payment-methods' ) );
|
||||
exit();
|
||||
}
|
||||
|
||||
try {
|
||||
$payment_token_endpoint = $container->get( 'api.endpoint.payment-token' );
|
||||
$payment_token_endpoint->delete_token_by_id( $token->get_token() );
|
||||
} catch ( RuntimeException $exception ) {
|
||||
wc_add_notice( __( 'Could not delete payment token. ', 'woocommerce-paypal-payments' ) . $exception->getMessage(), 'error' );
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
add_action(
|
||||
'woocommerce_paypal_payments_gateway_migrate_on_update',
|
||||
function () use ( $container ) {
|
||||
// phpcs:disable WordPress.DB.SlowDBQuery.slow_db_query_meta_key
|
||||
// phpcs:disable WordPress.DB.SlowDBQuery.slow_db_query_meta_query
|
||||
$customers = new WP_User_Query(
|
||||
array(
|
||||
'fields' => 'ID',
|
||||
'limit' => -1,
|
||||
'meta_key' => 'ppcp-vault-token',
|
||||
)
|
||||
);
|
||||
// phpcs:enable
|
||||
|
||||
$migrate = $container->get( 'vaulting.payment-tokens-migration' );
|
||||
assert( $migrate instanceof PaymentTokensMigration );
|
||||
|
||||
foreach ( $customers->get_results() as $id ) {
|
||||
$migrate->migrate_payment_tokens_for_user( (int) $id );
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
add_filter(
|
||||
'woocommerce_available_payment_gateways',
|
||||
function( array $methods ): array {
|
||||
global $wp;
|
||||
if ( isset( $wp->query_vars['add-payment-method'] ) ) {
|
||||
unset( $methods[ PayPalGateway::ID ] );
|
||||
}
|
||||
|
||||
return $methods;
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -1,22 +0,0 @@
|
|||
const path = require('path');
|
||||
const isProduction = process.env.NODE_ENV === 'production';
|
||||
|
||||
module.exports = {
|
||||
devtool: isProduction ? 'source-map' : 'eval-source-map',
|
||||
mode: isProduction ? 'production' : 'development',
|
||||
target: 'web',
|
||||
entry: {
|
||||
'myaccount-payments': path.resolve('./resources/js/myaccount-payments.js'),
|
||||
},
|
||||
output: {
|
||||
path: path.resolve(__dirname, 'assets/'),
|
||||
filename: 'js/[name].js',
|
||||
},
|
||||
module: {
|
||||
rules: [{
|
||||
test: /\.js?$/,
|
||||
exclude: /node_modules/,
|
||||
loader: 'babel-loader',
|
||||
}]
|
||||
}
|
||||
};
|
|
@ -202,7 +202,7 @@ class PayPalGateway extends \WC_Payment_Gateway {
|
|||
$this->api_shop_country = $api_shop_country;
|
||||
|
||||
if ( $this->onboarded ) {
|
||||
$this->supports = array( 'refunds' );
|
||||
$this->supports = array( 'refunds', 'tokenization' );
|
||||
}
|
||||
if (
|
||||
defined( 'PPCP_FLAG_SUBSCRIPTION' )
|
||||
|
@ -223,6 +223,7 @@ class PayPalGateway extends \WC_Payment_Gateway {
|
|||
'subscription_payment_method_change_customer',
|
||||
'subscription_payment_method_change_admin',
|
||||
'multiple_subscriptions',
|
||||
'tokenization',
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -168,8 +168,7 @@ class SettingsListener {
|
|||
* Listens if the merchant ID should be updated.
|
||||
*/
|
||||
public function listen_for_merchant_id() {
|
||||
|
||||
if ( ! $this->is_valid_site_request() ) {
|
||||
if ( ! $this->is_valid_site_request() || $this->state->current_state() === State::STATE_ONBOARDED ) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -28,6 +28,7 @@ use WooCommerce\PayPalCommerce\Webhooks\Handler\PaymentCaptureReversed;
|
|||
use WooCommerce\PayPalCommerce\Vendor\Psr\Container\ContainerInterface;
|
||||
use WooCommerce\PayPalCommerce\Webhooks\Handler\VaultCreditCardCreated;
|
||||
use WooCommerce\PayPalCommerce\Webhooks\Handler\VaultPaymentTokenCreated;
|
||||
use WooCommerce\PayPalCommerce\Webhooks\Handler\VaultPaymentTokenDeleted;
|
||||
use WooCommerce\PayPalCommerce\Webhooks\Status\Assets\WebhooksStatusPageAssets;
|
||||
use WooCommerce\PayPalCommerce\Webhooks\Status\WebhookSimulation;
|
||||
|
||||
|
@ -73,6 +74,8 @@ return array(
|
|||
$prefix = $container->get( 'api.prefix' );
|
||||
$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' );
|
||||
|
||||
return array(
|
||||
new CheckoutOrderApproved( $logger, $prefix, $order_endpoint ),
|
||||
new CheckoutOrderCompleted( $logger, $prefix ),
|
||||
|
@ -80,8 +83,8 @@ return array(
|
|||
new PaymentCaptureRefunded( $logger, $prefix ),
|
||||
new PaymentCaptureReversed( $logger, $prefix ),
|
||||
new PaymentCaptureCompleted( $logger, $prefix, $order_endpoint ),
|
||||
new VaultPaymentTokenCreated( $logger, $prefix, $authorized_payments_processor ),
|
||||
new VaultCreditCardCreated( $logger, $prefix ),
|
||||
new VaultPaymentTokenCreated( $logger, $prefix, $authorized_payments_processor, $payment_token_factory ),
|
||||
new VaultPaymentTokenDeleted( $logger ),
|
||||
new PaymentCapturePending( $logger ),
|
||||
);
|
||||
},
|
||||
|
|
|
@ -10,6 +10,12 @@ declare(strict_types=1);
|
|||
namespace WooCommerce\PayPalCommerce\Webhooks\Handler;
|
||||
|
||||
use Psr\Log\LoggerInterface;
|
||||
use WC_Payment_Token_CC;
|
||||
use WC_Payment_Tokens;
|
||||
use WooCommerce\PayPalCommerce\Vaulting\PaymentTokenFactory;
|
||||
use WooCommerce\PayPalCommerce\Vaulting\PaymentTokenPayPal;
|
||||
use WooCommerce\PayPalCommerce\WcGateway\Gateway\CreditCardGateway;
|
||||
use WooCommerce\PayPalCommerce\WcGateway\Gateway\PayPalGateway;
|
||||
use WooCommerce\PayPalCommerce\WcGateway\Processor\AuthorizedPaymentsProcessor;
|
||||
use WP_REST_Request;
|
||||
use WP_REST_Response;
|
||||
|
@ -40,17 +46,31 @@ class VaultPaymentTokenCreated implements RequestHandler {
|
|||
*/
|
||||
protected $authorized_payments_processor;
|
||||
|
||||
/**
|
||||
* The payment token factory.
|
||||
*
|
||||
* @var PaymentTokenFactory
|
||||
*/
|
||||
protected $payment_token_factory;
|
||||
|
||||
/**
|
||||
* VaultPaymentTokenCreated constructor.
|
||||
*
|
||||
* @param LoggerInterface $logger The logger.
|
||||
* @param string $prefix The prefix.
|
||||
* @param AuthorizedPaymentsProcessor $authorized_payments_processor The authorized payment processor.
|
||||
* @param PaymentTokenFactory $payment_token_factory The payment token factory.
|
||||
*/
|
||||
public function __construct( LoggerInterface $logger, string $prefix, AuthorizedPaymentsProcessor $authorized_payments_processor ) {
|
||||
public function __construct(
|
||||
LoggerInterface $logger,
|
||||
string $prefix,
|
||||
AuthorizedPaymentsProcessor $authorized_payments_processor,
|
||||
PaymentTokenFactory $payment_token_factory
|
||||
) {
|
||||
$this->logger = $logger;
|
||||
$this->prefix = $prefix;
|
||||
$this->authorized_payments_processor = $authorized_payments_processor;
|
||||
$this->payment_token_factory = $payment_token_factory;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -98,6 +118,38 @@ class VaultPaymentTokenCreated implements RequestHandler {
|
|||
$wc_customer_id = (int) str_replace( $this->prefix, '', $customer_id );
|
||||
$this->authorized_payments_processor->capture_authorized_payments_for_customer( $wc_customer_id );
|
||||
|
||||
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 );
|
||||
|
||||
$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 );
|
||||
}
|
||||
|
||||
$payment_token_paypal->save();
|
||||
WC_Payment_Tokens::set_users_default( $wc_customer_id, $payment_token_paypal->get_id() );
|
||||
}
|
||||
}
|
||||
|
||||
$response['success'] = true;
|
||||
return new WP_REST_Response( $response );
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<?php
|
||||
/**
|
||||
* Handles the Webhook VAULT.CREDIT-CARD.CREATED
|
||||
* Handles the Webhook VAULT.PAYMENT-TOKEN.DELETED
|
||||
*
|
||||
* @package WooCommerce\PayPalCommerce\Webhooks\Handler
|
||||
*/
|
||||
|
@ -10,37 +10,29 @@ declare(strict_types=1);
|
|||
namespace WooCommerce\PayPalCommerce\Webhooks\Handler;
|
||||
|
||||
use Psr\Log\LoggerInterface;
|
||||
use WC_Payment_Tokens;
|
||||
use WP_REST_Request;
|
||||
use WP_REST_Response;
|
||||
|
||||
/**
|
||||
* Class VaultCreditCardCreated
|
||||
* Class VaultPaymentTokenDeleted
|
||||
*/
|
||||
class VaultCreditCardCreated implements RequestHandler {
|
||||
class VaultPaymentTokenDeleted implements RequestHandler {
|
||||
|
||||
/**
|
||||
* The logger.
|
||||
*
|
||||
* @var LoggerInterface
|
||||
*/
|
||||
protected $logger;
|
||||
private $logger;
|
||||
|
||||
/**
|
||||
* The prefix.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $prefix;
|
||||
|
||||
/**
|
||||
* VaultCreditCardCreated constructor.
|
||||
* VaultPaymentTokenDeleted constructor.
|
||||
*
|
||||
* @param LoggerInterface $logger The logger.
|
||||
* @param string $prefix The prefix.
|
||||
*/
|
||||
public function __construct( LoggerInterface $logger, string $prefix ) {
|
||||
public function __construct( LoggerInterface $logger ) {
|
||||
$this->logger = $logger;
|
||||
$this->prefix = $prefix;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -50,7 +42,7 @@ class VaultCreditCardCreated implements RequestHandler {
|
|||
*/
|
||||
public function event_types(): array {
|
||||
return array(
|
||||
'VAULT.CREDIT-CARD.CREATED',
|
||||
'VAULT.PAYMENT-TOKEN.DELETED',
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -73,15 +65,31 @@ class VaultCreditCardCreated implements RequestHandler {
|
|||
* @return WP_REST_Response
|
||||
*/
|
||||
public function handle_request( WP_REST_Request $request ): WP_REST_Response {
|
||||
// TODO currently this webhook is not triggered from PayPal, implement it once is available.
|
||||
$response = array( 'success' => false );
|
||||
|
||||
$message = 'VAULT.CREDIT-CARD.CREATED received.';
|
||||
$this->logger->log( 'info', $message );
|
||||
$response = array(
|
||||
'success' => true,
|
||||
'message' => $message,
|
||||
);
|
||||
if ( ! is_null( $request['resource'] ) && isset( $request['resource']['id'] ) ) {
|
||||
$token_id = wc_clean( wp_unslash( $request['resource']['id'] ?? '' ) );
|
||||
|
||||
/**
|
||||
* Needed for database query.
|
||||
*
|
||||
* @psalm-suppress InvalidGlobal
|
||||
*/
|
||||
global $wpdb;
|
||||
|
||||
$token = $wpdb->get_row(
|
||||
$wpdb->prepare(
|
||||
"SELECT * FROM {$wpdb->prefix}woocommerce_payment_tokens WHERE token=%s",
|
||||
$token_id
|
||||
)
|
||||
);
|
||||
|
||||
if ( isset( $token->token_id ) ) {
|
||||
WC_Payment_Tokens::delete( $token->token_id );
|
||||
}
|
||||
}
|
||||
|
||||
$response['success'] = true;
|
||||
return new WP_REST_Response( $response );
|
||||
}
|
||||
}
|
|
@ -11,7 +11,6 @@
|
|||
"install:modules:ppcp-button": "cd modules/ppcp-button && yarn install",
|
||||
"install:modules:ppcp-wc-gateway": "cd modules/ppcp-wc-gateway && yarn install",
|
||||
"install:modules:ppcp-webhooks": "cd modules/ppcp-webhooks && yarn install",
|
||||
"install:modules:ppcp-vaulting": "cd modules/ppcp-vaulting && yarn install",
|
||||
"install:modules:ppcp-order-tracking": "cd modules/ppcp-order-tracking && yarn install",
|
||||
"install:modules:ppcp-onboarding": "cd modules/ppcp-onboarding && yarn install",
|
||||
"install:modules:ppcp-compat": "cd modules/ppcp-compat && yarn install",
|
||||
|
@ -20,7 +19,6 @@
|
|||
"build:modules:ppcp-button": "cd modules/ppcp-button && yarn run build",
|
||||
"build:modules:ppcp-wc-gateway": "cd modules/ppcp-wc-gateway && yarn run build",
|
||||
"build:modules:ppcp-webhooks": "cd modules/ppcp-webhooks && yarn run build",
|
||||
"build:modules:ppcp-vaulting": "cd modules/ppcp-vaulting && yarn run build",
|
||||
"build:modules:ppcp-order-tracking": "cd modules/ppcp-order-tracking && yarn run build",
|
||||
"build:modules:ppcp-onboarding": "cd modules/ppcp-onboarding && yarn run build",
|
||||
"build:modules:ppcp-compat": "cd modules/ppcp-compat && yarn run build",
|
||||
|
@ -30,7 +28,6 @@
|
|||
"watch:modules:ppcp-button": "cd modules/ppcp-button && yarn run watch",
|
||||
"watch:modules:ppcp-wc-gateway": "cd modules/ppcp-wc-gateway && yarn run watch",
|
||||
"watch:modules:ppcp-webhooks": "cd modules/ppcp-webhooks && yarn run watch",
|
||||
"watch:modules:ppcp-vaulting": "cd modules/ppcp-vaulting && yarn run watch",
|
||||
"watch:modules:ppcp-order-tracking": "cd modules/ppcp-order-tracking && yarn run watch",
|
||||
"watch:modules:ppcp-onboarding": "cd modules/ppcp-onboarding && yarn run watch",
|
||||
"watch:modules:ppcp-compat": "cd modules/ppcp-compat && yarn run watch",
|
||||
|
|
|
@ -1,162 +0,0 @@
|
|||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace WooCommerce\PayPalCommerce\Subscription\Repository;
|
||||
|
||||
use WooCommerce\PayPalCommerce\ApiClient\Endpoint\PaymentTokenEndpoint;
|
||||
use WooCommerce\PayPalCommerce\ApiClient\Entity\PaymentToken;
|
||||
use WooCommerce\PayPalCommerce\ApiClient\Exception\RuntimeException;
|
||||
use WooCommerce\PayPalCommerce\ApiClient\Factory\PaymentTokenFactory;
|
||||
use WooCommerce\PayPalCommerce\TestCase;
|
||||
use Mockery;
|
||||
use Mockery\Adapter\Phpunit\MockeryPHPUnitIntegration;
|
||||
use WooCommerce\PayPalCommerce\Vaulting\PaymentTokenRepository;
|
||||
use function Brain\Monkey\Functions\expect;
|
||||
use function Brain\Monkey\Functions\when;
|
||||
|
||||
class PaymentTokenRepositoryTest extends TestCase
|
||||
{
|
||||
use MockeryPHPUnitIntegration;
|
||||
|
||||
private $factory;
|
||||
private $endpoint;
|
||||
private $sut;
|
||||
|
||||
public function setUp(): void
|
||||
{
|
||||
parent::setUp();
|
||||
$this->factory = Mockery::mock(PaymentTokenFactory::class);
|
||||
$this->endpoint = Mockery::mock(PaymentTokenEndpoint::class);
|
||||
$this->sut = new PaymentTokenRepository($this->factory, $this->endpoint);
|
||||
}
|
||||
|
||||
public function testForUserIdFromArray()
|
||||
{
|
||||
$id = 1;
|
||||
$token = ['id' => 'foo'];
|
||||
$paymentToken = Mockery::mock(PaymentToken::class);
|
||||
$paymentToken->shouldReceive('id')
|
||||
->andReturn('foo');
|
||||
|
||||
expect('get_user_meta')->with($id, $this->sut::USER_META, true)
|
||||
->andReturn($token);
|
||||
|
||||
$this->factory->shouldReceive('from_array')->with($token)
|
||||
->andReturn($paymentToken);
|
||||
|
||||
$result = $this->sut->for_user_id($id);
|
||||
$this->assertInstanceOf(PaymentToken::class, $result);
|
||||
}
|
||||
|
||||
public function testFetchForUserId()
|
||||
{
|
||||
$id = 1;
|
||||
$source = new \stdClass();
|
||||
$paymentToken = new PaymentToken('foo', $source, 'PAYMENT_METHOD_TOKEN');
|
||||
|
||||
when('get_user_meta')->justReturn([]);
|
||||
$this->endpoint->shouldReceive('for_user')
|
||||
->with($id)
|
||||
->andReturn([$paymentToken]);
|
||||
expect('update_user_meta')->with($id, $this->sut::USER_META, $paymentToken->to_array());
|
||||
|
||||
$result = $this->sut->for_user_id($id);
|
||||
$this->assertInstanceOf(PaymentToken::class, $result);
|
||||
}
|
||||
|
||||
public function testForUserIdFails()
|
||||
{
|
||||
$id = 1;
|
||||
when('get_user_meta')->justReturn([]);
|
||||
|
||||
$this->endpoint
|
||||
->expects('for_user')
|
||||
->with($id)
|
||||
->andThrow(RuntimeException::class);
|
||||
|
||||
$result = $this->sut->for_user_id($id);
|
||||
$this->assertNull($result);
|
||||
}
|
||||
|
||||
public function testDeleteToken()
|
||||
{
|
||||
$id = 1;
|
||||
$paymentToken = Mockery::mock(PaymentToken::class);
|
||||
$paymentToken->shouldReceive('id')
|
||||
->andReturn('foo');
|
||||
|
||||
expect('delete_user_meta')->with($id, $this->sut::USER_META);
|
||||
$this->endpoint->shouldReceive('delete_token')
|
||||
->with($paymentToken);
|
||||
|
||||
$this->sut->delete_token($id, $paymentToken);
|
||||
}
|
||||
|
||||
public function testAllForUserId()
|
||||
{
|
||||
$id = 1;
|
||||
$tokens = [];
|
||||
|
||||
$this->endpoint->shouldReceive('for_user')
|
||||
->with($id)
|
||||
->andReturn($tokens);
|
||||
expect('update_user_meta')->with($id, $this->sut::USER_META, $tokens);
|
||||
|
||||
$result = $this->sut->all_for_user_id($id);
|
||||
$this->assertSame($tokens, $result);
|
||||
}
|
||||
|
||||
public function test_AllForUserIdReturnsEmptyArrayIfGettingTokenFails()
|
||||
{
|
||||
$id = 1;
|
||||
$tokens = [];
|
||||
|
||||
$this->endpoint
|
||||
->expects('for_user')
|
||||
->with($id)
|
||||
->andThrow(RuntimeException::class);
|
||||
|
||||
$result = $this->sut->all_for_user_id($id);
|
||||
$this->assertSame($tokens, $result);
|
||||
}
|
||||
|
||||
public function testTokensContainCardReturnsTrue()
|
||||
{
|
||||
$source = new \stdClass();
|
||||
$card = new \stdClass();
|
||||
$source->card = $card;
|
||||
$token = Mockery::mock(PaymentToken::class);
|
||||
$tokens = [$token];
|
||||
|
||||
$token->shouldReceive('source')->andReturn($source);
|
||||
|
||||
$this->assertTrue($this->sut->tokens_contains_card($tokens));
|
||||
}
|
||||
|
||||
public function testTokensContainCardReturnsFalse()
|
||||
{
|
||||
$tokens = [];
|
||||
$this->assertFalse($this->sut->tokens_contains_card($tokens));
|
||||
}
|
||||
|
||||
public function testTokensContainPayPalReturnsTrue()
|
||||
{
|
||||
$source = new \stdClass();
|
||||
$paypal = new \stdClass();
|
||||
$source->paypal = $paypal;
|
||||
$token = Mockery::mock(PaymentToken::class);
|
||||
$tokens = [$token];
|
||||
|
||||
$token->shouldReceive('source')->andReturn($source);
|
||||
|
||||
$this->assertTrue($this->sut->tokens_contains_paypal($tokens));
|
||||
}
|
||||
|
||||
public function testTokensContainPayPalReturnsFalse()
|
||||
{
|
||||
$tokens = [];
|
||||
$this->assertFalse($this->sut->tokens_contains_paypal($tokens));
|
||||
}
|
||||
|
||||
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue