赞
踩
<!--阿里云短信--> <dependency> <groupId>com.aliyun</groupId> <artifactId>aliyun-java-sdk-core</artifactId> <version>4.0.3</version> </dependency> <!--阿里云短信--> <dependency> <groupId>com.aliyun.oss</groupId> <artifactId>aliyun-sdk-oss</artifactId> <version>2.5.0</version> <exclusions> <exclusion> <artifactId>commons-lang</artifactId> <groupId>commons-lang</groupId> </exclusion> </exclusions> </dependency> <!-- 阿里云 短信--> <dependency> <groupId>com.aliyun</groupId> <artifactId>aliyun-java-sdk-dysmsapi</artifactId> <version>2.1.0</version> </dependency> <!-- 腾讯 短信--> <dependency> <groupId>com.github.qcloudsms</groupId> <artifactId>qcloudsms</artifactId> <version>1.0.5</version> </dependency> <!-- 腾讯 短信--> <dependency> <groupId>com.qcloud</groupId> <artifactId>cos_api</artifactId> <version>5.6.24</version> <exclusions> <exclusion> <artifactId>slf4j-log4j12</artifactId> <groupId>org.slf4j</groupId> </exclusion> </exclusions> </dependency> <!-- 腾讯 短信--> <dependency> <groupId>com.qiniu</groupId> <artifactId>qiniu-java-sdk</artifactId> <version>7.2.29</version> </dependency> <!-- 邮件--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-mail</artifactId> <version>2.1.9.RELEASE</version> </dependency> <!-- hutool--> <dependency> <groupId>cn.hutool</groupId> <artifactId>hutool-all</artifactId> <version>5.7.21</version> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <optional>true</optional> </dependency>
#通知相关配置 notify: mail: # 邮件通知配置,邮箱一般用于接收业务通知例如收到新的订单,sendto 定义邮件接收者,通常为 管理 人员 enable: false host: smtp.qq.com username: 121665820 password: xxxxxxxxx sendfrom: 121665820@qq.com sendto: 121665820@qq.com port: 465 # 短消息模版通知配置 # 短信息用于通知 ,例如 短信通知,注意配置格式;template-name,template-templateId 请参考 NotifyType 枚举值 sms: enable: false # 如果是腾讯云短信,则设置active的值tencent # 如果是阿里云短信,则设置active的值aliyun active: aliyun sign: zbwd template: - name: refund templateId: 159447 aliyun: regionId: xxx accessKeyId: xxx accessKeySecret: xxx tencent: appid: 111111111 appkey: xxxxxxxxxxxxxx
import lombok.Data; import org.springframework.boot.context.properties.ConfigurationProperties; import java.util.ArrayList; import java.util.List; import java.util.Map; /** * @author yzd */ @Data @ConfigurationProperties(prefix = "notify") public class NotifyProperties { private Sms sms; private Mail mail; @Data public static class Mail { private boolean enable; private String host; private String username; private String password; private String sendfrom; private String sendto; private Integer port; } @Data public static class Sms { private boolean enable; private String active; private String sign; private Aliyun aliyun; private Tencent tencent; private List<Map<String, String>> template = new ArrayList<>(); @Data public static class Tencent { private int appid; private String appkey; } @Data public static class Aliyun { private String regionId; private String accessKeyId; private String accessKeySecret; } } }
import com.github.qcloudsms.SmsSingleSender; import com.zbwd.plan.notify.AliyunSmsSender; import com.zbwd.plan.notify.NotifyService; import com.zbwd.plan.notify.TencentSmsSender; import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.mail.javamail.JavaMailSender; import org.springframework.mail.javamail.JavaMailSenderImpl; import java.util.Properties; /** * @author YZD */ @Configuration @EnableConfigurationProperties(NotifyProperties.class) public class NotifyAutoConfiguration { private final NotifyProperties properties; public NotifyAutoConfiguration(NotifyProperties properties) { this.properties = properties; } @Bean public NotifyService notifyService() { NotifyService notifyService = new NotifyService(); NotifyProperties.Mail mailConfig = properties.getMail(); if (mailConfig.isEnable()) { notifyService.setMailSender(mailSender()); notifyService.setSendFrom(mailConfig.getSendfrom()); notifyService.setSendTo(mailConfig.getSendto()); } NotifyProperties.Sms smsConfig = properties.getSms(); if (smsConfig.isEnable()) { if ("aliyun".equalsIgnoreCase(smsConfig.getActive())) { notifyService.setSmsSender(aliyunSmsSender()); } if ("tencent".equalsIgnoreCase(smsConfig.getActive())) { notifyService.setSmsSender(tencentSmsSender()); } notifyService.setSmsTemplate(smsConfig.getTemplate()); } return notifyService; } public JavaMailSender mailSender() { NotifyProperties.Mail mailConfig = properties.getMail(); JavaMailSenderImpl mailSender = new JavaMailSenderImpl(); mailSender.setHost(mailConfig.getHost()); mailSender.setUsername(mailConfig.getUsername()); mailSender.setPassword(mailConfig.getPassword()); mailSender.setPort(mailConfig.getPort()); Properties properties = new Properties(); properties.put("mail.smtp.auth", true); properties.put("mail.smtp.timeout", 5000); properties.put("mail.smtp.starttls.enable", true); properties.put("mail.smtp.socketFactory.fallback", "false"); //阿里云 必须加入配置 outlook配置又不需要 视情况而定.发送不成功多数是这里的配置问题 properties.put("mail.smtp.socketFactory.class", "javax.net.ssl.SSLSocketFactory"); properties.put("mail.smtp.socketFactory.port", mailConfig.getPort()); properties.put("debug", true); mailSender.setJavaMailProperties(properties); return mailSender; } /** * 腾讯 短信发送 * * @return */ public TencentSmsSender tencentSmsSender() { NotifyProperties.Sms smsConfig = properties.getSms(); TencentSmsSender smsSender = new TencentSmsSender(); NotifyProperties.Sms.Tencent tencent = smsConfig.getTencent(); smsSender.setSender(new SmsSingleSender(tencent.getAppid(), tencent.getAppkey())); smsSender.setSign(smsConfig.getSign()); return smsSender; } /** * 阿里云短信发送 * * @return */ public AliyunSmsSender aliyunSmsSender() { NotifyProperties.Sms smsConfig = properties.getSms(); AliyunSmsSender smsSender = new AliyunSmsSender(); NotifyProperties.Sms.Aliyun aliyun = smsConfig.getAliyun(); smsSender.setSign(smsConfig.getSign()); smsSender.setRegionId(aliyun.getRegionId()); smsSender.setAccessKeyId(aliyun.getAccessKeyId()); smsSender.setAccessKeySecret(aliyun.getAccessKeySecret()); return smsSender; } }
/** * 短信 发送 * * @author yzd */ public interface SmsSender { /** * 发送短信息 * 阿里云必须要模板 * * @param phone 接收通知的电话号码 * @param content 短消息内容 * @return SmsResult SmsResult */ @Deprecated SmsResult send(String phone, String content); /** * 短信发送,支持向多个不同的手机号码发送同样内容的短信 * * @param phoneNumbers 必填,接收短信的手机号码。 * 格式: * 国内短信:11位手机号码,例如15951955195。 * 国际/港澳台消息:国际区号+号码,例如85200000000。 * 支持对多个手机号码发送短信,手机号码之间以英文逗号(,)分隔。上限为1000个手机号码。批量调用相对于单条调用及时性稍有延迟 * signName 必填,短信签名名称 * @param templateId 必填,短信模板ID * @param params 必填,短信模板变量对应的实际值,JSON格式 * 腾讯云短信模板参数是数组,因此短信模板形式如 “短信参数{1}, 短信参数{2}” * 阿里云短信模板参数是JSON,因此短信模板形式如“短信参数{param1}, 短信参数{param2}” * @return SmsResult SmsResult */ SmsResult sendWithTemplate(String phoneNumbers, String templateId, String[] params); }
import com.github.qcloudsms.SmsSingleSender; import com.github.qcloudsms.SmsSingleSenderResult; import com.github.qcloudsms.httpclient.HTTPException; import lombok.Data; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import java.io.IOException; /** * 腾讯云短信服务 * * @author Administrator */ @Data public class TencentSmsSender implements SmsSender { private final Log logger = LogFactory.getLog(TencentSmsSender.class); private SmsSingleSender sender; private String sign; @Override public SmsResult send(String phone, String content) { try { SmsSingleSenderResult result = sender.send(0, "86", phone, content, "", ""); logger.debug(result); SmsResult smsResult = new SmsResult(); smsResult.setSuccessful(true); smsResult.setResult(result); return smsResult; } catch (HTTPException | IOException e) { logger.error(e.getMessage(), e); } SmsResult smsResult = new SmsResult(); smsResult.setSuccessful(false); return smsResult; } /** * @param phone 电话 * @param templateId 模板 * @param params 必填,短信模板变量对应的实际值,JSON格式 * 腾讯云短信模板参数是数组,因此短信模板形式如 “短信参数{1}, 短信参数{2}” * 阿里云短信模板参数是JSON,因此短信模板形式如“短信参数{param1}, 短信参数{param2}” * @return */ @Override public SmsResult sendWithTemplate(String phone, String templateId, String[] params) { try { SmsSingleSenderResult result = sender.sendWithParam("86", phone, Integer.parseInt(templateId), params, this.sign, "", ""); logger.debug(result); SmsResult smsResult = new SmsResult(); smsResult.setSuccessful(true); smsResult.setResult(result); return smsResult; } catch (HTTPException | IOException e) { logger.error(e.getMessage(), e); } SmsResult smsResult = new SmsResult(); smsResult.setSuccessful(false); return smsResult; } public void setSign(String sign) { this.sign = sign; } }
import cn.hutool.json.JSONUtil; import com.aliyuncs.CommonRequest; import com.aliyuncs.CommonResponse; import com.aliyuncs.DefaultAcsClient; import com.aliyuncs.IAcsClient; import com.aliyuncs.http.MethodType; import com.aliyuncs.profile.DefaultProfile; import lombok.Data; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; /** * 阿里云短信服务 * * @author YZD */ @Data public class AliyunSmsSender implements SmsSender { private final Log logger = LogFactory.getLog(AliyunSmsSender.class); private String regionId; private String accessKeyId; private String accessKeySecret; private String sign; private final String okCode = "OK"; private static String DOMAIN = "dysmsapi.aliyuncs.com"; private static String VERSION = "2017-05-25"; private static String SEND_SMS_ACTION = "SendSms"; private static String REGIN_ID_NAME = "RegionId"; private static String PHONE_NUMBERS = "PhoneNumbers"; private static String SIGN_NAME = "SignName"; private static String TEMPLATE_CODE = "TemplateCode"; private static String TEMPLATE_PARAM = "TemplateParam"; @Override public SmsResult send(String phone, String content) { SmsResult smsResult = new SmsResult(); smsResult.setSuccessful(false); return smsResult; } /** * 短信发送,支持向多个不同的手机号码发送同样内容的短信 * * @param phoneNumbers 必填,接收短信的手机号码。 * 格式: * 国内短信:11位手机号码,例如15951955195。 * 国际/港澳台消息:国际区号+号码,例如85200000000。 * 支持对多个手机号码发送短信,手机号码之间以英文逗号(,)分隔。上限为1000个手机号码。批量调用相对于单条调用及时性稍有延迟 * signName 必填,短信签名名称 * @param templateId 必填,短信模板ID * @param params 必填,短信模板变量对应的实际值,JSON格式 * 腾讯云短信模板参数是数组,因此短信模板形式如 “短信参数{1}, 短信参数{2}” * 阿里云短信模板参数是JSON,因此短信模板形式如“短信参数{param1}, 短信参数{param2}” * @return SmsResult SmsResult */ @Override public SmsResult sendWithTemplate(String phoneNumbers, String templateId, String[] params) { DefaultProfile profile = DefaultProfile.getProfile(this.regionId, this.accessKeyId, this.accessKeySecret); IAcsClient client = new DefaultAcsClient(profile); CommonRequest request = new CommonRequest(); request.setMethod(MethodType.POST); request.setDomain(DOMAIN); request.setVersion(VERSION); request.setAction(SEND_SMS_ACTION); request.putQueryParameter(REGIN_ID_NAME, this.regionId); request.putQueryParameter(PHONE_NUMBERS, phoneNumbers); request.putQueryParameter(SIGN_NAME, this.sign); request.putQueryParameter(TEMPLATE_CODE, templateId); String templateParam = params[0]; request.putQueryParameter(TEMPLATE_PARAM, templateParam); SmsResult smsResult = new SmsResult(); smsResult.setSuccessful(false); try { CommonResponse response = client.getCommonResponse(request); smsResult.setResult(response); String code = String.valueOf(JSONUtil.parseObj(response.getData()).get("Code")); if (response.getHttpResponse().isSuccess() && okCode.equals(code)) { smsResult.setSuccessful(true); } else { logger.error("短信发送失败:" + response.getData()); } } catch (Exception e) { logger.error("短信发送失败:", e); } return smsResult; } }
import lombok.Data; import org.springframework.mail.MailSender; import org.springframework.mail.SimpleMailMessage; import org.springframework.scheduling.annotation.Async; import java.util.ArrayList; import java.util.List; import java.util.Map; /** * 通知服务类 * 不注入 根据 配置参数 手动注入 * * @author YZD */ @Data public class NotifyService { /** * 邮件发送者 */ private String sendFrom; /** * 邮件接受者 */ private String sendTo; /** * 邮件发送 接口 */ private MailSender mailSender; /** * 短信 发送接口 */ private SmsSender smsSender; /** * 短信 模板 列表 */ private List<Map<String, String>> smsTemplate = new ArrayList<>(); /** * 是否启用 短信 * * @return 是否启用 */ public boolean isSmsEnable() { return smsSender != null; } /** * 是否启用 邮件 * * @return 是否启用 邮件 */ public boolean isMailEnable() { return mailSender != null; } /** * 短信消息通知 异步 * * @param phoneNumber 接收通知的电话号码 * @param message 短消息内容,这里短消息内容必须已经在短信平台审核通过 * 阿里云必须要模板 */ @Async public void notifySms(String phoneNumber, String message) { if (smsSender == null) { return; } smsSender.send(phoneNumber, message); } /** * 短信模版消息通知 异步 * * @param phoneNumbers 必填,接收短信的手机号码。 * 格式: * 国内短信:11位手机号码,例如15951955195。 * 国际/港澳台消息:国际区号+号码,例如85200000000。 * 支持对多个手机号码发送短信,手机号码之间以英文逗号(,)分隔。上限为1000个手机号码。批量调用相对于单条调用及时性稍有延迟 * signName 必填,短信签名名称 * @param notifyType 通知类别,通过该枚举值在配置文件中获取相应的模版ID * @param params 通知模版内容里的参数,类似"您的验证码为{1}"中{1}的值 * 必填,短信模板变量对应的实际值,JSON格式 * 腾讯云短信模板参数是数组,因此短信模板形式如 “短信参数{1}, 短信参数{2}” * 阿里云短信模板参数是JSON,因此短信模板形式如“短信参数{param1}, 短信参数{param2}” */ @Async public void notifySmsTemplate(String phoneNumbers, NotifyType notifyType, String[] params) { if (smsSender == null) { return; } String templateIdStr = getTemplateId(notifyType, smsTemplate); if (templateIdStr == null) { return; } smsSender.sendWithTemplate(phoneNumbers, templateIdStr, params); } /** * 发送短信模版消息通知 同步 * * @param phoneNumbers 必填,接收短信的手机号码。 * 格式: * 国内短信:11位手机号码,例如15951955195。 * 国际/港澳台消息:国际区号+号码,例如85200000000。 * 支持对多个手机号码发送短信,手机号码之间以英文逗号(,)分隔。上限为1000个手机号码。批量调用相对于单条调用及时性稍有延迟 * signName 必填,短信签名名称 * @param notifyType 通知类别,通过该枚举值在配置文件中获取相应的模版ID * 必填,短信模板变量对应的实际值,JSON格式 * 腾讯云短信模板参数是数组,因此短信模板形式如 “短信参数{1}, 短信参数{2}” * 阿里云短信模板参数是JSON,因此短信模板形式如“短信参数{param1}, 短信参数{param2}” * @return SmsResult SmsResult */ public SmsResult notifySmsTemplateSync(String phoneNumbers, NotifyType notifyType, String[] params) { if (smsSender == null) { return null; } return smsSender.sendWithTemplate(phoneNumbers, getTemplateId(notifyType, smsTemplate), params); } /** * 邮件消息通知, 异步 * 接收者在spring.mail.sendto中指定 * * @param subject 邮件标题 * @param content 邮件内容 */ @Async public void notifyMail(String subject, String content) { if (mailSender == null) { return; } SimpleMailMessage message = new SimpleMailMessage(); message.setFrom(sendFrom); message.setTo(sendTo); message.setSubject(subject); message.setText(content); mailSender.send(message); } /** * 获取 短信 发送 模板 标识 * * @param notifyType 模板类型 名称 * @param values 模板列表 map * @return */ private String getTemplateId(NotifyType notifyType, List<Map<String, String>> values) { for (Map<String, String> item : values) { String notifyTypeStr = notifyType.getType(); if (item.get("name").equalsIgnoreCase(notifyTypeStr)) { return item.get("templateId"); } } return null; } }
import com.zbwd.plan.PlanApplication; 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.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Import; import org.springframework.context.annotation.Primary; import org.springframework.core.task.SyncTaskExecutor; import org.springframework.test.context.junit4.SpringRunner; import org.springframework.test.context.web.WebAppConfiguration; import java.util.concurrent.Executor; /** * 测试短信发送服务 * <p> * 注意LitemallNotifyService采用异步线程操作 * 因此测试的时候需要睡眠一会儿,保证任务执行 * <p> * 开发者需要确保: * 1. 在腾讯云短信平台设置短信签名和短信模板notify.properties已经设置正确 * 2. 在腾讯云短信平台设置短信签名和短信模板 * 3. 在当前测试类设置好正确的手机号码 */ @WebAppConfiguration @RunWith(SpringRunner.class) @SpringBootTest public class SmsTest { @Autowired private NotifyService notifyService; @Test public void testCaptcha() { String phone = "xxxxxxxxxxx"; String[] params = new String[]{"123456"}; notifyService.notifySmsTemplate(phone, NotifyType.REFUND, params); } @Test public void testPaySucceed() { String phone = "xxxxxxxxxxx"; String[] params = new String[]{"123456"}; notifyService.notifySmsTemplate(phone, NotifyType.REFUND, params); } @Test public void testShip() { String phone = "xxxxxxxxxxx"; String[] params = new String[]{"123456"}; notifyService.notifySmsTemplate(phone, NotifyType.REFUND, params); } @Test public void testRefund() { String phone = "xxxxxxxxxxx"; String[] params = new String[]{"123456"}; notifyService.notifySmsTemplate(phone, NotifyType.REFUND, params); } @Configuration @Import(PlanApplication.class) static class ContextConfiguration { @Bean @Primary public Executor executor() { return new SyncTaskExecutor(); } } }
import com.zbwd.plan.PlanApplication; 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.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Import; import org.springframework.context.annotation.Primary; import org.springframework.core.task.SyncTaskExecutor; import org.springframework.test.context.junit4.SpringRunner; import org.springframework.test.context.web.WebAppConfiguration; import java.util.concurrent.Executor; /** * 测试邮件发送服务 * <p> * 注意LitemallNotifyService采用异步线程操作 * 因此测试的时候需要睡眠一会儿,保证任务执行 * <p> * 开发者需要确保: * 1. 在相应的邮件服务器设置正确notify.properties已经设置正确 * 2. 在相应的邮件服务器设置正确 */ @WebAppConfiguration @RunWith(SpringRunner.class) @SpringBootTest public class MailTest { @Autowired private NotifyService notifyService; @Test public void testMail() { notifyService.notifyMail("订单信息", "订单1111111已付款,请发货"); } @Configuration @Import(PlanApplication.class) static class ContextConfiguration { @Bean @Primary public Executor executor() { return new SyncTaskExecutor(); } } }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。