diff --git a/assets/onepay_domestic.png b/assets/onepay_domestic.png new file mode 100644 index 0000000..92059e6 Binary files /dev/null and b/assets/onepay_domestic.png differ diff --git a/inc/class-wooviet-admin-page.php b/inc/class-wooviet-admin-page.php index d572d55..b022f64 100644 --- a/inc/class-wooviet-admin-page.php +++ b/inc/class-wooviet-admin-page.php @@ -88,6 +88,34 @@ class WooViet_Admin_Page { value=""> + + + + + - diff --git a/inc/class-wooviet-onepay-domestic.php b/inc/class-wooviet-onepay-domestic.php new file mode 100644 index 0000000..b5e1afb --- /dev/null +++ b/inc/class-wooviet-onepay-domestic.php @@ -0,0 +1,403 @@ +id = strtolower( __CLASS__ ); + $this->has_fields = false; + $this->order_button_text = __( 'Proceed to OnePay', 'woo-viet' ); + $this->method_title = __( 'OnePay Domestic Gateway (by Woo Viet)', 'woo-viet' ); + $this->method_description = __( 'OnePay supports all major bank ATMs in Vietnam.', 'woo-viet' ); + $this->supports = array( + 'products', + ); + + // 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' ) . sprintf( '
', WOO_VIET_URL . 'assets/onepay_domestic.png' ); + + $this->testmode = 'yes' === $this->get_option( 'testmode', 'no' ); + $this->merchant_id = $this->get_option( 'merchant_id' ); + $this->access_code = $this->get_option( 'access_code' ); + $this->secure_secret = $this->get_option( 'secure_secret' ); + $this->user = $this->get_option( 'user' ); + $this->password = $this->get_option( 'password' ); + + // Process the admin options + add_action( 'woocommerce_update_options_payment_gateways_' . $this->id, array( + $this, + 'process_admin_options' + ) ); + + add_action( 'woocommerce_thankyou_' . $this->id, array( $this, 'handle_onepay_return_url' ) ); + + add_action( 'woocommerce_api_' . strtolower( __CLASS__ ), array( $this, 'handle_onepay_ipn' ) ); + + } + + /** + * Initialise Gateway Settings Form Fields. + */ + public function init_form_fields() { + $this->form_fields = include( 'onepay/domestic-settings.php' ); + } + + /** + * Get the IPN URL for OnePay + * Format: http://my-site.com/wc-api/WooViet_OnePay_Domestic/ + */ + static function get_onepay_ipn_url() { + return WC()->api_request_url( __CLASS__ ); + } + + /** + * Process the payment + * + * @param int $order_id + * + * @return array + */ + public function process_payment( $order_id ) { + $order = wc_get_order( $order_id ); + + return array( + 'result' => 'success', + 'redirect' => $this->get_pay_url( $order ) + ); + } + + /** + * Get the OnePay pay URL for an order + * AND set the queryDR cron for this transaction + * + * @param WC_Order $order + * + * @return string + */ + public function get_pay_url( $order ) { + $args = array( + 'Title' => __( 'OnePay Payment Title', 'woo-viet' ), + 'vpc_Merchant' => $this->merchant_id, + 'vpc_AccessCode' => $this->access_code, + 'vpc_MerchTxnRef' => sprintf( '%1$s_%2$s', $order->id, date( 'YmdHis' ) ), + 'vpc_OrderInfo' => substr( + sprintf( 'Order #%1$s - %2$s', $order->id, get_home_url() ), + 0, + 32 ), // Limit 32 characters + 'vpc_Amount' => $order->get_total() * 100, // Multiplying 100 is a requirement from OnePay + 'vpc_ReturnURL' => $this->get_return_url( $order ), + 'vpc_Version' => '2', + 'vpc_Command' => 'pay', + 'vpc_Locale' => ( 'vi' == get_locale() ) ? 'vn' : 'en', + 'vpc_Currency' => 'VND', + 'vpc_TicketNo' => $_SERVER['REMOTE_ADDR'], + ); + + // Set the queryDR cron for this transaction + $this->set_onepay_querydr_cron( $args['vpc_MerchTxnRef'] ); + + // Get the secure hash + $vpc_SecureHash = $this->create_vpc_SecureHash( $args ); + + // Add the secure hash to the args + $args['vpc_SecureHash'] = $vpc_SecureHash; + $http_args = http_build_query( $args, '', '&' ); + + if ( $this->testmode ) { + return 'https://mtf.onepay.vn/onecomm-pay/vpc.op?' . $http_args; + } else { + return 'https://onepay.vn/onecomm-pay/vpc.op?' . $http_args; + } + + } + + /** + * Set the cron job running queryDR in 20 mintues + * Because the OnePay payment timeout is 15 minutes + * + * @param string $vpc_MerchTxnRef + */ + public function set_onepay_querydr_cron( $vpc_MerchTxnRef ) { + + wp_schedule_single_event( + time() + 20 * 60, + 'wooviet_handle_onepay_querydr', + array( $vpc_MerchTxnRef ) + ); + + } + + /** + * Create the vpc_SecureHash value. + * @see https://mtf.onepay.vn/developer/?page=modul_noidia_php + * + * @param array $args + * + * @return string + */ + public function create_vpc_SecureHash( $args ) { + $stringHashData = ""; + + // arrange array data a-z before make a hash + ksort( $args ); + + foreach ( $args as $key => $value ) { + + if ( strlen( $value ) > 0 ) { + if ( ( strlen( $value ) > 0 ) && ( ( substr( $key, 0, 4 ) == "vpc_" ) || ( substr( $key, 0, 5 ) == "user_" ) ) ) { + $stringHashData .= $key . "=" . $value . "&"; + } + } + } + //Remove the last character "&" + $stringHashData = rtrim( $stringHashData, "&" ); + + return strtoupper( hash_hmac( 'SHA256', $stringHashData, pack( 'H*', $this->secure_secret ) ) ); + } + + /** + * Handle the return URL - GET request from OnePay + */ + public function handle_onepay_return_url() { + + if ( isset( $_GET['vpc_SecureHash'] ) ) { + + $this->process_onepay_response_data( $_GET, 'return' ); + + } + } + + /** + * Handle the repsonse data from OnePay + * + * @param string $args the response data from OnePay + * @param string $type + */ + public function process_onepay_response_data( $args, $type ) { + $types_accepted = array( + 'return', + 'ipn', + 'querydr', + ); + + // Do nothing if the type is wrong + if ( ! in_array( $type, $types_accepted ) ) { + return; + } + + $is_secure = false; + $is_querydr_exists = false; + + if ( 'return' == $type OR 'ipn' == $type ) { + $vpc_SecureHash = $args['vpc_SecureHash']; + + // Remove the parameter "vpc_SecureHash" for validating SecureHash + unset( $args['vpc_SecureHash'] ); + + $is_secure = $this->check_vpc_SecureHash( $args, $vpc_SecureHash ); + + } elseif ( 'querydr' == $type ) { + $is_querydr_exists = ( 'Y' == $args['vpc_DRExists'] ); + + } + + // Process the data + if ( $is_secure OR $is_querydr_exists ) { + /** + * $vpc_MerchTxnRef looks like this "139_20170418101843" or {order_id}_{date_time} + * @see $this->get_pay_url(); + */ + $vpc_MerchTxnRef = $args['vpc_MerchTxnRef']; + $vpc_TxnResponseCode = $args['vpc_TxnResponseCode']; + + // Get the order_id part only + $order_id = substr( $vpc_MerchTxnRef, 0, strrpos( $vpc_MerchTxnRef, '_' ) ); + + $order = wc_get_order( $order_id ); + + // Add the order note for the reference + $order_note = sprintf( + __( 'OnePay Domestic Gateway Info | Code: %1$s | Message: %2$s | MerchantTxnRef: %3$s | Type: %4$s', 'woo-viet' ), + $vpc_TxnResponseCode, + $this->OnePay_getResponseDescription( $vpc_TxnResponseCode ), + $vpc_MerchTxnRef, + $type + ); + $order->add_order_note( $order_note ); + + // If the payment is successful, update the order + if ( "0" == $vpc_TxnResponseCode ) { + $order->payment_complete(); + } + + switch ( $type ) { + + case 'return': + wp_redirect( $this->get_return_url( $order ) ); + break; + + case 'ipn': + exit( 'responsecode=1&desc=confirm-success' ); + break; + + case 'querydr': + // Do nothing + break; + } + + } else { + if ( 'ipn' == $type ) { + exit( 'responsecode=0&desc=confirm-success' ); + } + + } + } + + /** + * Whether or not the arguments and a provided $vpc_SecureHash are the same + * + * @see https://mtf.onepay.vn/developer/?page=modul_noidia_php + * + * @param $args + * @param $vpc_SecureHash + * + * @return bool + */ + public function check_vpc_SecureHash( $args, $vpc_SecureHash ) { + // Generate the "vpc_SecureHash" value from $args + $vpc_SecureHash_from_args = $this->create_vpc_SecureHash( $args ); + + if ( $vpc_SecureHash_from_args == $vpc_SecureHash ) { + return true; + } else { + return false; + } + } + + /** + * Get the response description based on the response code + * This is code is from OnePay + * + * @param string $responseCode + * + * @return string + */ + public function OnePay_getResponseDescription( $responseCode ) { + + switch ( $responseCode ) { + case "0" : + $result = "Giao dịch thành công - Approved"; + break; + case "1" : + $result = "Ngân hàng từ chối giao dịch - Bank Declined"; + break; + case "3" : + $result = "Mã đơn vị không tồn tại - Merchant not exist"; + break; + case "4" : + $result = "Không đúng access code - Invalid access code"; + break; + case "5" : + $result = "Số tiền không hợp lệ - Invalid amount"; + break; + case "6" : + $result = "Mã tiền tệ không tồn tại - Invalid currency code"; + break; + case "7" : + $result = "Lỗi không xác định - Unspecified Failure "; + break; + case "8" : + $result = "Số thẻ không đúng - Invalid card Number"; + break; + case "9" : + $result = "Tên chủ thẻ không đúng - Invalid card name"; + break; + case "10" : + $result = "Thẻ hết hạn/Thẻ bị khóa - Expired Card"; + break; + case "11" : + $result = "Thẻ chưa đăng ký sử dụng dịch vụ - Card Not Registed Service(internet banking)"; + break; + case "12" : + $result = "Ngày phát hành/Hết hạn không đúng - Invalid card date"; + break; + case "13" : + $result = "Vượt quá hạn mức thanh toán - Exist Amount"; + break; + case "21" : + $result = "Số tiền không đủ để thanh toán - Insufficient fund"; + break; + case "99" : + $result = "Người sủ dụng hủy giao dịch - User cancel"; + break; + default : + $result = "Giao dịch thất bại - Failured"; + } + + return $result; + } + + /** + * Handle the IPN POST request from OnePay + */ + public function handle_onepay_ipn() { + + if ( isset( $_REQUEST['vpc_SecureHash'] ) ) { + + $this->process_onepay_response_data( $_REQUEST, 'ipn' ); + + } + } + + /** + * Handle the queryDR request + * + * @param string $vpc_MerchTxnRef + */ + public function handle_onepay_querydr( $vpc_MerchTxnRef ) { + // Build the queryDR link + $args = array( + 'vpc_Command' => 'queryDR', + 'vpc_Version' => '1', + 'vpc_MerchTxnRef' => $vpc_MerchTxnRef, + 'vpc_Merchant' => $this->merchant_id, + 'vpc_AccessCode' => $this->access_code, + 'vpc_User' => $this->user, + 'vpc_Password' => $this->password, + ); + + $http_args = http_build_query( $args, '', '&' ); + + if ( $this->testmode ) { + $http_link = 'https://mtf.onepay.vn/onecomm-pay/Vpcdps.op?' . $http_args; + } else { + $http_link = 'https://onepay.vn/onecomm-pay/Vpcdps.op?' . $http_args; + } + + // Connect to OnePay to get the queryDR info + $http_response = wp_remote_get( $http_link ); + parse_str( wp_remote_retrieve_body( $http_response ), $args_response ); + + // Process the data + $this->process_onepay_response_data( $args_response, 'querydr' ); + + } + +} diff --git a/inc/onepay/domestic-settings.php b/inc/onepay/domestic-settings.php new file mode 100644 index 0000000..9ac09bc --- /dev/null +++ b/inc/onepay/domestic-settings.php @@ -0,0 +1,93 @@ + array( + 'title' => __( 'Enable/Disable', 'woo-viet' ), + 'type' => 'checkbox', + 'label' => __( 'OnePay Domestic Gateway (by Woo Viet)', 'woo-viet' ), + 'default' => 'no' + ), + 'testmode' => array( + 'title' => __( 'OnePay Sandbox', 'woocommerce' ), + 'type' => 'checkbox', + 'label' => __( 'Enable OnePay sandbox (testing)', 'woocommerce' ), + 'default' => 'no', + 'description' => sprintf( __( 'OnePay sandbox can be used to test payments. See the testing info.', 'woocommerce' ), 'https://mtf.onepay.vn/developer/?page=modul_noidia' ), + //@todo: add the logo https://mtf.onepay.vn/developer/?page=logo + ), + 'title' => array( + 'title' => __( 'Title', 'woo-viet' ), + 'type' => 'text', + 'description' => __( 'This controls the title which the user sees during checkout.', 'woo-viet' ), + 'default' => __( 'OnePay Domestic Gateway', 'woo-viet' ), + 'desc_tip' => true, + ), + 'description' => array( + 'title' => __( 'Description', 'woo-viet' ), + 'type' => 'textarea', + 'desc_tip' => true, + 'description' => __( 'This controls the description which the user sees during checkout.', 'woo-viet' ), + 'default' => __( 'With OnePay, you can make payment by using any local Vietnam ATM card.', 'woo-viet' ) + ), + 'api_details' => array( + 'title' => __( 'API Credentials', 'woo-viet' ), + 'type' => 'title', + 'description' => sprintf( __( 'Enter your OnePay API credentials. Contact OnePay to have your credentials %shere%s.', 'woo-viet' ), '', '' ), + ), + 'merchant_id' => array( + 'title' => __( 'Merchant ID', 'woo-viet' ), + 'type' => 'text', + 'description' => __( 'Get your Merchant ID from OnePay.', 'woo-viet' ), + 'default' => '', + 'desc_tip' => true, + 'placeholder' => __( 'Required. Provided by OnePay.', 'woo-viet' ) + ), + 'access_code' => array( + 'title' => __( 'Access Code', 'woocommerce' ), + 'type' => 'text', + 'description' => __( 'Get your Access Code from OnePay.', 'woo-viet' ), + 'default' => '', + 'desc_tip' => true, + 'placeholder' => __( 'Required. Provided by OnePay.', 'woo-viet' ) + ), + 'secure_secret' => array( + 'title' => __( 'Secure Secret', 'woocommerce' ), + 'type' => 'text', + 'description' => __( 'Get your Secure Secret from OnePay.', 'woo-viet' ), + 'default' => '', + 'desc_tip' => true, + 'placeholder' => __( 'Required. Provided by OnePay.', 'woo-viet' ) + ), + 'user' => array( + 'title' => __( 'User for queryDR. Test value: op01', 'woocommerce' ), + 'type' => 'text', + 'description' => __( 'Get your user info from OnePay.', 'woo-viet' ), + 'default' => '', + 'desc_tip' => true, + 'placeholder' => __( 'Required. Provided by OnePay', 'woo-viet' ) + ), + 'password' => array( + 'title' => __( 'Password for queryDR. Test value: op123456', 'woocommerce' ), + 'type' => 'text', + 'description' => __( 'Get your password info from OnePay.', 'woo-viet' ), + 'default' => '', + 'desc_tip' => true, + 'placeholder' => __( 'Required. Provided by OnePay.', 'woo-viet' ) + ), + 'more_info' => array( + 'title' => __( 'Instant Payment Notification (IPN)', 'woo-viet' ), + 'type' => 'title', + 'description' => + sprintf( 'URL: %s', WooViet_OnePay_Domestic::get_onepay_ipn_url() ) . '

' . + sprintf( __( '%sContact OnePay%s to configure this URL on its site. This is required based on its guidelines.', 'woo-viet' ), '', '' ), + ), + +); \ No newline at end of file diff --git a/readme.md b/readme.md index 7b6175c..7e8af69 100644 --- a/readme.md +++ b/readme.md @@ -6,7 +6,7 @@ |Tags| WooCommerce Vietnam, vietnam, vietnamese, vietnam provinces, paypal for vietnam dong, vnd, vietnam dong, vietnam currency, vietnam customization | | Requires at least | 4.3 | | Tested up to | 4.7 | -| Stable tag | 1.2 | +| Stable tag | 1.3 | | License | GPLv2 or later | | License URI | https://www.gnu.org/licenses/gpl-2.0.html | @@ -22,8 +22,10 @@ Xem phiên bản tiếng Việt tại đây https://vi.wordpress.org/plugins/woo * Change the VND currency symbol `đ` to anything, e.g: `VND`, `VNĐ`, `đồng`, etc. * Add provinces for Vietnam when visitors select Vietnam as a country of the shipping (billing) address. This is not available in WooCommerce by default. +* Add districts to Vietnam provinces. * Convert `000` of prices to `K` (or anything). E.g: `50000` (VND) will be `50K` (VND), or `50 thousand` (VND). * Support `VND` for [the PayPal Standard gateway](https://docs.woocommerce.com/document/paypal-standard/). Convert `VND` prices to any PayPal supported currency before sending visitors to the PayPal pages. +* Add [the OnePay domestic (local ATM cards) gateway](http://onepay.com.vn/). ## ROAD MAP @@ -72,6 +74,12 @@ Follow these steps to install and use the plugin: ## Changelog +### 1.3 - 2017.04.22 +* Add [the OnePay domestic (local ATM cards) gateway](http://onepay.com.vn/) + +### 1.2 - 2017.03.03 +* Integrate all districts to Vietnam provinces. Credits: [WC City Select by 8manos](https://github.com/8manos/wc-city-select) and [the Vietnam district data by 10h30](https://github.com/htdat/woo-viet/issues/4#issuecomment-277449462) + ### 1.1 * Replace all “WooCommerce for Vietnam” to “Woo Viet” * Replace all “woocomerce-for-vietnam” to “woo-viet” @@ -79,4 +87,4 @@ Follow these steps to install and use the plugin: ### 1.0 * First release. -* Upload to WordPress.org +* Upload to WordPress.org \ No newline at end of file diff --git a/readme.txt b/readme.txt index 46295b2..8bc2146 100644 --- a/readme.txt +++ b/readme.txt @@ -1,9 +1,9 @@ === Woo Viet - WooCommerce for Vietnam === Contributors: htdat -Tags: WooCommerce Vietnam, vietnam, vietnamese, vietnam provinces, paypal for vietnam dong, vnd, vietnam dong, vietnam currency, vietnam customization +Tags: OnePay WooCommerce, OnePay Vietnam, WooCommerce Vietnam, vietnam, vietnamese, vietnam provinces, paypal for vietnam dong, vnd, vietnam dong, vietnam currency, vietnam customization Requires at least: 4.3 -Tested up to: 4.7.2 -Stable tag: 1.2 +Tested up to: 4.7.4 +Stable tag: 1.3 License: GPLv2 or later License URI: https://www.gnu.org/licenses/gpl-2.0.html @@ -15,6 +15,9 @@ Add features to WooCommerce stores having anything related to Vietnam: currency, Xem phiên bản tiếng Việt tại đây https://vi.wordpress.org/plugins/woo-viet/ +**NEW FEATURE**: +Add [the OnePay domestic (local ATM cards) gateway](http://onepay.com.vn/). + = FEATURES = * Change the VND currency symbol `đ` to anything, e.g: `VND`, `VNĐ`, `đồng`, etc. @@ -22,6 +25,7 @@ Xem phiên bản tiếng Việt tại đây https://vi.wordpress.org/plugins/woo * Add districts to Vietnam provinces. * Convert `000` of prices to `K` (or anything). E.g: `50000` (VND) will be `50K` (VND), or `50 thousand` (VND). * Support `VND` for [the PayPal Standard gateway](https://docs.woocommerce.com/document/paypal-standard/). Convert `VND` prices to any PayPal supported currency before sending visitors to the PayPal pages. +* Add [the OnePay domestic (local ATM cards) gateway](http://onepay.com.vn/). = ROAD MAP = @@ -65,11 +69,14 @@ Follow these steps to install and use the plugin: 1. The settings page under WooCommerce -> Woo Viet. 2. Prices are changed to "K", and the symbol is now "VND". -3. List provinces when selecting Vietnam. +3. List provinces and districts when selecting Vietnam. 4. Let clients know about the currency conversion before switching to the PayPal pages. == Changelog == += 1.3 - 2017.04.22 = +* Add [the OnePay domestic (local ATM cards) gateway](http://onepay.com.vn/). + = 1.2 - 2017.03.03 = * Integrate all districts to Vietnam provinces. Credits: [WC City Select by 8manos](https://github.com/8manos/wc-city-select) and [the Vietnam district data by 10h30](https://github.com/htdat/woo-viet/issues/4#issuecomment-277449462) @@ -84,5 +91,8 @@ Follow these steps to install and use the plugin: == Upgrade Notice == += 1.3 = +The new version 1.2 comes with the feature "Add the OnePay domestic (local ATM cards) gateway]" + = 1.2 = The new version 1.2 comes with the feature "Add districts to Vietnam provinces". diff --git a/screenshot-1.png b/screenshot-1.png index c4dfefb..26c3aa1 100644 Binary files a/screenshot-1.png and b/screenshot-1.png differ diff --git a/screenshot-3.png b/screenshot-3.png index 9a27bf8..c44e560 100644 Binary files a/screenshot-3.png and b/screenshot-3.png differ diff --git a/woo-viet.php b/woo-viet.php index e056150..522435d 100644 --- a/woo-viet.php +++ b/woo-viet.php @@ -7,7 +7,7 @@ * Author URI: https://profiles.wordpress.org/htdat * Text Domain: woo-viet * Domain Path: /languages - * Version: 1.2 + * Version: 1.3 * License: GPLv2+ */ @@ -16,7 +16,7 @@ if ( ! defined( 'ABSPATH' ) ) { } define( 'WOO_VIET_DIR', plugin_dir_path( __FILE__ ) ); -// define( 'WOO_VIET_URL', plugins_url( '/', __FILE__ ) ); +define( 'WOO_VIET_URL', plugins_url( '/', __FILE__ ) ); /** * Start the instance @@ -40,7 +40,7 @@ class WooViet { array( 'enabled' => 'yes', ), - 'add_city' => + 'add_city' => array( 'enabled' => 'yes', ), @@ -60,6 +60,10 @@ class WooViet { 'currency' => 'USD', 'rate' => '22770', ), + 'add_onepay_domestic' => + array( + 'enabled' => 'yes', + ), ); /** * The properties to manage all classes under the "inc/" folder @@ -133,6 +137,26 @@ class WooViet { $settings = self::get_settings(); + // Check if "Add the OnePay Domestic Gateway" is enabled + if ( 'yes' == $settings['add_onepay_domestic']['enabled'] + AND 'VND' == get_woocommerce_currency() + ) { + include( 'inc/class-wooviet-onepay-domestic.php' ); + + add_filter( 'woocommerce_payment_gateways', array( $this, 'add_gateway_class' ) ); + + // Add the action to check the cron job for handling queryDR + // It's not possible to add in the class "WooViet_OnePay_Domestic_Hook" because it's NOT always loadded + if ( defined( 'DOING_CRON' ) and DOING_CRON ) { + $this->WooViet_OnePay_Domestic_Hook = new WooViet_OnePay_Domestic(); + add_action( 'wooviet_handle_onepay_querydr', array( + $this->WooViet_OnePay_Domestic_Hook, + 'handle_onepay_querydr' + ), 10, 1 ); + } + + } + // Check if "Add provinces for Vietnam " is enabled. if ( 'yes' == $settings['add_province']['enabled'] ) { include( WOO_VIET_DIR . 'inc/class-wooviet-provinces.php' ); @@ -177,7 +201,23 @@ class WooViet { static function get_settings() { $settings = get_option( 'woo-viet', self::$default_settings ); $settings = wp_parse_args( $settings, self::$default_settings ); + return $settings; } + /** + * Add the gateways to WooCommerce + * + * @param array $methods + * + * @since 1.3 + * @return array + */ + public function add_gateway_class( $methods ) { + $methods[] = 'WooViet_OnePay_Domestic'; + + return $methods; + + } + } \ No newline at end of file

+ + > + +
+
+ +
@@ -99,14 +127,14 @@ class WooViet_Admin_Page {

+

> + >