Browse Source

腾讯物联网 微信用户注册登录

yanyuan
zhizhi wu 4 years ago
parent
commit
5a72f70da1
  1. 10
      signin/src/main/java/com/ccsens/signin/api/FiotExplorerController.java
  2. 1
      signin/src/main/java/com/ccsens/signin/bean/vo/FiotVo.java
  3. 4
      signin/src/main/resources/application.yml
  4. 2
      util/src/main/java/com/ccsens/util/KCPlayerSignature.java
  5. 32
      util/src/main/java/com/ccsens/util/RestTemplateUtil.java
  6. 13
      wechatutil/src/main/java/com/ccsens/wechatutil/bean/po/wxfiotexplorer/FiotSignin.java
  7. 3
      wechatutil/src/main/java/com/ccsens/wechatutil/bean/po/wxfiotexplorer/FiotSigninResponse.java
  8. 4
      wechatutil/src/main/java/com/ccsens/wechatutil/bean/po/wxfiotexplorer/ResponseInfo.java
  9. 137
      wechatutil/src/main/java/com/ccsens/wechatutil/util/TC3Util.java
  10. 26
      wechatutil/src/main/java/com/ccsens/wechatutil/wxfiotexplorer/FiotExplorerSigninUtil.java
  11. 4
      wechatutil/src/main/resources/application.yml

10
signin/src/main/java/com/ccsens/signin/api/FiotExplorerController.java

@ -12,6 +12,7 @@ import com.ccsens.signin.exception.UserLoginException;
import com.ccsens.util.JsonResponse;
import com.ccsens.util.WebConstant;
import com.ccsens.util.wx.WxXcxUtil;
import com.ccsens.wechatutil.bean.po.wxfiotexplorer.FiotSigninResponse;
import com.ccsens.wechatutil.wxfiotexplorer.FiotExplorerSigninUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParams;
@ -45,12 +46,13 @@ public class FiotExplorerController {
public JsonResponse<FiotVo.Signin> userSignin(@ApiParam @Validated @RequestBody(required = true)FiotDto.Signin signin) throws Exception {
log.info("物联网用户登录:{}", signin);
String type = "FIOT";
WxXcxUtil.WechatUser wechatUser = WxXcxUtil.getUserInfo(signin.getCode(), type);
String token = FiotExplorerSigninUtil.getToken(wechatUser.openid, signin.getNickName(), signin.getAvatar(), WxXcxUtil.appId(type));
WxXcxUtil.WechatUser wechatUser = WxXcxUtil.getUserInfo(signin.getCode(), "yanyuan");
log.info("用户账号:{}", wechatUser);
FiotSigninResponse response = FiotExplorerSigninUtil.getToken(wechatUser.openid, signin.getNickName(), signin.getAvatar(), WxXcxUtil.appId(type));
FiotVo.Signin vo = new FiotVo.Signin();
vo.setToken(token);
vo.setToken(response.getToken());
vo.setExpireAt(response.getExpireAt());
log.info("物联网用户登录结果:{}", vo);
return JsonResponse.newInstance().ok(vo);
}
}

1
signin/src/main/java/com/ccsens/signin/bean/vo/FiotVo.java

@ -14,5 +14,6 @@ public class FiotVo {
@ApiModel("物联网登录-返回")
public static class Signin{
private String token;
private long expireAt;
}
}

4
signin/src/main/resources/application.yml

@ -1,5 +1,5 @@
spring:
profiles:
active: prod
include: util-prod,common
active: test
include: util-test,common

2
util/src/main/java/com/ccsens/util/KCPlayerSignature.java

@ -59,7 +59,7 @@ public class KCPlayerSignature{
return strSign;
}
private String base64Encode(byte[] buffer) {
public static String base64Encode(byte[] buffer) {
Base64.Encoder encoder = Base64.getEncoder();
return encoder.encodeToString(buffer);
}

32
util/src/main/java/com/ccsens/util/RestTemplateUtil.java

@ -1,5 +1,6 @@
package com.ccsens.util;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
@ -87,6 +88,37 @@ public class RestTemplateUtil {
return response.getBody();
}
public static String postBodySpecialHeader(String url, Object params, Map<String, String> headMap) {
log.info("路径:{}, 参数:{}", url, params);
HttpHeaders httpHeaders = new HttpHeaders();
MediaType type=MediaType.parseMediaType("application/json;charset=UTF-8");
httpHeaders.setContentType(type);
if (CollectionUtil.isNotEmpty(headMap)) {
for (Map.Entry<String, String> entry: headMap.entrySet()) {
httpHeaders.set(entry.getKey(), entry.getValue());
}
}
// MultiValueMap<String, Object> map=new LinkedMultiValueMap<>();
JSONObject json = JSON.parseObject(JSON.toJSONString(params));
HttpEntity<Map<String, Object>> objectHttpEntity = new HttpEntity<>(json,httpHeaders);
URI uri = null;
try {
uri = new URI(url);
}catch (URISyntaxException e) {
log.error("转换路径异常:{}", e);
throw new BaseException(CodeEnum.URL_ERROR);
}
log.info("uri:{}",uri);
log.info("json:{}",json);
log.info("objectHttpEntity:{}",objectHttpEntity);
ResponseEntity<String> response = util.restTemplate.postForEntity(uri, objectHttpEntity, String.class);
log.info("返回:{}", response);
return response.getBody();
}
public static String postBody1(String url, List<? extends Object> params) {
log.info("路径:{}, 参数:{}", url, params);
HttpHeaders httpHeaders = new HttpHeaders();

13
wechatutil/src/main/java/com/ccsens/wechatutil/bean/po/wxfiotexplorer/FiotSignin.java

@ -5,6 +5,7 @@ import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.HexUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.annotation.JSONField;
import com.ccsens.wechatutil.util.TC3Util;
import lombok.Data;
@ -23,38 +24,47 @@ public class FiotSignin {
/**
* 公共参数本接口取值AppGetTokenByWeiXin
*/
@JSONField(name="Action")
private String Action = "AppGetTokenByWeiXin";
/**
* 公共参数唯一请求 ID可自行生成推荐使用 uuid定位问题时需提供该次请求的 RequestId
*/
@JSONField(name="RequestId")
private String RequestId = UUID.randomUUID().toString();
/**
* 公共参数应用 AppKey 用于标识对应的小程序或 App
*/
@JSONField(name="AppKey")
private String AppKey = null;
/**
* 公共参数请求签名需用户自行生成用于校验请求的合法性
*/
@JSONField(name="Signature")
private String Signature = null;
/**
* 公共参数请求的 UINX 时间戳秒级
*/
@JSONField(name="Timestamp")
private long Timestamp = System.currentTimeMillis() / 1000;
/**
* 公共参数随机正整数 Timestamp 联合起来防止重放攻击
*/
@JSONField(name="Nonce")
private int Nonce = new Random().nextInt(10000);
/**
* 微信用户的 OpenID UnionID
*/
@JSONField(name="WxOpenID")
private String WxOpenID;
/**
* 昵称
*/
@JSONField(name="NickName")
private String NickName;
/**
* 头像
*/
@JSONField(name="Avatar")
private String Avatar;
public FiotSignin() {
@ -66,7 +76,8 @@ public class FiotSignin {
this.NickName = nickName;
this.Avatar = avatar;
this.AppKey = appKey;
this.Signature = TC3Util.generateSignature("iot", "iot.cloud.tencent.com", this.Timestamp, null);
JSONObject json = JSONObject.parseObject(JSONObject.toJSONString(this));
this.Signature = TC3Util.generateSignature(json);
}

3
wechatutil/src/main/java/com/ccsens/wechatutil/bean/po/wxfiotexplorer/FiotSigninResponse.java

@ -1,5 +1,6 @@
package com.ccsens.wechatutil.bean.po.wxfiotexplorer;
import com.alibaba.fastjson.annotation.JSONField;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
@ -11,7 +12,9 @@ import lombok.Data;
@Data
public class FiotSigninResponse {
@ApiModelProperty("截止时间,UINX 秒级时间戳")
@JSONField(name = "ExpireAt")
private Long ExpireAt;
@ApiModelProperty("开发平台返回的 AccessToken,通过该 Token 进行登录后的接口请求")
@JSONField(name = "Token")
private String Token;
}

4
wechatutil/src/main/java/com/ccsens/wechatutil/bean/po/wxfiotexplorer/ResponseInfo.java

@ -10,7 +10,9 @@ import lombok.Data;
*/
@Data
public class ResponseInfo<T> {
private Info<T> Response;
private int code;
private String msg;
private Info<T> data;
private String RequestId;

137
wechatutil/src/main/java/com/ccsens/wechatutil/util/TC3Util.java

@ -1,6 +1,9 @@
package com.ccsens.wechatutil.util;
import cn.hutool.core.codec.Base64Encoder;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSONObject;
import com.ccsens.util.KCPlayerSignature;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
@ -9,9 +12,7 @@ import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.TimeZone;
import java.util.TreeMap;
import java.util.*;
/**
* @description:
@ -22,7 +23,12 @@ public class TC3Util {
private final static Charset UTF8 = StandardCharsets.UTF_8;
private final static String SECRET_ID = "AKIDxhBRRAdplRpwnMfnfGaeRxDBsJTN0NTI";
private final static String SECRET_KEY = "Zrte9MPFo68tMZU8WcXDeqnVx95rYzA6";
private final static String APP_KEY = "mEulfDBBOFeOjGavy";
private final static String APP_SECRET = "FaFKWiwVUWbJmfxVnSdd";
private final static String CT_JSON = "application/json; charset=utf-8";
//签名算法
private static final String HMAC_ALGORITHM = "HmacSHA1";
private static final String CONTENT_CHARSET = "UTF-8";
public static byte[] hmac256(byte[] key, String msg) throws Exception {
Mac mac = Mac.getInstance("HmacSHA256");
@ -37,6 +43,72 @@ public class TC3Util {
return DatatypeConverter.printHexBinary(d).toLowerCase();
}
public static Map<String, String> getHeaders(String service, long timestamp, String signature){
Map<String, String> headMap = new HashMap<>();
String algorithm = "TC3-HMAC-SHA256";
String signedHeaders = "content-type;host";
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
// 注意时区,否则容易出错
sdf.setTimeZone(TimeZone.getTimeZone("UTC"));
String date = sdf.format(new Date(Long.valueOf(timestamp + "000")));
String credentialScope = date + "/" + service + "/" + "tc3_request";
String authorization = algorithm + " " + "Credential=" + SECRET_ID + "/" + credentialScope + ", "
+ "SignedHeaders=" + signedHeaders + ", " + "Signature=" + signature;
headMap.put("Authorization", authorization);
return headMap;
}
public static void main(String[] args) throws Exception {
JSONObject json = new JSONObject();
json.put("Action","AppGetTokenByWeiXin");
json.put("RequestId","4c582f20-608a-41eb-8a04-b19cd341a328");
json.put("AppKey","mEulfDBBOFeOjGavy");
json.put("Timestamp","1638345578");
json.put("Nonce","3493");
json.put("WxOpenId","oOBSe5HAi885IlNeAAb3FQYxwExI");
json.put("NickName","wu");
json.put("Avatar","https://thirdwx.qlogo.cn/mmopen/vi_32/4KIkPtTLnuGdQPo1YqiaqRAgjyIPz4NyDzZVwwKJiatibWhszIH02XmWyqnl7LW1zYmRMbF2UYQG5o4N0cgyPH0qw/132");
System.out.println(json);
String s = generateSignature(json);
System.out.println("s:" + s);
// String data = "Action=AppCreateCellphoneUser&AppKey=ahPxdK****TGrejd&CountryCode=86&Nonce=71087795&Password=My!P@ssword&PhoneNumber=13900000000&RequestId=8b8d499bbba1ac28b6da21b4&Timestamp=1546315200&VerificationCode=123456";
// Mac mac = Mac.getInstance(HMAC_ALGORITHM);
// SecretKeySpec secretKey = new SecretKeySpec("NcbHqk****TCGbKnQH".getBytes(), HMAC_ALGORITHM);
// mac.init(secretKey);
//
// byte[] hash = mac.doFinal(data.getBytes());
// String strSign = Base64Encoder.encode(hash);
// System.out.println("strSign:" + strSign);
}
public static String generateSignature(Map<String, Object> param) throws Exception {
StringBuilder builder = new StringBuilder();
Set<String> keys = param.keySet();
Object[] keyArr = keys.toArray();
Arrays.sort(keyArr);
for (Object keyObj: keyArr) {
String key = (String) keyObj;
if (param.get(key) == null || "".equals(param.get(key))) {
continue;
}
builder.append(key.replaceAll("_",".")).append("=").append(param.get(key)).append("&");
}
System.out.println("builder:" + builder.toString());
String plaintext = builder.substring(0, builder.length() - 1);
Mac mac = Mac.getInstance(HMAC_ALGORITHM);
SecretKeySpec secretKey = new SecretKeySpec(APP_SECRET.getBytes(), HMAC_ALGORITHM);
mac.init(secretKey);
byte[] hash = mac.doFinal(plaintext.getBytes());
// String strSign = KCPlayerSignature.base64Encode(hash);
String strSign = Base64Encoder.encode(hash);
// strSign = strSign.replace(" ", "").replace("\n", "").replace("\r", "");
return strSign;
}
public static String generateSignature(String service, String host, long timestamp, String payload) throws Exception {
//String service = "cvm";
//String host = "cvm.tencentcloudapi.com";
@ -74,34 +146,35 @@ public class TC3Util {
byte[] secretService = hmac256(secretDate, service);
byte[] secretSigning = hmac256(secretService, "tc3_request");
String signature = DatatypeConverter.printHexBinary(hmac256(secretSigning, stringToSign)).toLowerCase();
System.out.println(signature);
// ************* 步骤 4:拼接 Authorization *************
String authorization = algorithm + " " + "Credential=" + SECRET_ID + "/" + credentialScope + ", "
+ "SignedHeaders=" + signedHeaders + ", " + "Signature=" + signature;
TreeMap<String, String> headers = new TreeMap<String, String>();
headers.put("Authorization", authorization);
headers.put("Content-Type", CT_JSON);
headers.put("Host", host);
// headers.put("X-TC-Action", action);
// headers.put("X-TC-Timestamp", timestamp);
// headers.put("X-TC-Version", version);
// headers.put("X-TC-Region", region);
StringBuilder sb = new StringBuilder();
sb.append("curl -X POST https://").append(host)
.append(" -H \"Authorization: ").append(authorization).append("\"")
.append(" -H \"Content-Type: application/json; charset=utf-8\"")
.append(" -H \"Host: ").append(host).append("\"");
// .append(" -H \"X-TC-Action: ").append(action).append("\"")
// .append(" -H \"X-TC-Timestamp: ").append(timestamp).append("\"")
// .append(" -H \"X-TC-Version: ").append(version).append("\"")
// .append(" -H \"X-TC-Region: ").append(region).append("\"")
if (StrUtil.isNotEmpty(payload)) {
sb.append(" -d '").append(payload).append("'");
}
return sb.toString();
return signature;
// System.out.println(signature);
//
// // ************* 步骤 4:拼接 Authorization *************
// String authorization = algorithm + " " + "Credential=" + SECRET_ID + "/" + credentialScope + ", "
// + "SignedHeaders=" + signedHeaders + ", " + "Signature=" + signature;
//
// TreeMap<String, String> headers = new TreeMap<String, String>();
// headers.put("Authorization", authorization);
// headers.put("Content-Type", CT_JSON);
// headers.put("Host", host);
//// headers.put("X-TC-Action", action);
//// headers.put("X-TC-Timestamp", timestamp);
//// headers.put("X-TC-Version", version);
//// headers.put("X-TC-Region", region);
//
// StringBuilder sb = new StringBuilder();
// sb.append("curl -X POST https://").append(host)
// .append(" -H \"Authorization: ").append(authorization).append("\"")
// .append(" -H \"Content-Type: application/json; charset=utf-8\"")
// .append(" -H \"Host: ").append(host).append("\"");
//// .append(" -H \"X-TC-Action: ").append(action).append("\"")
//// .append(" -H \"X-TC-Timestamp: ").append(timestamp).append("\"")
//// .append(" -H \"X-TC-Version: ").append(version).append("\"")
//// .append(" -H \"X-TC-Region: ").append(region).append("\"")
// if (StrUtil.isNotEmpty(payload)) {
// sb.append(" -d '").append(payload).append("'");
// }
//
// return sb.toString();
}
}

26
wechatutil/src/main/java/com/ccsens/wechatutil/wxfiotexplorer/FiotExplorerSigninUtil.java

@ -9,6 +9,7 @@ import com.ccsens.util.exception.BaseException;
import com.ccsens.wechatutil.bean.po.wxfiotexplorer.FiotSignin;
import com.ccsens.wechatutil.bean.po.wxfiotexplorer.FiotSigninResponse;
import com.ccsens.wechatutil.bean.po.wxfiotexplorer.ResponseInfo;
import com.ccsens.wechatutil.util.TC3Util;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
@ -46,13 +47,13 @@ public class FiotExplorerSigninUtil {
public static String getToken(String openId, String nickName, String avatar, String appKey) throws Exception {
public static FiotSigninResponse getToken(String openId, String nickName, String avatar, String appKey) throws Exception {
log.info("物联网查询token:{},{},{}", openId, nickName, avatar);
String key = StrUtil.format(TOKEN_KEY, openId);
Object o = util.redisUtil.get(key);
log.info("{}缓存的token:{}", key, o);
if (o != null) {
return (String) o;
return (FiotSigninResponse) o;
}
// 查询token
@ -61,17 +62,22 @@ public class FiotExplorerSigninUtil {
String s = RestTemplateUtil.postBody(SIGN_URL, fiotSignin);
log.info("登录结果:{}", s);
if (StrUtil.isEmpty(s)) {
log.info("登录结果为空");
throw new BaseException(CodeError.THIRD_ERROR);
}
ResponseInfo<FiotSigninResponse> res = JSONObject.parseObject(s, ResponseInfo.class);
if (res.getResponse() == null) {
throw new BaseException(CodeError.THIRD_ERROR);
} else if (res.getResponse().getError() != null ) {
throw new BaseException(CodeError.THIRD_ERROR.getCode(), res.getResponse().getError().getMessage());
JSONObject json = JSONObject.parseObject(s);
log.info("json:{}", json);
String dataKey = "data";
String realDataKey = "Data";
if (json.get(dataKey) == null || json.getJSONObject(dataKey).get(realDataKey) == null) {
log.info("数据异常");
throw new BaseException(CodeError.THIRD_ERROR.getCode(), json.getString("msg"));
}
FiotSigninResponse data = res.getResponse().getData();
util.redisUtil.set(key, data.getToken(), data.getExpireAt() - System.currentTimeMillis()/1000);
return data.getToken();
FiotSigninResponse data = JSONObject.parseObject(json.getJSONObject(dataKey).getString(realDataKey), FiotSigninResponse.class);
util.redisUtil.set(key, data, data.getExpireAt() - System.currentTimeMillis()/1000);
log.info("登录返回:{}", data);
return data;
}

4
wechatutil/src/main/resources/application.yml

@ -1,5 +1,5 @@
spring:
profiles:
active: dev
include: util-dev,common
active: test
include: util-test,common

Loading…
Cancel
Save