新增华为云短信
This commit is contained in:
parent
0b580d2fe2
commit
29cfc30459
|
@ -20,7 +20,7 @@ import org.springframework.security.access.prepost.PreAuthorize;
|
|||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import javax.validation.Valid;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
|
@ -72,8 +72,8 @@ public class SmsPlatformController {
|
|||
SmsConfig config = SmsPlatformConvert.INSTANCE.convert2(entity);
|
||||
|
||||
// 短信参数
|
||||
Map<String, String> params = new HashMap<>();
|
||||
if(!StringUtils.isAnyBlank(vo.getParamKey(), vo.getParamValue())) {
|
||||
Map<String, String> params = new LinkedHashMap<>();
|
||||
if (StringUtils.isNotBlank(vo.getParamValue())) {
|
||||
params.put(vo.getParamKey(), vo.getParamValue());
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,195 @@
|
|||
package net.maku.message.sms;
|
||||
|
||||
import cn.hutool.core.io.IoUtil;
|
||||
import cn.hutool.core.map.MapUtil;
|
||||
import cn.hutool.core.util.CharsetUtil;
|
||||
import lombok.Data;
|
||||
import net.maku.framework.common.exception.FastException;
|
||||
import net.maku.framework.common.utils.JsonUtils;
|
||||
import net.maku.message.sms.config.SmsConfig;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.http.HttpStatus;
|
||||
|
||||
import javax.net.ssl.*;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.net.URL;
|
||||
import java.net.URLEncoder;
|
||||
import java.security.MessageDigest;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.security.cert.X509Certificate;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* 华为云短信
|
||||
*
|
||||
* @author 阿沐 babamu@126.com
|
||||
*/
|
||||
public class HuaweiSmsStrategy implements SmsStrategy {
|
||||
// 无需修改,用于格式化鉴权头域,给"X-WSSE"参数赋值
|
||||
private static final String WSSE_HEADER_FORMAT = "UsernameToken Username=\"%s\",PasswordDigest=\"%s\",Nonce=\"%s\",Created=\"%s\"";
|
||||
// 无需修改,用于格式化鉴权头域,给"Authorization"参数赋值
|
||||
private static final String AUTH_HEADER_VALUE = "WSSE realm=\"SDP\",profile=\"UsernameToken\",type=\"Appkey\"";
|
||||
private final SmsConfig smsConfig;
|
||||
|
||||
public HuaweiSmsStrategy(SmsConfig smsConfig) {
|
||||
this.smsConfig = smsConfig;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void send(String mobile, Map<String, String> params) {
|
||||
// APP接入地址(在控制台"应用管理"页面获取)+接口访问URI
|
||||
String url = "https://smsapi.cn-north-4.myhuaweicloud.com:443/sms/batchSendSms/v1";
|
||||
|
||||
// 有参数则设置
|
||||
String templateParas = null;
|
||||
if (MapUtil.isNotEmpty(params)) {
|
||||
templateParas = JsonUtils.toJsonString(params.values().toArray(new String[0]));
|
||||
}
|
||||
|
||||
// 请求Body,不携带签名名称时,signature请填null
|
||||
String body = buildRequestBody(smsConfig.getSenderId(), "+86" + mobile, smsConfig.getTemplateId(), templateParas, null, smsConfig.getSignName());
|
||||
if (StringUtils.isBlank(body)) {
|
||||
throw new FastException("body is null.");
|
||||
}
|
||||
|
||||
// 请求Headers中的X-WSSE参数值
|
||||
String wsseHeader = buildWsseHeader(smsConfig.getAccessKey(), smsConfig.getSecretKey());
|
||||
if (StringUtils.isBlank(wsseHeader)) {
|
||||
throw new FastException("wsse header is null.");
|
||||
}
|
||||
|
||||
try {
|
||||
// 使用 https
|
||||
trustAllHttpsCertificates();
|
||||
|
||||
URL realUrl = new URL(url);
|
||||
HttpsURLConnection connection = (HttpsURLConnection) realUrl.openConnection();
|
||||
HostnameVerifier hv = (hostname, session) -> true;
|
||||
connection.setHostnameVerifier(hv);
|
||||
connection.setDoOutput(true);
|
||||
connection.setDoInput(true);
|
||||
connection.setUseCaches(true);
|
||||
connection.setRequestMethod("POST");
|
||||
connection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
|
||||
connection.setRequestProperty("Authorization", AUTH_HEADER_VALUE);
|
||||
connection.setRequestProperty("X-WSSE", wsseHeader);
|
||||
connection.connect();
|
||||
|
||||
IoUtil.writeUtf8(connection.getOutputStream(), true, body);
|
||||
|
||||
int status = connection.getResponseCode();
|
||||
if (status == HttpStatus.OK.value()) {
|
||||
String response = IoUtil.read(connection.getInputStream(), CharsetUtil.CHARSET_UTF_8);
|
||||
HuaweiSmsResult result = JsonUtils.parseObject(response, HuaweiSmsResult.class);
|
||||
|
||||
// 短信是否发送成功
|
||||
assert result != null;
|
||||
if (!"000000".equals(result.code)) {
|
||||
throw new FastException(result.description);
|
||||
}
|
||||
} else { //400 401
|
||||
throw new FastException(IoUtil.read(connection.getErrorStream(), CharsetUtil.CHARSET_UTF_8));
|
||||
}
|
||||
} catch (Exception e) {
|
||||
throw new FastException("短信发送失败:", e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 构造请求Body体
|
||||
*
|
||||
* @param signature | 签名名称,使用国内短信通用模板时填写
|
||||
*/
|
||||
static String buildRequestBody(String sender, String receiver, String templateId, String templateParas,
|
||||
String statusCallBack, String signature) {
|
||||
if (null == sender || null == receiver || null == templateId || sender.isEmpty() || receiver.isEmpty()
|
||||
|| templateId.isEmpty()) {
|
||||
throw new FastException("buildRequestBody(): sender, receiver or templateId is null.");
|
||||
}
|
||||
Map<String, String> map = new HashMap<>();
|
||||
|
||||
map.put("from", sender);
|
||||
map.put("to", receiver);
|
||||
map.put("templateId", templateId);
|
||||
if (null != templateParas && !templateParas.isEmpty()) {
|
||||
map.put("templateParas", templateParas);
|
||||
}
|
||||
if (null != statusCallBack && !statusCallBack.isEmpty()) {
|
||||
map.put("statusCallback", statusCallBack);
|
||||
}
|
||||
if (null != signature && !signature.isEmpty()) {
|
||||
map.put("signature", signature);
|
||||
}
|
||||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
String temp = "";
|
||||
|
||||
for (String s : map.keySet()) {
|
||||
try {
|
||||
temp = URLEncoder.encode(map.get(s), "UTF-8");
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
sb.append(s).append("=").append(temp).append("&");
|
||||
}
|
||||
|
||||
return sb.deleteCharAt(sb.length() - 1).toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* 构造X-WSSE参数值
|
||||
*/
|
||||
static String buildWsseHeader(String appKey, String appSecret) {
|
||||
if (null == appKey || null == appSecret || appKey.isEmpty() || appSecret.isEmpty()) {
|
||||
throw new FastException("buildWsseHeader(): appKey or appSecret is null.");
|
||||
}
|
||||
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'");
|
||||
String time = sdf.format(new Date());
|
||||
String nonce = UUID.randomUUID().toString().replace("-", "");
|
||||
|
||||
MessageDigest md;
|
||||
byte[] passwordDigest = null;
|
||||
|
||||
try {
|
||||
md = MessageDigest.getInstance("SHA-256");
|
||||
md.update((nonce + time + appSecret).getBytes());
|
||||
passwordDigest = md.digest();
|
||||
} catch (NoSuchAlgorithmException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
String passwordDigestBase64Str = Base64.getEncoder().encodeToString(passwordDigest);
|
||||
|
||||
return String.format(WSSE_HEADER_FORMAT, appKey, passwordDigestBase64Str, nonce, time);
|
||||
}
|
||||
|
||||
static void trustAllHttpsCertificates() throws Exception {
|
||||
TrustManager[] trustAllCerts = new TrustManager[]{
|
||||
new X509TrustManager() {
|
||||
public void checkClientTrusted(X509Certificate[] chain, String authType) {
|
||||
|
||||
}
|
||||
|
||||
public void checkServerTrusted(X509Certificate[] chain, String authType) {
|
||||
|
||||
}
|
||||
|
||||
public X509Certificate[] getAcceptedIssuers() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
};
|
||||
SSLContext sc = SSLContext.getInstance("SSL");
|
||||
sc.init(null, trustAllCerts, null);
|
||||
HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
|
||||
}
|
||||
|
||||
@Data
|
||||
static class HuaweiSmsResult {
|
||||
// code为000000,表示成功
|
||||
private String code;
|
||||
private String description;
|
||||
private List<Object> result;
|
||||
}
|
||||
}
|
|
@ -19,6 +19,10 @@ public class SmsContext {
|
|||
this.smsStrategy = new AliyunSmsStrategy(config);
|
||||
} else if (config.getPlatform() == SmsPlatformEnum.QCLOUD.getValue()) {
|
||||
this.smsStrategy = new QcloudSmsStrategy(config);
|
||||
} else if (config.getPlatform() == SmsPlatformEnum.QINIU.getValue()) {
|
||||
this.smsStrategy = new QiniuSmsStrategy(config);
|
||||
} else if (config.getPlatform() == SmsPlatformEnum.HUAWEI.getValue()) {
|
||||
this.smsStrategy = new HuaweiSmsStrategy(config);
|
||||
} else {
|
||||
throw new FastException("未知的短信平台");
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user