定义短信回调的结果
parent
0d0110ec08
commit
c91833a504
|
@ -128,13 +128,13 @@ public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
|
|||
// 设置每个请求的权限
|
||||
.authorizeRequests()
|
||||
// 登陆的接口,可匿名访问
|
||||
.antMatchers(webProperties.getApiPrefix() + "/login").anonymous()
|
||||
.antMatchers(api("/login")).anonymous()
|
||||
// 通用的接口,可匿名访问
|
||||
.antMatchers( webProperties.getApiPrefix() + "/system/captcha/**").anonymous()
|
||||
.antMatchers(api("/system/captcha/**")).anonymous()
|
||||
// 静态资源,可匿名访问
|
||||
.antMatchers(HttpMethod.GET, "/*.html", "/**/*.html", "/**/*.css", "/**/*.js").permitAll()
|
||||
// 文件的获取接口,可匿名访问
|
||||
.antMatchers(webProperties.getApiPrefix() + "/infra/file/get/**").anonymous()
|
||||
.antMatchers(api("/infra/file/get/**")).anonymous()
|
||||
// Swagger 接口文档
|
||||
.antMatchers("/swagger-ui.html").anonymous()
|
||||
.antMatchers("/swagger-resources/**").anonymous()
|
||||
|
@ -148,13 +148,19 @@ public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
|
|||
.antMatchers("/actuator/**").anonymous()
|
||||
// Druid 监控
|
||||
.antMatchers("/druid/**").anonymous()
|
||||
// 短信回调 API
|
||||
.antMatchers(api("/system/sms/callback/**")).anonymous()
|
||||
// 除上面外的所有请求全部需要鉴权认证
|
||||
.anyRequest().authenticated()
|
||||
.and()
|
||||
.headers().frameOptions().disable();
|
||||
httpSecurity.logout().logoutUrl(webProperties.getApiPrefix() + "/logout").logoutSuccessHandler(logoutSuccessHandler);
|
||||
httpSecurity.logout().logoutUrl(api("/logout")).logoutSuccessHandler(logoutSuccessHandler);
|
||||
// 添加 JWT Filter
|
||||
httpSecurity.addFilterBefore(authenticationTokenFilter, UsernamePasswordAuthenticationFilter.class);
|
||||
}
|
||||
|
||||
private String api(String url) {
|
||||
return webProperties.getApiPrefix() + url;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,10 +1,9 @@
|
|||
package cn.iocoder.dashboard.framework.sms.core.client;
|
||||
|
||||
import cn.iocoder.dashboard.common.core.KeyValue;
|
||||
import cn.iocoder.dashboard.framework.sms.core.client.dto.SmsResultDetail;
|
||||
import cn.iocoder.dashboard.framework.sms.core.client.dto.SmsReceiveRespDTO;
|
||||
import cn.iocoder.dashboard.framework.sms.core.client.dto.SmsSendRespDTO;
|
||||
|
||||
import javax.servlet.ServletRequest;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
|
@ -31,15 +30,15 @@ public interface SmsClient {
|
|||
* @param templateParams 短信模板参数
|
||||
* @return 短信发送结果
|
||||
*/
|
||||
SmsCommonResult<SmsSendRespDTO> send(Long logId, String mobile, String apiTemplateId, List<KeyValue<String, Object>> templateParams);
|
||||
SmsCommonResult<SmsSendRespDTO> sendSms(Long logId, String mobile, String apiTemplateId, List<KeyValue<String, Object>> templateParams);
|
||||
|
||||
// TODO FROM 芋艿 to ZZF:是不是可以改成意图更明确的解析返回结果,例如说 parseXXXX
|
||||
/**
|
||||
* 短信发送回调请求处理
|
||||
* 解析接收短信的接收结果
|
||||
*
|
||||
* @param request 请求
|
||||
* @return 短信发送结果
|
||||
* @param text 结果
|
||||
* @return 结果内容
|
||||
* @throws Throwable 当解析 text 发生异常时,则会抛出异常
|
||||
*/
|
||||
SmsResultDetail smsSendCallbackHandle(ServletRequest request) throws Exception;
|
||||
SmsCommonResult<SmsReceiveRespDTO> parseSmsReceiveStatus(String text) throws Throwable;
|
||||
|
||||
}
|
||||
|
|
|
@ -18,6 +18,14 @@ public interface SmsClientFactory {
|
|||
*/
|
||||
SmsClient getSmsClient(Long channelId);
|
||||
|
||||
/**
|
||||
* 获得短信 Client
|
||||
*
|
||||
* @param channelCode 渠道编码
|
||||
* @return 短信 Client
|
||||
*/
|
||||
SmsClient getSmsClient(String channelCode);
|
||||
|
||||
/**
|
||||
* 创建短信 Client
|
||||
*
|
||||
|
|
|
@ -7,10 +7,12 @@ import java.io.Serializable;
|
|||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* 消息内容实体类
|
||||
* 消息接收 Response DTO
|
||||
*
|
||||
* @author 芋道源码
|
||||
*/
|
||||
@Data
|
||||
public class SmsResultDetail implements Serializable {
|
||||
public class SmsReceiveRespDTO implements Serializable {
|
||||
|
||||
/**
|
||||
* 唯一标识
|
|
@ -4,6 +4,7 @@ import cn.iocoder.dashboard.common.core.KeyValue;
|
|||
import cn.iocoder.dashboard.framework.sms.core.client.SmsClient;
|
||||
import cn.iocoder.dashboard.framework.sms.core.client.SmsCodeMapping;
|
||||
import cn.iocoder.dashboard.framework.sms.core.client.SmsCommonResult;
|
||||
import cn.iocoder.dashboard.framework.sms.core.client.dto.SmsReceiveRespDTO;
|
||||
import cn.iocoder.dashboard.framework.sms.core.client.dto.SmsSendRespDTO;
|
||||
import cn.iocoder.dashboard.framework.sms.core.property.SmsChannelProperties;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
@ -68,12 +69,12 @@ public abstract class AbstractSmsClient implements SmsClient {
|
|||
}
|
||||
|
||||
@Override
|
||||
public final SmsCommonResult<SmsSendRespDTO> send(Long logId, String mobile,
|
||||
String apiTemplateId, List<KeyValue<String, Object>> templateParams) {
|
||||
public final SmsCommonResult<SmsSendRespDTO> sendSms(Long logId, String mobile,
|
||||
String apiTemplateId, List<KeyValue<String, Object>> templateParams) {
|
||||
// 执行短信发送
|
||||
SmsCommonResult<SmsSendRespDTO> result;
|
||||
try {
|
||||
result = doSend(logId, mobile, apiTemplateId, templateParams);
|
||||
result = doSendSms(logId, mobile, apiTemplateId, templateParams);
|
||||
} catch (Throwable ex) {
|
||||
// 打印异常日志
|
||||
log.error("[send][发送短信异常,sendLogId({}) mobile({}) apiTemplateId({}) templateParams({})]",
|
||||
|
@ -84,17 +85,20 @@ public abstract class AbstractSmsClient implements SmsClient {
|
|||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 发送消息
|
||||
*
|
||||
* @param sendLogId 发送日志编号
|
||||
* @param mobile 手机号
|
||||
* @param apiTemplateId 短信 API 的模板编号
|
||||
* @param templateParams 短信模板参数
|
||||
* @return 短信发送结果
|
||||
*/
|
||||
protected abstract SmsCommonResult<SmsSendRespDTO> doSend(Long sendLogId, String mobile,
|
||||
String apiTemplateId, List<KeyValue<String, Object>> templateParams)
|
||||
protected abstract SmsCommonResult<SmsSendRespDTO> doSendSms(Long sendLogId, String mobile,
|
||||
String apiTemplateId, List<KeyValue<String, Object>> templateParams)
|
||||
throws Throwable;
|
||||
|
||||
@Override
|
||||
public SmsCommonResult<SmsReceiveRespDTO> parseSmsReceiveStatus(String text) throws Throwable {
|
||||
try {
|
||||
return doParseSmsReceiveStatus(text);
|
||||
} catch (Throwable ex) {
|
||||
log.error("[parseSmsReceiveStatus][text({}) 解析发生异常]", text, ex);
|
||||
throw ex;
|
||||
}
|
||||
}
|
||||
|
||||
protected abstract SmsCommonResult<SmsReceiveRespDTO> doParseSmsReceiveStatus(String text) throws Throwable;
|
||||
|
||||
}
|
||||
|
|
|
@ -10,8 +10,9 @@ import lombok.extern.slf4j.Slf4j;
|
|||
import org.springframework.util.Assert;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.Arrays;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ConcurrentMap;
|
||||
|
||||
/**
|
||||
* 短信客户端工厂接口
|
||||
|
@ -26,20 +27,45 @@ public class SmsClientFactoryImpl implements SmsClientFactory {
|
|||
* 短信客户端 Map
|
||||
* key:渠道编号,使用 {@link SmsChannelProperties#getId()}
|
||||
*/
|
||||
private final Map<Long, AbstractSmsClient> clients = new ConcurrentHashMap<>();
|
||||
private final ConcurrentMap<Long, AbstractSmsClient> channelIdClients = new ConcurrentHashMap<>();
|
||||
|
||||
/**
|
||||
* 短信客户端 Map
|
||||
* key:渠道编码,使用 {@link SmsChannelProperties#getCode()} ()}
|
||||
*
|
||||
* 注意,一些场景下,需要获得某个渠道类型的客户端,所以需要使用它。
|
||||
* 例如说,解析短信接收结果,是相对通用的,不需要使用某个渠道编号的 {@link #channelIdClients}
|
||||
*/
|
||||
private final ConcurrentMap<String, AbstractSmsClient> channelCodeClients = new ConcurrentHashMap<>();
|
||||
|
||||
public SmsClientFactoryImpl() {
|
||||
// 初始化 channelCodeClients 集合
|
||||
Arrays.stream(SmsChannelEnum.values()).forEach(channel -> {
|
||||
// 创建一个空的 SmsChannelProperties 对象
|
||||
SmsChannelProperties properties = new SmsChannelProperties().setCode(channel.getCode());
|
||||
// 创建 Sms 客户端
|
||||
AbstractSmsClient smsClient = createSmsClient(properties);
|
||||
channelCodeClients.put(channel.getCode(), smsClient);
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public SmsClient getSmsClient(Long channelId) {
|
||||
return clients.get(channelId);
|
||||
return channelIdClients.get(channelId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SmsClient getSmsClient(String channelCode) {
|
||||
return channelCodeClients.get(channelCode);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void createOrUpdateSmsClient(SmsChannelProperties properties) {
|
||||
AbstractSmsClient client = clients.get(properties.getId());
|
||||
AbstractSmsClient client = channelIdClients.get(properties.getId());
|
||||
if (client == null) {
|
||||
client = this.createSmsClient(properties);
|
||||
client.init();
|
||||
clients.put(client.getId(), client);
|
||||
channelIdClients.put(client.getId(), client);
|
||||
} else {
|
||||
client.refresh(properties);
|
||||
}
|
||||
|
|
|
@ -5,7 +5,7 @@ import cn.hutool.core.date.DateUtil;
|
|||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.iocoder.dashboard.common.core.KeyValue;
|
||||
import cn.iocoder.dashboard.framework.sms.core.client.SmsCommonResult;
|
||||
import cn.iocoder.dashboard.framework.sms.core.client.dto.SmsResultDetail;
|
||||
import cn.iocoder.dashboard.framework.sms.core.client.dto.SmsReceiveRespDTO;
|
||||
import cn.iocoder.dashboard.framework.sms.core.client.dto.SmsSendRespDTO;
|
||||
import cn.iocoder.dashboard.framework.sms.core.client.impl.AbstractSmsClient;
|
||||
import cn.iocoder.dashboard.framework.sms.core.property.SmsChannelProperties;
|
||||
|
@ -61,8 +61,8 @@ public class AliyunSmsClient extends AbstractSmsClient {
|
|||
}
|
||||
|
||||
@Override
|
||||
protected SmsCommonResult<SmsSendRespDTO> doSend(Long sendLogId, String mobile,
|
||||
String apiTemplateId, List<KeyValue<String, Object>> templateParams) {
|
||||
protected SmsCommonResult<SmsSendRespDTO> doSendSms(Long sendLogId, String mobile,
|
||||
String apiTemplateId, List<KeyValue<String, Object>> templateParams) {
|
||||
// 构建参数
|
||||
SendSmsRequest request = new SendSmsRequest();
|
||||
request.setSysMethod(MethodType.POST);
|
||||
|
@ -110,11 +110,10 @@ public class AliyunSmsClient extends AbstractSmsClient {
|
|||
* @return
|
||||
* @throws Exception
|
||||
*/
|
||||
@Override
|
||||
public SmsResultDetail smsSendCallbackHandle(ServletRequest request) throws Exception {
|
||||
public SmsReceiveRespDTO smsSendCallbackHandle(ServletRequest request) throws Exception {
|
||||
BufferedReader reader = new BufferedReader(new InputStreamReader(request.getInputStream()));
|
||||
String paramStr = reader.readLine();
|
||||
List<Map<String, Object>> params = JsonUtils.parseByType(paramStr, new TypeReference<List<Map<String, Object>>>() {
|
||||
List<Map<String, Object>> params = JsonUtils.parseObject(paramStr, new TypeReference<List<Map<String, Object>>>() {
|
||||
});
|
||||
if (CollectionUtil.isNotEmpty(params)) {
|
||||
Map<String, Object> sendResultParamMap = params.get(0);
|
||||
|
@ -123,6 +122,11 @@ public class AliyunSmsClient extends AbstractSmsClient {
|
|||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected SmsCommonResult<SmsReceiveRespDTO> doParseSmsReceiveStatus(String text) throws Throwable {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 短信发送回调辅助类
|
||||
*/
|
||||
|
@ -168,8 +172,8 @@ public class AliyunSmsClient extends AbstractSmsClient {
|
|||
return sendResultParamMap.get(CallbackField.OUT_ID).toString();
|
||||
}
|
||||
|
||||
public SmsResultDetail toResultDetail() {
|
||||
SmsResultDetail resultDetail = new SmsResultDetail();
|
||||
public SmsReceiveRespDTO toResultDetail() {
|
||||
SmsReceiveRespDTO resultDetail = new SmsReceiveRespDTO();
|
||||
resultDetail.setSendStatus(getSendStatus());
|
||||
resultDetail.setApiId(getBizId());
|
||||
resultDetail.setSendTime(getSendTime());
|
||||
|
|
|
@ -2,33 +2,31 @@ package cn.iocoder.dashboard.framework.sms.core.client.impl.yunpian;
|
|||
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import cn.hutool.core.collection.CollectionUtil;
|
||||
import cn.hutool.core.date.DateUtil;
|
||||
import cn.hutool.core.util.CharsetUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.hutool.core.util.URLUtil;
|
||||
import cn.iocoder.dashboard.common.core.KeyValue;
|
||||
import cn.iocoder.dashboard.framework.sms.core.client.SmsCommonResult;
|
||||
import cn.iocoder.dashboard.framework.sms.core.client.dto.SmsResultDetail;
|
||||
import cn.iocoder.dashboard.framework.sms.core.client.dto.SmsReceiveRespDTO;
|
||||
import cn.iocoder.dashboard.framework.sms.core.client.dto.SmsSendRespDTO;
|
||||
import cn.iocoder.dashboard.framework.sms.core.client.impl.AbstractSmsClient;
|
||||
import cn.iocoder.dashboard.framework.sms.core.enums.SmsConstants;
|
||||
import cn.iocoder.dashboard.framework.sms.core.property.SmsChannelProperties;
|
||||
import cn.iocoder.dashboard.modules.system.enums.sms.SysSmsSendStatusEnum;
|
||||
import cn.iocoder.dashboard.util.date.DateUtils;
|
||||
import cn.iocoder.dashboard.util.json.JsonUtils;
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import com.fasterxml.jackson.core.type.TypeReference;
|
||||
import com.yunpian.sdk.YunpianClient;
|
||||
import com.yunpian.sdk.constant.YunpianConstant;
|
||||
import com.yunpian.sdk.model.Result;
|
||||
import com.yunpian.sdk.model.SmsSingleSend;
|
||||
import lombok.Data;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import javax.servlet.ServletRequest;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.net.URLEncoder;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.StringJoiner;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* 云片短信客户端的实现类
|
||||
|
@ -65,8 +63,8 @@ public class YunpianSmsClient extends AbstractSmsClient {
|
|||
}
|
||||
|
||||
@Override
|
||||
protected SmsCommonResult<SmsSendRespDTO> doSend(Long sendLogId, String mobile,
|
||||
String apiTemplateId, List<KeyValue<String, Object>> templateParams) throws Throwable {
|
||||
protected SmsCommonResult<SmsSendRespDTO> doSendSms(Long sendLogId, String mobile,
|
||||
String apiTemplateId, List<KeyValue<String, Object>> templateParams) throws Throwable {
|
||||
// 构建参数
|
||||
Map<String, String> request = new HashMap<>();
|
||||
request.put(YunpianConstant.APIKEY, properties.getApiKey());
|
||||
|
@ -74,7 +72,7 @@ public class YunpianSmsClient extends AbstractSmsClient {
|
|||
request.put(YunpianConstant.TPL_ID, apiTemplateId);
|
||||
request.put(YunpianConstant.TPL_VALUE, formatTplValue(templateParams));
|
||||
request.put(YunpianConstant.UID, String.valueOf(sendLogId));
|
||||
request.put(Helper.CALLBACK, properties.getCallbackUrl());
|
||||
request.put(YunpianConstant.CALLBACK_URL, properties.getCallbackUrl());
|
||||
|
||||
// 执行发送
|
||||
Result<SmsSingleSend> sendResult = client.sms().tpl_single_send(request);
|
||||
|
@ -107,15 +105,6 @@ public class YunpianSmsClient extends AbstractSmsClient {
|
|||
return sendResult.getMsg() + " => " + sendResult.getDetail();
|
||||
}
|
||||
|
||||
/**
|
||||
* 云片的比较复杂,又是加密又是套娃的
|
||||
*/
|
||||
@Override
|
||||
public SmsResultDetail smsSendCallbackHandle(ServletRequest request) throws UnsupportedEncodingException {
|
||||
Map<String, String> map = getRequestParams(request);
|
||||
return Helper.getSmsResultDetailByParam(map);
|
||||
}
|
||||
|
||||
/**
|
||||
* 从 request 中获取请求中传入的短信发送结果信息
|
||||
*
|
||||
|
@ -127,7 +116,7 @@ public class YunpianSmsClient extends AbstractSmsClient {
|
|||
Map<String, String[]> parameterMap = request.getParameterMap();
|
||||
String[] smsStatuses = parameterMap.get(YunpianConstant.SMS_STATUS);
|
||||
String encode = URLEncoder.encode(smsStatuses[0], CharsetUtil.UTF_8);
|
||||
List<Map<String, String>> paramList = JsonUtils.parseByType(encode, callbackType);
|
||||
List<Map<String, String>> paramList = JsonUtils.parseObject(encode, callbackType);
|
||||
if (CollectionUtil.isNotEmpty(paramList)) {
|
||||
return paramList.get(0);
|
||||
}
|
||||
|
@ -135,46 +124,63 @@ public class YunpianSmsClient extends AbstractSmsClient {
|
|||
+ JsonUtils.toJsonString(request.getParameterMap()));
|
||||
}
|
||||
|
||||
/**
|
||||
* 云片的回调函数的一些辅助方法
|
||||
*/
|
||||
private static class Helper {
|
||||
|
||||
//短信唯一标识
|
||||
private final static String API_ID = "sid";
|
||||
|
||||
//回调地址·
|
||||
private final static String CALLBACK = "callback";
|
||||
|
||||
//手机号
|
||||
private final static String MOBILE = "mobile";
|
||||
|
||||
//错误信息
|
||||
private final static String ERROR_MSG = "error_msg";
|
||||
|
||||
//用户接收时间 字符串 标准格式
|
||||
private final static String USER_RECEIVE_TIME = "user_receive_time";
|
||||
|
||||
//发送状态
|
||||
private final static String REPORT_STATUS = "report_status";
|
||||
|
||||
private static int getSendStatus(Map<String, String> map) {
|
||||
String reportStatus = map.get(REPORT_STATUS);
|
||||
return SmsConstants.SUCCESS.equals(reportStatus)
|
||||
? SysSmsSendStatusEnum.SUCCESS.getStatus()
|
||||
: SysSmsSendStatusEnum.FAILURE.getStatus();
|
||||
}
|
||||
|
||||
public static SmsResultDetail getSmsResultDetailByParam(Map<String, String> map) {
|
||||
SmsResultDetail detail = new SmsResultDetail();
|
||||
detail.setPhone(map.get(MOBILE));
|
||||
detail.setMessage(map.get(ERROR_MSG));
|
||||
detail.setSendTime(DateUtil.parseTime(map.get(USER_RECEIVE_TIME)));
|
||||
detail.setSendStatus(getSendStatus(map));
|
||||
detail.setApiId(API_ID);
|
||||
|
||||
detail.setCallbackResponseBody(SmsConstants.SUCCESS);
|
||||
return detail;
|
||||
}
|
||||
@Override
|
||||
protected SmsCommonResult<SmsReceiveRespDTO> doParseSmsReceiveStatus(String text) throws Throwable {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 短信接收状态
|
||||
*
|
||||
* 参见 https://www.yunpian.com/official/document/sms/zh_cn/domestic_push_report 文档
|
||||
*
|
||||
* @author 芋道源码
|
||||
*/
|
||||
@Data
|
||||
public static class SmsReceiveStatus {
|
||||
|
||||
/**
|
||||
* 运营商反馈代码的中文解释
|
||||
*
|
||||
* 默认不推送此字段,如需推送,请联系客服
|
||||
*/
|
||||
@JsonProperty("error_detail")
|
||||
private String errorDetail;
|
||||
/**
|
||||
* 短信编号
|
||||
*/
|
||||
private Long sid;
|
||||
/**
|
||||
* 用户自定义 id
|
||||
*
|
||||
* 这里我们传递的是 SysSmsLogDO 的日志编号
|
||||
*/
|
||||
private Long uid;
|
||||
/**
|
||||
* 用户接收时间
|
||||
*/
|
||||
@JsonProperty("user_receive_time")
|
||||
@JsonFormat(pattern = DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
|
||||
private Date userReceiveTime;
|
||||
/**
|
||||
* 运营商返回的代码,如:"DB:0103"
|
||||
*
|
||||
* 由于不同运营商信息不同,此字段仅供参考;
|
||||
*/
|
||||
@JsonProperty("error_msg")
|
||||
private String errorMsg;
|
||||
/**
|
||||
* 接收手机号
|
||||
*/
|
||||
private String mobile;
|
||||
/**
|
||||
* 接收状态
|
||||
*
|
||||
* 目前仅有 SUCCESS / FAIL,所以使用 Boolean 接收
|
||||
*/
|
||||
@JsonProperty("report_status")
|
||||
private String reportStatus;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -16,8 +16,9 @@ public enum SmsChannelEnum {
|
|||
|
||||
YUN_PIAN("YUN_PIAN", "云片"),
|
||||
ALIYUN("ALIYUN", "阿里云"),
|
||||
TENCENT("TENCENT", "腾讯云"),
|
||||
HUA_WEI("HUA_WEI", "华为云"),;
|
||||
// TENCENT("TENCENT", "腾讯云"),
|
||||
// HUA_WEI("HUA_WEI", "华为云"),
|
||||
;
|
||||
|
||||
/**
|
||||
* 编码
|
||||
|
|
|
@ -1,16 +0,0 @@
|
|||
package cn.iocoder.dashboard.framework.sms.core.enums;
|
||||
|
||||
/**
|
||||
* 短信相关常量类
|
||||
*
|
||||
* @author zzf
|
||||
* @date 2021/3/5 10:42
|
||||
*/
|
||||
public interface SmsConstants {
|
||||
|
||||
|
||||
String COMMA = ",";
|
||||
|
||||
String SUCCESS = "SUCCESS";
|
||||
|
||||
}
|
|
@ -0,0 +1,34 @@
|
|||
package cn.iocoder.dashboard.modules.system.controller.sms;
|
||||
|
||||
import cn.hutool.core.util.URLUtil;
|
||||
import cn.iocoder.dashboard.common.pojo.CommonResult;
|
||||
import cn.iocoder.dashboard.framework.sms.core.enums.SmsChannelEnum;
|
||||
import cn.iocoder.dashboard.modules.system.service.sms.SysSmsService;
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiImplicitParam;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
|
||||
@Api(tags = "短信回调")
|
||||
@RestController
|
||||
@RequestMapping("/system/sms/callback")
|
||||
public class SmsCallbackController {
|
||||
|
||||
@Resource
|
||||
private SysSmsService smsService;
|
||||
|
||||
@PostMapping("/sms/yunpian")
|
||||
@ApiOperation(value = "云片短信的回调", notes = "参见 https://www.yunpian.com/official/document/sms/zh_cn/domestic_push_report 文档")
|
||||
@ApiImplicitParam(name = "sms_status", value = "发送状态", required = true, example = "[{具体内容}]", dataTypeClass = Long.class)
|
||||
public CommonResult<Boolean> receiveYunpianSmsStatus(@RequestParam("sms_status") String smsStatus) throws Throwable {
|
||||
String text = URLUtil.decode(smsStatus); // decode 解码参数,因为它被 encode
|
||||
smsService.receiveSmsStatus(SmsChannelEnum.YUN_PIAN.getCode(), text);
|
||||
return CommonResult.success(true);
|
||||
}
|
||||
|
||||
}
|
|
@ -1,48 +0,0 @@
|
|||
package cn.iocoder.dashboard.modules.system.controller.sms;
|
||||
|
||||
import cn.iocoder.dashboard.modules.system.service.sms.SysSmsService;
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.servlet.ServletRequest;
|
||||
|
||||
/**
|
||||
* 短信默认回调接口
|
||||
*
|
||||
* @author zzf
|
||||
* @date 2021/3/5 8:59
|
||||
*/
|
||||
@Api(tags = "短信回调api")
|
||||
@RestController
|
||||
@RequestMapping("/sms/callback")
|
||||
public class SmsDefaultCallbackController {
|
||||
|
||||
@Resource
|
||||
private SysSmsService smsService;
|
||||
|
||||
|
||||
@ApiOperation(value = "短信发送回调接口")
|
||||
@PostMapping("/sms-send")
|
||||
public Object sendSmsCallback(ServletRequest request) {
|
||||
return smsService.smsSendCallbackHandle(request);
|
||||
}
|
||||
|
||||
/*
|
||||
@Resource
|
||||
private SmsSendStreamProducer smsSendStreamProducer;
|
||||
|
||||
@ApiOperation("redis stream测试")
|
||||
@GetMapping("/test/redis/stream")
|
||||
public void test() {
|
||||
SmsBody smsBody = new SmsBody();
|
||||
smsBody.setSmsLogId(1L);
|
||||
smsBody.setTemplateCode("sdf");
|
||||
smsBody.setTemplateContent("sdf");
|
||||
smsSendStreamProducer.sendSmsSendMessage(smsBody, "18216466755");
|
||||
}*/
|
||||
|
||||
}
|
|
@ -2,7 +2,6 @@ package cn.iocoder.dashboard.modules.system.service.sms;
|
|||
|
||||
import cn.iocoder.dashboard.modules.system.mq.message.sms.SysSmsSendMessage;
|
||||
|
||||
import javax.servlet.ServletRequest;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
|
@ -24,11 +23,12 @@ public interface SysSmsService {
|
|||
void doSendSms(SysSmsSendMessage message);
|
||||
|
||||
/**
|
||||
* 处理短信发送回调函数
|
||||
* 接收短信的接收结果
|
||||
*
|
||||
* @param request 请求
|
||||
* @return 响应数据
|
||||
* @param channelCode 渠道编码
|
||||
* @param text 结果内容
|
||||
* @throws Throwable 处理失败时,抛出异常
|
||||
*/
|
||||
Object smsSendCallbackHandle(ServletRequest request);
|
||||
void receiveSmsStatus(String channelCode, String text) throws Throwable;
|
||||
|
||||
}
|
||||
|
|
|
@ -7,6 +7,7 @@ import cn.iocoder.dashboard.common.enums.UserTypeEnum;
|
|||
import cn.iocoder.dashboard.framework.sms.core.client.SmsClient;
|
||||
import cn.iocoder.dashboard.framework.sms.core.client.SmsClientFactory;
|
||||
import cn.iocoder.dashboard.framework.sms.core.client.SmsCommonResult;
|
||||
import cn.iocoder.dashboard.framework.sms.core.client.dto.SmsReceiveRespDTO;
|
||||
import cn.iocoder.dashboard.framework.sms.core.client.dto.SmsSendRespDTO;
|
||||
import cn.iocoder.dashboard.modules.system.dal.dataobject.sms.SysSmsTemplateDO;
|
||||
import cn.iocoder.dashboard.modules.system.dal.dataobject.user.SysUserDO;
|
||||
|
@ -21,7 +22,6 @@ import org.springframework.stereotype.Service;
|
|||
import org.springframework.util.Assert;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.servlet.ServletRequest;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
|
@ -139,7 +139,7 @@ public class SysSmsServiceImpl implements SysSmsService {
|
|||
SmsClient smsClient = smsClientFactory.getSmsClient(message.getChannelId());
|
||||
Assert.notNull(smsClient, String.format("短信客户端(%d) 不存在", message.getChannelId()));
|
||||
// 发送短信
|
||||
SmsCommonResult<SmsSendRespDTO> sendResult = smsClient.send(message.getLogId(), message.getMobile(),
|
||||
SmsCommonResult<SmsSendRespDTO> sendResult = smsClient.sendSms(message.getLogId(), message.getMobile(),
|
||||
message.getApiTemplateId(), message.getTemplateParams());
|
||||
smsLogService.updateSmsSendResult(message.getLogId(), sendResult.getCode(), sendResult.getMsg(),
|
||||
sendResult.getApiCode(), sendResult.getApiMsg(), sendResult.getApiRequestId(),
|
||||
|
@ -147,11 +147,12 @@ public class SysSmsServiceImpl implements SysSmsService {
|
|||
}
|
||||
|
||||
@Override
|
||||
public Object smsSendCallbackHandle(ServletRequest request) {
|
||||
// SmsResultDetail smsResultDetail = smsClientFactory.getSmsResultDetailFromCallbackQuery(request);
|
||||
// logService.updateSendLogByResultDetail(smsResultDetail);
|
||||
// return smsResultDetail.getCallbackResponseBody();
|
||||
return null;
|
||||
public void receiveSmsStatus(String channelCode, String text) throws Throwable {
|
||||
// 获得渠道对应的 SmsClient 客户端
|
||||
SmsClient smsClient = smsClientFactory.getSmsClient(channelCode);
|
||||
Assert.notNull(smsClient, String.format("短信客户端(%s) 不存在", channelCode));
|
||||
// 解析内容
|
||||
SmsCommonResult<SmsReceiveRespDTO> receiveResult = smsClient.parseSmsReceiveStatus(text);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -2,12 +2,14 @@ package cn.iocoder.dashboard.util.json;
|
|||
|
||||
import cn.hutool.core.util.ArrayUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.iocoder.dashboard.framework.sms.core.client.impl.yunpian.YunpianSmsClient;
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import com.fasterxml.jackson.core.type.TypeReference;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Set;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* JSON 工具类
|
||||
|
@ -59,7 +61,7 @@ public class JsonUtils {
|
|||
}
|
||||
}
|
||||
|
||||
public static Object parseObject(String text, TypeReference<Set<Long>> typeReference) {
|
||||
public static <T> T parseObject(String text, TypeReference<T> typeReference) {
|
||||
try {
|
||||
return objectMapper.readValue(text, typeReference);
|
||||
} catch (IOException e) {
|
||||
|
@ -67,12 +69,21 @@ public class JsonUtils {
|
|||
}
|
||||
}
|
||||
|
||||
public static <T> T parseByType(String text, TypeReference<T> typeReference) {
|
||||
public static <T> List<T> parseArray(String text, Class<T> clazz) {
|
||||
if (StrUtil.isEmpty(text)) {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
try {
|
||||
return objectMapper.readValue(text, typeReference);
|
||||
return objectMapper.readValue(text, objectMapper.getTypeFactory().constructCollectionType(List.class, clazz));
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
String text = "[{\"sid\":9527,\"uid\":null,\"user_receive_time\":\"2014-03-17 22:55:21\",\"error_msg\":\"\",\"mobile\":\"15205201314\",\"report_status\":\"SUCCESS\"},{\"sid\":9528,\"uid\":null,\"user_receive_time\":\"2014-03-17 22:55:23\",\"error_msg\":\"\",\"mobile\":\"15212341234\",\"report_status\":\"SUCCESS\"}]";
|
||||
List<YunpianSmsClient.SmsReceiveStatus> result = parseArray(text, YunpianSmsClient.SmsReceiveStatus.class);
|
||||
System.out.println(result);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -32,7 +32,7 @@ public class AliyunSmsClientTest {
|
|||
templateParams.add(new KeyValue<>("code", "1024"));
|
||||
// templateParams.put("operation", "嘿嘿");
|
||||
// SmsResult result = smsClient.send(1L, "15601691399", "4372216", templateParams);
|
||||
SmsCommonResult<SmsSendRespDTO> result = smsClient.send(1L, "15601691399", "SMS_207945135", templateParams);
|
||||
SmsCommonResult<SmsSendRespDTO> result = smsClient.sendSms(1L, "15601691399", "SMS_207945135", templateParams);
|
||||
System.out.println(result);
|
||||
}
|
||||
|
||||
|
|
|
@ -31,7 +31,7 @@ public class YunpianSmsClientIntegrationTest {
|
|||
templateParams.add(new KeyValue<>("code", "1024"));
|
||||
templateParams.add(new KeyValue<>("operation", "嘿嘿"));
|
||||
// SmsResult result = smsClient.send(1L, "15601691399", "4372216", templateParams);
|
||||
SmsCommonResult<SmsSendRespDTO> result = smsClient.send(1L, "15601691399", "4383920", templateParams);
|
||||
SmsCommonResult<SmsSendRespDTO> result = smsClient.sendSms(1L, "15601691399", "4383920", templateParams);
|
||||
System.out.println(result);
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue