<?php
/*
 * Class to handle Server Integration Method (SIM) payemtn
 */
class RM_Anet_Sim
{
     protected $msg = array();
     private $rm_anet;
     private $live_url;
     private $test_url;
     
     public function __construct(){
         $this->rm_anet= rm_anet();
         $this->live_url          = 'https://accept.authorize.net/payment/payment';
         $this->test_url          = 'https://test.authorize.net/payment/payment';
     }
      
     /**
       * Check for valid Authorize.net server callback to validate the transaction response.
      **/
      function check_authorize_response()
      {
        $options= new RM_Anet_Options();
        
        if (count($_POST)){
            if(!isset($_SERVER['REQUEST_METHOD']) || strtoupper($_SERVER['REQUEST_METHOD']) !== 'POST'){
                return;
            }
            $is_authnet_request = (isset($_POST['action']) && sanitize_text_field(wp_unslash($_POST['action'])) === 'rm_authnet_ipn')
                                || isset($_POST['x_invoice_num'], $_POST['log_id'])
                                || isset($_POST['x_trans_id']);
            if(!isset($_POST['x_invoice_num'], $_POST['log_id'], $_POST['sub_id'], $_POST['x_trans_id'])){
                if($is_authnet_request)
                    $this->send_authorize_response(false);
                return;
            }
            
            $log_id = absint($_POST['log_id']);
            $sub_id = absint($_POST['sub_id']);
            $x_invoice_num = sanitize_text_field(wp_unslash($_POST['x_invoice_num']));
            $x_trans_id = sanitize_text_field(wp_unslash($_POST['x_trans_id']));
            if(!$log_id || !$sub_id || !$x_invoice_num || !$x_trans_id){
                $this->send_authorize_response(false);
            }
            
            $log = RM_DBManager::get_row('PAYPAL_LOGS', $log_id);
            if(empty($log) || $log->invoice != $x_invoice_num || absint($log->submission_id) !== $sub_id || $log->pay_proc !== 'anet_sim'){
                $this->send_authorize_response(false);
            }
            
            $current_status = strtolower((string)$log->status);
            if($current_status === 'completed'){
                if((string)$log->txn_id === (string)$x_trans_id){
                    $this->send_authorize_response(true, $log);
                }
                $this->send_authorize_response(false);
            }
            if($current_status !== 'pending'){
                $this->send_authorize_response(false);
            }

            $ex_data = maybe_unserialize($log->ex_data);
            $user_id = (int)$ex_data['user_id'];
            $form_id = $log->form_id;
            $form = new RM_Forms;
            $form->load_from_db($form_id);
            
            $verified_transaction = $this->verify_authorize_transaction($x_trans_id, $log, $options);
            if(!$verified_transaction){
                $this->send_authorize_response(false);
            }
            
            $curr_date = RM_Utilities::get_current_time(); // date_i18n(get_option('date_format'));
            $log_array = maybe_serialize($verified_transaction);
            
            if($form->form_options->user_auto_approval == 'default'){
                $check_setting = $options->get_value_of('user_auto_approval');
            } else {
                $check_setting = $form->form_options->user_auto_approval;
            }

            if ($user_id && $check_setting == "yes"){
                $user_service = new RM_User_Services();
                $user_service->activate_user_by_id($user_id);
            }
            
            if (!is_user_logged_in() && $form->form_options->auto_login)
            {
                $_SESSION['RM_SLI_UID'] = $user_id;     
            }
            
                RM_DBManager::update_row('PAYPAL_LOGS', $log_id, array(
                    'status' => 'completed',
                    'txn_id' => $x_trans_id,
                    'posted_date' => $curr_date,
                    'log' => $log_array), array('%s', '%s', '%s', '%s'));

            $this->send_authorize_response(true, $log);
        }
        
      }
      
      private function verify_authorize_transaction($trans_id, $log, RM_Anet_Options $options)
      {
          $login_id = $options->get_value_of('anet_login_id');
          $trans_key = $options->get_value_of('anet_trans_key');
          if(empty($login_id) || empty($trans_key))
              return false;
          
          $request = new SimpleXMLElement('<?xml version="1.0" encoding="utf-8"?><getTransactionDetailsRequest xmlns="AnetApi/xml/v1/schema/AnetApiSchema.xsd"></getTransactionDetailsRequest>');
          $merchant_authentication = $request->addChild('merchantAuthentication');
          $merchant_authentication->addChild('name', $login_id);
          $merchant_authentication->addChild('transactionKey', $trans_key);
          $request->addChild('transId', $trans_id);
          
          $url = $options->get_value_of('anet_test_mode') == 'yes' ? 'https://apitest.authorize.net/xml/v1/request.api' : 'https://api.authorize.net/xml/v1/request.api';
          $response = wp_remote_post($url, array(
              'headers' => array('Content-Type' => 'application/xml'),
              'body' => $request->asXML(),
              'timeout' => 45,
              'sslverify' => true,
          ));
          
          if(is_wp_error($response))
              return false;
          if(wp_remote_retrieve_response_code($response) !== 200)
              return false;
          
          $body = wp_remote_retrieve_body($response);
          if(empty($body))
              return false;
          
          $body = str_replace('xmlns="AnetApi/xml/v1/schema/AnetApiSchema.xsd"', '', $body);
          $transaction_response = simplexml_load_string($body);
          if(!$transaction_response || (string)$transaction_response->messages->resultCode !== 'Ok' || empty($transaction_response->transaction))
              return false;
          
          $transaction = $transaction_response->transaction;
          $transaction_id = (string)$transaction->transId;
          $invoice_num = (string)$transaction->order->invoiceNumber;
          $transaction_status = (string)$transaction->transactionStatus;
          $transaction_amount = (string)$transaction->authAmount;
          if($transaction_amount === '')
              $transaction_amount = (string)$transaction->settleAmount;
          
          $accepted_statuses = array('capturedPendingSettlement', 'settledSuccessfully');
          if($transaction_id !== (string)$trans_id || $invoice_num !== (string)$log->invoice || !in_array($transaction_status, $accepted_statuses))
              return false;
          
          if(abs(floatval($transaction_amount) - floatval($log->total_amount)) >= 0.01)
              return false;
          
          return array(
              'x_trans_id' => $transaction_id,
              'x_invoice_num' => $invoice_num,
              'x_amount' => $transaction_amount,
              'transaction_status' => $transaction_status,
              'auth_code' => (string)$transaction->authCode,
              'response_code' => (string)$transaction->responseCode,
              'avs_response' => (string)$transaction->AVSResponse,
              'raw_response' => json_decode(json_encode($transaction_response), true),
          );
      }
      
      private function send_authorize_response($success, $log = null)
      {
          $message = $success ? esc_html__('Submitted','registrationmagic-addon') : esc_html__('Payment verification failed. Please contact the site administrator.','registrationmagic-addon');
          
          if($success && !empty($log)){
              $form = new RM_Forms;
              $form->load_from_db($log->form_id);
              $message = $form->form_options->form_success_message != "" ? apply_filters('rm_form_success_msg',$form->form_options->form_success_message,$log->form_id,$log->submission_id) : $form->get_form_name() . " " . esc_html__('Submitted','registrationmagic-addon');
          }
          
          echo '<div id="rmform"><br><br><div class="rm-post-sub-msg">' . wp_kses_post((string)$message) . '</div></div>';
          die;
      }
      
      
     
      /**
      * Generate authorize.net button link
      **/
      private function generate_authorize_form($data)
      {
         global $wp; 
         $options= new RM_Anet_Options();
         $p= get_the_ID();
         $form = new RM_Forms();
         $form->load_from_db($data->form_id);
         // Insert log
          $curr_date = RM_Utilities::get_current_time(); //date_i18n(get_option('date_format'));
          $total_amount= $data->pricing_details->total_price;
          $ex_data['user_id'] = isset($data->user_id) ? $data->user_id : null;
          if ($total_amount <= 0.0)
          {
                $log_entry_id = RM_DBManager::insert_row('PAYPAL_LOGS', array('submission_id' => $data->submission_id,
                            'form_id' => $data->form_id,
                            'invoice' => $data->order_id,
                            'status' => 'Completed',
                            'total_amount' => $total_amount,
                            'currency' => $data->currency,
                            'posted_date' => $curr_date,
                            'pay_proc' => 'anet_sim',
                            'bill' => maybe_serialize($data->pricing_details),
                            'ex_data' => maybe_serialize($ex_data)),
                             array('%d', '%d', '%s', '%s', '%f', '%s', '%s', '%s', '%s','%s'));
                
                return true;
           } else
            {
                $log_entry_id = RM_DBManager::insert_row('PAYPAL_LOGS', array('submission_id' => $data->submission_id,
                            'form_id' => $data->form_id,
                            'invoice' => $data->order_id,
                            'status' => 'Pending',
                            'total_amount' => $total_amount,
                            'currency' => $data->currency,
                            'posted_date' => $curr_date,
                            'pay_proc' => 'anet_sim',
                            'bill' => maybe_serialize($data->pricing_details),
                            'ex_data' => maybe_serialize($ex_data)),
                             array('%d', '%d', '%s', '%s', '%f', '%s', '%s', '%s', '%s','%s'));
            }
            
         $login_id= $options->get_value_of('anet_login_id'); 
         $trans_key= $options->get_value_of('anet_trans_key'); 
         $anet_test_mode= $options->get_value_of('anet_test_mode');
         
         //format URL for authoriznet
         $redirect_url = rtrim((string)home_url(add_query_arg(array(),$wp->request)),'/').'/';
         $redirect_url= add_query_arg(array("rm_success"=>1,"rm_sub_id"=>$data->submission_id,
                                     "rm_form_id"=>$data->form_id,"p"=>$p),$redirect_url );
         $redirection_url= RM_Utilities::get_form_redirection_url($form);
         if(!empty($redirection_url)){
             $redirect_url= $redirection_url;
         }
         $authorize_args = array(
            
            'x_login'                  => $login_id,
            'x_amount'                 => $data->pricing_details->total_price,
            'x_invoice_num'            => $data->order_id,
            'x_relay_url'              => $redirect_url,
            'x_email'                  => $data->user_email,
            'x_currency_code'           => $data->currency, 
            );

         if($anet_test_mode=="yes"){
           $processURI = $this->test_url;
         }
         else{
            $processURI = $this->live_url;
         }
         
        include('gettoken.php');
        //ob_start();
        $html_form = '<div id="response"></div>';
        $html_form .= '<div id="payment_html">';
        $html_form .= '<center><h2>'.__('Please wait, your order is being processed and you will be redirected to the payment window.', 'registrationmagic-addon').'</h2></center>';
        $html_form .= '<center><br><br>'.__('If you are not automatically redirected to Authorize.Net Payment window within 5 seconds...', 'registrationmagic-addon').'<br><br>';
        $html_form .= '<form id="payform" target="payframe" action="'.$processURI.'" method="post">'
                . '<input type="hidden" id="token" name="token" value="'.$token.'">'
                . '<input type="submit" class="button" onclick="rm_anet_sim_submit()" value="'.__('Click Here','registrationmagic-addon').'" />'
                . '</form>'
                . '</div>'
                . '<style>#payframe{border-style:none;height:615px;width:100%;display:none;}</style>'
                . '<script type="text/javascript">
                    setTimeout(function() { rm_anet_sim_submit(); }, 5000);
                    function rm_anet_sim_submit()
                    {
                        jQuery("#payform").submit();
                        jQuery("#payframe").show();
                        setTimeout(function() { jQuery("#payment_html").hide(); }, 1000);
                    }
                    </script>
                    <iframe name="payframe" id="payframe" class="test"></iframe>';
        ?>
        <script>
            window.CommunicationHandler = {};
            function parseQueryString(str) {
                var vars = [];
                var arr = str.split('&');
                var pair;
                for (var i = 0; i < arr.length; i++) {
                    pair = arr[i].split('=');
                    vars[pair[0]] = unescape(pair[1]);
                }
                return vars;
            }
            window.CommunicationHandler.onReceiveCommunication = function (argument) {
                $=jQuery;
                params = parseQueryString(argument.qstr);
                parentFrame = argument.parent.split('/')[4];
                switch (params['action']) {
                    case "cancel":
                        //window.location.reload();
                    case "transactResponse":
                        var transResponse = JSON.parse(params['response']);
                        if (transResponse.transId > 0) {
                            $('#payform').hide();
                            $('#payframe').hide();
                            //$('#response').html("<?php echo __('Thank you for payment.<br>Your Transaction Id is: ','registrationmagic-addon') ?>"+transResponse.transId);
                            
                            $.ajax({
                                url: "<?php echo site_url('/','https') ?>wp-admin/admin-ajax.php",
                                    type: "POST",
                                    data: {action:'rm_authnet_ipn',x_trans_id:transResponse.transId,'x_invoice_num': transResponse.orderInvoiceNumber,log_id:'<?php echo $log_entry_id ?>',x_response_code:transResponse.responseCode,x_amount:transResponse.totalAmount,x_email:'<?php echo $data->user_email ?>','sub_id':'<?php echo $data->submission_id; ?>'},
                                    success: function(data) {
                                        $("#response").append(data);
                                        var redirection = '<?php echo $redirect_url; ?>';
                                        if(redirection){
                                            location.href= redirection;
                                        }
                                    }
                            });
                        }
                }
            }
        </script>
        
  
        <?php
        
       // $html_content = ob_get_contents();
        $data=array();
        $data['html']= $html_form;
        $data['status']='do_not_redirect';
       //  ob_end_clean();
        // echo $html_form;
         return $data;
      }
      
      
    public function process_payment($form, $request, $params)
      { 
        $data= new stdClass();
        if ($form->get_form_type() === RM_REG_FORM)
        $data->user_id = $form->get_registered_user_id();
        $data->user_email= $params['user_email'];
        $data->pricing_details = $form->get_pricing_detail($request->req);
        $options= new RM_Anet_Options();
        $data->currency= $options->get_value_of('currency'); 
        $data->order_id = (string) date("His") . rand(1234, 9632);
        $data->form_name= $form->get_form_name();
        $data->form_id= $params['form_id'];
        $data->order_id = apply_filters('rm_inovice_number_format',$data->order_id, $data->form_id);
        $data->submission_id= $params['sub_detail']->submission_id;
            
        return $this->generate_authorize_form($data);
    }  
}
