212 lines
6.4 KiB
PHP
212 lines
6.4 KiB
PHP
<?php
|
|
/**
|
|
*
|
|
* REST API PayPal buttons controller
|
|
*
|
|
* @package WooCommerce\RestApi
|
|
* @since 10.3.0
|
|
*/
|
|
|
|
declare(strict_types=1);
|
|
|
|
defined( 'ABSPATH' ) || exit;
|
|
|
|
use Automattic\WooCommerce\Enums\OrderStatus;
|
|
|
|
if ( ! class_exists( 'WC_Gateway_Paypal_Constants' ) ) {
|
|
require_once WC_ABSPATH . 'includes/gateways/paypal/includes/class-wc-gateway-paypal-constants.php';
|
|
}
|
|
|
|
if ( ! class_exists( 'WC_Gateway_Paypal_Request' ) ) {
|
|
require_once WC_ABSPATH . 'includes/gateways/paypal/includes/class-wc-gateway-paypal-request.php';
|
|
}
|
|
|
|
|
|
/**
|
|
* REST API PayPal buttons controller class.
|
|
*
|
|
* @package WooCommerce\RestApi
|
|
* @extends WC_REST_Controller
|
|
*/
|
|
class WC_REST_Paypal_Buttons_Controller extends WC_REST_Controller {
|
|
|
|
/**
|
|
* Endpoint namespace.
|
|
*
|
|
* @var string
|
|
*/
|
|
protected $namespace = 'wc/v3';
|
|
|
|
/**
|
|
* Route base.
|
|
*
|
|
* @var string
|
|
*/
|
|
protected $rest_base = 'paypal-buttons';
|
|
|
|
/**
|
|
* Register the routes for the PayPal buttons functionality handler.
|
|
*
|
|
* @return void
|
|
*/
|
|
public function register_routes() {
|
|
register_rest_route(
|
|
$this->namespace,
|
|
'/' . $this->rest_base . '/create-order',
|
|
array(
|
|
'methods' => WP_REST_Server::CREATABLE,
|
|
'callback' => array( $this, 'create_order' ),
|
|
'permission_callback' => array( $this, 'validate_create_order_request' ),
|
|
)
|
|
);
|
|
|
|
register_rest_route(
|
|
$this->namespace,
|
|
'/' . $this->rest_base . '/cancel-payment',
|
|
array(
|
|
'methods' => WP_REST_Server::CREATABLE,
|
|
'callback' => array( $this, 'cancel_payment' ),
|
|
'permission_callback' => array( $this, 'validate_cancel_payment_request' ),
|
|
)
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Validate the create order request.
|
|
*
|
|
* @param WP_REST_Request $request The request object.
|
|
* @return bool True if the create order request is valid, false otherwise.
|
|
*/
|
|
public function validate_create_order_request( WP_REST_Request $request ) {
|
|
if ( $request->get_header( 'Nonce' ) ) {
|
|
$nonce = $request->get_header( 'Nonce' );
|
|
return wp_verify_nonce( $nonce, 'wc_gateway_paypal_standard_create_order' );
|
|
}
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* Validate the cancel payment request.
|
|
*
|
|
* @param WP_REST_Request $request The request object.
|
|
* @return bool True if the cancel payment request is valid, false otherwise.
|
|
*/
|
|
public function validate_cancel_payment_request( WP_REST_Request $request ) {
|
|
if ( $request->get_header( 'Nonce' ) ) {
|
|
$nonce = $request->get_header( 'Nonce' );
|
|
return wp_verify_nonce( $nonce, 'wc_gateway_paypal_standard_cancel_payment' );
|
|
}
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* Create a PayPal order.
|
|
*
|
|
* @param WP_REST_Request $request The request object.
|
|
* @return WP_REST_Response The response object.
|
|
*/
|
|
public function create_order( WP_REST_Request $request ) {
|
|
$data = $request->get_json_params();
|
|
|
|
if ( empty( $data['order_id'] ) || empty( $data['order_key'] ) ) {
|
|
return new WP_REST_Response( array( 'error' => 'Invalid request' ), 400 );
|
|
}
|
|
|
|
$payment_source = isset( $data['payment_source'] ) ? sanitize_text_field( $data['payment_source'] ) : '';
|
|
if ( empty( $payment_source ) || ! in_array( $payment_source, WC_Gateway_Paypal_Constants::SUPPORTED_PAYMENT_SOURCES, true ) ) {
|
|
return new WP_REST_Response( array( 'error' => 'Missing/Invalid payment source: ' . esc_html( $payment_source ) ), 400 );
|
|
}
|
|
|
|
$order_id = $data['order_id'];
|
|
$order = wc_get_order( $order_id );
|
|
|
|
if ( ! $order ) {
|
|
return new WP_REST_Response( array( 'error' => 'Order not found' ), 404 );
|
|
}
|
|
|
|
$order_key = $data['order_key'];
|
|
if ( ! $order_key || ! hash_equals( $order->get_order_key(), $order_key ) ) {
|
|
return new WP_REST_Response( array( 'error' => 'Order not found' ), 404 );
|
|
}
|
|
|
|
if ( ! in_array( $order->get_status(), array( OrderStatus::CHECKOUT_DRAFT, OrderStatus::PENDING ), true ) ) {
|
|
return new WP_REST_Response( array( 'error' => 'Invalid order status' ), 409 );
|
|
}
|
|
|
|
$gateway = WC_Gateway_Paypal::get_instance();
|
|
|
|
// For Buttons requests, we need to explicitly set the payment method to PayPal.
|
|
$order->set_payment_method( $gateway->id );
|
|
$order->save();
|
|
|
|
$paypal_request = new WC_Gateway_Paypal_Request( $gateway );
|
|
$paypal_order = $paypal_request->create_paypal_order(
|
|
$order,
|
|
$payment_source,
|
|
array(
|
|
'is_js_sdk_flow' => true,
|
|
'app_switch_request_origin' => $data['app_switch_request_origin'] ?? '',
|
|
)
|
|
);
|
|
|
|
if ( ! $paypal_order || empty( $paypal_order['id'] ) ) {
|
|
return new WP_REST_Response( array( 'error' => 'Failed to create PayPal order' ), 400 );
|
|
}
|
|
|
|
$order->update_meta_data( '_paypal_order_id', $paypal_order['id'] );
|
|
$order->update_status( OrderStatus::PENDING );
|
|
$order->save();
|
|
|
|
return new WP_REST_Response(
|
|
array(
|
|
'paypal_order_id' => $paypal_order['id'] ?? null,
|
|
'order_id' => $order_id,
|
|
'return_url' => esc_url_raw( add_query_arg( 'utm_nooverride', '1', $gateway->get_return_url( $order ) ) ),
|
|
),
|
|
200
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Cancel a PayPal payment. This is used to move the woocommerce order back to a draft status.
|
|
*
|
|
* @param WP_REST_Request $request The request object.
|
|
* @return WP_REST_Response The response object.
|
|
*/
|
|
public function cancel_payment( WP_REST_Request $request ) {
|
|
$data = $request->get_json_params();
|
|
|
|
$order_id = isset( $data['order_id'] ) ? absint( $data['order_id'] ) : 0;
|
|
$paypal_order_id = isset( $data['paypal_order_id'] ) ? wc_clean( $data['paypal_order_id'] ) : '';
|
|
if ( ! $order_id || '' === $paypal_order_id ) {
|
|
return new WP_REST_Response( array( 'error' => 'Invalid request' ), 400 );
|
|
}
|
|
|
|
$order = wc_get_order( $order_id );
|
|
if ( ! $order ) {
|
|
return new WP_REST_Response( array( 'error' => 'Order not found' ), 404 );
|
|
}
|
|
|
|
// Verify order by checking the PayPal order ID.
|
|
$paypal_order_id_from_meta = $order->get_meta( '_paypal_order_id' );
|
|
if ( $paypal_order_id_from_meta !== $paypal_order_id ) {
|
|
return new WP_REST_Response( array( 'error' => 'Invalid PayPal order' ), 404 );
|
|
}
|
|
|
|
// If order is already in draft status, do nothing and return success.
|
|
if ( $order->has_status( OrderStatus::CHECKOUT_DRAFT ) ) {
|
|
return new WP_REST_Response( array( 'success' => true ), 200 );
|
|
}
|
|
|
|
// If order is not pending, return an error.
|
|
if ( ! $order->has_status( OrderStatus::PENDING ) ) {
|
|
return new WP_REST_Response( array( 'error' => 'Order is not pending' ), 409 );
|
|
}
|
|
|
|
$order->update_status( OrderStatus::CHECKOUT_DRAFT );
|
|
$order->save();
|
|
|
|
return new WP_REST_Response( array( 'success' => true ), 200 );
|
|
}
|
|
}
|