<?php
namespace Models;

class sberbank_qr {
	public $f3, $sets, $config;
	public $keys=array(
		'operation_id'=>'Идентификатор операции',
		'operation_date_time'=>'Дата/Время совершения операции',
		'rrn'=>'RRN операции',
		'operation_type'=>'Тип операции',
		'operation_sum'=>'Сумма операции',
		'operation_currency'=>'Валюта операции',
		'auth_code'=>'Код авторизации',
		'response_code'=>'',
		'Код выполнения запроса'=>'',
		'response_desc'=>'Описание кода выполнения запроса',
		'client_name'=>'Имя Отчество Ф. плательщика'
	);
	public $operation_types=array(
		'PAY'=>'Оплата',
		'REVERSE'=>'Отмена',
		'REFUND'=>'Возврат'
	);
	
	function __construct($f3, $sets, $config) {
		$this->f3=$f3;
		$this->sets=$sets;
        $this->config=$config;
	}

	function guid() {
		$guid=md5(microtime().rand(0,99999999));
		return $guid;
	}

	function send_curl($url, $headers, $vars) {
		$curl = curl_init();
		curl_setopt($curl, CURLOPT_URL,$url);
		curl_setopt($curl, CURLOPT_HTTPHEADER, $headers);
		curl_setopt($curl, CURLOPT_FOLLOWLOCATION, 1);
		curl_setopt($curl, CURLOPT_POST,true);
		curl_setopt($curl, CURLOPT_POSTFIELDS, $vars);
		curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
		curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, true);
		curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, 2);
		curl_setopt($curl, CURLOPT_CAINFO, __DIR__.'/cacerts.cer');
		curl_setopt($curl, CURLOPT_SSLCERT, __DIR__.'/client_cert.crt');
		curl_setopt($curl, CURLOPT_SSLKEY, __DIR__.'/private.key');
		$data = curl_exec($curl);
		curl_close($curl);
		return $data;
	}

	function token($guid, $scope) {
		$vars=array(
			'grant_type'=>'client_credentials',
			'scope'=>$scope
		);

		$headers=array(
			'Accept: application/json',
			'Content-Type: application/x-www-form-urlencoded',
			'RqUID: '.$guid,
			'Authorization: Basic '.base64_encode($this->config['clientID'].':'.$this->config['clientSecret'])
		);
		$url='https://mc.api.sberbank.ru:443/prod/tokens/v3/oauth';
		$data=$this->send_curl($url, $headers, http_build_query($vars));
		if($data) {
			$json=json_decode($data, true);
			if(!$json) {
				return array(
					'success'=>false,
					'txt'=>'Неизвестная ошибка'
				);
			}
			if($json['access_token']) {
				return array(
					'success'=>true,
					'token'=>$json['access_token']
				);
			}
			return array(
				'success'=>false,
				'txt'=>$json['httpMessage'].'; '.$json['moreInformation']
			);
		}
		else {
			return array(
				'success'=>false,
				'txt'=>'Невозможно получить токен авторизации СБП'
			);
		}
	}

	function create_cancel_qr($guid, $token, $type, $sum, $return_epay) {
		$date=date('Y-m-d').'T'.date('H:i:s').'Z';
		$title='Возврат по чеку '.$return_epay['id'];
		$vars=array(
			'rq_uid'=>(string)$guid,
			'rq_tm'=>(string)$date,
			'order_id'=>(string)$return_epay['sbp_order_id'],
			//'operation_type'=>($type=='cancel'?'REVERSE':'REFUND'),
			'operation_type'=>'REFUND',
			'operation_id'=>(string)$return_epay['transid'],
			'auth_code'=>(string)$return_epay['authcode'],
			'id_qr'=>(string)$this->config['id_qr'],
			'tid'=>(string)$this->config['tid'],
			'cancel_operation_sum'=>$sum,
			'operation_currency'=>(string)'643',
			'operation_description'=>(string)$title
		);

		$headers=array(
			'Accept: */*',
			'Content-Type: application/json',
			'RqUID: '.$guid,
			'Authorization: Bearer '.$token
		);
		$url="https://mc.api.sberbank.ru:443/prod/qr/order/v3/cancel";
		$data=$this->send_curl($url, $headers, json_encode($vars));
		if($data) {
			$json=json_decode($data, true);
			if(!$json) {
				return array(
					'success'=>false,
					'txt'=>'Неизвестная ошибка'
				);
			}
			if($json['error_code']=='000000' && ($json['order_state']=='REVERSED' || $json['order_state']=='REFUNDED')) {
				$slip='';
				foreach ($json as $key => $value) {
					if($key && isset($this->keys[$key]) && $this->keys[$key]!='') {
						if($key=='operation_sum') $value=number_format($value/100, 2, '.', '');
						if($key=='operation_type') $value=$this->operation_types[$value];
						$slip.=$this->keys[$key].":\n".$value."\n";
					}
				}
				$slip.="Идентификатор операции в СБП:\n".$json['sbp_operation_params']['sbp_cancel_operation_id']."\n";
				return array(
					'success'=>true,
					'txt'=>nl2br($slip),
					'slip'=>nl2br($slip),
					'pan'=>'',
					'transid'=>$json['operation_id'],
					'authcode'=>$json['auth_code']
				);
			}
			elseif(mb_substr($json['error_code'], 0, 2)=='13' || $json['error_code']=='000000') {
				$n=10;
				while ($n>0) {
					sleep(3);
					$control_data['order_id']=$json['order_id'];
					$control_data['receipt_id']=$return_epay['id']>0?$return_epay['id']:$return_epay['parent_id'];
					$res=$this->paycontrol_qr($control_data);
					if($res['success']) {
						return $res;
					}
					$n-=1;
				}
			}
			elseif(isset($json['error_code']) && (mb_substr($json['error_code'], 0, 2)!='13' || !$json['order_state'])) {
				return array(
					'success'=>false,
					'txt'=>'Код ошибки '.$json['error_code'].'. '.$json['error_description']
				);
			}
			return array(
				'success'=>false,
				'txt'=>$json['httpMessage'].'; '.$json['moreInformation']
			);
		}
		else {
			return array(
				'success'=>false,
				'txt'=>'Неудается отправить запрос на создание QR-кода'
			);
		}
	}

	function create_sale_qr($guid, $token, $sum) {
		$receipt_id=(string)$this->f3->get('COOKIE.receipt_id');
		$date=date('Y-m-d').'T'.date('H:i:s').'Z';
		$title='Оплата по чеку '.$receipt_id;
		$vars=array(
			'rq_uid'=>(string)$guid,
			'rq_tm'=>(string)$date,
			'member_id'=>(string)$this->config['member_id'],
			'order_number'=>(string)$receipt_id.'-'.date('Y-m-d-H-i-s'),
			'order_create_date'=>(string)$date,
			'order_params_type'=>array(
				array(
					'position_name'=>(string)$title,
					'position_count'=>(int)1,
					'position_sum'=>(int)$sum,
					'position_description'=>(string)$title
				)
			),
			'id_qr'=>(string)$this->config['id_qr'],
			'order_sum'=>(int)$sum,
			'currency'=>(string)'643',
			'description'=>(string)$title,
			//'sbp_member_id'=>(string)'100000000111'
		);

		$headers=array(
			'Accept: */*',
			'Content-Type: application/json',
			'RqUID: '.$guid,
			'Authorization: Bearer '.$token
		);
		$url="https://mc.api.sberbank.ru:443/prod/qr/order/v3/creation";
		$data=$this->send_curl($url, $headers, json_encode($vars));
		if($data) {
			$json=json_decode($data, true);
			if(!$json) {
				return array(
					'success'=>false,
					'txt'=>'Неизвестная ошибка'
				);
			}
			if($json['error_code']=='000000' && $json['order_state']=='CREATED') {
				return array(
					'success'=>true,
					'qr'=>$json['order_form_url'],
					'sbp_order_id'=>$json['order_id'],
					'receipt_id'=>$receipt_id,
					'show_qr'=>'/receipts/show_qr?receipt_id='.$receipt_id.'&order_id='.$json['order_id'].'&epay='.$this->sets['id'].'&sum='.$sum.'&url='.urlencode($json['order_form_url'])
				);
			}
			elseif(isset($json['error_code'])) {
				return array(
					'success'=>false,
					'txt'=>'Код ошибки '.$json['error_code'].'. '.$json['error_description']
				);
			}
			return array(
				'success'=>false,
				'txt'=>$json['httpMessage'].'; '.$json['moreInformation']
			);
		}
		else {
			return array(
				'success'=>false,
				'txt'=>'Неудается отправить запрос на создание QR-кода'
			);
		}
	}

	function ticket($type, $sum, $return_epay=null) {
		$guid=$this->guid();
		if($type=='sale') {
			$scope='https://api.sberbank.ru/qr/order.create';
		}
		else {
			$scope='https://api.sberbank.ru/qr/order.cancel';
		}
		$token=$this->token($guid, $scope);
		if(!$token['success']) {
			return $token;
		}
		if($type=='sale') {
			return $this->create_sale_qr($guid, $token['token'], $sum*100);
		}
		if(!$return_epay['transid']) {
			$return_epay['order_id']=$return_epay['sbp_order_id'];
			$return_epay['receipt_id']=$return_epay['id'];
			$res=$this->paycontrol_qr($return_epay);
			if($res['success']) {
				$return_epay['transid']=$res['transid'];
			}
		}
		return $this->create_cancel_qr($guid, $token['token'], $type, $sum*100, $return_epay);

	}

	function get_status($guid, $token, $data) {
		$date=date('Y-m-d').'T'.date('H:i:s').'Z';
		$vars=array(
			'rq_uid'=>(string)$guid,
			'rq_tm'=>(string)$date,
			'order_id'=>(string)$data['order_id'],
			'tid'=>(string)$this->config['tid'],
			'partner_order_number'=>(string)$data['receipt_id']
		);

		$headers=array(
			'Accept: */*',
			'Content-Type: application/json',
			'RqUID: '.$guid,
			'Authorization: Bearer '.$token
		);
		$url="https://mc.api.sberbank.ru:443/prod/qr/order/v3/status";
		$res=$this->send_curl($url, $headers, json_encode($vars));
		if($res) {
			$json=json_decode($res, true);
			if(!$json) {
				return array(
					'success'=>false,
					'txt'=>'Неизвестная ошибка'
				);
			}
			if($json['error_code']=='000000') {
				if($json['order_state']=='PAID' || $json['order_state']=='REVERSED' || $json['order_state']=='REFUNDED') {
					$slip='';
					$json['order_operation_params']=array_reverse($json['order_operation_params']);
					foreach ($json['order_operation_params'][0] as $key => $value) {
						if($key && isset($this->keys[$key]) && $this->keys[$key]!='') {
							if($key=='operation_sum') $value=number_format($value/100, 2, '.', '');
							if($key=='operation_type') $value=$this->operation_types[$value];
							$slip.=$this->keys[$key].":\n".$value."\n";
						}
					}
					$slip.="Идентификатор операции в СБП:\n".$json['sbp_operation_params']['sbp_operation_id']."\n";
					return array(
						'success'=>true,
						'txt'=>nl2br($slip),
						'slip'=>nl2br($slip),
						'pan'=>isset($json['sbp_operation_params']['sbp_masked_payer_id'])?$json['sbp_operation_params']['sbp_masked_payer_id']:'',
						'transid'=>$json['order_operation_params'][0]['operation_id'],
						'authcode'=>$json['order_operation_params'][0]['auth_code'],
					);
				}
				else {
					return array(
						'success'=>false,
						'txt'=>'Статус платежа: '.$json['order_state']
					);
				}
			}
			elseif(isset($json['error_code'])) {
				return array(
					'success'=>false,
					'txt'=>'Код ошибки '.$json['error_code'].'. '.$json['error_description']
				);
			}
			return array(
				'success'=>false,
				'txt'=>$json['httpMessage'].'; '.$json['moreInformation']
			);
		}
		else {
			return array(
				'success'=>false,
				'txt'=>'Не удается отправить запрос статуса'
			);
		}
	}

	function paycontrol_qr($data) {
		$guid=$this->guid();
		$token=$this->token($guid, 'https://api.sberbank.ru/qr/order.status');
		if(!$token['success']) {
			return $token;
		}
		return $this->get_status($guid, $token['token'], $data);
	}

	function z() {
		$cheq=$this->sets['title']."\nСмена успешно закрыта";
		return array(
			'success'=>true,
			'txt'=>nl2br($cheq),
			'slip'=>nl2br($cheq),
			'pan'=>0,
			'transid'=>0,
			'authcode'=>0
		);
	}

	function x() {
		$cheq='';
		return array(
			'success'=>true,
			'txt'=>nl2br($cheq),
			'slip'=>nl2br($cheq),
			'pan'=>0,
			'transid'=>0,
			'authcode'=>0
		);
	}
}
