mirror of
https://github.com/woocommerce/woocommerce-paypal-payments.git
synced 2025-09-06 18:16:38 +08:00
Add pay with save payment method (WIP)
This commit is contained in:
parent
5811b5f60d
commit
92a574f4fa
5 changed files with 298 additions and 28 deletions
|
@ -91,12 +91,30 @@ class CardFieldsRenderer {
|
||||||
this.spinner.block();
|
this.spinner.block();
|
||||||
this.errorHandler.clear();
|
this.errorHandler.clear();
|
||||||
|
|
||||||
|
const paymentToken = document.querySelector('input[name="wc-ppcp-credit-card-gateway-payment-token"]:checked').value
|
||||||
|
if(paymentToken !== 'new') {
|
||||||
|
fetch(this.defaultConfig.ajax.capture_card_payment.endpoint, {
|
||||||
|
method: 'POST',
|
||||||
|
credentials: 'same-origin',
|
||||||
|
body: JSON.stringify({
|
||||||
|
nonce: this.defaultConfig.ajax.capture_card_payment.nonce,
|
||||||
|
payment_token: paymentToken
|
||||||
|
})
|
||||||
|
}).then((res) => {
|
||||||
|
return res.json();
|
||||||
|
}).then((data) => {
|
||||||
|
document.querySelector('#place_order').click();
|
||||||
|
});
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
cardField.submit()
|
cardField.submit()
|
||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
this.spinner.unblock();
|
this.spinner.unblock();
|
||||||
console.error(error)
|
console.error(error)
|
||||||
this.errorHandler.message(this.defaultConfig.hosted_fields.labels.fields_not_valid);
|
this.errorHandler.message(this.defaultConfig.hosted_fields.labels.fields_not_valid);
|
||||||
})
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -9,6 +9,7 @@ declare(strict_types=1);
|
||||||
|
|
||||||
namespace WooCommerce\PayPalCommerce\SavePaymentMethods;
|
namespace WooCommerce\PayPalCommerce\SavePaymentMethods;
|
||||||
|
|
||||||
|
use WooCommerce\PayPalCommerce\SavePaymentMethods\Endpoint\CaptureCardPayment;
|
||||||
use WooCommerce\PayPalCommerce\SavePaymentMethods\Endpoint\CreatePaymentToken;
|
use WooCommerce\PayPalCommerce\SavePaymentMethods\Endpoint\CreatePaymentToken;
|
||||||
use WooCommerce\PayPalCommerce\SavePaymentMethods\Endpoint\CreateSetupToken;
|
use WooCommerce\PayPalCommerce\SavePaymentMethods\Endpoint\CreateSetupToken;
|
||||||
use WooCommerce\PayPalCommerce\SavePaymentMethods\Helper\SavePaymentMethodsApplies;
|
use WooCommerce\PayPalCommerce\SavePaymentMethods\Helper\SavePaymentMethodsApplies;
|
||||||
|
@ -74,4 +75,16 @@ return array(
|
||||||
$container->get( 'save-payment-methods.wc-payment-tokens' )
|
$container->get( 'save-payment-methods.wc-payment-tokens' )
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
'save-payment-methods.endpoint.capture-card-payment' => static function( ContainerInterface $container): CaptureCardPayment {
|
||||||
|
return new CaptureCardPayment(
|
||||||
|
$container->get( 'button.request-data' ),
|
||||||
|
$container->get( 'api.host' ),
|
||||||
|
$container->get( 'api.bearer' ),
|
||||||
|
$container->get( 'api.factory.order' ),
|
||||||
|
$container->get('api.factory.purchase-unit'),
|
||||||
|
$container->get('api.endpoint.order'),
|
||||||
|
$container->get('session.handler'),
|
||||||
|
$container->get( 'woocommerce.logger.woocommerce' )
|
||||||
|
);
|
||||||
|
}
|
||||||
);
|
);
|
||||||
|
|
|
@ -0,0 +1,195 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* The Capture Card Payment endpoint.
|
||||||
|
*
|
||||||
|
* @package WooCommerce\PayPalCommerce\ApiClient\Endpoint
|
||||||
|
*/
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace WooCommerce\PayPalCommerce\SavePaymentMethods\Endpoint;
|
||||||
|
|
||||||
|
use Psr\Log\LoggerInterface;
|
||||||
|
use RuntimeException;
|
||||||
|
use stdClass;
|
||||||
|
use WC_Payment_Tokens;
|
||||||
|
use WooCommerce\PayPalCommerce\ApiClient\Authentication\Bearer;
|
||||||
|
use WooCommerce\PayPalCommerce\ApiClient\Endpoint\OrderEndpoint;
|
||||||
|
use WooCommerce\PayPalCommerce\ApiClient\Endpoint\RequestTrait;
|
||||||
|
use WooCommerce\PayPalCommerce\ApiClient\Entity\PurchaseUnit;
|
||||||
|
use WooCommerce\PayPalCommerce\ApiClient\Factory\OrderFactory;
|
||||||
|
use WooCommerce\PayPalCommerce\ApiClient\Factory\PurchaseUnitFactory;
|
||||||
|
use WooCommerce\PayPalCommerce\Button\Endpoint\EndpointInterface;
|
||||||
|
use WooCommerce\PayPalCommerce\Button\Endpoint\RequestData;
|
||||||
|
use WooCommerce\PayPalCommerce\Session\SessionHandler;
|
||||||
|
use WP_Error;
|
||||||
|
|
||||||
|
class CaptureCardPayment implements EndpointInterface {
|
||||||
|
|
||||||
|
use RequestTrait;
|
||||||
|
|
||||||
|
const ENDPOINT = 'ppc-capture-card-payment';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The request data.
|
||||||
|
*
|
||||||
|
* @var RequestData
|
||||||
|
*/
|
||||||
|
private $request_data;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The host.
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
private $host;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The bearer.
|
||||||
|
*
|
||||||
|
* @var Bearer
|
||||||
|
*/
|
||||||
|
private $bearer;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The order factory.
|
||||||
|
*
|
||||||
|
* @var OrderFactory
|
||||||
|
*/
|
||||||
|
private $order_factory;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The purchase unit factory.
|
||||||
|
*
|
||||||
|
* @var PurchaseUnitFactory
|
||||||
|
*/
|
||||||
|
private $purchase_unit_factory;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The order endpoint.
|
||||||
|
*
|
||||||
|
* @var OrderEndpoint
|
||||||
|
*/
|
||||||
|
private $order_endpoint;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The session handler.
|
||||||
|
*
|
||||||
|
* @var SessionHandler
|
||||||
|
*/
|
||||||
|
private $session_handler;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The logger.
|
||||||
|
*
|
||||||
|
* @var LoggerInterface
|
||||||
|
*/
|
||||||
|
private $logger;
|
||||||
|
|
||||||
|
public function __construct(
|
||||||
|
RequestData $request_data,
|
||||||
|
string $host,
|
||||||
|
Bearer $bearer,
|
||||||
|
OrderFactory $order_factory,
|
||||||
|
PurchaseUnitFactory $purchase_unit_factory,
|
||||||
|
OrderEndpoint $order_endpoint,
|
||||||
|
SessionHandler $session_handler,
|
||||||
|
LoggerInterface $logger
|
||||||
|
) {
|
||||||
|
$this->request_data = $request_data;
|
||||||
|
$this->host = $host;
|
||||||
|
$this->bearer = $bearer;
|
||||||
|
$this->order_factory = $order_factory;
|
||||||
|
$this->purchase_unit_factory = $purchase_unit_factory;
|
||||||
|
$this->order_endpoint = $order_endpoint;
|
||||||
|
$this->logger = $logger;
|
||||||
|
$this->session_handler = $session_handler;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the nonce.
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public static function nonce(): string {
|
||||||
|
return self::ENDPOINT;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function handle_request(): bool {
|
||||||
|
$data = $this->request_data->read_request( $this->nonce() );
|
||||||
|
|
||||||
|
$tokens = WC_Payment_Tokens::get_customer_tokens(get_current_user_id());
|
||||||
|
foreach ($tokens as $token) {
|
||||||
|
if($token->get_id() === (int)$data['payment_token']) {
|
||||||
|
try {
|
||||||
|
$order = $this->create_order($token->get_token());
|
||||||
|
|
||||||
|
$id = $order->id ?? '';
|
||||||
|
$status = $order->status ?? '';
|
||||||
|
$payment_source = isset($order->payment_source->card) ? 'card' : '';
|
||||||
|
if($id && $status && $payment_source) {
|
||||||
|
WC()->session->set('ppcp_saved_payment_card', array(
|
||||||
|
'order_id' => $id,
|
||||||
|
'status' => $status,
|
||||||
|
'payment_source' => $payment_source
|
||||||
|
));
|
||||||
|
|
||||||
|
wp_send_json_success();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
} catch (RuntimeException $exception) {
|
||||||
|
wp_send_json_error();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
wp_send_json_error();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates PayPal order from the given card vault id.
|
||||||
|
*
|
||||||
|
* @param string $vault_id
|
||||||
|
* @return stdClass
|
||||||
|
*/
|
||||||
|
private function create_order(string $vault_id): stdClass {
|
||||||
|
$items = array( $this->purchase_unit_factory->from_wc_cart());
|
||||||
|
|
||||||
|
$data = array(
|
||||||
|
'intent' => 'CAPTURE',
|
||||||
|
'purchase_units' => array_map(
|
||||||
|
static function ( PurchaseUnit $item ): array {
|
||||||
|
return $item->to_array( true, false );
|
||||||
|
},
|
||||||
|
$items
|
||||||
|
),
|
||||||
|
'payment_source' => array(
|
||||||
|
'card' => array(
|
||||||
|
'vault_id' => $vault_id
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
$bearer = $this->bearer->bearer();
|
||||||
|
$url = trailingslashit( $this->host ) . 'v2/checkout/orders';
|
||||||
|
$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 ( $response instanceof WP_Error ) {
|
||||||
|
throw new RuntimeException( $response->get_error_message() );
|
||||||
|
}
|
||||||
|
|
||||||
|
return json_decode( $response['body'] );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -18,6 +18,7 @@ use WooCommerce\PayPalCommerce\ApiClient\Entity\Order;
|
||||||
use WooCommerce\PayPalCommerce\ApiClient\Entity\PaymentSource;
|
use WooCommerce\PayPalCommerce\ApiClient\Entity\PaymentSource;
|
||||||
use WooCommerce\PayPalCommerce\ApiClient\Exception\PayPalApiException;
|
use WooCommerce\PayPalCommerce\ApiClient\Exception\PayPalApiException;
|
||||||
use WooCommerce\PayPalCommerce\ApiClient\Exception\RuntimeException;
|
use WooCommerce\PayPalCommerce\ApiClient\Exception\RuntimeException;
|
||||||
|
use WooCommerce\PayPalCommerce\SavePaymentMethods\Endpoint\CaptureCardPayment;
|
||||||
use WooCommerce\PayPalCommerce\SavePaymentMethods\Endpoint\CreatePaymentToken;
|
use WooCommerce\PayPalCommerce\SavePaymentMethods\Endpoint\CreatePaymentToken;
|
||||||
use WooCommerce\PayPalCommerce\SavePaymentMethods\Endpoint\CreateSetupToken;
|
use WooCommerce\PayPalCommerce\SavePaymentMethods\Endpoint\CreateSetupToken;
|
||||||
use WooCommerce\PayPalCommerce\Vendor\Dhii\Container\ServiceProvider;
|
use WooCommerce\PayPalCommerce\Vendor\Dhii\Container\ServiceProvider;
|
||||||
|
@ -50,37 +51,21 @@ class SavePaymentMethodsModule implements ModuleInterface {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Adds `id_token` to localized script data.
|
|
||||||
add_filter(
|
add_filter(
|
||||||
'woocommerce_paypal_payments_localized_script_data',
|
'woocommerce_paypal_payments_localized_script_data',
|
||||||
function( array $localized_script_data ) use ( $c ) {
|
function( array $localized_script_data ) use ( $c ) {
|
||||||
$api = $c->get('api.user-id-token');
|
$api = $c->get('api.user-id-token');
|
||||||
assert($api instanceof UserIdToken);
|
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 );
|
|
||||||
}
|
|
||||||
|
|
||||||
$id_token = $api->id_token( $target_customer_id );
|
|
||||||
$localized_script_data['save_payment_methods'] = array(
|
|
||||||
'id_token' => $id_token,
|
|
||||||
);
|
|
||||||
|
|
||||||
$localized_script_data['data_client_id']['set_attribute'] = false;
|
|
||||||
|
|
||||||
} catch ( RuntimeException $exception ) {
|
|
||||||
$logger = $c->get('woocommerce.logger.woocommerce');
|
$logger = $c->get('woocommerce.logger.woocommerce');
|
||||||
assert($logger instanceof LoggerInterface);
|
assert($logger instanceof LoggerInterface);
|
||||||
|
|
||||||
$error = $exception->getMessage();
|
$localized_script_data = $this->add_id_token_to_script_data($api, $logger, $localized_script_data);
|
||||||
if ( is_a( $exception, PayPalApiException::class ) ) {
|
|
||||||
$error = $exception->get_details( $error );
|
|
||||||
}
|
|
||||||
|
|
||||||
$logger->error( $error );
|
$localized_script_data['ajax']['capture_card_payment'] = array(
|
||||||
}
|
'endpoint' => \WC_AJAX::get_endpoint( CaptureCardPayment::ENDPOINT ),
|
||||||
|
'nonce' => wp_create_nonce( CaptureCardPayment::nonce() ),
|
||||||
|
);
|
||||||
|
|
||||||
return $localized_script_data;
|
return $localized_script_data;
|
||||||
}
|
}
|
||||||
|
@ -329,5 +314,53 @@ class SavePaymentMethodsModule implements ModuleInterface {
|
||||||
return $supports;
|
return $supports;
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
add_action(
|
||||||
|
'wc_ajax_' . CaptureCardPayment::ENDPOINT,
|
||||||
|
static function () use ( $c ) {
|
||||||
|
$endpoint = $c->get( 'save-payment-methods.endpoint.capture-card-payment' );
|
||||||
|
assert( $endpoint instanceof CaptureCardPayment );
|
||||||
|
|
||||||
|
$endpoint->handle_request();
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds id token to localized script data.
|
||||||
|
*
|
||||||
|
* @param UserIdToken $api User id token api.
|
||||||
|
* @param LoggerInterface $logger The logger.
|
||||||
|
* @param array $localized_script_data The localized script data.
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
private function add_id_token_to_script_data(
|
||||||
|
UserIdToken $api,
|
||||||
|
LoggerInterface $logger,
|
||||||
|
array $localized_script_data
|
||||||
|
): array {
|
||||||
|
try {
|
||||||
|
$target_customer_id = '';
|
||||||
|
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);
|
||||||
|
$localized_script_data['save_payment_methods'] = array(
|
||||||
|
'id_token' => $id_token,
|
||||||
|
);
|
||||||
|
|
||||||
|
$localized_script_data['data_client_id']['set_attribute'] = false;
|
||||||
|
|
||||||
|
} catch (RuntimeException $exception) {
|
||||||
|
$error = $exception->getMessage();
|
||||||
|
if (is_a($exception, PayPalApiException::class)) {
|
||||||
|
$error = $exception->get_details($error);
|
||||||
|
}
|
||||||
|
|
||||||
|
$logger->error($error);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $localized_script_data;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,13 +11,13 @@ namespace WooCommerce\PayPalCommerce\WcGateway\Gateway;
|
||||||
|
|
||||||
use Exception;
|
use Exception;
|
||||||
use Psr\Log\LoggerInterface;
|
use Psr\Log\LoggerInterface;
|
||||||
use WC_Customer;
|
|
||||||
use WC_Order;
|
use WC_Order;
|
||||||
use WooCommerce\PayPalCommerce\ApiClient\Endpoint\PaymentsEndpoint;
|
use WooCommerce\PayPalCommerce\ApiClient\Endpoint\PaymentsEndpoint;
|
||||||
use WooCommerce\PayPalCommerce\ApiClient\Exception\PayPalApiException;
|
use WooCommerce\PayPalCommerce\ApiClient\Exception\PayPalApiException;
|
||||||
use WooCommerce\PayPalCommerce\ApiClient\Exception\RuntimeException;
|
use WooCommerce\PayPalCommerce\ApiClient\Exception\RuntimeException;
|
||||||
use WooCommerce\PayPalCommerce\Onboarding\State;
|
use WooCommerce\PayPalCommerce\Onboarding\State;
|
||||||
use WooCommerce\PayPalCommerce\Session\SessionHandler;
|
use WooCommerce\PayPalCommerce\Session\SessionHandler;
|
||||||
|
use WooCommerce\PayPalCommerce\WcGateway\Processor\TransactionIdHandlingTrait;
|
||||||
use WooCommerce\PayPalCommerce\WcSubscriptions\Helper\SubscriptionHelper;
|
use WooCommerce\PayPalCommerce\WcSubscriptions\Helper\SubscriptionHelper;
|
||||||
use WooCommerce\PayPalCommerce\Vaulting\PaymentTokenRepository;
|
use WooCommerce\PayPalCommerce\Vaulting\PaymentTokenRepository;
|
||||||
use WooCommerce\PayPalCommerce\Vaulting\VaultedCreditCardHandler;
|
use WooCommerce\PayPalCommerce\Vaulting\VaultedCreditCardHandler;
|
||||||
|
@ -32,7 +32,7 @@ use WooCommerce\PayPalCommerce\Vendor\Psr\Container\ContainerInterface;
|
||||||
*/
|
*/
|
||||||
class CreditCardGateway extends \WC_Payment_Gateway_CC {
|
class CreditCardGateway extends \WC_Payment_Gateway_CC {
|
||||||
|
|
||||||
use ProcessPaymentTrait, GatewaySettingsRendererTrait;
|
use ProcessPaymentTrait, GatewaySettingsRendererTrait, TransactionIdHandlingTrait;
|
||||||
|
|
||||||
const ID = 'ppcp-credit-card-gateway';
|
const ID = 'ppcp-credit-card-gateway';
|
||||||
|
|
||||||
|
@ -365,6 +365,17 @@ class CreditCardGateway extends \WC_Payment_Gateway_CC {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$saved_payment_card = WC()->session->get('ppcp_saved_payment_card');
|
||||||
|
if($saved_payment_card) {
|
||||||
|
if($saved_payment_card['payment_source'] === 'card' && $saved_payment_card['status'] === 'COMPLETED') {
|
||||||
|
$this->update_transaction_id( $saved_payment_card['order_id'], $wc_order );
|
||||||
|
$wc_order->payment_complete();
|
||||||
|
WC()->session->set( 'ppcp_saved_payment_card', null );
|
||||||
|
|
||||||
|
return $this->handle_payment_success( $wc_order );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* If customer has chosen a saved credit card payment.
|
* If customer has chosen a saved credit card payment.
|
||||||
*/
|
*/
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue