· 5 years ago · Jul 27, 2020, 05:16 AM
1<?php
2
3/**
4 * Qlicknpay Payment Gateway Class
5 */
6class Qlicknpay extends WC_Payment_Gateway {
7 function __construct() {
8 $this->id = "Qlicknpay";
9
10 $this->method_title = __( "QlicknPay", 'Qlicknpay' );
11
12 $this->method_description = __( "QlicknPay Payment Gateway Plug-in for WooCommerce", 'Qlicknpay' );
13
14 $this->title = __( "QlicknPay - Pay with internet banking (FPX) or credit / debit cards", 'Qlicknpay' );
15
16 // $this->icon = 'https://www.Qlicknpay.com/merchant/assets/images/pdtlogonew.png';
17
18 $this->has_fields = true;
19
20 $this->init_form_fields();
21
22 $this->init_settings();
23
24 foreach ( $this->settings as $setting_key => $value ) {
25 $this->$setting_key = $value;
26 }
27
28 add_action( 'woocommerce_api_'. strtolower( get_class($this) ), array( $this, 'check_Qlicknpay_response' ) );
29
30 if ( is_admin() ) {
31 add_action( 'woocommerce_update_options_payment_gateways_' . $this->id, array(
32 $this,
33 'process_admin_options'
34 ) );
35 }
36
37 add_action( 'woocommerce_receipt_' . $this->id, array(
38 $this,
39 'pay_for_order'
40 ) );
41
42
43
44
45 }
46
47 # Build the administration fields for this specific Gateway
48 public function init_form_fields() {
49 $this->form_fields = array(
50 'enabled' => array(
51 'title' => __( 'Enable / Disable', 'Qlicknpay' ),
52 'label' => __( 'Enable this payment gateway', 'Qlicknpay' ),
53 'type' => 'checkbox',
54 'default' => 'no',
55 ),
56 'payment_gateway_status' => array(
57 'title' => 'Payment Gateway Status',
58 'description' => 'Improtant: Please make sure you select the correct status.',
59 'type' => 'select',
60 'default' => '1',
61 'label' => 'Label', // checkbox only
62 'options' => array(
63 '1' => 'Demo',
64 '2' => 'Live Production'
65 ) // array of options for select/multiselects only
66 ),
67 'universal_form' => array(
68 'title' => __( 'Merchant ID', 'Qlicknpay' ),
69 'type' => 'text',
70 'desc_tip' => __( 'This is the merchant ID that you can obtain from profile page in QlicknPay', 'Qlicknpay' ),
71 ),
72 'secretkey' => array(
73 'title' => __( 'API Key', 'Qlicknpay' ),
74 'type' => 'text',
75 'desc_tip' => __( 'This is the API key that you can obtain from profile page in QlicknPay profile', 'Qlicknpay' ),
76 ),
77 'order_status' => array(
78 'title' => 'Order Status',
79 'desc_tip' => __( 'Order status to be set after the payment was done. (For Success transaction only)', 'Qlicknpay' ),
80 'type' => 'select',
81 'default' => '1',
82 'label' => 'Label', // checkbox only
83 'options' => array(
84 'processing' => 'Processing',
85 'completed' => 'Completed'
86 ) // array of options for select/multiselects only
87 ),
88 'title' => array(
89 'title' => __( 'Title', 'Qlicknpay' ),
90 'type' => 'text',
91 'description' => __( 'This controls the title which the user sees during checkout.', 'Qlicknpay' ),
92 'default' => __( 'QlicknPay - Pay with internet banking (FPX) or credit / debit cards', 'Qlicknpay' ),
93 'desc_tip' => true,
94 ),
95 'description' => array(
96 'title' => __( 'Payment Description', 'Qlicknpay' ),
97 'type' => 'textarea',
98 'default' => ''
99 )
100 );
101 }
102
103 public function admin_options() {
104 ?>
105 <h3><?php _e( 'Custom Payment Settings', 'woocommerce-other-payment-gateway' ); ?></h3>
106 <div id="poststuff">
107 <div id="post-body" class="metabox-holder columns-2">
108 <div id="post-body-content">
109 <table class="form-table">
110 <?php $this->generate_settings_html();?>
111 </table><!--/.form-table-->
112 </div>
113 <div id="postbox-container-1" class="postbox-container">
114 <div id="side-sortables" class="meta-box-sortables ui-sortable">
115
116 <div class="postbox ">
117 <div class="handlediv" title="Click to toggle"><br></div>
118 <h3 class="hndle"><span align="center"> QlicknPay <br>
119 Payment. Collection. Recovery.</span></h3>
120 <div class="inside">
121 <div class="support-widget">
122 <ul>
123 <li>» Pay Bills & Collect Faster</li>
124 <li>» Instant Settlements From Your Online Sales</li>
125 <li>» Collect Your Recurring Payments On Time</li>
126 </ul>
127 <a href="https://www.Qlicknpay.com/" class="button wpruby_button" target="_blank">Register Now</a>
128 </div>
129 </div>
130 </div>
131 </div>
132 </div>
133 </div>
134 </div>
135 <div class="clear"></div>
136 <style type="text/css">
137 .wpruby_button{
138 background-color:#f3b007 !important;
139 border-color:#f3b007 !important;
140 color:#ffffff !important;
141 width:100%;
142 padding:5px !important;
143 text-align:center;
144 height:35px !important;
145 font-size:12pt !important;
146 }
147 </style>
148 <?php
149 }
150
151 # Submit payment
152 public function process_payment( $order_id ) {
153 # Get this order's information so that we know who to charge and how much
154
155
156 $order = wc_get_order($order_id);
157 $order->update_status('pending');
158
159 return array(
160 'result' => 'success',
161 'redirect' => './wc-api/Qlicknpay/?submit_data=true&order_id='.$order_id
162 );
163 }
164
165
166 public function check_Qlicknpay_response() {
167
168 $submit_data = sanitize_text_field($_GET['submit_data']);
169
170 if(isset($submit_data) && $submit_data == 'true')
171 {
172 $order_id = sanitize_text_field($_GET['order_id']);
173
174 $customer_order = wc_get_order( $order_id );
175
176 $x = 1;
177 $old_wc = version_compare( WC_VERSION, '3.0', '<' );
178
179 foreach ($customer_order->get_items() as $item_id => $item_data)
180 {
181
182
183 // Get an instance of corresponding the WC_Product object
184 $product = $old_wc ? $item_data->product : $item_data->get_product();
185 $product_name = $old_wc ? $item_data['name'] : $product->get_name();
186 $product_quantity = $old_wc ? $customer_order->get_item_meta($item_id, '_qty', true) : $item_data->get_quantity();
187 $product_total = $old_wc ? $customer_order->get_item_meta($item_id, '_line_total', true) : $item_data->get_total();
188
189 $product_id = $item_data['product_id'];
190
191 $products = wc_get_product( $product_id );
192
193 $product_image = $products->get_image();
194
195 preg_match_all('#\bhttps?://[^,\s()<>]+(?:\([\w\d]+\)|([^,[:punct:]\s]|/))#', $product_image, $match);
196
197 $path = parse_url($match[0][0], PHP_URL_PATH);
198
199 if(!isset($prod) || $prod == '')
200 {
201 $prod = array(
202 "pn$x" => $product_name,
203 "pq$x" => $product_quantity,
204 "pt$x" => $product_total,
205 "pi$x" => $path
206 );
207 }
208
209 else
210 {
211 $prod["pn$x"] = $product_name;
212 $prod["pq$x"] = $product_quantity;
213 $prod["pt$x"] = $product_total;
214 $prod["pi$x"] = $path;
215
216 }
217 $x++;
218 }
219
220 # Prepare the data to send to Qlicknpay
221 $detail = "Your order is : ".$order_id;
222
223 $order_id = sanitize_text_field($old_wc ? $customer_order->id : $customer_order->get_id());
224 $amount = number_format($old_wc ? $customer_order->order_total : $customer_order->get_total(), 2);
225 $name = sanitize_text_field($old_wc ? $customer_order->billing_first_name . ' ' . $customer_order->billing_last_name : $customer_order->get_billing_first_name() . ' ' . $customer_order->get_billing_last_name());
226 $email = sanitize_email($old_wc ? $customer_order->billing_email : $customer_order->get_billing_email());
227 $phone = sanitize_text_field($old_wc ? $customer_order->billing_phone : $customer_order->get_billing_phone());
228 $address_1 = sanitize_text_field($old_wc ? $customer_order->shipping_address_1 : $customer_order->get_billing_address_1());
229 $address_2 = sanitize_text_field($old_wc ? $customer_order->shipping_address_2 : $customer_order->get_billing_address_2());
230 $city = sanitize_text_field($old_wc ? $customer_order->shipping_city : $customer_order->get_billing_city());
231 $state = sanitize_text_field($old_wc ? $customer_order->shipping_state : $customer_order->get_billing_state());
232 $postcode = sanitize_text_field($old_wc ? $customer_order->shipping_postcode : $customer_order->get_billing_postcode());
233 $order_notes = sanitize_text_field($old_wc ? $customer_order->customer_note : $customer_order->get_customer_note());
234
235 $universal_form = sanitize_text_field($this->universal_form);
236 $secretkey = sanitize_text_field($this->secretkey);
237
238 $hash_send = md5( $secretkey . $universal_form . $order_id . $amount . $detail );
239
240 $characters = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
241 $charactersLength = strlen($characters);
242 $randomString = '';
243
244 for ($i = 0; $i < 3; $i++) {
245 $randomString .= $characters[rand(0, $charactersLength - 1)];
246 }
247 $new_order_id = $universal_form."-".$order_id."-".date("his")."-".$randomString;
248
249 $post_args = array(
250 'merchant_id' => $universal_form,
251 'order_detail' => $detail,
252 'total_amount' => $amount,
253 'invoice' => $order_id,
254 'invoice_temp' => $new_order_id,
255 'total_item_type' => $x,
256 'hash' => $hash_send,
257 'buyer_name' => $name,
258 'buyer_email' => $email,
259 'buyer_phone' => $phone,
260 'address_1' => $address_1,
261 'address_2' => $address_2,
262 'city' => $city,
263 'state' => $state,
264 'postcode' => $postcode,
265 'comment' => $order_notes
266 );
267
268 $payment_gateway_status = sanitize_text_field($this->payment_gateway_status);
269
270 if($payment_gateway_status == '1')
271 {
272 echo "<form action='https://www.demo.Qlicknpay.com/merchant/api/v2/woocommerce_receiver.php' id='submit_data' method='POST'>";
273 }
274 else
275 {
276 echo "<form action='https://www.Qlicknpay.com/merchant/api/v2/woocommerce_receiver.php' id='submit_data' method='POST'>";
277 }
278
279 foreach ($post_args as $key => $value) {
280 echo "<input type='hidden' name='$key' value='$value' >";
281 }
282
283 foreach ($prod as $key => $value) {
284 echo "<input type='hidden' name='$key' value='$value' >";
285 }
286 echo "</form>";
287 echo "<script>document.getElementById('submit_data').submit();</script>";
288 }
289 else if(isset($_REQUEST['order_id']) && isset($_REQUEST['status']))
290 {
291 $secretkey = sanitize_text_field($this->secretkey);
292
293 $order_id_req = sanitize_text_field($_REQUEST['order_id']);
294 $status_req = sanitize_text_field($_REQUEST['status']);
295 $key_req = sanitize_text_field($_REQUEST['key_'.$order_id_req]);
296
297 $hash_received_order = md5( $secretkey . $order_id_req . $status_req);
298
299 if(isset($key_req) && $hash_received_order == $key_req)
300 {
301 $order = wc_get_order( str_replace('WC', '', $order_id_req) );
302
303 if($status_req == 'Transaction Approved' && $order != null)
304 {
305
306 $old_wc = version_compare( WC_VERSION, '3.0', '<' );
307
308
309 $order_id = sanitize_text_field($old_wc ? $order->id : $order->get_id());
310 $order_total = number_format($old_wc ? $order->order_total : $order->get_total(),2);
311 $first_name = sanitize_text_field($old_wc ? $order->billing_first_name : $order->get_billing_first_name());
312 $last_name = sanitize_text_field($old_wc ? $order->billing_last_name : $order->get_billing_last_name());
313 $billing_email = sanitize_email($old_wc ? $order->billing_email : $order->get_billing_email());
314 $billing_phone = sanitize_text_field($old_wc ? $order->billing_phone : $order->get_billing_phone());
315 $shipping_address_1 = sanitize_text_field($old_wc ? $order->shipping_address_1 : $order->get_billing_address_1());
316 $shipping_address_2 = sanitize_text_field($old_wc ? $order->shipping_address_2 : $order->get_billing_address_2());
317 $shipping_city = sanitize_text_field($old_wc ? $order->shipping_city : $order->get_billing_city());
318 $state = sanitize_text_field($old_wc ? $order->shipping_state : $order->get_billing_state());
319 $shipping_postcode = sanitize_text_field($old_wc ? $order->shipping_postcode : $order->get_billing_postcode());
320 $order_notes = sanitize_text_field($old_wc ? $order->customer_note : $order->get_customer_note());
321
322 $currency = get_woocommerce_currency_symbol();
323
324
325 if($state == 'JHR'){$state = 'Johor';}
326 else if($state == 'KDH'){$state = 'Kedah';}
327 else if($state == 'KTN'){$state = 'Kelantan';}
328 else if($state == 'LBN'){$state = 'Labuan';}
329 else if($state == 'MLK'){$state = 'Malacca (Melaka)';}
330 else if($state == 'NSN'){$state = 'Negeri Sembilan';}
331 else if($state == 'PHG'){$state = 'Pahang';}
332 else if($state == 'PNG'){$state = 'Penang (Pulau Pinang)';}
333 else if($state == 'PRK'){$state = 'Perak';}
334 else if($state == 'PLS'){$state = 'Perlis';}
335 else if($state == 'SBH'){$state = 'Sabah';}
336 else if($state == 'SWK'){$state = 'Sarawak';}
337 else if($state == 'SGR'){$state = 'Selangor';}
338 else if($state == 'TRG'){$state = 'Terengganu';}
339 else if($state == 'PJY'){$state = 'Putrajaya';}
340 else if($state == 'KUL'){$state = 'KUL';}
341
342 get_header();
343 echo "
344 <style>
345 .qnpwrapper {
346 margin: 5% 30% 5% 30%;
347 margin-top: 0%;
348 }
349 .qnptext {
350 font-size: 15px;
351 font-weight: bold;
352 }
353 /* MOBILE SIZE */
354 @media only screen and (max-width: 768px) {
355 .qnpwrapper {
356 margin: 5% 5% 5% 5%;
357 margin-top: 0%;
358 }
359
360 .qnptext {
361 font-size: 10px;
362 font-weight: bold;
363 }
364 }
365 </style>
366 <div class='qnpwrapper'>
367 <h5><font color='grey'>Order #$order_id</font></h5>
368 <h3>Thank you $first_name $last_name</h3>
369 <table width='100%'>
370 <tr>
371 <td class='qnptext' colspan='2'><b>CUSTOMER INFORMATION</b></td>
372 </tr>
373 <tr>
374 <td class='qnptext'>Email</td>
375 <td><small>$billing_email</small></td>
376 </tr>
377 <tr>
378 <td class='qnptext'>Phone</td>
379 <td><small>$billing_phone</small></td>
380 </tr>
381 <tr>
382 <td class='qnptext'>Shipping Address</td>
383 <td><small>$shipping_address_1<br>$shipping_address_2</small></td>
384 </tr>
385 <tr>
386 <td class='qnptext'>City</td>
387 <td><small>$shipping_city</small></td>
388 </tr>
389 <tr>
390 <td class='qnptext'>State</td>
391 <td><small>$state</small></td>
392 </tr>
393 <tr>
394 <td class='qnptext'>Poscode</td>
395 <td><small>$shipping_postcode</small></td>
396 </tr>
397 <tr>
398 <td class='qnptext'>Customer note</td>
399 <td><small>$order_notes</small></td>
400 </tr>
401 </table>
402 <br>
403 <table width='100%'>
404 <tr>
405 <td class='qnptext' colspan='4'><b>ORDER DETAILS</b></td>
406 </tr>
407 <tr>
408 <td class='qnptext' >Product Name</td>
409 <td class='qnptext' >Product Image</td>
410 <td class='qnptext' >Product Quantity</td>
411 <td class='qnptext' >Product Price</td>
412 </tr>
413
414 ";
415 $total = 0;
416 foreach ($order->get_items() as $item_id => $item_data) {
417
418 // Get an instance of corresponding the WC_Product object
419 if(!$old_wc)
420 {
421 $product = $item_data->get_product();
422 }
423
424 $product_name = $old_wc ? $item_data['name'] : $product->get_name();
425
426 $item_quantity = $old_wc ? $order->get_item_meta($item_id, '_qty', true) : $item_data->get_quantity();
427 $item_total = $old_wc ? $order->get_item_meta($item_id, '_line_total', true) : $item_data->get_total();
428
429
430 $item_total = number_format( $item_total, 2 );
431
432 $total = number_format( $total + $item_total, 2 );
433
434 $product_id = $item_data['product_id'];
435
436 $products = wc_get_product( $product_id );
437
438 $item_image = $old_wc ? $products->get_image(array( 80,80 )) : $products->get_image(array( 80 ));
439
440 echo "
441 <tr>
442 <td><small>$product_name</small></td>
443 <td><center>$item_image</center></td>
444 <td><center><small>x$item_quantity</small></center></td>
445 <td><small>$currency$item_total</small></td>
446 </tr>
447 ";
448 // Displaying this data (to check)
449 }
450
451 $final_total = number_format( $order_total , 2);
452 $others = number_format( $order_total - $total, 2);
453
454 echo "<tr>
455 <td class='qnptext' colspan='3'>Subtotal</td>
456 <td><small>$currency$total</small></td>
457 </tr>
458 <tr>
459 <td class='qnptext' colspan='3'>Others</td>
460 <td><small>$currency$others</small></td>
461 </tr>
462 <tr>
463 <td class='qnptext' colspan='3'>Payment Method</td>
464 <td><small><a href='https://www.Qlicknpay.com' target='_blank'><img src='https://www.Qlicknpay.com/merchant/assets/images/pdtlogonew.png' width='100'></a></small></td>
465 </tr>
466 <tr>
467 <td class='qnptext' colspan='3'>Final Amount</td>
468 <td class='qnptext' ><u>$currency$final_total</u></td>
469 </tr>
470 ";
471 echo "</table>
472 </div>";
473 get_footer();
474 exit;
475 }
476
477 else
478 {
479 get_header();
480
481 $string = wc_get_cart_url();
482 echo "<div style='min-height: 50vh;'>";
483 echo "<br><br><center>Sorry, your payment is failed. <a href='$string'><font color='blue'>Click here</font></a> to view your pending cart.</center>";
484 echo "</div>";
485
486 get_footer();
487 exit;
488 }
489
490 }
491 else if(isset($key_req) && $hash_received_order != $key_req)
492 {
493 get_header();
494
495 echo "<center>Invalid data.</center>";
496
497 get_footer();
498 exit;
499 }
500 }
501
502 else if ((isset( $_REQUEST['fpx_fpxTxnId'] ) || isset( $_REQUEST['paypal_trx_id'] ) || isset( $_REQUEST['mastercard_trx_id'] ) || isset( $_REQUEST['others_trx_id'] )) && isset( $_REQUEST['invoice'] ) && isset( $_REQUEST['msg'] ) && isset( $_REQUEST['hash'] ) ) {
503 global $woocommerce;
504
505 if(isset($_REQUEST['pay_method']) && sanitize_text_field($_REQUEST['pay_method']) == 'paypal')
506 {
507 $trx_id = sanitize_text_field($_REQUEST['paypal_trx_id']);
508 }
509 else if(isset($_REQUEST['pay_method']) && $_REQUEST['pay_method'] == 'mastercard')
510 {
511 $trx_id = sanitize_text_field($_REQUEST['mastercard_trx_id']);
512 }
513 else if(isset($_REQUEST['pay_method']) && $_REQUEST['pay_method'] == 'others')
514 {
515 $trx_id = sanitize_text_field($_REQUEST['others_trx_id']);
516
517 $_REQUEST['pay_method'] = sanitize_text_field($_REQUEST['trx_txt']);
518 }
519 else
520 {
521 $trx_id = sanitize_text_field($_REQUEST['fpx_fpxTxnId']);
522 }
523
524 $is_callback = isset( $_REQUEST['invoice'] ) ? true : false;
525
526 $order = wc_get_order( sanitize_text_field($_REQUEST['invoice']) );
527
528 $old_wc = version_compare( WC_VERSION, '3.0', '<' );
529
530 $order_id = $old_wc ? $order->id : $order->get_id();
531 $order_notes = $old_wc ? $order->customer_note : $order->get_customer_note();
532
533 if ( $order && $order_id != 0 ) {
534 # Check if the data sent is valid based on the hash value
535 $secretkey = sanitize_text_field($this->secretkey);
536
537 $hash_value = md5( $secretkey . $trx_id . sanitize_text_field($_REQUEST['invoice']) . sanitize_text_field($_REQUEST['msg']) );
538
539 if ( $hash_value == sanitize_text_field($_REQUEST['hash']) ) {
540 if ( sanitize_text_field($_REQUEST['msg']) == 'Transaction Approved' || sanitize_text_field($_REQUEST['msg']) == 'Success' ) {
541 if ( strtolower( $order->get_status() ) == 'pending' || strtolower( $order->get_status() ) == 'processing' ) {
542 # only update if order is pending
543 if ( strtolower( $order->get_status() ) == 'pending' ) {
544 $order->payment_complete();
545 $order->add_order_note( 'Payment successfully made through QlicknPay ('.sanitize_text_field($_REQUEST['pay_method']).'). Transaction reference is ' . sanitize_text_field($_REQUEST['cart_id']) );
546 $order->add_order_note( 'Customer Notes: '.$order_notes);
547 $order->update_status('completed');
548 $woocommerce->cart->empty_cart();
549 }
550
551 if ( $is_callback ) {
552 echo 'OK';
553 } else {
554 # redirect to order receive page
555 wp_redirect( $order->get_checkout_order_received_url() );
556 }
557
558 exit();
559 }
560 }
561 else if ( sanitize_text_field($_REQUEST['msg']) != 'Transaction Approved' ){
562 if ( strtolower( $order->get_status() ) == 'pending' ) {
563 $order->add_order_note( 'Payment was unsuccessful' );
564 $order->update_status('failed');
565 add_filter( 'the_content', 'Qlicknpay_payment_declined_msg' );
566 }
567 }
568 } else {
569 add_filter( 'the_content', 'Qlicknpay_hash_error_msg' );
570 }
571 }
572
573 if ( $is_callback ) {
574 echo 'OK';
575 exit();
576 }
577 }
578
579
580
581 }
582
583 # Validate fields, do nothing for the moment
584 public function validate_fields() {
585 return true;
586 }
587
588 # Check if we are forcing SSL on checkout pages, Custom function not required by the Gateway for now
589 public function do_ssl_check() {
590 if ( $this->enabled == "yes" ) {
591 if ( get_option( 'woocommerce_force_ssl_checkout' ) == "no" ) {
592 echo "<div class=\"error\"><p>" . sprintf( __( "<strong>%s</strong> is enabled and WooCommerce is not forcing the SSL certificate on your checkout page. Please ensure that you have a valid SSL certificate and that you are <a href=\"%s\">forcing the checkout pages to be secured.</a>" ), $this->method_title, admin_url( 'admin.php?page=wc-settings&tab=checkout' ) ) . "</p></div>";
593 }
594 }
595 }
596
597 /**
598 * Check if this gateway is enabled and available in the user's country.
599 * Note: Not used for the time being
600 * @return bool
601 */
602 public function is_valid_for_use() {
603 return in_array( get_woocommerce_currency(), array( 'MYR' ) );
604 }
605}
606