mirror of
https://github.com/woocommerce/woocommerce-paypal-payments.git
synced 2025-09-06 10:55:00 +08:00
Merge branch 'master' into feature-paypal-button-on-checkout
# Conflicts: # modules.local/ppcp-button/assets/js/button.js # modules.local/ppcp-button/assets/js/button.js.map
This commit is contained in:
commit
74b32a1369
16 changed files with 222 additions and 22 deletions
|
@ -37,13 +37,11 @@ return [
|
|||
);
|
||||
},
|
||||
'api.endpoint.order' => function (ContainerInterface $container) : OrderEndpoint {
|
||||
$sessionHandler = $container->get('session.handler');
|
||||
$orderFactory = $container->get('api.factory.order');
|
||||
$patchCollectionFactory = $container->get('api.factory.patch-collection-factory');
|
||||
return new OrderEndpoint(
|
||||
$container->get('api.host'),
|
||||
$container->get('api.bearer'),
|
||||
$sessionHandler,
|
||||
$orderFactory,
|
||||
$patchCollectionFactory
|
||||
);
|
||||
|
|
|
@ -16,20 +16,17 @@ class OrderEndpoint
|
|||
|
||||
private $host;
|
||||
private $bearer;
|
||||
private $sessionHandler;
|
||||
private $orderFactory;
|
||||
private $patchCollectionFactory;
|
||||
public function __construct(
|
||||
string $host,
|
||||
Bearer $bearer,
|
||||
SessionHandler $sessionHandler,
|
||||
OrderFactory $orderFactory,
|
||||
PatchCollectionFactory $patchCollectionFactory
|
||||
) {
|
||||
|
||||
$this->host = $host;
|
||||
$this->bearer = $bearer;
|
||||
$this->sessionHandler = $sessionHandler;
|
||||
$this->orderFactory = $orderFactory;
|
||||
$this->patchCollectionFactory = $patchCollectionFactory;
|
||||
}
|
||||
|
@ -37,7 +34,6 @@ class OrderEndpoint
|
|||
public function createForPurchaseUnits(PurchaseUnit ...$items) : Order
|
||||
{
|
||||
$bearer = $this->bearer->bearer();
|
||||
|
||||
$data = [
|
||||
'intent' => 'CAPTURE',
|
||||
'purchase_units' => array_map(
|
||||
|
@ -62,7 +58,6 @@ class OrderEndpoint
|
|||
}
|
||||
$json = json_decode($response['body']);
|
||||
$order = $this->orderFactory->fromPayPalResponse($json);
|
||||
$this->sessionHandler->replaceOrder($order);
|
||||
return $order;
|
||||
}
|
||||
|
||||
|
@ -90,7 +85,6 @@ class OrderEndpoint
|
|||
}
|
||||
$json = json_decode($response['body']);
|
||||
$order = $this->orderFactory->fromPayPalResponse($json);
|
||||
$this->sessionHandler->replaceOrder($order);
|
||||
return $order;
|
||||
}
|
||||
|
||||
|
@ -136,7 +130,6 @@ class OrderEndpoint
|
|||
}
|
||||
|
||||
$newOrder = $this->order($orderToUpdate->id());
|
||||
$this->sessionHandler->replaceOrder($newOrder);
|
||||
return $newOrder;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
|
||||
import onApprove from "./onApprove";
|
||||
|
||||
class CartConfig {
|
||||
|
||||
|
@ -26,12 +26,9 @@ class CartConfig {
|
|||
return data.data.id;
|
||||
});
|
||||
}
|
||||
const onApprove = (data, actions) => {
|
||||
return actions.redirect(this.config.redirect);
|
||||
}
|
||||
return {
|
||||
createOrder,
|
||||
onApprove,
|
||||
onApprove:onApprove(this),
|
||||
onError: (error) => {
|
||||
this.errorHandler.message(error);
|
||||
}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import ButtonsToggleListener from "./ButtonsToggleListener";
|
||||
import Product from "./Product";
|
||||
import onApprove from "./onApprove";
|
||||
class SingleProductConfig {
|
||||
|
||||
constructor(
|
||||
|
@ -29,12 +30,10 @@ class SingleProductConfig {
|
|||
);
|
||||
observer.init();
|
||||
}
|
||||
const onApprove = (data, actions) => {
|
||||
return actions.redirect(this.config.redirect);
|
||||
}
|
||||
|
||||
return {
|
||||
createOrder: this.createOrder(),
|
||||
onApprove,
|
||||
onApprove: onApprove(this),
|
||||
onError: (error) => {
|
||||
this.errorHandler.message(error);
|
||||
}
|
||||
|
@ -123,5 +122,4 @@ class SingleProductConfig {
|
|||
return this.formElement.classList.contains('grouped_form');
|
||||
}
|
||||
}
|
||||
|
||||
export default SingleProductConfig;
|
22
modules.local/ppcp-button/resources/js/modules/onApprove.js
Normal file
22
modules.local/ppcp-button/resources/js/modules/onApprove.js
Normal file
|
@ -0,0 +1,22 @@
|
|||
const onApprove = (context) => {
|
||||
return (data, actions) => {
|
||||
return fetch(context.config.ajax.approve_order.endpoint, {
|
||||
method: 'POST',
|
||||
body: JSON.stringify({
|
||||
nonce: context.config.ajax.approve_order.nonce,
|
||||
order_id:data.orderID
|
||||
})
|
||||
}).then((res)=>{
|
||||
return res.json();
|
||||
}).then((data)=>{
|
||||
if (!data.success) {
|
||||
//Todo: Error handling
|
||||
return;
|
||||
}
|
||||
location.href = context.config.redirect;
|
||||
});
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
export default onApprove;
|
|
@ -5,6 +5,7 @@ namespace Inpsyde\PayPalCommerce\Button;
|
|||
|
||||
use Inpsyde\PayPalCommerce\Button\Assets\SmartButton;
|
||||
use Dhii\Data\Container\ContainerInterface;
|
||||
use Inpsyde\PayPalCommerce\Button\Endpoint\ApproveOrderEndpoint;
|
||||
use Inpsyde\PayPalCommerce\Button\Endpoint\ChangeCartEndpoint;
|
||||
use Inpsyde\PayPalCommerce\Button\Endpoint\CreateOrderEndpoint;
|
||||
use Inpsyde\PayPalCommerce\Button\Endpoint\RequestData;
|
||||
|
@ -40,4 +41,10 @@ return [
|
|||
$apiClient = $container->get('api.endpoint.order');
|
||||
return new CreateOrderEndpoint($requestData, $repository, $apiClient);
|
||||
},
|
||||
'button.endpoint.approve-order' => function (ContainerInterface $container) : ApproveOrderEndpoint {
|
||||
$requestData = $container->get('button.request-data');
|
||||
$apiClient = $container->get('api.endpoint.order');
|
||||
$sessionHandler = $container->get('session.handler');
|
||||
return new ApproveOrderEndpoint($requestData, $apiClient, $sessionHandler);
|
||||
},
|
||||
];
|
||||
|
|
|
@ -3,6 +3,7 @@ declare(strict_types=1);
|
|||
|
||||
namespace Inpsyde\PayPalCommerce\Button\Assets;
|
||||
|
||||
use Inpsyde\PayPalCommerce\Button\Endpoint\ApproveOrderEndpoint;
|
||||
use Inpsyde\PayPalCommerce\Button\Endpoint\ChangeCartEndpoint;
|
||||
use Inpsyde\PayPalCommerce\Button\Endpoint\CreateOrderEndpoint;
|
||||
|
||||
|
@ -48,7 +49,7 @@ class SmartButton
|
|||
);
|
||||
add_action(
|
||||
'woocommerce_widget_shopping_cart_buttons',
|
||||
function() {
|
||||
function () {
|
||||
echo '<span id="ppc-button-minicart"></span>';
|
||||
},
|
||||
30
|
||||
|
@ -81,6 +82,10 @@ class SmartButton
|
|||
'endpoint' => home_url(\WC_AJAX::get_endpoint(CreateOrderEndpoint::ENDPOINT)),
|
||||
'nonce' => wp_create_nonce(CreateOrderEndpoint::nonce()),
|
||||
],
|
||||
'approve_order' => [
|
||||
'endpoint' => home_url(\WC_AJAX::get_endpoint(ApproveOrderEndpoint::ENDPOINT)),
|
||||
'nonce' => wp_create_nonce(ApproveOrderEndpoint::nonce()),
|
||||
],
|
||||
],
|
||||
'button' => [
|
||||
'wrapper' => '#ppc-button',
|
||||
|
|
|
@ -6,6 +6,7 @@ namespace Inpsyde\PayPalCommerce\Button;
|
|||
use Dhii\Container\ServiceProvider;
|
||||
use Dhii\Modular\Module\ModuleInterface;
|
||||
use Inpsyde\PayPalCommerce\Button\Assets\SmartButton;
|
||||
use Inpsyde\PayPalCommerce\Button\Endpoint\ApproveOrderEndpoint;
|
||||
use Inpsyde\PayPalCommerce\Button\Endpoint\ChangeCartEndpoint;
|
||||
use Inpsyde\PayPalCommerce\Button\Endpoint\CreateOrderEndpoint;
|
||||
use Inpsyde\PayPalCommerce\Button\Endpoint\RequestData;
|
||||
|
@ -56,6 +57,17 @@ class ButtonModule implements ModuleInterface
|
|||
}
|
||||
);
|
||||
|
||||
add_action(
|
||||
'wc_ajax_' . ApproveOrderEndpoint::ENDPOINT,
|
||||
function () use ($container) {
|
||||
$endpoint = $container->get('button.endpoint.approve-order');
|
||||
/**
|
||||
* @var ChangeCartEndpoint $endpoint
|
||||
*/
|
||||
$endpoint->handleRequest();
|
||||
}
|
||||
);
|
||||
|
||||
add_action(
|
||||
'wc_ajax_' . CreateOrderEndpoint::ENDPOINT,
|
||||
function () use ($container) {
|
||||
|
|
|
@ -0,0 +1,74 @@
|
|||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Inpsyde\PayPalCommerce\Button\Endpoint;
|
||||
|
||||
|
||||
use Inpsyde\PayPalCommerce\ApiClient\Endpoint\OrderEndpoint;
|
||||
use Inpsyde\PayPalCommerce\ApiClient\Entity\OrderStatus;
|
||||
use Inpsyde\PayPalCommerce\Button\Exception\RuntimeException;
|
||||
use Inpsyde\PayPalCommerce\Session\SessionHandler;
|
||||
|
||||
class ApproveOrderEndpoint implements EndpointInterface
|
||||
{
|
||||
|
||||
const ENDPOINT = 'ppc-approve-order';
|
||||
|
||||
private $requestData;
|
||||
private $sessionHandler;
|
||||
private $apiEndpoint;
|
||||
public function __construct(
|
||||
RequestData $requestData,
|
||||
OrderEndpoint $apiEndpoint,
|
||||
SessionHandler $sessionHandler
|
||||
) {
|
||||
|
||||
$this->requestData = $requestData;
|
||||
$this->apiEndpoint = $apiEndpoint;
|
||||
$this->sessionHandler = $sessionHandler;
|
||||
}
|
||||
|
||||
public static function nonce(): string
|
||||
{
|
||||
return self::ENDPOINT . get_current_user_id();
|
||||
}
|
||||
|
||||
public function handleRequest(): bool
|
||||
{
|
||||
try {
|
||||
$data = $this->requestData->readRequest($this->nonce());
|
||||
if (! isset($data['order_id'])) {
|
||||
throw new RuntimeException(__("No order id given", "woocommerce-paypal-commerce-gateway"));
|
||||
}
|
||||
|
||||
$order = $this->apiEndpoint->order($data['order_id']);
|
||||
if (! $order) {
|
||||
throw new RuntimeException(
|
||||
sprintf(
|
||||
// translators: %s is the id of the order.
|
||||
__('Order %s not found.', 'woocommerce-paypal-commerce-gateway'),
|
||||
$data['order_id']
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
if (! $order->status()->is(OrderStatus::APPROVED)) {
|
||||
|
||||
throw new RuntimeException(
|
||||
sprintf(
|
||||
// translators: %s is the id of the order.
|
||||
__('Order %s is not approved yet.', 'woocommerce-paypal-commerce-gateway'),
|
||||
$data['order_id']
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
$this->sessionHandler->replaceOrder($order);
|
||||
wp_send_json_success($order);
|
||||
return true;
|
||||
} catch (\RuntimeException $error) {
|
||||
wp_send_json_error($error->getMessage());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -40,7 +40,7 @@ class CreateOrderEndpoint implements EndpointInterface
|
|||
...$purchaseUnits
|
||||
);
|
||||
wp_send_json_success($order->toArray());
|
||||
return false;
|
||||
return true;
|
||||
} catch (\RuntimeException $error) {
|
||||
wp_send_json_error($error->getMessage());
|
||||
return false;
|
||||
|
|
|
@ -4,9 +4,12 @@ declare(strict_types=1);
|
|||
namespace Inpsyde\PayPalCommerce\Session;
|
||||
|
||||
use Dhii\Data\Container\ContainerInterface;
|
||||
use Inpsyde\PayPalCommerce\Session\Cancellation\CancelController;
|
||||
use Inpsyde\PayPalCommerce\Session\Cancellation\CancelView;
|
||||
|
||||
return [
|
||||
'session.handler' => function (ContainerInterface $container) : SessionHandler {
|
||||
|
||||
if (is_admin()) {
|
||||
return new SessionHandler();
|
||||
}
|
||||
|
@ -18,4 +21,13 @@ return [
|
|||
WC()->session->set(SessionHandler::ID, $sessionHandler);
|
||||
return $sessionHandler;
|
||||
},
|
||||
'session.cancellation.view' => function (ContainerInterface $container) : CancelView {
|
||||
return new CancelView();
|
||||
},
|
||||
'session.cancellation.controller' => function (ContainerInterface $container) : CancelController {
|
||||
return new CancelController(
|
||||
$container->get('session.handler'),
|
||||
$container->get('session.cancellation.view')
|
||||
);
|
||||
},
|
||||
];
|
||||
|
|
|
@ -0,0 +1,46 @@
|
|||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Inpsyde\PayPalCommerce\Session\Cancellation;
|
||||
|
||||
use Inpsyde\PayPalCommerce\Session\SessionHandler;
|
||||
|
||||
class CancelController
|
||||
{
|
||||
|
||||
private $sessionHandler;
|
||||
private $view;
|
||||
public function __construct(
|
||||
SessionHandler $sessionHandler,
|
||||
CancelView $view
|
||||
) {
|
||||
|
||||
$this->view = $view;
|
||||
$this->sessionHandler = $sessionHandler;
|
||||
}
|
||||
|
||||
public function run()
|
||||
{
|
||||
$paramName = 'ppcp-cancel';
|
||||
$nonce = 'ppcp-cancel-' . get_current_user_id();
|
||||
if (isset($_GET[$paramName]) && // Input var ok.
|
||||
wp_verify_nonce(
|
||||
sanitize_text_field(wp_unslash($_GET[$paramName])), // Input var ok.
|
||||
$nonce
|
||||
)
|
||||
) { // Input var ok.
|
||||
$this->sessionHandler->destroySessionData();
|
||||
}
|
||||
if (! $this->sessionHandler->order()) {
|
||||
return;
|
||||
}
|
||||
|
||||
$url = add_query_arg([$paramName => wp_create_nonce($nonce)], wc_get_checkout_url());
|
||||
add_action(
|
||||
'woocommerce_review_order_after_submit',
|
||||
function () use ($url) {
|
||||
$this->view->renderSessionCancelation($url);
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
23
modules.local/ppcp-session/src/Cancellation/CancelView.php
Normal file
23
modules.local/ppcp-session/src/Cancellation/CancelView.php
Normal file
|
@ -0,0 +1,23 @@
|
|||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Inpsyde\PayPalCommerce\Session\Cancellation;
|
||||
|
||||
class CancelView
|
||||
{
|
||||
|
||||
public function renderSessionCancelation(string $url)
|
||||
{
|
||||
?>
|
||||
<p
|
||||
class="has-text-align-center ppcp-cancel"
|
||||
>
|
||||
<a
|
||||
href="<?php echo esc_url($url); ?>"
|
||||
><?php
|
||||
esc_html_e('Cancel', 'woocommerce-paypal-commerce-gateway');
|
||||
?></a>
|
||||
</p>
|
||||
<?php
|
||||
}
|
||||
}
|
|
@ -22,6 +22,13 @@ class SessionHandler
|
|||
return $this;
|
||||
}
|
||||
|
||||
public function destroySessionData() : SessionHandler
|
||||
{
|
||||
$this->order = null;
|
||||
$this->storeSession();
|
||||
return $this;
|
||||
}
|
||||
|
||||
private function storeSession()
|
||||
{
|
||||
WC()->session->set(self::ID, $this);
|
||||
|
|
|
@ -5,6 +5,7 @@ namespace Inpsyde\PayPalCommerce\Session;
|
|||
|
||||
use Dhii\Container\ServiceProvider;
|
||||
use Dhii\Modular\Module\ModuleInterface;
|
||||
use Inpsyde\PayPalCommerce\Session\Cancellation\CancelController;
|
||||
use Interop\Container\ServiceProviderInterface;
|
||||
use Psr\Container\ContainerInterface;
|
||||
|
||||
|
@ -24,7 +25,11 @@ class SessionModule implements ModuleInterface
|
|||
add_action(
|
||||
'woocommerce_init',
|
||||
function () use ($container) {
|
||||
$container->get('session.handler');
|
||||
$controller = $container->get('session.cancellation.controller');
|
||||
/**
|
||||
* @var CancelController $controller
|
||||
*/
|
||||
$controller->run();
|
||||
}
|
||||
);
|
||||
}
|
||||
|
|
|
@ -101,6 +101,7 @@ class WcGateway extends \WC_Payment_Gateway
|
|||
$wcOrder->update_status('processing', __('Payment received.', 'woocommerce-paypal-gateway'));
|
||||
}
|
||||
$woocommerce->cart->empty_cart();
|
||||
$this->sessionHandler->destroySessionData();
|
||||
|
||||
return [
|
||||
'result' => 'success',
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue