PluginProbe
MakeCommerce for WooCommerce / 4.0.0
MakeCommerce for WooCommerce v4.0.0
4.1.0 4.0.8 trunk 1.0 1.0.1 1.0.2 1.0.3 1.1.0 1.1.1 1.1.2 1.1.3 1.1.4 1.1.5 1.1.6 1.1.7 2.0.0 2.1.0 2.1.1 2.1.2 2.1.3 2.1.4 2.1.5 2.2.0 2.2.1 2.2.2 All 96 releases
makecommerce / payment / payment.php

payment.php in MakeCommerce for WooCommerce 4.0.0, at payment/payment.php

399 lines 11.6 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 /**
4 * The payment functionality of the plugin.
5 *
6 * @link https://makecommerce.net/
7 * @since 3.0.0
8 *
9 * @package Makecommerce
10 * @subpackage Makecommerce/admin
11 */
12
13 namespace MakeCommerce;
14
15 use Automattic\WooCommerce\Utilities\OrderUtil;
16 /**
17 * The payment functionality of the plugin.
18 *
19 * Defines the plugin name, version, and two examples hooks for how to
20 * enqueue the admin-specific stylesheet and JavaScript.
21 *
22 * @package Makecommerce
23 * @subpackage Makecommerce/payment
24 * @author Maksekeskus AS <support@maksekeskus.ee>
25 */
26 class Payment {
27
28 /**
29 * The ID of this plugin.
30 *
31 * @since 3.0.0
32 * @access private
33 * @var string $plugin_name The ID of this plugin.
34 */
35 private $plugin_name;
36
37 /**
38 * The version of this plugin.
39 *
40 * @since 3.0.0
41 * @access private
42 * @var string $version The current version of this plugin.
43 */
44 private $version;
45
46 private Loader $loader;
47
48 /**
49 * Initialize the class and set its properties.
50 *
51 * @since 3.0.0
52 * @param string $plugin_name The name of this plugin.
53 * @param string $version The version of this plugin.
54 */
55 public function __construct( $plugin_name, $version, Loader $loader ) {
56
57 $this->plugin_name = $plugin_name;
58 $this->version = $version;
59 $this->loader = $loader;
60
61 $this->loader->add_action( 'plugins_loaded', $this, 'initialize_payment_gateways' );
62 $this->loader->add_action( 'woocommerce_before_checkout_form', $this, 'check_payment_status' );
63 }
64
65 /**
66 * Initialize all payment gateways
67 *
68 * @since 3.0.0
69 */
70 public function initialize_payment_gateways() {
71 //WooCommerce
72 new Payment\Gateway\WooCommerce( true );
73 }
74
75 /**
76 * Returns price excluding taxes
77 *
78 * @since 3.0.0
79 */
80 public static function get_rate_without_taxes( $method, $rate ) {
81
82 if ( empty( $rate[$method] ) ) {
83 return 0;
84 }
85
86 $rate = $rate[$method];
87
88 return $rate->cost;
89 }
90
91 /**
92 * Returns price including taxes
93 *
94 * @since 3.0.0
95 */
96 public static function get_rate_with_taxes( $method, $rate ) {
97
98 if ( empty( $rate[$method] ) ) {
99 return 0;
100 }
101
102 $rate = $rate[$method];
103 $price = $rate->cost;
104
105 if ( empty( $rate->taxes ) ) {
106 return $price;
107 }
108
109 foreach ( $rate->taxes as $tax ) {
110 $price += $tax;
111 }
112
113 return $price;
114 }
115
116 /**
117 * Update banklinks
118 *
119 * @since 3.0.0
120 */
121 public static function update_banklinks() {
122
123 $obj = new Payment\Gateway\WooCommerce( true );
124
125 $obj->mc_banklinks_reload( true );
126
127 }
128
129 /**
130 * Add check for unsuccesful payment redirects
131 * Displays notice if something went wrong
132 *
133 * @since 3.0.12
134 */
135 public function check_payment_status()
136 {
137 if ( isset ( $_GET['mc_payment_status'] ) ) {
138 switch( $_GET['mc_payment_status'] ) {
139 case 'failed':
140 wc_add_notice( __( 'Payment failed', 'wc_makecommerce_domain' ), 'error' );
141 break;
142 case 'cancelled':
143 wc_add_notice( __( 'Payment transaction cancelled', 'wc_makecommerce_domain' ), 'error' );
144 break;
145 case 'expired':
146 wc_add_notice( __( 'Payment transaction expired', 'wc_makecommerce_domain' ), 'error' );
147 break;
148 }
149
150 // Avoid multiple error messages
151 unset($_GET['mc_payment_status']);
152 }
153 }
154
155 /**
156 * Check payment and process order if completed, canceled
157 *
158 * @since 3.0.0
159 */
160 public static function check_payment( $settings = array() ) {
161
162 global $woocommerce;
163
164 $api = \MakeCommerce::get_api();
165
166 //set the correct language
167 if ( isset( $_GET["lang1"] ) ) {
168 \MakeCommerce\i18n::switch_language( $_GET["lang1"] );
169 }
170
171 $returnUrl = home_url();
172
173 $request = stripslashes_deep( $_POST );
174
175 if ( $api->verifyMac( $request ) ) {
176
177 $data = $api->extractRequestData( $request );
178 $transactionId = false;
179 $reference = false;
180
181 if ( !empty( $data['error'] ) ) {
182
183 //add status and send client back to checkout
184 return add_query_arg( 'mc_payment_status', 'failed', wc_get_checkout_url() );
185 }
186
187 if ( !empty( $data['message_type'] ) ) {
188
189 if ( $data['message_type'] === 'payment_return' ) {
190
191 $transactionId = $data['transaction'];
192 $reference = $data['reference'];
193 $paymentStatus = $data['status'];
194 $totalAmount = $data['amount'];
195 }
196
197 if ( $data['message_type'] === 'token_return' ) {
198 if ( !empty( $data['transaction']['reference'] ) ) {
199 $reference = $data['transaction']['reference'];
200 }
201
202 $paymentStatus = $data['transaction']['status'];
203 $transactionId = $data['transaction']['id'];
204 }
205 }
206 }
207
208 // if we didn't find reference to an Order, we send user to shop landing-page. TODO: could be improved
209 if ( empty( $transactionId ) ) {
210 return $returnUrl;
211 }
212
213 //get the post id using transactionid
214 $orderId = self::get_postid_using_metakey( '_makecommerce_transaction_id', $transactionId );
215
216 $order = wc_get_order( $orderId );
217
218 // if we didn't find the Order, we send user to shop landing-page. TODO: could be improved
219 if ( !$order || !$order->get_id() ) {
220 return $returnUrl;
221 }
222
223 $returnUrl = $order->get_meta( '_makecommerce_order_received_url', true );
224 if ( !$returnUrl ) {
225 $returnUrl = $order->get_checkout_order_received_url();
226 }
227
228 // Disregard with subscription method change as amounts do not match (0 vs order total)
229 // Only check sums if $totalAmount is set
230 // Trx total and order total did not match
231 if ( $order->get_status() !== 'active' && isset( $totalAmount ) && $totalAmount != $order->get_total() ) {
232
233 if ( $paymentStatus == 'COMPLETED' ) {
234 $notes[] = sprintf('%s: %s.',
235 __( 'Order total and transaction amount did not match! Please contact us at', 'wc_makecommerce_domain' ),
236 __( 'support@maksekeskus.ee', 'wc_makecommerce_domain' )
237 );
238 $notes[] = sprintf('%s: %s.',
239 __( 'Transaction ID that was assigned to this order', 'wc_makecommerce_domain' ),
240 '<a target=_blank href="'.$api->getEnvUrls()->merchantUrl.'merchant/shop/deals/detail.html?id='. $transactionId .'">'.$transactionId.'</a>'
241 );
242 $notes[] = sprintf('%s: %s€',
243 __( 'Amount that was paid', 'wc_makecommerce_domain' ),
244 $totalAmount
245 );
246
247 $order->add_order_note( implode( "\r\n", $notes ) );
248
249 // Empty the cart so the customer is not tempted to pay again
250 $woocommerce->cart->empty_cart();
251
252 return $returnUrl;
253 }
254
255 // If the payment was not complete then send the customer back to checkout
256 return wc_get_checkout_url();
257 }
258
259 if ( $paymentStatus == 'EXPIRED' || $paymentStatus == 'CANCELLED' || $paymentStatus == 'COMPLETED' ) {
260
261 //get transaction to update the payment method.
262 $transaction = $api->getTransaction( $transactionId );
263
264 //make sure the payment method is the same for simplecheckout and normal version.
265 $paymentMethod = "";
266 if ( isset( $transaction->type ) && isset( $transaction->method ) ) {
267 $paymentMethod = $transaction->channel;
268 }
269
270 //update _makecommerce_preselected_method
271 $order->update_meta_data( '_makecommerce_preselected_method', $paymentMethod );
272 $order->save();
273 }
274
275 if ( $paymentStatus == 'CANCELLED' || ( $paymentStatus == 'EXPIRED' && $order->get_status() == "pending" ) ) {
276 //send client back to checkout
277 $returnUrl = wc_get_checkout_url();
278 }
279
280 // Avoid duplicate method changes for subscriptions
281 $check_status = true;
282
283 if ( !empty( $data['token']['id'] ) && !empty( $data['token']['multiuse'] ) ) {
284 // Order is a subscription and saved token is different from response token
285 if ( $order->get_meta( '_makecommerce_payment_token', true) !== $data['token']['id'] ) {
286 $check_status = false;
287 }
288 }
289
290 //check if we already processed this status in the past.
291 if ( $check_status && $order->get_meta( '_makecommerce_payment_processed_status', true ) == $paymentStatus ) {
292 return $returnUrl;
293 }
294
295 if ( $paymentStatus === 'COMPLETED' ) {
296 $order->update_meta_data( '_makecommerce_payment_processed_status', $paymentStatus );
297 $order->save();
298 }
299
300 switch( $paymentStatus ) {
301
302 case 'CANCELLED':
303 // Do not update status when disabled in settings
304 if ( ( $settings['disable_cancelled_payment_update'] ?? '' ) !== 'yes' ) {
305 // Update automatically
306 $order->update_status( 'cancelled' );
307 $order->update_meta_data( '_makecommerce_payment_processed_status', $paymentStatus );
308 }
309
310 $returnUrl = add_query_arg( 'mc_payment_status', 'cancelled', $returnUrl );
311
312 break;
313 case 'EXPIRED':
314 //only update if order status is pending payment
315 if ( $order->get_status() == "pending" ) {
316
317 // Do not update order status if disabled in settings
318 if ( ( $settings['disable_expired_payment_update'] ?? '' ) !== 'yes' ) {
319 // Update automatically
320 $order->update_status( 'cancelled' );
321 $order->update_meta_data( '_makecommerce_payment_processed_status', $paymentStatus );
322 }
323
324 $returnUrl = add_query_arg( 'mc_payment_status', 'expired', $returnUrl );
325 }
326
327 break;
328 case 'COMPLETED':
329 $orderNote = array();
330 $transactionIdText = __( 'Transaction ID', 'wc_makecommerce_domain' );
331 $paymentOptionText = __( 'Payment option', 'wc_makecommerce_domain' );
332 $transactionIdText = \MakeCommerce\i18n::get_string_from_mo( 'Transaction ID', 'wc_makecommerce_domain', \MakeCommerce\i18n::get_site_default_language() );
333 $paymentOptionText = \MakeCommerce\i18n::get_string_from_mo( 'Payment option', 'wc_makecommerce_domain', \MakeCommerce\i18n::get_site_default_language() );
334
335 $orderNote[] = $transactionIdText . ': <a target=_blank href="'.$api->getEnvUrls()->merchantUrl.'merchant/shop/deals/detail.html?id='. $transactionId .'">'.$transactionId.'</a>';
336 $orderNote[] = $paymentOptionText . ': ' . $order->get_meta( '_makecommerce_preselected_method', true );
337 $order->add_order_note( implode( "\r\n", $orderNote ) );
338
339 if ( !empty( $data['token'] ) && !empty( $data['token']['multiuse'] ) ) {
340 $order->update_meta_data( '_makecommerce_payment_token', $data['token']['id'] );
341 $order->update_meta_data( '_makecommerce_payment_token_valid_until', $data['token']['valid_until'] );
342 }
343
344 if ( isset( $_GET['lang1'] ) ) {
345 $order->update_meta_data( 'wpml_language', $_GET["lang1"] );
346 }
347
348 $order->payment_complete( $transactionId );
349 $woocommerce->cart->empty_cart();
350
351 break;
352 }
353
354 // Save all changes to order
355 $order->save();
356
357 return $returnUrl;
358 }
359
360 /**
361 * Returns post_id using transaction id or false if not found
362 *
363 * @since 3.0.4
364 */
365 public static function get_postid_using_metakey( $meta_key, $transactionId ) {
366 global $wpdb;
367
368 if ( class_exists( OrderUtil::class )
369 && OrderUtil::custom_orders_table_usage_is_enabled()
370 ) {
371 // HPOS
372 $results = $wpdb->get_results(
373 $wpdb->prepare("
374 SELECT {$wpdb->prefix}wc_orders.id
375 FROM {$wpdb->prefix}wc_orders
376 INNER JOIN {$wpdb->prefix}wc_orders_meta AS meta ON meta.order_id = {$wpdb->prefix}wc_orders.id AND meta.meta_key = %s
377 WHERE meta.meta_value = %s
378 ",
379 $meta_key,
380 $transactionId
381 )
382 );
383
384 if ( isset( $results[0]->id ) ) {
385 return $results[0]->id;
386 }
387 } else {
388 // Legacy DB
389 $wpdb->query("SELECT `post_id` FROM $wpdb->postmeta WHERE `meta_key` = '". $meta_key ."' AND `meta_value` = '" . $transactionId . "'");
390
391 if ( isset( $wpdb->last_result[0]->post_id ) ) {
392 return $wpdb->last_result[0]->post_id;
393 }
394 }
395
396 return false;
397 }
398 }
399