/*********************************************************************
* All Rights reserved,Copyright (c) K-Opticom
**********************************************************************
*＜プログラム内容＞
*    システム名        ：eo顧客基幹システム
*    モジュール名    ：JFUAgentUserPwdChgCC
*    ソースファイル名：JFUAgentUserPwdChgCC.java
*    作成者            ：FJ
*    日付            ：2019年11月1日
*＜機能概要＞
*    アカウント認証(営業支援)(FUIFE168)の共通コンポーネント
*＜修正履歴＞
*    バージョン      修正日      修正者      修正内容
*    v46.00.00       2019/11/01  FJ)西川     ANK-3766-00-00_営業チャネルでの既契約者対応
*    v48.00.00       2020/01/27  FJ)張本     ANK-3795-00-00_見込顧客システム構築対応
*    v49.00.00       2020/06/17  FJ)大島     ANK-3867-00-00_eフロント向けAPIの機能変更
*    v49.00.00       2020/07/08  FJ)大島     ANK-3867-01-00_eフロント向けAPIの機能変更(連携項目追加対応)
*    v52.00.00       2021/02/12  FJ)大島     ANK-3969-00-00_eフロント向けアカウント認証機能の一時無効化機能の開発
*    v57.00          2021/12/28  FJ)張本     ANK-4170-00-00_eフロントの改善要望に関するeo顧客基幹SのAPI・画面連携変更対応(2022年1月下旬リリース)
*    v57.01          2022/02/09  FJ)張本    ANK-4173-00-00_【eo顧客】解約後の契約情報表示、再申込対応
**********************************************************************/
package com.fujitsu.futurity.bp.custom.common;

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.Map.Entry;

import com.fujitsu.futurity.bp.x21.bpm.ServiceComponentRequestInvoker;
import com.fujitsu.futurity.bp.x21.bpm.db.SessionHandle;
import com.fujitsu.futurity.bp.x21.bpm.exception.RequestParameterException;
import com.fujitsu.futurity.bp.x21.bpm.parameter.IRequestParameterReadWrite;
import com.fujitsu.futurity.bp.x21.cc.AbstractCommonComponent;
import com.fujitsu.futurity.bp.x21.cc.exception.SCCallException;
import com.fujitsu.futurity.common.JCMConstants;
import com.fujitsu.futurity.common.JSYLogBase;
import com.fujitsu.futurity.common.x01.sc.SCControlMapKeys;
import com.fujitsu.futurity.mapping.bp.common.TemplateErrorUtil;
import com.fujitsu.futurity.model.base.CAANMsg;
import com.fujitsu.futurity.model.common.JCMAPLConstMgr;
import com.fujitsu.futurity.model.common.check.HalfCharCheck;
import com.fujitsu.futurity.model.common.check.LengthCheck;
import com.fujitsu.futurity.model.ejb.common.JSYejbLog;

import eo.common.constant.JFUStrConst;
import eo.common.constant.JPCModelConstant;
import eo.common.util.JCCcomEncryptionUtil;
import eo.common.util.JFUCommonUtil;
import eo.common.util.JPCDateUtil;
import eo.ejb.cbs.cbsmsg.ECK0011A010CBSMsg;
import eo.ejb.cbs.cbsmsg.EFU0221B010CBSMsg;
import eo.ejb.cbs.cbsmsg.EFU0221D010CBSMsg;
import eo.ejb.cbs.cbsmsg.EFU0371D010CBSMsg;
import eo.ejb.cbs.cbsmsg.EKK0061A010CBSMsg;
import eo.ejb.cbs.cbsmsg.EKK0061A010CBSMsg1List;
import eo.ejb.cbs.cbsmsg.EZM0011B020CBSMsg;
import eo.ejb.cbs.cbsmsg.EZM0501A010CBSMsg;
import eo.ejb.cbs.cbsmsg.EZM0501A010CBSMsg1List;
import eo.ejb.cbs.cbsmsg.EZM0501B010CBSMsg;
import eo.ejb.cbs.cbsmsg.EZM0501B010CBSMsg1List;
import eo.ejb.cbs.cbsmsg.EZM0501D020CBSMsg;
import eo.ejb.cbs.cbsmsg.EZM0531A010CBSMsg;
import eo.ejb.common.JFUModelCommon;

/**
 * 量販・訪販ユーザパスワード変更（営業支援）の共通コンポーネントクラスです。
 * <br>
 * @author 富士通
 *
 */
public class JFUAgentUserPwdChgCC extends AbstractCommonComponent
{

	/** テンプレートID(EKK0061A010) 代理店一意照会 */
	private static final String TEMPLATE_ID_EKK0061A010 = "EKK0061A010";

	/** テンプレートID(EZM0501A010) 量販訪販ユーザーパスワード一意照会 */
	private static final String TEMPLATE_ID_EZM0501A010 = "EZM0501A010";

	/** テンプレートID(EZM0011B020) 権限一覧照会 */
	private static final String TEMPLATE_ID_EZM0011B020 = "EZM0011B020";

	/** テンプレートID(EFU0221B010) 担当者ログイン実績一覧照会 */
	private static final String TEMPLATE_ID_EFU0221B010 = "EFU0221B010";

	/** テンプレートID(EFU0221D010) 担当者ログイン実績登録 */
	private static final String TEMPLATE_ID_EFU0221D010 = "EFU0221D010";

	/** テンプレートID(EZM0501B010) 量販訪販ユーザーパスワード一覧照会 */
	private static final String TEMPLATE_ID_EZM0501B010 = "EZM0501B010";

	/** テンプレートID(EZM0501D020) 量販訪販ユーザーパスワード登録 */
	private static final String TEMPLATE_ID_EZM0501D020 = "EZM0501D020";

	/** テンプレートID(EZM0501D020) アカウント認証無効設定一意照会 */
	private static final String TEMPLATE_ID_EZM0531A010 = "EZM0531A010";

	/** テンプレートID(EFU0371D010) 量販訪販Ｗｅｂアクセス認証キー登録 */
	private static final String TEMPLATE_ID_EFU0371D010 = "EFU0371D010";

	/** テンプレートID(ECK0011A010) お客様一意照会 */
	private static final String TEMPLATE_ID_ECK0011A010 = "ECK0011A010";

	/** アプリケーションプロパティ 共通キー */
	private static final String APLCONST_ENCRYPT_KEY = "ENCRYPT_KEY";

	/** アプリケーションプロパティ eoと営業支援システムの共通キー */
	private static final String APLCONST_COMMKEY = "FU_EIGYOSHIEN_COMMKEY";

	/** アプリケーションプロパティ パスワード有効日数（90） */
	private static final String APLCONST_PASSYUKODAY_KEY = "FU_RHVH_PASS_YUKODAY";

	/** アプリケーションプロパティ パスワード履歴チェック数（8） */
	private static final String APLCONST_PASSRIREKINUM_KEY = "FU_RHVH_PASS_RIREKINUM";

	/** 権限コード 量販 */
	private static final String AUTHORITYCD_RH_AUFU051000010 = "AUFU051000010";

	/** 権限コード 訪販 */
	private static final String AUTHORITYCD_VH_AUFU052000010 = "AUFU052000010";

	/** 受付担当者コード 量販 */
	private static final String UKTNTSHASKBTCD_RH = "02";

	/** 受付担当者コード 訪販 */
	private static final String UKTNTSHASKBTCD_VH = "03";

	/** Ｗｅｂアクセス認証キー種別コード */
	private static final String WEB_ACCSS_NSKEY_SBT_CD = "01";

	/** リクエストパラメータキー 機能コード */
	private static final String REQ_KEY_FUNC_CODE = "funcCode";

	/** リクエストパラメータキー 取扱コード2 */
	private static final String REQ_KEY_AGENCY_CODE2 = "agencyCode2";

	/** リクエストパラメータキー 従業員番号 */
	private static final String REQ_KEY_ID = "id";

	/** リクエストパラメータキー パスワード */
	private static final String REQ_KEY_PASSWORD = "password";

	/** リクエストパラメータキー 新パスワード */
	private static final String REQ_KEY_PASSWORD_NEW = "passwordNew";

	/** リクエストパラメータキー 暗号化キー */
	private static final String REQ_KEY_CK = "ck";

	/** リクエストパラメータキー Web申込データ */
	private static final String REQ_KEY_WEB_MSKM_DATA = "webMskmData";

	/** リクエストパラメータキー Web申込機能コード */
	private static final String REQ_KEY_WEB_MSKM_FUNC_CD = "webMskmFuncCode";

	/** リクエストパラメータキー SYSID */
	private static final String REQ_KEY_SYSID = "sysid";

	/** リクエストパラメータキー サービス契約回線内訳番号 */
	private static final String REQ_KEY_SVC_KEI_KAISEN_UCSK_NO = "svcKeiKaisenUcwkNo";

	/** リクエストパラメータキー 署名必須設定 */
	private static final String REQ_KEY_SIGN_REQ = "signReq";

	/** レスポンスキー 取扱コード1 */
	private static final String RES_KEY_AGENCY_CODE1 = "agencyCode1";

	/** レスポンスキー 取扱コード1名称 */
	private static final String RES_KEY_AGENCY_CODE1_NM = "agencyCode1Nm";

	/** レスポンスキー 認証結果 */
	private static final String RES_KEY_AUTHENTICATION_RESULT = "authenticationResult";

	/** レスポンスキー ワンタイムキー */
	private static final String RES_KEY_ONTIME_KEY = "onetimeKey";
	
	/** CCパラメータ：エラー情報 */
	private static final String ERROR_INFO = "ERROR_INFO";

	/** CCパラメータ：エラーコード */
	private static final String ERROR_CODE = "errCode";

	/** CCパラメータ：エラーメッセージ */
	private static final String ERROR_MESSAGE = "errMessage";

	/** レスポンス値 認証結果 0：認証OK／パスワード変更OK */
	private static final String RES_AUTHENTICATION_RESULT_0 = "0";

	/** レスポンス値 認証結果 1：有効期限切れ */
	private static final String RES_AUTHENTICATION_RESULT_1 = "1";

	/** レスポンス値 認証結果 9：認証エラー／パスワード変更エラー */
	private static final String RES_AUTHENTICATION_RESULT_9 = "9";

// ANK-3867-00-00 ADD START
	/** レスポンス値 取扱コード2名称 */
	private static final String RES_KEY_AGENCY_CODE2_NM = "agencyCode2Nm";

	/** レスポンス値 従業員名称 */
	private static final String RES_KEY_ID_NM = "idNm";

	/** レスポンス値 チャネル */
	private static final String RES_KEY_CHANNEL = "channel";
// ANK-3867-00-00 ADD END
// ANK-3867-01-00 ADD START
	/** レスポンス値 表示用取扱名称 */
	private static final String RES_KEY_DISPLAYAGENCYNM = "displayAgencyNm";
// ANK-3867-01-00 ADD END

	/** APIエラーコード_1001：必須チェックエラー */
	private static final String RES_KEY_ERROR_CODE_1001 = "1001";
	/** APIエラーコード_1002：属性チェックエラー */
	private static final String RES_KEY_ERROR_CODE_1002 = "1002";
	/** APIエラーコード_1003：桁数チェックエラー */
	private static final String RES_KEY_ERROR_CODE_1003 = "1003";

	/** APIエラーコード_2001 */
	private static final String RES_KEY_ERROR_CODE_2001 = "2001";
	/** APIエラーコード_2002 */
	private static final String RES_KEY_ERROR_CODE_2002 = "2002";
	/** APIエラーコード_3001 */
	private static final String RES_KEY_ERROR_CODE_3001 = "3001";
	/** APIエラーメッセージ_3001 */
	private static final String RES_ERRORMSG_3001 = "アカウント認証無効期間中";
	
	/** APIリターンコード_0000 正常終了 */
	private static final String RETURN_CD_0000 = "0000";
	/** APIリターンコード_9000_システムエラー */
	private static final String RETURN_CD_9000 = "9000";
	/** リターンメッセージ_システムエラー */
	public static final String RETURN_MESSAGE_SYSTEM_ERROR = "システムエラー";

	/** 半角コロン */
	private static final String COLON = ":";
	/** カンマ */
	public static final String COMMA = ",";

	/** 属性チェック 半角数字1 */
	private static final String ATTR_HANNKAKUSUUJI1 = "hannkakusuuji1";

	/** 属性チェック 半角英数字1 */
	private static final String ATTR_HANNKAKUESUUJI1 = "hannkakuesuuji1";

	/** 属性チェック 半角英数字2 */
	private static final String ATTR_HANNKAKUESUUJI2 = "hannkakuesuuji2";

	/** 属性チェック 半角英数字8 */
	private static final String ATTR_HANNKAKUESUUJI8 = "hannkakuesuuji8";

	/** ＷＥＢ申込機能コード有効 */
	private static final List<String> WEB_MSKM_FUNC_CD_YUKO = Arrays.asList(JPCModelConstant.FUNC_CD_1, JPCModelConstant.FUNC_CD_2, JPCModelConstant.FUNC_CD_3);

	/** 署名必須設定有効 */
	private static final List<String> SIGN_REQ_YUKO = Arrays.asList(JFUStrConst.CD00002_1);

	/**
	 * 量販・訪販ユーザパスワード変更を行います。
	 * <br>
	 * @param handle セッションハンドル
	 * @param param リクエストパラメータ
	 * @param fixedText ユーザ定義文字列
	 * @return リクエストパラメータ
	 * @throws Throwable 例外が発生した場合
	 */
	@SuppressWarnings("unchecked")
	public IRequestParameterReadWrite execute(SessionHandle handle, IRequestParameterReadWrite param, String fixedText) throws Throwable
	{

		// 量販・訪販ユーザパスワード変更CCマップ
		Map<String, Object> ccMsg = (Map<String, Object>)param.getData(fixedText);
		// SC呼び出し部品のインスタンス生成（引数にはログに出力するクラス名を渡す。空文字を設定した場合はログに出力されない）
		ServiceComponentRequestInvoker scCall = new ServiceComponentRequestInvoker();

		try
		{

			// ===========================================================================
			// 返却値の初期値を設定する。
			// ===========================================================================
			// 取扱コード1
			ccMsg.put(RES_KEY_AGENCY_CODE1, "");
			// 取扱コード1名称
			ccMsg.put(RES_KEY_AGENCY_CODE1_NM, "");
			// 認証結果「"9"：認証エラー／パスワード変更エラー」
			ccMsg.put(RES_KEY_AUTHENTICATION_RESULT, RES_AUTHENTICATION_RESULT_9);
// ANK-3867-00-00 ADD START
			// 取扱コード2名称
			ccMsg.put(RES_KEY_AGENCY_CODE2_NM, "");
			// 従業員名称
			ccMsg.put(RES_KEY_ID_NM, "");
			// チャネル
			ccMsg.put(RES_KEY_CHANNEL, "");
			// 表示用取扱名称
			ccMsg.put(RES_KEY_DISPLAYAGENCYNM, "");
// ANK-3867-00-00 ADD END
			// ワンタイムキー
			ccMsg.put(RES_KEY_ONTIME_KEY, "");

			// 営業支援システムからのウェブ申込データを取得する。
			Map<String, Object> webMskmData = (Map<String, Object>)ccMsg.get(REQ_KEY_WEB_MSKM_DATA);
			// ウェブ申込データをDB登録用に保持する。
			Map<String, Object> inputData = new HashMap<String, Object>();

			// ===========================================================================
			// パスワード変更処理の呼出しを判定する。
			// ===========================================================================
			// パスワード変更（機能コードが「2」）の場合に「true」
			boolean isPassChngCall = JPCModelConstant.FUNC_CD_2.equals(ccMsg.get(REQ_KEY_FUNC_CODE));
			// ワンタイムキー取得（機能コードが「3」）の場合に「true」
			boolean isOnetimeKeyCall = JPCModelConstant.FUNC_CD_3.equals(ccMsg.get(REQ_KEY_FUNC_CODE));

			// 復号化処理前の場合：true、復号化処理後の場合：false
			boolean isDecryptAfter = false;

			// ===========================================================================
			// 単項目チェック@(復号化前)内容を定義
			// ===========================================================================
			// パラメータチェック（必須、属性、桁数）
			// ・いずれかの項目でエラーが発生した場合、認証結果を「"9"：認証エラー」で返却する。

			HashMap<String, String> checkUnitParamMap = new HashMap<String, String>();
			HashMap<String, String> checkUnitMskDtMap = new HashMap<String, String>();
			// 暗号化キー:チェックなし

			// 暗号化キー:ck:必須チェックのみ実施する。
			checkUnitParamMap.put(REQ_KEY_CK, "");

			if (!isOnetimeKeyCall)
			{
				// パスワード:password:必須チェックのみ実施する。
				checkUnitParamMap.put(REQ_KEY_PASSWORD, "");
			}

			// 機能コード:funcCode:半角数字1
			checkUnitParamMap.put(REQ_KEY_FUNC_CODE, "hannkakusuuji1:1,1");

			// 取扱コード2:agencyCode2:半角英数字8
			checkUnitParamMap.put(REQ_KEY_AGENCY_CODE2, "hannkakuesuuji8:11,11");

			// 従業員番号:id:半角英数字1
			checkUnitParamMap.put(REQ_KEY_ID, "hannkakuesuuji1:6,6");

			if (isPassChngCall)
			{
				// パスワード変更（機能コードが「2」）の場合

				// パスワード:passwordNew:必須チェックのみ実施する。
				checkUnitParamMap.put(REQ_KEY_PASSWORD_NEW, "");
			}

			// ===========================================================================
			// 単項目チェック@(復号化処理前)
			// ===========================================================================
			List<Map<String, String>> errorList = checkUnitParam(ccMsg, checkUnitParamMap, null, null, isDecryptAfter);

			String funcCode = (String)ccMsg.get(REQ_KEY_FUNC_CODE);

			if (!JFUBPCommon.isNull(funcCode)
					&& !(JPCModelConstant.FUNC_CD_1.equals(funcCode) || isPassChngCall || JPCModelConstant.FUNC_CD_3.equals(funcCode)))
			{
				// 機能コードが「1：アカウント認証」または「2：パスワード変更」以外の場合はエラー

				errorList = setGyomuErrorList(errorList, REQ_KEY_FUNC_CODE, funcCode, RES_KEY_ERROR_CODE_1002);
			}

			// ===========================================================================
			// 単項目チェック（Ｗｅｂ申込データ）
			// ===========================================================================
			if (isOnetimeKeyCall)
			{
				// 機能コード:funcCode:必須
				checkUnitMskDtMap.put(REQ_KEY_WEB_MSKM_FUNC_CD, "");

				if (!JFUBPCommon.isNull(webMskmData))
				{
					// Web申込機能コード
					String mskmFuncCd = (String)webMskmData.get(REQ_KEY_WEB_MSKM_FUNC_CD);
					// 署名必須設定
					String signReq = (String)webMskmData.get(REQ_KEY_SIGN_REQ);

					// Web申込機能コードが「2：サービス追加」「3：再申込」の場合
					if (JPCModelConstant.FUNC_CD_2.equals(webMskmData.get(REQ_KEY_WEB_MSKM_FUNC_CD))
							|| JPCModelConstant.FUNC_CD_3.equals(webMskmData.get(REQ_KEY_WEB_MSKM_FUNC_CD)))
					{
						// SYSID:sysid:必須
						checkUnitMskDtMap.put(REQ_KEY_SYSID, "");
					}
					// Web申込機能コードが「3：再申込」の場合
					if (JPCModelConstant.FUNC_CD_3.equals(webMskmData.get(REQ_KEY_WEB_MSKM_FUNC_CD)))
					{
						// サービス契約回線内訳番号:svcKeiKaisenUcwkNo:必須
						checkUnitMskDtMap.put(REQ_KEY_SVC_KEI_KAISEN_UCSK_NO, "");
					}
					errorList.addAll(checkUnitParam(webMskmData, checkUnitMskDtMap, null, null, isDecryptAfter));

					if (!JFUBPCommon.isNull(mskmFuncCd) && !WEB_MSKM_FUNC_CD_YUKO.contains(mskmFuncCd))
					{
						// Web申込機能コードが有効でない場合はエラー
						errorList = setGyomuErrorList(errorList, REQ_KEY_WEB_MSKM_FUNC_CD, mskmFuncCd, RES_KEY_ERROR_CODE_1002);
					}
					if (!JFUBPCommon.isNull(signReq) && !SIGN_REQ_YUKO.contains(signReq))
					{
						// 署名必須設定が「1」以外
						errorList = setGyomuErrorList(errorList, REQ_KEY_SIGN_REQ, signReq, RES_KEY_ERROR_CODE_1002);
					}
					// ウェブ申込データをDB登録用に保持する。
					inputData.putAll(webMskmData);
				}
				else
				{
					errorList.addAll(checkUnitParam(ccMsg, checkUnitMskDtMap, null, null, isDecryptAfter));
				}
			}

			if (errorList.size() > 0)
			{
				// エラーが存在する場合

				ccMsg.put(ERROR_INFO, errorList);
				param.setControlMapData(SCControlMapKeys.RETURN_CODE, RETURN_CD_0000);
				param.setControlMapData(SCControlMapKeys.RETURN_MESSAGE, null);

				outBusLog(ccMsg, "単項目チェックエラー1");

				return param;
			}

			// ===========================================================================
			// 復号化処理
			// ===========================================================================

			// 共通暗号キー取得処理
			// 営業支援システムとeo顧客基幹システムのそれぞれで保持する同一の共通暗号キーを取得する。
			// eo顧客基幹システムでは、共通暗号化キーをeo独自の共通キーで更に暗号化しプロパティに設定する。
			String commonKey = JCMAPLConstMgr.getString(APLCONST_COMMKEY);

			// 営業支援システムからのパスワードを取得する。
			String passwordEncrypt = JFUBPCommon.nvl((String)ccMsg.get(REQ_KEY_PASSWORD), "");

			// リクエストより「暗号化キー」を取得し共通暗号キーで復号化する。
			String rondomKeyEncrypt = (String)ccMsg.get(REQ_KEY_CK);
			String rondomKey = JCCcomEncryptionUtil.decrypt(commonKey, rondomKeyEncrypt);

			// 復号化した「暗号化キー」で「パスワード」を復号化する。
			String password = JCCcomEncryptionUtil.decryptKey(rondomKey, passwordEncrypt);

			String passwordNewEncrypt = null;
			String passwordNew = null;

			String sysid = null;
			String svcKeiKaisenUcwkNo = null;

			if (isPassChngCall)
			{
				// パスワード変更（機能コードが「2」）の場合

				// 復号化した「暗号化キー」で「新パスワード」を復号化する。
				passwordNewEncrypt = (String)ccMsg.get(REQ_KEY_PASSWORD_NEW);
				passwordNew = JCCcomEncryptionUtil.decryptKey(rondomKey, passwordNewEncrypt);
			}
			if (isOnetimeKeyCall)
			{
				// パスワード変更（機能コードが「3」）の場合

				if (webMskmData.containsKey(REQ_KEY_SYSID))
				{
					// 営業支援システムからのSYSIDを取得する。
					String sysidEncrypt = JFUBPCommon.nvl((String)webMskmData.get(REQ_KEY_SYSID), "");
					// 復号化した「暗号化キー」で「SYSID」を復号化する。
					sysid = JCCcomEncryptionUtil.decryptKey(rondomKey, sysidEncrypt);

					inputData.put(REQ_KEY_SYSID, sysid);
				}

				if (webMskmData.containsKey(REQ_KEY_SVC_KEI_KAISEN_UCSK_NO))
				{
					// 営業支援システムからのサービス契約回線内訳番号を取得する。
					String svcKeiKaisenUcwkNoEncrypt = JFUBPCommon.nvl((String)webMskmData.get(REQ_KEY_SVC_KEI_KAISEN_UCSK_NO), "");
					// 復号化した「暗号化キー」で「サービス契約回線内訳番号」を復号化する。
					svcKeiKaisenUcwkNo = JCCcomEncryptionUtil.decryptKey(rondomKey, svcKeiKaisenUcwkNoEncrypt);
		
					inputData.put(REQ_KEY_SVC_KEI_KAISEN_UCSK_NO, svcKeiKaisenUcwkNo);
				}
			}

			// 復号化処理後の為、trueを設定する。
			isDecryptAfter = true;

			// ===========================================================================
			// 単項目チェックA(復号化後)内容を定義
			// ===========================================================================
			// パラメータチェック（必須、属性、桁数）
			// ※『パスワード』は復号化し必須チェックのみ、『新パスワード』は復号化し必須、属性（文字種）、桁数チェックを行う。
			// ・いずれかの項目でエラーが発生した場合、認証結果を「"9"：認証エラー」で返却する。

			// パスワード:password:必須チェックのみ実施する。
			checkUnitParamMap.put(REQ_KEY_PASSWORD, "");

			if (isPassChngCall)
			{
				// パスワード変更（機能コードが「2」）の場合

				// 新パスワード:passwordNew:半角英数字2
				checkUnitParamMap.put(REQ_KEY_PASSWORD_NEW, "hannkakuesuuji2:6,24");
			}

			// ===========================================================================
			// 単項目チェックA(復号化処理後)
			// ===========================================================================
			errorList = checkUnitParam(ccMsg, checkUnitParamMap, password, passwordNew, isDecryptAfter);

			// ===========================================================================
			// 単項目チェック（Ｗｅｂ申込データ）
			// ===========================================================================
			if (isOnetimeKeyCall)
			{
				// ワンタイムキー取得（機能コードが「3」）の場合

				if (JPCModelConstant.FUNC_CD_2.equals(webMskmData.get(REQ_KEY_WEB_MSKM_FUNC_CD))
						|| JPCModelConstant.FUNC_CD_3.equals(webMskmData.get(REQ_KEY_WEB_MSKM_FUNC_CD)))
				{
					// Web申込機能コードが「2：サービス追加」「3：再申込」の場合

					// SYSID:sysid:半角英数字1
					checkUnitMskDtMap.put(REQ_KEY_SYSID, "hannkakuesuuji1:10,10");
				}

				if (JPCModelConstant.FUNC_CD_3.equals(webMskmData.get(REQ_KEY_WEB_MSKM_FUNC_CD)))
				{
					// Web申込機能コードが「3：再申込」の場合

					// サービス契約回線内訳番号:svcKeiKaisenUcwkNo:半角英数字1
					checkUnitMskDtMap.put(REQ_KEY_SVC_KEI_KAISEN_UCSK_NO, "hannkakuesuuji1:12,12");
				}

				errorList = checkUnitParam(webMskmData, checkUnitMskDtMap, sysid, svcKeiKaisenUcwkNo, isDecryptAfter);
			}

			if (errorList.size() > 0)
			{
				// エラーが存在する場合

				ccMsg.put(ERROR_INFO, errorList);
				param.setControlMapData(SCControlMapKeys.RETURN_CODE, RETURN_CD_0000);
				param.setControlMapData(SCControlMapKeys.RETURN_MESSAGE, null);

				outBusLog(ccMsg, "単項目チェックエラー2");

				return param;
			}

			// パスワード新旧チェック
			if (isPassChngCall && passwordEncrypt.equals(passwordNewEncrypt))
			{
				// パスワード変更（機能コードが「2」）で且つ『パスワード』と『新パスワード』が同一の場合

				errorList = setGyomuErrorList(errorList, REQ_KEY_PASSWORD_NEW, passwordNewEncrypt, RES_KEY_ERROR_CODE_2001);
				ccMsg.put(ERROR_INFO, errorList);

				param.setControlMapData(SCControlMapKeys.RETURN_CODE, RETURN_CD_0000);
				param.setControlMapData(SCControlMapKeys.RETURN_MESSAGE, null);

				outBusLog(ccMsg, "パスワード新旧チェックエラー");

				return param;
			}
// ANK-3969-00-00 ADD START
			// アカウント認証無効設定一意照会 EZM0531A010
			// 従業員番号
			String userId = (String)ccMsg.get(REQ_KEY_ID);
			// ログイン日付(運用日付)yyyyMMddHHmm
			String loginDateTime = JCCBPCommon.getOpeDateTime(null).substring(0, 12);

			// アカウント認証無効設定一意照会の上りマッピング
			Object[][] ezm0531A010In =
					{ { EZM0531A010CBSMsg.TEMPLATEID, TEMPLATE_ID_EZM0531A010 }, { EZM0531A010CBSMsg.FUNC_CODE, JPCModelConstant.FUNC_CD_2 }, { EZM0531A010CBSMsg.KEY_USER_ID, userId }, { EZM0531A010CBSMsg.KEY_LOGIN_TIME, loginDateTime } };

			// サービスIF実行
			CAANMsg ezm0531A010Msg = callSC(handle, scCall, param, fixedText, ezm0531A010In, new EZM0531A010CBSMsg().getContents());

			// アカウント認証無効設定一意照会明細
			CAANMsg[] ezm0531A010Msg1List = ezm0531A010Msg.getCAANMsgList(EZM0531A010CBSMsg.EZM0531A010CBSMSG1LIST);

			// サービスIF実行結果チェック
			if (ezm0531A010Msg1List.length > 0 && !isOnetimeKeyCall)
			{
				// 認証結果を「"9"：認証エラー」で返却する。
				errorList = new ArrayList<Map<String, String>>();
				Map<String, String> returnMap = new HashMap<String, String>();
				// 業務エラー設定
				returnMap.put(ERROR_CODE, RES_KEY_ERROR_CODE_3001);
				returnMap.put(ERROR_MESSAGE, RES_ERRORMSG_3001);
				errorList.add(returnMap);
				
				ccMsg.put(ERROR_INFO, errorList);
				ccMsg.put(RES_KEY_AUTHENTICATION_RESULT, RES_AUTHENTICATION_RESULT_9);
				param.setControlMapData(SCControlMapKeys.RETURN_CODE, RETURN_CD_0000);
				param.setControlMapData(SCControlMapKeys.RETURN_MESSAGE, null);

				outBusLog(ccMsg, "ログイン禁止期間チェックエラー");

				return param;
			}
// ANK-3969-00-00 ADD END
			// ===========================================================================
			// 取扱コードチェック
			// ===========================================================================
			// 『取扱コード2』で「KK0061_代理店」マスタを検索し、存在チェックを行う。

			// 取扱コード2(代理店コード)
			String agencyCode2 = (String)ccMsg.get(REQ_KEY_AGENCY_CODE2);

			// 代理店一意照会の上りマッピング
			Object[][] ekk0061a010In =
					{ { EKK0061A010CBSMsg.TEMPLATEID, TEMPLATE_ID_EKK0061A010 }, { EKK0061A010CBSMsg.FUNC_CODE, JPCModelConstant.FUNC_CD_2 }, { EKK0061A010CBSMsg.KEY_AGNT_CD, agencyCode2 },
							{ EKK0061A010CBSMsg.KEY_RSV_APLY_YMD, JCCBPCommon.getOpeDate(null) } };

			// サービスIF実行
			CAANMsg ekk0061a010Msg = callSC(handle, scCall, param, fixedText, ekk0061a010In, new EKK0061A010CBSMsg().getContents());

			// 代理店一意照会明細
			CAANMsg[] ekk0061a010Msg1List = ekk0061a010Msg.getCAANMsgList(EKK0061A010CBSMsg.EKK0061A010CBSMSG1LIST);

			// サービスIF実行結果チェック
			if (ekk0061a010Msg1List == null || ekk0061a010Msg1List.length == 0)
			{
				// 取得件数が0件の場合、認証結果を「"9"：認証エラー／パスワード変更エラー」で返却する。

				param.setControlMapData(SCControlMapKeys.RETURN_CODE, RETURN_CD_0000);
				param.setControlMapData(SCControlMapKeys.RETURN_MESSAGE, null);

				outBusLog(ccMsg, "取扱コード存在チェックエラー");

				return param;
			}

			// ===========================================================================
			// 『取扱コード2』に紐づく「上位代理店コード」を取得
			// ===========================================================================

			// 取扱コード1(上位代理店コード)
			String agencyCode1 = nullToStr(ekk0061a010Msg1List[0].getString(EKK0061A010CBSMsg1List.JOI_AGNT_CD));
			// 取扱コード1(上位代理店コード名称)
			String agencyCode1Nm = nullToStr(ekk0061a010Msg1List[0].getString(EKK0061A010CBSMsg1List.JOI_AGNT_CD_NM));
// ANK-3867-00-00 ADD START
			// 取扱コード2名称
			String agencyCode2Nm = nullToStr(ekk0061a010Msg1List[0].getString(EKK0061A010CBSMsg1List.AGNT_NM));
			// 表示用取扱名称
			String displayAgencyNm = nullToStr(ekk0061a010Msg1List[0].getString(EKK0061A010CBSMsg1List.FRNT_SCREEN_DSP_TRAT_CD_NM));
// ANK-3867-00-00 ADD END
			
			if (JFUBPCommon.isNull(agencyCode1))
			{
				// 上位代理店が未設定の場合、認証結果を「"9"：認証エラー／パスワード変更エラー」で返却する。

				param.setControlMapData(SCControlMapKeys.RETURN_CODE, RETURN_CD_0000);
				param.setControlMapData(SCControlMapKeys.RETURN_MESSAGE, null);

				outBusLog(ccMsg, "上位代理店コード未設定エラー");

				return param;
			}

			// 「上位代理店コード」をレスポンス項目の『取扱コード1』に設定する。
			ccMsg.put(RES_KEY_AGENCY_CODE1, agencyCode1);
			// 「上位代理店コード名称」をレスポンス項目の『取扱コード1名称』に設定する。
			ccMsg.put(RES_KEY_AGENCY_CODE1_NM, agencyCode1Nm);
// ANK-3867-00-00 ADD START
			// 取扱コード2で取得した代理店名をレスポンス項目の『取扱コード2名称』に設定する。
			ccMsg.put(RES_KEY_AGENCY_CODE2_NM, agencyCode2Nm);
			// 取扱コード2で取得したフロント画面表示用取扱コード名をレスポンス項目の『表示用取扱名称』に設定する。
			ccMsg.put(RES_KEY_DISPLAYAGENCYNM, displayAgencyNm);
// ANK-3867-00-00 ADD END

			// ===========================================================================
			// 『取扱コード2』に紐づく「フロントログイン制御コード」を取得
			// ===========================================================================

			// フロントログイン制御コード
			String frntLoginCtrlCd = nullToStr(ekk0061a010Msg1List[0].getString(EKK0061A010CBSMsg1List.FRNT_LOGIN_CTRL_CD));

			// 権限コード
			String authorityCd = null;

			// 受付担当者識別コード
			String ukTntshaSkbtCd = null;

			// 「フロントログイン制御コード」で「量販」、または「訪販」かを判断する。
			if (JFUStrConst.CD01400_3.equals(frntLoginCtrlCd) || JFUStrConst.CD01400_1.equals(frntLoginCtrlCd))
			{
				// 量販

				// 権限コードに「AUFU051000010：量販権限」を設定する。
				authorityCd = AUTHORITYCD_RH_AUFU051000010;

				// 受付担当者識別コードに「02：量販店員」を設定する。
				ukTntshaSkbtCd = UKTNTSHASKBTCD_RH;
			}
			else if (JFUStrConst.CD01400_2.equals(frntLoginCtrlCd) || JFUStrConst.CD01400_4.equals(frntLoginCtrlCd))
			{
				// 訪販

				// 権限コードに「AUFU052000010：訪販権限」を設定する。
				authorityCd = AUTHORITYCD_VH_AUFU052000010;

				// 受付担当者識別コードに「03：訪問販売」を設定する。
				ukTntshaSkbtCd = UKTNTSHASKBTCD_VH;
			}
			else
			{
				// 販売タイプが上記以外の場合、認証結果を「"9"：認証エラー／パスワード変更エラー」で返却する。

				param.setControlMapData(SCControlMapKeys.RETURN_CODE, RETURN_CD_0000);
				param.setControlMapData(SCControlMapKeys.RETURN_MESSAGE, null);

				outBusLog(ccMsg, "フロントログイン制御コード範囲外エラー");

				return param;
			}
// ANK-3867-00-00 ADD START
			String tratCdYoMkmChannelCd = nullToStr(ekk0061a010Msg1List[0].getString(EKK0061A010CBSMsg1List.TRAT_CD_YO_MKM_CHANNEL_CD));
			// チャネルに「取扱コード用申込チャネルコード」を設定する。
			ccMsg.put(RES_KEY_CHANNEL, tratCdYoMkmChannelCd);
// ANK-3867-00-00 ADD END

			// ===========================================================================
			// 認証チェック
			// ===========================================================================
			// 『従業員番号』で「ZM0501_量販訪販ユーザーパスワード」スキーマを検索し取得する。

			// 従業員番号
			String id = (String)ccMsg.get(REQ_KEY_ID);

			// 量販訪販ユーザーパスワード一意照会 EZM0501A010

			// 量販訪販ユーザーパスワード一意照会の上りマッピング
			Object[][] ezm0501A010In =
					{ { EZM0501A010CBSMsg.TEMPLATEID, TEMPLATE_ID_EZM0501A010 }, { EZM0501A010CBSMsg.FUNC_CODE, JPCModelConstant.FUNC_CD_2 }, { EZM0501A010CBSMsg.KEY_USER_ID, id } };

			// サービスIF実行
			CAANMsg ezm0501A010Msg = callSC(handle, scCall, param, fixedText, ezm0501A010In, new EZM0501A010CBSMsg().getContents());

			// 量販訪販ユーザーパスワード一意照会明細
			CAANMsg[] ezm0501A010Msg1List = ezm0501A010Msg.getCAANMsgList(EZM0501A010CBSMsg.EZM0501A010CBSMSG1LIST);

			// サービスIF実行結果チェック
			if (ezm0501A010Msg1List == null || ezm0501A010Msg1List.length == 0)
			{
				// 取得件数が0件の場合、認証結果を「"9"：認証エラー／パスワード変更エラー」で返却する。

				param.setControlMapData(SCControlMapKeys.RETURN_CODE, RETURN_CD_0000);
				param.setControlMapData(SCControlMapKeys.RETURN_MESSAGE, null);

				outBusLog(ccMsg, "従業員番号存在チェックエラー");

				return param;
			}

			// 復号化キー（暗号化）
			String key = JCMAPLConstMgr.getString(APLCONST_ENCRYPT_KEY);

			// 量販訪販ユーザーパスワード（暗号化）
			String rhVhUserPwdEncrypt = ezm0501A010Msg1List[0].getString(EZM0501A010CBSMsg1List.RH_VH_USER_PWD);

			// 量販訪販ユーザーパスワード（復号化）
			String rhVhUserPwd = JCCcomEncryptionUtil.decrypt(key, rhVhUserPwdEncrypt);

			// パスワードと『パスワード』が一致するかチェックする。
			if (!password.equals(rhVhUserPwd) && !isOnetimeKeyCall)
			{
				// 一致しない場合、認証エラーとして、認証結果を「"9"：認証エラー／パスワード変更エラー」で返却する。

				param.setControlMapData(SCControlMapKeys.RETURN_CODE, RETURN_CD_0000);
				param.setControlMapData(SCControlMapKeys.RETURN_MESSAGE, null);

				outBusLog(ccMsg, "パスワード認証エラー");

				return param;
			}

			// パスワード設定年月日時分秒のミリ秒を除き取得する。(yyyyMMddhhmmss)
			String pwdSetteDtm = ezm0501A010Msg1List[0].getString(EZM0501A010CBSMsg1List.PWD_SETTE_DTM).substring(0, 14);

			// 最終更新更新年月日時分秒を取得する。(yyyyMMddhhmmss)
			String lastUpdDtmBf = ezm0501A010Msg1List[0].getString(EZM0501A010CBSMsg1List.UPD_DTM);

// ANK-3867-00-00 ADD START
			// 従業員名の取得
			String idNm =  nullToStr(ezm0501A010Msg1List[0].getString(EZM0501A010CBSMsg1List.USER_NM));
			// レスポンス項目に「従業員名」を設定する。
			ccMsg.put(RES_KEY_ID_NM, idNm);
// ANK-3867-00-00 ADD END
			// ===========================================================================
			// 権限チェック
			// ===========================================================================
			// 『従業員番号』で権限関連のマスタを検索し権限コードが量販の場合「AUFU051000010」、訪販の場合「AUFU052000010」と一致するかチェックする。
			// ・一致しない場合、認証エラーとして、認証結果を「"9"：認証エラー」で返却する。
			// ・一致する場合、下記Dへ移る。
			// [権限関連マスタ]
			// ZM0011_権限、ZM0021_ロール_権限、ZM0031_ロール、ZM0041_権限グループ、ZM0051_ユーザー、ZM0131_ユーザー保持対象権限グループ

			// 権限一覧照会（ユーザーＩＤ）の上りマッピング
			Object[][] ezm0011B020In =
					{ { EZM0011B020CBSMsg.TEMPLATEID, TEMPLATE_ID_EZM0011B020 }, { EZM0011B020CBSMsg.FUNC_CODE, JPCModelConstant.FUNC_CD_1 }, { EZM0011B020CBSMsg.KEY_USER_ID, id },
							{ EZM0011B020CBSMsg.KEY_APLY_YMD, JCCBPCommon.getOpeDate(null) }, { EZM0011B020CBSMsg.KEY_AUTHORITY_CD, authorityCd } };

			// サービスIF実行
			CAANMsg ezm0011B020Msg = callSC(handle, scCall, param, fixedText, ezm0011B020In, new EZM0011B020CBSMsg().getContents());
			// 権限一覧照会（ユーザーＩＤ）明細
			CAANMsg[] ezm0011B020Msg1List = ezm0011B020Msg.getCAANMsgList(EZM0011B020CBSMsg.EZM0011B020CBSMSG1LIST);

			// サービスIF実行結果チェック
			if (ezm0011B020Msg1List == null || ezm0011B020Msg1List.length == 0)
			{
				// 存在しない場合、認証結果を「"9"：認証エラー／パスワード変更エラー」で返却する。

				param.setControlMapData(SCControlMapKeys.RETURN_CODE, RETURN_CD_0000);
				param.setControlMapData(SCControlMapKeys.RETURN_MESSAGE, null);

				outBusLog(ccMsg, "権限チェックエラー");

				return param;
			}

			// 機能コード別の最終処理
			if (JPCModelConstant.FUNC_CD_1.equals(funcCode))
			{
				//(1) アカウント認証（機能コードが「1」）

				// ===========================================================================
				// ログイン実績確認
				// ===========================================================================
				// 代理店ユーザーログイン実績一覧照会の上りマッピング

				Object[][] efu0221B010In =
						{ { EFU0221B010CBSMsg.TEMPLATEID, TEMPLATE_ID_EFU0221B010 }, { EFU0221B010CBSMsg.FUNC_CODE, JPCModelConstant.FUNC_CD_1 }, { EFU0221B010CBSMsg.KEY_USER_ID, id },
								{ EFU0221B010CBSMsg.KEY_LOGIN_DTM, JCCBPCommon.getOpeDateTimeStamp(null) } };

				// サービスIF実行
				CAANMsg efu0221B010Msg = callSC(handle, scCall, param, fixedText, efu0221B010In, new EFU0221B010CBSMsg().getContents());

				// 代理店ユーザーログイン実績一覧照会明細
				CAANMsg[] efu0221B010Msg1List = efu0221B010Msg.getCAANMsgList(EFU0221B010CBSMsg.EFU0221B010CBSMSG1LIST);

				// 初回ログインフラグに「1：初回ログイン」を設定する。
				String firstLoginFlg = JFUStrConst.CD01361_1;
				if (efu0221B010Msg1List != null && efu0221B010Msg1List.length > 0)
				{
					// 検索結果レコードが1件以上ある場合

					// 初回ログインフラグに「0：初回ログインでない」を設定する。
					firstLoginFlg = JFUStrConst.CD01361_0;
				}

				// ===========================================================================
				// ログイン実績登録
				// ===========================================================================
				// ログイン情報を「FU0221_代理店ユーザーログイン実績」スキーマに登録する。
				//
				//  「FU0221_代理店ユーザーログイン実績」スキーマの登録内容
				//  -------------------------------------------------------------------------------------------------
				//  ||項目                 |設定内容                                                              |
				//  -------------------------------------------------------------------------------------------------
				//  |1 |ユーザーID           |『従業員番号』を設定する。                                            |
				//  -------------------------------------------------------------------------------------------------
				//  |2 |ログイン年月日時分秒 |オンライン運用年月日時分秒を設定する。                                |
				//  -------------------------------------------------------------------------------------------------
				//  |3 |代理店コード         |『取扱コード1』（上記Aで取得した「上位代理店コード」）を設定する。   |
				//  -------------------------------------------------------------------------------------------------
				//  |4 |受付担当者識別コード |量販の場合、「02：量販店員」を設定する。                              |
				//  |  |                     |訪販の場合、「03：訪問販売」を設定する。                              |
				//  -------------------------------------------------------------------------------------------------
				//  |5 |初回ログインフラグ   |従業員番号の登録実績がある場合、「0：初回ログインでない」を設定する。 |
				//  |  |                     |従業員番号の登録実績がない場合、「1：初回ログイン」を設定する。       |
				//  -------------------------------------------------------------------------------------------------

				// 担当者ログイン実績登録の上りマッピング
				Object[][] efu0221D010In =
						{ { EFU0221D010CBSMsg.TEMPLATEID, TEMPLATE_ID_EFU0221D010 }, { EFU0221D010CBSMsg.FUNC_CODE, JPCModelConstant.FUNC_CD_1 },
								{ EFU0221D010CBSMsg.LOGIN_DTM, JCCBPCommon.getOpeDateTimeStamp(null) }, { EFU0221D010CBSMsg.AGNT_CD, agencyCode1 },
								{ EFU0221D010CBSMsg.UK_TNTSHA_SKBT_CD, ukTntshaSkbtCd }, { EFU0221D010CBSMsg.FIRST_LOGIN_FLG, firstLoginFlg }, { EFU0221D010CBSMsg.USER_ID, id } };

				// サービスIF実行
				callSC(handle, scCall, param, fixedText, efu0221D010In, new EFU0221D010CBSMsg().getContents());

				// ===========================================================================
				// パスワード有効期限（90日）チェック
				// ===========================================================================
				// パスワードの最終設定日からの経過日数がパスワード有効日数以上かをチェックする。

				// ログイン日付(運用日付)yyyyMMddHHmmss
				String opeDateTime = JCCBPCommon.getOpeDateTime(null);

				// パスワードの有効日数をアプリケーションプロパティファイルより取得する。
				String passwordYukoDay = JCMAPLConstMgr.getString(APLCONST_PASSYUKODAY_KEY);

				// 有効期限を取得
				int diffDate = JPCDateUtil.subtractDay(opeDateTime, pwdSetteDtm);

				if (diffDate >= Integer.parseInt(passwordYukoDay))
				{
					// パスワード有効日数以上（パスワードの有効期限切れ）の場合

					// 認証結果を「"1"：有効期限切れ」で返却する。
					ccMsg.put(RES_KEY_AUTHENTICATION_RESULT, RES_AUTHENTICATION_RESULT_1);
					param.setControlMapData(SCControlMapKeys.RETURN_CODE, RETURN_CD_0000);
					param.setControlMapData(SCControlMapKeys.RETURN_MESSAGE, null);

					outBusLog(ccMsg, "パスワード有効期限エラー");

					return param;
				}
				else
				{
					// パスワード有効日数未満（認証OK）の場合

					// 認証結果を「"0"：認証OK」で返却する。
					ccMsg.put(RES_KEY_AUTHENTICATION_RESULT, RES_AUTHENTICATION_RESULT_0);
					param.setControlMapData(SCControlMapKeys.RETURN_CODE, RETURN_CD_0000);
					param.setControlMapData(SCControlMapKeys.RETURN_MESSAGE, null);

					return param;
				}
			}
			else if (JPCModelConstant.FUNC_CD_2.equals(funcCode))
			{
				//(2) パスワード変更（機能コードが「2」）

				// ===========================================================================
				// パスワード履歴チェック
				// ===========================================================================
				// 『新パスワード』が「ZM0501_量販訪販ユーザーパスワード」スキーマに登録されている直近8世代のパスワードと一致するかをチェックする。

				// 量販訪販ユーザーパスワード一覧照会の上りマッピング
				Object[][] ezm0501B010In =
						{ { EZM0501B010CBSMsg.TEMPLATEID, TEMPLATE_ID_EZM0501B010 }, { EZM0501B010CBSMsg.FUNC_CODE, JPCModelConstant.FUNC_CD_1 }, { EZM0501B010CBSMsg.KEY_USER_ID, id } };

				// サービスIF実行
				CAANMsg ezm0501B010Msg = callSC(handle, scCall, param, fixedText, ezm0501B010In, new EZM0501B010CBSMsg().getContents());

				// 量販訪販ユーザーパスワード一覧照会明細
				CAANMsg[] ezm0501B010Msg1List = ezm0501B010Msg.getCAANMsgList(EZM0501B010CBSMsg.EZM0501B010CBSMSG1LIST);

				// パスワードカウント
				int pwdCnt = 0;

				// サービスIF実行結果チェック
				if (ezm0501B010Msg1List != null && ezm0501B010Msg1List.length > 0)
				{
					// パスワード履歴チェック時のチェックする履歴数("8")をアプリケーションプロパティファイルより取得する。
					int passRerekiCheckNum = Integer.parseInt(JCMAPLConstMgr.getString(APLCONST_PASSRIREKINUM_KEY));

					for (int i = 0; i < ezm0501B010Msg1List.length && pwdCnt < passRerekiCheckNum; i++)
					{
						CAANMsg ezm0501B010Msg1 = ezm0501B010Msg1List[i];

						// パスワード操作内容コードが3(初期化)の場合
						if (JFUStrConst.CD01426_3.equals(ezm0501B010Msg1.getObject(EZM0501B010CBSMsg1List.PWD_SOSA_NAIYO_CD)))
						{
							continue;
						}

						// 量販訪販ユーザーパスワード（復号化）
						String rhVhUserPwdOldEncrypt = (String)ezm0501B010Msg1.getObject(EZM0501B010CBSMsg1List.RH_VH_USER_PWD);

						String rhVhUserPwdOld = JCCcomEncryptionUtil.decrypt(key, rhVhUserPwdOldEncrypt);

						if (passwordNew.equals(rhVhUserPwdOld))
						{
							//『新パスワード』が直近8世代のパスワード履歴と同一の場合

							// 認証結果を「"9"：パスワード変更エラー」で返却する。
							errorList = setGyomuErrorList(errorList, REQ_KEY_PASSWORD_NEW, passwordNewEncrypt, RES_KEY_ERROR_CODE_2002);
							ccMsg.put(ERROR_INFO, errorList);

							param.setControlMapData(SCControlMapKeys.RETURN_CODE, RETURN_CD_0000);
							param.setControlMapData(SCControlMapKeys.RETURN_MESSAGE, null);

							outBusLog(ccMsg, "パスワード履歴存在チェックエラー");

							return param;
						}
						pwdCnt++;
					}
				}

				// ===========================================================================
				// Eパスワード変更
				// ===========================================================================
				// 『新パスワード』を「ZM0501_量販訪販ユーザーパスワード」スキーマに登録し、認証結果を「"0"：パスワード変更OK」で返却する。
				//
				//  「ZM0501_量販訪販ユーザーパスワード」スキーマの登録内容
				//  ------------------------------------------------------------------------
				//  ||項目                       |設定内容                               |
				//  ------------------------------------------------------------------------
				//  |1 |ユーザーID                 |『従業員番号』を設定する。             |
				//  ------------------------------------------------------------------------
				//  |2 |パスワード設定年月日時分秒 |オンライン運用年月日時分秒を設定する。 |
				//  ------------------------------------------------------------------------
				//  |3 |量販訪販ユーザーパスワード |『新パスワード』を暗号化し設定する。   |
				//  ------------------------------------------------------------------------
				//  |4 |パスワード操作内容コード   |「2：変更」を設定する。                |
				//  ------------------------------------------------------------------------

				// 量販訪販ユーザーパスワード（復号化）
				String rhVhUserPwdDecrypt = JCCcomEncryptionUtil.encrypt(key, passwordNew);

				// 量販訪販ユーザーパスワード変更の上りマッピング
				Object[][] ezm0501D020In =
						{ { EZM0501D020CBSMsg.TEMPLATEID, TEMPLATE_ID_EZM0501D020 }, { EZM0501D020CBSMsg.FUNC_CODE, JPCModelConstant.FUNC_CD_1 }, { EZM0501D020CBSMsg.USER_ID, id },
								{ EZM0501D020CBSMsg.RH_VH_USER_PWD, rhVhUserPwdDecrypt }, { EZM0501D020CBSMsg.LAST_UPD_DTM_BF, lastUpdDtmBf } };

				// サービスIF実行
				callSC(handle, scCall, param, fixedText, ezm0501D020In, new EZM0501D020CBSMsg().getContents());
				// 認証結果に「"0"：パスワード変更OK」を設定する。
				ccMsg.put(RES_KEY_AUTHENTICATION_RESULT, RES_AUTHENTICATION_RESULT_0);
			}

			if (JPCModelConstant.FUNC_CD_3.equals(funcCode))
			{
				//(3) ワンタイムキー取得（機能コードが「3」）

				// お客様一意照会 ECK0011A010
				if (!JFUBPCommon.isNull(inputData.get(REQ_KEY_SYSID)))
				{
					// お客様一意照会の上りマッピング
					Object[][] eck0011A010In =
							{ { ECK0011A010CBSMsg.TEMPLATEID, TEMPLATE_ID_ECK0011A010 }, { ECK0011A010CBSMsg.FUNC_CODE, JPCModelConstant.FUNC_CD_2 },
									{ ECK0011A010CBSMsg.KEY_SYSID, inputData.get(REQ_KEY_SYSID) },
									{ ECK0011A010CBSMsg.KEY_RSV_APLY_YMD, JFUBPCommon.getOpeDate(null) } };
	
					// サービスIF実行
					CAANMsg eck0011A010Msg = callSC(handle, scCall, param, fixedText, eck0011A010In, new ECK0011A010CBSMsg().getContents());
	
					// お客様一意照会明細
					CAANMsg[] eck0011A010Msg1List = eck0011A010Msg.getCAANMsgList(ECK0011A010CBSMsg.ECK0011A010CBSMSG1LIST);
	
					// サービスIF実行結果チェック
					if (eck0011A010Msg1List == null || eck0011A010Msg1List.length == 0)
					{
						// 取得件数が0件の場合、認証結果を「"9"：認証エラー／パスワード変更エラー」で返却する。
	
						param.setControlMapData(SCControlMapKeys.RETURN_CODE, RETURN_CD_0000);
						param.setControlMapData(SCControlMapKeys.RETURN_MESSAGE, null);
	
						outBusLog(ccMsg, "SYSID存在チェックエラー");
	
						return param;
					}
				}

				// 量販訪販Ｗｅｂアクセス認証キー登録 EFU0371D010

				// システム日付 ＋ 有効期限を取得する
				Calendar calendar = Calendar.getInstance();
				SimpleDateFormat formYMDHMS = new SimpleDateFormat("yyyyMMddHHmmssSSS");
				calendar.setTime(formYMDHMS.parse(JPCBPCommon.getSysDateTimeStamp()));
				calendar.add(Calendar.MINUTE, 1);
				String work_yk_time = formYMDHMS.format(calendar.getTime());

				// 量販訪販Ｗｅｂアクセス認証キー登録の上りマッピング
				Object[][] EFU0371D010In =
						{ { EFU0371D010CBSMsg.TEMPLATEID, TEMPLATE_ID_EFU0371D010 }
						, { EFU0371D010CBSMsg.FUNC_CODE, JPCModelConstant.FUNC_CD_1 }
						, { EFU0371D010CBSMsg.AGNT_CD, agencyCode2 }
						, { EFU0371D010CBSMsg.USER_ID, id }
						, { EFU0371D010CBSMsg.RH_VH_WEBANK_SBT_CD, WEB_ACCSS_NSKEY_SBT_CD }
						, { EFU0371D010CBSMsg.WEB_ACCSS_NSKEY_STAT_CD, JFUStrConst.CD00016_0 }
						, { EFU0371D010CBSMsg.YK_KIGEN_DTM, work_yk_time }
						, { EFU0371D010CBSMsg.INPUT_DATA, JFUModelCommon.getJsonString(inputData) }
						};

				// サービスIF実行
				CAANMsg EFU0371D010Msg = callSC(handle, scCall, param, fixedText, EFU0371D010In, new EFU0371D010CBSMsg().getContents());

				// Ｗｅｂアクセス認証キー
				String webAcssNskey = EFU0371D010Msg.getString((EFU0371D010CBSMsg.RH_VH_WEB_ACCSS_NSKEY));

				// 「暗号化キー」でＷｅｂアクセス認証キーを暗号化する。
				String enWebAcssNskey = JFUCommonUtil.encrypt(rondomKey, webAcssNskey);

				// ワンタイムキーに暗号化したＷｅｂアクセス認証キーを設定する。
				ccMsg.put(RES_KEY_ONTIME_KEY, enWebAcssNskey);

				// 認証結果に「"0"：ワンタイムキー取得OK」を設定する。
				ccMsg.put(RES_KEY_AUTHENTICATION_RESULT, RES_AUTHENTICATION_RESULT_0);
			}
		}
		// サービスインターフェース呼び出しでエラーが発生した場合
		catch (SCCallException scCallEx)
		{
			// システムエラーを設定する
			param.setControlMapData(SCControlMapKeys.RETURN_CODE, RETURN_CD_9000);
			param.setControlMapData(SCControlMapKeys.RETURN_MESSAGE, RETURN_MESSAGE_SYSTEM_ERROR);
			outBusLog(ccMsg, RETURN_MESSAGE_SYSTEM_ERROR);
			return param;
		}

		param.setControlMapData(SCControlMapKeys.RETURN_CODE, RETURN_CD_0000);
		param.setControlMapData(SCControlMapKeys.RETURN_MESSAGE, null);
		return param;
	}

	/**
	 * 項目名がnullかチェックする
	 * 
	 * @param str 項目名
	 * @return 項目名
	 */
	private String nullToStr(String str)
	{
		if (str == null)
		{
			str = "";
		}
		return str;
	}

	/**
	 * 単項目チェック
	 *
	 * @param ccMsg
	 * @param itemInfoMap
	 * @param pass
	 * @param passNew
	 * @param isDecryptAfter
	 * @return
	 * @throws Exception
	 */
	private List<Map<String, String>> checkUnitParam(Map<String, Object> ccMsg, HashMap<String, String> itemInfoMap, String pass, String passNew, boolean isDecryptAf) throws Exception
	{
		Set<Entry<String, String>> itemInfoMapEntrySet = itemInfoMap.entrySet();
		// エラーリスト
		List<Map<String, String>> errorList = new ArrayList<Map<String, String>>();
		for (Entry<String, String> entry : itemInfoMapEntrySet)
		{
			// チェック情報をチェックパターンと桁数値に分割
			String itemCkeckInfo = entry.getValue();
			String[] itemCkeckInfoArray = itemCkeckInfo.split(COLON);

			String itemCkeckPattern = null;
			int itemCkeckLenMin = 0;
			int itemCkeckLenMax = 0;

			if (itemCkeckInfoArray != null && itemCkeckInfoArray.length == 2)
			{
				// チェックパターン
				itemCkeckPattern = itemCkeckInfoArray[0];

				// 桁数値を最小値と最大値に分割
				String[] itemCkeckLenArray = itemCkeckInfoArray[1].split(COMMA);
				if (itemCkeckLenArray != null && itemCkeckLenArray.length == 2)
				{
					// 桁数：最小値を取得。
					itemCkeckLenMin = Integer.parseInt(itemCkeckLenArray[0]);
					// 桁数：最大値を取得。
					itemCkeckLenMax = Integer.parseInt(itemCkeckLenArray[1]);
				}
			}

			// 項目値
			String itemName = entry.getKey();
			String itemValue = (String)ccMsg.get(itemName);

			if (isDecryptAf)
			{
				// 復号化後のパスワード値で単項目チェックを実施する。

				if (REQ_KEY_PASSWORD.equals(itemName))
				{
					itemValue = pass;
				}
				else if (REQ_KEY_PASSWORD_NEW.equals(itemName))
				{
					itemValue = passNew;
				}
				else if (REQ_KEY_SYSID.equals(itemName))
				{
					itemValue = pass;
				}
				else if (REQ_KEY_SVC_KEI_KAISEN_UCSK_NO.equals(itemName))
				{
					itemValue = passNew;
				}
				else
				{
					// その他の項目値はそのまま使用する。
				}
			}

			// 必須チェック
			if (JFUBPCommon.isNull(itemValue))
			{
				// 必須チェックエラー
				errorList = setGyomuErrorList(errorList, itemName, (String)ccMsg.get(itemName), RES_KEY_ERROR_CODE_1001);
			}
			else if (itemCkeckPattern != null)
			{
				// 属性チェック
				// 各チェックパターンによりチェックを行う
				if (ATTR_HANNKAKUSUUJI1.equals(itemCkeckPattern) && !HalfCharCheck.isNumber1Check(itemValue))
				{
					// 半角数字1

					// 属性チェックエラー
					errorList = setGyomuErrorList(errorList, itemName, (String)ccMsg.get(itemName), RES_KEY_ERROR_CODE_1002);
				}
				else if (ATTR_HANNKAKUESUUJI1.equals(itemCkeckPattern) && !HalfCharCheck.isEnNumber1Check(itemValue))
				{
					// 半角英数字1

					// 属性チェックエラー
					errorList = setGyomuErrorList(errorList, itemName, (String)ccMsg.get(itemName), RES_KEY_ERROR_CODE_1002);
				}
				else if (ATTR_HANNKAKUESUUJI2.equals(itemCkeckPattern) && !HalfCharCheck.isEnNumber2Check(itemValue))
				{
					// 半角英数字2

					// 属性チェックエラー
					errorList = setGyomuErrorList(errorList, itemName, (String)ccMsg.get(itemName), RES_KEY_ERROR_CODE_1002);
				}
				else if (ATTR_HANNKAKUESUUJI8.equals(itemCkeckPattern) && !HalfCharCheck.isEnNumber8Check(itemValue))
				{
					// 半角英数字8

					// 属性チェックエラー
					errorList = setGyomuErrorList(errorList, itemName, (String)ccMsg.get(itemName), RES_KEY_ERROR_CODE_1002);
				}
				else if (REQ_KEY_PASSWORD_NEW.equals(itemName) && isDecryptAf)
				{
					// パスワード変更（機能コードが「2」）の場合
					// 以下の4カテゴリのうち3カテゴリ以上の文字種が混在しているかチェックする。

					int matchCnt = 0;

					//・半角数字
					if (itemValue.matches(".*[0-9].*"))
					{
						matchCnt++;
					}

					//・半角英大文字
					if (itemValue.matches(".*[A-Z].*"))
					{
						matchCnt++;
					}

					//・半角英小文字
					if (itemValue.matches(".*[a-z].*"))
					{
						matchCnt++;
					}

					//・半角記号 #$%&()*+-,/;:<=>?@[]^_~!{}
					if (itemValue.matches(".*[#$%&()*+-,/;:<=>?@\\[\\]\\^_~!{}].*"))
					{
						matchCnt++;
					}

					if (matchCnt < 3)
					{
						// 属性チェックエラー
						errorList = setGyomuErrorList(errorList, itemName, (String)ccMsg.get(itemName), RES_KEY_ERROR_CODE_1002);
					}
					else
					{
						//・記号チェック
						// チェックパターン「半角英数字2」で絞り込んでいるため、「"'.|\`」が入力された場合は、エラー
						for (int i = 0; i < itemValue.length(); i++)
						{
							char c = itemValue.charAt(i);
							if (c == 0x0022 || c == 0x0027 || c == 0x002e || c == 0x005c || c == 0x0060 || c == 0x007c)
							{
								// 属性チェックエラー
								errorList = setGyomuErrorList(errorList, itemName, (String)ccMsg.get(itemName), RES_KEY_ERROR_CODE_1002);
								break;
							}
						}
					}
				}

				// 桁数チェック
				if (itemCkeckLenMax != 0 && !LengthCheck.isLength2Check(itemValue, itemCkeckLenMin, itemCkeckLenMax))
				{

					// 桁数チェックエラー
					errorList = setGyomuErrorList(errorList, itemName, (String)ccMsg.get(itemName), RES_KEY_ERROR_CODE_1003);
				}
			}
		}
		return errorList;
	}

	/**
	 * 業務エラー情報作成(エラーリスト追加時)
	 *
	 * @param itemName
	 * @param itemValue
	 * @param errorCode
	 * @return
	 * @throws Exception
	 */
	private List<Map<String, String>> setGyomuErrorList(List<Map<String, String>> errorList, String itemName, String itemValue, String errorCode) throws Exception
	{

		if (errorList == null)
		{
			errorList = new ArrayList<Map<String, String>>();
		}

		Map<String, String> returnMap = new HashMap<String, String>();

		// 業務エラー設定
		returnMap.put(ERROR_CODE, errorCode);

		// エラーメッセージ設定
		String errMessage = itemName + COLON + itemValue;

		returnMap.put(ERROR_MESSAGE, errMessage);

		errorList.add(returnMap);

		return errorList;
	}

	/**
	 * SC(サービスインターフェイス）を呼び出す。
	 * 
	 * @param handle セッションハンドル
	 * @param scCall SC呼び出し部品
	 * @param param リクエストパラメータ
	 * @param dataMapKey パラメータキー
	 * @param mappingData マッピングデータ
	 * @param contents CAANMsgのコンテンツ
	 * @return CAANMsg
	 * @throws Throwable 例外が発生した場合
	 */
	@SuppressWarnings("unchecked")
	private CAANMsg callSC(SessionHandle handle, ServiceComponentRequestInvoker scCall, IRequestParameterReadWrite param, String dataMapKey, Object[][] mappingData, Object[][] contents)
			throws Throwable
	{
		HashMap<String, Object> paramMap = editInMsg(param, mappingData);

		Map<?, ?> result = scCall.run(paramMap, handle);

		CAANMsg[] templates = (CAANMsg[])result.get(JCMConstants.TEMPLATE_LIST_KEY);

		CAANMsg msg = templates[0];

		// リターンコード取得
		int return_code = (Integer)result.get(JCMConstants.RET_CD_INT_KEY);
		int status = msg.getInt(JCMConstants.STATUS_INT_KEY);

		editErrorInfoCom(param, templates, return_code, dataMapKey, mappingData, contents);

		// エラー情報のマップを取得
		ArrayList<Object> errorList = (ArrayList<Object>)param.getControlMapData(SCControlMapKeys.ERROR_INFO);

		if (null == errorList)
		{
			errorList = new ArrayList<Object>();
		}

		// コントロールマップに設定
		param.setControlMapData(SCControlMapKeys.ERROR_INFO, TemplateErrorUtil.getErrorInfo(result, errorList));

		// 異常の場合、SCCallExceptionを生成してスローする
		if (JPCModelConstant.NORMAL_END < return_code || JPCModelConstant.WARNING < status)
		{
			throw new SCCallException("戻り値不正", String.valueOf(return_code), status);
		}

		return msg;
	}

	/**
	 * 共通項目のメッセージを作成します。
	 * 
	 * @param param リクエストパラメータ
	 * @param mappingData マッピングデータ
	 * @return HashMap<String, Object>
	 * @throws RequestParameterException リクエストパラメータの操作でエラーが発生した場合
	 */
	private HashMap<String, Object> editInMsg(IRequestParameterReadWrite param, Object[][] mappingData) throws RequestParameterException
	{
		HashMap<String, Object> paramMap = new HashMap<String, Object>();

		// 【取得元：電文ヘッダ(ヘッダ)】
		// 電文ID
		paramMap.put(JCMConstants.TRANZACTION_ID_KEY, param.getTelegramID());

		// ユースケースID
		paramMap.put(JCMConstants.USECASE_ID_KEY, param.getUsecaseID());

		// オペレーションID
		paramMap.put(JCMConstants.OPERATION_ID_KEY, param.getOperationID());

		// サービス呼び出し区分
		paramMap.put(JCMConstants.CALL_TYPE_KEY, param.getCallType());

		// 【取得元：ユーザエリア(コントロールマップ)】
		// 依頼先ホスト名
		paramMap.put(JCMConstants.CLIENT_HOST_NAME_KEY, param.getControlMapData(SCControlMapKeys.REQ_HOSTNAME));

		// 依頼元IPアドレス
		paramMap.put(JCMConstants.CLIENT_IP_ADDRESS_KEY, param.getControlMapData(SCControlMapKeys.REQ_HOSTIP));

		// 依頼元画面ID
		paramMap.put(JCMConstants.INVOKE_GAMEN_ID_KEY, param.getControlMapData(SCControlMapKeys.REQ_VIEWID));

		// オペレータID
		paramMap.put(JCMConstants.OPERATOR_ID_KEY, param.getControlMapData(SCControlMapKeys.OPERATOR_ID));

		String svcIf = (String)mappingData[0][1];

		CAANMsg template = new CAANMsg(String.format("eo.ejb.cbs.cbsmsg.%sCBSMsg", svcIf));

		// オペレータID
		template.set(JCMConstants.OPERATOR_ID_KEY, param.getControlMapData(SCControlMapKeys.OPERATOR_ID));

		// 運用日付
		template.set(JCMConstants.OPERATE_DATE_KEY, param.getControlMapData(SCControlMapKeys.OPE_DATE));

		// 運用日時
		template.set(JCMConstants.OPERATE_DATETIME_KEY, param.getControlMapData(SCControlMapKeys.OPE_TIME));

		for (int i = 0; i < mappingData.length; i++)
		{
			if ("".equals(mappingData[i][1]))
			{
				template.setNull((String)mappingData[i][0]);
			}
			else
			{
				template.set((String)mappingData[i][0], mappingData[i][1]);
			}
		}

		CAANMsg[] templates = new CAANMsg[1];

		templates[0] = template;

		paramMap.put(JCMConstants.TEMPLATE_LIST_KEY, templates);

		return paramMap;
	}

	/**
	 * エラー情報を取得します。
	 * 
	 * @param param リクエストパラメータ
	 * @param templates CAANMsgクラス
	 * @param returnCode リターンコード
	 * @param dataMapKey パラメータキー
	 * @param mappingData マッピングデータ
	 * @param contents CAANMsgのコンテンツ
	 * @return IRequestParameterReadWrite
	 * @throws RequestParameterException リクエストパラメータの操作でエラーが発生した場合
	 */
	@SuppressWarnings("unchecked")
	private IRequestParameterReadWrite editErrorInfoCom(IRequestParameterReadWrite param, CAANMsg[] templates, int returnCode, String dataMapKey, Object[][] mappingData, Object[][] contents)
			throws RequestParameterException
	{
		CAANMsg template = templates[0];

		int templateStatus = template.getInt(JCMConstants.STATUS_INT_KEY);

		if (0 != returnCode)
		{
			templateStatus = 9000;
		}

		if (null == JCMAPLConstMgr.getString("RETURN_MESSAGE_" + String.format("%1$04d", templateStatus)))
		{
			templateStatus = 0;
		}

		int bpStatus = 0;

		Object obj = param.getControlMapData(SCControlMapKeys.RETURN_CODE);

		if (null == obj)
		{
			bpStatus = -1;
		}
		else
		{
			bpStatus = Integer.parseInt((String)param.getControlMapData(SCControlMapKeys.RETURN_CODE));
		}

		if (templateStatus > bpStatus)
		{
			// BPにサービスコンポーネントのステータスを設定する。
			String formatStatus = String.format("%1$04d", templateStatus);

			String message = JCMAPLConstMgr.getString("RETURN_MESSAGE_" + formatStatus);

			param.setControlMapData(SCControlMapKeys.RETURN_CODE, formatStatus);

			param.setControlMapData(SCControlMapKeys.RETURN_MESSAGE, message);
		}

		Map<String, String> inMap = null;

		// ユーザデータ情報
		inMap = (Map<String, String>)param.getData(dataMapKey);

		for (int i = 0; null != contents && i < contents.length; i++)
		{
			String itemNm = (String)contents[i][0];
			if (itemNm.endsWith("_err"))
			{
				String errCd = template.getString(itemNm);
				if (!JFUBPCommon.isNull(errCd))
				{
					inMap.put(itemNm, errCd);
				}
			}
		}
		return param;
	}

	/**
	 * ビジネスログ出力メッセージ
	 *
	 * @param ccMsg
	 * @param msg
	 */
	private void outBusLog(Map<String, Object> ccMsg, String msg)
	{
		StringBuffer outBusLogMsg = new StringBuffer();
		outBusLogMsg.append("FUIFE168#JFUAgentUserPwdChgCC#funcCode(").append(ccMsg.get(REQ_KEY_FUNC_CODE)).append(")：id(").append(ccMsg.get(REQ_KEY_ID)).append(")：agencyCode2(").append(
				ccMsg.get(REQ_KEY_AGENCY_CODE2)).append(")：").append(msg);
		JSYejbLog.println(JSYLogBase.EXECUTION, this.getClass(), outBusLogMsg);
	}

}