#记一次接入华为云短信
几个月前,也就是公司网站第一个版本上线的时候,当时有业务需要短信验证,于是购买了华为云的短信业务.在此简单的记录一下华为云短信api的接入,比较简单,拿来就可以用
这里我首先定义了一个实体类,方便参数注入
public class SmsConfig {
//短信发送apiURI
private String url;
//APP_Key
private String appKey;
//APP_Secret
private String appSecret ;
//国内短信签名通道号或国际/港澳台短信通道号
private String sender ;
//模板ID
private String templateId ;
//签名名称
private String signature;
//返回信息回调URI
//选填,短信状态报告接收地址,推荐使用域名,为空或者不填表示不接收状态报告
private String statusCallBack;
}
这是首先要定义的两个方法,从华为云短信官方文档中找到,主要作用建立短信发送的请求头和请求体
直接从文档中拿取
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\"";
public String buildRequestBody(String sender,String receiver,String templateId,String templateParas,String statusCallbackUrl,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 (null != signature && !signature.isEmpty()) {
keyValues.add(new BasicNameValuePair("signature", signature));
}
return URLEncodedUtils.format(keyValues, Charset.forName("UTF-8"));
}
public 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);
}
最后这个就是发送功能的主要代码
@Autowired
private SmsConfig smsConfig;
public void sendMsg(String receiver,String templateParas) {
String body = this.buildRequestBody(smsConfig.getSender(), receiver, smsConfig.getTemplateId(), templateParas, smsConfig.getStatusCallBack(), smsConfig.getSignature());
if (null == body || body.isEmpty()) {
System.out.println("body is null.");
return;
}
String wsseHeader = this.buildWsseHeader(smsConfig.getAppKey(), smsConfig.getAppSecret());
if (null == wsseHeader || wsseHeader.isEmpty()) {
System.out.println("wsse header is null.");
return;
}
try {
CloseableHttpClient client = HttpClients.custom()
.setSSLContext(new SSLContextBuilder().loadTrustMaterial(null,
(x509CertChain, authType) -> true).build())
.setSSLHostnameVerifier(NoopHostnameVerifier.INSTANCE)
.build();
HttpResponse response = client.execute(RequestBuilder.create("POST")//请求方法POST
.setUri(smsConfig.getUrl())
.addHeader(HttpHeaders.CONTENT_TYPE, "application/x-www-form-urlencoded")
.addHeader(HttpHeaders.AUTHORIZATION, AUTH_HEADER_VALUE)
.addHeader("X-WSSE", wsseHeader)
.setEntity(new StringEntity(body)).build());
System.out.println(response.toString()); //打印响应头域信息
System.out.println(EntityUtils.toString(response.getEntity()));//打印响应消息实体
}catch(Exception e) {
log.error("[发送消息接口调用错误");
}
}