package com.yifu.cloud.plus.v1.ekp.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.icbc.api.DefaultIcbcClient;
import com.icbc.api.IcbcApiException;
import com.icbc.api.IcbcConstants;
import com.icbc.api.UiIcbcClient;
import com.icbc.api.request.JftApiPayrollQueryDetailRequestV1;
import com.icbc.api.request.JftApiVendorSeparateAccountsBusinessOpenRequestV1;
import com.icbc.api.request.JftUiPayrollComfirmSubmitRequestV1;
import com.icbc.api.response.JftApiPayrollQueryDetailResponseV1;
import com.icbc.api.response.JftApiVendorSeparateAccountsBusinessOpenResponseV1;
import com.icbc.api.utils.IcbcSignature;
import com.icbc.api.utils.WebUtils;
import com.yifu.cloud.plus.v1.ekp.config.IcbcConfigProperties;
import com.yifu.cloud.plus.v1.ekp.entity.EkpSocialInfo;
import com.yifu.cloud.plus.v1.ekp.mapper.EkpSocialInfoMapper;
import com.yifu.cloud.plus.v1.ekp.service.IcbcTransactionFlowIssueService;
import com.yifu.cloud.plus.v1.yifu.common.core.util.Common;
import com.yifu.cloud.plus.v1.yifu.common.core.util.R;
import lombok.RequiredArgsConstructor;
import lombok.extern.log4j.Log4j2;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletRequest;
import java.io.FileInputStream;
import java.io.IOException;
import java.math.BigInteger;
import java.net.URLDecoder;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.text.SimpleDateFormat;
import java.util.Base64;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/**
 * 聚富通到账通知交易流水查询
 *
 * @author huyc
 * @date 2024-05-23 11:21:56
 */
@Log4j2
@Service
@RequiredArgsConstructor
@EnableConfigurationProperties(IcbcConfigProperties.class)
public class IcbcTransactionFlowIssueServiceImpl extends ServiceImpl<EkpSocialInfoMapper, EkpSocialInfo> implements IcbcTransactionFlowIssueService {

	@Autowired
	private IcbcConfigProperties icbcConfigProperties;

	//1、网关公钥
	private static final String APIGW_PUBLIC_KEY = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCMpjaWjngB4E3ATh+G1DVAmQnIpiPEFAEDqRfNGAVvvH35yDetqewKi0l7OEceTMN1C6NPym3zStvSoQayjYV+eIcZERkx31KhtFu9clZKgRTyPjdKMIth/wBtPKjL/5+PYalLdomM4ONthrPgnkN4x4R0+D4+EBpXo8gNiAFsNwIDAQAB";
	//2、appid
	private static final String APP_ID = "11000000000000028685";
	//3、密钥对认证方式，公钥在API平台登记，此处为私钥
	private static final String MY_PRIVATE_KEY = "MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCEZYrhm3dBp3PqlMc9fBBEE8Tp8M34Yy6Ucs3FV/VahsdHaLe0kEPugf1twbt/hD4hdIwzUj/ZtG2BhusRiMptdlWtNKcIgFxaaFaKANKrIodeQjv0jjZvK9ugoQxmiM4gF5SGX2a847zohv/6TvAYiB9AI3tdKQTbj6I3pwmuO3cfzgU5IwepeguE4fxqnh7C19MEq4vXv0yBq/f43zQ2HBMS+KRgokNLUBqoEOyfaKkPL9ot+zISPwENQOLqQMZ1hczp5tEB2FeZecdzrzjeXkzPSy1ZJmNyNuOl+WG85aoeDJTQ7hx/g6KFA6zU2VBGUR7q4pXdGRslpa6KYETBAgMBAAECggEALkfElXqf5G5hocWiJAcDNJjog5JunX4mITREY9CMbrmgXYDofpDTfkMoUL6hCUEz6sPv4lzE/xgIE3gTIcz8Xek4p9Q480rTfbLtVU5WVgY65aMnjCROOOxO2MaTLCB0VVmIzLP6mNrPBUVzo48GdLzYl7YPgJA/J3T9EpEsXB/iAdjiv/VH9vOIW6WUlQUSceyNznf1rfwMJvHt7zb56IJGZMq9G6C5SUeqWbqbvNi+nL8yeu8fM/O/ERZJQBDwMXbRAPvhhcbDwVzpg4BRc7AVv0SLzy6ZA2+zLJmDe9F9uXmG6QQ4ra8mDqLeugDP9blKUOEm8JLIh7nzvhpNhQKBgQDK4ZEz1zui6GQsxsnbm24EvparfniPqDBS/V29MDZysXDmG123R22RA//BWC3m5cY+3vg0ayCGaXRrc9/V+u+jmwVfsR6XCM6WM2IZVVFBUzqKMlTKsZ4n3V/6pqBHG8++GUab5W6p/7NYI22xx0ZFObEt4EkaaaP7RzY6AVrtCwKBgQCnD6P24uR6VHN84lhyZl+iJW6azTd26AhaJ768wSl5rqN6N4AV9cXeAUKylPgMPvy+2mjNX7He0Oitb7/lrKK93/olmDQoHpqj1yZum8VVPiyEKk6qCoYYoHEloLPJDPRs6yiBjrO8oghHRuyJErKRN6IZC3Rq/mrXuDwrZYS84wKBgFn9wDisigly56xs6PD+esij+ZVMXhHq2rSVKlVW42/wgVGwZdt8VX9ztKiAgqve1BbjNFmcAytb74YSOgFic5Wwl6uglx8LiwdY93ShQY+maVsPhEj8jFjGe2JlMscX8QgzkfxowrOpdlXsMSYgbG0ccBkXWZXbsh8tsUH9g+WNAoGAbQ5avOo0uF603Uts7ZFC0Lia0Vcx499oxGG5s8Js7tBAS6I7bRp5xokQHz/8BRKBL52oWJklpgy+N6oBnU7rFgRGaZBITABedqIWppHtac4ihUyQ+ZPRIfZqpmOXuaFJVmjUkm6zimpD+TOlaX3ZL88fdDX0E3xuBtBwBuxIkH0CgYEAlXyBbG2/fVV/PDUVCAA+aeWstojR1ncDhJmFnENSk5I/y3mh+d+u4ZG3hmVQZfR1EYM+n9wPQ2LxqNpGPA8o4JK/MSfVKun4lBwjkergHzxWJ5AMuYL1DPrOtMPEqrTqOHfVzSZGsz9cMK4tDWETKKFBOM/5oSdGGW3oYvzcS0M=";

	public R submitIcbcTransactionFlow() {
		//应用方加密串
		UiIcbcClient client = new UiIcbcClient(APP_ID, IcbcConstants.SIGN_TYPE_RSA2, MY_PRIVATE_KEY,
				IcbcConstants.CHARSET_UTF8);
		JftUiPayrollComfirmSubmitRequestV1 request = new JftUiPayrollComfirmSubmitRequestV1();
		request.setServiceUrl("https://gw.open.icbc.com.cn/ui/jft/ui/payroll/comfirmsubmit/V1");
		JftUiPayrollComfirmSubmitRequestV1.JjftUiPayrolComfirmSubmitRequestV1BizV1 bizContent =
				new JftUiPayrollComfirmSubmitRequestV1.JjftUiPayrolComfirmSubmitRequestV1BizV1();
		bizContent.setAppId(APP_ID);
		//HR系统名称
		bizContent.setAppName("HRO");
		//企业编号
		bizContent.setOutVendorId("020101190");
		//操作类型：1-受理 2-审核
		bizContent.setOprType("1");
		bizContent.setTotalAmt("2");
		bizContent.setTotalCount("2");
		bizContent.setAppSerialno("WX104");
		bizContent.setFileCheckSign("1");
		bizContent.setLocalFilepath("D:/icbcFile/020101190_WX104_0_20240909.xls");
		bizContent.setFileMdcode(getMdCode("D:/icbcFile/020101190_WX104_0_20240909.xls"));
		bizContent.setFileType("1");
		bizContent.setNotifyUrl(null);
		bizContent.setAppRemark("备注");
		JSONObject jsonObject = new JSONObject();
		jsonObject.put("key",request);

		request.setBizContent(bizContent);
		System.out.println("request: " + JSON.toJSONString(request));

		try {
			String result = client.buildPostForm(request);
			if (Common.isNotNull(result)) {
				return R.ok();
			}
		} catch (IcbcApiException e) {
			e.printStackTrace();
			return R.failed();
		}
		return R.ok();
	}

	public R selectIcbcTransactionFlowInfo() {

		//应用方加密串
		String AES_Key = "8jTKCqZ9035g+HRzpZQqZA==";
		DefaultIcbcClient client = new DefaultIcbcClient(APP_ID, IcbcConstants.SIGN_TYPE_RSA2,
				MY_PRIVATE_KEY, IcbcConstants.CHARSET_UTF8, IcbcConstants.FORMAT_JSON,
				APIGW_PUBLIC_KEY, IcbcConstants.ENCRYPT_TYPE_AES, AES_Key, null, null);
		JftApiPayrollQueryDetailRequestV1 request = new JftApiPayrollQueryDetailRequestV1();
		request.setServiceUrl("https://gw.open.icbc.com.cn/api/jft/api/payroll/querydetail/V1");
		JftApiPayrollQueryDetailRequestV1.JftApiPayrollQueryDetailRequestV1Biz bizContent = new
				JftApiPayrollQueryDetailRequestV1.JftApiPayrollQueryDetailRequestV1Biz();
		bizContent.setAppId(APP_ID);
		bizContent.setOutVendorId("020101190");
		bizContent.setType("2");
		//批次号，appSerialno为空时，必输
		bizContent.setAppBatserialno("WX04");
		//内部批次号，组成规则：批次号-顺序号，appBatserialno为空时必输
//		bizContent.setAppSerialno("WX04-1");
		bizContent.setStartId("0");
		bizContent.setEndId("10");
		request.setBizContent(bizContent);
		try {
			JftApiPayrollQueryDetailResponseV1 responseV1 = client.execute(request);
			if (Common.isNotNull(responseV1)) {
				return R.ok();
			}
		} catch (IcbcApiException e) {
			e.printStackTrace();
			return R.failed();
		}
		return R.ok();
	}

	public R businessOpen() {

		String apiUrl= "https://gw.open.icbc.com.cn/api/jft/api/vendor/separate/accounts/business/open/V1";
		String encryptKey = "u1NKBJOMzvkHFvGiKbsq3g==";
		//签名类型为RSA2时，需传入appid，私钥和网关公钥，签名类型使用定值IcbcConstants.SIGN_TYPE_RSA2，其他参数使用缺省值
		DefaultIcbcClient client = new DefaultIcbcClient(APP_ID,"RSA2", MY_PRIVATE_KEY,"UTF-8", "json",APIGW_PUBLIC_KEY,"AES",encryptKey, "", "");
		JftApiVendorSeparateAccountsBusinessOpenRequestV1 request = new JftApiVendorSeparateAccountsBusinessOpenRequestV1();
		//4、根据测试环境和生产环境替换相应ip和端口
		request.setServiceUrl(apiUrl);
		//5、请对照接口文档用bizContent.setxxx()方法对业务上送数据进行赋值
		JftApiVendorSeparateAccountsBusinessOpenRequestV1.JftApiVendorSeparateAccountsBusinessOpenRequestV1Biz bizContent = new JftApiVendorSeparateAccountsBusinessOpenRequestV1.JftApiVendorSeparateAccountsBusinessOpenRequestV1Biz();
		bizContent.setAppId(APP_ID);
		bizContent.setOutVendorId("0202407190000011934");
		bizContent.setOutVendorManagerId("0202407190000011934");
		bizContent.setOutUpperVendorId(APP_ID);
		bizContent.setVendorName("安徽皖信人力资源管理有限公司");
		bizContent.setBizType("01");
		bizContent.setOpenCardType("0");
		bizContent.setBusinessType("02");//开通业务类型
		bizContent.setSubBusinessType("03");//开通业务类型
		bizContent.setBusSwitch("1");//业务开通关闭标志，开通时传1  关闭时传0
		bizContent.setRegistType("1");//注册标识 1 注册+开通业务 2 仅维护业务
		bizContent.setUpperMcardNo("");
		bizContent.setEqfEnsurePhone("");
		request.setBizContent(bizContent);
		JftApiVendorSeparateAccountsBusinessOpenResponseV1 response;
		JSONObject jsonObject = new JSONObject();
		jsonObject.put("key",request);
		String a = jsonObject.toJSONString();
		try {
			response = (JftApiVendorSeparateAccountsBusinessOpenResponseV1)client.execute(request, System.currentTimeMillis()+"");
			if (response.isSuccess()) {
				//6、业务成功处理，请根据接口文档用response.getxxx()获取同步返回的业务数据
				System.out.println("ReturnCode:"+response.getReturnCode());
				System.out.println("response:" + response);
			} else {
				//失败
				System.out.println("ReturnCode:"+response.getReturnCode());
				System.out.println("ReturnMsg:"+response.getReturnMsg());
			}
		} catch (IcbcApiException e) {
			e.printStackTrace();
		}
		return R.ok();
	}

	public R asyncNotice(HttpServletRequest request) throws Exception {

		//验签
		String api = "/icbcIssue/notifyUrl";
		boolean verifyFlag = verifySignData(request, api);
		String returnJson;
		if (verifyFlag) {// 验签成功
			log.info("解密...");
			String bizContent = dencrypt(request);
			log.info("解密后参数:" + bizContent);// 进行自己的处理,此处默认处理成功，返回通知方成功,return_code=0
			String copReturnCode = "0";// 通知合作方接收成功的返回码，固定
			String copReturnMsg = "success";// 合作方的返回信息，固定
			returnJson = sign(request, copReturnCode, copReturnMsg);
			log.error("通知响应json结果：{}", returnJson);
			return R.ok(returnJson);
		} else {// 验签失败
			String copReturnCode = "-12345";
			String copReturnMsg = "icbc jft sign not pass.";
			returnJson = sign(request, copReturnCode, copReturnMsg);
			log.error("通知响应json结果：{}", returnJson);
			return R.failed(returnJson);
		}
	}

	public String getMdCode(String filePath) {

		FileInputStream in = null;
		byte[] buffer = new byte[1024];
		String mdCode;
		try {
			MessageDigest digest = MessageDigest.getInstance("SHA-256");
			in = new FileInputStream(filePath);
			int len;
			while ((len = in.read(buffer, 0, 1024)) != -1) {
				digest.update(buffer, 0, len);
			}
			BigInteger bigInt = new BigInteger(1, digest.digest());
			mdCode = bigInt.toString();
			return mdCode;
		} catch (NoSuchAlgorithmException noSuchExc) {
			mdCode = null;
		} catch (IOException exception) {
			exception.printStackTrace();
			return null;
		} finally {
			if (in != null) {
				try {
					in.close();
				} catch (IOException exc) {
					;
				}
			}
		}
		return mdCode;
	}

	/**
	 * 验签方法
	 *
	 * @param request
	 * @param path
	 * @return
	 * @throws Exception
	 */
	private boolean verifySignData(HttpServletRequest request, String path) throws Exception {
		// 网关公钥
		Map<String, String> params = new HashMap<>();
		String api = request.getParameter("api");
		String from = request.getParameter("from");
		String appId = request.getParameter("app_id");
		String charset = request.getParameter("charset");
		String format = request.getParameter("format");
		//String encrypt_type = request.getParameter("encrypt_type");
		String timestamp = request.getParameter("timestamp");
		String bizContent = request.getParameter("biz_content");
		String signType = request.getParameter("sign_type");
		String sign = request.getParameter("sign");
		params.put("from", from);
		params.put("api", api);
		params.put("app_id", appId);
		params.put("charset", charset);
		params.put("format", format);
		//params.put("encrypt_type", encrypt_type);
		params.put("timestamp", timestamp);
		params.put("biz_content", bizContent);
		params.put("sign_type", signType);// 目前上行网关签名暂时仅支持RSA
		//验证工行上行网关RSA签名
		String signStr = WebUtils.buildOrderedSignStr(path, params);
		log.error("验签入参，signStr：[[{}]], sign_type：[[{}]], APIGW_PUBLIC_KEY：[[{}]], charset：[[{}]], sign：[[{}]]",
				signStr, signType, APIGW_PUBLIC_KEY, sign);
		return IcbcSignature.verify(signStr, signType, APIGW_PUBLIC_KEY, charset, sign);

	}

	/**
	 * 解密
	 *
	 * @param request
	 * @return
	 * @throws IOException
	 */
	private String dencrypt(HttpServletRequest request) throws IOException {
		String bizContent = URLDecoder.decode(request.getParameter("biz_content"),"utf-8");
		// 解析请求数据map
		ObjectMapper mapper = new ObjectMapper();
		Map<String, String> transMap = mapper.readValue(bizContent, Map.class);
		// 获取报文密文信息
		String notifyData = transMap.get("notifyData");
		return new String(Base64.getDecoder().decode(notifyData));
	}

	/**
	 * 加签方法
	 *
	 * @param request
	 * @param copReturnCode
	 * @param copReturnMsg
	 * @return
	 * @throws Exception
	 */
	private String sign(HttpServletRequest request, String copReturnCode, String copReturnMsg) throws Exception {
		String msgId = new SimpleDateFormat("yyyyMMdd").format(new Date())
				+ new SimpleDateFormat("HHmmss").format(new Date());
		String responseBizContent = "{\"return_code\":\"" + copReturnCode + "\",\"return_msg\":\"" + copReturnMsg + "\""
				+ ",\"msg_id\":\"" + msgId + "\"}";
		String charset = request.getParameter("charset");// 调用过程使用的编码格式

		//商户对消息返回响应进行签名，签名方式需与在API平台登记APP的sign_type保持一致(目前基本都是RSA2)
		String signType = IcbcConstants.SIGN_TYPE_RSA2;
		String signStr = "\"response_biz_content\":" + responseBizContent + "," + "\"sign_type\":" + "\"" + signType
				+ "\"";
		String signParam = IcbcSignature.sign(signStr, signType, MY_PRIVATE_KEY, charset);
		String returnJson = "{\"response_biz_content\":" + responseBizContent + ",\"sign_type\":\"" + signType + "\""
				+ ",\"sign\":\"" + signParam + "\"}";
		return returnJson;
	}

}
