mirror of
https://gitee.com/durcframework/SOP.git
synced 2025-11-13 09:46:09 +08:00
回调管理
This commit is contained in:
@@ -10,7 +10,7 @@
|
|||||||
|
|
||||||
通过简单的配置后,你的项目就具备了和支付宝开放平台的一样的接口提供能力。
|
通过简单的配置后,你的项目就具备了和支付宝开放平台的一样的接口提供能力。
|
||||||
|
|
||||||
SOP封装了开放平台大部分功能包括:签名验证、统一异常处理、统一返回内容 、业务参数验证(JSR-303)、秘钥管理等,未来还会实现更多功能。
|
SOP封装了开放平台大部分功能包括:签名验证、统一异常处理、统一返回内容 、业务参数验证(JSR-303)、秘钥管理、接口回调等。
|
||||||
|
|
||||||
|
|
||||||
## 项目特点
|
## 项目特点
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
## 日常更新
|
## 日常更新
|
||||||
|
|
||||||
|
- 2025-11-01:添加回调处理。有升级SQL,见:[sop-20251101.sql](./upgrade/sop-20251101.sql)
|
||||||
- 2025-09-12:修复推送文档报找不到@Open注解问题
|
- 2025-09-12:修复推送文档报找不到@Open注解问题
|
||||||
- 2025-08-29:smart-doc升级到3.1.1
|
- 2025-08-29:smart-doc升级到3.1.1
|
||||||
- 2025-08-17:admin后台可关联商户;fastmybatis升级到3.1.7。有升级SQL,见:[sop-20250817.sql](./upgrade/sop-20250817.sql)
|
- 2025-08-17:admin后台可关联商户;fastmybatis升级到3.1.7。有升级SQL,见:[sop-20250817.sql](./upgrade/sop-20250817.sql)
|
||||||
|
|||||||
3
pom.xml
3
pom.xml
@@ -24,6 +24,7 @@
|
|||||||
<module>sop-gateway</module>
|
<module>sop-gateway</module>
|
||||||
<module>sop-registry</module>
|
<module>sop-registry</module>
|
||||||
<module>sop-support</module>
|
<module>sop-support</module>
|
||||||
|
<module>sop-notify</module>
|
||||||
</modules>
|
</modules>
|
||||||
|
|
||||||
<properties>
|
<properties>
|
||||||
@@ -127,7 +128,7 @@
|
|||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.alibaba</groupId>
|
<groupId>com.alibaba</groupId>
|
||||||
<artifactId>transmittable-thread-local</artifactId>
|
<artifactId>transmittable-thread-local</artifactId>
|
||||||
<version>2.14.5</version>
|
<version>2.14.2</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.google.guava</groupId>
|
<groupId>com.google.guava</groupId>
|
||||||
|
|||||||
@@ -0,0 +1,23 @@
|
|||||||
|
package com.gitee.sop.admin.common.enums;
|
||||||
|
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Getter;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author 六如
|
||||||
|
*/
|
||||||
|
@AllArgsConstructor
|
||||||
|
@Getter
|
||||||
|
public enum NotifyStatusEnum implements IntEnum {
|
||||||
|
|
||||||
|
// 状态,1-发送成功,2-发送失败,3-重试结束
|
||||||
|
SEND_SUCCESS(1, "发送成功"),
|
||||||
|
SEND_FAIL(2, "发送失败"),
|
||||||
|
RETRY_OVER(3, "重试结束"),
|
||||||
|
END(4, "手动结束");
|
||||||
|
|
||||||
|
private final Integer value;
|
||||||
|
|
||||||
|
private final String description;
|
||||||
|
|
||||||
|
}
|
||||||
@@ -38,6 +38,11 @@ public class IsvInfo {
|
|||||||
*/
|
*/
|
||||||
private String remark;
|
private String remark;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 回调接口
|
||||||
|
*/
|
||||||
|
private String notifyUrl;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 添加时间
|
* 添加时间
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -0,0 +1,99 @@
|
|||||||
|
package com.gitee.sop.admin.dao.entity;
|
||||||
|
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
|
||||||
|
import com.gitee.fastmybatis.annotation.Pk;
|
||||||
|
import com.gitee.fastmybatis.annotation.PkStrategy;
|
||||||
|
import com.gitee.fastmybatis.annotation.Table;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 表名:notify_info
|
||||||
|
* 备注:回调信息
|
||||||
|
*
|
||||||
|
* @author 六如
|
||||||
|
*/
|
||||||
|
@Table(name = "notify_info", pk = @Pk(name = "id", strategy = PkStrategy.INCREMENT))
|
||||||
|
@Data
|
||||||
|
public class NotifyInfo {
|
||||||
|
|
||||||
|
private Long id;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* app_id
|
||||||
|
*/
|
||||||
|
private String appId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* api_name
|
||||||
|
*/
|
||||||
|
private String apiName;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* api_version
|
||||||
|
*/
|
||||||
|
private String apiVersion;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 最近一次发送时间
|
||||||
|
*/
|
||||||
|
private LocalDateTime lastSendTime;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 下一次发送时间
|
||||||
|
*/
|
||||||
|
private LocalDateTime nextSendTime;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 已发送次数
|
||||||
|
*/
|
||||||
|
private Integer sendCnt;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 发送内容
|
||||||
|
*/
|
||||||
|
private String content;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 状态,1-发送成功,2-发送失败,3-重试结束
|
||||||
|
*/
|
||||||
|
private Integer notifyStatus;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 失败原因
|
||||||
|
*/
|
||||||
|
private String errorMsg;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 返回结果
|
||||||
|
*/
|
||||||
|
private String resultContent;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 备注
|
||||||
|
*/
|
||||||
|
private String remark;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 回调url
|
||||||
|
*/
|
||||||
|
private String notifyUrl;
|
||||||
|
|
||||||
|
private LocalDateTime addTime;
|
||||||
|
|
||||||
|
private LocalDateTime updateTime;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建人id
|
||||||
|
*/
|
||||||
|
private Long addBy;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 修改人id
|
||||||
|
*/
|
||||||
|
private Long updateBy;
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
package com.gitee.sop.admin.dao.mapper;
|
||||||
|
|
||||||
|
import com.gitee.fastmybatis.core.mapper.BaseMapper;
|
||||||
|
import com.gitee.sop.admin.dao.entity.NotifyInfo;
|
||||||
|
import org.apache.ibatis.annotations.Mapper;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author 六如
|
||||||
|
*/
|
||||||
|
@Mapper
|
||||||
|
public interface NotifyInfoMapper extends BaseMapper<NotifyInfo> {
|
||||||
|
|
||||||
|
}
|
||||||
@@ -28,6 +28,11 @@
|
|||||||
<artifactId>admin-dao</artifactId>
|
<artifactId>admin-dao</artifactId>
|
||||||
<version>5.0.0-SNAPSHOT</version>
|
<version>5.0.0-SNAPSHOT</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.gitee.sop</groupId>
|
||||||
|
<artifactId>sop-notify-api</artifactId>
|
||||||
|
<version>5.0.0-SNAPSHOT</version>
|
||||||
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.apache.dubbo</groupId>
|
<groupId>org.apache.dubbo</groupId>
|
||||||
<artifactId>dubbo</artifactId>
|
<artifactId>dubbo</artifactId>
|
||||||
|
|||||||
@@ -119,10 +119,7 @@ public class IsvInfoService implements ServiceSupport<IsvInfo, IsvInfoMapper> {
|
|||||||
|
|
||||||
@Transactional(rollbackFor = Exception.class)
|
@Transactional(rollbackFor = Exception.class)
|
||||||
public int update(IsvInfoUpdateDTO isvInfoUpdateDTO) {
|
public int update(IsvInfoUpdateDTO isvInfoUpdateDTO) {
|
||||||
IsvInfo isvInfo = new IsvInfo();
|
IsvInfo isvInfo = CopyUtil.copyBean(isvInfoUpdateDTO, IsvInfo::new);
|
||||||
isvInfo.setId(isvInfoUpdateDTO.getId());
|
|
||||||
isvInfo.setStatus(isvInfoUpdateDTO.getStatus());
|
|
||||||
isvInfo.setRemark(isvInfoUpdateDTO.getRemark());
|
|
||||||
int cnt = this.update(isvInfo);
|
int cnt = this.update(isvInfo);
|
||||||
sendChangeEvent(isvInfoUpdateDTO.getId());
|
sendChangeEvent(isvInfoUpdateDTO.getId());
|
||||||
return cnt;
|
return cnt;
|
||||||
@@ -185,4 +182,11 @@ public class IsvInfoService implements ServiceSupport<IsvInfo, IsvInfoMapper> {
|
|||||||
sendChangeEvent(isvId);
|
sendChangeEvent(isvId);
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Integer setNotifyUrl(Long id, String url) {
|
||||||
|
return this.query()
|
||||||
|
.eq(IsvInfo::getId, id)
|
||||||
|
.set(IsvInfo::getNotifyUrl, url)
|
||||||
|
.update();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,4 +24,9 @@ public class IsvInfoAddDTO {
|
|||||||
@Length(max = 500)
|
@Length(max = 500)
|
||||||
private String remark;
|
private String remark;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 回调接口
|
||||||
|
*/
|
||||||
|
private String notifyUrl;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -58,4 +58,9 @@ public class IsvInfoDTO {
|
|||||||
*/
|
*/
|
||||||
private String merchantCode;
|
private String merchantCode;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 回调接口
|
||||||
|
*/
|
||||||
|
private String notifyUrl;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,61 @@
|
|||||||
|
package com.gitee.sop.admin.service.serve;
|
||||||
|
|
||||||
|
import com.gitee.fastmybatis.core.PageInfo;
|
||||||
|
import com.gitee.fastmybatis.core.query.LambdaQuery;
|
||||||
|
import com.gitee.fastmybatis.core.support.LambdaService;
|
||||||
|
import com.gitee.sop.admin.common.enums.NotifyStatusEnum;
|
||||||
|
import com.gitee.sop.admin.common.exception.BizException;
|
||||||
|
import com.gitee.sop.admin.dao.entity.NotifyInfo;
|
||||||
|
import com.gitee.sop.admin.dao.mapper.NotifyInfoMapper;
|
||||||
|
import com.gitee.sop.notify.api.NotifyService;
|
||||||
|
import com.gitee.sop.notify.api.resp.NotifyResponse;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
import org.apache.dubbo.config.annotation.DubboReference;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author thc
|
||||||
|
*/
|
||||||
|
@Slf4j
|
||||||
|
@Service
|
||||||
|
public class NotifyInfoService implements LambdaService<NotifyInfo, NotifyInfoMapper> {
|
||||||
|
|
||||||
|
@DubboReference
|
||||||
|
private NotifyService notifyService;
|
||||||
|
|
||||||
|
public PageInfo<NotifyInfo> doPage(LambdaQuery<NotifyInfo> query) {
|
||||||
|
query.orderByDesc(NotifyInfo::getId);
|
||||||
|
PageInfo<NotifyInfo> page = this.page(query);
|
||||||
|
|
||||||
|
// 格式转换
|
||||||
|
return page.convert(isvInfo -> {
|
||||||
|
|
||||||
|
return isvInfo;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public int push(Long id, String url) {
|
||||||
|
if (StringUtils.isNotBlank(url)) {
|
||||||
|
this.query()
|
||||||
|
.eq(NotifyInfo::getId, id)
|
||||||
|
.set(NotifyInfo::getNotifyUrl, url)
|
||||||
|
.update();
|
||||||
|
}
|
||||||
|
NotifyResponse notifyResponse = notifyService.notifyImmediately(id);
|
||||||
|
log.info("重新推送结果, notifyResponse={}", notifyResponse);
|
||||||
|
if (!notifyResponse.getSuccess()) {
|
||||||
|
throw new BizException(notifyResponse.getMsg());
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int end(Long id) {
|
||||||
|
return this.query()
|
||||||
|
.eq(NotifyInfo::getId, id)
|
||||||
|
.eq(NotifyInfo::getNotifyStatus, NotifyStatusEnum.SEND_FAIL.getValue())
|
||||||
|
.set(NotifyInfo::getNotifyStatus, NotifyStatusEnum.END.getValue())
|
||||||
|
.update();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -24,4 +24,5 @@ public class IsvInfoAddParam {
|
|||||||
@Length(max = 500)
|
@Length(max = 500)
|
||||||
private String remark;
|
private String remark;
|
||||||
|
|
||||||
|
private String notifyUrl;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -58,4 +58,9 @@ public class IsvInfoVO {
|
|||||||
*/
|
*/
|
||||||
private String merchantCode;
|
private String merchantCode;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 回调接口
|
||||||
|
*/
|
||||||
|
private String notifyUrl;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
package com.gitee.sop.admin.controller.serve;
|
package com.gitee.sop.admin.controller.serve.api;
|
||||||
|
|
||||||
import com.gitee.fastmybatis.core.PageInfo;
|
import com.gitee.fastmybatis.core.PageInfo;
|
||||||
import com.gitee.fastmybatis.core.query.Query;
|
import com.gitee.fastmybatis.core.query.Query;
|
||||||
@@ -6,8 +6,8 @@ import com.gitee.sop.admin.common.dto.StatusUpdateDTO;
|
|||||||
import com.gitee.sop.admin.common.req.StatusUpdateParam;
|
import com.gitee.sop.admin.common.req.StatusUpdateParam;
|
||||||
import com.gitee.sop.admin.common.resp.Result;
|
import com.gitee.sop.admin.common.resp.Result;
|
||||||
import com.gitee.sop.admin.common.util.CopyUtil;
|
import com.gitee.sop.admin.common.util.CopyUtil;
|
||||||
import com.gitee.sop.admin.controller.serve.param.ApiInfoPageParam;
|
import com.gitee.sop.admin.controller.serve.api.param.ApiInfoPageParam;
|
||||||
import com.gitee.sop.admin.controller.serve.vo.ApiInfoVO;
|
import com.gitee.sop.admin.controller.serve.api.vo.ApiInfoVO;
|
||||||
import com.gitee.sop.admin.dao.entity.ApiInfo;
|
import com.gitee.sop.admin.dao.entity.ApiInfo;
|
||||||
import com.gitee.sop.admin.service.serve.ApiInfoService;
|
import com.gitee.sop.admin.service.serve.ApiInfoService;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
package com.gitee.sop.admin.controller.serve.param;
|
package com.gitee.sop.admin.controller.serve.api.param;
|
||||||
|
|
||||||
import com.gitee.fastmybatis.core.query.Operator;
|
import com.gitee.fastmybatis.core.query.Operator;
|
||||||
import com.gitee.fastmybatis.core.query.annotation.Condition;
|
import com.gitee.fastmybatis.core.query.annotation.Condition;
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
package com.gitee.sop.admin.controller.serve.param;
|
package com.gitee.sop.admin.controller.serve.api.param;
|
||||||
|
|
||||||
import com.gitee.fastmybatis.core.query.Operator;
|
import com.gitee.fastmybatis.core.query.Operator;
|
||||||
import com.gitee.fastmybatis.core.query.annotation.Condition;
|
import com.gitee.fastmybatis.core.query.annotation.Condition;
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
package com.gitee.sop.admin.controller.serve.vo;
|
package com.gitee.sop.admin.controller.serve.api.vo;
|
||||||
|
|
||||||
import com.gitee.sop.admin.service.jackson.convert.annotation.UserFormat;
|
import com.gitee.sop.admin.service.jackson.convert.annotation.UserFormat;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
@@ -0,0 +1,68 @@
|
|||||||
|
package com.gitee.sop.admin.controller.serve.notify;
|
||||||
|
|
||||||
|
import com.gitee.fastmybatis.core.PageInfo;
|
||||||
|
import com.gitee.fastmybatis.core.query.LambdaQuery;
|
||||||
|
import com.gitee.sop.admin.common.req.IdParam;
|
||||||
|
import com.gitee.sop.admin.common.resp.Result;
|
||||||
|
import com.gitee.sop.admin.common.util.CopyUtil;
|
||||||
|
import com.gitee.sop.admin.controller.serve.notify.param.NotifyInfoSearchParam;
|
||||||
|
import com.gitee.sop.admin.controller.serve.notify.param.NotifyPushParam;
|
||||||
|
import com.gitee.sop.admin.controller.serve.notify.vo.NotifyInfoVO;
|
||||||
|
import com.gitee.sop.admin.dao.entity.NotifyInfo;
|
||||||
|
import com.gitee.sop.admin.service.serve.NotifyInfoService;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.validation.annotation.Validated;
|
||||||
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
|
import org.springframework.web.bind.annotation.PostMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RequestBody;
|
||||||
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author thc
|
||||||
|
*/
|
||||||
|
@RestController
|
||||||
|
@RequestMapping("serve/notify")
|
||||||
|
public class NotifyInfoController {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private NotifyInfoService notifyInfoService;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 分页查询
|
||||||
|
*
|
||||||
|
* @param param 查询参数
|
||||||
|
* @return 返回分页结果
|
||||||
|
*/
|
||||||
|
@GetMapping("/page")
|
||||||
|
public Result<PageInfo<NotifyInfoVO>> page(NotifyInfoSearchParam param) {
|
||||||
|
LambdaQuery<NotifyInfo> query = param.toLambdaQuery(NotifyInfo.class);
|
||||||
|
PageInfo<NotifyInfoVO> pageInfo = notifyInfoService.doPage(query)
|
||||||
|
.convert(data -> CopyUtil.copyBean(data, NotifyInfoVO::new));
|
||||||
|
return Result.ok(pageInfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 重新推送
|
||||||
|
*
|
||||||
|
* @param param 表单数据
|
||||||
|
* @return 返回影响行数
|
||||||
|
*/
|
||||||
|
@PostMapping("/push")
|
||||||
|
public Result<Integer> update(@Validated @RequestBody NotifyPushParam param) {
|
||||||
|
return Result.ok(notifyInfoService.push(param.getId(), param.getUrl()));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 结束重试
|
||||||
|
*
|
||||||
|
* @param param 表单数据
|
||||||
|
* @return 返回影响行数
|
||||||
|
*/
|
||||||
|
@PostMapping("/end")
|
||||||
|
public Result<Integer> end(@Validated @RequestBody IdParam param) {
|
||||||
|
return Result.ok(notifyInfoService.end(param.getId()));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,72 @@
|
|||||||
|
package com.gitee.sop.admin.controller.serve.notify.param;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 新增表单
|
||||||
|
*
|
||||||
|
* @author thc
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class NotifyInfoAddParam {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* app_id
|
||||||
|
*/
|
||||||
|
private String appId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* api_name
|
||||||
|
*/
|
||||||
|
private String apiName;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* api_version
|
||||||
|
*/
|
||||||
|
private String apiVersion;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 最近一次发送时间
|
||||||
|
*/
|
||||||
|
private LocalDateTime lastSendTime;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 下一次发送时间
|
||||||
|
*/
|
||||||
|
private LocalDateTime nextSendTime;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 最大发送次数
|
||||||
|
*/
|
||||||
|
private Integer sendMax;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 已发送次数
|
||||||
|
*/
|
||||||
|
private Integer sendCnt;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 发送内容
|
||||||
|
*/
|
||||||
|
private String content;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 状态,1-发送成功,2-发送失败,3-重试结束
|
||||||
|
*/
|
||||||
|
private Integer notifyStatus;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 失败原因
|
||||||
|
*/
|
||||||
|
private String errorMsg;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 备注
|
||||||
|
*/
|
||||||
|
private String remark;
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,106 @@
|
|||||||
|
package com.gitee.sop.admin.controller.serve.notify.param;
|
||||||
|
|
||||||
|
import com.gitee.fastmybatis.core.query.Operator;
|
||||||
|
import com.gitee.fastmybatis.core.query.annotation.Condition;
|
||||||
|
import com.gitee.fastmybatis.core.query.param.PageParam;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.EqualsAndHashCode;
|
||||||
|
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查询表单
|
||||||
|
*
|
||||||
|
* @author thc
|
||||||
|
*/
|
||||||
|
@EqualsAndHashCode(callSuper = true)
|
||||||
|
@Data
|
||||||
|
public class NotifyInfoSearchParam extends PageParam {
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* app_id
|
||||||
|
*/
|
||||||
|
@Condition(operator = Operator.like)
|
||||||
|
private String appId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* api_name
|
||||||
|
*/
|
||||||
|
@Condition(operator = Operator.like)
|
||||||
|
private String apiName;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* api_version
|
||||||
|
*/
|
||||||
|
@Condition(operator = Operator.like)
|
||||||
|
private String apiVersion;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 最近一次发送时间
|
||||||
|
*/
|
||||||
|
@Condition
|
||||||
|
private LocalDateTime lastSendTime;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 下一次发送时间
|
||||||
|
*/
|
||||||
|
@Condition
|
||||||
|
private LocalDateTime nextSendTime;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 最大发送次数
|
||||||
|
*/
|
||||||
|
@Condition
|
||||||
|
private Integer sendMax;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 已发送次数
|
||||||
|
*/
|
||||||
|
@Condition
|
||||||
|
private Integer sendCnt;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 发送内容
|
||||||
|
*/
|
||||||
|
@Condition(operator = Operator.like)
|
||||||
|
private String content;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 状态,1-发送成功,2-发送失败,3-重试结束
|
||||||
|
*/
|
||||||
|
@Condition
|
||||||
|
private Integer notifyStatus;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 失败原因
|
||||||
|
*/
|
||||||
|
@Condition(operator = Operator.like)
|
||||||
|
private String errorMsg;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 备注
|
||||||
|
*/
|
||||||
|
@Condition(operator = Operator.like)
|
||||||
|
private String remark;
|
||||||
|
|
||||||
|
@Condition
|
||||||
|
private LocalDateTime addTime;
|
||||||
|
|
||||||
|
@Condition
|
||||||
|
private LocalDateTime updateTime;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建人id
|
||||||
|
*/
|
||||||
|
@Condition
|
||||||
|
private Long addBy;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 修改人id
|
||||||
|
*/
|
||||||
|
@Condition
|
||||||
|
private Long updateBy;
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
package com.gitee.sop.admin.controller.serve.notify.param;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.EqualsAndHashCode;
|
||||||
|
|
||||||
|
import javax.validation.constraints.NotNull;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 修改表单
|
||||||
|
*
|
||||||
|
* @author thc
|
||||||
|
*/
|
||||||
|
@EqualsAndHashCode(callSuper = true)
|
||||||
|
@Data
|
||||||
|
public class NotifyInfoUpdateParam extends NotifyInfoAddParam {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* id
|
||||||
|
*/
|
||||||
|
@NotNull(message = "id必填")
|
||||||
|
private Long id;
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
package com.gitee.sop.admin.controller.serve.notify.param;
|
||||||
|
|
||||||
|
import com.gitee.sop.admin.common.req.IdParam;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public class NotifyPushParam extends IdParam {
|
||||||
|
|
||||||
|
private String url;
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,96 @@
|
|||||||
|
package com.gitee.sop.admin.controller.serve.notify.vo;
|
||||||
|
|
||||||
|
import com.gitee.sop.admin.service.jackson.convert.annotation.UserFormat;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 返回结果
|
||||||
|
*
|
||||||
|
* @author thc
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class NotifyInfoVO {
|
||||||
|
|
||||||
|
private Long id;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* app_id
|
||||||
|
*/
|
||||||
|
private String appId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* api_name
|
||||||
|
*/
|
||||||
|
private String apiName;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* api_version
|
||||||
|
*/
|
||||||
|
private String apiVersion;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 最近一次发送时间
|
||||||
|
*/
|
||||||
|
private LocalDateTime lastSendTime;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 下一次发送时间
|
||||||
|
*/
|
||||||
|
private LocalDateTime nextSendTime;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 最大发送次数
|
||||||
|
*/
|
||||||
|
private Integer sendMax;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 已发送次数
|
||||||
|
*/
|
||||||
|
private Integer sendCnt;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 发送内容
|
||||||
|
*/
|
||||||
|
private String content;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 状态,1-发送成功,2-发送失败,3-重试结束
|
||||||
|
*/
|
||||||
|
private Integer notifyStatus;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 失败原因
|
||||||
|
*/
|
||||||
|
private String errorMsg;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 返回结果
|
||||||
|
*/
|
||||||
|
private String resultContent;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 备注
|
||||||
|
*/
|
||||||
|
private String remark;
|
||||||
|
|
||||||
|
private LocalDateTime addTime;
|
||||||
|
|
||||||
|
private LocalDateTime updateTime;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建人id
|
||||||
|
*/
|
||||||
|
@UserFormat
|
||||||
|
private Long addBy;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 修改人id
|
||||||
|
*/
|
||||||
|
@UserFormat
|
||||||
|
private Long updateBy;
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
36
sop-admin/sop-admin-frontend/src/api/notifyInfo.ts
Normal file
36
sop-admin/sop-admin-frontend/src/api/notifyInfo.ts
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
import { createUrl, http } from "@/utils/http";
|
||||||
|
import type { PageResult, Result } from "@/model";
|
||||||
|
|
||||||
|
// 后端请求接口
|
||||||
|
const apiUrl: any = createUrl({
|
||||||
|
page: "/serve/notify/page",
|
||||||
|
push: "/serve/notify/push",
|
||||||
|
end: "/serve/notify/end"
|
||||||
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 接口管理
|
||||||
|
*/
|
||||||
|
export const api: any = {
|
||||||
|
/**
|
||||||
|
* 分页查询
|
||||||
|
* @param params 查询参数
|
||||||
|
*/
|
||||||
|
page(params: object): Promise<PageResult> {
|
||||||
|
return http.get<PageResult, any>(apiUrl.page, { params });
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* 推送
|
||||||
|
* @param data 表单内容
|
||||||
|
*/
|
||||||
|
push(data: object) {
|
||||||
|
return http.post<Result<any>, any>(apiUrl.push, { data });
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* 关闭
|
||||||
|
* @param data 表单内容
|
||||||
|
*/
|
||||||
|
end(data: object) {
|
||||||
|
return http.post<Result<any>, any>(apiUrl.end, { data });
|
||||||
|
}
|
||||||
|
};
|
||||||
@@ -17,3 +17,10 @@ export enum RegSource {
|
|||||||
SYS = 1,
|
SYS = 1,
|
||||||
CUSTOM = 2
|
CUSTOM = 2
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export enum NotifyStatusEnum {
|
||||||
|
SUCCESS = 1,
|
||||||
|
FAIL = 2,
|
||||||
|
END = 3,
|
||||||
|
STOP = 4
|
||||||
|
}
|
||||||
|
|||||||
@@ -239,7 +239,8 @@ export function useIsvList() {
|
|||||||
id: 0,
|
id: 0,
|
||||||
status: StatusEnum.ENABLE,
|
status: StatusEnum.ENABLE,
|
||||||
keyFormat: KeyFormatEnum.PKCS8,
|
keyFormat: KeyFormatEnum.PKCS8,
|
||||||
remark: ""
|
remark: "",
|
||||||
|
notifyUrl: ""
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
const editFormData = ref<FieldValues>(editFormDataGen());
|
const editFormData = ref<FieldValues>(editFormDataGen());
|
||||||
@@ -280,6 +281,11 @@ export function useIsvList() {
|
|||||||
showWordLimit: true,
|
showWordLimit: true,
|
||||||
autosize: { minRows: 2, maxRows: 4 }
|
autosize: { minRows: 2, maxRows: 4 }
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "回调接口",
|
||||||
|
prop: "notifyUrl",
|
||||||
|
valueType: "input"
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|||||||
382
sop-admin/sop-admin-frontend/src/views/serve/notify/index.ts
Normal file
382
sop-admin/sop-admin-frontend/src/views/serve/notify/index.ts
Normal file
@@ -0,0 +1,382 @@
|
|||||||
|
import { onMounted, ref } from "vue";
|
||||||
|
import {
|
||||||
|
type ButtonsCallBackParams,
|
||||||
|
type PageInfo,
|
||||||
|
type PlusColumn,
|
||||||
|
useTable
|
||||||
|
} from "plus-pro-components";
|
||||||
|
import { ElMessage, ElMessageBox } from "element-plus";
|
||||||
|
import { api } from "@/api/notifyInfo";
|
||||||
|
import { WarnTriangleFilled } from "@element-plus/icons-vue";
|
||||||
|
import { NotifyStatusEnum } from "@/model/enums";
|
||||||
|
|
||||||
|
export function useEntNotifyInfo() {
|
||||||
|
const isAdd = ref(false);
|
||||||
|
|
||||||
|
// ========= search form =========
|
||||||
|
|
||||||
|
// 查询表单对象
|
||||||
|
const searchFormData = ref({
|
||||||
|
appId: "",
|
||||||
|
apiName: "",
|
||||||
|
apiVersion: "",
|
||||||
|
notifyStatus: "",
|
||||||
|
pageIndex: 1,
|
||||||
|
pageSize: 10
|
||||||
|
});
|
||||||
|
|
||||||
|
// 查询表单字段定义
|
||||||
|
const searchFormColumns: PlusColumn[] = [
|
||||||
|
{
|
||||||
|
label: "AppId",
|
||||||
|
prop: "appId"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "接口名称",
|
||||||
|
prop: "apiName"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "接口版本",
|
||||||
|
prop: "apiVersion"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "状态",
|
||||||
|
prop: "notifyStatus",
|
||||||
|
width: 80,
|
||||||
|
valueType: "select",
|
||||||
|
options: [
|
||||||
|
{
|
||||||
|
label: "成功",
|
||||||
|
value: NotifyStatusEnum.SUCCESS,
|
||||||
|
color: "green"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "失败",
|
||||||
|
value: NotifyStatusEnum.FAIL,
|
||||||
|
color: "red"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "重试结束",
|
||||||
|
value: NotifyStatusEnum.END,
|
||||||
|
color: "gray"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
// ========= table =========
|
||||||
|
|
||||||
|
// 表格对象
|
||||||
|
const {
|
||||||
|
tableData,
|
||||||
|
total,
|
||||||
|
pageInfo,
|
||||||
|
buttons: actionButtons
|
||||||
|
} = useTable<any[]>();
|
||||||
|
// 默认每页条数,默认10
|
||||||
|
pageInfo.value.pageSize = 10;
|
||||||
|
|
||||||
|
// 表格字段定义
|
||||||
|
const tableColumns: PlusColumn[] = [
|
||||||
|
{
|
||||||
|
label: "AppId",
|
||||||
|
prop: "appId"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "接口名称",
|
||||||
|
prop: "apiName"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "接口版本",
|
||||||
|
prop: "apiVersion"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
width: 120,
|
||||||
|
label: "最近一次发送时间",
|
||||||
|
prop: "lastSendTime"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
width: 120,
|
||||||
|
label: "下一次发送时间",
|
||||||
|
prop: "nextSendTime"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "已发送次数",
|
||||||
|
prop: "sendCnt"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "发送内容",
|
||||||
|
prop: "content"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "状态",
|
||||||
|
prop: "notifyStatus",
|
||||||
|
width: 100,
|
||||||
|
valueType: "select",
|
||||||
|
options: [
|
||||||
|
{
|
||||||
|
label: "成功",
|
||||||
|
value: NotifyStatusEnum.SUCCESS,
|
||||||
|
color: "green"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "失败",
|
||||||
|
value: NotifyStatusEnum.FAIL,
|
||||||
|
color: "red"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "重试结束",
|
||||||
|
value: NotifyStatusEnum.END,
|
||||||
|
color: "gray"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "重试结束",
|
||||||
|
value: NotifyStatusEnum.STOP,
|
||||||
|
color: "gray"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "失败原因",
|
||||||
|
prop: "errorMsg"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "返回结果",
|
||||||
|
prop: "resultContent",
|
||||||
|
width: 120
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "备注",
|
||||||
|
prop: "remark"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
width: 120,
|
||||||
|
label: "添加时间",
|
||||||
|
prop: "addTime"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
width: 120,
|
||||||
|
label: "修改时间",
|
||||||
|
prop: "updateTime"
|
||||||
|
}
|
||||||
|
];
|
||||||
|
// 表格按钮定义
|
||||||
|
actionButtons.value = [
|
||||||
|
{
|
||||||
|
text: "推送",
|
||||||
|
props: {
|
||||||
|
type: "primary"
|
||||||
|
},
|
||||||
|
onClick(params: ButtonsCallBackParams) {
|
||||||
|
ElMessageBox.prompt("回调URL", "推送", {
|
||||||
|
confirmButtonText: "确定",
|
||||||
|
cancelButtonText: "取消",
|
||||||
|
inputPlaceholder: "【选填】不填使用默认URL"
|
||||||
|
})
|
||||||
|
.then(({ value }) => {
|
||||||
|
api
|
||||||
|
.push({
|
||||||
|
id: params.row.id,
|
||||||
|
url: value
|
||||||
|
})
|
||||||
|
.then(() => {
|
||||||
|
ElMessage.success("操作成功");
|
||||||
|
search();
|
||||||
|
});
|
||||||
|
})
|
||||||
|
.catch(() => {});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
text: "结束重试",
|
||||||
|
show: (row: any) => row.notifyStatus === 2,
|
||||||
|
props: {
|
||||||
|
type: "danger"
|
||||||
|
},
|
||||||
|
confirm: {
|
||||||
|
// @ts-ignore
|
||||||
|
popconfirmProps: {
|
||||||
|
width: 150,
|
||||||
|
icon: WarnTriangleFilled,
|
||||||
|
iconColor: "red"
|
||||||
|
},
|
||||||
|
message: _ => `确定要结束重试吗?`
|
||||||
|
},
|
||||||
|
onConfirm(params: ButtonsCallBackParams) {
|
||||||
|
api.end(params.row).then(() => {
|
||||||
|
ElMessage.success("操作成功");
|
||||||
|
search();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
// ========= dialog form =========
|
||||||
|
|
||||||
|
// 弹窗显示
|
||||||
|
const dlgShow = ref(false);
|
||||||
|
const dlgTitle = ref("");
|
||||||
|
// 表单值
|
||||||
|
const editFormDataGen = () => {
|
||||||
|
return {
|
||||||
|
appId: "",
|
||||||
|
apiName: "",
|
||||||
|
apiVersion: "",
|
||||||
|
lastSendTime: "",
|
||||||
|
nextSendTime: "",
|
||||||
|
sendMax: "",
|
||||||
|
sendCnt: "",
|
||||||
|
content: "",
|
||||||
|
notifyStatus: "",
|
||||||
|
errorMsg: "",
|
||||||
|
remark: ""
|
||||||
|
};
|
||||||
|
};
|
||||||
|
const editFormData = ref<any>(editFormDataGen());
|
||||||
|
const editFormRules = {
|
||||||
|
appId: [{ required: true, message: "请输入app_id" }],
|
||||||
|
apiName: [{ required: true, message: "请输入api_name" }],
|
||||||
|
apiVersion: [{ required: true, message: "请输入api_version" }]
|
||||||
|
};
|
||||||
|
|
||||||
|
// 表单内容
|
||||||
|
const editFormColumns: PlusColumn[] = [
|
||||||
|
{
|
||||||
|
label: "app_id",
|
||||||
|
prop: "appId",
|
||||||
|
valueType: "input"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "api_name",
|
||||||
|
prop: "apiName",
|
||||||
|
valueType: "input"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "api_version",
|
||||||
|
prop: "apiVersion",
|
||||||
|
valueType: "input"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "最近一次发送时间",
|
||||||
|
prop: "lastSendTime",
|
||||||
|
valueType: "input"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "下一次发送时间",
|
||||||
|
prop: "nextSendTime",
|
||||||
|
valueType: "input"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "已发送次数",
|
||||||
|
prop: "sendCnt",
|
||||||
|
valueType: "input"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "发送内容",
|
||||||
|
prop: "content",
|
||||||
|
valueType: "input"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "状态,1-发送成功,2-发送失败,3-重试结束",
|
||||||
|
prop: "notifyStatus",
|
||||||
|
valueType: "input"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "失败原因",
|
||||||
|
prop: "errorMsg",
|
||||||
|
valueType: "input"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "备注",
|
||||||
|
prop: "remark",
|
||||||
|
valueType: "input"
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
// ========= event =========
|
||||||
|
|
||||||
|
// 添加按钮事件
|
||||||
|
const handleAdd = () => {
|
||||||
|
isAdd.value = true;
|
||||||
|
editFormData.value = editFormDataGen();
|
||||||
|
dlgTitle.value = "新增";
|
||||||
|
dlgShow.value = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
// 保存按钮事件,校验成功后触发
|
||||||
|
const handleSave = () => {
|
||||||
|
const postData = editFormData.value;
|
||||||
|
const pms = isAdd.value ? api.add(postData) : api.update(postData);
|
||||||
|
pms.then(() => {
|
||||||
|
ElMessage.success("保存成功");
|
||||||
|
dlgShow.value = false;
|
||||||
|
search();
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
// 点击查询按钮
|
||||||
|
const handleSearch = () => {
|
||||||
|
pageInfo.value.page = 1;
|
||||||
|
search();
|
||||||
|
};
|
||||||
|
|
||||||
|
// 分页事件
|
||||||
|
const handlePaginationChange = (_pageInfo: PageInfo): void => {
|
||||||
|
pageInfo.value = _pageInfo;
|
||||||
|
search();
|
||||||
|
};
|
||||||
|
|
||||||
|
// 查询
|
||||||
|
const search = async () => {
|
||||||
|
try {
|
||||||
|
const { data } = await doSearch();
|
||||||
|
tableData.value = data.list;
|
||||||
|
total.value = data.total;
|
||||||
|
} catch (error) {}
|
||||||
|
};
|
||||||
|
// 请求接口
|
||||||
|
const doSearch = async () => {
|
||||||
|
// 查询参数
|
||||||
|
const data = searchFormData.value;
|
||||||
|
// 添加分页参数
|
||||||
|
data.pageIndex = pageInfo.value.page;
|
||||||
|
data.pageSize = pageInfo.value.pageSize;
|
||||||
|
|
||||||
|
return api.page(data);
|
||||||
|
};
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
// 页面加载
|
||||||
|
search();
|
||||||
|
});
|
||||||
|
|
||||||
|
function viewContent(row: any) {
|
||||||
|
ElMessageBox.alert(
|
||||||
|
`<textarea style="width: 400px;height: 300px;" readonly>${row.content}</textarea>`,
|
||||||
|
"发送内容",
|
||||||
|
{
|
||||||
|
dangerouslyUseHTMLString: true
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
actionButtons,
|
||||||
|
dlgShow,
|
||||||
|
dlgTitle,
|
||||||
|
editFormColumns,
|
||||||
|
editFormData,
|
||||||
|
editFormRules,
|
||||||
|
handleAdd,
|
||||||
|
handlePaginationChange,
|
||||||
|
handleSave,
|
||||||
|
handleSearch,
|
||||||
|
pageInfo,
|
||||||
|
searchFormColumns,
|
||||||
|
searchFormData,
|
||||||
|
tableColumns,
|
||||||
|
tableData,
|
||||||
|
total,
|
||||||
|
viewContent
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -0,0 +1,73 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import { useEntNotifyInfo } from "./index";
|
||||||
|
const {
|
||||||
|
actionButtons,
|
||||||
|
dlgShow,
|
||||||
|
dlgTitle,
|
||||||
|
editFormColumns,
|
||||||
|
editFormData,
|
||||||
|
editFormRules,
|
||||||
|
handleAdd,
|
||||||
|
handlePaginationChange,
|
||||||
|
handleSave,
|
||||||
|
handleSearch,
|
||||||
|
pageInfo,
|
||||||
|
searchFormColumns,
|
||||||
|
searchFormData,
|
||||||
|
tableColumns,
|
||||||
|
tableData,
|
||||||
|
total,
|
||||||
|
viewContent
|
||||||
|
} = useEntNotifyInfo();
|
||||||
|
</script>
|
||||||
|
<template>
|
||||||
|
<el-card shadow="never">
|
||||||
|
<template #header>
|
||||||
|
<PlusSearch
|
||||||
|
v-model="searchFormData"
|
||||||
|
:columns="searchFormColumns"
|
||||||
|
:show-number="3"
|
||||||
|
label-position="right"
|
||||||
|
:has-reset="true"
|
||||||
|
@reset="handleSearch"
|
||||||
|
@search="handleSearch"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
|
<PlusTable
|
||||||
|
:columns="tableColumns"
|
||||||
|
:table-data="tableData"
|
||||||
|
:action-bar="{ buttons: actionButtons, width: 130 }"
|
||||||
|
:pagination="{
|
||||||
|
total,
|
||||||
|
modelValue: pageInfo,
|
||||||
|
pageSizeList: [10, 20, 50, 100],
|
||||||
|
align: 'right'
|
||||||
|
}"
|
||||||
|
showOverflowTooltip
|
||||||
|
adaptive
|
||||||
|
@paginationChange="handlePaginationChange"
|
||||||
|
>
|
||||||
|
<template #title>
|
||||||
|
<el-button type="primary" @click="handleAdd">新增</el-button>
|
||||||
|
</template>
|
||||||
|
<template #plus-cell-content="scoped">
|
||||||
|
<el-link type="primary" @click="viewContent(scoped.row)">
|
||||||
|
查看
|
||||||
|
</el-link>
|
||||||
|
</template>
|
||||||
|
</PlusTable>
|
||||||
|
<PlusDialogForm
|
||||||
|
v-model:visible="dlgShow"
|
||||||
|
v-model="editFormData"
|
||||||
|
:dialog="{ title: dlgTitle }"
|
||||||
|
:form="{
|
||||||
|
columns: editFormColumns,
|
||||||
|
rules: editFormRules,
|
||||||
|
labelWidth: '100px',
|
||||||
|
labelPosition: 'right'
|
||||||
|
}"
|
||||||
|
:hasErrorTip="false"
|
||||||
|
@confirm="handleSave"
|
||||||
|
/>
|
||||||
|
</el-card>
|
||||||
|
</template>
|
||||||
25
sop-example/example-notify/.gitignore
vendored
Executable file
25
sop-example/example-notify/.gitignore
vendored
Executable file
@@ -0,0 +1,25 @@
|
|||||||
|
target/
|
||||||
|
!.mvn/wrapper/maven-wrapper.jar
|
||||||
|
|
||||||
|
### STS ###
|
||||||
|
.apt_generated
|
||||||
|
.classpath
|
||||||
|
.factorypath
|
||||||
|
.project
|
||||||
|
.settings
|
||||||
|
.springBeans
|
||||||
|
|
||||||
|
### IntelliJ IDEA ###
|
||||||
|
.idea
|
||||||
|
*.iws
|
||||||
|
*.iml
|
||||||
|
*.ipr
|
||||||
|
|
||||||
|
### NetBeans ###
|
||||||
|
nbproject/private/
|
||||||
|
build/
|
||||||
|
nbbuild/
|
||||||
|
dist/
|
||||||
|
nbdist/
|
||||||
|
.nb-gradle/
|
||||||
|
/local-config/
|
||||||
148
sop-example/example-notify/pom.xml
Executable file
148
sop-example/example-notify/pom.xml
Executable file
@@ -0,0 +1,148 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
|
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
<parent>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-parent</artifactId>
|
||||||
|
<version>2.6.15</version>
|
||||||
|
<relativePath/> <!-- lookup parent from repository -->
|
||||||
|
</parent>
|
||||||
|
|
||||||
|
<groupId>com.gitee.sop</groupId>
|
||||||
|
<artifactId>example-notify</artifactId>
|
||||||
|
<version>5.0.0-SNAPSHOT</version>
|
||||||
|
<name>example-notify</name>
|
||||||
|
|
||||||
|
<properties>
|
||||||
|
<java.version>1.8</java.version>
|
||||||
|
<!-- dubbo版本 -->
|
||||||
|
<dubbo.version>3.2.16</dubbo.version>
|
||||||
|
</properties>
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
<!-- 回调处理 -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.gitee.sop</groupId>
|
||||||
|
<artifactId>sop-notify-api</artifactId>
|
||||||
|
<version>5.0.0-SNAPSHOT</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<!-- sop接入依赖 -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.gitee.sop</groupId>
|
||||||
|
<artifactId>sop-spring-boot-starter</artifactId>
|
||||||
|
<version>5.0.0-SNAPSHOT</version>
|
||||||
|
</dependency>
|
||||||
|
<!-- nacos注册中心 -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.dubbo</groupId>
|
||||||
|
<artifactId>dubbo-nacos-spring-boot-starter</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<!-- zookeeper注册中心 -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.dubbo</groupId>
|
||||||
|
<artifactId>dubbo-zookeeper-curator5-spring-boot-starter</artifactId>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-web</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.gitee.sop</groupId>
|
||||||
|
<artifactId>sdk-java</artifactId>
|
||||||
|
<version>5.0.0-SNAPSHOT</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-test</artifactId>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.projectlombok</groupId>
|
||||||
|
<artifactId>lombok</artifactId>
|
||||||
|
<version>1.18.34</version>
|
||||||
|
<scope>provided</scope>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
|
||||||
|
<dependencyManagement>
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.dubbo</groupId>
|
||||||
|
<artifactId>dubbo-bom</artifactId>
|
||||||
|
<version>${dubbo.version}</version>
|
||||||
|
<type>pom</type>
|
||||||
|
<scope>import</scope>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
</dependencyManagement>
|
||||||
|
|
||||||
|
<build>
|
||||||
|
<plugins>
|
||||||
|
<!-- 打包时跳过测试 -->
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-surefire-plugin</artifactId>
|
||||||
|
<version>2.12.4</version>
|
||||||
|
<configuration>
|
||||||
|
<skipTests>true</skipTests>
|
||||||
|
</configuration>
|
||||||
|
</plugin>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||||
|
</plugin>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-compiler-plugin</artifactId>
|
||||||
|
<version>3.13.0</version>
|
||||||
|
<configuration>
|
||||||
|
<source>${java.version}</source>
|
||||||
|
<target>${java.version}</target>
|
||||||
|
<encoding>UTF-8</encoding>
|
||||||
|
<compilerArgs>
|
||||||
|
<arg>-parameters</arg>
|
||||||
|
</compilerArgs>
|
||||||
|
</configuration>
|
||||||
|
</plugin>
|
||||||
|
<!-- 文档推送 -->
|
||||||
|
<plugin>
|
||||||
|
<groupId>com.ly.smart-doc</groupId>
|
||||||
|
<artifactId>smart-doc-maven-plugin</artifactId>
|
||||||
|
<version>3.0.9</version>
|
||||||
|
<configuration>
|
||||||
|
<!--指定生成文档的使用的配置文件-->
|
||||||
|
<configFile>./src/main/resources/smart-doc.json</configFile>
|
||||||
|
<!--指定项目名称-->
|
||||||
|
<projectName>${project.artifactId}</projectName>
|
||||||
|
</configuration>
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.gitee.sop</groupId>
|
||||||
|
<artifactId>sop-service-support</artifactId>
|
||||||
|
<version>5.0.0-SNAPSHOT</version>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
</plugin>
|
||||||
|
</plugins>
|
||||||
|
</build>
|
||||||
|
|
||||||
|
<repositories>
|
||||||
|
<repository>
|
||||||
|
<id>spring-milestones</id>
|
||||||
|
<name>Spring Milestones</name>
|
||||||
|
<url>https://repo.spring.io/milestone</url>
|
||||||
|
</repository>
|
||||||
|
<repository>
|
||||||
|
<id>maven_central</id>
|
||||||
|
<name>Maven Central</name>
|
||||||
|
<url>https://repo.maven.apache.org/maven2/</url>
|
||||||
|
</repository>
|
||||||
|
</repositories>
|
||||||
|
|
||||||
|
</project>
|
||||||
1
sop-example/example-notify/push-doc.sh
Normal file
1
sop-example/example-notify/push-doc.sh
Normal file
@@ -0,0 +1 @@
|
|||||||
|
mvn -Dfile.encoding=UTF-8 -Dcheckstyle.skip=true smart-doc:torna-rpc
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
package com.gitee.sop.notifyexample;
|
||||||
|
|
||||||
|
import org.apache.dubbo.config.spring.context.annotation.EnableDubbo;
|
||||||
|
import org.springframework.boot.SpringApplication;
|
||||||
|
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||||
|
|
||||||
|
@SpringBootApplication
|
||||||
|
@EnableDubbo
|
||||||
|
public class ExampleNotifyApplication {
|
||||||
|
|
||||||
|
public static void main(String[] args) {
|
||||||
|
SpringApplication.run(ExampleNotifyApplication.class, args);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,71 @@
|
|||||||
|
package com.gitee.sop.notifyexample.controller;
|
||||||
|
|
||||||
|
|
||||||
|
import com.alibaba.fastjson2.JSON;
|
||||||
|
import com.alibaba.fastjson2.JSONObject;
|
||||||
|
import com.gitee.sop.sdk.sign.SignUtil;
|
||||||
|
import com.gitee.sop.sdk.sign.SopSignException;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.http.HttpStatus;
|
||||||
|
import org.springframework.http.ResponseEntity;
|
||||||
|
import org.springframework.web.bind.annotation.PostMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RequestBody;
|
||||||
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 处理回调
|
||||||
|
*
|
||||||
|
* @author 六如
|
||||||
|
*/
|
||||||
|
@RestController
|
||||||
|
@Slf4j
|
||||||
|
public class DemoCallbackController {
|
||||||
|
// 平台下发的公钥
|
||||||
|
String publicKey = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAj0CaMfudpfsrzgT7014aIGQPiEHvk5JPMlHH7YI5JYk+yAgePntojJ8/q1nmeHAauJqEYuCZHfqcjxzLM2hVvttrXtiacTMlr/ea9CGJtx4m20ltrsPOIXPXXZUToxXgO7X1FNvgXgeBBPcWLrsmJUgAQbM1KG/bo9QdNp/cFf5tBuo+1fXB9qXlZnSCbvQwrhfDGAF7NmEYkvkoQeys9YkASAl+zeEOXdBkPQjKDd9USyb/tIkrgLmeo0EOp+PytmEOAsMPSeIEdRcwrgg16X9BvMvnPKLTetQxXILG7r6kkkLj1pVA8EGinRDFu0jwp/Wu+wwUvRlpDRvUbyWEOQIDAQAB";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 模拟客户端处理接口回调
|
||||||
|
* 回调接口:http://127.0.0.1:7074/notify/callback
|
||||||
|
* 返回状态200表示成功收到请求
|
||||||
|
* 返回非200表示处理失败,平台会进行重试,重试机制见:com.gitee.sop.notify.service.NotifyBizService#timeLevel
|
||||||
|
* @param content
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
@PostMapping("notify/callback")
|
||||||
|
public ResponseEntity<String> callback(@RequestBody String content) {
|
||||||
|
log.info("收到回调通知, content={}", content);
|
||||||
|
JSONObject jsonObject = JSON.parseObject(content);
|
||||||
|
// 签名校验
|
||||||
|
if (!checkSign(jsonObject)) {
|
||||||
|
return ResponseEntity.status(HttpStatus.SERVICE_UNAVAILABLE)
|
||||||
|
.body("ERR");
|
||||||
|
}
|
||||||
|
log.info("签名验证通过,处理业务逻辑");
|
||||||
|
String method = jsonObject.getString("method");
|
||||||
|
// 判断业务类型,处理不同业务
|
||||||
|
switch (method) {
|
||||||
|
// 处理订单创建回调
|
||||||
|
case "shop.order.create": {
|
||||||
|
JSONObject bizContent = jsonObject.getJSONObject("biz_content");
|
||||||
|
log.info("业务参数,bizContent={}", bizContent);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case "shop.order.close": {
|
||||||
|
// 处理订单关闭回调
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:{}
|
||||||
|
}
|
||||||
|
// 返回200状态即可
|
||||||
|
return ResponseEntity.ok("success");
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean checkSign(JSONObject jsonObject) {
|
||||||
|
try {
|
||||||
|
return SignUtil.rsaCheckV2(jsonObject, publicKey, "UTF-8", "RSA2");
|
||||||
|
} catch (SopSignException e) {
|
||||||
|
log.error("签名校验错误, jsonObject={}", jsonObject, e);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
package com.gitee.sop.notifyexample.open;
|
||||||
|
|
||||||
|
import com.gitee.sop.notifyexample.open.req.CreateOrderRequest;
|
||||||
|
import com.gitee.sop.notifyexample.open.resp.CreateOrderResponse;
|
||||||
|
import com.gitee.sop.support.annotation.Open;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 回调接口
|
||||||
|
*
|
||||||
|
* @author 六如
|
||||||
|
*/
|
||||||
|
public interface OpenNotify {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 下单-回调
|
||||||
|
*
|
||||||
|
* @apiNote 演示回调
|
||||||
|
*/
|
||||||
|
@Open("shop.order.create")
|
||||||
|
CreateOrderResponse createOrder(CreateOrderRequest request);
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
package com.gitee.sop.notifyexample.open.impl;
|
||||||
|
|
||||||
|
import com.gitee.sop.notifyexample.open.OpenNotify;
|
||||||
|
import com.gitee.sop.notifyexample.open.req.CreateOrderRequest;
|
||||||
|
import com.gitee.sop.notifyexample.open.resp.CreateOrderResponse;
|
||||||
|
import com.gitee.sop.notifyexample.service.OrderService;
|
||||||
|
import com.gitee.sop.support.context.OpenContext;
|
||||||
|
import org.apache.dubbo.config.annotation.DubboService;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 开放接口实现
|
||||||
|
*
|
||||||
|
* @author 六如
|
||||||
|
*/
|
||||||
|
@DubboService(validation = "true")
|
||||||
|
public class OpenNotifyImpl implements OpenNotify {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private OrderService orderService;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CreateOrderResponse createOrder(CreateOrderRequest request) {
|
||||||
|
OpenContext openContext = OpenContext.current();
|
||||||
|
CreateOrderResponse response = new CreateOrderResponse();
|
||||||
|
String bizNumber = orderService.createOrder(request, openContext);
|
||||||
|
response.setOrderNo(bizNumber);
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,47 @@
|
|||||||
|
package com.gitee.sop.notifyexample.open.req;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
import org.hibernate.validator.constraints.Length;
|
||||||
|
|
||||||
|
import javax.validation.constraints.NotBlank;
|
||||||
|
import javax.validation.constraints.NotNull;
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建订单
|
||||||
|
*
|
||||||
|
* @author 六如
|
||||||
|
* https://opendocs.alipay.com/open/29ae8cb6_alipay.trade.wap.pay?pathHash=1ef587fd&ref=api&scene=21
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class CreateOrderRequest {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 商户网站唯一订单号
|
||||||
|
*
|
||||||
|
* @mock 70501111111S001111119
|
||||||
|
*/
|
||||||
|
@Length(max = 64)
|
||||||
|
@NotBlank(message = "商户网站唯一订单号必填")
|
||||||
|
private String outTradeNo;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 订单总金额.单位为元,精确到小数点后两位,取值范围:[0.01,100000000]
|
||||||
|
*
|
||||||
|
* @mock 9.00
|
||||||
|
*/
|
||||||
|
@NotNull(message = "订单总金额不能为空")
|
||||||
|
private BigDecimal totalAmount;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 订单标题。注意:不可使用特殊字符,如 /,=,& 等。
|
||||||
|
*
|
||||||
|
* @mock 大乐透
|
||||||
|
*/
|
||||||
|
@Length(max = 256)
|
||||||
|
@NotBlank(message = "订单标题不能为空")
|
||||||
|
private String subject;
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
package com.gitee.sop.notifyexample.open.resp;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import javax.validation.constraints.NotNull;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author 六如
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class CreateOrderResponse {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 订单号
|
||||||
|
*
|
||||||
|
* @mock 111
|
||||||
|
*/
|
||||||
|
@NotNull
|
||||||
|
private String orderNo;
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,77 @@
|
|||||||
|
package com.gitee.sop.notifyexample.service;
|
||||||
|
|
||||||
|
import com.gitee.sop.notify.api.NotifyService;
|
||||||
|
import com.gitee.sop.notify.api.req.NotifyRequest;
|
||||||
|
import com.gitee.sop.notify.api.resp.NotifyResponse;
|
||||||
|
import com.gitee.sop.notifyexample.open.req.CreateOrderRequest;
|
||||||
|
import com.gitee.sop.support.context.OpenContext;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.apache.dubbo.config.annotation.DubboReference;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.UUID;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 订单服务,回调处理
|
||||||
|
*
|
||||||
|
* @author 六如
|
||||||
|
*/
|
||||||
|
@Service
|
||||||
|
@Slf4j
|
||||||
|
public class OrderService {
|
||||||
|
|
||||||
|
@DubboReference
|
||||||
|
private NotifyService notifyService;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 下单成功
|
||||||
|
*
|
||||||
|
* @param request 入参
|
||||||
|
* @param openContext 开放平台上下文
|
||||||
|
* @return 返回订单编号
|
||||||
|
*/
|
||||||
|
public String createOrder(CreateOrderRequest request, OpenContext openContext) {
|
||||||
|
// 处理业务,回调客户端
|
||||||
|
// 生成一个业务编号
|
||||||
|
String orderNo = UUID.randomUUID().toString();
|
||||||
|
log.info("生成订单,编号:{}", orderNo);
|
||||||
|
// 模拟业务处理耗时
|
||||||
|
try {
|
||||||
|
TimeUnit.MILLISECONDS.sleep(500);
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
// 发送回调
|
||||||
|
this.sendNotifyTask(request, openContext, orderNo);
|
||||||
|
return orderNo;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void sendNotifyTask(CreateOrderRequest request, OpenContext openContext, String orderNo) {
|
||||||
|
// 回调
|
||||||
|
NotifyRequest notifyRequest = new NotifyRequest();
|
||||||
|
notifyRequest.setAppId(openContext.getAppId());
|
||||||
|
notifyRequest.setApiName(openContext.getApiName());
|
||||||
|
notifyRequest.setVersion(openContext.getVersion());
|
||||||
|
notifyRequest.setClientIp(openContext.getClientIp());
|
||||||
|
notifyRequest.setNotifyUrl(openContext.getNotifyUrl());
|
||||||
|
notifyRequest.setCharset(openContext.getCharset());
|
||||||
|
Map<String, Object> bizParams = new HashMap<>();
|
||||||
|
bizParams.put("orderNo", orderNo);
|
||||||
|
bizParams.put("msg", "success");
|
||||||
|
bizParams.put("price", "100");
|
||||||
|
notifyRequest.setBizParams(bizParams);
|
||||||
|
notifyRequest.setRemark("下单回调");
|
||||||
|
|
||||||
|
// 发送回调任务
|
||||||
|
NotifyResponse notifyResponse = notifyService.notify(notifyRequest);
|
||||||
|
log.info("回调返回,notifyResponse={}", notifyResponse);
|
||||||
|
if (notifyResponse.getSuccess()) {
|
||||||
|
log.info("保存notifyId到数据库, notifyId={}", notifyResponse.getNotifyId());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
1
sop-example/example-notify/src/main/resources/application-dev.properties
Executable file
1
sop-example/example-notify/src/main/resources/application-dev.properties
Executable file
@@ -0,0 +1 @@
|
|||||||
|
dubbo.registry.address=zookeeper://localhost:2181
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
|
||||||
|
dubbo.registry.address=nacos://localhost:8848
|
||||||
10
sop-example/example-notify/src/main/resources/application.properties
Executable file
10
sop-example/example-notify/src/main/resources/application.properties
Executable file
@@ -0,0 +1,10 @@
|
|||||||
|
spring.profiles.active=dev
|
||||||
|
|
||||||
|
server.port=7074
|
||||||
|
spring.application.name=example-notify
|
||||||
|
|
||||||
|
dubbo.protocol.name=dubbo
|
||||||
|
dubbo.protocol.port=-1
|
||||||
|
dubbo.application.qos-enable=false
|
||||||
|
dubbo.consumer.check=false
|
||||||
|
dubbo.registry.address=zookeeper://localhost:2181
|
||||||
27
sop-example/example-notify/src/main/resources/doc.json
Executable file
27
sop-example/example-notify/src/main/resources/doc.json
Executable file
@@ -0,0 +1,27 @@
|
|||||||
|
{
|
||||||
|
// 开启推送
|
||||||
|
"enable": true,
|
||||||
|
// 扫描package,多个用;隔开
|
||||||
|
"basePackage": "com.gitee.sop.payment.open",
|
||||||
|
// 推送URL,IP端口对应Torna服务器
|
||||||
|
"url": "http://localhost:7700/api",
|
||||||
|
// 模块token
|
||||||
|
"token": "34ff76952462413982d21219cf099d46",
|
||||||
|
// 推送人
|
||||||
|
"author": "Jim",
|
||||||
|
// 打开调试:true/false
|
||||||
|
"debug": true,
|
||||||
|
// 是否替换文档,true:替换,false:不替换(追加)。默认:true
|
||||||
|
"isReplace": true,
|
||||||
|
// 第三方jar中的class配置
|
||||||
|
"jarClass": {
|
||||||
|
"com.xx.Page": {
|
||||||
|
"records": { "value": "查询数据列表", "example": "" },
|
||||||
|
"total": { "value": "总数", "example": "100" },
|
||||||
|
"size": { "value": "页数", "example": "10" },
|
||||||
|
"current": { "value": "当前页", "example": "1" },
|
||||||
|
"countId": { "hidden": true },
|
||||||
|
"orders": { "hidden": true }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
# 错误配置
|
||||||
|
|
||||||
|
# 系统配置
|
||||||
|
isp.error_isv.common-error=The system is busy.
|
||||||
|
isp.error_isv.invalid-parameter=Invalid parameter, {0}
|
||||||
|
|
||||||
|
# ==== 参数配置 ====
|
||||||
|
|
||||||
|
goods.remark.notNull=The goods_remark can not be null
|
||||||
|
goods.comment.length=The goods_comment length must >= {0} and <= {1}
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
# 错误配置
|
||||||
|
|
||||||
|
# 系统繁忙
|
||||||
|
isp.error_isv.common-error=\u7cfb\u7edf\u7e41\u5fd9
|
||||||
|
# 参数无效
|
||||||
|
isp.error_isv.invalid-parameter=\u53c2\u6570\u65e0\u6548, {0}
|
||||||
|
|
||||||
|
# ==== 参数配置 ====
|
||||||
|
|
||||||
|
# 商品备注不能为空
|
||||||
|
goods.remark.notNull=\u5546\u54c1\u5907\u6ce8\u4e0d\u80fd\u4e3a\u7a7a
|
||||||
|
# 商品评论长度必须在{0}和{1}之间
|
||||||
|
goods.comment.length=\u5546\u54c1\u8bc4\u8bba\u957f\u5ea6\u5fc5\u987b\u5728{0}\u548c{1}\u4e4b\u95f4
|
||||||
|
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
isp.goods_error_100=the goods_name can NOT be null
|
||||||
|
isp.goods_error_101=the goods_name must bigger than {0}
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
# 商品名字不能为空
|
||||||
|
isp.goods_error_100=\u5546\u54C1\u540D\u79F0\u4E0D\u80FD\u4E3A\u7A7A
|
||||||
|
|
||||||
|
# 商品名称太短,不能小于{0}个字
|
||||||
|
isp.goods_error_101=\u5546\u54C1\u540D\u79F0\u592A\u77ED\uFF0C\u4E0D\u80FD\u5C0F\u4E8E{0}\u4E2A\u5B57
|
||||||
13
sop-example/example-notify/src/main/resources/smart-doc.json
Normal file
13
sop-example/example-notify/src/main/resources/smart-doc.json
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
{
|
||||||
|
"framework": "sop",
|
||||||
|
"outPath": "target/doc",
|
||||||
|
"projectName": "项目",
|
||||||
|
"packageFilters": "com.gitee.sop.payment.open.*",
|
||||||
|
"openUrl": "http://localhost:7700/api", // torna服务器地址
|
||||||
|
"appToken": "34ff76952462413982d21219cf099d46", // torna应用token
|
||||||
|
"debugEnvName":"本地环境",
|
||||||
|
"debugEnvUrl":"http://127.0.0.1:8081",
|
||||||
|
"tornaDebug": true,
|
||||||
|
"replace": true,
|
||||||
|
"showValidation": false
|
||||||
|
}
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
package com.gitee.sop.notifyexample;
|
||||||
|
|
||||||
|
|
||||||
|
import cn.torna.swaggerplugin.SwaggerPlugin;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 推送swagger文档
|
||||||
|
* @author thc
|
||||||
|
*/
|
||||||
|
public class DocPushTest {
|
||||||
|
public static void main(String[] args) {
|
||||||
|
SwaggerPlugin.pushDoc();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -13,5 +13,6 @@
|
|||||||
<module>example-payment</module>
|
<module>example-payment</module>
|
||||||
<module>example-product</module>
|
<module>example-product</module>
|
||||||
<module>example-rest</module>
|
<module>example-rest</module>
|
||||||
|
<module>example-notify</module>
|
||||||
</modules>
|
</modules>
|
||||||
</project>
|
</project>
|
||||||
|
|||||||
24
sop-notify/pom.xml
Normal file
24
sop-notify/pom.xml
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
<parent>
|
||||||
|
<groupId>com.gitee.sop</groupId>
|
||||||
|
<artifactId>sop-parent</artifactId>
|
||||||
|
<version>5.0.0-SNAPSHOT</version>
|
||||||
|
</parent>
|
||||||
|
|
||||||
|
<artifactId>sop-notify</artifactId>
|
||||||
|
<packaging>pom</packaging>
|
||||||
|
|
||||||
|
<properties>
|
||||||
|
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||||
|
</properties>
|
||||||
|
|
||||||
|
<modules>
|
||||||
|
<module>sop-notify-api</module>
|
||||||
|
<module>sop-notify-service</module>
|
||||||
|
</modules>
|
||||||
|
|
||||||
|
</project>
|
||||||
31
sop-notify/sop-notify-api/pom.xml
Normal file
31
sop-notify/sop-notify-api/pom.xml
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
<groupId>com.gitee.sop</groupId>
|
||||||
|
<artifactId>sop-notify-api</artifactId>
|
||||||
|
<version>5.0.0-SNAPSHOT</version>
|
||||||
|
|
||||||
|
<properties>
|
||||||
|
<maven.compiler.source>8</maven.compiler.source>
|
||||||
|
<maven.compiler.target>8</maven.compiler.target>
|
||||||
|
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||||
|
</properties>
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>javax.validation</groupId>
|
||||||
|
<artifactId>validation-api</artifactId>
|
||||||
|
<version>2.0.1.Final</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.projectlombok</groupId>
|
||||||
|
<artifactId>lombok</artifactId>
|
||||||
|
<version>1.18.36</version>
|
||||||
|
<optional>true</optional>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
|
||||||
|
</project>
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
package com.gitee.sop.notify.api;
|
||||||
|
|
||||||
|
import com.gitee.sop.notify.api.req.NotifyRequest;
|
||||||
|
import com.gitee.sop.notify.api.resp.NotifyResponse;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 回调接口
|
||||||
|
*
|
||||||
|
* @author 六如
|
||||||
|
*/
|
||||||
|
public interface NotifyService {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 回调
|
||||||
|
*
|
||||||
|
* @param request 参数
|
||||||
|
* @return 返回结果
|
||||||
|
*/
|
||||||
|
NotifyResponse notify(NotifyRequest request);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 回调立即发送
|
||||||
|
*
|
||||||
|
* @param notifyId notifyId
|
||||||
|
* @return 返回结果
|
||||||
|
*/
|
||||||
|
NotifyResponse notifyImmediately(Long notifyId);
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,66 @@
|
|||||||
|
package com.gitee.sop.notify.api.req;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import javax.validation.constraints.NotBlank;
|
||||||
|
import javax.validation.constraints.NotNull;
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author 六如
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class NotifyRequest implements Serializable {
|
||||||
|
private static final long serialVersionUID = -4018307141661725928L;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* appId
|
||||||
|
*/
|
||||||
|
@NotBlank(message = "appId必填")
|
||||||
|
private String appId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* apiName
|
||||||
|
*/
|
||||||
|
@NotBlank(message = "apiName必填")
|
||||||
|
private String apiName;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* version
|
||||||
|
*/
|
||||||
|
@NotBlank(message = "version必填")
|
||||||
|
private String version;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 编码
|
||||||
|
*/
|
||||||
|
@NotBlank(message = "charset必填")
|
||||||
|
private String charset;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* token,没有返回null
|
||||||
|
*/
|
||||||
|
private String appAuthToken;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 客户端ip
|
||||||
|
*/
|
||||||
|
private String clientIp;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 回调地址
|
||||||
|
*/
|
||||||
|
private String notifyUrl;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 业务参数
|
||||||
|
*/
|
||||||
|
@NotNull(message = "bizParams必填")
|
||||||
|
private Map<String, Object> bizParams;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 备注
|
||||||
|
*/
|
||||||
|
private String remark;
|
||||||
|
}
|
||||||
@@ -0,0 +1,39 @@
|
|||||||
|
package com.gitee.sop.notify.api.resp;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author 六如
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class NotifyResponse implements Serializable {
|
||||||
|
private static final long serialVersionUID = 5813802354743928430L;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 返回请求id
|
||||||
|
*/
|
||||||
|
private Long notifyId;
|
||||||
|
|
||||||
|
private Boolean success = true;
|
||||||
|
|
||||||
|
private String msg;
|
||||||
|
|
||||||
|
public static NotifyResponse success(Long notifyId) {
|
||||||
|
NotifyResponse notifyResponse = new NotifyResponse();
|
||||||
|
notifyResponse.setNotifyId(notifyId);
|
||||||
|
notifyResponse.setSuccess(true);
|
||||||
|
notifyResponse.setMsg("");
|
||||||
|
return notifyResponse;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static NotifyResponse error(String msg) {
|
||||||
|
NotifyResponse notifyResponse = new NotifyResponse();
|
||||||
|
notifyResponse.setNotifyId(null);
|
||||||
|
notifyResponse.setSuccess(false);
|
||||||
|
notifyResponse.setMsg(msg);
|
||||||
|
return notifyResponse;
|
||||||
|
}
|
||||||
|
}
|
||||||
154
sop-notify/sop-notify-service/pom.xml
Normal file
154
sop-notify/sop-notify-service/pom.xml
Normal file
@@ -0,0 +1,154 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
<parent>
|
||||||
|
<groupId>com.gitee.sop</groupId>
|
||||||
|
<artifactId>sop-notify</artifactId>
|
||||||
|
<version>5.0.0-SNAPSHOT</version>
|
||||||
|
</parent>
|
||||||
|
|
||||||
|
<artifactId>sop-notify-service</artifactId>
|
||||||
|
<version>5.0.0-SNAPSHOT</version>
|
||||||
|
|
||||||
|
<properties>
|
||||||
|
<java.version>1.8</java.version>
|
||||||
|
<!-- dubbo版本 -->
|
||||||
|
<dubbo.version>3.2.16</dubbo.version>
|
||||||
|
</properties>
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.gitee.sop</groupId>
|
||||||
|
<artifactId>sop-notify-api</artifactId>
|
||||||
|
<version>5.0.0-SNAPSHOT</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.gitee.sop</groupId>
|
||||||
|
<artifactId>sdk-java</artifactId>
|
||||||
|
<version>5.0.0-SNAPSHOT</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>io.gitee.durcframework</groupId>
|
||||||
|
<artifactId>fastmybatis-spring-boot-starter</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>net.oschina.durcframework</groupId>
|
||||||
|
<artifactId>http-helper</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<!-- sop接入依赖 -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.gitee.sop</groupId>
|
||||||
|
<artifactId>sop-spring-boot-starter</artifactId>
|
||||||
|
<version>5.0.0-SNAPSHOT</version>
|
||||||
|
</dependency>
|
||||||
|
<!-- nacos注册中心 -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.dubbo</groupId>
|
||||||
|
<artifactId>dubbo-nacos-spring-boot-starter</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<!-- zookeeper注册中心 -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.dubbo</groupId>
|
||||||
|
<artifactId>dubbo-zookeeper-curator5-spring-boot-starter</artifactId>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-jdbc</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>mysql</groupId>
|
||||||
|
<artifactId>mysql-connector-java</artifactId>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-test</artifactId>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.projectlombok</groupId>
|
||||||
|
<artifactId>lombok</artifactId>
|
||||||
|
<version>1.18.34</version>
|
||||||
|
<scope>provided</scope>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
|
||||||
|
<dependencyManagement>
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.dubbo</groupId>
|
||||||
|
<artifactId>dubbo-bom</artifactId>
|
||||||
|
<version>${dubbo.version}</version>
|
||||||
|
<type>pom</type>
|
||||||
|
<scope>import</scope>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
</dependencyManagement>
|
||||||
|
|
||||||
|
<build>
|
||||||
|
<plugins>
|
||||||
|
<!-- 打包时跳过测试 -->
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-surefire-plugin</artifactId>
|
||||||
|
<version>2.12.4</version>
|
||||||
|
<configuration>
|
||||||
|
<skipTests>true</skipTests>
|
||||||
|
</configuration>
|
||||||
|
</plugin>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||||
|
</plugin>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-compiler-plugin</artifactId>
|
||||||
|
<version>3.13.0</version>
|
||||||
|
<configuration>
|
||||||
|
<source>${java.version}</source>
|
||||||
|
<target>${java.version}</target>
|
||||||
|
<encoding>UTF-8</encoding>
|
||||||
|
<compilerArgs>
|
||||||
|
<arg>-parameters</arg>
|
||||||
|
</compilerArgs>
|
||||||
|
</configuration>
|
||||||
|
</plugin>
|
||||||
|
<!-- 文档推送 -->
|
||||||
|
<plugin>
|
||||||
|
<groupId>com.ly.smart-doc</groupId>
|
||||||
|
<artifactId>smart-doc-maven-plugin</artifactId>
|
||||||
|
<version>3.0.9</version>
|
||||||
|
<configuration>
|
||||||
|
<!--指定生成文档的使用的配置文件-->
|
||||||
|
<configFile>./src/main/resources/smart-doc.json</configFile>
|
||||||
|
<!--指定项目名称-->
|
||||||
|
<projectName>${project.artifactId}</projectName>
|
||||||
|
</configuration>
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.gitee.sop</groupId>
|
||||||
|
<artifactId>sop-service-support</artifactId>
|
||||||
|
<version>5.0.0-SNAPSHOT</version>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
</plugin>
|
||||||
|
</plugins>
|
||||||
|
</build>
|
||||||
|
|
||||||
|
<repositories>
|
||||||
|
<repository>
|
||||||
|
<id>spring-milestones</id>
|
||||||
|
<name>Spring Milestones</name>
|
||||||
|
<url>https://repo.spring.io/milestone</url>
|
||||||
|
</repository>
|
||||||
|
<repository>
|
||||||
|
<id>maven_central</id>
|
||||||
|
<name>Maven Central</name>
|
||||||
|
<url>https://repo.maven.apache.org/maven2/</url>
|
||||||
|
</repository>
|
||||||
|
</repositories>
|
||||||
|
</project>
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
package com.gitee.sop.notify;
|
||||||
|
|
||||||
|
import org.apache.dubbo.config.spring.context.annotation.EnableDubbo;
|
||||||
|
import org.springframework.boot.SpringApplication;
|
||||||
|
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||||
|
import org.springframework.scheduling.annotation.EnableScheduling;
|
||||||
|
|
||||||
|
@SpringBootApplication
|
||||||
|
@EnableDubbo
|
||||||
|
@EnableScheduling
|
||||||
|
public class SopNotifyApplication {
|
||||||
|
|
||||||
|
public static void main(String[] args) {
|
||||||
|
SpringApplication.run(SopNotifyApplication.class, args);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,99 @@
|
|||||||
|
package com.gitee.sop.notify.dao.entity;
|
||||||
|
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
|
||||||
|
import com.gitee.fastmybatis.annotation.Pk;
|
||||||
|
import com.gitee.fastmybatis.annotation.PkStrategy;
|
||||||
|
import com.gitee.fastmybatis.annotation.Table;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 表名:notify_info
|
||||||
|
* 备注:回调信息
|
||||||
|
*
|
||||||
|
* @author 六如
|
||||||
|
*/
|
||||||
|
@Table(name = "notify_info", pk = @Pk(name = "id", strategy = PkStrategy.INCREMENT))
|
||||||
|
@Data
|
||||||
|
public class NotifyInfo {
|
||||||
|
|
||||||
|
private Long id;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* app_id
|
||||||
|
*/
|
||||||
|
private String appId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* api_name
|
||||||
|
*/
|
||||||
|
private String apiName;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* api_version
|
||||||
|
*/
|
||||||
|
private String apiVersion;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 回调url
|
||||||
|
*/
|
||||||
|
private String notifyUrl;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 最近一次发送时间
|
||||||
|
*/
|
||||||
|
private LocalDateTime lastSendTime;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 下一次发送时间
|
||||||
|
*/
|
||||||
|
private LocalDateTime nextSendTime;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 已发送次数
|
||||||
|
*/
|
||||||
|
private Integer sendCnt;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 发送内容
|
||||||
|
*/
|
||||||
|
private String content;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 状态,1-发送成功,2-发送失败,3-重试结束
|
||||||
|
*/
|
||||||
|
private Integer notifyStatus;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 失败原因
|
||||||
|
*/
|
||||||
|
private String errorMsg;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 返回结果
|
||||||
|
*/
|
||||||
|
private String resultContent;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 备注
|
||||||
|
*/
|
||||||
|
private String remark;
|
||||||
|
|
||||||
|
private LocalDateTime addTime;
|
||||||
|
|
||||||
|
private LocalDateTime updateTime;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建人id
|
||||||
|
*/
|
||||||
|
private Long addBy;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 修改人id
|
||||||
|
*/
|
||||||
|
private Long updateBy;
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
package com.gitee.sop.notify.dao.mapper;
|
||||||
|
|
||||||
|
import org.apache.ibatis.annotations.Mapper;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author 六如
|
||||||
|
*/
|
||||||
|
@Mapper
|
||||||
|
public interface IsvMapper {
|
||||||
|
|
||||||
|
String getPrivatePlatformKey(String appId);
|
||||||
|
|
||||||
|
String getNotifyUrl(String appId);
|
||||||
|
}
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
package com.gitee.sop.notify.dao.mapper;
|
||||||
|
|
||||||
|
import com.gitee.fastmybatis.core.mapper.BaseMapper;
|
||||||
|
import com.gitee.sop.notify.dao.entity.NotifyInfo;
|
||||||
|
import org.apache.ibatis.annotations.Mapper;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author 六如
|
||||||
|
*/
|
||||||
|
@Mapper
|
||||||
|
public interface NotifyInfoMapper extends BaseMapper<NotifyInfo> {
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,48 @@
|
|||||||
|
package com.gitee.sop.notify.dubbo;
|
||||||
|
|
||||||
|
import com.gitee.sop.notify.api.NotifyService;
|
||||||
|
import com.gitee.sop.notify.api.req.NotifyRequest;
|
||||||
|
import com.gitee.sop.notify.api.resp.NotifyResponse;
|
||||||
|
import com.gitee.sop.notify.service.NotifyBizService;
|
||||||
|
import com.gitee.sop.notify.service.bo.NotifyBO;
|
||||||
|
import com.gitee.sop.sdk.sign.SopSignException;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.apache.dubbo.config.annotation.DubboService;
|
||||||
|
import org.springframework.beans.BeanUtils;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author 六如
|
||||||
|
*/
|
||||||
|
@DubboService(validation = "true")
|
||||||
|
@Slf4j
|
||||||
|
public class NotifyServiceImpl implements NotifyService {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private NotifyBizService notifyBizService;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public NotifyResponse notify(NotifyRequest request) {
|
||||||
|
NotifyBO notifyBO = new NotifyBO();
|
||||||
|
BeanUtils.copyProperties(request, notifyBO);
|
||||||
|
try {
|
||||||
|
Long notifyId = notifyBizService.notify(notifyBO);
|
||||||
|
return NotifyResponse.success(notifyId);
|
||||||
|
} catch (SopSignException e) {
|
||||||
|
log.error("回调异常,服务端签名失败, request={}", request, e);
|
||||||
|
return NotifyResponse.error(e.getErrMsg());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public NotifyResponse notifyImmediately(Long notifyId) {
|
||||||
|
try {
|
||||||
|
notifyBizService.notifyImmediately(notifyId);
|
||||||
|
return NotifyResponse.success(notifyId);
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("回调异常, notifyId={}", notifyId, e);
|
||||||
|
return NotifyResponse.error(e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
package com.gitee.sop.notify.enums;
|
||||||
|
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Getter;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author 六如
|
||||||
|
*/
|
||||||
|
@AllArgsConstructor
|
||||||
|
@Getter
|
||||||
|
public enum NotifyStatusEnum {
|
||||||
|
|
||||||
|
// 状态,1-发送成功,2-发送失败,3-重试结束
|
||||||
|
SEND_SUCCESS(1, "发送成功"),
|
||||||
|
SEND_FAIL(2, "发送失败"),
|
||||||
|
RETRY_OVER(3, "重试结束");
|
||||||
|
|
||||||
|
private final Integer value;
|
||||||
|
|
||||||
|
private final String description;
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
package com.gitee.sop.notify.schedule;
|
||||||
|
|
||||||
|
import com.gitee.sop.notify.service.NotifyBizService;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.scheduling.annotation.Scheduled;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author 六如
|
||||||
|
*/
|
||||||
|
@Component
|
||||||
|
public class NotifySchedule {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private NotifyBizService notifyBizService;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 每分钟执行一次
|
||||||
|
*/
|
||||||
|
@Scheduled(cron = "0 0/1 * * * ?")
|
||||||
|
public void run() {
|
||||||
|
notifyBizService.retry(LocalDateTime.now());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
package com.gitee.sop.notify.service;
|
||||||
|
|
||||||
|
import com.gitee.sop.notify.dao.mapper.IsvMapper;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author 六如
|
||||||
|
*/
|
||||||
|
@Service
|
||||||
|
public class IsvService {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private IsvMapper isvMapper;
|
||||||
|
|
||||||
|
public String getPrivatePlatformKey(String appId) {
|
||||||
|
return isvMapper.getPrivatePlatformKey(appId);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getNotifyUrl(String appId) {
|
||||||
|
return isvMapper.getNotifyUrl(appId);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,243 @@
|
|||||||
|
package com.gitee.sop.notify.service;
|
||||||
|
|
||||||
|
import com.alibaba.fastjson.JSON;
|
||||||
|
import com.gitee.fastmybatis.core.support.LambdaService;
|
||||||
|
import com.gitee.httphelper.HttpHelper;
|
||||||
|
import com.gitee.httphelper.result.ResponseResult;
|
||||||
|
import com.gitee.sop.notify.dao.entity.NotifyInfo;
|
||||||
|
import com.gitee.sop.notify.dao.mapper.NotifyInfoMapper;
|
||||||
|
import com.gitee.sop.notify.enums.NotifyStatusEnum;
|
||||||
|
import com.gitee.sop.notify.service.bo.NotifyBO;
|
||||||
|
import com.gitee.sop.sdk.sign.SignUtil;
|
||||||
|
import com.gitee.sop.sdk.sign.SopSignException;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
import org.apache.commons.lang3.math.NumberUtils;
|
||||||
|
import org.apache.http.HttpStatus;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import java.text.SimpleDateFormat;
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 回调业务逻辑处理
|
||||||
|
*
|
||||||
|
* @author 六如
|
||||||
|
*/
|
||||||
|
@Service
|
||||||
|
@Slf4j
|
||||||
|
public class NotifyBizService implements LambdaService<NotifyInfo, NotifyInfoMapper> {
|
||||||
|
|
||||||
|
// 对应第1,2,3...次尝试
|
||||||
|
// 即1分钟后进行第一次尝试,如果失败,5分钟后进行第二次尝试
|
||||||
|
@Value("${sop.notify.time-level:1m,5m,10m,30m,1h,2h,5h}")
|
||||||
|
private String timeLevel;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private IsvService isvService;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 第一次发送
|
||||||
|
*
|
||||||
|
* @param notifyBO 回调内容
|
||||||
|
* @return 返回回调id
|
||||||
|
* @throws SopSignException 异常处理
|
||||||
|
*/
|
||||||
|
public Long notify(NotifyBO notifyBO) throws SopSignException {
|
||||||
|
NotifyInfo notifyInfo = buildRecord(notifyBO);
|
||||||
|
return doNotify(notifyBO, notifyInfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void notifyImmediately(Long notifyId) throws SopSignException {
|
||||||
|
NotifyInfo notifyInfo = this.getById(notifyId);
|
||||||
|
String content = notifyInfo.getContent();
|
||||||
|
NotifyBO notifyBO = JSON.parseObject(content, NotifyBO.class);
|
||||||
|
// 发送请求
|
||||||
|
doNotify(notifyBO, notifyInfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 重试
|
||||||
|
*
|
||||||
|
* @param now 当前时间
|
||||||
|
*/
|
||||||
|
public void retry(LocalDateTime now) {
|
||||||
|
LocalDateTime nextTime = now.withSecond(0).withNano(0);
|
||||||
|
List<NotifyInfo> list = this.query()
|
||||||
|
.eq(NotifyInfo::getNextSendTime, nextTime)
|
||||||
|
.eq(NotifyInfo::getNotifyStatus, NotifyStatusEnum.SEND_FAIL.getValue())
|
||||||
|
.list();
|
||||||
|
if (list.isEmpty()) {
|
||||||
|
log.info("[notify]无重试记录");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (NotifyInfo notifyInfo : list) {
|
||||||
|
retry(notifyInfo);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void retry(NotifyInfo notifyInfo) {
|
||||||
|
String content = notifyInfo.getContent();
|
||||||
|
NotifyBO notifyBO = JSON.parseObject(content, NotifyBO.class);
|
||||||
|
try {
|
||||||
|
log.info("[notify]开始重试, notifyId={}", notifyInfo.getId());
|
||||||
|
if (Objects.equals(notifyInfo.getNotifyStatus(), NotifyStatusEnum.RETRY_OVER.getValue())) {
|
||||||
|
log.warn("重试次数已用尽, notifyId={}", notifyInfo.getId());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// 发送请求
|
||||||
|
doNotify(notifyBO, notifyInfo);
|
||||||
|
} catch (SopSignException e) {
|
||||||
|
log.error("[notify]重试签名错误,notifyId={}", notifyInfo.getId(), e);
|
||||||
|
throw new RuntimeException("重试失败,签名错误");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 构建下一次重试时间
|
||||||
|
*
|
||||||
|
* @param currentSendCnt 当前发送次数
|
||||||
|
* @return 返回null表示重试次数用完
|
||||||
|
*/
|
||||||
|
private LocalDateTime buildNextSendTime(Integer currentSendCnt) {
|
||||||
|
String[] split = timeLevel.split(",");
|
||||||
|
if (currentSendCnt >= split.length) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
// 1m
|
||||||
|
String exp = split[currentSendCnt - 1];
|
||||||
|
// 秒,毫秒归零f
|
||||||
|
LocalDateTime time = LocalDateTime.now().withSecond(0).withNano(0);
|
||||||
|
// 最后一个字符,如:m,h,d
|
||||||
|
char ch = exp.charAt(exp.length() - 1);
|
||||||
|
int value = NumberUtils.toInt(exp.substring(0, exp.length() - 1));
|
||||||
|
switch (String.valueOf(ch).toLowerCase()) {
|
||||||
|
case "m":
|
||||||
|
return time.plusMinutes(value);
|
||||||
|
case "h":
|
||||||
|
return time.plusHours(value);
|
||||||
|
case "d":
|
||||||
|
return time.plusDays(value);
|
||||||
|
default:
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private Long doNotify(NotifyBO notifyBO, NotifyInfo notifyInfo) throws SopSignException {
|
||||||
|
notifyInfo.setSendCnt(notifyInfo.getSendCnt() + 1);
|
||||||
|
notifyInfo.setLastSendTime(LocalDateTime.now());
|
||||||
|
notifyInfo.setNotifyUrl(buildNotifyUrl(notifyBO, notifyInfo));
|
||||||
|
|
||||||
|
String notifyUrl = notifyInfo.getNotifyUrl();
|
||||||
|
// 构建请求参数
|
||||||
|
Map<String, String> params = buildParams(notifyBO);
|
||||||
|
try {
|
||||||
|
if (StringUtils.isBlank(notifyUrl)) {
|
||||||
|
throw new RuntimeException("回调接口不能为空");
|
||||||
|
}
|
||||||
|
|
||||||
|
String json = JSON.toJSONString(params);
|
||||||
|
log.info("发送回调请求,notifyUrl={}, content={}", notifyUrl, json);
|
||||||
|
ResponseResult responseResult = HttpHelper.postJson(notifyUrl, json)
|
||||||
|
.execute();
|
||||||
|
|
||||||
|
// 这里判断收到200认为请求成功
|
||||||
|
int status = responseResult.getStatus();
|
||||||
|
String resultContent = responseResult.asString();
|
||||||
|
notifyInfo.setResultContent(resultContent);
|
||||||
|
if (status == HttpStatus.SC_OK) {
|
||||||
|
// 更新状态
|
||||||
|
notifyInfo.setNotifyStatus(NotifyStatusEnum.SEND_SUCCESS.getValue());
|
||||||
|
notifyInfo.setErrorMsg("");
|
||||||
|
} else {
|
||||||
|
// 回调失败
|
||||||
|
log.error("回调状态非200:{}, result={}", status, resultContent);
|
||||||
|
throw new RuntimeException(resultContent);
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("回调请求失败, notifyUrl={}, params={}, notifyBO={}", notifyUrl, params, notifyBO, e);
|
||||||
|
notifyInfo.setNotifyStatus(NotifyStatusEnum.SEND_FAIL.getValue());
|
||||||
|
notifyInfo.setErrorMsg(e.getMessage());
|
||||||
|
|
||||||
|
LocalDateTime nextSendTime = buildNextSendTime(notifyInfo.getSendCnt());
|
||||||
|
notifyInfo.setNextSendTime(nextSendTime);
|
||||||
|
|
||||||
|
if (nextSendTime == null) {
|
||||||
|
log.error("回调请求次数达到上线, notifyUrl={}, params={}", notifyUrl, params);
|
||||||
|
notifyInfo.setNotifyStatus(NotifyStatusEnum.RETRY_OVER.getValue());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this.saveOrUpdate(notifyInfo);
|
||||||
|
|
||||||
|
return notifyInfo.getId();
|
||||||
|
}
|
||||||
|
|
||||||
|
private Map<String, String> buildParams(NotifyBO notifyBO) throws SopSignException {
|
||||||
|
// 公共请求参数
|
||||||
|
Map<String, String> params = new HashMap<>();
|
||||||
|
String appId = notifyBO.getAppId();
|
||||||
|
params.put("app_id", appId);
|
||||||
|
params.put("method", notifyBO.getApiName());
|
||||||
|
params.put("format", "json");
|
||||||
|
params.put("charset", notifyBO.getCharset());
|
||||||
|
params.put("sign_type", "RSA2");
|
||||||
|
params.put("timestamp", new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
|
||||||
|
params.put("version", notifyBO.getVersion());
|
||||||
|
|
||||||
|
// 业务参数
|
||||||
|
Map<String, Object> bizContent = notifyBO.getBizParams();
|
||||||
|
|
||||||
|
params.put("biz_content", JSON.toJSONString(bizContent));
|
||||||
|
String content = SignUtil.getSignContent(params);
|
||||||
|
|
||||||
|
String privateKey = isvService.getPrivatePlatformKey(appId);
|
||||||
|
String sign = SignUtil.rsa256Sign(content, privateKey, notifyBO.getCharset());
|
||||||
|
params.put("sign", sign);
|
||||||
|
|
||||||
|
return params;
|
||||||
|
}
|
||||||
|
|
||||||
|
private String buildNotifyUrl(NotifyBO notifyBO, NotifyInfo notifyInfo) {
|
||||||
|
String savedUrl = notifyInfo.getNotifyUrl();
|
||||||
|
if (StringUtils.isNotBlank(savedUrl)) {
|
||||||
|
return savedUrl;
|
||||||
|
}
|
||||||
|
String notifyUrl = notifyBO.getNotifyUrl();
|
||||||
|
if (StringUtils.isBlank(notifyUrl)) {
|
||||||
|
notifyUrl = isvService.getNotifyUrl(notifyBO.getAppId());
|
||||||
|
}
|
||||||
|
return notifyUrl;
|
||||||
|
}
|
||||||
|
|
||||||
|
private NotifyInfo buildRecord(NotifyBO notifyBO) {
|
||||||
|
NotifyInfo notifyInfo = new NotifyInfo();
|
||||||
|
notifyInfo.setAppId(notifyBO.getAppId());
|
||||||
|
notifyInfo.setApiName(notifyBO.getApiName());
|
||||||
|
notifyInfo.setApiVersion(notifyBO.getVersion());
|
||||||
|
notifyInfo.setSendCnt(0);
|
||||||
|
notifyInfo.setContent(JSON.toJSONString(notifyBO));
|
||||||
|
notifyInfo.setNotifyStatus(0);
|
||||||
|
notifyInfo.setErrorMsg("");
|
||||||
|
notifyInfo.setRemark(notifyBO.getRemark());
|
||||||
|
notifyInfo.setAddTime(LocalDateTime.now());
|
||||||
|
notifyInfo.setUpdateTime(LocalDateTime.now());
|
||||||
|
notifyInfo.setAddBy(0L);
|
||||||
|
notifyInfo.setUpdateBy(0L);
|
||||||
|
|
||||||
|
return notifyInfo;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,64 @@
|
|||||||
|
package com.gitee.sop.notify.service.bo;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import javax.validation.constraints.NotBlank;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author 六如
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class NotifyBO {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* appId
|
||||||
|
*/
|
||||||
|
@NotBlank(message = "appId必填")
|
||||||
|
private String appId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* apiName
|
||||||
|
*/
|
||||||
|
@NotBlank(message = "apiName必填")
|
||||||
|
private String apiName;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* version
|
||||||
|
*/
|
||||||
|
@NotBlank(message = "version必填")
|
||||||
|
private String version;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* token,没有返回null
|
||||||
|
*/
|
||||||
|
private String appAuthToken;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 客户端ip
|
||||||
|
*/
|
||||||
|
private String clientIp;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 回调地址
|
||||||
|
*/
|
||||||
|
@NotBlank(message = "notifyUrl必填")
|
||||||
|
private String notifyUrl;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 编码
|
||||||
|
*/
|
||||||
|
private String charset;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 业务参数
|
||||||
|
*/
|
||||||
|
@NotBlank(message = "bizParams必填")
|
||||||
|
private Map<String, Object> bizParams;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 备注
|
||||||
|
*/
|
||||||
|
private String remark;
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
mybatis.print-sql=true
|
||||||
|
|
||||||
|
# mysql config
|
||||||
|
mysql.host=127.0.0.1:3306
|
||||||
|
mysql.db=sop
|
||||||
|
mysql.username=root
|
||||||
|
mysql.password=12345678
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
dubbo.registry.address=nacos://localhost:8848
|
||||||
|
|
||||||
|
mybatis.print-sql=true
|
||||||
|
|
||||||
|
# mysql config
|
||||||
|
mysql.host=127.0.0.1:3306
|
||||||
|
mysql.db=sop
|
||||||
|
mysql.username=root
|
||||||
|
mysql.password=root
|
||||||
47
sop-notify/sop-notify-service/src/main/resources/application.properties
Executable file
47
sop-notify/sop-notify-service/src/main/resources/application.properties
Executable file
@@ -0,0 +1,47 @@
|
|||||||
|
server.port=8085
|
||||||
|
spring.profiles.active=dev
|
||||||
|
|
||||||
|
spring.application.name=sop-notify
|
||||||
|
|
||||||
|
dubbo.protocol.name=dubbo
|
||||||
|
dubbo.protocol.port=-1
|
||||||
|
dubbo.application.qos-enable=false
|
||||||
|
dubbo.consumer.check=false
|
||||||
|
# ### register config see:https://cn.dubbo.apache.org/zh-cn/overview/mannual/java-sdk/reference-manual/registry/overview/
|
||||||
|
# ------
|
||||||
|
# nacos://localhost:8848 Cluster config:nacos://localhost:8848?backup=localshot:8846,localshot:8847
|
||||||
|
# zookeeper://localhost:2181 Cluster config:zookeeper://10.20.153.10:2181?backup=10.20.153.11:2181,10.20.153.12:2181
|
||||||
|
# redis://localhost:6379 Cluster config:redis://10.20.153.10:6379?backup=10.20.153.11:6379,10.20.153.12:6379
|
||||||
|
# ------
|
||||||
|
dubbo.registry.address=zookeeper://localhost:2181
|
||||||
|
|
||||||
|
####### mysql config #######
|
||||||
|
mysql.host=127.0.0.1:3306
|
||||||
|
mysql.db=sop
|
||||||
|
mysql.username=
|
||||||
|
mysql.password=
|
||||||
|
|
||||||
|
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
|
||||||
|
spring.datasource.url=jdbc:mysql://${mysql.host}/${mysql.db}?useUnicode=true&characterEncoding=utf-8&zeroDateTimeBehavior=convertToNull&serverTimezone=Asia/Shanghai
|
||||||
|
spring.datasource.username=${mysql.username}
|
||||||
|
spring.datasource.password=${mysql.password}
|
||||||
|
|
||||||
|
####### mybatis config #######
|
||||||
|
mybatis.fill.com.gitee.fastmybatis.core.support.LocalDateTimeFillInsert=add_time
|
||||||
|
mybatis.fill.com.gitee.fastmybatis.core.support.LocalDateTimeFillUpdate=update_time
|
||||||
|
# mybatis config file
|
||||||
|
mybatis.config-location=classpath:mybatis/mybatisConfig.xml
|
||||||
|
mybatis.mapper-locations=classpath:mybatis/mapper/*.xml
|
||||||
|
|
||||||
|
# log level
|
||||||
|
logging.level.com.gitee.sop=info
|
||||||
|
# log path
|
||||||
|
logging.file.name=logs/sop-notify.log
|
||||||
|
# print SQL
|
||||||
|
logging.level.com.gitee.sop.notify.dao=error
|
||||||
|
logging.level.com.gitee.fastmybatis=info
|
||||||
|
mybatis.print-sql=false
|
||||||
|
|
||||||
|
# \u5BF9\u5E94\u7B2C1\uFF0C2\uFF0C3...\u6B21\u5C1D\u8BD5
|
||||||
|
# \u53731\u5206\u949F\u540E\u8FDB\u884C\u7B2C\u4E00\u6B21\u5C1D\u8BD5\uFF0C\u5982\u679C\u5931\u8D25\uFF0C5\u5206\u949F\u540E\u8FDB\u884C\u7B2C\u4E8C\u6B21\u5C1D\u8BD5
|
||||||
|
sop.notify.time-level:1m,5m,10m,30m,1h,2h,5h
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" ?>
|
||||||
|
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
|
||||||
|
<mapper namespace="com.gitee.sop.notify.dao.mapper.IsvMapper">
|
||||||
|
|
||||||
|
<select id="getPrivatePlatformKey" resultType="String">
|
||||||
|
select t2.private_key_platform
|
||||||
|
from isv_info t inner join isv_keys t2 on t.id = t2.isv_id
|
||||||
|
where app_id=#{appId}
|
||||||
|
limit 1
|
||||||
|
</select>
|
||||||
|
|
||||||
|
<select id="getNotifyUrl" resultType="String">
|
||||||
|
select t.notify_url
|
||||||
|
from isv_info t
|
||||||
|
where app_id=#{appId}
|
||||||
|
limit 1
|
||||||
|
</select>
|
||||||
|
|
||||||
|
</mapper>
|
||||||
26
sop-notify/sop-notify-service/src/main/resources/mybatis/mybatisConfig.xml
Executable file
26
sop-notify/sop-notify-service/src/main/resources/mybatis/mybatisConfig.xml
Executable file
@@ -0,0 +1,26 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd">
|
||||||
|
<configuration>
|
||||||
|
<settings>
|
||||||
|
<!-- 全局映射器启用缓存 -->
|
||||||
|
<setting name="cacheEnabled" value="true" />
|
||||||
|
<!-- 查询时,关闭关联对象即时加载以提高性能 -->
|
||||||
|
<setting name="lazyLoadingEnabled" value="true" />
|
||||||
|
<!-- 对于未知的SQL查询,允许返回不同的结果集以达到通用的效果 -->
|
||||||
|
<setting name="multipleResultSetsEnabled" value="true" />
|
||||||
|
<!-- 允许使用列标签代替列名 -->
|
||||||
|
<setting name="useColumnLabel" value="true" />
|
||||||
|
<!-- 允许使用自定义的主键值(比如由程序生成的UUID 32位编码作为键值),数据表的PK生成策略将被覆盖 -->
|
||||||
|
<setting name="useGeneratedKeys" value="false" />
|
||||||
|
<!-- 对于批量更新操作缓存SQL以提高性能:BATCH -->
|
||||||
|
<setting name="defaultExecutorType" value="SIMPLE" />
|
||||||
|
<!-- 超时设置 -->
|
||||||
|
<setting name="defaultStatementTimeout" value="25000" />
|
||||||
|
</settings>
|
||||||
|
|
||||||
|
<plugins>
|
||||||
|
<plugin interceptor="com.gitee.fastmybatis.core.support.plugin.SqlFormatterPlugin">
|
||||||
|
</plugin>
|
||||||
|
</plugins>
|
||||||
|
|
||||||
|
</configuration>
|
||||||
@@ -1,42 +0,0 @@
|
|||||||
package com.gitee.sop.support.dto;
|
|
||||||
|
|
||||||
import lombok.Data;
|
|
||||||
|
|
||||||
import java.io.Serializable;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 回调信息
|
|
||||||
*
|
|
||||||
* @author 六如
|
|
||||||
*/
|
|
||||||
@Data
|
|
||||||
public class NotifyInfo implements Serializable {
|
|
||||||
private static final long serialVersionUID = -2492336644456313771L;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 链路id
|
|
||||||
*/
|
|
||||||
private String traceId;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 回调接口
|
|
||||||
*/
|
|
||||||
private String url;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 跟在url后面的参数
|
|
||||||
*/
|
|
||||||
private Map<String, Object> query;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 请求头
|
|
||||||
*/
|
|
||||||
private Map<String, Object> header;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 请求体
|
|
||||||
*/
|
|
||||||
private Map<String, Object> body;
|
|
||||||
|
|
||||||
}
|
|
||||||
65
sop-test/src/test/java/com/gitee/sop/test/NotifyTest.java
Normal file
65
sop-test/src/test/java/com/gitee/sop/test/NotifyTest.java
Normal file
@@ -0,0 +1,65 @@
|
|||||||
|
package com.gitee.sop.test;
|
||||||
|
|
||||||
|
import java.util.LinkedHashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author 六如
|
||||||
|
*/
|
||||||
|
public class NotifyTest extends TestBase {
|
||||||
|
|
||||||
|
String url = "http://localhost:8081/api";
|
||||||
|
String appId = "2019032617262200001";
|
||||||
|
String privateKey = "MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCXJv1pQFqWNA/++OYEV7WYXwexZK/J8LY1OWlP9X0T6wHFOvxNKRvMkJ5544SbgsJpVcvRDPrcxmhPbi/sAhdO4x2PiPKIz9Yni2OtYCCeaiE056B+e1O2jXoLeXbfi9fPivJZkxH/tb4xfLkH3bA8ZAQnQsoXA0SguykMRZntF0TndUfvDrLqwhlR8r5iRdZLB6F8o8qXH6UPDfNEnf/K8wX5T4EB1b8x8QJ7Ua4GcIUqeUxGHdQpzNbJdaQvoi06lgccmL+PHzminkFYON7alj1CjDN833j7QMHdPtS9l7B67fOU/p2LAAkPMtoVBfxQt9aFj7B8rEhGCz02iJIBAgMBAAECggEARqOuIpY0v6WtJBfmR3lGIOOokLrhfJrGTLF8CiZMQha+SRJ7/wOLPlsH9SbjPlopyViTXCuYwbzn2tdABigkBHYXxpDV6CJZjzmRZ+FY3S/0POlTFElGojYUJ3CooWiVfyUMhdg5vSuOq0oCny53woFrf32zPHYGiKdvU5Djku1onbDU0Lw8w+5tguuEZ76kZ/lUcccGy5978FFmYpzY/65RHCpvLiLqYyWTtaNT1aQ/9pw4jX9HO9NfdJ9gYFK8r/2f36ZE4hxluAfeOXQfRC/WhPmiw/ReUhxPznG/WgKaa/OaRtAx3inbQ+JuCND7uuKeRe4osP2jLPHPP6AUwQKBgQDUNu3BkLoKaimjGOjCTAwtp71g1oo+k5/uEInAo7lyEwpV0EuUMwLA/HCqUgR4K9pyYV+Oyb8d6f0+Hz0BMD92I2pqlXrD7xV2WzDvyXM3s63NvorRooKcyfd9i6ccMjAyTR2qfLkxv0hlbBbsPHz4BbU63xhTJp3Ghi0/ey/1HQKBgQC2VsgqC6ykfSidZUNLmQZe3J0p/Qf9VLkfrQ+xaHapOs6AzDU2H2osuysqXTLJHsGfrwVaTs00ER2z8ljTJPBUtNtOLrwNRlvgdnzyVAKHfOgDBGwJgiwpeE9voB1oAV/mXqSaUWNnuwlOIhvQEBwekqNyWvhLqC7nCAIhj3yvNQKBgQCqYbeec56LAhWP903Zwcj9VvG7sESqXUhIkUqoOkuIBTWFFIm54QLTA1tJxDQGb98heoCIWf5x/A3xNI98RsqNBX5JON6qNWjb7/dobitti3t99v/ptDp9u8JTMC7penoryLKK0Ty3bkan95Kn9SC42YxaSghzqkt+uvfVQgiNGQKBgGxU6P2aDAt6VNwWosHSe+d2WWXt8IZBhO9d6dn0f7ORvcjmCqNKTNGgrkewMZEuVcliueJquR47IROdY8qmwqcBAN7Vg2K7r7CPlTKAWTRYMJxCT1Hi5gwJb+CZF3+IeYqsJk2NF2s0w5WJTE70k1BSvQsfIzAIDz2yE1oPHvwVAoGAA6e+xQkVH4fMEph55RJIZ5goI4Y76BSvt2N5OKZKd4HtaV+eIhM3SDsVYRLIm9ZquJHMiZQGyUGnsvrKL6AAVNK7eQZCRDk9KQz+0GKOGqku0nOZjUbAu6A2/vtXAaAuFSFx1rUQVVjFulLexkXR3KcztL1Qu2k5pB6Si0K/uwQ=";
|
||||||
|
|
||||||
|
private final Client client = new Client(url, appId, privateKey, AllInOneTest::assertResult);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 以get方式提交
|
||||||
|
*/
|
||||||
|
public void testGet() {
|
||||||
|
// 参见:com.gitee.sop.notifyexample.open.req.CreateOrderRequest
|
||||||
|
Map<String, Object> bizContent = new LinkedHashMap<>();
|
||||||
|
bizContent.put("outTradeNo", "1111");
|
||||||
|
bizContent.put("totalAmount", "100");
|
||||||
|
bizContent.put("subject", "话费");
|
||||||
|
|
||||||
|
Client.RequestBuilder requestBuilder = new Client.RequestBuilder()
|
||||||
|
.method("shop.order.create")
|
||||||
|
.version("1.0")
|
||||||
|
// 回调地址,见:com.gitee.sop.notifyexample.controller.DemoCallbackController
|
||||||
|
.notifyUrl("http://127.0.0.1:7074/notify/callback")
|
||||||
|
.bizContent(bizContent)
|
||||||
|
.httpMethod(HttpTool.HTTPMethod.GET)
|
||||||
|
.callback((requestInfo, responseData) -> {
|
||||||
|
System.out.println(responseData);
|
||||||
|
});
|
||||||
|
|
||||||
|
client.execute(requestBuilder);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 不填notifyUrl
|
||||||
|
*/
|
||||||
|
public void testGet2() {
|
||||||
|
// 参见:com.gitee.sop.notifyexample.open.req.CreateOrderRequest
|
||||||
|
Map<String, Object> bizContent = new LinkedHashMap<>();
|
||||||
|
bizContent.put("outTradeNo", "1111");
|
||||||
|
bizContent.put("totalAmount", "100");
|
||||||
|
bizContent.put("subject", "话费");
|
||||||
|
|
||||||
|
Client.RequestBuilder requestBuilder = new Client.RequestBuilder()
|
||||||
|
.method("shop.order.create")
|
||||||
|
.version("1.0")
|
||||||
|
// 回调地址,见:com.gitee.sop.notifyexample.controller.DemoCallbackController
|
||||||
|
//.notifyUrl("http://127.0.0.1:7074/notify/callback")
|
||||||
|
.bizContent(bizContent)
|
||||||
|
.httpMethod(HttpTool.HTTPMethod.POST)
|
||||||
|
.callback((requestInfo, responseData) -> {
|
||||||
|
System.out.println(responseData);
|
||||||
|
});
|
||||||
|
|
||||||
|
client.execute(requestBuilder);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
31
sop.sql
31
sop.sql
@@ -493,7 +493,6 @@ CREATE TABLE `help_doc` (
|
|||||||
PRIMARY KEY (`id`)
|
PRIMARY KEY (`id`)
|
||||||
) ENGINE=InnoDB COMMENT='帮助内容表';
|
) ENGINE=InnoDB COMMENT='帮助内容表';
|
||||||
|
|
||||||
|
|
||||||
-- 2025-08-17
|
-- 2025-08-17
|
||||||
CREATE TABLE `isv_merchant`
|
CREATE TABLE `isv_merchant`
|
||||||
(
|
(
|
||||||
@@ -507,3 +506,33 @@ CREATE TABLE `isv_merchant`
|
|||||||
PRIMARY KEY (`id`),
|
PRIMARY KEY (`id`),
|
||||||
UNIQUE KEY `uk_appid_merchant` (`app_id`, merchant_code)
|
UNIQUE KEY `uk_appid_merchant` (`app_id`, merchant_code)
|
||||||
) ENGINE=InnoDB COMMENT='isv商户关系表';
|
) ENGINE=InnoDB COMMENT='isv商户关系表';
|
||||||
|
|
||||||
|
-- 2025-11-01
|
||||||
|
ALTER TABLE `isv_info`
|
||||||
|
ADD COLUMN `notify_url` varchar(256) NULL COMMENT '回调接口';
|
||||||
|
|
||||||
|
CREATE TABLE `notify_info` (
|
||||||
|
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
|
||||||
|
`app_id` varchar(64) NOT NULL COMMENT 'app_id',
|
||||||
|
`api_name` varchar(64) NOT NULL COMMENT 'api_name',
|
||||||
|
`api_version` varchar(16) NOT NULL COMMENT 'api_version',
|
||||||
|
`notify_url` varchar(255) DEFAULT '' COMMENT '回调url',
|
||||||
|
`last_send_time` datetime DEFAULT NULL COMMENT '最近一次发送时间',
|
||||||
|
`next_send_time` datetime DEFAULT NULL COMMENT '下一次发送时间',
|
||||||
|
`send_max` int(11) DEFAULT NULL COMMENT '最大发送次数',
|
||||||
|
`send_cnt` int(11) DEFAULT NULL COMMENT '已发送次数',
|
||||||
|
`content` text COMMENT '发送内容',
|
||||||
|
`notify_status` tinyint(4) DEFAULT '1' COMMENT '状态,1-发送成功,2-发送失败,3-重试结束',
|
||||||
|
`error_msg` text COMMENT '失败原因',
|
||||||
|
`result_content` text COMMENT '返回结果',
|
||||||
|
`remark` varchar(256) DEFAULT '' COMMENT '备注',
|
||||||
|
`add_time` datetime DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
`update_time` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||||
|
`add_by` bigint(20) DEFAULT '0' COMMENT '创建人id',
|
||||||
|
`update_by` bigint(20) DEFAULT '0' COMMENT '修改人id',
|
||||||
|
PRIMARY KEY (`id`),
|
||||||
|
KEY `idx_app_id` (`app_id`) USING BTREE
|
||||||
|
) ENGINE=InnoDB COMMENT='回调信息';
|
||||||
|
|
||||||
|
INSERT INTO `sys_resource` ( `menu_type`, `title`, `name`, `path`, `component`, `rank`, `redirect`, `icon`, `extra_icon`, `enter_transition`, `leave_transition`, `active_path`, `auths`, `frame_src`, `frame_loading`, `keep_alive`, `hidden_tag`, `fixed_tag`, `show_link`, `show_parent`, `parent_id`, `is_deleted`, `add_time`, `update_time`, `add_by`, `update_by`) VALUES
|
||||||
|
(0, '回调管理', 'NotifyMgr', '/serve/notify', '', 99, '', 'ri:align-vertically', '', '', '', '', '', '', 0, 0, 0, 0, 1, 0, 1, 0, '2025-11-01 20:37:08', '2025-11-01 20:37:08', 1, 1);
|
||||||
|
|||||||
29
upgrade/sop-20251101.sql
Normal file
29
upgrade/sop-20251101.sql
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
ALTER TABLE `isv_info`
|
||||||
|
ADD COLUMN `notify_url` varchar(256) NULL COMMENT '回调接口';
|
||||||
|
|
||||||
|
CREATE TABLE `notify_info`
|
||||||
|
(
|
||||||
|
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
|
||||||
|
`app_id` varchar(64) NOT NULL COMMENT 'app_id',
|
||||||
|
`api_name` varchar(64) NOT NULL COMMENT 'api_name',
|
||||||
|
`api_version` varchar(16) NOT NULL COMMENT 'api_version',
|
||||||
|
`notify_url` varchar(255) DEFAULT '' COMMENT '回调url',
|
||||||
|
`last_send_time` datetime DEFAULT NULL COMMENT '最近一次发送时间',
|
||||||
|
`next_send_time` datetime DEFAULT NULL COMMENT '下一次发送时间',
|
||||||
|
`send_max` int(11) DEFAULT NULL COMMENT '最大发送次数',
|
||||||
|
`send_cnt` int(11) DEFAULT NULL COMMENT '已发送次数',
|
||||||
|
`content` text COMMENT '发送内容',
|
||||||
|
`notify_status` tinyint(4) DEFAULT '1' COMMENT '状态,1-发送成功,2-发送失败,3-重试结束',
|
||||||
|
`error_msg` text COMMENT '失败原因',
|
||||||
|
`result_content` text COMMENT '返回结果',
|
||||||
|
`remark` varchar(256) DEFAULT '' COMMENT '备注',
|
||||||
|
`add_time` datetime DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
`update_time` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||||
|
`add_by` bigint(20) DEFAULT '0' COMMENT '创建人id',
|
||||||
|
`update_by` bigint(20) DEFAULT '0' COMMENT '修改人id',
|
||||||
|
PRIMARY KEY (`id`),
|
||||||
|
KEY `idx_app_id` (`app_id`) USING BTREE
|
||||||
|
) ENGINE=InnoDB COMMENT='回调信息';
|
||||||
|
|
||||||
|
INSERT INTO `sys_resource` ( `menu_type`, `title`, `name`, `path`, `component`, `rank`, `redirect`, `icon`, `extra_icon`, `enter_transition`, `leave_transition`, `active_path`, `auths`, `frame_src`, `frame_loading`, `keep_alive`, `hidden_tag`, `fixed_tag`, `show_link`, `show_parent`, `parent_id`, `is_deleted`, `add_time`, `update_time`, `add_by`, `update_by`) VALUES
|
||||||
|
(0, '回调管理', 'NotifyMgr', '/serve/notify', '', 99, '', 'ri:align-vertically', '', '', '', '', '', '', 0, 0, 0, 0, 1, 0, 1, 0, '2025-11-01 20:37:08', '2025-11-01 20:37:08', 1, 1);
|
||||||
Reference in New Issue
Block a user