package jp.co.sint.mpi;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.ServletException;

import java.text.SimpleDateFormat;
import java.util.Hashtable;
import java.util.Map;
import java.util.Date;
//import java.util.Iterator;
import java.io.IOException;

import java.util.TimeZone;

import jp.co.sint.beans.front.UICasher;
import jp.co.sint.config.SIConfig;

import org.apache.log4j.Logger;

/**
 * <p>Authコマンドを発行する.</p>
 *
 * @author SBI VeriTrans Co., Ltd.
 * @version 1.0, 2005/05 created.
 */

public final class McAuthServlet extends McController {
    protected Logger logger = null;
    private String msg = null;
    
    /**
    * <p>POST リクエストを処理するメソッド</p>
    *  @param request HttpServletRequest HTTPサーブレットリクエスト
    *  @param response HttpServletResponse HTTPサーブレットレスポンス
    */
    public void doPost(HttpServletRequest request,HttpServletResponse response) throws ServletException,IOException {
    String orderID = null;
    String  sAction = null;
    
    String accept = "";
    String userAgent = "";
    String acsUrl = "";
    String md= null;
    
    logger = LoggerFactory.getTraceLogger();
    // セッションを取得
    // logger.info("Session ID = " + session.getId()); // debug
    try {
        //Hashtable params = Util.getInstance().getQuery(request, getEncode());
        UICasher lCasherID = (UICasher) request.getSession().getAttribute(SIConfig.SISESSION_CASHER_NAME);
        
        logger.info("getQuery... done."); // debug
        TimeZone nowtime = TimeZone.getDefault();
        logger.info("Now time zone["+ nowtime + "]"); // debug
        
        // 支払ページからカード番号を取得
        final String cardNumber = lCasherID.getCardNo();
        logger.info("card no=************"); // debug
        // 支払ページからカード有効期限を取得
        final String cardExp = lCasherID.getCardExpired();
        logger.info("card exp=**/**"); // debug
        // 支払ページからカード金額を取得
        final String amount = lCasherID.getSumOfF();
        logger.info("amount="+ amount); // debug
        // ヘッダー情報取得(HTTP ACCEPT)
        accept = request.getHeader("Accept");
        logger.info("HTTP ACCEPT="+ accept); // debug
        // ヘッダー情報取得(HTTP USER AGENT)
        userAgent = request.getHeader("User-Agent");
        logger.info("USER AGENT =" + userAgent); // debug
        // 支払ページにマーチャント指定があれば取得
        //final String merchant_no = (String)params.get("merchant_specify");
        
        // カード番号と有効期限にてMDKに本人認証を要求する
        //*********     MDK のクラス呼び出し   *********//
        //System.setProperty("Jp.BuySmart.DddLib.directPath", "true");
        Jp.BuySmart.DddLib.Transaction dddtran = Jp.BuySmart.DddLib.TransactionFactory.createInstance();
        
        //***********************************************
        //        送信用パラメータマップ定義
        //***********************************************
        
        Map sendParams =  new Hashtable();
        // 初期値設定
        sendParams = Jp.BuySmart.DddLib.TransactionFactory.createRequest();
        logger.info("Auth initial parameta set ... done.  "); // debug
        // コマンド文字列追加
        sendParams.put(Jp.BuySmart.DddLib.Transaction.REQ_COMMAND, Jp.BuySmart.DddLib.Transaction.CMD_AUTH);
        logger.info("add  CMD stirngs to auth map data ... done.  "); // debug
        
        // ヘッダー情報追加 (HTTP ACCEPT)
        if (accept == null) {
            accept = "";
        }
        sendParams.put(Jp.BuySmart.DddLib.Transaction.REQ_TAG_A_HTTP_ACCEPT, accept);
        logger.info("add  Header info (ACCEPT) to auth map data ... done.  "); // debug
        // ヘッダー情報追加(HTTP USER AGENT)
        sendParams.put(Jp.BuySmart.DddLib.Transaction.REQ_TAG_A_HTTP_USER_AGENT, userAgent);
        logger.info("add  Header info (HTTP USER AGENT) to auth map data ... done.  "); // debug
        // カード番号追加
        sendParams.put(Jp.BuySmart.DddLib.Transaction.REQ_TAG_A_CARD_NUMBER, cardNumber);
        logger.info("add  card number to auth map data ... done.  "); // debug
        // カード有効期限追加
        sendParams.put(Jp.BuySmart.DddLib.Transaction.REQ_TAG_A_CARD_EXP, cardExp);
        logger.info("add  card exp to auth map data ... done.  "); // debug
        // 金額追加
        sendParams.put(Jp.BuySmart.DddLib.Transaction.REQ_TAG_A_AMOUNT, amount);
        logger.info("add  amount  to auth map data ... done.  "); // debug
        
        // MDKに送信する電文内容書き出し
        /*
        logger.info("****** Send AUTH Data to  MDK ******");
        Iterator itr = sendParams.keySet().iterator();
        while (itr.hasNext()) {
            String key = (String)itr.next();
            String value = (String)sendParams.get(key);
            //logger.info("key["+ key +"]=[" + value + "]");
        }
        */
        // 戻り値Map定義
        Map receiveParams = new Hashtable();
        
        // MDK本人認証要求
        receiveParams = dddtran.doTransaction(sendParams);
        
        // debug 受信した電文内容書き出し
        /*
        itr = receiveParams.keySet().iterator();
        logger.info("AUTH procces Data from MDK");
        while (itr.hasNext()) {
            String key = (String)itr.next();
            String value = (String)receiveParams.get(key);
            //logger.info("key["+ key +"]=[" + value + "]");
        }
        */
        
        // アクションコード取得
        sAction = (String)receiveParams.get(Jp.BuySmart.DddLib.Transaction.RES_TAG_ACTION_CODE);
        // トランザクション番号取得
        final String sTxnId = (String)receiveParams.get(Jp.BuySmart.DddLib.Transaction.RES_TAG_A_TXN_ID);
        // jspTemplate取得
        final String jspTemplate = getJspTemplate();
        
        // 本人認証許可の場合(アクションコードで処理判定)
        if (sAction.equals(AUTH_OK)) {
            //MDの作成
            Map  mdParam = new Hashtable();
            // トランザクション番号格納
            mdParam.put(Jp.BuySmart.DddLib.Transaction.RES_TAG_A_TXN_ID, sTxnId);
            // 金額格納
            mdParam.put(Jp.BuySmart.DddLib.Transaction.REQ_TAG_A_AMOUNT, amount);
            // お客様設定用項目(自由にカスタマイズしてご使用下さい)
            //mdParam.put("customize-key", "customize-param");
            
            // MD作成MDKコール
            // どのマーチャントが選ばれたかを次の処理に送ってないので、
            // MD作成前に初期状態のTransactionのインスタンスを取得する。
            dddtran = Jp.BuySmart.DddLib.TransactionFactory.createInstance();
            md = dddtran.createMerchantData(mdParam);
            //logger.info("create MD... done. MD = " + md); // debug
            
            // PAReqの作成
            final String pareq = (String)receiveParams.get(Jp.BuySmart.DddLib.Transaction.RES_TAG_A_PAREQ);
            //logger.info("pareq = [" + pareq + "]"); // debug
            // 転送先URL取得
            acsUrl = (String)receiveParams.get(Jp.BuySmart.DddLib.Transaction.RES_TAG_A_ACS_URL);
            //acsUrl = getValidURL();
            //logger.info("acsUrl = [" + acsUrl + "]"); // debug
            // termURL取得
            final String termUrl = getTermURL();
            
            // HTML作成
            // 本人認証画面を表示
            // カード番号書き込み
            request.setAttribute(Jp.BuySmart.DddLib.Transaction.REQ_TAG_A_CARD_NUMBER, cardNumber);
            logger.info("set card-number to Request Attribute... done."); // debug
            // カード名称
            request.setAttribute(Message.CARD_NAME, "DummyCard");
            logger.info("set card-name to Request Attribute... done."); // debug
            // カード有効期限書き込み
            request.setAttribute(Jp.BuySmart.DddLib.Transaction.REQ_TAG_A_CARD_EXP, cardExp);
            logger.info("set card-exp to Request Attribute... done."); // debug
            // 金額書き込み
            request.setAttribute(Jp.BuySmart.DddLib.Transaction.REQ_TAG_A_AMOUNT, amount);
            logger.info("set amount to Request Attribute... done."); // debug
            // 転送先URL（ダミーACS入力画面）書き込み
            request.setAttribute(ACTION, acsUrl);
            logger.info("set action to Request Attribute... done."); // debug
            // ACSサイトからの情報の転送先書き込み
            request.setAttribute(TERM_URL, termUrl);
            logger.info("set action to Request Attribute... done."); // debug
            // MD書き込み
            request.setAttribute(MD, md);
            logger.info("set MD to Request Attribute... done."); // debug
            // PAReq書き込み
            request.setAttribute(Jp.BuySmart.DddLib.Transaction.RES_TAG_A_PAREQ, pareq);
            logger.info("set PAReq to Request Attribute... done."); // debug
            
            dispatchTo(jspTemplate + "/auth_ok.jsp", request, response);
            logger.info(jspTemplate + "/auth_ok.jsp");
        }
        // 決済の場合
        else if ((sAction.equals(SETTLEMENT_PERMITION)) || (sAction.equals(SETTLEMENT_PERMITION_AUTH_MISS))) {
            // 3D情報の取り出し
            final String xMsgVersion = (String)receiveParams.get(Jp.BuySmart.DddLib.Transaction.RES_TAG_V_3D_MSG_VERSION);
            logger.info("Msg-Version-Number = " + xMsgVersion);
            final String xID = (String)receiveParams.get(Jp.BuySmart.DddLib.Transaction.RES_TAG_V_3D_XID);
            logger.info("XID = " + xID);
            final String xStatus = (String)receiveParams.get(Jp.BuySmart.DddLib.Transaction.RES_TAG_V_3D_XSTATUS);
            logger.info("XStatus = " + xStatus);
            final String xCavv = (String)receiveParams.get(Jp.BuySmart.DddLib.Transaction.RES_TAG_V_3D_CAVV);
            logger.info("CAVV = " + xCavv);
            final String xCavvAlgorithm = (String)receiveParams.get(Jp.BuySmart.DddLib.Transaction.RES_TAG_V_3D_CAVV_ALGORITHM);
            logger.info("CAVV-Algorithm = " + xCavvAlgorithm);
            final String xEci = (String)receiveParams.get(Jp.BuySmart.DddLib.Transaction.RES_TAG_V_3D_ECI);
            logger.info("ECI = " + xEci);
            
            // gen order-id
            SimpleDateFormat formatter = new SimpleDateFormat ("yyyyMMddHHmmss");
            Date date = new Date();
            orderID  = formatter.format(date);
            
            // 決済処理用リクエストパラメータ生成
            Hashtable data = new Hashtable();
            data.put(Message.ORDER_ID, orderID); // 取引 ID
            data.put(Message.CARD_NUMBER, cardNumber); // カード番号
            data.put(Message.CARD_EXP, cardExp); // 有効期限
            data.put(Message.AMOUNT, amount); // 金額
            
            // set 3-D Secure Parameters
            if (xEci != null) {
                // 3d-msg-version
                data.put(Message.MSG_VERSION, xMsgVersion);
                // 3d-xid
                data.put(Message.XID, xID);
                // 3d-xstatus
                data.put(Message.XSTATUS, xStatus);
                // 3d-cavv
                data.put(Message.CAVV, xCavv);
                // 3d-cavv-algorithm
                data.put(Message.CAVV_ALGORITHM, xCavvAlgorithm);
                // 3d-eci
                data.put(Message.ECI, xEci);
            }
            logger.info("***** Letter encode conversion has Begin *****"); // debug
            // 取引結果ページ表示
            String status = Jp.BuySmart.DddLib.Transaction.RES_TAG_MSTATUS;
            if (status.equals(Jp.BuySmart.DddLib.Transaction.RES_V_MSTATUS_SC)) { // 決済成功
                dispatchTo("/thanks?a="+SIConfig.SIACTION_REGIST, request, response);//受注確定
            }
            else { // 決済失敗
                // エラーページを表示
                request.setAttribute("errmsg", "決済エラーが発生しました。");
                dispatchTo("/casher?a="+SIConfig.SIACTION_CANCEL, request, response);
                return;
            }
        }
        
        // 3DGW利用不可の場合(action-code=190)
        else if (sAction.equals(AUTH_NG)) {
        // エラーページを表示
            msg = "エラーコード[" + (String)receiveParams.get(Jp.BuySmart.DddLib.Transaction.RES_TAG_ERR_CODE) + "]現在、 3DGWは利用不可です。" ;
            request.setAttribute("errmsg",msg);
            dispatchTo("/casher?a="+SIConfig.SIACTION_CANCEL, request, response);
            return;
        }
        // 本人認証結果が決済不可の場合
        else if (sAction.equals(SETTLEMENT_REFUSED)) {
            msg = "エラーコード[" + (String)receiveParams.get(Jp.BuySmart.DddLib.Transaction.RES_TAG_ERR_CODE) + "] 本人認証に失敗しました。決済不可です。";
            request.setAttribute("errmsg",    msg);
            dispatchTo("/casher?a="+SIConfig.SIACTION_CANCEL, request, response);
            return;
        }
        else if (sAction == null) {
            request.setAttribute("errmsg", "アクションコードがNULLです。");
            dispatchTo("/casher?a="+SIConfig.SIACTION_CANCEL, request, response);
            return;
        }
    }catch (Exception e) {
        logger.info("Unexpected Error Rised ",e); // debug
        // エラーページを表示する
        dispatchToError(e, request, response);
    }
    }
}
