This commit is contained in:
David Remer 2020-08-25 15:13:56 +03:00
parent 7d490c6b7c
commit 2d48166eb1
8 changed files with 77 additions and 47 deletions

View file

@ -533,7 +533,10 @@ class SmartButton implements SmartButtonInterface
'intent' => ($this->settings->has('intent')) ? 'intent' => ($this->settings->has('intent')) ?
$this->settings->get('intent') : 'capture', $this->settings->get('intent') : 'capture',
]; ];
if (defined('WP_DEBUG') && \WP_DEBUG && WC()->customer && WC()->customer->get_billing_country()) { if (
defined('WP_DEBUG') && \WP_DEBUG
&& WC()->customer && WC()->customer->get_billing_country()
) {
$params['buyer-country'] = WC()->customer->get_billing_country(); $params['buyer-country'] = WC()->customer->get_billing_country();
} }
$payee = $this->payeeRepository->payee(); $payee = $this->payeeRepository->payee();

View file

@ -51,10 +51,13 @@ class ButtonModule implements ModuleInterface
$smartButton->enqueue(); $smartButton->enqueue();
}); });
add_action( add_filter(
'woocommerce_create_order', 'woocommerce_create_order',
static function ($value) use ($container) { static function ($value) use ($container) {
$earlyOrderHelper = $container->get('button.helper.early-order-handler'); $earlyOrderHelper = $container->get('button.helper.early-order-handler');
if (! is_null($value)) {
$value = (int) $value;
}
/** /**
* @var EarlyOrderHandler $earlyOrderHelper * @var EarlyOrderHandler $earlyOrderHelper
*/ */
@ -65,8 +68,8 @@ class ButtonModule implements ModuleInterface
$this->registerAjaxEndpoints($container); $this->registerAjaxEndpoints($container);
} }
private function registerAjaxEndpoints(ContainerInterface $container) { private function registerAjaxEndpoints(ContainerInterface $container)
{
add_action( add_action(
'wc_ajax_' . DataClientIdEndpoint::ENDPOINT, 'wc_ajax_' . DataClientIdEndpoint::ENDPOINT,
static function () use ($container) { static function () use ($container) {

View file

@ -29,6 +29,8 @@ class CreateOrderEndpoint implements EndpointInterface
private $sessionHandler; private $sessionHandler;
private $settings; private $settings;
private $earlyOrderHandler; private $earlyOrderHandler;
private $order;
public function __construct( public function __construct(
RequestData $requestData, RequestData $requestData,
CartRepository $repository, CartRepository $repository,
@ -92,36 +94,28 @@ class CreateOrderEndpoint implements EndpointInterface
return true; return true;
} catch (\RuntimeException $error) { } catch (\RuntimeException $error) {
wp_send_json_error( wp_send_json_error(
__('Something went wrong. Please try again or choose another payment source.', 'woocommerce-paypal-commerce-gateway') __(
'Something went wrong. Please try again or choose another payment source.',
'woocommerce-paypal-commerce-gateway'
)
); );
return false; return false;
} }
} }
private function validateForm(string $formValues, Order $order) { private function validateForm(string $formValues, Order $order)
{
$this->order = $order;
$parsedValues = wp_parse_args($formValues); $parsedValues = wp_parse_args($formValues);
$_POST = $parsedValues; $_POST = $parsedValues;
$_REQUEST = $parsedValues; $_REQUEST = $parsedValues;
add_filter( add_filter(
'woocommerce_after_checkout_validation', 'woocommerce_after_checkout_validation',
function($data, \WP_Error $errors) use ($order) { [
if (! $errors->errors) { $this,
'afterCheckoutValidation',
/** ],
* In case we are onboarded and everything is fine with the \WC_Order
* we want this order to be created. We will intercept it and leave it
* in the "Pending payment" status though, which than later will change
* during the "onApprove"-JS callback or the webhook listener.
*/
if (! $this->earlyOrderHandler->shouldCreateEarlyOrder()) {
wp_send_json_success($order->toArray());
}
$this->earlyOrderHandler->registerForOrder($order);
return $data;
}
wp_send_json_error($errors->get_error_message());
},
10, 10,
2 2
); );
@ -129,4 +123,25 @@ class CreateOrderEndpoint implements EndpointInterface
$checkout->process_checkout(); $checkout->process_checkout();
} }
public function afterCheckoutValidation(array $data, \WP_Error $errors): array
{
$order = $this->order;
if (! $errors->errors) {
/**
* In case we are onboarded and everything is fine with the \WC_Order
* we want this order to be created. We will intercept it and leave it
* in the "Pending payment" status though, which than later will change
* during the "onApprove"-JS callback or the webhook listener.
*/
if (! $this->earlyOrderHandler->shouldCreateEarlyOrder()) {
wp_send_json_success($order->toArray());
}
$this->earlyOrderHandler->registerForOrder($order);
return $data;
}
wp_send_json_error($errors->get_error_message());
return $data;
}
} }

View file

@ -14,13 +14,12 @@ use Inpsyde\PayPalCommerce\Webhooks\Handler\PrefixTrait;
class EarlyOrderHandler class EarlyOrderHandler
{ {
use PrefixTrait; use PrefixTrait;
private $state; private $state;
private $orderProcessor; private $orderProcessor;
private $sessionHandler; private $sessionHandler;
public function __construct( public function __construct(
State $state, State $state,
OrderProcessor $orderProcessor, OrderProcessor $orderProcessor,
@ -34,15 +33,15 @@ class EarlyOrderHandler
$this->prefix = $prefix; $this->prefix = $prefix;
} }
public function shouldCreateEarlyOrder() : bool public function shouldCreateEarlyOrder(): bool
{ {
return $this->state->currentState() === State::STATE_ONBOARDED; return $this->state->currentState() === State::STATE_ONBOARDED;
} }
public function determineWcOrderId($value) : ?int { //phpcs:disable WordPress.Security.NonceVerification.Recommended
if (! is_null($value)) { public function determineWcOrderId(int $value = null): ?int
$value = (int) $value; {
}
if (! isset($_REQUEST['ppcp-resume-order'])) { if (! isset($_REQUEST['ppcp-resume-order'])) {
return $value; return $value;
} }
@ -54,31 +53,35 @@ class EarlyOrderHandler
return $value; return $value;
} }
$orderId = false;
foreach ($order->purchaseUnits() as $purchaseUnit) { foreach ($order->purchaseUnits() as $purchaseUnit) {
if ($purchaseUnit->customId() === sanitize_text_field(wp_unslash($_REQUEST['ppcp-resume-order']))) { if ($purchaseUnit->customId() === sanitize_text_field(wp_unslash($_REQUEST['ppcp-resume-order']))) {
$orderId = (int) $this->sanitizeCustomId($purchaseUnit->customId()); $orderId = (int) $this->sanitizeCustomId($purchaseUnit->customId());
if ($orderId === $resumeOrderId) {
$value = $orderId;
}
} }
} }
if ($orderId === $resumeOrderId) {
$value = $orderId;
}
return $value; return $value;
} }
//phpcs:enable WordPress.Security.NonceVerification.Recommended
public function registerForOrder(Order $order): bool { public function registerForOrder(Order $order): bool
{
$success = (bool) add_action( $success = (bool) add_action(
'woocommerce_checkout_order_processed', 'woocommerce_checkout_order_processed',
function($orderId) use ($order) { function ($orderId) use ($order) {
try { try {
$order = $this->configureSessionAndOrder((int) $orderId, $order); $order = $this->configureSessionAndOrder((int) $orderId, $order);
wp_send_json_success($order->toArray()); wp_send_json_success($order->toArray());
return true; } catch (\RuntimeException $error) {
} catch (\RuntimeException $error) {
wp_send_json_error( wp_send_json_error(
__('Something went wrong. Please try again or choose another payment source.', 'woocommerce-paypal-commerce-gateway') __(
'Something went wrong. Please try again or choose another payment source.',
'woocommerce-paypal-commerce-gateway'
)
); );
return false;
} }
} }
); );

View file

@ -125,12 +125,14 @@ class PayPalGateway extends \WC_Payment_Gateway
/** /**
* If the WC_Order is payed through the approved webhook. * If the WC_Order is payed through the approved webhook.
*/ */
//phpcs:disable WordPress.Security.NonceVerification.Recommended
if (isset($_REQUEST['ppcp-resume-order']) && $wcOrder->has_status('processing')) { if (isset($_REQUEST['ppcp-resume-order']) && $wcOrder->has_status('processing')) {
return [ return [
'result' => 'success', 'result' => 'success',
'redirect' => $this->get_return_url($wcOrder), 'redirect' => $this->get_return_url($wcOrder),
]; ];
} }
//phpcs:enable WordPress.Security.NonceVerification.Recommended
if ($this->orderProcessor->process($wcOrder, $woocommerce)) { if ($this->orderProcessor->process($wcOrder, $woocommerce)) {
return [ return [

View file

@ -107,7 +107,10 @@ class OrderProcessor
private function captureAuthorizedDownloads(Order $order): bool private function captureAuthorizedDownloads(Order $order): bool
{ {
if (! $this->settings->has('capture_for_virtual_only') || ! $this->settings->get('capture_for_virtual_only')) { if (
! $this->settings->has('capture_for_virtual_only')
|| ! $this->settings->get('capture_for_virtual_only')
) {
return false; return false;
} }

View file

@ -1,17 +1,15 @@
<?php <?php
declare(strict_types=1); declare(strict_types=1);
namespace Inpsyde\PayPalCommerce\Webhooks\Handler; namespace Inpsyde\PayPalCommerce\Webhooks\Handler;
use Inpsyde\PayPalCommerce\ApiClient\Endpoint\OrderEndpoint; use Inpsyde\PayPalCommerce\ApiClient\Endpoint\OrderEndpoint;
use Inpsyde\PayPalCommerce\ApiClient\Entity\Order;
use Inpsyde\PayPalCommerce\ApiClient\Exception\RuntimeException; use Inpsyde\PayPalCommerce\ApiClient\Exception\RuntimeException;
use Psr\Log\LoggerInterface; use Psr\Log\LoggerInterface;
class CheckoutOrderApproved implements RequestHandler class CheckoutOrderApproved implements RequestHandler
{ {
use PrefixTrait; use PrefixTrait;
private $logger; private $logger;
@ -36,6 +34,7 @@ class CheckoutOrderApproved implements RequestHandler
return in_array($request['event_type'], $this->eventTypes(), true); return in_array($request['event_type'], $this->eventTypes(), true);
} }
//phpcs:disable Inpsyde.CodeQuality.FunctionLength.TooLong
public function handleRequest(\WP_REST_Request $request): \WP_REST_Response public function handleRequest(\WP_REST_Request $request): \WP_REST_Response
{ {
$response = ['success' => false]; $response = ['success' => false];
@ -74,7 +73,8 @@ class CheckoutOrderApproved implements RequestHandler
} }
try { try {
$order = isset($request['resource']['id']) ? $this->orderEndpoint->order($request['resource']['id']) : null; $order = isset($request['resource']['id']) ?
$this->orderEndpoint->order($request['resource']['id']) : null;
if (! $order) { if (! $order) {
$message = sprintf( $message = sprintf(
// translators: %s is the PayPal webhook Id. // translators: %s is the PayPal webhook Id.
@ -152,7 +152,7 @@ class CheckoutOrderApproved implements RequestHandler
__('Payment received.', 'woocommerce-paypal-commerce-gateway') __('Payment received.', 'woocommerce-paypal-commerce-gateway')
: __('Payment can be captured.', 'woocommerce-paypal-commerce-gateway'); : __('Payment can be captured.', 'woocommerce-paypal-commerce-gateway');
foreach ($wcOrders as $wcOrder) { foreach ($wcOrders as $wcOrder) {
if (! in_array($wcOrder->get_status(),['pending', 'on-hold'])) { if (! in_array($wcOrder->get_status(), ['pending', 'on-hold'], true)) {
continue; continue;
} }
/** /**
@ -181,4 +181,5 @@ class CheckoutOrderApproved implements RequestHandler
$response['success'] = true; $response['success'] = true;
return rest_ensure_response($response); return rest_ensure_response($response);
} }
} //phpcs:enable Inpsyde.CodeQuality.FunctionLength.TooLong
}

View file

@ -97,7 +97,7 @@ class CheckoutOrderCompleted implements RequestHandler
} }
foreach ($wcOrders as $wcOrder) { foreach ($wcOrders as $wcOrder) {
if (! in_array($wcOrder->get_status(),['pending', 'on-hold'])) { if (! in_array($wcOrder->get_status(), ['pending', 'on-hold'], true)) {
continue; continue;
} }
/** /**