package com.unionpay.acp.demo.acp7Contract.back;

import com.unionpay.acp.demo.DemoUtil;
import com.unionpay.acp.sdk.Acp7Service;
import com.unionpay.acp.sdk.SDKConfig;
import com.unionpay.acp.sdk.SDKConstants;
import org.apache.log4j.Logger;
import org.json.JSONException;
import org.json.JSONObject;

import java.util.*;

/**
 * 营销活动列表查询
 * 声明：以下代码只是为了方便商户测试而提供的样例代码，商户可以根据自己需要，按照技术文档编写。该代码仅供参考，不提供编码，性能，规范性等方面的保障<br>
 * 更多问题请使用open网站查找，开放平台-帮助与支持-商户入网测试FAQ，https://open.unionpay.com/tjweb/support/faq/mchlist
 */
public class Demo10_11_DiscountListQuery_Back {

    private final static Logger logger = Logger.getLogger(Demo10_11_DiscountListQuery_Back.class);

    private String bizMethod;
    private String url;

    public Demo10_11_DiscountListQuery_Back(String bizMethod, String url){
        this.bizMethod = bizMethod;
        this.url = url;
    }

    public static void main(String [] s){
        Demo10_11_DiscountListQuery_Back demo = new Demo10_11_DiscountListQuery_Back("acp.discount.list.query", SDKConfig.getConfig().getV7TransUrl());
        Map<String, String> reqMap;
        Map<String, String> rspMap;

        Map<String, String> reqData = new TreeMap<String, String>();

        /***产品参数***/
        reqData.put("version", "7.0.1");                 //版本号
        reqData.put("signMethod", "RSA2");               //签名方法
        reqData.put("bizMethod", demo.bizMethod);        //交易类型

        /***商户接入参数***/
        reqData.put("appId", SDKConfig.getValueFromConfig("appId"));      //发送方系统索引号
        reqData.put("appType", SDKConfig.getValueFromConfig("appType"));  //01机构、02商户
        reqData.put("reqId", DemoUtil.getReqId());    //发送方流水号，可以自行定制规则

        /***业务参数***/
        Map<String, Object> bodyMap = new HashMap<String, Object>();
        //TODO 以下参数请按真实情况填写
        bodyMap.put("accessType", SDKConfig.getValueFromConfig("accessType")); //1机构，0商户
        bodyMap.put("acqInsCode", SDKConfig.getValueFromConfig("acqInsCode"));//收单机构代码,机构接入必填
        bodyMap.put("merId", SDKConfig.getValueFromConfig("merId")); //商户号，请修改为自己的商户号
        bodyMap.put("orderId", DemoUtil.getOrderId()); //商户订单号，8-32位数字字母，不能含“-”或“_”，可以自行定制规则，此处为演示方便默认取了个值
        bodyMap.put("txnTime", DemoUtil.getTxnTime());//订单发送时间，格式为yyyyMMddHHmmss，取北京时间，此处为演示方便默认取了个值
        bodyMap.put("reqReserved", SDKConfig.getValueFromConfig("reqReserved"));//请求方保留域:支付成功后在查询API和支付通知中原样返回，该字段主要用于商户携带订单的自定义数据
        bodyMap.put("txnAmt", SDKConfig.getValueFromConfig("txnAmt"));//请求方保留域:支付成功后在查询API和支付通知中原样返回，该字段主要用于商户携带订单的自定义数据
        bodyMap.put("currencyCode", SDKConfig.getValueFromConfig("currencyCode"));//交易币种
        bodyMap.put("transScene", SDKConfig.getValueFromConfig("transScene"));//交易场景


        if ("1".equals(SDKConfig.getValueFromConfig("accessType"))) {
            Map<String, Object> merInfo = new HashMap<>(); //接入类型为收单机构接入时需上送
            merInfo.put("merCatCode", SDKConfig.getValueFromConfig("merCatCode"));//商户类别,接入类型为收单机构接入时需上送，填写MCC码
            merInfo.put("merName", SDKConfig.getValueFromConfig("merName"));//商户名称
            merInfo.put("merAbbr", SDKConfig.getValueFromConfig("merAbbr")); //商户简称;
            bodyMap.put("merInfo", JSONObject.wrap(merInfo));//接入类型为收单机构接入时需上送
        }

        if ("2".equals(SDKConfig.getValueFromConfig("accessType"))) {
            Map<String, Object> subMerInfoMap = new HashMap<>(); //接入类型为平台类商户接入时需上送
            subMerInfoMap.put("subMerId", SDKConfig.getValueFromConfig("subMerId"));//二级商户代码
            subMerInfoMap.put("subMerName", SDKConfig.getValueFromConfig("subMerName"));//二级商户名称
            subMerInfoMap.put("subMerAbbr", SDKConfig.getValueFromConfig("subMerAbbr")); //二级商户简称
            bodyMap.put("subMerInfo", JSONObject.wrap(subMerInfoMap));//接入类型为平台商户接入接入时需上送
        }

        Map<String, Object> accountVerifyInfo = new HashMap<String, Object>();
        accountVerifyInfo.put("certifTp", SDKConfig.getValueFromConfig("certifTp"));       //证件类型
        accountVerifyInfo.put("certifId", SDKConfig.getValueFromConfig("certifId"));       //证件号
        accountVerifyInfo.put("customerNm", SDKConfig.getValueFromConfig("customerNm"));       //姓名
        accountVerifyInfo.put("smsCode", SDKConfig.getValueFromConfig("smsCode"));       //短信验证码
        accountVerifyInfo.put("accNo", SDKConfig.getValueFromConfig("accNo"));       //卡号
        accountVerifyInfo.put("phoneNo", SDKConfig.getValueFromConfig("phoneNo"));       //手机号
        accountVerifyInfo.put("expired", SDKConfig.getValueFromConfig("expired"));       //有效期
        accountVerifyInfo.put("cvn2", SDKConfig.getValueFromConfig("cvn2"));       //cvn2

        if ("1".equals(SDKConfig.getValueFromConfig("isEncrypt"))) {
            //入网配置加密时填写方式
            try {
                String key = DemoUtil.getRandomString(32);
                bodyMap.put("encryptData",
                        JSONObject.wrap(Acp7Service.rsaEnc(
                                Acp7Service.buildDataMap("accountVerifyInfo",
                                        Acp7Service.base64Encode(JSONObject.wrap(accountVerifyInfo).toString())),
                                key, SDKConstants.UTF_8_ENCODING)));
            } catch (Exception e) {
                e.printStackTrace();
            }
        } else {
            //入网配置不加密时填写方式
            bodyMap.put("accountVerifyInfo", Acp7Service.base64Encode(JSONObject.wrap(accountVerifyInfo).toString()));
        }

        // tokenInfo transScene=002时，必送
        Map<String, Object> tokenInfoMap = new HashMap<String, Object>();
        tokenInfoMap.put("trId", SDKConfig.getValueFromConfig("trId"));
        tokenInfoMap.put("tokenType", SDKConfig.getValueFromConfig("tokenType"));
        tokenInfoMap.put("token", SDKConfig.getValueFromConfig("token"));
        tokenInfoMap.put("tokenEnd", SDKConfig.getValueFromConfig("tokenEnd"));
        bodyMap.put("tokenInfo", JSONObject.wrap(tokenInfoMap));

        // 营销信息域	discountInfo
        Map<String, Object> discountInfo = new HashMap<>();

        // 单品信息	goodsDetail
        List<Map<String, Object>> goodsDetailList = new ArrayList<>();
        Map<String, Object> goodsDetail = new HashMap<String, Object>();
        goodsDetail.put("id", SDKConfig.getValueFromConfig("id"));
        goodsDetail.put("name", SDKConfig.getValueFromConfig("name"));
        goodsDetail.put("price", SDKConfig.getValueFromConfig("price"));
        goodsDetail.put("quantity", SDKConfig.getValueFromConfig("quantity"));
        goodsDetail.put("category", SDKConfig.getValueFromConfig("category"));
        goodsDetail.put("addnInfo", SDKConfig.getValueFromConfig("addnInfo"));
        goodsDetailList.add(goodsDetail);
        discountInfo.put("goodsDetail", goodsDetailList);

        discountInfo.put("discountId", SDKConfig.getValueFromConfig("discountId"));
        discountInfo.put("discountCode", SDKConfig.getValueFromConfig("discountCode"));
        discountInfo.put("productNum", SDKConfig.getValueFromConfig("productNum"));

        bodyMap.put("discountInfo", JSONObject.wrap(discountInfo)); //营销信息域

        bodyMap.put("maskedCardNo", SDKConfig.getValueFromConfig("maskedCardNo"));//掩码卡号

        // 商户控制信息域
        Map<String, Object> merCtrlInfoMap = new HashMap<String, Object>();
        merCtrlInfoMap.put("noPromotionFlag", SDKConfig.getValueFromConfig("noPromotionFlag"));
        bodyMap.put("merCtrlInfo", JSONObject.wrap(merCtrlInfoMap));

        reqData.put("body", JSONObject.wrap(bodyMap).toString());

        /**对请求参数进行签名并发送http post请求，接收同步应答报文**/
        reqMap = Acp7Service.sign(reqData);      //报文中sign,signId的值是在sign方法中获取并自动赋值的，只要证书配置正确即可。
        rspMap = Acp7Service.post(reqMap, demo.url);  //发送请求报文并接受同步应答（默认连接超时时间30秒，读取返回结果超时时间30秒）;这里调用sign之后，调用post之前不能对map中的键值对做任何修改，如果修改会导致验签不通过

        /***应答处理***/
        if(rspMap == null || rspMap.size() == 0) {
            logger.info("post失败，请看下日志文件。");
            return;
        }

        if(!Acp7Service.validate(rspMap)) {
            logger.info("验签失败");
            return;
        }

        Map<String, Object> rspBody;
        try {
            if(rspMap.containsKey("body")) {
                rspBody = DemoUtil.unwarpJson(new JSONObject(rspMap.get("body")));
                String code = (String) rspBody.get("code") ;
                if(!("0000000000").equals(code)){
                    String msg = (String) rspBody.get("msg");
                    StringBuffer stringBuffer = new StringBuffer();
                    stringBuffer.append("返回了失败应答：code=" + code + "，msg=" + msg);
                    String subMsg = (String) rspBody.get("subMsg");
                    String subCode = (String) rspBody.get("subCode");
                    if(subCode != null) {
                        stringBuffer.append("，subCode=" + subCode + "，subMsg=" + subMsg);
                    }
                    logger.info(stringBuffer.toString());
                    return;
                }
                if (rspBody.containsKey("encryptData")) {
                    Map<String, Object> encryptData = (Map<String, Object>) rspBody.get(SDKConstants.param_encryptData);
                    String decKey = (String) encryptData.get(SDKConstants.param_key);
                    String decData = (String) encryptData.get(SDKConstants.param_data);
                    try {
                        String decodeStr = Acp7Service.rsaDec(decData, decKey);
                        logger.info("解银联加密后的敏感信息的报文：" + decodeStr);
                    } catch (Exception e) {
                        logger.error(e);
                    }
                }

                return;
            }
        } catch (JSONException e) {
            logger.info("应答体解json失败。");//正常不会进这个逻辑
            return;
        }

    }

}
