commit
f2cd7532a9
@ -1,8 +1,22 @@
|
|||||||
package com.java3y.austin.common.dto.model;
|
package com.java3y.austin.common.dto.model;
|
||||||
|
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Builder;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author 3y
|
* @author 3y
|
||||||
*/
|
*/
|
||||||
|
@Data
|
||||||
|
@Builder
|
||||||
|
@AllArgsConstructor
|
||||||
|
@NoArgsConstructor
|
||||||
public class MiniProgramContentModel extends ContentModel {
|
public class MiniProgramContentModel extends ContentModel {
|
||||||
|
/**
|
||||||
|
* 模板消息发送的数据
|
||||||
|
*/
|
||||||
|
Map<String, String> map;
|
||||||
}
|
}
|
||||||
|
@ -1,9 +1,23 @@
|
|||||||
package com.java3y.austin.common.dto.model;
|
package com.java3y.austin.common.dto.model;
|
||||||
|
|
||||||
|
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Builder;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author 3y
|
* @author 3y
|
||||||
|
*
|
||||||
|
* 通知栏消息推送
|
||||||
*/
|
*/
|
||||||
|
@Data
|
||||||
|
@Builder
|
||||||
|
@AllArgsConstructor
|
||||||
|
@NoArgsConstructor
|
||||||
public class PushContentModel extends ContentModel {
|
public class PushContentModel extends ContentModel {
|
||||||
|
|
||||||
|
private String title;
|
||||||
|
private String content;
|
||||||
|
private String url;
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,37 @@
|
|||||||
|
package com.java3y.austin.cron.dto.getui;
|
||||||
|
|
||||||
|
import com.alibaba.fastjson.annotation.JSONField;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Builder;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author 3y
|
||||||
|
* @date 2022/5/8
|
||||||
|
* <p>
|
||||||
|
* https://docs.getui.com/getui/server/rest_v2/token/
|
||||||
|
*/
|
||||||
|
@NoArgsConstructor
|
||||||
|
@Data
|
||||||
|
@AllArgsConstructor
|
||||||
|
@Builder
|
||||||
|
public class GeTuiTokenResultDTO {
|
||||||
|
|
||||||
|
|
||||||
|
@JSONField(name = "msg")
|
||||||
|
private String msg;
|
||||||
|
@JSONField(name = "code")
|
||||||
|
private Integer code;
|
||||||
|
@JSONField(name = "data")
|
||||||
|
private DataDTO data;
|
||||||
|
|
||||||
|
@NoArgsConstructor
|
||||||
|
@Data
|
||||||
|
public static class DataDTO {
|
||||||
|
@JSONField(name = "expire_time")
|
||||||
|
private String expireTime;
|
||||||
|
@JSONField(name = "token")
|
||||||
|
private String token;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,40 @@
|
|||||||
|
package com.java3y.austin.cron.dto.getui;
|
||||||
|
|
||||||
|
import cn.hutool.crypto.SecureUtil;
|
||||||
|
import cn.hutool.http.ContentType;
|
||||||
|
import cn.hutool.http.Header;
|
||||||
|
import cn.hutool.http.HttpRequest;
|
||||||
|
import com.alibaba.fastjson.JSON;
|
||||||
|
import com.alibaba.fastjson.annotation.JSONField;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Builder;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 请求token时的参数
|
||||||
|
* @author 3y
|
||||||
|
* https://docs.getui.com/getui/server/rest_v2/token/
|
||||||
|
*/
|
||||||
|
@NoArgsConstructor
|
||||||
|
@Data
|
||||||
|
@Builder
|
||||||
|
@AllArgsConstructor
|
||||||
|
public class QueryTokenParamDTO {
|
||||||
|
/**
|
||||||
|
* sign
|
||||||
|
*/
|
||||||
|
@JSONField(name = "sign")
|
||||||
|
private String sign;
|
||||||
|
/**
|
||||||
|
* timestamp
|
||||||
|
*/
|
||||||
|
@JSONField(name = "timestamp")
|
||||||
|
private String timestamp;
|
||||||
|
/**
|
||||||
|
* appkey
|
||||||
|
*/
|
||||||
|
@JSONField(name = "appkey")
|
||||||
|
private String appKey;
|
||||||
|
}
|
@ -1,4 +1,4 @@
|
|||||||
package com.java3y.austin.handler.domain;
|
package com.java3y.austin.handler.deduplication;
|
||||||
|
|
||||||
import com.alibaba.fastjson.annotation.JSONField;
|
import com.alibaba.fastjson.annotation.JSONField;
|
||||||
import com.java3y.austin.common.domain.TaskInfo;
|
import com.java3y.austin.common.domain.TaskInfo;
|
@ -0,0 +1,36 @@
|
|||||||
|
package com.java3y.austin.handler.deduplication.limit;
|
||||||
|
|
||||||
|
import com.java3y.austin.common.domain.TaskInfo;
|
||||||
|
import com.java3y.austin.handler.deduplication.service.AbstractDeduplicationService;
|
||||||
|
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author cao
|
||||||
|
* @date 2022-04-20 12:00
|
||||||
|
*/
|
||||||
|
public abstract class AbstractLimitService implements LimitService {
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取得到当前消息模板所有的去重Key
|
||||||
|
*
|
||||||
|
* @param taskInfo
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
protected List<String> deduplicationAllKey(AbstractDeduplicationService service, TaskInfo taskInfo) {
|
||||||
|
List<String> result = new ArrayList<>(taskInfo.getReceiver().size());
|
||||||
|
for (String receiver : taskInfo.getReceiver()) {
|
||||||
|
String key = deduplicationSingleKey(service, taskInfo, receiver);
|
||||||
|
result.add(key);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
protected String deduplicationSingleKey(AbstractDeduplicationService service, TaskInfo taskInfo, String receiver) {
|
||||||
|
|
||||||
|
return service.deduplicationSingleKey(taskInfo, receiver);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,25 @@
|
|||||||
|
package com.java3y.austin.handler.deduplication.limit;
|
||||||
|
|
||||||
|
import com.java3y.austin.common.domain.TaskInfo;
|
||||||
|
import com.java3y.austin.handler.deduplication.DeduplicationParam;
|
||||||
|
import com.java3y.austin.handler.deduplication.service.AbstractDeduplicationService;
|
||||||
|
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author cao
|
||||||
|
* @date 2022-04-20 11:58
|
||||||
|
*/
|
||||||
|
public interface LimitService {
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 去重限制
|
||||||
|
* @param service 去重器对象
|
||||||
|
* @param taskInfo
|
||||||
|
* @param param 去重参数
|
||||||
|
* @return 返回不符合条件的手机号码
|
||||||
|
*/
|
||||||
|
Set<String> limitFilter(AbstractDeduplicationService service, TaskInfo taskInfo, DeduplicationParam param);
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,33 @@
|
|||||||
|
package com.java3y.austin.handler.domain.push;
|
||||||
|
|
||||||
|
|
||||||
|
import com.java3y.austin.common.domain.TaskInfo;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Builder;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
@NoArgsConstructor
|
||||||
|
@AllArgsConstructor
|
||||||
|
@Data
|
||||||
|
@Builder
|
||||||
|
public class PushParam {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 调用 接口时需要的token
|
||||||
|
*/
|
||||||
|
private String token;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 调用接口时需要的appId
|
||||||
|
*/
|
||||||
|
private String appId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 消息模板的信息
|
||||||
|
*/
|
||||||
|
private TaskInfo taskInfo;
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,54 @@
|
|||||||
|
package com.java3y.austin.handler.domain.push.getui;
|
||||||
|
|
||||||
|
import com.alibaba.fastjson.annotation.JSONField;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Builder;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 批量推送消息的param
|
||||||
|
*
|
||||||
|
* @author 3y
|
||||||
|
* https://docs.getui.com/getui/server/rest_v2/push/
|
||||||
|
*/
|
||||||
|
@NoArgsConstructor
|
||||||
|
@AllArgsConstructor
|
||||||
|
@Data
|
||||||
|
@Builder
|
||||||
|
public class BatchSendPushParam {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* audience
|
||||||
|
*/
|
||||||
|
@JSONField(name = "audience")
|
||||||
|
private AudienceVO audience;
|
||||||
|
/**
|
||||||
|
* taskid
|
||||||
|
*/
|
||||||
|
@JSONField(name = "taskid")
|
||||||
|
private String taskId;
|
||||||
|
/**
|
||||||
|
* isAsync
|
||||||
|
*/
|
||||||
|
@JSONField(name = "is_async")
|
||||||
|
private Boolean isAsync;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* AudienceVO
|
||||||
|
*/
|
||||||
|
@NoArgsConstructor
|
||||||
|
@Data
|
||||||
|
@Builder
|
||||||
|
@AllArgsConstructor
|
||||||
|
public static class AudienceVO {
|
||||||
|
/**
|
||||||
|
* cid
|
||||||
|
*/
|
||||||
|
@JSONField(name = "cid")
|
||||||
|
private Set<String> cid;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,115 @@
|
|||||||
|
package com.java3y.austin.handler.domain.push.getui;
|
||||||
|
|
||||||
|
import com.alibaba.fastjson.annotation.JSONField;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Builder;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 推送消息的param
|
||||||
|
* @author 3y
|
||||||
|
* https://docs.getui.com/getui/server/rest_v2/push/
|
||||||
|
*/
|
||||||
|
@NoArgsConstructor
|
||||||
|
@AllArgsConstructor
|
||||||
|
@Data
|
||||||
|
@Builder
|
||||||
|
public class SendPushParam {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* requestId
|
||||||
|
*/
|
||||||
|
@JSONField(name = "request_id")
|
||||||
|
private String requestId;
|
||||||
|
/**
|
||||||
|
* settings
|
||||||
|
*/
|
||||||
|
@JSONField(name = "settings")
|
||||||
|
private SettingsVO settings;
|
||||||
|
/**
|
||||||
|
* audience
|
||||||
|
*/
|
||||||
|
@JSONField(name = "audience")
|
||||||
|
private AudienceVO audience;
|
||||||
|
/**
|
||||||
|
* pushMessage
|
||||||
|
*/
|
||||||
|
@JSONField(name = "push_message")
|
||||||
|
private PushMessageVO pushMessage;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* SettingsVO
|
||||||
|
*/
|
||||||
|
@NoArgsConstructor
|
||||||
|
@Data
|
||||||
|
public static class SettingsVO {
|
||||||
|
/**
|
||||||
|
* ttl
|
||||||
|
*/
|
||||||
|
@JSONField(name = "ttl")
|
||||||
|
private Integer ttl;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* AudienceVO
|
||||||
|
*/
|
||||||
|
@NoArgsConstructor
|
||||||
|
@Data
|
||||||
|
@AllArgsConstructor
|
||||||
|
@Builder
|
||||||
|
public static class AudienceVO {
|
||||||
|
/**
|
||||||
|
* cid
|
||||||
|
*/
|
||||||
|
@JSONField(name = "cid")
|
||||||
|
private Set<String> cid;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* PushMessageVO
|
||||||
|
*/
|
||||||
|
@NoArgsConstructor
|
||||||
|
@Data
|
||||||
|
@AllArgsConstructor
|
||||||
|
@Builder
|
||||||
|
public static class PushMessageVO {
|
||||||
|
/**
|
||||||
|
* notification
|
||||||
|
*/
|
||||||
|
@JSONField(name = "notification")
|
||||||
|
private NotificationVO notification;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* NotificationVO
|
||||||
|
*/
|
||||||
|
@NoArgsConstructor
|
||||||
|
@Data
|
||||||
|
@AllArgsConstructor
|
||||||
|
@Builder
|
||||||
|
public static class NotificationVO {
|
||||||
|
/**
|
||||||
|
* title
|
||||||
|
*/
|
||||||
|
@JSONField(name = "title")
|
||||||
|
private String title;
|
||||||
|
/**
|
||||||
|
* body
|
||||||
|
*/
|
||||||
|
@JSONField(name = "body")
|
||||||
|
private String body;
|
||||||
|
/**
|
||||||
|
* clickType
|
||||||
|
*/
|
||||||
|
@JSONField(name = "click_type")
|
||||||
|
private String clickType;
|
||||||
|
/**
|
||||||
|
* url
|
||||||
|
*/
|
||||||
|
@JSONField(name = "url")
|
||||||
|
private String url;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,38 @@
|
|||||||
|
package com.java3y.austin.handler.domain.push.getui;
|
||||||
|
|
||||||
|
|
||||||
|
import com.alibaba.fastjson.JSONObject;
|
||||||
|
import com.alibaba.fastjson.annotation.JSONField;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Builder;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 发送消息后的返回值
|
||||||
|
* @author 3y
|
||||||
|
* https://docs.getui.com/getui/server/rest_v2/common_args/?id=doc-title-1
|
||||||
|
*/
|
||||||
|
@Builder
|
||||||
|
@Data
|
||||||
|
@AllArgsConstructor
|
||||||
|
@NoArgsConstructor
|
||||||
|
public class SendPushResult {
|
||||||
|
/**
|
||||||
|
* msg
|
||||||
|
*/
|
||||||
|
@JSONField(name = "msg")
|
||||||
|
private String msg;
|
||||||
|
/**
|
||||||
|
* code
|
||||||
|
*/
|
||||||
|
@JSONField(name = "code")
|
||||||
|
private Integer code;
|
||||||
|
/**
|
||||||
|
* data
|
||||||
|
*/
|
||||||
|
@JSONField(name = "data")
|
||||||
|
private JSONObject data;
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,37 @@
|
|||||||
|
package com.java3y.austin.handler.domain.wechat;
|
||||||
|
|
||||||
|
import lombok.Builder;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author sunql
|
||||||
|
* @date 2022年05月06日 9:56
|
||||||
|
*
|
||||||
|
* 服务号参数
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@Builder
|
||||||
|
public class WeChatOfficialParam {
|
||||||
|
/**
|
||||||
|
* 业务Id
|
||||||
|
*/
|
||||||
|
private Long messageTemplateId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 关注服务号得用户
|
||||||
|
*/
|
||||||
|
private Set<String> openIds;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 模板消息的信息载体
|
||||||
|
*/
|
||||||
|
private Map<String, String> data;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 发送账号
|
||||||
|
*/
|
||||||
|
private Integer sendAccount;
|
||||||
|
}
|
@ -0,0 +1,26 @@
|
|||||||
|
package com.java3y.austin.handler.enums;
|
||||||
|
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.ToString;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 限流枚举
|
||||||
|
*
|
||||||
|
* @author 3y
|
||||||
|
*/
|
||||||
|
@Getter
|
||||||
|
@ToString
|
||||||
|
@AllArgsConstructor
|
||||||
|
public enum RateLimitStrategy {
|
||||||
|
|
||||||
|
|
||||||
|
REQUEST_RATE_LIMIT(10, "根据真实请求数限流"),
|
||||||
|
SEND_USER_NUM_RATE_LIMIT(20, "根据发送用户数限流"),
|
||||||
|
;
|
||||||
|
|
||||||
|
private Integer code;
|
||||||
|
private String description;
|
||||||
|
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,39 @@
|
|||||||
|
package com.java3y.austin.handler.flowcontrol;
|
||||||
|
|
||||||
|
import com.google.common.util.concurrent.RateLimiter;
|
||||||
|
import com.java3y.austin.handler.enums.RateLimitStrategy;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Builder;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author 3y
|
||||||
|
* @date 2022/4/18
|
||||||
|
* <p>
|
||||||
|
* 流量控制所需要的参数
|
||||||
|
*/
|
||||||
|
@Builder
|
||||||
|
@Data
|
||||||
|
@AllArgsConstructor
|
||||||
|
@NoArgsConstructor
|
||||||
|
public class FlowControlParam {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 限流器
|
||||||
|
* 子类初始化的时候指定
|
||||||
|
*/
|
||||||
|
protected RateLimiter rateLimiter;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 限流器初始限流大小
|
||||||
|
* 子类初始化的时候指定
|
||||||
|
*/
|
||||||
|
protected Double rateInitValue;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 限流的策略
|
||||||
|
* 子类初始化的时候指定
|
||||||
|
*/
|
||||||
|
protected RateLimitStrategy rateLimitStrategy;
|
||||||
|
}
|
@ -0,0 +1,20 @@
|
|||||||
|
package com.java3y.austin.handler.flowcontrol;
|
||||||
|
|
||||||
|
import com.java3y.austin.common.domain.TaskInfo;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author 3y
|
||||||
|
* 流量控制服务
|
||||||
|
*/
|
||||||
|
public interface FlowControlService {
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据渠道进行流量控制
|
||||||
|
*
|
||||||
|
* @param taskInfo
|
||||||
|
* @param flowControlParam
|
||||||
|
*/
|
||||||
|
void flowControl(TaskInfo taskInfo, FlowControlParam flowControlParam);
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,67 @@
|
|||||||
|
package com.java3y.austin.handler.handler.impl;
|
||||||
|
|
||||||
|
import com.alibaba.fastjson.JSON;
|
||||||
|
import com.google.common.base.Throwables;
|
||||||
|
import com.java3y.austin.common.domain.TaskInfo;
|
||||||
|
import com.java3y.austin.common.dto.model.MiniProgramContentModel;
|
||||||
|
import com.java3y.austin.common.dto.model.OfficialAccountsContentModel;
|
||||||
|
import com.java3y.austin.common.enums.ChannelType;
|
||||||
|
import com.java3y.austin.handler.domain.wechat.WeChatMiniProgramParam;
|
||||||
|
import com.java3y.austin.handler.domain.wechat.WeChatOfficialParam;
|
||||||
|
import com.java3y.austin.handler.handler.BaseHandler;
|
||||||
|
import com.java3y.austin.handler.handler.Handler;
|
||||||
|
import com.java3y.austin.handler.script.MiniProgramAccountService;
|
||||||
|
import com.java3y.austin.handler.script.OfficialAccountService;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author sunql
|
||||||
|
* 微信小程序发送订阅消息
|
||||||
|
*/
|
||||||
|
@Component
|
||||||
|
@Slf4j
|
||||||
|
public class MiniProgramAccountHandler extends BaseHandler implements Handler {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private MiniProgramAccountService miniProgramAccountService;
|
||||||
|
|
||||||
|
public MiniProgramAccountHandler() {
|
||||||
|
channelCode = ChannelType.MINI_PROGRAM.getCode();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean handler(TaskInfo taskInfo) {
|
||||||
|
WeChatMiniProgramParam miniProgramParam = buildMiniProgramParam(taskInfo);
|
||||||
|
try {
|
||||||
|
miniProgramAccountService.send(miniProgramParam);
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("MiniProgramAccountHandler#handler fail:{},params:{}",
|
||||||
|
Throwables.getStackTraceAsString(e), JSON.toJSONString(taskInfo));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 通过taskInfo构建小程序订阅消息
|
||||||
|
*
|
||||||
|
* @param taskInfo
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
private WeChatMiniProgramParam buildMiniProgramParam(TaskInfo taskInfo) {
|
||||||
|
// 小程序订阅消息可以关联到系统业务,通过接口查询。
|
||||||
|
WeChatMiniProgramParam miniProgramParam = WeChatMiniProgramParam.builder()
|
||||||
|
.openIds(taskInfo.getReceiver())
|
||||||
|
.messageTemplateId(taskInfo.getMessageTemplateId())
|
||||||
|
.sendAccount(taskInfo.getSendAccount())
|
||||||
|
.build();
|
||||||
|
|
||||||
|
MiniProgramContentModel contentModel = (MiniProgramContentModel) taskInfo.getContentModel();
|
||||||
|
miniProgramParam.setData(contentModel.getMap());
|
||||||
|
return miniProgramParam;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,19 @@
|
|||||||
|
package com.java3y.austin.handler.script;
|
||||||
|
|
||||||
|
import com.java3y.austin.handler.domain.wechat.WeChatMiniProgramParam;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author sunql
|
||||||
|
*/
|
||||||
|
public interface MiniProgramAccountService {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 发送订阅消息
|
||||||
|
*
|
||||||
|
* @param miniProgramParam 订阅消息参数
|
||||||
|
* @return
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
|
void send(WeChatMiniProgramParam miniProgramParam) throws Exception;
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,93 @@
|
|||||||
|
package com.java3y.austin.handler.script.impl;
|
||||||
|
|
||||||
|
import cn.binarywang.wx.miniapp.api.WxMaService;
|
||||||
|
import cn.binarywang.wx.miniapp.api.WxMaSubscribeService;
|
||||||
|
import cn.binarywang.wx.miniapp.api.impl.WxMaServiceImpl;
|
||||||
|
import cn.binarywang.wx.miniapp.api.impl.WxMaSubscribeServiceImpl;
|
||||||
|
import cn.binarywang.wx.miniapp.bean.WxMaSubscribeMessage;
|
||||||
|
import cn.binarywang.wx.miniapp.config.impl.WxMaDefaultConfigImpl;
|
||||||
|
import com.java3y.austin.common.constant.SendAccountConstant;
|
||||||
|
import com.java3y.austin.common.dto.account.WeChatMiniProgramAccount;
|
||||||
|
import com.java3y.austin.handler.domain.wechat.WeChatMiniProgramParam;
|
||||||
|
import com.java3y.austin.handler.script.MiniProgramAccountService;
|
||||||
|
import com.java3y.austin.support.utils.AccountUtils;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author sunql
|
||||||
|
* @date 2022年05月06日 16:41
|
||||||
|
*/
|
||||||
|
@Service
|
||||||
|
@Slf4j
|
||||||
|
public class MiniProgramAccountServiceImpl implements MiniProgramAccountService {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private AccountUtils accountUtils;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void send(WeChatMiniProgramParam miniProgramParam) throws Exception {
|
||||||
|
WeChatMiniProgramAccount miniProgramAccount = accountUtils.getAccount(miniProgramParam.getSendAccount(),
|
||||||
|
SendAccountConstant.WECHAT_MINI_PROGRAM_ACCOUNT_KEY,
|
||||||
|
SendAccountConstant.WECHAT_MINI_PROGRAM_PREFIX,
|
||||||
|
WeChatMiniProgramAccount.class);
|
||||||
|
|
||||||
|
WxMaSubscribeService wxMaSubscribeService = initService(miniProgramAccount);
|
||||||
|
List<WxMaSubscribeMessage> subscribeMessageList = assembleReq(miniProgramParam, miniProgramAccount);
|
||||||
|
for (WxMaSubscribeMessage subscribeMessage : subscribeMessageList) {
|
||||||
|
wxMaSubscribeService.sendSubscribeMsg(subscribeMessage);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 组装发送模板信息参数
|
||||||
|
*/
|
||||||
|
private List<WxMaSubscribeMessage> assembleReq(WeChatMiniProgramParam miniProgramParam, WeChatMiniProgramAccount miniProgramAccount) {
|
||||||
|
Set<String> receiver = miniProgramParam.getOpenIds();
|
||||||
|
List<WxMaSubscribeMessage> messageList = new ArrayList<>(receiver.size());
|
||||||
|
|
||||||
|
// 构建微信小程序订阅消息
|
||||||
|
for (String openId : receiver) {
|
||||||
|
WxMaSubscribeMessage subscribeMessage = WxMaSubscribeMessage.builder()
|
||||||
|
.toUser(openId)
|
||||||
|
.data(getWxMTemplateData(miniProgramParam.getData()))
|
||||||
|
.miniprogramState(miniProgramAccount.getMiniProgramState())
|
||||||
|
.templateId(miniProgramAccount.getTemplateId())
|
||||||
|
.page(miniProgramAccount.getPage())
|
||||||
|
.build();
|
||||||
|
messageList.add(subscribeMessage);
|
||||||
|
}
|
||||||
|
return messageList;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 构建订阅消息参数
|
||||||
|
*
|
||||||
|
* @returnp
|
||||||
|
*/
|
||||||
|
private List<WxMaSubscribeMessage.MsgData> getWxMTemplateData(Map<String, String> data) {
|
||||||
|
List<WxMaSubscribeMessage.MsgData> templateDataList = new ArrayList<>(data.size());
|
||||||
|
data.forEach((k, v) -> templateDataList.add(new WxMaSubscribeMessage.MsgData(k, v)));
|
||||||
|
return templateDataList;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 初始化微信小程序
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
private WxMaSubscribeServiceImpl initService(WeChatMiniProgramAccount miniProgramAccount) {
|
||||||
|
WxMaService wxMaService = new WxMaServiceImpl();
|
||||||
|
WxMaDefaultConfigImpl wxMaConfig = new WxMaDefaultConfigImpl();
|
||||||
|
wxMaConfig.setAppid(miniProgramAccount.getAppId());
|
||||||
|
wxMaConfig.setSecret(miniProgramAccount.getAppSecret());
|
||||||
|
wxMaService.setWxMaConfig(wxMaConfig);
|
||||||
|
return new WxMaSubscribeServiceImpl(wxMaService);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,95 @@
|
|||||||
|
package com.java3y.austin.service.api.impl.service;
|
||||||
|
|
||||||
|
import com.java3y.austin.common.enums.RespStatusEnum;
|
||||||
|
import com.java3y.austin.common.vo.BasicResultVO;
|
||||||
|
import com.java3y.austin.service.api.domain.BatchSendRequest;
|
||||||
|
import com.java3y.austin.service.api.domain.MessageParam;
|
||||||
|
import com.java3y.austin.service.api.domain.SendRequest;
|
||||||
|
import com.java3y.austin.service.api.domain.SendResponse;
|
||||||
|
import com.java3y.austin.service.api.enums.BusinessCode;
|
||||||
|
import com.java3y.austin.service.api.impl.domain.SendTaskModel;
|
||||||
|
import com.java3y.austin.support.pipeline.BusinessProcess;
|
||||||
|
import com.java3y.austin.support.pipeline.ProcessContext;
|
||||||
|
import com.java3y.austin.support.pipeline.ProcessController;
|
||||||
|
import com.java3y.austin.support.pipeline.ProcessTemplate;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
import org.junit.jupiter.api.extension.ExtendWith;
|
||||||
|
import org.mockito.InjectMocks;
|
||||||
|
import org.mockito.Mock;
|
||||||
|
import org.mockito.Spy;
|
||||||
|
import org.mockito.junit.jupiter.MockitoExtension;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
|
import static org.mockito.Mockito.when;
|
||||||
|
|
||||||
|
@ExtendWith(MockitoExtension.class)
|
||||||
|
class SendServiceImplTest {
|
||||||
|
|
||||||
|
@Spy
|
||||||
|
private ProcessController processController;
|
||||||
|
|
||||||
|
@Mock
|
||||||
|
private Map<String, ProcessTemplate> templateConfig;
|
||||||
|
|
||||||
|
@Spy
|
||||||
|
private ProcessTemplate processTemplate;
|
||||||
|
|
||||||
|
@Mock
|
||||||
|
private BusinessProcess businessProcess;
|
||||||
|
|
||||||
|
@InjectMocks
|
||||||
|
private SendServiceImpl sendServiceImplUnderTest;
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testSend() {
|
||||||
|
|
||||||
|
// params
|
||||||
|
final SendRequest sendRequest = new SendRequest("send", 1L,
|
||||||
|
new MessageParam("13711111111", new HashMap<>(), new HashMap<>()));
|
||||||
|
|
||||||
|
// predict result
|
||||||
|
final ProcessContext<SendTaskModel> processContext = new ProcessContext<>(sendRequest.getCode(), new SendTaskModel(), false, new BasicResultVO<>(
|
||||||
|
RespStatusEnum.SUCCESS, "data"));
|
||||||
|
final SendResponse expectedResult = new SendResponse(processContext.getResponse().getStatus(), processContext.getResponse().getMsg());
|
||||||
|
|
||||||
|
|
||||||
|
// stub
|
||||||
|
Map<String, ProcessTemplate> templateConfig = new HashMap<>(4);
|
||||||
|
processTemplate.setProcessList(Arrays.asList(businessProcess));
|
||||||
|
templateConfig.put(BusinessCode.COMMON_SEND.getCode(), processTemplate);
|
||||||
|
|
||||||
|
processController.setTemplateConfig(templateConfig);
|
||||||
|
|
||||||
|
|
||||||
|
// Run the test
|
||||||
|
final SendResponse result = sendServiceImplUnderTest.send(sendRequest);
|
||||||
|
|
||||||
|
// Verify the results
|
||||||
|
assertEquals(expectedResult, result);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testBatchSend() {
|
||||||
|
// Setup
|
||||||
|
final BatchSendRequest batchSendRequest = new BatchSendRequest("code", 0L,
|
||||||
|
Arrays.asList(new MessageParam("receiver", new HashMap<>(), new HashMap<>())));
|
||||||
|
final SendResponse expectedResult = new SendResponse("status", "msg");
|
||||||
|
|
||||||
|
// Configure ProcessController.process(...).
|
||||||
|
final ProcessContext processContext = new ProcessContext<>("code", null, false, new BasicResultVO<>(
|
||||||
|
RespStatusEnum.SUCCESS, "data"));
|
||||||
|
when(processController.process(new ProcessContext<>("code", null, false, new BasicResultVO<>(
|
||||||
|
RespStatusEnum.SUCCESS, "data")))).thenReturn(processContext);
|
||||||
|
|
||||||
|
// Run the test
|
||||||
|
final SendResponse result = sendServiceImplUnderTest.batchSend(batchSendRequest);
|
||||||
|
|
||||||
|
// Verify the results
|
||||||
|
assertEquals(expectedResult, result);
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in new issue