SpringBoot调用华为云短信实现发短信功能
参考 发送短信_消息&短信 MSGSMS_华为云
1.引入华为云短信pom依赖
<dependency> <groupId>com.huaweicloud.sdk</groupId> <artifactId>huaweicloud-sdk-smsapi</artifactId> <version>3.1.125</version> </dependency>
2.参考华为云短信官方文档
Java_消息&短信 MSGSMS_华为云
import com.huaweicloud.sdk.core.auth.BasicCredentials;
import com.huaweicloud.sdk.core.http.HttpMethod;
import com.huaweicloud.sdk.core.http.HttpRequest;
import com.huaweicloud.sdk.smsapi.utils.SmsAkSkSigner;
import com.knowdee.cc.common.domain.CcSendMsgInfo;
import com.knowdee.cc.common.service.ICcSendMsgInfoService;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.conn.ssl.NoopHostnameVerifier;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.ssl.SSLContextBuilder;
import org.apache.http.util.EntityUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import javax.net.ssl.SSLContext;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.*;
import static java.nio.charset.StandardCharsets.UTF_8;
@Service
@Slf4j
public class HuaweiSmsService {
@Value("${huawei.cloud.sms.access-key}")
private String accessKey;
@Value("${huawei.cloud.sms.secret-key}")
private String secretKey;
@Value("${huawei.cloud.sms.signature}")
private String signature;
@Value("${huawei.cloud.sms.endpoint}")
private String endpoint;
@Resource
private ICcSendMsgInfoService ccSendMsgInfoService;
private static CloseableHttpClient httpClient = null;
public static void main(String[] args) throws Exception {
/*
* Send an SMS message using a special AK/SK authentication algorithm.
* When the MSGSMS is used to send SMS messages, the AK is app_key, and the SK is app_secret.
* There will be security risks if the app_key/app_secret used for authentication is directly written into code.
* We suggest encrypting the app_key/app_secret in the configuration file or environment variables for storage.
* In this sample, the app_key/app_secret is stored in environment variables for identity authentication.
* Before running this sample, set the environment variables CLOUD_SDK_MSGSMS_APPKEY and CLOUD_SDK_MSGSMS_APPSECRET.
* CLOUD_SDK_MSGSMS_APPKEY indicates the application key (app_key), and CLOUD_SDK_MSGSMS_APPSECRET indicates the application secret (app_secret).
* You can obtain the value from Application Management on the console or by calling the open API of Application Management.
*/
//String ak = System.getenv("CLOUD_SDK_MSGSMS_APPKEY");
//String sk = System.getenv("CLOUD_SDK_MSGSMS_APPSECRET");
// if (Objects.isNull(ak) || Objects.isNull(sk)) {
// System.out.println("the ak or sk is null. please config the environment CLOUD_SDK_MSGSMS_APPKEY and CLOUD_SDK_MSGSMS_APPSECRET first!");
// return;
// }
// To prevent API invoking failures caused by HTTPS certificate authentication failures, ignore the certificate trust issue to simplify the sample code.
// httpClient = createIgnoreSSLHttpClient();
// HuaweiSmsService huaweiSmsService = new HuaweiSmsService();
// huaweiSmsService.sendSms("","xALlH903ix07t4agS5122U0O6A9J", "CSjuauYNbBHI0FqH3rCUI3Dpl0yA");
}
/**
* Example of Invoking the batchSendSms Interface to Send an SMS Message
*
* @param ak AK is the app_key of the SMS application.
* @param sk SK is the app_secret of the SMS application.
* @throws UnsupportedEncodingException
*/
public Boolean sendSms(String templateId, String phone, String content) throws UnsupportedEncodingException {
// This address is of Beijing 4. Replace it with the actual value.
//String uri = "https://smsapi.cn-north-4.myhuaweicloud.com:443/sms/batchSendSms/v1";
try {
httpClient = createIgnoreSSLHttpClient();
} catch (Exception e) {
throw new RuntimeException(e);
}
String uri = endpoint + "/sms/batchSendSms/v1";
// Construct the message body of the sample code.
// For details about how to construct a body, see the API description.
StringBuilder body = new StringBuilder();
appendToBody(body, "from=", signature);
appendToBody(body, "&to=", phone);
appendToBody(body, "&templateId=", templateId);
appendToBody(body, "&templateParas=", "[\"" + content + "\"]");
//appendToBody(body, "&statusCallback=", "https://test/report");
log.info("body:" + body);
//System.out.println("body:" + body);
// Signature operation of the batchsendsms interface
Boolean flag = false;
Map<String, String> signedHeaders = sign(accessKey, secretKey, body.toString(), uri);
if (Objects.isNull(signedHeaders)) {
//System.out.println("sign failed!");
log.info("sign failed!");
return flag;
}
// Print Signature Results
//System.out.println("BatchSendSms sign result:" + signedHeaders);
log.info("BatchSendSms sign result:" + signedHeaders);
HttpPost postRequest = new HttpPost(uri);
postRequest.setHeader("Accept", "application/json");
postRequest.setHeader("Content-Type", "application/x-www-form-urlencoded");
signedHeaders.forEach((key, value) -> postRequest.setHeader(key, value));
postRequest.setEntity(new StringEntity(body.toString(), StandardCharsets.UTF_8));
// Invoke /sms/batchSendSms/v1 api to send messages
try (CloseableHttpResponse response = httpClient.execute(postRequest)) {
// Print the response status code.
// System.out.println("Response Status Code: " + response.getStatusLine().getStatusCode());
// System.out.println("Response Content: " + EntityUtils.toString(response.getEntity()));
log.info("Response Status Code: " + response.getStatusLine().getStatusCode());
log.info("Response Content: " + EntityUtils.toString(response.getEntity()));
if (response.getStatusLine().getStatusCode() == 200) {
flag = true;
}else{
CcSendMsgInfo ccSendMsgInfo = new CcSendMsgInfo();
ccSendMsgInfo.setContent(content);
ccSendMsgInfo.setTemplateId(templateId);
ccSendMsgInfo.setTime(new Date());
ccSendMsgInfo.setPhone(phone);
ccSendMsgInfo.setFailInfo(response.getStatusLine().getReasonPhrase());
ccSendMsgInfoService.getBaseMapper().insert(ccSendMsgInfo);
}
// Print the response content.
} catch (IOException e) {
//System.out.println("response exception:" + e);
log.info("response exception:" + e);
}
return flag;
}
/**
* Create an HTTP client that ignores the HTTPS certificate check.
*
* @return HTTP client
* @throws Exception
*/
private CloseableHttpClient createIgnoreSSLHttpClient() throws Exception {
SSLContext sslContext = new SSLContextBuilder().loadTrustMaterial(null, (x509CertChain, authType) -> true).build();
return HttpClients.custom().setSSLSocketFactory(new SSLConnectionSocketFactory(sslContext, NoopHostnameVerifier.INSTANCE)).build();
}
/**
* Add the parameter to the original body after URL encoding.
*
* @param body Message body
* @param key Parameter key
* @param val Parameter value
* @throws UnsupportedEncodingException
*/
private static void appendToBody(StringBuilder body, String key, String val) throws UnsupportedEncodingException {
if (null != val && !val.isEmpty()) {
body.append(key).append(URLEncoder.encode(val, UTF_8.name()));
}
}
/**
* The algorithm for generating the signature header field (Authorization, X-Sdk-Date, Host) is provided.
*
* @param ak AK is the app_key of the SMS application.
* @param sk SK is the app_secret of the SMS application.
* @param body Message body to be signed
* @param endpoint the api uri
* @return signature header field (Authorization, X-Sdk-Date, Host)
*/
private static Map<String, String> sign(String ak, String sk, String body, String endpoint) {
// The signature algorithm uses the AK and SK signature algorithms provided by HUAWEI CLOUD IAM and API Gateway.
// Signature algorithm implementation. The capabilities provided by the SDK are used here.
// Developers can also use the signature capability provided by HUAWEI CLOUD APIG. For details, see the following website: https://support.huaweicloud.com/devg-apisign/api-sign-sdk-java.html
// For the signature operation of an interface, the signature must contain the body.
return SmsAkSkSigner.sign(HttpRequest.newBuilder().withBodyAsString(body)
.withMethod(HttpMethod.POST)
.withEndpoint(endpoint)
.addHeader("Content-Type", "application/x-www-form-urlencoded").build(),
new BasicCredentials().withAk(ak).withSk(sk));
}
}