mirror of
https://github.com/woocommerce/woocommerce-paypal-payments.git
synced 2025-09-05 08:59:14 +08:00
Save checkout form before free trial redirect
This commit is contained in:
parent
c8e492ed1e
commit
79f2c9a1fa
8 changed files with 220 additions and 26 deletions
|
@ -17,6 +17,7 @@ import {
|
|||
import {hide, setVisible, setVisibleByClass} from "./modules/Helper/Hiding";
|
||||
import {isChangePaymentPage} from "./modules/Helper/Subscriptions";
|
||||
import FreeTrialHandler from "./modules/ActionHandler/FreeTrialHandler";
|
||||
import FormSaver from './modules/Helper/FormSaver';
|
||||
|
||||
// TODO: could be a good idea to have a separate spinner for each gateway,
|
||||
// but I think we care mainly about the script loading, so one spinner should be enough.
|
||||
|
@ -24,11 +25,18 @@ const buttonsSpinner = new Spinner(document.querySelector('.ppc-button-wrapper')
|
|||
const cardsSpinner = new Spinner('#ppcp-hosted-fields');
|
||||
|
||||
const bootstrap = () => {
|
||||
const checkoutFormSelector = 'form.woocommerce-checkout';
|
||||
|
||||
const errorHandler = new ErrorHandler(PayPalCommerceGateway.labels.error.generic);
|
||||
const spinner = new Spinner();
|
||||
const creditCardRenderer = new CreditCardRenderer(PayPalCommerceGateway, errorHandler, spinner);
|
||||
|
||||
const freeTrialHandler = new FreeTrialHandler(PayPalCommerceGateway, spinner, errorHandler);
|
||||
const formSaver = new FormSaver(
|
||||
PayPalCommerceGateway.ajax.save_checkout_form.endpoint,
|
||||
PayPalCommerceGateway.ajax.save_checkout_form.nonce,
|
||||
);
|
||||
|
||||
const freeTrialHandler = new FreeTrialHandler(PayPalCommerceGateway, checkoutFormSelector, formSaver, spinner, errorHandler);
|
||||
|
||||
jQuery('form.woocommerce-checkout input').on('keydown', e => {
|
||||
if (e.key === 'Enter' && [
|
||||
|
@ -88,7 +96,7 @@ const bootstrap = () => {
|
|||
}
|
||||
}
|
||||
|
||||
const form = document.querySelector('form.woocommerce-checkout');
|
||||
const form = document.querySelector(checkoutFormSelector);
|
||||
if (form) {
|
||||
jQuery('#ppcp-funding-source-form-input').remove();
|
||||
form.insertAdjacentHTML(
|
||||
|
|
|
@ -1,44 +1,50 @@
|
|||
import {PaymentMethods} from "../Helper/CheckoutMethodState";
|
||||
import errorHandler from "../ErrorHandler";
|
||||
|
||||
class FreeTrialHandler {
|
||||
constructor(
|
||||
config,
|
||||
formSelector,
|
||||
formSaver,
|
||||
spinner,
|
||||
errorHandler
|
||||
) {
|
||||
this.config = config;
|
||||
this.formSelector = formSelector;
|
||||
this.formSaver = formSaver;
|
||||
this.spinner = spinner;
|
||||
this.errorHandler = errorHandler;
|
||||
}
|
||||
|
||||
handle()
|
||||
async handle()
|
||||
{
|
||||
this.spinner.block();
|
||||
|
||||
fetch(this.config.ajax.vault_paypal.endpoint, {
|
||||
method: 'POST',
|
||||
credentials: 'same-origin',
|
||||
body: JSON.stringify({
|
||||
nonce: this.config.ajax.vault_paypal.nonce,
|
||||
return_url: location.href
|
||||
}),
|
||||
}).then(res => {
|
||||
return res.json();
|
||||
}).then(data => {
|
||||
try {
|
||||
await this.formSaver.save(document.querySelector(this.formSelector));
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
}
|
||||
|
||||
try {
|
||||
const res = await fetch(this.config.ajax.vault_paypal.endpoint, {
|
||||
method: 'POST',
|
||||
credentials: 'same-origin',
|
||||
body: JSON.stringify({
|
||||
nonce: this.config.ajax.vault_paypal.nonce,
|
||||
return_url: location.href,
|
||||
}),
|
||||
});
|
||||
|
||||
const data = await res.json();
|
||||
|
||||
if (!data.success) {
|
||||
this.spinner.unblock();
|
||||
console.error(data);
|
||||
this.errorHandler.message(data.data.message);
|
||||
throw Error(data.data.message);
|
||||
}
|
||||
|
||||
location.href = data.data.approve_link;
|
||||
}).catch(error => {
|
||||
} catch (error) {
|
||||
this.spinner.unblock();
|
||||
console.error(error);
|
||||
this.errorHandler.genericError();
|
||||
});
|
||||
this.errorHandler.message(data.data.message);
|
||||
}
|
||||
}
|
||||
}
|
||||
export default FreeTrialHandler;
|
||||
|
|
26
modules/ppcp-button/resources/js/modules/Helper/FormSaver.js
Normal file
26
modules/ppcp-button/resources/js/modules/Helper/FormSaver.js
Normal file
|
@ -0,0 +1,26 @@
|
|||
export default class FormSaver {
|
||||
constructor(url, nonce) {
|
||||
this.url = url;
|
||||
this.nonce = nonce;
|
||||
}
|
||||
|
||||
async save(form) {
|
||||
const formData = new FormData(form);
|
||||
const formJsonObj = Object.fromEntries(formData.entries());
|
||||
|
||||
const res = await fetch(this.url, {
|
||||
method: 'POST',
|
||||
credentials: 'same-origin',
|
||||
body: JSON.stringify({
|
||||
nonce: this.nonce,
|
||||
form: formJsonObj,
|
||||
}),
|
||||
});
|
||||
|
||||
const data = await res.json();
|
||||
|
||||
if (!data.success) {
|
||||
throw Error(data.data.message);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -9,6 +9,8 @@ declare(strict_types=1);
|
|||
|
||||
namespace WooCommerce\PayPalCommerce\Button;
|
||||
|
||||
use WooCommerce\PayPalCommerce\Button\Endpoint\SaveCheckoutFormEndpoint;
|
||||
use WooCommerce\PayPalCommerce\Button\Helper\CheckoutFormSaver;
|
||||
use WooCommerce\PayPalCommerce\Vendor\Psr\Container\ContainerInterface;
|
||||
use WooCommerce\PayPalCommerce\Button\Assets\DisabledSmartButton;
|
||||
use WooCommerce\PayPalCommerce\Button\Assets\SmartButton;
|
||||
|
@ -181,6 +183,16 @@ return array(
|
|||
$logger
|
||||
);
|
||||
},
|
||||
'button.checkout-form-saver' => static function ( ContainerInterface $container ): CheckoutFormSaver {
|
||||
return new CheckoutFormSaver();
|
||||
},
|
||||
'button.endpoint.save-checkout-form' => static function ( ContainerInterface $container ): SaveCheckoutFormEndpoint {
|
||||
return new SaveCheckoutFormEndpoint(
|
||||
$container->get( 'button.request-data' ),
|
||||
$container->get( 'button.checkout-form-saver' ),
|
||||
$container->get( 'woocommerce.logger.woocommerce' )
|
||||
);
|
||||
},
|
||||
'button.endpoint.data-client-id' => static function( ContainerInterface $container ) : DataClientIdEndpoint {
|
||||
$request_data = $container->get( 'button.request-data' );
|
||||
$identity_token = $container->get( 'api.endpoint.identity-token' );
|
||||
|
|
|
@ -21,6 +21,7 @@ use WooCommerce\PayPalCommerce\Button\Endpoint\ChangeCartEndpoint;
|
|||
use WooCommerce\PayPalCommerce\Button\Endpoint\CreateOrderEndpoint;
|
||||
use WooCommerce\PayPalCommerce\Button\Endpoint\DataClientIdEndpoint;
|
||||
use WooCommerce\PayPalCommerce\Button\Endpoint\RequestData;
|
||||
use WooCommerce\PayPalCommerce\Button\Endpoint\SaveCheckoutFormEndpoint;
|
||||
use WooCommerce\PayPalCommerce\Button\Endpoint\StartPayPalVaultingEndpoint;
|
||||
use WooCommerce\PayPalCommerce\Button\Helper\MessagesApply;
|
||||
use WooCommerce\PayPalCommerce\Onboarding\Environment;
|
||||
|
@ -761,22 +762,26 @@ class SmartButton implements SmartButtonInterface {
|
|||
'redirect' => wc_get_checkout_url(),
|
||||
'context' => $this->context(),
|
||||
'ajax' => array(
|
||||
'change_cart' => array(
|
||||
'change_cart' => array(
|
||||
'endpoint' => \WC_AJAX::get_endpoint( ChangeCartEndpoint::ENDPOINT ),
|
||||
'nonce' => wp_create_nonce( ChangeCartEndpoint::nonce() ),
|
||||
),
|
||||
'create_order' => array(
|
||||
'create_order' => array(
|
||||
'endpoint' => \WC_AJAX::get_endpoint( CreateOrderEndpoint::ENDPOINT ),
|
||||
'nonce' => wp_create_nonce( CreateOrderEndpoint::nonce() ),
|
||||
),
|
||||
'approve_order' => array(
|
||||
'approve_order' => array(
|
||||
'endpoint' => \WC_AJAX::get_endpoint( ApproveOrderEndpoint::ENDPOINT ),
|
||||
'nonce' => wp_create_nonce( ApproveOrderEndpoint::nonce() ),
|
||||
),
|
||||
'vault_paypal' => array(
|
||||
'vault_paypal' => array(
|
||||
'endpoint' => \WC_AJAX::get_endpoint( StartPayPalVaultingEndpoint::ENDPOINT ),
|
||||
'nonce' => wp_create_nonce( StartPayPalVaultingEndpoint::nonce() ),
|
||||
),
|
||||
'save_checkout_form' => array(
|
||||
'endpoint' => \WC_AJAX::get_endpoint( SaveCheckoutFormEndpoint::ENDPOINT ),
|
||||
'nonce' => wp_create_nonce( SaveCheckoutFormEndpoint::nonce() ),
|
||||
),
|
||||
),
|
||||
'enforce_vault' => $this->has_subscriptions(),
|
||||
'can_save_vault_token' => $this->can_save_vault_token(),
|
||||
|
|
|
@ -9,6 +9,7 @@ declare(strict_types=1);
|
|||
|
||||
namespace WooCommerce\PayPalCommerce\Button;
|
||||
|
||||
use WooCommerce\PayPalCommerce\Button\Endpoint\SaveCheckoutFormEndpoint;
|
||||
use WooCommerce\PayPalCommerce\Vendor\Dhii\Container\ServiceProvider;
|
||||
use WooCommerce\PayPalCommerce\Vendor\Dhii\Modular\Module\ModuleInterface;
|
||||
use WooCommerce\PayPalCommerce\Button\Assets\SmartButtonInterface;
|
||||
|
@ -156,6 +157,16 @@ class ButtonModule implements ModuleInterface {
|
|||
$endpoint->handle_request();
|
||||
}
|
||||
);
|
||||
|
||||
add_action(
|
||||
'wc_ajax_' . SaveCheckoutFormEndpoint::ENDPOINT,
|
||||
static function () use ( $container ) {
|
||||
$endpoint = $container->get( 'button.endpoint.save-checkout-form' );
|
||||
assert( $endpoint instanceof SaveCheckoutFormEndpoint );
|
||||
|
||||
$endpoint->handle_request();
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -0,0 +1,94 @@
|
|||
<?php
|
||||
/**
|
||||
* Saves the form data to the WC customer and session.
|
||||
*
|
||||
* @package WooCommerce\PayPalCommerce\Button\Endpoint
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace WooCommerce\PayPalCommerce\Button\Endpoint;
|
||||
|
||||
use Exception;
|
||||
use Psr\Log\LoggerInterface;
|
||||
use WooCommerce\PayPalCommerce\Button\Helper\CheckoutFormSaver;
|
||||
|
||||
/**
|
||||
* Class SaveCheckoutFormEndpoint
|
||||
*/
|
||||
class SaveCheckoutFormEndpoint implements EndpointInterface {
|
||||
const ENDPOINT = 'ppc-save-checkout-form';
|
||||
|
||||
/**
|
||||
* The Request Data Helper.
|
||||
*
|
||||
* @var RequestData
|
||||
*/
|
||||
private $request_data;
|
||||
|
||||
/**
|
||||
* The checkout form saver.
|
||||
*
|
||||
* @var CheckoutFormSaver
|
||||
*/
|
||||
private $checkout_form_saver;
|
||||
|
||||
/**
|
||||
* The logger.
|
||||
*
|
||||
* @var LoggerInterface
|
||||
*/
|
||||
protected $logger;
|
||||
|
||||
/**
|
||||
* SaveCheckoutFormEndpoint constructor.
|
||||
*
|
||||
* @param RequestData $request_data The Request Data Helper.
|
||||
* @param CheckoutFormSaver $checkout_form_saver The checkout form saver.
|
||||
* @param LoggerInterface $logger The logger.
|
||||
*/
|
||||
public function __construct(
|
||||
RequestData $request_data,
|
||||
CheckoutFormSaver $checkout_form_saver,
|
||||
LoggerInterface $logger
|
||||
) {
|
||||
|
||||
$this->request_data = $request_data;
|
||||
$this->checkout_form_saver = $checkout_form_saver;
|
||||
$this->logger = $logger;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the nonce.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function nonce(): string {
|
||||
return self::ENDPOINT;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles the request.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function handle_request(): bool {
|
||||
try {
|
||||
$data = $this->request_data->read_request( $this->nonce() );
|
||||
|
||||
$this->checkout_form_saver->save( $data['form'] );
|
||||
|
||||
wp_send_json_success();
|
||||
return true;
|
||||
} catch ( Exception $error ) {
|
||||
$this->logger->error( 'Checkout form saving failed: ' . $error->getMessage() );
|
||||
|
||||
wp_send_json_error(
|
||||
array(
|
||||
'message' => $error->getMessage(),
|
||||
)
|
||||
);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
32
modules/ppcp-button/src/Helper/CheckoutFormSaver.php
Normal file
32
modules/ppcp-button/src/Helper/CheckoutFormSaver.php
Normal file
|
@ -0,0 +1,32 @@
|
|||
<?php
|
||||
/**
|
||||
* Saves the form data to the WC customer and session.
|
||||
*
|
||||
* @package WooCommerce\PayPalCommerce\Button\Helper
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace WooCommerce\PayPalCommerce\Button\Helper;
|
||||
|
||||
use WC_Checkout;
|
||||
|
||||
/**
|
||||
* Class CheckoutFormSaver
|
||||
*/
|
||||
class CheckoutFormSaver extends WC_Checkout {
|
||||
/**
|
||||
* Saves the form data to the WC customer and session.
|
||||
*
|
||||
* @param array $data The form data.
|
||||
* @return void
|
||||
*/
|
||||
public function save( array $data ) {
|
||||
foreach ( $data as $key => $value ) {
|
||||
$_POST[ $key ] = $value;
|
||||
}
|
||||
$data = $this->get_posted_data();
|
||||
|
||||
$this->update_session( $data );
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue