mirror of
https://github.com/woocommerce/woocommerce-paypal-payments.git
synced 2025-09-06 18:16:38 +08:00
Merge branch 'trunk' into PCP-2722-add-block-checkout-compatibility-to-advanced-card-processing
This commit is contained in:
commit
4b3cd53f73
21 changed files with 665 additions and 51 deletions
|
@ -60,7 +60,8 @@ class CartActionHandler {
|
|||
funding_source: window.ppcpFundingSource,
|
||||
bn_code:bnCode,
|
||||
payer,
|
||||
context:this.config.context
|
||||
context:this.config.context,
|
||||
payment_source: data.paymentSource
|
||||
}),
|
||||
}).then(function(res) {
|
||||
return res.json();
|
||||
|
|
|
@ -0,0 +1,126 @@
|
|||
import {paypalAddressToWc} from "../../../../../ppcp-blocks/resources/js/Helper/Address.js";
|
||||
import {convertKeysToSnakeCase} from "../../../../../ppcp-blocks/resources/js/Helper/Helper.js";
|
||||
|
||||
/**
|
||||
* Handles the shipping option change in PayPal.
|
||||
*
|
||||
* @param data
|
||||
* @param actions
|
||||
* @param config
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
export const handleShippingOptionsChange = async (data, actions, config) => {
|
||||
try {
|
||||
const shippingOptionId = data.selectedShippingOption?.id;
|
||||
|
||||
if (shippingOptionId) {
|
||||
await fetch(config.ajax.update_customer_shipping.shipping_options.endpoint, {
|
||||
method: 'POST',
|
||||
credentials: 'same-origin',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'X-WC-Store-API-Nonce': config.ajax.update_customer_shipping.wp_rest_nonce,
|
||||
},
|
||||
body: JSON.stringify({
|
||||
rate_id: shippingOptionId,
|
||||
})
|
||||
})
|
||||
.then(response => {
|
||||
return response.json();
|
||||
})
|
||||
.then(cardData => {
|
||||
const shippingMethods = document.querySelectorAll('.shipping_method');
|
||||
|
||||
shippingMethods.forEach(function(method) {
|
||||
if (method.value === shippingOptionId) {
|
||||
method.checked = true;
|
||||
}
|
||||
});
|
||||
})
|
||||
}
|
||||
|
||||
const res = await fetch(config.ajax.update_shipping.endpoint, {
|
||||
method: 'POST',
|
||||
credentials: 'same-origin',
|
||||
body: JSON.stringify({
|
||||
nonce: config.ajax.update_shipping.nonce,
|
||||
order_id: data.orderID,
|
||||
})
|
||||
});
|
||||
|
||||
const json = await res.json();
|
||||
|
||||
if (!json.success) {
|
||||
throw new Error(json.data.message);
|
||||
}
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
|
||||
actions.reject();
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Handles the shipping address change in PayPal.
|
||||
*
|
||||
* @param data
|
||||
* @param actions
|
||||
* @param config
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
export const handleShippingAddressChange = async (data, actions, config) => {
|
||||
try {
|
||||
const address = paypalAddressToWc(convertKeysToSnakeCase(data.shippingAddress));
|
||||
|
||||
// Retrieve current cart contents
|
||||
await fetch(config.ajax.update_customer_shipping.shipping_address.cart_endpoint)
|
||||
.then(response => {
|
||||
return response.json();
|
||||
})
|
||||
.then(cartData => {
|
||||
// Update shipping address in the cart data
|
||||
cartData.shipping_address.address_1 = address.address_1;
|
||||
cartData.shipping_address.address_2 = address.address_2;
|
||||
cartData.shipping_address.city = address.city;
|
||||
cartData.shipping_address.state = address.state;
|
||||
cartData.shipping_address.postcode = address.postcode;
|
||||
cartData.shipping_address.country = address.country;
|
||||
|
||||
// Send update request
|
||||
return fetch(config.ajax.update_customer_shipping.shipping_address.update_customer_endpoint, {
|
||||
method: 'POST',
|
||||
credentials: 'same-origin',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'X-WC-Store-API-Nonce': config.ajax.update_customer_shipping.wp_rest_nonce,
|
||||
},
|
||||
body: JSON.stringify({
|
||||
shipping_address: cartData.shipping_address,
|
||||
})
|
||||
}).then(function (res) {
|
||||
return res.json();
|
||||
}).then(function (customerData) {
|
||||
jQuery(".cart_totals .shop_table").load(location.href + " " + ".cart_totals .shop_table" + ">*", "");
|
||||
})
|
||||
})
|
||||
|
||||
const res = await fetch(config.ajax.update_shipping.endpoint, {
|
||||
method: 'POST',
|
||||
credentials: 'same-origin',
|
||||
body: JSON.stringify({
|
||||
nonce: config.ajax.update_shipping.nonce,
|
||||
order_id: data.orderID,
|
||||
})
|
||||
});
|
||||
|
||||
const json = await res.json();
|
||||
|
||||
if (!json.success) {
|
||||
throw new Error(json.data.message);
|
||||
}
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
|
||||
actions.reject();
|
||||
}
|
||||
};
|
|
@ -10,6 +10,7 @@ const onApprove = (context, errorHandler) => {
|
|||
nonce: context.config.ajax.approve_order.nonce,
|
||||
order_id:data.orderID,
|
||||
funding_source: window.ppcpFundingSource,
|
||||
should_create_wc_order: !context.config.vaultingEnabled || data.paymentSource !== 'venmo'
|
||||
})
|
||||
}).then((res)=>{
|
||||
return res.json();
|
||||
|
@ -20,7 +21,11 @@ const onApprove = (context, errorHandler) => {
|
|||
errorHandler.genericError();
|
||||
});
|
||||
}
|
||||
location.href = context.config.redirect;
|
||||
|
||||
let orderReceivedUrl = data.data?.order_received_url
|
||||
|
||||
location.href = orderReceivedUrl ? orderReceivedUrl : context.config.redirect;
|
||||
|
||||
});
|
||||
|
||||
}
|
||||
|
|
|
@ -3,6 +3,10 @@ import {loadScript} from "@paypal/paypal-js";
|
|||
import {keysToCamelCase} from "../Helper/Utils";
|
||||
import widgetBuilder from "./WidgetBuilder";
|
||||
import {normalizeStyleForFundingSource} from "../Helper/Style";
|
||||
import {
|
||||
handleShippingOptionsChange,
|
||||
handleShippingAddressChange,
|
||||
} from "../Helper/ShippingHandler.js";
|
||||
|
||||
class Renderer {
|
||||
constructor(creditCardRenderer, defaultSettings, onSmartButtonClick, onSmartButtonsInit) {
|
||||
|
@ -64,6 +68,15 @@ class Renderer {
|
|||
}
|
||||
}
|
||||
|
||||
shouldHandleShippingInPaypal = (venmoButtonClicked) => {
|
||||
if (!this.defaultSettings.should_handle_shipping_in_paypal) {
|
||||
console.log('no')
|
||||
return false;
|
||||
}
|
||||
|
||||
return !venmoButtonClicked || !this.defaultSettings.vaultingEnabled;
|
||||
}
|
||||
|
||||
renderButtons(wrapper, style, contextConfig, hasEnabledSeparateGateways, fundingSource = null) {
|
||||
if (! document.querySelector(wrapper) || this.isAlreadyRendered(wrapper, fundingSource, hasEnabledSeparateGateways) ) {
|
||||
// Try to render registered buttons again in case they were removed from the DOM by an external source.
|
||||
|
@ -75,17 +88,24 @@ class Renderer {
|
|||
contextConfig.fundingSource = fundingSource;
|
||||
}
|
||||
|
||||
let venmoButtonClicked = false;
|
||||
|
||||
const buttonsOptions = () => {
|
||||
return {
|
||||
style,
|
||||
...contextConfig,
|
||||
onClick: this.onSmartButtonClick,
|
||||
onClick: (data, actions) => {
|
||||
venmoButtonClicked = data.fundingSource === 'venmo'
|
||||
this.onSmartButtonClick
|
||||
},
|
||||
onInit: (data, actions) => {
|
||||
if (this.onSmartButtonsInit) {
|
||||
this.onSmartButtonsInit(data, actions);
|
||||
}
|
||||
this.handleOnButtonsInit(wrapper, data, actions);
|
||||
},
|
||||
onShippingOptionsChange: (data, actions) => this.shouldHandleShippingInPaypal(venmoButtonClicked) ? handleShippingOptionsChange(data, actions, this.defaultSettings) : null,
|
||||
onShippingAddressChange: (data, actions) => this.shouldHandleShippingInPaypal(venmoButtonClicked) ? handleShippingAddressChange(data, actions, this.defaultSettings) : null,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -16,6 +16,7 @@ use WooCommerce\PayPalCommerce\Button\Helper\CartProductsHelper;
|
|||
use WooCommerce\PayPalCommerce\Button\Helper\CheckoutFormSaver;
|
||||
use WooCommerce\PayPalCommerce\Button\Endpoint\SaveCheckoutFormEndpoint;
|
||||
use WooCommerce\PayPalCommerce\Button\Helper\ContextTrait;
|
||||
use WooCommerce\PayPalCommerce\Button\Helper\WooCommerceOrderCreator;
|
||||
use WooCommerce\PayPalCommerce\Button\Validation\CheckoutFormValidator;
|
||||
use WooCommerce\PayPalCommerce\Button\Endpoint\ValidateCheckoutEndpoint;
|
||||
use WooCommerce\PayPalCommerce\Session\SessionHandler;
|
||||
|
@ -147,7 +148,8 @@ return array(
|
|||
$container->get( 'wcgateway.funding-sources-without-redirect' ),
|
||||
$container->get( 'vaulting.vault-v3-enabled' ),
|
||||
$container->get( 'api.endpoint.payment-tokens' ),
|
||||
$container->get( 'woocommerce.logger.woocommerce' )
|
||||
$container->get( 'woocommerce.logger.woocommerce' ),
|
||||
$container->get( 'button.handle-shipping-in-paypal' )
|
||||
);
|
||||
},
|
||||
'button.url' => static function ( ContainerInterface $container ): string {
|
||||
|
@ -157,7 +159,13 @@ return array(
|
|||
);
|
||||
},
|
||||
'button.pay-now-contexts' => static function ( ContainerInterface $container ): array {
|
||||
return array( 'checkout', 'pay-now' );
|
||||
$defaults = array( 'checkout', 'pay-now' );
|
||||
|
||||
if ( $container->get( 'button.handle-shipping-in-paypal' ) ) {
|
||||
return array_merge( $defaults, array( 'cart', 'product', 'mini-cart' ) );
|
||||
}
|
||||
|
||||
return $defaults;
|
||||
},
|
||||
'button.request-data' => static function ( ContainerInterface $container ): RequestData {
|
||||
return new RequestData();
|
||||
|
@ -221,14 +229,18 @@ return array(
|
|||
return new EarlyOrderHandler( $state, $order_processor, $session_handler );
|
||||
},
|
||||
'button.endpoint.approve-order' => static function ( ContainerInterface $container ): ApproveOrderEndpoint {
|
||||
$request_data = $container->get( 'button.request-data' );
|
||||
$order_endpoint = $container->get( 'api.endpoint.order' );
|
||||
$session_handler = $container->get( 'session.handler' );
|
||||
$three_d_secure = $container->get( 'button.helper.three-d-secure' );
|
||||
$settings = $container->get( 'wcgateway.settings' );
|
||||
$dcc_applies = $container->get( 'api.helpers.dccapplies' );
|
||||
$order_helper = $container->get( 'api.order-helper' );
|
||||
$logger = $container->get( 'woocommerce.logger.woocommerce' );
|
||||
$request_data = $container->get( 'button.request-data' );
|
||||
$order_endpoint = $container->get( 'api.endpoint.order' );
|
||||
$session_handler = $container->get( 'session.handler' );
|
||||
$three_d_secure = $container->get( 'button.helper.three-d-secure' );
|
||||
$settings = $container->get( 'wcgateway.settings' );
|
||||
$dcc_applies = $container->get( 'api.helpers.dccapplies' );
|
||||
$order_helper = $container->get( 'api.order-helper' );
|
||||
$final_review_enabled = $container->get( 'blocks.settings.final_review_enabled' );
|
||||
$wc_order_creator = $container->get( 'button.helper.wc-order-creator' );
|
||||
$gateway = $container->get( 'wcgateway.paypal-gateway' );
|
||||
$subscription_helper = $container->get( 'wc-subscriptions.helper' );
|
||||
$logger = $container->get( 'woocommerce.logger.woocommerce' );
|
||||
return new ApproveOrderEndpoint(
|
||||
$request_data,
|
||||
$order_endpoint,
|
||||
|
@ -237,6 +249,10 @@ return array(
|
|||
$settings,
|
||||
$dcc_applies,
|
||||
$order_helper,
|
||||
$final_review_enabled,
|
||||
$gateway,
|
||||
$wc_order_creator,
|
||||
$subscription_helper,
|
||||
$logger
|
||||
);
|
||||
},
|
||||
|
@ -342,6 +358,10 @@ return array(
|
|||
* May result in slower popup performance, additional loading.
|
||||
*/
|
||||
'button.handle-shipping-in-paypal' => static function ( ContainerInterface $container ): bool {
|
||||
return false;
|
||||
return ! $container->get( 'blocks.settings.final_review_enabled' );
|
||||
},
|
||||
|
||||
'button.helper.wc-order-creator' => static function ( ContainerInterface $container ): WooCommerceOrderCreator {
|
||||
return new WooCommerceOrderCreator( $container->get( 'wcgateway.funding-source.renderer' ), $container->get( 'session.handler' ) );
|
||||
},
|
||||
);
|
||||
|
|
|
@ -19,6 +19,7 @@ use WooCommerce\PayPalCommerce\ApiClient\Entity\Money;
|
|||
use WooCommerce\PayPalCommerce\ApiClient\Entity\PaymentToken;
|
||||
use WooCommerce\PayPalCommerce\ApiClient\Factory\PayerFactory;
|
||||
use WooCommerce\PayPalCommerce\ApiClient\Helper\DccApplies;
|
||||
use WooCommerce\PayPalCommerce\Blocks\Endpoint\UpdateShippingEndpoint;
|
||||
use WooCommerce\PayPalCommerce\Button\Endpoint\ApproveOrderEndpoint;
|
||||
use WooCommerce\PayPalCommerce\Button\Endpoint\ApproveSubscriptionEndpoint;
|
||||
use WooCommerce\PayPalCommerce\Button\Endpoint\CartScriptParamsEndpoint;
|
||||
|
@ -217,6 +218,13 @@ class SmartButton implements SmartButtonInterface {
|
|||
*/
|
||||
private $logger;
|
||||
|
||||
/**
|
||||
* Whether the shipping should be handled in PayPal.
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
private $should_handle_shipping_in_paypal;
|
||||
|
||||
/**
|
||||
* SmartButton constructor.
|
||||
*
|
||||
|
@ -242,6 +250,7 @@ class SmartButton implements SmartButtonInterface {
|
|||
* @param bool $vault_v3_enabled Whether Vault v3 module is enabled.
|
||||
* @param PaymentTokensEndpoint $payment_tokens_endpoint Payment tokens endpoint.
|
||||
* @param LoggerInterface $logger The logger.
|
||||
* @param bool $should_handle_shipping_in_paypal Whether the shipping should be handled in PayPal.
|
||||
*/
|
||||
public function __construct(
|
||||
string $module_url,
|
||||
|
@ -265,7 +274,8 @@ class SmartButton implements SmartButtonInterface {
|
|||
array $funding_sources_without_redirect,
|
||||
bool $vault_v3_enabled,
|
||||
PaymentTokensEndpoint $payment_tokens_endpoint,
|
||||
LoggerInterface $logger
|
||||
LoggerInterface $logger,
|
||||
bool $should_handle_shipping_in_paypal
|
||||
) {
|
||||
|
||||
$this->module_url = $module_url;
|
||||
|
@ -290,6 +300,7 @@ class SmartButton implements SmartButtonInterface {
|
|||
$this->vault_v3_enabled = $vault_v3_enabled;
|
||||
$this->logger = $logger;
|
||||
$this->payment_tokens_endpoint = $payment_tokens_endpoint;
|
||||
$this->should_handle_shipping_in_paypal = $should_handle_shipping_in_paypal;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1133,6 +1144,21 @@ document.querySelector("#payment").before(document.querySelector(".ppcp-messages
|
|||
'endpoint' => \WC_AJAX::get_endpoint( CreatePaymentTokenForGuest::ENDPOINT ),
|
||||
'nonce' => wp_create_nonce( CreatePaymentTokenForGuest::nonce() ),
|
||||
),
|
||||
'update_shipping' => array(
|
||||
'endpoint' => \WC_AJAX::get_endpoint( UpdateShippingEndpoint::ENDPOINT ),
|
||||
'nonce' => wp_create_nonce( UpdateShippingEndpoint::nonce() ),
|
||||
),
|
||||
'update_customer_shipping' => array(
|
||||
'shipping_options' => array(
|
||||
'endpoint' => '/wp-json/wc/store/cart/select-shipping-rate',
|
||||
),
|
||||
'shipping_address' => array(
|
||||
'cart_endpoint' => '/wp-json/wc/store/cart/',
|
||||
'update_customer_endpoint' => '/wp-json/wc/store/v1/cart/update-customer/',
|
||||
),
|
||||
'wp_rest_nonce' => wp_create_nonce( 'wc_store_api' ),
|
||||
'update_shipping_method' => \WC_AJAX::get_endpoint( 'update_shipping_method' ),
|
||||
),
|
||||
),
|
||||
'cart_contains_subscription' => $this->subscription_helper->cart_contains_subscription(),
|
||||
'subscription_plan_id' => $this->subscription_helper->paypal_subscription_id(),
|
||||
|
@ -1253,6 +1279,8 @@ document.querySelector("#payment").before(document.querySelector(".ppcp-messages
|
|||
'user' => array(
|
||||
'is_logged' => is_user_logged_in(),
|
||||
),
|
||||
'should_handle_shipping_in_paypal' => $this->should_handle_shipping_in_paypal && ! $this->is_checkout(),
|
||||
'vaultingEnabled' => $this->settings->has( 'vault_enabled' ) && $this->settings->get( 'vault_enabled' ),
|
||||
);
|
||||
|
||||
if ( 'pay-now' === $this->context() ) {
|
||||
|
@ -1333,7 +1361,7 @@ document.querySelector("#payment").before(document.querySelector(".ppcp-messages
|
|||
'integration-date' => PAYPAL_INTEGRATION_DATE,
|
||||
'components' => implode( ',', $this->components() ),
|
||||
'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',
|
||||
'commit' => 'false',
|
||||
'intent' => $intent,
|
||||
);
|
||||
|
||||
|
|
|
@ -14,20 +14,25 @@ use Exception;
|
|||
use Psr\Log\LoggerInterface;
|
||||
use WooCommerce\PayPalCommerce\ApiClient\Endpoint\OrderEndpoint;
|
||||
use WooCommerce\PayPalCommerce\ApiClient\Entity\OrderStatus;
|
||||
use WooCommerce\PayPalCommerce\ApiClient\Entity\PaymentSource;
|
||||
use WooCommerce\PayPalCommerce\ApiClient\Exception\PayPalApiException;
|
||||
use WooCommerce\PayPalCommerce\ApiClient\Helper\DccApplies;
|
||||
use WooCommerce\PayPalCommerce\ApiClient\Helper\OrderHelper;
|
||||
use WooCommerce\PayPalCommerce\Button\Exception\RuntimeException;
|
||||
use WooCommerce\PayPalCommerce\Button\Helper\ContextTrait;
|
||||
use WooCommerce\PayPalCommerce\Button\Helper\ThreeDSecure;
|
||||
use WooCommerce\PayPalCommerce\Button\Helper\WooCommerceOrderCreator;
|
||||
use WooCommerce\PayPalCommerce\Session\SessionHandler;
|
||||
use WooCommerce\PayPalCommerce\WcGateway\Gateway\PayPalGateway;
|
||||
use WooCommerce\PayPalCommerce\WcGateway\Settings\Settings;
|
||||
use WooCommerce\PayPalCommerce\WcSubscriptions\Helper\SubscriptionHelper;
|
||||
|
||||
/**
|
||||
* Class ApproveOrderEndpoint
|
||||
*/
|
||||
class ApproveOrderEndpoint implements EndpointInterface {
|
||||
|
||||
use ContextTrait;
|
||||
|
||||
const ENDPOINT = 'ppc-approve-order';
|
||||
|
||||
/**
|
||||
|
@ -79,6 +84,34 @@ class ApproveOrderEndpoint implements EndpointInterface {
|
|||
*/
|
||||
protected $order_helper;
|
||||
|
||||
/**
|
||||
* Whether the final review is enabled.
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
protected $final_review_enabled;
|
||||
|
||||
/**
|
||||
* The WC gateway.
|
||||
*
|
||||
* @var PayPalGateway
|
||||
*/
|
||||
protected $gateway;
|
||||
|
||||
/**
|
||||
* The WooCommerce order creator.
|
||||
*
|
||||
* @var WooCommerceOrderCreator
|
||||
*/
|
||||
protected $wc_order_creator;
|
||||
|
||||
/**
|
||||
* The Subscription Helper.
|
||||
*
|
||||
* @var SubscriptionHelper
|
||||
*/
|
||||
protected $subscription_helper;
|
||||
|
||||
/**
|
||||
* The logger.
|
||||
*
|
||||
|
@ -89,14 +122,18 @@ class ApproveOrderEndpoint implements EndpointInterface {
|
|||
/**
|
||||
* ApproveOrderEndpoint constructor.
|
||||
*
|
||||
* @param RequestData $request_data The request data helper.
|
||||
* @param OrderEndpoint $order_endpoint The order endpoint.
|
||||
* @param SessionHandler $session_handler The session handler.
|
||||
* @param ThreeDSecure $three_d_secure The 3d secure helper object.
|
||||
* @param Settings $settings The settings.
|
||||
* @param DccApplies $dcc_applies The DCC applies object.
|
||||
* @param OrderHelper $order_helper The order helper.
|
||||
* @param LoggerInterface $logger The logger.
|
||||
* @param RequestData $request_data The request data helper.
|
||||
* @param OrderEndpoint $order_endpoint The order endpoint.
|
||||
* @param SessionHandler $session_handler The session handler.
|
||||
* @param ThreeDSecure $three_d_secure The 3d secure helper object.
|
||||
* @param Settings $settings The settings.
|
||||
* @param DccApplies $dcc_applies The DCC applies object.
|
||||
* @param OrderHelper $order_helper The order helper.
|
||||
* @param bool $final_review_enabled Whether the final review is enabled.
|
||||
* @param PayPalGateway $gateway The WC gateway.
|
||||
* @param WooCommerceOrderCreator $wc_order_creator The WooCommerce order creator.
|
||||
* @param SubscriptionHelper $subscription_helper The subscription helper.
|
||||
* @param LoggerInterface $logger The logger.
|
||||
*/
|
||||
public function __construct(
|
||||
RequestData $request_data,
|
||||
|
@ -106,17 +143,25 @@ class ApproveOrderEndpoint implements EndpointInterface {
|
|||
Settings $settings,
|
||||
DccApplies $dcc_applies,
|
||||
OrderHelper $order_helper,
|
||||
bool $final_review_enabled,
|
||||
PayPalGateway $gateway,
|
||||
WooCommerceOrderCreator $wc_order_creator,
|
||||
SubscriptionHelper $subscription_helper,
|
||||
LoggerInterface $logger
|
||||
) {
|
||||
|
||||
$this->request_data = $request_data;
|
||||
$this->api_endpoint = $order_endpoint;
|
||||
$this->session_handler = $session_handler;
|
||||
$this->threed_secure = $three_d_secure;
|
||||
$this->settings = $settings;
|
||||
$this->dcc_applies = $dcc_applies;
|
||||
$this->order_helper = $order_helper;
|
||||
$this->logger = $logger;
|
||||
$this->request_data = $request_data;
|
||||
$this->api_endpoint = $order_endpoint;
|
||||
$this->session_handler = $session_handler;
|
||||
$this->threed_secure = $three_d_secure;
|
||||
$this->settings = $settings;
|
||||
$this->dcc_applies = $dcc_applies;
|
||||
$this->order_helper = $order_helper;
|
||||
$this->final_review_enabled = $final_review_enabled;
|
||||
$this->gateway = $gateway;
|
||||
$this->wc_order_creator = $wc_order_creator;
|
||||
$this->subscription_helper = $subscription_helper;
|
||||
$this->logger = $logger;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -182,6 +227,7 @@ class ApproveOrderEndpoint implements EndpointInterface {
|
|||
);
|
||||
}
|
||||
$this->session_handler->replace_order( $order );
|
||||
|
||||
wp_send_json_success();
|
||||
}
|
||||
|
||||
|
@ -200,6 +246,19 @@ class ApproveOrderEndpoint implements EndpointInterface {
|
|||
$this->session_handler->replace_funding_source( $funding_source );
|
||||
|
||||
$this->session_handler->replace_order( $order );
|
||||
|
||||
if ( ! $this->subscription_helper->plugin_is_active() && apply_filters( 'woocommerce_paypal_payments_toggle_final_review_checkbox', false ) ) {
|
||||
$this->toggle_final_review_enabled_setting();
|
||||
}
|
||||
|
||||
$should_create_wc_order = $data['should_create_wc_order'] ?? false;
|
||||
if ( ! $this->final_review_enabled && ! $this->is_checkout() && $should_create_wc_order ) {
|
||||
$wc_order = $this->wc_order_creator->create_from_paypal_order( $order, WC()->cart );
|
||||
$this->gateway->process_payment( $wc_order->get_id() );
|
||||
$order_received_url = $wc_order->get_checkout_order_received_url();
|
||||
|
||||
wp_send_json_success( array( 'order_received_url' => $order_received_url ) );
|
||||
}
|
||||
wp_send_json_success();
|
||||
return true;
|
||||
} catch ( Exception $error ) {
|
||||
|
@ -216,4 +275,15 @@ class ApproveOrderEndpoint implements EndpointInterface {
|
|||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Will toggle the "final confirmation" checkbox.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function toggle_final_review_enabled_setting(): void {
|
||||
$final_review_enabled_setting = $this->settings->has( 'blocks_final_review_enabled' ) && $this->settings->get( 'blocks_final_review_enabled' );
|
||||
$final_review_enabled_setting ? $this->settings->set( 'blocks_final_review_enabled', false ) : $this->settings->set( 'blocks_final_review_enabled', true );
|
||||
$this->settings->persist();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -246,6 +246,7 @@ class CreateOrderEndpoint implements EndpointInterface {
|
|||
$this->parsed_request_data = $data;
|
||||
$payment_method = $data['payment_method'] ?? '';
|
||||
$funding_source = $data['funding_source'] ?? '';
|
||||
$payment_source = $data['payment_source'] ?? '';
|
||||
$wc_order = null;
|
||||
if ( 'pay-now' === $data['context'] ) {
|
||||
$wc_order = wc_get_order( (int) $data['order_id'] );
|
||||
|
@ -261,7 +262,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( null, $this->handle_shipping_in_paypal );
|
||||
$this->purchase_unit = $this->purchase_unit_factory->from_wc_cart( null, $this->should_handle_shipping_in_paypal( $payment_source ) );
|
||||
|
||||
// Do not allow completion by webhooks when started via non-checkout buttons,
|
||||
// it is needed only for some APMs in checkout.
|
||||
|
@ -610,4 +611,20 @@ class CreateOrderEndpoint implements EndpointInterface {
|
|||
'custom_id' => $order->purchase_units()[0]->custom_id(),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the shipping should be handled in PayPal popup.
|
||||
*
|
||||
* @param string $payment_source The payment source.
|
||||
* @return bool true if the shipping should be handled in PayPal popup, otherwise false.
|
||||
*/
|
||||
protected function should_handle_shipping_in_paypal( string $payment_source ): bool {
|
||||
$is_vaulting_enabled = $this->settings->has( 'vault_enabled' ) && $this->settings->get( 'vault_enabled' );
|
||||
|
||||
if ( ! $this->handle_shipping_in_paypal ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return ! $is_vaulting_enabled || $payment_source !== 'venmo';
|
||||
}
|
||||
}
|
||||
|
|
228
modules/ppcp-button/src/Helper/WooCommerceOrderCreator.php
Normal file
228
modules/ppcp-button/src/Helper/WooCommerceOrderCreator.php
Normal file
|
@ -0,0 +1,228 @@
|
|||
<?php
|
||||
/**
|
||||
* Can create WC orders.
|
||||
*
|
||||
* @package WooCommerce\PayPalCommerce\Button\Helper
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace WooCommerce\PayPalCommerce\Button\Helper;
|
||||
|
||||
use RuntimeException;
|
||||
use WC_Cart;
|
||||
use WC_Order;
|
||||
use WC_Order_Item_Product;
|
||||
use WC_Order_Item_Shipping;
|
||||
use WooCommerce\PayPalCommerce\ApiClient\Entity\Order;
|
||||
use WooCommerce\PayPalCommerce\ApiClient\Entity\Payer;
|
||||
use WooCommerce\PayPalCommerce\ApiClient\Entity\Shipping;
|
||||
use WooCommerce\PayPalCommerce\Session\SessionHandler;
|
||||
use WooCommerce\PayPalCommerce\WcGateway\FundingSource\FundingSourceRenderer;
|
||||
use WooCommerce\PayPalCommerce\WcGateway\Gateway\PayPalGateway;
|
||||
|
||||
/**
|
||||
* Class WooCommerceOrderCreator
|
||||
*/
|
||||
class WooCommerceOrderCreator {
|
||||
|
||||
/**
|
||||
* The funding source renderer.
|
||||
*
|
||||
* @var FundingSourceRenderer
|
||||
*/
|
||||
protected $funding_source_renderer;
|
||||
|
||||
/**
|
||||
* The Session handler.
|
||||
*
|
||||
* @var SessionHandler
|
||||
*/
|
||||
protected $session_handler;
|
||||
|
||||
/**
|
||||
* WooCommerceOrderCreator constructor.
|
||||
*
|
||||
* @param FundingSourceRenderer $funding_source_renderer The funding source renderer.
|
||||
* @param SessionHandler $session_handler The session handler.
|
||||
*/
|
||||
public function __construct(
|
||||
FundingSourceRenderer $funding_source_renderer,
|
||||
SessionHandler $session_handler
|
||||
) {
|
||||
$this->funding_source_renderer = $funding_source_renderer;
|
||||
$this->session_handler = $session_handler;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates WC order based on given PayPal order.
|
||||
*
|
||||
* @param Order $order The PayPal order.
|
||||
* @param WC_Cart $wc_cart The Cart.
|
||||
* @return WC_Order The WC order.
|
||||
* @throws RuntimeException If problem creating.
|
||||
*/
|
||||
public function create_from_paypal_order( Order $order, WC_Cart $wc_cart ): WC_Order {
|
||||
$wc_order = wc_create_order();
|
||||
|
||||
if ( ! $wc_order instanceof WC_Order ) {
|
||||
throw new RuntimeException( 'Problem creating WC order.' );
|
||||
}
|
||||
|
||||
$this->configure_line_items( $wc_order, $wc_cart );
|
||||
$this->configure_shipping( $wc_order, $order->payer(), $order->purchase_units()[0]->shipping() );
|
||||
$this->configure_payment_source( $wc_order );
|
||||
$this->configure_customer( $wc_order );
|
||||
$this->configure_coupons( $wc_order, $wc_cart->get_applied_coupons() );
|
||||
|
||||
$wc_order->calculate_totals();
|
||||
$wc_order->save();
|
||||
|
||||
return $wc_order;
|
||||
}
|
||||
|
||||
/**
|
||||
* Configures the line items.
|
||||
*
|
||||
* @param WC_Order $wc_order The WC order.
|
||||
* @param WC_Cart $wc_cart The Cart.
|
||||
* @return void
|
||||
*/
|
||||
protected function configure_line_items( WC_Order $wc_order, WC_Cart $wc_cart ): void {
|
||||
$cart_contents = $wc_cart->get_cart();
|
||||
|
||||
foreach ( $cart_contents as $cart_item ) {
|
||||
$product_id = $cart_item['product_id'] ?? 0;
|
||||
$variation_id = $cart_item['variation_id'] ?? 0;
|
||||
$quantity = $cart_item['quantity'] ?? 0;
|
||||
$variation_attributes = $cart_item['variation'];
|
||||
|
||||
$item = new WC_Order_Item_Product();
|
||||
$item->set_product_id( $product_id );
|
||||
$item->set_quantity( $quantity );
|
||||
|
||||
if ( $variation_id ) {
|
||||
$item->set_variation_id( $variation_id );
|
||||
$item->set_variation( $variation_attributes );
|
||||
}
|
||||
|
||||
$product = wc_get_product( $variation_id ?: $product_id );
|
||||
if ( ! $product ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$item->set_name( $product->get_name() );
|
||||
$item->set_subtotal( $product->get_price() * $quantity );
|
||||
$item->set_total( $product->get_price() * $quantity );
|
||||
|
||||
$wc_order->add_item( $item );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Configures the shipping & billing addresses for WC order from given payer.
|
||||
*
|
||||
* @param WC_Order $wc_order The WC order.
|
||||
* @param Payer|null $payer The payer.
|
||||
* @param Shipping|null $shipping The shipping.
|
||||
* @return void
|
||||
*/
|
||||
protected function configure_shipping( WC_Order $wc_order, ?Payer $payer, ?Shipping $shipping ): void {
|
||||
$shipping_address = null;
|
||||
$billing_address = null;
|
||||
$shipping_options = null;
|
||||
|
||||
if ( $payer ) {
|
||||
$address = $payer->address();
|
||||
$payer_name = $payer->name();
|
||||
|
||||
$billing_address = array(
|
||||
'first_name' => $payer_name ? $payer_name->given_name() : '',
|
||||
'last_name' => $payer_name ? $payer_name->surname() : '',
|
||||
'address_1' => $address ? $address->address_line_1() : '',
|
||||
'address_2' => $address ? $address->address_line_2() : '',
|
||||
'city' => $address ? $address->admin_area_2() : '',
|
||||
'state' => $address ? $address->admin_area_1() : '',
|
||||
'postcode' => $address ? $address->postal_code() : '',
|
||||
'country' => $address ? $address->country_code() : '',
|
||||
);
|
||||
}
|
||||
|
||||
if ( $shipping ) {
|
||||
$address = $shipping->address();
|
||||
|
||||
$shipping_address = array(
|
||||
'first_name' => $shipping->name(),
|
||||
'last_name' => '',
|
||||
'address_1' => $address->address_line_1(),
|
||||
'address_2' => $address->address_line_2(),
|
||||
'city' => $address->admin_area_2(),
|
||||
'state' => $address->admin_area_1(),
|
||||
'postcode' => $address->postal_code(),
|
||||
'country' => $address->country_code(),
|
||||
);
|
||||
|
||||
$shipping_options = $shipping->options()[0] ?? '';
|
||||
}
|
||||
|
||||
if ( $shipping_address ) {
|
||||
$wc_order->set_shipping_address( $shipping_address );
|
||||
}
|
||||
|
||||
if ( $billing_address || $shipping_address ) {
|
||||
$wc_order->set_billing_address( $billing_address ?: $shipping_address );
|
||||
}
|
||||
|
||||
if ( $shipping_options ) {
|
||||
$shipping = new WC_Order_Item_Shipping();
|
||||
$shipping->set_method_title( $shipping_options->label() );
|
||||
$shipping->set_method_id( $shipping_options->id() );
|
||||
$shipping->set_total( $shipping_options->amount()->value_str() );
|
||||
|
||||
$wc_order->add_item( $shipping );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Configures the payment source.
|
||||
*
|
||||
* @param WC_Order $wc_order The WC order.
|
||||
* @return void
|
||||
*/
|
||||
protected function configure_payment_source( WC_Order $wc_order ): void {
|
||||
$funding_source = $this->session_handler->funding_source();
|
||||
$wc_order->set_payment_method( PayPalGateway::ID );
|
||||
|
||||
if ( $funding_source ) {
|
||||
$wc_order->set_payment_method_title( $this->funding_source_renderer->render_name( $funding_source ) );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Configures the customer ID.
|
||||
*
|
||||
* @param WC_Order $wc_order The WC order.
|
||||
* @return void
|
||||
*/
|
||||
protected function configure_customer( WC_Order $wc_order ): void {
|
||||
$current_user = wp_get_current_user();
|
||||
|
||||
if ( $current_user->ID !== 0 ) {
|
||||
$wc_order->set_customer_id( $current_user->ID );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Configures the applied coupons.
|
||||
*
|
||||
* @param WC_Order $wc_order The WC order.
|
||||
* @param string[] $coupons The list of applied coupons.
|
||||
* @return void
|
||||
*/
|
||||
protected function configure_coupons( WC_Order $wc_order, array $coupons ): void {
|
||||
foreach ( $coupons as $coupon_code ) {
|
||||
$wc_order->apply_coupon( $coupon_code );
|
||||
}
|
||||
}
|
||||
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue