package com.qunzhixinxi.hnqz.admin.controller;

import cn.hutool.core.date.LocalDateTimeUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.qunzhixinxi.hnqz.admin.api.constant.CacheConstants;
import com.qunzhixinxi.hnqz.admin.api.entity.SysDept;
import com.qunzhixinxi.hnqz.admin.api.entity.SysSocialDetails;
import com.qunzhixinxi.hnqz.admin.api.entity.SysUser;
import com.qunzhixinxi.hnqz.admin.api.entity.UserAgreementSignatureRecord;
import com.qunzhixinxi.hnqz.admin.config.TaxNotifyConfig;
import com.qunzhixinxi.hnqz.admin.entity.SysCertResultRecord;
import com.qunzhixinxi.hnqz.admin.entity.SysDeptSub;
import com.qunzhixinxi.hnqz.admin.entity.WmDaAgent;
import com.qunzhixinxi.hnqz.admin.entity.WmDaDrugEnt;
import com.qunzhixinxi.hnqz.admin.entity.WmScorePackageSettleNote;
import com.qunzhixinxi.hnqz.admin.enums.SubjectTypeEnum;
import com.qunzhixinxi.hnqz.admin.mapper.SysCertResultRecordMapper;
import com.qunzhixinxi.hnqz.admin.mapper.SysSocialDetailsMapper;
import com.qunzhixinxi.hnqz.admin.mapper.UserAgreementSignatureRecordMapper;
import com.qunzhixinxi.hnqz.admin.service.*;
import com.qunzhixinxi.hnqz.admin.service.retry.PartyARetryService;
import com.qunzhixinxi.hnqz.common.core.constant.enums.LoginTypeEnum;
import com.qunzhixinxi.hnqz.common.core.util.R;
import com.qunzhixinxi.hnqz.common.log.annotation.SysLog;
import com.qunzhixinxi.hnqz.common.security.annotation.Inner;
import com.qunzhixinxi.hnqz.common.security.service.HnqzUser;
import com.qunzhixinxi.hnqz.common.security.util.SecurityUtils;
import com.qunzhixinxi.hnqz.common.taxhelper.common.CommonConstants;
import com.qunzhixinxi.hnqz.common.taxhelper.config.TaxHelperConfig;
import com.qunzhixinxi.hnqz.common.taxhelper.entity.model.TaxHelperAddMemberModel;
import com.qunzhixinxi.hnqz.common.taxhelper.entity.model.TaxHelperAppletBizTokenModel;
import com.qunzhixinxi.hnqz.common.taxhelper.entity.model.TaxHelperBindingCardConfirmModel;
import com.qunzhixinxi.hnqz.common.taxhelper.entity.model.TaxHelperBindingCardVerificationModel;
import com.qunzhixinxi.hnqz.common.taxhelper.entity.model.TaxHelperECheckModel;
import com.qunzhixinxi.hnqz.common.taxhelper.entity.model.TaxHelperEidTokenModel;
import com.qunzhixinxi.hnqz.common.taxhelper.entity.model.TaxHelperGetUserAgreementModel;
import com.qunzhixinxi.hnqz.common.taxhelper.entity.model.TaxHelperUserAgreementAuthorizationModel;
import com.qunzhixinxi.hnqz.common.taxhelper.entity.request.TaxHelperAddMemberRequest;
import com.qunzhixinxi.hnqz.common.taxhelper.entity.request.TaxHelperAppletBizTokenRequest;
import com.qunzhixinxi.hnqz.common.taxhelper.entity.request.TaxHelperBindingCardConfirmRequest;
import com.qunzhixinxi.hnqz.common.taxhelper.entity.request.TaxHelperBindingCardVerificationRequest;
import com.qunzhixinxi.hnqz.common.taxhelper.entity.request.TaxHelperECheckRequest;
import com.qunzhixinxi.hnqz.common.taxhelper.entity.request.TaxHelperEidTokenRequest;
import com.qunzhixinxi.hnqz.common.taxhelper.entity.request.TaxHelperGetUserAgreementRequest;
import com.qunzhixinxi.hnqz.common.taxhelper.entity.request.TaxHelperUserAgreementAuthorizationRequest;
import com.qunzhixinxi.hnqz.common.taxhelper.entity.response.TaxHelperResponse;
import com.qunzhixinxi.hnqz.common.taxhelper.entity.vo.TaxHelperAddMemberVo;
import com.qunzhixinxi.hnqz.common.taxhelper.entity.vo.TaxHelperBingCardConfirmVo;
import com.qunzhixinxi.hnqz.common.taxhelper.entity.vo.TaxHelperECheckFaceNotify;
import com.qunzhixinxi.hnqz.common.taxhelper.enums.TaxHelperCertStatus;
import com.qunzhixinxi.hnqz.common.taxhelper.service.TaxHelperService;
import jdk.nashorn.internal.parser.Token;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import java.time.LocalDateTime;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.TimeUnit;

/**
 * {@code WmTaxHelperController} 税邦云控制类
 *
 * @author Hengchen.Sun
 * @version 1.0.0
 * @date 2021-03-03
 * @since ver.1.0.0
 */
@Slf4j
@RestController
@AllArgsConstructor
@RequestMapping("/taxhelper")
public class WmTaxHelperController {

	private final SysUserService userService;
	private final SysDeptService deptService;
	private final TaxHelperService taxHelperService;
	private final RedisTemplate redisTemplate;
	private final SysSocialDetailsMapper sysSocialDetailsMapper;
	private final TaxNotifyConfig taxNotifyConfig;
	private final WmTaskSettleNoteService noteService;
	private final WmDaAgentService wmDaAgentService;
	private final WmDaDrugEntService wmDaDrugEntService;
	private final SysCertResultRecordMapper sysCertResultRecordMapper;
	private final WmScorePackageSettleNoteService settleNoteService;
	private final SysDeptSubService sysDeptSubService;
	private final PartyARetryService partyARetryService;
	private final UserAgreementSignatureRecordMapper userAgreementSignatureRecordMapper;


	/**
	 * 税邦云增员
	 *
	 * @param vo 税邦云增员vo
	 * @return 返回增员结果
	 */
	@SysLog(value = "税邦云增员")
	@PostMapping(value = "/addMember")
	public R taxHelperAddMember(@RequestBody TaxHelperAddMemberVo vo) {

		// 获取用户
		HnqzUser hnqzUser = SecurityUtils.getUser();
		SysUser user = userService.getById(hnqzUser.getId());

		SysDeptSub query = new SysDeptSub();
		query.setDeptId(user.getDeptId());
		query.setSubjectType(SubjectTypeEnum.TYPE_SHUIBANGYUN.getCode());
		query.setEnableFlag(SubjectTypeEnum.ENABLE_FLAG_TRUE.getCode());
		SysDeptSub deptSub = sysDeptSubService.getOne(Wrappers.query(query));

		// 处理用户认证类型
		if (!Objects.equals(TaxHelperCertStatus.UN_CERT.getCode(), user.getCertStatus())) {
			log.error("当前用户：{}-{}，不支持税邦云增员。", user.getRealname(), user.getUsername());
			return R.failed("用户状态不支持税邦云增员");
		}

		if (null != deptSub && StringUtils.isNotEmpty(deptSub.getAppId()) && StringUtils.isNotEmpty(deptSub.getSubjectUserType())) {
			TaxHelperConfig config = new TaxHelperConfig();
			config.setAppId(deptSub.getAppId());
			config.setAppSecrete(deptSub.getAppSecret());
			config.setQueryUrl(deptSub.getQueryUrl());
			TaxHelperAddMemberModel model = new TaxHelperAddMemberModel(config);
			model.setType(Integer.parseInt(deptSub.getSubjectUserType()));
			model.setIdCard(vo.getIdNumber());
			model.setPhone(user.getUsername());
			model.setName(user.getRealname());
			model.setNotifyUrl("http://localhost:8808");

			SysDept dept = deptService.getById(user.getDeptId());
			model.setEnterpriseCode(dept.getTaxCode());

			if (StringUtils.isEmpty(model.getEnterpriseCode())) {
				return R.failed("未配置企业的统一社会信用代码");
			}

			TaxHelperAddMemberRequest request = new TaxHelperAddMemberRequest(model);
			TaxHelperResponse response = taxHelperService.addMembers(request);

			// 记录认证结果
			SysCertResultRecord record = new SysCertResultRecord();
			record.setCode(response.getCode());
			record.setCreateTime(LocalDateTime.now());
			record.setDeptId(dept.getDeptId());
			record.setMessage(StringUtils.isNotEmpty(response.getMessage()) ? response.getMessage() : "无");
			record.setStatus(null);
			record.setSubjectType(1);
			record.setMethod("增员");
			record.setUserId(user.getUserId());
			sysCertResultRecordMapper.insert(record);

			if (response.success()) {
				// 更新用户
				SysUser tmp = new SysUser();
				tmp.setUserId(user.getUserId());
				tmp.setCertStatus(TaxHelperCertStatus.ADD_MEMBER.getCode());
				tmp.setIdCardNumber(vo.getIdNumber());
				tmp.setUpdateTime(LocalDateTime.now());
				userService.updateById(tmp);
				return R.ok(response.getMessage());
			} else {
				log.info("税邦云增员失败：{},{}，原因是：{}", user.getRealname(), user.getUsername(),
						response.getMessage());
				return R.failed(response.getMessage());
			}
		} else {
			log.error("当前结算主体：{}，信息不全。", deptSub.getSubjectName());
			return R.failed("当前结算主体信息不全，不能增员!");
		}
	}

	/**
	 * 回传用户协议授权信息
	 *
	 * @return 回传结果
	 */
	@SysLog(value = "税邦云回传用户协议授权信息")
	@PostMapping(value = "/agreement-signature")
	public R<?> userAgreementAuthorization() {
		HnqzUser hnqzUser = SecurityUtils.getUser();

		// 判断当前用户是否已经存在回调操作，避免同时多次回调
		String cacheKey = CacheConstants.TAX_HELPER_CHECK_FACE_NOTIFY_KEY + hnqzUser.getId();
		if (redisTemplate.hasKey(cacheKey)) {
			log.error("当前用户：{}，正在处理回调操作。", hnqzUser.getId());
			R.failed("系统正在处理，请稍后");
		} else {
			// 加锁
			redisTemplate.opsForValue().set(cacheKey, IdUtil.fastSimpleUUID(), 5, TimeUnit.SECONDS);
		}

		// 获取用户
		SysUser user = userService.getById(hnqzUser.getId());

		// 校验用户是否已经签署了信息
		if (user.getTaxHelperAgreementSignature() == 1) {
			return R.ok("已经签署");
		}

		// 获取结算主体
		SysDept dept = deptService.getById(user.getDeptId());

		SysDeptSub query = new SysDeptSub();
		query.setDeptId(user.getDeptId());
		query.setSubjectType(SubjectTypeEnum.TYPE_SHUIBANGYUN.getCode());
		query.setEnableFlag(SubjectTypeEnum.ENABLE_FLAG_TRUE.getCode());
		SysDeptSub deptSub = sysDeptSubService.getOne(Wrappers.query(query));
		if (null != deptSub && StringUtils.isNotEmpty(deptSub.getAppId())) {
			TaxHelperConfig config = new TaxHelperConfig();
			config.setAppId(deptSub.getAppId());
			config.setAppSecrete(deptSub.getAppSecret());
			config.setQueryUrl(deptSub.getQueryUrl());

			// 获取
			TaxHelperGetUserAgreementModel getUserAgreementModel = new TaxHelperGetUserAgreementModel(config);
			getUserAgreementModel.setEnterpriseCode(dept.getTaxCode());
			TaxHelperGetUserAgreementRequest getUserAgreementRequest = new TaxHelperGetUserAgreementRequest(getUserAgreementModel);
			TaxHelperResponse userAgreement = taxHelperService.getUserAgreement(getUserAgreementRequest);

			// 记录认证结果
			SysCertResultRecord record = new SysCertResultRecord();
			record.setCode(userAgreement.getCode());
			record.setCreateTime(LocalDateTime.now());
			record.setDeptId(dept.getDeptId());
			record.setMessage(StringUtils.isNotEmpty(userAgreement.getMessage()) ? userAgreement.getMessage() : "无");
			record.setStatus(null);
			record.setSubjectType(1);
			record.setMethod("税邦云用户协议");
			record.setUserId(user.getUserId());
			sysCertResultRecordMapper.insert(record);


			if (!userAgreement.success()) {
				return R.failed(userAgreement);
			}


			//
			TaxHelperUserAgreementAuthorizationModel model = new TaxHelperUserAgreementAuthorizationModel(config);
			model.setEnterpriseCode(dept.getTaxCode());
			LocalDateTime signTime = LocalDateTime.now();
			model.setAuthorizationTime(LocalDateTimeUtil.format(signTime, CommonConstants.DEFAULT_DATE_TIME_FORMAT_PATTERN));
			model.setIdCard(user.getIdCardNumber());

			TaxHelperUserAgreementAuthorizationRequest request = new TaxHelperUserAgreementAuthorizationRequest(model);
			TaxHelperResponse response = taxHelperService.userAgreementAuthorization(request);

			// 记录认证结果
			record.setCode(response.getCode());
			record.setCreateTime(LocalDateTime.now());
			record.setDeptId(dept.getDeptId());
			record.setMessage(StringUtils.isNotEmpty(response.getMessage()) ? response.getMessage() : "无");
			record.setStatus(null);
			record.setSubjectType(1);
			record.setMethod("税邦云回传用户协议授权信息");
			record.setUserId(user.getUserId());
			sysCertResultRecordMapper.insert(record);

			if (response.success()) {
				// 签署协议
				UserAgreementSignatureRecord uasr = new UserAgreementSignatureRecord();
				uasr.setAgreement(userAgreement.getData());
				uasr.setUserId(user.getUserId());
				uasr.setCreateTime(LocalDateTime.now());
				uasr.setTarget(1);
				uasr.setSignTime(signTime);
				userAgreementSignatureRecordMapper.insert(uasr);


				// 修改用户状态
				user.setUpdateTime(LocalDateTime.now());
				user.setTaxHelperAgreementSignature(1);
				userService.updateById(user);


				return R.ok(response);
			}
			return R.failed(response);
		}
		return R.failed("该结算主体信息不全，不支持税邦云操作");

	}

	/**
	 * 获取税邦云E证通认证token
	 *
	 * @return 返回获取结果
	 */
	@SysLog(value = "获取税邦云E证通认证token")
	@GetMapping(value = "/e-token")
	public R taxHelperECheckToken() {

		HnqzUser hnqzUser = SecurityUtils.getUser();
		// 判断当前用户是否已经存在回调操作，避免同时多次回调
		String cacheKey = CacheConstants.TAX_HELPER_CHECK_FACE_NOTIFY_KEY + hnqzUser.getId();
		if (redisTemplate.hasKey(cacheKey)) {
			log.error("当前用户：{}，正在处理回调操作。", hnqzUser.getId());
			R.failed("系统正在处理，请稍后");
		} else {
			// 加锁
			redisTemplate.opsForValue().set(cacheKey, IdUtil.fastSimpleUUID(), 3, TimeUnit.SECONDS);
		}

		// 获取用户
		SysUser user = userService.getById(hnqzUser.getId());
		// 获取结算主体
		SysDept dept = deptService.getById(user.getDeptId());

		SysDeptSub query = new SysDeptSub();
		query.setDeptId(user.getDeptId());
		query.setSubjectType(SubjectTypeEnum.TYPE_SHUIBANGYUN.getCode());
		query.setEnableFlag(SubjectTypeEnum.ENABLE_FLAG_TRUE.getCode());
		SysDeptSub deptSub = sysDeptSubService.getOne(Wrappers.query(query));
		if (null != deptSub && StringUtils.isNotEmpty(deptSub.getAppId())) {
			TaxHelperConfig config = new TaxHelperConfig();
			config.setAppId(deptSub.getAppId());
			config.setAppSecrete(deptSub.getAppSecret());
			config.setQueryUrl(deptSub.getQueryUrl());

			TaxHelperEidTokenModel model = new TaxHelperEidTokenModel(config);
			model.setIdCard(user.getIdCardNumber());

			TaxHelperEidTokenRequest request = new TaxHelperEidTokenRequest(model);
			TaxHelperResponse response = taxHelperService.getEidToken(request);

			// 记录认证结果
			SysCertResultRecord record = new SysCertResultRecord();
			record.setCode(response.getCode());
			record.setCreateTime(LocalDateTime.now());
			record.setDeptId(dept.getDeptId());
			record.setMessage(StringUtils.isNotEmpty(response.getMessage()) ? response.getMessage() : "无");
			record.setStatus(StringUtils.isNotEmpty(response.getData()) ? response.getData() : null);
			record.setSubjectType(1);
			record.setMethod("获取微信E证通TOKEN");
			record.setUserId(user.getUserId());
			sysCertResultRecordMapper.insert(record);

			if (response.success()) {
				// 修改用户状态
				user.setUpdateTime(LocalDateTime.now());
				if (Objects.equals(user.getCertStatus(), TaxHelperCertStatus.ADD_MEMBER.getCode())) {
					user.setCertStatus(TaxHelperCertStatus.CHECKING_UNBIND.getCode());
				} else if (Objects.equals(user.getCertStatus(), TaxHelperCertStatus.UNCHECKED_BIND.getCode())) {
					user.setCertStatus(TaxHelperCertStatus.CHECKING_BIND.getCode());
				}
				userService.updateById(user);
				log.error("获取e证通token为：{}", response.getMessage());
				return R.ok(response);
			} else {
				// 上次认证成功
				if (CommonConstants.LAST_STATUS_SUCCESS_CODE == Integer.parseInt(response.getData())) {
					// 修改用户状态
					user.setUpdateTime(LocalDateTime.now());
					if (Objects.equals(user.getCertStatus(), TaxHelperCertStatus.ADD_MEMBER.getCode())
							|| Objects.equals(user.getCertStatus(), TaxHelperCertStatus.CHECKING_UNBIND.getCode())) {
						user.setCertStatus(TaxHelperCertStatus.CHECKED_UNBIND.getCode());
					} else if (Objects.equals(user.getCertStatus(), TaxHelperCertStatus.UNCHECKED_BIND.getCode())
							|| Objects.equals(user.getCertStatus(), TaxHelperCertStatus.CHECKING_BIND.getCode())
					) {
						user.setCertStatus(TaxHelperCertStatus.CERT.getCode());
					}
					userService.updateById(user);
					log.warn("获取e证通token为：{}", response.getMessage());
					return R.ok(response);
				}

				log.error("获取e证通token失败：{}", response.getMessage());
				return R.failed(response);
			}
		}
		return R.failed("该结算主体信息不全，不支持税邦云操作");
	}

	/**
	 * E证通回调
	 *
	 * @return 回调结果
	 */
	@SysLog(value = "E证通回调")
	@GetMapping(value = "/e-check-result")
	public R taxHelperECheckFaceNotify(@RequestParam String eCheckToken) {

		HnqzUser hnqzUser = SecurityUtils.getUser();

		// 判断当前用户是否已经存在回调操作，避免同时多次回调
		String cacheKey = CacheConstants.TAX_HELPER_CHECK_FACE_NOTIFY_KEY + hnqzUser.getId();
		if (redisTemplate.hasKey(cacheKey)) {
			log.error("当前用户：{}，正在处理回调操作。", hnqzUser.getId());
			return R.failed("正在处理回调操作");
		} else {
			// 加锁
			redisTemplate.opsForValue().set(cacheKey, IdUtil.fastSimpleUUID(), 3, TimeUnit.SECONDS);
		}

		// 获取用户
		SysUser user = userService.getById(hnqzUser.getId());
		int certStatus = user.getCertStatus();

		// 判断是否认证成功
		if (Objects.equals(certStatus, TaxHelperCertStatus.CERT.getCode()) || Objects.equals(certStatus, TaxHelperCertStatus.CHECKED_UNBIND
				.getCode())) {
			log.info("当前用户：{}-{}，税邦云认证已成功。", user.getRealname(), user.getUsername());
			return R.failed("税邦云认证已成功");
		}

		SysDeptSub query = new SysDeptSub();
		query.setDeptId(user.getDeptId());
		query.setSubjectType(SubjectTypeEnum.TYPE_SHUIBANGYUN.getCode());
		query.setEnableFlag(SubjectTypeEnum.ENABLE_FLAG_TRUE.getCode());
		SysDeptSub deptSub = sysDeptSubService.getOne(Wrappers.query(query));
		if (null != deptSub && StringUtils.isNotEmpty(deptSub.getAppId())) {
			TaxHelperConfig config = new TaxHelperConfig();
			config.setAppId(deptSub.getAppId());
			config.setAppSecrete(deptSub.getAppSecret());
			config.setQueryUrl(deptSub.getQueryUrl());

			TaxHelperECheckModel model = new TaxHelperECheckModel(config);
			model.setToken(eCheckToken);

			TaxHelperECheckRequest request = new TaxHelperECheckRequest(model);
			TaxHelperResponse response = taxHelperService.getECheckFace(request);
			String message = response.getMessage();
			String status = response.getData();

			// 记录认证结果
			SysCertResultRecord record = new SysCertResultRecord();
			record.setCode(response.getCode());
			record.setCreateTime(LocalDateTime.now());
			record.setDeptId(user.getDeptId());
			record.setMessage(StringUtils.isNotEmpty(message) ? message + "(" + eCheckToken + ")" : eCheckToken);
			record.setStatus(response.getData());
			record.setSubjectType(1);
			record.setMethod("E证通认证状态查询");
			record.setUserId(user.getUserId());
			sysCertResultRecordMapper.insert(record);
			if (response.success()) {
				// 认证成功更新用户状态
				if ("1".equals(status)) {
					switch (certStatus) {
						case 11:
						case 14:
							certStatus = TaxHelperCertStatus.CHECKED_UNBIND.getCode();
							break;
						case 13:
						case 16:
							certStatus = TaxHelperCertStatus.CERT.getCode();
							break;
					}
				}

				// 认证失败
				if ("2".equals(status)) {
					log.error("当前用户：{}-{}，认证失败，原因：{}。", user.getRealname(), user.getUsername(), message);
					if (Objects.equals(user.getCertStatus(), TaxHelperCertStatus.CHECKING_UNBIND.getCode())) {
						certStatus = TaxHelperCertStatus.ADD_MEMBER.getCode();
					} else if (Objects.equals(user.getCertStatus(), TaxHelperCertStatus.CHECKING_BIND.getCode())) {
						certStatus = TaxHelperCertStatus.UNCHECKED_BIND.getCode();
					}
				}

				// 认证中
				if ("3".equals(status)) {
					log.error("当前用户：{}-{}，认证中...", user.getRealname(), user.getUsername());

				}

				user.setUpdateTime(LocalDateTime.now());
				user.setCertStatus(certStatus);
				userService.updateById(user);

				// 返回认证结果
				return R.ok(response);
			}
			return R.failed(response);
		}
		return R.failed("该结算主体信息不全，不支持税邦云操作");
	}


	/**
	 * 获取税邦云认证token
	 *
	 * @return 返回获取结果
	 */
	@SysLog(value = "获取税邦云认证token")
	@GetMapping(value = "/bizToken")
	public R taxHelperAppletBizToken() {

		HnqzUser hnqzUser = SecurityUtils.getUser();
		// 判断当前用户是否已经存在回调操作，避免同时多次回调
		String cacheKey = CacheConstants.TAX_HELPER_CHECK_FACE_NOTIFY_KEY + hnqzUser.getId();
		if (redisTemplate.hasKey(cacheKey)) {
			log.error("当前用户：{}，正在处理回调操作。", hnqzUser.getId());
			R.failed("系统正在处理，请稍后");
		} else {
			// 加锁
			redisTemplate.opsForValue().set(cacheKey, IdUtil.fastSimpleUUID(), 3, TimeUnit.SECONDS);
		}

		// 获取用户
		SysUser user = userService.getById(hnqzUser.getId());
		// 获取结算主体
		SysDept dept = deptService.getById(user.getDeptId());

		/**
		 * @Modify: start
		 * @Version: v2021.4.16
		 * @Author: ryz
		 * @Date: 2021/4/28
		 */
		SysDeptSub query = new SysDeptSub();
		query.setDeptId(user.getDeptId());
		query.setSubjectType(SubjectTypeEnum.TYPE_SHUIBANGYUN.getCode());
		query.setEnableFlag(SubjectTypeEnum.ENABLE_FLAG_TRUE.getCode());
		SysDeptSub deptSub = sysDeptSubService.getOne(Wrappers.query(query));
		if (null != deptSub && StringUtils.isNotEmpty(deptSub.getAppId())) {
			TaxHelperConfig config = new TaxHelperConfig();
			config.setAppId(deptSub.getAppId());
			config.setAppSecrete(deptSub.getAppSecret());
			config.setQueryUrl(deptSub.getQueryUrl());

			TaxHelperAppletBizTokenModel model = new TaxHelperAppletBizTokenModel(config);
			model.setIdCard(user.getIdCardNumber());
			model.setNotifyUrl(taxNotifyConfig.getNotifyUrl() + "/admin/taxhelper/" + user.getUserId() + "/v1/checkFaceNotify");

			TaxHelperAppletBizTokenRequest request = new TaxHelperAppletBizTokenRequest(model);
			TaxHelperResponse response = taxHelperService.getAppletBizToken(request);

			// 记录认证结果
			SysCertResultRecord record = new SysCertResultRecord();
			record.setCode(response.getCode());
			record.setCreateTime(LocalDateTime.now());
			record.setDeptId(dept.getDeptId());
			record.setMessage(StringUtils.isNotEmpty(response.getMessage()) ? response.getMessage() : "无");
			record.setStatus(null);
			record.setSubjectType(1);
			record.setMethod("获取小程序认证TOKEN");
			record.setUserId(user.getUserId());
			sysCertResultRecordMapper.insert(record);

			if (response.success()) {
				// 修改用户状态
				user.setUpdateTime(LocalDateTime.now());
				if (Objects.equals(user.getCertStatus(), TaxHelperCertStatus.ADD_MEMBER.getCode())) {
					user.setCertStatus(TaxHelperCertStatus.CHECKING_UNBIND.getCode());
				} else if (Objects.equals(user.getCertStatus(), TaxHelperCertStatus.UNCHECKED_BIND.getCode())) {
					user.setCertStatus(TaxHelperCertStatus.CHECKING_BIND.getCode());
				}
				userService.updateById(user);
				return R.ok(response.getMessage());
			} else {
				// 处理税邦云认证成功，但回调认证结果为失败，再次请求显示成
				if (StringUtils.equals(CommonConstants.ALREADY_CERT_SUCCESSFUL, response.getMessage())) {
					// 修改用户状态
					user.setUpdateTime(LocalDateTime.now());
					if (Objects.equals(user.getCertStatus(), TaxHelperCertStatus.ADD_MEMBER.getCode())) {
						user.setCertStatus(TaxHelperCertStatus.CHECKED_UNBIND.getCode());
					} else if (Objects.equals(user.getCertStatus(), TaxHelperCertStatus.UNCHECKED_BIND.getCode())) {
						user.setCertStatus(TaxHelperCertStatus.CERT.getCode());
					}
					userService.updateById(user);
					return R.ok("已认证成功");
				}
				return R.failed(response.getMessage());
			}
		}
		return R.failed("该结算主体信息不全，不支持税邦云操作");
	}

	/**
	 * 小程序认证回调
	 *
	 * @param userId 用户id
	 * @return 回调结果
	 */
	@Inner(value = false)
	@PostMapping(value = "/{user_id}/{version}/checkFaceNotify")
	public Integer taxHelperCheckFaceNotify(@PathVariable(value = "user_id") Integer userId,
											@PathVariable(value = "version") String version,
											@RequestBody String body) {

		// 判断当前用户是否已经存在回调操作，避免同时多次回调
		String cacheKey = CacheConstants.TAX_HELPER_CHECK_FACE_NOTIFY_KEY + userId;
		if (redisTemplate.hasKey(cacheKey)) {
			log.error("当前用户：{}，正在处理回调操作。", userId);
			return 4000;
		} else {
			// 加锁
			redisTemplate.opsForValue().set(cacheKey, IdUtil.fastSimpleUUID(), 3, TimeUnit.SECONDS);
		}

		// 获取用户
		SysUser user = userService.getById(userId);
		int certStatus = user.getCertStatus();

		// 判断是否认证成功
		if (Objects.equals(certStatus, TaxHelperCertStatus.CERT.getCode()) || Objects.equals(certStatus, TaxHelperCertStatus.CHECKED_UNBIND
				.getCode())) {
			log.info("当前用户：{}-{}，税邦云认证已成功。", user.getRealname(), user.getUsername());
			return 2000;
		}

		try {
			// 获取税邦云账号
			SysSocialDetails condition = new SysSocialDetails();
			condition.setType(LoginTypeEnum.TAX_HELPER.getType());
			SysSocialDetails socialDetails = sysSocialDetailsMapper.selectOne(new QueryWrapper<>(condition));
			String randomKey = socialDetails.getRandomKey();

			//解密回调信息
			String resInfo = taxHelperService.decryptResp(body, randomKey);

			// 判断结果
			JSONObject jsonObject = JSONUtil.parseObj(resInfo);
			String token = jsonObject.getStr("token");
			String message = jsonObject.getStr("message");
			int status = jsonObject.getInt("status");

			// 记录认证结果
			SysCertResultRecord record = new SysCertResultRecord();
			record.setCode(null);
			record.setCreateTime(LocalDateTime.now());
			record.setDeptId(user.getDeptId());
			record.setMessage(StringUtils.isNotEmpty(message) ? message + "(" + token + ")" : token);
			record.setStatus(status + "");
			record.setSubjectType(1);
			record.setMethod("认证回调");
			record.setUserId(user.getUserId());
			sysCertResultRecordMapper.insert(record);

			// 更新用户信息
			SysUser sysUser = new SysUser();
			sysUser.setUserId(userId);
			sysUser.setUpdateTime(LocalDateTime.now());

			// 认证成功更新用户状态
			if (status == 1) {
				switch (certStatus) {
					case 11:
					case 14:
						certStatus = TaxHelperCertStatus.CHECKED_UNBIND.getCode();
						break;
					case 13:
					case 16:
						certStatus = TaxHelperCertStatus.CERT.getCode();
						break;
				}
			}

			// 认证失败
			if (status == 2) {
				log.error("当前用户：{}-{}，认证失败，原因：{}。", user.getRealname(), user.getUsername(), message);
				if (Objects.equals(user.getCertStatus(), TaxHelperCertStatus.CHECKING_UNBIND.getCode())) {
					certStatus = TaxHelperCertStatus.ADD_MEMBER.getCode();
				} else if (Objects.equals(user.getCertStatus(), TaxHelperCertStatus.CHECKING_BIND.getCode())) {
					certStatus = TaxHelperCertStatus.UNCHECKED_BIND.getCode();
				}
			}

			// 认证中
			if (status == 3) {
				log.error("当前用户：{}-{}，认证中...", user.getRealname(), user.getUsername());
			}

			sysUser.setCertStatus(certStatus);
			userService.updateById(sysUser);

			//回调
			if ("v2".equals(version)) {
				Map<String, Object> params = new HashMap<>();
				params.put("mobile", user.getUsername());
				params.put("status", status);
				params.put("message", message);
				partyARetryService.doRetryableCertCallBack(params);
			}

		} catch (Exception e) {
			log.error("税邦云解密失败");
			return 4000;
		}

		return 2000;
	}

	/**
	 * 获取税邦云绑卡验证码
	 *
	 * @param payAccount 银行卡号
	 * @param phone      手机号
	 * @return 获取信息
	 */
	@SysLog(value = "获取税邦云绑卡验证码")
	@GetMapping(value = "/bindingCardVerification")
	public R bindingCardVerification(@RequestParam(value = "payAccount") String payAccount,
									 @RequestParam(value = "phone") String phone) {

		HnqzUser hnqzUser = SecurityUtils.getUser();
		SysUser user = userService.getById(hnqzUser.getId());
		// 获取结算主题
		SysDept dept = deptService.getById(user.getDeptId());
		/**
		 * @Modify: start
		 * @Version: v2021.4.16
		 * @Author: ryz
		 * @Date: 2021/4/28
		 */
		SysDeptSub query = new SysDeptSub();
		query.setDeptId(user.getDeptId());
		query.setSubjectType(SubjectTypeEnum.TYPE_SHUIBANGYUN.getCode());
		query.setEnableFlag(SubjectTypeEnum.ENABLE_FLAG_TRUE.getCode());
		SysDeptSub deptSub = sysDeptSubService.getOne(Wrappers.query(query));

		if (null != deptSub && StringUtils.isNotEmpty(deptSub.getAppId())) {
			TaxHelperConfig config = new TaxHelperConfig();
			config.setAppId(deptSub.getAppId());
			config.setAppSecrete(deptSub.getAppSecret());
			config.setQueryUrl(deptSub.getQueryUrl());

			TaxHelperBindingCardVerificationModel model = new TaxHelperBindingCardVerificationModel(config);
			model.setPayAccountPhone(phone);
			model.setPayAccount(payAccount);
			model.setIdCard(user.getIdCardNumber());
			TaxHelperBindingCardVerificationRequest request = new TaxHelperBindingCardVerificationRequest(model);
			TaxHelperResponse response = taxHelperService.bindingCardVerification(request);

			// 记录认证结果
			SysCertResultRecord record = new SysCertResultRecord();
			record.setCode(response.getCode());
			record.setCreateTime(LocalDateTime.now());
			record.setDeptId(dept.getDeptId());
			record.setMessage(StringUtils.isNotEmpty(response.getMessage()) ? response.getMessage() : "无");
			record.setStatus(null);
			record.setSubjectType(1);
			record.setMethod("获取绑卡验证码");
			record.setUserId(user.getUserId());
			sysCertResultRecordMapper.insert(record);

			if (response.success()) {
				return R.ok(response.getMessage());
			} else {
				return R.failed(response.getMessage());
			}
		}
		return R.failed("该结算主体信息不全，不支持税邦云操作");
	}

	/**
	 * 绑卡确认
	 *
	 * @param vo 绑卡确认vo
	 * @return 获取信息
	 */
	@SysLog(value = "绑卡确认")
	@PostMapping(value = "/bindingCardConfirm")
	public R bindingCardVerification(@RequestBody TaxHelperBingCardConfirmVo vo) {

		HnqzUser hnqzUser = SecurityUtils.getUser();

		// 判断当前用户是否已经存在回调操作，避免同时多次回调
		String cacheKey = CacheConstants.TAX_HELPER_CHECK_FACE_NOTIFY_KEY + hnqzUser.getId();
		if (redisTemplate.hasKey(cacheKey)) {
			log.error("当前用户：{}，正在处理回调操作。", hnqzUser.getId());
			R.failed("系统正在处理，请稍后");
		} else {
			// 加锁
			redisTemplate.opsForValue().set(cacheKey, IdUtil.fastSimpleUUID(), 3, TimeUnit.SECONDS);
		}

		SysUser user = userService.getById(hnqzUser.getId());

		// 校验用户状态
		if (!Objects.equals(user.getCertStatus(), TaxHelperCertStatus.ADD_MEMBER.getCode())
				&& !Objects.equals(user.getCertStatus(), TaxHelperCertStatus.CHECKED_UNBIND.getCode())
				&& !Objects.equals(user.getCertStatus(), TaxHelperCertStatus.CHECKING_UNBIND.getCode())) {
			return R.failed("当前用户状态不支持获取验证码");
		}

		// 获取结算主题
		SysDept dept = deptService.getById(user.getDeptId());
		/**
		 * @Modify: start
		 * @Version: v2021.4.16
		 * @Author: ryz
		 * @Date: 2021/4/28
		 */
		SysDeptSub query = new SysDeptSub();
		query.setDeptId(user.getDeptId());
		query.setSubjectType(SubjectTypeEnum.TYPE_SHUIBANGYUN.getCode());
		query.setEnableFlag(SubjectTypeEnum.ENABLE_FLAG_TRUE.getCode());
		SysDeptSub deptSub = sysDeptSubService.getOne(Wrappers.query(query));

		if (null != deptSub && StringUtils.isNotEmpty(deptSub.getAppId())) {
			TaxHelperConfig config = new TaxHelperConfig();
			config.setAppId(deptSub.getAppId());
			config.setAppSecrete(deptSub.getAppSecret());
			config.setQueryUrl(deptSub.getQueryUrl());

			TaxHelperBindingCardConfirmModel model = new TaxHelperBindingCardConfirmModel(config);
			model.setVerificationCode(vo.getVerificationCode());
			model.setPayAccount(vo.getPayAccount());
			model.setIdCard(user.getIdCardNumber());
//			model.setNotifyUrl("http://localhost:8808/notify");
			model.setNotifyUrl(taxNotifyConfig.getNotifyUrl());
			TaxHelperBindingCardConfirmRequest request = new TaxHelperBindingCardConfirmRequest(model);
			TaxHelperResponse response = taxHelperService.bindingCardConfirm(request);

			// 记录认证结果
			SysCertResultRecord record = new SysCertResultRecord();
			record.setCode(response.getCode());
			record.setCreateTime(LocalDateTime.now());
			record.setDeptId(dept.getDeptId());
			record.setMessage(StringUtils.isNotEmpty(response.getMessage()) ? response.getMessage() : "无");
			record.setStatus(null);
			record.setSubjectType(1);
			record.setMethod("确认绑卡");
			record.setUserId(user.getUserId());
			sysCertResultRecordMapper.insert(record);

			if (response.success()) {
				SysUser sysUser = new SysUser();
				sysUser.setBankCardNumber(vo.getPayAccount());
				sysUser.setUserId(user.getUserId());

				if (Objects.equals(user.getCertStatus(), TaxHelperCertStatus.ADD_MEMBER.getCode())) {
					sysUser.setCertStatus(TaxHelperCertStatus.UNCHECKED_BIND.getCode());
				} else if (Objects.equals(user.getCertStatus(), TaxHelperCertStatus.CHECKED_UNBIND.getCode())) {
					sysUser.setCertStatus(TaxHelperCertStatus.CERT.getCode());
				} else {
					sysUser.setCertStatus(TaxHelperCertStatus.CHECKING_BIND.getCode());
				}

				sysUser.setUpdateTime(LocalDateTime.now());
				userService.updateById(sysUser);
				return R.ok(response.getMessage());
			} else {
				log.info("税邦云绑卡失败：{},{}，原因是：{}", user.getRealname(), user.getUsername(), response.getMessage());
				return R.failed(response.getMessage());
			}
		}

		return R.failed("该结算主体信息不全，不支持税邦云操作");
	}

	/**
	 * 结算回调操作
	 *
	 * @param userId 用户id
	 * @param body   回调内容（加密）
	 * @return 回调结果
	 */
	@Inner(value = false)
	@PostMapping(value = "/{user_id}/settlementNotify")
	public String taxHelperSettlementNotify(@PathVariable(value = "user_id") String userId,
													   @RequestBody String body) {
		// 判断当前用户是否已经存在回调操作，避免多次回调
		String cacheKey = CacheConstants.TAX_HELPER_SETTLEMENT_NOTIFY_KEY + userId;
		boolean absent = redisTemplate.opsForValue().setIfAbsent(cacheKey, userId, 3, TimeUnit.SECONDS);

		if (!absent) {
			log.error("当前用户：{}，正在处理结算回调操作。", userId);
			return responseJson(4000,"结算通知回调重复");
		}

		try {
			// 获取税邦云账号
			SysSocialDetails condition = new SysSocialDetails();
			condition.setType(LoginTypeEnum.TAX_HELPER.getType());
			SysSocialDetails socialDetails = sysSocialDetailsMapper.selectOne(new QueryWrapper<>(condition));
			String randomKey = socialDetails.getRandomKey();

			//解密回调信息
			String resInfo = taxHelperService.decryptResp(body, randomKey);
			JSONObject jsonObject = JSONUtil.parseObj(resInfo);
			String code = jsonObject.getStr("code");
			String streamId = jsonObject.getStr("streamId");

			int settleStatus = 1;
			// 回调成功操作
			if (!"2000".equals(code)) {
				settleStatus = 2;
			}

			settleNoteService.settleNotify(streamId, settleStatus, true);


		} catch (Exception e) {
			log.error("税邦云解密失败");
		}
		return responseJson(2000,"结算通知回调成功");
	}


	/**
	 * 结算回调操作
	 *
	 * @param userId  用户id
	 * @param version 版本
	 * @param body    回调内容（加密）
	 * @return 回调结果
	 */
	@Inner(value = false)
	@PostMapping(value = "/{user_id}/{version}/settlementNotify")
	public String taxHelperSettlementNotifyV2(@PathVariable(value = "user_id") String userId,
											  @PathVariable(value = "version") String version,
											  @RequestBody String body) {

		// 判断当前用户是否已经存在回调操作，避免多次回调
		String cacheKey = CacheConstants.TAX_HELPER_SETTLEMENT_NOTIFY_KEY + userId;

		boolean absent = redisTemplate.opsForValue().setIfAbsent(cacheKey, userId, 3, TimeUnit.SECONDS);

		if (!absent) {
			log.error("当前用户：{}，正在处理结算回调操作。", userId);
			return responseJson(4000,"结算通知回调重复");
		}

		try {
			// 获取税邦云账号
			SysSocialDetails condition = new SysSocialDetails();
			condition.setType(LoginTypeEnum.TAX_HELPER.getType());
			SysSocialDetails socialDetails = sysSocialDetailsMapper.selectOne(new QueryWrapper<>(condition));
			String randomKey = socialDetails.getRandomKey();

			//解密回调信息
			String resInfo = taxHelperService.decryptResp(body, randomKey);
			JSONObject jsonObject = JSONUtil.parseObj(resInfo);
			String code = jsonObject.getStr("code");
			String streamId = jsonObject.getStr("streamId");

			int settleStatus = 1;
			// 回调成功操作
			if (!"2000".equals(code)) {
				settleStatus = 2;
			}

			R<?> r = settleNoteService.settleNotify(streamId, settleStatus, !userId.contains("|"));

			//回调
			if ("v2".equals(version)) {
				List<WmScorePackageSettleNote> noteList = (List<WmScorePackageSettleNote>) r.getData();
				partyARetryService.doRetryableSettleNoteCallBack(noteList);
			}


		} catch (Exception e) {
			log.error("税邦云解密失败");
		}

		return responseJson(2000,"结算通知回调成功");
	}

	/**
	 * 获取响应结果
	 *
	 * @param code    响应状态码
	 * @param message 响应信息
	 * @return 响应json字符串
	 */
	private String responseJson(Integer code, String message) {
		Map response = new HashMap(2);
		response.put("code", code);
		response.put("message", message);
		return JSONUtil.toJsonStr(response);
	}
}
