Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
76.47% covered (warning)
76.47%
26 / 34
66.67% covered (warning)
66.67%
2 / 3
CRAP
0.00% covered (danger)
0.00%
0 / 1
AJAX
76.47% covered (warning)
76.47%
26 / 34
66.67% covered (warning)
66.67%
2 / 3
13.88
0.00% covered (danger)
0.00%
0 / 1
 __construct
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 get_order_details
100.00% covered (success)
100.00%
25 / 25
100.00% covered (success)
100.00%
1 / 1
7
 is_user_authorized
0.00% covered (danger)
0.00%
0 / 8
0.00% covered (danger)
0.00%
0 / 1
20
1<?php
2/**
3 * AJAX endpoint for fetching order information.
4 *
5 * TODO: Move this to /integrations/woocommerce.
6 *
7 * Used on Thank You and my-account screens to query for transaction updates.
8 *
9 * @package    brianhenryie/bh-wp-bitcoin-gateway
10 */
11
12namespace BrianHenryIE\WP_Bitcoin_Gateway\Integrations\WooCommerce;
13
14use Psr\Log\LoggerAwareTrait;
15use Psr\Log\LoggerInterface;
16use WC_Order;
17
18/**
19 * Action `bh_wp_bitcoin_gateway_refresh_order_details` hooked to `wp_ajax` and `wp_ajax_nopriv`.
20 */
21class AJAX {
22    use LoggerAwareTrait;
23
24    /**
25     * Constructor
26     *
27     * @param API_WooCommerce_Interface $api The main plugin functions, to get order information.
28     * @param LoggerInterface           $logger A PSR logger.
29     */
30    public function __construct(
31        protected API_WooCommerce_Interface $api,
32        LoggerInterface $logger
33    ) {
34        $this->setLogger( $logger );
35    }
36
37    /**
38     * Return data for number of confirmations,
39     * is the order paid.
40     * does more need to be sent
41     *
42     * @hooked wp_ajax_bh_wp_bitcoin_gateway_refresh_order_details
43     * @hooked wp_ajax_nopriv_bh_wp_bitcoin_gateway_refresh_order_details
44     */
45    public function get_order_details(): void {
46
47        if ( ! check_ajax_referer( Frontend_Assets::class, false, false ) ) {
48            wp_send_json_error( array( 'message' => 'Bad/no nonce.' ), 400 );
49        }
50
51        if ( ! isset( $_POST['order_id'] ) || ! is_numeric( $_POST['order_id'] ) ) {
52            wp_send_json_error( array( 'message' => 'No order id provided.' ), 400 );
53        }
54
55        $order_id = intval( wp_unslash( $_POST['order_id'] ) );
56
57        $order = wc_get_order( $order_id );
58
59        if ( ! ( $order instanceof WC_Order ) ) {
60            wp_send_json_error( array( 'message' => 'Invalid order id: ' . $order_id ), 400 );
61        }
62
63        $this->is_user_authorized( $order );
64
65        $this->api->check_order_for_payment( $order );
66        $result = $this->api->get_formatted_order_details( $order );
67
68        // These are the only keys used by the JavaScript.
69        $allowed_keys = array(
70            'btc_address',
71            'btc_total',
72            'order_id',
73            'btc_amount_received',
74            'status',
75            'amount_received',
76            'order_status_formatted',
77            'last_checked_time_formatted',
78        );
79
80        foreach ( array_keys( $result ) as $key ) {
81            if ( ! in_array( $key, $allowed_keys, true ) ) {
82                unset( $result[ $key ] );
83            }
84        }
85
86        wp_send_json_success( $result );
87    }
88
89    /**
90     * Check permission to view the order.
91     *
92     * @see \WC_Shortcode_Checkout::guest_should_verify_email()
93     * @see woocommerce/templates/checkout/form-verify-email.php
94     * @see OrderAuthorizationTrait
95     * @see \WC_Shortcode_Checkout::order_received()
96     *
97     * @param WC_Order $order To find is there a user id set on the order.
98     */
99    protected function is_user_authorized( WC_Order $order ): void {
100
101        // If the order has no user/customer id, we assume that WooCommerce verified them before displaying the page.
102        if ( empty( $order->get_customer_id() ) ) {
103            return;
104        }
105
106        // Shop admin?
107        if ( current_user_can( 'read_private_shop_orders' ) ) {
108            return;
109        }
110
111        $wp_user = wp_get_current_user();
112
113        // Logged in and owns the order.
114        if ( $order->get_customer_id() === $wp_user->ID ) {
115            return;
116        }
117
118        wp_send_json_error( array( 'message' => 'Logged in user does not own this order.' ), 403 );
119    }
120}