import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.codec.binary.Hex;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.HttpHeaders;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.methods.RequestBuilder;
import org.apache.http.client.utils.URLEncodedUtils;
import org.apache.http.conn.ssl.NoopHostnameVerifier;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.ssl.SSLContextBuilder;
import org.apache.http.util.EntityUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.nio.charset.Charset;
import java.security.KeyManagementException;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@Service
@Slf4j
public class HwySmsMsgSendStyleImpl extends AbSmsMsgSendStyle {
// 用于格式化鉴权头域,给“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\"";
@Autowired
protected HttpServletRequest request;
@Override
public boolean send(String phone, String content, Map<String, String> properties, String modelId) throws IOException {
log.warn("华为短信发送---------------------------开始----------------");
// 开发准备:APP接入地址 + 接口访问URI
String url = properties.get("url");
// 开发准备:APP_Key
String appKey = properties.get("appKey");
// 开发准备:APP_Secret
String appSecret = properties.get("appSecret");
// 开发准备:签名通道号
String sender = properties.get("sender");
// 填写短信接收人号码,多个号码之间用英文逗号分隔
String receiver = phone;
// 开发准备:模板ID
String templateId = modelId;
//sx102 id
String extend = properties.get("sx102Id");
// // 开发准备:模板名称
// String signature = properties.get("signature");
String statusCallBack = properties.get("statusCallBack");
//处理模板
String unprocessedContent = properties.get("unprocessedContent");
String parameter = properties.get("parameter");
// 创建一个列表,存储参数值
List<String> params = new ArrayList<>();;
if (StringUtils.isNotBlank(parameter)){
// 解析 JSON 数据
JSONObject jsonData = JSON.parseObject(parameter);
// 提取模板中的参数名
List<String> placeholders = extractPlaceholders(unprocessedContent);
// 遍历模板中的参数名,从数据中提取对应的参数值
for (String placeholder : placeholders) {
String paramValue = jsonData.getString(placeholder);
params.add(paramValue);
}
// 转换列表为数组
String[] resultArray = params.toArray(new String[0]);
}else {
params.add(content);
}
String finaPparameter = JSON.toJSONString(params);
// 状态报告接收地址,为空或者不填表示不接收状态报告
log.warn("平台模板内容-----"+content+";处理后模板内容-----"+JSON.toJSONString(params));
if (StringUtils.isBlank(url) || StringUtils.isBlank(appKey) || StringUtils.isBlank(appSecret) || StringUtils.isBlank(sender) || StringUtils.isBlank(receiver) || StringUtils.isBlank(templateId)) {
log.error(String.format("华为短信参数值不符合要求:url: %s; appKey: %s; appSecret: %s;sender: %s;receiver: %s;templateId: %s;extend: %s;",
url, appKey, appSecret, sender, receiver, templateId,extend));
return false;
}
// 请求Body
String body = buildRequestBody(sender, receiver, templateId, finaPparameter, statusCallBack,extend, "");
// 请求Headers中的X-WSSE参数值
String wsseHeader = buildWsseHeader(appKey, appSecret);
// 如果JDK版本是1.8,可使用如下代码
CloseableHttpClient client;
HttpResponse response = null;
try {
client = HttpClients.custom()
.setSSLContext(
new SSLContextBuilder().loadTrustMaterial(null, (x509CertChain, authType) -> true).build())
.setSSLHostnameVerifier(NoopHostnameVerifier.INSTANCE).build();
response = client.execute(RequestBuilder.create("POST").setUri(url)
.addHeader(HttpHeaders.CONTENT_TYPE, "application/x-www-form-urlencoded")
.addHeader(HttpHeaders.AUTHORIZATION, AUTH_HEADER_VALUE).addHeader("X-WSSE", wsseHeader)
.setEntity(new StringEntity(body)).build());
} catch (KeyManagementException e) {
log.error(e.getMessage(), e);
} catch (NoSuchAlgorithmException e) {
log.error(e.getMessage(), e);
} catch (KeyStoreException e) {
log.error(e.getMessage(), e);
}
String responseEntity = EntityUtils.toString(response.getEntity());
String code = JSON.parseObject(responseEntity).getString("code");
String description = JSON.parseObject(responseEntity).getString("description");
// 获取状态码
int statusCode = response.getStatusLine().getStatusCode();
if (statusCode == 200) {
if (code.equals("000000") && description.equals("Success")) {
log.warn("ex102Id:"+extend+"华为短信发送---------------------------结束----------------成功");
return true;
}
} else {
log.warn("ex102Id:"+extend+"华为短信发送---------------------------结束----------------statusCode");
}
return false;
}
static String buildRequestBody(String sender, String receiver, String templateId, String templateParas,
String statusCallbackUrl, String extend,String signature) {
if (null == sender || null == receiver || null == templateId || sender.isEmpty() || receiver.isEmpty()
|| templateId.isEmpty()) {
System.out.println("buildRequestBody(): sender, receiver or templateId is null.");
return null;
}
List<NameValuePair> keyValues = new ArrayList<NameValuePair>();
keyValues.add(new BasicNameValuePair("from", sender));
keyValues.add(new BasicNameValuePair("to", receiver));
keyValues.add(new BasicNameValuePair("templateId", templateId));
if (null != templateParas && !templateParas.isEmpty()) {
keyValues.add(new BasicNameValuePair("templateParas", templateParas));
}
if (null != statusCallbackUrl && !statusCallbackUrl.isEmpty()) {
keyValues.add(new BasicNameValuePair("statusCallback", statusCallbackUrl));
}
if (StringUtils.isNotBlank(extend) && !extend.isEmpty()) {
keyValues.add(new BasicNameValuePair("extend", extend));
}
log.warn("华为短信参数值-------------------------------"+JSON.toJSONString(keyValues));
return URLEncodedUtils.format(keyValues, Charset.forName("UTF-8"));
}
static String buildWsseHeader(String appKey, String appSecret) {
if (null == appKey || null == appSecret || appKey.isEmpty() || appSecret.isEmpty()) {
System.out.println("buildWsseHeader(): appKey or appSecret is null.");
return null;
}
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'");
String time = sdf.format(new Date()); //Created
String nonce = UUID.randomUUID().toString().replace("-", ""); //Nonce
byte[] passwordDigest = DigestUtils.sha256(nonce + time + appSecret);
String hexDigest = Hex.encodeHexString(passwordDigest);
String passwordDigestBase64Str = Base64.getEncoder().encodeToString(hexDigest.getBytes()); //PasswordDigest
return String.format(WSSE_HEADER_FORMAT, appKey, passwordDigestBase64Str, nonce, time);
}
private static List<String> extractPlaceholders(String template) {
List<String> placeholders = new ArrayList<>();
Pattern pattern = Pattern.compile("\\$\\{(.*?)}");
Matcher matcher = pattern.matcher(template);
while (matcher.find()) {
String placeholder = matcher.group(1);
placeholders.add(placeholder);
}
return placeholders;
}
@Override
public String getName() {
return "华为云短信";
}
}
完整案例可以直接使用。