From e36b32a97ddef14e728065067d552e0b46e2c36b Mon Sep 17 00:00:00 2001 From: cherishsince Date: Mon, 20 Apr 2020 11:36:44 +0800 Subject: [PATCH] =?UTF-8?q?-=20=E4=BF=AE=E6=94=B9=E7=BB=93=E6=9E=84?= =?UTF-8?q?=EF=BC=9A=E7=9F=AD=E4=BF=A1=20smsSign=20-=20=E4=BF=AE=E6=94=B9?= =?UTF-8?q?=E7=BB=93=E6=9E=84=EF=BC=9A=E7=9F=AD=E4=BF=A1=20smsTemplate?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- admin-web/src/models/sms/smsSignList.js | 19 +- admin-web/src/models/sms/smsTemplateList.js | 17 +- admin-web/src/pages/Sms/SignList.js | 4 +- admin-web/src/pages/Sms/TemplateList.js | 8 +- admin-web/src/services/sms.js | 17 +- pom.xml | 16 + system/system-biz/pom.xml | 12 +- .../system/biz/bo/smsSign/ListSmsSignBO.java | 53 +++ .../mall/system/biz/bo/smsSign/SmsSignBO.java | 40 ++ .../biz/bo/smsTemplate/ListSmsTemplateBO.java | 103 +++++ .../biz/bo/smsTemplate/SmsTemplateBO.java | 44 ++ .../system/biz/convert/SmsSignConvert.java | 29 ++ .../biz/convert/SmsTemplateConvert.java | 32 ++ .../system/biz/dao/sms/SmsSendMapper.java | 15 + .../system/biz/dao/sms/SmsSignMapper.java | 15 + .../system/biz/dao/sms/SmsTemplateMapper.java | 15 + .../biz/dataobject/sms/SmsSendLogDO.java | 37 ++ .../system/biz/dataobject/sms/SmsSignDO.java | 48 ++ .../biz/dataobject/sms/SmsTemplateDO.java | 59 +++ .../system/biz/dto/smsSign/AddSignDTO.java | 21 + .../biz/dto/smsSign/ListSmsSignDTO.java | 28 ++ .../system/biz/dto/smsSign/UpdateSignDTO.java | 24 + .../dto/smsTemplate/ListSmsTemplateDTO.java | 30 ++ .../system/biz/enums/AdminErrorCodeEnum.java | 85 ++++ .../mall/system/biz/enums/package-info.java | 5 + .../biz/enums/sms/SmsApplyStatusEnum.java | 31 ++ .../system/biz/enums/sms/SmsPlatformEnum.java | 41 ++ .../system/biz/enums/sms/SmsTypeEnum.java | 42 ++ .../system/biz/service/sms/SmsClient.java | 64 +++ .../system/biz/service/sms/SmsService.java | 117 +++++ .../biz/service/sms/SmsServiceImpl.java | 423 ++++++++++++++++++ .../service/sms/client/SmsAliYunClient.java | 163 +++++++ .../service/sms/client/SmsYunPianClient.java | 242 ++++++++++ .../admin/AdminsSmsSignController.java | 57 +++ .../admin/AdminsSmsTemplateController.java | 68 +++ .../rest/convert/sms/AdminsSmsConvert.java | 32 ++ .../rest/request/smsSign/AddSignRequest.java | 22 + .../request/smsSign/UpdateSignRequest.java | 23 + .../smsTemplate/AddSmsTemplateRequest.java | 49 ++ .../smsTemplate/ListSmsTemplateRequest.java | 30 ++ .../smsTemplate/UpdateSmsTemplateRequest.java | 53 +++ 41 files changed, 2214 insertions(+), 19 deletions(-) create mode 100644 system/system-biz/src/main/java/cn/iocoder/mall/system/biz/bo/smsSign/ListSmsSignBO.java create mode 100644 system/system-biz/src/main/java/cn/iocoder/mall/system/biz/bo/smsSign/SmsSignBO.java create mode 100644 system/system-biz/src/main/java/cn/iocoder/mall/system/biz/bo/smsTemplate/ListSmsTemplateBO.java create mode 100644 system/system-biz/src/main/java/cn/iocoder/mall/system/biz/bo/smsTemplate/SmsTemplateBO.java create mode 100644 system/system-biz/src/main/java/cn/iocoder/mall/system/biz/convert/SmsSignConvert.java create mode 100644 system/system-biz/src/main/java/cn/iocoder/mall/system/biz/convert/SmsTemplateConvert.java create mode 100644 system/system-biz/src/main/java/cn/iocoder/mall/system/biz/dao/sms/SmsSendMapper.java create mode 100644 system/system-biz/src/main/java/cn/iocoder/mall/system/biz/dao/sms/SmsSignMapper.java create mode 100644 system/system-biz/src/main/java/cn/iocoder/mall/system/biz/dao/sms/SmsTemplateMapper.java create mode 100644 system/system-biz/src/main/java/cn/iocoder/mall/system/biz/dataobject/sms/SmsSendLogDO.java create mode 100644 system/system-biz/src/main/java/cn/iocoder/mall/system/biz/dataobject/sms/SmsSignDO.java create mode 100644 system/system-biz/src/main/java/cn/iocoder/mall/system/biz/dataobject/sms/SmsTemplateDO.java create mode 100644 system/system-biz/src/main/java/cn/iocoder/mall/system/biz/dto/smsSign/AddSignDTO.java create mode 100644 system/system-biz/src/main/java/cn/iocoder/mall/system/biz/dto/smsSign/ListSmsSignDTO.java create mode 100644 system/system-biz/src/main/java/cn/iocoder/mall/system/biz/dto/smsSign/UpdateSignDTO.java create mode 100644 system/system-biz/src/main/java/cn/iocoder/mall/system/biz/dto/smsTemplate/ListSmsTemplateDTO.java create mode 100644 system/system-biz/src/main/java/cn/iocoder/mall/system/biz/enums/AdminErrorCodeEnum.java create mode 100644 system/system-biz/src/main/java/cn/iocoder/mall/system/biz/enums/package-info.java create mode 100644 system/system-biz/src/main/java/cn/iocoder/mall/system/biz/enums/sms/SmsApplyStatusEnum.java create mode 100644 system/system-biz/src/main/java/cn/iocoder/mall/system/biz/enums/sms/SmsPlatformEnum.java create mode 100644 system/system-biz/src/main/java/cn/iocoder/mall/system/biz/enums/sms/SmsTypeEnum.java create mode 100644 system/system-biz/src/main/java/cn/iocoder/mall/system/biz/service/sms/SmsClient.java create mode 100644 system/system-biz/src/main/java/cn/iocoder/mall/system/biz/service/sms/SmsService.java create mode 100644 system/system-biz/src/main/java/cn/iocoder/mall/system/biz/service/sms/SmsServiceImpl.java create mode 100644 system/system-biz/src/main/java/cn/iocoder/mall/system/biz/service/sms/client/SmsAliYunClient.java create mode 100644 system/system-biz/src/main/java/cn/iocoder/mall/system/biz/service/sms/client/SmsYunPianClient.java create mode 100644 system/system-rest/src/main/java/cn/iocoder/mall/system/rest/controller/admin/AdminsSmsSignController.java create mode 100644 system/system-rest/src/main/java/cn/iocoder/mall/system/rest/controller/admin/AdminsSmsTemplateController.java create mode 100644 system/system-rest/src/main/java/cn/iocoder/mall/system/rest/convert/sms/AdminsSmsConvert.java create mode 100644 system/system-rest/src/main/java/cn/iocoder/mall/system/rest/request/smsSign/AddSignRequest.java create mode 100644 system/system-rest/src/main/java/cn/iocoder/mall/system/rest/request/smsSign/UpdateSignRequest.java create mode 100644 system/system-rest/src/main/java/cn/iocoder/mall/system/rest/request/smsTemplate/AddSmsTemplateRequest.java create mode 100644 system/system-rest/src/main/java/cn/iocoder/mall/system/rest/request/smsTemplate/ListSmsTemplateRequest.java create mode 100644 system/system-rest/src/main/java/cn/iocoder/mall/system/rest/request/smsTemplate/UpdateSmsTemplateRequest.java diff --git a/admin-web/src/models/sms/smsSignList.js b/admin-web/src/models/sms/smsSignList.js index f50a8fdd5..feefbb0c6 100644 --- a/admin-web/src/models/sms/smsSignList.js +++ b/admin-web/src/models/sms/smsSignList.js @@ -1,9 +1,12 @@ -import { pageSign, addSign, updateSign, deletedSign } from '../../services/sms'; +import { addSign, deletedSign, pageSign, updateSign } from '../../services/sms'; export default { namespace: 'smsSignList', state: { + total: 0, + index: 1, + size: 20, list: [], }, @@ -13,7 +16,10 @@ export default { if (response.code === 0) { yield put({ type: 'pageSuccess', - payload: response.data, + payload: { + data: response.data, + params: payload, + }, }); } }, @@ -46,10 +52,15 @@ export default { reducers: { pageSuccess(state, { payload }) { - const { data } = payload; + const { data, params } = payload; + const { pageNo, pageSize } = params; + const { list, total } = data; return { ...state, - list: data, + size: pageSize, + index: pageNo, + total, + list, }; }, }, diff --git a/admin-web/src/models/sms/smsTemplateList.js b/admin-web/src/models/sms/smsTemplateList.js index 748fad7f4..2bc032a5b 100644 --- a/admin-web/src/models/sms/smsTemplateList.js +++ b/admin-web/src/models/sms/smsTemplateList.js @@ -4,6 +4,9 @@ export default { namespace: 'smsTemplateList', state: { + total: 0, + index: 1, + size: 20, list: [], }, @@ -13,7 +16,10 @@ export default { if (response.code === 0) { yield put({ type: 'pageSuccess', - payload: response.data, + payload: { + data: response.data, + params: payload, + }, }); } }, @@ -46,10 +52,15 @@ export default { reducers: { pageSuccess(state, { payload }) { - const { data } = payload; + const { data, params } = payload; + const { pageNo, pageSize } = params; + const { list, total } = data; return { ...state, - list: data, + size: pageSize, + index: pageNo, + total, + list, }; }, }, diff --git a/admin-web/src/pages/Sms/SignList.js b/admin-web/src/pages/Sms/SignList.js index 0d4898a0d..a80441229 100644 --- a/admin-web/src/pages/Sms/SignList.js +++ b/admin-web/src/pages/Sms/SignList.js @@ -40,9 +40,9 @@ class SignList extends PureComponent { dispatch({ type: 'smsSignList/page', payload: { - current, + pageNo: current, total, - size, + pageSize: size, ...searchParams, }, }); diff --git a/admin-web/src/pages/Sms/TemplateList.js b/admin-web/src/pages/Sms/TemplateList.js index 0c725ea00..c18ab2b5a 100644 --- a/admin-web/src/pages/Sms/TemplateList.js +++ b/admin-web/src/pages/Sms/TemplateList.js @@ -42,9 +42,9 @@ class TemplateList extends PureComponent { dispatch({ type: 'smsSignList/page', payload: { - current: 1, + pageNo: 1, total: 0, - size: 100, + pageSize: 100, // ...searchParams, }, }); @@ -57,9 +57,9 @@ class TemplateList extends PureComponent { dispatch({ type: 'smsTemplateList/page', payload: { - current, + pageNo: current, total, - size, + pageSize: size, ...searchParams, }, }); diff --git a/admin-web/src/services/sms.js b/admin-web/src/services/sms.js index 67d65717c..7216143a5 100644 --- a/admin-web/src/services/sms.js +++ b/admin-web/src/services/sms.js @@ -10,14 +10,20 @@ export async function pageSign(params) { } export async function addSign(params) { - return request(`/admin-api/admins/sms/sign/add?${stringify(params)}`, { + return request(`/admin-api/admins/sms/sign/add`, { method: 'POST', + body: { + ...params, + }, }); } export async function updateSign(params) { - return request(`/admin-api/admins/sms/sign/update?${stringify(params)}`, { + return request(`/admin-api/admins/sms/sign/update`, { method: 'PUT', + body: { + ...params, + }, }); } @@ -30,8 +36,11 @@ export async function deletedSign(params) { // template export async function pageTemplate(params) { - return request(`/admin-api/admins/sms/template/page?${stringify(params)}`, { - method: 'GET', + return request(`/admin-api/admins/sms/template/page`, { + method: 'POST', + body: { + ...params, + }, }); } diff --git a/pom.xml b/pom.xml index 5eca5d951..33107926f 100644 --- a/pom.xml +++ b/pom.xml @@ -56,6 +56,10 @@ 2.5 + + 1.2.7 + 4.1.0 + 1.8 6.0.16.Final 1.2.56 @@ -170,6 +174,18 @@ ${xxl-job.version} + + + com.yunpian.sdk + yunpian-java-sdk + ${yunpian-java-sdk.version} + + + com.aliyun + aliyun-java-sdk-core + ${aliyun-java-sdk-core.version} + + com.qiniu diff --git a/system/system-biz/pom.xml b/system/system-biz/pom.xml index fa74d3961..71cc2cb2b 100644 --- a/system/system-biz/pom.xml +++ b/system/system-biz/pom.xml @@ -43,12 +43,21 @@ com.alibaba druid-spring-boot-starter - com.baomidou mybatis-plus-boot-starter + + + com.yunpian.sdk + yunpian-java-sdk + + + com.aliyun + aliyun-java-sdk-core + + org.mapstruct @@ -58,7 +67,6 @@ org.mapstruct mapstruct-jdk8 - org.projectlombok lombok diff --git a/system/system-biz/src/main/java/cn/iocoder/mall/system/biz/bo/smsSign/ListSmsSignBO.java b/system/system-biz/src/main/java/cn/iocoder/mall/system/biz/bo/smsSign/ListSmsSignBO.java new file mode 100644 index 000000000..bc3a3db8d --- /dev/null +++ b/system/system-biz/src/main/java/cn/iocoder/mall/system/biz/bo/smsSign/ListSmsSignBO.java @@ -0,0 +1,53 @@ +package cn.iocoder.mall.system.biz.bo.smsSign; + +import com.fasterxml.jackson.annotation.JsonFormat; +import lombok.Data; +import lombok.experimental.Accessors; + +import java.util.Date; + +/** + * sms page + * + * @author Sin + * @time 2019/5/19 4:23 PM + */ +@Data +@Accessors(chain = true) +public class ListSmsSignBO { + + /** + * 编号 + */ + private Integer id; + /** + * 短信平台 + */ + private Integer platform; + /** + * 签名名称 + */ + private String sign; + /** + * 审核状态 + *

+ * - 1、审核中 + * - 2、审核成功 + * - 3、审核失败 + */ + private Integer applyStatus; + /** + * 审核信息 + */ + private String applyMessage; + /** + * 更新时间 + */ + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private Date updateTime; + /** + * 创建时间 + */ + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private Date createTime; +} diff --git a/system/system-biz/src/main/java/cn/iocoder/mall/system/biz/bo/smsSign/SmsSignBO.java b/system/system-biz/src/main/java/cn/iocoder/mall/system/biz/bo/smsSign/SmsSignBO.java new file mode 100644 index 000000000..e14e3f38e --- /dev/null +++ b/system/system-biz/src/main/java/cn/iocoder/mall/system/biz/bo/smsSign/SmsSignBO.java @@ -0,0 +1,40 @@ +package cn.iocoder.mall.system.biz.bo.smsSign; + +import lombok.Data; +import lombok.experimental.Accessors; + +/** + * 短信签名 + * + * @author Sin + * @time 2019/5/16 6:30 PM + */ +@Data +@Accessors(chain = true) +public class SmsSignBO { + + /** + * 编号 + */ + private Integer id; + /** + * 签名id 这个是第三方的 + */ + private Integer signId; + /** + * 签名名称 + */ + private String sign; + /** + * 审核状态 + * + * - 1、审核中 + * - 2、审核成功 + * - 3、审核失败 + */ + private Integer applyStatus; + /** + * 审核信息 + */ + private String applyMessage; +} diff --git a/system/system-biz/src/main/java/cn/iocoder/mall/system/biz/bo/smsTemplate/ListSmsTemplateBO.java b/system/system-biz/src/main/java/cn/iocoder/mall/system/biz/bo/smsTemplate/ListSmsTemplateBO.java new file mode 100644 index 000000000..0cbf83d58 --- /dev/null +++ b/system/system-biz/src/main/java/cn/iocoder/mall/system/biz/bo/smsTemplate/ListSmsTemplateBO.java @@ -0,0 +1,103 @@ +package cn.iocoder.mall.system.biz.bo.smsTemplate; + +import com.fasterxml.jackson.annotation.JsonFormat; +import lombok.Data; +import lombok.experimental.Accessors; + +import java.util.Date; + +/** + * sms page + * + * @author Sin + * @time 2019/5/19 4:23 PM + */ +@Data +@Accessors(chain = true) +public class ListSmsTemplateBO { + + /** + * 编号 + */ + private Integer id; + /** + * 模板编号 (第三方的) + */ + private Integer smsSignId; + /** + * 短信签名 id + */ + private String platform; + /** + * 短信模板 Code + */ + private String templateCode; + /** + * 短信模板 + */ + private String template; + /** + * 短信类型 + */ + private Integer smsType; + /** + * 审核状态 + *

+ * 1、审核中 + * 2、审核成功 + * 3、审核失败 + */ + private Integer applyStatus; + /** + * 审核信息 + */ + private String applyMessage; + /** + * 更新时间 + */ + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private Date updateTime; + /** + * 创建时间 + */ + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private Date createTime; + + /// + /// 关联字段 + + /** + * 签名信息 + */ + private Sign sign; + + + @Data + @Accessors(chain = true) + public static class Sign { + /** + * 编号 + */ + private Integer id; + /** + * 签名id 这个是第三方的 + */ + private String platformId; + /** + * 签名名称 + */ + private String sign; + /** + * 审核状态 + *

+ * - 1、审核中 + * - 2、审核成功 + * - 3、审核失败 + */ + private Integer applyStatus; + /** + * 审核信息 + */ + private String applyMessage; + } +} diff --git a/system/system-biz/src/main/java/cn/iocoder/mall/system/biz/bo/smsTemplate/SmsTemplateBO.java b/system/system-biz/src/main/java/cn/iocoder/mall/system/biz/bo/smsTemplate/SmsTemplateBO.java new file mode 100644 index 000000000..d19aab797 --- /dev/null +++ b/system/system-biz/src/main/java/cn/iocoder/mall/system/biz/bo/smsTemplate/SmsTemplateBO.java @@ -0,0 +1,44 @@ +package cn.iocoder.mall.system.biz.bo.smsTemplate; + +import lombok.Data; +import lombok.experimental.Accessors; + +/** + * 短信 template + * + * @author Sin + * @time 2019/5/16 7:41 PM + */ +@Data +@Accessors(chain = true) +public class SmsTemplateBO { + + /** + * 编号 + */ + private Integer id; + /** + * 模板编号 (第三方的) + */ + private Integer smsSignId; + /** + * 短信签名 id + */ + private String platformId; + /** + * 短信模板 + */ + private String template; + /** + * 审核状态 + * + * 1、审核中 + * 2、审核成功 + * 3、审核失败 + */ + private Integer applyStatus; + /** + * 审核信息 + */ + private String applyMessage; +} diff --git a/system/system-biz/src/main/java/cn/iocoder/mall/system/biz/convert/SmsSignConvert.java b/system/system-biz/src/main/java/cn/iocoder/mall/system/biz/convert/SmsSignConvert.java new file mode 100644 index 000000000..02a1cb837 --- /dev/null +++ b/system/system-biz/src/main/java/cn/iocoder/mall/system/biz/convert/SmsSignConvert.java @@ -0,0 +1,29 @@ +package cn.iocoder.mall.system.biz.convert; + +import cn.iocoder.mall.system.biz.bo.smsSign.ListSmsSignBO; +import cn.iocoder.mall.system.biz.bo.smsSign.SmsSignBO; +import cn.iocoder.mall.system.biz.dataobject.sms.SmsSignDO; +import org.mapstruct.Mapper; +import org.mapstruct.Mappings; +import org.mapstruct.factory.Mappers; + +import java.util.List; + +/** + * 短信 签名 + * + * @author Sin + * @time 2019/5/16 6:31 PM + */ +@Mapper +public interface SmsSignConvert { + + SmsSignConvert INSTANCE = Mappers.getMapper(SmsSignConvert.class); + + @Mappings({}) + SmsSignBO convert(SmsSignDO smsSignDO); + + @Mappings({}) + List convert(List smsSignDOList); + +} diff --git a/system/system-biz/src/main/java/cn/iocoder/mall/system/biz/convert/SmsTemplateConvert.java b/system/system-biz/src/main/java/cn/iocoder/mall/system/biz/convert/SmsTemplateConvert.java new file mode 100644 index 000000000..586fcc389 --- /dev/null +++ b/system/system-biz/src/main/java/cn/iocoder/mall/system/biz/convert/SmsTemplateConvert.java @@ -0,0 +1,32 @@ +package cn.iocoder.mall.system.biz.convert; + +import cn.iocoder.mall.system.biz.bo.smsTemplate.ListSmsTemplateBO; +import cn.iocoder.mall.system.biz.bo.smsTemplate.SmsTemplateBO; +import cn.iocoder.mall.system.biz.dataobject.sms.SmsSignDO; +import cn.iocoder.mall.system.biz.dataobject.sms.SmsTemplateDO; +import org.mapstruct.Mapper; +import org.mapstruct.Mappings; +import org.mapstruct.factory.Mappers; + +import java.util.List; + +/** + * 短信 template + * + * @author Sin + * @time 2019/5/16 7:43 PM + */ +@Mapper +public interface SmsTemplateConvert { + + SmsTemplateConvert INSTANCE = Mappers.getMapper(SmsTemplateConvert.class); + + @Mappings({}) + SmsTemplateBO convert(SmsTemplateDO smsTemplateDO); + + @Mappings({}) + List convert(List smsTemplateDOList); + + @Mappings({}) + List convertTemplateSign(List smsSignDOList); +} diff --git a/system/system-biz/src/main/java/cn/iocoder/mall/system/biz/dao/sms/SmsSendMapper.java b/system/system-biz/src/main/java/cn/iocoder/mall/system/biz/dao/sms/SmsSendMapper.java new file mode 100644 index 000000000..88475fab0 --- /dev/null +++ b/system/system-biz/src/main/java/cn/iocoder/mall/system/biz/dao/sms/SmsSendMapper.java @@ -0,0 +1,15 @@ +package cn.iocoder.mall.system.biz.dao.sms; + +import cn.iocoder.mall.system.biz.dataobject.sms.SmsSendLogDO; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import org.springframework.stereotype.Repository; + +/** + * 短信 + * + * @author Sin + * @time 2019/5/16 6:18 PM + */ +@Repository +public interface SmsSendMapper extends BaseMapper { +} diff --git a/system/system-biz/src/main/java/cn/iocoder/mall/system/biz/dao/sms/SmsSignMapper.java b/system/system-biz/src/main/java/cn/iocoder/mall/system/biz/dao/sms/SmsSignMapper.java new file mode 100644 index 000000000..e3f8ac542 --- /dev/null +++ b/system/system-biz/src/main/java/cn/iocoder/mall/system/biz/dao/sms/SmsSignMapper.java @@ -0,0 +1,15 @@ +package cn.iocoder.mall.system.biz.dao.sms; + +import cn.iocoder.mall.system.biz.dataobject.sms.SmsSignDO; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import org.springframework.stereotype.Repository; + +/** + * 短信 + * + * @author Sin + * @time 2019/5/16 6:18 PM + */ +@Repository +public interface SmsSignMapper extends BaseMapper { +} diff --git a/system/system-biz/src/main/java/cn/iocoder/mall/system/biz/dao/sms/SmsTemplateMapper.java b/system/system-biz/src/main/java/cn/iocoder/mall/system/biz/dao/sms/SmsTemplateMapper.java new file mode 100644 index 000000000..04770f2ff --- /dev/null +++ b/system/system-biz/src/main/java/cn/iocoder/mall/system/biz/dao/sms/SmsTemplateMapper.java @@ -0,0 +1,15 @@ +package cn.iocoder.mall.system.biz.dao.sms; + +import cn.iocoder.mall.system.biz.dataobject.sms.SmsTemplateDO; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import org.springframework.stereotype.Repository; + +/** + * 短信 template + * + * @author Sin + * @time 2019/5/16 6:18 PM + */ +@Repository +public interface SmsTemplateMapper extends BaseMapper { +} diff --git a/system/system-biz/src/main/java/cn/iocoder/mall/system/biz/dataobject/sms/SmsSendLogDO.java b/system/system-biz/src/main/java/cn/iocoder/mall/system/biz/dataobject/sms/SmsSendLogDO.java new file mode 100644 index 000000000..0a376d11c --- /dev/null +++ b/system/system-biz/src/main/java/cn/iocoder/mall/system/biz/dataobject/sms/SmsSendLogDO.java @@ -0,0 +1,37 @@ +package cn.iocoder.mall.system.biz.dataobject.sms; + +import cn.iocoder.common.framework.dataobject.BaseDO; +import lombok.Data; +import lombok.experimental.Accessors; + +/** + * 短信 client log + * + * @author Sin + * @time 2019/5/25 12:36 PM + */ +@Data +@Accessors(chain = true) +public class SmsSendLogDO extends BaseDO { + + /** + * 编号 + */ + private Integer id; + /** + * 短信模板 + */ + private Integer templateId; + /** + * 短信 + */ + private String template; + /** + * 参数 + */ + private String params; + /** + * 发送信息 + */ + private String message; +} diff --git a/system/system-biz/src/main/java/cn/iocoder/mall/system/biz/dataobject/sms/SmsSignDO.java b/system/system-biz/src/main/java/cn/iocoder/mall/system/biz/dataobject/sms/SmsSignDO.java new file mode 100644 index 000000000..e5fe58225 --- /dev/null +++ b/system/system-biz/src/main/java/cn/iocoder/mall/system/biz/dataobject/sms/SmsSignDO.java @@ -0,0 +1,48 @@ +package cn.iocoder.mall.system.biz.dataobject.sms; + +import cn.iocoder.common.framework.dataobject.DeletableDO; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; +import lombok.experimental.Accessors; + +/** + * 短信签名 + * + * 签名是短信发送前缀 如:【阿里云】、【小红书】 + * + * @author Sin + * @time 2019/5/16 12:28 PM + */ +@Data +@Accessors(chain = true) +@TableName("sms_sign") +public class SmsSignDO extends DeletableDO { + + /** + * 编号 + */ + private Integer id; + /** + * 签名名称 + */ + private String sign; + /** + * 平台 + * + * 1、云片 + * 2、阿里云 + */ + private Integer platform; + /** + * 审核状态 + * + * - 1、审核中 + * - 2、审核成功 + * - 10、审核失败 + */ + private Integer applyStatus; + /** + * 审核信息 + */ + private String applyMessage; +} diff --git a/system/system-biz/src/main/java/cn/iocoder/mall/system/biz/dataobject/sms/SmsTemplateDO.java b/system/system-biz/src/main/java/cn/iocoder/mall/system/biz/dataobject/sms/SmsTemplateDO.java new file mode 100644 index 000000000..1dc760ebf --- /dev/null +++ b/system/system-biz/src/main/java/cn/iocoder/mall/system/biz/dataobject/sms/SmsTemplateDO.java @@ -0,0 +1,59 @@ +package cn.iocoder.mall.system.biz.dataobject.sms; + +import cn.iocoder.common.framework.dataobject.DeletableDO; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; +import lombok.experimental.Accessors; + +/** + * 短信 模板 + * + * @author Sin + * @time 2019/5/16 12:31 PM + */ +@Data +@Accessors(chain = true) +@TableName("sms_template") +public class SmsTemplateDO extends DeletableDO { + + /** + * 编号 + */ + private Integer id; + /** + * 模板编号 (第三方的) + */ + private Integer smsSignId; + /** + * 模板 code(第三方平台 code) + */ + private String templateCode; + /** + * 短信签名 id + */ + private Integer platform; + /** + * 短信模板 + */ + private String template; + /** + * 短信类型 + * + * - 验证码类 + * - 通知类 + * - 营销类 + */ + private Integer smsType; + /** + * 审核状态 + * + * 1、审核中 + * 2、审核成功 + * 10、审核失败 + */ + private Integer applyStatus; + /** + * 审核信息 + */ + private String applyMessage; +} diff --git a/system/system-biz/src/main/java/cn/iocoder/mall/system/biz/dto/smsSign/AddSignDTO.java b/system/system-biz/src/main/java/cn/iocoder/mall/system/biz/dto/smsSign/AddSignDTO.java new file mode 100644 index 000000000..01fc7bfcb --- /dev/null +++ b/system/system-biz/src/main/java/cn/iocoder/mall/system/biz/dto/smsSign/AddSignDTO.java @@ -0,0 +1,21 @@ +package cn.iocoder.mall.system.biz.dto.smsSign; + +import lombok.Data; +import lombok.experimental.Accessors; + +import java.io.Serializable; + +/** + * 添加 sign + * + * author: sin + * time: 2020/4/20 11:10 上午 + */ +@Data +@Accessors(chain = true) +public class AddSignDTO implements Serializable { + + private String sign; + + private Integer platform; +} diff --git a/system/system-biz/src/main/java/cn/iocoder/mall/system/biz/dto/smsSign/ListSmsSignDTO.java b/system/system-biz/src/main/java/cn/iocoder/mall/system/biz/dto/smsSign/ListSmsSignDTO.java new file mode 100644 index 000000000..518fcdb13 --- /dev/null +++ b/system/system-biz/src/main/java/cn/iocoder/mall/system/biz/dto/smsSign/ListSmsSignDTO.java @@ -0,0 +1,28 @@ +package cn.iocoder.mall.system.biz.dto.smsSign; + +import cn.iocoder.common.framework.vo.PageParam; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import lombok.experimental.Accessors; + +/** + * page 短信模板 query + * + * @author Sin + * @time 2019/5/19 4:32 PM + */ +@Data +@Accessors(chain = true) +@ApiModel("短信服务查询") +public class ListSmsSignDTO extends PageParam { + + @ApiModelProperty("编号") + private Integer id; + + @ApiModelProperty("签名") + private String sign; + + @ApiModelProperty("申请状态") + private Integer applyStatus; +} diff --git a/system/system-biz/src/main/java/cn/iocoder/mall/system/biz/dto/smsSign/UpdateSignDTO.java b/system/system-biz/src/main/java/cn/iocoder/mall/system/biz/dto/smsSign/UpdateSignDTO.java new file mode 100644 index 000000000..8e45514f4 --- /dev/null +++ b/system/system-biz/src/main/java/cn/iocoder/mall/system/biz/dto/smsSign/UpdateSignDTO.java @@ -0,0 +1,24 @@ +package cn.iocoder.mall.system.biz.dto.smsSign; + +import lombok.Data; +import lombok.experimental.Accessors; + +import java.io.Serializable; + +/** + * 更新签名 + *

+ * author: sin + * time: 2020/4/20 11:05 上午 + */ +@Data +@Accessors(chain = true) +public class UpdateSignDTO implements Serializable { + + private Integer id; + + private String sign; + + private Integer platform; + +} diff --git a/system/system-biz/src/main/java/cn/iocoder/mall/system/biz/dto/smsTemplate/ListSmsTemplateDTO.java b/system/system-biz/src/main/java/cn/iocoder/mall/system/biz/dto/smsTemplate/ListSmsTemplateDTO.java new file mode 100644 index 000000000..86eaecb50 --- /dev/null +++ b/system/system-biz/src/main/java/cn/iocoder/mall/system/biz/dto/smsTemplate/ListSmsTemplateDTO.java @@ -0,0 +1,30 @@ +package cn.iocoder.mall.system.biz.dto.smsTemplate; + +import cn.iocoder.common.framework.vo.PageParam; +import lombok.Data; +import lombok.experimental.Accessors; + +import javax.validation.constraints.NotNull; + +/** + * page 短信模板 query + * + * @author Sin + * @time 2019/5/19 4:32 PM + */ +@Data +@Accessors(chain = true) +public class ListSmsTemplateDTO extends PageParam { + + @NotNull + private String id; + + @NotNull + private Integer smsSignId; + + @NotNull + private String template; + + @NotNull + private String applyStatus; +} diff --git a/system/system-biz/src/main/java/cn/iocoder/mall/system/biz/enums/AdminErrorCodeEnum.java b/system/system-biz/src/main/java/cn/iocoder/mall/system/biz/enums/AdminErrorCodeEnum.java new file mode 100644 index 000000000..db625e84a --- /dev/null +++ b/system/system-biz/src/main/java/cn/iocoder/mall/system/biz/enums/AdminErrorCodeEnum.java @@ -0,0 +1,85 @@ +package cn.iocoder.mall.system.biz.enums; + +/** + * 错误码枚举类 + * + * 管理员系统,使用 1-002-000-000 段 + */ +public enum AdminErrorCodeEnum { + + // ========== OAUTH2 模块 ========== + OAUTH2_UNKNOWN(1002001000, "未知错误"), // 预留 +// OAUTH2_INVALID_GRANT_BAD_CREDENTIALS(1001001001, "密码不正确"), // 暂时没用到 +// OAUTH2_INVALID_GRANT_USERNAME_NOT_FOUND(1001001002, "账号不存在"), // 暂时没用到 +// OAUTH2_INVALID_GRANT(1001001010, ""), // 预留 + OAUTH2_INVALID_TOKEN_NOT_FOUND(1002001011, "访问令牌不存在"), + OAUTH2_INVALID_TOKEN_EXPIRED(1002001012, "访问令牌已过期"), + OAUTH2_INVALID_TOKEN_INVALID(1002001013, "访问令牌已失效"), + OAUTH2_NOT_LOGIN(1002001015, "账号未登陆"), + OAUTH2_INVALID_TOKEN_ERROR_USER_TYPE(1002001016, "访问令牌用户类型不正确"), + OAUTH_INVALID_REFRESH_TOKEN_NOT_FOUND(1002001017, "刷新令牌不存在"), + OAUTH_INVALID_REFRESH_TOKEN_EXPIRED(1002001018, "访问令牌已过期"), + OAUTH_INVALID_REFRESH_TOKEN_INVALID(1002001019, "刷新令牌已失效"), + + // ========== 管理员模块 1002002000 ========== + ADMIN_USERNAME_NOT_REGISTERED(1002002000, "账号不存在"), + ADMIN_PASSWORD_ERROR(1002002001, "密码不正确"), + ADMIN_IS_DISABLE(1002002002, "账号被禁用"), + ADMIN_USERNAME_EXISTS(1002002002, "账号已经存在"), + ADMIN_STATUS_EQUALS(1002002003, "账号已经是该状态"), + ADMIN_DELETE_ONLY_DISABLE(1002002004, "只有关闭的账号才可以删除"), + ADMIN_ADMIN_STATUS_CAN_NOT_UPDATE(1002002005, "管理员的账号状态不允许变更"), + ADMIN_ASSIGN_ROLE_NOT_EXISTS(1002002006, "分配员工角色时,有角色不存在"), + ADMIN_INVALID_PERMISSION(1002002007, "没有该操作权限"), + ADMIN_ADMIN_CAN_NOT_UPDATE(1002002008, "管理员的账号不允许变更"), + ADMIN_DEMO_CAN_NOT_WRITE(1002002009, "演示账号,暂不允许写操作。欢迎加入我们的交流群:http://t.cn/EKEr5WE"), + + // ========== 资源模块 1002003000 ========== + RESOURCE_NAME_DUPLICATE(1002003000, "已经存在该名字的资源"), + RESOURCE_PARENT_NOT_EXISTS(1002003001, "父资源不存在"), + RESOURCE_PARENT_ERROR(1002003002, "不能设置自己为父资源"), + RESOURCE_NOT_EXISTS(1002003003, "资源不存在"), + RESOURCE_EXISTS_CHILDREN(1002003004, "存在子资源,无法删除"), + RESOURCE_PARENT_NOT_MENU(1002003005, "父资源的类型必须是菜单"), + + // ========== 角色模块 1002004000 ========== + ROLE_NOT_EXISTS(1002004000, "角色不存在"), + ROLE_ASSIGN_RESOURCE_NOT_EXISTS(1002004001, "分配角色资源时,有资源不存在"), + + // ========== 数据字典模块 1002005000 ========== + DATA_DICT_EXISTS(1002005000, "该数据字典已经存在"), + DATA_DICT_NOT_EXISTS(1002005001, "该数据字典不存在"), + + // ========== 短信模板 1002006000 ========== + SMS_PLATFORM_FAIL(1002006000, "短信平台调用失败【具体错误会动态替换】"), + SMS_SIGN_NOT_EXISTENT(1002006001, "短信签名不存在"), + SMS_SIGN_IS_EXISTENT(1002006002, "短信签名已存在"), + SMS_TEMPLATE_NOT_EXISTENT(1002006020, "短信签名不存在"), + SMS_TEMPLATE_IS_EXISTENT(1002006021, "短信签名不存在"), + SMS_NOT_SEND_CLIENT(1002006030, "短信没有发送的client"), + + // ========== 部门模块 1002007000 ========== + DEPT_SAME_LEVEL_NAME_EXITS(1002007001,"当前级别部门名字已存在"), + DEPT_PARENT_NOT_EXITS(1002007002,"父级部门不存在"), + DEPT_NOT_EXITS(1002007003, "当前部门不存在"), + DEPT_EXITS_CHILDREN(1002007004, "当前部门存在子部门"), + DEPT_PARENT_NOT_LEGAL(1002007005, "父级部门不合法"), + ; + + private final int code; + private final String message; + + AdminErrorCodeEnum(int code, String message) { + this.code = code; + this.message = message; + } + + public int getCode() { + return code; + } + + public String getMessage() { + return message; + } + +} diff --git a/system/system-biz/src/main/java/cn/iocoder/mall/system/biz/enums/package-info.java b/system/system-biz/src/main/java/cn/iocoder/mall/system/biz/enums/package-info.java new file mode 100644 index 000000000..9a1ed1792 --- /dev/null +++ b/system/system-biz/src/main/java/cn/iocoder/mall/system/biz/enums/package-info.java @@ -0,0 +1,5 @@ +/** + * author: sin + * time: 2020/4/20 10:12 上午 + */ +package cn.iocoder.mall.system.biz.enums; \ No newline at end of file diff --git a/system/system-biz/src/main/java/cn/iocoder/mall/system/biz/enums/sms/SmsApplyStatusEnum.java b/system/system-biz/src/main/java/cn/iocoder/mall/system/biz/enums/sms/SmsApplyStatusEnum.java new file mode 100644 index 000000000..80ce41876 --- /dev/null +++ b/system/system-biz/src/main/java/cn/iocoder/mall/system/biz/enums/sms/SmsApplyStatusEnum.java @@ -0,0 +1,31 @@ +package cn.iocoder.mall.system.biz.enums.sms; + +/** + * 短信审核状态 + * + * @author Sin + * @time 2019/5/16 12:48 PM + */ +public enum SmsApplyStatusEnum { + + CHECKING(1, "审核中"), + SUCCESS(2, "审核成功"), + FAIL(10, "审核失败"), + ; + + private final Integer value; + private final String name; + + SmsApplyStatusEnum(int code, String message) { + this.value = code; + this.name = message; + } + + public int getValue() { + return value; + } + + public String getName() { + return name; + } +} diff --git a/system/system-biz/src/main/java/cn/iocoder/mall/system/biz/enums/sms/SmsPlatformEnum.java b/system/system-biz/src/main/java/cn/iocoder/mall/system/biz/enums/sms/SmsPlatformEnum.java new file mode 100644 index 000000000..ce125e1ba --- /dev/null +++ b/system/system-biz/src/main/java/cn/iocoder/mall/system/biz/enums/sms/SmsPlatformEnum.java @@ -0,0 +1,41 @@ +package cn.iocoder.mall.system.biz.enums.sms; + +import cn.iocoder.common.framework.core.IntArrayValuable; + +import java.util.Arrays; + +/** + * 短信审核状态 + * + * @author Sin + * @time 2019/5/16 12:48 PM + */ +public enum SmsPlatformEnum implements IntArrayValuable { + + YunPian(1, "云片"), + AliYun(2, "阿里云"), + ; + + public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(SmsPlatformEnum::getValue).toArray(); + + private final Integer value; + private final String name; + + SmsPlatformEnum(Integer code, String message) { + this.value = code; + this.name = message; + } + + public Integer getValue() { + return value; + } + + public String getName() { + return name; + } + + @Override + public int[] array() { + return ARRAYS; + } +} diff --git a/system/system-biz/src/main/java/cn/iocoder/mall/system/biz/enums/sms/SmsTypeEnum.java b/system/system-biz/src/main/java/cn/iocoder/mall/system/biz/enums/sms/SmsTypeEnum.java new file mode 100644 index 000000000..29fafc9e8 --- /dev/null +++ b/system/system-biz/src/main/java/cn/iocoder/mall/system/biz/enums/sms/SmsTypeEnum.java @@ -0,0 +1,42 @@ +package cn.iocoder.mall.system.biz.enums.sms; + +import cn.iocoder.common.framework.core.IntArrayValuable; + +import java.util.Arrays; + +/** + * 短信审核状态 + * + * @author Sin + * @time 2019/5/16 12:48 PM + */ +public enum SmsTypeEnum implements IntArrayValuable { + + VERIFICATION_CODE(1, "验证码"), + NOTICE(2, "通知"), + MARKETING(3, "营销"), + ; + + public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(SmsTypeEnum::getValue).toArray(); + + private final Integer value; + private final String name; + + SmsTypeEnum(Integer code, String message) { + this.value = code; + this.name = message; + } + + public Integer getValue() { + return value; + } + + public String getName() { + return name; + } + + @Override + public int[] array() { + return ARRAYS; + } +} diff --git a/system/system-biz/src/main/java/cn/iocoder/mall/system/biz/service/sms/SmsClient.java b/system/system-biz/src/main/java/cn/iocoder/mall/system/biz/service/sms/SmsClient.java new file mode 100644 index 000000000..bb1eecaab --- /dev/null +++ b/system/system-biz/src/main/java/cn/iocoder/mall/system/biz/service/sms/SmsClient.java @@ -0,0 +1,64 @@ +package cn.iocoder.mall.system.biz.service.sms; + +import lombok.Data; +import lombok.experimental.Accessors; + +import java.util.List; +import java.util.Map; + +/** + * 短信平台 + * + * @author Sin + * @time 2019/5/16 6:33 PM + */ +public interface SmsClient { + + /** + * 短信发送 - 单个 + * + * @param mobile 手机号 + * @param sign 签名 + * @param templateCode 短信模板code + * @param template 短信模板 + * @param templateParams 短信模板 params + * @return 发送后信息 + */ + SendResult singleSend(String mobile, String sign, String templateCode, + String template, Map templateParams); + + /** + * 短信发送 - 批量 + * + * @param mobileList 手机号 + * @param sign 签名 + * @param templateCode 短信模板 code + * @param template 短信模板 + * @param templateParams 短信模板params + * @return 发送后信息 + */ + SendResult batchSend(List mobileList, String sign, String templateCode, + String template, Map templateParams); + + @Data + @Accessors(chain = true) + class SendResult { + + public static final int SUCCESS_CODE = 0; + public static final int ERROR_CODE = 1; + public static final String SUCCESS_MESSAGE = "SUCCESS"; + + /** + * 错误码 + */ + private Integer code; + /** + * 错误信息 + */ + private String message; + /** + * 是否成功 + */ + private Boolean isSuccess; + } +} diff --git a/system/system-biz/src/main/java/cn/iocoder/mall/system/biz/service/sms/SmsService.java b/system/system-biz/src/main/java/cn/iocoder/mall/system/biz/service/sms/SmsService.java new file mode 100644 index 000000000..69c3f698e --- /dev/null +++ b/system/system-biz/src/main/java/cn/iocoder/mall/system/biz/service/sms/SmsService.java @@ -0,0 +1,117 @@ +package cn.iocoder.mall.system.biz.service.sms; + +import cn.iocoder.common.framework.vo.PageResult; +import cn.iocoder.mall.system.biz.bo.smsSign.ListSmsSignBO; +import cn.iocoder.mall.system.biz.bo.smsTemplate.ListSmsTemplateBO; +import cn.iocoder.mall.system.biz.bo.smsSign.SmsSignBO; +import cn.iocoder.mall.system.biz.bo.smsTemplate.SmsTemplateBO; +import cn.iocoder.mall.system.biz.dto.smsSign.AddSignDTO; +import cn.iocoder.mall.system.biz.dto.smsSign.ListSmsSignDTO; +import cn.iocoder.mall.system.biz.dto.smsTemplate.ListSmsTemplateDTO; +import cn.iocoder.mall.system.biz.dto.smsSign.UpdateSignDTO; + +import java.util.List; +import java.util.Map; + +/** + * 短信服务 + * + * @author Sin + * @time 2019/5/16 9:54 AM + */ +public interface SmsService { + + /** + * 短信模板 - 分页 + * + * @param listSmsSignDTO + * @return + */ + PageResult listSmsSign(ListSmsSignDTO listSmsSignDTO); + + /** + * 短信模板 - 分页 + * + * @param listSmsTemplateDTO + * @return + */ + PageResult listSmsTemplate(ListSmsTemplateDTO listSmsTemplateDTO); + + /** + * 签名 - 创建 + * + * @param addSignDTO + */ + void addSign(AddSignDTO addSignDTO); + + /** + * 签名 - 获取 + * + * @param id + */ + SmsSignBO getSign(Integer id); + + /** + * 签名 - 更新 + * + * @param updateSignDTO + */ + void updateSign(UpdateSignDTO updateSignDTO); + + /** + * 签名 - 更新 + * + * @param id + */ + void deleteSign(Integer id); + + /** + * 模板 - 创建 + * + * @param smsSignId 选用的哪个签名 + * @param templateCode 模板code + * @param template 模板内容 + * @param platform 平台 + */ + void addTemplate(Integer smsSignId, String templateCode, + String template, Integer platform, Integer smsType); + + /** + * 模板 - 获取 + * + * @param id + */ + SmsTemplateBO getTemplate(Integer id, Integer platform); + + /** + * 模板 - 更新 + * + * @param id 模板id + * @param smsSignId 短期签名 + * @param template 模板内容 + * @param platform 短信平台 + */ + void updateTemplate(Integer id, Integer smsSignId, String templateCode, + String template, Integer platform, Integer smsType); + + /** + * 模板 - 删除 + * + * @param id + */ + void deleteTemplate(Integer id); + + /** + * 短信发送 - 单个 + * + * @return + */ + void singleSend(String mobile, Integer smsTemplateId, Map params); + + /** + * 短信发送 - 批量 + * + * @return + */ + void batchSend(List mobileList, Integer smsTemplateId, Map params); +} diff --git a/system/system-biz/src/main/java/cn/iocoder/mall/system/biz/service/sms/SmsServiceImpl.java b/system/system-biz/src/main/java/cn/iocoder/mall/system/biz/service/sms/SmsServiceImpl.java new file mode 100644 index 000000000..3f2ab55ba --- /dev/null +++ b/system/system-biz/src/main/java/cn/iocoder/mall/system/biz/service/sms/SmsServiceImpl.java @@ -0,0 +1,423 @@ +package cn.iocoder.mall.system.biz.service.sms; + +import cn.iocoder.common.framework.constant.DeletedStatusEnum; +import cn.iocoder.common.framework.exception.ServiceException; +import cn.iocoder.common.framework.vo.PageResult; +import cn.iocoder.mall.system.biz.bo.smsSign.ListSmsSignBO; +import cn.iocoder.mall.system.biz.bo.smsTemplate.ListSmsTemplateBO; +import cn.iocoder.mall.system.biz.bo.smsSign.SmsSignBO; +import cn.iocoder.mall.system.biz.bo.smsTemplate.SmsTemplateBO; +import cn.iocoder.mall.system.biz.convert.SmsSignConvert; +import cn.iocoder.mall.system.biz.convert.SmsTemplateConvert; +import cn.iocoder.mall.system.biz.dao.sms.SmsSendMapper; +import cn.iocoder.mall.system.biz.dao.sms.SmsSignMapper; +import cn.iocoder.mall.system.biz.dao.sms.SmsTemplateMapper; +import cn.iocoder.mall.system.biz.dataobject.sms.SmsSendLogDO; +import cn.iocoder.mall.system.biz.dataobject.sms.SmsSignDO; +import cn.iocoder.mall.system.biz.dataobject.sms.SmsTemplateDO; +import cn.iocoder.mall.system.biz.dto.smsSign.AddSignDTO; +import cn.iocoder.mall.system.biz.dto.smsSign.ListSmsSignDTO; +import cn.iocoder.mall.system.biz.dto.smsTemplate.ListSmsTemplateDTO; +import cn.iocoder.mall.system.biz.dto.smsSign.UpdateSignDTO; +import cn.iocoder.mall.system.biz.enums.AdminErrorCodeEnum; +import cn.iocoder.mall.system.biz.enums.sms.SmsApplyStatusEnum; +import cn.iocoder.mall.system.biz.enums.sms.SmsPlatformEnum; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.util.CollectionUtils; +import org.springframework.util.StringUtils; + +import java.util.*; +import java.util.stream.Collectors; + +/** + * 短信 + * + * @author Sin + * @time 2019/5/16 10:30 AM + */ +@Service +@org.apache.dubbo.config.annotation.Service(validation = "true", version = "${dubbo.provider.SmsService.version}") +public class SmsServiceImpl implements SmsService { + + @Autowired + private SmsSignMapper smsSignMapper; + @Autowired + private SmsTemplateMapper smsTemplateMapper; + @Autowired + private SmsSendMapper smsSendMapper; + + @Autowired + @Qualifier("smsYunPianClient") + private SmsClient smsYunPianClient; + @Autowired + @Qualifier("smsAliYunClient") + private SmsClient smsAliYunClient; + + @Override + public PageResult listSmsSign(ListSmsSignDTO queryDTO) { + QueryWrapper queryWrapper = new QueryWrapper<>(); + if (queryDTO.getApplyStatus() != null) { + queryWrapper.eq("apply_status", queryDTO.getApplyStatus()); + } + if (!StringUtils.isEmpty(queryDTO.getSign())) { + queryWrapper.like("sign", queryDTO.getSign()); + } + if (!StringUtils.isEmpty(queryDTO.getId())) { + queryWrapper.eq("id", queryDTO.getId()); + } + + Page page = new Page() + .setSize(queryDTO.getPageSize()) + .setCurrent(queryDTO.getPageNo()) + .setDesc("create_time"); + + IPage signPage = smsSignMapper.selectPage(page, queryWrapper); + List signList = SmsSignConvert.INSTANCE.convert(signPage.getRecords()); + return new PageResult().setList(signList).setTotal((int) signPage.getTotal()); + } + + @Override + public PageResult listSmsTemplate(ListSmsTemplateDTO listSmsTemplateDTO) { + QueryWrapper queryWrapper = new QueryWrapper<>(); + if (listSmsTemplateDTO.getApplyStatus() != null) { + queryWrapper.eq("apply_status", listSmsTemplateDTO.getApplyStatus()); + } + if (listSmsTemplateDTO.getSmsSignId() != null) { + queryWrapper.eq("sms_sign_id", listSmsTemplateDTO.getSmsSignId()); + } + if (!StringUtils.isEmpty(listSmsTemplateDTO.getTemplate())) { + queryWrapper.like("template", listSmsTemplateDTO.getTemplate()); + } + if (!StringUtils.isEmpty(listSmsTemplateDTO.getId())) { + queryWrapper.eq("id", listSmsTemplateDTO.getId()); + } + + Page page = new Page() + .setSize(listSmsTemplateDTO.getPageSize()) + .setCurrent(listSmsTemplateDTO.getPageNo()) + .setDesc("create_time"); + + IPage signPage = smsTemplateMapper.selectPage(page, queryWrapper); + + List templateList + = SmsTemplateConvert.INSTANCE.convert(signPage.getRecords()); + + if (CollectionUtils.isEmpty(templateList)) { + return new PageResult<>().setList(Collections.EMPTY_LIST).setTotal((int) signPage.getTotal()); + } + + // 获取 sign + Set smsSignIds = templateList.stream().map( + ListSmsTemplateBO::getSmsSignId).collect(Collectors.toSet()); + + List smsSignDOList = smsSignMapper.selectList( + new QueryWrapper().in("id", smsSignIds)); + + List signList = SmsTemplateConvert.INSTANCE.convertTemplateSign(smsSignDOList); + + Map smsSignDOMap = signList + .stream().collect(Collectors.toMap(ListSmsTemplateBO.Sign::getId, o -> o)); + + // 设置 sign + + templateList.forEach(template -> { + if (smsSignDOMap.containsKey(template.getSmsSignId())) { + template.setSign(smsSignDOMap.get(template.getSmsSignId())); + } + }); + + return new PageResult().setList(templateList).setTotal((int) signPage.getTotal()); + } + + @Override + @Transactional + public void addSign(AddSignDTO addSignDTO) { + + // 避免重复 + SmsSignDO smsSignDO = smsSignMapper.selectOne( + new QueryWrapper() + .eq("platform", addSignDTO.getPlatform()) + .eq("sign", addSignDTO.getSign()) + ); + + if (smsSignDO != null) { + throw new ServiceException(AdminErrorCodeEnum.SMS_SIGN_IS_EXISTENT.getCode(), + AdminErrorCodeEnum.SMS_SIGN_IS_EXISTENT.getMessage()); + } + + // 保存数据库 + smsSignMapper.insert( + (SmsSignDO) new SmsSignDO() + .setSign(addSignDTO.getSign()) + .setPlatform(addSignDTO.getPlatform()) + .setApplyStatus(SmsApplyStatusEnum.SUCCESS.getValue()) + .setDeleted(DeletedStatusEnum.DELETED_NO.getValue()) + .setUpdateTime(new Date()) + .setCreateTime(new Date()) + ); + } + + @Override + public SmsSignBO getSign(Integer signId) { + SmsSignDO smsSignDO = smsSignMapper.selectOne( + new QueryWrapper() + .eq("id", signId) + .eq("deleted", DeletedStatusEnum.DELETED_NO.getValue())); + + if (smsSignDO == null) { + throw new ServiceException(AdminErrorCodeEnum.SMS_SIGN_NOT_EXISTENT.getCode(), + AdminErrorCodeEnum.SMS_SIGN_NOT_EXISTENT.getMessage()); + } + + return SmsSignConvert.INSTANCE.convert(smsSignDO); + } + + @Override + @Transactional + public void updateSign(UpdateSignDTO updateSignDTO) { + // 避免重复 + SmsSignDO smsSignDO = smsSignMapper.selectOne( + new QueryWrapper() + .eq("sign", updateSignDTO.getSign()) + .eq("platform", updateSignDTO.getPlatform())); + + if (smsSignDO != null) { + throw new ServiceException(AdminErrorCodeEnum.SMS_SIGN_IS_EXISTENT.getCode(), + AdminErrorCodeEnum.SMS_SIGN_IS_EXISTENT.getMessage()); + } + + // 更新 + smsSignMapper.update( + (SmsSignDO) new SmsSignDO() + .setSign(updateSignDTO.getSign()) + .setPlatform(updateSignDTO.getPlatform()) + .setUpdateTime(new Date()), + new QueryWrapper().eq("id", updateSignDTO.getId()) + ); + } + + @Override + public void deleteSign(Integer id) { + SmsSignDO smsSignDO = smsSignMapper.selectOne( + new QueryWrapper() + .eq("id", id)); + + if (smsSignDO == null) { + throw new ServiceException(AdminErrorCodeEnum.SMS_SIGN_NOT_EXISTENT.getCode(), + AdminErrorCodeEnum.SMS_SIGN_NOT_EXISTENT.getMessage()); + } + + // 更新 deleted 为 YES + smsSignMapper.delete(new UpdateWrapper() + .set("deleted", DeletedStatusEnum.DELETED_YES.getName()) + .eq("id", id) + ); + } + + @Override + @Transactional + public void addTemplate(Integer smsSignId, String templateCode, + String template, Integer platform, Integer smsType) { + + SmsSignDO smsSignDO = smsSignMapper.selectOne( + new QueryWrapper().eq("id", smsSignId)); + + if (smsSignDO == null) { + throw new ServiceException(AdminErrorCodeEnum.SMS_SIGN_NOT_EXISTENT.getCode(), + AdminErrorCodeEnum.SMS_SIGN_NOT_EXISTENT.getMessage()); + } + + // 保存数据库 + smsTemplateMapper.insert( + (SmsTemplateDO) new SmsTemplateDO() + .setId(null) + .setSmsSignId(smsSignId) + .setTemplateCode(templateCode) + .setTemplate(template) + .setPlatform(platform) + .setSmsType(smsType) + .setApplyStatus(SmsApplyStatusEnum.SUCCESS.getValue()) + .setApplyMessage("") + .setDeleted(DeletedStatusEnum.DELETED_NO.getValue()) + .setCreateTime(new Date()) + ); + } + + @Override + public SmsTemplateBO getTemplate(Integer id, Integer platform) { + SmsTemplateDO smsTemplateDO = smsTemplateMapper.selectOne( + new QueryWrapper() + .eq("platform", platform) + .eq("id", id)); + + if (smsTemplateDO == null) { + throw new ServiceException(AdminErrorCodeEnum.SMS_TEMPLATE_NOT_EXISTENT.getCode(), + AdminErrorCodeEnum.SMS_TEMPLATE_NOT_EXISTENT.getMessage()); + } + + return SmsTemplateConvert.INSTANCE.convert(smsTemplateDO); + } + + @Override + @Transactional + public void updateTemplate(Integer id, Integer smsSignId, String templateCode, + String template, Integer platform, Integer smsType) { + SmsTemplateDO smsTemplateDO = smsTemplateMapper.selectOne( + new QueryWrapper().eq("id", id)); + + if (smsTemplateDO == null) { + throw new ServiceException(AdminErrorCodeEnum.SMS_TEMPLATE_NOT_EXISTENT.getCode(), + AdminErrorCodeEnum.SMS_TEMPLATE_NOT_EXISTENT.getMessage()); + } + + SmsSignDO smsSignDO = smsSignMapper.selectOne( + new QueryWrapper().eq("id", smsTemplateDO.getSmsSignId())); + + if (smsSignDO == null) { + throw new ServiceException(AdminErrorCodeEnum.SMS_SIGN_NOT_EXISTENT.getCode(), + AdminErrorCodeEnum.SMS_SIGN_NOT_EXISTENT.getMessage()); + } + + smsTemplateMapper.update( + (SmsTemplateDO) new SmsTemplateDO() + .setSmsSignId(smsSignId) + .setTemplateCode(templateCode) + .setTemplate(template) + .setPlatform(platform) + .setSmsType(smsType) + .setUpdateTime(new Date()), + new QueryWrapper().eq("id", id) + ); + } + + @Override + @Transactional + public void deleteTemplate(Integer id) { + SmsTemplateDO smsTemplateDO = smsTemplateMapper.selectOne( + new QueryWrapper().eq("id", id)); + + if (smsTemplateDO == null + || smsTemplateDO.getDeleted().equals(DeletedStatusEnum.DELETED_YES.getValue())) { + throw new ServiceException(AdminErrorCodeEnum.SMS_TEMPLATE_NOT_EXISTENT.getCode(), + AdminErrorCodeEnum.SMS_TEMPLATE_NOT_EXISTENT.getMessage()); + } + + // 删除 数据库模板 + SmsTemplateDO updateTemplate =new SmsTemplateDO(); + updateTemplate.setDeleted(DeletedStatusEnum.DELETED_YES.getValue()); + smsTemplateMapper.delete( + new UpdateWrapper() + .set("deleted", DeletedStatusEnum.DELETED_YES) + .eq("id", id)); + } + + @Override + public void singleSend(String mobile, Integer smsTemplateId, Map params) { + SmsTemplateDO smsTemplateDO = smsTemplateMapper.selectOne( + new QueryWrapper().eq("id", smsTemplateId)); + + if (smsTemplateDO == null + || smsTemplateDO.getDeleted().equals(DeletedStatusEnum.DELETED_YES.getValue())) { + throw new ServiceException(AdminErrorCodeEnum.SMS_TEMPLATE_NOT_EXISTENT.getCode(), + AdminErrorCodeEnum.SMS_TEMPLATE_NOT_EXISTENT.getMessage()); + } + + SmsSignDO smsSignDO = smsSignMapper.selectOne( + new QueryWrapper().eq("id", smsTemplateDO.getSmsSignId())); + + if (smsSignDO == null) { + throw new ServiceException(AdminErrorCodeEnum.SMS_SIGN_NOT_EXISTENT.getCode(), + AdminErrorCodeEnum.SMS_SIGN_NOT_EXISTENT.getMessage()); + } + + // 获取 client + SmsClient smsClient = getSmsClient(smsTemplateDO.getPlatform()); + // 发送短信 + SmsClient.SendResult sendResult = smsClient.singleSend(mobile, smsSignDO.getSign(), + smsTemplateDO.getTemplateCode(), smsTemplateDO.getTemplate(), params); + + // 添加日志 + smsSendMapper.insert( + (SmsSendLogDO) new SmsSendLogDO() + .setTemplateId(smsTemplateDO.getId()) + .setTemplate(smsTemplateDO.getTemplate()) + .setMessage(sendResult.getMessage()) + .setCreateTime(new Date()) + ); + } + + @Override + public void batchSend(List mobileList, Integer smsTemplateId, Map params) { + SmsTemplateDO smsTemplateDO = smsTemplateMapper.selectOne( + new QueryWrapper().eq("id", smsTemplateId)); + + if (smsTemplateDO == null + || smsTemplateDO.getDeleted().equals(DeletedStatusEnum.DELETED_YES.getValue())) { + throw new ServiceException(AdminErrorCodeEnum.SMS_TEMPLATE_NOT_EXISTENT.getCode(), + AdminErrorCodeEnum.SMS_TEMPLATE_NOT_EXISTENT.getMessage()); + } + + SmsSignDO smsSignDO = smsSignMapper.selectOne( + new QueryWrapper().eq("id", smsTemplateDO.getSmsSignId())); + + if (smsSignDO == null) { + // 添加日志 + smsSendMapper.insert( + (SmsSendLogDO) new SmsSendLogDO() + .setTemplateId(smsTemplateDO.getId()) + .setTemplate(smsTemplateDO.getTemplate()) + .setMessage("发送成功!") + .setCreateTime(new Date()) + ); + + throw new ServiceException(AdminErrorCodeEnum.SMS_SIGN_NOT_EXISTENT.getCode(), + AdminErrorCodeEnum.SMS_SIGN_NOT_EXISTENT.getMessage()); + } + + // 获取 client + SmsClient smsClient = getSmsClient(smsTemplateDO.getPlatform()); + + // 发送短信 + SmsClient.SendResult sendResult = smsClient.batchSend(mobileList, smsSignDO.getSign(), + smsTemplateDO.getTemplateCode(), smsTemplateDO.getTemplate(), params); + + // 添加日志 + smsSendMapper.insert( + (SmsSendLogDO) new SmsSendLogDO() + .setTemplateId(smsTemplateDO.getId()) + .setTemplate(smsTemplateDO.getTemplate()) + .setMessage(sendResult.getMessage()) + .setCreateTime(new Date()) + ); + } + + /** + * 获取 sms 对于的 client + * + * @param platform + * @return + */ + private SmsClient getSmsClient(Integer platform) { + SmsClient smsClient = null; + if (SmsPlatformEnum.YunPian.getValue().equals(platform)) { + smsClient = smsYunPianClient; + } else if (SmsPlatformEnum.AliYun.getValue().equals(platform)) { + smsClient = smsAliYunClient; + } + + if (smsClient == null) { + throw new ServiceException( + AdminErrorCodeEnum.SMS_NOT_SEND_CLIENT.getCode(), + AdminErrorCodeEnum.SMS_NOT_SEND_CLIENT.getMessage()); + } + + return smsClient; + } +} diff --git a/system/system-biz/src/main/java/cn/iocoder/mall/system/biz/service/sms/client/SmsAliYunClient.java b/system/system-biz/src/main/java/cn/iocoder/mall/system/biz/service/sms/client/SmsAliYunClient.java new file mode 100644 index 000000000..06272d09c --- /dev/null +++ b/system/system-biz/src/main/java/cn/iocoder/mall/system/biz/service/sms/client/SmsAliYunClient.java @@ -0,0 +1,163 @@ +package cn.iocoder.mall.system.biz.service.sms.client; + +import cn.iocoder.mall.system.biz.service.sms.SmsClient; +import com.alibaba.fastjson.JSON; +import com.aliyuncs.CommonRequest; +import com.aliyuncs.CommonResponse; +import com.aliyuncs.DefaultAcsClient; +import com.aliyuncs.IAcsClient; +import com.aliyuncs.exceptions.ClientException; +import com.aliyuncs.http.MethodType; +import com.aliyuncs.profile.DefaultProfile; +import lombok.Data; +import lombok.experimental.Accessors; +import org.apache.commons.lang3.exception.ExceptionUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Component; + +import java.util.Collections; +import java.util.List; +import java.util.Map; + +/** + * 短信 AliYun client + * + * @author Sin + * @time 2019/5/25 12:28 PM + */ +@Component +public class SmsAliYunClient implements SmsClient { + + private static final Logger LOGGER = LoggerFactory.getLogger(SmsAliYunClient.class); + + private static final String DOMAIN = "dysmsapi.aliyuncs.com"; + private static final String SUCCESS_CODE = "OK"; + private static final String SUCCESS_MESSAGE = "OK"; + /** + * 阿里云短信 - 批量推送最大数 500,支持 1000 + */ + private static final int MAX_BATCH_SIZE = 500; + + @Value("${sms.aliYun.accessKeyId?:'default_value'}") + private String accessKeyId; + @Value("${sms.aliYun.accessSecret?:'default_value'}") + private String accessSecret; + + @Data + @Accessors(chain = true) + public static class Result { + /** + * 发送回执ID,可根据该ID在接口QuerySendDetails中查询具体的发送状态。 + */ + private String BizId; + /** + * 请求状态码。 + * + * - OK 蔡成功 + */ + private String Code; + /** + * 状态码的描述。 + */ + private String Message; + /** + * 请求ID。 + */ + private String RequestId; + } + + @Override + public SendResult singleSend(String mobile, String sign, String templateCode, + String template, Map templateParams) { + // params + CommonRequest request = new CommonRequest(); + request.setMethod(MethodType.POST); + request.setDomain(DOMAIN); + request.setVersion("2017-05-25"); + request.setAction("SendSms"); + request.putQueryParameter("PhoneNumbers", mobile); + request.putQueryParameter("SignName", sign); + request.putQueryParameter("TemplateCode", templateCode); + request.putQueryParameter("TemplateParam", JSON.toJSONString(templateParams)); + + // 发送请求 + return doSend(request); + } + + @Override + public SendResult batchSend(List mobileList, String sign, String templateCode, + String template, Map templateParams) { + + // 最大发送数为 1000,我们设置为 500 个, 分段发送 + int maxSendSize = MAX_BATCH_SIZE; + int maxSendSizeCount = mobileList.size() % maxSendSize == 0 + ? mobileList.size() / maxSendSize + : mobileList.size() / maxSendSize + 1; + + SendResult sendResult = null; + for (int i = 0; i < maxSendSizeCount; i++) { + // 分批发送 + List batchSendMobile = mobileList + .subList(i * maxSendSize, (i + 1) * maxSendSize); + + // params + CommonRequest request = new CommonRequest(); + request.setMethod(MethodType.POST); + request.setDomain(DOMAIN); + request.setVersion("2017-05-25"); + request.setAction("SendBatchSms"); + request.putQueryParameter("PhoneNumberJson", JSON.toJSONString(batchSendMobile)); + request.putQueryParameter("SignNameJson", JSON.toJSONString(Collections.singletonList(sign))); + request.putQueryParameter("TemplateCode", templateCode); + request.putQueryParameter("TemplateParamJson", JSON.toJSONString(Collections.singletonList(templateParams))); + + // 发送请求 + sendResult = doSend(request); + } + return sendResult; + } + + private SendResult doSend(CommonRequest request) { + // 获取 client + IAcsClient client = getClient(); + try { + CommonResponse response = client.getCommonResponse(request); + Result result = JSON.parseObject(response.getData(), Result.class); + if (!SUCCESS_CODE.equals(result.getCode())) { + + LOGGER.info("发送验证码失败 params {} res {}", JSON.toJSON(request), JSON.toJSON(result)); + + // 错误发送失败 + return new SendResult() + .setIsSuccess(false) + .setCode(SendResult.ERROR_CODE) + .setMessage(result.getMessage()); + } else { + LOGGER.info("发送验证码失败 params {} res", JSON.toJSON(request), JSON.toJSON(result)); + + // 发送成功 + return new SendResult() + .setIsSuccess(true) + .setCode(SendResult.SUCCESS_CODE) + .setMessage(result.getMessage()); + } + } catch (ClientException e) { + LOGGER.error("发送验证码异常 {}", ExceptionUtils.getMessage(e)); + return new SendResult() + .setIsSuccess(false) + .setCode(SendResult.ERROR_CODE) + .setMessage(ExceptionUtils.getMessage(e)); + } + } + + /** + * 获取 client + * + * @return + */ + private IAcsClient getClient() { + return new DefaultAcsClient(DefaultProfile.getProfile("default", accessKeyId, accessSecret)); + } +} diff --git a/system/system-biz/src/main/java/cn/iocoder/mall/system/biz/service/sms/client/SmsYunPianClient.java b/system/system-biz/src/main/java/cn/iocoder/mall/system/biz/service/sms/client/SmsYunPianClient.java new file mode 100644 index 000000000..fe633f7c0 --- /dev/null +++ b/system/system-biz/src/main/java/cn/iocoder/mall/system/biz/service/sms/client/SmsYunPianClient.java @@ -0,0 +1,242 @@ +package cn.iocoder.mall.system.biz.service.sms.client; + +import cn.iocoder.common.framework.exception.ServiceException; +import cn.iocoder.mall.system.biz.enums.AdminErrorCodeEnum; +import cn.iocoder.mall.system.biz.service.sms.SmsClient; +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; +import org.apache.http.HttpEntity; +import org.apache.http.NameValuePair; +import org.apache.http.client.entity.UrlEncodedFormEntity; +import org.apache.http.client.methods.CloseableHttpResponse; +import org.apache.http.client.methods.HttpPost; +import org.apache.http.impl.client.CloseableHttpClient; +import org.apache.http.impl.client.HttpClients; +import org.apache.http.message.BasicNameValuePair; +import org.apache.http.util.EntityUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Component; +import org.springframework.util.CollectionUtils; + +import java.util.ArrayList; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; + +/** + * 云片 短信平台 + * + * @author Sin + * @time 2019/5/16 6:34 PM + */ +@Component +public class SmsYunPianClient implements SmsClient { + + protected static final Logger LOGGER = LoggerFactory.getLogger(SmsYunPianClient.class); + + private static final int SUCCESS_CODE = 0; + private static final String SUCCESS_MESSAGE = "SUCCESS"; + + /** + * 云片短信 - 批量推送最大数 500,支持 1000 + */ + private static final int MAX_BATCH_SIZE = 500; + /** + * 模板 - 参数拼接 + */ + private static final String PARAM_TEMPLATE = "#%s#"; + /** + * 模板 - 签名拼接 + */ + private static final String SIGN_TEMPLATE = "【%s】%s"; + + /** + * 签名 - 添加 + */ + private static final String URL_SIGN_ADD = "https://sms.yunpian.com/v2/sign/add.json"; + /** + * 签名 - 获取 + */ + private static final String URL_SIGN_GET = "https://sms.yunpian.com/v2/sign/get.json"; + /** + * 签名 - 更新 + */ + private static final String URL_SIGN_UPDATE = "https://sms.yunpian.com/v2/sign/update.json"; + /** + * 模板 - 添加 + */ + private static final String URL_TEMPLATE_ADD = "https://sms.yunpian.com/v2/tpl/add.json"; + /** + * 模板 - 获取 + */ + private static final String URL_TEMPLATE_GET = "https://sms.yunpian.com/v2/tpl/get.json"; + /** + * 模板 - 更新 + */ + private static final String URL_TEMPLATE_UPDATE = "https://sms.yunpian.com/v2/tpl/update.json"; + /** + * 模板 - 删除 + */ + private static final String URL_TEMPLATE_DELETE = "https://sms.yunpian.com/v2/tpl/del.json"; + /** + * 短信发送 - 单个 + */ + private static final String URL_SEND_SINGLE = "https://sms.yunpian.com/v2/sms/single_send.json"; + /** + * 短信发送 - 批量 + */ + private static final String URL_SEND_BATCH = "https://sms.yunpian.com/v2/sms/batch_send.json"; + + + //编码格式。发送编码格式统一用UTF-8 + private static String ENCODING = "UTF-8"; + + @Value("${sms.yunPian.apiKey?:'default_value'}") + private String apiKey; + + @Override + public SendResult singleSend(String mobile, String sign, String templateCode, String template, Map templateParams) { + // build 模板 + template = buildTemplate(sign, template, templateParams); + + // 请求参数 + Map params = new LinkedHashMap<>(); + params.put("apikey", apiKey); + params.put("mobile", mobile); + params.put("text", template); + // TODO: 2019/5/19 sin 运营商发送报告 回调 + // params.put("callback_url", template); + String result = post(URL_SEND_SINGLE, params); + JSONObject jsonObject = JSON.parseObject(result); + if (jsonObject.containsKey("code") + && !(jsonObject.getInteger("code") == SUCCESS_CODE)) { + throw new ServiceException(AdminErrorCodeEnum.SMS_PLATFORM_FAIL.getCode(), + jsonObject.getString("detail")); + } + + return new SendResult() + .setIsSuccess(SUCCESS_CODE == jsonObject.getInteger("code")) + .setCode(jsonObject.getInteger("code")) + .setMessage(jsonObject.getString("detail")); + } + + @Override + public SendResult batchSend(List mobileList, String sign, + String templateCode, String template, + Map templateParams) { + // build 模板 + template = buildTemplate(sign, template, templateParams); + + // 最大发送数为 1000,我们设置为 500 个, 分段发送 + int maxSendSize = MAX_BATCH_SIZE; + int maxSendSizeCount = mobileList.size() % maxSendSize == 0 + ? mobileList.size() / maxSendSize + : mobileList.size() / maxSendSize + 1; + int j = 0; + int j2 = mobileList.size(); + + for (int i = 0; i < maxSendSizeCount; i++) { + StringBuffer sendMobileStr = new StringBuffer(); + for (int k = j; k < j2; k++) { + sendMobileStr.append(","); + sendMobileStr.append(mobileList.get(k)); + } + + String dividedMobile = sendMobileStr.toString().substring(1); + + // 发送手机号 + Map params = new LinkedHashMap<>(); + params.put("apikey", apiKey); + params.put("mobile", dividedMobile); + params.put("text", template); + // TODO: 2019/5/19 sin 运营商发送报告 回调 + // params.put("callback_url", template); + String result = post(URL_SEND_BATCH, params); + JSONObject jsonObject = JSON.parseObject(result); + if (jsonObject.containsKey("code") + && !(jsonObject.getInteger("code") == SUCCESS_CODE)) { + throw new ServiceException(AdminErrorCodeEnum.SMS_PLATFORM_FAIL.getCode(), + jsonObject.getString("detail")); + } + + // 用于递增 maxSendSize + j = j2; + j2 = j + maxSendSize; + } + + return new SendResult() + .setIsSuccess(true) + .setCode(SUCCESS_CODE) + .setMessage(SUCCESS_MESSAGE); + } + + /** + * 构建模板 + * + * @param sign + * @param template + * @param templateParams + * @return + */ + private static String buildTemplate(String sign, String template, + Map templateParams) { + + if (CollectionUtils.isEmpty(templateParams)) { + return template; + } + + for (Map.Entry entry : templateParams.entrySet()) { + String paramsKey = entry.getKey(); + String value = entry.getValue(); + String paramPlace = String.format(PARAM_TEMPLATE, paramsKey); + template = template.replaceAll(paramPlace, value); + } + + template = String.format(SIGN_TEMPLATE, sign, template); + return template; + } + + /** + * 基于HttpClient 4.3的通用POST方法 + * + * @param url 提交的URL + * @param paramsMap 提交<参数,值>Map + * @return 提交响应 + */ + + public static String post(String url, Map paramsMap) { + CloseableHttpClient client = HttpClients.createDefault(); + String responseText = ""; + CloseableHttpResponse response = null; + try { + HttpPost method = new HttpPost(url); + if (paramsMap != null) { + List paramList = new ArrayList<>(); + for (Map.Entry param : paramsMap.entrySet()) { + NameValuePair pair = new BasicNameValuePair(param.getKey(), + param.getValue()); + paramList.add(pair); + } + method.setEntity(new UrlEncodedFormEntity(paramList, ENCODING)); + } + response = client.execute(method); + HttpEntity entity = response.getEntity(); + if (entity != null) { + responseText = EntityUtils.toString(entity, ENCODING); + } + } catch (Exception e) { + e.printStackTrace(); + } finally { + try { + response.close(); + } catch (Exception e) { + e.printStackTrace(); + } + } + + LOGGER.debug("云片短信平台 res: {}", responseText); + return responseText; + } +} diff --git a/system/system-rest/src/main/java/cn/iocoder/mall/system/rest/controller/admin/AdminsSmsSignController.java b/system/system-rest/src/main/java/cn/iocoder/mall/system/rest/controller/admin/AdminsSmsSignController.java new file mode 100644 index 000000000..1359d88ee --- /dev/null +++ b/system/system-rest/src/main/java/cn/iocoder/mall/system/rest/controller/admin/AdminsSmsSignController.java @@ -0,0 +1,57 @@ +package cn.iocoder.mall.system.rest.controller.admin; + +import cn.iocoder.common.framework.vo.CommonResult; +import cn.iocoder.common.framework.vo.PageResult; +import cn.iocoder.mall.system.biz.bo.smsSign.ListSmsSignBO; +import cn.iocoder.mall.system.biz.dto.smsSign.ListSmsSignDTO; +import cn.iocoder.mall.system.biz.service.sms.SmsService; +import cn.iocoder.mall.system.rest.convert.sms.AdminsSmsConvert; +import cn.iocoder.mall.system.rest.request.smsSign.AddSignRequest; +import cn.iocoder.mall.system.rest.request.smsSign.UpdateSignRequest; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +/** + * 短信服务 + * + * @author Sin + * @time 2019/5/26 12:26 PM + */ +@RestController +@RequestMapping("admins/sms/sign") +@Api("短信服务(签名)") +public class AdminsSmsSignController { + + @Autowired + private SmsService smsService; + + @GetMapping("page") + @ApiOperation("签名-page") + public CommonResult> pageSign(@Validated ListSmsSignDTO listSmsSignDTO) { + return CommonResult.success(smsService.listSmsSign(listSmsSignDTO)); + } + + @PostMapping("add") + @ApiOperation("签名-添加") + public CommonResult addSign(@RequestBody AddSignRequest addSignRequest) { + smsService.addSign(AdminsSmsConvert.INSTANCE.convert(addSignRequest)); + return CommonResult.success(null); + } + + @PutMapping("update") + @ApiOperation("签名-更新") + public CommonResult updateSign(@RequestBody UpdateSignRequest updateSignRequest) { + smsService.updateSign(AdminsSmsConvert.INSTANCE.convert(updateSignRequest)); + return CommonResult.success(null); + } + + @DeleteMapping("deleted") + @ApiOperation("签名-删除") + public CommonResult deletedSign(@RequestParam("id") Integer id) { + smsService.deleteSign(id); + return CommonResult.success(null); + } +} diff --git a/system/system-rest/src/main/java/cn/iocoder/mall/system/rest/controller/admin/AdminsSmsTemplateController.java b/system/system-rest/src/main/java/cn/iocoder/mall/system/rest/controller/admin/AdminsSmsTemplateController.java new file mode 100644 index 000000000..853d1b5be --- /dev/null +++ b/system/system-rest/src/main/java/cn/iocoder/mall/system/rest/controller/admin/AdminsSmsTemplateController.java @@ -0,0 +1,68 @@ +package cn.iocoder.mall.system.rest.controller.admin; + +import cn.iocoder.common.framework.vo.CommonResult; +import cn.iocoder.common.framework.vo.PageResult; +import cn.iocoder.mall.system.biz.bo.smsTemplate.ListSmsTemplateBO; +import cn.iocoder.mall.system.biz.dto.smsTemplate.ListSmsTemplateDTO; +import cn.iocoder.mall.system.biz.service.sms.SmsService; +import cn.iocoder.mall.system.rest.convert.sms.AdminsSmsConvert; +import cn.iocoder.mall.system.rest.request.smsTemplate.AddSmsTemplateRequest; +import cn.iocoder.mall.system.rest.request.smsTemplate.ListSmsTemplateRequest; +import cn.iocoder.mall.system.rest.request.smsTemplate.UpdateSmsTemplateRequest; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +/** + * 短信服务 + * + * @author Sin + * @time 2019/5/26 12:26 PM + */ +@RestController +@RequestMapping("admins/sms/template") +@Api("短信服务(短信模板)") +public class AdminsSmsTemplateController { + + @Autowired + private SmsService smsService; + + @PostMapping("page") + @ApiOperation("短信模板-page") + public CommonResult> pageSign(@RequestBody ListSmsTemplateRequest request) { + return CommonResult.success(smsService.listSmsTemplate(AdminsSmsConvert.INSTANCE.convert(request))); + } + + @PostMapping("add") + @ApiOperation("短信模板-添加") + public CommonResult addSign(@RequestBody AddSmsTemplateRequest smsTemplateAddPO) { + smsService.addTemplate( + smsTemplateAddPO.getSmsSignId(), + smsTemplateAddPO.getTemplateCode(), + smsTemplateAddPO.getTemplate(), + smsTemplateAddPO.getPlatform(), + smsTemplateAddPO.getSmsType()); + return CommonResult.success(null); + } + + @PutMapping("update") + @ApiOperation("短信模板-更新") + public CommonResult updateSign(@RequestBody UpdateSmsTemplateRequest smsTemplateUpdatePO) { + smsService.updateTemplate( + smsTemplateUpdatePO.getId(), + smsTemplateUpdatePO.getSmsSignId(), + smsTemplateUpdatePO.getTemplateCode(), + smsTemplateUpdatePO.getTemplate(), + smsTemplateUpdatePO.getPlatform(), + smsTemplateUpdatePO.getSmsType()); + return CommonResult.success(null); + } + + @DeleteMapping("deleted") + @ApiOperation("短信模板-删除") + public CommonResult deletedSign(@RequestParam("id") Integer id) { + smsService.deleteTemplate(id); + return CommonResult.success(null); + } +} diff --git a/system/system-rest/src/main/java/cn/iocoder/mall/system/rest/convert/sms/AdminsSmsConvert.java b/system/system-rest/src/main/java/cn/iocoder/mall/system/rest/convert/sms/AdminsSmsConvert.java new file mode 100644 index 000000000..d3d559439 --- /dev/null +++ b/system/system-rest/src/main/java/cn/iocoder/mall/system/rest/convert/sms/AdminsSmsConvert.java @@ -0,0 +1,32 @@ +package cn.iocoder.mall.system.rest.convert.sms; + +import cn.iocoder.mall.system.biz.dto.smsSign.AddSignDTO; +import cn.iocoder.mall.system.biz.dto.smsSign.UpdateSignDTO; +import cn.iocoder.mall.system.biz.dto.smsTemplate.ListSmsTemplateDTO; +import cn.iocoder.mall.system.rest.request.smsSign.AddSignRequest; +import cn.iocoder.mall.system.rest.request.smsSign.UpdateSignRequest; +import cn.iocoder.mall.system.rest.request.smsTemplate.ListSmsTemplateRequest; +import org.mapstruct.Mapper; +import org.mapstruct.Mappings; +import org.mapstruct.factory.Mappers; + +/** + * sms admins convert + * + * author: sin + * time: 2020/4/20 11:07 上午 + */ +@Mapper +public interface AdminsSmsConvert { + + AdminsSmsConvert INSTANCE = Mappers.getMapper(AdminsSmsConvert.class); + + @Mappings({}) + AddSignDTO convert(AddSignRequest addSignRequest); + + @Mappings({}) + UpdateSignDTO convert(UpdateSignRequest updateSignRequest); + + @Mappings({}) + ListSmsTemplateDTO convert(ListSmsTemplateRequest listSmsTemplateRequest); +} diff --git a/system/system-rest/src/main/java/cn/iocoder/mall/system/rest/request/smsSign/AddSignRequest.java b/system/system-rest/src/main/java/cn/iocoder/mall/system/rest/request/smsSign/AddSignRequest.java new file mode 100644 index 000000000..071711db0 --- /dev/null +++ b/system/system-rest/src/main/java/cn/iocoder/mall/system/rest/request/smsSign/AddSignRequest.java @@ -0,0 +1,22 @@ +package cn.iocoder.mall.system.rest.request.smsSign; + +import lombok.Data; +import lombok.experimental.Accessors; +import org.springframework.web.bind.annotation.RequestParam; + +import java.io.Serializable; + +/** + * 添加 sign + * + * author: sin + * time: 2020/4/20 11:10 上午 + */ +@Data +@Accessors(chain = true) +public class AddSignRequest implements Serializable { + + private String sign; + + private Integer platform; +} diff --git a/system/system-rest/src/main/java/cn/iocoder/mall/system/rest/request/smsSign/UpdateSignRequest.java b/system/system-rest/src/main/java/cn/iocoder/mall/system/rest/request/smsSign/UpdateSignRequest.java new file mode 100644 index 000000000..f8d05e91b --- /dev/null +++ b/system/system-rest/src/main/java/cn/iocoder/mall/system/rest/request/smsSign/UpdateSignRequest.java @@ -0,0 +1,23 @@ +package cn.iocoder.mall.system.rest.request.smsSign; + +import lombok.Data; +import lombok.experimental.Accessors; + +import java.io.Serializable; + +/** + * 更新签名 + *

+ * author: sin + * time: 2020/4/20 11:02 上午 + */ +@Data +@Accessors(chain = true) +public class UpdateSignRequest implements Serializable { + + private Integer id; + + private String sign; + + private Integer platform; +} diff --git a/system/system-rest/src/main/java/cn/iocoder/mall/system/rest/request/smsTemplate/AddSmsTemplateRequest.java b/system/system-rest/src/main/java/cn/iocoder/mall/system/rest/request/smsTemplate/AddSmsTemplateRequest.java new file mode 100644 index 000000000..36ab20484 --- /dev/null +++ b/system/system-rest/src/main/java/cn/iocoder/mall/system/rest/request/smsTemplate/AddSmsTemplateRequest.java @@ -0,0 +1,49 @@ +package cn.iocoder.mall.system.rest.request.smsTemplate; + +import cn.iocoder.common.framework.validator.InEnum; +import cn.iocoder.mall.system.biz.enums.sms.SmsPlatformEnum; +import cn.iocoder.mall.system.biz.enums.sms.SmsTypeEnum; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import lombok.experimental.Accessors; + +import javax.validation.constraints.NotNull; +import javax.validation.constraints.Size; +import java.io.Serializable; + +/** + * 短信模板 add + * + * @author Sin + * @time 2019/5/26 12:37 PM + */ +@ApiModel("短信模板-添加") +@Data +@Accessors(chain = true) +public class AddSmsTemplateRequest implements Serializable { + + @ApiModelProperty("短信签名id") + @NotNull(message = "短信短信签名id不能为空!") + private Integer smsSignId; + + @ApiModelProperty("短信模板code") + @NotNull + @Size(min = 3, max = 50, message = "短信code在 3-50 之间") + private String templateCode; + + @ApiModelProperty("短信模板") + @NotNull + @Size(min = 3, max = 255, message = "短信在 3-255 之间") + private String template; + + @ApiModelProperty("短信模板-平台") + @NotNull + @InEnum(value = SmsPlatformEnum.class) + private Integer platform; + + @ApiModelProperty("短信模板-平台") + @NotNull + @InEnum(value = SmsTypeEnum.class) + private Integer smsType; +} diff --git a/system/system-rest/src/main/java/cn/iocoder/mall/system/rest/request/smsTemplate/ListSmsTemplateRequest.java b/system/system-rest/src/main/java/cn/iocoder/mall/system/rest/request/smsTemplate/ListSmsTemplateRequest.java new file mode 100644 index 000000000..285d11e7c --- /dev/null +++ b/system/system-rest/src/main/java/cn/iocoder/mall/system/rest/request/smsTemplate/ListSmsTemplateRequest.java @@ -0,0 +1,30 @@ +package cn.iocoder.mall.system.rest.request.smsTemplate; + +import cn.iocoder.common.framework.vo.PageParam; +import lombok.Data; +import lombok.experimental.Accessors; + +import javax.validation.constraints.NotNull; + +/** + * page 短信模板 query + * + * @author Sin + * @time 2019/5/19 4:32 PM + */ +@Data +@Accessors(chain = true) +public class ListSmsTemplateRequest extends PageParam { + + @NotNull + private String id; + + @NotNull + private Integer smsSignId; + + @NotNull + private String template; + + @NotNull + private String applyStatus; +} diff --git a/system/system-rest/src/main/java/cn/iocoder/mall/system/rest/request/smsTemplate/UpdateSmsTemplateRequest.java b/system/system-rest/src/main/java/cn/iocoder/mall/system/rest/request/smsTemplate/UpdateSmsTemplateRequest.java new file mode 100644 index 000000000..b879893d0 --- /dev/null +++ b/system/system-rest/src/main/java/cn/iocoder/mall/system/rest/request/smsTemplate/UpdateSmsTemplateRequest.java @@ -0,0 +1,53 @@ +package cn.iocoder.mall.system.rest.request.smsTemplate; + +import cn.iocoder.common.framework.validator.InEnum; +import cn.iocoder.mall.system.biz.enums.sms.SmsPlatformEnum; +import cn.iocoder.mall.system.biz.enums.sms.SmsTypeEnum; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import lombok.experimental.Accessors; + +import javax.validation.constraints.NotNull; +import javax.validation.constraints.Size; +import java.io.Serializable; + +/** + * 短信模板 add + * + * @author Sin + * @time 2019/5/26 12:37 PM + */ +@ApiModel("短信模板-添加") +@Data +@Accessors(chain = true) +public class UpdateSmsTemplateRequest implements Serializable { + + @ApiModelProperty("短信模板id") + @NotNull(message = "短信模板不能为空!") + private Integer id; + + @ApiModelProperty("短信签名id") + @NotNull(message = "短信短信签名id不能为空!") + private Integer smsSignId; + + @ApiModelProperty("短信模板code") + @NotNull + @Size(min = 3, max = 50, message = "短信code在 3-50 之间") + private String templateCode; + + @ApiModelProperty("短信模板") + @NotNull + @Size(min = 3, max = 255, message = "短信在 3-255 之间") + private String template; + + @ApiModelProperty("短信模板-平台") + @NotNull + @InEnum(value = SmsPlatformEnum.class) + private Integer platform; + + @ApiModelProperty("短信模板-平台") + @NotNull + @InEnum(value = SmsTypeEnum.class) + private Integer smsType; +}