package com.ltkj.web.controller.app;
|
|
import com.alibaba.fastjson.JSON;
|
import com.alibaba.fastjson.JSONObject;
|
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
import com.google.gson.Gson;
|
import com.google.gson.reflect.TypeToken;
|
import com.ltkj.common.core.controller.BaseController;
|
import com.ltkj.common.core.domain.AjaxResult;
|
import com.ltkj.common.utils.StringUtils;
|
import com.ltkj.common.utils.WechatUtil;
|
import com.ltkj.common.utils.sign.Base64;
|
import com.ltkj.framework.config.JwtUtils;
|
import com.ltkj.framework.config.UserHoder;
|
import com.ltkj.hosp.domain.GetPhone;
|
import com.ltkj.hosp.domain.Wxuser;
|
import com.ltkj.hosp.service.IAbucoderWxuserService;
|
import io.swagger.annotations.Api;
|
import io.swagger.annotations.ApiOperation;
|
import io.swagger.annotations.ApiParam;
|
import lombok.extern.slf4j.Slf4j;
|
import okhttp3.OkHttpClient;
|
import okhttp3.Request;
|
import okhttp3.Response;
|
import org.aspectj.bridge.MessageWriter;
|
import org.bouncycastle.jce.provider.BouncyCastleProvider;
|
import org.springframework.beans.factory.annotation.Value;
|
import org.springframework.web.bind.annotation.*;
|
import org.springframework.web.client.RestTemplate;
|
import sun.misc.BASE64Decoder;
|
|
import javax.annotation.Resource;
|
import javax.crypto.Cipher;
|
import javax.crypto.spec.IvParameterSpec;
|
import javax.crypto.spec.SecretKeySpec;
|
import javax.net.ssl.*;
|
import java.io.*;
|
import java.net.URL;
|
import java.security.AlgorithmParameters;
|
import java.security.Security;
|
import java.security.cert.CertificateException;
|
import java.security.cert.X509Certificate;
|
import java.util.Arrays;
|
import java.util.Date;
|
import java.util.HashMap;
|
import java.util.Map;
|
|
/**
|
* @Author: 西安路泰科技有限公司/赵佳豪
|
* @Date: 2022/11/17 11:01
|
*/
|
|
/**
|
* 客户移动端端操作接口
|
*/
|
@RestController
|
@RequestMapping("/cus")
|
@Api(tags = "A小程序端登录接口大全")
|
@Slf4j
|
public class WxloginController extends BaseController {
|
|
|
@Resource
|
private IAbucoderWxuserService wxuserService;
|
|
@Value("${xcx.appid}")
|
private String appid;
|
|
@Value("${xcx.secret}")
|
private String secret;
|
|
/**
|
* 小程序登录
|
* @param code 小程序wx.login返回的临时凭证
|
* @return
|
*/
|
@PostMapping("/wx/login")
|
@ApiOperation("小程序登录接口")
|
public AjaxResult login(@RequestParam @ApiParam(value = "code") String code,
|
@RequestParam @ApiParam(value = "number") String number,
|
@RequestParam @ApiParam(value = "iv") String iv) {
|
|
// 用户登录凭证(有效期五分钟)
|
if (StringUtils.isEmpty(code)) {
|
return AjaxResult.error("登录凭证不能为空");
|
}
|
JSONObject jsonObject = code2sessionKey(code);
|
String openId = jsonObject.getString("openid");
|
String sessionKey = jsonObject.getString("session_key");
|
if (StringUtils.isEmpty(openId)) {
|
return AjaxResult.error("登录失败,无效的登录凭证");
|
}
|
JSONObject parse = decryptionUserInfo(number, sessionKey, iv);
|
if (null != parse) {
|
LambdaQueryWrapper<Wxuser> wq = new LambdaQueryWrapper<>();
|
wq.eq(Wxuser::getOpenid, openId);
|
Wxuser one = wxuserService.getOne(wq);
|
Map<String, Object> map = new HashMap<>();
|
if (null != one) {
|
one.setUpdateTime(new Date());
|
one.setWxMiniOpenId(openId);
|
wxuserService.updateById(one);
|
map.put("wxuser", one);
|
} else {
|
Wxuser wxuser = new Wxuser();
|
wxuser.setOpenid(openId);
|
wxuser.setNickname(parse.get("nickName").toString());
|
wxuser.setAvatar(parse.get("avatarUrl").toString());
|
wxuser.setGender((Integer) parse.get("gender"));
|
wxuser.setCreateTime(new Date());
|
wxuser.setWxMiniOpenId(openId);
|
wxuserService.save(wxuser);
|
map.put("wxuser",wxuser);
|
}
|
// 生成令牌
|
String token = JwtUtils.getToken(map);
|
Map<String, Object> map1 = new HashMap<>();
|
map1.put("token", token);
|
map1.put("openId", openId);
|
map1.put("sessionKey", sessionKey);
|
return AjaxResult.success(map1);
|
}
|
return AjaxResult.success("授权失败");
|
}
|
|
/**
|
* @return
|
*/
|
@GetMapping("/wx/getWxInfo")
|
@ApiOperation(value = "小程序获取用户详情信息接口")
|
public AjaxResult getWxInfo() {
|
Wxuser wxuser = UserHoder.getWxuser();
|
LambdaQueryWrapper<Wxuser>wq=new LambdaQueryWrapper<>();
|
wq.eq(Wxuser::getOpenid,wxuser.getOpenid());
|
Wxuser one = wxuserService.getOne(wq);
|
return AjaxResult.success(one);
|
}
|
/**
|
* 微信手机号码绑定
|
*/
|
@PostMapping("/wx/bindPhone")
|
@ApiOperation(value = "根据身份证号获取用户信息")
|
public AjaxResult bindPhone(@RequestParam String openId,
|
@RequestParam String sessionKey,
|
@RequestParam String iv,
|
@RequestParam String encryptedData,
|
@RequestParam String code) {
|
|
|
LambdaQueryWrapper<Wxuser> wq = new LambdaQueryWrapper<>();
|
wq.eq(Wxuser::getOpenid, openId);
|
Wxuser one = wxuserService.getOne(wq);
|
if (one != null) {
|
try {
|
BASE64Decoder decoder = new BASE64Decoder();
|
byte[] raw = decoder.decodeBuffer(sessionKey);
|
SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES");
|
IvParameterSpec iv1 = new IvParameterSpec(decoder.decodeBuffer(iv));
|
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding","BC");
|
cipher.init(Cipher.DECRYPT_MODE, skeySpec, iv1);
|
OkHttpClient client = new OkHttpClient();
|
Request okrequest = new Request.Builder()
|
.url("https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=" + appid + "&secret=" + secret)
|
.build();
|
Response okresponse = client.newCall(okrequest).execute();
|
String responsedata = okresponse.body().string();
|
Gson gson = new Gson();
|
GetPhone o = gson.fromJson(responsedata, new TypeToken<GetPhone>() {
|
}.getType());
|
com.alibaba.fastjson2.JSONObject jsonObject = new com.alibaba.fastjson2.JSONObject();
|
jsonObject.put("code", code);
|
String json = jsonObject.toString();
|
String url = "https://api.weixin.qq.com/wxa/business/getuserphonenumber?access_token=" + o.getAccess_token();
|
RestTemplate restTemplate = new RestTemplate();
|
String result = restTemplate.postForObject(url, json, String.class);
|
String getJsona = com.alibaba.fastjson2.JSON.parseObject(result).getString("phone_info");
|
String strjsona = com.alibaba.fastjson2.JSON.parseObject(getJsona, String.class); //指定获取 字段名对象信息,如果为单个String可不指定,这里作为实例写出
|
String phone = com.alibaba.fastjson2.JSON.parseObject(strjsona).getString("phoneNumber");
|
one.setPhone(phone);
|
one.setUpdateTime(new Date());
|
if (wxuserService.updateById(one)) {
|
return AjaxResult.success(phone);
|
}
|
return AjaxResult.success(phone);
|
} catch (Exception ex) {
|
return AjaxResult.success();
|
}
|
}
|
return AjaxResult.success();
|
}
|
|
/**
|
* 发送请求用code换取sessionKey和相关信息
|
* @param code
|
* @return
|
*/
|
public JSONObject code2sessionKey(String code) {
|
String stringToken = String.format(
|
"https://api.weixin.qq.com/sns/jscode2session?appid=%s&secret=%s&js_code=%s&grant_type=authorization_code",
|
appid, secret, code);
|
String response = httpsRequestToString(stringToken, "GET", null);
|
return JSON.parseObject(response);
|
}
|
|
/**
|
* 小程序解密用户数据
|
* @param encryptedData
|
* @param sessionKey
|
* @param iv
|
* @return
|
*
|
*/
|
/**
|
* 解决java不支持AES/CBC/PKCS7Padding模式解密
|
*/
|
static {
|
Security.addProvider(new BouncyCastleProvider());
|
}
|
|
public static JSONObject decryptionUserInfo(String encryptedData, String sessionKey, String iv) {
|
// 被加密的数据
|
byte[] dataByte = Base64.decode(encryptedData);
|
// 加密秘钥
|
byte[] keyByte = Base64.decode(sessionKey);
|
// 偏移量
|
byte[] ivByte = Base64.decode(iv);
|
|
try {
|
// 如果密钥不足16位,那么就补足. 这个if 中的内容很重要
|
int base = 16;
|
if (keyByte.length % base != 0) {
|
int groups = keyByte.length / base + (keyByte.length % base != 0 ? 1 : 0);
|
byte[] temp = new byte[groups * base];
|
Arrays.fill(temp, (byte) 0);
|
System.arraycopy(keyByte, 0, temp, 0, keyByte.length);
|
keyByte = temp;
|
}
|
// 初始化
|
Security.addProvider(new BouncyCastleProvider());
|
/**
|
* 解决java不支持AES/CBC/PKCS7Padding模式解密
|
*/
|
|
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS7Padding", "BC");
|
SecretKeySpec spec = new SecretKeySpec(keyByte, "AES");
|
AlgorithmParameters parameters = AlgorithmParameters.getInstance("AES");
|
parameters.init(new IvParameterSpec(ivByte));
|
cipher.init(Cipher.DECRYPT_MODE, spec, parameters);// 初始化
|
byte[] resultByte = cipher.doFinal(dataByte);
|
if (null != resultByte && resultByte.length > 0) {
|
String result = new String(resultByte, "UTF-8");
|
return JSONObject.parseObject(result);
|
|
}
|
} catch (Exception e) {
|
e.printStackTrace();
|
}
|
return null;
|
}
|
|
|
|
/**
|
* 发送https请求
|
*
|
* @param path
|
* @param method
|
* @param body
|
* @return
|
*/
|
public String httpsRequestToString(String path, String method, String body) {
|
if (path == null || method == null) {
|
return null;
|
}
|
String response = null;
|
InputStream inputStream = null;
|
InputStreamReader inputStreamReader = null;
|
BufferedReader bufferedReader = null;
|
HttpsURLConnection conn = null;
|
try {
|
// 创建SSLConrext对象,并使用我们指定的信任管理器初始化
|
SSLContext sslContext = SSLContext.getInstance("SSL", "SunJSSE");
|
TrustManager[] tm = {new X509TrustManager() {
|
@Override
|
public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {
|
}
|
|
@Override
|
public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
|
}
|
|
@Override
|
public X509Certificate[] getAcceptedIssuers() {
|
return null;
|
}
|
|
}};
|
sslContext.init(null, tm, new java.security.SecureRandom());
|
|
// 从上面对象中得到SSLSocketFactory
|
SSLSocketFactory ssf = sslContext.getSocketFactory();
|
|
URL url = new URL(path);
|
conn = (HttpsURLConnection) url.openConnection();
|
conn.setSSLSocketFactory(ssf);
|
|
conn.setDoOutput(true);
|
conn.setDoInput(true);
|
conn.setUseCaches(false);
|
|
// 设置请求方式(get|post)
|
conn.setRequestMethod(method);
|
|
// 有数据提交时
|
if (null != body) {
|
OutputStream outputStream = conn.getOutputStream();
|
outputStream.write(body.getBytes("UTF-8"));
|
outputStream.close();
|
}
|
|
// 将返回的输入流转换成字符串
|
inputStream = conn.getInputStream();
|
inputStreamReader = new InputStreamReader(inputStream, "UTF-8");
|
bufferedReader = new BufferedReader(inputStreamReader);
|
String str = null;
|
StringBuffer buffer = new StringBuffer();
|
while ((str = bufferedReader.readLine()) != null) {
|
buffer.append(str);
|
}
|
|
response = buffer.toString();
|
} catch (Exception e) {
|
|
} finally {
|
if (conn != null) {
|
conn.disconnect();
|
}
|
try {
|
bufferedReader.close();
|
inputStreamReader.close();
|
inputStream.close();
|
} catch (IOException execption) {
|
|
}
|
}
|
return response;
|
}
|
|
}
|