PluginProbe
Booktics – Appointment Booking Calendar for Service Businesses / 1.0.28
Booktics – Appointment Booking Calendar for Service Businesses v1.0.28
1.0.29 1.0.28 1.0.27 1.0.26 1.0.25 1.0.24 1.0.23 1.0.22 1.0.21 1.0.20 1.0.19 trunk 1.0.0 1.0.1 1.0.10 1.0.11 1.0.12 1.0.13 1.0.14 1.0.15 1.0.16 1.0.17 1.0.18 1.0.2 1.0.3 All 31 releases
booktics / core / module / woocommerce-addon / service / woocommerce-payment-method.php

woocommerce-payment-method.php in Booktics – Appointment Booking Calendar for Service Businesses 1.0.28, at core/module/woocommerce-addon/service/woocommerce-payment-method.php

175 lines 5.3 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace Booktics\Module\Woocommerce_Addon\Service;
4
5 if ( ! defined( 'ABSPATH' ) ) exit;
6
7 use Booktics\Models\Order_Model;
8 use Booktics\Payment\Payment_Methods\Abstract_Payment_Method;
9 use Booktics\Payment\Payment_Status;
10 use WP_Error;
11
12 /**
13 * WooCommerce payment method.
14 *
15 * WooCommerce is used purely as the checkout and gateway funnel: the booking
16 * is added to the WooCommerce cart and the customer pays on the store's own
17 * checkout page. The WooCommerce order id is stored on the Booktics order in
18 * `payment_intent_id`.
19 *
20 * Payment state is never decided here. WooCommerce already knows what counts
21 * as paid ( wc_get_is_paid_statuses(), which a store can filter ), so this
22 * class asks WooCommerce instead of maintaining a second opinion. A cash-on
23 * -delivery or bank-transfer order sitting at `on-hold` is therefore not paid,
24 * and the slot stays held until the shop owner moves it.
25 */
26 class Woocommerce_Payment_Method extends Abstract_Payment_Method {
27
28 /**
29 * Payment method id, as stored on the Booktics order.
30 *
31 * @var string
32 */
33 protected $id = 'woocommerce';
34
35 /**
36 * Human readable name.
37 *
38 * @var string
39 */
40 protected $name = 'WooCommerce';
41
42 /**
43 * Hand the booking over to the WooCommerce cart.
44 *
45 * No money moves here. The booking and its held slot already exist; this
46 * puts the matching line item in the cart and returns the checkout URL the
47 * customer is sent to, where the store's own gateways take over.
48 *
49 * @param Order_Model $order The Booktics order being paid.
50 *
51 * @return array
52 */
53 public function process_payment( $order ) {
54 return ( new Cart_Handoff() )->handoff( $order );
55 }
56
57 /**
58 * Validate the payment data supplied by the client.
59 *
60 * WooCommerce collects everything it needs on its own checkout page, so
61 * there is nothing for the booking form to supply.
62 *
63 * @return array
64 */
65 public function validate_payment_data() {
66 return array( 'status' => 'success' );
67 }
68
69 /**
70 * Read the payment state of the linked WooCommerce order.
71 *
72 * @param Order_Model $order The Booktics order.
73 *
74 * @return string One of the Payment_Status constants.
75 */
76 public function get_payment_status( $order ): string {
77 $wc_order = $this->get_wc_order( $order );
78
79 if ( ! $wc_order ) {
80 return Payment_Status::FAILED;
81 }
82
83 if ( $wc_order->get_status() === 'refunded' ) {
84 return Payment_Status::REFUNDED;
85 }
86
87 // WooCommerce's own definition of paid, including any store-side filter
88 // on woocommerce_order_is_paid_statuses.
89 if ( $wc_order->is_paid() ) {
90 return Payment_Status::COMPLETED;
91 }
92
93 return Payment_Status::FAILED;
94 }
95
96 /**
97 * Decide what to do with a slot held by an unpaid WooCommerce order.
98 *
99 * `pending` means the customer reached checkout and never paid, so the slot
100 * is released once the reservation window has passed. `on-hold` means the
101 * payment is pending settlement — a bank transfer or cheque, which can take
102 * days — so the slot is held indefinitely and re-checked on a later sweep.
103 *
104 * @param Order_Model $order The Booktics order whose slot is being evaluated.
105 *
106 * @return string One of the RESERVATION_* constants.
107 */
108 public function resolve_reservation_action( $order ): string {
109 $wc_order = $this->get_wc_order( $order );
110
111 if ( ! $wc_order ) {
112 // WooCommerce may simply be deactivated. Never cancel a customer's
113 // booking because we cannot currently see its order.
114 return self::RESERVATION_WAIT;
115 }
116
117 if ( $wc_order->is_paid() ) {
118 return self::RESERVATION_REPAIR;
119 }
120
121 switch ( $wc_order->get_status() ) {
122 case 'on-hold':
123 return self::RESERVATION_WAIT;
124
125 case 'failed':
126 case 'cancelled':
127 case 'pending':
128 return self::RESERVATION_RELEASE;
129
130 default:
131 return self::RESERVATION_WAIT;
132 }
133 }
134
135 /**
136 * Refunds are initiated in WooCommerce admin only.
137 *
138 * Booktics never calls a gateway refund for these orders; the listener in
139 * the sync hook reacts to woocommerce_order_refunded instead.
140 *
141 * @param Order_Model $order The Booktics order.
142 *
143 * @return WP_Error
144 */
145 public function process_refund( $order ) {
146 return new WP_Error(
147 'booktics_wc_refund_in_woocommerce',
148 __( 'This booking was paid through WooCommerce. Refund it from the WooCommerce order and the booking will update automatically.', 'booktics' )
149 );
150 }
151
152 /**
153 * Resolve the WooCommerce order linked to a Booktics order.
154 *
155 * @param Order_Model|object $order The Booktics order.
156 *
157 * @return \WC_Order|null
158 */
159 private function get_wc_order( $order ) {
160 if ( ! function_exists( 'wc_get_order' ) ) {
161 return null;
162 }
163
164 $wc_order_id = is_object( $order ) ? ( $order->payment_intent_id ?? 0 ) : 0;
165
166 if ( ! $wc_order_id ) {
167 return null;
168 }
169
170 $wc_order = wc_get_order( $wc_order_id );
171
172 return $wc_order instanceof \WC_Order ? $wc_order : null;
173 }
174 }
175