PluginProbe
HyperPay Payments / 1.7
HyperPay Payments v1.7
6.6.0 trunk 1.7 1.8 1.8.1 1.8.2 1.8.3 1.8.4 1.8.5 1.9.5 1.9.6 1.9.7 1.9.8 1.9.9 2.0.0 2.1.0 2.2.0 2.3.0 2.3.1 2.3.2 2.3.3 3.0.0 3.0.5 4.0.0 4.0.2 All 34 releases
hyperpay-gateways / includes / Hyperpay_main_class.php

Hyperpay_main_class.php in HyperPay Payments 1.7, at includes/Hyperpay_main_class.php

917 lines 31.8 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 /**
4 * HayperPay main class created to extends from it
5 * when create a new paymentsgateways
6 *
7 */
8 class Hyperpay_main_class extends WC_Payment_Gateway
9 {
10
11 /**
12 * if payments have direct fields on ckeckout page
13 *
14 * @var boolean
15 */
16 public $has_fields = false;
17 protected $loader;
18 public $invoice_id;
19
20 /**
21 * check if user sigined in or not
22 *
23 * @var boolean
24 */
25 protected $is_registered_user = false;
26
27 /**
28 * Mada BlackBins
29 *
30 * @var array
31 */
32 protected $blackBins = [];
33
34 /**
35 * supported brands thats will showing on settings and checkout page
36 *
37 * @var array
38 */
39 protected $supported_brands = [];
40
41
42 /**
43 * CopyAndPay script URL
44 *
45 * @var string
46 */
47 protected $script_url = "https://oppwa.com/v1/paymentWidgets.js?checkoutId=";
48
49 /**
50 * CopyAndPay prepare checkout link
51 *
52 * @method POST
53 * @var string
54 */
55 protected $token_url = "https://oppwa.com/v1/checkouts";
56
57 /**
58 * get transaction status
59 * @method GET
60 * @var string
61 *
62 * ##TOKEN## will replace with transaction id when fire the request
63 */
64 protected $transaction_status_url = "https://oppwa.com/v1/checkouts/##TOKEN##/payment";
65
66 /**
67 * Query transaction report
68 *
69 * @method GET
70 * @var string
71 */
72 protected $query_url = "https://oppwa.com/v1/query";
73
74
75 /**
76 * payment styles that will show in settings
77 *
78 * @var array
79 *
80 */
81 protected $hyperpay_payment_style = [
82 'card' => 'Card',
83 'plain' => 'Plain'
84 ];
85
86 protected $dataTosend = [];
87
88
89 function __construct()
90 {
91
92 $this->init_settings(); // <== to get saved settings from database
93 $this->init_form_fields(); // <== render form inside admin panel
94 $this->is_arabic = substr(get_locale(), 0, 2) == 'ar'; // <== to get current locale
95
96 $this->testmode = $this->get_option('testmode'); // <== check if payments on test mode
97 $this->title = $this->get_option('title'); // <== get title from setting
98 $this->trans_type = $this->get_option('trans_type'); // <== get transaction type [DB / Pre-Auth] from setting
99 $this->trans_mode = $this->get_option('trans_mode'); // <== get transaction mode [INTERNAL / EXTERNAL / LIVE] from setting
100 $this->accesstoken = $this->get_option('accesstoken'); // <== get accesstoke from setting
101 $this->entityid = $this->get_option('entityId'); // <== get entityId from setting
102 $this->brands = is_array($this->get_option('brands')) ? $this->get_option('brands') : [$this->get_option('brands')]; // <== get brands from setting
103
104 $this->payment_style = $this->get_option('payment_style'); // <== get style from setting
105 $this->mailerrors = $this->get_option('mailerrors'); // <== get if mail error check or not from setting
106 $this->order_status = $this->get_option('order_status'); // <== get order status after success from setting
107 $this->tokenization = $this->get_option('tokenization'); // <== get tokenization from setting if enabled store user ditails in DB
108 $this->redirect_page_id = $this->get_option('redirect_page_id'); // <== after order complete redirect to selected page
109 $this->custom_style = $this->get_option('custom_style'); // <== get custom style from setting
110
111 /**
112 * if test mode is one
113 * overwrite currents URLs ti test URLs
114 */
115 if ($this->testmode) {
116 $this->query_url = "https://test.oppwa.com/v1/query";
117 $this->token_url = "https://test.oppwa.com/v1/checkouts";
118 $this->script_url = "https://test.oppwa.com/v1/paymentWidgets.js?checkoutId=";
119 $this->transaction_status_url = "https://test.oppwa.com/v1/checkouts/##TOKEN##/payment";
120 }
121
122 $this->query_url .= "?entityId=" . $this->entityid;
123 $this->transaction_status_url .= "?entityId=" . $this->entityid;
124
125 /**
126 * default faild message
127 * @var string
128 */
129 $this->failed_message = __('Your transaction has been declined.', 'hyperpay-payments');
130 $this->success_message = __('Your payment has been processed successfully.', 'hyperpay-payments');
131
132 /**
133 * overwrite default update function
134 *
135 * @param woocommerce_update_options_payment_gateways_<payment_id>
136 * @param array[class,function_name]
137 */
138
139 add_action('woocommerce_update_options_payment_gateways_' . $this->id, array(&$this, 'process_admin_options'));
140
141 /**
142 * prepare checkout form
143 *
144 * @param string woocommerce_receipt_<payments_id>
145 * @param array[class,function_name]
146 */
147
148 add_action("woocommerce_receipt_{$this->id}", [$this, 'receipt_page']);
149
150 /**
151 * set payments icon from assets/images/BRAND-log.png
152 *
153 * make sure when add new image to rename image accorden this format BRAND_NAME-logo.png
154 *
155 * @param string woocommerce_gateway_icon
156 * @param array[class,function_name]
157 *
158 */
159 add_filter('woocommerce_gateway_icon', [$this, 'set_icons'], 10, 2);
160
161 /**
162 * to include assets/js/admin.js <JavaScript>
163 *
164 * @param string admin_enqueue_scripts
165 * @param array[class,function_name]
166 *
167 */
168 add_action('admin_enqueue_scripts', [$this, 'admin_script']);
169 }
170
171
172
173 /**
174 * for validate settings form
175 * @return void
176 */
177
178 public function admin_script(): void
179 {
180 global $current_tab, $current_section;
181
182 /**
183 * to make sure load admin.js just when currents pyments opened
184 *
185 */
186 if ($current_tab == 'checkout' && $current_section == $this->id) {
187
188 $data = [
189 'id' => $this->id,
190 'url' => $this->token_url,
191 'code_setting' => wp_enqueue_code_editor(['type' => 'text/css'])
192 ];
193
194 wp_enqueue_script('hyperpay_admin', HYPERPAY_PLUGIN_DIR . '/assets/js/admin.js', ['jquery'], false, true);
195 wp_localize_script('hyperpay_admin', 'data', $data);
196 }
197 }
198
199
200 /**
201 * to set payment icon based on supported brands
202 *
203 * @param string $icon
204 * @param string $id currnet payment id
205 *
206 * @return string $icon new icon
207 *
208 */
209
210 public function set_icons($icon, $id): string
211 {
212
213 if ($id == $this->id) {
214 $icons = "";
215 foreach ($this->brands as $brand) {
216 $img = HYPERPAY_PLUGIN_DIR . '/assets/images/default.png';
217
218 if (file_exists(HYPERPAY_ABSPATH . '/assets/images/' . esc_attr($brand) . "-logo.png"))
219 $img = HYPERPAY_PLUGIN_DIR . '/assets/images/' . esc_attr($brand) . "-logo.png";
220
221 $icons .= "<img style='padding:2px' src='$img' >";
222 }
223 return $icons;
224 }
225 return $icon;
226 }
227
228 /**
229 * Here you can define all fiels thats will showning in setting page
230 * @return void
231 */
232 public function init_form_fields(): void
233 {
234
235 $this->form_fields = [
236 'enabled' => [
237 'title' => __('Enable/Disable', 'hyperpay-payments'),
238 'type' => 'checkbox',
239 'label' => __('Enable Payment Module.', 'hyperpay-payments'),
240 'default' => 'no'
241 ],
242 'testmode' => [
243 'title' => __('Test mode', 'hyperpay-payments'),
244 'type' => 'select',
245 'options' => ['0' => __('Off', 'hyperpay-payments'), '1' => __('On', 'hyperpay-payments')]
246 ],
247 'title' => [
248 'title' => __('Title:', 'hyperpay-payments'),
249 'type' => 'text',
250 'description' => ' ' . __('This controls the title which the user sees during checkout.', 'hyperpay-payments'),
251 'default' => $this->method_title ?? __('Credit Card', 'hyperpay-payments')
252 ],
253 'trans_type' => [
254 'title' => __('Transaction type', 'hyperpay-payments'),
255 'type' => 'select',
256 'options' => $this->get_hyperpay_trans_type(),
257 ],
258 'trans_mode' => array(
259 'title' => __('Transaction mode', 'hyperpay-payments'),
260 'type' => 'select',
261 'options' => $this->get_hyperpay_trans_mode(),
262 'description' => ''
263 ),
264 'accesstoken' => [
265 'title' => __('Access Token', 'hyperpay-payments'),
266 'type' => 'text',
267 ],
268 'entityId' => [
269 'title' => __('Entity ID', 'hyperpay-payments'),
270 'type' => 'text',
271 ],
272 'tokenization' => [
273 'title' => __('Tokenization', 'hyperpay-payments'),
274 'type' => 'select',
275 'options' => $this->get_hyperpay_tokenization(),
276 ],
277 'brands' => [
278 'title' => __('Brands', 'hyperpay-payments'),
279 'class' => count($this->supported_brands) !== 1 ?: 'disabled',
280 'type' => count($this->supported_brands) > 1 ? 'multiselect' : 'select',
281 'options' => $this->supported_brands,
282 ],
283 'payment_style' => [
284 'title' => __('Payment Style', 'hyperpay-payments'),
285 'type' => 'select',
286 'class' => count($this->hyperpay_payment_style) !== 1 ?: 'disabled',
287 'options' => $this->hyperpay_payment_style,
288 'default' => 'plain'
289 ],
290 'custom_style' => [
291 'title' => __('Custom Style', 'hyperpay-payments'),
292 'type' => 'textarea',
293 'description' => 'Input custom css for payment (Optional)',
294 'class' => 'hyperpay_custom_style'
295 ],
296 'mailerrors' => [
297 'title' => __('Enable error logging by email?', 'hyperpay-payments'),
298 'type' => 'checkbox',
299 'label' => __('Yes'),
300 'default' => 'no',
301 'description' => __('If checked, an email will be sent to ' . get_bloginfo('admin_email') . ' whenever a callback fails.'),
302 ],
303 'redirect_page_id' => [
304 'title' => __('Return Page', 'hyperpay-payments'),
305 'type' => 'select',
306 'options' => $this->get_pages('Select Page'),
307 'description' => __("success page", 'hyperpay-payments')
308 ],
309 'order_status' => [
310 'title' => __('Status Of Order', 'hyperpay-payments'),
311 'type' => 'select',
312 'options' => $this->get_order_status(),
313 'description' => __("select order status after success transaction.", 'hyperpay-payments')
314 ]
315 ];
316 }
317
318
319 /**
320 * to fill order_status select fiels
321 *
322 * @return array
323 */
324 function get_order_status(): array
325 {
326 $order_status = [
327
328 'processing' => __('Processing', 'hyperpay-payments'),
329 'completed' => __('Completed', 'hyperpay-payments')
330 ];
331
332 return $order_status;
333 }
334
335 /**
336 * to fill tokenization select fiels
337 *
338 * @return array
339 */
340 function get_hyperpay_tokenization(): array
341 {
342 $hyperpay_tokenization = [
343 'enable' => __('Enable', 'hyperpay-payments'),
344 'disable' => __('Disable', 'hyperpay-payments')
345 ];
346
347 return $hyperpay_tokenization;
348 }
349
350 /**
351 * to fill trans_type select fiels
352 *
353 * @return array
354 */
355 function get_hyperpay_trans_type(): array
356 {
357 $hyperpay_trans_type = [
358 'DB' => 'Debit',
359 'PA' => 'Pre-Authorization'
360 ];
361
362 return $hyperpay_trans_type;
363 }
364
365 /**
366 * to fill trans_mode select fiels
367 *
368 * @return array
369 */
370 function get_hyperpay_trans_mode(): array
371 {
372 $hyperpay_trans_type = [
373 'INTERNAL' => 'Internal',
374 'EXTERNAL' => 'External',
375 'LIVE' => 'Live'
376 ];
377
378
379 return $hyperpay_trans_type;
380 }
381
382 /**
383 * This function fire when click on Place order at checkout page
384 * @param int $order_id
385 *
386 * @return void
387 */
388 function receipt_page($order_id): void
389 {
390
391 global $woocommerce;
392 $error_code = '';
393 $error = false;
394 $order = new WC_Order($order_id);
395 // new transaction contain g2p_token
396 if (isset($_GET['g2p_token'])) {
397 $token = sanitize_text_field($_GET['g2p_token']);
398 $this->renderPaymentForm($order, $token);
399 }
400
401 // old transaction contain id
402 if (isset($_GET['id'])) {
403 $token = sanitize_text_field($_GET['id']);
404 $error_code = '';
405 $error_description = '';
406 $url = str_replace('##TOKEN##', $token, $this->transaction_status_url);
407 // set header request to contain access token
408 $auth = [
409 'headers' => ['Authorization' => 'Bearer ' . $this->accesstoken]
410 ];
411 $response = wp_remote_get($url, $auth);
412 $resultJson = wp_remote_retrieve_body($response);
413 $resultJson = json_decode($resultJson, true);
414
415 if (isset($resultJson['result']['code'])) {
416 // check if transaction faild and the reason if mada card or not
417 $mada = $this->check_mada($resultJson);
418 $success = $mada['status'];
419 $failed_msg = $mada['msg'];
420 $orderid = $resultJson['merchantTransactionId'] ?? '';
421 $order = new WC_Order($orderid);
422 if ($order) {
423 if ($success) {
424 WC()->session->set('hp_payment_retry', 0);
425 if ($order->status != 'completed') {
426 $order->update_status($this->order_status);
427 $woocommerce->cart->empty_cart();
428 $uniqueId = $resultJson['id'];
429 /**
430 * update or create user data
431 */
432 if (isset($resultJson['registrationId'])) {
433 $registrationID = $resultJson['registrationId'];
434 $customerID = $order->get_customer_id();
435 global $wpdb;
436 $registrationIDs = $wpdb->get_results(
437 $wpdb->prepare(
438 "SELECT * FROM {$wpdb->prefix}woocommerce_saving_cards
439 WHERE registration_id = %s
440 and mode = %d",
441 $registrationID,
442 $this->testmode
443 )
444 );
445
446 if (count($registrationIDs) == 0) {
447
448 $wpdb->insert(
449 "{$wpdb->prefix}woocommerce_saving_cards",
450 [
451 'customer_id' => $customerID,
452 'registration_id' => $registrationID,
453 'mode' => $this->testmode,
454 ]
455 );
456 }
457 }
458 $order->add_order_note($this->success_message . __('Transaction ID: ', 'hyperpay-payments') . esc_html($uniqueId));
459 if (array_key_exists('invoice_id', $resultJson['resultDetails'])) {
460 $this->invoice_id = $resultJson['resultDetails']['invoice_id'];
461 $order->add_order_note($this->invoice_id, 1);
462 }
463 }
464 wp_redirect($this->get_return_url($order));
465 } else {
466 $error = true;
467 }
468 } else {
469 $error = true;
470 }
471 $error_code = $resultJson['result']['code'];
472 $error_description = $resultJson['result']['description'];
473 $resultDetails = [['error' => $failed_msg ? $error_description : 'configration error']];
474
475 /**
476 * get extended description
477 */
478 if (isset($resultJson['resultDetails']['ExtendedDescription'])) {
479 $resultDetails = $resultJson['resultDetails']['ExtendedDescription'];
480 if ($this->isJson($resultDetails)) {
481 $resultDetails = json_decode($resultDetails, true);
482 if (array_key_exists('details', $resultDetails)) {
483 $resultDetails = $resultDetails['details'];
484 }
485 }
486 }
487 } else {
488 $error = true;
489 }
490 if ($error)
491 $this->process_faild_payment($order, $error_code, $failed_msg, $error_description, $resultDetails);
492 }
493 }
494
495 private function isJson($string)
496 {
497 json_decode($string);
498 return json_last_error() === JSON_ERROR_NONE;
499 }
500
501 /**
502 *
503 * render CopyAndPay form
504 * @param WC_Order $order
505 * @param string $token
506 * @return void
507 */
508 private function renderPaymentForm(WC_Order $order, string $token): void
509 {
510
511 $scriptURL = $this->script_url;
512 $scriptURL .= $token;
513
514 $payment_brands = $this->brands;
515 if (is_array($this->brands))
516 $payment_brands = implode(' ', $this->brands);
517
518 $postbackURL = $order->get_checkout_payment_url(true);
519
520 if (parse_url($postbackURL, PHP_URL_QUERY)) {
521 $postbackURL .= '&';
522 } else {
523 $postbackURL .= '?';
524 }
525 $postbackURL .= 'hpOrderId=' . $order->get_id();
526
527 $dataObj = [
528 'is_arabic' => esc_js($this->is_arabic),
529 'style' => esc_js($this->payment_style),
530 'tokenization' => esc_js($this->tokenization),
531 'postbackURL' => esc_url($postbackURL),
532 'payment_brands' => esc_js($payment_brands)
533 ];
534
535
536 // include CopyAndPay script to show the form
537 wp_enqueue_script('wpwl_hyperpay_script', $scriptURL, null, null);
538
539 // include assests\js\script.js to set wpwlOptions
540 wp_enqueue_script('hyperpay_script', HYPERPAY_PLUGIN_DIR . '/assets/js/script.js', ['jquery'], false, true);
541
542 // pass data to assests\js\script.js
543 wp_localize_script('hyperpay_script', 'dataObj', $dataObj);
544
545 // apply custom style that's entered on setting page <custom_style>
546 ;
547
548 wp_register_style( 'hyperpay-inline', false ); // phpcs:ignore
549 wp_enqueue_style( 'hyperpay-inline' );
550 wp_add_inline_style( 'hyperpay-inline', $this->custom_style );
551
552 if($this->id == 'hyperpay_mada'){
553 wp_enqueue_style('hyperpay_mada_style', HYPERPAY_PLUGIN_DIR . '/assets/css/mada.css');
554 }
555 }
556
557
558 /**
559 * Process the payment and return the result
560 * @param int $order_id
561 * @return array[redirect,token,result]
562 *
563 */
564 public function process_payment($order_id): array
565 {
566 global $woocommerce;
567 $order = new WC_Order($order_id);
568 $customerID = $order->get_customer_id();
569
570 if ($customerID > 0 && get_current_user_id() == $customerID) {
571 //Registered
572 $this->is_registered_user = true;
573 } else {
574 //Guest
575 $this->is_registered_user = false;
576 }
577
578
579 $shipping_cost = number_format($order->get_shipping_total(), 2, '.', '');
580
581 $orderAmount = number_format($order->get_total(), 2, '.', '');
582 $amount = number_format(round($orderAmount, 2), 2, '.', '');
583
584 $currency = get_woocommerce_currency();
585 $firstName = $order->get_billing_first_name();
586 $family = $order->get_billing_last_name();
587 $street = $order->get_billing_address_1();
588 $zip = $order->get_billing_postcode();
589 $city = $order->get_billing_city();
590 $state = $order->get_billing_state();
591 $country = $order->get_billing_country();
592 $email = $order->get_billing_email();
593
594 $firstName = preg_replace('/\s/', '', str_replace("&", "", $firstName));
595 $family = preg_replace('/\s/', '', str_replace("&", "", $family));
596 $street = preg_replace('/\s/', '', str_replace("&", "", $street));
597 $city = preg_replace('/\s/', '', str_replace("&", "", $city));
598 $state = preg_replace('/\s/', '', str_replace("&", "", $state));
599 $country = preg_replace('/\s/', '', str_replace("&", "", $country));
600
601 if (empty($state)) {
602 $state = $city;
603 }
604
605 // set data to post
606 $url = $this->token_url;
607 $data = [
608 'headers' => [
609 "Authorization" => "Bearer {$this->accesstoken}"
610 ],
611 'body' => [
612 "entityId" => $this->entityid,
613 "amount" => $amount,
614 "currency" => $currency,
615 "paymentType" => $this->trans_type,
616 "merchantTransactionId" => $order_id,
617 "customer.email" => $email,
618 "notificationUrl" => $order->get_checkout_payment_url(true),
619 "customParameters[bill_number]" => $order_id,
620 "customer.givenName" => $firstName,
621 "customer.surname" => $family,
622 "billing.street1" => $street,
623 "billing.city" => $city,
624 "billing.state" => $state,
625 "billing.country" => $country,
626 "billing.postcode" => $zip,
627 "shipping.postcode" => $zip,
628 "shipping.street1" => $street,
629 "shipping.city" => $city,
630 "shipping.state" => $state,
631 "shipping.country" => $country,
632 "shipping.cost" => $shipping_cost,
633 "customParameters[branch_id]" => '1',
634 "customParameters[teller_id]" => '1',
635 "customParameters[device_id]" => '1',
636 ]
637 ];
638
639
640 if ($this->testmode) {
641 $data['body']["testMode"] = $this->trans_mode;
642 }
643
644 $data_to_validate = [
645 'first name' => $firstName,
646 'last name' => $family,
647 'street' => $street,
648 'city' => $city,
649 'state' => $state,
650 'email' => $email
651 ];
652
653 /**
654 *
655 * validate data to prevent arabic character
656 */
657 $this->validate_form($data_to_validate);
658
659
660 if ($this->tokenization == 'enable' && $this->is_registered_user == true) {
661
662 global $wpdb;
663
664 $data["createRegistration"] = "true";
665
666 $registrationIDs = $wpdb->get_results(
667 $wpdb->prepare(
668 "SELECT * FROM {$wpdb->prefix}woocommerce_saving_cards WHERE customer_id = %s and mode = %d" , $customerID , $this->testmode
669 )
670 );
671
672 if ($registrationIDs) {
673
674 foreach ($registrationIDs as $key => $id) {
675 $data["registrations[$key].id"] = $id->registration_id;
676 }
677 }
678 }
679
680 // add extra parameters if exists
681 $data = array_merge_recursive($data, $this->setExtraData($order));
682
683 // HTTP Request to oppwa to get checkout id
684 $response = wp_remote_post($url, $data);
685
686
687 if (is_wp_error($response) || wp_remote_retrieve_response_code($response) != 200) {
688 $description = json_decode(wp_remote_retrieve_body($response), true)['result']['description'];
689 wc_add_notice(__("Problem with payments :$description", 'hyperpay-payments'), 'error');
690 throw new \Exception();
691 }
692
693 $response = wp_remote_retrieve_body($response);
694
695 $result = json_decode($response, true);
696
697 if (array_key_exists('id', $result)) {
698 $token = $result['id'];
699 }
700
701
702
703 // add g2p_token to url query
704 return [
705 'result' => 'success',
706 'token' => $token ?? null,
707 'redirect' => add_query_arg('g2p_token', $token, $order->get_checkout_payment_url(true))
708 ];
709 }
710
711 /**
712 * to get all pages of website to fill <redirect to> option in admin setting
713 *
714 * @param bool
715 * @param bool
716 * @return array
717 *
718 */
719 function get_pages(bool $title = false, bool $indent = true): array
720 {
721 $wp_pages = get_pages('sort_column=menu_order');
722 $page_list = [];
723
724 if ($title)
725 $page_list[] = $title;
726
727 foreach ($wp_pages as $page) {
728 $prefix = '';
729 // show indented child pages?
730 if ($indent) {
731 $has_parent = $page->post_parent;
732 while ($has_parent) {
733 $prefix .= ' - ';
734 $next_page = get_page($has_parent);
735 $has_parent = $next_page->post_parent;
736 }
737 }
738 // add to page list array array
739 $page_list[$page->ID] = $prefix . $page->post_title;
740 }
741
742 return $page_list;
743 }
744
745 /**
746 * check if all data valid to post {English Charachter}
747 * @param array
748 * @return void
749 */
750 function validate_form(array $data): void
751 {
752 $errors = [];
753
754
755 foreach ($data as $key => $field) {
756 if (!preg_match("/^[a-zA-Z0-9-._!`'#%&,:;<>=@{}~\$\(\)\*\+\/\\\?\[\]\^\| +]+$/", $field) || strlen($field) < 3)
757 $errors[$key] = $key . ' ' . __('format error', 'hyperpay-payments');
758 }
759
760 if (!preg_match('/^[_a-z0-9-]+(\.[_a-z0-9-]+)*@[a-z0-9-]{4,}+(\.[a-z0-9-])*(\.[a-z]{3,})$/', $data['email'])) {
761 $errors['email'] = __('Email format not valid', 'hyperpay-payments');
762 }
763
764
765 if ($errors) {
766 foreach ($errors as $msg) {
767 wc_add_notice('<strong>*' . $msg . '</strong>', 'error');
768 }
769 throw new Exception();
770 }
771 }
772
773 /**
774 *
775 * GET request to transaction report to check if transaction exists or not
776 * @param int
777 * @return array $response
778 *
779 */
780 public function queryTransactionReport(string $merchantTrxId): array
781 {
782
783 $url = $this->query_url . "&merchantTransactionId=$merchantTrxId";
784 $response = wp_remote_get($url, ["headers" => ["Authorization" => "Bearer {$this->accesstoken}"]]);
785
786 $response = wp_remote_retrieve_body($response);
787 $response = json_decode($response, true);
788
789 return $response;
790 }
791
792
793
794 /**
795 *
796 * check if the reason of rejection was mada card
797 *
798 * @param array $resultJson
799 * @return array[status,msg]
800 */
801 public function check_mada(array $resultJson): array
802 {
803
804 $success = false;
805 $failed_msg = '';
806
807 $successCodePattern = '/^(000\.000\.|000\.100\.1|000\.[36])/';
808 $successManualReviewCodePattern = '/^(000\.400\.0|000\.400\.100)/';
809 //success status
810 if (
811 preg_match($successCodePattern, $resultJson['result']['code']) ||
812 preg_match($successManualReviewCodePattern, $resultJson['result']['code']) ||
813 $resultJson['result']['code'] == '800.400.500' // success code for Aman
814 ) {
815 $success = 1;
816 } else {
817 //fail case
818
819 if (isset($resultJson['card']['bin']) && $resultJson['result']['code'] == '800.300.401') {
820 $searchBin = $resultJson['card']['bin'];
821 if (in_array($searchBin, $this->blackBins)) {
822 $failed_msg = __('Sorry! Please select "mada" payment option in order to be able to complete your purchase successfully.', 'hyperpay-payments');
823 }
824 }
825 }
826
827
828 return [
829 'status' => $success,
830 'msg' => $failed_msg
831 ];
832 }
833
834
835 /**
836 * handel faild pyments
837 * @param WC_Order $order
838 * @param string $messege
839 * @return void
840 */
841 public function process_faild_payment(WC_Order $order, string $error_code, string $msg, string $description, $resultDetails): void
842 {
843
844 if ( isset($_GET['hpOrderId'])) {
845 $hpOrderId = sanitize_text_field($_GET['hpOrderId']);
846 $queryResponse = $this->queryTransactionReport($hpOrderId);
847
848 if (array_key_exists('payments', $queryResponse)) {
849
850 $this->processQueryResult($queryResponse, $order);
851 }
852 }
853
854
855 $order->add_order_note("{$this->failed_message} $error_code : $description");
856 wc_add_notice(__('Your transaction has been declined.', 'hyperpay-payments') . "<br>" . esc_html($msg), 'error');
857
858 if (is_array($resultDetails)) {
859 foreach ($resultDetails as $error) {
860 $order->add_order_note("extended description : " . ($error['error'] ?? $resultDetails['message']));
861 wc_add_notice($error['error'] ?? $resultDetails['message'], 'error');
862 }
863 } else {
864 $order->add_order_note("extended description : $resultDetails");
865 wc_add_notice($resultDetails, 'error');
866 }
867
868 $order->update_status('cancelled');
869 wc_print_notices();
870 }
871
872 /**
873 * check the result of transaction if success of faild
874 *
875 * @param array $resultJson
876 * @param WC_Order $order
877 * @return void
878 */
879 public function processQueryResult(array $resultJson, WC_Order $order): void
880 {
881 global $woocommerce;
882 $success = 0;
883
884 $payment = end($resultJson['payments']); // get the last transaction
885
886 if (isset($payment['result']['code'])) {
887 $result = $this->check_mada($payment);
888 $success = $result['status'];
889
890 if ($success) {
891 if ($order->status != 'completed') {
892 $order->update_status($this->order_status);
893 $woocommerce->cart->empty_cart();
894 $uniqueId = $payment['id'];
895 $order->add_order_note($this->success_message . __('Transaction ID: ', 'hyperpay-payments') . esc_html($uniqueId));
896
897 if (array_key_exists('invoice_id', $payment['resultDetails'])) {
898 $this->invoice_id = $payment['resultDetails']['invoice_id'];
899 $order->add_order_note($this->invoice_id, 1);
900 }
901 wp_redirect($this->get_return_url($order));
902 }
903 }
904 }
905 }
906
907 /**
908 * set customParameters of requested data
909 * @param WC_Order $order
910 * @return array
911 */
912 public function setExtraData(WC_Order $order): array
913 {
914 return [];
915 }
916 }
917