From ccdd494f313da7bee733d42e510e9cd4cd20ae19 Mon Sep 17 00:00:00 2001 From: Minh Nhut Date: Tue, 7 Apr 2020 20:42:03 +0700 Subject: [PATCH] Release 1.0.2 --- assets/css/woo-vnpay.css | 19 ++ assets/images/caution.svg | 1 + assets/images/correct.svg | 1 + includes/class-woo-vnpay-license.php | 76 ++++++ includes/class-woo-vnpay-option-page.php | 37 +++ includes/class-woo-vnpay-payment-gateway.php | 243 +++++++++++++++++++ includes/class-woo-vnpay-response.php | 129 ++++++++++ includes/vnpay/vnpay-settings.php | 112 +++++++++ index.php | 2 + readme.txt | 10 + woo-vnpay.php | 122 ++++++++++ 11 files changed, 752 insertions(+) create mode 100755 assets/css/woo-vnpay.css create mode 100755 assets/images/caution.svg create mode 100755 assets/images/correct.svg create mode 100644 includes/class-woo-vnpay-license.php create mode 100644 includes/class-woo-vnpay-option-page.php create mode 100644 includes/class-woo-vnpay-payment-gateway.php create mode 100644 includes/class-woo-vnpay-response.php create mode 100644 includes/vnpay/vnpay-settings.php create mode 100644 index.php create mode 100644 readme.txt create mode 100644 woo-vnpay.php diff --git a/assets/css/woo-vnpay.css b/assets/css/woo-vnpay.css new file mode 100755 index 0000000..2990573 --- /dev/null +++ b/assets/css/woo-vnpay.css @@ -0,0 +1,19 @@ +.vnpay-payment-gateway-wrapper .vnpay-payment-gateway-notification { + max-width: 600px; + margin: 0 auto; + border: 1px solid #dcd7ca; + border-radius: 6px; + padding: 20px 15px; + text-align: center; +} +.vnpay-payment-gateway-wrapper .vnpay-payment-gateway-notification img { + width: 100px; + height: auto; + margin: 0 auto; +} +.vnpay-payment-gateway-wrapper .vnpay-payment-gateway-notification .notification-title { + margin: 10px 0; + font-size: 30px; +} + +/*# sourceMappingURL=wc-vnpay-payment-gateway.css.map */ diff --git a/assets/images/caution.svg b/assets/images/caution.svg new file mode 100755 index 0000000..f5cd4fc --- /dev/null +++ b/assets/images/caution.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/assets/images/correct.svg b/assets/images/correct.svg new file mode 100755 index 0000000..3aae61c --- /dev/null +++ b/assets/images/correct.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/includes/class-woo-vnpay-license.php b/includes/class-woo-vnpay-license.php new file mode 100644 index 0000000..2107793 --- /dev/null +++ b/includes/class-woo-vnpay-license.php @@ -0,0 +1,76 @@ + $current_domain, + "license-key" => $license_key, + "product-id" => WOO_VNPAY_PRODUCT_ID + ); + $result = $this->execPostRequestAPI($api_host, json_encode($data)); + $jsonResult = json_decode($result, true); + if ($jsonResult['result']['status'] == "active" && $jsonResult['result']['product-id'] == WOO_VNPAY_PRODUCT_ID) { + if (!file_exists(WOO_VNPAY_LICENSE_FILE_PATH)) { + $content = $jsonResult['result']['status']; + $fp = fopen(WOO_VNPAY_LICENSE_FILE_PATH, "wb"); + fwrite($fp, $content); + fclose($fp); + } + } else if ($jsonResult['result']['status'] == "not-active") { + if (file_exists(WOO_VNPAY_LICENSE_FILE_PATH)) { + unlink(WOO_VNPAY_LICENSE_FILE_PATH); + } + } + } + + function check_license_file_type() + { + if (file_exists(WOO_VNPAY_LICENSE_FILE_PATH)) { + return true; + } else { + return false; + } + } + + /** + * @param $url + * @param $data + * @return bool|string + */ + public function execPostRequestAPI($url, $data) + { + $ch = curl_init($url); + curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "POST"); + curl_setopt($ch, CURLOPT_POSTFIELDS, $data); + curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); + curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false); + curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); + curl_setopt($ch, CURLOPT_HTTPHEADER, array( + 'Content-Type: application/json;charset=UTF-8' + ) + ); + curl_setopt($ch, CURLOPT_TIMEOUT, 400); + curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 0); + $result = curl_exec($ch); + curl_close($ch); + return $result; + } + + } + +endif; diff --git a/includes/class-woo-vnpay-option-page.php b/includes/class-woo-vnpay-option-page.php new file mode 100644 index 0000000..fd10af4 --- /dev/null +++ b/includes/class-woo-vnpay-option-page.php @@ -0,0 +1,37 @@ +Woo_VNPAY_Options = get_option('woo_vnpay'); + } + + function register_options_page() + { + add_options_page('MoMo for WooCommerce', 'Woo VNPay', 'manage_options', 'vnpay-for-woo-option', array( + $this, + 'option_page' + )); + } + + function option_page() + { + require_once('admin/option-page.php'); + } + + function option_page_data() + { + $Woo_VNPAY_Options = array(); + $Woo_VNPAY_Options["license_key"] = ""; + add_option('woo_vnpay', $Woo_VNPAY_Options); + } + + } + +endif; diff --git a/includes/class-woo-vnpay-payment-gateway.php b/includes/class-woo-vnpay-payment-gateway.php new file mode 100644 index 0000000..a38e48a --- /dev/null +++ b/includes/class-woo-vnpay-payment-gateway.php @@ -0,0 +1,243 @@ +id = 'woo_vnpay'; + $this->has_fields = false; + $this->method_title = __('VNPAY', 'woo-vnpay'); + $this->method_description = __('Thanh toán qua VNPAY.', 'woo-vnpay'); + + // Load the settings. + $this->init_form_fields(); + $this->init_settings(); + + // Define user set variables + $this->title = $this->get_option('title'); + $this->description = $this->get_option('description'); + $this->instructions = ""; + + // Actions + add_action('woocommerce_update_options_payment_gateways_' . $this->id, array($this, 'process_admin_options')); + add_filter('woocommerce_order_button_text', array($this, 'order_button_name')); + add_action('woocommerce_thankyou_' . $this->id, array($this, 'vnpay_payment_results')); + } + + public function init_form_fields() + { + $this->form_fields = include('vnpay/vnpay-settings.php'); + } + + /** + * @param int $order_id + * @return array + */ + public function process_payment($order_id) + { + $order = wc_get_order($order_id); + $order->update_status($this->get_option('order_created')); + + return array( + 'result' => 'success', + 'redirect' => $this->get_pay_url($order) + ); + } + + /** + * @param $order + * + * @return string + */ + public function get_pay_url($order) + { + $vnp_TmnCode = $this->get_option('vnp_TmnCode'); + $vnp_HashSecret = $this->get_option('vnp_HashSecret'); + $vnp_Url = $this->get_option('vnp_Url'); + $vnp_Returnurl = admin_url('admin-ajax.php?action=vnpay_response&type=international'); + $array = array( + '{{orderid}}' => $order->get_id() + ); + $order_desc = strtr($this->get_option('order_desc'), $array); + $vnp_TxnRef = $order->get_id(); + $vnp_OrderInfo = $order_desc; + $vnp_OrderType = 'other'; + $vnp_Amount = number_format($order->get_total(), 2, '.', '') * 100; + $vnp_Locale = 'vn'; + $vnp_BankCode = ''; + $vnp_IpAddr = $_SERVER['REMOTE_ADDR']; + $inputData = array( + "vnp_Version" => "2.0.0", + "vnp_TmnCode" => $vnp_TmnCode, + "vnp_Amount" => $vnp_Amount, + "vnp_Command" => "pay", + "vnp_CreateDate" => date('YmdHis'), + "vnp_CurrCode" => "VND", + "vnp_IpAddr" => $vnp_IpAddr, + "vnp_Locale" => $vnp_Locale, + "vnp_OrderInfo" => $vnp_OrderInfo, + "vnp_OrderType" => $vnp_OrderType, + "vnp_ReturnUrl" => $vnp_Returnurl, + "vnp_TxnRef" => $vnp_TxnRef, + ); + if (isset($vnp_BankCode) && $vnp_BankCode != "") { + $inputData['vnp_BankCode'] = $vnp_BankCode; + } + ksort($inputData); + $query = ""; + $i = 0; + $hashdata = ""; + foreach ($inputData as $key => $value) { + if ($i == 1) { + $hashdata .= '&' . $key . "=" . $value; + } else { + $hashdata .= $key . "=" . $value; + $i = 1; + } + $query .= urlencode($key) . "=" . urlencode($value) . '&'; + } + + $vnp_Url = $vnp_Url . "?" . $query; + if (isset($vnp_HashSecret)) { + $vnpSecureHash = hash('sha256', $vnp_HashSecret . $hashdata); + $vnp_Url .= 'vnp_SecureHashType=SHA256&vnp_SecureHash=' . $vnpSecureHash; + } + + return $vnp_Url; + } + + public function vnpay_payment_results($order_id) + { + $hashSecret = $this->get_option('vnp_HashSecret'); + $inputData = array(); + $data = $_REQUEST; + foreach ($data as $key => $value) { + if (substr($key, 0, 4) == "vnp_") { + $inputData[$key] = $value; + } + } + $vnp_SecureHash = $inputData['vnp_SecureHash']; + unset($inputData['vnp_SecureHashType']); + unset($inputData['vnp_SecureHash']); + ksort($inputData); + $i = 0; + $hashData = ""; + foreach ($inputData as $key => $value) { + if ($i == 1) { + $hashData = $hashData . '&' . $key . "=" . $value; + } else { + $hashData = $hashData . $key . "=" . $value; + $i = 1; + } + } + + $secureHash = hash('sha256', $hashSecret . $hashData); + if ($secureHash == $vnp_SecureHash) { + if ($_GET['vnp_ResponseCode'] == '00') { + $amount = $inputData['vnp_Amount'] / 100; + $array = array( + '{{orderid}}' => $order_id, + '{{amount}}' => number_format($amount, '0', '.', '.') . 'đ', + '{{transaction}}' => $inputData['vnp_TransactionNo'] + ); + $payment_notice_successful = strtr($this->get_option('payment_notice_successful'), $array); + ?> +
+
+ Giao dịch thành công +

Thanh toán thành công

+

+
+
+ +
+
+ Thanh toán không thành công +

Thanh toán không thành công

+

Đã có lỗi trong quá trình thanh toán, vui lòng thử + lại!

+
+
+ +
+
+ Cảnh báo +

Cảnh báo

+

Chữ ký không hợp lệ

+
+
+ session->get('chosen_payment_method'); + if ($chosen_payment_method == 'woo_vnpay') { + $order_button_name = $this->get_option('button_label');; + } ?> + isValidCurrency()) { + parent::admin_options(); + } else { + ?> +
+

+ : + +

+
+ action(); + } + + public function action() + { + add_action('wp_ajax_vnpay_response', array($this, 'checkResponse')); + add_action('wp_ajax_nopriv_vnpay_response', array($this, 'checkResponse')); + } + + public function checkResponse() + { + global $woocommerce; + $checkoutUrl = $woocommerce->cart->get_checkout_url(); + $gateway = new Woo_VNPay_Payment_Gateway; + $hashSecret = $gateway->get_option('vnp_HashSecret'); + $inputData = array(); + $returnData = array(); + $amount = $_GET["vnp_Amount"] / 100; + $txnResponseCode = $_GET["vnp_ResponseCode"]; + $order = $this->getOrder($_GET["vnp_OrderInfo"]); + $data = $_REQUEST; + foreach ($data as $key => $value) { + if (substr($key, 0, 4) == "vnp_") { + $inputData[$key] = $value; + } + } + $vnp_SecureHash = $inputData['vnp_SecureHash']; + unset($inputData['vnp_SecureHashType']); + unset($inputData['vnp_SecureHash']); + ksort($inputData); + $i = 0; + $hashData = ""; + foreach ($inputData as $key => $value) { + if ($i == 1) { + $hashData = $hashData . '&' . $key . "=" . $value; + } else { + $hashData = $hashData . $key . "=" . $value; + $i = 1; + } + } + $vnpTranId = $inputData['vnp_TransactionNo']; //Mã giao dịch tại VNPAY + $vnp_BankCode = $inputData['vnp_BankCode']; //Ngân hàng thanh toán + $secureHash = hash('sha256', $hashSecret . $hashData); + $Status = 0; + $orderId = $inputData['vnp_TxnRef']; + $transStatus = ''; + + if ($order->post_status != null && $order->post_status != '') { + //Check chữ ký + if ($secureHash == $vnp_SecureHash) { + //Check Status của đơn hàng + if ($order->get_status() != null && $order->get_status() != $gateway->get_option('payment_success')) { + if ($inputData['vnp_ResponseCode'] == '00') { + $transStatus = 'Thanh toán thành công. Mã giao dịch tại VNPAY: ' . $vnpTranId . '. Nội dung thanh toán: ' . $_GET["vnp_OrderInfo"]; + $returnData['RspCode'] = '00'; + $returnData['Message'] = 'Confirm Success'; + $returnData['Signature'] = $secureHash; + $order->update_status($gateway->get_option('payment_success')); + $order->add_order_note(__($transStatus, 'woo-vnpay')); + $woocommerce->cart->empty_cart(); + $url = wc_get_checkout_url() . 'order-received/' . $order->get_id() . '/?key=' . $order->order_key . '&' . $hashData . '&vnp_SecureHash=' . $vnp_SecureHash; + wp_redirect($url); + + } else { + $returnData['RspCode'] = '00'; + $returnData['Message'] = 'Confirm Success'; + $returnData['Signature'] = $secureHash; + $order->add_order_note(__('Thanh toán không thành công', 'woo-vnpay')); + $order->update_status('failed'); + $woocommerce->cart->empty_cart(); + $url = wc_get_checkout_url() . 'order-received/' . $order->get_id() . '/?key=' . $order->order_key . '&' . $hashData . '&vnp_SecureHash=' . $vnp_SecureHash; + wp_redirect($url); + } + } else { + $returnData['RspCode'] = '02'; + $returnData['Message'] = 'Order already confirmed'; + $order->update_status($gateway->get_option('payment_failed')); + $order->add_order_note(__('Order already confirmed ', 'woo-vnpay')); + $woocommerce->cart->empty_cart(); + $url = wc_get_checkout_url() . 'order-received/' . $order->get_id() . '/?key=' . $order->order_key . '&' . $hashData . '&vnp_SecureHash=' . $vnp_SecureHash; + wp_redirect($url); + } + } else { + $returnData['RspCode'] = '97'; + $returnData['Message'] = 'Chu ky khong hop le'; + $returnData['Signature'] = $secureHash; + $order->update_status($gateway->get_option('payment_failed')); + $order->add_order_note(__('Chu ky khong hop le', 'woo-vnpay')); + $woocommerce->cart->empty_cart(); + $url = wc_get_checkout_url() . 'order-received/' . $order->get_id() . '/?key=' . $order->order_key . '&' . $hashData . '&vnp_SecureHash=' . $vnp_SecureHash; + wp_redirect($url); + } + } else { + $returnData['RspCode'] = '01'; + $returnData['Message'] = 'Order not found'; + $order->update_status($gateway->get_option('payment_failed')); + $order->add_order_note(__('Order not found', 'woo-vnpay')); + $woocommerce->cart->empty_cart(); + $url = wc_get_checkout_url() . 'order-received/' . $order->get_id() . '/?key=' . $order->order_key . '&' . $hashData . '&vnp_SecureHash=' . $vnp_SecureHash; + wp_redirect($url); + } + echo json_encode($returnData); + die(); + } + + public function getOrder($orderId) + { + preg_match_all('!\d+!', $orderId, $matches); + $order = new \WC_Order($matches[0][0]); + + return $order; + } + } +} diff --git a/includes/vnpay/vnpay-settings.php b/includes/vnpay/vnpay-settings.php new file mode 100644 index 0000000..8c42449 --- /dev/null +++ b/includes/vnpay/vnpay-settings.php @@ -0,0 +1,112 @@ + array( + 'title' => __('Bật/Tắt', 'woo-vnpay'), + 'type' => 'checkbox', + 'label' => __('Bật phương thức thanh toán', 'woo-vnpay'), + 'default' => 'yes' + ), + 'title' => array( + 'title' => __('Tiêu đề', 'woo-vnpay'), + 'type' => 'text', + 'description' => __('Tên phương thức thanh toán.', 'woo-vnpay'), + 'default' => __('VNPAY', 'woo-vnpay'), + 'desc_tip' => true, + ), + 'description' => array( + 'title' => __('Mô tả', 'woo-vnpay'), + 'type' => 'textarea', + 'description' => __('Mô tả phương thức thanh toán.', 'woo-vnpay'), + 'default' => __('Thực hiện thanh toán qua VNPAY.', 'woo-vnpay'), + 'desc_tip' => true, + ), + 'order_desc' => array( + 'title' => __('Nội dung thanh toán', 'woo-vnpay'), + 'type' => 'text', + 'description' => __('Giúp chủ cửa hàng nhận biết thanh toán cho đơn hàng nào.', 'woo-vnpay'), + 'default' => __('DH{{orderid}}', 'woo-vnpay'), + 'desc_tip' => true, + ), + 'button_label' => array( + 'title' => __('Nút thanh toán', 'woo-vnpay'), + 'type' => 'text', + 'description' => __('Thay đổi tên nút thanh toán.', 'woo-vnpay'), + 'default' => __('Thanh toán qua VNPAY', 'woo-vnpay'), + 'desc_tip' => true, + ), + 'payment_notice_successful' => array( + 'title' => __('Thông báo khi thanh toán thành công', 'woo-vnpay'), + 'type' => 'textarea', + 'description' => __('{{orderid}} Mã đơn hàng. {{amount}} Số tiền. {{transaction}} Mã giao dịch tại VNPAY.', 'woo-vnpay'), + 'default' => __('Quý khách đã thanh toán {{amount}} thành công cho đơn hàng {{orderid}}. Mã giao dịch tại VNPAY {{transaction}}. Xin chân thành cảm ơn quý khách!', 'woo-vnpay'), + 'desc_tip' => false, + ), + 'order_created' => array( + 'title' => __('Trạng thái đơn hàng sau khi đặt hàng', 'woo-vnpay'), + 'type' => 'select', + 'options' => array( + 'pending' => __('Chờ thanh toán', 'woocommerce'), + 'processing' => __('Đang xử lý', 'woocommerce'), + 'on-hold' => __('Tạm giữ', 'woocommerce'), + 'completed' => __('Đã hoàn thành', 'woocommerce'), + 'cancelled' => __('Đã hủy', 'woocommerce'), + 'refunded' => __('Đã hoàn lại tiền', 'woocommerce'), + 'failed' => __('Thất bại', 'woocommerce') + ), + 'default' => 'pending', + 'desc_tip' => true, + ), + 'payment_success' => array( + 'title' => __('Trạng thái đơn hàng khi thanh toán thành công', 'woo-vnpay'), + 'type' => 'select', + 'options' => array( + 'pending' => __('Chờ thanh toán', 'woocommerce'), + 'processing' => __('Đang xử lý', 'woocommerce'), + 'on-hold' => __('Tạm giữ', 'woocommerce'), + 'completed' => __('Đã hoàn thành', 'woocommerce'), + 'cancelled' => __('Đã hủy', 'woocommerce'), + 'refunded' => __('Đã hoàn lại tiền', 'woocommerce'), + 'failed' => __('Thất bại', 'woocommerce') + ), + 'default' => 'processing', + 'desc_tip' => true, + ), + 'payment_failed' => array( + 'title' => __('Trạng thái đơn hàng khi thanh toán thất bại', 'woo-vnpay'), + 'type' => 'select', + 'options' => array( + 'pending' => __('Chờ thanh toán', 'woocommerce'), + 'processing' => __('Đang xử lý', 'woocommerce'), + 'on-hold' => __('Tạm giữ', 'woocommerce'), + 'completed' => __('Đã hoàn thành', 'woocommerce'), + 'cancelled' => __('Đã hủy', 'woocommerce'), + 'refunded' => __('Đã hoàn lại tiền', 'woocommerce'), + 'failed' => __('Thất bại', 'woocommerce') + ), + 'default' => 'cancelled', + 'desc_tip' => true, + ), + 'vnp_Url' => array( + 'title' => __('URL khởi tạo giao dịch', 'woo-vnpay'), + 'type' => 'text', + 'description' => __('URL do VNPAY cung cấp.', 'woo-vnpay'), + 'desc_tip' => false, + ), + 'vnp_TmnCode' => array( + 'title' => __('Partner code', 'woo-vnpay'), + 'type' => 'text', + 'description' => __('Partner code do VNPAY cung cấp.', 'woo-vnpay'), + 'desc_tip' => false, + ), + 'vnp_HashSecret' => array( + 'title' => __('Secret key', 'woo-vnpay'), + 'type' => 'password', + 'description' => __('Secret key do VNPAY cung cấp.', 'woo-vnpay'), + 'desc_tip' => false, + ) +); diff --git a/index.php b/index.php new file mode 100644 index 0000000..6220032 --- /dev/null +++ b/index.php @@ -0,0 +1,2 @@ +define('WOO_VNPAY_PLUGIN_PATH', plugin_dir_path(__FILE__)); + $this->define('WOO_VNPAY_PLUGIN_BASENAME', plugin_basename(__FILE__)); + $this->define('WOO_VNPAY_PLUGIN_URL', plugin_dir_url(__FILE__)); + + //includes + $this->woo_vnpay_include('includes/class-woo-vnpay-payment-gateway.php'); + $this->woo_vnpay_include('includes/class-woo-vnpay-response.php'); + $this->woo_vnpay_include('includes/class-woo-vnpay-license.php'); + + //action + add_filter('woocommerce_payment_gateways', array($this, 'add_gateway_class')); + add_filter('plugin_action_links_' . WOO_VNPAY_PLUGIN_BASENAME, array($this, 'add_settings_link')); + add_action('wp_enqueue_scripts', array($this, 'plugin_assets'), 1); + + new VNPAYResponse(); + } + + /** + * define + * + * @param $name + * @param bool $value + */ + function define($name, $value = true) + { + if (!defined($name)) { + define($name, $value); + } + } + + /** + * get path + * + * @param string $path + * + * @return string + */ + function get_path($path = '') + { + return WOO_VNPAY_PLUGIN_PATH . $path; + } + + /** + * include + * + * @param $file + */ + function woo_vnpay_include($file) + { + $path = $this->get_path($file); + if (file_exists($path)) { + include_once($path); + } + } + + /** + * @param $methods + * @return array + */ + public function add_gateway_class($methods) + { + $methods[] = 'Woo_VNPay_Payment_Gateway'; + return $methods; + } + + + public function add_settings_link($links) + { + $plugin_links = array( + '' . __('Thiết lập', 'woo-momo') . '' + ); + + return array_merge($plugin_links, $links); + } + + + public function plugin_assets() + { + wp_enqueue_style('woo-vnpay-style', WOO_VNPAY_PLUGIN_URL . 'assets/css/woo-vnpay.css', array(), '1.0.0', 'all'); + } + + } + + new WooVNPay(); +endif;