✨ 新增短信发送模块
This commit is contained in:
@@ -118,6 +118,13 @@
|
||||
<artifactId>ballcat-spring-boot-starter-kafka</artifactId>
|
||||
<version>${revision}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.hccake</groupId>
|
||||
<artifactId>ballcat-spring-boot-starter-sms</artifactId>
|
||||
<version>${revision}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- extends -->
|
||||
<dependency>
|
||||
<groupId>com.hccake</groupId>
|
||||
<artifactId>ballcat-extend-dingtalk</artifactId>
|
||||
|
||||
54
ballcat-starters/ballcat-spring-boot-starter-sms/pom.xml
Normal file
54
ballcat-starters/ballcat-spring-boot-starter-sms/pom.xml
Normal file
@@ -0,0 +1,54 @@
|
||||
<?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">
|
||||
<parent>
|
||||
<artifactId>ballcat-starters</artifactId>
|
||||
<groupId>com.hccake</groupId>
|
||||
<version>${revision}</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<artifactId>ballcat-spring-boot-starter-sms</artifactId>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>cn.hutool</groupId>
|
||||
<artifactId>hutool-all</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.hccake</groupId>
|
||||
<artifactId>ballcat-common-core</artifactId>
|
||||
</dependency>
|
||||
<!-- spring boot 配置所需依赖 -->
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-configuration-processor</artifactId>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-autoconfigure</artifactId>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.tencentcloudapi</groupId>
|
||||
<artifactId>tencentcloud-sdk-java</artifactId>
|
||||
<version>3.1.42</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.hccake</groupId>
|
||||
<artifactId>ballcat-extend-mybatis-plus</artifactId>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>mysql</groupId>
|
||||
<artifactId>mysql-connector-java</artifactId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-jdbc</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
@@ -0,0 +1,45 @@
|
||||
package com.hccake.starter.sms;
|
||||
|
||||
import com.hccake.starter.sms.impl.TencentSenderImpl;
|
||||
import com.hccake.starter.sms.impl.TianYiHongSenderImpl;
|
||||
import com.hccake.starter.sms.impl.XinKuKaSenderImpl;
|
||||
import com.hccake.starter.sms.impl.xinkuka.service.XinKuKaSmsSendService;
|
||||
import com.hccake.starter.sms.properties.SmsProperties;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
|
||||
/**
|
||||
* @author lingting 2020/4/26 9:45
|
||||
*/
|
||||
@EnableConfigurationProperties({ SmsProperties.class })
|
||||
public class SmsAutoConfiguration {
|
||||
|
||||
@Autowired
|
||||
private SmsProperties properties;
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean(com.hccake.starter.sms.SmsSender.class)
|
||||
@ConditionalOnProperty(name = "sms.type", havingValue = "TENCENT")
|
||||
public com.hccake.starter.sms.SmsSender<com.hccake.starter.sms.SmsSenderParams, com.hccake.starter.sms.SmsSenderResult> tencentSmsSender() {
|
||||
return new TencentSenderImpl(properties);
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean(com.hccake.starter.sms.SmsSender.class)
|
||||
@ConditionalOnProperty(name = "sms.type", havingValue = "TIAN_YI_HONG")
|
||||
public com.hccake.starter.sms.SmsSender<com.hccake.starter.sms.SmsSenderParams, com.hccake.starter.sms.SmsSenderResult> tianYiHongSmsSender() {
|
||||
return new TianYiHongSenderImpl(properties);
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean(com.hccake.starter.sms.SmsSender.class)
|
||||
@ConditionalOnProperty(name = "sms.type", havingValue = "XIN_KU_KA")
|
||||
public com.hccake.starter.sms.SmsSender<com.hccake.starter.sms.SmsSenderParams, com.hccake.starter.sms.SmsSenderResult> xinKuKaSmsSender(
|
||||
XinKuKaSmsSendService sendService) {
|
||||
return new XinKuKaSenderImpl(properties, sendService);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
package com.hccake.starter.sms;
|
||||
|
||||
/**
|
||||
* 短信发送 接口类
|
||||
*
|
||||
* @author lingting 2020/4/26 9:55
|
||||
*/
|
||||
public interface SmsSender<T, R> {
|
||||
|
||||
/**
|
||||
* 发送短信
|
||||
* @param p 参数配置
|
||||
* @return boolean
|
||||
* @author lingting 2020-04-26 11:44:46
|
||||
*/
|
||||
R send(T p);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,124 @@
|
||||
package com.hccake.starter.sms;
|
||||
|
||||
import cn.hutool.core.date.DateUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.hutool.core.util.URLUtil;
|
||||
import cn.hutool.crypto.SecureUtil;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.hccake.ballcat.common.core.util.SpringUtil;
|
||||
import com.hccake.starter.sms.constant.SmsConstants;
|
||||
import com.hccake.starter.sms.properties.SmsProperties;
|
||||
import com.hccake.starter.sms.properties.extra.Account;
|
||||
import com.hccake.starter.sms.properties.extra.Tencent;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import lombok.SneakyThrows;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
/**
|
||||
* @author lingting 2020/4/26 11:40
|
||||
*/
|
||||
@Getter
|
||||
@Setter
|
||||
@Accessors(chain = true)
|
||||
public class SmsSenderParams {
|
||||
|
||||
/**
|
||||
* 下发手机号码,采用 e.164 标准,格式为+[国家或地区码][手机号],单次请求最多支持200个手机号且要求全为境内手机号或全为境外手机号。
|
||||
* 例如:+8613711112222, 其中前面有一个+号 ,86为国家码,13711112222为手机号。
|
||||
*/
|
||||
private Set<String> phoneNumbers;
|
||||
|
||||
/**
|
||||
* 短信模板参数
|
||||
*/
|
||||
private List<Object> templateParam;
|
||||
|
||||
/**
|
||||
* 短信内容
|
||||
*/
|
||||
private String content;
|
||||
|
||||
/**
|
||||
* 使用此号码发送短信
|
||||
*/
|
||||
private String usePhone;
|
||||
|
||||
/**
|
||||
* 国家代码 比如 CN
|
||||
*/
|
||||
private String country;
|
||||
|
||||
{
|
||||
// 初始化参数
|
||||
this.phoneNumbers = new HashSet<>();
|
||||
this.templateParam = new ArrayList<>();
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加电话
|
||||
*/
|
||||
public SmsSenderParams addPhone(String phone) {
|
||||
this.phoneNumbers.add(phone);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加模板参数
|
||||
*
|
||||
* @author lingting 2020-04-26 11:07:36
|
||||
*/
|
||||
public SmsSenderParams addTemplateParam(Object param) {
|
||||
this.templateParam.add(param);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成参数-腾讯云平台
|
||||
*/
|
||||
@SneakyThrows
|
||||
public String generateTencentParams(Tencent tencent) {
|
||||
Map<String, Object> json = new HashMap<>(5);
|
||||
json.put("PhoneNumberSet", phoneNumbers);
|
||||
|
||||
json.put("SmsSdkAppid", tencent.getSdkId());
|
||||
|
||||
if (tencent.getTemplateId() != null) {
|
||||
json.put("TemplateID", tencent.getTemplateId());
|
||||
}
|
||||
|
||||
if (StrUtil.isNotEmpty(tencent.getSign())) {
|
||||
json.put("Sign", tencent.getSign());
|
||||
}
|
||||
if (templateParam.size() != 0) {
|
||||
json.put("TemplateParamSet", templateParam);
|
||||
}
|
||||
return SmsSenderResult.getObjectMapper().writeValueAsString(json);
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成参数-码平台
|
||||
*/
|
||||
public String generateTianYiHongParams(SmsProperties properties) {
|
||||
Account account = properties.getAccounts().get(country);
|
||||
String dateTime = DateUtil.format(LocalDateTime.now(), "yyyyMMddHHmmss");
|
||||
return URLUtil.encode("account=" + account.getAccount() + "&sign="
|
||||
+ SecureUtil.md5(account.getAccount() + account.getPassword() + dateTime) + "&datetime=" + dateTime
|
||||
+ "&numbers=" + phoneNumbers.iterator().next() + "&content=" + content
|
||||
+ (country.equals(SmsConstants.SENDER_ID_COUNTRY) ? "&senderid=THRONE" : ""));
|
||||
}
|
||||
|
||||
@Override
|
||||
@SneakyThrows
|
||||
public String toString() {
|
||||
return SmsSenderResult.getObjectMapper().writeValueAsString(this);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,148 @@
|
||||
package com.hccake.starter.sms;
|
||||
|
||||
import cn.hutool.core.convert.Convert;
|
||||
import com.fasterxml.jackson.core.type.TypeReference;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.hccake.ballcat.common.core.util.SpringUtil;
|
||||
import com.hccake.starter.sms.enums.TypeEnum;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import lombok.Getter;
|
||||
import lombok.SneakyThrows;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
/**
|
||||
* 短信发送结果
|
||||
*
|
||||
* @author lingting 2020/4/26 13:22
|
||||
*/
|
||||
@Getter
|
||||
@Accessors(chain = true)
|
||||
public class SmsSenderResult {
|
||||
|
||||
public static ObjectMapper getObjectMapper() {
|
||||
return SpringUtil.getBean(ObjectMapper.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* 状态字段名
|
||||
*/
|
||||
private static final String TIAN_YI_HONG_STATUS = "status";
|
||||
|
||||
/**
|
||||
* 信息字段名
|
||||
*/
|
||||
private static final String TIAN_YI_HONG_MSG = "desc";
|
||||
|
||||
/**
|
||||
* 短信平台
|
||||
*
|
||||
* @see com.hccake.starter.sms.constant.SmsConstants
|
||||
*/
|
||||
protected String platform;
|
||||
|
||||
/**
|
||||
* 发送的目标
|
||||
*/
|
||||
protected String target;
|
||||
|
||||
/**
|
||||
* 是否发送成功
|
||||
*/
|
||||
protected boolean success;
|
||||
|
||||
/**
|
||||
* 提示信息
|
||||
*/
|
||||
protected String msg;
|
||||
|
||||
/**
|
||||
* 请求的详细信息-各平台自定义
|
||||
*/
|
||||
protected String req;
|
||||
|
||||
/**
|
||||
* 返回结果信息
|
||||
*/
|
||||
protected String res;
|
||||
|
||||
private SmsSenderResult() {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 出现异常返回结果
|
||||
* @param platform 平台
|
||||
* @param phoneNumbers 目标手机号
|
||||
* @param id 异常id
|
||||
* @param e 异常信息
|
||||
* @return com.hccake.starter.sms.domain.SendResult
|
||||
* @author lingting 2020-04-26 13:43:39
|
||||
*/
|
||||
@SneakyThrows
|
||||
public static SmsSenderResult generateException(TypeEnum platform, Set<String> phoneNumbers, String id,
|
||||
Throwable e) {
|
||||
SmsSenderResult result = new SmsSenderResult();
|
||||
result.success = false;
|
||||
result.msg = "短信发送失败,出现异常:" + e.getMessage() + "," + id;
|
||||
result.target = getObjectMapper().writeValueAsString(phoneNumbers);
|
||||
result.platform = platform.name();
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成结果数据
|
||||
* @param resp 请求的返回结果
|
||||
* @param phoneNumbers 目标号码
|
||||
*/
|
||||
@SneakyThrows
|
||||
public static SmsSenderResult generate(String resp, String req, Set<String> phoneNumbers) {
|
||||
SmsSenderResult result = new SmsSenderResult();
|
||||
result.res = resp;
|
||||
// 没有异常就是成功!
|
||||
result.success = true;
|
||||
result.platform = TypeEnum.TENCENT.name();
|
||||
result.target = getObjectMapper().writeValueAsString(phoneNumbers);
|
||||
result.req = req;
|
||||
return result;
|
||||
}
|
||||
|
||||
@SneakyThrows
|
||||
public static SmsSenderResult generateTianYiHong(String resp, String req, Set<String> phoneNumbers) {
|
||||
SmsSenderResult result = new SmsSenderResult();
|
||||
result.res = resp;
|
||||
// 没有异常就是成功!
|
||||
result.success = true;
|
||||
result.platform = TypeEnum.TIAN_YI_HONG.name();
|
||||
result.target = getObjectMapper().writeValueAsString(phoneNumbers);
|
||||
result.req = req;
|
||||
|
||||
Map<String, Object> map = getObjectMapper().readValue(resp, new TypeReference<Map<String, Object>>() {
|
||||
});
|
||||
if (Convert.toInt(map.get(TIAN_YI_HONG_STATUS), -1) < 0) {
|
||||
result.success = false;
|
||||
result.msg = Convert.toStr(map.get(TIAN_YI_HONG_MSG), "获取错误信息失败!");
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@SneakyThrows
|
||||
public static SmsSenderResult generateXinKuKa(String resp, String req, Set<String> phoneNumbers) {
|
||||
SmsSenderResult result = new SmsSenderResult();
|
||||
result.res = resp;
|
||||
// 没有异常就是成功!
|
||||
result.success = true;
|
||||
result.platform = TypeEnum.XIN_KU_KA.name();
|
||||
result.target = getObjectMapper().writeValueAsString(phoneNumbers);
|
||||
result.res = resp;
|
||||
result.req = req;
|
||||
return result;
|
||||
}
|
||||
|
||||
@SneakyThrows
|
||||
@Override
|
||||
public String toString() {
|
||||
return getObjectMapper().writeValueAsString(this);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
package com.hccake.starter.sms.constant;
|
||||
|
||||
/**
|
||||
* @author lingting 2020/4/26 11:28
|
||||
*/
|
||||
public class SmsConstants {
|
||||
|
||||
/**
|
||||
* 需要注明 sender id 的国家
|
||||
*/
|
||||
public static final String SENDER_ID_COUNTRY = "IN";
|
||||
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
package com.hccake.starter.sms.constant;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
|
||||
/**
|
||||
* @author lingting 2020/5/6 21:41
|
||||
*/
|
||||
public class SmsSendConstants {
|
||||
|
||||
@Getter
|
||||
@AllArgsConstructor
|
||||
public enum state {
|
||||
|
||||
/**
|
||||
* 状态值 说明
|
||||
*/
|
||||
notSend(0, "未发送"),
|
||||
|
||||
sending(1, "已在发送队列"),
|
||||
|
||||
success(2, "发送成功"),
|
||||
|
||||
failed(3, "发送失败"),
|
||||
|
||||
;
|
||||
|
||||
private final int val;
|
||||
|
||||
private final String text;
|
||||
|
||||
}
|
||||
|
||||
@Getter
|
||||
@AllArgsConstructor
|
||||
public enum type {
|
||||
|
||||
/**
|
||||
* 状态值 说明
|
||||
*/
|
||||
sms(0, "短信"),
|
||||
|
||||
mms(1, "彩信"),
|
||||
|
||||
;
|
||||
|
||||
private final int val;
|
||||
|
||||
private final String text;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
package com.hccake.starter.sms.enums;
|
||||
|
||||
/**
|
||||
* @author lingting 2020-08-30 22:20
|
||||
*/
|
||||
|
||||
public enum TypeEnum {
|
||||
|
||||
/**
|
||||
* 短信发送类型
|
||||
*/
|
||||
TENCENT,
|
||||
|
||||
TIAN_YI_HONG,
|
||||
|
||||
XIN_KU_KA,
|
||||
|
||||
;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
package com.hccake.starter.sms.exception;
|
||||
|
||||
/**
|
||||
* @author lingting 2020/4/26 10:16
|
||||
*/
|
||||
public class SmsException extends RuntimeException {
|
||||
|
||||
public SmsException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
public SmsException(String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
package com.hccake.starter.sms.impl;
|
||||
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.hccake.starter.sms.SmsSenderResult;
|
||||
import com.hccake.starter.sms.enums.TypeEnum;
|
||||
import java.util.Set;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
/**
|
||||
* @author lingting 2020/4/26 13:45
|
||||
*/
|
||||
@Slf4j
|
||||
public class BaseServiceImpl {
|
||||
|
||||
/**
|
||||
* b 异常返回处理
|
||||
*/
|
||||
public SmsSenderResult errRet(TypeEnum platform, Set<String> phoneNumbers, String msg, Exception e) {
|
||||
String id = StrUtil.uuid();
|
||||
log.error(msg + "\nerror_id: " + id, e);
|
||||
return SmsSenderResult.generateException(platform, phoneNumbers, id, e);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
package com.hccake.starter.sms.impl;
|
||||
|
||||
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.v20190711.SmsClient;
|
||||
import com.tencentcloudapi.sms.v20190711.models.SendSmsRequest;
|
||||
import com.tencentcloudapi.sms.v20190711.models.SendSmsResponse;
|
||||
import com.hccake.starter.sms.SmsSender;
|
||||
import com.hccake.starter.sms.SmsSenderParams;
|
||||
import com.hccake.starter.sms.SmsSenderResult;
|
||||
import com.hccake.starter.sms.enums.TypeEnum;
|
||||
import com.hccake.starter.sms.properties.SmsProperties;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||
|
||||
/**
|
||||
* @author lingting 2020/4/26 10:03
|
||||
*/
|
||||
@ConditionalOnProperty(name = "sms.type", havingValue = "TENCENT")
|
||||
public class TencentSenderImpl extends BaseServiceImpl implements SmsSender<SmsSenderParams, SmsSenderResult> {
|
||||
|
||||
private final SmsProperties properties;
|
||||
|
||||
private final Credential cred;
|
||||
|
||||
public TencentSenderImpl(SmsProperties properties) {
|
||||
this.properties = properties;
|
||||
cred = new Credential(properties.getId(), properties.getKey());
|
||||
}
|
||||
|
||||
@Override
|
||||
public SmsSenderResult send(SmsSenderParams smsSenderParams) {
|
||||
try {
|
||||
HttpProfile httpProfile = new HttpProfile();
|
||||
httpProfile.setEndpoint(properties.getTencent().getEndpoint());
|
||||
|
||||
ClientProfile clientProfile = new ClientProfile();
|
||||
clientProfile.setHttpProfile(httpProfile);
|
||||
|
||||
SmsClient client = new SmsClient(cred, properties.getTencent().getRegion(), clientProfile);
|
||||
|
||||
SendSmsRequest req = SendSmsRequest.fromJsonString(
|
||||
smsSenderParams.generateTencentParams(properties.getTencent()), SendSmsRequest.class);
|
||||
SendSmsResponse resp = client.SendSms(req);
|
||||
return SmsSenderResult.generate(SendSmsRequest.toJsonString(resp), smsSenderParams.toString(),
|
||||
smsSenderParams.getPhoneNumbers());
|
||||
}
|
||||
catch (TencentCloudSDKException e) {
|
||||
return errRet(TypeEnum.TENCENT, smsSenderParams.getPhoneNumbers(), "腾讯云平台发送短信出现异常!", e);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
package com.hccake.starter.sms.impl;
|
||||
|
||||
import cn.hutool.http.HttpUtil;
|
||||
import com.hccake.starter.sms.SmsSender;
|
||||
import com.hccake.starter.sms.SmsSenderParams;
|
||||
import com.hccake.starter.sms.SmsSenderResult;
|
||||
import com.hccake.starter.sms.enums.TypeEnum;
|
||||
import com.hccake.starter.sms.properties.SmsProperties;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||
|
||||
/**
|
||||
* @author lingting 2020/4/26 10:03
|
||||
*/
|
||||
@ConditionalOnProperty(name = "sms.type", havingValue = "TIAN_YI_HONG")
|
||||
@RequiredArgsConstructor
|
||||
public class TianYiHongSenderImpl extends BaseServiceImpl implements SmsSender<SmsSenderParams, SmsSenderResult> {
|
||||
|
||||
private final SmsProperties properties;
|
||||
|
||||
@Override
|
||||
public SmsSenderResult send(SmsSenderParams smsSenderParams) {
|
||||
try {
|
||||
String req = properties.getUrl() + "?" + smsSenderParams.generateTianYiHongParams(properties);
|
||||
String res = HttpUtil.get(req);
|
||||
return SmsSenderResult.generateTianYiHong(res, "方法参数:" + smsSenderParams.toString() + " ;请求: " + req,
|
||||
smsSenderParams.getPhoneNumbers());
|
||||
}
|
||||
catch (Exception e) {
|
||||
return errRet(TypeEnum.TIAN_YI_HONG, smsSenderParams.getPhoneNumbers(), "码平台发送短信出现异常!", e);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
package com.hccake.starter.sms.impl;
|
||||
|
||||
import cn.hutool.core.date.DateUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.hccake.starter.sms.SmsSender;
|
||||
import com.hccake.starter.sms.SmsSenderParams;
|
||||
import com.hccake.starter.sms.SmsSenderResult;
|
||||
import com.hccake.starter.sms.constant.SmsSendConstants;
|
||||
import com.hccake.starter.sms.enums.TypeEnum;
|
||||
import com.hccake.starter.sms.exception.SmsException;
|
||||
import com.hccake.starter.sms.impl.xinkuka.model.XinKuKaSend;
|
||||
import com.hccake.starter.sms.impl.xinkuka.service.XinKuKaSmsSendService;
|
||||
import com.hccake.starter.sms.properties.SmsProperties;
|
||||
import com.hccake.starter.sms.properties.extra.XinKuKa;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||
|
||||
/**
|
||||
* @author lingting 2020/5/7 15:25
|
||||
*/
|
||||
@ConditionalOnProperty(name = "sms.type", havingValue = "XIN_KU_KA")
|
||||
@RequiredArgsConstructor
|
||||
public class XinKuKaSenderImpl extends BaseServiceImpl implements SmsSender<SmsSenderParams, SmsSenderResult> {
|
||||
|
||||
private final SmsProperties properties;
|
||||
|
||||
private final XinKuKaSmsSendService sendService;
|
||||
|
||||
private XinKuKa xinKuKa = null;
|
||||
|
||||
@Override
|
||||
public SmsSenderResult send(SmsSenderParams smsSenderParams) {
|
||||
if (xinKuKa == null) {
|
||||
xinKuKa = properties.getXinKuKa();
|
||||
}
|
||||
|
||||
List<XinKuKaSend> list = new ArrayList<>();
|
||||
XinKuKaSend send;
|
||||
// 配置发送数据
|
||||
for (String p : smsSenderParams.getPhoneNumbers()) {
|
||||
send = new XinKuKaSend();
|
||||
// 指定发送短信
|
||||
send.setSmsType(SmsSendConstants.type.sms.getVal());
|
||||
|
||||
// 指定号码发送
|
||||
if (xinKuKa.getMode() == XinKuKa.Mode.number) {
|
||||
send.setPhoNum(StrUtil.isEmpty(smsSenderParams.getUsePhone()) ? xinKuKa.getNumber()
|
||||
: smsSenderParams.getUsePhone());
|
||||
}
|
||||
send.setSmsNumber(p);
|
||||
// 不指定端口发送
|
||||
send.setPortNum(-1);
|
||||
send.setSmsContent(smsSenderParams.getContent());
|
||||
send.setSmsState(SmsSendConstants.state.notSend.getVal());
|
||||
list.add(send);
|
||||
}
|
||||
|
||||
if (sendService.saveBatch(list)) {
|
||||
return SmsSenderResult.generateXinKuKa("数据已全部入库-当前时间:" + DateUtil.now(), smsSenderParams.toString(),
|
||||
smsSenderParams.getPhoneNumbers());
|
||||
}
|
||||
return errRet(TypeEnum.XIN_KU_KA, smsSenderParams.getPhoneNumbers(), "发送失败!", new SmsException("短信发送失败!"));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
package com.hccake.starter.sms.impl.xinkuka.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.hccake.starter.sms.impl.xinkuka.model.XinKuKaSend;
|
||||
|
||||
/**
|
||||
* @author lingting 2020/5/6 21:46
|
||||
*/
|
||||
public interface SmsSendMapper extends BaseMapper<XinKuKaSend> {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
package com.hccake.starter.sms.impl.xinkuka.model;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import com.baomidou.mybatisplus.extension.activerecord.Model;
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
/**
|
||||
* @author lingting 2020/5/6 17:51
|
||||
*/
|
||||
@Data
|
||||
@Accessors(chain = true)
|
||||
@TableName("sms_send")
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@ApiModel(value = "短信发送表")
|
||||
public class XinKuKaSend extends Model<XinKuKaSend> {
|
||||
|
||||
@TableId
|
||||
private Long id;
|
||||
|
||||
@ApiModelProperty("大于0表示指定端口号发送")
|
||||
@TableField("PortNum")
|
||||
private Integer portNum;
|
||||
|
||||
@ApiModelProperty("接收号码")
|
||||
@TableField("smsNumber")
|
||||
private String smsNumber;
|
||||
|
||||
@ApiModelProperty("彩信标题,如果发送彩信不能为空")
|
||||
@TableField("smsSubject")
|
||||
private String smsSubject;
|
||||
|
||||
@ApiModelProperty("发送内容")
|
||||
@TableField("smsContent")
|
||||
private String smsContent;
|
||||
|
||||
@ApiModelProperty("0:短信 1:彩信")
|
||||
@TableField("smsType")
|
||||
private Integer smsType;
|
||||
|
||||
@ApiModelProperty("手机号")
|
||||
@TableField("PhoNum")
|
||||
private String phoNum;
|
||||
|
||||
@ApiModelProperty("状态")
|
||||
@TableField("smsState")
|
||||
private Integer smsState;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
package com.hccake.starter.sms.impl.xinkuka.service;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
import com.hccake.starter.sms.impl.xinkuka.model.XinKuKaSend;
|
||||
|
||||
/**
|
||||
* @author lingting 2020/5/7 16:51
|
||||
*/
|
||||
public interface XinKuKaSmsSendService extends IService<XinKuKaSend> {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
package com.hccake.starter.sms.impl.xinkuka.service.impl;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import com.hccake.starter.sms.impl.xinkuka.mapper.SmsSendMapper;
|
||||
import com.hccake.starter.sms.impl.xinkuka.model.XinKuKaSend;
|
||||
import com.hccake.starter.sms.impl.xinkuka.service.XinKuKaSmsSendService;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
/**
|
||||
* @author lingting 2020/5/7 16:52
|
||||
*/
|
||||
@Service
|
||||
@ConditionalOnProperty(name = "sms.type", havingValue = "XIN_KU_KA")
|
||||
public class XinKuKaSmsSendServiceImpl extends ServiceImpl<SmsSendMapper, XinKuKaSend>
|
||||
implements XinKuKaSmsSendService {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
package com.hccake.starter.sms.properties;
|
||||
|
||||
import com.hccake.starter.sms.enums.TypeEnum;
|
||||
import com.hccake.starter.sms.properties.extra.Account;
|
||||
import com.hccake.starter.sms.properties.extra.Tencent;
|
||||
import com.hccake.starter.sms.properties.extra.TianYiHong;
|
||||
import com.hccake.starter.sms.properties.extra.XinKuKa;
|
||||
import java.util.Map;
|
||||
import lombok.Data;
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.boot.context.properties.NestedConfigurationProperty;
|
||||
|
||||
/**
|
||||
* @author lingting 2020/4/26 9:43
|
||||
*/
|
||||
@Data
|
||||
@ConfigurationProperties(prefix = "ballcat.starter.sms")
|
||||
public class SmsProperties {
|
||||
|
||||
/**
|
||||
* 类型
|
||||
*/
|
||||
private TypeEnum type = TypeEnum.XIN_KU_KA;
|
||||
|
||||
/**
|
||||
* 请求路径
|
||||
*/
|
||||
private String url;
|
||||
|
||||
/**
|
||||
* app id
|
||||
*/
|
||||
private String id;
|
||||
|
||||
/**
|
||||
* app key
|
||||
*/
|
||||
private String key;
|
||||
|
||||
/**
|
||||
* 部分平台需要使用账号密码,都在这里配置
|
||||
*/
|
||||
private Map<String, Account> accounts;
|
||||
|
||||
/**
|
||||
* 腾讯云所需额外参数
|
||||
*/
|
||||
@NestedConfigurationProperty
|
||||
private Tencent tencent;
|
||||
|
||||
/**
|
||||
* 码平台所用发送短信所需额外参数
|
||||
*/
|
||||
@NestedConfigurationProperty
|
||||
private TianYiHong tianYiHong;
|
||||
|
||||
/**
|
||||
* 新酷卡猫池配置
|
||||
*/
|
||||
@NestedConfigurationProperty
|
||||
private XinKuKa xinKuKa;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
package com.hccake.starter.sms.properties.extra;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* 用于需要 账号密码的 平台
|
||||
*
|
||||
* @author lingting 2020/4/26 19:51
|
||||
*/
|
||||
@Data
|
||||
public class Account {
|
||||
|
||||
/**
|
||||
* 账号
|
||||
*/
|
||||
private String account;
|
||||
|
||||
/**
|
||||
* 密码
|
||||
*/
|
||||
private String password;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
package com.hccake.starter.sms.properties.extra;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* @author lingting 2020/5/6 17:16
|
||||
*/
|
||||
@Data
|
||||
public class Tencent {
|
||||
|
||||
/**
|
||||
* 调用api参数所需的 sdk ip
|
||||
*/
|
||||
private int sdkId;
|
||||
|
||||
/**
|
||||
* 配置节点
|
||||
*/
|
||||
private String endpoint = "sms.tencentcloudapi.com";
|
||||
|
||||
/**
|
||||
* 分区
|
||||
*/
|
||||
private String region = "";
|
||||
|
||||
/**
|
||||
* 短信模板id
|
||||
*/
|
||||
private Integer templateId = null;
|
||||
|
||||
/**
|
||||
* 短信签名,发往国内必填
|
||||
*/
|
||||
private String sign = null;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
package com.hccake.starter.sms.properties.extra;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* 天一泓 配置
|
||||
*
|
||||
* @author lingting 2020/5/6 17:16
|
||||
*/
|
||||
@Data
|
||||
public class TianYiHong {
|
||||
|
||||
/**
|
||||
* 密码的密钥
|
||||
*/
|
||||
private String passwordKey;
|
||||
|
||||
/**
|
||||
* 安全密钥
|
||||
*/
|
||||
private String secretKey;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,80 @@
|
||||
package com.hccake.starter.sms.properties.extra;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.Getter;
|
||||
|
||||
/**
|
||||
* 新酷卡猫池配置
|
||||
*
|
||||
* @author lingting 2020/5/6 16:59
|
||||
*/
|
||||
@Data
|
||||
public class XinKuKa {
|
||||
|
||||
/**
|
||||
* 猫池短信发送模式
|
||||
*/
|
||||
private Mode mode = Mode.random;
|
||||
|
||||
/**
|
||||
* 指定手机号
|
||||
*/
|
||||
private String number;
|
||||
|
||||
/**
|
||||
* 指定端口
|
||||
*/
|
||||
private String port;
|
||||
|
||||
/**
|
||||
* 数据库配置
|
||||
*/
|
||||
private DataBase dataBase;
|
||||
|
||||
@Getter
|
||||
@AllArgsConstructor
|
||||
public enum Mode {
|
||||
|
||||
/**
|
||||
* 随机选择可用通道发送
|
||||
*/
|
||||
random,
|
||||
/**
|
||||
* 匹配指定手机号发送
|
||||
*/
|
||||
number,
|
||||
/**
|
||||
* 匹配指定端口发送
|
||||
*/
|
||||
@Deprecated
|
||||
port,
|
||||
|
||||
;
|
||||
|
||||
}
|
||||
|
||||
@Data
|
||||
public static class DataBase {
|
||||
|
||||
/**
|
||||
* 使用哪种数据库
|
||||
*/
|
||||
private Kind kind = Kind.mysql;
|
||||
|
||||
@Getter
|
||||
@AllArgsConstructor
|
||||
public enum Kind {
|
||||
|
||||
/**
|
||||
* 使用mysql 数据库
|
||||
*/
|
||||
mysql,
|
||||
|
||||
;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
|
||||
com.hccake.starter.sms.SmsAutoConfiguration,\
|
||||
com.hccake.starter.sms.impl.xinkuka.service.impl.XinKuKaSmsSendServiceImpl
|
||||
@@ -0,0 +1,40 @@
|
||||
# 新酷卡所属表
|
||||
CREATE TABLE IF NOT EXISTS `port_info`
|
||||
(
|
||||
`Id` int(11) NOT NULL AUTO_INCREMENT,
|
||||
`PortNum` int(11) unsigned NOT NULL DEFAULT '0' COMMENT '端口号',
|
||||
`IMSI` varchar(255) NOT NULL DEFAULT '' COMMENT '用户识别码(IMSI)',
|
||||
`ICCID` varchar(255) DEFAULT '' COMMENT '卡识别码(ICCID)',
|
||||
`PhoNum` varchar(255) DEFAULT NULL COMMENT '手机号',
|
||||
PRIMARY KEY (`Id`)
|
||||
) ENGINE = INNODB
|
||||
DEFAULT CHARSET = gbk;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `sms_recv`
|
||||
(
|
||||
`Id` int(11) NOT NULL AUTO_INCREMENT,
|
||||
`PortNum` int(11) unsigned DEFAULT '0' COMMENT '接收短信的端口号',
|
||||
`PhoNum` varchar(255) DEFAULT '' COMMENT '手机号',
|
||||
`IMSI` varchar(255) DEFAULT NULL COMMENT '用户识别码(IMSI)',
|
||||
`ICCID` varchar(255) DEFAULT NULL COMMENT '卡识别码(ICCID)',
|
||||
`smsDate` varchar(255) NOT NULL DEFAULT '' COMMENT '短信日期,注意是smsDate而不是smsData',
|
||||
`smsNumber` varchar(255) NOT NULL DEFAULT '' COMMENT '短信号码',
|
||||
`smsContent` varchar(255) NOT NULL DEFAULT '' COMMENT '短信内容',
|
||||
PRIMARY KEY (`Id`)
|
||||
) ENGINE = INNODB
|
||||
DEFAULT CHARSET = gbk;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `sms_send`
|
||||
(
|
||||
`Id` int(11) NOT NULL AUTO_INCREMENT,
|
||||
`PortNum` int(11) DEFAULT '-1' COMMENT '大于0表示指定端口号发送',
|
||||
`smsNumber` varchar(255) NOT NULL DEFAULT '' COMMENT '接收号码',
|
||||
`smsSubject` varchar(255) DEFAULT '' COMMENT '彩信标题,如果发送彩信不能为空',
|
||||
`smsContent` varchar(255) NOT NULL DEFAULT '' COMMENT '发送内容',
|
||||
`smsType` int(11) unsigned DEFAULT '0' COMMENT '0:短信 1:彩信',
|
||||
`PhoNum` varchar(255) DEFAULT NULL COMMENT '手机号',
|
||||
`smsState` int(11) unsigned NOT NULL DEFAULT '0' COMMENT '0:未发送 1:已在发送队列 2:发送成功 3:发送失败',
|
||||
PRIMARY KEY (`Id`)
|
||||
) ENGINE = INNODB
|
||||
DEFAULT CHARSET = gbk
|
||||
ROW_FORMAT = DYNAMIC;
|
||||
@@ -23,6 +23,7 @@
|
||||
<module>ballcat-spring-boot-starter-redis</module>
|
||||
<module>ballcat-spring-boot-starter-storage</module>
|
||||
<module>ballcat-spring-boot-starter-swagger</module>
|
||||
<module>ballcat-spring-boot-starter-sms</module>
|
||||
</modules>
|
||||
|
||||
</project>
|
||||
Reference in New Issue
Block a user