<?php
require_once(SITE_LOGICS . 'settlement/model.php');

class LogicSettlement extends SettlementModelClass {

	/*-------------------------------------------------------------------------
	* @ メンバ変数
	-------------------------------------------------------------------------*/
	private $htmlStr = NO_STRING;	// 表示用HTML文字列

	/*-------------------------------------------------------------------------
	* @function_name: ロジックのコンストラクタ
	* @parameter	: なし
	* @return		: なし
	-------------------------------------------------------------------------*/
	function __construct() {
		parent::__construct();
	}

	/*-------------------------------------------------------------------------
	* @function_name: ロジック（各クラス共通）
	* @parameter	: なし
	* @return		: TRUE:ロジック成功、FALSE:ロジック失敗
	-------------------------------------------------------------------------*/
	function logic() {

		try {
			// 初期データ処理
			$this -> init();
			
			// ロジック実行
			$this -> biz();

			// POSTのログを取る
			if($this -> getProgramCode() != NO_STRING)
			    $this -> logPost($this -> getProgramCode());
		} catch (Exception $e) {
			throw $e;
		}
	}

	/*-------------------------------------------------------------------------
	* @function_name: ロジックの実行
	* @parameter	: なし
	* @return		: なし
	-------------------------------------------------------------------------*/
	private function biz() {
	    switch($this -> getType()){
	        case TYPE_SETTLEMENT_EXPRESS_API:
	            $this -> restore();
	            $this -> select();
	            break;
	        case TYPE_SETTLEMENT_EXPRESS_SUBMIT:
	            try {
	                $registResult = $this -> regist();
	                $this -> forward($registResult);
	            } catch(Exception $e) {
	                $this -> forward(VAL_INT_1);
	            }
	            break;
	    }
	}

	/*-------------------------------------------------------------------------
	* @function_name: データのロード
	* @parameter	: なし
	* @return		: なし
	-------------------------------------------------------------------------*/
	private function select() {
		$this -> setAccount($this -> getAccountCommon($this -> getToAccount()));
	}

	/*-------------------------------------------------------------------------
	* @function_name: データの登録
	* @parameter	: なし
	* @return		: なし
	-------------------------------------------------------------------------*/
	private function regist() {
		if($this -> accessModify('INSERT_TRANSFER_API', $this -> getRegistData())) {

			// コミッションの登録（送金元）
			$this -> registCommision(VAR_TRANSFER
									, null
									, $this -> getFromAccount()
									, $this -> getDebitCurrency()
									, $this -> getFromFee());

			// コミッションの登録（送金先）
			$this -> registCommision(VAR_TRANSFER
									, null
									, $this -> getToAccount()
									, $this -> getCurrency()
									, $this -> getToFee());

			// 異通貨の場合は為替コミッション発生
			$from	= $this -> getDebitCurrency();
			$to		= $this -> getCurrency();

			if($from != $to) {

				// 着金額指定の場合
			    $this -> registCommisionExchange($this -> getFromAccount()
													, $to
													, $from
													, $this -> currencyToInt($this -> getDebitAmount(), $from));
			}

			// メールを送信（送金元ユーザ）
			$params = $this -> getSendDataFrom();
			$this -> sendMailByTmp('transfer_send_user.xml'
									, $params
									, $params[VAL_INT_11]
									, VAR_CS_MAIL_ADDRESS);

			// メールを送信（送金先ユーザ）
			$params = $this -> getSendDataTo();
			$this -> sendMailByTmp('transfer_receive_user.xml'
									, $params
									, $params[VAL_INT_11]
									, VAR_CS_MAIL_ADDRESS);
			
			$this -> updateSettlementFormStatus();
			return NO_COUNT;
		} else {
			return VAL_INT_1;
		}
	}

	/*-------------------------------------------------------------------------
	 * @function_name: データは商人へ送信する処理
	 * @parameter	: なし
	 * @return		: なし
	 -------------------------------------------------------------------------*/
	private function sendCallbackToIntegrator($callBack, $data){
	    //log directory
	    $apiPath 		= dirname(SYSTEM_PATH).DIRECTORY_SEPARATOR.'api';
	    $responseUrl 	= $apiPath.DIRECTORY_SEPARATOR.'Logs'.DIRECTORY_SEPARATOR.'settlement'.DIRECTORY_SEPARATOR.'settlement_response_data';
	    
	    if(!file_exists($responseUrl)){
	        mkdir($responseUrl, 0777, true);
	    }
	    
	    // callback sender to merchant and response logger
	    $context = curl_init();
	    
	    curl_setopt_array($context, [
	        CURLOPT_URL => $callBack,
	        CURLOPT_RETURNTRANSFER => true,
	        CURLOPT_FOLLOWLOCATION => true,
	        CURLOPT_HEADER => true,
	        CURLOPT_ENCODING => "utf8",
	        CURLOPT_POSTFIELDS => $data,
	        CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
	        CURLOPT_CUSTOMREQUEST => "POST",
	        CURLOPT_HTTPHEADER => [
	            "Content-Type: application/x-www-form-urlencoded",
	            "Content-length: ".strlen($data)
	        ]
	    ]);
	    
	    if($err = curl_error($context)){
	        $cboutput = $err;
	    }else {
	        $cboutput           = curl_exec($context);
	        $headerSize         = curl_getinfo($context, CURLINFO_HEADER_SIZE);
	        $responseHeaders    = substr($cboutput, 0, $headerSize);
	        $responseBody       = substr($cboutput, $headerSize);
	        
	        $cboutput = "[Headers]\n\n{$responseHeaders}[Body]\n\n{$responseBody}";
	    }
	    
	    //logging response data
	    $logFileName = $responseUrl.DIRECTORY_SEPARATOR.'Log_H'.date("Y-m-d").'.log';
	    
	    error_log("\r\n[".date("Y-m-d H:i:s")."][{$this -> getProgramCode()}]\r\n\nReturn URL:\r\n\n{$callBack}\r\n\nContext: {$data}\r\n\nResponse:\r\n\n{$cboutput}\r\n",
	    VAL_INT_3,
	    $logFileName);
	    
	    chmod($logFileName, 511);
	    // end of logging response data
	}
	
	/*-------------------------------------------------------------------------
	* @function_name: データの登録
	* @parameter	: なし
	* @return		: なし
	-------------------------------------------------------------------------*/
	private function forward($result) {
	    header("Content-type: text/plain");
		
		// 変数宣言部
		$url = NO_STRING;
		$data		= null;

		// 転送先
		$url		= $this -> getUrl();
		$callBack	= $this -> getCallBackUrl();
		$failUrl	= $this -> getFailUrl();

		// コールバック
		$data = $this -> getForwardParams($result);
		$jsonData = json_encode($data);
		$data = http_build_query($data, '', '&');
		
		if(isset($_SERVER['REMOTE_ADDR'])) {
			$ip = $_SERVER['REMOTE_ADDR'];
		}

		if(isset($_SERVER['HTTP_REFERER'])) {
		    $referer = $this -> sqlSanitation($_SERVER['HTTP_REFERER']);
		    
		    if(strlen($referer) > VAL_INT_256)
		        $referer = preg_replace("/\\?.*/", "", $referer);
		}
		
		// 転送をする
		if($result == NO_COUNT) {	// 正常終了
		    $this -> sendCallbackToIntegrator($callBack, $data);
		    
            // this insert command also comtains data that will passed to merchant's system.    
			$this -> accessModifyCommon('INSERT_LOG_POST', array(
			    $ip, 
			    $this -> getProgramCode(),
			    $referer, 
			    "[CALLBACK_SUCCESSFUL]{$jsonData}"));

            if($url != NO_STRING)
                header("Location: {$url}");
            else
                echo "Successfully transferred!";
		} else {						// 異常
			$this -> accessModifyCommon('INSERT_LOG_POST', array(
			    $ip,
			    $this -> getProgramCode(),
			    $referer,
			    "[CALLBACK_ERROR]{$jsonData}"));
			
			if($failUrl != NO_STRING) 
				header("Location: {$failUrl}");
			else
			    echo "The settlement failed to proceed!";
		}
	}

	function updateSettlementFormStatus(){
	    $this -> accessModify("UPDATE_SETTLEMENT_FORM", [$this -> getFormName()], false);
	}
}
?>