/*******************************************************************************
*	All Rights reserved,Copyright (c) K-Opticom
********************************************************************************
*＜プログラム内容＞
*	システム名		：eo顧客基幹システム
*	モジュール名	：JECHA0010001TPMA
*	ソースファイル名：JECHA0010001TPMA.java
*	作成者			：FJ）麻生
*	日付			：2019年12月13日
*＜機能概要＞
*	SMAPS即時決済SMS送信依頼独自処理部品です。
*＜修正履歴＞
*	バージョン	修正日		修正者		修正内容
*	v47.00.00	2019/12/13	FJ）麻生	【ANK-3716-00-00】SMAPS即時決済送信処理システム化
*	v47.00.01	2019/12/13	FJ）麻生	【IT2-2019-0000041】注文日時の桁数不正
*
********************************************************************************/
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 java.util.regex.Matcher;
import java.util.regex.Pattern;

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.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.util.JCCToolTextDateFormat;
import eo.common.util.JCHStringUtil;
import eo.ejb.cbs.cbsmsg.ECHA0010001CBSMsg;
import eo.ejb.cbs.cbsmsg.ECHA0010001CBSMsg1List;
import eo.ejb.common.JPCModelCommon;


/**
 * SMAPS即時決済SMS送信依頼独自処理部品です。
 * <br>
 * @author FJ
 *
 */
public class JECHA0010001TPMA implements TemplateMainHandler
{	
	/** モード取得用キー */
	private static final String SMAPS_MODE_KEY = "CH_SMAPS_MODE";

	/** 実連携モード */
	private static final String MODE_REAL = "1";

	/** エラーフラグ(E1：必須チェックエラー) */
	private static final String E1_ERR_FLAG = "E1";

	/** エラーフラグ(E2：ドメインチェックエラー) */
	private static final String E2_ERR_FLAG = "E2";

	/** エラーフラグ(E3：桁数チェックエラー) */
	private static final String E3_ERR_FLAG = "E3";

	/** エラーフラグ(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";

	/** SMAPS文字コード */
	private static final String SMAPS_ENCODING = "UTF-8";

	/** URL取得用キー */
	private static final String URL_KEY = "CH_SMAPS_URL";

	/** SMSAUTHCODE取得用キー */
	private static final String SMSAUTHCODE_KEY = "CH_SMAPS_SMSAUTHCODE";

	/** SHORTNAME取得用キー */
	private static final String SHORTNAME_KEY = "CH_SMAPS_SHORTNAME";

	/** SMSメッセージ内容取得用キー */
	private static final String SMSMESSAGE_KEY = "CH_SMAPS_SMSMESSAGE";

	/** ラベル名取得用キー */
	private static final String LABEL_KEY = "CH_SMAPS_LABEL";

	/** 商品確認画面に表示するメッセージ取得用キー */
	private static final String CONFIRMMESSAGE_KEY = "CH_SMAPS_CONFIRMMESSAGE";

	/** 備考取得用キー */
	private static final String NOTE_KEY = "CH_SMAPS_NOTE";

	/** 決済OK後遷移URL取得用キー */
	private static final String PAYMENTOKURL_KEY = "CH_SMAPS_PAYMENTOKURL";

	/** 決済NG後遷移URL取得用キー */
	private static final String PAYMENTNGURL_KEY = "CH_SMAPS_PAYMENTNGURL";

	/** 接続タイムアウト取得用キー */
	private static final String CONNECT_TIMEOUT_KEY = "CH_SMAPS_CONNECT_TIMEOUT";

	/** 読取タイムアウト取得用キー */
	private static final String READ_TIMEOUT_KEY = "CH_SMAPS_READ_TIMEOUT";

	/** リトライ回数取得用キー */
	private static final String RETRYCOUNT_KEY = "CH_SMAPS_RETRYCOUNT";

	/** リトライインターバル取得用キー */
	private static final String RETRYINTERVAL_KEY = "CH_SMAPS_RETRYINTERVAL";

	/** スタブHTTPステータス取得用キー */
	private static final String STUB_HTTP_STATUS_KEY = "CH_SMAPS_STUB_HTTP_STATUS";

	/** スタブ応答コード取得用キー */
	private static final String STUB_CODE_KEY = "CH_SMAPS_STUB_CODE";

	/** スタブメッセージ取得用キー */
	private static final String STUB_MESSAGE_KEY = "CH_SMAPS_STUB_MESSAGE";

	/** フリー項目２取得元取得用キー */
	private static final String FREEFIELD2_ENV_KEY = "CH_SMAPS_FREEFIELD2_ENV";

	/** フリー項目２取得用キー */
	private static final String FREEFIELD2_KEY = "CH_SMAPS_FREEFIELD2";

	/** フリー項目２取得元(プロパティファイル) */
	private static final String FREEFIELD2_ENV_APLCONST = "1";

	/** 応答コードOK */
	private static final String CODE_OK = "001";

	/** 【HTTPヘッダ】  */
	/** 認証コード  */
	private static final String SMS_AUTH_CODE = "sms-auth-code";

	/** 【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 LOGINURLSHORTNAME = "loginUrlShortName";

	/** 【SMS送信情報】  */
	/** 電話番号 */
	private static final String MOBILETEL = "mobiletel";

	/** SMSメッセージ */
	private static final String SMSMESSAGE = "smsMessage";

	/** フリー項目２ */
	private static final String FREEFIELD2 = "freeField2";

	/** 【期限設定】 */
	/** トークン有効期限 */
	private static final String TOKENLIMIT = "tokenLimit";

	/** 認証パラメータリスト */
	private static final String AUTHINFOLIST = "authInfoList";

	/** ラベル名 */
	private static final String LABEL = "label";

	/** 値 */
	private static final String AUTHVALUE = "authValue";

	/** 入力モード */
	private static final String INPUTMODE = "inputMode";
	
	/** 【決済ポータル画面表示情報】 */
	/** 商品パラメータ */
	private static final String ITEMPARAM = "itemParam";

	/** 決済方法 */
	private static final String SETTLETYPE = "settleType";

	/** 商品確認メッセージ */
	private static final String CONFIRMMESSAGE = "confirmMessage";

	/** No. */
	private static final String ORDERNO = "orderNo";

	/** 注文日時 */
	private static final String ORDERDATE = "orderDate";

	/** 商品区分 */
	private static final String ITEMTYPE = "itemType";

	/** 課金方法 */
	private static final String PAYMENTTYPE = "paymentType";

	/** 合計金額 */
	private static final String PAYMENTPRICE = "paymentPrice";

	/** 備考 */
	private static final String NOTE = "note";

	/** ダミーURL */
	private static final String DUMMY_URL = "DUMMY";

	/** ダミーSMSAUTHCODE */
	private static final String DUMMY_SMS_AUTH_CODE = "1234567890";

	/** ダミーSHORT_NAME */
	private static final String DUMMY_LOGIN_URL_SHORT_NAME = "dummy";

	/** 【決済終了情報】 */
	/** 決済OK後遷移URL */
	private static final String PAYMENTOKURL = "paymentOkUrl";

	/** 決済NG後遷移URL */
	private static final String PAYMENTNGURL = "paymentNgUrl";

	/** 【処理結果】 */
	/** 応答コード */
	private static final String CODE = "code";

	/** メッセージ */
	private static final String MESSAGE = "message";

	/**
	 * 個別割引適用可否照会・変更依頼を行います。
	 * 
	 * @param inCBSMsg 個別割引適用可否照会・変更依頼メッセージ
	 * @param inContext AgentDispatchContext
	 */
	public static void call_CHIFE068(CAANMsg inCBSMsg, AgentDispatchContext inContext)
	{

		// 開始ログ出力を実施。
		JSYejbLog.println(JSYejbLog.DEBUG, JECHA0010001TPMA.class, "JECHA0010001TPMA#invoke start");
		
		String[] response = new String[]{"", "", ""};
		
		// 請求書発行シーケンスは請求の登録後に設定されるため単項目チェックを実施
		// 必須チェック
		if (JCHStringUtil.isNullBlank(inCBSMsg.getString(ECHA0010001CBSMsg.SKS_HAKKO_SEQ)))
		{
			inCBSMsg.set(ECHA0010001CBSMsg.STATUS, StatusCodes.SINGLEDATA_ERR);
			inCBSMsg.set(ECHA0010001CBSMsg.SKS_HAKKO_SEQ_ERR, E1_ERR_FLAG);
			editOutMsg(inCBSMsg, response);
			return;
		}
		// ドメインチェック
		Matcher mtc = Pattern.compile("[0-9a-zA-Z]+").matcher(inCBSMsg.getString(ECHA0010001CBSMsg.SKS_HAKKO_SEQ));
		if (!mtc.matches())
		{
			inCBSMsg.set(ECHA0010001CBSMsg.STATUS, StatusCodes.SINGLEDATA_ERR);
			inCBSMsg.set(ECHA0010001CBSMsg.SKS_HAKKO_SEQ_ERR, E2_ERR_FLAG);
			editOutMsg(inCBSMsg, response);
			return;
		}
		// 桁数チェック
		if (inCBSMsg.getString(ECHA0010001CBSMsg.SKS_HAKKO_SEQ).length() != 2)
		{
			inCBSMsg.set(ECHA0010001CBSMsg.STATUS, StatusCodes.SINGLEDATA_ERR);
			inCBSMsg.set(ECHA0010001CBSMsg.SKS_HAKKO_SEQ_ERR, E3_ERR_FLAG);
			editOutMsg(inCBSMsg, response);
			return;
		}
		
		/** 接続先などの判定に使用
		*   1： 本番・検証、2: 開発
		*/
		String mode = JCMAPLConstMgr.getString(SMAPS_MODE_KEY);
		// アプリケーションプロパティ設定チェック
		if(JCHStringUtil.isNullBlank(mode))
		{
			// ステータス設定（設定値取得エラー）
			inCBSMsg.set(ECHA0010001CBSMsg.STATUS, StatusCodes.RELATION_ERR);
			inCBSMsg.set(ECHA0010001CBSMsg.SEIKY_KEI_NO_ERR, EA_ERR_FLAG);
			editOutMsg(inCBSMsg, response);
			return;
		}
		
		// eo顧客 ⇒ そとれんへの送信先URLを設定
		String strUrl = "";
		// 認証コード
		String smsAuthCode = "";
		// 略称（URL用）
		String loginUrlShortName = "";
		
		if (MODE_REAL.equals(mode))
		{
			// 本番・検証：propertiesに設定された値を使用
			strUrl = JCMAPLConstMgr.getString(URL_KEY);
			smsAuthCode = JCMAPLConstMgr.getString(SMSAUTHCODE_KEY);
			loginUrlShortName = JCMAPLConstMgr.getString(SHORTNAME_KEY);
		}
		else
		{
			// スタブモード
			// スタブ用設定値取得
			if(!getStubParams(response))
			{
				// ステータス設定（設定値取得エラー）
				inCBSMsg.set(ECHA0010001CBSMsg.STATUS, StatusCodes.RELATION_ERR);
				inCBSMsg.set(ECHA0010001CBSMsg.SEIKY_KEI_NO_ERR, EA_ERR_FLAG);
				editOutMsg(inCBSMsg, response);
				return;
			}
			// 開発：設定しない
			strUrl = DUMMY_URL;
			smsAuthCode = DUMMY_SMS_AUTH_CODE;
			loginUrlShortName = DUMMY_LOGIN_URL_SHORT_NAME;
		}
		
		// SMSメッセージ内容
		String smsMessage = JCMAPLConstMgr.getString(SMSMESSAGE_KEY);
		// ラベル名
		String label = JCMAPLConstMgr.getString(LABEL_KEY);
		// 商品確認画面に表示するメッセージ
		String confirmMessage = JCMAPLConstMgr.getString(CONFIRMMESSAGE_KEY);
		// 備考
		String note = JCMAPLConstMgr.getString(NOTE_KEY);
		// 決済OK後遷移URL
		String paymentOkUrl = JCMAPLConstMgr.getString(PAYMENTOKURL_KEY);
		// 決済NG後遷移URL
		String paymentNgUrl = JCMAPLConstMgr.getString(PAYMENTNGURL_KEY);
		// 接続タイムアウト
		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);
		// フリー項目２取得元
		String freefield2Env = JCMAPLConstMgr.getString(FREEFIELD2_ENV_KEY);
		// フリー項目２
		String freefield2 = JCMAPLConstMgr.getString(FREEFIELD2_KEY);
		// アプリケーションプロパティ設定チェック
		if(JCHStringUtil.isNullBlank(strUrl)
				|| JCHStringUtil.isNullBlank(smsAuthCode)
				|| JCHStringUtil.isNullBlank(loginUrlShortName)
				|| JCHStringUtil.isNullBlank(smsMessage)
				|| JCHStringUtil.isNullBlank(label)
				|| JCHStringUtil.isNullBlank(confirmMessage)
				|| JCHStringUtil.isNullBlank(note)
				|| JCHStringUtil.isNullBlank(paymentOkUrl)
				|| JCHStringUtil.isNullBlank(paymentNgUrl)
				|| JCHStringUtil.isNullBlank(strConnectTimeout)
				|| JCHStringUtil.isNullBlank(strReadTimeout)
				|| JCHStringUtil.isNullBlank(strRetryCount)
				|| JCHStringUtil.isNullBlank(strRetryInterval)
				|| JCHStringUtil.isNullBlank(freefield2Env))
		{
			// ステータス設定（設定値取得エラー）
			inCBSMsg.set(ECHA0010001CBSMsg.STATUS, StatusCodes.RELATION_ERR);
			inCBSMsg.set(ECHA0010001CBSMsg.SEIKY_KEI_NO_ERR, EA_ERR_FLAG);
			editOutMsg(inCBSMsg, response);
			return;
		}
		JSYejbLog.println(JSYejbLog.EXECUTION, JECHA0010001TPMA.class , "JECHA0010001TPMA#sms-auth-code=" + smsAuthCode);
		JSYejbLog.println(JSYejbLog.EXECUTION, JECHA0010001TPMA.class , "JECHA0010001TPMA#Content-Type=" + CONTENT_TYPE_VALUE);
		JSYejbLog.println(JSYejbLog.EXECUTION, JECHA0010001TPMA.class , "JECHA0010001TPMA#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, loginUrlShortName, smsMessage, label, confirmMessage, note, paymentOkUrl,
					paymentNgUrl, freefield2Env, freefield2);
			if (!JCHStringUtil.isNullBlank(json))
			{
				String logStr = json.replaceAll("\\s+", " ");
				logStr = maskJson(logStr, MOBILETEL, 13);
				logStr = maskJson(logStr, AUTHVALUE, 8);
				JSYejbLog.println(JSYejbLog.EXECUTION, JECHA0010001TPMA.class , "JECHA0010001TPMA#request=" + logStr);
			}

			if (MODE_REAL.equals(mode))
			{
				// SMAPSのSMS送信APIに対してリクエストを送信する。
				response = callPost(strUrl, smsAuthCode, json, connectTimeout, readTimeout, retryCount, retryInterval);
			}
			else
			{
				// スタブを呼ぶ。
				response = callStub(response);
			}
			
			// 共通API連携実行結果判定
			if (response != null && response.length == 3)
			{
				// HTTPステータスをログ出力
				JSYejbLog.println(JSYejbLog.EXECUTION, JECHA0010001TPMA.class, "JECHA0010001TPMA#http_status=" + response[0]);
				// 応答コード（001:正常）の場合
				if (CODE_OK.equals(response[1]))
				{
					// ステータス設定（0:正常終了）
					inCBSMsg.set(ECHA0010001CBSMsg.STATUS, StatusCodes.NORMAL_END);
				}
				// 応答コード（001:正常）以外の場合
				else
				{
					// ステータス設定（応答コードエラー）
					inCBSMsg.set(ECHA0010001CBSMsg.STATUS, StatusCodes.RELATION_ERR);
					inCBSMsg.set(ECHA0010001CBSMsg.SEIKY_KEI_NO_ERR, EB_ERR_FLAG);
				}
			}
		}
		catch (Exception e)
		{
			// ステータス設定（実行時エラー）
			inCBSMsg.set(ECHA0010001CBSMsg.STATUS, StatusCodes.RELATION_ERR);
			inCBSMsg.set(ECHA0010001CBSMsg.SEIKY_KEI_NO_ERR, EC_ERR_FLAG);
		}
		finally
		{
			// レスポンス電文を設定
			editOutMsg(inCBSMsg, response);
		}
		// 終了ログ出力を実施。
		JSYejbLog.println(JSYejbLog.DEBUG, JECHA0010001TPMA.class, "JECHA0010001TPMA#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(ECHA0010001CBSMsg1List.class.getName());
		
		String httpStatus = "";
		String code = "";
		String message = "";
		
		if (response != null)
		{
			if (response.length > 0)
			{
				httpStatus = nullToBlank(response[0]);
			}
			if (response.length > 1)
			{
				code = nullToBlank(response[1]);
			}
			if (response.length > 2)
			{
				message = nullToBlank(response[2]);
			}
		}
		
		msg1.set(ECHA0010001CBSMsg1List.HTTP_STATUS, httpStatus);
		msg1.set(ECHA0010001CBSMsg1List.CODE, code);
		msg1.set(ECHA0010001CBSMsg1List.MESSAGE, message);
		msg1List.add(msg1);
		
		// Listから配列に変換して設定
		inCBSMsg.set(ECHA0010001CBSMsg.ECHA0010001CBSMSG1LIST, msg1List.toArray(new CAANMsg[msg1List.size()]));
	}
	
	/**
	 * SMAPS APIに対して送信するリクエストパラメータを作成する。
	 * @param inCBSMsg CAANメッセージ
	 * @param inContext コンテキスト
	 * @param mode 処理区分
	 * @param loginUrlShortName 略称（URL用）
	 * @param smsMessage SMSメッセージ
	 * @param label ラベル名
	 * @param confirmMessage 商品確認メッセージ
	 * @param note 備考
	 * @param paymentOkUrl 決済OK後遷移URL
	 * @param paymentNgUrl 決済NG後遷移URL
	 * @param freefield2Env フリー項目２取得元
	 * @param freefield2 フリー項目２
	 * @return SMAPS JSON形式のリクエストパラメータを返却する。
	 * @throws IOException JOSN形式へ変換する際のI/O例外
	 */
	private static String requestParamMake(CAANMsg inCBSMsg, AgentDispatchContext inContext, String mode, String loginUrlShortName
			, String smsMessage, String label, String confirmMessage, String note, String paymentOkUrl, String paymentNgUrl
			, String freefield2Env, String freefield2) throws IOException
	{
		// 運用日付
		String opeDate = (String)JPCModelCommon.getOpeDate(inCBSMsg, inContext, null);
		String opeDateFmt = new JCCToolTextDateFormat("yyyy/MM/dd", "yyyyMMdd").formattedPrint(opeDate);

		// 支払・取扱・有効期限日
		String payKigenYmd = inCBSMsg.getString(ECHA0010001CBSMsg.PAY_KIGEN_YMD);
		String payKigenYmdFmt = new JCCToolTextDateFormat("yyyy/MM/dd", "yyyyMMdd").formattedPrint(payKigenYmd);
		// 決済方法
		String settleType[] = new String[]{inCBSMsg.getString(ECHA0010001CBSMsg.KSSAI_WAY)};
		// 請求先番号＋請求年月＋発行シーケンス
		String orderNo = inCBSMsg.getString(ECHA0010001CBSMsg.SEIKY_KEI_NO)
							+ inCBSMsg.getString(ECHA0010001CBSMsg.SEIKY_YM)
							+ (inCBSMsg.getString(ECHA0010001CBSMsg.SKS_HAKKO_SEQ).substring(1));

		// JOSN形式へ変換するためのMAP
		Map<String, Object> requestMap = new HashMap<String, Object>();
		// 変換後文字列
		String json = "";

		// 略称（URL用）
		requestMap.put(LOGINURLSHORTNAME, loginUrlShortName);

		// ▼▼▼▼▼▼▼▼▼▼▼【SMS送信情報】▼▼▼▼▼▼▼▼▼▼▼

		// 電話番号
		requestMap.put(MOBILETEL, inCBSMsg.getString(ECHA0010001CBSMsg.TEL_NO));

		// SMSメッセージ
		requestMap.put(SMSMESSAGE, smsMessage);

		if (FREEFIELD2_ENV_APLCONST.equals(freefield2Env))
		{
			// フリー項目２
			requestMap.put(FREEFIELD2, freefield2);
		}
		else
		{
			// フリー項目２
			requestMap.put(FREEFIELD2, payKigenYmd);
		}
		if (requestMap.get(FREEFIELD2) == null)
		{
			requestMap.put(FREEFIELD2, "");
		}

		// トークン有効期限
		requestMap.put(TOKENLIMIT, payKigenYmdFmt + " 23:00");

		// ▲▲▲▲▲▲▲▲▲▲▲【SMS送信情報】▲▲▲▲▲▲▲▲▲▲▲

		// ▼▼▼▼▼▼▼▼▼▼▼【期限設定】▼▼▼▼▼▼▼▼▼▼▼

		// 認証パラメータリスト
		List<Map<String, String>> authInfoList = new ArrayList<Map<String, String>>();

		Map<String, String> authInfoMap = new HashMap<String, String>();
		// ラベル名
		authInfoMap.put(LABEL, label);
		// 値
		authInfoMap.put(AUTHVALUE, inCBSMsg.getString(ECHA0010001CBSMsg.SECR_QS_ANS));
		// 入力モード
		authInfoMap.put(INPUTMODE, "1");

		// 認証パラメータリストの設定
		authInfoList.add(authInfoMap);
		requestMap.put(AUTHINFOLIST, authInfoList);
		// ▲▲▲▲▲▲▲▲▲▲▲【期限設定】▲▲▲▲▲▲▲▲▲▲▲

		// ▼▼▼▼▼▼▼▼▼▼▼【決済ポータル画面表示情報】▼▼▼▼▼▼▼▼▼▼▼

		// 商品パラメータ
		Map<String, Object> itemParamMap = new HashMap<String, Object>();

		// 決済方法
		itemParamMap.put(SETTLETYPE, settleType);
		// 商品確認メッセージ
		itemParamMap.put(CONFIRMMESSAGE, confirmMessage);
		// No.
		itemParamMap.put(ORDERNO, orderNo);
		// 注文日時
		// IT2-2019-0000041 MOD START
//		itemParamMap.put(ORDERDATE, opeDateFmt.substring(0, 8) + "01 9:00");
		itemParamMap.put(ORDERDATE, opeDateFmt.substring(0, 8) + "01 09:00");
		// IT2-2019-0000041 MOD END
		// 商品区分
		itemParamMap.put(ITEMTYPE, "1");
		// 課金方法
		itemParamMap.put(PAYMENTTYPE, "1");
		// 合計金額
		itemParamMap.put(PAYMENTPRICE, inCBSMsg.getString(ECHA0010001CBSMsg.SEIKY_AMNT));
		// 備考
		itemParamMap.put(NOTE, note);
		
		// 商品パラメータの設定
		requestMap.put(ITEMPARAM, itemParamMap);
		// ▲▲▲▲▲▲▲▲▲▲▲【決済ポータル画面表示情報】▲▲▲▲▲▲▲▲▲▲▲

		// ▼▼▼▼▼▼▼▼▼▼▼【決済終了情報】▼▼▼▼▼▼▼▼▼▼▼

		// 決済OK後遷移URL
		requestMap.put(PAYMENTOKURL, paymentOkUrl);

		// 決済NG後遷移URL
		requestMap.put(PAYMENTNGURL, paymentNgUrl);

		// ▲▲▲▲▲▲▲▲▲▲▲【決済終了情報】▲▲▲▲▲▲▲▲▲▲▲

		ObjectMapper mapper = new ObjectMapper();
		mapper.enable(SerializationFeature.INDENT_OUTPUT);
		try
		{
			// JOSN形式へ変換
			json = mapper.writeValueAsString(requestMap);

		} catch (IOException e)
		{
			e.printStackTrace();
			throw e;
		}
		
		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] = JCMAPLConstMgr.getString(STUB_MESSAGE_KEY);
		// アプリケーションプロパティ設定チェック
		if(JCHStringUtil.isNullBlank(response[0]))
		{
			return false;
		}
		
		return true;
	}

	/**
	 * SMAPS APIに対して送信するリクエストパラメータを作成する。
	 * @param strPostUrl 送信先URL
	 * @param smsAuthCode 認証コード
	 * @param json 送信するJSON文字列
	 * @param connectTimeout 接続タイムアウト
	 * @param readTimeout 読取タイムアウト
	 * @param retryCount リトライ回数
	 * @param retryInterval リトライインターバル
	 * @return JSONレスポンスから取得したパラメータ
	 * @throws Exception 
	 */
	private static String[] callPost(String strPostUrl, String smsAuthCode, String json, int connectTimeout, int readTimeout, int retryCount,
			int retryInterval)
	throws IOException
	{
		// レスポンス
		StringBuffer result = new StringBuffer();
		// 応答コード
		String code = null;
		// メッセージ
		String message = 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(SMS_AUTH_CODE, smsAuthCode);
				con.setRequestProperty(CONTENT_TYPE, CONTENT_TYPE_VALUE);

				//タイムアウト設定
				con.setConnectTimeout(connectTimeout);
				con.setReadTimeout(readTimeout);

				con.setDoOutput(true);
				OutputStreamWriter out = new OutputStreamWriter(con.getOutputStream(), SMAPS_ENCODING);
				out.write(json);

				out.flush();

				// 接続開始ログ
				JSYejbLog.println(JSYejbLog.DEBUG, JECHA0010001TPMA.class, "JECHA0010001TPMA#connect start");

				// 接続
				con.connect();

				httpStatus = con.getResponseCode();

				// 接続終了ログ
				JSYejbLog.println(JSYejbLog.DEBUG, JECHA0010001TPMA.class, "JECHA0010001TPMA#connect end");

				
				// 通信に成功したテキストを取得する
				final InputStream in = con.getInputStream();
				String encoding = con.getContentEncoding();
				if (null == encoding)
				{
					encoding = SMAPS_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(CODE) != null)
				{
					code = root.get(CODE).textValue();
				}
				if (root.get(MESSAGE) != null)
				{
					message = root.get(MESSAGE).textValue();
				}
				// レスポンスをログ出力
				JSYejbLog.println(JSYejbLog.EXECUTION, JECHA0010001TPMA.class ,("JECHA0010001TPMA#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), code, message};
	}

	/**
	 * スタブをコールする
	 * @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(CODE, response[1]);
			if (CODE_OK.equals(response[1]))
			{
				responseMap.put(MESSAGE, null);
			}
			else
			{
				responseMap.put(MESSAGE, 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, JECHA0010001TPMA.class, ("JECHA0010001TPMA#response=" + json).replaceAll("\\s+", " "));
		}
		
		return response;
	}

	/**
	 * nullを空文字に置き換え
	 * 
	 * @param str 置き換え対象文字列
	 * @return
	 */
	private static String nullToBlank(String str)
	{
		if (str == null)
		{
			return "";
		}
		return str;
	}

	/**
	 * JSONをマスク
	 * 
	 * @param json マスクするJSON
	 * @param maskKey マスクするキー
	 * @param count マスクする文字数
	 * @return マスク後の文字列
	 */
	private static String maskJson(String json, String maskKey, int count)
	{
		String ret = "";
		
		if (!JCHStringUtil.isNullBlank(json))
		{
			StringBuffer sb = new StringBuffer();
			for (int i = 0; i < count; i++)
			{
				sb.append("\\*");
			}
			ret = json.replaceAll("(\"" + maskKey + "\"\\s*:\\s*\")[^\"]*\"", "$1" + sb.toString() + "\"");
		}
		
		return ret;
	}
}
