/*******************************************************************************
*	All Rights reserved,Copyright (c) K-Opticom
********************************************************************************
*＜プログラム内容＞
*	システム名		：eo顧客基幹システム
*	モジュール名	：JECHA0020001TPMA
*	ソースファイル名：JECHA0020001TPMA.java
*	作成者			：FJ）三原
*	日付			：2019年12月13日
*＜機能概要＞
*	請求情報連携（さくらKCS）独自処理部品です。
*＜修正履歴＞
*	バージョン	修正日		修正者		修正内容
*	v52.00.00	2020/11/24	FJ）三原	【ANK-3838-00-00】窓口払い手数料の顧客負担方式導入
*	v52.00.01	2021/01/09  FJ）星野   【ANK-3838-32-00】コンビニ会社コードの４分割化
*	v54.00.00	2021/09/01	FJ)西窪		【ANK-4102-00-00】窓口払い手数料の顧客負担方式導入 STEP3
*	v54.00.01	2021/09/01	FJ) 西窪	【IT2-2021-0000029】EANバーコード設定値修正
*	v57.00.00	2022/02/25  FJ）西窪	【ANK-4206-00-00】請求書再発行時の発行回数改善対応
********************************************************************************/
package eo.ejb.cbs.mainproc;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.json.JSONException;
import org.json.JSONObject;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fujitsu.futurity.common.JCCWebAddTrnId;
import com.fujitsu.futurity.common.JCMConstants;
import com.fujitsu.futurity.model.base.CAANMsg;
import com.fujitsu.futurity.model.common.JCMAPLConstMgr;
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 com.fujitsu.futurity.model.ejb.common.fw.TemplateMainHandler;

import eo.common.constant.JACStrConst;
import eo.common.util.JCHCommonFormatUtil;
import eo.common.util.JCHStringUtil;
import eo.ejb.cbs.cbsmsg.ECHA0020001CBSMsg;
import eo.ejb.cbs.cbsmsg.ECHA0020001CBSMsg1List;
import eo.ejb.common.JCCModelCommon;
import eo.ejb.common.JCHModelCommon;


/**
 * SMAPS即時決済SMS送信依頼独自処理部品です。
 * <br>
 * @author FJ
 *
 */
public class JECHA0020001TPMA implements TemplateMainHandler
{
	/** モード取得用キー */
	private static final String SAKURA_MODE_KEY = "CH_SAKURA_KCS_MODE";
	
	/** 実連携モード */
	private static final String MODE_REAL = "1";
	
	/** エラーフラグ(EA：設定値取得エラー) */
	private static final String EA_ERR_FLAG = "EA";
	
	/** エラーフラグ(EB：応答コードエラー) */
	private static final String EB_ERR_FLAG = "EB";
	
	/** エラーフラグ(EC：実行時エラー) */
	private static final String EC_ERR_FLAG = "EC";
	
	/** さくらKCS文字コード */
	private static final String SAKURA_KCS_ENCODING = "UTF-8";
	
	/** URL取得用キー */
	private static final String URL_KEY = "CH_SAKURA_KCS_URL";
	
	/** 接続タイムアウト取得用キー */
	private static final String CONNECT_TIMEOUT_KEY = "CH_SAKURA_KCS_CONNECT_TIMEOUT";
	
	/** 読取タイムアウト取得用キー */
	private static final String READ_TIMEOUT_KEY = "CH_SAKURA_KCS_READ_TIMEOUT";
	
	/** リトライ回数取得用キー */
	private static final String RETRYCOUNT_KEY = "CH_SAKURA_KCS_RETRYCOUNT";
	
	/** リトライインターバル取得用キー */
	private static final String RETRYINTERVAL_KEY = "CH_SAKURA_KCS_RETRYINTERVAL";
	
	/** スタブHTTPステータス取得用キー */
	private static final String STUB_HTTP_STATUS_KEY = "CH_SAKURA_KCS_STUB_HTTP_STATUS";
	
	/** スタブ応答コード取得用キー */
	private static final String STUB_CODE_KEY = "CH_SAKURA_KCS_STUB_CODE";
	
	/** スタブメッセージ取得用キー */
	private static final String STUB_MESSAGE_KEY = "CH_SAKURA_KCS_STUB_MESSAGE";
	
	/** 応答コードOK */
	private static final String CODE_OK = "00000";
	
	/** 【HTTPヘッダ】  */
	/** CONTENT_TYPE  */
	private static final String CONTENT_TYPE = "Content-Type";
	
	/** CONTENT_TYPE_設定値  */
	private static final String CONTENT_TYPE_VALUE = "application/json; charset=UTF-8";
	
	/** 【パラメータ一覧】  */
	/** ダミーURL */
	private static final String DUMMY_URL = "DUMMY";
	
	/** 請求先番号 */
	private static final String SK_SAKI_NO = "sk_saki_no";
	
	/** 請求年月 */
	private static final String SK_NENGETSU = "sk_nengetsu";
	
	/** 請求金額 */
	private static final String SK_KINGAKU = "sk_kingaku";
	
	/** 発行シーケンス */
	private static final String HK_SEQUENCE = "hk_sequence";
	
	/** ファイナンスコード */
	private static final String FINANCE_CD = "finance_cd";
	
	/** 収納企業コード */
	private static final String SYUNO_CO_CD = "syuno_co_cd";
	
	/** 請求番号 */
	private static final String KS_SK_NO = "ks_sk_no";
	
	/** コンビニ支払期限 */
	private static final String SHIHARAI_DATE = "shiharai_date";
	
	/** 【処理結果】 */
	/** 応答コード */
	private static final String RES_CD = "res_cd";
	
	/** メッセージ */
	private static final String RES_MSG = "res_msg";
	
	/** 【業パラ一覧】  */
	/** 業パラＩＤ_メーカーコード */
	private static final String [] WORK_PARAM_ID_MAKER_CD =
	{
		JACStrConst.WKPARA_CH_MAKER_NCU_SAKURA		// メーカーコード（通常・顧客負担）（さくらＫＣＳ）
		, JACStrConst.WKPARA_CH_MAKER_NCO_SAKURA	// メーカーコード（通常・企業負担）（さくらＫＣＳ）
		, JACStrConst.WKPARA_CH_MAKER_RCU_SAKURA	// メーカーコード（リアル・顧客負担）（さくらＫＣＳ）
		, JACStrConst.WKPARA_CH_MAKER_RCO_SAKURA	// メーカーコード（リアル・企業負担）（さくらＫＣＳ）
	};
	
	/** 業パラＩＤ_会社コード */
	private static final String [] WORK_PARAM_ID_KAISHA_CD =
	{
// ANK-3838-32-00対応 20210109 星野 MOD START
//		JACStrConst.WKPARA_CH_COMP_NOR_SAKURA		// 会社コード（通常）（さくらＫＣＳ）
//		, JACStrConst.WKPARA_CH_COMP_REA_SAKURA		// 会社コード（リアル）（さくらＫＣＳ）
		
		JACStrConst.WKPARA_CH_COMP_NCU_SAKURA		// 会社コード（通常・顧客負担）（さくらＫＣＳ）
		, JACStrConst.WKPARA_CH_COMP_NCO_SAKURA		// 会社コード（通常・企業負担）（さくらＫＣＳ）
		, JACStrConst.WKPARA_CH_COMP_RCU_SAKURA		// 会社コード（リアル・顧客負担）（さくらＫＣＳ）
		, JACStrConst.WKPARA_CH_COMP_RCO_SAKURA		// 会社コード（リアル・企業負担）（さくらＫＣＳ）
// ANK-3838-32-00対応 20210109 星野 MOD END
	};

	/**
	 * 請求情報連携（さくらKCS）を行います。
	 * 
	 * @param inCBSMsg 請求情報連携（さくらKCS）メッセージ
	 * @param inContext AgentDispatchContext
	 */
	public static void call_CHIFE083(CAANMsg inCBSMsg, AgentDispatchContext inContext)
	{
		// 開始ログ出力を実施。
		JSYejbLog.println(JSYejbLog.DEBUG, JECHA0020001TPMA.class, "JECHA0020001TPMA#invoke start");
		
		String[] response = new String[]{"", "", ""};
		
		/** 接続先などの判定に使用
		*   1： 本番・検証、2: 開発
		*/
		String mode = JCMAPLConstMgr.getString(SAKURA_MODE_KEY);
		// アプリケーションプロパティ設定チェック
		if(JCHStringUtil.isNullBlank(mode))
		{
			// ステータス設定（設定値取得エラー）
			inCBSMsg.set(ECHA0020001CBSMsg.STATUS, StatusCodes.RELATION_ERR);
			inCBSMsg.set(ECHA0020001CBSMsg.SEIKY_KEI_NO_ERR, EA_ERR_FLAG);
			editOutMsg(inCBSMsg, response);
			return;
		}
		
		// eo顧客 ⇒ さくらKCSへの送信先URLを設定
		String strUrl = "";
		
		if (MODE_REAL.equals(mode))
		{
			// 本番・検証：propertiesに設定された値を使用
			strUrl = JCMAPLConstMgr.getString(URL_KEY);
		}
		else
		{
			// スタブモード
			// スタブ用設定値取得
			if(!getStubParams(response))
			{
				// ステータス設定（設定値取得エラー）
				inCBSMsg.set(ECHA0020001CBSMsg.STATUS, StatusCodes.RELATION_ERR);
				inCBSMsg.set(ECHA0020001CBSMsg.SEIKY_KEI_NO_ERR, EA_ERR_FLAG);
				editOutMsg(inCBSMsg, response);
				return;
			}
			// 開発：設定しない
			strUrl = DUMMY_URL;
		}
		
		// 接続タイムアウト
		String strConnectTimeout = JCMAPLConstMgr.getString(CONNECT_TIMEOUT_KEY);
		// 読取タイムアウト
		String strReadTimeout = JCMAPLConstMgr.getString(READ_TIMEOUT_KEY);
		// リトライ回数
		String strRetryCount = JCMAPLConstMgr.getString(RETRYCOUNT_KEY);
		// リトライインターバル
		String strRetryInterval = JCMAPLConstMgr.getString(RETRYINTERVAL_KEY);
		
		// アプリケーションプロパティ設定チェック
		if(JCHStringUtil.isNullBlank(strUrl)
				|| JCHStringUtil.isNullBlank(strConnectTimeout)
				|| JCHStringUtil.isNullBlank(strReadTimeout)
				|| JCHStringUtil.isNullBlank(strRetryCount)
				|| JCHStringUtil.isNullBlank(strRetryInterval))
		{
			// ステータス設定（設定値取得エラー）
			inCBSMsg.set(ECHA0020001CBSMsg.STATUS, StatusCodes.RELATION_ERR);
			inCBSMsg.set(ECHA0020001CBSMsg.SEIKY_KEI_NO_ERR, EA_ERR_FLAG);
			editOutMsg(inCBSMsg, response);
			return;
		}
		JSYejbLog.println(JSYejbLog.EXECUTION, JECHA0020001TPMA.class , "JECHA0020001TPMA#URL=" + strUrl);
		
		// 接続タイムアウト
		int connectTimeout = Integer.parseInt(strConnectTimeout);
		// 読取タイムアウト
		int readTimeout = Integer.parseInt(strReadTimeout);
		// リトライ回数
		int retryCount = Integer.parseInt(strRetryCount);
		// リトライインターバル
		int retryInterval = Integer.parseInt(strRetryInterval);
		
		try
		{
			// JSON形式の文字列を作成する。
			String json = requestParamMake(inCBSMsg, inContext, mode);
			if (!JCHStringUtil.isNullBlank(json))
			{
				JSYejbLog.println(JSYejbLog.EXECUTION, JECHA0020001TPMA.class , "JECHA0020001TPMA#request=" + json);
			}
			
			if (MODE_REAL.equals(mode))
			{
				// さくらKCSに対してリクエストを送信する。
				response = callPost(strUrl, json, connectTimeout, readTimeout, retryCount, retryInterval);
			}
			else
			{
				// スタブを呼ぶ。
				response = callStub(response);
			}
			
			// 共通API連携実行結果判定
			if (response != null && response.length == 3)
			{
				// HTTPステータスをログ出力
				JSYejbLog.println(JSYejbLog.EXECUTION, JECHA0020001TPMA.class, "JECHA0020001TPMA#http_status=" + response[0]);
				// ANK-4102-00-00 DEL START
//				// 応答コード（001:正常）の場合
//				if (CODE_OK.equals(response[1]))
//				{
				// ANK-4102-00-00 DEL END
				// さくらKCS側で業務エラーとなった場合でもコミットを行うために、正常終了で返却する。
					// ステータス設定（0:正常終了）
					inCBSMsg.set(ECHA0020001CBSMsg.STATUS, StatusCodes.NORMAL_END);
					
				// ANK-4102-00-00 DEL START
//				}
//				// 応答コード（001:正常）以外の場合
//				else
//				{
//					inCBSMsg.set(ECHA0020001CBSMsg.STATUS, StatusCodes.NORMAL_END);
//				}
				// ANK-4102-00-00 DEL END
			}
		}
		catch (Exception e)
		{
			// ステータス設定（実行時エラー）
			inCBSMsg.set(ECHA0020001CBSMsg.STATUS, StatusCodes.RELATION_ERR);
			inCBSMsg.set(ECHA0020001CBSMsg.SEIKY_KEI_NO_ERR, EC_ERR_FLAG);
		}
		finally
		{
			// レスポンス電文を設定
			editOutMsg(inCBSMsg, response);
		}
		// 終了ログ出力を実施。
		JSYejbLog.println(JSYejbLog.DEBUG, JECHA0020001TPMA.class, "JECHA0020001TPMA#invoke end");
	}

	/**
	 * 共通APIのレスポンス電文を設定します。
	 * <br>
	 * @param inCBSMsg 個別割引適用可否照会・変更依頼メッセージ
	 * @param resServiceMap レスポンスサービスマップ
	 */
	private static void editOutMsg(CAANMsg inCBSMsg, String[] response)
	{
		List<CAANMsg> msg1List = new ArrayList<CAANMsg>();
		
		CAANMsg msg1 = new CAANMsg(ECHA0020001CBSMsg1List.class.getName());
		
		String httpStatus = "";
		String resCd = "";
		String resMsg = "";
		
		if (response != null)
		{
			if (response.length > 0)
			{
				httpStatus = nullToBlank(response[0]);
			}
			if (response.length > 1)
			{
				resCd = nullToBlank(response[1]);
			}
			if (response.length > 2)
			{
				resMsg = nullToBlank(response[2]);
			}
		}
		
		msg1.set(ECHA0020001CBSMsg1List.HTTP_STATUS, httpStatus);
		msg1.set(ECHA0020001CBSMsg1List.RES_CD, resCd);
		msg1.set(ECHA0020001CBSMsg1List.RES_MSG, resMsg);
		msg1List.add(msg1);
		
		// Listから配列に変換して設定
		inCBSMsg.set(ECHA0020001CBSMsg.ECHA0020001CBSMSG1LIST, msg1List.toArray(new CAANMsg[msg1List.size()]));
	}
	
	/**
	 * 請求情報連携（さくらKCS）APIに対して送信するリクエストパラメータを作成する。
	 * @param inCBSMsg CAANメッセージ
	 * @param inContext コンテキスト
	 * @param mode 処理区分
	 * @return SMAPS JSON形式のリクエストパラメータを返却する。
	 * @throws IOException JOSN形式へ変換する際のI/O例外
	 */
	private static String requestParamMake(CAANMsg inCBSMsg, AgentDispatchContext inContext, String mode) throws IOException
	{
		// 運用日
		String opeDate = JCCModelCommon.getOpeDate(inCBSMsg, null);
		
		// 請求先番号
		String skSakiNo = inCBSMsg.getString(ECHA0020001CBSMsg.SEIKY_KEI_NO);
		
		// 請求年月
		String skNengetsu = inCBSMsg.getString(ECHA0020001CBSMsg.SEIKY_YM);
		
		// 請求金額
		String skKingaku = inCBSMsg.getString(ECHA0020001CBSMsg.SEIKY_AMNT);
		
		// 請求発行シーケンス
		String hkSequence = inCBSMsg.getString(ECHA0020001CBSMsg.HAKKO_SEQ).substring(1, 2);
		
		// 手数料負担方式コード
		String commisionFtnHskCd = inCBSMsg.getString(ECHA0020001CBSMsg.COMMISION_FTN_HSK_CD);
		
		// バーコード区分
		String barcodeDiv = inCBSMsg.getString(ECHA0020001CBSMsg.BARCODE_DIV);
		
		// 業務パラメータ管理よりメーカーコードを取得する
		HashMap<String, String> makerCdMap = new HashMap<String, String>();
		
		for (String workParamIdMakerCd: WORK_PARAM_ID_MAKER_CD)
		{
			makerCdMap.put(workParamIdMakerCd, JCHModelCommon.getWorkParam(workParamIdMakerCd));
		}
		
		// 業務パラメータ管理より会社コードを取得する
		HashMap<String, String> kaishaCdMap = new HashMap<String, String>();
		
		for (String workParamIdKaishaCd: WORK_PARAM_ID_KAISHA_CD)
		{
			kaishaCdMap.put(workParamIdKaishaCd, JCHModelCommon.getWorkParam(workParamIdKaishaCd));
		}
		
		// メーカーコード(ファイナンスコード)を決定する
		String financeCd = "";
		String tmpFinanceCd = "";
		
		// バーコード区分が"0"(通常)の場合
		if (JACStrConst.BARCODE_DIV_NORMAL.equals(barcodeDiv))
		{
			// 手数料負担方式コードが"1"(顧客負担の場合)
			if (JACStrConst.FTN_HOSHIKI_KO.equals(commisionFtnHskCd))
			{
				tmpFinanceCd  = makerCdMap.get(JACStrConst.WKPARA_CH_MAKER_NCU_SAKURA);
			}
			// 手数料負担方式コードが"2"(企業負担の場合)
			else if (JACStrConst.FTN_HOSHIKI_KI.equals(commisionFtnHskCd))
			{
				tmpFinanceCd  = makerCdMap.get(JACStrConst.WKPARA_CH_MAKER_NCO_SAKURA);
			}
		}
		// バーコード区分が"1"(リアル)の場合
		else if (JACStrConst.BARCODE_DIV_REAL.equals(barcodeDiv))
		{
			// 手数料負担方式コードが"1"(顧客負担の場合)
			if (JACStrConst.FTN_HOSHIKI_KO.equals(commisionFtnHskCd))
			{
				tmpFinanceCd  = makerCdMap.get(JACStrConst.WKPARA_CH_MAKER_RCU_SAKURA);
			}
			// 手数料負担方式コードが"2"(企業負担の場合)
			else if (JACStrConst.FTN_HOSHIKI_KI.equals(commisionFtnHskCd))
			{
				tmpFinanceCd  = makerCdMap.get(JACStrConst.WKPARA_CH_MAKER_RCO_SAKURA);
			}
		}
		// 上1桁を除去する
		if (tmpFinanceCd != null && !"".equals(tmpFinanceCd))
		{
			financeCd = tmpFinanceCd.substring(1,6);
		}
		
		// 会社コード(収納機関コード)を決定する
		String syunoCoCd = "";
		// バーコード区分が"0"(通常)の場合
		if (JACStrConst.BARCODE_DIV_NORMAL.equals(barcodeDiv))
		{
// ANK-3838-32-00対応 20210109 星野 MOD START
//			syunoCoCd  = kaishaCdMap.get(JACStrConst.WKPARA_CH_COMP_NOR_SAKURA);
			
			// 手数料負担方式コードが"1"(顧客負担の場合)
			if (JACStrConst.FTN_HOSHIKI_KO.equals(commisionFtnHskCd))
			{
				syunoCoCd  = kaishaCdMap.get(JACStrConst.WKPARA_CH_COMP_NCU_SAKURA);
			}
			// 手数料負担方式コードが"2"(企業負担の場合)
			else if (JACStrConst.FTN_HOSHIKI_KI.equals(commisionFtnHskCd))
			{
				syunoCoCd  = kaishaCdMap.get(JACStrConst.WKPARA_CH_COMP_NCO_SAKURA);
			}
// ANK-3838-32-00対応 20210109 星野 MOD END
		}
		// バーコード区分が"1"(リアル)の場合
		else if (JACStrConst.BARCODE_DIV_REAL.equals(barcodeDiv))
		{
// ANK-3838-32-00対応 20210109 星野 MOD START
//			syunoCoCd  = kaishaCdMap.get(JACStrConst.WKPARA_CH_COMP_REA_SAKURA);
			
			// 手数料負担方式コードが"1"(顧客負担の場合)
			if (JACStrConst.FTN_HOSHIKI_KO.equals(commisionFtnHskCd))
			{
				syunoCoCd  = kaishaCdMap.get(JACStrConst.WKPARA_CH_COMP_RCU_SAKURA);
			}
			// 手数料負担方式コードが"2"(企業負担の場合)
			else if (JACStrConst.FTN_HOSHIKI_KI.equals(commisionFtnHskCd))
			{
				syunoCoCd  = kaishaCdMap.get(JACStrConst.WKPARA_CH_COMP_RCO_SAKURA);
			}
// ANK-3838-32-00対応 20210109 星野 MOD END
		}
		
		// 会社コード(収納機関コード)
		
		// 群
		// ANK-4206-00-00 MOD START
//		String gunCd = JACStrConst.GUN_NO;
		String gunCd = inCBSMsg.getString(ECHA0020001CBSMsg.GUN_NO);
		// ANK-4206-00-00 MOD END
		
		// IT2-2021-0000029 MOD START
//		// ANK-4102-00-00 MOD START
		// 請求番号(1〜2桁:請求月、3〜4桁:請求年(下2桁)、5桁:群、6桁:請求発行シーケンス(下1桁)、7〜16桁:請求契約番号、17桁:請求発行シーケンス(下1桁))
		String ksSkNo = skNengetsu.substring(4, 6) + skNengetsu.substring(2, 4) + gunCd + hkSequence + skSakiNo + hkSequence;
//		// 請求番号(1〜2桁:運用日の月、3〜4桁:運用日の年(下2桁)、5桁:群、6桁:請求発行シーケンス(下1桁)、7〜16桁:請求契約番号、17桁:請求発行シーケンス(下1桁))
//		String ksSkNo = opeDate.substring(4, 6) + opeDate.substring(6, 8) + gunCd + hkSequence + skSakiNo + hkSequence;
//		// ANK-4102-00-00 MOD END
		// IT2-2021-0000029 MOD END
		
		// コンビニ支払期限
		String shiharaiDate = inCBSMsg.getString(ECHA0020001CBSMsg.PAY_KIGEN_YMD);
		
		// JOSN形式へ変換するためのMAP
		Map<String, Object> requestMap = new HashMap<String, Object>();
		
		// 変換後文字列
		String json = "";
		
		// 請求先番号
		requestMap.put(SK_SAKI_NO, skSakiNo);
		
		// 請求年月
		requestMap.put(SK_NENGETSU, skNengetsu);
		
		// 請求金額
		requestMap.put(SK_KINGAKU, skKingaku);
		
		// 発行シーケンス
		requestMap.put(HK_SEQUENCE, hkSequence);
		
		// ファイナンスコード
		requestMap.put(FINANCE_CD, financeCd);
		
		// 収納企業コード
		requestMap.put(SYUNO_CO_CD, syunoCoCd);
		
		// 請求番号
		requestMap.put(KS_SK_NO, ksSkNo);
		
		// コンビニ支払期限
		requestMap.put(SHIHARAI_DATE, shiharaiDate);
		
		ObjectMapper mapper = new ObjectMapper();
		mapper.enable(SerializationFeature.INDENT_OUTPUT);
		
		// JOSN形式へ変換
		json = mapper.writeValueAsString(requestMap);
		
		return json;
	}

	/**
	 * レスポンス設定値を取得する
	 * @param response レスポンス設定値
	 * @return 取得結果
	 */
	private static boolean getStubParams(String[] response)
	{
		// HTTPステータス
		response[0] = JCMAPLConstMgr.getString(STUB_HTTP_STATUS_KEY);
		// 応答コード
		response[1] = JCMAPLConstMgr.getString(STUB_CODE_KEY);
		// メッセージ(例：\正\常\終\了)
		response[2] = convUnicode(JCMAPLConstMgr.getString(STUB_MESSAGE_KEY));
		// アプリケーションプロパティ設定チェック
		if(JCHStringUtil.isNullBlank(response[0]))
		{
			return false;
		}
		
		return true;
	}

	/**
	 * 請求情報連携（さくらKCS）APIに対して送信するリクエストパラメータを作成する。
	 * @param strPostUrl 送信先URL
	 * @param json 送信するJSON文字列
	 * @param connectTimeout 接続タイムアウト
	 * @param readTimeout 読取タイムアウト
	 * @param retryCount リトライ回数
	 * @param retryInterval リトライインターバル
	 * @return JSONレスポンスから取得したパラメータ
	 * @throws Exception 
	 */
	private static String[] callPost(String strPostUrl, String json, int connectTimeout, int readTimeout, int retryCount,
			int retryInterval)
	throws IOException
	{
		// レスポンス
		StringBuffer result = new StringBuffer();
		// 結果コード
		String resCd = null;
		// 結果メッセージ
		String resMsg = null;
		
		HttpURLConnection con = null;
		
		int httpStatus = 500;
		int reqCnt = retryCount + 1;
		IOException ex = null;
		
		for (int i = 0; i < reqCnt; i++)
		{
			try
			{
				ex = null;
				URL url = new URL(strPostUrl);
				con = (HttpURLConnection) url.openConnection();
				// HTTPリクエストコード
				con.setRequestMethod("POST");
				// HTTPヘッダの設定
				con.setRequestProperty(CONTENT_TYPE, CONTENT_TYPE_VALUE);
				
				//タイムアウト設定
				con.setConnectTimeout(connectTimeout);
				con.setReadTimeout(readTimeout);
				
				con.setDoOutput(true);
				OutputStreamWriter out = new OutputStreamWriter(con.getOutputStream(), SAKURA_KCS_ENCODING);
				out.write(json);
				
				out.flush();
				
				// 接続開始ログ
				JSYejbLog.println(JSYejbLog.DEBUG, JECHA0020001TPMA.class, "JECHA0020001TPMA#connect start");
				
				// 接続
				con.connect();
				
				httpStatus = con.getResponseCode();
				
				// 接続終了ログ
				JSYejbLog.println(JSYejbLog.DEBUG, JECHA0020001TPMA.class, "JECHA0020001TPMA#connect end");
				
				// 通信に成功したテキストを取得する
				final InputStream in = con.getInputStream();
				String encoding = con.getContentEncoding();
				if (null == encoding)
				{
					encoding = SAKURA_KCS_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();
				ObjectMapper mapper = new ObjectMapper();
				JsonNode root = mapper.readTree(result.toString());
				// 【処理結果】を取得
				if (root.get(RES_CD) != null)
				{
					resCd = root.get(RES_CD).textValue();
				}
				if (root.get(RES_MSG) != null)
				{
					resMsg = root.get(RES_MSG).textValue();
				}
				// レスポンスをログ出力
				JSYejbLog.println(JSYejbLog.EXECUTION, JECHA0020001TPMA.class ,("JECHA0020001TPMA#response=" +
						result.toString()).replaceAll("\\s+", " "));
			}
			catch (IOException e)
			{
				e.printStackTrace();
				ex = e;
			}
			finally
			{
				if (con != null)
				{
					//切断処理
					con.disconnect();
					con = null;
				}
			}
			// 失敗時はリトライ回数の上限までリトライ
			if (((ex != null) || (httpStatus != HttpURLConnection.HTTP_OK)) && (i < retryCount))
			{
				try
				{
					Thread.sleep(retryInterval);
				}
				catch (InterruptedException e)
				{
					// 割り込み要求による例外は無視
				}
				continue;
			}
			else
			{
				break;
			}
		}
		
		// 例外情報がある場合はthrowする
		if (ex != null)
		{
			throw ex;
		}
		
		return new String[] {String.valueOf(httpStatus), resCd, resMsg};
	}

	/**
	 * スタブをコールする
	 * @param response レスポンス設定値
	 * @return レスポンス設定値
	 * @throws JsonProcessingException JSONへの変換時例外
	 */
	private static String[] callStub(String[] response) throws JsonProcessingException
	{
		if (!JCHStringUtil.isNullBlank(response[1]))
		{
			Map<String, Object> responseMap = new HashMap<String, Object>();
			responseMap.put(RES_CD, response[1]);
			responseMap.put(RES_MSG, response[2]);
			ObjectMapper mapper = new ObjectMapper();
			mapper.enable(SerializationFeature.INDENT_OUTPUT);
			
			// JOSN形式へ変換
			String json;
			try {
				json = mapper.writeValueAsString(responseMap);
			} catch (JsonProcessingException e) {
				e.printStackTrace();
				throw e;
			}
			// レスポンスをログ出力
			JSYejbLog.println(JSYejbLog.EXECUTION, JECHA0020001TPMA.class, ("JECHA0020001TPMA#response=" + json).replaceAll("\\s+", " "));
		}
		
		return response;
	}

	/**
	 * nullを空文字に置き換え
	 * 
	 * @param str 置き換え対象文字列
	 * @return
	 */
	private static String nullToBlank(String str)
	{
		if (str == null)
		{
			return "";
		}
		return str;
	}

	/**
	 * 取得したUnicodeの文字列をUTF8の文字列に変換します
	 * 
	 * @param unicode 変換対象文字列(Unicode)
	 * @return encodedText 変換後の文字列
	 */
	private static String convUnicode(String unicode)
	{
		
		String[] codeStrs = unicode.split("\\\\u");
		
		int[] codePoints = new int[codeStrs.length - 1];
		
		for (int i = 0; i < codePoints.length; i++)
		{
			codePoints[i] = Integer.parseInt(codeStrs[i + 1], 16);
		}
		
		String encodedText = new String(codePoints, 0, codePoints.length);
		
		return encodedText;
	}
}
