Skip to content

Commit

Permalink
Merge pull request #1779 from woocommerce/PCP-1393-update-to-vault-v-3
Browse files Browse the repository at this point in the history
Save payment methods (Vault v3) integration (1393)
  • Loading branch information
Dinamiko authored Dec 5, 2023
2 parents e3eeb04 + 290f4bc commit 45516d0
Show file tree
Hide file tree
Showing 100 changed files with 5,282 additions and 1,259 deletions.
11 changes: 10 additions & 1 deletion modules.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,14 @@
( require "$modules_dir/ppcp-onboarding/module.php" )(),
( require "$modules_dir/ppcp-session/module.php" )(),
( require "$modules_dir/ppcp-status-report/module.php" )(),
( require "$modules_dir/ppcp-subscription/module.php" )(),
( require "$modules_dir/ppcp-wc-subscriptions/module.php" )(),
( require "$modules_dir/ppcp-wc-gateway/module.php" )(),
( require "$modules_dir/ppcp-webhooks/module.php" )(),
( require "$modules_dir/ppcp-vaulting/module.php" )(),
( require "$modules_dir/ppcp-order-tracking/module.php" )(),
( require "$modules_dir/ppcp-uninstall/module.php" )(),
( require "$modules_dir/ppcp-blocks/module.php" )(),
( require "$modules_dir/ppcp-paypal-subscriptions/module.php" )(),
);
if ( apply_filters(
// phpcs:ignore WordPress.NamingConventions.ValidHookName.UseUnderscores
Expand Down Expand Up @@ -60,5 +61,13 @@
$modules[] = ( require "$modules_dir/ppcp-card-fields/module.php" )();
}

if ( apply_filters(
//phpcs:disable WordPress.NamingConventions.ValidHookName.UseUnderscores
'woocommerce.feature-flags.woocommerce_paypal_payments.save_payment_methods_enabled',
getenv( 'PCP_SAVE_PAYMENT_METHODS' ) === '1'
) ) {
$modules[] = ( require "$modules_dir/ppcp-save-payment-methods/module.php" )();
}

return $modules;
};
189 changes: 106 additions & 83 deletions modules/ppcp-api-client/services.php

Large diffs are not rendered by default.

105 changes: 105 additions & 0 deletions modules/ppcp-api-client/src/Authentication/UserIdToken.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
<?php
/**
* Generates user ID token for payer.
*
* @package WooCommerce\PayPalCommerce\ApiClient\Authentication
*/

namespace WooCommerce\PayPalCommerce\ApiClient\Authentication;

use Psr\Log\LoggerInterface;
use WooCommerce\PayPalCommerce\ApiClient\Endpoint\RequestTrait;
use WooCommerce\PayPalCommerce\ApiClient\Exception\PayPalApiException;
use WooCommerce\PayPalCommerce\ApiClient\Exception\RuntimeException;
use WP_Error;

/**
* Class UserIdToken
*/
class UserIdToken {

use RequestTrait;

/**
* The host.
*
* @var string
*/
private $host;

/**
* The bearer.
*
* @var Bearer
*/
private $bearer;

/**
* The logger.
*
* @var LoggerInterface
*/
private $logger;

/**
* UserIdToken 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;
}

/**
* Returns `id_token` which uniquely identifies the payer.
*
* @param string $target_customer_id Vaulted customer id.
*
* @return string
*
* @throws PayPalApiException If the request fails.
* @throws RuntimeException If something unexpected happens.
*/
public function id_token( string $target_customer_id = '' ): string {
$bearer = $this->bearer->bearer();

$url = trailingslashit( $this->host ) . 'v1/oauth2/token?grant_type=client_credentials&response_type=id_token';
if ( $target_customer_id ) {
$url = add_query_arg(
array(
'target_customer_id' => $target_customer_id,
),
$url
);
}

$args = array(
'method' => 'POST',
'headers' => array(
'Authorization' => 'Bearer ' . $bearer->token(),
'Content-Type' => 'application/x-www-form-urlencoded',
),
);

$response = $this->request( $url, $args );
if ( $response instanceof WP_Error ) {
throw new RuntimeException( $response->get_error_message() );
}

$json = json_decode( $response['body'] );
$status_code = (int) wp_remote_retrieve_response_code( $response );
if ( 200 !== $status_code ) {
throw new PayPalApiException( $json, $status_code );
}

return $json->id_token;
}
}
25 changes: 14 additions & 11 deletions modules/ppcp-api-client/src/Endpoint/OrderEndpoint.php
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
use WooCommerce\PayPalCommerce\ApiClient\Helper\ErrorResponse;
use WooCommerce\PayPalCommerce\ApiClient\Repository\ApplicationContextRepository;
use Psr\Log\LoggerInterface;
use WooCommerce\PayPalCommerce\Subscription\Helper\SubscriptionHelper;
use WooCommerce\PayPalCommerce\WcSubscriptions\Helper\SubscriptionHelper;
use WooCommerce\PayPalCommerce\WcGateway\FraudNet\FraudNet;
use WP_Error;

Expand Down Expand Up @@ -178,8 +178,10 @@ public function with_bn_code( string $bn_code ): OrderEndpoint {
* @param string $shipping_preference One of ApplicationContext::SHIPPING_PREFERENCE_ values.
* @param Payer|null $payer The payer off the order.
* @param PaymentToken|null $payment_token The payment token.
* @param string $paypal_request_id The paypal request id.
* @param string $paypal_request_id The PayPal request id.
* @param string $user_action The user action.
* @param string $payment_method WC payment method.
* @param array $request_data Request data.
*
* @return Order
* @throws RuntimeException If the request fails.
Expand All @@ -190,7 +192,9 @@ public function create(
Payer $payer = null,
PaymentToken $payment_token = null,
string $paypal_request_id = '',
string $user_action = ApplicationContext::USER_ACTION_CONTINUE
string $user_action = ApplicationContext::USER_ACTION_CONTINUE,
string $payment_method = '',
array $request_data = array()
): Order {
$bearer = $this->bearer->bearer();
$data = array(
Expand Down Expand Up @@ -221,7 +225,7 @@ static function ( PurchaseUnit $item ) use ( $shipping_preference ): array {
/**
* The filter can be used to modify the order creation request body data.
*/
$data = apply_filters( 'ppcp_create_order_request_body_data', $data );
$data = apply_filters( 'ppcp_create_order_request_body_data', $data, $payment_method, $request_data );
$url = trailingslashit( $this->host ) . 'v2/checkout/orders';
$args = array(
'method' => 'POST',
Expand Down Expand Up @@ -260,26 +264,25 @@ static function ( PurchaseUnit $item ) use ( $shipping_preference ): array {
);
throw $error;
}

$json = json_decode( $response['body'] );
$status_code = (int) wp_remote_retrieve_response_code( $response );
if ( 201 !== $status_code ) {
if ( ! in_array( $status_code, array( 200, 201 ), true ) ) {
$error = new PayPalApiException(
$json,
$status_code
);
$this->logger->log(
'warning',

$this->logger->warning(
sprintf(
'Failed to create order. PayPal API response: %1$s',
$error->getMessage()
),
array(
'args' => $args,
'response' => $response,
)
);

throw $error;
}

$order = $this->order_factory->from_paypal_response( $json );

do_action( 'woocommerce_paypal_payments_paypal_order_created', $order );
Expand Down
155 changes: 155 additions & 0 deletions modules/ppcp-api-client/src/Endpoint/PaymentMethodTokensEndpoint.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,155 @@
<?php
/**
* The Payment Method Tokens endpoint.
*
* @package WooCommerce\PayPalCommerce\ApiClient\Endpoint
*/

declare(strict_types=1);

namespace WooCommerce\PayPalCommerce\ApiClient\Endpoint;

use Psr\Log\LoggerInterface;
use stdClass;
use WooCommerce\PayPalCommerce\ApiClient\Authentication\Bearer;
use WooCommerce\PayPalCommerce\ApiClient\Entity\PaymentSource;
use WooCommerce\PayPalCommerce\ApiClient\Exception\PayPalApiException;
use WooCommerce\PayPalCommerce\ApiClient\Exception\RuntimeException;

/**
* Class PaymentMethodTokensEndpoint
*/
class PaymentMethodTokensEndpoint {

use RequestTrait;

/**
* The host.
*
* @var string
*/
private $host;

/**
* 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;
}

/**
* 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(),
),
);

$bearer = $this->bearer->bearer();
$url = trailingslashit( $this->host ) . 'v3/vault/setup-tokens';

$args = array(
'method' => 'POST',
'headers' => array(
'Authorization' => 'Bearer ' . $bearer->token(),
'Content-Type' => 'application/json',
'PayPal-Request-Id' => uniqid( 'ppcp-', true ),
),
'body' => wp_json_encode( $data ),
);

$response = $this->request( $url, $args );

if ( is_wp_error( $response ) || ! is_array( $response ) ) {
throw new RuntimeException( 'Not able to create setup token.' );
}

$json = json_decode( $response['body'] );
$status_code = (int) wp_remote_retrieve_response_code( $response );
if ( ! in_array( $status_code, array( 200, 201 ), true ) ) {
throw new PayPalApiException(
$json,
$status_code
);
}

return $json;
}

/**
* 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(),
),
);

$bearer = $this->bearer->bearer();
$url = trailingslashit( $this->host ) . 'v3/vault/payment-tokens';

$args = array(
'method' => 'POST',
'headers' => array(
'Authorization' => 'Bearer ' . $bearer->token(),
'Content-Type' => 'application/json',
'PayPal-Request-Id' => uniqid( 'ppcp-', true ),
),
'body' => wp_json_encode( $data ),
);

$response = $this->request( $url, $args );

if ( is_wp_error( $response ) || ! is_array( $response ) ) {
throw new RuntimeException( 'Not able to create setup token.' );
}

$json = json_decode( $response['body'] );
$status_code = (int) wp_remote_retrieve_response_code( $response );
if ( ! in_array( $status_code, array( 200, 201 ), true ) ) {
throw new PayPalApiException(
$json,
$status_code
);
}

return $json;
}
}
Loading

0 comments on commit 45516d0

Please sign in to comment.