PluginProbe
WCPOS – Point of Sale (POS) plugin for WooCommerce / 1.9.16
WCPOS – Point of Sale (POS) plugin for WooCommerce v1.9.16
1.10.19 1.10.18 1.10.17 1.10.16 1.10.15 1.10.13 1.10.14 1.10.12 1.10.11 1.10.10 1.10.9 1.10.8 untagged-3d9b7ccddc54df87c672 1.10.7 1.10.6 1.10.5 1.10.3 1.10.4 1.10.2 1.10.1 1.10.0 1.9.17 1.9.15 1.9.16 1.9.14 All 163 releases
woocommerce-pos / includes / Gateways / Card.php

Card.php in WCPOS – Point of Sale (POS) plugin for WooCommerce 1.9.16, at includes/Gateways/Card.php

313 lines 9.1 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Provides a Card Payment Gateway.
4 *
5 * @author Paul Kilmurray <paul@kilbot.com>
6 *
7 * @see https://wcpos.com
8 *
9 * @extends WC_Payment_Gateway
10 * @package WCPOS\WooCommercePOS
11 */
12
13 namespace WCPOS\WooCommercePOS\Gateways;
14
15 use WC_Payment_Gateway;
16
17 /**
18 * Card class.
19 */
20 class Card extends WC_Payment_Gateway {
21 /**
22 * Constructor for the gateway.
23 */
24 public function __construct() {
25 $this->id = 'pos_card';
26 $this->title = /* translators: POS payment gateway label shown during checkout. */ __( 'Card', 'woocommerce-pos' );
27 $this->description = '';
28 $this->icon = apply_filters( 'woocommerce_pos_card_icon', '' );
29 $this->has_fields = true;
30 $this->enabled = 'no';
31 $this->supports = array( 'products', 'refunds' );
32
33 // Actions.
34 // @phpstan-ignore-next-line -- Action hook type mismatch.
35 add_action(
36 'woocommerce_pos_update_options_payment_gateways_' . $this->id,
37 array(
38 $this,
39 'process_admin_options',
40 )
41 );
42 add_action( 'woocommerce_thankyou_pos_card', array( $this, 'calculate_cashback' ) );
43 add_filter( 'wcpos_payment_gateway_provider', array( $this, 'wcpos_provider' ), 10, 3 );
44 add_filter( 'wcpos_payment_gateway_pos_type', array( $this, 'wcpos_pos_type' ), 10, 3 );
45 add_filter( 'wcpos_payment_gateway_provider_data', array( $this, 'wcpos_provider_data' ), 10, 3 );
46 add_filter( 'wcpos_payment_gateway_bootstrap', array( $this, 'wcpos_bootstrap' ), 10, 4 );
47 add_filter( 'wcpos_process_checkout_action_' . $this->id, array( $this, 'wcpos_process_checkout_action' ), 10, 5 );
48 }
49
50 /**
51 * Display the payment fields in the checkout.
52 */
53 public function payment_fields(): void {
54 if ( $this->description ) {
55 echo '<p>' . wp_kses_post( $this->description ) . '</p>';
56 }
57
58 $currency_pos = get_option( 'woocommerce_currency_pos' );
59
60 if ( 'left' == $currency_pos || 'left_space' == $currency_pos ) {
61 $left_addon = '<span class="input-group-addon">' . get_woocommerce_currency_symbol( get_woocommerce_currency() ) . '</span>';
62 $right_addon = '';
63 } else {
64 $left_addon = '';
65 $right_addon = '<span class="input-group-addon">' . get_woocommerce_currency_symbol( get_woocommerce_currency() ) . '</span>';
66 }
67
68 echo '
69 <div class="form-row " id="pos-cashback_field">
70 <label for="pos-cashback" class="">' . /* translators: POS payment gateway label shown during checkout. */ esc_html__( 'Cashback', 'woocommerce-pos' ) . '</label>
71 <div class="input-group">
72 ' . wp_kses_post( $left_addon ) . '
73 <input type="text" class="form-control" name="pos-cashback" id="pos-cashback" placeholder="" maxlength="20" data-value="0" data-numpad="cash" data-label="' . /* translators: POS payment gateway label shown during checkout. */ esc_attr__( 'Cashback', 'woocommerce-pos' ) . '">
74 ' . wp_kses_post( $right_addon ) . '
75 </div>';
76 wp_nonce_field( 'pos_card_payment_nonce', 'pos_card_payment_nonce_field' );
77 echo '
78 </div>
79 ';
80 }
81
82 /**
83 * Process the payment.
84 *
85 * @param int $order_id Order ID.
86 *
87 * @return array
88 */
89 public function process_payment( $order_id ) {
90 // Check nonce.
91 if ( ! isset( $_POST['pos_card_payment_nonce_field'] ) || ! wp_verify_nonce( sanitize_text_field( wp_unslash( $_POST['pos_card_payment_nonce_field'] ) ), 'pos_card_payment_nonce' ) ) {
92 wp_die( /* translators: Checkout error shown when card nonce validation fails. */ esc_html__( 'Nonce verification failed', 'woocommerce-pos' ) );
93 }
94
95 // get order object.
96 $order = wc_get_order( $order_id );
97
98 $cashback = 0; // Initialize with default value.
99 if ( isset( $_POST['pos-cashback'] ) && ! empty( $_POST['pos-cashback'] ) ) {
100 $cashback = wc_format_decimal( sanitize_text_field( wp_unslash( $_POST['pos-cashback'] ) ) );
101 }
102
103 $result = $this->apply_card_payment( $order, $cashback );
104 if ( is_wp_error( $result ) ) {
105 wc_add_notice( $result->get_error_message(), 'error' );
106
107 return array(
108 'result' => 'failure',
109 'redirect' => '',
110 );
111 }
112
113 // success.
114 return array(
115 'result' => 'success',
116 'redirect' => $this->get_return_url( $order ),
117 );
118 }
119
120 /**
121 * Process a refund.
122 *
123 * Card refunds are handled manually, so just return true.
124 *
125 * @param int $order_id Order ID.
126 * @param float|null $amount Refund amount.
127 * @param string $reason Refund reason.
128 *
129 * @return bool
130 */
131 public function process_refund( $order_id, $amount = null, $reason = '' ) {
132 return true;
133 }
134
135 /**
136 * Calculate and display cashback.
137 *
138 * @param int $order_id Order ID.
139 */
140 public function calculate_cashback( $order_id ): void {
141 $message = '';
142 $order = wc_get_order( $order_id );
143 $cashback = $order->get_meta( '_pos_card_cashback' );
144
145 // construct message.
146 if ( $cashback ) {
147 $message = /* translators: POS payment gateway label shown during checkout. */ __( 'Cashback', 'woocommerce-pos' ) . ': ';
148 $message .= wc_price( $cashback );
149 }
150
151 echo wp_kses_post( $message );
152 }
153
154 /**
155 * POS provider family.
156 *
157 * @param string $provider Provider value.
158 * @param mixed $gateway Gateway object.
159 * @param mixed $request REST request.
160 */
161 public function wcpos_provider( $provider, $gateway, $request = null ) {
162 if ( $gateway instanceof WC_Payment_Gateway && $this->id === $gateway->id ) {
163 return 'wcpos';
164 }
165
166 return $provider;
167 }
168
169 /**
170 * POS type.
171 *
172 * @param string $pos_type POS type.
173 * @param mixed $gateway Gateway object.
174 * @param mixed $request REST request.
175 */
176 public function wcpos_pos_type( $pos_type, $gateway, $request = null ) {
177 if ( $gateway instanceof WC_Payment_Gateway && $this->id === $gateway->id ) {
178 return 'manual';
179 }
180
181 return $pos_type;
182 }
183
184 /**
185 * Non-secret provider data.
186 *
187 * @param array $provider_data Provider data.
188 * @param mixed $gateway Gateway object.
189 * @param mixed $request REST request.
190 */
191 public function wcpos_provider_data( $provider_data, $gateway, $request = null ) {
192 if ( $gateway instanceof WC_Payment_Gateway && $this->id === $gateway->id ) {
193 return array();
194 }
195
196 return $provider_data;
197 }
198
199 /**
200 * Bootstrap response for POS card.
201 *
202 * @param array $response Bootstrap response.
203 * @param string $gateway_id Gateway ID.
204 * @param array $context Bootstrap context.
205 * @param mixed $request REST request.
206 */
207 public function wcpos_bootstrap( $response, $gateway_id, $context = array(), $request = null ) {
208 if ( $this->id === $gateway_id ) {
209 return array(
210 'gateway_id' => $gateway_id,
211 'status' => 'ready',
212 'expires_at' => null,
213 'provider_data' => array(),
214 );
215 }
216
217 return $response;
218 }
219
220 /**
221 * Handle POS checkout contract for card.
222 *
223 * @param array|\WP_Error $state Checkout state.
224 * @param string $action Checkout action.
225 * @param array $payment_data Payment data.
226 * @param \WC_Order $order Order object.
227 * @param mixed $request REST request.
228 */
229 public function wcpos_process_checkout_action( $state, $action, $payment_data, $order, $request = null ) {
230 if ( is_wp_error( $state ) ) {
231 return $state;
232 }
233
234 if ( ( $state['gateway_id'] ?? '' ) !== $this->id ) {
235 return $state;
236 }
237
238 if ( 'cancel' === $action ) {
239 $state['status'] = 'cancelled';
240 return $state;
241 }
242
243 if ( 'start' !== $action ) {
244 return $state;
245 }
246
247 $cashback = isset( $payment_data['cashback_amount'] ) && '' !== $payment_data['cashback_amount']
248 ? wc_format_decimal( $payment_data['cashback_amount'] )
249 : 0;
250
251 $result = $this->apply_card_payment( $order, $cashback );
252 if ( is_wp_error( $result ) ) {
253 return $result;
254 }
255
256 $state['status'] = 'completed';
257 $state['provider_data'] = array(
258 'cashback' => $order->get_meta( '_pos_card_cashback' ),
259 );
260
261 return $state;
262 }
263
264 /**
265 * Apply card payment changes to an order.
266 *
267 * @param \WC_Order $order Order object.
268 * @param float|int|string $cashback Cashback amount.
269 *
270 * @return true|\WP_Error
271 */
272 private function apply_card_payment( $order, $cashback ) {
273 $cashback = wc_format_decimal( $cashback );
274
275 if ( (float) $cashback < 0 ) {
276 return new \WP_Error(
277 'wcpos_invalid_cashback_amount',
278 __( 'Cashback amount must be zero or greater.', 'woocommerce-pos' ),
279 array( 'status' => 400 )
280 );
281 }
282
283 $order->set_payment_method( $this->id );
284 $order->set_payment_method_title( $this->title );
285
286 if ( 0 !== $cashback && '0' !== (string) $cashback ) {
287 $order->update_meta_data( '_pos_card_cashback', $cashback );
288
289 $item_id = wc_add_order_item(
290 $order->get_id(),
291 array(
292 'order_item_name' => /* translators: Fee line-item name for cashback charged on card payment. */ __( 'Cashback', 'woocommerce-pos' ),
293 'order_item_type' => 'fee',
294 )
295 );
296
297 if ( $item_id ) {
298 wc_add_order_item_meta( $item_id, '_line_total', $cashback );
299 wc_add_order_item_meta( $item_id, '_line_tax', 0 );
300 wc_add_order_item_meta( $item_id, '_line_subtotal', $cashback );
301 wc_add_order_item_meta( $item_id, '_line_subtotal_tax', 0 );
302 wc_add_order_item_meta( $item_id, '_tax_class', 'zero-rate' );
303 }
304
305 $order->set_total( wc_format_decimal( \floatval( $order->get_total() ) + \floatval( $cashback ) ) );
306 }
307
308 $order->payment_complete();
309
310 return true;
311 }
312 }
313