- 各短信平台兼容问题,放弃 sign 和 template 模板审核过程
- 增加短信类型 - 云片ok - 阿里云 未完成
This commit is contained in:
parent
e8e4a4781c
commit
74724637b7
@ -330,7 +330,7 @@ public class OrderServiceImpl implements OrderService {
|
|||||||
// if (commonResult.isError()) {
|
// if (commonResult.isError()) {
|
||||||
// //手动开启事务回滚
|
// //手动开启事务回滚
|
||||||
// TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
|
// TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
|
||||||
// return ServiceExceptionUtil.error(OrderErrorCodeEnum.ORDER_GET_PAY_FAIL.getCode());
|
// return ServiceExceptionUtil.error(OrderErrorCodeEnum.ORDER_GET_PAY_FAIL.getValue());
|
||||||
// }
|
// }
|
||||||
|
|
||||||
// TODO: 2019-03-17 Sin 需要发送 创建成果 MQ 消息,业务扩展和统计
|
// TODO: 2019-03-17 Sin 需要发送 创建成果 MQ 消息,业务扩展和统计
|
||||||
|
@ -1,116 +0,0 @@
|
|||||||
package cn.iocoder.mall.admin.api;
|
|
||||||
|
|
||||||
import lombok.Data;
|
|
||||||
import lombok.experimental.Accessors;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 短信平台
|
|
||||||
*
|
|
||||||
* @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 template 模板内容
|
|
||||||
* @param tplType 1 为验证码类型,其他为 null
|
|
||||||
*/
|
|
||||||
Result createTemplate(String template, Integer tplType);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 模板 - 获取
|
|
||||||
*
|
|
||||||
* @param tplId
|
|
||||||
*/
|
|
||||||
Result getTemplate(String tplId);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 模板 - 更新
|
|
||||||
*
|
|
||||||
* @param tplId 选用的哪个签名
|
|
||||||
* @param template 模板内容
|
|
||||||
* @param tplType 1 为验证码类型,其他为 null
|
|
||||||
*/
|
|
||||||
Result updateTemplate(String tplId, String template, Integer tplType);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 模板 - 删除
|
|
||||||
*
|
|
||||||
* @param tplId
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
Result deleteTemplate(String tplId);
|
|
||||||
|
|
||||||
|
|
||||||
@Data
|
|
||||||
@Accessors(chain = true)
|
|
||||||
class SendResult {
|
|
||||||
|
|
||||||
private Boolean hasSuccess;
|
|
||||||
|
|
||||||
private Integer code;
|
|
||||||
|
|
||||||
private String message;
|
|
||||||
|
|
||||||
private List<String> success;
|
|
||||||
|
|
||||||
private List<String> fail;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 短信发送 - 单个
|
|
||||||
*
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
SendResult singleSend(String mobile, String template);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 短信发送 - 批量
|
|
||||||
*
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
SendResult batchSend(List<String> mobileList, String template);
|
|
||||||
}
|
|
@ -39,47 +39,56 @@ public interface SmsService {
|
|||||||
*
|
*
|
||||||
* @param sign
|
* @param sign
|
||||||
*/
|
*/
|
||||||
void createSign(String sign);
|
void createSign(String sign, Integer platform);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 签名 - 获取
|
* 签名 - 获取
|
||||||
*
|
*
|
||||||
* @param sign
|
* @param id
|
||||||
*/
|
*/
|
||||||
SmsSignBO getSign(String sign);
|
SmsSignBO getSign(Integer id);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 签名 - 更新
|
* 签名 - 更新
|
||||||
*
|
*
|
||||||
* @param oldSign
|
* @param id
|
||||||
* @param sign
|
* @param newSign
|
||||||
|
* @param platform
|
||||||
*/
|
*/
|
||||||
void updateSign(String oldSign, String sign);
|
void updateSign(Integer id, String newSign, Integer platform);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 签名 - 更新
|
||||||
|
*
|
||||||
|
* @param id
|
||||||
|
*/
|
||||||
|
void deleteSign(Integer id);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 模板 - 创建
|
* 模板 - 创建
|
||||||
*
|
*
|
||||||
* @param smsSignId 选用的哪个签名
|
* @param smsSignId 选用的哪个签名
|
||||||
* @param template 模板内容
|
* @param template 模板内容
|
||||||
* @param tplType 1 为验证码类型,其他为 null
|
* @param platform 平台
|
||||||
*/
|
*/
|
||||||
void createTemplate(Integer smsSignId, String template, Integer tplType);
|
void createTemplate(Integer smsSignId, String template, Integer platform, Integer smsType);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 模板 - 获取
|
* 模板 - 获取
|
||||||
*
|
*
|
||||||
* @param id
|
* @param id
|
||||||
*/
|
*/
|
||||||
SmsTemplateBO getTemplate(Integer id);
|
SmsTemplateBO getTemplate(Integer id, Integer platform);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 模板 - 更新
|
* 模板 - 更新
|
||||||
*
|
*
|
||||||
* @param id 模板id
|
* @param id 模板id
|
||||||
|
* @param smsSignId 短期签名
|
||||||
* @param template 模板内容
|
* @param template 模板内容
|
||||||
* @param tplType 1 为验证码类型,其他为 null
|
* @param platform 短信平台
|
||||||
*/
|
*/
|
||||||
void updateTemplate(Integer id, String template, Integer tplType);
|
void updateTemplate(Integer id, Integer smsSignId, String template, Integer platform, Integer smsType);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 模板 - 删除
|
* 模板 - 删除
|
||||||
|
@ -56,6 +56,7 @@ public enum AdminErrorCodeEnum {
|
|||||||
SMS_SIGN_IS_EXISTENT(1002006002, "短信签名已存在"),
|
SMS_SIGN_IS_EXISTENT(1002006002, "短信签名已存在"),
|
||||||
SMS_TEMPLATE_NOT_EXISTENT(1002006020, "短信签名不存在"),
|
SMS_TEMPLATE_NOT_EXISTENT(1002006020, "短信签名不存在"),
|
||||||
SMS_TEMPLATE_IS_EXISTENT(1002006021, "短信签名不存在"),
|
SMS_TEMPLATE_IS_EXISTENT(1002006021, "短信签名不存在"),
|
||||||
|
SMS_NOT_SEND_CLIENT(1002006030, "短信没有发送的client"),
|
||||||
;
|
;
|
||||||
|
|
||||||
private final int code;
|
private final int code;
|
||||||
|
@ -0,0 +1,11 @@
|
|||||||
|
package cn.iocoder.mall.admin.api.constant;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 字典 key
|
||||||
|
*
|
||||||
|
* @author Sin
|
||||||
|
* @time 2019/5/25 3:36 PM
|
||||||
|
*/
|
||||||
|
public class DictKeyConstants {
|
||||||
|
|
||||||
|
}
|
@ -13,19 +13,19 @@ public enum SmsApplyStatusEnum {
|
|||||||
FAIL(3, "审核失败"),
|
FAIL(3, "审核失败"),
|
||||||
;
|
;
|
||||||
|
|
||||||
private final int code;
|
private final Integer value;
|
||||||
private final String message;
|
private final String name;
|
||||||
|
|
||||||
SmsApplyStatusEnum(int code, String message) {
|
SmsApplyStatusEnum(int code, String message) {
|
||||||
this.code = code;
|
this.value = code;
|
||||||
this.message = message;
|
this.name = message;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getCode() {
|
public int getValue() {
|
||||||
return code;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getMessage() {
|
public String getName() {
|
||||||
return message;
|
return name;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,30 @@
|
|||||||
|
package cn.iocoder.mall.admin.api.constant;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 短信审核状态
|
||||||
|
*
|
||||||
|
* @author Sin
|
||||||
|
* @time 2019/5/16 12:48 PM
|
||||||
|
*/
|
||||||
|
public enum SmsPlatformEnum {
|
||||||
|
|
||||||
|
YunPian(1, "云片"),
|
||||||
|
AliYun(2, "阿里云"),
|
||||||
|
;
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,31 @@
|
|||||||
|
package cn.iocoder.mall.admin.api.constant;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 短信审核状态
|
||||||
|
*
|
||||||
|
* @author Sin
|
||||||
|
* @time 2019/5/16 12:48 PM
|
||||||
|
*/
|
||||||
|
public enum SmsTypeEnum {
|
||||||
|
|
||||||
|
VERIFICATION_CODE(1, "验证码"),
|
||||||
|
NOTICE(1, "通知"),
|
||||||
|
MARKETING(2, "营销"),
|
||||||
|
;
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
@ -31,7 +31,6 @@
|
|||||||
<groupId>org.springframework</groupId>
|
<groupId>org.springframework</groupId>
|
||||||
<artifactId>spring-jdbc</artifactId>
|
<artifactId>spring-jdbc</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.alibaba</groupId>
|
<groupId>com.alibaba</groupId>
|
||||||
<artifactId>druid-spring-boot-starter</artifactId>
|
<artifactId>druid-spring-boot-starter</artifactId>
|
||||||
@ -72,12 +71,22 @@
|
|||||||
<artifactId>yunpian-java-sdk</artifactId>
|
<artifactId>yunpian-java-sdk</artifactId>
|
||||||
<version>1.2.7</version>
|
<version>1.2.7</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.aliyun</groupId>
|
||||||
|
<artifactId>aliyun-java-sdk-core</artifactId>
|
||||||
|
<version>4.1.0</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
<!-- test -->
|
<!-- test -->
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.springframework.boot</groupId>
|
<groupId>org.springframework.boot</groupId>
|
||||||
<artifactId>spring-boot-starter-test</artifactId>
|
<artifactId>spring-boot-starter-test</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.junit.jupiter</groupId>
|
||||||
|
<artifactId>junit-jupiter-api</artifactId>
|
||||||
|
<version>5.4.0</version>
|
||||||
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
<build>
|
<build>
|
||||||
|
@ -0,0 +1,83 @@
|
|||||||
|
package cn.iocoder.mall.admin.client;
|
||||||
|
|
||||||
|
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.springframework.beans.factory.annotation.Value;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
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 {
|
||||||
|
|
||||||
|
@Value("sms.aliYun.accessKeyId")
|
||||||
|
private String accessKeyId;
|
||||||
|
@Value("sms.aliYun.accessSecret")
|
||||||
|
private String accessSecret;
|
||||||
|
|
||||||
|
private static final String DOMAIN = "dysmsapi.aliyuncs.com";
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SendResult singleSend(String mobile, String sign, String template, Map<String, String> params) {
|
||||||
|
IAcsClient client = getClient();
|
||||||
|
CommonRequest request = new CommonRequest();
|
||||||
|
request.setMethod(MethodType.POST);
|
||||||
|
request.setDomain(DOMAIN);
|
||||||
|
request.setVersion("2017-05-25");
|
||||||
|
request.setAction("SendSms");
|
||||||
|
|
||||||
|
try {
|
||||||
|
CommonResponse response = client.getCommonResponse(request);
|
||||||
|
System.out.println(response.getData());
|
||||||
|
} catch (ClientException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SendResult batchSend(List<String> mobileList, String sign, String template, Map<String, String> params) {
|
||||||
|
|
||||||
|
// 获取 client
|
||||||
|
IAcsClient client = getClient();
|
||||||
|
|
||||||
|
// params
|
||||||
|
CommonRequest request = new CommonRequest();
|
||||||
|
request.setMethod(MethodType.POST);
|
||||||
|
request.setDomain(DOMAIN);
|
||||||
|
request.setVersion("2017-05-25");
|
||||||
|
request.setAction("SendBatchSms");
|
||||||
|
|
||||||
|
try {
|
||||||
|
CommonResponse response = client.getCommonResponse(request);
|
||||||
|
System.out.println(response.getData());
|
||||||
|
} catch (ServerException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
} catch (ClientException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取 client
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
private IAcsClient getClient() {
|
||||||
|
return new DefaultAcsClient(DefaultProfile.getProfile("default", accessKeyId, accessSecret));
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,41 @@
|
|||||||
|
package cn.iocoder.mall.admin.client;
|
||||||
|
|
||||||
|
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 {
|
||||||
|
|
||||||
|
@Data
|
||||||
|
@Accessors(chain = true)
|
||||||
|
class SendResult {
|
||||||
|
|
||||||
|
private Boolean isSuccess;
|
||||||
|
|
||||||
|
private Integer code;
|
||||||
|
|
||||||
|
private String message;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 短信发送 - 单个
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
SendResult singleSend(String mobile, String sign, String template, Map<String, String> params);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 短信发送 - 批量
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
SendResult batchSend(List<String> mobileList, String sign, String template, Map<String, String> params);
|
||||||
|
}
|
@ -0,0 +1,264 @@
|
|||||||
|
package cn.iocoder.mall.admin.client;
|
||||||
|
|
||||||
|
import cn.iocoder.common.framework.exception.ServiceException;
|
||||||
|
import cn.iocoder.mall.admin.api.constant.AdminErrorCodeEnum;
|
||||||
|
import cn.iocoder.mall.admin.api.constant.SmsApplyStatusEnum;
|
||||||
|
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;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 云片短信 - 批量推送最大数 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}")
|
||||||
|
private String apiKey;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SendResult singleSend(String mobile, String sign, String template, Map<String, String> templateParams) {
|
||||||
|
|
||||||
|
// build 模板
|
||||||
|
template = buildTemplate(sign, template, templateParams);
|
||||||
|
|
||||||
|
// 请求参数
|
||||||
|
Map<String, String> 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<String> mobileList, String sign, String template, Map<String, String> templateParams) {
|
||||||
|
|
||||||
|
// build 模板
|
||||||
|
template = buildTemplate(sign, template, templateParams);
|
||||||
|
|
||||||
|
// 最大发送数为 1000,我们设置为 500 个, 分段发送
|
||||||
|
int maxSendSize = MAX_BATCH_SIZE;
|
||||||
|
int maxSendSizeCount = mobileList.size() % maxSendSize;
|
||||||
|
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<String, String> 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(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 构建模板
|
||||||
|
*
|
||||||
|
* @param sign
|
||||||
|
* @param template
|
||||||
|
* @param params
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
private static String buildTemplate(String sign, String template, Map<String, String> params) {
|
||||||
|
if (CollectionUtils.isEmpty(params)) {
|
||||||
|
return template;
|
||||||
|
}
|
||||||
|
|
||||||
|
LOGGER.debug("模板构建 before -> {}", template);
|
||||||
|
|
||||||
|
for (Map.Entry<String, String> entry : params.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);
|
||||||
|
LOGGER.debug("模板构建 after -> {}", template);
|
||||||
|
return template;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 短信 status 和 云片状态 映射关系
|
||||||
|
*
|
||||||
|
* @param checkStatus
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
private static Integer smsStatusMapping(String checkStatus) {
|
||||||
|
Integer applyStatus;
|
||||||
|
switch (checkStatus) {
|
||||||
|
case "SUCCESS":
|
||||||
|
applyStatus = SmsApplyStatusEnum.SUCCESS.getValue();
|
||||||
|
break;
|
||||||
|
case "FAIL":
|
||||||
|
applyStatus = SmsApplyStatusEnum.FAIL.getValue();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
applyStatus = SmsApplyStatusEnum.CHECKING.getValue();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return applyStatus;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 基于HttpClient 4.3的通用POST方法
|
||||||
|
*
|
||||||
|
* @param url 提交的URL
|
||||||
|
* @param paramsMap 提交<参数,值>Map
|
||||||
|
* @return 提交响应
|
||||||
|
*/
|
||||||
|
|
||||||
|
public static String post(String url, Map<String, String> paramsMap) {
|
||||||
|
|
||||||
|
// TODO: 2019/5/25 Sin 这个地方需要 记录日志
|
||||||
|
CloseableHttpClient client = HttpClients.createDefault();
|
||||||
|
String responseText = "";
|
||||||
|
CloseableHttpResponse response = null;
|
||||||
|
try {
|
||||||
|
HttpPost method = new HttpPost(url);
|
||||||
|
if (paramsMap != null) {
|
||||||
|
List<NameValuePair> paramList = new ArrayList<>();
|
||||||
|
for (Map.Entry<String, String> 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;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,33 @@
|
|||||||
|
package cn.iocoder.mall.admin.dataobject;
|
||||||
|
|
||||||
|
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 SmsClientLog extends BaseDO {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 编号
|
||||||
|
*/
|
||||||
|
private Integer id;
|
||||||
|
/**
|
||||||
|
* 短信模板
|
||||||
|
*/
|
||||||
|
private Integer templateId;
|
||||||
|
/**
|
||||||
|
* 短信
|
||||||
|
*/
|
||||||
|
private String template;
|
||||||
|
/**
|
||||||
|
* 发送信息
|
||||||
|
*/
|
||||||
|
private String message;
|
||||||
|
}
|
@ -22,14 +22,17 @@ public class SmsSignDO extends DeletableDO {
|
|||||||
* 编号
|
* 编号
|
||||||
*/
|
*/
|
||||||
private Integer id;
|
private Integer id;
|
||||||
/**
|
|
||||||
* 签名id 这个是第三方的
|
|
||||||
*/
|
|
||||||
private String platformId;
|
|
||||||
/**
|
/**
|
||||||
* 签名名称
|
* 签名名称
|
||||||
*/
|
*/
|
||||||
private String sign;
|
private String sign;
|
||||||
|
/**
|
||||||
|
* 平台
|
||||||
|
*
|
||||||
|
* 1、云片
|
||||||
|
* 2、阿里云
|
||||||
|
*/
|
||||||
|
private Integer platform;
|
||||||
/**
|
/**
|
||||||
* 审核状态
|
* 审核状态
|
||||||
*
|
*
|
||||||
|
@ -28,11 +28,19 @@ public class SmsTemplateDO extends DeletableDO {
|
|||||||
/**
|
/**
|
||||||
* 短信签名 id
|
* 短信签名 id
|
||||||
*/
|
*/
|
||||||
private String platformId;
|
private Integer platform;
|
||||||
/**
|
/**
|
||||||
* 短信模板
|
* 短信模板
|
||||||
*/
|
*/
|
||||||
private String template;
|
private String template;
|
||||||
|
/**
|
||||||
|
* 短信类型
|
||||||
|
*
|
||||||
|
* - 验证码类
|
||||||
|
* - 通知类
|
||||||
|
* - 营销类
|
||||||
|
*/
|
||||||
|
private Integer smsType;
|
||||||
/**
|
/**
|
||||||
* 审核状态
|
* 审核状态
|
||||||
*
|
*
|
||||||
|
@ -2,7 +2,10 @@ package cn.iocoder.mall.admin.service;
|
|||||||
|
|
||||||
import cn.iocoder.common.framework.constant.DeletedStatusEnum;
|
import cn.iocoder.common.framework.constant.DeletedStatusEnum;
|
||||||
import cn.iocoder.common.framework.exception.ServiceException;
|
import cn.iocoder.common.framework.exception.ServiceException;
|
||||||
import cn.iocoder.mall.admin.api.SmsPlatform;
|
import cn.iocoder.mall.admin.api.DataDictService;
|
||||||
|
import cn.iocoder.mall.admin.api.constant.SmsApplyStatusEnum;
|
||||||
|
import cn.iocoder.mall.admin.api.constant.SmsPlatformEnum;
|
||||||
|
import cn.iocoder.mall.admin.client.SmsClient;
|
||||||
import cn.iocoder.mall.admin.api.SmsService;
|
import cn.iocoder.mall.admin.api.SmsService;
|
||||||
import cn.iocoder.mall.admin.api.bo.sms.SmsSignBO;
|
import cn.iocoder.mall.admin.api.bo.sms.SmsSignBO;
|
||||||
import cn.iocoder.mall.admin.api.bo.sms.PageSmsSignBO;
|
import cn.iocoder.mall.admin.api.bo.sms.PageSmsSignBO;
|
||||||
@ -49,8 +52,13 @@ public class SmsServiceImpl implements SmsService {
|
|||||||
private SmsTemplateMapper smsTemplateMapper;
|
private SmsTemplateMapper smsTemplateMapper;
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
@Qualifier("smsYunPianPlatform")
|
@Qualifier("smsYunPianClient")
|
||||||
private SmsPlatform smsPlatform;
|
private SmsClient smsYunPianClient;
|
||||||
|
@Autowired
|
||||||
|
@Qualifier("smsAliYunClient")
|
||||||
|
private SmsClient smsAliYunClient;
|
||||||
|
@Autowired
|
||||||
|
private DataDictService dataDictService;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public PageSmsSignBO pageSmsSign(PageQuerySmsSignDTO queryDTO) {
|
public PageSmsSignBO pageSmsSign(PageQuerySmsSignDTO queryDTO) {
|
||||||
@ -108,26 +116,26 @@ public class SmsServiceImpl implements SmsService {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
@Transactional
|
@Transactional
|
||||||
public void createSign(String sign) {
|
public void createSign(String sign, Integer platform) {
|
||||||
|
|
||||||
// 避免重复
|
// 避免重复
|
||||||
SmsSignDO smsSignDO = smsSignMapper.selectOne(
|
SmsSignDO smsSignDO = smsSignMapper.selectOne(
|
||||||
new QueryWrapper<SmsSignDO>().eq("sign", sign));
|
new QueryWrapper<SmsSignDO>()
|
||||||
|
.eq("platform", platform)
|
||||||
|
.eq("sign", sign)
|
||||||
|
);
|
||||||
|
|
||||||
if (smsSignDO != null) {
|
if (smsSignDO != null) {
|
||||||
throw new ServiceException(AdminErrorCodeEnum.SMS_SIGN_IS_EXISTENT.getCode(),
|
throw new ServiceException(AdminErrorCodeEnum.SMS_SIGN_IS_EXISTENT.getCode(),
|
||||||
AdminErrorCodeEnum.SMS_SIGN_IS_EXISTENT.getMessage());
|
AdminErrorCodeEnum.SMS_SIGN_IS_EXISTENT.getMessage());
|
||||||
}
|
}
|
||||||
|
|
||||||
// 创建平台 sign
|
|
||||||
SmsPlatform.Result result = smsPlatform.createSign(sign);
|
|
||||||
|
|
||||||
// 保存数据库
|
// 保存数据库
|
||||||
smsSignMapper.insert(
|
smsSignMapper.insert(
|
||||||
(SmsSignDO) new SmsSignDO()
|
(SmsSignDO) new SmsSignDO()
|
||||||
.setSign(sign)
|
.setSign(sign)
|
||||||
.setPlatformId(result.getId())
|
.setPlatform(platform)
|
||||||
.setApplyStatus(result.getApplyStatus())
|
.setApplyStatus(SmsApplyStatusEnum.SUCCESS.getValue())
|
||||||
.setDeleted(DeletedStatusEnum.DELETED_NO.getValue())
|
.setDeleted(DeletedStatusEnum.DELETED_NO.getValue())
|
||||||
.setUpdateTime(new Date())
|
.setUpdateTime(new Date())
|
||||||
.setCreateTime(new Date())
|
.setCreateTime(new Date())
|
||||||
@ -135,9 +143,11 @@ public class SmsServiceImpl implements SmsService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public SmsSignBO getSign(String sign) {
|
public SmsSignBO getSign(Integer signId) {
|
||||||
SmsSignDO smsSignDO = smsSignMapper.selectOne(
|
SmsSignDO smsSignDO = smsSignMapper.selectOne(
|
||||||
new QueryWrapper<SmsSignDO>().eq("sign", sign));
|
new QueryWrapper<SmsSignDO>()
|
||||||
|
.eq("id", signId)
|
||||||
|
.eq("deleted", DeletedStatusEnum.DELETED_NO.getValue()));
|
||||||
|
|
||||||
if (smsSignDO == null) {
|
if (smsSignDO == null) {
|
||||||
throw new ServiceException(AdminErrorCodeEnum.SMS_SIGN_NOT_EXISTENT.getCode(),
|
throw new ServiceException(AdminErrorCodeEnum.SMS_SIGN_NOT_EXISTENT.getCode(),
|
||||||
@ -149,33 +159,49 @@ public class SmsServiceImpl implements SmsService {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
@Transactional
|
@Transactional
|
||||||
public void updateSign(String oldSign, String sign) {
|
public void updateSign(Integer id, String newSign, Integer platform) {
|
||||||
// 避免重复
|
// 避免重复
|
||||||
SmsSignDO smsSignDO = smsSignMapper.selectOne(
|
SmsSignDO smsSignDO = smsSignMapper.selectOne(
|
||||||
new QueryWrapper<SmsSignDO>().eq("sign", oldSign));
|
new QueryWrapper<SmsSignDO>()
|
||||||
|
.eq("sign", newSign)
|
||||||
|
.eq("platform", platform));
|
||||||
|
|
||||||
|
if (smsSignDO != null) {
|
||||||
|
throw new ServiceException(AdminErrorCodeEnum.SMS_SIGN_IS_EXISTENT.getCode(),
|
||||||
|
AdminErrorCodeEnum.SMS_SIGN_IS_EXISTENT.getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
// 更新
|
||||||
|
smsSignMapper.update(
|
||||||
|
(SmsSignDO) new SmsSignDO()
|
||||||
|
.setSign(newSign)
|
||||||
|
.setPlatform(platform)
|
||||||
|
.setUpdateTime(new Date()),
|
||||||
|
new QueryWrapper<SmsSignDO>().eq("id", id)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void deleteSign(Integer id) {
|
||||||
|
SmsSignDO smsSignDO = smsSignMapper.selectOne(
|
||||||
|
new QueryWrapper<SmsSignDO>()
|
||||||
|
.eq("id", id));
|
||||||
|
|
||||||
if (smsSignDO == null) {
|
if (smsSignDO == null) {
|
||||||
throw new ServiceException(AdminErrorCodeEnum.SMS_SIGN_NOT_EXISTENT.getCode(),
|
throw new ServiceException(AdminErrorCodeEnum.SMS_SIGN_NOT_EXISTENT.getCode(),
|
||||||
AdminErrorCodeEnum.SMS_SIGN_NOT_EXISTENT.getMessage());
|
AdminErrorCodeEnum.SMS_SIGN_NOT_EXISTENT.getMessage());
|
||||||
}
|
}
|
||||||
|
|
||||||
// 更新平台
|
// 更新 deleted 为 YES
|
||||||
SmsPlatform.Result result = smsPlatform.updateSign(oldSign, sign);
|
smsSignMapper.delete(new UpdateWrapper<SmsSignDO>()
|
||||||
|
.set("deleted", DeletedStatusEnum.DELETED_YES.getName())
|
||||||
// 更新
|
.eq("id", id)
|
||||||
smsSignMapper.updateById(
|
|
||||||
(SmsSignDO) new SmsSignDO()
|
|
||||||
.setId(smsSignDO.getId())
|
|
||||||
.setPlatformId(result.getId())
|
|
||||||
.setSign(sign)
|
|
||||||
.setApplyStatus(result.getApplyStatus())
|
|
||||||
.setUpdateTime(new Date())
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@Transactional
|
@Transactional
|
||||||
public void createTemplate(Integer smsSignId, String template, Integer tplType) {
|
public void createTemplate(Integer smsSignId, String template, Integer platform, Integer smsType) {
|
||||||
|
|
||||||
SmsSignDO smsSignDO = smsSignMapper.selectOne(
|
SmsSignDO smsSignDO = smsSignMapper.selectOne(
|
||||||
new QueryWrapper<SmsSignDO>().eq("id", smsSignId));
|
new QueryWrapper<SmsSignDO>().eq("id", smsSignId));
|
||||||
@ -185,28 +211,27 @@ public class SmsServiceImpl implements SmsService {
|
|||||||
AdminErrorCodeEnum.SMS_SIGN_NOT_EXISTENT.getMessage());
|
AdminErrorCodeEnum.SMS_SIGN_NOT_EXISTENT.getMessage());
|
||||||
}
|
}
|
||||||
|
|
||||||
// 调用平台
|
|
||||||
SmsPlatform.Result result = smsPlatform
|
|
||||||
.createTemplate(String.format(SMS_TEMPLATE, smsSignDO.getSign(), template), tplType);
|
|
||||||
|
|
||||||
// 保存数据库
|
// 保存数据库
|
||||||
smsTemplateMapper.insert(
|
smsTemplateMapper.insert(
|
||||||
(SmsTemplateDO) new SmsTemplateDO()
|
(SmsTemplateDO) new SmsTemplateDO()
|
||||||
.setId(null)
|
.setId(null)
|
||||||
.setSmsSignId(smsSignId)
|
.setSmsSignId(smsSignId)
|
||||||
.setPlatformId(result.getId())
|
|
||||||
.setTemplate(template)
|
.setTemplate(template)
|
||||||
.setApplyStatus(result.getApplyStatus())
|
.setPlatform(platform)
|
||||||
.setApplyMessage(result.getApplyMessage())
|
.setSmsType(smsType)
|
||||||
|
.setApplyStatus(SmsApplyStatusEnum.SUCCESS.getValue())
|
||||||
|
.setApplyMessage("")
|
||||||
.setDeleted(DeletedStatusEnum.DELETED_NO.getValue())
|
.setDeleted(DeletedStatusEnum.DELETED_NO.getValue())
|
||||||
.setCreateTime(new Date())
|
.setCreateTime(new Date())
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public SmsTemplateBO getTemplate(Integer id) {
|
public SmsTemplateBO getTemplate(Integer id, Integer platform) {
|
||||||
SmsTemplateDO smsTemplateDO = smsTemplateMapper.selectOne(
|
SmsTemplateDO smsTemplateDO = smsTemplateMapper.selectOne(
|
||||||
new QueryWrapper<SmsTemplateDO>().eq("id", id));
|
new QueryWrapper<SmsTemplateDO>()
|
||||||
|
.eq("platform", platform)
|
||||||
|
.eq("id", id));
|
||||||
|
|
||||||
if (smsTemplateDO == null) {
|
if (smsTemplateDO == null) {
|
||||||
throw new ServiceException(AdminErrorCodeEnum.SMS_TEMPLATE_NOT_EXISTENT.getCode(),
|
throw new ServiceException(AdminErrorCodeEnum.SMS_TEMPLATE_NOT_EXISTENT.getCode(),
|
||||||
@ -218,7 +243,7 @@ public class SmsServiceImpl implements SmsService {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
@Transactional
|
@Transactional
|
||||||
public void updateTemplate(Integer id, String template, Integer tplType) {
|
public void updateTemplate(Integer id, Integer smsSignId, String template, Integer platform, Integer smsType) {
|
||||||
SmsTemplateDO smsTemplateDO = smsTemplateMapper.selectOne(
|
SmsTemplateDO smsTemplateDO = smsTemplateMapper.selectOne(
|
||||||
new QueryWrapper<SmsTemplateDO>().eq("id", id));
|
new QueryWrapper<SmsTemplateDO>().eq("id", id));
|
||||||
|
|
||||||
@ -230,16 +255,17 @@ public class SmsServiceImpl implements SmsService {
|
|||||||
SmsSignDO smsSignDO = smsSignMapper.selectOne(
|
SmsSignDO smsSignDO = smsSignMapper.selectOne(
|
||||||
new QueryWrapper<SmsSignDO>().eq("id", smsTemplateDO.getSmsSignId()));
|
new QueryWrapper<SmsSignDO>().eq("id", smsTemplateDO.getSmsSignId()));
|
||||||
|
|
||||||
|
if (smsSignDO == null) {
|
||||||
SmsPlatform.Result result = smsPlatform.updateTemplate(
|
throw new ServiceException(AdminErrorCodeEnum.SMS_SIGN_NOT_EXISTENT.getCode(),
|
||||||
smsTemplateDO.getPlatformId(),
|
AdminErrorCodeEnum.SMS_SIGN_NOT_EXISTENT.getMessage());
|
||||||
String.format(SMS_TEMPLATE, smsSignDO.getSign(), template), tplType);
|
}
|
||||||
|
|
||||||
smsTemplateMapper.update(
|
smsTemplateMapper.update(
|
||||||
(SmsTemplateDO) new SmsTemplateDO()
|
(SmsTemplateDO) new SmsTemplateDO()
|
||||||
|
.setSmsSignId(smsSignId)
|
||||||
.setTemplate(template)
|
.setTemplate(template)
|
||||||
.setApplyStatus(result.getApplyStatus())
|
.setPlatform(platform)
|
||||||
.setApplyMessage(result.getApplyMessage())
|
.setSmsType(smsType)
|
||||||
.setUpdateTime(new Date()),
|
.setUpdateTime(new Date()),
|
||||||
new QueryWrapper<SmsTemplateDO>().eq("id", id)
|
new QueryWrapper<SmsTemplateDO>().eq("id", id)
|
||||||
);
|
);
|
||||||
@ -257,20 +283,17 @@ public class SmsServiceImpl implements SmsService {
|
|||||||
AdminErrorCodeEnum.SMS_TEMPLATE_NOT_EXISTENT.getMessage());
|
AdminErrorCodeEnum.SMS_TEMPLATE_NOT_EXISTENT.getMessage());
|
||||||
}
|
}
|
||||||
|
|
||||||
// 删除 平台的模板
|
|
||||||
smsPlatform.deleteTemplate(smsTemplateDO.getPlatformId());
|
|
||||||
|
|
||||||
// 删除 数据库模板
|
// 删除 数据库模板
|
||||||
SmsTemplateDO updateTemplate =new SmsTemplateDO();
|
SmsTemplateDO updateTemplate =new SmsTemplateDO();
|
||||||
updateTemplate.setDeleted(DeletedStatusEnum.DELETED_YES.getValue());
|
updateTemplate.setDeleted(DeletedStatusEnum.DELETED_YES.getValue());
|
||||||
smsTemplateMapper.delete(new UpdateWrapper<SmsTemplateDO>()
|
smsTemplateMapper.delete(
|
||||||
.set("deleted", DeletedStatusEnum.DELETED_YES).eq("id", id));
|
new UpdateWrapper<SmsTemplateDO>()
|
||||||
|
.set("deleted", DeletedStatusEnum.DELETED_YES)
|
||||||
|
.eq("id", id));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void singleSend(String mobile, Integer smsTemplateId, Map<String, String> params) {
|
public void singleSend(String mobile, Integer smsTemplateId, Map<String, String> params) {
|
||||||
|
|
||||||
// TODO: 2019/5/21 Sin params 参数为特换到模板中
|
|
||||||
SmsTemplateDO smsTemplateDO = smsTemplateMapper.selectOne(
|
SmsTemplateDO smsTemplateDO = smsTemplateMapper.selectOne(
|
||||||
new QueryWrapper<SmsTemplateDO>().eq("id", smsTemplateId));
|
new QueryWrapper<SmsTemplateDO>().eq("id", smsTemplateId));
|
||||||
|
|
||||||
@ -283,14 +306,19 @@ public class SmsServiceImpl implements SmsService {
|
|||||||
SmsSignDO smsSignDO = smsSignMapper.selectOne(
|
SmsSignDO smsSignDO = smsSignMapper.selectOne(
|
||||||
new QueryWrapper<SmsSignDO>().eq("id", smsTemplateDO.getSmsSignId()));
|
new QueryWrapper<SmsSignDO>().eq("id", smsTemplateDO.getSmsSignId()));
|
||||||
|
|
||||||
smsPlatform.singleSend(mobile,
|
if (smsSignDO == null) {
|
||||||
String.format(SMS_TEMPLATE, smsSignDO.getSign(), smsTemplateDO.getTemplate()));
|
throw new ServiceException(AdminErrorCodeEnum.SMS_SIGN_NOT_EXISTENT.getCode(),
|
||||||
|
AdminErrorCodeEnum.SMS_SIGN_NOT_EXISTENT.getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取 client
|
||||||
|
SmsClient smsClient = getSmsClient(smsTemplateDO.getPlatform());
|
||||||
|
// 发送短信
|
||||||
|
smsClient.singleSend(mobile, smsSignDO.getSign(), smsTemplateDO.getTemplate(), params);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void batchSend(List<String> mobileList, Integer smsTemplateId, Map<String, String> params) {
|
public void batchSend(List<String> mobileList, Integer smsTemplateId, Map<String, String> params) {
|
||||||
// TODO: 2019/5/21 Sin params 参数为特换到模板中
|
|
||||||
|
|
||||||
SmsTemplateDO smsTemplateDO = smsTemplateMapper.selectOne(
|
SmsTemplateDO smsTemplateDO = smsTemplateMapper.selectOne(
|
||||||
new QueryWrapper<SmsTemplateDO>().eq("id", smsTemplateId));
|
new QueryWrapper<SmsTemplateDO>().eq("id", smsTemplateId));
|
||||||
|
|
||||||
@ -303,7 +331,37 @@ public class SmsServiceImpl implements SmsService {
|
|||||||
SmsSignDO smsSignDO = smsSignMapper.selectOne(
|
SmsSignDO smsSignDO = smsSignMapper.selectOne(
|
||||||
new QueryWrapper<SmsSignDO>().eq("id", smsTemplateDO.getSmsSignId()));
|
new QueryWrapper<SmsSignDO>().eq("id", smsTemplateDO.getSmsSignId()));
|
||||||
|
|
||||||
smsPlatform.batchSend(mobileList,
|
if (smsSignDO == null) {
|
||||||
String.format(SMS_TEMPLATE, smsSignDO.getSign(), smsTemplateDO.getTemplate()));
|
throw new ServiceException(AdminErrorCodeEnum.SMS_SIGN_NOT_EXISTENT.getCode(),
|
||||||
|
AdminErrorCodeEnum.SMS_SIGN_NOT_EXISTENT.getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取 client
|
||||||
|
SmsClient smsClient = getSmsClient(smsTemplateDO.getPlatform());
|
||||||
|
// 发送短信
|
||||||
|
smsClient.batchSend(mobileList, smsSignDO.getSign(), smsTemplateDO.getTemplate(), params);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取 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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,419 +0,0 @@
|
|||||||
package cn.iocoder.mall.admin.service;
|
|
||||||
|
|
||||||
import cn.iocoder.common.framework.exception.ServiceException;
|
|
||||||
import cn.iocoder.mall.admin.api.SmsPlatform;
|
|
||||||
import cn.iocoder.mall.admin.api.constant.AdminErrorCodeEnum;
|
|
||||||
import cn.iocoder.mall.admin.api.constant.SmsApplyStatusEnum;
|
|
||||||
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.assertj.core.util.Lists;
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
import org.springframework.beans.factory.annotation.Value;
|
|
||||||
import org.springframework.stereotype.Service;
|
|
||||||
|
|
||||||
import java.util.*;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 云片 短信平台
|
|
||||||
*
|
|
||||||
* @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地址
|
|
||||||
|
|
||||||
//模板发送接口的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";
|
|
||||||
/**
|
|
||||||
* 模板 - 删除
|
|
||||||
*/
|
|
||||||
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.apiKey}")
|
|
||||||
private String apiKey;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Result createSign(String sign) {
|
|
||||||
try {
|
|
||||||
// 存在直接 return 相当于,创建了
|
|
||||||
return getSign(sign);
|
|
||||||
} catch (ServiceException e) {
|
|
||||||
// skip 不存在会进这里,不错任何操作
|
|
||||||
}
|
|
||||||
|
|
||||||
// 调用 短信平台
|
|
||||||
Map<String, String> 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.containsKey("code")
|
|
||||||
&& !(jsonObject.getInteger("code") == SUCCESS_CODE)) {
|
|
||||||
throw new ServiceException(AdminErrorCodeEnum.SMS_PLATFORM_FAIL.getCode(),
|
|
||||||
jsonObject.getString("detail"));
|
|
||||||
}
|
|
||||||
|
|
||||||
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<String, String> 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.containsKey("code")
|
|
||||||
&& !(jsonObject.getInteger("code") == SUCCESS_CODE)) {
|
|
||||||
throw new ServiceException(AdminErrorCodeEnum.SMS_PLATFORM_FAIL.getCode(),
|
|
||||||
jsonObject.getString("detail"));
|
|
||||||
}
|
|
||||||
|
|
||||||
JSONArray jsonArray = jsonObject.getJSONArray("sign");
|
|
||||||
if (jsonArray.size() <= 0) {
|
|
||||||
throw new ServiceException(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<String, String> 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.containsKey("code")
|
|
||||||
&& !(jsonObject.getInteger("code") == SUCCESS_CODE)) {
|
|
||||||
throw new ServiceException(AdminErrorCodeEnum.SMS_PLATFORM_FAIL.getCode(),
|
|
||||||
jsonObject.getString("detail"));
|
|
||||||
}
|
|
||||||
|
|
||||||
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 template, Integer tplType) {
|
|
||||||
Map<String, String> params = new LinkedHashMap<>();
|
|
||||||
params.put("apikey", apiKey);
|
|
||||||
params.put("tpl_content", template);
|
|
||||||
if (tplType != null) {
|
|
||||||
params.put("tplType", String.valueOf(tplType));
|
|
||||||
}
|
|
||||||
String result = post(URL_TEMPLATE_ADD, 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"));
|
|
||||||
}
|
|
||||||
|
|
||||||
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 tplId) {
|
|
||||||
Map<String, String> params = new LinkedHashMap<>();
|
|
||||||
params.put("apikey", apiKey);
|
|
||||||
params.put("tpl_id", tplId);
|
|
||||||
String result = post(URL_TEMPLATE_GET, 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"));
|
|
||||||
}
|
|
||||||
|
|
||||||
String checkStatus = jsonObject.getString("check_status");
|
|
||||||
Integer applyStatus = smsStatusMapping(checkStatus);
|
|
||||||
String reason = jsonObject.getString("reason");
|
|
||||||
return new Result().setId(tplId).setApplyStatus(applyStatus).setApplyMessage(reason);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Result updateTemplate(String tplId, String template, Integer tplType) {
|
|
||||||
Map<String, String> params = new LinkedHashMap<>();
|
|
||||||
params.put("apikey", apiKey);
|
|
||||||
params.put("tpl_id", tplId);
|
|
||||||
params.put("tpl_content", template);
|
|
||||||
String result = post(URL_TEMPLATE_UPDATE, 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"));
|
|
||||||
}
|
|
||||||
|
|
||||||
JSONObject templateJSONObject = (JSONObject) jsonObject.get("template");
|
|
||||||
String checkStatus = templateJSONObject.getString("check_status");
|
|
||||||
Integer applyStatus = smsStatusMapping(checkStatus);
|
|
||||||
String reason = jsonObject.getString("reason");
|
|
||||||
return new Result().setId(tplId).setApplyStatus(applyStatus).setApplyMessage(reason);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Result deleteTemplate(String tplId) {
|
|
||||||
|
|
||||||
// 如果不存在/已删除,直接返回
|
|
||||||
try {
|
|
||||||
getTemplate(tplId);
|
|
||||||
} catch (ServiceException e) {
|
|
||||||
// skip
|
|
||||||
return new Result().setId(tplId).setApplyStatus(null).setApplyMessage(null);
|
|
||||||
}
|
|
||||||
|
|
||||||
Map<String, String> params = new LinkedHashMap<>();
|
|
||||||
params.put("apikey", apiKey);
|
|
||||||
params.put("tpl_id", tplId);
|
|
||||||
String result = post(URL_TEMPLATE_DELETE, 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 Result().setId(tplId).setApplyStatus(null).setApplyMessage(null);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public SendResult singleSend(String mobile, String template) {
|
|
||||||
Map<String, String> 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_TEMPLATE_DELETE, 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()
|
|
||||||
.setHasSuccess(SUCCESS_CODE == jsonObject.getInteger("code"))
|
|
||||||
.setCode(jsonObject.getInteger("code"))
|
|
||||||
.setMessage(jsonObject.getString("detail"))
|
|
||||||
.setSuccess(Lists.newArrayList(mobile))
|
|
||||||
.setFail(Collections.EMPTY_LIST);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public SendResult batchSend(List<String> mobileList, String template) {
|
|
||||||
|
|
||||||
// 最大发送数为 1000,我们设置为 500 个, 分段发送
|
|
||||||
int maxSendSize = 500;
|
|
||||||
int maxSendSizeCount = mobileList.size() % maxSendSize;
|
|
||||||
int j = 0;
|
|
||||||
int j2 = maxSendSize;
|
|
||||||
|
|
||||||
List<String> successList = new ArrayList<>();
|
|
||||||
List<String> failList = new ArrayList<>();
|
|
||||||
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<String, String> 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"));
|
|
||||||
}
|
|
||||||
|
|
||||||
JSONArray jsonArray = jsonObject.getJSONArray("data");
|
|
||||||
for (Object o : jsonArray) {
|
|
||||||
JSONObject dataJSONObject = (JSONObject) o;
|
|
||||||
if (SUCCESS_CODE == dataJSONObject.getInteger("code")) {
|
|
||||||
successList.add(dataJSONObject.getString("mobile"));
|
|
||||||
} else {
|
|
||||||
failList.add(dataJSONObject.getString("mobile"));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 用于递增 maxSendSize
|
|
||||||
j = j2;
|
|
||||||
j2 = j + maxSendSize;
|
|
||||||
}
|
|
||||||
|
|
||||||
return new SendResult()
|
|
||||||
.setHasSuccess(true)
|
|
||||||
.setCode(SUCCESS_CODE)
|
|
||||||
.setMessage(null)
|
|
||||||
.setSuccess(successList)
|
|
||||||
.setFail(failList);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 短信 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<String, String> paramsMap) {
|
|
||||||
CloseableHttpClient client = HttpClients.createDefault();
|
|
||||||
String responseText = "";
|
|
||||||
CloseableHttpResponse response = null;
|
|
||||||
try {
|
|
||||||
HttpPost method = new HttpPost(url);
|
|
||||||
if (paramsMap != null) {
|
|
||||||
List<NameValuePair> paramList = new ArrayList<>();
|
|
||||||
for (Map.Entry<String, String> 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;
|
|
||||||
}
|
|
||||||
}
|
|
@ -26,7 +26,13 @@ mybatis-plus:
|
|||||||
|
|
||||||
# sms
|
# sms
|
||||||
sms:
|
sms:
|
||||||
|
yunPian:
|
||||||
apiKey: d4705399e71e822fe3a90f801ed95bd9
|
apiKey: d4705399e71e822fe3a90f801ed95bd9
|
||||||
|
aliYun:
|
||||||
|
accessKeyId: d4705399e71e822fe3a90f801ed95bd9
|
||||||
|
accessSecret: d4705399e71e822fe3a90f801ed95bd9
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# dubbo
|
# dubbo
|
||||||
dubbo:
|
dubbo:
|
||||||
|
@ -0,0 +1,56 @@
|
|||||||
|
package cn.iocoder.mall.admin.client;
|
||||||
|
|
||||||
|
import cn.iocoder.mall.admin.SystemApplicationTest;
|
||||||
|
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 com.google.common.collect.ImmutableMap;
|
||||||
|
import org.assertj.core.util.Lists;
|
||||||
|
import org.junit.Before;
|
||||||
|
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;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 短信 sms client test
|
||||||
|
*
|
||||||
|
* @author Sin
|
||||||
|
* @time 2019/5/25 12:46 PM
|
||||||
|
*/
|
||||||
|
@RunWith(SpringRunner.class)
|
||||||
|
@SpringBootTest(classes = SystemApplicationTest.class)
|
||||||
|
public class SmsYunPianClientTest {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private SmsYunPianClient smsYunPianClient;
|
||||||
|
|
||||||
|
private String sign = null;
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void setup() {
|
||||||
|
sign = "悦跑运动";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void sendMobileTest() {
|
||||||
|
String mobile = "13302926050";
|
||||||
|
String template = "您的验证码是#code#,打死也不告诉别人哦。";
|
||||||
|
smsYunPianClient.singleSend(mobile, sign, template, ImmutableMap.of("code", "1111"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void batchSendTest() {
|
||||||
|
String mobile = "13302926050";
|
||||||
|
String template = "您的验证码是#code#,打死也不告诉别人哦。";
|
||||||
|
smsYunPianClient.batchSend(Lists.newArrayList(mobile), sign, template, ImmutableMap.of("code", "2222"));
|
||||||
|
}
|
||||||
|
}
|
@ -1,10 +1,16 @@
|
|||||||
package cn.iocoder.mall.admin.service;
|
package cn.iocoder.mall.admin.service;
|
||||||
|
|
||||||
|
import cn.iocoder.common.framework.exception.ServiceException;
|
||||||
import cn.iocoder.mall.admin.SystemApplicationTest;
|
import cn.iocoder.mall.admin.SystemApplicationTest;
|
||||||
|
import cn.iocoder.mall.admin.api.SmsService;
|
||||||
import cn.iocoder.mall.admin.api.bo.sms.SmsSignBO;
|
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.SmsPlatformEnum;
|
||||||
|
import cn.iocoder.mall.admin.api.constant.SmsTypeEnum;
|
||||||
|
import com.google.common.collect.ImmutableMap;
|
||||||
|
import org.assertj.core.util.Lists;
|
||||||
import org.junit.Assert;
|
import org.junit.Assert;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
import org.junit.jupiter.api.Assertions;
|
||||||
import org.junit.runner.RunWith;
|
import org.junit.runner.RunWith;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.boot.test.context.SpringBootTest;
|
import org.springframework.boot.test.context.SpringBootTest;
|
||||||
@ -21,55 +27,57 @@ import org.springframework.test.context.junit4.SpringRunner;
|
|||||||
public class SmsServiceImplTest {
|
public class SmsServiceImplTest {
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private SmsServiceImpl smsService;
|
private SmsService smsService;
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void createSignTest() {
|
public void createSignTest() {
|
||||||
smsService.createSign("测试签名1");
|
smsService.createSign("悦跑运动", SmsPlatformEnum.YunPian.getValue());
|
||||||
// smsService.createSign("悦跑会");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void getSignTest() {
|
public void getSignTest() {
|
||||||
SmsSignBO smsSignBO = smsService.getSign("悦跑会");
|
SmsSignBO smsSignBO = smsService.getSign(3);
|
||||||
Assert.assertNotNull(smsSignBO);
|
Assert.assertNotNull("不能为空!", smsSignBO);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void updateSignTest() {
|
public void updateSignTest() {
|
||||||
smsService.updateSign("测试签名2", "测试签名3");
|
String oldSign = "悦跑运动2";
|
||||||
SmsSignBO newSmsSignBO = smsService.getSign("测试签名3");
|
String newSign = "悦跑运动";
|
||||||
Assert.assertNotNull(newSmsSignBO);
|
smsService.updateSign(3, newSign, SmsPlatformEnum.YunPian.getValue());
|
||||||
|
SmsSignBO smsSignBO = smsService.getSign(3);
|
||||||
|
Assert.assertTrue("更新不成功!", smsSignBO.getSign().equals(newSign));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
///
|
@Test
|
||||||
/// template
|
public void deletedSignTest() {
|
||||||
|
smsService.deleteSign(3);
|
||||||
|
Assertions.assertThrows(ServiceException.class, () -> {
|
||||||
|
smsService.getSign(3);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void createTemplateTest() {
|
public void createTemplateTest() {
|
||||||
smsService.createTemplate(1, "打死也不要告诉别人哦002 #code# ", 1);
|
String template = "您的验证码是#code#,打死也不告诉别人哦。";
|
||||||
}
|
smsService.createTemplate(3, template,
|
||||||
|
SmsPlatformEnum.YunPian.getValue(),
|
||||||
@Test
|
SmsTypeEnum.VERIFICATION_CODE.getValue());
|
||||||
public void getTemplateTest() {
|
|
||||||
SmsTemplateBO smsTemplateBO = smsService.getTemplate(3);
|
|
||||||
Assert.assertNotNull(smsTemplateBO);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void updateTemplateTest() {
|
|
||||||
smsService.updateTemplate(3, "打死也不要告诉别人哦444 #code# ", 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void deleteTemplateTest() {
|
|
||||||
smsService.deleteTemplate(3);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void singleSendTest() {
|
public void singleSendTest() {
|
||||||
String mobile = "13302926050";
|
String mobile = "13302926050";
|
||||||
smsService.singleSend(mobile, 1);
|
Integer templateId = 5;
|
||||||
|
smsService.singleSend(mobile, templateId, ImmutableMap.of("code", "8888"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void batchSendTest() {
|
||||||
|
String mobile = "13302926050";
|
||||||
|
Integer templateId = 5;
|
||||||
|
smsService.batchSend(Lists.newArrayList(mobile), templateId, ImmutableMap.of("code", "8888"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user