mirror of
https://github.com/woocommerce/woocommerce-paypal-payments.git
synced 2025-09-06 12:25:15 +08:00
Merge branch 'trunk' into PCP-1544-pay-order-currency
This commit is contained in:
commit
d2a5ecf3b8
125 changed files with 9483 additions and 789 deletions
|
@ -9,6 +9,39 @@ class CartActionHandler {
|
|||
this.errorHandler = errorHandler;
|
||||
}
|
||||
|
||||
subscriptionsConfiguration() {
|
||||
return {
|
||||
createSubscription: (data, actions) => {
|
||||
return actions.subscription.create({
|
||||
'plan_id': this.config.subscription_plan_id
|
||||
});
|
||||
},
|
||||
onApprove: (data, actions) => {
|
||||
fetch(this.config.ajax.approve_subscription.endpoint, {
|
||||
method: 'POST',
|
||||
credentials: 'same-origin',
|
||||
body: JSON.stringify({
|
||||
nonce: this.config.ajax.approve_subscription.nonce,
|
||||
order_id: data.orderID,
|
||||
subscription_id: data.subscriptionID
|
||||
})
|
||||
}).then((res)=>{
|
||||
return res.json();
|
||||
}).then((data) => {
|
||||
if (!data.success) {
|
||||
console.log(data)
|
||||
throw Error(data.data.message);
|
||||
}
|
||||
|
||||
location.href = this.config.redirect;
|
||||
});
|
||||
},
|
||||
onError: (err) => {
|
||||
console.error(err);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
configuration() {
|
||||
const createOrder = (data, actions) => {
|
||||
const payer = payerData();
|
||||
|
|
|
@ -11,6 +11,34 @@ class CheckoutActionHandler {
|
|||
this.spinner = spinner;
|
||||
}
|
||||
|
||||
subscriptionsConfiguration() {
|
||||
return {
|
||||
createSubscription: (data, actions) => {
|
||||
return actions.subscription.create({
|
||||
'plan_id': this.config.subscription_plan_id
|
||||
});
|
||||
},
|
||||
onApprove: (data, actions) => {
|
||||
fetch(this.config.ajax.approve_subscription.endpoint, {
|
||||
method: 'POST',
|
||||
credentials: 'same-origin',
|
||||
body: JSON.stringify({
|
||||
nonce: this.config.ajax.approve_subscription.nonce,
|
||||
order_id: data.orderID,
|
||||
subscription_id: data.subscriptionID
|
||||
})
|
||||
}).then((res)=>{
|
||||
return res.json();
|
||||
}).then((data) => {
|
||||
document.querySelector('#place_order').click();
|
||||
});
|
||||
},
|
||||
onError: (err) => {
|
||||
console.error(err);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
configuration() {
|
||||
const spinner = this.spinner;
|
||||
const createOrder = (data, actions) => {
|
||||
|
@ -81,7 +109,7 @@ class CheckoutActionHandler {
|
|||
const input = document.createElement('input');
|
||||
input.setAttribute('type', 'hidden');
|
||||
input.setAttribute('name', 'ppcp-resume-order');
|
||||
input.setAttribute('value', data.data.purchase_units[0].custom_id);
|
||||
input.setAttribute('value', data.data.custom_id);
|
||||
document.querySelector(formSelector).appendChild(input);
|
||||
return data.data.id;
|
||||
});
|
||||
|
|
|
@ -18,6 +18,56 @@ class SingleProductActionHandler {
|
|||
this.errorHandler = errorHandler;
|
||||
}
|
||||
|
||||
subscriptionsConfiguration() {
|
||||
return {
|
||||
createSubscription: (data, actions) => {
|
||||
return actions.subscription.create({
|
||||
'plan_id': this.config.subscription_plan_id
|
||||
});
|
||||
},
|
||||
onApprove: (data, actions) => {
|
||||
fetch(this.config.ajax.approve_subscription.endpoint, {
|
||||
method: 'POST',
|
||||
credentials: 'same-origin',
|
||||
body: JSON.stringify({
|
||||
nonce: this.config.ajax.approve_subscription.nonce,
|
||||
order_id: data.orderID,
|
||||
subscription_id: data.subscriptionID
|
||||
})
|
||||
}).then((res)=>{
|
||||
return res.json();
|
||||
}).then(() => {
|
||||
const id = document.querySelector('[name="add-to-cart"]').value;
|
||||
const products = [new Product(id, 1, null)];
|
||||
|
||||
fetch(this.config.ajax.change_cart.endpoint, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
credentials: 'same-origin',
|
||||
body: JSON.stringify({
|
||||
nonce: this.config.ajax.change_cart.nonce,
|
||||
products,
|
||||
})
|
||||
}).then((result) => {
|
||||
return result.json();
|
||||
}).then((result) => {
|
||||
if (!result.success) {
|
||||
console.log(result)
|
||||
throw Error(result.data.message);
|
||||
}
|
||||
|
||||
location.href = this.config.redirect;
|
||||
})
|
||||
});
|
||||
},
|
||||
onError: (err) => {
|
||||
console.error(err);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
configuration()
|
||||
{
|
||||
return {
|
||||
|
|
|
@ -50,6 +50,14 @@ class CartBootstrap {
|
|||
this.errorHandler,
|
||||
);
|
||||
|
||||
if(
|
||||
PayPalCommerceGateway.data_client_id.has_subscriptions
|
||||
&& PayPalCommerceGateway.data_client_id.paypal_subscriptions_enabled
|
||||
) {
|
||||
this.renderer.render(actionHandler.subscriptionsConfiguration());
|
||||
return;
|
||||
}
|
||||
|
||||
this.renderer.render(
|
||||
actionHandler.configuration()
|
||||
);
|
||||
|
|
|
@ -64,9 +64,15 @@ class CheckoutBootstap {
|
|||
this.spinner
|
||||
);
|
||||
|
||||
this.renderer.render(
|
||||
actionHandler.configuration()
|
||||
);
|
||||
if(
|
||||
PayPalCommerceGateway.data_client_id.has_subscriptions
|
||||
&& PayPalCommerceGateway.data_client_id.paypal_subscriptions_enabled
|
||||
) {
|
||||
this.renderer.render(actionHandler.subscriptionsConfiguration(), {}, actionHandler.configuration());
|
||||
return;
|
||||
}
|
||||
|
||||
this.renderer.render(actionHandler.configuration(), {}, actionHandler.configuration());
|
||||
}
|
||||
|
||||
updateUi() {
|
||||
|
|
|
@ -110,6 +110,14 @@ class SingleProductBootstap {
|
|||
this.errorHandler,
|
||||
);
|
||||
|
||||
if(
|
||||
PayPalCommerceGateway.data_client_id.has_subscriptions
|
||||
&& PayPalCommerceGateway.data_client_id.paypal_subscriptions_enabled
|
||||
) {
|
||||
this.renderer.render(actionHandler.subscriptionsConfiguration());
|
||||
return;
|
||||
}
|
||||
|
||||
this.renderer.render(
|
||||
actionHandler.configuration()
|
||||
);
|
||||
|
|
|
@ -10,7 +10,7 @@ class Renderer {
|
|||
this.renderedSources = new Set();
|
||||
}
|
||||
|
||||
render(contextConfig, settingsOverride = {}) {
|
||||
render(contextConfig, settingsOverride = {}, contextConfigOverride = () => {}) {
|
||||
const settings = merge(this.defaultSettings, settingsOverride);
|
||||
|
||||
const enabledSeparateGateways = Object.fromEntries(Object.entries(
|
||||
|
@ -50,7 +50,7 @@ class Renderer {
|
|||
}
|
||||
|
||||
if (this.creditCardRenderer) {
|
||||
this.creditCardRenderer.render(settings.hosted_fields.wrapper, contextConfig);
|
||||
this.creditCardRenderer.render(settings.hosted_fields.wrapper, contextConfigOverride);
|
||||
}
|
||||
|
||||
for (const [fundingSource, data] of Object.entries(enabledSeparateGateways)) {
|
||||
|
|
|
@ -9,11 +9,13 @@ declare(strict_types=1);
|
|||
|
||||
namespace WooCommerce\PayPalCommerce\Button;
|
||||
|
||||
use WooCommerce\PayPalCommerce\Button\Endpoint\ApproveSubscriptionEndpoint;
|
||||
use WooCommerce\PayPalCommerce\Button\Endpoint\CartScriptParamsEndpoint;
|
||||
use WooCommerce\PayPalCommerce\Button\Helper\CheckoutFormSaver;
|
||||
use WooCommerce\PayPalCommerce\Button\Endpoint\SaveCheckoutFormEndpoint;
|
||||
use WooCommerce\PayPalCommerce\Button\Validation\CheckoutFormValidator;
|
||||
use WooCommerce\PayPalCommerce\Button\Endpoint\ValidateCheckoutEndpoint;
|
||||
use WooCommerce\PayPalCommerce\Subscription\Helper\SubscriptionHelper;
|
||||
use WooCommerce\PayPalCommerce\Vendor\Psr\Container\ContainerInterface;
|
||||
use WooCommerce\PayPalCommerce\Button\Assets\DisabledSmartButton;
|
||||
use WooCommerce\PayPalCommerce\Button\Assets\SmartButton;
|
||||
|
@ -65,25 +67,37 @@ return array(
|
|||
|
||||
return $dummy_ids[ $shop_country ] ?? $container->get( 'button.client_id' );
|
||||
},
|
||||
'button.smart-button' => static function ( ContainerInterface $container ): SmartButtonInterface {
|
||||
'button.is_paypal_continuation' => static function( ContainerInterface $container ): bool {
|
||||
$session_handler = $container->get( 'session.handler' );
|
||||
|
||||
$order = $session_handler->order();
|
||||
if ( ! $order ) {
|
||||
return false;
|
||||
}
|
||||
$source = $order->payment_source();
|
||||
if ( $source && $source->card() ) {
|
||||
return false; // Ignore for DCC.
|
||||
}
|
||||
if ( 'card' === $session_handler->funding_source() ) {
|
||||
return false; // Ignore for card buttons.
|
||||
}
|
||||
|
||||
return true;
|
||||
},
|
||||
'button.smart-button' => static function ( ContainerInterface $container ): SmartButtonInterface {
|
||||
$state = $container->get( 'onboarding.state' );
|
||||
/**
|
||||
* The state.
|
||||
*
|
||||
* @var State $state
|
||||
*/
|
||||
if ( $state->current_state() !== State::STATE_ONBOARDED ) {
|
||||
return new DisabledSmartButton();
|
||||
}
|
||||
|
||||
$settings = $container->get( 'wcgateway.settings' );
|
||||
$paypal_disabled = ! $settings->has( 'enabled' ) || ! $settings->get( 'enabled' );
|
||||
if ( $paypal_disabled ) {
|
||||
return new DisabledSmartButton();
|
||||
}
|
||||
|
||||
$payer_factory = $container->get( 'api.factory.payer' );
|
||||
$request_data = $container->get( 'button.request-data' );
|
||||
|
||||
$client_id = $container->get( 'button.client_id' );
|
||||
$dcc_applies = $container->get( 'api.helpers.dccapplies' );
|
||||
$subscription_helper = $container->get( 'subscription.helper' );
|
||||
|
@ -110,6 +124,7 @@ return array(
|
|||
$container->get( 'wcgateway.all-funding-sources' ),
|
||||
$container->get( 'button.basic-checkout-validation-enabled' ),
|
||||
$container->get( 'button.early-wc-checkout-validation-enabled' ),
|
||||
$container->get( 'button.pay-now-contexts' ),
|
||||
$container->get( 'woocommerce.logger.woocommerce' )
|
||||
);
|
||||
},
|
||||
|
@ -119,6 +134,9 @@ return array(
|
|||
dirname( realpath( __FILE__ ), 3 ) . '/woocommerce-paypal-payments.php'
|
||||
);
|
||||
},
|
||||
'button.pay-now-contexts' => static function ( ContainerInterface $container ): array {
|
||||
return array( 'checkout', 'pay-now' );
|
||||
},
|
||||
'button.request-data' => static function ( ContainerInterface $container ): RequestData {
|
||||
return new RequestData();
|
||||
},
|
||||
|
@ -156,6 +174,8 @@ return array(
|
|||
$registration_needed,
|
||||
$container->get( 'wcgateway.settings.card_billing_data_mode' ),
|
||||
$container->get( 'button.early-wc-checkout-validation-enabled' ),
|
||||
$container->get( 'button.pay-now-contexts' ),
|
||||
$container->get( 'button.handle-shipping-in-paypal' ),
|
||||
$logger
|
||||
);
|
||||
},
|
||||
|
@ -187,6 +207,13 @@ return array(
|
|||
$logger
|
||||
);
|
||||
},
|
||||
'button.endpoint.approve-subscription' => static function( ContainerInterface $container ): ApproveSubscriptionEndpoint {
|
||||
return new ApproveSubscriptionEndpoint(
|
||||
$container->get( 'button.request-data' ),
|
||||
$container->get( 'api.endpoint.order' ),
|
||||
$container->get( 'session.handler' )
|
||||
);
|
||||
},
|
||||
'button.checkout-form-saver' => static function ( ContainerInterface $container ): CheckoutFormSaver {
|
||||
return new CheckoutFormSaver();
|
||||
},
|
||||
|
@ -266,4 +293,12 @@ return array(
|
|||
'button.validation.wc-checkout-validator' => static function ( ContainerInterface $container ): CheckoutFormValidator {
|
||||
return new CheckoutFormValidator();
|
||||
},
|
||||
|
||||
/**
|
||||
* If true, the shipping methods are sent to PayPal allowing the customer to select it inside the popup.
|
||||
* May result in slower popup performance, additional loading.
|
||||
*/
|
||||
'button.handle-shipping-in-paypal' => static function ( ContainerInterface $container ): bool {
|
||||
return false;
|
||||
},
|
||||
);
|
||||
|
|
|
@ -26,7 +26,7 @@ class DisabledSmartButton implements SmartButtonInterface {
|
|||
/**
|
||||
* Whether the scripts should be loaded.
|
||||
*/
|
||||
public function should_load(): bool {
|
||||
public function should_load_ppcp_script(): bool {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
@ -18,6 +18,7 @@ use WooCommerce\PayPalCommerce\ApiClient\Entity\PaymentToken;
|
|||
use WooCommerce\PayPalCommerce\ApiClient\Factory\PayerFactory;
|
||||
use WooCommerce\PayPalCommerce\ApiClient\Helper\DccApplies;
|
||||
use WooCommerce\PayPalCommerce\Button\Endpoint\ApproveOrderEndpoint;
|
||||
use WooCommerce\PayPalCommerce\Button\Endpoint\ApproveSubscriptionEndpoint;
|
||||
use WooCommerce\PayPalCommerce\Button\Endpoint\CartScriptParamsEndpoint;
|
||||
use WooCommerce\PayPalCommerce\Button\Endpoint\ChangeCartEndpoint;
|
||||
use WooCommerce\PayPalCommerce\Button\Endpoint\CreateOrderEndpoint;
|
||||
|
@ -68,13 +69,6 @@ class SmartButton implements SmartButtonInterface {
|
|||
*/
|
||||
private $version;
|
||||
|
||||
/**
|
||||
* The Session Handler.
|
||||
*
|
||||
* @var SessionHandler
|
||||
*/
|
||||
private $session_handler;
|
||||
|
||||
/**
|
||||
* The settings.
|
||||
*
|
||||
|
@ -166,13 +160,6 @@ class SmartButton implements SmartButtonInterface {
|
|||
*/
|
||||
protected $early_validation_enabled;
|
||||
|
||||
/**
|
||||
* The logger.
|
||||
*
|
||||
* @var LoggerInterface
|
||||
*/
|
||||
private $logger;
|
||||
|
||||
/**
|
||||
* Cached payment tokens.
|
||||
*
|
||||
|
@ -180,12 +167,33 @@ class SmartButton implements SmartButtonInterface {
|
|||
*/
|
||||
private $payment_tokens = null;
|
||||
|
||||
/**
|
||||
* The contexts that should have the Pay Now button.
|
||||
*
|
||||
* @var string[]
|
||||
*/
|
||||
private $pay_now_contexts;
|
||||
|
||||
/**
|
||||
* The logger.
|
||||
*
|
||||
* @var LoggerInterface
|
||||
*/
|
||||
private $logger;
|
||||
|
||||
/**
|
||||
* Session handler.
|
||||
*
|
||||
* @var SessionHandler
|
||||
*/
|
||||
private $session_handler;
|
||||
|
||||
/**
|
||||
* SmartButton constructor.
|
||||
*
|
||||
* @param string $module_url The URL to the module.
|
||||
* @param string $version The assets version.
|
||||
* @param SessionHandler $session_handler The Session Handler.
|
||||
* @param string $version The assets version.
|
||||
* @param SessionHandler $session_handler The Session handler.
|
||||
* @param Settings $settings The Settings.
|
||||
* @param PayerFactory $payer_factory The Payer factory.
|
||||
* @param string $client_id The client ID.
|
||||
|
@ -200,6 +208,7 @@ class SmartButton implements SmartButtonInterface {
|
|||
* @param array $all_funding_sources All existing funding sources.
|
||||
* @param bool $basic_checkout_validation_enabled Whether the basic JS validation of the form iss enabled.
|
||||
* @param bool $early_validation_enabled Whether to execute WC validation of the checkout form.
|
||||
* @param array $pay_now_contexts The contexts that should have the Pay Now button.
|
||||
* @param LoggerInterface $logger The logger.
|
||||
*/
|
||||
public function __construct(
|
||||
|
@ -220,6 +229,7 @@ class SmartButton implements SmartButtonInterface {
|
|||
array $all_funding_sources,
|
||||
bool $basic_checkout_validation_enabled,
|
||||
bool $early_validation_enabled,
|
||||
array $pay_now_contexts,
|
||||
LoggerInterface $logger
|
||||
) {
|
||||
|
||||
|
@ -240,6 +250,7 @@ class SmartButton implements SmartButtonInterface {
|
|||
$this->all_funding_sources = $all_funding_sources;
|
||||
$this->basic_checkout_validation_enabled = $basic_checkout_validation_enabled;
|
||||
$this->early_validation_enabled = $early_validation_enabled;
|
||||
$this->pay_now_contexts = $pay_now_contexts;
|
||||
$this->logger = $logger;
|
||||
}
|
||||
|
||||
|
@ -254,10 +265,6 @@ class SmartButton implements SmartButtonInterface {
|
|||
$this->render_message_wrapper_registrar();
|
||||
}
|
||||
|
||||
if ( ! $this->can_save_vault_token() && $this->has_subscriptions() ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (
|
||||
$this->settings->has( 'dcc_enabled' )
|
||||
&& $this->settings->get( 'dcc_enabled' )
|
||||
|
@ -284,7 +291,7 @@ class SmartButton implements SmartButtonInterface {
|
|||
add_filter(
|
||||
'woocommerce_credit_card_form_fields',
|
||||
function ( array $default_fields, $id ) use ( $subscription_helper ) : array {
|
||||
if ( is_user_logged_in() && $this->settings->has( 'vault_enabled' ) && $this->settings->get( 'vault_enabled' ) && CreditCardGateway::ID === $id ) {
|
||||
if ( is_user_logged_in() && $this->settings->has( 'vault_enabled_dcc' ) && $this->settings->get( 'vault_enabled_dcc' ) && CreditCardGateway::ID === $id ) {
|
||||
|
||||
$default_fields['card-vault'] = sprintf(
|
||||
'<p class="form-row form-row-wide"><label for="ppcp-credit-card-vault"><input class="ppcp-credit-card-vault" type="checkbox" id="ppcp-credit-card-vault" name="vault">%s</label></p>',
|
||||
|
@ -455,10 +462,6 @@ class SmartButton implements SmartButtonInterface {
|
|||
add_action(
|
||||
$this->mini_cart_button_renderer_hook(),
|
||||
function () {
|
||||
if ( ! $this->can_save_vault_token() && $this->has_subscriptions() ) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ( $this->is_cart_price_total_zero() || $this->is_free_trial_cart() ) {
|
||||
return;
|
||||
}
|
||||
|
@ -509,31 +512,70 @@ class SmartButton implements SmartButtonInterface {
|
|||
}
|
||||
|
||||
/**
|
||||
* Whether the scripts should be loaded.
|
||||
* Whether any of our scripts (for DCC or product, mini-cart, non-block cart/checkout) should be loaded.
|
||||
*/
|
||||
public function should_load(): bool {
|
||||
public function should_load_ppcp_script(): bool {
|
||||
$buttons_enabled = $this->settings->has( 'enabled' ) && $this->settings->get( 'enabled' );
|
||||
if ( ! is_checkout() && ! $buttons_enabled ) {
|
||||
if ( ! $buttons_enabled ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
if ( in_array( $this->context(), array( 'checkout-block', 'cart-block' ), true ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return $this->should_load_buttons() || $this->can_render_dcc();
|
||||
}
|
||||
|
||||
/**
|
||||
* Enqueues the scripts.
|
||||
* Determines whether the button component should be loaded.
|
||||
*/
|
||||
public function enqueue(): void {
|
||||
if ( ! $this->should_load() ) {
|
||||
return;
|
||||
public function should_load_buttons() : bool {
|
||||
$buttons_enabled = $this->settings->has( 'enabled' ) && $this->settings->get( 'enabled' );
|
||||
if ( ! $buttons_enabled ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$load_script = false;
|
||||
if ( is_checkout() && $this->settings->has( 'dcc_enabled' ) && $this->settings->get( 'dcc_enabled' ) ) {
|
||||
$load_script = true;
|
||||
$smart_button_enabled_for_current_location = $this->settings_status->is_smart_button_enabled_for_location( $this->context() );
|
||||
$smart_button_enabled_for_mini_cart = $this->settings_status->is_smart_button_enabled_for_location( 'mini-cart' );
|
||||
$messaging_enabled_for_current_location = $this->settings_status->is_pay_later_messaging_enabled_for_location( $this->context() );
|
||||
|
||||
switch ( $this->context() ) {
|
||||
case 'checkout':
|
||||
case 'cart':
|
||||
case 'pay-now':
|
||||
return $smart_button_enabled_for_current_location || $messaging_enabled_for_current_location;
|
||||
case 'checkout-block':
|
||||
case 'cart-block':
|
||||
return $smart_button_enabled_for_current_location;
|
||||
case 'product':
|
||||
return $smart_button_enabled_for_current_location || $messaging_enabled_for_current_location || $smart_button_enabled_for_mini_cart;
|
||||
default:
|
||||
return $smart_button_enabled_for_mini_cart;
|
||||
}
|
||||
if ( $this->load_button_component() ) {
|
||||
$load_script = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether DCC fields can be rendered.
|
||||
*/
|
||||
public function can_render_dcc() : bool {
|
||||
return $this->settings->has( 'dcc_enabled' ) && $this->settings->get( 'dcc_enabled' )
|
||||
&& $this->settings->has( 'client_id' ) && $this->settings->get( 'client_id' )
|
||||
&& $this->dcc_applies->for_country_currency()
|
||||
&& in_array( $this->context(), array( 'checkout', 'pay-now' ), true );
|
||||
}
|
||||
|
||||
/**
|
||||
* Enqueues our scripts/styles (for DCC and product, mini-cart and non-block cart/checkout)
|
||||
*/
|
||||
public function enqueue(): void {
|
||||
if ( $this->can_render_dcc() ) {
|
||||
wp_enqueue_style(
|
||||
'ppcp-hosted-fields',
|
||||
untrailingslashit( $this->module_url ) . '/assets/css/hosted-fields.css',
|
||||
array(),
|
||||
$this->version
|
||||
);
|
||||
}
|
||||
|
||||
if ( in_array( $this->context(), array( 'pay-now', 'checkout' ), true ) ) {
|
||||
|
@ -543,31 +585,21 @@ class SmartButton implements SmartButtonInterface {
|
|||
array(),
|
||||
$this->version
|
||||
);
|
||||
|
||||
if ( $this->can_render_dcc() ) {
|
||||
wp_enqueue_style(
|
||||
'ppcp-hosted-fields',
|
||||
untrailingslashit( $this->module_url ) . '/assets/css/hosted-fields.css',
|
||||
array(),
|
||||
$this->version
|
||||
);
|
||||
}
|
||||
}
|
||||
if ( $load_script ) {
|
||||
wp_enqueue_script(
|
||||
'ppcp-smart-button',
|
||||
untrailingslashit( $this->module_url ) . '/assets/js/button.js',
|
||||
array( 'jquery' ),
|
||||
$this->version,
|
||||
true
|
||||
);
|
||||
|
||||
wp_localize_script(
|
||||
'ppcp-smart-button',
|
||||
'PayPalCommerceGateway',
|
||||
$this->script_data()
|
||||
);
|
||||
}
|
||||
wp_enqueue_script(
|
||||
'ppcp-smart-button',
|
||||
untrailingslashit( $this->module_url ) . '/assets/js/button.js',
|
||||
array( 'jquery' ),
|
||||
$this->version,
|
||||
true
|
||||
);
|
||||
|
||||
wp_localize_script(
|
||||
'ppcp-smart-button',
|
||||
'PayPalCommerceGateway',
|
||||
$this->script_data()
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -577,10 +609,6 @@ class SmartButton implements SmartButtonInterface {
|
|||
*/
|
||||
public function button_renderer( string $gateway_id ) {
|
||||
|
||||
if ( ! $this->can_save_vault_token() && $this->has_subscriptions() ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$available_gateways = WC()->payment_gateways->get_available_payment_gateways();
|
||||
|
||||
if ( ! isset( $available_gateways[ $gateway_id ] ) ) {
|
||||
|
@ -596,9 +624,6 @@ class SmartButton implements SmartButtonInterface {
|
|||
* Renders the HTML for the credit messaging.
|
||||
*/
|
||||
public function message_renderer() {
|
||||
if ( ! $this->can_save_vault_token() && $this->has_subscriptions() ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$product = wc_get_product();
|
||||
|
||||
|
@ -666,18 +691,6 @@ class SmartButton implements SmartButtonInterface {
|
|||
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether DCC fields can be rendered.
|
||||
*
|
||||
* @return bool
|
||||
* @throws NotFoundException When a setting was not found.
|
||||
*/
|
||||
private function can_render_dcc() : bool {
|
||||
|
||||
$can_render = $this->settings->has( 'dcc_enabled' ) && $this->settings->get( 'dcc_enabled' ) && $this->settings->has( 'client_id' ) && $this->settings->get( 'client_id' ) && $this->dcc_applies->for_country_currency();
|
||||
return $can_render;
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders the HTML for the DCC fields.
|
||||
*/
|
||||
|
@ -710,7 +723,6 @@ class SmartButton implements SmartButtonInterface {
|
|||
* Whether we can store vault tokens or not.
|
||||
*
|
||||
* @return bool
|
||||
* @throws NotFoundException If a setting hasn't been found.
|
||||
*/
|
||||
public function can_save_vault_token(): bool {
|
||||
|
||||
|
@ -744,6 +756,25 @@ class SmartButton implements SmartButtonInterface {
|
|||
return $this->subscription_helper->cart_contains_subscription();
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether PayPal subscriptions is enabled or not.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
private function paypal_subscriptions_enabled(): bool {
|
||||
if ( defined( 'PPCP_FLAG_SUBSCRIPTIONS_API' ) && ! PPCP_FLAG_SUBSCRIPTIONS_API ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
try {
|
||||
$subscriptions_mode = $this->settings->get( 'subscriptions_mode' );
|
||||
} catch ( NotFoundException $exception ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return $subscriptions_mode === 'subscriptions_api';
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the 3D Secure contingency settings.
|
||||
*
|
||||
|
@ -764,7 +795,6 @@ class SmartButton implements SmartButtonInterface {
|
|||
* The configuration for the smart buttons.
|
||||
*
|
||||
* @return array
|
||||
* @throws NotFoundException If a setting hasn't been found.
|
||||
*/
|
||||
public function script_data(): array {
|
||||
$is_free_trial_cart = $this->is_free_trial_cart();
|
||||
|
@ -777,43 +807,49 @@ class SmartButton implements SmartButtonInterface {
|
|||
'url_params' => $url_params,
|
||||
'script_attributes' => $this->attributes(),
|
||||
'data_client_id' => array(
|
||||
'set_attribute' => ( is_checkout() && $this->dcc_is_enabled() ) || $this->can_save_vault_token(),
|
||||
'endpoint' => \WC_AJAX::get_endpoint( DataClientIdEndpoint::ENDPOINT ),
|
||||
'nonce' => wp_create_nonce( DataClientIdEndpoint::nonce() ),
|
||||
'user' => get_current_user_id(),
|
||||
'has_subscriptions' => $this->has_subscriptions(),
|
||||
'set_attribute' => ( is_checkout() && $this->dcc_is_enabled() ) || $this->can_save_vault_token(),
|
||||
'endpoint' => \WC_AJAX::get_endpoint( DataClientIdEndpoint::ENDPOINT ),
|
||||
'nonce' => wp_create_nonce( DataClientIdEndpoint::nonce() ),
|
||||
'user' => get_current_user_id(),
|
||||
'has_subscriptions' => $this->has_subscriptions(),
|
||||
'paypal_subscriptions_enabled' => $this->paypal_subscriptions_enabled(),
|
||||
),
|
||||
'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(
|
||||
'approve_subscription' => array(
|
||||
'endpoint' => \WC_AJAX::get_endpoint( ApproveSubscriptionEndpoint::ENDPOINT ),
|
||||
'nonce' => wp_create_nonce( ApproveSubscriptionEndpoint::nonce() ),
|
||||
),
|
||||
'vault_paypal' => array(
|
||||
'endpoint' => \WC_AJAX::get_endpoint( StartPayPalVaultingEndpoint::ENDPOINT ),
|
||||
'nonce' => wp_create_nonce( StartPayPalVaultingEndpoint::nonce() ),
|
||||
),
|
||||
'save_checkout_form' => array(
|
||||
'save_checkout_form' => array(
|
||||
'endpoint' => \WC_AJAX::get_endpoint( SaveCheckoutFormEndpoint::ENDPOINT ),
|
||||
'nonce' => wp_create_nonce( SaveCheckoutFormEndpoint::nonce() ),
|
||||
),
|
||||
'validate_checkout' => array(
|
||||
'validate_checkout' => array(
|
||||
'endpoint' => \WC_AJAX::get_endpoint( ValidateCheckoutEndpoint::ENDPOINT ),
|
||||
'nonce' => wp_create_nonce( ValidateCheckoutEndpoint::nonce() ),
|
||||
),
|
||||
'cart_script_params' => array(
|
||||
'cart_script_params' => array(
|
||||
'endpoint' => \WC_AJAX::get_endpoint( CartScriptParamsEndpoint::ENDPOINT ),
|
||||
),
|
||||
),
|
||||
'subscription_plan_id' => $this->paypal_subscription_id(),
|
||||
'enforce_vault' => $this->has_subscriptions(),
|
||||
'can_save_vault_token' => $this->can_save_vault_token(),
|
||||
'is_free_trial_cart' => $is_free_trial_cart,
|
||||
|
@ -911,6 +947,15 @@ class SmartButton implements SmartButtonInterface {
|
|||
$localize['button']['style']['tagline'] = false;
|
||||
}
|
||||
|
||||
if ( $this->is_paypal_continuation() ) {
|
||||
$order = $this->session_handler->order();
|
||||
assert( $order !== null );
|
||||
|
||||
$localize['continuation'] = array(
|
||||
'order_id' => $order->id(),
|
||||
);
|
||||
}
|
||||
|
||||
$this->request_data->dequeue_nonce_fix();
|
||||
return $localize;
|
||||
}
|
||||
|
@ -933,21 +978,24 @@ class SmartButton implements SmartButtonInterface {
|
|||
* The JavaScript SDK url parameters.
|
||||
*
|
||||
* @return array
|
||||
* @throws NotFoundException If a setting was not found.
|
||||
*/
|
||||
private function url_params(): array {
|
||||
$intent = ( $this->settings->has( 'intent' ) ) ? $this->settings->get( 'intent' ) : 'capture';
|
||||
$product_intent = $this->subscription_helper->current_product_is_subscription() ? 'authorize' : $intent;
|
||||
$other_context_intent = $this->subscription_helper->cart_contains_subscription() ? 'authorize' : $intent;
|
||||
$context = $this->context();
|
||||
try {
|
||||
$intent = $this->intent();
|
||||
} catch ( NotFoundException $exception ) {
|
||||
$intent = 'capture';
|
||||
}
|
||||
|
||||
$params = array(
|
||||
$subscription_mode = $this->settings->has( 'subscriptions_mode' ) ? $this->settings->get( 'subscriptions_mode' ) : '';
|
||||
$params = array(
|
||||
'client-id' => $this->client_id,
|
||||
'currency' => $this->currency,
|
||||
'integration-date' => PAYPAL_INTEGRATION_DATE,
|
||||
'components' => implode( ',', $this->components() ),
|
||||
'vault' => $this->can_save_vault_token() ? 'true' : 'false',
|
||||
'commit' => is_checkout() ? 'true' : 'false',
|
||||
'intent' => $this->context() === 'product' ? $product_intent : $other_context_intent,
|
||||
'vault' => ( $this->can_save_vault_token() || $this->subscription_helper->need_subscription_intent( $subscription_mode ) ) ? 'true' : 'false',
|
||||
'commit' => in_array( $context, $this->pay_now_contexts, true ) ? 'true' : 'false',
|
||||
'intent' => $intent,
|
||||
);
|
||||
if (
|
||||
$this->environment->current_environment_is( Environment::SANDBOX )
|
||||
|
@ -991,6 +1039,13 @@ class SmartButton implements SmartButtonInterface {
|
|||
}
|
||||
}
|
||||
|
||||
if ( in_array( $context, array( 'checkout-block', 'cart-block' ), true ) ) {
|
||||
$disable_funding = array_diff(
|
||||
array_keys( $this->all_funding_sources ),
|
||||
array( 'venmo', 'paylater' )
|
||||
);
|
||||
}
|
||||
|
||||
if ( $this->is_free_trial_cart() ) {
|
||||
$all_sources = array_keys( $this->all_funding_sources );
|
||||
if ( $is_dcc_enabled || $is_separate_card_enabled ) {
|
||||
|
@ -1001,8 +1056,8 @@ class SmartButton implements SmartButtonInterface {
|
|||
|
||||
$enable_funding = array( 'venmo' );
|
||||
|
||||
if ( $this->settings_status->is_pay_later_button_enabled_for_location( $this->context() ) ||
|
||||
$this->settings_status->is_pay_later_messaging_enabled_for_location( $this->context() )
|
||||
if ( $this->settings_status->is_pay_later_button_enabled_for_location( $context ) ||
|
||||
$this->settings_status->is_pay_later_messaging_enabled_for_location( $context )
|
||||
) {
|
||||
$enable_funding[] = 'paylater';
|
||||
} else {
|
||||
|
@ -1071,7 +1126,7 @@ class SmartButton implements SmartButtonInterface {
|
|||
private function components(): array {
|
||||
$components = array();
|
||||
|
||||
if ( $this->load_button_component() ) {
|
||||
if ( $this->should_load_buttons() ) {
|
||||
$components[] = 'buttons';
|
||||
$components[] = 'funding-eligibility';
|
||||
}
|
||||
|
@ -1087,34 +1142,10 @@ class SmartButton implements SmartButtonInterface {
|
|||
return $components;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines whether the button component should be loaded.
|
||||
*
|
||||
* @return bool
|
||||
* @throws NotFoundException If a setting has not been found.
|
||||
*/
|
||||
private function load_button_component() : bool {
|
||||
$smart_button_enabled_for_current_location = $this->settings_status->is_smart_button_enabled_for_location( $this->context() );
|
||||
$smart_button_enabled_for_mini_cart = $this->settings_status->is_smart_button_enabled_for_location( 'mini-cart' );
|
||||
$messaging_enabled_for_current_location = $this->settings_status->is_pay_later_messaging_enabled_for_location( $this->context() );
|
||||
|
||||
switch ( $this->context() ) {
|
||||
case 'checkout':
|
||||
case 'cart':
|
||||
case 'pay-now':
|
||||
return $smart_button_enabled_for_current_location || $messaging_enabled_for_current_location;
|
||||
case 'product':
|
||||
return $smart_button_enabled_for_current_location || $messaging_enabled_for_current_location || $smart_button_enabled_for_mini_cart;
|
||||
default:
|
||||
return $smart_button_enabled_for_mini_cart;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether DCC is enabled or not.
|
||||
*
|
||||
* @return bool
|
||||
* @throws NotFoundException If a setting has not been found.
|
||||
*/
|
||||
private function dcc_is_enabled(): bool {
|
||||
if ( ! is_checkout() ) {
|
||||
|
@ -1143,9 +1174,11 @@ class SmartButton implements SmartButtonInterface {
|
|||
* @param string $context The context.
|
||||
*
|
||||
* @return string
|
||||
* @throws NotFoundException When a setting hasn't been found.
|
||||
*/
|
||||
private function style_for_context( string $style, string $context ): string {
|
||||
// Use the cart/checkout styles for blocks.
|
||||
$context = str_replace( '-block', '', $context );
|
||||
|
||||
$defaults = array(
|
||||
'layout' => 'vertical',
|
||||
'size' => 'responsive',
|
||||
|
@ -1362,6 +1395,57 @@ class SmartButton implements SmartButtonInterface {
|
|||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns PayPal subscription plan id from WC subscription product.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
private function paypal_subscription_id(): string {
|
||||
if ( $this->subscription_helper->current_product_is_subscription() ) {
|
||||
$product = wc_get_product();
|
||||
assert( $product instanceof WC_Product );
|
||||
|
||||
if ( $product->get_type() === 'subscription' && $product->meta_exists( 'ppcp_subscription_plan' ) ) {
|
||||
return $product->get_meta( 'ppcp_subscription_plan' )['id'];
|
||||
}
|
||||
}
|
||||
|
||||
$cart = WC()->cart ?? null;
|
||||
if ( ! $cart || $cart->is_empty() ) {
|
||||
return '';
|
||||
}
|
||||
$items = $cart->get_cart_contents();
|
||||
foreach ( $items as $item ) {
|
||||
$product = wc_get_product( $item['product_id'] );
|
||||
assert( $product instanceof WC_Product );
|
||||
|
||||
if ( $product->get_type() === 'subscription' && $product->meta_exists( 'ppcp_subscription_plan' ) ) {
|
||||
return $product->get_meta( 'ppcp_subscription_plan' )['id'];
|
||||
}
|
||||
}
|
||||
|
||||
return '';
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the intent.
|
||||
*
|
||||
* @return string
|
||||
* @throws NotFoundException If intent is not found.
|
||||
*/
|
||||
private function intent(): string {
|
||||
$intent = ( $this->settings->has( 'intent' ) ) ? $this->settings->get( 'intent' ) : 'capture';
|
||||
$product_intent = $this->subscription_helper->current_product_is_subscription() ? 'authorize' : $intent;
|
||||
$other_context_intent = $this->subscription_helper->cart_contains_subscription() ? 'authorize' : $intent;
|
||||
|
||||
$subscription_mode = $this->settings->has( 'subscriptions_mode' ) ? $this->settings->get( 'subscriptions_mode' ) : '';
|
||||
if ( $this->subscription_helper->need_subscription_intent( $subscription_mode ) ) {
|
||||
return 'subscription';
|
||||
}
|
||||
|
||||
return $this->context() === 'product' ? $product_intent : $other_context_intent;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the ID of WC order on the order-pay page, or 0.
|
||||
*
|
||||
|
|
|
@ -22,22 +22,15 @@ interface SmartButtonInterface {
|
|||
public function render_wrapper(): bool;
|
||||
|
||||
/**
|
||||
* Whether the scripts should be loaded.
|
||||
* Whether any of our scripts (for DCC or product, mini-cart, non-block cart/checkout) should be loaded.
|
||||
*/
|
||||
public function should_load(): bool;
|
||||
public function should_load_ppcp_script(): bool;
|
||||
|
||||
/**
|
||||
* Enqueues the necessary scripts.
|
||||
* Enqueues our scripts/styles (for DCC and product, mini-cart and non-block cart/checkout)
|
||||
*/
|
||||
public function enqueue(): void;
|
||||
|
||||
/**
|
||||
* Whether the running installation could save vault tokens or not.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function can_save_vault_token(): bool;
|
||||
|
||||
/**
|
||||
* The configuration for the smart buttons.
|
||||
*
|
||||
|
|
|
@ -9,6 +9,7 @@ declare(strict_types=1);
|
|||
|
||||
namespace WooCommerce\PayPalCommerce\Button;
|
||||
|
||||
use WooCommerce\PayPalCommerce\Button\Endpoint\ApproveSubscriptionEndpoint;
|
||||
use WooCommerce\PayPalCommerce\Button\Endpoint\CartScriptParamsEndpoint;
|
||||
use WooCommerce\PayPalCommerce\Button\Endpoint\SaveCheckoutFormEndpoint;
|
||||
use WooCommerce\PayPalCommerce\Button\Endpoint\ValidateCheckoutEndpoint;
|
||||
|
@ -63,14 +64,12 @@ class ButtonModule implements ModuleInterface {
|
|||
add_action(
|
||||
'wp_enqueue_scripts',
|
||||
static function () use ( $c ) {
|
||||
|
||||
$smart_button = $c->get( 'button.smart-button' );
|
||||
/**
|
||||
* The Smart Button.
|
||||
*
|
||||
* @var SmartButtonInterface $smart_button
|
||||
*/
|
||||
$smart_button->enqueue();
|
||||
assert( $smart_button instanceof SmartButtonInterface );
|
||||
|
||||
if ( $smart_button->should_load_ppcp_script() ) {
|
||||
$smart_button->enqueue();
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
|
@ -147,6 +146,16 @@ class ButtonModule implements ModuleInterface {
|
|||
}
|
||||
);
|
||||
|
||||
add_action(
|
||||
'wc_ajax_' . ApproveSubscriptionEndpoint::ENDPOINT,
|
||||
static function () use ( $container ) {
|
||||
$endpoint = $container->get( 'button.endpoint.approve-subscription' );
|
||||
assert( $endpoint instanceof ApproveSubscriptionEndpoint );
|
||||
|
||||
$endpoint->handle_request();
|
||||
}
|
||||
);
|
||||
|
||||
add_action(
|
||||
'wc_ajax_' . CreateOrderEndpoint::ENDPOINT,
|
||||
static function () use ( $container ) {
|
||||
|
|
|
@ -180,7 +180,7 @@ class ApproveOrderEndpoint implements EndpointInterface {
|
|||
);
|
||||
}
|
||||
$this->session_handler->replace_order( $order );
|
||||
wp_send_json_success( $order );
|
||||
wp_send_json_success();
|
||||
}
|
||||
|
||||
if ( $this->order_helper->contains_physical_goods( $order ) && ! $order->status()->is( OrderStatus::APPROVED ) && ! $order->status()->is( OrderStatus::CREATED ) ) {
|
||||
|
@ -198,7 +198,7 @@ class ApproveOrderEndpoint implements EndpointInterface {
|
|||
$this->session_handler->replace_funding_source( $funding_source );
|
||||
|
||||
$this->session_handler->replace_order( $order );
|
||||
wp_send_json_success( $order );
|
||||
wp_send_json_success();
|
||||
return true;
|
||||
} catch ( Exception $error ) {
|
||||
$this->logger->error( 'Order approve failed: ' . $error->getMessage() );
|
||||
|
|
|
@ -0,0 +1,94 @@
|
|||
<?php
|
||||
/**
|
||||
* Endpoint to handle PayPal Subscription created.
|
||||
*
|
||||
* @package WooCommerce\PayPalCommerce\Button\Endpoint
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace WooCommerce\PayPalCommerce\Button\Endpoint;
|
||||
|
||||
use WooCommerce\PayPalCommerce\ApiClient\Endpoint\OrderEndpoint;
|
||||
use WooCommerce\PayPalCommerce\Button\Exception\RuntimeException;
|
||||
use WooCommerce\PayPalCommerce\Session\SessionHandler;
|
||||
|
||||
/**
|
||||
* Class ApproveSubscriptionEndpoint
|
||||
*/
|
||||
class ApproveSubscriptionEndpoint implements EndpointInterface {
|
||||
|
||||
const ENDPOINT = 'ppc-approve-subscription';
|
||||
|
||||
/**
|
||||
* The request data helper.
|
||||
*
|
||||
* @var RequestData
|
||||
*/
|
||||
private $request_data;
|
||||
|
||||
/**
|
||||
* The order endpoint.
|
||||
*
|
||||
* @var OrderEndpoint
|
||||
*/
|
||||
private $order_endpoint;
|
||||
|
||||
/**
|
||||
* The session handler.
|
||||
*
|
||||
* @var SessionHandler
|
||||
*/
|
||||
private $session_handler;
|
||||
|
||||
/**
|
||||
* ApproveSubscriptionEndpoint constructor.
|
||||
*
|
||||
* @param RequestData $request_data The request data helper.
|
||||
* @param OrderEndpoint $order_endpoint The order endpoint.
|
||||
* @param SessionHandler $session_handler The session handler.
|
||||
*/
|
||||
public function __construct(
|
||||
RequestData $request_data,
|
||||
OrderEndpoint $order_endpoint,
|
||||
SessionHandler $session_handler
|
||||
) {
|
||||
$this->request_data = $request_data;
|
||||
$this->order_endpoint = $order_endpoint;
|
||||
$this->session_handler = $session_handler;
|
||||
}
|
||||
|
||||
/**
|
||||
* The nonce.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function nonce(): string {
|
||||
return self::ENDPOINT;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles the request.
|
||||
*
|
||||
* @return bool
|
||||
* @throws RuntimeException When order not found or handling failed.
|
||||
*/
|
||||
public function handle_request(): bool {
|
||||
$data = $this->request_data->read_request( $this->nonce() );
|
||||
if ( ! isset( $data['order_id'] ) ) {
|
||||
throw new RuntimeException(
|
||||
__( 'No order id given', 'woocommerce-paypal-payments' )
|
||||
);
|
||||
}
|
||||
|
||||
$order = $this->order_endpoint->order( $data['order_id'] );
|
||||
$this->session_handler->replace_order( $order );
|
||||
|
||||
if ( isset( $data['subscription_id'] ) ) {
|
||||
WC()->session->set( 'ppcp_subscription_id', $data['subscription_id'] );
|
||||
}
|
||||
|
||||
wp_send_json_success();
|
||||
return true;
|
||||
}
|
||||
}
|
|
@ -138,6 +138,20 @@ class CreateOrderEndpoint implements EndpointInterface {
|
|||
*/
|
||||
protected $early_validation_enabled;
|
||||
|
||||
/**
|
||||
* The contexts that should have the Pay Now button.
|
||||
*
|
||||
* @var string[]
|
||||
*/
|
||||
private $pay_now_contexts;
|
||||
|
||||
/**
|
||||
* If true, the shipping methods are sent to PayPal allowing the customer to select it inside the popup.
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
private $handle_shipping_in_paypal;
|
||||
|
||||
/**
|
||||
* The logger.
|
||||
*
|
||||
|
@ -159,6 +173,8 @@ class CreateOrderEndpoint implements EndpointInterface {
|
|||
* @param bool $registration_needed Whether a new user must be registered during checkout.
|
||||
* @param string $card_billing_data_mode The value of card_billing_data_mode from the settings.
|
||||
* @param bool $early_validation_enabled Whether to execute WC validation of the checkout form.
|
||||
* @param string[] $pay_now_contexts The contexts that should have the Pay Now button.
|
||||
* @param bool $handle_shipping_in_paypal If true, the shipping methods are sent to PayPal allowing the customer to select it inside the popup.
|
||||
* @param LoggerInterface $logger The logger.
|
||||
*/
|
||||
public function __construct(
|
||||
|
@ -173,6 +189,8 @@ class CreateOrderEndpoint implements EndpointInterface {
|
|||
bool $registration_needed,
|
||||
string $card_billing_data_mode,
|
||||
bool $early_validation_enabled,
|
||||
array $pay_now_contexts,
|
||||
bool $handle_shipping_in_paypal,
|
||||
LoggerInterface $logger
|
||||
) {
|
||||
|
||||
|
@ -187,6 +205,8 @@ class CreateOrderEndpoint implements EndpointInterface {
|
|||
$this->registration_needed = $registration_needed;
|
||||
$this->card_billing_data_mode = $card_billing_data_mode;
|
||||
$this->early_validation_enabled = $early_validation_enabled;
|
||||
$this->pay_now_contexts = $pay_now_contexts;
|
||||
$this->handle_shipping_in_paypal = $handle_shipping_in_paypal;
|
||||
$this->logger = $logger;
|
||||
}
|
||||
|
||||
|
@ -226,7 +246,7 @@ class CreateOrderEndpoint implements EndpointInterface {
|
|||
}
|
||||
$this->purchase_unit = $this->purchase_unit_factory->from_wc_order( $wc_order );
|
||||
} else {
|
||||
$this->purchase_unit = $this->purchase_unit_factory->from_wc_cart();
|
||||
$this->purchase_unit = $this->purchase_unit_factory->from_wc_cart( null, $this->handle_shipping_in_paypal );
|
||||
|
||||
// The cart does not have any info about payment method, so we must handle free trial here.
|
||||
if ( (
|
||||
|
@ -272,7 +292,7 @@ class CreateOrderEndpoint implements EndpointInterface {
|
|||
! $this->early_order_handler->should_create_early_order()
|
||||
|| $this->registration_needed
|
||||
|| isset( $data['createaccount'] ) && '1' === $data['createaccount'] ) {
|
||||
wp_send_json_success( $order->to_array() );
|
||||
wp_send_json_success( $this->make_response( $order ) );
|
||||
}
|
||||
|
||||
$this->early_order_handler->register_for_order( $order );
|
||||
|
@ -284,7 +304,7 @@ class CreateOrderEndpoint implements EndpointInterface {
|
|||
$wc_order->save_meta_data();
|
||||
}
|
||||
|
||||
wp_send_json_success( $order->to_array() );
|
||||
wp_send_json_success( $this->make_response( $order ) );
|
||||
return true;
|
||||
|
||||
} catch ( ValidationException $error ) {
|
||||
|
@ -342,7 +362,7 @@ class CreateOrderEndpoint implements EndpointInterface {
|
|||
* during the "onApprove"-JS callback or the webhook listener.
|
||||
*/
|
||||
if ( ! $this->early_order_handler->should_create_early_order() ) {
|
||||
wp_send_json_success( $order->to_array() );
|
||||
wp_send_json_success( $this->make_response( $order ) );
|
||||
}
|
||||
$this->early_order_handler->register_for_order( $order );
|
||||
return $data;
|
||||
|
@ -385,6 +405,9 @@ class CreateOrderEndpoint implements EndpointInterface {
|
|||
$funding_source
|
||||
);
|
||||
|
||||
$action = in_array( $this->parsed_request_data['context'], $this->pay_now_contexts, true ) ?
|
||||
ApplicationContext::USER_ACTION_PAY_NOW : ApplicationContext::USER_ACTION_CONTINUE;
|
||||
|
||||
if ( 'card' === $funding_source ) {
|
||||
if ( CardBillingMode::MINIMAL_INPUT === $this->card_billing_data_mode ) {
|
||||
if ( ApplicationContext::SHIPPING_PREFERENCE_SET_PROVIDED_ADDRESS === $shipping_preference ) {
|
||||
|
@ -410,7 +433,9 @@ class CreateOrderEndpoint implements EndpointInterface {
|
|||
$shipping_preference,
|
||||
$payer,
|
||||
null,
|
||||
$this->payment_method()
|
||||
$this->payment_method(),
|
||||
'',
|
||||
$action
|
||||
);
|
||||
} catch ( PayPalApiException $exception ) {
|
||||
// Looks like currently there is no proper way to validate the shipping address for PayPal,
|
||||
|
@ -544,4 +569,17 @@ class CreateOrderEndpoint implements EndpointInterface {
|
|||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the response data for success response.
|
||||
*
|
||||
* @param Order $order The PayPal order.
|
||||
* @return array
|
||||
*/
|
||||
private function make_response( Order $order ): array {
|
||||
return array(
|
||||
'id' => $order->id(),
|
||||
'custom_id' => $order->purchase_units()[0]->custom_id(),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,24 +17,32 @@ trait ContextTrait {
|
|||
* @return string
|
||||
*/
|
||||
protected function context(): string {
|
||||
$context = 'mini-cart';
|
||||
if ( is_product() || wc_post_content_has_shortcode( 'product_page' ) ) {
|
||||
$context = 'product';
|
||||
return 'product';
|
||||
}
|
||||
|
||||
// has_block may not work if called too early, such as during the block registration.
|
||||
if ( has_block( 'woocommerce/cart' ) ) {
|
||||
return 'cart-block';
|
||||
}
|
||||
|
||||
if ( is_cart() ) {
|
||||
$context = 'cart';
|
||||
}
|
||||
|
||||
if ( is_checkout() && ! $this->is_paypal_continuation() ) {
|
||||
$context = 'checkout';
|
||||
return 'cart';
|
||||
}
|
||||
|
||||
if ( is_checkout_pay_page() ) {
|
||||
$context = 'pay-now';
|
||||
return 'pay-now';
|
||||
}
|
||||
|
||||
return $context;
|
||||
if ( has_block( 'woocommerce/checkout' ) ) {
|
||||
return 'checkout-block';
|
||||
}
|
||||
|
||||
if ( ( is_checkout() ) && ! $this->is_paypal_continuation() ) {
|
||||
return 'checkout';
|
||||
}
|
||||
|
||||
return 'mini-cart';
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue