Merge branch 'master' into vip

pull/9/head
3y 3 years ago
commit 9d1221d8e7

@ -73,4 +73,11 @@ public class SendAccountConstant {
public static final String SMS_PREFIX = "sms_";
/**
* code
*/
public static final Integer TENCENT_SMS_CODE = 10;
public static final Integer YUN_PIAN_SMS_CODE = 20;
}

@ -0,0 +1,45 @@
package com.java3y.austin.common.dto.account;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
*
*
*
* [{"sms_20":{"url":"https://sms.yunpian.com/v2/sms/tpl_batch_send.json","apikey":"ca55d4c8544444444444622221b5cd7","tpl_id":"533332222282","supplierId":20,"supplierName":"云片"}}]
*
* @author 3y
*/
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class YunPianSmsAccount {
/**
* apikey
*/
private String apikey;
/**
* tplId
*/
private String tplId;
/**
* api
*/
private String url;
/**
* Id
*/
private Integer supplierId;
/**
*
*/
private String supplierName;
}

@ -15,7 +15,8 @@ public enum SmsStatus {
SEND_SUCCESS(10,"调用渠道接口发送成功"),
RECEIVE_SUCCESS(20,"用户收到短信(收到渠道短信回执,状态成功)"),
RECEIVE_FAIL(30, "用户收不到短信(收到渠道短信回执,状态失败)");
RECEIVE_FAIL(30, "用户收不到短信(收到渠道短信回执,状态失败)"),
SEND_FAIL(40, "调用渠道接口发送失败");
private Integer code;
private String description;

@ -0,0 +1,30 @@
package com.java3y.austin.handler.domain.sms;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
*
*
* @author 3y
*/
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class MessageTypeSmsConfig {
/**
* ()
*/
private Integer weights;
/**
* script
*/
private String scriptName;
}

@ -28,10 +28,4 @@ public class SmsParam {
*
*/
private String content;
/**
*
*/
private Integer sendAccount;
}

@ -0,0 +1,81 @@
package com.java3y.austin.handler.domain.sms;
import com.alibaba.fastjson.annotation.JSONField;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.List;
@NoArgsConstructor
@Data
public class YunPianSendResult {
/**
* totalCount
*/
@JSONField(name = "total_count")
private Integer totalCount;
/**
* totalFee
*/
@JSONField(name = "total_fee")
private String totalFee;
/**
* unit
*/
@JSONField(name = "unit")
private String unit;
/**
* data
*/
@JSONField(name = "data")
private List<DataDTO> data;
/**
* DataDTO
*/
@NoArgsConstructor
@Data
public static class DataDTO {
/**
* httpStatusCode
*/
@JSONField(name = "http_status_code")
private Integer httpStatusCode;
/**
* code
*/
@JSONField(name = "code")
private Integer code;
/**
* msg
*/
@JSONField(name = "msg")
private String msg;
/**
* count
*/
@JSONField(name = "count")
private Integer count;
/**
* fee
*/
@JSONField(name = "fee")
private Integer fee;
/**
* unit
*/
@JSONField(name = "unit")
private String unit;
/**
* mobile
*/
@JSONField(name = "mobile")
private String mobile;
/**
* sid
*/
@JSONField(name = "sid")
private String sid;
}
}

@ -4,14 +4,11 @@ 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 com.java3y.austin.handler.wechat.MiniProgramAccountService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

@ -8,7 +8,7 @@ import com.java3y.austin.common.enums.ChannelType;
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.OfficialAccountService;
import com.java3y.austin.handler.wechat.OfficialAccountService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

@ -3,14 +3,19 @@ package com.java3y.austin.handler.handler.impl;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.ctrip.framework.apollo.Config;
import com.ctrip.framework.apollo.spring.annotation.ApolloConfig;
import com.google.common.base.Throwables;
import com.java3y.austin.common.constant.AustinConstant;
import com.java3y.austin.common.domain.TaskInfo;
import com.java3y.austin.common.dto.model.SmsContentModel;
import com.java3y.austin.common.enums.ChannelType;
import com.java3y.austin.handler.domain.sms.MessageTypeSmsConfig;
import com.java3y.austin.handler.domain.sms.SmsParam;
import com.java3y.austin.handler.handler.BaseHandler;
import com.java3y.austin.handler.handler.Handler;
import com.java3y.austin.handler.script.SmsScript;
import com.java3y.austin.handler.script.SmsScriptHolder;
import com.java3y.austin.support.dao.SmsRecordDao;
import com.java3y.austin.support.domain.SmsRecord;
import lombok.extern.slf4j.Slf4j;
@ -18,6 +23,7 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.List;
import java.util.Random;
/**
*
@ -36,7 +42,10 @@ public class SmsHandler extends BaseHandler implements Handler {
private SmsRecordDao smsRecordDao;
@Autowired
private SmsScript smsScript;
private SmsScriptHolder smsScriptHolder;
@ApolloConfig("boss.austin")
private Config config;
@Override
@ -45,14 +54,20 @@ public class SmsHandler extends BaseHandler implements Handler {
.phones(taskInfo.getReceiver())
.content(getSmsContent(taskInfo))
.messageTemplateId(taskInfo.getMessageTemplateId())
.sendAccount(taskInfo.getSendAccount())
.build();
try {
List<SmsRecord> recordList = smsScript.send(smsParam);
if (!CollUtil.isEmpty(recordList)) {
smsRecordDao.saveAll(recordList);
/**
* 1
* 2
*/
MessageTypeSmsConfig[] messageTypeSmsConfigs = loadBalance(getMessageTypeSmsConfig(taskInfo.getMsgType()));
for (MessageTypeSmsConfig messageTypeSmsConfig : messageTypeSmsConfigs) {
List<SmsRecord> recordList = smsScriptHolder.route(messageTypeSmsConfig.getScriptName()).send(smsParam);
if (CollUtil.isNotEmpty(recordList)) {
smsRecordDao.saveAll(recordList);
return true;
}
}
return true;
} catch (Exception e) {
log.error("SmsHandler#handler fail:{},params:{}",
Throwables.getStackTraceAsString(e), JSON.toJSONString(smsParam));
@ -60,6 +75,71 @@ public class SmsHandler extends BaseHandler implements Handler {
return false;
}
/**
*
*
*
* @param messageTypeSmsConfigs
*/
private MessageTypeSmsConfig[] loadBalance(List<MessageTypeSmsConfig> messageTypeSmsConfigs) {
int total = 0;
for (MessageTypeSmsConfig channelConfig : messageTypeSmsConfigs) {
total += channelConfig.getWeights();
}
// 生成一个随机数[1,total],看落到哪个区间
Random random = new Random();
int index = random.nextInt(total) + 1;
MessageTypeSmsConfig supplier = null;
MessageTypeSmsConfig supplierBack = null;
for (int i = 0; i < messageTypeSmsConfigs.size(); ++i) {
if (index <= messageTypeSmsConfigs.get(i).getWeights()) {
supplier = messageTypeSmsConfigs.get(i);
int j = (i + 1) % messageTypeSmsConfigs.size(); // 取下一个供应商
if (i == j) {
return new MessageTypeSmsConfig[]{supplier};
}
supplierBack = messageTypeSmsConfigs.get(j);
return new MessageTypeSmsConfig[]{supplier, supplierBack};
}
index -= messageTypeSmsConfigs.get(i).getWeights();
}
return null;
}
/**
* ()
* <p>
*
* keymsg_type_sms_config
* value[{"message_type_10":[{"weights":80,"scriptName":"TencentSmsScript"},{"weights":20,"scriptName":"YunPianSmsScript"}]},{"message_type_20":[{"weights":20,"scriptName":"YunPianSmsScript"}]},{"message_type_30":[{"weights":20,"scriptName":"TencentSmsScript"}]},{"message_type_40":[{"weights":20,"scriptName":"TencentSmsScript"}]}]
* TencentSmsScript 80%YunPianSmsScript20%
* YunPianSmsScript
* TencentSmsScript
*
* @param msgType
* @return
*/
private List<MessageTypeSmsConfig> getMessageTypeSmsConfig(Integer msgType) {
String apolloKey = "msg_type_sms_config";
String messagePrefix = "message_type_";
String property = config.getProperty(apolloKey, AustinConstant.APOLLO_DEFAULT_VALUE_JSON_ARRAY);
JSONArray jsonArray = JSON.parseArray(property);
for (int i = 0; i < jsonArray.size(); i++) {
JSONArray array = jsonArray.getJSONObject(i).getJSONArray(messagePrefix + msgType);
if (CollUtil.isNotEmpty(array)) {
List<MessageTypeSmsConfig> result = JSON.parseArray(JSON.toJSONString(array), MessageTypeSmsConfig.class);
return result;
}
}
return null;
}
/**
*
* <p>

@ -0,0 +1,55 @@
package com.java3y.austin.handler.receipt;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateUtil;
import com.alibaba.fastjson.JSON;
import com.google.common.base.Throwables;
import com.java3y.austin.common.constant.SendAccountConstant;
import com.java3y.austin.common.dto.account.TencentSmsAccount;
import com.java3y.austin.common.enums.SmsStatus;
import com.java3y.austin.support.config.SupportThreadPoolConfig;
import com.java3y.austin.support.domain.SmsRecord;
import com.tencentcloudapi.sms.v20210111.SmsClient;
import com.tencentcloudapi.sms.v20210111.models.PullSmsSendStatus;
import com.tencentcloudapi.sms.v20210111.models.PullSmsSendStatusRequest;
import com.tencentcloudapi.sms.v20210111.models.PullSmsSendStatusResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
/**
*
*
* @author 3y
*/
@Component
@Slf4j
public class SmsReceipt {
@Autowired
private TencentSmsReceipt tencentSmsReceipt;
@Autowired
private YunPianSmsReceipt yunPianSmsReceipt;
@PostConstruct
private void init() {
SupportThreadPoolConfig.getPendingSingleThreadPool().execute(() -> {
while (true) {
tencentSmsReceipt.pull();
yunPianSmsReceipt.pull();
try {
Thread.sleep(200);
} catch (InterruptedException e) {
}
}
});
}
}

@ -13,13 +13,11 @@ import com.java3y.austin.support.dao.SmsRecordDao;
import com.java3y.austin.support.domain.SmsRecord;
import com.java3y.austin.support.utils.AccountUtils;
import com.tencentcloudapi.common.Credential;
import com.tencentcloudapi.common.exception.TencentCloudSDKException;
import com.tencentcloudapi.common.profile.ClientProfile;
import com.tencentcloudapi.common.profile.HttpProfile;
import com.tencentcloudapi.sms.v20210111.SmsClient;
import com.tencentcloudapi.sms.v20210111.models.*;
import lombok.extern.slf4j.Slf4j;
import org.jetbrains.annotations.NotNull;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@ -30,7 +28,7 @@ import java.util.List;
/**
*
*
*
* @author 3y
*/
@ -45,60 +43,55 @@ public class TencentSmsReceipt {
@Autowired
private SmsRecordDao smsRecordDao;
@PostConstruct
private void init() {
/**
*
*/
public void pull() {
// 获取腾讯云账号信息
TencentSmsAccount account = accountUtils.getAccount(10, SendAccountConstant.SMS_ACCOUNT_KEY, SendAccountConstant.SMS_PREFIX, TencentSmsAccount.class);
SupportThreadPoolConfig.getPendingSingleThreadPool().execute(() -> {
while (true) {
try {
SmsClient client = getSmsClient(account);
// 每次拉取10条
PullSmsSendStatusRequest req = new PullSmsSendStatusRequest();
req.setLimit(10L);
req.setSmsSdkAppId(account.getSmsSdkAppId());
PullSmsSendStatusResponse resp = client.PullSmsSendStatus(req);
List<SmsRecord> smsRecordList = new ArrayList<>();
if (resp != null && resp.getPullSmsSendStatusSet() != null && resp.getPullSmsSendStatusSet().length > 0) {
log.debug("receipt sms:{}", JSON.toJSONString(resp.getPullSmsSendStatusSet()));
for (PullSmsSendStatus pullSmsSendStatus : resp.getPullSmsSendStatusSet()) {
SmsRecord smsRecord = SmsRecord.builder()
.sendDate(Integer.valueOf(DateUtil.format(new Date(), DatePattern.PURE_DATE_PATTERN)))
.messageTemplateId(0L)
.phone(Long.valueOf(pullSmsSendStatus.getSubscriberNumber()))
.supplierId(account.getSupplierId())
.supplierName(account.getSupplierName())
.msgContent("")
.seriesId(pullSmsSendStatus.getSerialNo())
.chargingNum(0)
.status("SUCCESS".equals(pullSmsSendStatus.getReportStatus()) ? SmsStatus.RECEIVE_SUCCESS.getCode() : SmsStatus.RECEIVE_FAIL.getCode())
.reportContent(pullSmsSendStatus.getDescription())
.updated(Math.toIntExact(pullSmsSendStatus.getUserReceiveTime()))
.created(Math.toIntExact(DateUtil.currentSeconds()))
.build();
smsRecordList.add(smsRecord);
}
}
if (!CollUtil.isEmpty(smsRecordList)) {
smsRecordDao.saveAll(smsRecordList);
}
Thread.sleep(200);
} catch (Exception e) {
log.error("TencentSmsReceipt#init fail!{}", Throwables.getStackTraceAsString(e));
try {
SmsClient client = getSmsClient(account);
// 每次拉取10条
PullSmsSendStatusRequest req = new PullSmsSendStatusRequest();
req.setLimit(10L);
req.setSmsSdkAppId(account.getSmsSdkAppId());
PullSmsSendStatusResponse resp = client.PullSmsSendStatus(req);
List<SmsRecord> smsRecordList = new ArrayList<>();
if (resp != null && resp.getPullSmsSendStatusSet() != null && resp.getPullSmsSendStatusSet().length > 0) {
log.debug("receipt sms:{}", JSON.toJSONString(resp.getPullSmsSendStatusSet()));
for (PullSmsSendStatus pullSmsSendStatus : resp.getPullSmsSendStatusSet()) {
SmsRecord smsRecord = SmsRecord.builder()
.sendDate(Integer.valueOf(DateUtil.format(new Date(), DatePattern.PURE_DATE_PATTERN)))
.messageTemplateId(0L)
.phone(Long.valueOf(pullSmsSendStatus.getSubscriberNumber()))
.supplierId(account.getSupplierId())
.supplierName(account.getSupplierName())
.msgContent("")
.seriesId(pullSmsSendStatus.getSerialNo())
.chargingNum(0)
.status("SUCCESS".equals(pullSmsSendStatus.getReportStatus()) ? SmsStatus.RECEIVE_SUCCESS.getCode() : SmsStatus.RECEIVE_FAIL.getCode())
.reportContent(pullSmsSendStatus.getDescription())
.updated(Math.toIntExact(pullSmsSendStatus.getUserReceiveTime()))
.created(Math.toIntExact(DateUtil.currentSeconds()))
.build();
smsRecordList.add(smsRecord);
}
}
});
if (!CollUtil.isEmpty(smsRecordList)) {
smsRecordDao.saveAll(smsRecordList);
}
} catch (Exception e) {
log.error("TencentSmsReceipt#init fail!{}", Throwables.getStackTraceAsString(e));
}
}
/**
* smsClient
*
* @param account
* @return
*/

@ -0,0 +1,25 @@
package com.java3y.austin.handler.receipt;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
/**
*
*
* @author 3y
*/
@Component
@Slf4j
public class YunPianSmsReceipt {
/**
*
*/
public void pull() {
}
}

@ -0,0 +1,42 @@
package com.java3y.austin.handler.script;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ArrayUtils;
import org.springframework.beans.factory.annotation.Autowired;
import javax.annotation.PostConstruct;
import java.lang.annotation.Annotation;
/**
* sms
*
* @author 3y
*/
@Slf4j
public abstract class BaseSmsScript implements SmsScript {
@Autowired
private SmsScriptHolder smsScriptHolder;
@PostConstruct
public void registerProcessScript() {
if (ArrayUtils.isEmpty(this.getClass().getAnnotations())) {
log.error("BaseSmsScript can not find annotation!");
return;
}
Annotation handlerAnnotations = null;
for (Annotation annotation : this.getClass().getAnnotations()) {
if (annotation instanceof SmsScriptHandler) {
handlerAnnotations = annotation;
break;
}
}
if (handlerAnnotations == null) {
log.error("handler annotations not declared");
return;
}
//注册handler
smsScriptHolder.putHandler(((SmsScriptHandler) handlerAnnotations).value(), this);
}
}

@ -17,8 +17,8 @@ public interface SmsScript {
*
* @param smsParam
* @return
* @throws Exception
*/
List<SmsRecord> send(SmsParam smsParam) throws Exception;
List<SmsRecord> send(SmsParam smsParam);
}

@ -0,0 +1,27 @@
package com.java3y.austin.handler.script;
import org.springframework.stereotype.Component;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
*
*
* @author 3y
*/
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE})
@Component
public @interface SmsScriptHandler {
/**
*
*
* @return
*/
String value();
}

@ -0,0 +1,25 @@
package com.java3y.austin.handler.script;
import org.springframework.stereotype.Component;
import java.util.HashMap;
import java.util.Map;
/**
* sendAccount->SmsScript
*
* @author 3y
*/
@Component
public class SmsScriptHolder {
private Map<String, SmsScript> handlers = new HashMap<>(8);
public void putHandler(String scriptName, SmsScript handler) {
handlers.put(scriptName, handler);
}
public SmsScript route(String scriptName) {
return handlers.get(scriptName);
}
}

@ -4,11 +4,15 @@ import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.IdUtil;
import com.alibaba.fastjson.JSON;
import com.google.common.base.Throwables;
import com.java3y.austin.common.constant.SendAccountConstant;
import com.java3y.austin.common.dto.account.TencentSmsAccount;
import com.java3y.austin.common.enums.SmsStatus;
import com.java3y.austin.handler.domain.sms.SmsParam;
import com.java3y.austin.common.dto.account.TencentSmsAccount;
import com.java3y.austin.handler.script.BaseSmsScript;
import com.java3y.austin.handler.script.SmsScript;
import com.java3y.austin.handler.script.SmsScriptHandler;
import com.java3y.austin.support.domain.SmsRecord;
import com.java3y.austin.support.utils.AccountUtils;
import com.tencentcloudapi.common.Credential;
@ -20,7 +24,6 @@ import com.tencentcloudapi.sms.v20210111.models.SendSmsResponse;
import com.tencentcloudapi.sms.v20210111.models.SendStatus;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.Date;
@ -33,9 +36,10 @@ import java.util.List;
* 2. 使SDK
* 3. 使API Explorer
*/
@Service
@Slf4j
public class TencentSmsScript implements SmsScript {
@SmsScriptHandler("TencentSmsScript")
public class TencentSmsScript extends BaseSmsScript implements SmsScript {
private static final Integer PHONE_NUM = 11;
@ -43,12 +47,17 @@ public class TencentSmsScript implements SmsScript {
private AccountUtils accountUtils;
@Override
public List<SmsRecord> send(SmsParam smsParam) throws Exception {
TencentSmsAccount tencentSmsAccount = accountUtils.getAccount(smsParam.getSendAccount(), SendAccountConstant.SMS_ACCOUNT_KEY, SendAccountConstant.SMS_PREFIX, TencentSmsAccount.class);
SmsClient client = init(tencentSmsAccount);
SendSmsRequest request = assembleReq(smsParam, tencentSmsAccount);
SendSmsResponse response = client.SendSms(request);
return assembleSmsRecord(smsParam, response, tencentSmsAccount);
public List<SmsRecord> send(SmsParam smsParam) {
try {
TencentSmsAccount tencentSmsAccount = accountUtils.getAccount(SendAccountConstant.TENCENT_SMS_CODE, SendAccountConstant.SMS_ACCOUNT_KEY, SendAccountConstant.SMS_PREFIX, TencentSmsAccount.class);
SmsClient client = init(tencentSmsAccount);
SendSmsRequest request = assembleReq(smsParam, tencentSmsAccount);
SendSmsResponse response = client.SendSms(request);
return assembleSmsRecord(smsParam, response, tencentSmsAccount);
} catch (Exception e) {
log.error("TencentSmsScript#send fail:{},params:{}", Throwables.getStackTraceAsString(e), JSON.toJSONString(smsParam));
return null;
}
}

@ -0,0 +1,108 @@
package com.java3y.austin.handler.script.impl;
import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.http.Header;
import cn.hutool.http.HttpRequest;
import com.alibaba.fastjson.JSON;
import com.google.common.base.Throwables;
import com.java3y.austin.common.constant.SendAccountConstant;
import com.java3y.austin.common.dto.account.YunPianSmsAccount;
import com.java3y.austin.common.enums.SmsStatus;
import com.java3y.austin.handler.domain.sms.SmsParam;
import com.java3y.austin.handler.domain.sms.YunPianSendResult;
import com.java3y.austin.handler.script.BaseSmsScript;
import com.java3y.austin.handler.script.SmsScript;
import com.java3y.austin.handler.script.SmsScriptHandler;
import com.java3y.austin.support.domain.SmsRecord;
import com.java3y.austin.support.utils.AccountUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import java.util.*;
/**
* @author 3y
* @date 2022523
* https://www.yunpian.com/official/document/sms/zh_CN/domestic_list
*/
@Slf4j
@SmsScriptHandler("YunPianSmsScript")
public class YunPianSmsScript extends BaseSmsScript implements SmsScript {
@Autowired
private AccountUtils accountUtils;
@Override
public List<SmsRecord> send(SmsParam smsParam) {
try {
YunPianSmsAccount account = accountUtils.getAccount(SendAccountConstant.YUN_PIAN_SMS_CODE, SendAccountConstant.SMS_ACCOUNT_KEY, SendAccountConstant.SMS_PREFIX, YunPianSmsAccount.class);
Map<String, Object> params = assembleParam(smsParam, account);
String result = HttpRequest.post(account.getUrl())
.header(Header.CONTENT_TYPE.getValue(), "application/x-www-form-urlencoded;charset=utf-8;")
.header(Header.ACCEPT.getValue(), "application/json;charset=utf-8;")
.form(params)
.timeout(2000)
.execute().body();
YunPianSendResult yunPianSendResult = JSON.parseObject(result, YunPianSendResult.class);
return assembleSmsRecord(smsParam, yunPianSendResult, account);
} catch (Exception e) {
log.error("YunPianSmsScript#send fail:{},params:{}", Throwables.getStackTraceAsString(e), JSON.toJSONString(smsParam));
return null;
}
}
/**
*
*
* @param smsParam
* @param account
* @return
*/
private Map<String, Object> assembleParam(SmsParam smsParam, YunPianSmsAccount account) {
Map<String, Object> params = new HashMap<>();
params.put("apikey", account.getApikey());
params.put("mobile", StringUtils.join(smsParam.getPhones(), StrUtil.C_COMMA));
params.put("tpl_id", account.getTplId());
params.put("tpl_value", "");
return params;
}
private List<SmsRecord> assembleSmsRecord(SmsParam smsParam, YunPianSendResult response, YunPianSmsAccount account) {
if (response == null || ArrayUtil.isEmpty(response.getData())) {
return null;
}
List<SmsRecord> smsRecordList = new ArrayList<>();
for (YunPianSendResult.DataDTO datum : response.getData()) {
SmsRecord smsRecord = SmsRecord.builder()
.sendDate(Integer.valueOf(DateUtil.format(new Date(), DatePattern.PURE_DATE_PATTERN)))
.messageTemplateId(smsParam.getMessageTemplateId())
.phone(Long.valueOf(datum.getMobile()))
.supplierId(account.getSupplierId())
.supplierName(account.getSupplierName())
.msgContent(smsParam.getContent())
.seriesId(datum.getSid())
.chargingNum(Math.toIntExact(datum.getCount()))
.status("0".equals(datum.getCode()) ? SmsStatus.SEND_SUCCESS.getCode() : SmsStatus.SEND_FAIL.getCode())
.reportContent(datum.getMsg())
.created(Math.toIntExact(DateUtil.currentSeconds()))
.updated(Math.toIntExact(DateUtil.currentSeconds()))
.build();
smsRecordList.add(smsRecord);
}
return smsRecordList;
}
}

@ -1,4 +1,4 @@
package com.java3y.austin.handler.script;
package com.java3y.austin.handler.wechat;
import com.java3y.austin.handler.domain.wechat.WeChatMiniProgramParam;

@ -1,4 +1,4 @@
package com.java3y.austin.handler.script;
package com.java3y.austin.handler.wechat;
import com.java3y.austin.handler.domain.wechat.WeChatOfficialParam;
import me.chanjar.weixin.mp.bean.template.WxMpTemplateMessage;

@ -1,4 +1,4 @@
package com.java3y.austin.handler.script.impl;
package com.java3y.austin.handler.wechat.impl;
import cn.binarywang.wx.miniapp.api.WxMaService;
import cn.binarywang.wx.miniapp.api.WxMaSubscribeService;
@ -9,7 +9,7 @@ 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.handler.wechat.MiniProgramAccountService;
import com.java3y.austin.support.utils.AccountUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;

@ -1,9 +1,9 @@
package com.java3y.austin.handler.script.impl;
package com.java3y.austin.handler.wechat.impl;
import com.java3y.austin.common.constant.SendAccountConstant;
import com.java3y.austin.common.dto.account.WeChatOfficialAccount;
import com.java3y.austin.handler.domain.wechat.WeChatOfficialParam;
import com.java3y.austin.handler.script.OfficialAccountService;
import com.java3y.austin.handler.wechat.OfficialAccountService;
import com.java3y.austin.support.utils.AccountUtils;
import lombok.extern.slf4j.Slf4j;
import me.chanjar.weixin.mp.api.WxMpService;

@ -15,6 +15,7 @@ import com.java3y.austin.support.pipeline.ProcessContext;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
@ -29,18 +30,23 @@ import java.util.stream.Collectors;
@Service
public class AfterParamCheckAction implements BusinessProcess<SendTaskModel> {
public static final String PHONE_REGEX_EXP = "^((13[0-9])|(14[5,7,9])|(15[0-3,5-9])|(166)|(17[0-9])|(18[0-9])|(19[1,8,9]))\\d{8}$";
public static final String EMAIL_REGEX_EXP = "[a-zA-Z0-9]+@[a-zA-Z0-9]+\\\\.[a-zA-Z0-9]+";
public static final HashMap<Integer, String> CHANNEL_REGEX_EXP = new HashMap<>();
static {
CHANNEL_REGEX_EXP.put(IdType.PHONE.getCode(), PHONE_REGEX_EXP);
CHANNEL_REGEX_EXP.put(IdType.EMAIL.getCode(), EMAIL_REGEX_EXP);
}
@Override
public void process(ProcessContext<SendTaskModel> context) {
SendTaskModel sendTaskModel = context.getProcessModel();
List<TaskInfo> taskInfo = sendTaskModel.getTaskInfo();
// 1. 过滤掉不合法的手机号
filterIllegalPhoneNum(taskInfo);
// 2.
// 1. 过滤掉不合法的手机号、邮件
filterIllegalReceiver(taskInfo);
if (CollUtil.isEmpty(taskInfo)) {
context.setNeedBreak(true).setResponse(BasicResultVO.fail(RespStatusEnum.CLIENT_BAD_PARAMETERS));
@ -48,31 +54,35 @@ public class AfterParamCheckAction implements BusinessProcess<SendTaskModel> {
}
/**
*
*
*
*
* @param taskInfo
*/
private void filterIllegalPhoneNum(List<TaskInfo> taskInfo) {
private void filterIllegalReceiver(List<TaskInfo> taskInfo) {
Integer idType = CollUtil.getFirst(taskInfo.iterator()).getIdType();
Integer sendChannel = CollUtil.getFirst(taskInfo.iterator()).getSendChannel();
if (IdType.PHONE.getCode().equals(idType) && ChannelType.SMS.getCode().equals(sendChannel)) {
Iterator<TaskInfo> iterator = taskInfo.iterator();
filter(taskInfo, CHANNEL_REGEX_EXP.get(idType));
}
// 利用正则找出不合法的手机号
while (iterator.hasNext()) {
TaskInfo task = iterator.next();
Set<String> illegalPhone = task.getReceiver().stream()
.filter(phone -> !ReUtil.isMatch(PHONE_REGEX_EXP, phone))
.collect(Collectors.toSet());
/**
*
*
* @param taskInfo
* @param regexExp
*/
private void filter(List<TaskInfo> taskInfo, String regexExp) {
Iterator<TaskInfo> iterator = taskInfo.iterator();
while (iterator.hasNext()) {
TaskInfo task = iterator.next();
Set<String> illegalPhone = task.getReceiver().stream()
.filter(phone -> !ReUtil.isMatch(regexExp, phone))
.collect(Collectors.toSet());
if (CollUtil.isNotEmpty(illegalPhone)) {
task.getReceiver().removeAll(illegalPhone);
log.error("messageTemplateId:{} find illegal phone!{}", task.getMessageTemplateId(), JSON.toJSONString(illegalPhone));
}
if (CollUtil.isEmpty(task.getReceiver())) {
iterator.remove();
}
if (CollUtil.isNotEmpty(illegalPhone)) {
task.getReceiver().removeAll(illegalPhone);
log.error("messageTemplateId:{} find illegal receiver!{}", task.getMessageTemplateId(), JSON.toJSONString(illegalPhone));
}
if (CollUtil.isEmpty(task.getReceiver())) {
iterator.remove();
}
}
}

@ -11,6 +11,7 @@ import com.java3y.austin.support.pipeline.ProcessContext;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
@ -23,6 +24,11 @@ import java.util.stream.Collectors;
@Service
public class PreParamCheckAction implements BusinessProcess<SendTaskModel> {
/**
*
*/
private static final Integer BATCH_RECEIVER_SIZE = 100;
@Override
public void process(ProcessContext<SendTaskModel> context) {
SendTaskModel sendTaskModel = context.getProcessModel();
@ -30,13 +36,13 @@ public class PreParamCheckAction implements BusinessProcess<SendTaskModel> {
Long messageTemplateId = sendTaskModel.getMessageTemplateId();
List<MessageParam> messageParamList = sendTaskModel.getMessageParamList();
// 没有传入 消息模板Id 或者 messageParam
// 1.没有传入 消息模板Id 或者 messageParam
if (messageTemplateId == null || CollUtil.isEmpty(messageParamList)) {
context.setNeedBreak(true).setResponse(BasicResultVO.fail(RespStatusEnum.CLIENT_BAD_PARAMETERS));
return;
}
// 过滤 receiver=null 的messageParam
// 2.过滤 receiver=null 的messageParam
List<MessageParam> resultMessageParamList = messageParamList.stream()
.filter(messageParam -> !StrUtil.isBlank(messageParam.getReceiver()))
.collect(Collectors.toList());
@ -44,7 +50,13 @@ public class PreParamCheckAction implements BusinessProcess<SendTaskModel> {
context.setNeedBreak(true).setResponse(BasicResultVO.fail(RespStatusEnum.CLIENT_BAD_PARAMETERS));
return;
}
sendTaskModel.setMessageParamList(resultMessageParamList);
// 3.过滤receiver大于100的请求
if (messageParamList.stream().anyMatch(messageParam -> messageParam.getReceiver().split(StrUtil.COMMA).length > BATCH_RECEIVER_SIZE)) {
context.setNeedBreak(true).setResponse(BasicResultVO.fail(RespStatusEnum.TOO_MANY_RECEIVER));
return;
}
}
}

@ -23,6 +23,7 @@ public class MessageParam {
/**
* @Description:
* ,
* 100
*
*/
private String receiver;

@ -21,7 +21,7 @@ public class AccountUtils {
private Config config;
/**
* (key:smsAccount)[{"sms_10":{"url":"sms.tencentcloudapi.com","region":"ap-guangzhou","secretId":"AKIDhDUUDfffffMEqBF1WljQq","secretKey":"B4h39yWnfffff7D2btue7JErDJ8gxyi","smsSdkAppId":"140025","templateId":"11897","signName":"Java3y公众号","supplierId":10,"supplierName":"腾讯云"}}]
* (key:smsAccount)[{"sms_10":{"url":"sms.tencentcloudapi.com","region":"ap-guangzhou","secretId":"AKIDhDUUDfrmQnvmMfhSw95lCMEqBF1WljQq","secretKey":"B4h39yWnnX0C6k7D2btue7JErDJ8gxyi","smsSdkAppId":"1400592125","templateId":"1182097","signName":"Java3y公众号","supplierId":10,"supplierName":"腾讯云"}},{"sms_20":{"url":"https://sms.yunpian.com/v2/sms/tpl_batch_send.json","apikey":"ca55d4c856d72e5d589361c4511b5cd7","tpl_id":"5236082","supplierId":20,"supplierName":"云片"}}]
* (key:emailAccount)[{"email_10":{"host":"smtp.qq.com","port":465,"user":"403686131@qq.com","pass":"","from":"403686131@qq.com"}}]
* (key:enterpriseWechatAccount)[{"enterprise_wechat_10":{"corpId":"wwf87603333e00069c","corpSecret":"-IFWxS2222QxzPIorNVUQn144444D915DM","agentId":10044442,"token":"rXROB3333Kf6i","aesKey":"MKZtoFxHIM44444M7ieag3r9ZPUsl"}}]
* (key:dingDingRobotAccount) [{"ding_ding_robot_10":{"secret":"SEC996d8d9d4768aded74114faae924f229229de444475a1c295d64fedf","webhook":"https://oapi.dingtalk.com/robot/send?access_token=8d03b644ffb6534b203d87333367328b0c3003d164715d2c6c6e56"}}]
@ -42,4 +42,7 @@ public class AccountUtils {
return null;
}
}

@ -197,14 +197,4 @@ public class DataServiceImpl implements DataService {
}
return businessId;
}
public static void main(String[] args) {
Long time = 1653140847 * 1000L;
String format = DateUtil.format(new Date(time), DatePattern.NORM_DATETIME_PATTERN);
System.out.println(format
);
}
}

Loading…
Cancel
Save