Java常用工具类
一. 序列化 / 反序列化
用于将
对象
转为Json
或Json
转对象
1. Json - jackson
Maven 包管理:
-
依赖(
.pom
):<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-json</artifactId> <version>2.5.5</version> </dependency>
-
工具类(
.java
)import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; public class JsonUtil { // 创建ObjectMapper对象 private static final ObjectMapper MAPPER = new ObjectMapper(); // 对象转为Json public static String objToJson(Object obj){ try { return MAPPER.writeValueAsString(obj); } catch (JsonProcessingException e) { e.printStackTrace(); } return null; } // Json转对象 public static <T> T jsonToBean(String json,Class<T> beanType){ try { return MAPPER.readValue(json,beanType); } catch (JsonProcessingException e) { e.printStackTrace(); } return null; } }
解决了LinkedHashMap转换类型出错的问题(从Redis取出来的数据)
// 解决LinkedHashMap转换问题
String cartItemDtoStr = JsonUtil.objToJson(redisTemplate.opsForHash().get(RedisKeyConfig.CART_KEY_USER_ID + userId, key));
CartItemDto cartItemDto = JsonUtil.jsonToBean(cartItemDtoStr, CartItemDto.class);
二. 鉴权
1. Jwt生成token
Maven 包管理:
-
依赖(
.pom
):<!-- JWT --> <dependency> <groupId>io.jsonwebtoken</groupId> <artifactId>jjwt</artifactId> <version>0.9.0</version> </dependency> <!-- 解决xml报错问题(jwt引起) --> <dependency> <groupId>javax.xml.bind</groupId> <artifactId>jaxb-api</artifactId> <version>2.3.0</version> </dependency> <dependency> <groupId>com.sun.xml.bind</groupId> <artifactId>jaxb-impl</artifactId> <version>2.3.0</version> </dependency> <dependency> <groupId>com.sun.xml.bind</groupId> <artifactId>jaxb-core</artifactId> <version>2.3.0</version> </dependency> <dependency> <groupId>javax.activation</groupId> <artifactId>activation</artifactId> <version>1.1.1</version> </dependency>
-
工具类(
.java
)import io.jsonwebtoken.Claims; import io.jsonwebtoken.Jwts; import io.jsonwebtoken.SignatureAlgorithm; import project.pet.request.LoginUser; import java.util.Date; public class JwtUtil { /** * token 过期时间,一般是7天,可根据业务进行调整 * 30 分钟过期 */ private static final long EXPIRE = 1000 * 60 * 30; /** * 加密的秘钥 */ private static final String SECRET = "xxit.comabc"; /** * 令牌前缀 */ private static final String TOKEN_PREFIX = "xxitcrm"; /** * subject */ private static final String SUBJECT = "login"; /** * 根据用户信息,生成token(令牌) * */ public static String geneJsonWebToken(/* 添加内容的对象 */LoginUser loginUser) { if (loginUser == null) { throw new NullPointerException("loginUser对象为空"); } // 过期时间 Date expirationTime = new Date(System.currentTimeMillis() + EXPIRE); String token = Jwts.builder().setSubject(SUBJECT) // 设置JWT的payload,包含用户ID、头像和姓名 .claim("id", loginUser.getId()) .claim("loginUser", loginUser) // 过期时间(毫秒Long类型) .claim("expirationTime", expirationTime) // 设置JWT的签发时间 .setIssuedAt(new Date()) // 设置JWT的过期时间 .setExpiration(expirationTime) // 使用HS256算法和密钥对JWT进行签名 .signWith(SignatureAlgorithm.HS256, SECRET) // 生成JWT字符串 .compact(); // 前缀加生成的token token = TOKEN_PREFIX + token; return token; } /** * 校验token的方法 */ public static Claims checkJWT(String token) { try { // 使用密钥解析token,获取Claims对象 return Jwts.parser().setSigningKey(SECRET) // 这一步是把前缀去了 .parseClaimsJws(token.replace(TOKEN_PREFIX, "")).getBody(); // 返回Claims对象 } catch (Exception e) { // 解析失败 System.out.println("jwt token解析失败"); // 输出错误信息 return null; // 返回null } } }
解析token内容
- 通过工具类里
checkJWT(String token)
来解析 token 里的用户信息(数据)
Claims claims = JwtUtil.checkJWT(token);
// 获取封装的内容(获取在工具类里设置的payload)
Integer id = (Integer) claims.get("id");
LoginUser loginuser = (LoginUser) claims.get("loginuser");
- 获取当前Token的创建时间与过期时间
// 创建生成token的对象
LoginUser loginUser = new LoginUser();
loginUser.setId(1L);
// 生成token
String token = JwtUtil.geneJsonWebToken(loginUser);
// 解析token
Claims claims = JwtUtil.checkJWT(token);
// 获取token过期时间(毫秒,在payload里设置的expirationTime字段 - Long类型)
// Tips:以下获取的都是时间戳!!!!
Long expirationTime = (Long) claims.get("expirationTime");
// 获取自带的过期时间与生成时间(Integer类型 - 秒)
Integer createTime = (Integer) claims.get("iat"); // 创建时间
Integer destroyTime = (Integer) claims.get("exp"); // 销毁时间
System.out.println(expirationTime); // 1688992877754
System.out.println(createTime); // 1688991077
System.out.println(destroyTime); // 1688992877
时间戳转换网站:时间戳(Unix timestamp)-时间戳转换器
三. 统一返回数据格式
前后端数据交互,统一返回
Json
格式
1. JsonData
Maven 包管理:
-
依赖(
.pom
)<!-- Jackson --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-json</artifactId> <version>2.5.5</version> </dependency> <dependency> <groupId>javax.servlet</groupId> <artifactId>javax.servlet-api</artifactId> <version>4.0.1</version> </dependency> <!-- 上面的jackson也可以改为fastjson --> <!-- 改为fastjason时需要修改下面工具类的响应方法 --> <dependency> <groupId>com.alibaba</groupId> <artifactId>fastjson</artifactId> <version>1.2.79</version> </dependency>
-
工具类(
.java
)// jackson import com.fasterxml.jackson.databind.ObjectMapper; // fastjson import com.alibaba.fastjson.JSON; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.io.PrintWriter; /** * 响应json 通用类 */ public class JsonData { /** * 状态码 0 表示成功,1表示处理中,-1表示失败 */ private Integer code; /** * 数据 */ private Object data; /** * 描述 */ private String msg; /** * 空构造 */ public JsonData() { } /** * 带参构造 * @param code * @param data * @param msg */ public JsonData(Integer code, Object data, String msg) { this.code = code; this.data = data; this.msg = msg; } /** * 成功,不需要传入数据 * @return */ public static JsonData buildSuccess() { return new JsonData(200, null, null); } /** * 成功,传入数据 * @param data * @return */ public static JsonData buildSuccess(Object data) { return new JsonData(200, data, null); } /** * 成功,传入数据和消息 * @param data * @param msg * @return */ public static JsonData buildSuccess(Object data,String msg){ return new JsonData(200,data,msg); } /** * 失败,传入描述信息 * @param msg * @return */ public static JsonData buildError(String msg) { return new JsonData(-1, null, msg); } public static JsonData buildError(String msg,Object data) { return new JsonData(-1, data, msg); } /** * 自定义状态码和错误信息 * @param code * @param msg * @return */ public static JsonData buildCodeAndMsg(int code, String msg) { return new JsonData(code, null, msg); } /** * 自定义状态码、数据以及消息信息 * @param code * @param msg * @param data * @return */ public static JsonData buildCodeAndMsgAndData(int code, String msg,Object data) { return new JsonData(code, data, msg); } /** * 将 封装的JsonData 对象转成json后响应客户端 * @param response * @param jsonData * @return */ public static void returnJson(HttpServletResponse response,JsonData jsonData){ try { response.setContentType("text/json;charset=utf-8"); PrintWriter out = response.getWriter(); // 使用jackson(两个只能选择一个啊) String result = new ObjectMapper().writeValueAsString(jsonData); // 使用fastjson // String result = JSON.toJSONString(jsonData); out.print(result); out.flush(); out.close(); } catch (IOException e) { System.err.println("响应json数据异常!!!"); e.printStackTrace(); } } public Integer getCode() { return code; } public void setCode(Integer code) { this.code = code; } public Object getData() { return data; } public void setData(Object data) { this.data = data; } public String getMsg() { return msg; } public void setMsg(String msg) { this.msg = msg; } @Override public String toString() { return "JsonData{" + "code=" + code + ", data=" + data + ", msg='" + msg + '\'' + '}'; } }
四. Http请求
用于发送请求,访问第三方的
Api
接口,以及解析其中的数据
1. httpclient
Tips:也可以用作解决跨域问题(代理服务器)!
Maven 包管理:
-
依赖(
.pom
)<dependency> <groupId>org.apache.httpcomponents</groupId> <artifactId>httpclient</artifactId> <version>4.5.13</version> </dependency>
1 - 常规请求
url传参
// 图片验证码
// https://www.mxnzp.com/api/verifycode/code?app_secret=申请的id&app_id=申请的id&type=类型(0:图片,1:Base64字节数组)&len=验证码长度
public static ImageVerification getImageVerification(){
// app_secret
String appSecret = "申请id";
// app_id
String appId = "申请id";
// 验证码类型
int type = 0;
// 验证码长度
int len = 6;
// url
String url = "https://www.mxnzp.com/api/verifycode/code?app_secret=" + appSecret + "&app_id=" + appId + "&type=" + type + "&len=" + len;
try {
// 创建一个HttpClient实例
HttpClient httpClient = HttpClientBuilder.create().build();
// 创建一个HttpGet请求,指定URL
HttpGet request = new HttpGet(url);
// 执行请求,并获取响应
HttpResponse response = httpClient.execute(request);
// 将响应实体转换为字符串
String responseBody = EntityUtils.toString(response.getEntity());
System.out.println("-----------------图片验证码-----------------");
System.out.println(responseBody);
System.out.println("-----------------图片验证码-----------------");
// 反序列化(把Json串转为JSONObject对象,用于获取指定信息)
// JSONObject来自于 org.json.JSONObject;包
// 例如json格式为:"{"data":"hello","msg","查询成功!","code":123}"
JSONObject jsonObject = new JSONObject(responseBody);
// 则可以通过jsonObject.getString("data")获取到hello
// 还有别的方法(用于获取不同的数据类型):
// jsonObject.get();
// jsonObject.getString();
// jsonObject.getInt();
// jsonObject.getBoolean();
// jsonObject.getDouble();
// jsonObject.getLong();
String data = jsonObject.getString("data");
// 转为实体类
ObjectMapper objectMapper = new ObjectMapper();
ImageVerification imageVerification = objectMapper.readValue(data, ImageVerification.class);
System.out.println("图片验证码的密码为:" + imageVerification.getVerifyCode());
return imageVerification;
} catch (Exception e) {
System.err.println("图片验证码获取失败!!!!");
throw new RuntimeException(e);
}
}
2 - 设置请求体 / 头
在有时候请求的时候并不能直接用url传参,而是使用post请求来获取信息的话,只能设置请求体或请求头去发送请求
public JsonData sendPhoneCode(String phone) {
// 创建HttpClient对象
HttpClient httpClient = HttpClientBuilder.create().build();
// 请求头参数
String nonce = getRandomNum();
String curTime = String.valueOf(System.currentTimeMillis());
String CheckSum = CheckSumBuilder.getCheckSum(APP_SECRET, nonce, curTime);
// 设置请求头(Header)
HttpPost httpPost = new HttpPost(url);
// 请求类型(application/x-www-form-urlencoded表单提交)
httpPost.setHeader(HttpHeaders.CONTENT_TYPE, "application/x-www-form-urlencoded");
// 字符编码
httpPost.setHeader("charset", "utf-8");
// 其他信息(根据Api提供方添加)
httpPost.setHeader("AppKey", APP_KEY);
httpPost.setHeader("Nonce", nonce);
httpPost.setHeader("CurTime", curTime);
httpPost.setHeader("CheckSum", checkSum);
// 创建请求体数据(Body)
List<NameValuePair> params = new ArrayList<>();
params.add(new BasicNameValuePair("mobile", phone));
params.add(new BasicNameValuePair("codeLen", CODE_LEN));
try {
httpPost.setEntity(new UrlEncodedFormEntity(params));
// 发送请求并获取响应
HttpResponse response = httpClient.execute(httpPost);
HttpEntity entity = response.getEntity();
String responseBody = EntityUtils.toString(entity);
System.out.println("发送验证码结果:" + responseBody);
JsonData jsonData = new JsonData();
// 把返回结果解析为键值对从而获取具体的信息
JSONObject jsonObject = new JSONObject(responseBody);
// 获取信息
int code = jsonObject.getInt("code");
String msg = jsonObject.getString("msg");
String data = jsonObject.getString("obj");
// 赋值响应
jsonData.setCode(code);
jsonData.setMsg(msg);
jsonData.setData(data);
return jsonData;
} catch (Exception e) {
throw new RuntimeException(e);
}
}
五. 短信验证码
用于请求第三方服务,发送短信验证码实现登录注册等功能…
1. 网易云信
官网:网易云信 - IM即时通讯云 -音视频通话 (163.com)
20次免费发送的次数
流程需求
需求:
- 身份证实名认证(不需要手持身份证)
- 环境:jdk 8 - 11 都可以,测试过
流程:
-
注册(实名认证)
-
登录
-
在首页点击
创建应用(填下应用名称、行业类型、应用简介以及应用环境)
-
创建完成之后点击你的项目名称,进入详情页面(
取AppKey
) -
在产品总览里 -> 短信 -> 免费开通(
开通下短信服务
) -
开通完之后点击功能配置(
查看剩余短信数量...
) -
点击安全配置(可以查看短信默认配置,可以
修改默认配置
) -
功能管理 -> 短信功能管理 -> 国内短信 -> 签名/正文模板管理(
获取发送短信的模板
) -
生成发送短信的模板(
这个就是你手机上短信的样子
) -
以上创建模板已经完成了,返回到第四步(回到应用首页),去选择
AppKey管理
这一项 -
获取
AppKey
与AppSecret
-
返回首页 -> 你的项目 -> 产品总览 -> 短信 -> 功能配置 -> 短信功能管理 -> 国内短信开发文档(
查看提供发送短信的接口
) -
进来之后有很多接口API,在这里我只说明下两个接口:发送短信已经校验短信正确性
1 - 公共请求头
不管是发送短信还是校验短信都需要设置如下
Header
参数
官方概述:Header 参数为公共请求参数,应用服务端请求云信 IM 服务端,都需在Header 中配置如下参数。
参数 | 参数说明 |
---|---|
AppKey | 通过云信控制台获取,详见[获取 App key](https://doc.yunxin.163.com/docs/Tk5NzkwOTY/TA1ODMzMDc?platformId=50434#获取 App Key) - 上面第11步 |
Nonce | 随机数(最大长度 128 个字符) - 可以自己写一个工具类随机生成128为数数字 |
CurTime | 当前 UTC 时间戳,从 1970 年 1 月 1 日 0 时 0 分 0 秒开始到 现在(指发起请求瞬间的前后 5 分钟内)的秒数(类型为 String) - 获取当前时间戳 |
CheckSum | SHA1(AppSecret + Nonce + CurTime),将该三个参数拼接的字符串进行 SHA1 哈希计算从而生成 16 进制字符(类型为 String,小写)出于安全性考虑,每个CheckSum 的有效期为 5 分钟(用CurTime 计算),建议每次请求都生成新的CheckSum ,同时请确认发起请求的服务器是与标准时间同步的,比如有NTP服务。CheckSum 检验失败时会返回 414 错误码,更多错误码信息请参见状态码。 - 官网提供的工具类 |
2 - 发送短信
接口介绍:
- 🔗URL:https://api.netease.im/sms/sendcode.action
请求说明:
POST https://api.netease.im/sms/sendcode.action HTTP/1.1
Content-Type:application/x-www-form-urlencoded;charset=utf-8
接口描述:
向指定的手机号码发送文本短信验证码或语音短信验证码。
参数说明:(设置的请求体)
参数 | 类型 | 必须 | 说明 |
---|---|---|---|
mobile | String | 是 | 目标手机号,非中国大陆手机号码需要填写国家代码(如美国:+1-xxxxxxxxxx)或地区代码(如香港:+852-xxxxxxxx) |
deviceId | String | 否 | 目标设备号,可选参数 |
templateid | int | 否 | 模板编号(如不指定则使用配置的默认模版) |
codeLen | int | 否 | 验证码长度,默认为 4 位,取值范围为 4-10 (注:语音验证码的取值范围为 4-8位)。 |
authCode | String | 否 | 客户自定义验证码,长度为 4 ~ 10 位,支持字母和数字。 如果设置了该参数,则codeLen参数无效 |
needUp | Boolean | 否 | 是否需要支持短信上行。true:需要,false:不需要 说明:如果开通了短信上行抄送功能,该参数需要设置为true,其它情况设置无效 |
请求示例:
curl -X POST -H "AppKey: go9dnk49bkd9jd9vmel1kglw0803mgq3" -H "CurTime: 1443592222" -H "CheckSum: 9e9db3b6c9abb2e1962cf3e6f7316fcc55583f86" -H "Nonce: 4tgggergigwow323t23t" -H "Content-Type: application/x-www-form-urlencoded" -d 'mobile=13812345678' 'https://api.netease.im/sms/sendcode.action'
返回说明:
http 响应:json
发送成功则返回相关信息。msg字段表示此次发送的sendid;obj字段表示此次发送的验证码。
"Content-Type": "application/json; charset=utf-8"
{
"code": 200,
"msg": "88",
"obj": "1908"
}
3 - 校验短信
接口介绍:
- 🔗URL:https://api.netease.im/sms/verifycode.action
请求说明:
POST https://api.netease.im/sms/verifycode.action HTTP/1.1
Content-Type:application/x-www-form-urlencoded;charset=utf-8
接口描述:
校验指定手机号的验证码是否合法。
参数说明:(设置的请求体)
参数 | 类型 | 必须 | 说明 |
---|---|---|---|
mobile | String | 是 | 目标手机号,非中国大陆手机号码需要填写国家代码(如美国:+1-xxxxxxxxxx)或地区代码(如香港:+852-xxxxxxxx) |
code | String | 是 | 验证码 |
curl请求示例
curl -X POST -H "AppKey: go9dnk49bkd9jd9vmel1kglw0803mgq3" -H "CurTime: 1443592222" -H "CheckSum: 9e9db3b6c9abb2e1962cf3e6f7316fcc55583f86" -H "Nonce: 4tgggergigwow323t23t" -H "Content-Type: application/x-www-form-urlencoded" -d 'mobile=13812345678&code=1234' 'https://api.netease.im/sms/verifycode.action'
返回说明
http 响应:json
"Content-Type": "application/json; charset=utf-8"
{
"code":200
}
4 - 返回常用状态码
200、301、315、403、404、413、414、500
具体请参考code状态表
5 - 工具类
以下为发送验证码 - 5分钟有效期并同一手机号60秒内不能重复发送请求
Java开发环境
-
依赖(
.pom
):<!-- 发送http请求 --> <dependency> <groupId>org.apache.httpcomponents</groupId> <artifactId>httpclient</artifactId> <version>4.5.13</version> </dependency> <!-- Redis操作 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> <version>2.5.5</version> </dependency> <dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-pool2</artifactId> <version>2.5.5</version> </dependency>
发送验证码与校验验证码
package project.pet.util.sms.eleven;
import org.apache.http.HttpEntity;
import org.apache.http.HttpHeaders;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.HttpClient;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;
import org.json.JSONObject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import project.pet.util.JsonData;
import project.pet.util.MyUtil;
import java.util.*;
import java.util.concurrent.TimeUnit;
/**
* 全 POST 请求
* <p>
* 接码平台:https://app.yunxin.163.com/global/home
* 参数:
* 1. AppKey:你的key
* 2. AppSecret:你的key
* 请求头:
* 1. Content-Type:application/x-www-form-urlencoded
* 2. charset:utf-8
* 3. AppKey:网站提供
* 4. Nonce:随机的 1 - 128 位随机数
* 5. CurTime:当前时间戳
* 6. CheckSum:AppSecret + Nonce + CurTime 组合的SHA1加密密文
* 请求体:
* 1. mobile:目标手机号码(收短信的人儿)
* 2. codeLen:短信验证码的长度(4-10位!)
* 3. code:校验的验证码(校验接口使用)
* 接口:
* 1. 发送验证码:https://api.netease.im/sms/sendcode.action
* 2. 校验验证码:https://api.netease.im/sms/verifycode.action
* Tips:
* 写的肥肠详细,短信数量没有了就去申请,一个人20条
*/
@Component
public class SendPhoneCode {
// AppKey
private final String APP_KEY = "你的key";
// AppSecret
private final String APP_SECRET = "你的key";
// 验证码位数
private final String CODE_LEN = String.valueOf(6);
// Redis操作
@Autowired
private RedisTemplate redisTemplate;
public JsonData sendPhoneCode(String phone) {
// 手机号码验证
if (!MyUtil.isValidPhoneNumber(phone)){
return JsonData.buildError("手机号码格式不合法!");
}
// 创建HttpClient对象
HttpClient httpClient = HttpClientBuilder.create().build();
// 请求头参数
String nonce = getRandomNum();
String curTime = String.valueOf(System.currentTimeMillis());
String CheckSum = CheckSumBuilder.getCheckSum(APP_SECRET, nonce, curTime);
// 获取剩余时间(以秒为单位)
Long remainingTime = redisTemplate.getExpire("smsCode:" + phone, TimeUnit.SECONDS);
// 用来实现对同一手机号60秒内不能发送多次请求获取验证码
if (remainingTime >= 240) {
return JsonData.buildCodeAndMsg(444, "60秒内只能请求一次,请待会儿再来!");
}
// 设置请求头
HttpPost httpPost = createHttpPost("https://api.netease.im/sms/sendcode.action", nonce, curTime, CheckSum);
// 创建请求体数据
List<NameValuePair> params = new ArrayList<>();
params.add(new BasicNameValuePair("mobile", phone));
params.add(new BasicNameValuePair("codeLen", CODE_LEN));
try {
httpPost.setEntity(new UrlEncodedFormEntity(params));
// 发送请求并获取响应
HttpResponse response = httpClient.execute(httpPost);
HttpEntity entity = response.getEntity();
String responseBody = EntityUtils.toString(entity);
System.out.println("发送验证码结果:" + responseBody);
JsonData jsonData = new JsonData();
// 把返回结果解析为键值对从而获取具体的信息
JSONObject jsonObject = new JSONObject(responseBody);
// 获取信息
int code = jsonObject.getInt("code");
String msg = jsonObject.getString("msg");
String data = jsonObject.getString("obj");
// 赋值响应
jsonData.setCode(code);
jsonData.setMsg(msg);
jsonData.setData(data);
// 存储到缓存中(必须找个地方存下,校验的时候需要取出来进行合成CheckSum来校验)
redisTemplate.opsForHash().put("smsCode:" + phone, "nonce", nonce);
redisTemplate.opsForHash().put("smsCode:" + phone, "curTime", curTime);
redisTemplate.opsForHash().put("smsCode:" + phone, "CheckSum", CheckSum);
// 存储验证码
redisTemplate.opsForHash().put("smsCode:" + phone, "code", data);
// 设置过期时间,标识(60s内重复请求)
redisTemplate.expire("smsCode:" + phone, 300, TimeUnit.SECONDS);
return jsonData;
} catch (Exception e) {
throw new RuntimeException(e);
}
}
public JsonData checkPhoneCode(String phone, String code) {
// 创建HttpClient对象
HttpClient httpClient = HttpClientBuilder.create().build();
// 创建HttpPost对象,设置URL
// 从缓存中获取值
Map<String, Object> entries = redisTemplate.opsForHash().entries("smsCode:" + phone);
if (entries.size() == 0) {
return JsonData.buildCodeAndMsg(404, "验证码已过期请重新发送!");
}
if (!entries.get("code").equals(code)) {
return JsonData.buildCodeAndMsg(413, "验证码有误请重新输入!");
}
// 请求头参数
String nonce = (String) entries.get("nonce");
String curTime = (String) entries.get("curTime");
String CheckSum = (String) entries.get("CheckSum");
// 设置请求头
HttpPost httpPost = createHttpPost("https://api.netease.im/sms/verifycode.action", nonce, curTime, CheckSum);
// 创建请求体数据
List<NameValuePair> params = new ArrayList<>();
params.add(new BasicNameValuePair("mobile", phone));
params.add(new BasicNameValuePair("code", code));
try {
httpPost.setEntity(new UrlEncodedFormEntity(params));
// 发送请求并获取响应
HttpResponse response = httpClient.execute(httpPost);
HttpEntity entity = response.getEntity();
String responseBody = EntityUtils.toString(entity);
System.out.println("校验验证码发送结果:" + responseBody);
JsonData jsonData = new JsonData();
JSONObject jsonObject = new JSONObject(responseBody);
int returnCode = jsonObject.getInt("code");
jsonData.setCode(returnCode);
if (returnCode!= 200){
jsonData.setMsg("验证码校验失败!");
jsonData.setData(jsonObject.getString("obj"));
return jsonData;
}
jsonData.setMsg("验证码正确!");
System.out.println("校验验证码结果:" + responseBody);
return jsonData;
} catch (Exception e) {
throw new RuntimeException(e);
}
}
// 设置公共请求头
private HttpPost createHttpPost(String url,String nonce,String curTime,String checkSum){
HttpPost httpPost = new HttpPost(url);
httpPost.setHeader(HttpHeaders.CONTENT_TYPE, "application/x-www-form-urlencoded");
httpPost.setHeader("charset", "utf-8");
httpPost.setHeader("AppKey", APP_KEY);
httpPost.setHeader("Nonce", nonce);
httpPost.setHeader("CurTime", curTime);
httpPost.setHeader("CheckSum", checkSum);
return httpPost;
}
// 生成1-128之间的随机长度(用于生成公共请求头参数的Nonce)
private String getRandomNum() {
int length = new Random().nextInt(128) + 1;
StringBuilder sb = new StringBuilder();
String characters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
Random random = new Random();
for (int i = 0; i < length; i++) {
int index = random.nextInt(characters.length());
char randomChar = characters.charAt(index);
sb.append(randomChar);
}
return sb.toString();
}
}
// 其中的JsonData为同一返回数据格式(在上面的笔记中可以找到)
// MyUtil为自己写的工具类
生成CheckSum的工具类(官方提供)
package project.pet.util.sms.eleven;
import java.security.MessageDigest;
public class CheckSumBuilder {
// 计算并获取CheckSum
public static String getCheckSum(String appSecret, String nonce, String curTime) {
return encode("sha1", appSecret + nonce + curTime);
}
// 计算并获取md5值
public static String getMD5(String requestBody) {
return encode("md5", requestBody);
}
private static String encode(String algorithm, String value) {
if (value == null) {
return null;
}
try {
MessageDigest messageDigest
= MessageDigest.getInstance(algorithm);
messageDigest.update(value.getBytes());
return getFormattedText(messageDigest.digest());
} catch (Exception e) {
throw new RuntimeException(e);
}
}
private static String getFormattedText(byte[] bytes) {
int len = bytes.length;
StringBuilder buf = new StringBuilder(len * 2);
for (int j = 0; j < len; j++) {
buf.append(HEX_DIGITS[(bytes[j] >> 4) & 0x0f]);
buf.append(HEX_DIGITS[bytes[j] & 0x0f]);
}
return buf.toString();
}
private static final char[] HEX_DIGITS = { '0', '1', '2', '3', '4', '5',
'6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
}