Commit 09c169c1 authored by beaver383's avatar beaver383
Browse files

Merge branch 'master' of https://github.com/beaver383/litemall

parents 1fddef33 d1e584a4
......@@ -61,8 +61,10 @@ litemall:
# 短信息用于通知客户,例如发货短信通知,注意配置格式;template-name,template-templateId 请参考 NotifyType 枚举值
sms:
enable: false
appid: 111111111
appkey: xxxxxxxxxxxxxx
# 如果是腾讯云短信,则设置active的值tencent
# 如果是阿里云短信,则设置active的值aliyun
active: tencent
sign: litemall
template:
- name: paySucceed
templateId: 156349
......@@ -72,6 +74,13 @@ litemall:
templateId: 158002
- name: refund
templateId: 159447
tencent:
appid: 111111111
appkey: xxxxxxxxxxxxxx
aliyun:
regionId: xxx
accessKeyId: xxx
accessKeySecret: xxx
# 微信模版通知配置
# 微信模版用于通知客户或者运营者,注意配置格式;template-name,template-templateId 请参考 NotifyType 枚举值
......
......@@ -589,24 +589,33 @@ litemall:
# 短信息用于通知客户,例如发货短信通知,注意配置格式;template-name,template-templateId 请参考 NotifyType 枚举值
sms:
enable: false
appid: 111111111
appkey: xxxxxxxxxxxxxx
# 如果是腾讯云短信,则设置active的值tencent
# 如果是阿里云短信,则设置active的值aliyun
active: tencent
sign: litemall
template:
- name: paySucceed
templateId: 156349
- name: captcha
templateId: 156433
- name: ship
templateId: 158002
- name: refund
templateId: 159447
- name: paySucceed
templateId: 156349
- name: captcha
templateId: 156433
- name: ship
templateId: 158002
- name: refund
templateId: 159447
tencent:
appid: 111111111
appkey: xxxxxxxxxxxxxx
aliyun:
regionId: xxx
accessKeyId: xxx
accessKeySecret: xxx
```
配置方式:
1. 腾讯云短信平台申请,然后设置四个场景的短信模板;
2. 开发者在配置文件设置`enable`的值`true`,然后其他信息设置
腾讯云短信平台申请的appid等值。
这里只测试过腾讯云短信平台,开发者需要自行测试其他短信云平台。
1. 腾讯云短信平台或者阿里云短信平台申请,然后设置四个场景的短信模板;
2. 开发者在配置文件设置`enable`的值`true`,设置`active`的值`tencent`或`aliyun`
3. 然后配置其他信息,例如腾讯云短信平台申请的appid等值。
这里只测试过腾讯云短信平台和阿里云短信平台,开发者需要自行测试其他短信云平台。
应用场景:
目前短信通知场景只支持支付成功、验证码、订单发送、退款成功四种情况。
......@@ -616,6 +625,17 @@ litemall:
当配置好信息以后,开发者可以litemall-core模块的`SmsTest`测试类中设置手机号和
模板所需要的参数值,独立启动`SmsTest`测试类发送短信,然后查看手机是否成功接收短信。
短信模板参数命名:
这里存在一个问题,即腾讯云短信的官方平台中申请短信模板格式的模板参数是数组,
例如“你好,验证码是{0},时间是{1}";
而阿里云短信的官方平台中申请短信模板的模板参数是JSON,
例如“你好,验证码是{param1},时间是{param2}"。
为了保持当前代码的通用性,本项目采用数组传递参数,而对阿里云申请模板的参数做了一定的假设:
1. 腾讯云模块参数,申请模板时按照官方设置即可,例如“你好,验证码是{0},时间是{1}";
2. 阿里云模板参数,本项目假定开发者在官方申请的参数格式应该采用"{ code: xxx, code1: xxx, code2: xxx }",
例如“你好,验证码是{code},时间是{code1}"。开发者可以查看`AliyunSmsSender`类的`sendWithTemplate`方法的
源代码即可理解。如果觉得不合理,可以自行调整相关代码。
#### 1.4.5.7 微信通知配置
微信通知是微信上收到的服务通知。
......@@ -867,32 +887,38 @@ litemall:
如果开发者设置SSH密钥,可以采用免密码登录;否则采用账号和密码登录。
#### 1.5.1.2 JDK8
#### 1.5.1.2 OpenJDK8
https://www.digitalocean.com/community/tutorials/how-to-install-java-with-apt-get-on-ubuntu-16-04
这里可以安装openjdk-8-jre
http://www.webupd8.org/2012/09/install-oracle-java-8-in-ubuntu-via-ppa.html
```bash
sudo apt-get update
sudo apt-get install openjdk-8-jre
```
如果希望采用jdk,而不是jre,则可以运行
```bash
sudo add-apt-repository ppa:webupd8team/java
sudo apt-get update
sudo apt-get install oracle-java8-installer
sudo apt-get install oracle-java8-set-default
sudo apt-get install openjdk-8-jdk
```
警告
> "ppa:webupd8team/java" 不是Oracle官方PPA,可能存在安全隐患
注意
> 如果用户想采用Oracle JDK8或者其他JDK环境,请查阅相关资料安装
#### 1.5.1.3 MySQL
https://www.digitalocean.com/community/tutorials/how-to-install-mysql-on-ubuntu-16-04
```
sudo apt-get update
sudo apt-get install mysql-server
sudo apt-get install mysql-client
```
如果配置MySQL,可以运行命令
```
mysql_secure_installation
```
#### 1.5.1.4 项目打包
1. 在主机或者开发机打包项目到deploy;
......
......@@ -16,6 +16,12 @@
<artifactId>hibernate-validator</artifactId>
</dependency>
<dependency>
<groupId>com.aliyun</groupId>
<artifactId>aliyun-java-sdk-core</artifactId>
<version>4.0.3</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
......
package org.linlinjava.litemall.core.notify;
import com.aliyuncs.CommonRequest;
import com.aliyuncs.CommonResponse;
import com.aliyuncs.DefaultAcsClient;
import com.aliyuncs.IAcsClient;
import com.aliyuncs.exceptions.ClientException;
import com.aliyuncs.exceptions.ServerException;
import com.aliyuncs.http.MethodType;
import com.aliyuncs.profile.DefaultProfile;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.linlinjava.litemall.core.util.JacksonUtil;
import java.util.HashMap;
import java.util.Map;
/*
* 阿里云短信服务
*/
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;
public String getRegionId() {
return regionId;
}
public void setRegionId(String regionId) {
this.regionId = regionId;
}
public String getAccessKeyId() {
return accessKeyId;
}
public void setAccessKeyId(String accessKeyId) {
this.accessKeyId = accessKeyId;
}
public String getAccessKeySecret() {
return accessKeySecret;
}
public void setAccessKeySecret(String accessKeySecret) {
this.accessKeySecret = accessKeySecret;
}
public String getSign() {
return sign;
}
public void setSign(String sign) {
this.sign = sign;
}
@Override
public SmsResult send(String phone, String content) {
SmsResult smsResult = new SmsResult();
smsResult.setSuccessful(false);
return smsResult;
}
@Override
public SmsResult sendWithTemplate(String phone, 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("dysmsapi.aliyuncs.com");
request.setVersion("2017-05-25");
request.setAction("SendSms");
request.putQueryParameter("RegionId", this.regionId);
request.putQueryParameter("PhoneNumbers", phone);
request.putQueryParameter("SignName", this.sign);
request.putQueryParameter("TemplateCode", templateId);
/*
NOTE:阿里云短信和腾讯云短信这里存在不一致
腾讯云短信模板参数是数组,因此短信模板形式如 “短信参数{1}, 短信参数{2}”
阿里云短信模板参数是JSON,因此短信模板形式如“短信参数{param1}, 短信参数{param2}”
为了保持统一,我们假定阿里云短信里面的参数是code,code1,code2...
如果开发者在阿里云短信申请的模板参数是其他命名,请开发者自行调整这里的代码,或者直接写死。
*/
String templateParam = "{}";
if(params.length == 1){
Map<String, String> data = new HashMap<>();
data.put("code", params[0]);
templateParam = JacksonUtil.toJson(data);
}
else if(params.length > 1){
Map<String, String> data = new HashMap<>();
data.put("code", params[0]);
for(int i = 1; i < params.length; i++){
data.put("code" + i, params[i]);
}
templateParam = JacksonUtil.toJson(data);
}
request.putQueryParameter("TemplateParam", templateParam);
try {
CommonResponse response = client.getCommonResponse(request);
SmsResult smsResult = new SmsResult();
smsResult.setSuccessful(true);
smsResult.setResult(response);
return smsResult;
} catch (ServerException e) {
e.printStackTrace();
} catch (ClientException e) {
e.printStackTrace();
}
SmsResult smsResult = new SmsResult();
smsResult.setSuccessful(false);
return smsResult;
}
}
......@@ -66,8 +66,7 @@ public class NotifyService {
return;
}
int templateId = Integer.parseInt(templateIdStr);
smsSender.sendWithTemplate(phoneNumber, templateId, params);
smsSender.sendWithTemplate(phoneNumber, templateIdStr, params);
}
/**
......@@ -82,9 +81,7 @@ public class NotifyService {
if (smsSender == null)
return null;
int templateId = Integer.parseInt(getTemplateId(notifyType, smsTemplate));
return smsSender.sendWithTemplate(phoneNumber, templateId, params);
return smsSender.sendWithTemplate(phoneNumber, getTemplateId(notifyType, smsTemplate), params);
}
/**
......
......@@ -13,10 +13,9 @@ public interface SmsSender {
/**
* 通过短信模版发送短信息
*
* @param phone 接收通知的电话号码
* @param phone 接收通知的电话号码
* @param templateId 通知模板ID
* @param params 通知模版内容里的参数,类似"您的验证码为{1}"中{1}的值
*/
SmsResult sendWithTemplate(String phone, int templateId, String[] params);
SmsResult sendWithTemplate(String phone, String templateId, String[] params);
}
\ No newline at end of file
......@@ -15,6 +15,7 @@ public class TencentSmsSender implements SmsSender {
private final Log logger = LogFactory.getLog(TencentSmsSender.class);
private SmsSingleSender sender;
private String sign;
public SmsSingleSender getSender() {
return sender;
......@@ -38,13 +39,15 @@ public class TencentSmsSender implements SmsSender {
logger.error(e.getMessage(), e);
}
return null;
SmsResult smsResult = new SmsResult();
smsResult.setSuccessful(false);
return smsResult;
}
@Override
public SmsResult sendWithTemplate(String phone, int templateId, String[] params) {
public SmsResult sendWithTemplate(String phone, String templateId, String[] params) {
try {
SmsSingleSenderResult result = sender.sendWithParam("86", phone, templateId, params, "", "", "");
SmsSingleSenderResult result = sender.sendWithParam("86", phone, Integer.parseInt(templateId), params, this.sign, "", "");
logger.debug(result);
SmsResult smsResult = new SmsResult();
......@@ -55,6 +58,12 @@ public class TencentSmsSender implements SmsSender {
logger.error(e.getMessage(), e);
}
return null;
SmsResult smsResult = new SmsResult();
smsResult.setSuccessful(false);
return smsResult;
}
public void setSign(String sign) {
this.sign = sign;
}
}
package org.linlinjava.litemall.core.notify.config;
import com.github.qcloudsms.SmsSingleSender;
import org.linlinjava.litemall.core.notify.AliyunSmsSender;
import org.linlinjava.litemall.core.notify.NotifyService;
import org.linlinjava.litemall.core.notify.TencentSmsSender;
import org.linlinjava.litemall.core.notify.WxTemplateSender;
......@@ -33,7 +34,13 @@ public class NotifyAutoConfiguration {
NotifyProperties.Sms smsConfig = properties.getSms();
if (smsConfig.isEnable()) {
notifyService.setSmsSender(tencentSmsSender());
if(smsConfig.getActive().equals("tencent")) {
notifyService.setSmsSender(tencentSmsSender());
}
else if(smsConfig.getActive().equals("aliyun")) {
notifyService.setSmsSender(aliyunSmsSender());
}
notifyService.setSmsTemplate(smsConfig.getTemplate());
}
......@@ -65,7 +72,21 @@ public class NotifyAutoConfiguration {
public TencentSmsSender tencentSmsSender() {
NotifyProperties.Sms smsConfig = properties.getSms();
TencentSmsSender smsSender = new TencentSmsSender();
smsSender.setSender(new SmsSingleSender(smsConfig.getAppid(), smsConfig.getAppkey()));
NotifyProperties.Sms.Tencent tencent = smsConfig.getTencent();
smsSender.setSender(new SmsSingleSender(tencent.getAppid(), tencent.getAppkey()));
smsSender.setSign(smsConfig.getSign());
return smsSender;
}
@Bean
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;
}
}
......@@ -95,8 +95,10 @@ public class NotifyProperties {
public static class Sms {
private boolean enable;
private int appid;
private String appkey;
private String active;
private String sign;
private Tencent tencent;
private Aliyun aliyun;
private List<Map<String, String>> template = new ArrayList<>();
public boolean isEnable() {
......@@ -107,28 +109,95 @@ public class NotifyProperties {
this.enable = enable;
}
public int getAppid() {
return appid;
public List<Map<String, String>> getTemplate() {
return template;
}
public void setAppid(int appid) {
this.appid = appid;
public void setTemplate(List<Map<String, String>> template) {
this.template = template;
}
public String getAppkey() {
return appkey;
public String getActive() {
return active;
}
public void setAppkey(String appkey) {
this.appkey = appkey;
public void setActive(String active) {
this.active = active;
}
public List<Map<String, String>> getTemplate() {
return template;
public String getSign() {
return sign;
}
public void setTemplate(List<Map<String, String>> template) {
this.template = template;
public void setSign(String sign) {
this.sign = sign;
}
public Tencent getTencent() {
return tencent;
}
public void setTencent(Tencent tencent) {
this.tencent = tencent;
}
public Aliyun getAliyun() {
return aliyun;
}
public void setAliyun(Aliyun aliyun) {
this.aliyun = aliyun;
}
public static class Tencent {
private int appid;
private String appkey;
public int getAppid() {
return appid;
}
public void setAppid(int appid) {
this.appid = appid;
}
public String getAppkey() {
return appkey;
}
public void setAppkey(String appkey) {
this.appkey = appkey;
}
}
public static class Aliyun {
private String regionId;
private String accessKeyId;
private String accessKeySecret;
public String getRegionId() {
return regionId;
}
public void setRegionId(String regionId) {
this.regionId = regionId;
}
public String getAccessKeyId() {
return accessKeyId;
}
public void setAccessKeyId(String accessKeyId) {
this.accessKeyId = accessKeyId;
}
public String getAccessKeySecret() {
return accessKeySecret;
}
public void setAccessKeySecret(String accessKeySecret) {
this.accessKeySecret = accessKeySecret;
}
}
}
......
package org.linlinjava.litemall.core.util;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
......@@ -161,4 +162,13 @@ public class JacksonUtil {
return null;
}
public static String toJson(Object data) {
ObjectMapper objectMapper = new ObjectMapper();
try {
return objectMapper.writeValueAsString(data);
} catch (JsonProcessingException e) {
e.printStackTrace();
}
return null;
}
}
......@@ -25,8 +25,10 @@ litemall:
# 短信息用于通知客户,例如发货短信通知,注意配置格式;template-name,template-templateId 请参考 NotifyType 枚举值
sms:
enable: false
appid: 111111111
appkey: xxxxxxxxxxxxxx
# 如果是腾讯云短信,则设置active的值tencent
# 如果是阿里云短信,则设置active的值aliyun
active: tencent
sign: litemall
template:
- name: paySucceed
templateId: 156349
......@@ -36,6 +38,14 @@ litemall:
templateId: 158002
- name: refund
templateId: 159447
tencent:
appid: 111111111
appkey: xxxxxxxxxxxxxx
aliyun:
regionId: xxx
accessKeyId: xxx
accessKeySecret: xxx
# 微信模版通知配置
# 微信模版用于通知客户或者运营者,注意配置格式;template-name,template-templateId 请参考 NotifyType 枚举值
......@@ -87,7 +97,7 @@ litemall:
# 对象存储配置
storage:
# 当前工作的对象存储模式,分别是local、aliyun、tencent、qiniu
active: local
active: tencent
# 本地对象存储配置信息
local:
storagePath: storage
......@@ -102,10 +112,10 @@ litemall:
# 腾讯对象存储配置信息
# 请参考 https://cloud.tencent.com/document/product/436/6249
tencent:
secretId: 111111
secretKey: xxxxxx
region: xxxxxx
bucketName: litemall
secretId: AKIDOccMr856uoU1Tsa2MQL5aqseBUWRrb5i
secretKey: XqtgEhIdrupTs4ygaWlkUUXv3w3FiwuD
region: ap-shanghai
bucketName: vytech-1300096589
# 七牛云对象存储配置信息
qiniu:
endpoint: http://pd5cb6ulu.bkt.clouddn.com
......
......@@ -115,7 +115,7 @@
<dependency>
<groupId>com.qcloud</groupId>
<artifactId>cos_api</artifactId>
<version>5.4.4</version>
<version>5.6.8</version>
</dependency>
<dependency>
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment