Handle shipping address/methods update

This commit is contained in:
Alex P 2023-04-27 09:06:38 +03:00
parent f396870610
commit efb86acb1f
No known key found for this signature in database
GPG key ID: 54487A734A204D71
6 changed files with 204 additions and 5 deletions

View file

@ -19,7 +19,7 @@ export const splitFullName = (fullName) => {
* @returns {Object}
*/
export const paypalAddressToWc = (address) => {
const map = {
let map = {
country_code: 'country',
address_line_1: 'address_1',
address_line_2: 'address_2',
@ -27,6 +27,14 @@ export const paypalAddressToWc = (address) => {
admin_area_2: 'city',
postal_code: 'postcode',
};
if (address.city) { // address not from API, such as onShippingChange
map = {
country_code: 'country',
state: 'state',
city: 'city',
postal_code: 'postcode',
};
}
const result = {};
Object.entries(map).forEach(([paypalKey, wcKey]) => {
if (address[paypalKey]) {

View file

@ -1,6 +1,6 @@
import {useEffect, useState} from '@wordpress/element';
import {registerExpressPaymentMethod, registerPaymentMethod} from '@woocommerce/blocks-registry';
import {paypalOrderToWcAddresses} from "./Helper/Address";
import {paypalAddressToWc, paypalOrderToWcAddresses} from "./Helper/Address";
import {loadPaypalScript} from '../../../ppcp-button/resources/js/modules/Helper/ScriptLoading'
const config = wc.wcSettings.getSetting('ppcp-gateway_data');
@ -132,11 +132,40 @@ const PayPalComponent = ({
let handleShippingChange = null;
if (shippingData.needsShipping && !config.finalReviewEnabled) {
handleShippingChange = (data) => {
handleShippingChange = async (data, actions) => {
console.log(data)
const shippingOptionId = data.selected_shipping_option.id;
shippingData.setSelectedRates(shippingOptionId)
try {
const shippingOptionId = data.selected_shipping_option?.id;
if (shippingOptionId) {
await shippingData.setSelectedRates(shippingOptionId);
}
const address = paypalAddressToWc(data.shipping_address);
await wp.data.dispatch('wc/store/cart').updateCustomerData({
shipping_address: address,
});
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();
}
};
}

View file

@ -9,6 +9,7 @@ declare(strict_types=1);
namespace WooCommerce\PayPalCommerce\Blocks;
use WooCommerce\PayPalCommerce\Blocks\Endpoint\UpdateShippingEndpoint;
use WooCommerce\PayPalCommerce\Vendor\Psr\Container\ContainerInterface;
return array(
@ -44,4 +45,13 @@ return array(
(bool) $settings->get( 'blocks_final_review_enabled' ) :
true;
},
'blocks.endpoint.update-shipping' => static function ( ContainerInterface $container ): UpdateShippingEndpoint {
return new UpdateShippingEndpoint(
$container->get( 'button.request-data' ),
$container->get( 'api.endpoint.order' ),
$container->get( 'api.factory.purchase-unit' ),
$container->get( 'woocommerce.logger.woocommerce' )
);
},
);

View file

@ -10,6 +10,7 @@ declare(strict_types=1);
namespace WooCommerce\PayPalCommerce\Blocks;
use Automattic\WooCommerce\Blocks\Payments\PaymentMethodRegistry;
use WooCommerce\PayPalCommerce\Blocks\Endpoint\UpdateShippingEndpoint;
use WooCommerce\PayPalCommerce\Button\Assets\SmartButton;
use WooCommerce\PayPalCommerce\Vendor\Dhii\Container\ServiceProvider;
use WooCommerce\PayPalCommerce\Vendor\Dhii\Modular\Module\ModuleInterface;
@ -77,6 +78,16 @@ class BlocksModule implements ModuleInterface {
},
)
);
add_action(
'wc_ajax_' . UpdateShippingEndpoint::ENDPOINT,
static function () use ( $c ) {
$endpoint = $c->get( 'blocks.endpoint.update-shipping' );
assert( $endpoint instanceof UpdateShippingEndpoint );
$endpoint->handle_request();
}
);
}
/**

View file

@ -0,0 +1,133 @@
<?php
/**
* Updates PayPal order with the current shipping methods.
*
* @package WooCommerce\PayPalCommerce\Button\Endpoint
*/
declare(strict_types=1);
namespace WooCommerce\PayPalCommerce\Blocks\Endpoint;
use Exception;
use Psr\Log\LoggerInterface;
use WooCommerce\PayPalCommerce\ApiClient\Endpoint\OrderEndpoint;
use WooCommerce\PayPalCommerce\ApiClient\Entity\Patch;
use WooCommerce\PayPalCommerce\ApiClient\Entity\PatchCollection;
use WooCommerce\PayPalCommerce\ApiClient\Factory\PurchaseUnitFactory;
use WooCommerce\PayPalCommerce\Button\Endpoint\EndpointInterface;
use WooCommerce\PayPalCommerce\Button\Endpoint\RequestData;
/**
* Class UpdateShippingEndpoint
*/
class UpdateShippingEndpoint implements EndpointInterface {
const ENDPOINT = 'ppc-update-shipping';
/**
* The Request Data Helper.
*
* @var RequestData
*/
private $request_data;
/**
* The order endpoint.
*
* @var OrderEndpoint
*/
private $order_endpoint;
/**
* The purchase unit factory.
*
* @var PurchaseUnitFactory
*/
private $purchase_unit_factory;
/**
* The logger.
*
* @var LoggerInterface
*/
protected $logger;
/**
* UpdateShippingEndpoint constructor.
*
* @param RequestData $request_data The Request Data Helper.
* @param OrderEndpoint $order_endpoint The order endpoint.
* @param PurchaseUnitFactory $purchase_unit_factory The purchase unit factory.
* @param LoggerInterface $logger The logger.
*/
public function __construct(
RequestData $request_data,
OrderEndpoint $order_endpoint,
PurchaseUnitFactory $purchase_unit_factory,
LoggerInterface $logger
) {
$this->request_data = $request_data;
$this->order_endpoint = $order_endpoint;
$this->purchase_unit_factory = $purchase_unit_factory;
$this->logger = $logger;
}
/**
* Returns the nonce.
*
* @return string
*/
public static function nonce(): string {
return self::ENDPOINT;
}
/**
* Handles the request.
*
* @return bool
*/
public function handle_request(): bool {
try {
$data = $this->request_data->read_request( $this->nonce() );
$order_id = $data['order_id'];
$pu = $this->purchase_unit_factory->from_wc_cart( null, true );
$pu_data = $pu->to_array();
if ( ! isset( $pu_data['shipping']['options'] ) ) {
wp_send_json_error(
array(
'message' => 'No shipping methods.',
)
);
return false;
}
// TODO: maybe should patch only if methods changed.
// But it seems a bit difficult to detect,
// e.g. ->order($id) may not have Shipping because we drop it when address or name are missing.
// Also may consider patching only amount and options instead of the whole PU, though not sure if it makes any difference.
$patches = new PatchCollection(
new Patch(
'replace',
"/purchase_units/@reference_id=='{$pu->reference_id()}'",
$pu_data
)
);
$this->order_endpoint->patch( $order_id, $patches );
wp_send_json_success();
return true;
} catch ( Exception $error ) {
wp_send_json_error(
array(
'message' => $error->getMessage(),
)
);
return false;
}
}
}

View file

@ -10,6 +10,8 @@ declare(strict_types=1);
namespace WooCommerce\PayPalCommerce\Blocks;
use Automattic\WooCommerce\Blocks\Payments\Integrations\AbstractPaymentMethodType;
use WC_AJAX;
use WooCommerce\PayPalCommerce\Blocks\Endpoint\UpdateShippingEndpoint;
use WooCommerce\PayPalCommerce\Button\Assets\SmartButtonInterface;
use WooCommerce\PayPalCommerce\Session\Cancellation\CancelController;
use WooCommerce\PayPalCommerce\Session\Cancellation\CancelView;
@ -174,6 +176,12 @@ class PayPalPaymentMethod extends AbstractPaymentMethodType {
'enabled' => $this->settings_status->is_smart_button_enabled_for_location( $script_data['context'] ),
'fundingSource' => $this->session_handler->funding_source(),
'finalReviewEnabled' => $this->final_review_enabled,
'ajax' => array(
'update_shipping' => array(
'endpoint' => WC_AJAX::get_endpoint( UpdateShippingEndpoint::ENDPOINT ),
'nonce' => wp_create_nonce( UpdateShippingEndpoint::nonce() ),
),
),
'scriptData' => $script_data,
);
}