/*********************************************************************
 *	All Rights reserved,Copyright (c) K-Opticom
 **********************************************************************
 *＜プログラム内容＞
 *	システム名         ：eo顧客基幹システム
 *	モジュール名        ：JKKejbKKA0120002SecProc
 *	ソースファイル名      ：JKKejbKKA0120002SecProc.java
 *	作成者           ：GDC)J.Hortilano 
 *	日付             ：2012年06月13日
 *＜機能概要＞
 *	オーソリ状況取得API（IVR）の副次処理部品
 *＜修正履歴＞
 *	バージョン          修正日          修正者                       修正内容
 *	v58.00.00       2022/06/14   GDC)J.Hortilano             ANK-3846-00-00_【クレカ】クリアパス→ペイジェント移行
 *	v58.00.01       2022/12/06    FJ)永井                    ANK-3846-13-00_【クレカ】クリアパス→ペイジェント移行 仕変13
 *	v66.00.00       2023/05/29    FJ)謝                      【ANK-4408-01-00】口振請求及びWeb申込システム移行 事前対応（ＩＶＲマイナーエラー対応）
 *	v67.00.00       2023/07/28    FJ)三角                    【ANK-4428-00-00】クレカIVRの識別ID有効期限切れ対応
 **********************************************************************/

package eo.ejb.common.db;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.net.HttpURLConnection;
import java.net.URL;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import com.fujitsu.futurity.model.base.CAANConnectionMgr;
import com.fujitsu.futurity.model.base.CAANException;
import com.fujitsu.futurity.model.base.CAANJDBCUtil;
import com.fujitsu.futurity.model.base.CAANMsg;
import com.fujitsu.futurity.model.base.CAANRuntimeException;
import com.fujitsu.futurity.model.base.jcc.util.JCCDateUtil;
import com.fujitsu.futurity.model.common.check.HalfCharCheck;
import com.fujitsu.futurity.model.ejb.common.JSYejbConnection;
import com.fujitsu.futurity.model.ejb.common.JSYejbLog;
import com.fujitsu.futurity.model.ejb.common.StatusCodes;
import com.fujitsu.futurity.model.ejb.common.fw.AgentDispatchContext;

import eo.common.util.JKKStringConverter;
import eo.common.util.JKKStringUtil;
import eo.ejb.cbm.entity.KK3381ETMsg;
import eo.ejb.cbs.cbsmsg.EKKA0120002CBSMsg;
import eo.ejb.cbs.cbsmsg.EKKA0120002CBSMsg1List;
import eo.ejb.cbs.cbsmsg.EKKA0120002CBSMsg2List;
import eo.ejb.common.JCCModelCommon;
import eo.ejb.common.JKKModelCommon;

import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;

/**
 * <p>
 * オーソリ状況取得API（IVR）独自処理部品
 * </p>
 * 
 * @author GDC)J.Hortilano
 */
public class JKKejbKKA0120002SecProc
{

	/** モード取得用キー */
	private static final String IVR_MODE_KEY = "IVR_API_TEST_MODE";
	/** テストモード OFF(本番・検証) */
	private static final String TEST_MODE_OFF = "OFF";
	
	
    /** URL */
    private static final String APL_CONST_URL_KEY = "KK_IVR_AUTH_JKY_GET_URL";
    /** タイムアウト時間 */
    private static final String APL_READTIMEOUT_KEY = "KK_IVR_AUTH_JKY_GET_TIMEOUT";


    /** APIキー */
	private static final String API_KEY = "apiKey";
	/** APIパスワード */
	private static final String API_PASSWORD = "apiPassword";
	/** 受付番号 */
	private static final String RECEIPT_NO = "receiptNo";
    /** 任意項目返却フラグ */
    private static final String ANYITEMRETURNFLG = "anyItemReturnFlg";
    /** 処理詳細返却フラグ */
    private static final String DETAILRETURNFLG = "detailReturnFlg";

    /** 固定値："0"(返却しない) */
    private static final String NOT_RETURNED = "0";
    
// ANK-4408-01-00 DEL START
//	/** エラーフラグ(EA：設定値取得エラー) */
//	private static final String EA_ERR_FLAG = "EA";
// ANK-4408-01-00 DEL END

	
	/** SMS文字コード */
	private static final String ENCODING = "UTF-8";
	/** CONTENT_TYPE  */
	private static final String CONTENT_TYPE = "Content-Type";
	/** CONTENT_TYPE_設定値  */
	private static final String CONTENT_TYPE_VALUE = "application/json; charset=UTF-8";
	
	
    /** 結果コード */
	private static final String RESULTCODE = "resultCode";
    /** エラーメッセージ一覧 */
	private static final String ERRORMESSAGELIST = "errorMessageList";
    /** 識別ID */
	private static final String DISCERNMENTID = "discernmentId";
    /** 識別ID 有効期限 */
	private static final String DISCERNMENTIDENDDATETIME = "discernmentIdEndDatetime";
    /** ステータスコード */
	private static final String STATUSCODE = "statusCode";
    /** フローレベルID */
	private static final String FLOWLEVELID = "flowLevelId";
    /** フローレベル名称 */
	private static final String FLOWLEVELNAME = "flowLevelName";
    /** 発信者電話番号 */
	private static final String CALLERTELNO = "callerTelNo";
    /** 着信日時 */
	private static final String INCOMINGDATETIME = "incomingDatetime";
    /** カード登録成功フラグ */
	private static final String SAVESUCCESSFLG = "saveSuccessFlg";
    /** PSP ステータスコード */
	private static final String PSPSTATUSCODE = "pspStatusCode";
    /** 処理実行日時 */
	private static final String TRANSACTIONDATETIME = "transactionDatetime";
    /** 処理結果 */
	private static final String RESULT = "result";
    /** レスポンスコード */
	private static final String RESPONSECODE = "responseCode";
    /** レスポンス詳細 */
	private static final String RESPONSEDETAIL = "responseDetail";
    /** 顧客カード数 */
	private static final String NUMOFCARDS = "numOfCards";
    /** 顧客カードID */
	private static final String CUSTOMERCARDID = "customerCardId";
    /** カード発行会社コード */
	private static final String ISSURID = "issurId";
    /** カード発行会社名 */
	private static final String ISSURNAME = "issurName";
    /** フィンガープリント */
	private static final String FINGERPRINT = "fingerprint";
    /** マスクされたカード番号 */
	private static final String MASKEDCARDNUMBER = "maskedCardNumber";
    /** カード有効期限 */
	private static final String CARDVALIDTERM = "cardValidTerm";
    /** カード名義人 */
	private static final String CARDHOLDERNAME = "cardholderName";
    /** 取扱カード会社コード */
	private static final String ACQID = "acqId";
    /** 取扱カード会社名 */
	private static final String ACQNAME = "acqName";
    /** 顧客ID */
	private static final String CUSTOMERID = "customerId";
    /** デビット・プリペイド判定結果 */
	private static final String DEBITPREPAIDTYPE = "debitPrepaidType";
    /** イシュア区分 */
	private static final String ISSURCLASS = "issurClass";
    /** カードブランド */
	private static final String CARDBRAND = "cardBrand";


    /** 最終処理結果 */
	private static final String LASTTRANSACTION = "lastTransaction";
    /** カード情報設定電文 */
	private static final String TELEGRAM025 = "telegram025";
// ANK-4428-00-00 ADD START
    /** 登録処理ID項目数 */
	private static final int ADD_TRN_ID_KMKNUM = 7;
// ANK-4428-00-00 ADD END

    /**
	 * コンストラクタ.
	 */
	public JKKejbKKA0120002SecProc()
	{
		super();
	}


	/**
	 * IVRのオーソリ状況取得APIを呼出す。
	 * @param inCBSMsg 個別割引適用可否照会・変更依頼メッセージ
	 * @param inContext AgentDispatchContext
	 * @throws Exception 
	 */
	public void execute(CAANMsg inCBSMsg, AgentDispatchContext inContext) throws Exception
	{
		// 開始ログ出力を実施。
		JSYejbLog.println(JSYejbLog.EXECUTION, JKKejbKKA0120002SecProc.class.getClass(), "JKKejbKKA0120002SecProc#execute START");
		
		String response = null;
		
		/** 接続先などの判定に使用
		*   OFF： 本番・検証、ON: 開発
		*/
		String mode = JCCModelCommon.getApplicationConst(IVR_MODE_KEY);

		String strUrl = "";
		
		// URL
		strUrl = JCCModelCommon.getApplicationConst(APL_CONST_URL_KEY);
		// 読取タイムアウト
		String strReadTimeout = JCCModelCommon.getApplicationConst(APL_READTIMEOUT_KEY);
		// APIキー
		String apiKey = JCCModelCommon.getApplicationConst(inCBSMsg.getString(EKKA0120002CBSMsg.APIKEY));
		// APIパスワード
		String apiPassword = JCCModelCommon.getApplicationConst(inCBSMsg.getString(EKKA0120002CBSMsg.APIPASSWORD));

		JSYejbLog.println(JSYejbLog.EXECUTION, JKKejbKKA0120002SecProc.class.getClass() , "JKKejbKKA0120002SecProc#Content-Type=" + CONTENT_TYPE_VALUE);
		JSYejbLog.println(JSYejbLog.EXECUTION, JKKejbKKA0120002SecProc.class.getClass() , "JKKejbKKA0120002SecProc#URL=" + strUrl);
		
		// 読取タイムアウト
		int readTimeout = Integer.parseInt(strReadTimeout);

		try
		{
			// JSON形式の文字列を作成する。
			String json = requestParamMake(inCBSMsg, inContext, apiKey, apiPassword);
			JSYejbLog.println(JSYejbLog.EXECUTION, JKKejbKKA0120002SecProc.class.getClass(), "JKKejbKKA0120002SecProc# request=" + json);

			// 本番・検証
			if (TEST_MODE_OFF.equals(mode))
			{
				// APIに対してリクエストを送信する。。
				response = callPost(strUrl, json, readTimeout);
				JSYejbLog.println(JSYejbLog.EXECUTION, JKKejbKKA0120002SecProc.class.getClass(), "JKKejbKKA0120002SecProc# response=" + response);
				
				// レスポンス電文を設定
				editOutMsg(inCBSMsg, response);
			}
			// テストモード（開発）
			else
			{
				JSYejbLog.println(JSYejbLog.EXECUTION, JKKejbKKA0120002SecProc.class.getClass(), "JKKejbKKA0120002SecProc# response=dummy");
				// ダミーレスポンス
				editDummyOutMsg(inCBSMsg, inContext);
			}
			
// ANK-4408-01-00 DEL START
//			// 結果コードチェック
//			String resultCode = inCBSMsg.getCAANMsgList(EKKA0120002CBSMsg.EKKA0120002CBSMSG1LIST)[0].getString(EKKA0120002CBSMsg1List.RESULTCODE);
//			if(!"0".equals(resultCode))
//			{
//				JSYejbLog.println(JSYejbLog.EXECUTION, JKKejbKKA0120002SecProc.class.getClass() , "結果コードエラー 結果コード："+resultCode);
//				// ステータス設定
//				inCBSMsg.set(EKKA0120002CBSMsg.STATUS, StatusCodes.RELATION_ERR);
//				inCBSMsg.set(EKKA0120002CBSMsg.RECEIPTNO_ERR, EA_ERR_FLAG);
//				return;
//
//			}
// ANK-4408-01-00 DEL END
		}
		catch (Exception e)
		{
			StringBuilder sb = new StringBuilder();
			StringWriter sw = new StringWriter();
			PrintWriter pw = new PrintWriter(sw);
			e.printStackTrace(pw);
			sb.append("\n" + sw.toString());
			JSYejbLog.println(JSYejbLog.EXECUTION, JKKejbKKA0120002SecProc.class.getClass(),"#JKKejbKKA0120002SecProc(Exception)発生" + sb.toString());
			
			throw e;
		}
		
		// 終了ログ出力を実施。
		JSYejbLog.println(JSYejbLog.EXECUTION, JKKejbKKA0120002SecProc.class.getClass(), "JKKejbKKA0120002SecProc#execute END");
	}

	/**
	 * 共通APIのレスポンス電文を設定します。
	 * <br>
	 * @param inCBSMsg 個別割引適用可否照会・変更依頼メッセージ
	 * @param resServiceMap レスポンスサービスマップ
	 * @throws IOException 
	 */
	@SuppressWarnings("unchecked")
	private void editOutMsg(CAANMsg inCBSMsg, String response) throws IOException, CAANException
	{
        List<CAANMsg> caanMsg1List = new ArrayList<CAANMsg>();
		
	    CAANMsg caanMsg = new CAANMsg(EKKA0120002CBSMsg1List.class.getName());

        Map<String, Object> map = new HashMap<String, Object>();
        ObjectMapper mapper = new ObjectMapper();
	    try
	    {
	    	// convert JSON string to Map
            map = mapper.readValue(response, new TypeReference<HashMap<String, Object>>() {});

            caanMsg.set(EKKA0120002CBSMsg1List.RESULTCODE, map.get(RESULTCODE));
            
            List<String> errorMessageList = (List<String>) map.get(ERRORMESSAGELIST);
            if(errorMessageList != null)
            {
                List<CAANMsg> caanMsg2List = new ArrayList<CAANMsg>();
                for(String errorMessage : errorMessageList)
                {
                	CAANMsg ekka0120001CBSMsg2 = new CAANMsg(EKKA0120002CBSMsg2List.class.getName());
                	ekka0120001CBSMsg2.set(EKKA0120002CBSMsg2List.ERRORMESSAGE, errorMessage);
                	caanMsg2List.add(ekka0120001CBSMsg2);
                }
                // Listから配列に変換して設定
                caanMsg.set(EKKA0120002CBSMsg1List.EKKA0120002CBSMSG2LIST, caanMsg2List.toArray(new CAANMsg[caanMsg2List.size()]));
            }

            caanMsg.set(EKKA0120002CBSMsg1List.DISCERNMENTID, map.get(DISCERNMENTID));
            caanMsg.set(EKKA0120002CBSMsg1List.DISCERNMENTIDENDDATETIME, map.get(DISCERNMENTIDENDDATETIME));
            caanMsg.set(EKKA0120002CBSMsg1List.STATUSCODE, map.get(STATUSCODE));
            caanMsg.set(EKKA0120002CBSMsg1List.FLOWLEVELID, map.get(FLOWLEVELID));
            caanMsg.set(EKKA0120002CBSMsg1List.FLOWLEVELNAME, map.get(FLOWLEVELNAME));
            caanMsg.set(EKKA0120002CBSMsg1List.CALLERTELNO, map.get(CALLERTELNO));
            caanMsg.set(EKKA0120002CBSMsg1List.INCOMINGDATETIME, map.get(INCOMINGDATETIME));
            caanMsg.set(EKKA0120002CBSMsg1List.SAVESUCCESSFLG, map.get(SAVESUCCESSFLG));

            // ※１：送受信で取得した最終処理結果(KEY:lastTransaction)の『カード情報設定電文』の結果(KEY:telegram025)
            Map<String, Object> finalTransMap = (Map<String, Object>)map.get(LASTTRANSACTION);
            if(finalTransMap != null)
            {
                Map<String, Object> telgramTransMap = (Map<String, Object>)finalTransMap.get(TELEGRAM025);
                if(telgramTransMap != null)
                {
	                caanMsg.set(EKKA0120002CBSMsg1List.PSPSTATUSCODE, telgramTransMap.get(PSPSTATUSCODE));
	                caanMsg.set(EKKA0120002CBSMsg1List.TRANSACTIONDATETIME, telgramTransMap.get(TRANSACTIONDATETIME));
	                caanMsg.set(EKKA0120002CBSMsg1List.RESULT, telgramTransMap.get(RESULT));
	                caanMsg.set(EKKA0120002CBSMsg1List.RESPONSECODE, telgramTransMap.get(RESPONSECODE));
	                caanMsg.set(EKKA0120002CBSMsg1List.RESPONSEDETAIL, telgramTransMap.get(RESPONSEDETAIL));
	                caanMsg.set(EKKA0120002CBSMsg1List.NUMOFCARDS, telgramTransMap.get(NUMOFCARDS));
	                caanMsg.set(EKKA0120002CBSMsg1List.CUSTOMERCARDID, telgramTransMap.get(CUSTOMERCARDID));
	                caanMsg.set(EKKA0120002CBSMsg1List.ISSURID, telgramTransMap.get(ISSURID));
	                caanMsg.set(EKKA0120002CBSMsg1List.ISSURNAME, telgramTransMap.get(ISSURNAME));
	                caanMsg.set(EKKA0120002CBSMsg1List.FINGERPRINT, telgramTransMap.get(FINGERPRINT));
	                caanMsg.set(EKKA0120002CBSMsg1List.MASKEDCARDNUMBER, telgramTransMap.get(MASKEDCARDNUMBER));
	                caanMsg.set(EKKA0120002CBSMsg1List.CARDVALIDTERM, telgramTransMap.get(CARDVALIDTERM));
	                caanMsg.set(EKKA0120002CBSMsg1List.CARDVALIDTERM, telgramTransMap.get(CARDVALIDTERM));
	                caanMsg.set(EKKA0120002CBSMsg1List.CARDHOLDERNAME, telgramTransMap.get(CARDHOLDERNAME));
	                caanMsg.set(EKKA0120002CBSMsg1List.ACQID, telgramTransMap.get(ACQID));
	                caanMsg.set(EKKA0120002CBSMsg1List.ACQNAME, telgramTransMap.get(ACQNAME));
	                caanMsg.set(EKKA0120002CBSMsg1List.CUSTOMERID, telgramTransMap.get(CUSTOMERID));
	                caanMsg.set(EKKA0120002CBSMsg1List.DEBITPREPAIDTYPE, telgramTransMap.get(DEBITPREPAIDTYPE));
	                caanMsg.set(EKKA0120002CBSMsg1List.ISSURCLASS, telgramTransMap.get(ISSURCLASS));
	                caanMsg.set(EKKA0120002CBSMsg1List.CARDBRAND, telgramTransMap.get(CARDBRAND));
                }
            }
            caanMsg1List.add(caanMsg);

            // Listから配列に変換して設定
            inCBSMsg.set(EKKA0120002CBSMsg.EKKA0120002CBSMSG1LIST, caanMsg1List.toArray(new CAANMsg[caanMsg1List.size()]));
	    }
        catch (IOException e)
	    {
	    	printErrorLog(e);
	    	throw e;
	    }
    
	}
	

	/**
	 * 共通APIのダミーレスポンスを設定します。
	 * <br>
	 * @throws IOException 
	 */
	private void editDummyOutMsg(CAANMsg inCBSMsg, AgentDispatchContext inContext) throws IOException
	{
        List<CAANMsg> caanMsg1List = new ArrayList<CAANMsg>();
		
	    CAANMsg caanMsg = new CAANMsg(EKKA0120002CBSMsg1List.class.getName());

    	String receiptNo = inCBSMsg.getString(EKKA0120002CBSMsg.RECEIPTNO);
    	boolean isOdd = false;
    	try {
			isOdd = (Long.parseLong(receiptNo) % 2 == 1);
		} catch (Exception e) {
		}
		String[] resultArray = getResultArray(inCBSMsg, inContext, receiptNo);
    	
    	// 結果コード
        String resultCode = resultArray[0];
		caanMsg.set(EKKA0120002CBSMsg1List.RESULTCODE, resultCode);
        
        // エラーメッセージ一覧
        if("30".equals(resultCode))
        {
            List<CAANMsg> caanMsg2List = new ArrayList<CAANMsg>();
        	CAANMsg ekka0120001CBSMsg2 = new CAANMsg(EKKA0120002CBSMsg2List.class.getName());
        	ekka0120001CBSMsg2.set(EKKA0120002CBSMsg2List.ERRORMESSAGE, "受付番号 が正しくありません。");
        	caanMsg2List.add(ekka0120001CBSMsg2);
        	CAANMsg ekka0120001CBSMsg2_2 = new CAANMsg(EKKA0120002CBSMsg2List.class.getName());
        	ekka0120001CBSMsg2_2.set(EKKA0120002CBSMsg2List.ERRORMESSAGE, "任意項目返却フラグ が正しくありません。");
        	caanMsg2List.add(ekka0120001CBSMsg2_2);
        	
            // Listから配列に変換して設定
            caanMsg.set(EKKA0120002CBSMsg1List.EKKA0120002CBSMSG2LIST, caanMsg2List.toArray(new CAANMsg[caanMsg2List.size()]));
        }
        
        if("0".equals(resultCode))
        {
            // 運用日付
			String opeDate = JKKModelCommon.getOpeDate(inCBSMsg);
// ANK-4428-00-00 DEL START
//			// 運用日付翌日
//			String nextDate = JKKModelCommon.addDay(inCBSMsg, inContext, opeDate, 1);
// ANK-4428-00-00 DEL END
			
			// 識別ID
            caanMsg.set(EKKA0120002CBSMsg1List.DISCERNMENTID, resultArray[5]);
// ANK-4428-00-00 ADD START
            if (!JKKStringUtil.isNullBlank(resultArray[6]))
            {
    			// 運用日付加減日
    			String randomDate = JKKModelCommon.addDay(inCBSMsg, inContext, opeDate, resultArray[6]);
            	// 識別ID有効期限 運用日付加減日00:00:00
                caanMsg.set(EKKA0120002CBSMsg1List.DISCERNMENTIDENDDATETIME, 
            		randomDate.substring(0, 4) + "/" + randomDate.substring(4, 6) + "/" + randomDate.substring(6, 8) + " " + getRandomTime(inCBSMsg, 1)
				);
            }
            else
            {
// ANK-4428-00-00 ADD END
// ANK-4428-00-00 MOD START
//            	// 識別ID有効期限 運用日翌日00:00:00
//              caanMsg.set(EKKA0120002CBSMsg1List.DISCERNMENTIDENDDATETIME, 
//            		nextDate.substring(0, 4) + "/" + nextDate.substring(4, 6) + "/" + nextDate.substring(6, 8) + " " + getRandomTime(inCBSMsg, 1)
//				);
            	// 識別ID有効期限 運用日00:00:00
                caanMsg.set(EKKA0120002CBSMsg1List.DISCERNMENTIDENDDATETIME, 
            		opeDate.substring(0, 4) + "/" + opeDate.substring(4, 6) + "/" + opeDate.substring(6, 8) + " " + getRandomTime(inCBSMsg, 1)
				);
            }
// ANK-4428-00-00 MOD END
            caanMsg.set(EKKA0120002CBSMsg1List.STATUSCODE, resultArray[1]);
// ANK-3846-13-00 ADD START
            //カード登録成功フラグが返却されないパターンがあるため、
            //カード登録成功フラグに「-1」が設定されていない場合のみカード登録設定フラグを返却する
            if(!"-1".equals(resultArray[2]))
            {
            	caanMsg.set(EKKA0120002CBSMsg1List.SAVESUCCESSFLG, resultArray[2]);
            }
// ANK-3846-13-00 ADD END

            String pspStatusCode = resultArray[3];
            if(!JKKStringUtil.isNullBlank(pspStatusCode))
            {
            	// PSP ステータスコード
                caanMsg.set(EKKA0120002CBSMsg1List.PSPSTATUSCODE, pspStatusCode);
                
                caanMsg.set(EKKA0120002CBSMsg1List.TRANSACTIONDATETIME, 
            		opeDate.substring(0, 4) + "/" + opeDate.substring(4, 6) + "/" + opeDate.substring(6, 8) + " " + getRandomTime(inCBSMsg, 3)
				);
                
                // IVR受付番号が奇数の場合はパターン1
                if(isOdd)
                {
	                caanMsg.set(EKKA0120002CBSMsg1List.FLOWLEVELID, "0000");
	                caanMsg.set(EKKA0120002CBSMsg1List.FLOWLEVELNAME, "XXXX");
	                caanMsg.set(EKKA0120002CBSMsg1List.CALLERTELNO, "09000000000");
	                caanMsg.set(EKKA0120002CBSMsg1List.INCOMINGDATETIME, 
	            		opeDate.substring(0, 4) + "/" + opeDate.substring(4, 6) + "/" + opeDate.substring(6, 8) + " " + getRandomTime(inCBSMsg, 2)
	    			);
	                
	                // 「PSP ステータスコード（pspStatusCode）」が「成功（0）」の場合のみ返却
	                if("0".equals(pspStatusCode))
	                {
		                String result = resultArray[4];
						caanMsg.set(EKKA0120002CBSMsg1List.RESULT, result);
						if("1".equals(result))
						{
			                caanMsg.set(EKKA0120002CBSMsg1List.RESPONSECODE, "XXXXX");
			                caanMsg.set(EKKA0120002CBSMsg1List.RESPONSEDETAIL, "XXXXXXXXXX");
						}
						else
						{
			                caanMsg.setNull(EKKA0120002CBSMsg1List.RESPONSECODE);
			                caanMsg.setNull(EKKA0120002CBSMsg1List.RESPONSEDETAIL);
						}
		                caanMsg.set(EKKA0120002CBSMsg1List.NUMOFCARDS, "1");
		                caanMsg.set(EKKA0120002CBSMsg1List.CUSTOMERCARDID, "012345678901234567");
		                caanMsg.set(EKKA0120002CBSMsg1List.ISSURID, "12345");
		                caanMsg.set(EKKA0120002CBSMsg1List.ISSURNAME, "XXXXXX");
		                caanMsg.set(EKKA0120002CBSMsg1List.FINGERPRINT, "XXXXXXXX");
		                caanMsg.set(EKKA0120002CBSMsg1List.MASKEDCARDNUMBER, "100000******0001");
		                caanMsg.set(EKKA0120002CBSMsg1List.CARDVALIDTERM, "1022");
		                caanMsg.set(EKKA0120002CBSMsg1List.CARDHOLDERNAME, "TARO YAMADA");
		                caanMsg.set(EKKA0120002CBSMsg1List.ACQID, "99663");
		                caanMsg.set(EKKA0120002CBSMsg1List.ACQNAME, "XXXXXX");
		                caanMsg.set(EKKA0120002CBSMsg1List.CUSTOMERID, "1234567890123456");
		                caanMsg.set(EKKA0120002CBSMsg1List.DEBITPREPAIDTYPE, "prepaid");
		                caanMsg.set(EKKA0120002CBSMsg1List.ISSURCLASS, "0");
		                caanMsg.set(EKKA0120002CBSMsg1List.CARDBRAND, "VISA");
	                }
                }
                // IVR受付番号が偶数の場合はパターン2
                else
                {
	                caanMsg.set(EKKA0120002CBSMsg1List.FLOWLEVELID, "9900");
	                caanMsg.set(EKKA0120002CBSMsg1List.FLOWLEVELNAME, "YYYY");
	                caanMsg.set(EKKA0120002CBSMsg1List.CALLERTELNO, "08012345678");
	                caanMsg.set(EKKA0120002CBSMsg1List.INCOMINGDATETIME, 
	            		opeDate.substring(0, 4) + "/" + opeDate.substring(4, 6) + "/" + opeDate.substring(6, 8) + " " + getRandomTime(inCBSMsg, 2)
	    			);
	                
	                // 「PSP ステータスコード（pspStatusCode）」が「成功（0）」の場合のみ返却
	                if("0".equals(pspStatusCode))
	                {
		                String result = resultArray[4];
						caanMsg.set(EKKA0120002CBSMsg1List.RESULT, result);
						if("1".equals(result))
						{
			                caanMsg.set(EKKA0120002CBSMsg1List.RESPONSECODE, "YYYYY");
			                caanMsg.set(EKKA0120002CBSMsg1List.RESPONSEDETAIL, "YYYYYYYYYY");
						}
						else
						{
			                caanMsg.setNull(EKKA0120002CBSMsg1List.RESPONSECODE);
			                caanMsg.setNull(EKKA0120002CBSMsg1List.RESPONSEDETAIL);
						}
		                caanMsg.set(EKKA0120002CBSMsg1List.NUMOFCARDS, "2");
		                caanMsg.set(EKKA0120002CBSMsg1List.CUSTOMERCARDID, "987654321098765432");
		                caanMsg.set(EKKA0120002CBSMsg1List.ISSURID, "67890");
		                caanMsg.set(EKKA0120002CBSMsg1List.ISSURNAME, "YYYYYY");
		                caanMsg.set(EKKA0120002CBSMsg1List.FINGERPRINT, "YYYYYYYY");
		                caanMsg.set(EKKA0120002CBSMsg1List.MASKEDCARDNUMBER, "000099******9900");
		                caanMsg.set(EKKA0120002CBSMsg1List.CARDVALIDTERM, "0423");
		                caanMsg.set(EKKA0120002CBSMsg1List.CARDHOLDERNAME, "HANAKO TANAKA");
		                caanMsg.set(EKKA0120002CBSMsg1List.ACQID, "99661");
		                caanMsg.set(EKKA0120002CBSMsg1List.ACQNAME, "YYYYYY");
		                caanMsg.set(EKKA0120002CBSMsg1List.CUSTOMERID, "7890123456789012");
		                caanMsg.set(EKKA0120002CBSMsg1List.DEBITPREPAIDTYPE, "debit");
		                caanMsg.set(EKKA0120002CBSMsg1List.ISSURCLASS, "1");
		                caanMsg.set(EKKA0120002CBSMsg1List.CARDBRAND, "JCB");
	                }
                }
            }

        }
        caanMsg1List.add(caanMsg);
        // Listから配列に変換して設定
        inCBSMsg.set(EKKA0120002CBSMsg.EKKA0120002CBSMSG1LIST, caanMsg1List.toArray(new CAANMsg[caanMsg1List.size()]));
    
	}


	private String getRandomTime(CAANMsg inCBSMsg, int i) {
		SimpleDateFormat form = new SimpleDateFormat("HH:mm:ss");
		// タイムスタンプ末尾6桁を時刻用乱数として利用
		String randomTimeSeed = JKKModelCommon.getOpeDateTimeStamp(inCBSMsg).substring(11,17);
		// HHMMSS扱いでmsecを算出
		long msec = 
			Integer.parseInt(randomTimeSeed.substring(0,2))*3600000 + 
			Integer.parseInt(randomTimeSeed.substring(2,4))*60000 + 
			Integer.parseInt(randomTimeSeed.substring(4,6))*1000;
		String randomtime = form.format(new Date(msec * i));
		return randomtime;
	}
	
	/**
	 * JSON形式の文字列を作成する。
	 * @param inCBSMsg CAANメッセージ
	 * @param inContext コンテキスト
	 * @return SMS JSON形式のリクエストパラメータを返却する。
	 * @throws IOException JOSN形式へ変換する際のI/O例外
	 */
	private String requestParamMake(CAANMsg inCBSMsg, AgentDispatchContext inContext, String apiKey, String apiPassword) throws IOException
	{
		// JOSN形式へ変換するためのMAP
		Map<String, Object> requestMap = new HashMap<String, Object>();
		// 変換後文字列
		String json = "";

		// APIキー
		requestMap.put(API_KEY, apiKey);
		// APIパスワード
		requestMap.put(API_PASSWORD, apiPassword);
		// 受付番号
		requestMap.put(RECEIPT_NO, inCBSMsg.getString(EKKA0120002CBSMsg.RECEIPTNO));
        // 任意項目返却フラグ
		requestMap.put(ANYITEMRETURNFLG, NOT_RETURNED);
        // 処理詳細返却フラグ
		requestMap.put(DETAILRETURNFLG, NOT_RETURNED);

		ObjectMapper mapper = new ObjectMapper();
		mapper.enable(SerializationFeature.INDENT_OUTPUT);
		try
		{
			// JOSN形式へ変換
			json = mapper.writeValueAsString(requestMap);

		} catch (IOException e)
		{
			printErrorLog(e);
			throw e;
		}
		
		return json;
	}


	/**
	 * APIに対して送信するリクエストパラメータを作成する。
	 * @param json 送信するJSON文字列
	 * @param readTimeout 読取タイムアウト
	 * @return JSONレスポンスから取得したパラメータ
	 * @throws Exception 
	 */
	private String callPost(String address, String json, int readTimeout) throws IOException
	{
		// レスポンス
		StringBuffer result = new StringBuffer();
		HttpURLConnection con = null;

		IOException ex = null;
// ANK-4408-01-00 ADD START
		int httpStatus = HttpURLConnection.HTTP_OK;
// ANK-4408-01-00 ADD END

		try
		{
			ex = null;
			URL url = new URL(address);
			con = (HttpURLConnection) url.openConnection();
			// HTTPリクエストコード
			con.setRequestMethod("POST");
			// HTTPヘッダの設定
			con.setRequestProperty(CONTENT_TYPE, CONTENT_TYPE_VALUE);

			//タイムアウト設定
			con.setReadTimeout(readTimeout);

			con.setDoOutput(true);
			OutputStreamWriter out = new OutputStreamWriter(con.getOutputStream(), ENCODING);
			out.write(json);

			out.flush();

			// 接続開始ログ
			JSYejbLog.println(JSYejbLog.EXECUTION, JKKejbKKA0120002SecProc.class.getClass(), "JKKejbKKA0120002SecProc#connect start");

			// 接続
			con.connect();

			// 接続終了ログ
			JSYejbLog.println(JSYejbLog.EXECUTION, JKKejbKKA0120002SecProc.class.getClass(), "JKKejbKKA0120002SecProc#connect end");

// ANK-4408-01-00 MOD START
//			int httpStatus = con.getResponseCode();
			httpStatus = con.getResponseCode();
// ANK-4408-01-00 MOD END
			// HTTPステータスをログ出力
			JSYejbLog.println(JSYejbLog.EXECUTION, JKKejbKKA0120001SecProc.class, "JKKejbKKA0120002SecProc#http_status=" + httpStatus);
			
			// 通信に成功したテキストを取得する
			final InputStream in = con.getInputStream();
			String encoding = con.getContentEncoding();
			if (null == encoding)
			{
				encoding = ENCODING;
			}

			final InputStreamReader inReader = new InputStreamReader(in, encoding);
			final BufferedReader bufReader = new BufferedReader(inReader);
			String line = null;

			while ((line = bufReader.readLine()) != null)
			{
				result.append(line);
			}
             
			bufReader.close();
			inReader.close();
			in.close();
			
			// レスポンスをログ出力
			JSYejbLog.println(JSYejbLog.EXECUTION, JKKejbKKA0120002SecProc.class.getClass() ,("JKKejbKKA0120002SecProc#response=" +
					result.toString()).replaceAll("\\s+", " "));
			
			// HTTPステータスを確認
// ANK-4408-01-00 MOD START
//			if( HttpURLConnection.HTTP_OK != httpStatus )
//			{
//				throw new IOException("HTTP Status Error:" + httpStatus);
//			}
			// 認証エラーの場合
			if( HttpURLConnection.HTTP_UNAUTHORIZED == httpStatus )
			{
				throw new IOException("HTTP Status Error:" + httpStatus);
			}
			
			// OK以外の場合
			if( HttpURLConnection.HTTP_OK != httpStatus )
			{
				// JOSN形式へ変換するためのMAP
				Map<String, Object> resultMap = new HashMap<String, Object>();
				
				// 結果コード
				resultMap.put(RESULTCODE, "");
				ObjectMapper mapper = new ObjectMapper();
				mapper.enable(SerializationFeature.INDENT_OUTPUT);
				
				// JOSN形式へ変換
				return mapper.writeValueAsString(resultMap);
			}
// ANK-4408-01-00 MOD END
		}
		catch (IOException e)
		{
			printErrorLog(e);
// ANK-4408-01-00 MOD START
//			ex = e;
			// 認証エラーの場合
			if( HttpURLConnection.HTTP_UNAUTHORIZED == httpStatus )
			{
				ex = e;
			}
			else
			{
				// JOSN形式へ変換するためのMAP
				Map<String, Object> resultMap = new HashMap<String, Object>();
				
				// 結果コード
				resultMap.put(RESULTCODE, "");
				ObjectMapper mapper = new ObjectMapper();
				mapper.enable(SerializationFeature.INDENT_OUTPUT);
				
				// JOSN形式へ変換
				return mapper.writeValueAsString(resultMap);
			}
// ANK-4408-01-00 MOD END
		}
		finally
		{
			if (con != null)
			{
				//切断処理
				con.disconnect();
				con = null;
			}
		}
	
		// 例外情報がある場合はthrowする
		if (ex != null)
		{
			throw ex;
		}
		
		return result.toString();
	}
	
	/**
	 * <p>
	 * スタブ動作用に 結果コード, ステータスコード, カード登録成功フラグ, PSP処理ステータス, 処理結果 IVR識別ID を取得する。
	 * </p>
	 * @param inCBSMsg 処理対象のメッセージキャリア
	 * @param inContext ディスパッチコンテキスト
	 * @param knkNo 金庫番号
	 * @throws IOException 
	 */
// ANK-4408-01-00 MOD START
//	private String[] getResultArray(CAANMsg inCBSMsg, AgentDispatchContext inContext, String ivrUkNo)
	private String[] getResultArray(CAANMsg inCBSMsg, AgentDispatchContext inContext, String ivrUkNo) throws IOException
// ANK-4408-01-00 MOD END
	{
		// コネクション
		Connection con1 = null;
		
		// プリペアステートメント
		PreparedStatement pstmt = null;
		
		// リザルトセット
		ResultSet rsltQuery = null;
		
		try
		{
			//コネクション取得
			con1 = JSYejbConnection.getConnection(KK3381ETMsg.getTableName());
			
			StringBuffer sql_Buff = new StringBuffer();
			
			sql_Buff.append("select IVR_SKBT_ID, ADD_TRN_ID ")
			.append("      from KK_T_IVR_PRG_KANRI KK3381 ")
			.append("      where ")
			.append("      KK3381.IVR_UK_NO = ?");
			
			//prepareStatementにSQL文をセット
			pstmt = con1.prepareStatement(sql_Buff.toString());
			
			//ログ出力(SQL文の出力)
			JSYejbLog.outlog(inContext, JSYejbLog.DBACCESS, this.getClass(), sql_Buff);
			
			// パラメータの設定
			CAANJDBCUtil.setParam(pstmt, 1, ivrUkNo);
			
			// ResultSetの取得
			rsltQuery = pstmt.executeQuery();
			
			// 登録処理ＩＤ を取得
			String addTrnId = "";
			String ivrSkbtId = "";
			if(rsltQuery.next())
			{
				ivrSkbtId = CAANJDBCUtil.getString(rsltQuery, 1);
				addTrnId = CAANJDBCUtil.getString(rsltQuery, 2);
			}
			
			// 結果配列 
			// resultCode, statusCode, saveSuccessFlg, pspStatusCode
// ANK-4428-00-00 MOD START
//			String[] resultArray = new String[]{"0","0","0", null, null, ""};
			String[] resultArray = new String[]{"0","0","0", null, null, "", null};
// ANK-4428-00-00 MOD END
			if(addTrnId!=null )
			{
				// 登録処理ＩＤをカンマ区切りで取得し頭５項目を処理結果とする
				String[] addTrnIdArray = addTrnId.split(",");
// ANK-4428-00-00 MOD START
//				if(addTrnIdArray != null && addTrnIdArray.length >= 5)
				if(addTrnIdArray != null && addTrnIdArray.length >= ADD_TRN_ID_KMKNUM)
// ANK-4428-00-00 MOD END
				{
					
					String resultCode = 		addTrnIdArray[0];
					String statusCode = 		addTrnIdArray[1];
					String saveSuccessFlg = 	addTrnIdArray[2];
					String pspStatusCode = 		addTrnIdArray[3];
					String result =				addTrnIdArray[4];
// ANK-4428-00-00 ADD START
					String kagenDays =			addTrnIdArray[6];
// ANK-4428-00-00 ADD END
					
					// pspStatusCodeは未設定がありうる 0,1以外は未設定扱いとする
					if(!"0".equals(pspStatusCode) && !"1".equals(pspStatusCode))
					{
						pspStatusCode = null;
					}
					// resultは未設定がありうる 0,1以外は未設定扱いとする
					if(!"0".equals(result) && !"1".equals(result))
					{
						result = null;
					}
// ANK-4428-00-00 ADD START
					// kagenDaysは未設定がありうる 数字以外は未設定扱いとする
					if(!HalfCharCheck.isNumber3Check(kagenDays))
					{
						kagenDays = null;
					}
// ANK-4428-00-00 ADD END
					
					
					resultArray[0] = resultCode;
					resultArray[1] = statusCode;
					resultArray[2] = saveSuccessFlg;
					resultArray[3] = pspStatusCode;
					resultArray[4] = result;
// ANK-4428-00-00 ADD START
					resultArray[6] = kagenDays;
// ANK-4428-00-00 ADD END
					
				}
// ANK-4408-01-00 MOD START
				// 登録処理ＩＤをカンマ区切りで取得し６項目をHTTP ステータスコードとする
// ANK-4428-00-00 MOD START
//				if(addTrnIdArray != null && addTrnIdArray.length >= 6)
				if(addTrnIdArray != null && addTrnIdArray.length >= ADD_TRN_ID_KMKNUM)
// ANK-4428-00-00 MOD END
				{
					if ("401".equals(addTrnIdArray[5]))
					{
						throw new IOException("HTTP Status Error:401");
					}
				}
// ANK-4408-01-00 MOD END
			}
			
			resultArray[5] = ivrSkbtId;
			
			return resultArray;
		}
		catch (SQLException e)
		{
			throw new CAANRuntimeException(e);
		}
		finally
		{
			// 資源の解放
			try
			{
				if (rsltQuery != null)
				{
					rsltQuery.close();
				}
				if (pstmt != null)
				{
					pstmt.close();
				}
				if (con1 != null)
				{
					CAANConnectionMgr.getInstance().close(con1);
				}
			}
			catch(SQLException e)
			{
				throw new CAANRuntimeException(e);
			}
		}
	}
	
	/**
	 * エラーログ出力
	 * @param e 発生した例外
	 */
	static private void printErrorLog(Exception e)
	{
		StringBuffer sb = new StringBuffer();
		sb.append(e.getMessage()+ "\n");
		sb.append(e.getClass().getName()+ "\n");
		StackTraceElement[] steAll = e.getStackTrace();
		for (StackTraceElement ste : steAll) {
			sb.append("	at " + ste.getClassName() + "." + ste.getMethodName() + "(" + ste.getFileName() + ":" + ste.getLineNumber()+")"+ "\n");
		}
		JSYejbLog.println(JSYejbLog.ERROR, JKKejbKKA0120002SecProc.class, sb.toString());
	}

}
