diff --git a/assets/js/wc-pg-blocks/wpp-wc-mellat-pg.js b/assets/js/wc-pg-blocks/wpp-wc-mellat-pg.js new file mode 100644 index 0000000..4b70f49 --- /dev/null +++ b/assets/js/wc-pg-blocks/wpp-wc-mellat-pg.js @@ -0,0 +1,19 @@ +const wppMellatPG_data = window.wc.wcSettings.getSetting( 'mellat_data', {} ); +const wppMellatPG_label = window.wp.htmlEntities.decodeEntities( wppMellatPG_data.title ) + || window.wp.i18n.__( 'Mellat Bank', 'wp-parsidate' ); +const wppMellatPG_content = ( wppMellatPG_data ) => { + return window.wp.htmlEntities.decodeEntities( wppMellatPG_data.description ); +}; +const wppMellatPG = { + name: 'mellat', + label: wppMellatPG_label, + content: Object( window.wp.element.createElement )( wppMellatPG_content, null ), + edit: Object( window.wp.element.createElement )( wppMellatPG_content, null ), + canMakePayment: () => true, + placeOrderButtonLabel: window.wp.i18n.__( 'Continue', 'wp-parsidate' ), + ariaLabel: wppMellatPG_label, + supports: { + features: wppMellatPG_data.supports, + }, +}; +window.wc.wcBlocksRegistry.registerPaymentMethod( wppMellatPG ); \ No newline at end of file diff --git a/assets/js/wc-pg-blocks/wpp-wc-mellat-pg.min.js b/assets/js/wc-pg-blocks/wpp-wc-mellat-pg.min.js new file mode 100644 index 0000000..245a7a6 --- /dev/null +++ b/assets/js/wc-pg-blocks/wpp-wc-mellat-pg.min.js @@ -0,0 +1 @@ +const wppMellatPG_data=window.wc.wcSettings.getSetting("mellat_data",{});const wppMellatPG_label=window.wp.htmlEntities.decodeEntities(wppMellatPG_data.title)||window.wp.i18n.__("Mellat Bank","wp-parsidate");const wppMellatPG_content=wppMellatPG_data=>{return window.wp.htmlEntities.decodeEntities(wppMellatPG_data.description)};const wppMellatPG={name:"mellat",label:wppMellatPG_label,content:Object(window.wp.element.createElement)(wppMellatPG_content,null),edit:Object(window.wp.element.createElement)(wppMellatPG_content,null),canMakePayment:()=>true,placeOrderButtonLabel:window.wp.i18n.__("Continue","wp-parsidate"),ariaLabel:wppMellatPG_label,supports:{features:wppMellatPG_data.supports}};window.wc.wcBlocksRegistry.registerPaymentMethod(wppMellatPG); \ No newline at end of file diff --git a/assets/js/wc-pg-blocks/wpp-wc-parsian-pg.js b/assets/js/wc-pg-blocks/wpp-wc-parsian-pg.js new file mode 100644 index 0000000..8ad4324 --- /dev/null +++ b/assets/js/wc-pg-blocks/wpp-wc-parsian-pg.js @@ -0,0 +1,19 @@ +const wppParsianPG_data = window.wc.wcSettings.getSetting( 'parsian_data', {} ); +const wppParsianPG_label = window.wp.htmlEntities.decodeEntities( wppParsianPG_data.title ) + || window.wp.i18n.__( 'Parsian Bank', 'wp-parsidate' ); +const wppParsianPG_content = ( wppParsianPG_data ) => { + return window.wp.htmlEntities.decodeEntities( wppParsianPG_data.description ); +}; +const wppParsianPG = { + name: 'parsian', + label: wppParsianPG_label, + content: Object( window.wp.element.createElement )( wppParsianPG_content, null ), + edit: Object( window.wp.element.createElement )( wppParsianPG_content, null ), + canMakePayment: () => true, + placeOrderButtonLabel: window.wp.i18n.__( 'Continue', 'wp-parsidate' ), + ariaLabel: wppParsianPG_label, + supports: { + features: wppParsianPG_data.supports, + }, +}; +window.wc.wcBlocksRegistry.registerPaymentMethod( wppParsianPG ); \ No newline at end of file diff --git a/assets/js/wc-pg-blocks/wpp-wc-parsian-pg.min.js b/assets/js/wc-pg-blocks/wpp-wc-parsian-pg.min.js new file mode 100644 index 0000000..efb8d75 --- /dev/null +++ b/assets/js/wc-pg-blocks/wpp-wc-parsian-pg.min.js @@ -0,0 +1 @@ +const wppParsianPG_data=window.wc.wcSettings.getSetting("parsian_data",{});const wppParsianPG_label=window.wp.htmlEntities.decodeEntities(wppParsianPG_data.title)||window.wp.i18n.__("Parsian Bank","wp-parsidate");const wppParsianPG_content=wppParsianPG_data=>{return window.wp.htmlEntities.decodeEntities(wppParsianPG_data.description)};const wppParsianPG={name:"parsian",label:wppParsianPG_label,content:Object(window.wp.element.createElement)(wppParsianPG_content,null),edit:Object(window.wp.element.createElement)(wppParsianPG_content,null),canMakePayment:()=>true,placeOrderButtonLabel:window.wp.i18n.__("Continue","wp-parsidate"),ariaLabel:wppParsianPG_label,supports:{features:wppParsianPG_data.supports}};window.wc.wcBlocksRegistry.registerPaymentMethod(wppParsianPG); \ No newline at end of file diff --git a/assets/js/wc-pg-blocks/wpp-wc-pasargad-pg.js b/assets/js/wc-pg-blocks/wpp-wc-pasargad-pg.js new file mode 100644 index 0000000..6c2628b --- /dev/null +++ b/assets/js/wc-pg-blocks/wpp-wc-pasargad-pg.js @@ -0,0 +1,19 @@ +const wppPasargadPG_data = window.wc.wcSettings.getSetting( 'pasargad_data', {} ); +const wppPasargadPG_label = window.wp.htmlEntities.decodeEntities( wppPasargadPG_data.title ) + || window.wp.i18n.__( 'Pasargad Bank', 'wp-parsidate' ); +const wppPasargadPG_content = ( wppPasargadPG_data ) => { + return window.wp.htmlEntities.decodeEntities( wppPasargadPG_data.description ); +}; +const wppPasargadPG = { + name: 'pasargad', + label: wppPasargadPG_label, + content: Object( window.wp.element.createElement )( wppPasargadPG_content, null ), + edit: Object( window.wp.element.createElement )( wppPasargadPG_content, null ), + canMakePayment: () => true, + placeOrderButtonLabel: window.wp.i18n.__( 'Continue', 'wp-parsidate' ), + ariaLabel: wppPasargadPG_label, + supports: { + features: wppPasargadPG_data.supports, + }, +}; +window.wc.wcBlocksRegistry.registerPaymentMethod( wppPasargadPG ); \ No newline at end of file diff --git a/assets/js/wc-pg-blocks/wpp-wc-pasargad-pg.min.js b/assets/js/wc-pg-blocks/wpp-wc-pasargad-pg.min.js new file mode 100644 index 0000000..b055b26 --- /dev/null +++ b/assets/js/wc-pg-blocks/wpp-wc-pasargad-pg.min.js @@ -0,0 +1 @@ +const wppPasargadPG_data=window.wc.wcSettings.getSetting("pasargad_data",{});const wppPasargadPG_label=window.wp.htmlEntities.decodeEntities(wppPasargadPG_data.title)||window.wp.i18n.__("Pasargad Bank","wp-parsidate");const wppPasargadPG_content=wppPasargadPG_data=>{return window.wp.htmlEntities.decodeEntities(wppPasargadPG_data.description)};const wppPasargadPG={name:"pasargad",label:wppPasargadPG_label,content:Object(window.wp.element.createElement)(wppPasargadPG_content,null),edit:Object(window.wp.element.createElement)(wppPasargadPG_content,null),canMakePayment:()=>true,placeOrderButtonLabel:window.wp.i18n.__("Continue","wp-parsidate"),ariaLabel:wppPasargadPG_label,supports:{features:wppPasargadPG_data.supports}};window.wc.wcBlocksRegistry.registerPaymentMethod(wppPasargadPG); \ No newline at end of file diff --git a/includes/plugins/wc-gateways/blocks/wpp-mellat-pg-block.php b/includes/plugins/wc-gateways/blocks/wpp-mellat-pg-block.php new file mode 100644 index 0000000..64a1f98 --- /dev/null +++ b/includes/plugins/wc-gateways/blocks/wpp-mellat-pg-block.php @@ -0,0 +1,81 @@ +settings = get_option( "woocommerce_{$this->name}_settings", [] ); + $this->gateway = new $class_name; + } + + /** + * Returns if this payment method should be active. If false, the scripts will not be enqueued. + * + * @return boolean + */ + public function is_active() { + return filter_var( $this->get_setting( 'enabled', true ), FILTER_VALIDATE_BOOLEAN ); + } + + /** + * Returns an array of scripts/handles to be registered for this payment method. + * + * @return array + */ + public function get_payment_method_script_handles() { + $script_id = "wpp-wc-$this->name-blocks-integration"; + $script_name = "wpp-wc-$this->name-pg.js"; + + wp_register_script( + $script_id, + WP_PARSI_URL . "assets/js/wc-pg-blocks/$script_name", + array( + 'wc-blocks-registry', + 'wc-settings', + 'wp-element', + 'wp-html-entities', + 'wp-i18n', + ), + false, + true + ); + + if ( function_exists( 'wp_set_script_translations' ) ) { + wp_set_script_translations( $script_id, 'wp-parsidate', WP_PARSI_DIR . 'languages/' ); + } + + return array( $script_id ); + } + + /** + * Returns an array of key=>value pairs of data made available to the payment methods script. + * + * @return array + */ + public function get_payment_method_data() { + return array( + 'title' => $this->get_setting( 'title' ), + 'description' => $this->get_setting( 'description' ), + 'supports' => $this->get_supported_features(), + ); + } + } +} \ No newline at end of file diff --git a/includes/plugins/wc-gateways/blocks/wpp-parsian-pg-block.php b/includes/plugins/wc-gateways/blocks/wpp-parsian-pg-block.php new file mode 100644 index 0000000..37edf55 --- /dev/null +++ b/includes/plugins/wc-gateways/blocks/wpp-parsian-pg-block.php @@ -0,0 +1,83 @@ +settings = get_option( "woocommerce_{$this->name}_settings", [] ); + $this->gateway = new $class_name; + } + + /** + * Returns if this payment method should be active. If false, the scripts will not be enqueued. + * + * @return boolean + */ + public function is_active() { + return filter_var( $this->get_setting( 'enabled', true ), FILTER_VALIDATE_BOOLEAN ); + } + + /** + * Returns an array of scripts/handles to be registered for this payment method. + * + * @return array + */ + public function get_payment_method_script_handles() { + $script_id = "wpp-wc-$this->name-blocks-integration"; + $script_name = "wpp-wc-$this->name-pg"; + $suffix = defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG || wpp_is_active( 'dev_mode' ) ? '' : '.min'; + + + wp_register_script( + $script_id, + WP_PARSI_URL . "assets/js/wc-pg-blocks/$script_name$suffix.js", + array( + 'wc-blocks-registry', + 'wc-settings', + 'wp-element', + 'wp-html-entities', + 'wp-i18n', + ), + false, + true + ); + + if ( function_exists( 'wp_set_script_translations' ) ) { + wp_set_script_translations( $script_id, 'wp-parsidate', WP_PARSI_DIR . 'languages/' ); + } + + return array( $script_id ); + } + + /** + * Returns an array of key=>value pairs of data made available to the payment methods script. + * + * @return array + */ + public function get_payment_method_data() { + return array( + 'title' => $this->get_setting( 'title' ), + 'description' => $this->get_setting( 'description' ), + 'supports' => $this->get_supported_features(), + ); + } + } +} \ No newline at end of file diff --git a/includes/plugins/wc-gateways/blocks/wpp-pasargad-pg-block.php b/includes/plugins/wc-gateways/blocks/wpp-pasargad-pg-block.php new file mode 100644 index 0000000..2c96251 --- /dev/null +++ b/includes/plugins/wc-gateways/blocks/wpp-pasargad-pg-block.php @@ -0,0 +1,81 @@ +settings = get_option( "woocommerce_{$this->name}_settings", [] ); + $this->gateway = new $class_name; + } + + /** + * Returns if this payment method should be active. If false, the scripts will not be enqueued. + * + * @return boolean + */ + public function is_active() { + return filter_var( $this->get_setting( 'enabled', true ), FILTER_VALIDATE_BOOLEAN ); + } + + /** + * Returns an array of scripts/handles to be registered for this payment method. + * + * @return array + */ + public function get_payment_method_script_handles() { + $script_id = "wpp-wc-$this->name-blocks-integration"; + $script_name = "wpp-wc-$this->name-pg.js"; + + wp_register_script( + $script_id, + WP_PARSI_URL . "assets/js/wc-pg-blocks/$script_name", + array( + 'wc-blocks-registry', + 'wc-settings', + 'wp-element', + 'wp-html-entities', + 'wp-i18n', + ), + false, + true + ); + + if ( function_exists( 'wp_set_script_translations' ) ) { + wp_set_script_translations( $script_id, 'wp-parsidate', WP_PARSI_DIR . 'languages/' ); + } + + return array( $script_id ); + } + + /** + * Returns an array of key=>value pairs of data made available to the payment methods script. + * + * @return array + */ + public function get_payment_method_data() { + return array( + 'title' => $this->get_setting( 'title' ), + 'description' => $this->get_setting( 'description' ), + 'supports' => $this->get_supported_features(), + ); + } + } +} \ No newline at end of file diff --git a/includes/plugins/wc-gateways/index.php b/includes/plugins/wc-gateways/index.php new file mode 100644 index 0000000..c051246 --- /dev/null +++ b/includes/plugins/wc-gateways/index.php @@ -0,0 +1,3 @@ += 0; $i -- ) { + $digit = ord( $data[ $i ] ); + $part_res = bcmul( $digit, $radix ); + $result = bcadd( $result, $part_res ); + $radix = bcmul( $radix, $base ); + } + + return $result; + } + + public static function number_to_binary( $number, $blocksize ) { + $base = "256"; + $result = ""; + $div = $number; + while ( $div > 0 ) { + $mod = bcmod( $div, $base ); + $div = bcdiv( $div, $base ); + $result = - rsa . phpchr( $mod ) . $result; + } + + return str_pad( $result, $blocksize, "\x00", STR_PAD_LEFT ); + } +} + +class RSAProcessor { + private $public_key; + private $private_key; + private $modulus; + private $key_length; + + public function __construct( $xmlRsakey = null, $type = null ) { + if ( $xmlRsakey == null ) { + $xmlObj = simplexml_load_file( "xmlfile/RSAKey.xml" ); + } elseif ( $type == RSAKeyType::XMLFile ) { + $xmlObj = simplexml_load_file( $xmlRsakey ); + } else { + $xmlObj = simplexml_load_string( $xmlRsakey ); + } + $this->modulus = RSA::binary_to_number( base64_decode( $xmlObj->Modulus ) ); + $this->public_key = RSA::binary_to_number( base64_decode( $xmlObj->Exponent ) ); + $this->private_key = RSA::binary_to_number( base64_decode( $xmlObj->D ) ); + $this->key_length = strlen( base64_decode( $xmlObj->Modulus ) ) * 8; + } + + public function getPublicKey() { + return $this->public_key; + } + + public function getPrivateKey() { + return $this->private_key; + } + + public function getKeyLength() { + return $this->key_length; + } + + public function getModulus() { + return $this->modulus; + } + + public function encrypt( $data ) { + return base64_encode( RSA::rsa_encrypt( $data, $this->public_key, $this->modulus, $this->key_length ) ); + } + + public function dencrypt( $data ) { + return RSA::rsa_decrypt( $data, $this->private_key, $this->modulus, $this->key_length ); + } + + public function sign( $data ) { + return RSA::rsa_sign( $data, $this->private_key, $this->modulus, $this->key_length ); + } + + public function verify( $data ) { + return RSA::rsa_verify( $data, $this->public_key, $this->modulus, $this->key_length ); + } +} + +class RSAKeyType { + const XMLFile = 0; + const XMLString = 1; +} + +function makeXMLTree( $data ) { + $ret = array(); + $parser = xml_parser_create(); + xml_parser_set_option( $parser, XML_OPTION_CASE_FOLDING, 0 ); + xml_parser_set_option( $parser, XML_OPTION_SKIP_WHITE, 1 ); + xml_parse_into_struct( $parser, $data, $values, $tags ); + xml_parser_free( $parser ); + $hash_stack = array(); + foreach ( $values as $key => $val ) { + switch ( $val['type'] ) { + case 'open': + $hash_stack[] = $val['tag']; + break; + case 'close': + array_pop( $hash_stack ); + break; + case 'complete': + $hash_stack[] = $val['tag']; + // uncomment to see what this function is doing + // echo("\$ret[" . implode($hash_stack, "][") . "] = '{$val[value]}';\n"); + eval( "\$ret[" . implode( $hash_stack, "][" ) . "] = '{$val[value]}';" ); + array_pop( $hash_stack ); + break; + } + } + + return $ret; +} + +/* ------------------------------------- CURL POST TO HTTPS --------------------------------- */ +function post2https( $fields_arr, $url ) { + //url-ify the data for the POST + foreach ( $fields_arr as $key => $value ) { + $fields_string .= $key . '=' . $value . '&'; + } + $fields_string = substr( $fields_string, 0, - 1 ); + + //open connection + $ch = curl_init(); + + //set the url, number of POST vars, POST data + curl_setopt( $ch, CURLOPT_URL, $url ); + curl_setopt( $ch, CURLOPT_POST, count( $fields_arr ) ); + curl_setopt( $ch, CURLOPT_POSTFIELDS, $fields_string ); + curl_setopt( $ch, CURLOPT_SSL_VERIFYPEER, false ); + curl_setopt( $ch, CURLOPT_RETURNTRANSFER, true ); + + + //execute post + $res = curl_exec( $ch ); + + //close connection + curl_close( $ch ); + + return $res; +} \ No newline at end of file diff --git a/includes/plugins/wc-gateways/wc-gateways.php b/includes/plugins/wc-gateways/wc-gateways.php index 41107e8..b87d01c 100644 --- a/includes/plugins/wc-gateways/wc-gateways.php +++ b/includes/plugins/wc-gateways/wc-gateways.php @@ -83,6 +83,7 @@ public function add_settings( $old_settings ) { 'std' => array( 'parsian', 'pasargad', 'mellat' ) ) ); + var_dump('ddddddddddddddddddddd'); return array_merge( $old_settings, $settings ); } diff --git a/includes/plugins/wc-gateways/wpp-parsian-gateway.php b/includes/plugins/wc-gateways/wpp-parsian-gateway.php new file mode 100644 index 0000000..7737a2f --- /dev/null +++ b/includes/plugins/wc-gateways/wpp-parsian-gateway.php @@ -0,0 +1,492 @@ +id = 'parsian'; + $this->gateway_name = __( 'Parsian Bank', 'wp-parsidate' ); + $this->method_title = $this->gateway_name; + $this->method_description = $this->gateway_name . ' ' . __( 'payment gateway (By WP-Parsidate)', 'wp-parsidate' ); + $this->has_fields = false; + $this->icon = apply_filters( $this->id . '_logo', WP_PARSI_URL . "assets/images/$this->id.png" ); + $this->redirect_uri = WC()->api_request_url( strtolower( get_class( $this ) ) ); + + $this->init_form_fields(); + $this->init_settings(); + + $this->parsian_login_account = $this->settings['parsian_login_account']; + $this->title = $this->settings['title']; + $this->description = $this->settings['description']; + $this->success_massage = $this->settings['success_massage']; + $this->failed_massage = $this->settings['failed_massage']; + $this->cancelled_massage = $this->settings['cancelled_massage']; + + add_action( 'woocommerce_update_options_payment_gateways_' . $this->id, array( $this, 'process_admin_options' ) ); + add_action( 'woocommerce_receipt_' . $this->id, array( $this, 'receipt_page' ) ); + add_action( 'woocommerce_api_' . strtolower( get_class( $this ) ), array( $this, 'callback' ) ); + } + + public function init_form_fields() { + $this->form_fields = apply_filters( 'wpp_wc_' . $this->id . '_gateway_config', array( + 'enabled' => array( + 'title' => __( 'Enabled/Disabled', 'wp-parsidate' ), + 'type' => 'checkbox', + /* translators: %s: Bank name */ + 'label' => sprintf( __( 'Activate or deactivate %s gateway', 'wp-parsidate' ), $this->gateway_name ), + 'default' => 'no' + ), + 'parsian_login_account' => array( + 'title' => __( 'Gateway password', 'wp-parsidate' ), + 'type' => 'text', + 'required' => true, + ), + 'title' => array( + 'title' => __( 'Gateway title', 'wp-parsidate' ), + 'type' => 'text', + 'description' => __( 'This name is displayed to the customer during the purchase process', 'wp-parsidate' ), + 'default' => $this->gateway_name + ), + 'description' => array( + 'title' => __( 'Gateway description', 'wp-parsidate' ), + 'type' => 'textarea', + 'description' => __( 'The description that will be displayed during the purchase process for the gateway', 'wp-parsidate' ), + /* translators: %s: Bank name */ + 'default' => sprintf( __( "Secure payment by all Shatab's cards through %s", 'wp-parsidate' ), $this->gateway_name ) + ), + 'success_massage' => array( + 'title' => __( 'Successful payment message', 'wp-parsidate' ), + 'type' => 'textarea', + 'description' => __( 'Enter the text of the message you want to display to the user after successful payment.', 'wp-parsidate' ), + 'default' => __( 'Thank you for your purchase. Your order has been successfully placed.', 'wp-parsidate' ) + ), + 'failed_massage' => array( + 'title' => __( 'Payment failed message', 'wp-parsidate' ), + 'type' => 'textarea', + 'description' => __( 'Enter the text of the message you want to display to the user after an unsuccessful payment.', 'wp-parsidate' ), + 'default' => __( 'Your payment has failed. Please try again or contact us in case of problems.', 'wp-parsidate' ) + ), + 'cancelled_massage' => array( + 'title' => __( 'Payment cancellation message', 'wp-parsidate' ), + 'type' => 'textarea', + 'description' => __( 'Enter the text of the message you want to display after the user cancels the payment. This message will be displayed after returning from the bank.', 'wp-parsidate' ), + 'default' => __( 'The payment remained incomplete due to your cancellation.', 'wp-parsidate' ) + ) + ) + ); + } + + public static function send_pay_request( $login_account, $amount, $order_id, $redirect, $additional = '' ) { + $args = array( + 'LoginAccount' => $login_account, + 'Amount' => $amount, + 'OrderId' => $order_id, + 'CallBackUrl' => $redirect, + 'AdditionalData' => $additional + ); + + if ( WPP_WC_Gateways::getInstance()->is_soap_enabled() ) { + try { + $client = new SoapClient( 'https://pec.shaparak.ir/NewIPGServices/Sale/SaleService.asmx?WSDL', array( 'soap_version' => 'SOAP_1_1', 'cache_wsdl' => WSDL_CACHE_NONE, 'encoding' => 'UTF-8' ) ); + $result = $client->SalePaymentRequest( array( "requestData" => $args ) ); + $output = array( + 'Status' => $result->SalePaymentRequestResult->Status, + 'Token' => $result->SalePaymentRequestResult->Token + ); + } catch ( Exception $e ) { + $output = array( 'Status' => '-1', 'Token' => '' ); + } + } else { + $output = array( 'Status' => '-2', 'Token' => '' ); + } + + return (object) $output; + } + + public static function verify_request( $login_account, $token ) { + $args = array( + 'LoginAccount' => $login_account, + 'Token' => $token + ); + if ( WPP_WC_Gateways::getInstance()->is_soap_enabled() ) { + try { + $client = new SoapClient( 'https://pec.shaparak.ir/NewIPGServices/Confirm/ConfirmService.asmx?WSDL', array( 'soap_version' => 'SOAP_1_1', 'cache_wsdl' => WSDL_CACHE_NONE, 'encoding' => 'UTF-8' ) ); + $result = $client->ConfirmPayment( array( "requestData" => $args ) ); + $output['Status'] = $result->ConfirmPaymentResult->Status; + $output['RRN'] = $result->ConfirmPaymentResult->RRN; + $output['CardNumberMasked'] = $result->ConfirmPaymentResult->CardNumberMasked ?? ''; + } catch ( Exception $e ) { + $output = array( 'Status' => '-1', 'RRN' => '' ); + } + } else { + $output = array( 'Status' => '-2', 'RRN' => '' ); + } + + return (object) $output; + } + + public static function reversal_request( $login_account, $token ) { + $args = array( + 'LoginAccount' => $login_account, + 'Token' => $token + ); + + if ( WPP_WC_Gateways::getInstance()->is_soap_enabled() ) { + try { + $client = new SoapClient( 'https://pec.shaparak.ir/NewIPGServices/Reverse/ReversalService.asmx?WSDL', array( 'soap_version' => 'SOAP_1_1', 'cache_wsdl' => WSDL_CACHE_NONE, 'encoding' => 'UTF-8' ) ); + $result = $client->ReversalRequest( array( "requestData" => $args ) ); + $output['Status'] = $result->ReversalRequestResult->Status; + $output['Token'] = $result->ReversalRequestResult->Token; + } catch ( Exception $e ) { + $output = array( 'Status' => '-1', 'Token' => '' ); + } + } else { + $output = array( 'Status' => '-2', 'Token' => '' ); + } + + return (object) $output; + } + + public static function error_response_handler( $code = '' ) { + $error_responses = array( + '-32768' => esc_html__( 'An unexpected error has occurred', 'wp-parsidate' ), + '-1552' => esc_html__( 'Transaction reversal is not allowed', 'wp-parsidate' ), + '-1551' => esc_html__( 'The transaction has already been reversed', 'wp-parsidate' ), + '-1550' => esc_html__( 'It is not possible to reverse the transaction in the current state', 'wp-parsidate' ), + '-1549' => esc_html__( 'The time allowed to request a transaction reversal has expired', 'wp-parsidate' ), + '-1548' => esc_html__( 'The bill payment request service call failed', 'wp-parsidate' ), + '-1540' => esc_html__( 'Transaction confirmation is unsuccessful', 'wp-parsidate' ), + '-1536' => esc_html__( 'The top-up charge request service call failed', 'wp-parsidate' ), + '-1533' => esc_html__( 'The transaction has already been confirmed', 'wp-parsidate' ), + '1532' => esc_html__( 'The transaction was confirmed by the recipient', 'wp-parsidate' ), + '-1531' => esc_html__( 'The transaction was unsuccessful due to your withdrawal from the bank', 'wp-parsidate' ), + '-1530' => esc_html__( 'The merchant is not authorized to confirm this transaction', 'wp-parsidate' ), + '-1528' => esc_html__( 'Payment information not found', 'wp-parsidate' ), + '-1527' => esc_html__( 'The purchase transaction payment request operation failed', 'wp-parsidate' ), + '-1507' => esc_html__( 'The transaction was sent back to the switch', 'wp-parsidate' ), + '-1505' => esc_html__( 'The transaction was confirmed by the merchant', 'wp-parsidate' ), + '-132' => esc_html__( 'The transaction amount is less than the minimum allowed', 'wp-parsidate' ), + '-131' => esc_html__( 'Token is invalid', 'wp-parsidate' ), + '-130' => esc_html__( 'Token has expired', 'wp-parsidate' ), + '-128' => esc_html__( 'The IP address format is not valid', 'wp-parsidate' ), + '-127' => esc_html__( 'The URL is not valid', 'wp-parsidate' ), + '-126' => esc_html__( "The merchant's identification code is not valid", 'wp-parsidate' ), + '-121' => esc_html__( 'The given string is not entirely numeric', 'wp-parsidate' ), + '-120' => esc_html__( 'The length of the input data is not valid', 'wp-parsidate' ), + '-119' => esc_html__( 'The organization is invalid', 'wp-parsidate' ), + '-118' => esc_html__( 'The value sent is not a number', 'wp-parsidate' ), + '-117' => esc_html__( 'The string length is less than the allowed limit', 'wp-parsidate' ), + '-116' => esc_html__( 'The length of the string exceeds the allowed limit', 'wp-parsidate' ), + '-115' => esc_html__( 'The payment ID is invalid', 'wp-parsidate' ), + '-114' => esc_html__( 'The bill ID is invalid', 'wp-parsidate' ), + '-113' => esc_html__( 'The input parameter is empty', 'wp-parsidate' ), + '-112' => esc_html__( 'The order number is duplicate', 'wp-parsidate' ), + '-111' => esc_html__( "The transaction amount is more than the merchant's limit", 'wp-parsidate' ), + '-108' => esc_html__( 'The ability to reverse the transaction is disabled for the merchant', 'wp-parsidate' ), + '-107' => esc_html__( 'The ability to send transaction confirmation is disabled for the merchant', 'wp-parsidate' ), + '-106' => esc_html__( 'Charging is disabled for the merchant', 'wp-parsidate' ), + '-105' => esc_html__( 'The top-up feature is disabled for the merchant', 'wp-parsidate' ), + '-104' => esc_html__( 'The ability to pay the bill is inactive for the merchant', 'wp-parsidate' ), + '-103' => esc_html__( 'The purchase feature is disabled for the merchant', 'wp-parsidate' ), + '-102' => esc_html__( 'The transaction was successfully rolled back', 'wp-parsidate' ), + '-101' => esc_html__( 'The merchant could not be authenticated', 'wp-parsidate' ), + '-100' => esc_html__( 'The merchant is inactive', 'wp-parsidate' ), + '-1' => esc_html__( 'Server error', 'wp-parsidate' ), + '0' => esc_html__( 'The operation is successful', 'wp-parsidate' ), + '1' => esc_html__( 'The card issuer refused to complete the transaction', 'wp-parsidate' ), + '2' => esc_html__( 'The confirmation operation of this transaction has already been done successfully', 'wp-parsidate' ), + '3' => esc_html__( 'The store merchant is invalid', 'wp-parsidate' ), + '5' => esc_html__( 'The transaction was abandoned', 'wp-parsidate' ), + '6' => esc_html__( 'An unknown error occurred', 'wp-parsidate' ), + '8' => esc_html__( 'By recognizing the identity of the card holder, the transaction is successful', 'wp-parsidate' ), + '9' => esc_html__( 'The received request is being followed up', 'wp-parsidate' ), + '10' => esc_html__( "The transaction with an amount lower than the requested amount (deficiency in the customer's account) has been accepted", 'wp-parsidate' ), + '12' => esc_html__( 'The transaction is invalid', 'wp-parsidate' ), + '13' => esc_html__( 'The transaction amount is incorrect', 'wp-parsidate' ), + '14' => esc_html__( 'The sent card number is invalid (does not exist)', 'wp-parsidate' ), + '15' => esc_html__( 'Card issuer is invalid (does not exist)', 'wp-parsidate' ), + '17' => esc_html__( 'The requesting customer has been deleted', 'wp-parsidate' ), + '20' => esc_html__( 'In a situation where the switch needs to query the card to accept the transaction, it may make a request from the card (terminal), this message indicates that the answer is invalid.', 'wp-parsidate' ), + '21' => esc_html__( 'If the response to the terminal request does not require any specific response or function, we will have this message.', 'wp-parsidate' ), + '22' => esc_html__( 'The transaction was suspected of malpractice (card, terminal, card holder), so it was not accepted', 'wp-parsidate' ), + '30' => esc_html__( 'The message format has errors', 'wp-parsidate' ), + '31' => esc_html__( 'The merchant is not supported by the switch', 'wp-parsidate' ), + '32' => esc_html__( "The transaction is incompletely completed (for example, a deposit transaction that is completed from the customer's point of view, but needs to be completed)", 'wp-parsidate' ), + '33' => esc_html__( 'The card has expired', 'wp-parsidate' ), + '38' => esc_html__( 'The number of incorrect password entries has exceeded the limit.', 'wp-parsidate' ), + '39' => esc_html__( 'There is no credit card account', 'wp-parsidate' ), + '40' => esc_html__( 'The requested operation is not supported', 'wp-parsidate' ), + '41' => esc_html__( 'The card has been declared lost', 'wp-parsidate' ), + '43' => esc_html__( 'The card has been declared stolen', 'wp-parsidate' ), + '45' => esc_html__( 'The bill can not be paid', 'wp-parsidate' ), + '51' => esc_html__( 'The account balance is insufficient', 'wp-parsidate' ), + '54' => esc_html__( 'The card has expired', 'wp-parsidate' ), + '55' => esc_html__( 'The card password is invalid', 'wp-parsidate' ), + '56' => esc_html__( 'The card is invalid', 'wp-parsidate' ), + '57' => esc_html__( 'The relevant transaction is not allowed by the card holder', 'wp-parsidate' ), + '58' => esc_html__( "It is not allowed to perform the relevant transaction by the operator's terminal", 'wp-parsidate' ), + '59' => esc_html__( 'The card is suspected of fraud', 'wp-parsidate' ), + '61' => esc_html__( 'The transaction amount is over the limit', 'wp-parsidate' ), + '62' => esc_html__( 'The card is limited', 'wp-parsidate' ), + '63' => esc_html__( 'The security measures have been violated', 'wp-parsidate' ), + '65' => esc_html__( 'The number of transaction requests exceeds the limit', 'wp-parsidate' ), + '68' => esc_html__( 'The response required to complete or complete the transaction has arrived too late', 'wp-parsidate' ), + '69' => esc_html__( 'The number of times the password has been repeated has exceeded the limit', 'wp-parsidate' ), + '75' => esc_html__( 'The number of incorrect password entries has exceeded the limit', 'wp-parsidate' ), + '78' => esc_html__( 'The card is not active', 'wp-parsidate' ), + '79' => esc_html__( 'The account connected to the card is invalid or has errors', 'wp-parsidate' ), + '80' => esc_html__( 'The transaction request has been rejected', 'wp-parsidate' ), + '81' => esc_html__( 'The card was not accepted', 'wp-parsidate' ), + '83' => esc_html__( 'The switch card service provider has not accepted the transaction', 'wp-parsidate' ), + '84' => esc_html__( 'In transactions that require communication with the exporter, if the exporter is not active, this message will be sent in response.', 'wp-parsidate' ), + '91' => esc_html__( 'The transaction authorization system is temporarily disabled or the time set for the authorization has expired', 'wp-parsidate' ), + '92' => esc_html__( 'The destination of the transaction was not found', 'wp-parsidate' ), + '93' => esc_html__( 'It is not possible to complete the transaction', 'wp-parsidate' ) + ); + + return $error_responses[ $code ] ?? esc_html__( 'The payment of the transaction was unsuccessful due to cancellation on the bank page', 'wp-parsidate' ); + } + + public static function display_error( $pay_status = '', $tran_id = '', $order_id = '', $is_callback = 1 ) { + $page_html = '
'; + $succeed_color = 'style="color:#008800"'; + $failed_color = 'style="color: #ff0000"'; + $desc_style = 'style="text-align:center;font-size:12px;margin:15px 0 20px;line-height:25px"'; + $back_to_checkout = sprintf( + ' %s
', + esc_url( wc_get_checkout_url() ), + __( 'Back to checkout', 'wp-parsidate' ) + ); + + if ( 'retry' === $pay_status ) { + $page_title = esc_html__( 'Temporary error in payment', 'wp-parsidate' ); + $order_note = esc_html__( 'When the customer returned from the bank, the bank server did not respond, the customer was asked to refresh the page', 'wp-parsidate' ); + $page_html .= '
::: ' . esc_html__( 'Temporary error in payment', 'wp-parsidate' ) . ' :::
+
' . esc_html__( 'The server of the internet portal has temporarily encountered a problem, to complete the transaction moments later, click on the button below', 'wp-parsidate' ) . '
+
+ + '; + } else { + $error_messages = array( + 'reversal_done' => array( + 'color' => $failed_color, + 'title' => esc_html__( 'Service delivery error', 'wp-parsidate' ), + /* translators: %s: Tracking number */ + 'message' => sprintf( esc_html__( 'Your payment with the tracking number %s has been successfully processed at the bank, but there has been a problem with the service', 'wp-parsidate' ), esc_html( $tran_id ) ), + 'description' => esc_html__( 'The order to return the money to your account has been registered in the bank, if the payment is not returned to your account within the next few hours, contact support (the maximum time to return to the account is 72 hours)', 'wp-parsidate' ), + 'order_note' => esc_html__( "The customer paid the amount, but when returning from the bank, there was a problem in providing the service, the order to return the money to the customer's account was registered in the bank.", 'wp-parsidate' ), + ), + 'reversal_error' => array( + 'color' => $failed_color, + 'title' => esc_html__( 'Service delivery error', 'wp-parsidate' ), + /* translators: %s: Tracking number */ + 'message' => sprintf( esc_html__( 'Your payment with the tracking number %s has been successfully made in the bank, but there is a problem in providing the service!', 'wp-parsidate' ), esc_html( $tran_id ) ), + 'description' => esc_html__( 'The order to return the money to your account has been registered in the bank, if the payment is not returned to your account within the next few hours, contact support (the maximum time to return to the account is 72 hours)', 'wp-parsidate' ), + 'order_note' => esc_html__( "The customer paid the amount, but when he returned from the bank, there was a problem in providing the service, there was an error in registering the order to return the money to the customer's account, this customer should either be provided with the service or the amount should be returned to his bank account.", 'wp-parsidate' ), + ), + 'already_been_completed' => array( + 'color' => $succeed_color, + 'title' => esc_html__( 'The order has already been paid', 'wp-parsidate' ), + /* translators: %s: Tracking number */ + 'message' => sprintf( esc_html__( 'Your order has already been successfully placed with tracking number %s', 'wp-parsidate' ), esc_html( $tran_id ) ), + 'description' => '', + 'order_note' => '' + ), + 'order_not_for_this_person' => array( + 'color' => $failed_color, + 'title' => esc_html__( 'The order number is incorrect', 'wp-parsidate' ), + 'message' => esc_html__( 'The order number is incorrect', 'wp-parsidate' ), + 'description' => esc_html__( 'The order number is incorrect; Call for support if needed', 'wp-parsidate' ), + 'order_note' => '' + ), + 'error_creating_order' => array( + 'color' => $failed_color, + 'title' => esc_html__( 'Problem with placing an order', 'wp-parsidate' ), + 'message' => esc_html__( 'The order number is incorrect', 'wp-parsidate' ), + 'description' => esc_html__( 'There is a problem with placing an order, please contact support', 'wp-parsidate' ), + 'order_note' => '' + ) + ); + + if ( array_key_exists( $pay_status, $error_messages ) ) { + $page_title = $error_messages[ $pay_status ]['title']; + $order_note = $error_messages[ $pay_status ]['order_note']; + $page_html .= sprintf( + '%s

%s
%s

%s', + $error_messages[ $pay_status ]['color'], + $page_title, + $desc_style, + $error_messages[ $pay_status ]['message'], + $error_messages[ $pay_status ]['description'], + $back_to_checkout + ); + } else if ( $is_callback == 0 ) { + $page_title = $order_note = esc_html__( 'Error sending to the bank', 'wp-parsidate' ); + $page_html .= sprintf( + '%s

%s

%s', + $failed_color, + $page_title, + $desc_style, + self::error_response_handler( $pay_status ), + $back_to_checkout + ); + } else { + $page_title = esc_html__( 'Payment was not made', 'wp-parsidate' ); + $order_note = esc_html__( 'Payment was not made', 'wp-parsidate' ) . ' - ' . self::error_response_handler( $pay_status ); + $page_html .= sprintf( + '%s

%s
%s

%s', + $failed_color, + $page_title, + $desc_style, + self::error_response_handler( $pay_status ), + esc_html__( 'If the payment has been deducted from your bank account, it will be automatically returned to your account by the bank (the final return time to the account is 72 hours) - contact support if needed.', 'wp-parsidate' ), + $back_to_checkout, + ); + } + } + + $page_html .= '
'; + $order = wc_get_order( $order_id ); + + if ( ! empty( $order ) && ! empty( $order_note ) && 'order_not_for_this_person' !== $pay_status ) { + $order->add_order_note( $order_note ); + } + + wp_die( $page_html, $page_title ); + } + + public static function redirect_to_bank( $url = '' ) { + if ( ! empty( $url ) ) { + if ( headers_sent() ) { + echo ''; + } else { + header( "Location: $url" ); + } + + exit(); + } + } + + public function process_payment( $order_id ) { + $order = wc_get_order( $order_id ); + + return array( + 'result' => 'success', + 'redirect' => $order->get_checkout_payment_url( true ) + ); + } + + public function receipt_page( $order_id ) { + if ( $order_id > 0 ) { + $order = wc_get_order( $order_id ); + $currency = strtolower( $order->get_currency() ); + $amount = absint( $order->get_total() ); + + if ( in_array( $currency, array( 'irt', 'toman', 'iran toman', 'iranian toman', 'iran-toman', 'iran_toman', 'تومان', 'تومان ایران' ) ) ) { + $amount = $amount * 10; + } else if ( 'irht' === $currency ) { + $amount = $amount * 1000 * 10; + } else if ( 'irhr' === $currency ) { + $amount = $amount * 1000; + } + + $login_account = $this->parsian_login_account; + $callback_url = $this->redirect_uri . "?order_id=" . $order_id; + $order_id = $order_id . mt_rand( 10, 100 ); + $request = self::send_pay_request( $login_account, $amount, $order_id, $callback_url ); + + if ( $request->Status == '0' && $request->Token > 0 ) { + self::redirect_to_bank( 'https://pec.shaparak.ir/NewIPG/?Token=' . $request->Token ); + + exit(); + } else { + $error_code = $request->Status; + } + } else { + $error_code = 'error_creating_order'; + } + + self::display_error( $error_code, '', $order_id, 0 ); + + return false; + } + + public function callback() { + $token = $_REQUEST['Token'] ?? ''; + $status = $_REQUEST['status'] ?? ''; + $order_id = $_REQUEST['OrderId'] ?? ''; + + if ( $status == '0' && $token > 0 ) { + if ( $order_id == substr( $order_id, 0, - 2 ) ) { + $order = wc_get_order( $order_id ); + + if ( isset( $order ) ) { + if ( 'wc-completed' === $order->get_status() ) { + $error_code = 'already_been_completed'; + } else { + $login_account = $this->parsian_login_account; + $request = self::verify_request( $login_account, $token ); + + if ( $request->Status == '0' && $request->RRN > 0 ) { + if ( $order->update_status( 'completed' ) ) { + $order->payment_complete(); + $order->add_order_note( __( 'Payment was successful.', 'wp-parsidate' ) . ' - ' . __( 'Tracking number:', 'wp-parsidate' ) . ' ' . $token, 1 ); + WC()->cart->empty_cart(); + + wp_safe_redirect( $this->get_return_url( $order ) ); + + exit(); + } else { + $reversal_request = self::reversal_request( $login_account, $token ); + + if ( $reversal_request == '0' ) { + $error_code = 'reversal_done'; + } else { + $error_code = 'reversal_error'; + } + } + } elseif ( $request->Status == '-1' ) { + $error_code = 'retry'; + } else { + $error_code = $request->Status; + } + } + } else { + $error_code = 'order_not_exist'; + } + } else { + $error_code = 'order_not_for_this_person'; + } + } else { + $error_code = $status; + } + + self::display_error( $error_code, $token, $order_id ); + + exit; + } + } + } + } + + add_action( 'plugins_loaded', 'wpp_parsian_payment_gateway_init', 0 ); +} \ No newline at end of file diff --git a/includes/plugins/wc-gateways/wpp-pasargad-gateway.php b/includes/plugins/wc-gateways/wpp-pasargad-gateway.php new file mode 100644 index 0000000..abe9f72 --- /dev/null +++ b/includes/plugins/wc-gateways/wpp-pasargad-gateway.php @@ -0,0 +1,586 @@ +id = 'pasargad'; + $this->gateway_name = __( 'Pasargad Bank', 'wp-parsidate' ); + $this->method_title = $this->gateway_name; + $this->method_description = $this->gateway_name . ' ' . __( 'payment gateway (By WP-Parsidate)', 'wp-parsidate' ); + $this->has_fields = false; + $this->icon = apply_filters( $this->id . '_logo', WP_PARSI_URL . "assets/images/$this->id.png" ); + $this->redirect_uri = WC()->api_request_url( strtolower( get_class( $this ) ) ); + + $this->init_form_fields(); + $this->init_settings(); + + $this->pasargad_terminal_id = $this->settings['pasargad_terminal_id']; + $this->pasargad_merchant_id = $this->settings['pasargad_merchant_id']; + $this->title = $this->settings['title']; + $this->description = $this->settings['description']; + $this->success_massage = $this->settings['success_massage']; + $this->failed_massage = $this->settings['failed_massage']; + $this->cancelled_massage = $this->settings['cancelled_massage']; + + add_action( 'woocommerce_update_options_payment_gateways_' . $this->id, array( $this, 'process_admin_options' ) ); + add_action( 'woocommerce_receipt_' . $this->id, array( $this, 'receipt_page' ) ); + add_action( 'woocommerce_api_' . strtolower( get_class( $this ) ), array( $this, 'callback' ) ); + } + + public function init_form_fields() { + $this->form_fields = apply_filters( 'wpp_wc_' . $this->id . '_gateway_config', array( + 'enabled' => array( + 'title' => __( 'Enabled/Disabled', 'wp-parsidate' ), + 'type' => 'checkbox', + /* translators: %s: Bank name */ + 'label' => sprintf( __( 'Activate or deactivate %s gateway', 'wp-parsidate' ), $this->gateway_name ), + 'default' => 'no' + ), + 'pasargad_terminal_id' => array( + 'title' => __( 'Terminal No.', 'wp-parsidate' ), + 'type' => 'text', + 'required' => true, + 'desc_tip' => true, + ), + 'pasargad_merchant_id' => array( + 'title' => __( 'Store No.', 'wp-parsidate' ), + 'type' => 'text', + 'required' => true, + 'desc_tip' => true, + ), + 'title' => array( + 'title' => __( 'Gateway title', 'wp-parsidate' ), + 'type' => 'text', + 'description' => __( 'This name is displayed to the customer during the purchase process', 'wp-parsidate' ), + 'default' => $this->gateway_name + ), + 'description' => array( + 'title' => __( 'Gateway description', 'wp-parsidate' ), + 'type' => 'textarea', + 'description' => __( 'The description that will be displayed during the purchase process for the gateway', 'wp-parsidate' ), + /* translators: %s: Bank name */ + 'default' => sprintf( __( "Secure payment by all Shatab's cards through %s", 'wp-parsidate' ), $this->gateway_name ) + ), + 'success_massage' => array( + 'title' => __( 'Successful payment message', 'wp-parsidate' ), + 'type' => 'textarea', + 'description' => __( 'Enter the text of the message you want to display to the user after successful payment.', 'wp-parsidate' ), + 'default' => __( 'Thank you for your purchase. Your order has been successfully placed.', 'wp-parsidate' ) + ), + 'failed_massage' => array( + 'title' => __( 'Payment failed message', 'wp-parsidate' ), + 'type' => 'textarea', + 'description' => __( 'Enter the text of the message you want to display to the user after an unsuccessful payment.', 'wp-parsidate' ), + 'default' => __( 'Your payment has failed. Please try again or contact us in case of problems.', 'wp-parsidate' ) + ), + 'cancelled_massage' => array( + 'title' => __( 'Payment cancellation message', 'wp-parsidate' ), + 'type' => 'textarea', + 'description' => __( 'Enter the text of the message you want to display after the user cancels the payment. This message will be displayed after returning from the bank.', 'wp-parsidate' ), + 'default' => __( 'The payment remained incomplete due to your cancellation.', 'wp-parsidate' ) + ) + ) + ); + } + + public static function send_pay_request( $invoice_number, $TerminalCode, $MerchantCode, $Amount, $RedirectAddress, $Mobile = '', $Email = '' ) { + require_once( WP_PARSI_DIR . 'includes/plugins/wc-gateways/lib/class-rsa.php' ); + + $processor = new RSAProcessor( WP_PARSI_DIR . 'includes/plugins/wc-gateways/lib/pasargad-certificate.xml', RSAKeyType::XMLFile ); + $data = array( + 'InvoiceNumber' => $invoice_number, + 'InvoiceDate' => parsidate( 'Y/m/d' ), + 'TerminalCode' => $TerminalCode, + 'MerchantCode' => $MerchantCode, + 'Amount' => $Amount, + 'RedirectAddress' => $RedirectAddress, + 'Timestamp' => date( 'Y/m/d H:i:s' ), + 'Action' => 1003, + 'Mobile' => $Mobile, + 'Email' => $Email + ); + + $sign_data = json_encode( $data ); + $sign_data = sha1( $sign_data, true ); + $sign_data = $processor->sign( $sign_data ); + $sign = base64_encode( $sign_data ); + + $request_args = array( + 'body' => json_encode( $data ), + 'headers' => array( + 'Content-Type' => 'application/json', + 'Sign' => $sign, + ), + 'timeout' => 30, + 'redirection' => 5, + 'blocking' => true, + ); + + $response = wp_remote_post( 'https://pep.shaparak.ir/Api/v1/Payment/GetToken', $request_args ); + + if ( is_wp_error( $response ) ) { + return false; + } + + return json_decode( wp_remote_retrieve_body( $response ) ); + } + + public static function check_transaction_result( $transaction_ref_id, $invoice_number = '', $invoice_date = '', $TerminalCode = '', $MerchantCode = '' ) { + $data = array( + 'InvoiceNumber' => $invoice_number, + 'InvoiceDate' => $invoice_date, + 'TerminalCode' => $TerminalCode, + 'MerchantCode' => $MerchantCode, + 'TransactionReferenceID' => $transaction_ref_id + ); + + $request_args = array( + 'body' => json_encode( $data ), + 'headers' => array( + 'Content-Type' => 'application/json', + ), + 'timeout' => 30, + 'redirection' => 5, + 'blocking' => true, + ); + + $response = wp_remote_post( 'https://pep.shaparak.ir/Api/v1/Payment/CheckTransactionResult', $request_args ); + + if ( is_wp_error( $response ) ) { + return false; + } + + return json_decode( wp_remote_retrieve_body( $response ) ); + } + + public static function verify_request( $invoice_number, $invoice_date, $TerminalCode, $MerchantCode, $Amount ) { + require_once( WP_PARSI_DIR . 'includes/plugins/wc-gateways/lib/class-rsa.php' ); + + $processor = new RSAProcessor( WP_PARSI_DIR . 'includes/plugins/wc-gateways/lib/pasargad-certificate.xml', RSAKeyType::XMLFile ); + $data = array( + 'InvoiceNumber' => $invoice_number, + 'InvoiceDate' => $invoice_date, + 'TerminalCode' => $TerminalCode, + 'MerchantCode' => $MerchantCode, + 'Amount' => $Amount, + 'Timestamp' => date( 'Y/m/d H:i:s' ) + ); + + $sign_data = json_encode( $data ); + $sign_data = sha1( $sign_data, true ); + $sign_data = $processor->sign( $sign_data ); + $sign = base64_encode( $sign_data ); + + $request_args = array( + 'body' => json_encode( $data ), + 'headers' => array( + 'Content-Type' => 'application/json', + 'Sign' => $sign, + ), + 'timeout' => 30, + 'redirection' => 5, + 'blocking' => true, + ); + + $response = wp_remote_post( 'https://pep.shaparak.ir/Api/v1/Payment/VerifyPayment', $request_args ); + + if ( is_wp_error( $response ) ) { + return false; + } + + return json_decode( wp_remote_retrieve_body( $response ) ); + } + + public static function reversal_request( $invoice_number, $invoice_date, $TerminalCode, $MerchantCode ) { + require_once( WP_PARSI_DIR . 'includes/plugins/wc-gateways/lib/class-rsa.php' ); + + $processor = new RSAProcessor( WP_PARSI_DIR . 'includes/plugins/wc-gateways/lib/pasargad-certificate.xml', RSAKeyType::XMLFile ); + $data = array( + 'InvoiceNumber' => $invoice_number, + 'InvoiceDate' => $invoice_date, + 'TerminalCode' => $TerminalCode, + 'MerchantCode' => $MerchantCode, + 'Timestamp' => date( 'Y/m/d H:i:s' ) + ); + + $sign_data = json_encode( $data ); + $sign_data = sha1( $sign_data, true ); + $sign_data = $processor->sign( $sign_data ); + $sign = base64_encode( $sign_data ); + + $request_args = array( + 'body' => json_encode( $data ), + 'headers' => array( + 'Content-Type' => 'application/json', + 'Sign' => $sign, + ), + 'timeout' => 30, + 'redirection' => 5, + 'blocking' => true, + ); + + $response = wp_remote_post( 'https://pep.shaparak.ir/Api/v1/Payment/RefundPayment', $request_args ); + + if ( is_wp_error( $response ) ) { + return false; + } + + return json_decode( wp_remote_retrieve_body( $response ) ); + } + + + public static function error_response_handler( $code = '' ) { + $error_responses = array( + '-32768' => esc_html__( 'An unexpected error has occurred', 'wp-parsidate' ), + '-1552' => esc_html__( 'Transaction reversal is not allowed', 'wp-parsidate' ), + '-1551' => esc_html__( 'The transaction has already been reversed', 'wp-parsidate' ), + '-1550' => esc_html__( 'It is not possible to reverse the transaction in the current state', 'wp-parsidate' ), + '-1549' => esc_html__( 'The time allowed to request a transaction reversal has expired', 'wp-parsidate' ), + '-1548' => esc_html__( 'The bill payment request service call failed', 'wp-parsidate' ), + '-1540' => esc_html__( 'Transaction confirmation is unsuccessful', 'wp-parsidate' ), + '-1536' => esc_html__( 'The top-up charge request service call failed', 'wp-parsidate' ), + '-1533' => esc_html__( 'The transaction has already been confirmed', 'wp-parsidate' ), + '1532' => esc_html__( 'The transaction was confirmed by the recipient', 'wp-parsidate' ), + '-1531' => esc_html__( 'The transaction was unsuccessful due to your withdrawal from the bank', 'wp-parsidate' ), + '-1530' => esc_html__( 'The merchant is not authorized to confirm this transaction', 'wp-parsidate' ), + '-1528' => esc_html__( 'Payment information not found', 'wp-parsidate' ), + '-1527' => esc_html__( 'The purchase transaction payment request operation failed', 'wp-parsidate' ), + '-1507' => esc_html__( 'The transaction was sent back to the switch', 'wp-parsidate' ), + '-1505' => esc_html__( 'The transaction was confirmed by the merchant', 'wp-parsidate' ), + '-132' => esc_html__( 'The transaction amount is less than the minimum allowed', 'wp-parsidate' ), + '-131' => esc_html__( 'Token is invalid', 'wp-parsidate' ), + '-130' => esc_html__( 'Token has expired', 'wp-parsidate' ), + '-128' => esc_html__( 'The IP address format is not valid', 'wp-parsidate' ), + '-127' => esc_html__( 'The URL is not valid', 'wp-parsidate' ), + '-126' => esc_html__( "The merchant's identification code is not valid", 'wp-parsidate' ), + '-121' => esc_html__( 'The given string is not entirely numeric', 'wp-parsidate' ), + '-120' => esc_html__( 'The length of the input data is not valid', 'wp-parsidate' ), + '-119' => esc_html__( 'The organization is invalid', 'wp-parsidate' ), + '-118' => esc_html__( 'The value sent is not a number', 'wp-parsidate' ), + '-117' => esc_html__( 'The string length is less than the allowed limit', 'wp-parsidate' ), + '-116' => esc_html__( 'The length of the string exceeds the allowed limit', 'wp-parsidate' ), + '-115' => esc_html__( 'The payment ID is invalid', 'wp-parsidate' ), + '-114' => esc_html__( 'The bill ID is invalid', 'wp-parsidate' ), + '-113' => esc_html__( 'The input parameter is empty', 'wp-parsidate' ), + '-112' => esc_html__( 'The order number is duplicate', 'wp-parsidate' ), + '-111' => esc_html__( "The transaction amount is more than the merchant's limit", 'wp-parsidate' ), + '-108' => esc_html__( 'The ability to reverse the transaction is disabled for the merchant', 'wp-parsidate' ), + '-107' => esc_html__( 'The ability to send transaction confirmation is disabled for the merchant', 'wp-parsidate' ), + '-106' => esc_html__( 'Charging is disabled for the merchant', 'wp-parsidate' ), + '-105' => esc_html__( 'The top-up feature is disabled for the merchant', 'wp-parsidate' ), + '-104' => esc_html__( 'The ability to pay the bill is inactive for the merchant', 'wp-parsidate' ), + '-103' => esc_html__( 'The purchase feature is disabled for the merchant', 'wp-parsidate' ), + '-102' => esc_html__( 'The transaction was successfully rolled back', 'wp-parsidate' ), + '-101' => esc_html__( 'The merchant could not be authenticated', 'wp-parsidate' ), + '-100' => esc_html__( 'The merchant is inactive', 'wp-parsidate' ), + '-1' => esc_html__( 'Server error', 'wp-parsidate' ), + '0' => esc_html__( 'The operation is successful', 'wp-parsidate' ), + '1' => esc_html__( 'The card issuer refused to complete the transaction', 'wp-parsidate' ), + '2' => esc_html__( 'The confirmation operation of this transaction has already been done successfully', 'wp-parsidate' ), + '3' => esc_html__( 'The store merchant is invalid', 'wp-parsidate' ), + '5' => esc_html__( 'The transaction was abandoned', 'wp-parsidate' ), + '6' => esc_html__( 'An unknown error occurred', 'wp-parsidate' ), + '8' => esc_html__( 'By recognizing the identity of the card holder, the transaction is successful', 'wp-parsidate' ), + '9' => esc_html__( 'The received request is being followed up', 'wp-parsidate' ), + '10' => esc_html__( "The transaction with an amount lower than the requested amount (deficiency in the customer's account) has been accepted", 'wp-parsidate' ), + '12' => esc_html__( 'The transaction is invalid', 'wp-parsidate' ), + '13' => esc_html__( 'The transaction amount is incorrect', 'wp-parsidate' ), + '14' => esc_html__( 'The sent card number is invalid (does not exist)', 'wp-parsidate' ), + '15' => esc_html__( 'Card issuer is invalid (does not exist)', 'wp-parsidate' ), + '17' => esc_html__( 'The requesting customer has been deleted', 'wp-parsidate' ), + '20' => esc_html__( 'In a situation where the switch needs to query the card to accept the transaction, it may make a request from the card (terminal), this message indicates that the answer is invalid.', 'wp-parsidate' ), + '21' => esc_html__( 'If the response to the terminal request does not require any specific response or function, we will have this message.', 'wp-parsidate' ), + '22' => esc_html__( 'The transaction was suspected of malpractice (card, terminal, card holder), so it was not accepted', 'wp-parsidate' ), + '30' => esc_html__( 'The message format has errors', 'wp-parsidate' ), + '31' => esc_html__( 'The merchant is not supported by the switch', 'wp-parsidate' ), + '32' => esc_html__( "The transaction is incompletely completed (for example, a deposit transaction that is completed from the customer's point of view, but needs to be completed)", 'wp-parsidate' ), + '33' => esc_html__( 'The card has expired', 'wp-parsidate' ), + '38' => esc_html__( 'The number of incorrect password entries has exceeded the limit.', 'wp-parsidate' ), + '39' => esc_html__( 'There is no credit card account', 'wp-parsidate' ), + '40' => esc_html__( 'The requested operation is not supported', 'wp-parsidate' ), + '41' => esc_html__( 'The card has been declared lost', 'wp-parsidate' ), + '43' => esc_html__( 'The card has been declared stolen', 'wp-parsidate' ), + '45' => esc_html__( 'The bill can not be paid', 'wp-parsidate' ), + '51' => esc_html__( 'The account balance is insufficient', 'wp-parsidate' ), + '54' => esc_html__( 'The card has expired', 'wp-parsidate' ), + '55' => esc_html__( 'The card password is invalid', 'wp-parsidate' ), + '56' => esc_html__( 'The card is invalid', 'wp-parsidate' ), + '57' => esc_html__( 'The relevant transaction is not allowed by the card holder', 'wp-parsidate' ), + '58' => esc_html__( "It is not allowed to perform the relevant transaction by the operator's terminal", 'wp-parsidate' ), + '59' => esc_html__( 'The card is suspected of fraud', 'wp-parsidate' ), + '61' => esc_html__( 'The transaction amount is over the limit', 'wp-parsidate' ), + '62' => esc_html__( 'The card is limited', 'wp-parsidate' ), + '63' => esc_html__( 'The security measures have been violated', 'wp-parsidate' ), + '65' => esc_html__( 'The number of transaction requests exceeds the limit', 'wp-parsidate' ), + '68' => esc_html__( 'The response required to complete or complete the transaction has arrived too late', 'wp-parsidate' ), + '69' => esc_html__( 'The number of times the password has been repeated has exceeded the limit', 'wp-parsidate' ), + '75' => esc_html__( 'The number of incorrect password entries has exceeded the limit', 'wp-parsidate' ), + '78' => esc_html__( 'The card is not active', 'wp-parsidate' ), + '79' => esc_html__( 'The account connected to the card is invalid or has errors', 'wp-parsidate' ), + '80' => esc_html__( 'The transaction request has been rejected', 'wp-parsidate' ), + '81' => esc_html__( 'The card was not accepted', 'wp-parsidate' ), + '83' => esc_html__( 'The switch card service provider has not accepted the transaction', 'wp-parsidate' ), + '84' => esc_html__( 'In transactions that require communication with the exporter, if the exporter is not active, this message will be sent in response.', 'wp-parsidate' ), + '91' => esc_html__( 'The transaction authorization system is temporarily disabled or the time set for the authorization has expired', 'wp-parsidate' ), + '92' => esc_html__( 'The destination of the transaction was not found', 'wp-parsidate' ), + '93' => esc_html__( 'It is not possible to complete the transaction', 'wp-parsidate' ) + ); + + return $error_responses[ $code ] ?? esc_html__( 'The payment of the transaction was unsuccessful due to cancellation on the bank page', 'wp-parsidate' ); + } + + + public static function display_error( $pay_status = '', $tran_id = '', $order_id = '', $is_callback = 1 ) { + $page_html = '
'; + $succeed_color = 'style="color:#008800"'; + $failed_color = 'style="color: #ff0000"'; + $desc_style = 'style="text-align:center;font-size:12px;margin:15px 0 20px;line-height:25px"'; + $back_to_checkout = sprintf( + '%s
', + esc_url( wc_get_checkout_url() ), + __( 'Back to checkout', 'wp-parsidate' ) + ); + + if ( 'retry' === $pay_status ) { + $page_title = esc_html__( 'Temporary error in payment', 'wp-parsidate' ); + $order_note = esc_html__( 'When the customer returned from the bank, the bank server did not respond, the customer was asked to refresh the page', 'wp-parsidate' ); + $page_html .= '
::: ' . esc_html__( 'Temporary error in payment', 'wp-parsidate' ) . ' :::
+
' . esc_html__( 'The server of the internet portal has temporarily encountered a problem, to complete the transaction moments later, click on the button below', 'wp-parsidate' ) . '
+
+ + '; + } else { + $error_messages = array( + 'reversal_done' => array( + 'color' => $failed_color, + 'title' => esc_html__( 'Service delivery error', 'wp-parsidate' ), + /* translators: %s: Tracking number */ + 'message' => sprintf( esc_html__( 'Your payment with the tracking number %s has been successfully processed at the bank, but there has been a problem with the service', 'wp-parsidate' ), esc_html( $tran_id ) ), + 'description' => esc_html__( 'The order to return the money to your account has been registered in the bank, if the payment is not returned to your account within the next few hours, contact support (the maximum time to return to the account is 72 hours)', 'wp-parsidate' ), + 'order_note' => esc_html__( "The customer paid the amount, but when returning from the bank, there was a problem in providing the service, the order to return the money to the customer's account was registered in the bank.", 'wp-parsidate' ), + ), + 'reversal_error' => array( + 'color' => $failed_color, + 'title' => esc_html__( 'Service delivery error', 'wp-parsidate' ), + /* translators: %s: Tracking number */ + 'message' => sprintf( esc_html__( 'Your payment with the tracking number %s has been successfully made in the bank, but there is a problem in providing the service!', 'wp-parsidate' ), esc_html( $tran_id ) ), + 'description' => esc_html__( 'The order to return the money to your account has been registered in the bank, if the payment is not returned to your account within the next few hours, contact support (the maximum time to return to the account is 72 hours)', 'wp-parsidate' ), + 'order_note' => esc_html__( "The customer paid the amount, but when he returned from the bank, there was a problem in providing the service, there was an error in registering the order to return the money to the customer's account, this customer should either be provided with the service or the amount should be returned to his bank account.", 'wp-parsidate' ), + ), + 'already_been_completed' => array( + 'color' => $succeed_color, + 'title' => esc_html__( 'The order has already been paid', 'wp-parsidate' ), + /* translators: %s: Tracking number */ + 'message' => sprintf( esc_html__( 'Your order has already been successfully placed with tracking number %s', 'wp-parsidate' ), esc_html( $tran_id ) ), + 'description' => '', + 'order_note' => '' + ), + 'order_not_for_this_person' => array( + 'color' => $failed_color, + 'title' => esc_html__( 'The order number is incorrect', 'wp-parsidate' ), + 'message' => esc_html__( 'The order number is incorrect', 'wp-parsidate' ), + 'description' => esc_html__( 'The order number is incorrect; Call for support if needed', 'wp-parsidate' ), + 'order_note' => '' + ), + 'error_creating_order' => array( + 'color' => $failed_color, + 'title' => esc_html__( 'Problem with placing an order', 'wp-parsidate' ), + 'message' => esc_html__( 'The order number is incorrect', 'wp-parsidate' ), + 'description' => esc_html__( 'There is a problem with placing an order, please contact support', 'wp-parsidate' ), + 'order_note' => '' + ) + ); + + if ( array_key_exists( $pay_status, $error_messages ) ) { + $page_title = $error_messages[ $pay_status ]['title']; + $order_note = $error_messages[ $pay_status ]['order_note']; + $page_html .= sprintf( + '%s

%s
%s

%s', + $error_messages[ $pay_status ]['color'], + $page_title, + $desc_style, + $error_messages[ $pay_status ]['message'], + $error_messages[ $pay_status ]['description'], + $back_to_checkout + ); + } else if ( $is_callback == 0 ) { + $page_title = $order_note = esc_html__( 'Error sending to the bank', 'wp-parsidate' ); + $page_html .= sprintf( + '%s

%s

%s', + $failed_color, + $page_title, + $desc_style, + self::error_response_handler( $pay_status ), + $back_to_checkout + ); + } else { + $page_title = esc_html__( 'Payment was not made', 'wp-parsidate' ); + $order_note = esc_html__( 'Payment was not made', 'wp-parsidate' ) . ' - ' . self::error_response_handler( $pay_status ); + $page_html .= sprintf( + '%s

%s
%s

%s', + $failed_color, + $page_title, + $desc_style, + self::error_response_handler( $pay_status ), + esc_html__( 'If the payment has been deducted from your bank account, it will be automatically returned to your account by the bank (the final return time to the account is 72 hours) - contact support if needed.', 'wp-parsidate' ), + $back_to_checkout, + ); + } + } + + $page_html .= '
'; + + if ( ! empty( $order_id ) && ! empty( $order_note ) && 'order_not_for_this_person' !== $pay_status ) { + $order = wc_get_order( $order_id ); + + $order->add_order_note( $order_note ); + } + + wp_die( $page_html, $page_title ); + } + + public static function redirect_to_bank( $url = '' ) { + if ( $url != '' ) { + if ( headers_sent() ) { + echo ''; + } else { + header( "Location: $url" ); + } + + exit(); + } + } + + public function process_payment( $order_id ) { + $order = wc_get_order( $order_id ); + + return array( + 'result' => 'success', + 'redirect' => $order->get_checkout_payment_url( true ) + ); + } + + public function receipt_page( $order_id ) { + if ( $order_id > 0 ) { + $order = wc_get_order( $order_id ); + $currency = strtolower( $order->get_currency() ); + $amount = absint( $order->get_total() ); + + if ( in_array( $currency, array( 'irt', 'toman', 'iran toman', 'iranian toman', 'iran-toman', 'iran_toman', 'تومان', 'تومان ایران' ) ) ) { + $amount = $amount * 10; + } else if ( 'irht' === $currency ) { + $amount = $amount * 1000 * 10; + } else if ( 'irhr' === $currency ) { + $amount = $amount * 1000; + } + + $terminal_id = $this->pasargad_terminal_id; + $merchant_id = $this->pasargad_merchant_id; + $callback_url = $this->redirect_uri . "?order_id=" . $order_id; + $order_id = $order_id . mt_rand( 10, 100 ); + $request = self::send_pay_request( $order_id, $terminal_id, $merchant_id, $amount, $callback_url ); + + if ( isset( $request ) && $request->IsSuccess ) { + self::redirect_to_bank( 'https://pep.shaparak.ir/payment.aspx?n=' . $request->Token ); + + exit; + } else { + + self::display_error( '', '', $order_id, 0 ); + } + } else { + self::display_error( 'error_creating_order', '', $order_id, 0 ); + } + + return false; + } + + public function callback() { + $order_id = $_GET['order_id'] ?? ''; + $transaction_ref_id = $_REQUEST['tref'] ?? ''; + $invoice_number = $_REQUEST['iN'] ?? ''; + $invoice_date = $_REQUEST['iD'] ?? ''; + $terminal_id = $this->pasargad_terminal_id; + $merchant_id = $this->pasargad_merchant_id; + + if ( $order_id == substr( $invoice_number, 0, - 2 ) ) { + $order = wc_get_order( $order_id ); + + if ( $order ) { + if ( 'wc-completed' === $order->get_status() ) { + $error_code = 'already_been_completed'; + } else { + if ( $transaction_ref_id != '' ) { + $check_result = self::check_transaction_result( $transaction_ref_id ); + } else { + $check_result = self::check_transaction_result( null, $invoice_number, $invoice_date, $terminal_id, $merchant_id ); + } + + if ( isset( $check_result ) && $check_result->IsSuccess && $check_result->InvoiceNumber == $invoice_number ) { + $amount = $check_result->Amount; + $request = self::verify_request( $invoice_number, $invoice_date, $terminal_id, $merchant_id, $amount ); + + if ( isset( $request ) && $request->IsSuccess ) { + if ( $order->update_status( 'processing' ) ) { + $order->payment_complete(); + $order->add_order_note( 'پرداخت شما با موفقیت با شماره پیگیری ' . $transaction_ref_id . ' انجام شد.', 1 ); + + WC()->cart->empty_cart(); + + wp_safe_redirect( $this->get_return_url( $order ) ); + + exit(); + } else { + $reversal_request = self::reversal_request( $invoice_number, $invoice_date, $terminal_id, $merchant_id ); + + if ( isset( $reversal_request ) && $reversal_request->IsSuccess ) { + $error_code = 'reversal_done'; + } else { + $error_code = 'reversal_error'; + } + } + } else { + $message = $request->Message; + } + } else { + $message = 'پرداخت توسط شما انجام نشده است ، در صورت نیاز با پشتیبانی تماس بگیرید'; + } + } + } else { + $error_code = 'order_not_exist'; + } + } else { + $error_code = 'order_not_for_this_person'; + } + + self::display_error( $error_code ?? null, $transaction_ref_id, 1, $message ?? '' ); + + exit; + } + } + } + } + + add_action( 'plugins_loaded', 'wpp_pasargad_payment_gateway_init' ); +} \ No newline at end of file diff --git a/includes/plugins/woocommerce.php b/includes/plugins/woocommerce.php index 8c59afc..6fb902d 100644 --- a/includes/plugins/woocommerce.php +++ b/includes/plugins/woocommerce.php @@ -16,6 +16,8 @@ class WPP_WooCommerce { * Hooks required tags */ private function __construct() { + $this->include_files(); + add_filter( 'wpp_plugins_compatibility_settings', array( $this, 'add_settings' ) ); if ( class_exists( 'WooCommerce' ) && get_locale() === 'fa_IR' ) { @@ -30,7 +32,9 @@ private function __construct() { add_filter( 'woocommerce_cart_total', 'fix_number' ); } - if ( wpp_is_active( 'woo_fix_date' ) ) { + if ( wpp_is_active( 'persian_date' ) ) { + add_action( 'wp_head', array( $this, 'fix_wc_date_time_direction' ) ); + add_filter( 'woocommerce_email_styles', array( $this, 'fix_emails_order_date_direction' ), 9999, 2 ); // Jalali datepicker add_action( 'admin_enqueue_scripts', array( $this, 'wpp_admin_woocommerce_jalali_datepicker_assets' ) ); @@ -46,7 +50,6 @@ private function __construct() { } add_filter( 'woocommerce_checkout_process', array( $this, 'wpp_accept_persian_numbers_in_checkout' ), 20 ); - add_filter( 'woocommerce_checkout_posted_data', array( $this, 'wpp_convert_non_persian_values_in_checkout' ), 10 ); if ( wpp_is_active( 'woo_validate_postcode' ) ) { @@ -56,15 +59,6 @@ private function __construct() { if ( wpp_is_active( 'woo_validate_phone' ) ) { add_action( 'woocommerce_after_checkout_validation', array( $this, 'wpp_validate_phone_number' ), 10, 2 ); } - - if ( wpp_is_active( 'woo_dropdown_cities' ) ) { - include_once WP_PARSI_DIR . 'includes/plugins/wc-cities/wc-city-select.php'; - } - - if ( get_locale() == 'fa_IR' && wpp_is_active( 'persian_date' ) ) { - add_filter( 'woocommerce_email_styles', array( $this, 'fix_emails_order_date_direction' ), 9999, 2 ); - add_action( 'woocommerce_before_account_navigation', array( $this, 'fix_myaccount_order_date_direction' ) ); - } } } @@ -81,6 +75,20 @@ public static function getInstance() { return self::$instance; } + /** + * Includes files for WooCommerce payment gateways + * + * @return void + * @since 4.0.1 + */ + public function include_files() { + if ( wpp_is_active( 'woo_dropdown_cities' ) ) { + include_once WP_PARSI_DIR . 'includes/plugins/wc-cities/wc-city-select.php'; + } + + require_once( WP_PARSI_DIR . 'includes/plugins/wc-gateways/wc-gateways.php' ); + } + /** * Adds settings for toggle fixing * @@ -90,19 +98,12 @@ public static function getInstance() { * @since 4.0.0 */ public function add_settings( $old_settings ) { - $settings = array( + $settings = apply_filters( 'wpp_woocommerce_settings', array( 'woocommerce' => array( 'id' => 'woocommerce', 'name' => __( 'WooCommerce', 'wp-parsidate' ), 'type' => 'header' ), - 'woo_fix_date' => array( - 'id' => 'woo_fix_date', - 'name' => __( 'Jalali Datepicker', 'wp-parsidate' ), - 'type' => 'checkbox', - 'options' => 1, - 'std' => 0 - ), 'woo_per_price' => array( 'id' => 'woo_per_price', 'name' => __( 'Fix prices', 'wp-parsidate' ), @@ -144,8 +145,8 @@ public function add_settings( $old_settings ) { 'type' => 'checkbox', 'options' => 1, 'std' => 0 - ) - ); + ), + ) ); return array_merge( $old_settings, $settings ); } @@ -167,7 +168,7 @@ public function wpp_admin_woocommerce_jalali_datepicker_assets() { $suffix = defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG || wpp_is_active( 'dev_mode' ) ? '' : '.min'; $current_screen = $screen->post_type; - if ( wpp_is_active( 'woo_fix_date' ) && in_array( $current_screen, array( 'product', 'shop_order', 'shop_coupon', 'wc-reports' ) ) ) { + if ( wpp_is_active( 'persian_date' ) && in_array( $current_screen, array( 'product', 'shop_order', 'shop_coupon', 'wc-reports' ) ) ) { wp_enqueue_script( 'wpp_jalali_datepicker', WP_PARSI_URL . 'assets/js/jalalidatepicker.min.js', array( 'jquery', 'jquery-ui-datepicker' ), WP_PARSI_VER ); wp_enqueue_style( 'wpp_jalali_datepicker', WP_PARSI_URL . "assets/css/jalalidatepicker$suffix.css", null, WP_PARSI_VER ); @@ -548,8 +549,10 @@ public function fix_emails_order_date_direction( $style, $email ) { * @return void * @since 5.0.0 */ - public function fix_myaccount_order_date_direction() { - echo ''; + public function fix_wc_date_time_direction() { + if ( is_woocommerce() || is_wc_endpoint_url() || is_cart() || is_checkout() ) { + echo ''; + } } } diff --git a/includes/settings.php b/includes/settings.php index 794ba7d..0347454 100644 --- a/includes/settings.php +++ b/includes/settings.php @@ -6,6 +6,7 @@ * Originally, wrote by Pippin Williamson * * @author Pippin Williamson + * @author Hamid Reza Yazdani * @author Ehsaan * @author Morteza Geransayeh * @author Mobin Ghasempoor @@ -96,7 +97,7 @@ function wpp_register_settings() { ); foreach ( $settings as $option ) { - $name = isset( $option['name'] ) ? $option['name'] : ''; + $name = $option['name'] ?? ''; add_settings_field( 'wpp_settings[' . $option['id'] . ']', @@ -105,13 +106,13 @@ function_exists( 'wpp_' . $option['type'] . '_callback' ) ? 'wpp_' . $option['ty 'wpp_settings_' . $tab, 'wpp_settings_' . $tab, array( - 'id' => isset( $option['id'] ) ? $option['id'] : null, + 'id' => $option['id'] ?? null, 'desc' => ! empty( $option['desc'] ) ? $option['desc'] : '', - 'name' => isset( $option['name'] ) ? $option['name'] : null, + 'name' => $option['name'] ?? null, 'section' => $tab, - 'size' => isset( $option['size'] ) ? $option['size'] : null, - 'options' => isset( $option['options'] ) ? $option['options'] : '', - 'std' => isset( $option['std'] ) ? $option['std'] : '' + 'size' => $option['size'] ?? null, + 'options' => $option['options'] ?? '', + 'std' => $option['std'] ?? '' ) ); @@ -155,14 +156,14 @@ function wpp_settings_sanitize( $input = array() ) { parse_str( $_POST['_wp_http_referer'], $referrer ); $settings = wpp_get_registered_settings(); - $tab = isset( $referrer['tab'] ) ? $referrer['tab'] : 'core'; + $tab = $referrer['tab'] ?? 'core'; $input = $input ?: array(); $input = apply_filters( 'wpp_settings_' . $tab . '_sanitize', $input ); // Loop through each setting being saved and pass it through a sanitization filter foreach ( $input as $key => $value ) { // Get the setting type (checkbox, select, etc.) - $type = isset( $settings[ $tab ][ $key ]['type'] ) ? $settings[ $tab ][ $key ]['type'] : false; + $type = $settings[ $tab ][ $key ]['type'] ?? false; if ( $type ) { // Field type specific filter @@ -181,7 +182,7 @@ function wpp_settings_sanitize( $input = array() ) { $key = $value['id']; } - if ( empty( $input[ $key ] ) ) { + if ( ! isset( $input[ $key ] ) ) { unset( $wpp_settings[ $key ] ); } } @@ -198,11 +199,6 @@ function wpp_settings_sanitize( $input = array() ) { * @since 2.0 */ function wpp_get_registered_settings() { - $options = array( - 'enable' => __( 'Enable', 'wp-parsidate' ), - 'disable' => __( 'Disable', 'wp-parsidate' ) - ); - return apply_filters( 'wpp_registered_settings', array( 'core' => apply_filters( 'wpp_core_settings', array( 'admin_lang' => array( @@ -374,38 +370,50 @@ function wpp_header_callback( $args ) { } /** + * Generates checkbox field + * * @param $args */ function wpp_checkbox_callback( $args ) { global $wpp_settings; - $checked = isset( $wpp_settings[ $args['id'] ] ) ? checked( 'enable', $wpp_settings[ $args['id'] ], false ) : ''; - $html = sprintf( '' . - '', - $args['id'], + if ( isset( $wpp_settings[ $args['id'] ] ) ) { + $checked = ! is_array( $wpp_settings[ $args['id'] ] ) ? checked( 'enable', $wpp_settings[ $args['id'] ], false ) : checked( 'enable', $wpp_settings[ $args['parent'] ][ $args['id'] ], false ); + } else { + $checked = ''; + } + $is_multiple = ! empty( $args['is_multiple'] ) ? ' checkbox-list' : ''; + $html = sprintf( '' . + '', + ! $is_multiple ? '[' . $args['id'] . ']' : '[' . $args['parent'] . '][' . $args['id'] . ']', $checked, empty( $args['desc'] ) ? 'empty-label' : '', - $args['desc'] + $is_multiple, + $args['desc'], ); echo $html; } /** + * Generates multiple checkboxes fields + * * @param $args */ function wpp_multicheck_callback( $args ) { - $html = ''; - - foreach ( $args['options'] as $key => $value ) { - $option_name = $args['id'] . '-' . $key; + global $wpp_settings; - wpp_checkbox_callback( array( - 'id' => $option_name, - 'desc' => $value - ) ); + $html = ''; - echo '
'; + foreach ( $args['options'] as $key => $option ) { + $html .= sprintf( + '', + $args['id'], + $key, + in_array( $key, $wpp_settings[ $args['id'] ] ) ? 'checked="checked"' : '', + $option, + $args['desc'] + ); } echo $html; @@ -439,15 +447,10 @@ function wpp_radio_callback( $args ) { function wpp_text_callback( $args ) { global $wpp_settings; - if ( isset( $wpp_settings[ $args['id'] ] ) ) { - $value = $wpp_settings[ $args['id'] ]; - } else { - $value = isset( $args['std'] ) ? $args['std'] : ''; - } - - $size = ( isset( $args['size'] ) ) ? $args['size'] : 'regular'; - $html = ''; - $html .= ''; + $value = $wpp_settings[ $args['id'] ] ?? $args['std'] ?? ''; + $size = ( isset( $args['size'] ) ) ? $args['size'] : 'regular'; + $html = ''; + $html .= ''; echo $html; } @@ -458,18 +461,13 @@ function wpp_text_callback( $args ) { function wpp_number_callback( $args ) { global $wpp_settings; - if ( isset( $wpp_settings[ $args['id'] ] ) ) { - $value = $wpp_settings[ $args['id'] ]; - } else { - $value = isset( $args['std'] ) ? $args['std'] : ''; - } - - $max = isset( $args['max'] ) ? $args['max'] : 999999; - $min = isset( $args['min'] ) ? $args['min'] : 0; - $step = isset( $args['step'] ) ? $args['step'] : 1; - $size = ( isset( $args['size'] ) ) ? $args['size'] : 'regular'; - $html = ''; - $html .= ''; + $value = $wpp_settings[ $args['id'] ] ?? $args['std'] ?? ''; + $max = $args['max'] ?? 999999; + $min = $args['min'] ?? 0; + $step = $args['step'] ?? 1; + $size = ( isset( $args['size'] ) ) ? $args['size'] : 'regular'; + $html = ''; + $html .= ''; echo $html; } @@ -480,15 +478,10 @@ function wpp_number_callback( $args ) { function wpp_textarea_callback( $args ) { global $wpp_settings; - if ( isset( $wpp_settings[ $args['id'] ] ) ) { - $value = $wpp_settings[ $args['id'] ]; - } else { - $value = isset( $args['std'] ) ? $args['std'] : ''; - } - - $size = ( isset( $args['size'] ) ) ? $args['size'] : 'regular'; - $html = ''; - $html .= ''; + $value = $wpp_settings[ $args['id'] ] ?? $args['std'] ?? ''; + $size = ( isset( $args['size'] ) ) ? $args['size'] : 'regular'; + $html = ''; + $html .= ''; echo $html; } @@ -499,15 +492,10 @@ function wpp_textarea_callback( $args ) { function wpp_password_callback( $args ) { global $wpp_settings; - if ( isset( $wpp_settings[ $args['id'] ] ) ) { - $value = $wpp_settings[ $args['id'] ]; - } else { - $value = isset( $args['std'] ) ? $args['std'] : ''; - } - - $size = ( isset( $args['size'] ) ) ? $args['size'] : 'regular'; - $html = ''; - $html .= ''; + $value = $wpp_settings[ $args['id'] ] ?? $args['std'] ?? ''; + $size = ( isset( $args['size'] ) ) ? $args['size'] : 'regular'; + $html = ''; + $html .= ''; echo $html; } @@ -523,20 +511,14 @@ function wpp_missing_callback( $args ) { return false; } - /** * @param $args */ function wpp_select_callback( $args ) { global $wpp_settings; - if ( isset( $wpp_settings[ $args['id'] ] ) ) { - $value = $wpp_settings[ $args['id'] ]; - } else { - $value = isset( $args['std'] ) ? $args['std'] : ''; - } - - $html = ''; foreach ( $args['options'] as $option => $name ) : $selected = selected( $option, $value, false ); @@ -555,13 +537,8 @@ function wpp_select_callback( $args ) { function wpp_color_select_callback( $args ) { global $wpp_settings; - if ( isset( $wpp_settings[ $args['id'] ] ) ) { - $value = $wpp_settings[ $args['id'] ]; - } else { - $value = isset( $args['std'] ) ? $args['std'] : ''; - } - - $html = ''; foreach ( $args['options'] as $option => $color ) : $selected = selected( $option, $value, false ); @@ -580,11 +557,7 @@ function wpp_color_select_callback( $args ) { function wpp_rich_editor_callback( $args ) { global $wpp_settings, $wp_version; - if ( isset( $wpp_settings[ $args['id'] ] ) ) { - $value = $wpp_settings[ $args['id'] ]; - } else { - $value = isset( $args['std'] ) ? $args['std'] : ''; - } + $value = $wpp_settings[ $args['id'] ] ?? $args['std'] ?? ''; if ( $wp_version >= 3.3 && function_exists( 'wp_editor' ) ) { ob_start(); @@ -609,16 +582,11 @@ function wpp_rich_editor_callback( $args ) { function wpp_upload_callback( $args ) { global $wpp_settings; - if ( isset( $wpp_settings[ $args['id'] ] ) ) { - $value = $wpp_settings[ $args['id'] ]; - } else { - $value = isset( $args['std'] ) ? $args['std'] : ''; - } - - $size = ( isset( $args['size'] ) ) ? $args['size'] : 'regular'; - $html = ''; - $html .= ' '; - $html .= ''; + $value = $wpp_settings[ $args['id'] ] ?? $args['std'] ?? ''; + $size = ( isset( $args['size'] ) ) ? $args['size'] : 'regular'; + $html = ''; + $html .= ' '; + $html .= ''; echo $html; } @@ -629,13 +597,8 @@ function wpp_upload_callback( $args ) { function wpp_color_callback( $args ) { global $wpp_settings; - if ( isset( $wpp_settings[ $args['id'] ] ) ) { - $value = $wpp_settings[ $args['id'] ]; - } else { - $value = isset( $args['std'] ) ? $args['std'] : ''; - } - - $default = isset( $args['std'] ) ? $args['std'] : ''; + $value = $wpp_settings[ $args['id'] ] ?? $args['std'] ?? ''; + $default = $args['std'] ?? ''; $size = ( isset( $args['size'] ) ) ? $args['size'] : 'regular'; $html = ''; $html .= '';