package com.unionpay.acp.demo;

import com.unionpay.acp.sdk.*;
import com.unionpay.acp.sdk.*;
import org.apache.log4j.Logger;

import java.util.HashMap;
import java.util.Map;

/**
 * 银联加密公钥更新查询(只适用于使用RSA证书加密的方式<即signMethod=01>，其他signMethod=11，12密钥加密用不到此交易)
 * 商户定期（1天1次）向银联全渠道系统发起获取加密公钥信息交易.
 * 本交易成功后会自动替换配置文件acp_sdk.properties文件中acpsdk.encryptCert.path指定的文件，可用不用手工替换
 * 声明：以下代码只是为了方便商户测试而提供的样例代码，商户可以根据自己需要，按照技术文档编写。该代码仅供参考，不提供编码，性能，规范性等方面的保障<br>
 */

public class Form36_17_EncryptCerUpdQry {

    private static Logger logger = Logger.getLogger(Form36_17_EncryptCerUpdQry.class);

    public static void main(String[] args) {
        //加载classpath下的acp_sdk.properties文件内容
        SDKConfig.getConfig().loadPropertiesFromSrc();

        Map<String, String> contentData = new HashMap<String, String>();
        contentData.put("version", DemoBase.version);                             //版本号
        contentData.put("encoding", DemoBase.encoding);                     //字符集编码 可以使用UTF-8,GBK两种方式
        contentData.put("signMethod", SDKConfig.getConfig().getSignMethod());    //签名方法  01:RSA证书方式  11：支持散列方式验证SHA-256 12：支持散列方式验证SM3
        contentData.put("txnType", "95");                                         //交易类型 95-银联加密公钥更新查询
        contentData.put("txnSubType", "00");                                     //交易子类型  默认00
        contentData.put("bizType", "000000");                                     //业务类型  默认
        contentData.put("channelType", "07");                                     //渠道类型

        contentData.put("certType", "01");                                         //01：敏感信息加密公钥(只有01可用)
        contentData.put("accessType", SDKConfig.getValueFromConfig("accessType")); //接入类型，商户接入固定填0，不需修改
        contentData.put("merId", SDKConfig.getValueFromConfig("merId"));

        if ("1".equals(SDKConfig.getValueFromConfig("accessType"))) {
            contentData.put("acqInsCode", SDKConfig.getValueFromConfig("acqInsCode"));//接入类型为收单机构接入时需上送
            contentData.put("merCatCode", SDKConfig.getValueFromConfig("merCatCode"));//填写MCC码，接入类型为收单机构接入时需上送
            contentData.put("merName", SDKConfig.getValueFromConfig("merName"));//接入类型为收单机构接入时需上送
            contentData.put("merEnName", SDKConfig.getValueFromConfig("merEnName"));//接入类型为收单机构接入时需上送
            contentData.put("merAbbr", SDKConfig.getValueFromConfig("merAbbr"));//接入类型为收单机构接入时需上送
        }

        if ("2".equals(SDKConfig.getValueFromConfig("accessType"))) {
            //接入类型为平台类商户接入时需上送
            contentData.put("subMerId", SDKConfig.getValueFromConfig("subMerId"));//二级商户代码
            contentData.put("subMerName", SDKConfig.getValueFromConfig("subMerName"));//二级商户名称
            contentData.put("subMerAbbr", SDKConfig.getValueFromConfig("subMerAbbr")); //二级商户简称
        }

        contentData.put("reqReserved", SDKConfig.getValueFromConfig("reqReserved"));//可选上送
        contentData.put("reserved", SDKConfig.getValueFromConfig("reserved"));//可选上送
        contentData.put("orderId", DemoUtil.getOrderId()); // 商户订单号，8-40位数字字母，不能含“-”或“_”，可以自行定制规则,此处为演示方便默认取了个值
        contentData.put("txnTime", DemoUtil.getTxnTime()); // 订单发送时间，格式为YYYYMMDDhhmmss，必须取当前时间，否则会报txnTime无效,此处为演示方便默认取了个值

        //contentData.put("orderId", DemoBase.getOrderId());             			 //商户订单号，8-40位数字字母，不能含“-”或“_”，可以自行定制规则
        //contentData.put("txnTime", DemoBase.getCurrentTime());         		     //订单发送时间，格式为yyyyMMddHHmmss，必须取当前时间，否则会报txnTime无效                         //账号类型
        contentData.put("ctrlRule", SDKConfig.getValueFromConfig("ctrlRule"));

        Map<String, String> reqData = AcpService.sign(contentData, DemoBase.encoding);               //报文中certId,signature的值是在signData方法中获取并自动赋值的，只要证书配置正确即可。
        String requestBackUrl = SDKConfig.getConfig().getBackRequestUrl();                               //交易请求url从配置文件读取对应属性文件acp_sdk.properties中的 acpsdk.backTransUrl
        Map<String, String> rspData = AcpService.post(reqData, requestBackUrl, DemoBase.encoding);  //发送请求报文并接受同步应答（默认连接超时时间30秒，读取返回结果超时时间30秒）;这里调用signData之后，调用submitUrl之前不能对submitFromData中的键值对做任何修改，如果修改会导致验签不通过

        if (!rspData.isEmpty()) {
            if (AcpService.validate(rspData, DemoBase.encoding)) {
                logger.info("验证签名成功");
                String respCode = rspData.get("respCode");
                if (("00").equals(respCode)) {
                    int resultCode = AcpService.updateEncryptCert(rspData);
                    if (resultCode == 1) {
                        logger.info("加密公钥更新成功");
                    } else if (resultCode == 0) {
                        logger.info("加密公钥无更新");
                    } else {
                        logger.info("加密公钥更新失败");
                    }

                } else {
                    //其他应答码为失败请排查原因
                    //TODO
                }
            } else {
                logger.error("验证签名失败");
                //TODO 检查验证签名失败的原因
            }
        } else {
            //未返回正确的http状态
            logger.error("未获取到返回报文或返回http状态码非200");
        }
    }
}
