<?php
/**
 * 決済プラグイン GMOペイメントゲートウェイ カード決済用クラス
 */
require_once(dirname(__FILE__).DIRECTORY_SEPARATOR.'MethodBase.class.php');
class shopping_order_settlement_MethodGmopgCard extends shopping_order_settlement_MethodBase {
	/**
	 * コンストラクタ
	 */
	function shopping_order_settlement_MethodGmopgCard() {
		$this->viewName			= 'クレジットカード';
		$this->enable			= false;
		$this->statusSettle		= 101;
		$this->settingValues	= array(
			'shop_id'		=> '',
			'shop_pass'		=> '',
			// 3Dセキュア対応
			'3d_secure'		=> '',
			// オーダー情報送信先URL
			'entry_url'		=> '',
			'exec_url'		=> '',
			'secure_url'	=> '',
			'alter_url'		=> '',
			'change_url'	=> '',
			'search_url'	=> '',
			// 分割払い可能カードブランド
			'credit_dev'	=> '',
		);
		$this->settingLabels	= array(
			'shop_id'		=> 'ショップID',
			'shop_pass'		=> 'ショップパスワード',
			'3d_secure'		=> '3Dセキュア対応',
			'entry_url'		=> 'オーダー情報送信先(取引登録)URL',
			'exec_url'		=> 'オーダー情報送信先(決済実行)URL',
			'secure_url'	=> 'オーダー情報送信先(3D認証決済実行)URL',
			'alter_url'		=> 'オーダー情報送信先(決済変更)URL',
			'change_url'	=> 'オーダー情報送信先(金額変更)URL',
			'search_url'	=> 'オーダー情報送信先(取引照会)URL',
			'credit_dev'	=> '分割払い可能カードブランド',
		);
		$this->feeType			= 0;
		$this->feeValue			= 0;
		$this->mailTemplateName	= 'thanks';
		$this->mailComment	= "クレジットカードにてお支払いが完了しています。";
		$this->mailOrder	= "クレジットカードにてお支払いが完了しています。\n";
		$this->cardDivHash	= array('01'=>'一括','03'=>'3回','05'=>'5回','06'=>'6回','10'=>'10回','12'=>'12回','15'=>'15回','18'=>'18回','20'=>'20回','24'=>'24回','99'=>'リボ');
		$this->explanation	= <<< __METHOD_EXPLANATION__
<div>
GMOペイメントゲートウェイ株式会社のクレジットカード決済代行を利用したお支払いです。<br />
ご入力頂いたカード情報は直接GMOペイメントゲートウェイ株式会社に送信いたします。当方ではカード情報は一切保持いたしません。<br />
</div>
__METHOD_EXPLANATION__;

		$this->attention	= <<< __METHOD_EXPLANATION__
<div>カード決済を実行します</div>
__METHOD_EXPLANATION__;
		$this->acsUrl	= '';
		$this->paReq	= '';
	}
	/**
	 * 決済方法名を取得
	 */
	function getMethodName() {
		return 'GMOペイメントゲートウェイ:クレジットカード決済プラグイン プロトコルタイプ';
	}
	/**
	 * 決済方法固有の番号を取得します。
	 */
	function getMethodNumber() {
		return '81';
	}
	/**
	 * Complete画面が必要か確認します
	 * @return true/false
	 */
	function needComplete(){
		return false;
	}
	/**
	 * 必要に応じた入力フォームHTML取得メソッド
	 */
	function getInputFormHtml( & $request, & $shoppingOrderObject ) {
		$gmopgCardNumber		= $shoppingOrderObject->gmopgcardnumber;
		$gmopgCardName		= $shoppingOrderObject->gmopgcardname;
		$errorMessage		= '';
		$formNumColor			= '#fff0ff';
		if( is_array($shoppingOrderObject->columnErrorHash['settle_method_errors']) && count($shoppingOrderObject->columnErrorHash['settle_method_errors'])>0 ) {
			foreach($shoppingOrderObject->columnErrorHash['settle_method_errors'] as $msg) {
				$errorMessage	.= '<span style="font-size:x-small;color:#ff0000;">'.$msg.'</span><br />';
			}
			$formNumColor	= '#fff0f0';
		}
		$returnString		= <<< __HTML_INPUTFORM__
カード番号とカード名義を入力してください。<br />
▼カード番号 <span style="font-size:x-small;color:#ff0000;">※選択した場合必須 ハイフンなしの半角数字で入力してください</span><br />
<input type="text" name="gmopgcardnumber" size="30" value="${gmopgCardNumber}" style="background-color:${formNumColor};" /><br />
▼カード名義 <span style="font-size:x-small;color:#ff0000;">※選択した場合必須 カードに記載の通り入力してください 例) TARO SHOP</span><br />
<input type="text" name="gmopgcardname" size="40" value="${gmopgCardName}" style="background-color:${formNumColor};" /><br />
▼カード有効期限 <span style="font-size:x-small;color:#ff0000;">※選択した場合必須</span><br />
<select name="gmopglimitmonth" style="background-color:${formNumColor};">
	<option value="" style="background-color:${formNumColor};">月</option>
__HTML_INPUTFORM__;
		for( $i=1; $i<=12; $i++ ) {
			$returnString	.= '<option value="'.sprintf('%02d',$i).'"';
			if( $shoppingOrderObject->gmopglimitmonth == sprintf('%02d',$i) ) {
				$returnString	.= ' selected';
			}
			$returnString	.= ' style="background-color:'.$formNumColor.';">'.sprintf('%02d',$i).'</option>';
		}
		$returnString	.= '</select>/<select name="gmopglimityear" style="background-color:'.$formNumColor.';">';
		$returnString	.= '<option value="" style="background-color:'.$formNumColor.';">年</option>';
		for( $i=date('y');$i<date('y')+10;$i++ ) {
			$returnString	.= '<option value="'.sprintf('%02d',$i).'"';
			if( $shoppingOrderObject->gmopglimityear == sprintf('%02d',$i) ) {
				$returnString	.= ' selected';
			}
			$returnString	.= ' style="background-color:'.$formNumColor.';">'.sprintf('%02d',$i).'</option>';
		}
		$returnString	.= '</select><br />';
		// 分割払い対応カードブランド
		$cardDivTypeArray	= array();
		if ( strlen($this->settingValues['credit_dev'])>0 ) {
			$cardDivTypeArray	= explode(',',$this->settingValues['credit_dev']);
		}
		if ( count($cardDivTypeArray)>0 ) {
			$cardTypeArray	= array('VISA','MASTER','JCB','DINERS','AMEX');
			$returnString	.= '▼カード種類 <br /><select name="gmopgcardtype" style="background-color:'.$formNumColor.';" onchange="">'
				.'<option value="" style="background-color:'.$formNumColor.';color:#800000;">必須</option>';
			$noneDivCardArray	= array();
			foreach( $cardTypeArray as $cardType ) {
				$returnString	.= '<option value="'.$cardType.'" style="background-color:'.$formNumColor.';"';
				if( $shoppingOrderObject->gmopgcardtype == $cardType ) {
					$returnString	.= ' selected';
				}
				$returnString	.= '>'.$cardType.'</option>';
				if( !in_array($cardType,$cardDivTypeArray) ) {
					array_push( $noneDivCardArray, $cardType );
				}
			}
			$returnString	.= '</select><br />';
			$returnString	.= '▼支払方法 <br /><select name="gmopgcarddiv" id="gmopgcarddiv" style="background-color:'.$formNumColor.';" onchange="">';
			foreach( $this->cardDivHash as $divVal => $divName ) {
				$returnString	.= '<option value="'.$divVal.'" style="background-color:'.$formNumColor.';"';
				if( $shoppingOrderObject->gmopgcarddiv == $divVal ) {
					$returnString	.= ' selected';
				}
				$returnString	.= '>'.$divName.'</option>';
			}
			$returnString	.= '</select><br />';
			if( count($noneDivCardArray) > 0 ) {
				$returnString	.= '<span style="font-size:x-small;color:#800000;">※'.implode(',',$noneDivCardArray).'は分割・リボをご利用いただけません。</span><br />';
			}
		}
		$returnString	.= $errorMessage;
		return $returnString;
	}
	/**
	 * confirm時の処理
	 */
	function confirm( & $request, & $shoppingOrderObject ) {
		// 入力フォームの内容を取得してショッピングオーダーオブジェクトに設定する
		$shoppingOrderObject->gmopgcardnumber	= mb_convert_kana(trim(stripslashes($_POST['gmopgcardnumber'])),'a');
		$shoppingOrderObject->gmopgcardnumber	= str_replace('-','',$shoppingOrderObject->gmopgcardnumber);
		$shoppingOrderObject->gmopgcardnumber	= str_replace('　','',$shoppingOrderObject->gmopgcardnumber);
		$shoppingOrderObject->gmopgcardname		= mb_convert_kana(trim(stripslashes($_POST['gmopgcardname'])),'a');
		$shoppingOrderObject->gmopgcardname		= str_replace('　','',$shoppingOrderObject->gmopgcardname);
		$shoppingOrderObject->gmopglimityear		= mb_convert_kana(trim(stripslashes($_POST['gmopglimityear'])),'a');
		$shoppingOrderObject->gmopglimitmonth	= mb_convert_kana(trim(stripslashes($_POST['gmopglimitmonth'])),'a');
		$shoppingOrderObject->gmopgcardtype		= mb_convert_kana(trim(stripslashes($_POST['gmopgcardtype'])),'a');
		$shoppingOrderObject->gmopgcarddiv		= mb_convert_kana(trim(stripslashes($_POST['gmopgcarddiv'])),'a');
		// 妥当性検査
		if( strlen($shoppingOrderObject->gmopgcardnumber) == 0 ) {
			$shoppingOrderObject->addColumnError($request,'settle_method_errors','shopping.error.plugin.gmocard.ord.requirenumber');
		} else if( preg_match('/^[0-9]{16}$/',$shoppingOrderObject->gmopgcardnumber) == 0 ) {
			$shoppingOrderObject->addColumnError($request,'settle_method_errors','shopping.error.plugin.gmocard.ord.invalidnumber');
		}
		if( strlen($shoppingOrderObject->gmopgcardname) == 0 ) {
			$shoppingOrderObject->addColumnError($request,'settle_method_errors','shopping.error.plugin.gmocard.ord.requirename');
		}
		if( strlen($shoppingOrderObject->gmopglimityear) == 0 ) {
			$shoppingOrderObject->addColumnError($request,'settle_method_errors','shopping.error.plugin.gmocard.ord.requireyear');
		} else if( preg_match('/^[0-9]{2}$/',$shoppingOrderObject->gmopglimityear) == 0 ) {
			$shoppingOrderObject->addColumnError($request,'settle_method_errors','shopping.error.plugin.gmocard.ord.invalidyear');
		}
		if( strlen($shoppingOrderObject->gmopglimitmonth) == 0 ) {
			$shoppingOrderObject->addColumnError($request,'settle_method_errors','shopping.error.plugin.gmocard.ord.requiremonth');
		} else if( preg_match('/^[0-9]{2}$/',$shoppingOrderObject->gmopglimitmonth) == 0 ) {
			$shoppingOrderObject->addColumnError($request,'settle_method_errors','shopping.error.plugin.gmocard.ord.invalidmonth');
		}
		// 分割払い入力
		$cardDivTypeArray	= array();
		if ( strlen($this->settingValues['credit_dev'])>0 ) {
			$cardDivTypeArray	= explode(',',$this->settingValues['credit_dev']);
		}
		$cardTypeArray		= array('VISA','MASTER','JCB','DINERS','AMEX');
		if( count($cardTypeArray) > 0 ){
			if( strlen($shoppingOrderObject->gmopgcardtype) == 0 ) {
				$shoppingOrderObject->addColumnError($request,'settle_method_errors','shopping.error.plugin.gmocard.ord.requirecardtype');
			} else if( !in_array($shoppingOrderObject->gmopgcardtype,$cardTypeArray) ) {
				$shoppingOrderObject->addColumnError($request,'settle_method_errors','shopping.error.plugin.gmocard.ord.invalidcardtype');
			} else if( !in_array($shoppingOrderObject->gmopgcardtype,$cardDivTypeArray) && '01' != $shoppingOrderObject->gmopgcarddiv ) {
				$shoppingOrderObject->addColumnError($request,'settle_method_errors','shopping.error.plugin.gmocard.ord.unavairablecard',array($shoppingOrderObject->gmopgcardtype));
			}
		}
	}
	/**
	 * execute時の処理
	 */
	function execute( & $request, & $shoppingOrderObject ) {
		$logMessage		= date('Y-m-d H:i:s')."\r\n";
		$httpRequest	= $this->startDeal($request,$shoppingOrderObject);
		if ( $httpRequest ) {
			// 応答内容の解析
			$responseCode	= $httpRequest->statusCode;
			$responseBody	= trim($httpRequest->responseBody);
			$responseBody	= str_replace("\r\n","\n",$responseBody);
			$responseBody	= str_replace("\r","\n",$responseBody);
			
			$paramStringArray	= array();
			$paramStringArray 	= explode('&',trim($responseBody));
			$responseParamHash	= array();
			foreach( $paramStringArray as $paramString ) {
				list( $key, $val ) = explode('=',trim($paramString));
				$responseParamHash[$key]	= $val;
			}
			if( strlen($responseParamHash['ErrCode'])==0 ) {
				$logMessage	.= 'START DEAL=OK';
				$logMessage	.= "\r\n\r\n".$responseBody;
				$line = $responseParamHash['AccessID']."\n".$responseParamHash['AccessPass'];
				$shoppingOrderObject->setSettleTransactionCode( $request, $line );
			} else {
//				$errCodeArray = array();
//				$errCodeArray = explode('|', $responseParamHash['ErrCode']);
				$errInfoArray = array();
				$errInfoArray = explode('|', $responseParamHash['ErrInfo']);
				$errMessageArray = array();
				$errMessageArray = $this->getErrInfoMessage( $request, $errInfoArray );
				if ( count($errMessageArray)==0 ) {
				} else {
					foreach( $errMessageArray as $errMessage ) {
						$shoppingOrderObject->addColumnError($request,'settle_method_errors',$errMessage);
					}
				}
			}
		} else {
			// リクエストエラー
			$shoppingOrderObject->addColumnError($request,'settle_method_errors','shopping.error.plugin.gmocard.ord.failtoconnect');
		}
		if( $request->isError() ) {
			$logMessage	.= 'START DEAL=NG\n'.implode("\n",$request->errors);
			$logMessage	.= "\r\n\r\n".$responseBody;
		}
		
		if( !$request->isError() ) {
			// 決済実行
			$httpRequest = $this->executeSettlement($request,$shoppingOrderObject);
			if ( $httpRequest ) {
				// 応答内容の解析
				$responseCode	= $httpRequest->statusCode;
				$responseBody	= trim($httpRequest->responseBody);
				$responseBody	= str_replace("\r\n","\n",$responseBody);
				$responseBody	= str_replace("\r","\n",$responseBody);

				$paramStringArray	= array();
				$paramStringArray 	= explode('&',trim($responseBody));
				$responseParamHash	= array();
				foreach( $paramStringArray as $paramString ) {
					list( $key, $val ) = explode('=',trim($paramString));
					$responseParamHash[$key]	= $val;
				}
				
				// 決済実行結果で本認証サービスに対応したパラメータが返されているか確認
				$isSecure = false;
				if ( array_key_exists('ACSUrl', $responseParamHash)
					&& array_key_exists('PaReq', $responseParamHash)
					&& array_key_exists('MD', $responseParamHash)
				) {
					$isSecure = true;
				}
				
				if ( $isSecure ) {
					// 決済トランザクションコードに本人認証サービスに必要な値を設定
					$line = "\n".$responseParamHash['MD'];
					$shoppingOrderObject->setSettleTransactionCode( $request, $line );
					$this->acsUrl	= $responseParamHash['ACSUrl'];
					$this->paReq	= $responseParamHash['PaReq'];
					
					$logMessage	.= "\n".'SETTLE=OK';
					$logMessage	.= "\r\n\r\n".$responseBody;
					$shoppingOrderObject->setSettlePrice($request,$shoppingOrderObject->payment_total);
				} else {
					// 通常決済処理
					if( strlen($responseParamHash['ErrCode'])==0 ) {
						$logMessage	.= "\n".'SETTLE=OK';
						$logMessage	.= "\r\n\r\n".$responseBody;
						$shoppingOrderObject->setSettlePrice($request,$shoppingOrderObject->payment_total);
					} else {
//						$errCodeArray = array();
//						$errCodeArray = explode('|', $responseParamHash['ErrCode']);
						$errInfoArray = array();
						$errInfoArray = explode('|', $responseParamHash['ErrInfo']);
						$errMessageArray = array();
						$errMessageArray = $this->getErrInfoMessage( $request, $errInfoArray );
						if ( count($errMessageArray)==0 ) {
							$shoppingOrderObject->addColumnError($request,'settle_method_errors','shopping.error.plugin.gmocard.ord.failtosettle');
						} else {
							foreach( $errMessageArray as $errMessage ) {
								$shoppingOrderObject->addColumnError($request,'settle_method_errors',$errMessage);
							}
						}
					}
				}
			} else {
				// リクエストエラー
				$shoppingOrderObject->addColumnError($request,'settle_method_errors','shopping.error.plugin.gmocard.ord.failtoconnect');
			}
			if( $request->isError() ) {
				$logMessage	.= "\n".'SETTLE=NG\n'.implode("\n",$request->errors);
				$logMessage	.= "\r\n\r\n".$responseBody;
			}
		}
		// 決済実行日を更新
		$shoppingOrderObject->setSettleDate( $request, $shoppingOrderObject->settle_date );
		$shoppingOrderObject->settleLogLn( $request, $logMessage );
		if( $request->isError() ) {
			return false;
		} else {
			return true;
		}
	}

	/**
	 * 取引登録を実行する。
	 */
	function startDeal( & $request, & $shoppingOrderObject ) {
		// HttpRequestクラス
		spider_Controller::loadClassDefinition('util_HttpRequest');
		$httpRequest	= new util_HttpRequest($this->settingValues['entry_url'],'post');
		// 基本情報設定
		// 取引ID
		$httpRequest->addPostData('ShopID', $this->settingValues['shop_id']);
		// 取引パスワード
		$httpRequest->addPostData('ShopPass', $this->settingValues['shop_pass']);
		// オーダーID
		$httpRequest->addPostData('OrderID', $shoppingOrderObject->order_id);
		// 支払方法 (CHECK：有効性チェック,CAPTURE：即時売上,AUTH：仮売上,SAUTH：簡易オーソリ)
		$httpRequest->addPostData('JobCd', 'CAPTURE');
		// 商品コード
		$httpRequest->addPostData('ItemCode', '');
		// 利用金額 ※処理区分が『有効性チェック』を除き必須
		$httpRequest->addPostData('Amount', $shoppingOrderObject->payment_total);
		// 税送料
		$httpRequest->addPostData('Tax', 0);
		// 本人認証サービス利用フラグ(0：行なわない,1：行なう)
		$httpRequest->addPostData('TdFlag', '0');
		// 3Dセキュア表示店舗名
		$httpRequest->addPostData('TdTenantName', '');

		// HTTPリクエスト実行
		if ( $httpRequest->send(null,60) ) {
			return $httpRequest;
		} else {
			return false;
		}
	}
	/**
	 * 決済実行する。
	 */
	function executeSettlement( & $request, & $shoppingOrderObject ) {
		list( $accessId, $accessPass ) = explode("\n",trim($shoppingOrderObject->settle_transaction_code));
		if ( strlen($accessId)>0 && strlen($accessPass)>0 ) {
			// 3Dセキュア対応の確認
			$isSecure = false;
			if( preg_match('/^([oO][nN]|[tT][rR][uU][eE]|[yY][eE][sS])$/',$this->settingValues['3d_secure']) > 0 ) {
				$isSecure = true;
			}
			// HttpRequestクラス
			spider_Controller::loadClassDefinition('util_HttpRequest');
			$httpRequest	= new util_HttpRequest($this->settingValues['exec_url'],'post');
			// 基本情報設定
			$httpRequest->addPostData('AccessID', $accessId);
			$httpRequest->addPostData('AccessPass', $accessPass);
			$httpRequest->addPostData('OrderID', $shoppingOrderObject->order_id);
			// 支払方法 ※処理区分が『有効性チェック』を除き、必須
			// (1：一括,2：分割,3：ボーナス一括,4：ボーナス分割,5：リボ)
			$method = 0;
			if ( $shoppingOrderObject->gmopgcarddiv=='01'
				|| !array_key_exists($shoppingOrderObject->gmopgcarddiv,$this->cardDivHash) )
			{
				// 一括
				$method = 1;
			} else if ( $shoppingOrderObject->gmopgcarddiv=='99' ) {
				// リボ
				$method = 5;
			} else {
				// 分割
				$method = 2;
			}
			$httpRequest->addPostData('Method', $method);
			// 支払回数 ※支払方法が『分割』もしくは『ボーナス分割』は必須
			$payTimes = '';
			if ( $method==2 ) {
				$payTimes = intval($shoppingOrderObject->gmopgcarddiv);
			}
			$httpRequest->addPostData('PayTimes', $payTimes);
			// カード番号
			$httpRequest->addPostData('CardNo', $shoppingOrderObject->gmopgcardnumber);
			// 有効期限(YYMM形式)
			$httpRequest->addPostData('Expire', $shoppingOrderObject->gmopglimityear.$shoppingOrderObject->gmopglimitmonth);
			// セキュリティーコード
			$httpRequest->addPostData('SecurityCode', '');
			
			if( $isSecure ) {
				// HTTP_ACCEPT
				$httpRequest->addPostData('HttpAccept', $_SERVER['HTTP_ACCEPT']);
				// HTTP_USER_AGENT
				$httpRequest->addPostData('HttpUserAgent', $_SERVER['HTTP_USER_AGENT']);
				// 仕様端末情報
				$httpRequest->addPostData('DeviceCategory', 0);
			} else {
				// 暗証番号
				$httpRequest->addPostData('PIN', '');
			}
			
			// 加盟店自由項目1~3
			$httpRequest->addPostData('ClientField1', $shoppingOrderObject->gmopgcardname);
			$httpRequest->addPostData('ClientField2', $shoppingOrderObject->gmopgcardtype);
			$httpRequest->addPostData('ClientField3', '');
			// 加盟店自由項目返却フラグ(0：返却しない,1：返却する)
			$httpRequest->addPostData('ClientFieldFlag', '1');
	
			// HTTPリクエスト実行
			if ( $httpRequest->send(null,60) ) {
				return $httpRequest;	
			} else {
				return false;
			}
		} else {
			return false;
		}
	}
	/**
	 * エラー詳細コードよりエラーメッセージを取得する。
	 */
	function getErrInfoMessage( & $request, $errInfoArray ) {
		$errMessageArray = array();
		foreach ( $errInfoArray as $errInfo ) {
			// エラーメッセージの取得
			$errInfoMessage = $GLOBALS['spider.messages']['shopping.error.plugin.gmocard.ord.'.$errInfo];
			if ( strlen($errInfoMessage)>0 ) {
				// エラーメッセージの文字列が重複していないか確認
				$isExist = false;
				foreach( $errMessageArray as $errMessage ) {
					if ( $errMessage==$errInfoMessage ) {
						$isExist = true;
						break;
					}
				}
				if ( !$isExist ) {
					// エラーメッセージの文字列が重複していなければ追加
					array_push($errMessageArray,$errInfoMessage);
				}
			}
		}
		return $errMessageArray;
	}
	
	/**
	 * complete時にパラメータから判断して指定の注文オブジェクトを作成します。
	 */
	function getCompleteShoppingObject( & $request ) {
		$dbo		= $request->getAttribute('dbo');
		// 本人認証サービス結果
		$pares	= trim(stripslashes($_POST['PaRes']));
		// 取引ID
		$md		= trim(stripslashes($_POST['MD']));

		// 取引IDから注文情報読み込みの試行
		if( strlen($pares) > 0 && strlen($md) > 0 ) {
			$sql	= 'SELECT '.TABLE_NAME_SHOPPING_ORDER.'.* '
				.' FROM '.TABLE_NAME_SHOPPING_ORDER
				.' WHERE '.TABLE_NAME_SHOPPING_ORDER.'.settle_transaction_code LIKE "%'.$md.'"'
			;
			$obj = spider_Controller::createObject('shopping_DaoShoppingOrder');
			$shoppingOrderObject = $dbo->queryAll( $sql,$obj,true,false );
			if ( false === $shoppingOrderObject ) {
				$shoppingOrderObject->addColumnError($request,'settle_method_errors','database2.error.common');
			} else {
				if( $shoppingOrderObject->settle_method == $this->getMethodNumber() ) {
					return $shoppingOrderObject;
				} else {
					return null;
				}
			}	
		}
		return null;
	}
	/**
	 * complete時の処理
	 */
	function settlement( & $request, & $shoppingOrderObject ) {
		$logMessage	= date('Y-m-d H:i:s')."\r\n";
		// 本人認証サービス結果
		$pares	= trim(stripslashes($_POST['PaRes']));
		// 取引ID
		$md		= trim(stripslashes($_POST['MD']));
		
		if ( strlen($pares) > 0 && strlen($md) > 0 ) {
			// HttpRequestクラス
			spider_Controller::loadClassDefinition('util_HttpRequest');
			$httpRequest	= new util_HttpRequest($this->settingValues['secure_url'],'post');
			$httpRequest->addPostData('PaRes', $pares);
			$httpRequest->addPostData('MD', $md);
			if ( $httpRequest->send(null,60) ) {
				if ( $httpRequest ) {
					// 応答内容の解析
					$responseCode	= $httpRequest->statusCode;
					$responseBody	= trim($httpRequest->responseBody);
					$responseBody	= str_replace("\r\n","\n",$responseBody);
					$responseBody	= str_replace("\r","\n",$responseBody);
	
					$paramStringArray	= array();
					$paramStringArray 	= explode('&',trim($responseBody));
					$responseParamHash	= array();
					foreach( $paramStringArray as $paramString ) {
						list( $key, $val ) = explode('=',trim($paramString));
						$responseParamHash[$key]	= $val;
					}
					if( strlen($responseParamHash['ErrCode'])==0 ) {
						$logMessage	.= "\n".'SETTLE=OK';
						$logMessage	.= "\r\n\r\n".$responseBody;
					} else {
//						$errCodeArray = array();
//						$errCodeArray = explode('|', $responseParamHash['ErrCode']);
						$errInfoArray = array();
						$errInfoArray = explode('|', $responseParamHash['ErrInfo']);
						$errMessageArray = array();
						$errMessageArray = $this->getErrInfoMessage( $request, $errInfoArray );
						if ( count($errMessageArray)==0 ) {
							$shoppingOrderObject->addColumnError($request,'settle_method_errors','shopping.error.plugin.gmocard.ord.failtosettle');
						} else {
							foreach( $errMessageArray as $errMessage ) {
								$shoppingOrderObject->addColumnError($request,'settle_method_errors',$errMessage);
							}
						}
					}
				}
			} else {
				$shoppingOrderObject->addColumnError($request,'settle_method_errors','shopping.error.plugin.gmocard.ord.failtoconnect');
			}
		} else {
			$shoppingOrderObject->addColumnError($request,'settle_method_errors','shopping.error.plugin.gmocard.ord.failtoprivacy');
		}
		
		if( !$request->isError() ) {
			// 決済成功の場合決済状態を支払済みに変更
			$logMessage	.= "\n\nSETTLE=OK\n".date('Y-m-d H:i:s');
			$shoppingOrderObject->setSettlePrice($request,$shoppingOrderObject->payment_total);
			$shoppingOrderObject->setSettleDate( $request, $shoppingOrderObject->settle_date );
		} else {
			// 決済失敗の場合
			$logMessage	.= "\n\nSETTLE=NG\n".date('Y-m-d H:i:s');
		}
		$shoppingOrderObject->settleLogLn( $request, $logMessage );
		if( $request->isError() ) {
			return false;
		} else {
			return true;
		}
	}
	/**
	 * 妥当性検査時の処理
	 */
	function validate( & $request ) {
		$this->enable	= true;
		$isError	= false;
		if( 0 != $this->feeType ) {
			$request->addLocaledError('shopping.error.plugin.gmocard.setting.nocharge',SPIDER_LOG_LEVEL_ERROR,array());
			$isError	= false;
		} else {
			$this->feeType	= 0;
			$this->feeValue	= 0;
		}
		$this->settingValues['shop_id']	= mb_convert_kana($this->settingValues['shop_id'],'a');
		if( strlen(trim($this->settingValues['shop_id'])) == 0 ) {
			$this->enable	= false;
		} else if( preg_match('/^[0-9a-zA-Z]+$/',$this->settingValues['shop_id']) == 0 ) {
			$request->addLocaledError('shopping.error.plugin.gmocard.setting.invalidshopid',SPIDER_LOG_LEVEL_ERROR,array());
		}
		$this->settingValues['shop_pass']	= mb_convert_kana($this->settingValues['shop_pass'],'a');
		if( strlen(trim($this->settingValues['shop_pass'])) == 0 ) {
			$this->enable	= false;
		}
		if( $this->enable ) {
			if( strlen($this->settingValues['entry_url']) == 0 ) {
				$request->addLocaledError('shopping.error.plugin.gmocard.setting.invalidurl1',SPIDER_LOG_LEVEL_ERROR,array());
			}
			if( strlen($this->settingValues['exec_url']) == 0 ) {
				$request->addLocaledError('shopping.error.plugin.gmocard.setting.invalidurl2',SPIDER_LOG_LEVEL_ERROR,array());
			}
			if( strlen($this->settingValues['alter_url']) == 0 ) {
				$request->addLocaledError('shopping.error.plugin.gmocard.setting.invalidurl3',SPIDER_LOG_LEVEL_ERROR,array());
			}
			if( strlen($this->settingValues['change_url']) == 0 ) {
				$request->addLocaledError('shopping.error.plugin.gmocard.setting.invalidurl4',SPIDER_LOG_LEVEL_ERROR,array());
			}
			if( $isError ) {
				$this->enable	= false;
			}
		}
		if( $request->isError() ) {
			return false;
		} else {
			return true;
		}
	}
	/**
	 * 決済状態同期が有効か確認する抽象メソッド
	 * 注文オブジェクトを引数にとって外部サービスの決済状態と状態を同期します
	 * @param $request spider_HttpRequestインスタンス参照
	 * @param $shoppingOrderObject shopping_DaoShoppingOrderインスタンス参照
	 * @return boolean 成功したらtrue/失敗したらfalse
	 */
	function enableSynchronize( $shoppingOrderObject = null ) {
		return true;
	}
	/**
	 * 決済状態同期の抽象メソッド
	 * 注文オブジェクトを引数にとって外部サービスの決済状態と状態を同期します
	 * @param $request spider_HttpRequestインスタンス参照
	 * @param $shoppingOrderObject shopping_DaoShoppingOrderインスタンス参照
	 * @return boolean 成功したらtrue/失敗したらfalse
	 */
	function settleSynchronize( & $request, & $shoppingOrderObject ) {
		if ( $shoppingOrderObject->status_flag<200 ) {
			$logMessage	= date('Y-m-d H:i:s')."\r\n";
			$dbo	= $request->getAttribute('dbo');
			// HttpRequestクラス
			spider_Controller::loadClassDefinition('util_HttpRequest');
			$httpRequest	= new util_HttpRequest($this->settingValues['search_url'],'post');
			// 注文ステータスが有効の場合のみ、決済状態同期を実行する
			// 基本情報設定
			$httpRequest->addPostData('ShopID', $this->settingValues['shop_id']);
			$httpRequest->addPostData('ShopPass', $this->settingValues['shop_pass']);
			// OrderID
			$httpRequest->addPostData('OrderID', $shoppingOrderObject->order_id);
			// HTTPリクエスト実行
			if( $httpRequest->send(null,60) ) {
				// 応答内容の解析
				$responseCode	= $httpRequest->statusCode;
				$responseBody	= trim($httpRequest->responseBody);
				$responseBody	= str_replace("\r\n","\n",$responseBody);
				$responseBody	= str_replace("\r","\n",$responseBody);
				// 結果
				$paramStringArray	= array();
				$paramStringArray 	= explode('&',trim($responseBody));
				$responseParamHash	= array();
				foreach( $paramStringArray as $paramString ) {
					list( $key, $val ) = explode('=',trim($paramString));
					$responseParamHash[$key]	= $val;
				}
				if( strlen($responseParamHash['ErrCode'])==0 ) {
					// 決済状態が一致しているか確認
					// Status(UNPROCESSED：未決済,CAPTURE：即時売上,VOID：取消)
					if ( $responseParamHash['Status']=='UNPROCESSED' ) {
						// 「新規」を設定
						$shoppingOrderObject->status_settle = 0;
					} else if ( $responseParamHash['Status']=='CAPTURE' ) {
						// 「納品済」を設定
						$shoppingOrderObject->status_settle = 101;
					} else if ( $responseParamHash['Status']=='VOID' ) {
						// 「キャンセル」を設定
						$shoppingOrderObject->status_settle = 201;
					} else {
						// 未設定のカード決済状態の場合、エラーを返す
						$shoppingOrderObject->addColumnError($request,'settle_method_errors','shopping.error.plugin.gmocard.ord.invalidstatus');
					}
				} else {
//					$errCodeArray = array();
//					$errCodeArray = explode('|', $responseParamHash['ErrCode']);
					$errInfoArray = array();
					$errInfoArray = explode('|', $responseParamHash['ErrInfo']);
					$errMessageArray = array();
					$errMessageArray = $this->getErrInfoMessage( $request, $errInfoArray );
					if ( count($errMessageArray)==0 ) {
						$shoppingOrderObject->addColumnError($request,'settle_method_errors','shopping.error.plugin.gmocard.ord.failtosync');
					} else {
						foreach( $errMessageArray as $errMessage ) {
							$shoppingOrderObject->addColumnError($request,'settle_method_errors',$errMessage);
						}
					}
				}
			} else {
				// リクエストエラー
				$shoppingOrderObject->addColumnError($request,'settle_method_errors','shopping.error.plugin.gmocard.ord.failtoconnect');
			}
			// 結果を格納した注文情報を更新
			if( $request->isError() ) {
				$logMessage	.= "\n".'SYNCHRONIZE=NG\n'.implode("\n",$request->errors);
			} else {
				$logMessage	.= "\n".'SYNCHRONIZE=OK';
			}
			$logMessage	.= "\r\n\r\n".$responseBody;
			$shoppingOrderObject->settleLogLn( $request, $logMessage );
			// 決済ログと状態更新
			$sql	= 'UPDATE '.TABLE_NAME_SHOPPING_ORDER.' SET '
				.' status_settle='.$shoppingOrderObject->status_settle
				.', updated_date=NOW()'
				.' WHERE order_number='.$shoppingOrderObject->order_number;
			if( $dbo->query($sql) ){
			} else {
				$shoppingOrderObject->addColumnError($request,'settle_method_errors','shopping.error.plugin.gmocard.ord.savedb',array($shoppingOrderObject->order_id));
				return false;
			}
		} else {
			return true;
		}
	}
	/**
	 * 決済キャンセルメソッド実装
	 * @param $request spider_HttpRequestインスタンス参照
	 * @param $shoppingOrderObject shopping_DaoShoppingOrderインスタンス参照
	 * @return boolean 成功したらtrue/失敗したらfalse
	 */
	function settleCancel( & $request, & $shoppingOrderObject ){
		list( $accessId, $accessPass ) = explode("\n",trim($shoppingOrderObject->settle_transaction_code));
		if ( strlen($accessId)>0 && strlen($accessPass)>0 ) {
			$logMessage	= date('Y-m-d H:i:s')."\r\n";
			$dbo	= $request->getAttribute('dbo');
			// HttpRequestクラス
			spider_Controller::loadClassDefinition('util_HttpRequest');
			$httpRequest	= new util_HttpRequest($this->settingValues['alter_url'],'post');
			// 基本情報設定
			$httpRequest->addPostData('ShopID', $this->settingValues['shop_id']);
			$httpRequest->addPostData('ShopPass', $this->settingValues['shop_pass']);
			$httpRequest->addPostData('AccessID', $accessId);
			$httpRequest->addPostData('AccessPass', $accessPass);
			// JobCd(VOID：取消,RETURN：返品,RETURNX：月跨り返品)
			$httpRequest->addPostData('JobCd', 'VOID');
			// HTTPリクエスト実行
			if( $httpRequest->send(null,60) ) {
				// 応答内容の解析
				$responseCode	= $httpRequest->statusCode;
				$responseBody	= trim($httpRequest->responseBody);
				$responseBody	= str_replace("\r\n","\n",$responseBody);
				$responseBody	= str_replace("\r","\n",$responseBody);
				// 結果
				$paramStringArray	= array();
				$paramStringArray 	= explode('&',trim($responseBody));
				$responseParamHash	= array();
				foreach( $paramStringArray as $paramString ) {
					list( $key, $val ) = explode('=',trim($paramString));
					$responseParamHash[$key]	= $val;
				}
				if( strlen($responseParamHash['ErrCode'])==0 ) {
				} else {
//					$errCodeArray = array();
//					$errCodeArray = explode('|', $responseParamHash['ErrCode']);
					$errInfoArray = array();
					$errInfoArray = explode('|', $responseParamHash['ErrInfo']);
					$errMessageArray = array();
					$errMessageArray = $this->getErrInfoMessage( $request, $errInfoArray );
					if ( count($errMessageArray)==0 ) {
						$shoppingOrderObject->addColumnError($request,'settle_method_errors','shopping.error.plugin.gmocard.ord.failtocancel');
					} else {
						foreach( $errMessageArray as $errMessage ) {
							$shoppingOrderObject->addColumnError($request,'settle_method_errors',$errMessage);
						}
					}
				}
			} else {
				// リクエストエラー
				$shoppingOrderObject->addColumnError($request,'settle_method_errors','shopping.error.plugin.gmocard.ord.failtoconnect');
			}
			// 結果を格納した注文情報を更新
			if( $request->isError() ) {
				$logMessage	.= "\n".'VOID=NG\n'.implode("\n",$request->errors);
			} else {
				$logMessage	.= "\n".'VOID=OK';
			}
			$logMessage	.= "\r\n\r\n".$responseBody;
			$shoppingOrderObject->settleLogLn( $request, $logMessage );
		} else {
			$shoppingOrderObject->addColumnError($request,'settle_method_errors','shopping.error.plugin.gmocard.ord.failtoload');
			return false;
		}
		return true;
	}
	/**
	 * 決済金額変更抽象メソッド
	 * @param $request spider_HttpRequestインスタンス参照
	 * @param $shoppingOrderObject shopping_DaoShoppingOrderインスタンス参照
	 * @return boolean 成功したらtrue/失敗したらfalse
	 */
	function settleChangeAmount( & $request, & $shoppingOrderObject ) {
		list( $accessId, $accessPass ) = explode("\n",trim($shoppingOrderObject->settle_transaction_code));
		if ( strlen($accessId)>0 && strlen($accessPass)>0 ) {
			$logMessage	= date('Y-m-d H:i:s')."\r\n";
			$dbo	= $request->getAttribute('dbo');
			// HttpRequestクラス
			spider_Controller::loadClassDefinition('util_HttpRequest');
			$httpRequest	= new util_HttpRequest($this->settingValues['change_url'],'post');
			// 基本情報設定
			$httpRequest->addPostData('ShopID', $this->settingValues['shop_id']);
			$httpRequest->addPostData('ShopPass', $this->settingValues['shop_pass']);
			$httpRequest->addPostData('AccessID', $accessId);
			$httpRequest->addPostData('AccessPass', $accessPass);
			// JobCd(CAPTURE：即時売上,AUTH：仮売上,SAUTH：簡易オーソリ)
			$httpRequest->addPostData('JobCd', 'CAPTURE');
			// 利用金額 ※変更後の利用金額を設定
			$httpRequest->addPostData('Amount', $shoppingOrderObject->payment_total);
			// 税送料
			$httpRequest->addPostData('Tax', 0);
			
			// HTTPリクエスト実行
			if( $httpRequest->send(null,60) ) {
				// 応答内容の解析
				$responseCode	= $httpRequest->statusCode;
				$responseBody	= trim($httpRequest->responseBody);
				$responseBody	= str_replace("\r\n","\n",$responseBody);
				$responseBody	= str_replace("\r","\n",$responseBody);
				// 結果
				$paramStringArray	= array();
				$paramStringArray 	= explode('&',trim($responseBody));
				$responseParamHash	= array();
				foreach( $paramStringArray as $paramString ) {
					list( $key, $val ) = explode('=',trim($paramString));
					$responseParamHash[$key]	= $val;
				}
				if( strlen($responseParamHash['ErrCode'])==0 ) {
				} else {
//					$errCodeArray = array();
//					$errCodeArray = explode('|', $responseParamHash['ErrCode']);
					$errInfoArray = array();
					$errInfoArray = explode('|', $responseParamHash['ErrInfo']);
					$errMessageArray = array();
					$errMessageArray = $this->getErrInfoMessage( $request, $errInfoArray );
					if ( count($errMessageArray)==0 ) {
						$shoppingOrderObject->addColumnError($request,'settle_method_errors','shopping.error.plugin.gmocard.ord.failtochange');
					} else {
						foreach( $errMessageArray as $errMessage ) {
							$shoppingOrderObject->addColumnError($request,'settle_method_errors',$errMessage);
						}
					}
				}
			} else {
				// リクエストエラー
				$shoppingOrderObject->addColumnError($request,'settle_method_errors','shopping.error.plugin.gmocard.ord.failtoconnect');
			}
			// 結果を格納した注文情報を更新
			if( $request->isError() ) {
				$logMessage	.= "\n".'CHANGEAMOUNT=NG\n'.implode("\n",$request->errors);
			} else {
				$logMessage	.= "\n".'CHANGEAMOUNT=OK';
			}
			$logMessage	.= "\r\n\r\n".$responseBody;
			$shoppingOrderObject->setSettlePrice($request,$shoppingOrderObject->payment_total);
			$shoppingOrderObject->settleLogLn( $request, $logMessage );
		} else {
			$shoppingOrderObject->addColumnError($request,'settle_method_errors','shopping.error.plugin.gmocard.ord.failtoload');
			return false;
		}
	} 
	/**
	 * 必要に応じた完了フォームHTML取得メソッド
	 */
	function getViewExecuteHtml( $shoppingOrderObject ) {
		// 3Dセキュア対応の確認
		$isSecure = false;
		if( preg_match('/^([oO][nN]|[tT][rR][uU][eE]|[yY][eE][sS])$/',$this->settingValues['3d_secure']) > 0 ) {
			$isSecure = true;
		}
		$returnString = '';
		if ( $isSecure ) {
			list( $accessId, $accessPass, $md ) = explode("\n",trim($shoppingOrderObject->settle_transaction_code));
			$returnString	= <<< __METHOD_EXPLANATION__
<form name="ACSCall" action="" method="POST">
<noscript>
<br /><br />
<center>
<h2>3-D セキュア認証を続けます。<br />ボタンをクリックしてください。</h2>
<input type="submit" value="OK">
</center>
</noscript>
__METHOD_EXPLANATION__;
			$returnString	.= '<input type="hidden" name="PaReq" value="'.$this->paReq.'">';
			$returnString	.= '<input type="hidden" name="TermUrl" value="'.SPIDER_URL_BASE.'shopping/order/complete.php">';
			$returnString	.= '<input type="hidden" name="MD" value="'.$md.'">';
			$returnString	.= '</form>';
		}
		return $returnString;
	}
}
?>