From 453235bb6abeb92211c7fe479bf1f738b14bbdb8 Mon Sep 17 00:00:00 2001 From: sin <2943460818@qq.com> Date: Thu, 16 May 2019 21:50:22 +0800 Subject: [PATCH] =?UTF-8?q?-=20=E6=B7=BB=E5=8A=A0=20SmsPlatform?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../iocoder/mall/admin/api/SmsPlatform.java | 80 ++++++ .../cn/iocoder/mall/admin/api/SmsService.java | 60 ++++ .../mall/admin/api/bo/sms/SmsSignBO.java | 40 +++ .../mall/admin/api/bo/sms/SmsTemplateBO.java | 44 +++ .../api/constant/AdminErrorCodeEnum.java | 9 + .../api/constant/SmsApplyStatusEnum.java | 31 ++ .../admin/api/exception/SmsFailException.java | 14 + system/system-service-impl/pom.xml | 10 + .../mall/admin/convert/SmsSignConvert.java | 22 ++ .../admin/convert/SmsTemplateConvert.java | 22 ++ .../iocoder/mall/admin/dao/SmsSignMapper.java | 15 + .../mall/admin/dao/SmsTemplateMapper.java | 16 ++ .../mall/admin/dataobject/SmsSignDO.java | 45 +++ .../mall/admin/dataobject/SmsTemplateDO.java | 45 +++ .../mall/admin/service/SmsServiceImpl.java | 172 +++++++++++ .../admin/service/SmsYunPianPlatform.java | 272 ++++++++++++++++++ .../main/resources/config/application.yaml | 6 + .../mall/admin/SystemApplicationTest.java | 20 ++ .../cn/iocoder/mall/admin/package-info.java | 5 + .../admin/service/SmsServiceImplTest.java | 29 ++ 20 files changed, 957 insertions(+) create mode 100644 system/system-service-api/src/main/java/cn/iocoder/mall/admin/api/SmsPlatform.java create mode 100644 system/system-service-api/src/main/java/cn/iocoder/mall/admin/api/SmsService.java create mode 100644 system/system-service-api/src/main/java/cn/iocoder/mall/admin/api/bo/sms/SmsSignBO.java create mode 100644 system/system-service-api/src/main/java/cn/iocoder/mall/admin/api/bo/sms/SmsTemplateBO.java create mode 100644 system/system-service-api/src/main/java/cn/iocoder/mall/admin/api/constant/SmsApplyStatusEnum.java create mode 100644 system/system-service-api/src/main/java/cn/iocoder/mall/admin/api/exception/SmsFailException.java create mode 100644 system/system-service-impl/src/main/java/cn/iocoder/mall/admin/convert/SmsSignConvert.java create mode 100644 system/system-service-impl/src/main/java/cn/iocoder/mall/admin/convert/SmsTemplateConvert.java create mode 100644 system/system-service-impl/src/main/java/cn/iocoder/mall/admin/dao/SmsSignMapper.java create mode 100644 system/system-service-impl/src/main/java/cn/iocoder/mall/admin/dao/SmsTemplateMapper.java create mode 100644 system/system-service-impl/src/main/java/cn/iocoder/mall/admin/dataobject/SmsSignDO.java create mode 100644 system/system-service-impl/src/main/java/cn/iocoder/mall/admin/dataobject/SmsTemplateDO.java create mode 100644 system/system-service-impl/src/main/java/cn/iocoder/mall/admin/service/SmsServiceImpl.java create mode 100644 system/system-service-impl/src/main/java/cn/iocoder/mall/admin/service/SmsYunPianPlatform.java create mode 100644 system/system-service-impl/src/test/java/cn/iocoder/mall/admin/SystemApplicationTest.java create mode 100644 system/system-service-impl/src/test/java/cn/iocoder/mall/admin/package-info.java create mode 100644 system/system-service-impl/src/test/java/cn/iocoder/mall/admin/service/SmsServiceImplTest.java diff --git a/system/system-service-api/src/main/java/cn/iocoder/mall/admin/api/SmsPlatform.java b/system/system-service-api/src/main/java/cn/iocoder/mall/admin/api/SmsPlatform.java new file mode 100644 index 000000000..597db3122 --- /dev/null +++ b/system/system-service-api/src/main/java/cn/iocoder/mall/admin/api/SmsPlatform.java @@ -0,0 +1,80 @@ +package cn.iocoder.mall.admin.api; + +import cn.iocoder.mall.admin.api.bo.sms.SmsSignBO; +import lombok.Data; +import lombok.experimental.Accessors; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * 短信平台 + * + * @author Sin + * @time 2019/5/16 6:33 PM + */ +public interface SmsPlatform { + + @Data + @Accessors(chain = true) + class Result { + /** + * 编号 + */ + private String id; + /** + * 审核状态 + */ + private Integer applyStatus; + /** + * 审核内容 + */ + private String applyMessage; + } + + /** + * 签名 - 创建 + * + * @param sign + */ + Result createSign(String sign); + + /** + * 签名 - 获取 + * + * @param sign + */ + Result getSign(String sign); + + /** + * 签名 - 更新 + * + * @param oldSign + * @param sign + */ + Result updateSign(String oldSign, String sign); + + /** + * 模板 - 创建 + * + * @param sign 选用的哪个签名 + * @param template 模板内容 + * @param tplType 1 为验证码类型,其他为 null + */ + Result createTemplate(String sign, String template, Integer tplType); + + /** + * 获取模板信息 + * + * @param tipId + */ + Result getTemplate(String tipId); + + /** + * 更新模板内容 + * + * @param tipId 选用的哪个签名 + * @param template 模板内容 + * @param tplType 1 为验证码类型,其他为 null + */ + Result updateTemplate(String tipId, String template, Integer tplType); +} diff --git a/system/system-service-api/src/main/java/cn/iocoder/mall/admin/api/SmsService.java b/system/system-service-api/src/main/java/cn/iocoder/mall/admin/api/SmsService.java new file mode 100644 index 000000000..a3d36139b --- /dev/null +++ b/system/system-service-api/src/main/java/cn/iocoder/mall/admin/api/SmsService.java @@ -0,0 +1,60 @@ +package cn.iocoder.mall.admin.api; + +import cn.iocoder.mall.admin.api.bo.sms.SmsSignBO; +import cn.iocoder.mall.admin.api.bo.sms.SmsTemplateBO; + +/** + * 短信服务 + * + * @author Sin + * @time 2019/5/16 9:54 AM + */ +public interface SmsService { + + /** + * 签名 - 创建 + * + * @param sign + */ + void createSign(String sign); + + /** + * 签名 - 获取 + * + * @param sign + */ + SmsSignBO getSign(String sign); + + /** + * 签名 - 更新 + * + * @param oldSign + * @param sign + */ + void updateSign(String oldSign, String sign); + + /** + * 模板 - 创建 + * + * @param smsSignId 选用的哪个签名 + * @param template 模板内容 + * @param tplType 1 为验证码类型,其他为 null + */ + void createTemplate(Integer smsSignId, String template, Integer tplType); + + /** + * 获取模板信息 + * + * @param id + */ + SmsTemplateBO getTemplate(String id); + + /** + * 更新模板内容 + * + * @param id 模板id + * @param template 模板内容 + * @param tplType 1 为验证码类型,其他为 null + */ + void updateTemplate(String id, String template, Integer tplType); +} diff --git a/system/system-service-api/src/main/java/cn/iocoder/mall/admin/api/bo/sms/SmsSignBO.java b/system/system-service-api/src/main/java/cn/iocoder/mall/admin/api/bo/sms/SmsSignBO.java new file mode 100644 index 000000000..220b01856 --- /dev/null +++ b/system/system-service-api/src/main/java/cn/iocoder/mall/admin/api/bo/sms/SmsSignBO.java @@ -0,0 +1,40 @@ +package cn.iocoder.mall.admin.api.bo.sms; + +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-service-api/src/main/java/cn/iocoder/mall/admin/api/bo/sms/SmsTemplateBO.java b/system/system-service-api/src/main/java/cn/iocoder/mall/admin/api/bo/sms/SmsTemplateBO.java new file mode 100644 index 000000000..e2094eeee --- /dev/null +++ b/system/system-service-api/src/main/java/cn/iocoder/mall/admin/api/bo/sms/SmsTemplateBO.java @@ -0,0 +1,44 @@ +package cn.iocoder.mall.admin.api.bo.sms; + +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-service-api/src/main/java/cn/iocoder/mall/admin/api/constant/AdminErrorCodeEnum.java b/system/system-service-api/src/main/java/cn/iocoder/mall/admin/api/constant/AdminErrorCodeEnum.java index 61f4dfd1d..3764d63a7 100644 --- a/system/system-service-api/src/main/java/cn/iocoder/mall/admin/api/constant/AdminErrorCodeEnum.java +++ b/system/system-service-api/src/main/java/cn/iocoder/mall/admin/api/constant/AdminErrorCodeEnum.java @@ -46,6 +46,15 @@ public enum AdminErrorCodeEnum { DATA_DICT_EXISTS(1002005000, "该数据字典已经存在"), DATA_DICT_NOT_EXISTS(1002005001, "该数据字典不存在"), + // ========== 短信模板 1002006000 ========== + SMS_SIGN_ADD_FAIL(1002006000, "短信签名添加失败"), + SMS_SIGN_NOT_EXISTENT(1002006001, "短信签名不存在"), + SMS_SIGN_IS_EXISTENT(1002006002, "短信签名已存在"), + SMS_SIGN_UPDATE_FAIL(1002006003, "短信更新失败"), + + SMS_TEMPLATE_ADD_FAIL(1002006020, "短信签名不存在"), + SMS_TEMPLATE_NOT_EXISTENT(1002006021, "短信签名不存在"), + SMS_TEMPLATE_IS_EXISTENT(1002006022, "短信签名不存在"), ; private final int code; diff --git a/system/system-service-api/src/main/java/cn/iocoder/mall/admin/api/constant/SmsApplyStatusEnum.java b/system/system-service-api/src/main/java/cn/iocoder/mall/admin/api/constant/SmsApplyStatusEnum.java new file mode 100644 index 000000000..eaf685687 --- /dev/null +++ b/system/system-service-api/src/main/java/cn/iocoder/mall/admin/api/constant/SmsApplyStatusEnum.java @@ -0,0 +1,31 @@ +package cn.iocoder.mall.admin.api.constant; + +/** + * 短信审核状态 + * + * @author Sin + * @time 2019/5/16 12:48 PM + */ +public enum SmsApplyStatusEnum { + + CHECKING(1, "审核中"), + SUCCESS(2, "审核成功"), + FAIL(3, "审核失败"), + ; + + private final int code; + private final String message; + + SmsApplyStatusEnum(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-service-api/src/main/java/cn/iocoder/mall/admin/api/exception/SmsFailException.java b/system/system-service-api/src/main/java/cn/iocoder/mall/admin/api/exception/SmsFailException.java new file mode 100644 index 000000000..631d8513f --- /dev/null +++ b/system/system-service-api/src/main/java/cn/iocoder/mall/admin/api/exception/SmsFailException.java @@ -0,0 +1,14 @@ +package cn.iocoder.mall.admin.api.exception; + +import cn.iocoder.common.framework.exception.ServiceException; + +/** + * @author Sin + * @time 2019/5/16 11:17 AM + */ +public class SmsFailException extends ServiceException { + + public SmsFailException(Integer code, String message) { + super(code, message); + } +} diff --git a/system/system-service-impl/pom.xml b/system/system-service-impl/pom.xml index 3360a821c..344d93443 100644 --- a/system/system-service-impl/pom.xml +++ b/system/system-service-impl/pom.xml @@ -67,7 +67,17 @@ com.google.guava guava + + com.yunpian.sdk + yunpian-java-sdk + 1.2.7 + + + + org.springframework.boot + spring-boot-starter-test + diff --git a/system/system-service-impl/src/main/java/cn/iocoder/mall/admin/convert/SmsSignConvert.java b/system/system-service-impl/src/main/java/cn/iocoder/mall/admin/convert/SmsSignConvert.java new file mode 100644 index 000000000..0173e30c7 --- /dev/null +++ b/system/system-service-impl/src/main/java/cn/iocoder/mall/admin/convert/SmsSignConvert.java @@ -0,0 +1,22 @@ +package cn.iocoder.mall.admin.convert; + +import cn.iocoder.mall.admin.api.bo.sms.SmsSignBO; +import cn.iocoder.mall.admin.dataobject.SmsSignDO; +import org.mapstruct.Mapper; +import org.mapstruct.Mappings; +import org.mapstruct.factory.Mappers; + +/** + * 短信 签名 + * + * @author Sin + * @time 2019/5/16 6:31 PM + */ +@Mapper +public interface SmsSignConvert { + + SmsSignConvert INSTANCE = Mappers.getMapper(SmsSignConvert.class); + + @Mappings({}) + SmsSignBO convert(SmsSignDO smsSignDO); +} diff --git a/system/system-service-impl/src/main/java/cn/iocoder/mall/admin/convert/SmsTemplateConvert.java b/system/system-service-impl/src/main/java/cn/iocoder/mall/admin/convert/SmsTemplateConvert.java new file mode 100644 index 000000000..d76c694b0 --- /dev/null +++ b/system/system-service-impl/src/main/java/cn/iocoder/mall/admin/convert/SmsTemplateConvert.java @@ -0,0 +1,22 @@ +package cn.iocoder.mall.admin.convert; + +import cn.iocoder.mall.admin.api.bo.sms.SmsTemplateBO; +import cn.iocoder.mall.admin.dataobject.SmsTemplateDO; +import org.mapstruct.Mapper; +import org.mapstruct.Mappings; +import org.mapstruct.factory.Mappers; + +/** + * 短信 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); +} diff --git a/system/system-service-impl/src/main/java/cn/iocoder/mall/admin/dao/SmsSignMapper.java b/system/system-service-impl/src/main/java/cn/iocoder/mall/admin/dao/SmsSignMapper.java new file mode 100644 index 000000000..351e0326c --- /dev/null +++ b/system/system-service-impl/src/main/java/cn/iocoder/mall/admin/dao/SmsSignMapper.java @@ -0,0 +1,15 @@ +package cn.iocoder.mall.admin.dao; + +import cn.iocoder.mall.admin.dataobject.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-service-impl/src/main/java/cn/iocoder/mall/admin/dao/SmsTemplateMapper.java b/system/system-service-impl/src/main/java/cn/iocoder/mall/admin/dao/SmsTemplateMapper.java new file mode 100644 index 000000000..91fa04057 --- /dev/null +++ b/system/system-service-impl/src/main/java/cn/iocoder/mall/admin/dao/SmsTemplateMapper.java @@ -0,0 +1,16 @@ +package cn.iocoder.mall.admin.dao; + +import cn.iocoder.common.framework.dataobject.BaseDO; +import cn.iocoder.mall.admin.dataobject.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-service-impl/src/main/java/cn/iocoder/mall/admin/dataobject/SmsSignDO.java b/system/system-service-impl/src/main/java/cn/iocoder/mall/admin/dataobject/SmsSignDO.java new file mode 100644 index 000000000..f25afcd1f --- /dev/null +++ b/system/system-service-impl/src/main/java/cn/iocoder/mall/admin/dataobject/SmsSignDO.java @@ -0,0 +1,45 @@ +package cn.iocoder.mall.admin.dataobject; + +import cn.iocoder.common.framework.dataobject.DeletableDO; +import com.baomidou.mybatisplus.annotation.TableId; +import lombok.Data; +import lombok.experimental.Accessors; + +/** + * 短信签名 + * + * 签名是短信发送前缀 如:【阿里云】、【小红书】 + * + * @author Sin + * @time 2019/5/16 12:28 PM + */ +@Data +@Accessors(chain = true) +public class SmsSignDO extends DeletableDO { + + /** + * 编号 + */ + @TableId("id") + private Integer id; + /** + * 签名id 这个是第三方的 + */ + private String platformId; + /** + * 签名名称 + */ + private String sign; + /** + * 审核状态 + * + * - 1、审核中 + * - 2、审核成功 + * - 3、审核失败 + */ + private Integer applyStatus; + /** + * 审核信息 + */ + private String applyMessage; +} diff --git a/system/system-service-impl/src/main/java/cn/iocoder/mall/admin/dataobject/SmsTemplateDO.java b/system/system-service-impl/src/main/java/cn/iocoder/mall/admin/dataobject/SmsTemplateDO.java new file mode 100644 index 000000000..00e7f18f1 --- /dev/null +++ b/system/system-service-impl/src/main/java/cn/iocoder/mall/admin/dataobject/SmsTemplateDO.java @@ -0,0 +1,45 @@ +package cn.iocoder.mall.admin.dataobject; + +import cn.iocoder.common.framework.dataobject.DeletableDO; +import lombok.Data; +import lombok.experimental.Accessors; + +/** + * 短信 模板 + * + * @author Sin + * @time 2019/5/16 12:31 PM + */ +@Data +@Accessors(chain = true) +public class SmsTemplateDO extends DeletableDO { + + /** + * 编号 + */ + 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-service-impl/src/main/java/cn/iocoder/mall/admin/service/SmsServiceImpl.java b/system/system-service-impl/src/main/java/cn/iocoder/mall/admin/service/SmsServiceImpl.java new file mode 100644 index 000000000..c65184024 --- /dev/null +++ b/system/system-service-impl/src/main/java/cn/iocoder/mall/admin/service/SmsServiceImpl.java @@ -0,0 +1,172 @@ +package cn.iocoder.mall.admin.service; + +import cn.iocoder.common.framework.constant.DeletedStatusEnum; +import cn.iocoder.mall.admin.api.SmsPlatform; +import cn.iocoder.mall.admin.api.SmsService; +import cn.iocoder.mall.admin.api.bo.sms.SmsSignBO; +import cn.iocoder.mall.admin.api.bo.sms.SmsTemplateBO; +import cn.iocoder.mall.admin.api.constant.AdminErrorCodeEnum; +import cn.iocoder.mall.admin.api.exception.SmsFailException; +import cn.iocoder.mall.admin.convert.SmsSignConvert; +import cn.iocoder.mall.admin.convert.SmsTemplateConvert; +import cn.iocoder.mall.admin.dao.SmsSignMapper; +import cn.iocoder.mall.admin.dao.SmsTemplateMapper; +import cn.iocoder.mall.admin.dataobject.SmsSignDO; +import cn.iocoder.mall.admin.dataobject.SmsTemplateDO; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +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 java.util.Date; + +/** + * 短信 + * + * @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 + @Qualifier("smsYunPianPlatform") + private SmsPlatform smsPlatform; + + @Override + @Transactional + public void createSign(String sign) { + + // 避免重复 + SmsSignDO smsSignDO = smsSignMapper.selectOne( + new QueryWrapper().eq("sign", sign)); + + if (smsSignDO != null) { + throw new SmsFailException(AdminErrorCodeEnum.SMS_SIGN_IS_EXISTENT.getCode(), + AdminErrorCodeEnum.SMS_SIGN_IS_EXISTENT.getMessage()); + } + + // 创建平台 sign + SmsPlatform.Result result = smsPlatform.createSign(sign); + + // 保存数据库 + smsSignMapper.insert( + (SmsSignDO) new SmsSignDO() + .setSign(sign) + .setPlatformId(result.getId()) + .setApplyStatus(result.getApplyStatus()) + .setDeleted(DeletedStatusEnum.DELETED_NO.getValue()) + .setUpdateTime(new Date()) + ); + } + + @Override + public SmsSignBO getSign(String sign) { + SmsSignDO smsSignDO = smsSignMapper.selectOne( + new QueryWrapper().eq("sign", sign)); + + if (smsSignDO == null) { + throw new SmsFailException(AdminErrorCodeEnum.SMS_SIGN_NOT_EXISTENT.getCode(), + AdminErrorCodeEnum.SMS_SIGN_NOT_EXISTENT.getMessage()); + } + + return SmsSignConvert.INSTANCE.convert(smsSignDO); + } + + @Override + @Transactional + public void updateSign(String oldSign, String sign) { + // 避免重复 + SmsSignDO smsSignDO = smsSignMapper.selectOne( + new QueryWrapper().eq("sign", oldSign)); + + if (smsSignDO == null) { + throw new SmsFailException(AdminErrorCodeEnum.SMS_SIGN_NOT_EXISTENT.getCode(), + AdminErrorCodeEnum.SMS_SIGN_NOT_EXISTENT.getMessage()); + } + + // 更新平台 + SmsPlatform.Result result = smsPlatform.updateSign(oldSign, sign); + + // 更新 + smsSignMapper.updateById( + (SmsSignDO) new SmsSignDO() + .setId(smsSignDO.getId()) + .setPlatformId(result.getId()) + .setSign(sign) + .setApplyStatus(result.getApplyStatus()) + .setUpdateTime(new Date()) + ); + } + + @Override + public void createTemplate(Integer smsSignId, String template, Integer tplType) { + + SmsSignDO smsSignDO = smsSignMapper.selectOne( + new QueryWrapper().eq("id", smsSignId)); + + if (smsSignDO == null) { + throw new SmsFailException(AdminErrorCodeEnum.SMS_SIGN_NOT_EXISTENT.getCode(), + AdminErrorCodeEnum.SMS_SIGN_NOT_EXISTENT.getMessage()); + } + + // 调用平台 + SmsPlatform.Result result = smsPlatform + .createTemplate(smsSignDO.getSign(), template, tplType); + + // 保存数据库 + smsTemplateMapper.insert( + (SmsTemplateDO) new SmsTemplateDO() + .setId(null) + .setSmsSignId(smsSignId) + .setPlatformId(result.getId()) + .setTemplate(template) + .setApplyStatus(result.getApplyStatus()) + .setApplyMessage(result.getApplyMessage()) + .setDeleted(DeletedStatusEnum.DELETED_NO.getValue()) + .setCreateTime(new Date()) + ); + } + + @Override + public SmsTemplateBO getTemplate(String id) { + SmsTemplateDO smsTemplateDO = smsTemplateMapper.selectOne( + new QueryWrapper().eq("id", id)); + + if (smsTemplateDO == null) { + throw new SmsFailException(AdminErrorCodeEnum.SMS_TEMPLATE_NOT_EXISTENT.getCode(), + AdminErrorCodeEnum.SMS_TEMPLATE_NOT_EXISTENT.getMessage()); + } + + return SmsTemplateConvert.INSTANCE.convert(smsTemplateDO); + } + + @Override + public void updateTemplate(String id, String template, Integer tplType) { + SmsTemplateDO smsTemplateDO = smsTemplateMapper.selectOne( + new QueryWrapper().eq("id", id)); + + if (smsTemplateDO == null) { + throw new SmsFailException(AdminErrorCodeEnum.SMS_TEMPLATE_NOT_EXISTENT.getCode(), + AdminErrorCodeEnum.SMS_TEMPLATE_NOT_EXISTENT.getMessage()); + } + + SmsPlatform.Result result = smsPlatform.updateTemplate( + smsTemplateDO.getPlatformId(), template, tplType); + + smsTemplateMapper.update( + (SmsTemplateDO) new SmsTemplateDO() + .setApplyStatus(result.getApplyStatus()) + .setApplyMessage(result.getApplyMessage()) + .setUpdateTime(new Date()), + new QueryWrapper().eq("id", id) + ); + } +} diff --git a/system/system-service-impl/src/main/java/cn/iocoder/mall/admin/service/SmsYunPianPlatform.java b/system/system-service-impl/src/main/java/cn/iocoder/mall/admin/service/SmsYunPianPlatform.java new file mode 100644 index 000000000..8d852a9d3 --- /dev/null +++ b/system/system-service-impl/src/main/java/cn/iocoder/mall/admin/service/SmsYunPianPlatform.java @@ -0,0 +1,272 @@ +package cn.iocoder.mall.admin.service; + +import cn.iocoder.mall.admin.api.SmsPlatform; +import cn.iocoder.mall.admin.api.constant.AdminErrorCodeEnum; +import cn.iocoder.mall.admin.api.constant.SmsApplyStatusEnum; +import cn.iocoder.mall.admin.api.exception.SmsFailException; +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONArray; +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.Service; + +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 + */ +@Service +public class SmsYunPianPlatform implements SmsPlatform { + + protected static final Logger LOGGER = LoggerFactory.getLogger(SmsPlatform.class); + + private static final int SUCCESS_CODE = 0; + + //查账户信息的http地址 + private static final String URI_GET_USER_INFO = + "https://sms.yunpian.com/v2/user/get.json"; + + //智能匹配模板发送接口的http地址 + private static final String URI_SEND_SMS = + "https://sms.yunpian.com/v2/sms/single_send.json"; + + //模板发送接口的http地址 + private static final String URI_TPL_SEND_SMS = + "https://sms.yunpian.com/v2/sms/tpl_single_send.json"; + + //发送语音验证码接口的http地址 + private static final String URI_SEND_VOICE = + "https://voice.yunpian.com/v2/voice/send.json"; + + //绑定主叫、被叫关系的接口http地址 + private static final String URI_SEND_BIND = + "https://call.yunpian.com/v2/call/bind.json"; + + //解绑主叫、被叫关系的接口http地址 + private static final String URI_SEND_UNBIND = + "https://call.yunpian.com/v2/call/unbind.json"; + + /** + * 签名 - 添加 + */ + 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"; + + //编码格式。发送编码格式统一用UTF-8 + private static String ENCODING = "UTF-8"; + + @Value("${sms.apiKey}") + private String apiKey; + + @Override + public Result createSign(String sign) { + // 调用 短信平台 + Map params = new LinkedHashMap<>(); + params.put("apikey", apiKey); + params.put("sign", sign); + params.put("notify", "true"); + String result = post(URL_SIGN_ADD, params); + JSONObject jsonObject = JSON.parseObject(result); + if (!(jsonObject.getInteger("code") == SUCCESS_CODE)) { + throw new SmsFailException(AdminErrorCodeEnum.SMS_SIGN_ADD_FAIL.getCode(), + AdminErrorCodeEnum.SMS_SIGN_ADD_FAIL.getMessage()); + } + + JSONObject signJSONObject = (JSONObject) jsonObject.get("sign"); + Integer applyState = smsStatusMapping(signJSONObject.getString("apply_state")); + return new Result().setId(null).setApplyStatus(applyState).setApplyMessage(null); + } + + @Override + public Result getSign(String sign) { + Map params = new LinkedHashMap<>(); + params.put("apikey", apiKey); + params.put("sign", sign); + params.put("page_num", "1"); + params.put("page_size", "20"); + String result = post(URL_SIGN_GET, params); + JSONObject jsonObject = JSON.parseObject(result); + + if (!(jsonObject.getInteger("code") == SUCCESS_CODE)) { + throw new SmsFailException(AdminErrorCodeEnum.SMS_SIGN_ADD_FAIL.getCode(), + AdminErrorCodeEnum.SMS_SIGN_ADD_FAIL.getMessage()); + } + + JSONArray jsonArray = jsonObject.getJSONArray("sign"); + if (jsonArray.size() <= 0) { + throw new SmsFailException(AdminErrorCodeEnum.SMS_SIGN_NOT_EXISTENT.getCode(), + AdminErrorCodeEnum.SMS_SIGN_NOT_EXISTENT.getMessage()); + } + + JSONObject signJSONObject = (JSONObject) jsonArray.get(0); + String checkStatus = signJSONObject.getString("check_status"); + String applyMessage = signJSONObject.getString("remark"); + Integer applyStatus = smsStatusMapping(checkStatus); + return new Result().setId(null).setApplyStatus(applyStatus).setApplyMessage(applyMessage); + } + + @Override + public Result updateSign(String oldSign, String sign) { + Map params = new LinkedHashMap<>(); + params.put("apikey", apiKey); + params.put("old_sign", oldSign); + params.put("sign", sign); + String result = post(URL_SIGN_UPDATE, params); + JSONObject jsonObject = JSON.parseObject(result); + + if (!(jsonObject.getInteger("code") == SUCCESS_CODE)) { + throw new SmsFailException(AdminErrorCodeEnum.SMS_SIGN_UPDATE_FAIL.getCode(), + AdminErrorCodeEnum.SMS_SIGN_UPDATE_FAIL.getMessage()); + } + + JSONObject signJSONObject = (JSONObject) jsonObject.get("sign"); + Integer applyState = smsStatusMapping(signJSONObject.getString("apply_state")); + return new Result().setId(null).setApplyStatus(applyState).setApplyMessage(null); + } + + @Override + public Result createTemplate(String sign, String template, Integer tplType) { + Map params = new LinkedHashMap<>(); + params.put("apikey", apiKey); + params.put("tpl_content", sign + template); + if (tplType != null) { + params.put("tplType", String.valueOf(tplType)); + } + String result = post(URL_TEMPLATE_ADD, params); + JSONObject jsonObject = JSON.parseObject(result); + String tipId = jsonObject.getString("tpl_id"); + String checkStatus = jsonObject.getString("check_status"); + String reason = jsonObject.getString("reason"); + Integer applyStatus = smsStatusMapping(checkStatus); + return new Result().setId(tipId).setApplyStatus(applyStatus).setApplyMessage(reason); + } + + @Override + public Result getTemplate(String tipId) { + Map params = new LinkedHashMap<>(); + params.put("apikey", apiKey); + params.put("tipId", tipId); + String result = post(URL_TEMPLATE_GET, params); + JSONObject jsonObject = JSON.parseObject(result); + + String checkStatus = jsonObject.getString("check_status"); + Integer applyStatus = smsStatusMapping(checkStatus); + String reason = jsonObject.getString("reason"); + return new Result().setId(tipId).setApplyStatus(applyStatus).setApplyMessage(reason); + } + + @Override + public Result updateTemplate(String tipId, String template, Integer tplType) { + Map params = new LinkedHashMap<>(); + params.put("apikey", apiKey); + params.put("tipId", tipId); + params.put("template", template); + String result = post(URL_TEMPLATE_UPDATE, params); + JSONObject jsonObject = JSON.parseObject(result); + + String checkStatus = jsonObject.getString("check_status"); + Integer applyStatus = smsStatusMapping(checkStatus); + String reason = jsonObject.getString("reason"); + return new Result().setId(tipId).setApplyStatus(applyStatus).setApplyMessage(reason); + } + + /** + * 短信 status 和 云片状态 映射关系 + * + * @param checkStatus + * @return + */ + private Integer smsStatusMapping(String checkStatus) { + Integer applyStatus; + switch (checkStatus) { + case "SUCCESS": + applyStatus = SmsApplyStatusEnum.SUCCESS.getCode(); + break; + case "FAIL": + applyStatus = SmsApplyStatusEnum.FAIL.getCode(); + break; + default: + applyStatus = SmsApplyStatusEnum.CHECKING.getCode(); + break; + } + return applyStatus; + } + + /** + * 基于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-service-impl/src/main/resources/config/application.yaml b/system/system-service-impl/src/main/resources/config/application.yaml index 2030b1573..7b8f80fb4 100644 --- a/system/system-service-impl/src/main/resources/config/application.yaml +++ b/system/system-service-impl/src/main/resources/config/application.yaml @@ -24,6 +24,10 @@ mybatis-plus: mapper-locations: classpath*:mapper/*.xml type-aliases-package: cn.iocoder.mall.admin.dataobject +# sms +sms: + apiKey: d4705399e71e822fe3a90f801ed95bd9 + # dubbo dubbo: application: @@ -49,6 +53,8 @@ dubbo: version: 1.0.0 RoleService: version: 1.0.0 + SmsService: + version: 1.0.0 # logging logging: diff --git a/system/system-service-impl/src/test/java/cn/iocoder/mall/admin/SystemApplicationTest.java b/system/system-service-impl/src/test/java/cn/iocoder/mall/admin/SystemApplicationTest.java new file mode 100644 index 000000000..d0acf0f3e --- /dev/null +++ b/system/system-service-impl/src/test/java/cn/iocoder/mall/admin/SystemApplicationTest.java @@ -0,0 +1,20 @@ +package cn.iocoder.mall.admin; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.scheduling.annotation.EnableAsync; + +/** + * 短信 application (test) + * + * @author Sin + * @time 2019/5/16 10:53 AM + */ +@SpringBootApplication(scanBasePackages = {"cn.iocoder.mall.admin"}) +@EnableAsync(proxyTargetClass = true) +public class SystemApplicationTest { + + public static void main(String[] args) { + SpringApplication.run(SystemApplicationTest.class); + } +} diff --git a/system/system-service-impl/src/test/java/cn/iocoder/mall/admin/package-info.java b/system/system-service-impl/src/test/java/cn/iocoder/mall/admin/package-info.java new file mode 100644 index 000000000..1a1304b65 --- /dev/null +++ b/system/system-service-impl/src/test/java/cn/iocoder/mall/admin/package-info.java @@ -0,0 +1,5 @@ +/** + * @author Sin + * @time 2019/5/16 10:52 AM + */ +package cn.iocoder.mall.admin; \ No newline at end of file diff --git a/system/system-service-impl/src/test/java/cn/iocoder/mall/admin/service/SmsServiceImplTest.java b/system/system-service-impl/src/test/java/cn/iocoder/mall/admin/service/SmsServiceImplTest.java new file mode 100644 index 000000000..07c1e6cc6 --- /dev/null +++ b/system/system-service-impl/src/test/java/cn/iocoder/mall/admin/service/SmsServiceImplTest.java @@ -0,0 +1,29 @@ +package cn.iocoder.mall.admin.service; + +import cn.iocoder.mall.admin.SystemApplicationTest; +import cn.iocoder.mall.admin.service.SmsServiceImpl; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.junit4.SpringRunner; + +/** + * 短信 test + * + * @author Sin + * @time 2019/5/16 10:52 AM + */ +@RunWith(SpringRunner.class) +@SpringBootTest(classes = SystemApplicationTest.class) +public class SmsServiceImplTest { + + @Autowired + private SmsServiceImpl smsService; + + @Test + public void createSignTest() { +// smsService.createSign("测试签名1"); + smsService.getSign("测试签名1"); + } +}