<?php
/* ********************** Support And Update By opencart-ir.com ***************************** */
/* ************************* Our WebSite - www.OpenCartFarsi.ir ***************************** */
/* ******************************* Last Update In 2022/01/22 ******************************** */
class ControllerExtensionPaymentZarinpal extends Controller {
	public function index() {
		$this->load->language('extension/payment/zarinpal');
		
		$data['text_connect'] = $this->language->get('text_connect');
		$data['text_loading'] = $this->language->get('text_loading');
		$data['text_wait'] = $this->language->get('text_wait');
		
    	$data['button_confirm'] = $this->language->get('button_confirm');

		return $this->load->view('extension/payment/zarinpal', $data);
	}

	public function confirm() {
		$this->load->language('extension/payment/zarinpal');
		
		$this->load->model('checkout/order');

		if (isset($this->session->data['order_id'])) {
			$order_id = $this->session->data['order_id'];
		} else {
			$order_id = 0;
		}
		$order_info = $this->model_checkout_order->getOrder($order_id);

		$order_total = $this->correctAmount($order_info);

		$json = array();
		
		$MerchantID = $this->config->get('payment_zarinpal_pin');  	//Required
		$Amount = $order_total; 									//Amount will be based on Rial  - Required
		$Description = $this->language->get('text_order_no') . $order_info['order_id']; // Required
		$Email = isset($order_info['email']) ? $order_info['email'] : ''; 	// Optional
		$Mobile = isset($order_info['telephone']) ? $order_info['telephone'] : $order_info['fax']; 	// Optional
		/*$enc_order_id = $this->encryption->encrypt($this->config->get('config_encryption'), $order_id);*/
		$CallbackURL = $this->url->link('extension/payment/zarinpal/callback', 'order_id=' . $order_id, true);  // Required

        $parameters = array(
			'merchant_id' 	=> $MerchantID,
            'amount'		=> $Amount,
            'metadata' 		=> array(
                'mobile'=> $Mobile,
                'email'	=> $Email,
            ),
            'callback_url' 	=> $CallbackURL,
            'description' 	=> $Description
		);
        $json_data = json_encode($parameters);
        $ch = curl_init('https://api.zarinpal.com/pg/v4/payment/request.json');
        curl_setopt($ch, CURLOPT_USERAGENT, 'ZarinPal Rest Api v4');
        curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'POST');
        curl_setopt($ch, CURLOPT_POSTFIELDS, $json_data);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_HTTPHEADER, array(
            'Content-Type: application/json',
            'Content-Length: ' . strlen($json_data)
        ));
        $result = curl_exec($ch);
        $err = curl_error($ch);
        $result = json_decode($result, true);
        curl_close($ch);

		if(!$result) {
			$json['error'] = $this->language->get('error_cant_connect');
		} elseif($result['data']['code'] == 100) {
            $action = 'https://www.zarinpal.com/pg/StartPay/' . $result['data']['authority'] . '/ZarinGate';
            $json['success'] = $action;
		} else {
			$json['error'] = $this->checkState($result['data']['code']);
		}

		$this->response->addHeader('Content-Type: application/json');
		$this->response->setOutput(json_encode($json));
	}

	public function callback() {
		/*if ($this->session->data['payment_method']['code'] == 'zarinpal') {*/
			$this->load->language('extension/payment/zarinpal');

			$this->document->setTitle($this->language->get('text_title'));
			
			$data['heading_title'] = $this->language->get('text_title');
			$data['text_results'] = $this->language->get('text_results');
			$data['button_continue'] = $this->language->get('button_continue');

			$data['results'] = "";
			$data['error_warning'] = "";
			$data['continue'] = "";

			$data['breadcrumbs'] = array();
			$data['breadcrumbs'][] = array(
				'text' => $this->language->get('text_home'), 
				'href' => $this->url->link('common/home', '', true)
			);
			$data['breadcrumbs'][] = array(
				'text' => $this->language->get('text_title'), 
				'href' => $this->url->link('checkout/checkout', '', true)
			);

			if (isset($this->request->get['order_id'])) {
				/*$my_order_id = $this->encryption->decrypt($this->config->get('config_encryption'), $this->request->get['order_id']);*/
				$my_order_id = $this->request->get['order_id'];
			} else {
				$my_order_id = 0;
			}
			if ($my_order_id > 0) {
				$order_id = $my_order_id;
			} else {
				if (isset($this->session->data['order_id'])) {
					$order_id = $this->session->data['order_id'];
				} else {
					$order_id = 0;
				}
			}

			$this->load->model('checkout/order');
			$order_info = $this->model_checkout_order->getOrder($order_id);

			try {
				if($this->request->get['Status'] != 'OK')
					throw new Exception($this->language->get('error_verify'));

				if (!$order_info)
					throw new Exception($this->language->get('error_order_id'));

				$authority = $this->request->get['Authority'];
				$amount = $this->correctAmount($order_info);

				$verify_result = $this->verifyPayment($authority, $amount);

				if (!$verify_result) {
					throw new Exception($this->language->get('error_connect_verify'));
				
				} else if($verify_result['data']['code'] == 100) {
					// success
					$RefID_number = $verify_result['data']['ref_id'];
					
					$comment = $this->language->get('text_results') . $RefID_number;
					$this->model_checkout_order->addOrderHistory($order_id, $this->config->get('payment_zarinpal_order_status_id'), $comment, true);

					$data['results'] = $RefID_number;
					$data['button_continue'] = $this->language->get('button_complete');
					$data['continue'] = $this->url->link('checkout/success');
				} else {
					// show error with status-code
					$status_code = $verify_result['data']['code'];
					throw new Exception($this->checkState($status_code));
				}

			} catch (Exception $e) {
				$data['error_warning'] = $e->getMessage();
				$data['button_continue'] = $this->language->get('button_view_cart');
				$data['continue'] = $this->url->link('checkout/cart');
			}

			$data['column_left'] = $this->load->controller('common/column_left');
			$data['column_right'] = $this->load->controller('common/column_right');
			$data['content_top'] = $this->load->controller('common/content_top');
			$data['content_bottom'] = $this->load->controller('common/content_bottom');
			$data['footer'] = $this->load->controller('common/footer');
			$data['header'] = $this->load->controller('common/header');

			$this->response->setOutput($this->load->view('extension/payment/zarinpal_confirm', $data));
		/*}*/
	}

	private function correctAmount($order_info) {
		$amount = $this->currency->format($order_info['total'], $order_info['currency_code'], $order_info['currency_value'], false);
		$amount = round($amount);
		$amount = $this->currency->convert($amount, $order_info['currency_code'], "RLS");
		return (int)$amount;
	}

	private function checkState($status) {
		$error_message = $this->language->get('error_status_undefined');

		if ($this->language->get('error_status_' . $status) != 'error_status_' . $status ) {
			$error_message = $this->language->get('error_status_' . $status);
		}

		return $error_message;
	}

	private function verifyPayment($authority, $amount) {
		$MerchantID = $this->config->get('payment_zarinpal_pin');

        $post_data = array(
			'merchant_id' 	=> $MerchantID,
			'authority' 	=> $authority,
			'amount' 		=> $amount
		);
        $json_data = json_encode($post_data);
        $ch = curl_init('https://api.zarinpal.com/pg/v4/payment/verify.json');
        curl_setopt($ch, CURLOPT_USERAGENT, 'ZarinPal Rest Api v4');
        curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'POST');
        curl_setopt($ch, CURLOPT_POSTFIELDS, $json_data);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_HTTPHEADER, array(
            'Content-Type: application/json',
            'Content-Length: ' . strlen($json_data)
        ));
        $result = curl_exec($ch);
        $err = curl_error($ch);
        curl_close($ch);
        $result = json_decode($result, true);

        if(!$result) {
            // echo  $this->language->get('error_cant_connect');
            return false;
        } else {
            return $result;
        }
	}

	public function encrypt($value) {
		$key = $this->config->get('config_encryption');
		$my_key = hash('sha256', $key, true);
		return strtr(base64_encode(mcrypt_encrypt(MCRYPT_RIJNDAEL_256, hash('sha256', $my_key, true), $value, MCRYPT_MODE_ECB)), '+/=', '-_,');
	}
	public function decrypt($value) {
		$key = $this->config->get('config_encryption');
		$my_key = hash('sha256', $key, true);
		return trim(mcrypt_decrypt(MCRYPT_RIJNDAEL_256, hash('sha256', $my_key, true), base64_decode(strtr($value, '-_,', '+/=')), MCRYPT_MODE_ECB));
	}
}
?>