Sfoglia il codice sorgente

Merge branch 'feat-20230724-fujianqifu'

lixuesong 1 anno fa
parent
commit
434ffb265c
17 ha cambiato i file con 1737 aggiunte e 28 eliminazioni
  1. 11 0
      db/v2.0/230725.sql
  2. 10 0
      hnqz-upms/hnqz-upms-api/src/main/java/com/qunzhixinxi/hnqz/admin/api/constant/CacheConstants.java
  3. 136 0
      hnqz-upms/hnqz-upms-biz/src/main/java/com/qunzhixinxi/hnqz/admin/controller/GigThirdApiController.java
  4. 72 0
      hnqz-upms/hnqz-upms-biz/src/main/java/com/qunzhixinxi/hnqz/admin/entity/QifuInputRecord.java
  5. 10 0
      hnqz-upms/hnqz-upms-biz/src/main/java/com/qunzhixinxi/hnqz/admin/enums/GigTypeEnum.java
  6. 2 0
      hnqz-upms/hnqz-upms-biz/src/main/java/com/qunzhixinxi/hnqz/admin/enums/SubjectLocation.java
  7. 2 0
      hnqz-upms/hnqz-upms-biz/src/main/java/com/qunzhixinxi/hnqz/admin/enums/SubjectTypeEnum.java
  8. 19 0
      hnqz-upms/hnqz-upms-biz/src/main/java/com/qunzhixinxi/hnqz/admin/mapper/QifuInputRecordMapper.java
  9. 49 3
      hnqz-upms/hnqz-upms-biz/src/main/java/com/qunzhixinxi/hnqz/admin/mq/GigSignCertReceiver.java
  10. 16 0
      hnqz-upms/hnqz-upms-biz/src/main/java/com/qunzhixinxi/hnqz/admin/service/gig/GigThirdApiService.java
  11. 127 1
      hnqz-upms/hnqz-upms-biz/src/main/java/com/qunzhixinxi/hnqz/admin/service/gig/impl/GigThirdApiServiceImpl.java
  12. 12 11
      hnqz-upms/hnqz-upms-biz/src/main/java/com/qunzhixinxi/hnqz/admin/service/gig/impl/SysUserSignCertServiceImpl.java
  13. 2 0
      hnqz-upms/hnqz-upms-biz/src/main/java/com/qunzhixinxi/hnqz/admin/service/impl/SysUserServiceImpl.java
  14. 205 1
      hnqz-upms/hnqz-upms-biz/src/main/java/com/qunzhixinxi/hnqz/admin/service/impl/WmPayOffServiceImpl.java
  15. 424 12
      hnqz-upms/hnqz-upms-biz/src/main/java/com/qunzhixinxi/hnqz/admin/service/impl/WmScorePackageSettleNoteServiceImpl.java
  16. 637 0
      hnqz-upms/hnqz-upms-biz/src/main/java/com/qunzhixinxi/hnqz/admin/util/SaasApiDemoV2.java
  17. 3 0
      hnqz-upms/hnqz-upms-biz/src/main/resources/mapper/WmScorePackageMapper.xml

+ 11 - 0
db/v2.0/230725.sql

@@ -0,0 +1,11 @@
+create table qifu_input_record
+(
+    id           int auto_increment comment '主键id'
+        primary key,
+    req_type     varchar(20)                        not null comment '请求业务类型',
+    req_id       varchar(64)                        null comment '请求序号',
+    req_body     text                               null comment '请求body',
+    decrypt_body text                               null comment '解密后的body',
+    create_time  datetime default CURRENT_TIMESTAMP null comment '创建时间'
+)
+    comment '福建企赋回调异步通知记录';

+ 10 - 0
hnqz-upms/hnqz-upms-api/src/main/java/com/qunzhixinxi/hnqz/admin/api/constant/CacheConstants.java

@@ -137,6 +137,16 @@ public interface CacheConstants {
 	 */
 	String HUI_QI_YUN_NOTIFY_KEY = "HUI:QI:YUN:NOTIFY:KEY:";
 
+	/**
+	 * 福建企赋签约异步结果回调key
+	 */
+	String QI_FU_SIGN_NOTIFY_KEY = "ZHONG:YI:YUN:SIGN:NOTIFY:KEY:";
+
+	/**
+	 * 福建企赋结算异步结果回调key
+	 */
+	String QI_FU_SETTLE_NOTIFY_KEY = "ZHONG:YI:YUN:SETTLE:NOTIFY:KEY:";
+
 	/**
 	 * 众蚁云签约异步结果回调key
 	 */

+ 136 - 0
hnqz-upms/hnqz-upms-biz/src/main/java/com/qunzhixinxi/hnqz/admin/controller/GigThirdApiController.java

@@ -6,17 +6,20 @@ import cn.hutool.core.util.NumberUtil;
 import cn.hutool.core.util.StrUtil;
 import cn.hutool.json.JSONObject;
 import cn.hutool.json.JSONUtil;
+import com.alibaba.fastjson.JSON;
 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import com.qunzhixinxi.hnqz.admin.api.constant.CacheConstants;
 import com.qunzhixinxi.hnqz.admin.api.dto.OladingCommonRequest;
 import com.qunzhixinxi.hnqz.admin.entity.HuiqiyunInputRecord;
 import com.qunzhixinxi.hnqz.admin.entity.LingcaiaiInputRecord;
 import com.qunzhixinxi.hnqz.admin.entity.OladingInputRecord;
+import com.qunzhixinxi.hnqz.admin.entity.QifuInputRecord;
 import com.qunzhixinxi.hnqz.admin.entity.SysDeptSub;
 import com.qunzhixinxi.hnqz.admin.entity.XinbadaInputRecord;
 import com.qunzhixinxi.hnqz.admin.entity.ZhongyiyunInputRecord;
 import com.qunzhixinxi.hnqz.admin.entity.ZhongzhiInputRecord;
 import com.qunzhixinxi.hnqz.admin.enums.SubjectLocation;
+import com.qunzhixinxi.hnqz.admin.mapper.QifuInputRecordMapper;
 import com.qunzhixinxi.hnqz.admin.service.HuiqiyunInputRecordService;
 import com.qunzhixinxi.hnqz.admin.service.LingcaiaiInputRecordService;
 import com.qunzhixinxi.hnqz.admin.service.SysDeptSubService;
@@ -25,6 +28,7 @@ import com.qunzhixinxi.hnqz.admin.service.ZhongyiyunInputRecordService;
 import com.qunzhixinxi.hnqz.admin.service.ZhongzhiInputRecordService;
 import com.qunzhixinxi.hnqz.admin.service.gig.GigThirdApiService;
 import com.qunzhixinxi.hnqz.admin.service.gig.OladingInputRecordService;
+import com.qunzhixinxi.hnqz.admin.util.SaasApiDemoV2;
 import com.qunzhixinxi.hnqz.admin.util.ZhongyiyunUtils;
 import com.qunzhixinxi.hnqz.common.log.annotation.SysLog;
 import com.qunzhixinxi.hnqz.common.security.annotation.Inner;
@@ -73,10 +77,142 @@ public class GigThirdApiController {
 
 	private final ZhongzhiInputRecordService zhongzhiInputRecordService;
 
+	private final QifuInputRecordMapper qifuInputRecordMapper;
+
 	private final SysDeptSubService sysDeptSubService;
 
 	private final RedisTemplate redisTemplate;
 
+
+	/**
+	 * 福建企赋结算异步通知回调
+	 *
+	 * @param body
+	 * @param headers
+	 * @return
+	 */
+	@Inner(value = false)
+	@SysLog("福建企赋结算异步通知回调")
+	@PostMapping("/qifu/pay-notify")
+	public String qiFuSettleNotifyRequest(@RequestBody String body, @RequestHeader HttpHeaders headers) {
+		log.info("福建企赋结算请求方法参数:body={}, headers={}", body, headers);
+
+		// 请求body json
+		JSONObject bodyJson = JSONUtil.parseObj(body);
+
+		// 请求序号
+		String reqId = bodyJson.getStr("reqId");
+
+		String redisKey = String.format("%s_%s", CacheConstants.QI_FU_SETTLE_NOTIFY_KEY, reqId);
+		Boolean absent = redisTemplate.opsForValue().setIfAbsent(redisKey, reqId, 30, TimeUnit.MINUTES);
+		if (Boolean.FALSE.equals(absent)) {
+			log.warn("存在在途操作reqId={}", reqId);
+			return "fail";
+		}
+
+		String decryptDataStr = null;
+		com.alibaba.fastjson.JSONObject unPackMessage = null;
+		try {
+			// 查询deptSub获取desKey
+			SysDeptSub deptSub = sysDeptSubService.getOne(Wrappers.<SysDeptSub>lambdaQuery()
+					.eq(SysDeptSub::getEnableFlag, "1")
+					.eq(SysDeptSub::getSubjectLocation, SubjectLocation.QI_FU)
+					.last("limit 1"));
+			if (deptSub == null || StrUtil.isBlank(deptSub.getAppId())) {
+				log.warn("未配置福建企赋deptSub reqId={}", reqId);
+				return "fail";
+			}
+
+			String publicKey = deptSub.getRsaPublicKey();
+
+			// 验签/解密
+			unPackMessage =
+					SaasApiDemoV2.unPackMessage(JSON.parseObject(body), com.alibaba.fastjson.JSONObject.class, publicKey);
+			decryptDataStr = com.alibaba.fastjson.JSONObject.toJSONString(unPackMessage);
+		} catch (Exception e) {
+			log.error("福建企赋结算回调参数异常", e);
+			return "fail";
+		} finally {
+			// 请求记录到数据库
+			QifuInputRecord inputRecord = new QifuInputRecord();
+			inputRecord.setReqId(reqId);
+			inputRecord.setReqType(QifuInputRecord.ReqType.SETTLE_NOTIFY.getType());
+			inputRecord.setReqBody(body);
+			inputRecord.setDecryptBody(decryptDataStr);
+			qifuInputRecordMapper.insert(inputRecord);
+		}
+
+		// 业务处理
+		gigThirdApiService.qiFuSettleNotify(unPackMessage);
+
+		return "success";
+	}
+
+	/**
+	 * 福建企赋签约异步通知回调
+	 *
+	 * @param body
+	 * @param headers
+	 * @return
+	 */
+	@Inner(value = false)
+	@SysLog("福建企赋签约异步通知回调")
+	@PostMapping("/qifu/sign-notify")
+	public String qiFuSignNotifyRequest(@RequestBody String body, @RequestHeader HttpHeaders headers) {
+		log.info("福建企赋签约请求方法参数:body={}, headers={}", body, headers);
+
+		// 请求body json
+		JSONObject bodyJson = JSONUtil.parseObj(body);
+
+		// 请求序号
+		String reqId = bodyJson.getStr("reqId");
+		String data = bodyJson.getStr("data");
+
+		String redisKey = String.format("%s_%s", CacheConstants.QI_FU_SIGN_NOTIFY_KEY, reqId);
+		Boolean absent = redisTemplate.opsForValue().setIfAbsent(redisKey, reqId, 30, TimeUnit.MINUTES);
+		if (Boolean.FALSE.equals(absent)) {
+			log.warn("存在在途操作reqId={}", reqId);
+			return "fail";
+		}
+
+		String decryptDataStr = null;
+		com.alibaba.fastjson.JSONObject unPackMessage = null;
+		try {
+			// 查询deptSub获取desKey
+			SysDeptSub deptSub = sysDeptSubService.getOne(Wrappers.<SysDeptSub>lambdaQuery()
+					.eq(SysDeptSub::getEnableFlag, "1")
+					.eq(SysDeptSub::getSubjectLocation, SubjectLocation.QI_FU)
+					.last("limit 1"));
+			if (deptSub == null || StrUtil.isBlank(deptSub.getAppId())) {
+				log.warn("未配置福建企赋deptSub reqId={}", reqId);
+				return "fail";
+			}
+
+			String publicKey = deptSub.getRsaPublicKey();
+
+			// 验签/解密
+			unPackMessage =
+					SaasApiDemoV2.unPackMessage(JSON.parseObject(body), com.alibaba.fastjson.JSONObject.class, publicKey);
+			decryptDataStr = com.alibaba.fastjson.JSONObject.toJSONString(unPackMessage);
+		} catch (Exception e) {
+			log.error("福建企赋签约回调参数异常", e);
+			return "fail";
+		} finally {
+			// 请求记录到数据库
+			QifuInputRecord inputRecord = new QifuInputRecord();
+			inputRecord.setReqId(reqId);
+			inputRecord.setReqType(QifuInputRecord.ReqType.SIGN_NOTIFY.getType());
+			inputRecord.setReqBody(body);
+			inputRecord.setDecryptBody(decryptDataStr);
+			qifuInputRecordMapper.insert(inputRecord);
+		}
+
+		// 业务处理
+		gigThirdApiService.qiFuSignNotify(unPackMessage);
+
+		return "success";
+	}
+
 	/**
 	 * 中智回调异步通知记录
 	 *

+ 72 - 0
hnqz-upms/hnqz-upms-biz/src/main/java/com/qunzhixinxi/hnqz/admin/entity/QifuInputRecord.java

@@ -0,0 +1,72 @@
+package com.qunzhixinxi.hnqz.admin.entity;
+
+import com.baomidou.mybatisplus.annotation.EnumValue;
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import com.baomidou.mybatisplus.extension.activerecord.Model;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.Getter;
+
+import java.time.LocalDateTime;
+import java.util.Date;
+
+/**
+ * 福建企赋回调异步通知记录
+ * @TableName qifu_input_record
+ */
+@TableName(value ="qifu_input_record")
+@Data
+public class QifuInputRecord extends Model<QifuInputRecord> {
+	private static final long serialVersionUID = 1L;
+
+    /**
+     * 主键id
+     */
+    @TableId(type = IdType.AUTO)
+    private Integer id;
+
+    /**
+     * 请求业务类型
+     */
+    private String reqType;
+
+    /**
+     * 请求序号
+     */
+    private String reqId;
+
+    /**
+     * 请求body
+     */
+    private String reqBody;
+
+    /**
+     * 解密后的body
+     */
+    private String decryptBody;
+
+    /**
+     * 创建时间
+     */
+    private LocalDateTime createTime;
+
+    @Getter
+    @AllArgsConstructor
+    public enum ReqType {
+        SIGN_NOTIFY("SIGN_NOTIFY", "签约回调"),
+        SETTLE_NOTIFY("SETTLE_NOTIFY", "结算回调");
+
+        /**
+         * 请求类型
+         */
+        @EnumValue
+        private final String type;
+
+        /**
+         * 描述
+         */
+        private final String desc;
+    }
+}

+ 10 - 0
hnqz-upms/hnqz-upms-biz/src/main/java/com/qunzhixinxi/hnqz/admin/enums/GigTypeEnum.java

@@ -25,6 +25,8 @@ public enum GigTypeEnum {
 	HUI_QI_YUN(6, "汇企云", "汇企云", HuiQiYunCertStatus.class),
 	ZHONG_YI_YUN(7, "众蚁云", "众蚁云", ZhongYiYunCertStatus.class),
 	ZHONG_ZHI(8, "中智", "中智", ZhongZhiCertStatus.class),
+	QI_FU(9, "福建企赋", "福建企赋", ZhongYiYunCertStatus.class),
+	SHEN_ZHEN_REN_CAI(10, "深圳人才", "深圳人才", OladingCertStatus.class),
 
 	MAH_SETTLE(99, "MAH结算", "MAH结算", null);
 
@@ -66,6 +68,7 @@ public enum GigTypeEnum {
 				certStatusStr = YeeCertStatus.resolve(String.valueOf(certStatus)).name();
 				break;
 			case OLADING:
+			case SHEN_ZHEN_REN_CAI:
 				certStatusStr = OladingCertStatus.resolve(String.valueOf(certStatus)).name();
 				break;
 			case ZHENG_QI_ZHI_XING:
@@ -83,6 +86,9 @@ public enum GigTypeEnum {
 			case ZHONG_ZHI:
 				certStatusStr = ZhongZhiCertStatus.resolve(certStatus).name();
 				break;
+			case QI_FU:
+				certStatusStr = ZhongYiYunCertStatus.resolve(certStatus).name();
+				break;
 			default:
 		}
 
@@ -109,6 +115,7 @@ public enum GigTypeEnum {
 				certStatusStr = YeeCertStatus.resolve(String.valueOf(certStatus)).getMessage();
 				break;
 			case OLADING:
+			case SHEN_ZHEN_REN_CAI:
 				certStatusStr = OladingCertStatus.resolve(String.valueOf(certStatus)).getMessage();
 				break;
 			case ZHENG_QI_ZHI_XING:
@@ -126,6 +133,9 @@ public enum GigTypeEnum {
 			case ZHONG_ZHI:
 				certStatusStr = ZhongZhiCertStatus.resolve(certStatus).getMessage();
 				break;
+			case QI_FU:
+				certStatusStr = ZhongYiYunCertStatus.resolve(certStatus).getMessage();
+				break;
 			default:
 		}
 

+ 2 - 0
hnqz-upms/hnqz-upms-biz/src/main/java/com/qunzhixinxi/hnqz/admin/enums/SubjectLocation.java

@@ -48,6 +48,8 @@ public enum SubjectLocation {
 	// 中智
 	ZHONG_ZHI("ZHONG_ZHI", GigTypeEnum.ZHONG_ZHI, "中智", 12, "zhongzhi_invoice"),
 	ZHAO_YU("ZHAO_YU", GigTypeEnum.OLADING, "钉灵工-河南兆宇", 13, "olading_zhaoyu_invoice"),
+	QI_FU("QI_FU", GigTypeEnum.QI_FU, "福建企赋", 14, "qifu_invoice"),
+	SHEN_ZHEN_REN_CAI("SHEN_ZHEN_REN_CAI", GigTypeEnum.SHEN_ZHEN_REN_CAI, "深圳之光", 14, "shenzhenrencai_invoice"),
 
 
 	MAH_SETTLE("MAH_SETTLE", GigTypeEnum.MAH_SETTLE, "MAH结算", 99, "");

+ 2 - 0
hnqz-upms/hnqz-upms-biz/src/main/java/com/qunzhixinxi/hnqz/admin/enums/SubjectTypeEnum.java

@@ -19,6 +19,8 @@ public enum SubjectTypeEnum {
 	TYPE_HUI_QI_YUN("6", "汇企云"),
 	TYPE_ZHONG_YI_YUN("7", "众蚁云"),
 	TYPE_ZHONG_ZHI("8", "中智"),
+	TYPE_QI_FU("9", "福建企赋"),
+	TYPE_SHEN_ZHEN_REN_CAI("10", "深圳人才"),
 
 	ENABLE_FLAG_FALSE("0", "无效"),
 	ENABLE_FLAG_TRUE("1", "有效"),

+ 19 - 0
hnqz-upms/hnqz-upms-biz/src/main/java/com/qunzhixinxi/hnqz/admin/mapper/QifuInputRecordMapper.java

@@ -0,0 +1,19 @@
+package com.qunzhixinxi.hnqz.admin.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.qunzhixinxi.hnqz.admin.entity.QifuInputRecord;
+import org.apache.ibatis.annotations.Mapper;
+
+/**
+* @author lixuesong
+* @description 针对表【qifu_input_record(汇企云回调异步通知记录)】的数据库操作Mapper
+* @createDate 2022-12-09 13:02:08
+*/
+@Mapper
+public interface QifuInputRecordMapper extends BaseMapper<QifuInputRecord> {
+
+}
+
+
+
+

+ 49 - 3
hnqz-upms/hnqz-upms-biz/src/main/java/com/qunzhixinxi/hnqz/admin/mq/GigSignCertReceiver.java

@@ -18,7 +18,6 @@ import com.qunzhixinxi.hnqz.admin.enums.*;
 import com.qunzhixinxi.hnqz.admin.service.SysDeptService;
 import com.qunzhixinxi.hnqz.admin.service.SysUserService;
 import com.qunzhixinxi.hnqz.admin.service.SysUserSubService;
-import com.qunzhixinxi.hnqz.admin.service.gig.SysUserSignCertService;
 import com.qunzhixinxi.hnqz.common.rabbitmq.annotation.RabbitMqComponent;
 import com.qunzhixinxi.hnqz.common.rabbitmq.core.BaseRabbiMqHandler;
 import com.qunzhixinxi.hnqz.common.rabbitmq.listenter.MqListener;
@@ -55,8 +54,6 @@ public class GigSignCertReceiver extends BaseRabbiMqHandler<String> {
 
 	private final SysUserSubService sysUserSubService;
 
-	private final SysUserSignCertService sysUserSignCertService;
-
 	private final RedisTemplate redisTemplate;
 
 	/**
@@ -147,6 +144,12 @@ public class GigSignCertReceiver extends BaseRabbiMqHandler<String> {
 							case ZHONG_ZHI:
 								this.zhongZhiHandler(user, dept, subjectResult);
 								break;
+							case QI_FU:
+								this.qifuHandler(user, dept, subjectResult);
+								break;
+							case SHEN_ZHEN_REN_CAI:
+								this.oladingChannelHandler(user, dept, subjectResult, SubjectLocation.SHEN_ZHEN_REN_CAI);
+								break;
 							default:
 						}
 					});
@@ -163,6 +166,49 @@ public class GigSignCertReceiver extends BaseRabbiMqHandler<String> {
         });
     }
 
+	/**
+	 * 福建企赋结果处理
+	 *
+	 * @param user          用户
+	 * @param dept          部门
+	 * @param subjectResult 结果
+	 */
+	private void qifuHandler(SysUser user, SysDept dept, JSONObject subjectResult) {
+		String code = subjectResult.getStr("code");
+		String certStatus = subjectResult.getStr("certStatus");
+		LocalDateTime now = LocalDateTime.now();
+		ZhongYiYunCertStatus zhongYiYunCertStatus = Enum.valueOf(ZhongYiYunCertStatus.class, certStatus);
+
+		// 拼接更新条件
+		LambdaUpdateWrapper<SysUserSub> updateWrapper = Wrappers.<SysUserSub>lambdaUpdate()
+				.eq(SysUserSub::getUserId, user.getUserId())
+				.eq(SysUserSub::getDeptId, dept.getDeptId())
+				.eq(SysUserSub::getSubjectLocation, SubjectLocation.QI_FU)
+				.eq(SysUserSub::getGigType, GigTypeEnum.QI_FU)
+				.set(SysUserSub::getUpdateTime, now)
+				.set(SysUserSub::getUpdateUser, 0)
+				.set(SysUserSub::getCertRemark, JSONUtil.toJsonStr(subjectResult));
+
+		if (ZhongYiYunCertStatus.SIGN.equals(zhongYiYunCertStatus)) {
+			// 众蚁云已签约 即对应这里的已认证
+			updateWrapper.set(SysUserSub::getCertStatus, ZhongYiYunCertStatus.CERT.getCode());
+			updateWrapper.set(SysUserSub::getCallbackStatus, GigCallBackStatus.RETURNED);
+		} else {
+			updateWrapper.set(SysUserSub::getCertStatus, zhongYiYunCertStatus.getCode());
+		}
+
+		sysUserSubService.update(updateWrapper);
+
+		// 结果放到redis
+		Map<String, Map<String, String>> resultMap = new HashMap<>(1);
+		Map<String, String> subMap = new HashMap<>(1);
+		subMap.put("certStatus", certStatus);
+		resultMap.put(SubjectLocation.QI_FU.getType(), subMap);
+		String key = CacheConstants.USER_SIGN_CERT_RESPONSE_KEY + user.getUserId();
+		log.info("缓存认证结果到redis:{}", JSONUtil.toJsonStr(resultMap));
+		redisTemplate.opsForValue().set(key, JSONUtil.toJsonStr(resultMap), 1, TimeUnit.MINUTES);
+	}
+
 	/**
 	 * 众蚁云结果处理
 	 *

+ 16 - 0
hnqz-upms/hnqz-upms-biz/src/main/java/com/qunzhixinxi/hnqz/admin/service/gig/GigThirdApiService.java

@@ -14,6 +14,22 @@ import java.util.List;
  */
 public interface GigThirdApiService {
 
+	/**
+	 * 福建企赋结算回调业务处理
+	 *
+	 * @param bodyJson
+	 * @return
+	 */
+	boolean qiFuSettleNotify(com.alibaba.fastjson.JSONObject bodyJson);
+
+	/**
+	 * 福建企赋签约回调业务处理
+	 *
+	 * @param newBodyJson
+	 * @return
+	 */
+	boolean qiFuSignNotify(com.alibaba.fastjson.JSONObject newBodyJson);
+
 	/**
 	 * 中智结算回调业务处理
 	 *

+ 127 - 1
hnqz-upms/hnqz-upms-biz/src/main/java/com/qunzhixinxi/hnqz/admin/service/gig/impl/GigThirdApiServiceImpl.java

@@ -15,6 +15,7 @@ import com.qunzhixinxi.hnqz.admin.api.entity.SysUser;
 import com.qunzhixinxi.hnqz.admin.config.TaxNotifyConfig;
 import com.qunzhixinxi.hnqz.admin.config.UpmsConfig;
 import com.qunzhixinxi.hnqz.admin.entity.HuiqiyunInputRecord;
+import com.qunzhixinxi.hnqz.admin.entity.QifuInputRecord;
 import com.qunzhixinxi.hnqz.admin.entity.SysDeptSub;
 import com.qunzhixinxi.hnqz.admin.entity.SysUserSub;
 import com.qunzhixinxi.hnqz.admin.entity.WmScorePackage;
@@ -27,6 +28,7 @@ import com.qunzhixinxi.hnqz.admin.enums.SubjectLocation;
 import com.qunzhixinxi.hnqz.admin.enums.SubjectTypeEnum;
 import com.qunzhixinxi.hnqz.admin.enums.ZhongYiYunCertStatus;
 import com.qunzhixinxi.hnqz.admin.event.OladingFinishTaskEvent;
+import com.qunzhixinxi.hnqz.admin.mapper.QifuInputRecordMapper;
 import com.qunzhixinxi.hnqz.admin.service.HuiqiyunInputRecordService;
 import com.qunzhixinxi.hnqz.admin.service.SysDeptService;
 import com.qunzhixinxi.hnqz.admin.service.SysDeptSubService;
@@ -87,6 +89,130 @@ public class GigThirdApiServiceImpl implements GigThirdApiService {
 
 	private final HuiqiyunInputRecordService huiqiyunInputRecordService;
 
+	/**
+	 * 福建企赋结算回调业务处理
+	 *
+	 * @param bodyJson
+	 * @return
+	 */
+	@Override
+	public boolean qiFuSettleNotify(com.alibaba.fastjson.JSONObject bodyJson) {
+		String reqId = bodyJson.getString("reqId");
+		String state = bodyJson.getString("state");
+
+		// 根据orderNo查询结算单
+		List<WmScorePackageSettleNote> settleNoteList = scorePackageSettleNoteService.list(Wrappers.<WmScorePackageSettleNote>lambdaQuery()
+				.eq(WmScorePackageSettleNote::getStreamId, reqId));
+		if (CollUtil.isEmpty(settleNoteList)) {
+			log.warn("订单reqId={}对应结算单不存在", reqId);
+			return false;
+		}
+
+		WmScorePackageSettleNote tmp = settleNoteList.get(0);
+
+		int yaoyiStatus = 0;
+		// 	state取值:
+		// 	SETSUCC结算成功;
+		//	SETFAIL:结算失败;
+		//	TICREF:已退票
+		if ("SETSUCC".equals(state)) {
+			// 对应要易结算成功状态
+			yaoyiStatus = 1;
+		} else if ("SETFAIL".equals(state)) {
+			yaoyiStatus = 2;
+		} else {
+			log.warn("当前结算state不处理");
+			redisTemplate.delete(CacheConstants.SETTLE_PACKAGE_KEY + tmp.getId());
+			return false;
+		}
+
+		// 修改结算状态
+		final int finalYaoyiStatus = yaoyiStatus;
+		List<WmScorePackageSettleNote> updateList = settleNoteList.stream().map(note -> {
+			WmScorePackageSettleNote updateEntity = new WmScorePackageSettleNote();
+			updateEntity.setId(note.getId());
+			updateEntity.setSettleNoteStatus(finalYaoyiStatus);
+			if (finalYaoyiStatus == 1){
+				updateEntity.setNotifyTime(LocalDateTime.now());
+			}
+			updateEntity.setUpdateTime(LocalDateTime.now());
+			return updateEntity;
+		}).collect(Collectors.toList());
+
+		scorePackageSettleNoteService.updateBatchById(updateList);
+
+		WmScorePackage scorePackage = scorePackageService.getById(tmp.getPackageId());
+
+		// 遥领不修改
+		if (!"1611890566".equals(scorePackage.getSendPackageDeptId())) {
+			// 更新积分包状态
+			log.info("更新积分包状态:{}", tmp);
+			WmScorePackage wmScorePackage = new WmScorePackage();
+			wmScorePackage.setId(tmp.getPackageId());
+			wmScorePackage.setSettleStatus(yaoyiStatus);
+			wmScorePackage.setUpdateTime(LocalDateTime.now());
+			scorePackageService.updateById(wmScorePackage);
+		}
+
+		redisTemplate.delete(CacheConstants.SETTLE_PACKAGE_KEY + tmp.getId());
+
+		return true;
+	}
+
+	/**
+	 * 福建企赋签约回调业务处理
+	 *
+	 * @param newBodyJson
+	 * @return
+	 */
+	@Override
+	public boolean qiFuSignNotify(com.alibaba.fastjson.JSONObject newBodyJson) {
+
+		String idCard = newBodyJson.getString("idCard");
+		String mobile = newBodyJson.getString("mobile");
+		String name = newBodyJson.getString("name");
+		String state = newBodyJson.getString("state");
+		String resMsg = newBodyJson.getString("resMsg");
+
+		// 查询当前用户
+		SysUser sysUser = sysUserService.getOne(Wrappers.<SysUser>lambdaQuery()
+				.eq(SysUser::getRealname, name)
+				.eq(SysUser::getIdCardNumber, idCard)
+				.eq(SysUser::getUsername, mobile)
+				.eq(SysUser::getDelFlag, DelEnum.NOT_DEL.val()));
+		if (sysUser == null) {
+			log.warn("用户不存在name={},idCard={},mobile={}", name, idCard, mobile);
+			return false;
+		}
+
+		// 查询对应userSub数据
+		SysUserSub userSub = sysUserSubService.getOne(Wrappers.<SysUserSub>lambdaQuery()
+				.eq(SysUserSub::getUserId, sysUser.getUserId())
+				.eq(SysUserSub::getSubjectLocation, SubjectLocation.QI_FU));
+		if (userSub == null) {
+			log.warn("没有查到对应userSub数据 userId={}", sysUser.getUserId());
+			return false;
+		}
+
+		// 更新userSub
+		SysUserSub updateUserSub = new SysUserSub();
+		updateUserSub.setId(userSub.getId());
+		if ("SIGN".equals(state)) {
+			// 已签约对应要易已认证
+			updateUserSub.setCertStatus(ZhongYiYunCertStatus.CERT.getCode());
+		}
+		updateUserSub.setCertRemark(String.format("%s;%s", userSub.getCertRemark(), String.format("签约回调:%s;", resMsg)));
+		updateUserSub.setFailReason(String.format("签约回调:%s;", resMsg));
+		updateUserSub.setCallbackStatus(GigCallBackStatus.RETURNED);
+		LocalDateTime now = LocalDateTime.now();
+		updateUserSub.setUpdateTime(now);
+		updateUserSub.setCallbackTime(now);
+		updateUserSub.setUpdateUser(0);
+		sysUserSubService.updateById(updateUserSub);
+
+		return true;
+	}
+
 	/**
 	 * 中智结算回调业务处理
 	 *
@@ -1012,7 +1138,7 @@ public class GigThirdApiServiceImpl implements GigThirdApiService {
 			params.put("requestId", RandomStringUtils.randomAlphabetic(12));
 			params.put("endType", "CSO");
 			params.put("enterpriseCode", dept.getTaxCode());
-			params.put("subjectType", "OLADING");
+			params.put("subjectType", note.getSubjectLocation().getGigType().name());
 			params.put("channel", "DEFAULT");
 			params.put("subjectLocation", note.getSubjectLocation());
 			params.put("taskId", note.getThirdTaskId());

+ 12 - 11
hnqz-upms/hnqz-upms-biz/src/main/java/com/qunzhixinxi/hnqz/admin/service/gig/impl/SysUserSignCertServiceImpl.java

@@ -347,6 +347,7 @@ public class SysUserSignCertServiceImpl implements SysUserSignCertService {
 					return R.ok();
 				}
 			case OLADING:
+			case SHEN_ZHEN_REN_CAI:
 				// 自由职家
 				if (OladingCertStatus.SIGNED.getCode().equals(String.valueOf(userSub.getCertStatus()))
 						|| OladingCertStatus.SIGNING.getCode().equals(String.valueOf(userSub.getCertStatus()))
@@ -419,7 +420,7 @@ public class SysUserSignCertServiceImpl implements SysUserSignCertService {
 				this.updateUserCertStatus(userSub.getId(), "内部状态对其", LangChaoCertStatus.SIGN.getCode(), null);
 				return R.ok();
 			case HUI_QI_YUN:
-				// 浪潮
+				// 汇企云
 				if (userSub.getCertStatus() > HuiQiYunCertStatus.UN_SIGN.getCode()) {
 					return R.ok();
 				}
@@ -440,13 +441,12 @@ public class SysUserSignCertServiceImpl implements SysUserSignCertService {
 
 				this.updateUserCertStatus(userSub.getId(), "内部状态对其", ZhongZhiCertStatus.SIGN.getCode(), null);
 				return R.ok();
-//			case HAN_TANG:
-//				// 汉唐
-//				if (userSub.getCertStatus() > HanTangCertStatus.UN_SIGN.getCode()) {
-//					return R.ok();
-//				}
-//				this.updateUserCertStatus(userSub.getId(), "内部状态对其", HanTangCertStatus.SIGN.getCode(), null);
-//				return R.ok();
+			case QI_FU:
+				if (userSub.getCertStatus() > HuiQiYunCertStatus.UN_SIGN.getCode()) {
+					return R.ok();
+				}
+				this.updateUserCertStatus(userSub.getId(), "内部状态对其", ZhongYiYunCertStatus.SIGN.getCode(), null);
+				return R.ok();
 			default:
 				message = "不支持该税源地操作";
 		}
@@ -635,10 +635,11 @@ public class SysUserSignCertServiceImpl implements SysUserSignCertService {
 					return true;
 				} else if (GigTypeEnum.ZHONG_ZHI.equals(sysUserSub.getGigType())) {
 					return true;
+				} else if (GigTypeEnum.QI_FU.equals(sysUserSub.getGigType())) {
+					return true;
+				} else if (GigTypeEnum.SHEN_ZHEN_REN_CAI.equals(sysUserSub.getGigType())) {
+					return true;
 				}
-//				else if (GigTypeEnum.HAN_TANG.equals(sysUserSub.getGigType())) {
-//					return true;
-//				}
 				return false;
 			}).forEach(userSub -> {
 

+ 2 - 0
hnqz-upms/hnqz-upms-biz/src/main/java/com/qunzhixinxi/hnqz/admin/service/impl/SysUserServiceImpl.java

@@ -217,6 +217,8 @@ public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> impl
 				case HUI_QI_YUN:
 				case ZHONG_YI_YUN:
 				case ZHONG_ZHI:
+				case QI_FU:
+				case SHEN_ZHEN_REN_CAI:
 					if (!Objects.equals(userSub.getCertStatus(), DingEnum.CER_STATUS_1.getType())) {
 						throw new RuntimeException(user.getRealname() + "未认证,不能发起结算");
 					}

+ 205 - 1
hnqz-upms/hnqz-upms-biz/src/main/java/com/qunzhixinxi/hnqz/admin/service/impl/WmPayOffServiceImpl.java

@@ -629,6 +629,14 @@ public class WmPayOffServiceImpl extends ServiceImpl<WmPayOffMapper, WmPayOff> i
 		else if (SubjectTypeEnum.TYPE_ZHONG_ZHI.getCode().equals(subType)) {
 			return this.settleByZhongZhi(input, wmScorePackage, taxCode, operator);
 		}
+		// 福建企赋
+		else if (SubjectTypeEnum.TYPE_QI_FU.getCode().equals(subType)) {
+			return this.settleByQiFu(input, wmScorePackage, taxCode, operator);
+		}
+		// 深圳人才
+		else if (SubjectTypeEnum.TYPE_SHEN_ZHEN_REN_CAI.getCode().equals(subType)) {
+			return settleByOlading(input, wmScorePackage, taxCode, operator);
+		}
 		// 税邦云
 		else {
 			log.info("税邦云结算开始-获取会员所属企业的统一社会信用代码:{} ", taxCode);
@@ -637,6 +645,202 @@ public class WmPayOffServiceImpl extends ServiceImpl<WmPayOffMapper, WmPayOff> i
 
 	}
 
+	/**
+	 * 福建企赋结算操作
+	 *
+	 * @param input          结算数据
+	 * @param wmScorePackage 积分包
+	 * @param taxCode        税号
+	 * @param operator       操作员
+	 * @return 结果
+	 */
+	private R<?> settleByQiFu(WmScorePackageSettleInput input,
+								  WmScorePackage wmScorePackage,
+								  String taxCode,
+								  HnqzUser operator) {
+
+		List<WmScorePackageSettleNote> notes = input.getNotes();
+		StringBuilder noticeInfo = new StringBuilder();
+
+		// WmScorePackageSettleNote
+		for (WmScorePackageSettleNote note : notes) {
+			note.setInvoiceType(input.getInvoiceCategory());
+			note.setCategoryName(StrUtil.isNotBlank(input.getCategoryName()) ? input.getCategoryName() : note.getCategoryName());
+			note.setSubToGigTime(LocalDateTime.now());
+		}
+		noteService.updateBatchById(notes);
+
+
+		for (WmScorePackageSettleNote note : notes) {
+			SysUser sysUser = sysUserMapper.selectById(note.getUserId());
+
+			Integer deptId;
+			// MAH结算校验原企业认证信息
+			if (input.getMahSettleDeptId() != null) {
+				deptId = sysUser.getDeptId();
+			} else {
+				deptId = operator.getDeptId();
+			}
+
+			SysUserSub userSub = sysUserSubMapper.selectOne(Wrappers.<SysUserSub>lambdaQuery()
+					.eq(SysUserSub::getUserId, sysUser.getUserId())
+					.eq(SysUserSub::getSubjectLocation, input.getSubjectLocation())
+					.eq(SysUserSub::getDeptId, deptId)
+			);
+
+			if (userSub == null) {
+				log.info("结算对象-" + sysUser.getRealname() + ":认证信息不存在,不能结算");
+				return R.failed("结算对象-" + sysUser.getRealname() + ":认证信息不存在,不能结算");
+			}
+
+			if (!Objects.equals(userSub.getCertStatus(), DingEnum.CER_STATUS_1.getType())) {
+				return R.failed(sysUser.getRealname() + "人员未认证或未绑卡,不能结算");
+			}
+
+			if (Boolean.TRUE.equals(redisTemplate.hasKey(CacheConstants.SETTLE_PACKAGE_KEY + note.getId()))) {
+				return R.failed("结算对象-" + sysUser.getRealname() + ":正在结算,请勿重复结算");
+			}
+
+			if (DingEnum.NOTE_STATUS_SUCCESS.getType().equals(note.getSettleNoteStatus())) {
+				log.info("结算对象-" + sysUser.getRealname() + ":已结算,请勿重复结算");
+				return R.failed("结算对象-" + sysUser.getRealname() + ":已结算,请勿重复结算");
+			}
+			if (DingEnum.NOTE_STATUS_SUBMIT.getType().equals(note.getSettleNoteStatus())) {
+				log.info("结算对象-" + sysUser.getRealname() + ":已提交,请等待耐心结算结果");
+				return R.failed("结算对象-" + sysUser.getRealname() + ":已提交,请等待耐心结算结果");
+			}
+		}
+
+		for (WmScorePackageSettleNote note : notes) {
+			// 加锁
+			redisTemplate.opsForValue().set(CacheConstants.SETTLE_PACKAGE_KEY + note.getId(),
+					note.getId(), CacheConstants.SETTLE_TIME, TimeUnit.DAYS);
+
+			SysUser sysUser = sysUserMapper.selectById(note.getUserId());
+
+			try {
+
+				// 获取请求token
+				String url = String.format(GIG_TOKEN_URL, upmsConfig.getGigServiceUrl());
+				log.info("远端请求gig-token:{}", url);
+				ResponseEntity<String> tokenResult = new RestTemplate().getForEntity(url, String.class,
+						String.valueOf(operator.getDeptId()), "settle", String.valueOf(operator.getId()));
+				log.warn("获取结算token:{}", tokenResult.getBody());
+				if (!JSONUtil.isJson(tokenResult.getBody())) {
+					return R.failed("获取结算token失败");
+				}
+
+				JSONObject jsonObject = JSONUtil.parseObj(tokenResult.getBody());
+
+				if (jsonObject.getInt("code") != 0 || StrUtil.isBlank(jsonObject.getStr("data"))) {
+					return R.failed("获取结算token失败");
+				}
+
+				String token = jsonObject.getStr("data");
+
+				// 间隔100毫秒
+				Thread.sleep(100);
+
+				// 封装结算参数
+				Map<String, Object> params = new HashMap<>();
+				params.put("token", token);
+				params.put("tenantId", operator.getDeptId());
+				params.put("operatorId", operator.getId());
+				params.put("requestId", RandomStringUtils.randomAlphabetic(12));
+				params.put("taskName", wmScorePackage.getScorePackageName() + "_" + System.currentTimeMillis());
+				params.put("amount", String.valueOf(note.getSettleAmount().doubleValue()));
+				params.put("taskStartTime", wmScorePackage.getCreateTime().toLocalDate());
+				params.put("taskEndTime", wmScorePackage.getUpdateTime().toLocalDate());
+				params.put("taskLocation", "要易云");
+				params.put("username", sysUser.getBankPhone());
+				params.put("idCard", sysUser.getIdCardNumber());
+				params.put("idCardType","ID_CARD");
+				params.put("realName", sysUser.getRealname());
+				params.put("bankCard", sysUser.getBankCardNumber());
+				params.put("bankPhone", sysUser.getBankPhone());
+				// 市场推广
+				params.put("tagId", upmsConfig.getTagId());
+				params.put("taskInvoiceContent", note.getCategoryName());
+				params.put("endType", "CSO");
+				params.put("enterpriseCode", taxCode);
+				params.put("subjectType", "QI_FU");
+				params.put("channel", "DEFAULT");
+				params.put("subjectLocation", input.getSubjectLocation().getType());
+				params.put("taxMode", "SPECIAL");
+				params.put("transactionModel", "CHANNEL");
+				params.put("taskDescription", "根据要求,执行、并完成学术推广活动,并以在线平台工具采集、记录活动内容");
+
+				// 发起结算
+				String url1 = String.format(GIG_SETTLE_URL, upmsConfig.getGigServiceUrl());
+				log.info("远端请求gig-settle:{}", url);
+				HttpHeaders headers = new HttpHeaders();
+				headers.setContentType(MediaType.APPLICATION_JSON);
+				log.info("福建企赋结算req: {}", params);
+				HttpEntity<String> result = new RestTemplate().exchange(url1, HttpMethod.POST, new HttpEntity<>(params, headers), String.class);
+				log.info("福建企赋结算resp:{}", result.getBody());
+				if (!JSONUtil.isJson(result.getBody())) {
+					return R.failed("结算失败");
+				}
+
+				JSONObject settleObj = JSONUtil.parseObj(result.getBody());
+
+
+				if (Objects.equals(settleObj.getInt("code"), CommonConstants.SUCCESS)) {
+					JSONObject dataJsonObj = settleObj.getJSONObject("data");
+					log.info("福建企赋结算提交成功: {}", settleObj.getStr("data"));
+					note.setUpdateTime(LocalDateTime.now());
+					//streamId 获取不到
+					if (dataJsonObj != null) {
+						String requestId = dataJsonObj.getStr("requestId");
+						if (StrUtil.isNotBlank(requestId)) {
+							note.setSettleNoteStatus(DingEnum.NOTE_STATUS_SUBMIT.getType());
+							// 新增字段streamId
+							note.setStreamId(requestId);
+							noticeInfo.append(sysUser.getRealname()).append(":提交结算成功;");
+						} else {
+							note.setSettleNoteStatus(DingEnum.NOTE_STATUS_FAIL.getType());
+							noticeInfo.append(sysUser.getRealname()).append(":" + dataJsonObj.getStr("message"));
+							redisTemplate.delete(CacheConstants.SETTLE_PACKAGE_KEY + note.getId());
+						}
+					} else {
+						log.warn("福建企赋结算提交成功 data 获取不到: {}", note.getSettleNo());
+						noticeInfo.append(sysUser.getRealname()).append(":提交结算成功,业务流水号获取不到,请联系管理员;");
+						redisTemplate.delete(CacheConstants.SETTLE_PACKAGE_KEY + note.getId());
+					}
+				} else {
+					log.warn("福建企赋结算失败: {}", note.getSettleNo());
+					note.setUpdateTime(LocalDateTime.now());
+					note.setSettleNoteStatus(DingEnum.NOTE_STATUS_FAIL.getType());
+					noticeInfo.append(sysUser.getRealname()).append(":结算提交失败-").append(settleObj.getStr("msg")).append(";");
+
+					log.info("认证状态异常,结算解锁settleNoteId:{}", note.getId());
+					redisTemplate.delete(CacheConstants.SETTLE_PACKAGE_KEY + note.getId());
+
+				}
+			} catch (Exception e) {
+				log.error("", e);
+				log.warn("福建企赋结算提交失败: {}", note.getSettleNo());
+				note.setUpdateTime(LocalDateTime.now());
+				note.setSettleNoteStatus(DingEnum.NOTE_STATUS_FAIL.getType());
+				noticeInfo.append(sysUser.getRealname()).append(":结算提交失败;");
+
+				log.info("认证状态异常,结算解锁settleNoteId:{}", note.getId());
+				redisTemplate.delete(CacheConstants.SETTLE_PACKAGE_KEY + note.getId());
+			}
+		}
+
+		noteService.updateBatchById(notes);
+
+		// 更新结算结果
+		SettleNoteStatusOutput output = noteService.selectSettleNoteStatus(input.getId());
+		WmScorePackage updateEntity = new WmScorePackage();
+		updateEntity.setId(input.getId());
+		updateEntity.setSettleStatus(output.toSettleStatus());
+		wmScorePackageService.updateById(updateEntity);
+
+		return R.ok(null, noticeInfo.toString());
+	}
+
 	/**
 	 * 中智结算操作
 	 *
@@ -1755,7 +1959,7 @@ public class WmPayOffServiceImpl extends ServiceImpl<WmPayOffMapper, WmPayOff> i
 				params.put("taskInvoiceContent", note.getCategoryName());
 				params.put("endType", "CSO");
 				params.put("enterpriseCode", taxCode);
-				params.put("subjectType", "OLADING");
+				params.put("subjectType", input.getSubjectLocation().getGigType().name());
 				params.put("channel", "DEFAULT");
 				params.put("subjectLocation", input.getSubjectLocation().getType());
 				params.put("taskDescription", "根据要求,执行、并完成学术推广活动,并以在线平台工具采集、记录活动内容");

+ 424 - 12
hnqz-upms/hnqz-upms-biz/src/main/java/com/qunzhixinxi/hnqz/admin/service/impl/WmScorePackageSettleNoteServiceImpl.java

@@ -649,6 +649,8 @@ public class WmScorePackageSettleNoteServiceImpl extends ServiceImpl<WmScorePack
 			case HUI_QI_YUN:
 			case ZHONG_YI_YUN:
 			case ZHONG_ZHI:
+			case QI_FU:
+			case SHEN_ZHEN_REN_CAI:
 				if (!Objects.equals(userSub.getCertStatus(), DingEnum.CER_STATUS_1.getType())) {
 					return R.failed(sysUser.getRealname() + "未认证,不能发起结算");
 				}
@@ -709,6 +711,16 @@ public class WmScorePackageSettleNoteServiceImpl extends ServiceImpl<WmScorePack
 			String taxCode = sysDept.getTaxCode();
 			return this.settleByZhongZhi(note, wmScorePackage, sysUser, taxCode);
 		}
+		// 福建企赋
+		else if (SubjectTypeEnum.TYPE_QI_FU.getCode().equals(subType)) {
+			String taxCode = sysDept.getTaxCode();
+			return this.settleByQiFu(note, wmScorePackage, sysUser, taxCode, sysDeptSub.getPathNo());
+		}
+		// 自由职家
+		else if (SubjectTypeEnum.TYPE_SHEN_ZHEN_REN_CAI.getCode().equals(subType)) {
+			String taxCode = sysDept.getTaxCode();
+			return settleByOlading(note, wmScorePackage, sysUser, taxCode);
+		}
 		// 税邦云
 		else {
 			String taxCode = sysDept.getTaxCode();
@@ -744,6 +756,12 @@ public class WmScorePackageSettleNoteServiceImpl extends ServiceImpl<WmScorePack
 		String[] ids = input.getIdStr().split(",");
 		List<WmScorePackageSettleNote> noteList = new ArrayList<>(ids.length);
 		List<WmScorePackageSettleNote> oladingNoteList = new ArrayList<>(ids.length);
+		List<WmScorePackageSettleNote> fuJianQiFuNoteList = new ArrayList<>(ids.length);
+		List<WmScorePackageSettleNote> shenZhenRenCaiNoteList = new ArrayList<>(ids.length);
+		List<WmScorePackageSettleNote> zhengQiZhiXingNoteList = new ArrayList<>(ids.length);
+		List<WmScorePackageSettleNote> huiQiYunNoteList = new ArrayList<>(ids.length);
+		List<WmScorePackageSettleNote> zhongZhiNoteList = new ArrayList<>(ids.length);
+		List<WmScorePackageSettleNote> zhongYiYunNoteList = new ArrayList<>(ids.length);
 		List<WmScorePackageSettleNote> langchaoNoteList = new ArrayList<>(ids.length);
 		for (int i = 0; i < ids.length; i++) {
 			String id = ids[i];
@@ -798,6 +816,8 @@ public class WmScorePackageSettleNoteServiceImpl extends ServiceImpl<WmScorePack
 				case HUI_QI_YUN:
 				case ZHONG_YI_YUN:
 				case ZHONG_ZHI:
+				case QI_FU:
+				case SHEN_ZHEN_REN_CAI:
 					if (!Objects.equals(userSub.getCertStatus(), DingEnum.CER_STATUS_1.getType())) {
 						return R.failed(sysUser.getRealname() + "未认证,不能发起结算");
 					}
@@ -827,10 +847,33 @@ public class WmScorePackageSettleNoteServiceImpl extends ServiceImpl<WmScorePack
 
 			}
 			// 自由职家
-			else if (SubjectTypeEnum.TYPE_OLADING.getCode().equals(subType) || SubjectTypeEnum.TYPE_ZHENG_QI_ZHI_XING.getCode().equals(subType)
-					|| SubjectTypeEnum.TYPE_HUI_QI_YUN.getCode().equals(subType) || SubjectTypeEnum.TYPE_ZHONG_ZHI.getCode().equals(subType)) {
+			else if (SubjectTypeEnum.TYPE_OLADING.getCode().equals(subType)) {
 				oladingNoteList.add(note);
 			}
+			// 汇企云
+			else if (SubjectTypeEnum.TYPE_HUI_QI_YUN.getCode().equals(subType)) {
+				huiQiYunNoteList.add(note);
+			}
+			// 正启之星
+			else if (SubjectTypeEnum.TYPE_ZHENG_QI_ZHI_XING.getCode().equals(subType)) {
+				zhengQiZhiXingNoteList.add(note);
+			}
+			// 中智
+			else if (SubjectTypeEnum.TYPE_ZHONG_ZHI.getCode().equals(subType)) {
+				zhongZhiNoteList.add(note);
+			}
+			// 众蚁云
+			else if (SubjectTypeEnum.TYPE_ZHONG_YI_YUN.getCode().equals(subType)) {
+				zhongYiYunNoteList.add(note);
+			}
+			// 福建企赋
+			else if (SubjectTypeEnum.TYPE_QI_FU.getCode().equals(subType)) {
+				fuJianQiFuNoteList.add(note);
+			}
+			// 深圳人才
+			else if (SubjectTypeEnum.TYPE_SHEN_ZHEN_REN_CAI.getCode().equals(subType)) {
+				shenZhenRenCaiNoteList.add(note);
+			}
 			// 浪潮
 			else if (SubjectTypeEnum.TYPE_LANG_CHAO.getCode().equals(subType)) {
 				langchaoNoteList.add(note);
@@ -859,13 +902,13 @@ public class WmScorePackageSettleNoteServiceImpl extends ServiceImpl<WmScorePack
 			// return settleByTaxHelper();
 		}
 		// 政企之星结算
-		if (CollectionUtils.isNotEmpty(oladingNoteList)) {
+		if (CollectionUtils.isNotEmpty(zhengQiZhiXingNoteList)) {
 			if (StringUtils.isNotEmpty(taxCode)) {
 				log.info("政企之星结算结算开始-获取会员所属企业的统一社会信用代码:{} ", taxCode);
 			} else {
 				return R.failed("未配置企业的统一社会信用代码");
 			}
-			return batchSettleBySinbaad(oladingNoteList, taxCode);
+			return batchSettleBySinbaad(zhengQiZhiXingNoteList, taxCode);
 			// return settleByTaxHelper();
 		}
 
@@ -886,34 +929,56 @@ public class WmScorePackageSettleNoteServiceImpl extends ServiceImpl<WmScorePack
 		}
 
 		// 汇企云结算
-		if (CollectionUtils.isNotEmpty(oladingNoteList)) {
+		if (CollectionUtils.isNotEmpty(huiQiYunNoteList)) {
 			if (StringUtils.isNotEmpty(taxCode)) {
 				log.info("汇企云结算开始-获取会员所属企业的统一社会信用代码:{} ", taxCode);
 			} else {
 				return R.failed("未配置企业的统一社会信用代码");
 			}
 			SysDeptSub sysDeptSub = subMap.get(SubjectLocation.HUI_QI_YUN.name());
-			return this.batchSettleByHuiQiYun(oladingNoteList, taxCode, sysDeptSub.getPathNo());
+			return this.batchSettleByHuiQiYun(huiQiYunNoteList, taxCode, sysDeptSub.getPathNo());
 		}
 
 		// 众蚁云
-		if (CollectionUtils.isNotEmpty(oladingNoteList)) {
+		if (CollectionUtils.isNotEmpty(zhongYiYunNoteList)) {
 			if (StringUtils.isNotEmpty(taxCode)) {
 				log.info("众蚁云结算开始-获取会员所属企业的统一社会信用代码:{} ", taxCode);
 			} else {
 				return R.failed("未配置企业的统一社会信用代码");
 			}
-			return this.batchSettleByZHongYiYun(oladingNoteList, taxCode);
+			return this.batchSettleByZHongYiYun(zhongYiYunNoteList, taxCode);
 		}
 
 		// 中智
-		if (CollectionUtils.isNotEmpty(oladingNoteList)) {
+		if (CollectionUtils.isNotEmpty(zhongZhiNoteList)) {
 			if (StringUtils.isNotEmpty(taxCode)) {
 				log.info("中智结算开始-获取会员所属企业的统一社会信用代码:{} ", taxCode);
 			} else {
 				return R.failed("未配置企业的统一社会信用代码");
 			}
-			return this.batchSettleByZhongzhi(oladingNoteList, taxCode);
+			return this.batchSettleByZhongzhi(zhongZhiNoteList, taxCode);
+		}
+
+		// 福建企赋
+		if (CollectionUtils.isNotEmpty(fuJianQiFuNoteList)) {
+			if (StringUtils.isNotEmpty(taxCode)) {
+				log.info("福建企赋结算开始-获取会员所属企业的统一社会信用代码:{} ", taxCode);
+			} else {
+				return R.failed("未配置企业的统一社会信用代码");
+			}
+			SysDeptSub sysDeptSub = subMap.get(SubjectLocation.QI_FU.name());
+			return this.batchSettleByQiFu(fuJianQiFuNoteList, taxCode, sysDeptSub.getPathNo());
+		}
+
+		// 深圳人才
+		if (CollectionUtils.isNotEmpty(shenZhenRenCaiNoteList)) {
+			if (StringUtils.isNotEmpty(taxCode)) {
+				log.info("深圳人才结算开始-获取会员所属企业的统一社会信用代码:{} ", taxCode);
+			} else {
+				return R.failed("未配置企业的统一社会信用代码");
+			}
+			SysDeptSub sysDeptSub = subMap.get(SubjectLocation.QI_FU.name());
+			return this.batchSettleByQiFu(shenZhenRenCaiNoteList, taxCode, sysDeptSub.getPathNo());
 		}
 
 		return R.ok();
@@ -924,6 +989,208 @@ public class WmScorePackageSettleNoteServiceImpl extends ServiceImpl<WmScorePack
 		return R.failed("因系统维护,暂时不能提起支付,有问题请联系客服");
 	}
 
+	/**
+	 * 福建企赋结算
+	 *
+	 * @param noteList 结算记录
+	 * @param taxCode  企业三合一码
+	 * @param pathNo 批次付款渠道编号
+	 * @return 结果
+	 */
+	private R batchSettleByQiFu(List<WmScorePackageSettleNote> noteList, String taxCode, String[] pathNo) {
+
+		// 加锁
+		List<Integer> noteIdList = noteList.stream().filter(note ->
+						redisTemplate.opsForValue().setIfAbsent(
+								CacheConstants.SETTLE_PACKAGE_KEY + ":note_id_" + note.getId(),
+								noteList, CacheConstants.SETTLE_TIME, TimeUnit.DAYS))
+				.mapToInt(WmScorePackageSettleNote::getId).boxed().collect(Collectors.toList());
+
+		// 加锁记录数不等于提交记录数,说明存在在途交易
+		if (CollectionUtils.isEmpty(noteIdList)) {
+			log.error("当前用户存在其他结算请求");
+			return R.failed("当前用户存在其他结算请求");
+		} else {
+			if (!Objects.equals(noteList.size(), noteIdList.size())) {
+				// 删除锁
+				noteIdList.forEach(id -> redisTemplate.delete(CacheConstants.SETTLE_PACKAGE_KEY + ":note_id_" + id));
+				log.error("当前用户存在其他结算请求");
+				return R.failed("当前用户存在其他结算请求");
+			}
+		}
+
+		HnqzUser operator = SecurityUtils.getUser();
+		String gigTokenUrl = upmsConfig.getGigServiceUrl() + "/gig/operation/token?tenantId={tenantId}&action={action}&userId={userId}";
+		String gigSettleUrl = upmsConfig.getGigServiceUrl() + "/gig/operation/settlement";
+
+		List<Map<String, Object>> settleParamsMapper = new ArrayList<>();
+		Map<String, Map<String, Object>> detailMap = new HashMap<>();
+		noteList.forEach(note -> {
+			WmScorePackage wmScorePackage = wmScorePackageMapper.selectById(note.getPackageId());
+			// 封装结算参数
+			Map<String, Object> params;
+			if (detailMap.containsKey(note.getIdCardNumber())) {
+				params = detailMap.get(note.getIdCardNumber());
+				params.put("amount", String.valueOf(new BigDecimal((String) params.get("amount")).add(note.getSettleAmount()).doubleValue()));
+
+
+				LocalDate startTime = (LocalDate) params.get("taskStartTime");
+				LocalDate endTime = (LocalDate) params.get("taskEndTime");
+				LocalDate noteCreateTime = wmScorePackage.getCreateTime().toLocalDate();
+				LocalDate noteUpdateTime = wmScorePackage.getUpdateTime().toLocalDate();
+
+				if (noteCreateTime.isBefore(startTime)) {
+					params.put("taskStartTime", wmScorePackage.getCreateTime().toLocalDate());
+				}
+				if (noteUpdateTime.isAfter(endTime)) {
+					params.put("taskEndTime", wmScorePackage.getUpdateTime().toLocalDate());
+				}
+
+				Set<Integer> ids = (Set<Integer>) params.get("noteIds");
+				ids.add(note.getId());
+				params.put("noteIds", ids);
+			} else {
+				SysUser sysUser = sysUserService.getById(note.getUserId());
+				params = new HashMap<>(19);
+				params.put("tenantId", operator.getDeptId());
+				params.put("operatorId", operator.getId());
+				params.put("requestId", RandomStringUtils.randomAlphabetic(12));
+				params.put("taskName", String.format("%s(%s)_%s", sysUser.getRealname(), sysUser.getUsername(), System.currentTimeMillis()));
+				params.put("amount", String.valueOf(note.getSettleAmount().doubleValue()));
+				params.put("taskStartTime", wmScorePackage.getCreateTime().toLocalDate());
+				params.put("taskEndTime", wmScorePackage.getUpdateTime().toLocalDate());
+				params.put("taskLocation", "要易云");
+				params.put("username", sysUser.getBankPhone());
+				params.put("idCard", note.getIdCardNumber());
+				params.put("idCardType","ID_CARD");
+				params.put("realName", sysUser.getRealname());
+				params.put("bankCard", sysUser.getBankCardNumber());
+				params.put("bankPhone", sysUser.getBankPhone());
+				params.put("tagId", upmsConfig.getTagId());
+				params.put("taskInvoiceContent", note.getCategoryName());
+				params.put("endType", "CSO");
+				params.put("enterpriseCode", taxCode);
+				params.put("subjectType", "QI_FU");
+				params.put("channel", "DEFAULT");
+				params.put("subjectLocation", note.getSubjectLocation());
+				params.put("taskDescription", "根据要求,执行、并完成学术推广活动,并以在线平台工具采集、记录活动内容");
+				params.put("taxMode", "SPECIAL");
+				params.put("transactionModel", "CHANNEL");
+
+				Set<Integer> noteIds = new HashSet<>();
+				noteIds.add(note.getId());
+				params.put("noteIds", noteIds);
+				detailMap.put(note.getIdCardNumber(), params);
+			}
+		});
+
+		detailMap.forEach((key, value) -> settleParamsMapper.add(value));
+
+
+		// 开始结算
+		for (Map<String, Object> params : settleParamsMapper) {
+
+			Set<Integer> noteIds = (Set<Integer>) params.get("noteIds");
+			try {
+				// 获取请求token
+				ResponseEntity<String> tokenResult = new RestTemplate().getForEntity(gigTokenUrl, String.class,
+						String.valueOf(operator.getDeptId()), "settle", String.valueOf(operator.getId()));
+				log.warn("获取结算token:{}", tokenResult.getBody());
+				if (!JSONUtil.isJson(tokenResult.getBody())) {
+					return R.failed("获取结算token失败");
+				}
+
+				JSONObject jsonObject = JSONUtil.parseObj(tokenResult.getBody());
+
+				if (jsonObject.getInt("code") != 0 || StrUtil.isBlank(jsonObject.getStr("data"))) {
+					return R.failed("获取结算token失败");
+				}
+
+				String token = jsonObject.getStr("data");
+
+				// 间隔100毫秒
+				Thread.sleep(100);
+
+				params.put("token", token);
+
+				// 发起结算
+				HttpHeaders headers = new HttpHeaders();
+				headers.setContentType(MediaType.APPLICATION_JSON);
+				log.info("福建企赋结算req: {}", params);
+				HttpEntity<String> result = new RestTemplate().exchange(gigSettleUrl, HttpMethod.POST, new HttpEntity<>(params, headers), String.class);
+				log.info("福建企赋结算resp: {}", result.getBody());
+				if (!JSONUtil.isJson(result.getBody())) {
+					return R.failed("结算失败");
+				}
+				JSONObject settelObj = JSONUtil.parseObj(result.getBody());
+
+				if (Objects.equals(settelObj.getInt("code"), CommonConstants.SUCCESS)) {
+					JSONObject dataJsonObj = settelObj.getJSONObject("data");
+
+					noteIds.forEach(id -> {
+						log.info("福建企赋结算结算提交成功");
+						// data获取不到
+						if (dataJsonObj == null) {
+							log.info("福建企赋提交成功 data 获取不到");
+							return;
+						}
+
+						WmScorePackageSettleNote note = new WmScorePackageSettleNote();
+						LocalDateTime now = LocalDateTime.now();
+						note.setId(id);
+						note.setSubToGigTime(now);
+						note.setUpdateTime(now);
+						String requestId = dataJsonObj.getStr("requestId");
+						if (StrUtil.isNotBlank(requestId)) {
+							note.setSettleNoteStatus(DingEnum.NOTE_STATUS_SUBMIT.getType());
+							// 新增字段streamId
+							note.setStreamId(requestId);
+						} else {
+							note.setSettleNoteStatus(DingEnum.NOTE_STATUS_FAIL.getType());
+							log.info("福建企赋提交成功 message:{}", dataJsonObj.getStr("message"));
+							redisTemplate.delete(CacheConstants.SETTLE_PACKAGE_KEY + ":note_id_" + note.getId());
+						}
+						this.baseMapper.updateById(note);
+					});
+
+				} else {
+					noteIds.forEach(id -> {
+						WmScorePackageSettleNote note = new WmScorePackageSettleNote();
+						note.setId(id);
+						log.info("福建企赋结算提交失败: {}", note.getSettleNo());
+						LocalDateTime now = LocalDateTime.now();
+						note.setUpdateTime(now);
+						note.setSubToGigTime(now);
+						note.setSettleNoteStatus(DingEnum.NOTE_STATUS_FAIL.getType());
+						this.baseMapper.updateById(note);
+						log.info("认证状态异常,结算解锁settleNoteId:{}", note.getId());
+						redisTemplate.delete(CacheConstants.SETTLE_PACKAGE_KEY + ":note_id_" + note.getId());
+					});
+
+					return R.ok("结算失败");
+				}
+
+			} catch (Exception e) {
+				log.error("", e);
+				noteIds.forEach(id -> {
+					WmScorePackageSettleNote note = new WmScorePackageSettleNote();
+					note.setId(id);
+					log.info("福建企赋结算提交失败: {}", note.getSettleNo());
+					LocalDateTime now = LocalDateTime.now();
+					note.setUpdateTime(now);
+					note.setSubToGigTime(now);
+					note.setSettleNoteStatus(DingEnum.NOTE_STATUS_FAIL.getType());
+					this.baseMapper.updateById(note);
+					log.info("认证状态异常,结算解锁settleNoteId:{}", note.getId());
+					redisTemplate.delete(CacheConstants.SETTLE_PACKAGE_KEY + ":note_id_" + note.getId());
+				});
+				return R.ok("结算失败");
+			}
+		}
+
+		return R.ok("提交结算成功");
+	}
+
 	/**
 	 * 中智结算
 	 *
@@ -2010,7 +2277,7 @@ public class WmScorePackageSettleNoteServiceImpl extends ServiceImpl<WmScorePack
 				params.put("taskInvoiceContent", note.getCategoryName());
 				params.put("endType", "CSO");
 				params.put("enterpriseCode", taxCode);
-				params.put("subjectType", "OLADING");
+				params.put("subjectType", note.getSubjectLocation().getGigType().name());
 				params.put("channel", "DEFAULT");
 				params.put("subjectLocation", note.getSubjectLocation());
 				params.put("taskDescription", "根据要求,执行、并完成学术推广活动,并以在线平台工具采集、记录活动内容");
@@ -2244,6 +2511,151 @@ public class WmScorePackageSettleNoteServiceImpl extends ServiceImpl<WmScorePack
 		}
 	}
 
+	/**
+	 * 福建企赋结算
+	 *
+	 * @param note
+	 * @param wmScorePackage
+	 * @param sysUser
+	 * @param taxCode
+	 * @return
+	 */
+	private R settleByQiFu(WmScorePackageSettleNote note,
+							   WmScorePackage wmScorePackage,
+							   SysUser sysUser,
+							   String taxCode,
+							   String[] pathNo) {
+
+		/**
+		 * 加锁
+		 */
+		redisTemplate.opsForValue().set(CacheConstants.SETTLE_PACKAGE_KEY + note.getId(),
+				note.getId(), CacheConstants.SETTLE_TIME, TimeUnit.DAYS);
+
+		/**
+		 * 开始结算
+		 */
+
+		HnqzUser operator = SecurityUtils.getUser();
+		String gigTokenUrl = upmsConfig.getGigServiceUrl() + "/gig/operation/token?tenantId={tenantId}&action={action}&userId={userId}";
+		String gigSettleUrl = upmsConfig.getGigServiceUrl() + "/gig/operation/settlement";
+
+		StringBuilder noticeInfo = new StringBuilder();
+		try {
+			// 获取请求token
+			ResponseEntity<String> tokenResult = new RestTemplate().getForEntity(gigTokenUrl, String.class,
+					String.valueOf(operator.getDeptId()), "settle", String.valueOf(operator.getId()));
+			log.warn("获取结算token:{}", tokenResult.getBody());
+			if (!JSONUtil.isJson(tokenResult.getBody())) {
+				return R.failed("获取结算token失败");
+			}
+
+			JSONObject jsonObject = JSONUtil.parseObj(tokenResult.getBody());
+
+			if (jsonObject.getInt("code") != 0 || StrUtil.isBlank(jsonObject.getStr("data"))) {
+				return R.failed("获取结算token失败");
+			}
+
+			String token = jsonObject.getStr("data");
+
+			// 间隔100毫秒
+			Thread.sleep(100);
+
+			// 封装结算参数
+			Map<String, Object> params = new HashMap<>();
+			params.put("token", token);
+			params.put("tenantId", operator.getDeptId());
+			params.put("operatorId", operator.getId());
+			params.put("requestId", RandomStringUtils.randomAlphabetic(12));
+			params.put("taskName", wmScorePackage.getScorePackageName() + "_" + System.currentTimeMillis());
+			params.put("amount", String.valueOf(note.getSettleAmount().doubleValue()));
+			params.put("taskStartTime", wmScorePackage.getCreateTime().toLocalDate());
+			params.put("taskEndTime", wmScorePackage.getUpdateTime().toLocalDate());
+			params.put("taskLocation", "要易云");
+			params.put("username", sysUser.getBankPhone());
+			params.put("idCard", sysUser.getIdCardNumber());
+			params.put("idCardType","ID_CARD");
+			params.put("realName", sysUser.getRealname());
+			params.put("bankCard", sysUser.getBankCardNumber());
+			params.put("bankPhone", sysUser.getBankPhone());
+			// 市场推广
+			params.put("tagId", upmsConfig.getTagId());
+			params.put("taskInvoiceContent", note.getCategoryName());
+			params.put("endType", "CSO");
+			params.put("enterpriseCode", taxCode);
+			params.put("subjectType", "QI_FU");
+			params.put("channel", "DEFAULT");
+			params.put("subjectLocation", note.getSubjectLocation().getType());
+			params.put("taxMode", "SPECIAL");
+			params.put("transactionModel", "CHANNEL");
+			params.put("taskDescription", "根据要求,执行、并完成学术推广活动,并以在线平台工具采集、记录活动内容");
+
+			// 发起结算
+			HttpHeaders headers = new HttpHeaders();
+			headers.setContentType(MediaType.APPLICATION_JSON);
+			log.info("福建企赋结算req: {}", params);
+			HttpEntity<String> result = new RestTemplate().exchange(gigSettleUrl, HttpMethod.POST, new HttpEntity<>(params, headers), String.class);
+			log.info("福建企赋结算resp: {}", result.getBody());
+			if (!JSONUtil.isJson(result.getBody())) {
+				return R.failed("结算失败");
+			}
+			JSONObject settelObj = JSONUtil.parseObj(result.getBody());
+
+			LocalDateTime now = LocalDateTime.now();
+			if (Objects.equals(settelObj.getInt("code"), CommonConstants.SUCCESS)) {
+				JSONObject dataJsonObj = settelObj.getJSONObject("data");
+
+				log.info("福建企赋结算提交成功: {}", note.getSettleNo());
+				note.setUpdateTime(now);
+				note.setSubToGigTime(now);
+				//data 获取不到
+				if (dataJsonObj != null) {
+					String requestId = dataJsonObj.getStr("requestId");
+					if (StrUtil.isNotBlank(requestId)) {
+						note.setSettleNoteStatus(DingEnum.NOTE_STATUS_SUBMIT.getType());
+						// 新增字段streamId
+						note.setStreamId(requestId);
+						noticeInfo.append(sysUser.getRealname()).append(":提交结算成功;");
+					} else {
+						note.setSettleNoteStatus(DingEnum.NOTE_STATUS_FAIL.getType());
+						noticeInfo.append(sysUser.getRealname()).append(":" + dataJsonObj.getStr("message"));
+						redisTemplate.delete(CacheConstants.SETTLE_PACKAGE_KEY + note.getId());
+					}
+				} else {
+					note.setSettleNoteStatus(DingEnum.NOTE_STATUS_FAIL.getType());
+					noticeInfo.append(sysUser.getRealname()).append(":提交结算成功,业务流水号获取不到,请联系管理员;");
+					log.warn("福建企赋结算提交成功 data 获取不到: {}", note.getSettleNo());
+					redisTemplate.delete(CacheConstants.SETTLE_PACKAGE_KEY + note.getId());
+				}
+			} else {
+				log.warn("福建企赋结算提交失败: {}", note.getSettleNo());
+				note.setUpdateTime(now);
+				note.setSubToGigTime(now);
+				note.setSettleNoteStatus(DingEnum.NOTE_STATUS_FAIL.getType());
+				noticeInfo.append(sysUser.getRealname()).append(":结算提交失败-").append(settelObj.getStr("msg")).append(";");
+
+				log.info("认证状态异常,结算解锁settleNoteId:{}", note.getId());
+				redisTemplate.delete(CacheConstants.SETTLE_PACKAGE_KEY + note.getId());
+
+			}
+		} catch (Exception e) {
+			log.error("", e);
+			log.warn("福建企赋结算提交失败: {}", note.getSettleNo());
+			LocalDateTime now = LocalDateTime.now();
+			note.setUpdateTime(now);
+			note.setSubToGigTime(now);
+			note.setSettleNoteStatus(DingEnum.NOTE_STATUS_FAIL.getType());
+			noticeInfo.append(sysUser.getRealname()).append(":结算提交失败;");
+
+			log.info("认证状态异常,结算解锁settleNoteId:{}", note.getId());
+			redisTemplate.delete(CacheConstants.SETTLE_PACKAGE_KEY + note.getId());
+		}
+
+		this.baseMapper.updateById(note);
+
+		return R.ok(null, noticeInfo.toString());
+	}
+
 	/**
 	 * 众蚁云结算
 	 *
@@ -3037,7 +3449,7 @@ public class WmScorePackageSettleNoteServiceImpl extends ServiceImpl<WmScorePack
 			params.put("taskInvoiceContent", note.getCategoryName());
 			params.put("endType", "CSO");
 			params.put("enterpriseCode", taxCode);
-			params.put("subjectType", "OLADING");
+			params.put("subjectType", note.getSubjectLocation().getGigType().name());
 			params.put("channel", "DEFAULT");
 			params.put("subjectLocation", note.getSubjectLocation());
 			params.put("taskDescription", "根据要求,执行、并完成学术推广活动,并以在线平台工具采集、记录活动内容");

+ 637 - 0
hnqz-upms/hnqz-upms-biz/src/main/java/com/qunzhixinxi/hnqz/admin/util/SaasApiDemoV2.java

@@ -0,0 +1,637 @@
+package com.qunzhixinxi.hnqz.admin.util;
+
+import cn.hutool.crypto.asymmetric.KeyType;
+import cn.hutool.crypto.asymmetric.RSA;
+import com.alibaba.fastjson.JSONObject;
+import org.springframework.util.StringUtils;
+
+import java.io.BufferedReader;
+import java.io.DataOutputStream;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.io.UnsupportedEncodingException;
+import java.lang.reflect.Field;
+import java.net.HttpURLConnection;
+import java.net.URL;
+import java.net.URLEncoder;
+import java.nio.charset.StandardCharsets;
+import java.security.KeyFactory;
+import java.security.PrivateKey;
+import java.security.PublicKey;
+import java.security.spec.PKCS8EncodedKeySpec;
+import java.security.spec.X509EncodedKeySpec;
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.SortedMap;
+import java.util.TreeMap;
+
+public class SaasApiDemoV2 {
+
+    public static String version = "1";
+    
+    public static String merId = "";
+
+    public static String tenantCode = "";
+
+    public static String levyCode = "";
+
+    public static String bankCode = "";
+
+    public static String localhost ="";
+
+    // 商户私钥
+    public static String privateKey = "";
+  
+    // 运营公钥
+    public static String publicKey = "";
+
+    /**
+     * soho签约
+     **/
+
+
+//    public static void main(String[] args) throws Exception {
+//        // sohoSign();
+////        sohoQuery();
+//        //sohoIdCardUpload();
+//        //rescindSoho();
+//        //downloadContract();
+//        //batchSoho();
+//        //accountBalance();
+//        //calculation();
+//        //accTransDetail();
+//        //levyInfo();
+//        //merchantInfo();
+//        //accNoInfo();
+//        //openMerchant();
+//        //selectMerchant();
+//        //supplementInfo();
+//        //selectProjectMcc();
+//        //createProject();
+//        //accReviewRecord();
+//        //payment();
+//        //queryBatch();
+//        //downloadReceipt();
+//        //downloadReceiptByDate();
+//        //queryMerplatOrderPage();
+//        //invoiceType();
+//        //invoiceMerSumAmt();
+//        //invoiceOpen();
+//        //invoicePic();
+//        //invoiceInfo();
+//        //openApiHelp();
+//    }
+
+    public static String ALGORITHM_DES = "DES";
+    public static String PKCS5 = "DES/ECB/PKCS5Padding";
+    public static String SIGN_ALGORITHMS = "SHA1WithRSA";// 摘要加密算饭
+    public static String CHAR_SET = "UTF-8";
+
+
+    public static boolean verify(String content, String sign, String public_key)
+            throws Exception {
+        KeyFactory keyFactory = KeyFactory.getInstance("RSA");
+        byte[] encodedKey = decode(public_key);
+        PublicKey pubKey = keyFactory.generatePublic(new X509EncodedKeySpec(
+                encodedKey));
+
+        java.security.Signature signature = java.security.Signature
+                .getInstance(SIGN_ALGORITHMS);
+
+        signature.initVerify(pubKey);
+        signature.update(content.getBytes(CHAR_SET));
+
+        boolean bverify = signature.verify(decode(sign));
+        return bverify;
+
+    }
+
+    public static String createSign(SortedMap<String, String> parameters) {
+        StringBuffer sb = new StringBuffer();
+        Set es = parameters.entrySet();
+        Iterator it = es.iterator();
+        while (it.hasNext()) {
+            Map.Entry entry = (Map.Entry) it.next();
+            String k = (String) entry.getKey();
+            Object v = entry.getValue();
+            if ("" != v && "null" != v && null != v && !"".equals(v) && !"sign".equals(k) && !"key".equals(k) && !"null".equals(v)) {
+                sb.append(k + "=" + v + "&");
+            }
+        }
+        // signature 不用添加到SortMap里面去,单独处理,编码方式采用UTF-8
+        return sb.toString().substring(0, sb.length() - 1);
+    }
+
+    public static String sendPost(String curl, String param) {
+        String result = "";// 返回的结果
+        BufferedReader in = null;// 读取响应输入流
+        try {
+            //创建连接
+            URL url = new URL(curl);
+            HttpURLConnection connection = (HttpURLConnection) url
+                    .openConnection();
+            connection.setDoOutput(true);
+            connection.setDoInput(true);
+            connection.setRequestMethod("POST");
+            connection.setUseCaches(false);
+            connection.setInstanceFollowRedirects(true);
+            connection.setRequestProperty("Content-Type",
+                    "application/json");
+            connection.setRequestProperty("token", "Bearer gfdsgfsgfdsgsrkljnfak[po[eghpaj");
+
+            connection.connect();
+
+            //POST请求
+            DataOutputStream out = new DataOutputStream(
+                    connection.getOutputStream());
+
+            out.writeBytes(param);
+            out.flush();
+            out.close();
+
+            //读取响应
+            // 定义BufferedReader输入流来读取URL的响应,并设置编码方式
+            in = new BufferedReader(new InputStreamReader(connection
+                    .getInputStream(), StandardCharsets.UTF_8));
+            String line;
+            // 读取返回的内容
+            while ((line = in.readLine()) != null) {
+                result += line;
+            }
+        } catch (Exception e) {
+            e.printStackTrace();
+            System.out.println("Http请求方法内部问题");
+        } finally {
+            try {
+                if (in != null) {
+                    in.close();
+                }
+            } catch (IOException ex) {
+                ex.printStackTrace();
+            }
+        }
+        return result;
+    }
+
+    /**
+     * @return
+     * @Author cuiLei
+     * @Description 将Map以key=value&格式拼接
+     * @Date 14:47 2021/4/7
+     **/
+    public static String createLinkString(Map<String, Object> params, boolean encode) {
+        List<String> keys = new ArrayList<String>(params.keySet());
+        Collections.sort(keys);//不按首字母排序, 需要按首字母排序请打开
+        StringBuilder prestrSB = new StringBuilder();
+        for (int i = 0; i < keys.size(); i++) {
+            String key = keys.get(i);
+            Object value = params.get(key);
+            if (StringUtils.isEmpty(value) || "null".equals(value) || "sign".equals(value) || "key".equals(value)) {
+                continue;
+            }
+            if (encode) {
+                try {
+                    value = URLEncoder.encode(value.toString(), "GBK");
+                } catch (UnsupportedEncodingException e) {
+                    e.printStackTrace();
+                }
+            }
+            if (i == keys.size() - 1) {// 拼接时,不包括最后一个&字符
+                prestrSB.append(key).append("=").append(value);
+            } else {
+                prestrSB.append(key).append("=").append(value).append("&");
+            }
+        }
+        return prestrSB.toString();
+    }
+
+
+    public static String sign(String content, String privateKey)
+            throws Exception {
+        byte[] str = decode(privateKey);
+        PKCS8EncodedKeySpec priPKCS8 = new PKCS8EncodedKeySpec(str);
+        KeyFactory keyf = KeyFactory.getInstance("RSA");
+        PrivateKey priKey = keyf.generatePrivate(priPKCS8);
+
+        java.security.Signature signature = java.security.Signature
+                .getInstance(SIGN_ALGORITHMS);
+
+        signature.initSign(priKey);
+        signature.update(content.getBytes(CHAR_SET));
+
+        byte[] signed = signature.sign();
+
+        return encode(signed);
+    }
+
+
+    static private final int BASELENGTH = 128;
+    static private final int LOOKUPLENGTH = 64;
+    static private final int TWENTYFOURBITGROUP = 24;
+    static private final int EIGHTBIT = 8;
+    static private final int SIXTEENBIT = 16;
+    static private final int FOURBYTE = 4;
+    static private final int SIGN = -128;
+    static private final char PAD = '=';
+    static private final boolean fDebug = false;
+    static final private byte[] base64Alphabet = new byte[BASELENGTH];
+    static final private char[] lookUpBase64Alphabet = new char[LOOKUPLENGTH];
+
+    static {
+        for (int i = 0; i < BASELENGTH; ++i) {
+            base64Alphabet[i] = -1;
+        }
+        for (int i = 'Z'; i >= 'A'; i--) {
+            base64Alphabet[i] = (byte) (i - 'A');
+        }
+        for (int i = 'z'; i >= 'a'; i--) {
+            base64Alphabet[i] = (byte) (i - 'a' + 26);
+        }
+
+        for (int i = '9'; i >= '0'; i--) {
+            base64Alphabet[i] = (byte) (i - '0' + 52);
+        }
+
+        base64Alphabet['+'] = 62;
+        base64Alphabet['/'] = 63;
+
+        for (int i = 0; i <= 25; i++) {
+            lookUpBase64Alphabet[i] = (char) ('A' + i);
+        }
+
+        for (int i = 26, j = 0; i <= 51; i++, j++) {
+            lookUpBase64Alphabet[i] = (char) ('a' + j);
+        }
+
+        for (int i = 52, j = 0; i <= 61; i++, j++) {
+            lookUpBase64Alphabet[i] = (char) ('0' + j);
+        }
+        lookUpBase64Alphabet[62] = (char) '+';
+        lookUpBase64Alphabet[63] = (char) '/';
+
+    }
+
+    private static boolean isWhiteSpace(char octect) {
+        return (octect == 0x20 || octect == 0xd || octect == 0xa || octect == 0x9);
+    }
+
+    private static boolean isPad(char octect) {
+        return (octect == PAD);
+    }
+
+    private static boolean isData(char octect) {
+        return (octect < BASELENGTH && base64Alphabet[octect] != -1);
+    }
+
+    /**
+     * remove WhiteSpace from MIME containing encoded Base64 data.
+     *
+     * @param data the byte array of base64 data (with WS)
+     * @return the new length
+     */
+    private static int removeWhiteSpace(char[] data) {
+        if (data == null) {
+            return 0;
+        }
+
+        // count characters that's not whitespace
+        int newSize = 0;
+        int len = data.length;
+        for (int i = 0; i < len; i++) {
+            if (!isWhiteSpace(data[i])) {
+                data[newSize++] = data[i];
+            }
+        }
+        return newSize;
+    }
+
+    public static String encode(byte[] binaryData) {
+
+        if (binaryData == null) {
+            return null;
+        }
+
+        int lengthDataBits = binaryData.length * EIGHTBIT;
+        if (lengthDataBits == 0) {
+            return "";
+        }
+
+        int fewerThan24bits = lengthDataBits % TWENTYFOURBITGROUP;
+        int numberTriplets = lengthDataBits / TWENTYFOURBITGROUP;
+        int numberQuartet = fewerThan24bits != 0 ? numberTriplets + 1 : numberTriplets;
+        char encodedData[] = null;
+
+        encodedData = new char[numberQuartet * 4];
+
+        byte k = 0, l = 0, b1 = 0, b2 = 0, b3 = 0;
+
+        int encodedIndex = 0;
+        int dataIndex = 0;
+        if (fDebug) {
+            System.out.println("number of triplets = " + numberTriplets);
+        }
+
+        for (int i = 0; i < numberTriplets; i++) {
+            b1 = binaryData[dataIndex++];
+            b2 = binaryData[dataIndex++];
+            b3 = binaryData[dataIndex++];
+
+            if (fDebug) {
+                System.out.println("b1= " + b1 + ", b2= " + b2 + ", b3= " + b3);
+            }
+
+            l = (byte) (b2 & 0x0f);
+            k = (byte) (b1 & 0x03);
+
+            byte val1 = ((b1 & SIGN) == 0) ? (byte) (b1 >> 2) : (byte) ((b1) >> 2 ^ 0xc0);
+            byte val2 = ((b2 & SIGN) == 0) ? (byte) (b2 >> 4) : (byte) ((b2) >> 4 ^ 0xf0);
+            byte val3 = ((b3 & SIGN) == 0) ? (byte) (b3 >> 6) : (byte) ((b3) >> 6 ^ 0xfc);
+
+            if (fDebug) {
+                System.out.println("val2 = " + val2);
+                System.out.println("k4   = " + (k << 4));
+                System.out.println("vak  = " + (val2 | (k << 4)));
+            }
+
+            encodedData[encodedIndex++] = lookUpBase64Alphabet[val1];
+            encodedData[encodedIndex++] = lookUpBase64Alphabet[val2 | (k << 4)];
+            encodedData[encodedIndex++] = lookUpBase64Alphabet[(l << 2) | val3];
+            encodedData[encodedIndex++] = lookUpBase64Alphabet[b3 & 0x3f];
+        }
+
+        // form integral number of 6-bit groups
+        if (fewerThan24bits == EIGHTBIT) {
+            b1 = binaryData[dataIndex];
+            k = (byte) (b1 & 0x03);
+            if (fDebug) {
+                System.out.println("b1=" + b1);
+                System.out.println("b1<<2 = " + (b1 >> 2));
+            }
+            byte val1 = ((b1 & SIGN) == 0) ? (byte) (b1 >> 2) : (byte) ((b1) >> 2 ^ 0xc0);
+            encodedData[encodedIndex++] = lookUpBase64Alphabet[val1];
+            encodedData[encodedIndex++] = lookUpBase64Alphabet[k << 4];
+            encodedData[encodedIndex++] = PAD;
+            encodedData[encodedIndex++] = PAD;
+        } else if (fewerThan24bits == SIXTEENBIT) {
+            b1 = binaryData[dataIndex];
+            b2 = binaryData[dataIndex + 1];
+            l = (byte) (b2 & 0x0f);
+            k = (byte) (b1 & 0x03);
+
+            byte val1 = ((b1 & SIGN) == 0) ? (byte) (b1 >> 2) : (byte) ((b1) >> 2 ^ 0xc0);
+            byte val2 = ((b2 & SIGN) == 0) ? (byte) (b2 >> 4) : (byte) ((b2) >> 4 ^ 0xf0);
+
+            encodedData[encodedIndex++] = lookUpBase64Alphabet[val1];
+            encodedData[encodedIndex++] = lookUpBase64Alphabet[val2 | (k << 4)];
+            encodedData[encodedIndex++] = lookUpBase64Alphabet[l << 2];
+            encodedData[encodedIndex++] = PAD;
+        }
+
+        return new String(encodedData);
+    }
+
+    /**
+     * Decodes Base64 data into octects
+     *
+     * @param encoded string containing Base64 data
+     * @return Array containind decoded data.
+     */
+    public static byte[] decode(String encoded) {
+
+        if (encoded == null) {
+            return null;
+        }
+
+        char[] base64Data = encoded.toCharArray();
+        // remove white spaces
+        int len = removeWhiteSpace(base64Data);
+
+        if (len % FOURBYTE != 0) {
+            return null;//should be divisible by four
+        }
+
+        int numberQuadruple = (len / FOURBYTE);
+
+        if (numberQuadruple == 0) {
+            return new byte[0];
+        }
+
+        byte decodedData[] = null;
+        byte b1 = 0, b2 = 0, b3 = 0, b4 = 0;
+        char d1 = 0, d2 = 0, d3 = 0, d4 = 0;
+
+        int i = 0;
+        int encodedIndex = 0;
+        int dataIndex = 0;
+        decodedData = new byte[(numberQuadruple) * 3];
+
+        for (; i < numberQuadruple - 1; i++) {
+
+            if (!isData((d1 = base64Data[dataIndex++])) || !isData((d2 = base64Data[dataIndex++]))
+                    || !isData((d3 = base64Data[dataIndex++]))
+                    || !isData((d4 = base64Data[dataIndex++]))) {
+                return null;
+            }//if found "no data" just return null
+
+            b1 = base64Alphabet[d1];
+            b2 = base64Alphabet[d2];
+            b3 = base64Alphabet[d3];
+            b4 = base64Alphabet[d4];
+
+            decodedData[encodedIndex++] = (byte) (b1 << 2 | b2 >> 4);
+            decodedData[encodedIndex++] = (byte) (((b2 & 0xf) << 4) | ((b3 >> 2) & 0xf));
+            decodedData[encodedIndex++] = (byte) (b3 << 6 | b4);
+        }
+
+        if (!isData((d1 = base64Data[dataIndex++])) || !isData((d2 = base64Data[dataIndex++]))) {
+            return null;//if found "no data" just return null
+        }
+
+        b1 = base64Alphabet[d1];
+        b2 = base64Alphabet[d2];
+
+        d3 = base64Data[dataIndex++];
+        d4 = base64Data[dataIndex++];
+        if (!isData((d3)) || !isData((d4))) {//Check if they are PAD characters
+            if (isPad(d3) && isPad(d4)) {
+                if ((b2 & 0xf) != 0)//last 4 bits should be zero
+                {
+                    return null;
+                }
+                byte[] tmp = new byte[i * 3 + 1];
+                System.arraycopy(decodedData, 0, tmp, 0, i * 3);
+                tmp[encodedIndex] = (byte) (b1 << 2 | b2 >> 4);
+                return tmp;
+            } else if (!isPad(d3) && isPad(d4)) {
+                b3 = base64Alphabet[d3];
+                if ((b3 & 0x3) != 0)//last 2 bits should be zero
+                {
+                    return null;
+                }
+                byte[] tmp = new byte[i * 3 + 2];
+                System.arraycopy(decodedData, 0, tmp, 0, i * 3);
+                tmp[encodedIndex++] = (byte) (b1 << 2 | b2 >> 4);
+                tmp[encodedIndex] = (byte) (((b2 & 0xf) << 4) | ((b3 >> 2) & 0xf));
+                return tmp;
+            } else {
+                return null;
+            }
+        } else { //No PAD e.g 3cQl
+            b3 = base64Alphabet[d3];
+            b4 = base64Alphabet[d4];
+            decodedData[encodedIndex++] = (byte) (b1 << 2 | b2 >> 4);
+            decodedData[encodedIndex++] = (byte) (((b2 & 0xf) << 4) | ((b3 >> 2) & 0xf));
+            decodedData[encodedIndex++] = (byte) (b3 << 6 | b4);
+
+        }
+
+        return decodedData;
+    }
+
+    private final static String[] hexDigits = {"0", "1", "2", "3", "4", "5", "6", "7", "8", "9",
+            "a", "b", "c", "d", "e", "f"};
+
+
+
+    static String formatDate(Date date, String format) {
+        SimpleDateFormat simpleDateFormat = new SimpleDateFormat(format);
+        String format1 = simpleDateFormat.format(date);
+        return format1;
+    }
+
+    public static String RSAPriKeyEncry(String priKey, String openText) {
+        RSA rsa = new RSA(priKey, null);
+        byte[] encrypt = rsa.encrypt(openText, KeyType.PrivateKey);
+        String ciphertext = encode(encrypt);
+        return ciphertext;
+    }
+
+    public static String sendPostHaveHead(String curl, String param, String sign) {
+        String result = "";// 返回的结果
+        BufferedReader in = null;// 读取响应输入流
+        try {
+            //创建连接
+            URL url = new URL(curl);
+            HttpURLConnection connection = (HttpURLConnection) url
+                    .openConnection();
+            connection.setDoOutput(true);
+            connection.setDoInput(true);
+            connection.setRequestMethod("POST");
+            connection.setUseCaches(false);
+            connection.setInstanceFollowRedirects(true);
+            connection.setRequestProperty("Content-Type",
+                    "application/json");
+            connection.setRequestProperty("sign", sign);
+
+            connection.connect();
+
+            //POST请求
+            DataOutputStream out = new DataOutputStream(
+                    connection.getOutputStream());
+
+            out.writeBytes(param);
+            out.flush();
+            out.close();
+
+            //读取响应
+            // 定义BufferedReader输入流来读取URL的响应,并设置编码方式
+            in = new BufferedReader(new InputStreamReader(connection
+                    .getInputStream(), StandardCharsets.UTF_8));
+            String line;
+            // 读取返回的内容
+            while ((line = in.readLine()) != null) {
+                result += line;
+            }
+        } catch (Exception e) {
+            e.printStackTrace();
+            System.out.println("Http请求方法内部问题");
+        } finally {
+            try {
+                if (in != null) {
+                    in.close();
+                }
+            } catch (IOException ex) {
+                ex.printStackTrace();
+            }
+        }
+        return result;
+    }
+
+    //解密验签工具
+    public static <T> T unPackMessage(JSONObject job, Class<T> clazz, String publicKey) throws Exception {
+        //验签
+//        String sign = job.get("sign").toString();
+//        job.put("sign",null);
+//        String signString = v2SortKey(job);
+//        System.out.println("验签串:"+signString);
+//        if(!StringUtils.isEmpty(sign)){
+//            boolean verify = verify(signString, sign, publicKey);
+//            System.out.println("验签结果:"+verify);
+//            if (!verify) {
+//                throw new RuntimeException("验签失败!");
+//            }
+//        }
+
+
+        //解密
+        String strData = job.get("data").toString();
+        if (job.getBoolean("encryptedState")) {
+            String s = RSAPubKDeCode(publicKey, strData);
+            return JSONObject.parseObject(s, clazz);
+        } else {
+            return JSONObject.parseObject(strData, clazz);
+        }
+    }
+
+    //解密验签工具
+    public static <T> T unPackMessage(JSONObject job, Class<T> clazz) throws Exception {
+        return unPackMessage(job, clazz, publicKey);
+    }
+
+    /**
+     * 对象转map
+     *
+     * @param object
+     * @return
+     */
+    public static Map<String, Object> objectToMap(Object object) {
+        Map<String, Object> dataMap = new HashMap<>();
+        Class<?> clazz = object.getClass();
+        for (Field field : clazz.getDeclaredFields()) {
+            try {
+                field.setAccessible(true);
+                dataMap.put(field.getName(), field.get(object));
+            } catch (IllegalAccessException e) {
+                e.printStackTrace();
+            }
+        }
+        return dataMap;
+    }
+
+    public static String v2SortKey(Map<String, Object> parameters) {
+        SortedMap<String, String> sortMap = new TreeMap<String, String>();
+        Set<String> keySet = parameters.keySet();
+        for (String key : keySet) {
+            sortMap.put(key, String.valueOf(parameters.get(key)));
+        }
+        return createSign(sortMap);
+    }
+
+    /**
+     * RSA公钥解密
+     */
+    public static String RSAPubKDeCode(String pubKey, String cipherText) {
+        RSA rsa = new RSA(null, pubKey);
+        byte[] decode = cn.hutool.core.codec.Base64.decode(cipherText);
+        byte[] decrypt = rsa.decrypt(decode, KeyType.PublicKey);
+        String openText = new String(decrypt);
+        return openText;
+    }
+}

+ 3 - 0
hnqz-upms/hnqz-upms-biz/src/main/resources/mapper/WmScorePackageMapper.xml

@@ -1518,6 +1518,9 @@
 			<if test="query.subType != null and query.subType != ''">
 				AND p.sub_type= #{query.subType}
 			</if>
+			 <if test="query.subjectLocation != null and query.subjectLocation != ''">
+		        AND p.sub_location = #{query.subjectLocation}
+			 </if>
 			<if test="query.userNames != null">
 				AND su.realname like CONCAT('%',#{query.userNames},'%')
 			</if>