<?php
/*
 * shopping/order/settlement/MethodBase.class.php
 * 
 * CopyRight(C) 2010 Shopformer Development Team. All Right Reserved
 * URL: http://sourceforge.jp/projects/shopformer/
 * 
 * 
 * Mail: m_nakashima@users.sourceforge.jp
 * Auther: Masanori Nakashima
 * Last Update: 2010-06-18
 */
require_once(dirname(dirname(dirname(dirname(__FILE__))))
	.DIRECTORY_SEPARATOR.'system'
	.DIRECTORY_SEPARATOR.'AbstractData.class.php');
/**
 * shopping_order_settlement_MethodBase
 * 決済プラグインベースクラス
 * 
 * shoppingパッケージ内にて注文の作成・編集や状態変更時に決済連携の処理を行うプラグインの
 * 抽象クラス。決済プラグインは全て本クラスを拡張して実装する必要があります。
 */
class shopping_order_settlement_MethodBase extends system_AbstractData {
	/** 方法表示名	*/
	var $viewName	= '';
	/** 設定値ハッシュ	*/
	var $settingValues	= array();
	/** 設定値ラベルハッシュ	*/
	var $settingLabels	= array();
	/** 決済準備ステータス	*/
	var $statusReady	= 0;
	/** 決済完了：正常時ステータス	*/
	var $statusNomal	= 0;
	/** 決済完了：エラー時ステータス	*/
	var $statusError	= 211;
	/** 正常終了時の決済状態	*/
	var $statusSettle	= 0;
	/** 決済手数料方式	0=なし, 1=固定額, 2=百分率 */
	var $feeType	= 0;
	/** 決済手数料値	*/
	var $feeValue	= 0;
	/** 決済方法に関する説明文	*/
	var $explanation		= '';
	/** 決済方法ごとのメールコメント	*/
	var $mailComment	= '';
	/** 決済方法ごとの発注メールコメント	*/
	var $mailOrder		= '';
	/** 入力確認画面での注意書き	*/
	var $attention			= '';
	/** 利用条件 金額下限	*/
	var $priceMinimum		= null;
	/** 利用条件 金額上限	*/
	var $priceMaximum		= null;
	/** 利用条件 会員種別 0=非会員, 1=会員, 2=特別会員 ... etc	*/
	var $memberClassArray	= null;
	/** 有効	*/
	var $enable				= true;
	/** 携帯利用可否	*/
	var $canMobile			= true;
	/** 注文完了時のメールテンプレート名	*/
	var $mailTemplateName	= 'thanks';
	/**
	 * コンストラクタ
	 */
	function shopping_order_settlement_MethodBase() {
	}
	/**
	 * 決済方法名を取得
	 * @return string 決済方法名称
	 */
	function getMethodName() {
		return '';
	}
	/**
	 * 決済方法名を取得
	 * @return string 表示名称文字列
	 */
	function getMethodViewName() {
		return $this->viewName;
	}
	/**
	 * AbstractDataのオーバーライド：getUniqueId
	 * @see system_AbstractData
	 * @return strings 固有ID
	 */
	function getUniqueId() {
		return sprintf('%04d',$this->getMethodNumber());
	}
	/**
	 * 決済方法固有の番号を取得します。
	 * @return int 決済方法固有番号
	 */
	function getMethodNumber() {
		return 0;
	}
	/**
	 * 決済方法に関する説明文を取得します
	 * @return string 決済方法説明文
	 */
	function getMethodExplanation() {
		return $this->explanation;
	}
	/**
	 * 決済方法ごとのメールコメントを取得
	 * @return string サンキューメールコメント文字列
	 */
	function getMailComment() {
		return $this->mailComment;
	}
	/**
	 * 決済方法ごとの発注メールコメントを取得
	 * @return string 発注メールコメント文字列
	 */
	function getMailOrder() {
		return $this->mailOrder;
	}
	/**
	 * 注文内容確認画面で注文ボタン上部に表示する決済方法特有の注意書きを取得します
	 */
	function getConfirmAttention() {
		return $this->attention;
	}
	/**
	 * 決済手数料を取得します
	 * @return int
	 */
	function getFee( $totalAmount ){
		if( $this->feeType == 2 ) {
			return $totalAmount * ($this->feeValue / 100);
		} else if( $this->feeType == 1 ) {
			return $this->feeValue;
		} else {
			return 0;
		}
	}
	/**
	 * 決済手数料を注文情報に設定
	 * @param $request spider_HttpRequestインスタンス参照
	 * @param $shoppingOrderObject shopping_DaoShoppingOrderオブジェクト
	 */
	function setSettleFee( & $request, & $shoppingOrderObject ) {
		foreach( $shoppingOrderObject->shoppingOrderAddressObjectArray as $num => $addressObject ) {
			$shoppingOrderObject->shoppingOrderAddressObjectArray[$num]->settle_fee	= 0;
		}
		if( !preg_match('/^[0-9]+$/',$this->feeValue) ) {
			$this->feeValue	= 0;
		}
		if( $this->feeType == 2 ) {
			$shoppingOrderObject->settle_fee	= ceil(($shoppingOrderObject->price_total + $shoppingOrderObject->wrapping_price) * $this->feeValue / 100);
		} else if( $this->feeType == 1 ) {
			$shoppingOrderObject->settle_fee	= $this->feeValue;
		} else {
			$shoppingOrderObject->settle_fee	= 0;
		}
	}
	/**
	 * Complete処理が必要か確認します
	 * @return boolean true/false
	 */
	function needComplete(){
		return false;
	}
	/**
	 * Complete処理の画面表示自体が必要か確認
	 * API経由のURLコールの場合はfalseを返してください
	 * 決済プロバイダからのリダイレクト戻りで画面表示が必要な場合はtrueを返してください
	 * @return boolean true/false
	 */
	function needCompleteView(){
		return false;
	}
	/**
	 * 注文完了時のメールテンプレート名を取得します
	 * @return string メールテンプレート名称
	 */
	function getCompleteMailTemplateName() {
		return $this->mailTemplateName;
	}
	/**
	 * 読み込み
	 * @param $request spider_HttpRequestインスタンス参照
	 */
	function load( & $request ) {
		return parent::load( $request, $this->getUniqueId() );
	}
	/**
	 * 必要に応じた入力フォームHTML取得メソッド
	 * @param $request spider_HttpRequestインスタンス参照
	 * @param $shoppingOrderObject shopping_DaoShoppingOrderインスタンス参照
	 * @return string 決済用入力フォームHTML文字列
	 */
	function getInputFormHtml( & $request, & $shoppingOrderObject ) {
		return '';
	}
	/**
	 * 必要に応じた完了フォームHTML取得メソッド
	 * @param $request spider_HttpRequestインスタンス参照
	 * @param $shoppingOrderObject shopping_DaoShoppingOrderインスタンス参照
	 * @return string 決済結果HTML文字列
	 */
	function getViewExecuteHtml( & $request, & $shoppingOrderObject ) {
		return '';
	}
	/**
	 * 妥当性検査時の処理
	 * @param $request spider_HttpRequestインスタンス参照
	 * @return boolean 成功したらtrue/失敗したらfalse
	 */
	function validate( & $request ) {
		return true;
	}
	/**
	 * confirm時の処理
	 * @param $request spider_HttpRequestインスタンス参照
	 * @param $shoppingOrderObject shopping_DaoShoppingOrderインスタンス参照
	 * @return boolean 成功したらtrue/失敗したらfalse
	 */
	function confirm( & $request, & $shoppingOrderObject ) {
		return true;
	}
	/**
	 * execute時の処理
	 * @param $request spider_HttpRequestインスタンス参照
	 * @param $shoppingOrderObject shopping_DaoShoppingOrderインスタンス参照
	 * @return boolean 成功したらtrue/失敗したらfalse
	 */
	function execute( & $request, & $shoppingOrderObject ) {
		$shoppingOrderObject->setSettlePrice( $request, 0 );
		return true;
	}
	/**
	 * complete時にパラメータから判断して指定の注文オブジェクトを作成します。
	 * @param $request spider_HttpRequestインスタンス参照
	 * @return $shoppingOrderObject shopping_DaoShoppingOrderインスタンス
	 */
	function getCompleteShoppingObject( & $request ) {
		return null;
	}
	/**
	 * settlement時の処理
	 * @param $request spider_HttpRequestインスタンス参照
	 * @param $shoppingOrderObject shopping_DaoShoppingOrderインスタンス参照
	 * @return boolean 成功したらtrue/失敗したらfalse
	 */
	function settlement( & $request, & $shoppingOrderObject ) {
		$shoppingOrderObject->setSettlePrice( $request, 0 );
		return true;
	}
	/**
	 * 注文状態変更時にコールされるメソッド
	 * @param $request spider_HttpRequestインスタンス参照
	 * @param $shoppingOrderObject shopping_DaoShoppingOrderインスタンス参照
	 * @return boolean 成功したらtrue/失敗したらfalse
	 */
	function modify( & $request, & $shoppingOrderObject ) {
		// 状態フラグ変更に伴う変更
		if( $shoppingOrderObject->status_flag != $shoppingOrderObject->status_flag_org ) {
			// 状態変更がある場合
			if( $shoppingOrderObject->status_flag_org < 100 ) {
				// 元の状態が確定以下の場合
				if( $shoppingOrderObject->status_flag >= 200 ) {
					// 確定未満→削除 = 決済キャンセル
					$this->settleCancel( $request, $shoppingOrderObject );
				} else if( $shoppingOrderObject->status_flag >= 100 ) {
					// 確定未満→確定 = 決済確認
					
				} else {
					// 確定未満→確定未満
					
				}
			} else if( $shoppingOrderObject->status_flag_org < 200 ) {
				// 元のステータスが確定の場合
				if( $shoppingOrderObject->status_flag >= 200 ) {
					// 確定→削除 = 決済キャンセル
					$this->settleCancel( $request, $shoppingOrderObject );
				} else if( $shoppingOrderObject->status_flag >= 100 ) {
					// 確定→確定 = 何もしない
				} else {
					// 確定→確定未満
				}
			} else {
				// 元のステータスが削除の場合
				if( $shoppingOrderObject->status_flag >= 200 ) {
					// 削除→削除
				} else if( $shoppingOrderObject->status_flag >= 100 ) {
					// 削除→確定 = キャンセル復帰処理
					$this->settleRecover( $request, $shoppingOrderObject );
				} else {
					// 削除→確定未満 = キャンセル復帰処理
					$this->settleRecover( $request, $shoppingOrderObject );
				}
			}
		}
		// 状態が有効の場合
		if( $shoppingOrderObject->status_flag < 200 ) {
			if( $shoppingOrderObject->payment_total != $shoppingOrderObject->payment_total_org ) {
				// 金額が変更されているなら金額変更処理
				$this->settleChangeAmount( $request, $shoppingOrderObject );
			}
		}
		// 戻り処理
		if( $request->isError() ) {
			return false;
		} else {
			return true;
		}
	}
	/**
	 * 指定された注文情報に対して本決済プラグインを利用可能か確認します
	 * @param $request spider_HttpRequestインスタンス参照
	 * @param $shoppingOrderObject shopping_DaoShoppingOrderインスタンス参照
	 * @return boolean 利用可能ならtrue/不可ならfalse
	 */
	function enableOnOrder( & $request, & $shoppingOrderObject ) {
		if( !is_null($shoppingOrderObject) ) {
			$productUnitHash	= $shoppingOrderObject->getProductUnitHash( $request );
			foreach( $productUnitHash as $key => $unitObject ) {
				if( $unitObject->delivery_type > 100 && $unitObject->delivery_type < 200 ) {
					// 月次課金や自動課金には対応しません
					return false;
				}
			}
			return true;
		} else {
			return false;
		}
	}
	/**
	 * 決済状態同期が有効か確認する抽象メソッド
	 * 注文オブジェクトを引数にとって外部サービスの決済状態と状態を同期します
	 * @param $request spider_HttpRequestインスタンス参照
	 * @param $shoppingOrderObject shopping_DaoShoppingOrderインスタンス参照
	 * @return boolean 成功したらtrue/失敗したらfalse
	 */
	function enableSynchronize( $shoppingOrderObject = null ) {
		return false;
	}
	/**
	 * 決済状態同期が有効か確認する抽象メソッド
	 * 注文オブジェクトを引数にとって外部サービスの決済状態と状態を同期します
	 * @param $request spider_HttpRequestインスタンス参照
	 * @param $shoppingOrderObject shopping_DaoShoppingOrderインスタンス参照
	 * @return boolean 成功したらtrue/失敗したらfalse
	 */
	function enableChangeAmount( $shoppingOrderObject = null ) {
		return true;
	}
	/**
	 * 決済状態同期の抽象メソッド
	 * 注文オブジェクトを引数にとって外部サービスの決済状態と状態を同期します
	 * @param $request spider_HttpRequestインスタンス参照
	 * @param $shoppingOrderObject shopping_DaoShoppingOrderインスタンス参照
	 * @return boolean 成功したらtrue/失敗したらfalse
	 */
	function settleSynchronize( & $request, & $shoppingOrderObject ) {
		return true;
	}
	/**
	 * 決済キャンセル抽象メソッド
	 * @param $request spider_HttpRequestインスタンス参照
	 * @param $shoppingOrderObject shopping_DaoShoppingOrderインスタンス参照
	 * @return boolean 成功したらtrue/失敗したらfalse
	 */
	function settleCancel( & $request, & $shoppingOrderObject ){
		return true;
	}
	/**
	 * 決済金額変更抽象メソッド
	 * @param $request spider_HttpRequestインスタンス参照
	 * @param $shoppingOrderObject shopping_DaoShoppingOrderインスタンス参照
	 * @return boolean 成功したらtrue/失敗したらfalse
	 */
	function settleChangeAmount( & $request, & $shoppingOrderObject ){
		$shoppingOrderObject->setSettlePrice( $request, $shoppingOrderObject->payment_total );
		return true;
	}
	/**
	 * 決済復帰抽象メソッド
	 * @param $request spider_HttpRequestインスタンス参照
	 * @param $shoppingOrderObject shopping_DaoShoppingOrderインスタンス参照
	 * @return boolean 成功したらtrue/失敗したらfalse
	 */
	function settleRecover( & $request, & $shoppingOrderObject ){
		return true;
	}
}
?>