Merge remote-tracking branch 'origin/master'

This commit is contained in:
zjf committed 2025-03-03 23:55:52 +08:00
commit de2c84eeff
33 files changed
+826 -203

No files matched your search

@@ -59,115 +59,117 @@ import java.util.concurrent.TimeUnit;
@RequiredArgsConstructor
public class PjcloudAuthenticationFailureEventHandler implements AuthenticationFailureHandler {
private static final MappingJackson2HttpMessageConverter errorHttpResponseConverter = new MappingJackson2HttpMessageConverter();
private static final MappingJackson2HttpMessageConverter errorHttpResponseConverter = new MappingJackson2HttpMessageConverter();
private final StringRedisTemplate redisTemplate;
private final StringRedisTemplate redisTemplate;
private final ApplicationEventPublisher publisher;
private final ApplicationEventPublisher publisher;
private final KeyStrResolver tenantKeyStrResolver;
private final KeyStrResolver tenantKeyStrResolver;
private final RemoteUserService userService;
private final RemoteUserService userService;
/**
* Called when an authentication attempt fails.
* @param request the request during which the authentication attempt occurred.
* @param response the response.
* @param exception the exception which was thrown to reject the authentication
* request.
*/
@Override
@SneakyThrows
public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response,
AuthenticationException exception) {
String grantType = request.getParameter(OAuth2ParameterNames.GRANT_TYPE);
exception.printStackTrace();
log.info("登录失败,异常:{}", exception.getLocalizedMessage());
/**
* Called when an authentication attempt fails.
*
* @param request the request during which the authentication attempt occurred.
* @param response the response.
* @param exception the exception which was thrown to reject the authentication
* request.
*/
@Override
@SneakyThrows
public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response,
AuthenticationException exception) {
String grantType = request.getParameter(OAuth2ParameterNames.GRANT_TYPE);
exception.printStackTrace();
log.info("登录失败,异常:|{}|stack:|{}|", exception.getLocalizedMessage(), exception.getStackTrace());
// 密码模式记录错误信息
if (OAuth2ParameterNames.PASSWORD.equals(grantType)) {
String username = request.getParameter(OAuth2ParameterNames.USERNAME);
// 密码模式记录错误信息
if (OAuth2ParameterNames.PASSWORD.equals(grantType)) {
String username = request.getParameter(OAuth2ParameterNames.USERNAME);
// 密码错误记录错误次数 (TOC用户不记录)
String header = WebUtils.getRequest().getHeader(SecurityConstants.HEADER_TOC);
if (exception instanceof OAuth2AuthenticationException
&& !SecurityConstants.HEADER_TOC_YES.equals(header)) {
recordLoginFailureTimes(username);
}
// 密码错误记录错误次数 (TOC用户不记录)
String header = WebUtils.getRequest().getHeader(SecurityConstants.HEADER_TOC);
if (exception instanceof OAuth2AuthenticationException
&& !SecurityConstants.HEADER_TOC_YES.equals(header)) {
recordLoginFailureTimes(username);
}
// 记录登录失败错误信息
sendFailureEventLog(request, exception, username);
}
// 记录登录失败错误信息
sendFailureEventLog(request, exception, username);
}
// 写出错误信息
sendErrorResponse(request, response, exception);
}
// 写出错误信息
sendErrorResponse(request, response, exception);
}
/**
* 记录失败日志
* @param request HttpServletRequest
* @param exception 错误日志
* @param username 用户名
*/
private void sendFailureEventLog(HttpServletRequest request, AuthenticationException exception, String username) {
SysLogDTO logVo = SysLogUtils.getSysLog();
logVo.setTitle("登录失败");
logVo.setLogType(LogTypeEnum.ERROR.getType());
logVo.setException(exception.getLocalizedMessage());
// 发送异步日志事件
String startTimeStr = request.getHeader(CommonConstants.REQUEST_START_TIME);
if (StrUtil.isNotBlank(startTimeStr)) {
Long startTime = Long.parseLong(startTimeStr);
Long endTime = System.currentTimeMillis();
logVo.setTime(endTime - startTime);
}
String header = request.getHeader(HttpHeaders.AUTHORIZATION);
String clientId = WebUtils.extractClientId(header).orElse(null);
logVo.setServiceId(clientId);
logVo.setCreateBy(username);
logVo.setTenantId(Long.parseLong(tenantKeyStrResolver.key()));
publisher.publishEvent(new SysLogEvent(logVo));
}
/**
* 记录失败日志
*
* @param request HttpServletRequest
* @param exception 错误日志
* @param username 用户名
*/
private void sendFailureEventLog(HttpServletRequest request, AuthenticationException exception, String username) {
SysLogDTO logVo = SysLogUtils.getSysLog();
logVo.setTitle("登录失败");
logVo.setLogType(LogTypeEnum.ERROR.getType());
logVo.setException(exception.getLocalizedMessage());
// 发送异步日志事件
String startTimeStr = request.getHeader(CommonConstants.REQUEST_START_TIME);
if (StrUtil.isNotBlank(startTimeStr)) {
Long startTime = Long.parseLong(startTimeStr);
Long endTime = System.currentTimeMillis();
logVo.setTime(endTime - startTime);
}
String header = request.getHeader(HttpHeaders.AUTHORIZATION);
String clientId = WebUtils.extractClientId(header).orElse(null);
logVo.setServiceId(clientId);
logVo.setCreateBy(username);
logVo.setTenantId(Long.parseLong(tenantKeyStrResolver.key()));
publisher.publishEvent(new SysLogEvent(logVo));
}
/**
* 记录登录失败此处,如果操作阈值 调用接口锁定用户
* @param username username
*/
private void recordLoginFailureTimes(String username) {
String key = String.format("%s:%s:%s", tenantKeyStrResolver.key(), CacheConstants.LOGIN_ERROR_TIMES, username);
Long deltaTimes = ParamResolver.getLong("LOGIN_ERROR_TIMES", 5L);
Long times = redisTemplate.opsForValue().increment(key);
/**
* 记录登录失败此处,如果操作阈值 调用接口锁定用户
*
* @param username username
*/
private void recordLoginFailureTimes(String username) {
String key = String.format("%s:%s:%s", tenantKeyStrResolver.key(), CacheConstants.LOGIN_ERROR_TIMES, username);
Long deltaTimes = ParamResolver.getLong("LOGIN_ERROR_TIMES", 5L);
Long times = redisTemplate.opsForValue().increment(key);
// 自动过期时间
Long deltaTime = ParamResolver.getLong("DELTA_TIME", 1L);
redisTemplate.expire(key, deltaTime, TimeUnit.HOURS);
// 自动过期时间
Long deltaTime = ParamResolver.getLong("DELTA_TIME", 1L);
redisTemplate.expire(key, deltaTime, TimeUnit.HOURS);
if (deltaTimes <= times) {
userService.lockUser(username);
}
}
if (deltaTimes <= times) {
userService.lockUser(username);
}
}
private void sendErrorResponse(HttpServletRequest request, HttpServletResponse response,
AuthenticationException exception) throws IOException {
ServletServerHttpResponse httpResponse = new ServletServerHttpResponse(response);
httpResponse.setStatusCode(HttpStatus.UNAUTHORIZED);
String errorMessage;
private void sendErrorResponse(HttpServletRequest request, HttpServletResponse response,
AuthenticationException exception) throws IOException {
ServletServerHttpResponse httpResponse = new ServletServerHttpResponse(response);
httpResponse.setStatusCode(HttpStatus.UNAUTHORIZED);
String errorMessage;
if (exception instanceof OAuth2AuthenticationException) {
OAuth2AuthenticationException authorizationException = (OAuth2AuthenticationException) exception;
errorMessage = StrUtil.isBlank(authorizationException.getError().getDescription())
? authorizationException.getError().getErrorCode()
: authorizationException.getError().getDescription();
if (exception instanceof OAuth2AuthenticationException) {
OAuth2AuthenticationException authorizationException = (OAuth2AuthenticationException) exception;
errorMessage = StrUtil.isBlank(authorizationException.getError().getDescription())
? authorizationException.getError().getErrorCode()
: authorizationException.getError().getDescription();
this.errorHttpResponseConverter.write(
R.failed(authorizationException.getError().getErrorCode(), errorMessage),
MediaType.APPLICATION_JSON, httpResponse);
this.errorHttpResponseConverter.write(
R.failed(authorizationException.getError().getErrorCode(), errorMessage),
MediaType.APPLICATION_JSON, httpResponse);
}
else {
errorMessage = exception.getLocalizedMessage();
this.errorHttpResponseConverter.write(R.failed(errorMessage), MediaType.APPLICATION_JSON, httpResponse);
}
}
} else {
errorMessage = exception.getLocalizedMessage();
this.errorHttpResponseConverter.write(R.failed(errorMessage), MediaType.APPLICATION_JSON, httpResponse);
}
}
}
@@ -138,5 +138,7 @@ public interface CacheConstants {
String THIRDPARTY_ZY_MER_TOKEN = "thirdparty:zy:mer_token";
String THIRDPARTY_ZY_SELF_TOKEN = "thirdparty:zy:self_token:";
/* ************************************* end 第三方对接相关 end ************************************* */
}
@@ -38,4 +38,10 @@ public enum HardOrderTypeEnum {
return refundList.contains(type);
}
public static List<String> getExternalCodes() {
return List.of(
HardOrderTypeEnum.FOREIGN_TICKET.type,
HardOrderTypeEnum.STRIDE_DEPT.type
);
}
}
@@ -31,6 +31,8 @@ public class HardOrderDto extends HardOrderEntity implements BaseIsIncludeTreeIn
private LocalDateTime[] payTimeList;
private List<String> orderTypeCodes;
/**
* 是否查询购物车列表
*/
@@ -0,0 +1,48 @@
package com.bsd.pjcloud.hard.api.vo.order;
import lombok.Data;
@Data
public class HardZyCardSyncVo {
/**
* 总人数
*/
private Long totalNum;
/**
* 总金额
*/
private Long totalMoney;
/**
* 年总人数
*/
private Long totalNumYear;
/**
* 年总金额
*/
private Long totalMoneyYear;
/**
* 月总人数
*/
private Long totalNumMonth;
/**
* 月总金额
*/
private Long totalMoneyMonth;
/**
* 月总人数
*/
private Long totalNumDay;
/**
* 月总金额
*/
private Long totalMoneyDay;
}
@@ -13,11 +13,13 @@ import com.bsd.pjcloud.common.core.util.R;
import com.bsd.pjcloud.common.log.annotation.SysLog;
import com.bsd.pjcloud.hard.api.constant.HardTypeEnum;
import com.bsd.pjcloud.hard.api.constant.order.HardOrderStatusEnum;
import com.bsd.pjcloud.hard.api.constant.order.HardOrderTypeEnum;
import com.bsd.pjcloud.hard.api.dto.order.HardDeptTotalDto;
import com.bsd.pjcloud.hard.api.dto.order.HardOrderDto;
import com.bsd.pjcloud.hard.api.vo.order.HardDeptTotalVo;
import com.bsd.pjcloud.hard.api.vo.order.HardOrderCsVo;
import com.bsd.pjcloud.hard.api.vo.order.HardOrderSbVo;
import com.bsd.pjcloud.hard.api.vo.order.HardZyCardSyncVo;
import com.bsd.pjcloud.hard.service.HardOrderTotalService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.security.SecurityRequirement;
@@ -45,6 +47,19 @@ public class HardOrderTotalController {
private final HardOrderTotalService HardOrderTotalService;
/* ************************************* start 远程调用 start ************************************* */
@PostMapping("/zy-card-sync")
@Operation(summary = "正元本地一卡通交易数据同步")
public R<HardZyCardSyncVo> zyCardSync() {
HardOrderDto dto = new HardOrderDto();
dto.setOrderStatusCodes(HardOrderStatusEnum.getPayPrice());
dto.setOrderTypeCodes(HardOrderTypeEnum.getExternalCodes());
return R.ok(HardOrderTotalService.totalYearMonthDay(dto));
}
/* ************************************* end 远程调用 end ************************************* */
@PostMapping("/page-list-sb")
@Operation(summary = "设备交易记录")
public R<Page<HardOrderSbVo>> pageListSb(@ParameterObject Page page, @RequestBody HardOrderDto dto) {
@@ -11,10 +11,7 @@ import com.bsd.pjcloud.hard.api.dto.order.HardOrderSumAndCountDto;
import com.bsd.pjcloud.hard.api.entity.HardManagerEntity;
import com.bsd.pjcloud.hard.api.entity.order.HardAfterSaleEntity;
import com.bsd.pjcloud.hard.api.entity.order.HardOrderEntity;
import com.bsd.pjcloud.hard.api.vo.order.HardOrderCsVo;
import com.bsd.pjcloud.hard.api.vo.order.HardOrderSbVo;
import com.bsd.pjcloud.hard.api.vo.order.HardOrderSumAndCountVo;
import com.bsd.pjcloud.hard.api.vo.order.HardOrderVo;
import com.bsd.pjcloud.hard.api.vo.order.*;
import com.github.yulichang.wrapper.MPJLambdaWrapper;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
@@ -98,4 +95,6 @@ public interface HardOrderMapper extends PjcloudBaseMapper<HardOrderEntity> {
List<HardOrderCsVo> listCs(@Param("dto") HardOrderDto dto);
List<HardOrderSumAndCountVo> sumAndCount(@Param("dto") HardOrderSumAndCountDto dto);
HardZyCardSyncVo totalYearMonthDay(@Param("dto") HardOrderDto hardOrderDto);
}
@@ -6,6 +6,7 @@ import com.bsd.pjcloud.hard.api.dto.order.HardOrderDto;
import com.bsd.pjcloud.hard.api.vo.order.HardDeptTotalVo;
import com.bsd.pjcloud.hard.api.vo.order.HardOrderCsVo;
import com.bsd.pjcloud.hard.api.vo.order.HardOrderSbVo;
import com.bsd.pjcloud.hard.api.vo.order.HardZyCardSyncVo;
import java.util.List;
@@ -20,4 +21,6 @@ public interface HardOrderTotalService {
List<HardOrderCsVo> listCs(HardOrderDto dto);
List<HardDeptTotalVo> pageListDept(HardDeptTotalDto dto);
HardZyCardSyncVo totalYearMonthDay(HardOrderDto dto);
}
@@ -8,16 +8,14 @@ import com.bsd.pjcloud.admin.api.entity.SysDept;
import com.bsd.pjcloud.admin.api.feign.RemoteDeptService;
import com.bsd.pjcloud.common.core.util.CollectionUtils;
import com.bsd.pjcloud.hard.api.constant.order.HardOrderStatusEnum;
import com.bsd.pjcloud.hard.api.constant.order.HardOrderTypeEnum;
import com.bsd.pjcloud.hard.api.dto.HardManagerDto;
import com.bsd.pjcloud.hard.api.dto.order.HardDeptTotalDto;
import com.bsd.pjcloud.hard.api.dto.order.HardOrderDto;
import com.bsd.pjcloud.hard.api.dto.order.HardOrderSumAndCountDto;
import com.bsd.pjcloud.hard.api.entity.HardManagerEntity;
import com.bsd.pjcloud.hard.api.utils.HardUtil;
import com.bsd.pjcloud.hard.api.vo.order.HardDeptTotalVo;
import com.bsd.pjcloud.hard.api.vo.order.HardOrderCsVo;
import com.bsd.pjcloud.hard.api.vo.order.HardOrderSbVo;
import com.bsd.pjcloud.hard.api.vo.order.HardOrderSumAndCountVo;
import com.bsd.pjcloud.hard.api.vo.order.*;
import com.bsd.pjcloud.hard.mapper.HardManagerMapper;
import com.bsd.pjcloud.hard.mapper.order.HardOrderMapper;
import com.bsd.pjcloud.hard.service.HardOrderTotalService;
@@ -291,4 +289,9 @@ public class HardOrderTotalServiceImpl implements HardOrderTotalService {
});
return resultListFuture.join();
}
@Override
public HardZyCardSyncVo totalYearMonthDay(HardOrderDto dto) {
return hardOrderMapper.totalYearMonthDay(dto);
}
}
@@ -189,4 +189,32 @@
group by a.dept_id
</select>
<select id="totalYearMonthDay" resultType="com.bsd.pjcloud.hard.api.vo.order.HardZyCardSyncVo">
SELECT
COUNT(0) AS totalNum,
SUM(a.pay_price) AS totalMoney,
SUM(CASE WHEN YEAR(a.create_time) = YEAR(CURRENT_DATE()) THEN 1 ELSE 0 END) AS totalNumYear,
SUM(CASE WHEN YEAR(a.create_time) = YEAR(CURRENT_DATE()) THEN a.pay_price ELSE 0 END) AS totalMoneyYear,
SUM(CASE WHEN YEAR(a.create_time) = YEAR(CURRENT_DATE()) AND MONTH(a.create_time) = MONTH(CURRENT_DATE()) THEN 1 ELSE 0 END) AS totalNumMonth,
SUM(CASE WHEN YEAR(a.create_time) = YEAR(CURRENT_DATE()) AND MONTH(a.create_time) = MONTH(CURRENT_DATE()) THEN a.pay_price ELSE 0 END) AS totalMoneyMonth,
SUM(CASE WHEN YEAR(a.create_time) = YEAR(CURRENT_DATE()) AND MONTH(a.create_time) = MONTH(CURRENT_DATE()) AND DAY(a.create_time) = DAY(CURRENT_DATE()) THEN 1 ELSE 0 END) AS totalNumDay,
SUM(CASE WHEN YEAR(a.create_time) = YEAR(CURRENT_DATE()) AND MONTH(a.create_time) = MONTH(CURRENT_DATE()) AND DAY(a.create_time) = DAY(CURRENT_DATE()) THEN a.pay_price ELSE 0 END) AS totalMoneyDay
FROM
hard_order a
<where>
a.del_flag = 0
<if test="dto.orderStatusCodes != null and dto.orderStatusCodes.size() != 0">
and a.order_status in
<foreach collection="dto.orderStatusCodes" item="v" open="(" close=")" separator=",">
#{v}
</foreach>
</if>
<if test="dto.orderTypeCodes != null and dto.orderTypeCodes.size() != 0">
and a.order_type in
<foreach collection="dto.orderTypeCodes" item="v" open="(" close=")" separator=",">
#{v}
</foreach>
</if>
</where>
</select>
</mapper>
@@ -8,9 +8,6 @@ import lombok.NoArgsConstructor;
/**
* 获取区域编码
*/
//@Builder
//@AllArgsConstructor
//@NoArgsConstructor
@Data
public class ZyForeignGetRegionIdByTokenDto {
}
@@ -14,15 +14,17 @@ import lombok.NoArgsConstructor;
@NoArgsConstructor
@Data
public class ZyMerSyncDealerInfoDto {
/**
* 所属记账单位编号
*/
private String EPID;
/**
* 商户所在系统的键值
*/
private String DealerKeyObj;
/**
* 商户名称
*/
private String DealerName;
/**
* 商户是否有效0:禁用 1:有效
@@ -30,9 +32,10 @@ public class ZyMerSyncDealerInfoDto {
private Integer IsValid;
/**
* 所属记账单位编号
* 商户名称
*/
private String EPID;
private String DealerName;
/**
* 每次推送版本号,格式化为14位字符串,如果是数字不足14位的,前面补0。
@@ -42,5 +45,5 @@ public class ZyMerSyncDealerInfoDto {
/**
* 商户类型,0食堂餐厅,1超市,2普通商家,3其他;不传默认是食堂餐厅类型
*/
private String DealerType;
private Integer DealerType;
}
@@ -0,0 +1,37 @@
package com.bsd.pjcloud.thirdparty.dto.zy.self;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class ZySelfTokenDto {
/**
* 第三方app用户id
*/
private String appid;
/**
* 第三方app用户密钥
*/
private String appSecret;
/**
* 用户唯一标识
*/
private String token;
/**
* 登录时间
*/
private Long loginTime;
/**
* 过期时间
*/
private Long expireTime;
}
@@ -0,0 +1,17 @@
package com.bsd.pjcloud.thirdparty.vo.zy;
import lombok.Data;
@Data
public class ZyBaseEncryptVo {
// 请求成功
public static String successCode = "0";
private String code;
private String data;
public boolean isSuccess() {
return successCode.equals(code);
}
}
@@ -1,14 +1,49 @@
package com.bsd.pjcloud.thirdparty.vo.zy;
import cn.hutool.core.util.ObjectUtil;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
public class ZyBaseVo {
// 请求成功
public static String successCode = "0";
private Integer code;
// 系统繁忙,具体看错误消息msg
public static String errorCode = "-1";
// 应用服务错误
public static String serviceError = "10003";
// 无效卡,错误信息可查看msg
public static String invalidCard = "10004";
// 记账单位数据不存在,请先同步
public static String accountBookIsEmpty = "20001";
// 请同步最新数据
public static String syncNewData = "20002";
// 缺少签名参数
public static String signIsEmpty = "30001";
// 无效的appId
public static String appIdError = "40001";
// 无效的appSecret
public static String appSecretError = "40002";
// 数据加密认证失败!sign值验证失败
public static String signError = "40003";
// 无效的access_token
public static String accessTokenError = "40004";
public static String defaultErrorMsg = "服务异常,请重试或联系管理员";
private String code;
private String msg;
@@ -12,7 +12,7 @@ public class ZyForeignGetRegionIdByTokenVo extends ZyBaseVo {
private VoData data;
@Data
static class VoData {
public static class VoData {
/**
* 区域编码
*/
@@ -22,7 +22,7 @@ public class ZyForeignGetRegionIdByTokenVo extends ZyBaseVo {
*/
private String regionAllName;
/**
* 地市简称
* 地市简称
*/
private String regionName;
}
@@ -1,13 +1,52 @@
package com.bsd.pjcloud.thirdparty.vo.zy.self;
import com.bsd.pjcloud.thirdparty.vo.zy.ZyBaseVo;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* 第三方一卡通系统提供冲正接口
*/
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class ZySelfCorrectVo extends ZyBaseVo {
/**
* 帐号
*/
private String accNum;
/**
* 用户姓名
*/
private String accName;
/**
* 人员编号
*/
private String perCode;
/**
* 订单流水号,全局唯一,第三方流水号
*/
private String platformSerialNum;
/**
* 智慧园区通刷服务平台扣费流水号
*/
private String serialNum;
/**
* 消费金额,格式是XX.XX元
*/
private String amount;
/**
* 第三方一卡通系统返回正常扣费的时间点 统一为yyyy-MM-dd HH:mm:ss
*/
private String recDate;
}
@@ -1,12 +1,18 @@
package com.bsd.pjcloud.thirdparty.vo.zy.self;
import com.bsd.pjcloud.thirdparty.vo.zy.ZyBaseVo;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* 第三方提供获取token
*/
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class ZySelfGetTokenVo extends ZyBaseVo {
private String access_token;
@@ -1,11 +1,52 @@
package com.bsd.pjcloud.thirdparty.vo.zy.self;
import com.bsd.pjcloud.thirdparty.vo.zy.ZyBaseVo;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* 第三方一卡通系统提供扣费接口
*/
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class ZySelfPayVo extends ZyBaseVo {
/**
* 帐号
*/
private String accNum;
/**
* 用户姓名
*/
private String accName;
/**
* 人员编号
*/
private String perCode;
/**
* 订单流水号,全局唯一,第三方流水号
*/
private String platformSerialNum;
/**
* 智慧园区通刷服务平台扣费流水号
*/
private String serialNum;
/**
* 消费金额,格式是XX.XX元
*/
private String amount;
/**
* 第三方一卡通系统返回正常扣费的时间点 统一为yyyy-MM-dd HH:mm:ss
*/
private String recDate;
}
+11
View File
@@ -104,6 +104,17 @@
<groupId>com.bsd</groupId>
<artifactId>pjcloud-common-seata</artifactId>
</dependency>
<dependency>
<groupId>commons-codec</groupId>
<artifactId>commons-codec</artifactId>
<version>1.15</version>
</dependency>
<!-- Token生成与解析-->
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
<version>0.9.1</version>
</dependency>
</dependencies>
<profiles>
<profile>
@@ -22,4 +22,10 @@ public class ZyConfig {
private String selfAppSecret;
private Long selfExpiresIn;
private String selfTokenKey;
private String selfTokenSecret;
}
@@ -0,0 +1,55 @@
package com.bsd.pjcloud.thirdparty.controller.zy;
import com.bsd.pjcloud.thirdparty.dto.zy.self.ZySelfCorrectDto;
import com.bsd.pjcloud.thirdparty.dto.zy.self.ZySelfGetTokenDto;
import com.bsd.pjcloud.thirdparty.dto.zy.self.ZySelfPayDto;
import com.bsd.pjcloud.thirdparty.service.impl.ZySelfService;
import com.bsd.pjcloud.thirdparty.vo.zy.self.ZySelfCorrectVo;
import com.bsd.pjcloud.thirdparty.vo.zy.self.ZySelfGetTokenVo;
import com.bsd.pjcloud.thirdparty.vo.zy.self.ZySelfPayVo;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.security.SecurityRequirement;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import org.springframework.http.HttpHeaders;
import org.springframework.web.bind.annotation.*;
import java.util.Date;
import java.util.Map;
@RestController
@RequiredArgsConstructor
@RequestMapping("/third/zy")
@Tag(description = "thirdPartyDept", name = "正元接口对接")
@SecurityRequirement(name = HttpHeaders.AUTHORIZATION)
public class ZySelfController {
private final ZySelfService zySelfService;
@GetMapping("/checkSystemStatus")
@Operation(summary = "第三方url健康探测", description = "第三方url健康探测")
public Map<String, Object> checkSystemStatus() {
return zySelfService.checkSystemStatus();
}
@GetMapping("/getToken")
@Operation(summary = "第三方提供获取token", description = "第三方提供获取token")
public ZySelfGetTokenVo getToken(ZySelfGetTokenDto params) {
return zySelfService.getToken(params);
}
@PostMapping("/correct")
@Operation(summary = "第三方一卡通系统提供冲正接口", description = "第三方一卡通系统提供冲正接口")
public ZySelfCorrectVo correct(@RequestBody ZySelfCorrectDto params, @RequestParam(value = "access_token", required = false) String accessToken) {
return zySelfService.correct(params, accessToken);
}
@PostMapping("/getToken")
@Operation(summary = "第三方一卡通系统提供扣费接口", description = "第三方一卡通系统提供扣费接口")
public ZySelfPayVo pay(@RequestBody ZySelfPayDto params, @RequestParam(value = "access_token", required = false) String accessToken) {
return zySelfService.pay(params, accessToken);
}
}
@@ -0,0 +1,8 @@
package com.bsd.pjcloud.thirdparty.service;
public interface ZyDoForeignService {
// 本地一卡通交易数据同步
void syncNativeCardTradeInfo();
}
@@ -15,6 +15,6 @@ public interface ZyForeignService {
/**
* 获取区域编码
*/
ZyForeignGetRegionIdByTokenVo getRegionIdByToken(ZyForeignGetRegionIdByTokenDto dto);
ZyForeignGetRegionIdByTokenVo.VoData getRegionIdByToken();
}
@@ -6,12 +6,14 @@ import com.bsd.pjcloud.thirdparty.dto.zy.mer.ZyMerSyncDealerInfoDto;
import com.bsd.pjcloud.thirdparty.dto.zy.mer.ZyMerSyncEnterpriseInfoDto;
import com.bsd.pjcloud.thirdparty.vo.zy.mer.*;
import java.util.List;
public interface ZyMerService {
/**
* 商户信息同步
*/
ZyMerSyncDealerInfoVo syncDealerInfoApi(ZyMerSyncDealerInfoDto dto);
ZyMerSyncDealerInfoVo syncDealerInfoApi(List<ZyMerSyncDealerInfoDto> dto);
/**
* 记账单位同步
@@ -1,4 +1,33 @@
package com.bsd.pjcloud.thirdparty.service.impl;
import com.bsd.pjcloud.thirdparty.dto.zy.self.ZySelfCorrectDto;
import com.bsd.pjcloud.thirdparty.dto.zy.self.ZySelfGetTokenDto;
import com.bsd.pjcloud.thirdparty.dto.zy.self.ZySelfPayDto;
import com.bsd.pjcloud.thirdparty.vo.zy.self.ZySelfCorrectVo;
import com.bsd.pjcloud.thirdparty.vo.zy.self.ZySelfGetTokenVo;
import com.bsd.pjcloud.thirdparty.vo.zy.self.ZySelfPayVo;
import java.util.Map;
public interface ZySelfService {
/**
* 第三方url健康探测
*/
Map<String, Object> checkSystemStatus();
/**
* 第三方提供获取token
*/
ZySelfGetTokenVo getToken(ZySelfGetTokenDto params);
/**
* 第三方一卡通系统提供冲正接口
*/
ZySelfCorrectVo correct(ZySelfCorrectDto params, String accessToken);
/**
* 第三方一卡通系统提供扣费接口
*/
ZySelfPayVo pay(ZySelfPayDto params, String accessToken);
}
@@ -0,0 +1,31 @@
package com.bsd.pjcloud.thirdparty.service.impl.zy;
import cn.hutool.core.util.ObjectUtil;
import com.bsd.pjcloud.thirdparty.dto.zy.foreign.ZyForeignSyncNativeCardTradeInfoDto;
import com.bsd.pjcloud.thirdparty.service.ZyDoForeignService;
import com.bsd.pjcloud.thirdparty.vo.zy.foreign.ZyForeignGetRegionIdByTokenVo;
import com.bsd.pjcloud.thirdparty.vo.zy.foreign.ZyForeignSyncNativeCardTradeInfoVo;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.validation.annotation.Validated;
@Service
@Validated
@Slf4j
@RequiredArgsConstructor
public class ZyDoForeignServiceImpl implements ZyDoForeignService {
private final ZyForeignServiceImpl zyForeignServiceImpl;
@Override
public void syncNativeCardTradeInfo() {
ZyForeignGetRegionIdByTokenVo.VoData region = zyForeignServiceImpl.getRegionIdByToken();
if (ObjectUtil.isEmpty(region)) {
return;
}
ZyForeignSyncNativeCardTradeInfoDto asyncDto = new ZyForeignSyncNativeCardTradeInfoDto();
asyncDto.setRegionCode(region.getRegionCode());
ZyForeignSyncNativeCardTradeInfoVo vo = zyForeignServiceImpl.syncNativeCardTradeInfoApi(asyncDto);
}
}
@@ -1,5 +1,6 @@
package com.bsd.pjcloud.thirdparty.service.impl.zy;
import cn.hutool.core.codec.Base64;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.http.HttpRequest;
import cn.hutool.json.JSONUtil;
@@ -9,6 +10,7 @@ import com.bsd.pjcloud.thirdparty.dto.zy.foreign.ZyForeignSyncNativeCardTradeInf
import com.bsd.pjcloud.thirdparty.service.impl.ZyForeignService;
import com.bsd.pjcloud.thirdparty.utils.zy.api.ZyApi;
import com.bsd.pjcloud.thirdparty.utils.zy.api.ZyApiTool;
import com.bsd.pjcloud.thirdparty.vo.zy.ZyBaseEncryptVo;
import com.bsd.pjcloud.thirdparty.vo.zy.foreign.ZyForeignGetRegionIdByTokenVo;
import com.bsd.pjcloud.thirdparty.vo.zy.foreign.ZyForeignSyncNativeCardTradeInfoVo;
import lombok.RequiredArgsConstructor;
@@ -64,24 +66,23 @@ public class ZyForeignServiceImpl implements ZyForeignService {
* 获取区域编码
*/
@Override
public ZyForeignGetRegionIdByTokenVo getRegionIdByToken(ZyForeignGetRegionIdByTokenDto dto) {
public ZyForeignGetRegionIdByTokenVo.VoData getRegionIdByToken() {
String url = zyConfig.getBaseUrl() + ZyApi.Foreign.GET_REGION_ID_BY_TOKEN;
try {
url = String.format(url, zyApiTool.getToken());
Map<String, Object> encryptionBody = new HashMap<>();
encryptionBody.put("accClasses", dto);
String body = zyApiTool.getEncryptionDto(encryptionBody);
String res = HttpRequest.post(url)
.body(body)
.execute()
.body();
String res = HttpRequest.get(url).execute().body();
if (ObjectUtil.isEmpty(res)) {
throw new RuntimeException("response is empty");
}
ZyForeignGetRegionIdByTokenVo vo = JSONUtil.toBean(res, ZyForeignGetRegionIdByTokenVo.class);
if (!vo.isSuccess()) {
throw new RuntimeException(String.format("请求错误res|%s|url|%s|body|%s|", res, url, body));
ZyBaseEncryptVo baseEncryptVo = JSONUtil.toBean(res, ZyBaseEncryptVo.class);
if (ObjectUtil.isEmpty(baseEncryptVo)) {
throw new RuntimeException(String.format("解密错误res|%s|url|%s|res|%s|", res, url, baseEncryptVo));
}
if (!baseEncryptVo.isSuccess()) {
throw new RuntimeException(String.format("请求错误res|%s|url|%s|", res, url));
}
String json = Base64.decodeStr(baseEncryptVo.getData());
ZyForeignGetRegionIdByTokenVo.VoData vo = JSONUtil.toBean(json, ZyForeignGetRegionIdByTokenVo.VoData.class);
return vo;
} catch (Exception e) {
log.error("|{}||getRegionIdByToken|意外的错误error|{}|", TAG, e.getMessage());
@@ -1,5 +1,6 @@
package com.bsd.pjcloud.thirdparty.service.impl.zy;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.http.HttpRequest;
import cn.hutool.json.JSONUtil;
@@ -17,7 +18,9 @@ import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.validation.annotation.Validated;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@Service
@@ -36,14 +39,23 @@ public class ZyMerServiceImpl implements ZyMerService {
* 商户信息同步
*/
@Override
public ZyMerSyncDealerInfoVo syncDealerInfoApi(ZyMerSyncDealerInfoDto dto) {
public ZyMerSyncDealerInfoVo syncDealerInfoApi(List<ZyMerSyncDealerInfoDto> dto) {
if (ObjectUtil.isEmpty(dto)) {
return null;
}
List<Map<String, Object>> listMap = new ArrayList<>();
for (ZyMerSyncDealerInfoDto v : dto) {
Map<String, Object> map = zyApiTool.removeEmptyMap(BeanUtil.beanToMap(v));
listMap.add(map);
}
String url = zyConfig.getBaseUrl() + ZyApi.Mer.SYNC_DEALER_INFO;
try {
url = String.format(url, zyApiTool.getToken());
Map<String, Object> encryptionBody = new HashMap<>();
encryptionBody.put("dealers", dto);
encryptionBody.put("dealers", listMap);
String body = zyApiTool.getEncryptionDto(encryptionBody);
String res = HttpRequest.post(url)
.contentType("application/x-www-form-urlencoded")
.body(body)
.execute()
.body();
@@ -1,14 +1,162 @@
package com.bsd.pjcloud.thirdparty.service.impl.zy;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.json.JSONUtil;
import com.bsd.pjcloud.common.core.constant.CacheConstants;
import com.bsd.pjcloud.thirdparty.config.ZyConfig;
import com.bsd.pjcloud.thirdparty.dto.zy.self.ZySelfCorrectDto;
import com.bsd.pjcloud.thirdparty.dto.zy.self.ZySelfGetTokenDto;
import com.bsd.pjcloud.thirdparty.dto.zy.self.ZySelfPayDto;
import com.bsd.pjcloud.thirdparty.dto.zy.self.ZySelfTokenDto;
import com.bsd.pjcloud.thirdparty.service.impl.ZySelfService;
import com.bsd.pjcloud.thirdparty.vo.zy.ZyBaseVo;
import com.bsd.pjcloud.thirdparty.vo.zy.self.ZySelfCorrectVo;
import com.bsd.pjcloud.thirdparty.vo.zy.self.ZySelfGetTokenVo;
import com.bsd.pjcloud.thirdparty.vo.zy.self.ZySelfPayVo;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.validation.annotation.Validated;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;
@Service
@Validated
@Slf4j
@RequiredArgsConstructor
public class ZySelfServiceImpl implements ZySelfService {
private final String TAG = "第三方需提供的接口api";
private final ZyConfig zyConfig;
private final StringRedisTemplate redisTemplate;
/**
* 第三方url健康探测
*/
@Override
public Map<String, Object> checkSystemStatus() {
String systemTime = DateUtil.formatDateTime(new Date());
Map<String, Object> result = Map.of("systemTime", systemTime);
log.info("|{}|checkSystemStatus res|{}|", TAG, JSONUtil.toJsonStr(result));
return result;
}
/**
* 第三方一卡通系统提供冲正接口
*/
@Override
public ZySelfCorrectVo correct(ZySelfCorrectDto params, String accessToken) {
ZySelfCorrectVo result = new ZySelfCorrectVo();
result.setCode(ZyBaseVo.errorCode);
boolean isToken = checkIsToken(accessToken);
if (!isToken) {
result.setCode(ZyBaseVo.accessTokenError);
result.setMsg("无效的access_token");
return result;
}
return null;
}
/**
* 第三方一卡通系统提供扣费接口
*/
@Override
public ZySelfPayVo pay(ZySelfPayDto params, String accessToken) {
ZySelfCorrectVo result = new ZySelfCorrectVo();
result.setCode(ZyBaseVo.errorCode);
boolean isToken = checkIsToken(accessToken);
if (!isToken) {
result.setCode(ZyBaseVo.accessTokenError);
result.setMsg("无效的access_token");
}
return null;
}
/**
* 第三方提供获取token
*/
@Override
public ZySelfGetTokenVo getToken(ZySelfGetTokenDto params) {
ZySelfGetTokenVo result = new ZySelfGetTokenVo();
result.setCode(ZyBaseVo.errorCode);
if (ObjectUtil.isEmpty(params.getAppid()) || ObjectUtil.equals(params.getAppid(), zyConfig.getSelfAppId())) {
result.setMsg("appid 无效");
return result;
}
if (ObjectUtil.isEmpty(params.getAppsecret()) || ObjectUtil.equals(params.getAppsecret(), zyConfig.getSelfAppSecret())) {
result.setMsg("appSecret 无效");
return result;
}
String redisKey = CacheConstants.THIRDPARTY_ZY_SELF_TOKEN;
redisTemplate.opsForValue().getAndDelete(redisKey);
try {
// 生成token
String token = generateToken(params);
result.setCode(ZyBaseVo.successCode);
result.setAccess_token(token);
result.setExpires_in(zyConfig.getSelfExpiresIn().toString());
return result;
} catch (Exception e) {
log.error("|{}|getToken意外的错误dto|{}|error|{}|stack|{}|", TAG, JSONUtil.toJsonStr(params), e.getMessage(), e.getStackTrace());
result.setMsg(ZyBaseVo.defaultErrorMsg);
return result;
}
}
private boolean checkIsToken(String string) {
if (ObjectUtil.isEmpty(string)) {
log.info("|{}|checkIsToken校验错误,未传入token|{}|", TAG, string);
return false;
}
Claims claims = Jwts.parser()
.setSigningKey(zyConfig.getSelfAppSecret())
.parseClaimsJws(string)
.getBody();
String token = (String) claims.get(zyConfig.getSelfTokenKey());
String redisKey = CacheConstants.THIRDPARTY_ZY_SELF_TOKEN + token;
String json = redisTemplate.opsForValue().get(redisKey);
if (ObjectUtil.isEmpty(json)) {
log.info("|{}|checkIsToken校验错误token|{}|", TAG, string);
return false;
}
log.info("|{}|checkIsToken校验成功info|{}|", TAG, json);
return true;
}
// 生成token
private String generateToken(ZySelfGetTokenDto dto) {
ZySelfTokenDto selfTokenDto = new ZySelfTokenDto();
String token = IdUtil.fastUUID();
Map<String, Object> claims = new HashMap<>();
claims.put(zyConfig.getSelfTokenKey(), token);
// 刷新token
selfTokenDto.setToken(token);
selfTokenDto.setAppid(dto.getAppid());
selfTokenDto.setAppSecret(dto.getAppsecret());
refreshToken(selfTokenDto);
return Jwts.builder()
.setClaims(claims)
.signWith(SignatureAlgorithm.HS512, zyConfig.getSelfTokenSecret()).compact();
}
/// 刷新token
public void refreshToken(ZySelfTokenDto dto) {
dto.setLoginTime(System.currentTimeMillis());
dto.setExpireTime(dto.getLoginTime() + zyConfig.getSelfExpiresIn() + 100);
String redisKey = CacheConstants.THIRDPARTY_ZY_SELF_TOKEN + dto.getToken();
redisTemplate.opsForValue().set(redisKey, JSONUtil.toJsonStr(dto), zyConfig.getSelfExpiresIn(), TimeUnit.MINUTES);
}
}
@@ -1,23 +1,27 @@
package com.bsd.pjcloud.thirdparty.utils.zy.api;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.codec.Base64;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.URLUtil;
import cn.hutool.http.HttpRequest;
import cn.hutool.json.JSONUtil;
import com.bsd.pjcloud.common.core.constant.CacheConstants;
import com.bsd.pjcloud.thirdparty.config.ZyConfig;
import com.bsd.pjcloud.thirdparty.vo.zy.mer.ZyMerGetTokenVo;
import io.undertow.security.idm.DigestAlgorithm;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.validation.annotation.Validated;
import org.apache.commons.codec.digest.DigestUtils;
import java.nio.charset.StandardCharsets;
import java.util.Base64;
import java.util.HashMap;
import java.util.Map;
import static org.apache.commons.codec.digest.DigestUtils.md5Hex;
import java.util.Set;
import java.util.TreeMap;
import java.util.concurrent.TimeUnit;
@Component
@Validated
@@ -25,13 +29,13 @@ import static org.apache.commons.codec.digest.DigestUtils.md5Hex;
@RequiredArgsConstructor
public class ZyApiTool {
private final String TAG = "正元请求工具类";
static private final String TAG = "正元请求工具类";
private final ZyConfig zyConfig;
private final StringRedisTemplate redisTemplate;
public ZyMerGetTokenVo getTokenApi() {
public ZyMerGetTokenVo getTokenApi() throws Exception {
String url = zyConfig.getBaseUrl() + ZyApi.Mer.GET_TOKEN;
url = String.format(url, zyConfig.getAppId(), zyConfig.getAppSecret());
try {
@@ -43,12 +47,12 @@ public class ZyApiTool {
throw new RuntimeException("response is empty");
}
ZyMerGetTokenVo vo = JSONUtil.toBean(res, ZyMerGetTokenVo.class);
if (!vo.isSuccess()) {
if (ObjectUtil.isEmpty(vo) || !ObjectUtil.isAllNotEmpty(vo.getAccess_token(), vo.getExpires_in())) {
throw new RuntimeException(String.format("请求错误res|%s|url|%s|", res, url));
}
return vo;
} catch (Exception e) {
log.error("|{}||getTokenApi|意外的错误error|{}|", TAG, e.getMessage());
log.error("|{}||getTokenApi|意外的错误error|{}|stack:|{}|", TAG, e.getMessage(), e.getStackTrace());
}
return null;
}
@@ -61,7 +65,16 @@ public class ZyApiTool {
ZyMerGetTokenVo vo = getTokenApi();
if (ObjectUtil.isNotEmpty(vo)) {
String accessToken = vo.getAccess_token();
String expiresIn = vo.getExpires_in();
redisTemplate.opsForValue().set(redisKey, accessToken);
try {
long expiresInNum = Long.parseLong(expiresIn);
if (ObjectUtil.isNotEmpty(expiresInNum) && expiresInNum > 100) {
redisTemplate.expire(redisKey, expiresInNum - 100, TimeUnit.SECONDS);
}
} catch (Exception e) {
log.error("|{}|意外的错误error|{}|stack|{}|", TAG, e.getMessage(), e.getStackTrace());
}
return accessToken;
}
}
@@ -72,15 +85,58 @@ public class ZyApiTool {
return null;
}
public <T> String getEncryptionDto(T params) {
String json = JSONUtil.toJsonStr(params);
String encodedData = Base64.getEncoder().encodeToString(json.getBytes(StandardCharsets.UTF_8));
String stringToSign = String.format("data=%s&key=%s", json, zyConfig.getAppId());
String sign = md5Hex(stringToSign);
public String getEncryptionDto(Map<String, Object> params) {
Map<String, Object> body = new HashMap<>();
body.put("data", encodedData);
body.put("sign", sign);
body.put("data", params);
prePost(body);
return JSONUtil.toJsonStr(body);
}
public Map<String, Object> removeEmptyMap(Map<String, Object> params) {
for (Map.Entry<String, Object> entry : params.entrySet()) {
Object value = entry.getValue();
if (value == null) {
params.remove(entry.getKey());
}
}
return params;
}
private void prePost(Map<String, Object> params) {
for (Map.Entry<String, Object> entry : params.entrySet()) {
Object value = entry.getValue();
if (value instanceof String) {
entry.setValue(URLUtil.encode((String) value));
} else {
String json = JSONUtil.toJsonStr(value);
entry.setValue(json);
}
}
String sign = generateSign(params);
for (Map.Entry<String, Object> entry : params.entrySet()) {
Object value = entry.getValue();
if (value instanceof String) {
entry.setValue(Base64.encode((String) value));
} else {
entry.setValue(Base64.encode(value.toString()));
}
}
params.put("sign", sign);
}
private String generateSign(Map<String, Object> params) {
// 将参数以参数名的字典升序排序
Map<String, Object> sortParams = new TreeMap<String, Object>(params);
Set<Map.Entry<String, Object>> entrys = sortParams.entrySet();
StringBuilder baseString = new StringBuilder();
for (Map.Entry<String, Object> entry : entrys) {
baseString.append(entry.getKey()).append("=").append(entry.getValue()).append("&");
}
baseString.append("key=").append(zyConfig.getAppId());
String signStr = baseString.toString();
String digestHex = DigestUtils.md5Hex(signStr);
log.info("|{}|加密前的参数为|{}|加密后的参数为|{}|", TAG, signStr, digestHex);
return digestHex;
}
}
@@ -45,8 +45,15 @@ oauth2:
# https://gwyc.zj.gov.cn/API/%E7%9C%81%E5%B9%B3%E5%8F%B0API%E5%AF%B9%E6%8E%A5%E6%8E%A5%E5%8F%A3.html
zy:
base-url: http://60.191.37.212:18079
app-id: 03D9608D1735D424F984733BA71321C6
app-secret: 65497A86DB1401B252FEA6DE0A080766
app-id: 689C8D6F5059A6F85B8BE45A49001ACB
app-secret: BD21DA0DEB8F0FC43246B0BD2FCAE6FF
self-base-url: http://60.191.37.212:18079
self-app-id: 03D9608D1735D424F984733BA71321C6
self-app-secret: 03D9608D1735D424F984733BA71321C6
self-app-id: xA5jF2vX4zO5mQ8tR9yE7rC7iI0fK0kI
self-app-secret: kE3hH5gF7zN0nH1yI5yX3vP0oP1hU0jE
# 失效时间单位秒
self-expires-in: 7200
# token key
self_token_key: zy_token
# token
self_token_secret: eV3dT0oD7iX8rK4eC3jS6fU8cU5cS6mJ
@@ -1,5 +1,6 @@
package com.bsd.pjcloud.admin;
import cn.hutool.core.date.DateUtil;
import cn.hutool.json.JSONUtil;
import com.bsd.pjcloud.thirdparty.ThirdPartyApp;
import com.bsd.pjcloud.thirdparty.dto.zy.foreign.ZyForeignGetRegionIdByTokenDto;
@@ -21,13 +22,16 @@ import com.bsd.pjcloud.thirdparty.vo.zy.mer.*;
import com.bsd.pjcloud.thirdparty.vo.zy.stride.ZyStrideAuthenticationVo;
import com.bsd.pjcloud.thirdparty.vo.zy.stride.ZyStrideConsumptionVo;
import com.bsd.pjcloud.thirdparty.vo.zy.stride.ZyStrideCorrectVo;
import io.undertow.security.idm.DigestAlgorithm;
import jakarta.annotation.Resource;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.util.Base64;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@SpringBootTest(classes = ThirdPartyApp.class)
@@ -49,9 +53,9 @@ public class ZyTest {
* 获取token
*/
@Test
public void merGetTokenApi() {
ZyMerGetTokenVo vo = zyApiTool.getTokenApi();
System.out.println(vo);
public void merGetTokenApi() throws Exception {
String token = zyApiTool.getToken();
System.out.println(token);
}
/**
@@ -59,15 +63,17 @@ public class ZyTest {
*/
@Test
public void merSyncDealerInfo() {
String currentIndex = String.valueOf(DateUtil.current());
ZyMerSyncDealerInfoDto dto = ZyMerSyncDealerInfoDto
.builder()
.DealerKeyObj("123")
.DealerName("食堂")
.DealerKeyObj(currentIndex)
.DealerName("食堂" + currentIndex)
.IsValid(1)
.EPID("1")
.EPID("EPID" + currentIndex)
.FixId("20190920100101")
.build();
ZyMerSyncDealerInfoVo vo = zyMerService.syncDealerInfoApi(dto);
List<ZyMerSyncDealerInfoDto> list = List.of(dto);
ZyMerSyncDealerInfoVo vo = zyMerService.syncDealerInfoApi(list);
System.out.println(vo);
}
@@ -121,8 +127,7 @@ public class ZyTest {
*/
@Test
public void foreignGetRegionIdByToken() {
ZyForeignGetRegionIdByTokenDto dto = new ZyForeignGetRegionIdByTokenDto();
ZyForeignGetRegionIdByTokenVo vo = zyForeignService.getRegionIdByToken(dto);
ZyForeignGetRegionIdByTokenVo.VoData vo = zyForeignService.getRegionIdByToken();
System.out.println(vo);
}
@@ -165,57 +170,26 @@ public class ZyTest {
/************************** end stride end **************************/
@Test
public void encryption() {
try {
public void encryption() throws Exception {
// 第一步:组装业务数据
String data = "{\"dealers\":[{\"EPID\": \"1\",\"DealerKeyObj\":\"123\",\"IsValid\":1,\"DealerName\":\"食堂\",\"FixId\":\"20190920100101\"}]}";
// 1. 构建业务数据
Map<String, Object> dealer = new HashMap<>();
dealer.put("EPID", "1");
dealer.put("DealerKeyObj", "123");
dealer.put("IsValid", 1);
dealer.put("DealerName", "食堂");
dealer.put("FixId", "20190920100101");
// 第二步:进行 Base64 编码
String encodedData = Base64.getEncoder().encodeToString(data.getBytes(StandardCharsets.UTF_8));
Map<String, Object> data = new HashMap<>();
data.put("dealers", new Object[]{dealer});
// 2. 生成 data 参数(Base64 编码)
String jsonData = JSONUtil.toJsonStr(data);
String base64Data = Base64.getEncoder().encodeToString(jsonData.getBytes("UTF-8"));
// 3. 生成签名
String signStr = String.format("data=%s&key=%s", jsonData, "03D9608D1735D424F984733BA71321C6");
String sign = md5(signStr).toUpperCase();
// 4. 构建请求参数
Map<String, String> params = new HashMap<>();
params.put("data", base64Data);
params.put("sign", sign);
System.out.println(params);
} catch (Exception e) {
e.printStackTrace();
}
// 输出结果
System.out.println("Base64 Encoded Data: " + encodedData);
}
// MD5 加密方法
private static String md5(String input) {
try {
MessageDigest md = MessageDigest.getInstance("MD5");
byte[] messageDigest = md.digest(input.getBytes());
StringBuilder hexString = new StringBuilder();
for (byte b : messageDigest) {
String hex = Integer.toHexString(0xFF & b);
if (hex.length() == 1) {
hexString.append('0');
}
hexString.append(hex);
}
return hexString.toString();
} catch (Exception e) {
throw new RuntimeException(e);
private static String md5(String input) throws Exception {
MessageDigest md = MessageDigest.getInstance("MD5");
byte[] messageDigest = md.digest(input.getBytes(StandardCharsets.UTF_8));
StringBuilder sb = new StringBuilder();
for (byte b : messageDigest) {
sb.append(String.format("%02x", b));
}
return sb.toString();
}
}