mirror of
https://github.com/woocommerce/woocommerce-paypal-payments.git
synced 2025-09-05 08:59:14 +08:00
Create order-tracking endpoint
This commit is contained in:
parent
8f45fa1cce
commit
7998699a6b
1 changed files with 344 additions and 0 deletions
|
@ -0,0 +1,344 @@
|
|||
<?php
|
||||
/**
|
||||
* The order tracking Endpoint.
|
||||
*
|
||||
* @package WooCommerce\PayPalCommerce\OrderTracking\Endpoint
|
||||
*/
|
||||
|
||||
declare( strict_types=1 );
|
||||
|
||||
namespace WooCommerce\PayPalCommerce\OrderTracking\Endpoint;
|
||||
|
||||
use Exception;
|
||||
use Psr\Log\LoggerInterface;
|
||||
use WC_Order;
|
||||
use WooCommerce\PayPalCommerce\ApiClient\Authentication\Bearer;
|
||||
use WooCommerce\PayPalCommerce\ApiClient\Endpoint\RequestTrait;
|
||||
use WooCommerce\PayPalCommerce\ApiClient\Entity\SellerStatus;
|
||||
use WooCommerce\PayPalCommerce\ApiClient\Exception\PayPalApiException;
|
||||
use WooCommerce\PayPalCommerce\ApiClient\Exception\RuntimeException;
|
||||
use WooCommerce\PayPalCommerce\ApiClient\Factory\SellerStatusFactory;
|
||||
use WooCommerce\PayPalCommerce\Button\Endpoint\RequestData;
|
||||
use WooCommerce\PayPalCommerce\WcGateway\Processor\TransactionIdHandlingTrait;
|
||||
|
||||
/**
|
||||
* @psalm-type SupportedStatuses = 'SHIPPED'|'ON_HOLD'|'DELIVERED'|'CANCELLED'
|
||||
* @psalm-type TrackingInfo = array{transaction_id: string, status: SupportedStatuses, tracking_number?: string, carrier?: string}
|
||||
* @psalm-type RequestValues = array{transaction_id: string, status: SupportedStatuses, order_id: int, action: 'create'|'update', tracking_number?: string, carrier?: string}
|
||||
* Class OrderTrackingEndpoint
|
||||
*/
|
||||
class OrderTrackingEndpoint {
|
||||
|
||||
use RequestTrait, TransactionIdHandlingTrait;
|
||||
|
||||
const ENDPOINT = 'ppc-tracking-info';
|
||||
/**
|
||||
* @var RequestData
|
||||
*/
|
||||
protected $request_data;
|
||||
|
||||
/**
|
||||
* The Host URL.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $host;
|
||||
|
||||
/**
|
||||
* The bearer.
|
||||
*
|
||||
* @var Bearer
|
||||
*/
|
||||
private $bearer;
|
||||
|
||||
/**
|
||||
* The logger.
|
||||
*
|
||||
* @var LoggerInterface
|
||||
*/
|
||||
private $logger;
|
||||
|
||||
/**
|
||||
* The seller status factory.
|
||||
*
|
||||
* @var SellerStatusFactory
|
||||
*/
|
||||
private $seller_status_factory;
|
||||
|
||||
/**
|
||||
* The partner ID.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $partner_id;
|
||||
|
||||
/**
|
||||
* The merchant ID.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $merchant_id;
|
||||
|
||||
/**
|
||||
* PartnersEndpoint constructor.
|
||||
*
|
||||
* @param string $host The host.
|
||||
* @param Bearer $bearer The bearer.
|
||||
* @param LoggerInterface $logger The logger.
|
||||
* @param RequestData $request_data
|
||||
*/
|
||||
public function __construct(
|
||||
string $host,
|
||||
Bearer $bearer,
|
||||
LoggerInterface $logger,
|
||||
RequestData $request_data
|
||||
) {
|
||||
$this->host = $host;
|
||||
$this->bearer = $bearer;
|
||||
$this->logger = $logger;
|
||||
$this->request_data = $request_data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles the request.
|
||||
*/
|
||||
public function handle_request() {
|
||||
try {
|
||||
$data = $this->request_data->read_request( $this->nonce() );
|
||||
$action = $data['action'];
|
||||
$request_body = $this->extract_tracking_information($data);
|
||||
$order_id = (int)$data['order_id'];
|
||||
$action === 'create' ? $this->add_tracking_information($request_body, $order_id) : $this->update_tracking_information($data, $order_id);
|
||||
|
||||
$action_message = $action === 'create' ? 'created' : 'updated';
|
||||
$message = __("successfully {$action_message}",'woocommerce-paypal-payments');
|
||||
wp_send_json_success(array('message' => $message));
|
||||
return true;
|
||||
} catch ( Exception $error ) {
|
||||
wp_send_json_error( $error->getMessage(), 500 );
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates the tracking information of a given order with the given data.
|
||||
*
|
||||
* @param array $data The tracking information to add.
|
||||
* @psalm-param TrackingInfo $data
|
||||
* @param int $order_id The order ID.
|
||||
* @throws RuntimeException If problem creating.
|
||||
*/
|
||||
public function add_tracking_information(array $data, int $order_id) : void {
|
||||
$url = trailingslashit( $this->host ) . 'v1/shipping/trackers-batch';
|
||||
|
||||
$body = array(
|
||||
'trackers' => array($data)
|
||||
);
|
||||
|
||||
$args = array(
|
||||
'method' => 'POST',
|
||||
'headers' => $this->request_headers(),
|
||||
'body' => wp_json_encode( $body ),
|
||||
);
|
||||
|
||||
$response = $this->request( $url, $args );
|
||||
|
||||
if ( is_wp_error( $response ) ) {
|
||||
$error = new RuntimeException(
|
||||
'Could not create order tracking information.'
|
||||
);
|
||||
$this->logger->log(
|
||||
'warning',
|
||||
$error->getMessage(),
|
||||
array(
|
||||
'args' => $args,
|
||||
'response' => $response,
|
||||
)
|
||||
);
|
||||
throw $error;
|
||||
}
|
||||
|
||||
$json = json_decode( $response['body'] );
|
||||
$status_code = (int) wp_remote_retrieve_response_code( $response );
|
||||
if ( 200 !== $status_code ) {
|
||||
$error = new PayPalApiException(
|
||||
$json,
|
||||
$status_code
|
||||
);
|
||||
$this->logger->log(
|
||||
'warning',
|
||||
sprintf(
|
||||
'Failed to create order tracking information. PayPal API response: %1$s',
|
||||
$error->getMessage()
|
||||
),
|
||||
array(
|
||||
'args' => $args,
|
||||
'response' => $response,
|
||||
)
|
||||
);
|
||||
throw $error;
|
||||
}
|
||||
|
||||
update_post_meta($order_id, '_ppcp_paypal_tracking_number', $data['tracking_number']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the tracking information of a given order.
|
||||
*
|
||||
* @param int $wc_order_id The order ID.
|
||||
* @return array The tracking information.
|
||||
* @psalm-return TrackingInfo
|
||||
*/
|
||||
public function get_tracking_information(int $wc_order_id) : array {
|
||||
$wc_order = wc_get_order( $wc_order_id );
|
||||
$transaction_id = $wc_order->get_transaction_id();
|
||||
$tracking_number = get_post_meta($wc_order_id, '_ppcp_paypal_tracking_number', true);
|
||||
$url = trailingslashit( $this->host ) . 'v1/shipping/trackers/'. $this->find_tracker_id($transaction_id, $tracking_number);
|
||||
|
||||
$args = array(
|
||||
'method' => 'GET',
|
||||
'headers' => $this->request_headers(),
|
||||
);
|
||||
|
||||
$response = $this->request( $url, $args );
|
||||
|
||||
if ( is_wp_error( $response ) ) {
|
||||
$error = new RuntimeException(
|
||||
'Could not fetch the tracking information.'
|
||||
);
|
||||
$this->logger->log(
|
||||
'warning',
|
||||
$error->getMessage(),
|
||||
array(
|
||||
'args' => $args,
|
||||
'response' => $response,
|
||||
)
|
||||
);
|
||||
throw $error;
|
||||
}
|
||||
|
||||
$data = json_decode( $response['body'] );
|
||||
$status_code = (int) wp_remote_retrieve_response_code( $response );
|
||||
|
||||
if ( 200 !== $status_code ) {
|
||||
return [];
|
||||
}
|
||||
|
||||
return array(
|
||||
'transaction_id' => $data->transaction_id ?? '',
|
||||
'status' => $data->status ?? '',
|
||||
'tracking_number' => $data->tracking_number ?? '',
|
||||
'carrier' => $data->carrier ?? '',
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the tracking information of a given order with the given data.
|
||||
*
|
||||
* @param array $data The tracking information to update.
|
||||
* @psalm-param TrackingInfo $data
|
||||
* @param int $order_id The order ID.
|
||||
* @throws RuntimeException If problem updating.
|
||||
*/
|
||||
public function update_tracking_information(array $data, int $order_id) : void {
|
||||
$tracking_info = $this->get_tracking_information($order_id);
|
||||
$transaction_id = $tracking_info['transaction_id'] ?? '';
|
||||
$tracking_number = $tracking_info['tracking_number'] ?? '';
|
||||
$url = trailingslashit( $this->host ) . 'v1/shipping/trackers/'. $this->find_tracker_id($transaction_id, $tracking_number);
|
||||
|
||||
$args = array(
|
||||
'method' => 'PUT',
|
||||
'headers' => $this->request_headers(),
|
||||
'body' => wp_json_encode( $data ),
|
||||
);
|
||||
|
||||
$response = $this->request( $url, $args );
|
||||
|
||||
if ( is_wp_error( $response ) ) {
|
||||
$error = new RuntimeException(
|
||||
'Could not update order tracking information.'
|
||||
);
|
||||
$this->logger->log(
|
||||
'warning',
|
||||
$error->getMessage(),
|
||||
array(
|
||||
'args' => $args,
|
||||
'response' => $response,
|
||||
)
|
||||
);
|
||||
throw $error;
|
||||
}
|
||||
|
||||
$json = json_decode( $response['body'] );
|
||||
$status_code = (int) wp_remote_retrieve_response_code( $response );
|
||||
if ( 204 !== $status_code ) {
|
||||
$error = new PayPalApiException(
|
||||
$json,
|
||||
$status_code
|
||||
);
|
||||
$this->logger->log(
|
||||
'warning',
|
||||
sprintf(
|
||||
'Failed to update the order tracking information. PayPal API response: %1$s',
|
||||
$error->getMessage()
|
||||
),
|
||||
array(
|
||||
'args' => $args,
|
||||
'response' => $response,
|
||||
)
|
||||
);
|
||||
throw $error;
|
||||
}
|
||||
|
||||
update_post_meta($order_id, '_ppcp_paypal_tracking_number', $data['tracking_number']);
|
||||
}
|
||||
|
||||
/**
|
||||
* The nonce.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function nonce(): string {
|
||||
return self::ENDPOINT;
|
||||
}
|
||||
|
||||
/**
|
||||
* Extracts the needed tracking information from given request data.
|
||||
*
|
||||
* @param array $data The request data map.
|
||||
* @psalm-param RequestValues $data
|
||||
* @return array A map of tracking information keys to values.
|
||||
* @psalm-return TrackingInfo
|
||||
*/
|
||||
protected function extract_tracking_information(array $data): array {
|
||||
return array(
|
||||
'transaction_id' => $data['transaction_id'] ?? '',
|
||||
'tracking_number' => $data['tracking_number'] ?? '',
|
||||
'status' => $data['status'] ?? '',
|
||||
'carrier' => $data['carrier'] ?? '',
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates the request headers.
|
||||
*
|
||||
* @return array The request headers.
|
||||
*/
|
||||
protected function request_headers(): array {
|
||||
return array(
|
||||
'Authorization' => 'Bearer ' . $this->bearer->bearer()->token(),
|
||||
'Content-Type' => 'application/json',
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds the tracker ID from given transaction ID and tracking number.
|
||||
*
|
||||
* @param string $transaction_id The transaction ID.
|
||||
* @param string $tracking_number The tracking number.
|
||||
* @return string The tracker ID.
|
||||
*/
|
||||
protected function find_tracker_id(string $transaction_id, string $tracking_number): string {
|
||||
return !empty($tracking_number) ? "{$transaction_id}-{$tracking_number}" : "{$transaction_id}-NOTRACKER";
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue