Commit 421fc632 authored by shiyu's avatar shiyu

Merge remote-tracking branch 'origin/master'

parents 37047fd3 3ac41f48
package com.wwdz.ch.db.dto.request;
import com.xxdxxs.entity.Entity;
import lombok.Data;
@Data
public class UserSearchRequestDto implements Entity {
private Long id;
private String mobile;
private String nickname;
}
......@@ -53,6 +53,12 @@
<artifactId>weixin-java-miniapp</artifactId>
</dependency>
<dependency>
<groupId>com.alipay.sdk</groupId>
<artifactId>alipay-sdk-java</artifactId>
<version>4.34.0.ALL</version>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
......
package com.wwdz.ch.wx.constant;
import java.util.HashMap;
import java.util.Map;
public enum LoginTypeEnum {
WECHAT(1, "微信"),
ALIPAY(2, "支付宝"),
TIKTOK(3, "抖音"),
;
private Integer code;
private String name;
LoginTypeEnum(Integer code, String name) {
this.code = code;
this.name = name;
}
public Integer getCode() {
return code;
}
public String getName() {
return name;
}
public static String getDesByCode(String code) {
for (LoginTypeEnum loginTypeEnum : LoginTypeEnum.values()) {
if (code.equals(loginTypeEnum.getCode())) {
return loginTypeEnum.getName();
}
}
return null;
}
/**
* 返回map
* @return
*/
public static Map<Integer, String> getLoginTypeEnumMap() {
Map<Integer, String> map = new HashMap<>();
for (LoginTypeEnum loginTypeEnum : LoginTypeEnum.values()) {
map.put(loginTypeEnum.getCode(), loginTypeEnum.getName());
}
return map;
}
}
......@@ -31,9 +31,16 @@ public class ItemRequestDto implements Entity {
private String detail;
// 藏品价格
private String price;
// 当前页
private Integer page;
// 页面大小
private Integer size;
// 页面路径
private String path;
// 查看详情的入口类型(1、钱柜,2、足迹)
private Integer type;
// 页面路径
private String pageUrl;
// 环境类型(1、微信,2、支付宝,3、抖音)
private Integer loginType;
}
......@@ -21,4 +21,6 @@ public class UserRequestDto implements Entity {
private String encryptedData;
private String iv;
private Integer type;
// 快捷登录方式(1、微信,2、支付宝,3、抖音)
private Integer loginType;
}
......@@ -12,9 +12,12 @@ import com.wwdz.ch.db.dao.*;
import com.wwdz.ch.db.domain.*;
import com.wwdz.ch.db.dto.request.EsSearchRequestDto;
import com.wwdz.ch.db.es.ItemEsDao;
import com.wwdz.ch.wx.constant.LoginTypeEnum;
import com.wwdz.ch.wx.entity.request.ItemRequestDto;
import com.wwdz.ch.wx.entity.vo.AgentTranceResponseVo;
import com.wwdz.ch.wx.entity.vo.ItemResponseVo;
import com.wwdz.ch.wx.manager.AlipayLoginManager;
import com.wwdz.ch.wx.manager.TikTokLoginManager;
import com.wwdz.ch.wx.manager.WxLoginManager;
import com.wwdz.ch.wx.service.ItemService;
import com.wwdz.ch.wx.util.StringUtil;
......@@ -59,6 +62,10 @@ public class ItemServiceImpl implements ItemService {
@Autowired
private WxLoginManager wxLoginManager;
@Autowired
private AlipayLoginManager alipayLoginManager;
@Autowired
private TikTokLoginManager tikTokLoginManager;
@Autowired
private QiniuStorage qiniuStorage;
@Autowired
private UserDao userDao;
......@@ -476,6 +483,7 @@ public class ItemServiceImpl implements ItemService {
String urlOfSize = qiniuStorage.generateUrl(keyName);
Map<String, Object> map = new HashMap<>();
map.put("url", urlOfSize);
logger.info("【请求结束】获取微信小程序码成功");
return Result.success(map);
} catch (Exception e) {
logger.error("获取微信小程序码失败", e);
......@@ -483,6 +491,51 @@ public class ItemServiceImpl implements ItemService {
}
}
@Override
public Result getAcode(String page, String scene, Integer loginType, HttpServletResponse response) {
try {
String url = "";
if (loginType.equals(LoginTypeEnum.WECHAT.getCode())) {
// 判断是否存储过该请求路径的微信小程序码图片
String keyName = CommConsts.UPLOAD_PRE_WXACODE_DIRECTORY + page + "/" + scene + "." + MediaTypeEnum.IMAGE_JPG.getExt();
FileInfo fileInfo = (FileInfo) qiniuStorage.checkFile(keyName);
if (Objects.isNull(fileInfo)) {
InputStream inputStream = wxLoginManager.getWxacodeStream(page, scene);
if (Objects.isNull(inputStream)) {
return Result.failed("获取微信小程序流失败");
}
// 新生成微信小程序码并上传到七牛云
qiniuStorage.store(inputStream, 1, MediaTypeEnum.IMAGE_JPG.getMime(), keyName);
}
url = qiniuStorage.generateUrl(keyName);
}
if (loginType.equals(LoginTypeEnum.ALIPAY.getCode())) {
url = alipayLoginManager.getAcode(page, scene);
if (StringUtils.isBlank(url)) {
return Result.failed("获取支付宝小程序码失败");
}
}
if (loginType.equals(LoginTypeEnum.TIKTOK.getCode())) {
String clientToken = tikTokLoginManager.getClientToken();
if (StringUtils.isBlank(clientToken)) {
return Result.failed("获取token失败");
}
url = tikTokLoginManager.getAcode(clientToken, page, scene);
if (StringUtils.isBlank(url)) {
return Result.failed("获取抖音小程序码失败");
}
}
Map<String, Object> map = new HashMap<>();
map.put("url", url);
logger.info("【请求结束】获取小程序码成功");
return Result.success(map);
} catch (Exception e) {
logger.error("获取小程序码失败", e);
return Result.failed("获取小程序码失败");
}
}
@Override
public Result getWxLink(String pageUrl) {
try {
......@@ -499,6 +552,41 @@ public class ItemServiceImpl implements ItemService {
}
}
@Override
public Result getLink(String pageUrl, Integer loginType) {
try {
String link = "";
if (loginType.equals(LoginTypeEnum.WECHAT.getCode())) {
link = wxLoginManager.getLink(pageUrl);
if (StringUtils.isBlank(link)) {
return Result.failed("获取微信小程序链接失败");
}
}
if (loginType.equals(LoginTypeEnum.ALIPAY.getCode())) {
link = alipayLoginManager.getLink(pageUrl);
if (StringUtils.isBlank(link)) {
return Result.failed("获取支付宝小程序链接失败");
}
}
if (loginType.equals(LoginTypeEnum.TIKTOK.getCode())) {
String clientToken = tikTokLoginManager.getClientToken();
if (StringUtils.isBlank(clientToken)) {
return Result.failed("获取token失败");
}
link = tikTokLoginManager.getLink(clientToken, pageUrl);
if (StringUtils.isBlank(link)) {
return Result.failed("获取抖音小程序链接失败");
}
}
Map<String, Object> map = new HashMap<>();
map.put("link", link);
return Result.success(map);
} catch (Exception e) {
logger.error("获取小程序链接失败", e);
return Result.failed("获取小程序链接失败");
}
}
@Override
public Result uploadImage(MultipartFile file) {
try {
......
......@@ -15,9 +15,12 @@ import com.wwdz.ch.db.dao.UserDao;
import com.wwdz.ch.db.domain.User;
import com.wwdz.ch.db.dto.request.FavoritesRequestDto;
import com.wwdz.ch.wx.constant.CacheCodeConstants;
import com.wwdz.ch.wx.constant.LoginTypeEnum;
import com.wwdz.ch.wx.dao.UserInfo;
import com.wwdz.ch.wx.dao.UserToken;
import com.wwdz.ch.wx.entity.request.UserRequestDto;
import com.wwdz.ch.wx.manager.AlipayLoginManager;
import com.wwdz.ch.wx.manager.TikTokLoginManager;
import com.wwdz.ch.wx.manager.UserTokenManager;
import com.wwdz.ch.wx.manager.WxLoginManager;
import com.wwdz.ch.wx.service.FavoritesService;
......@@ -60,6 +63,10 @@ public class UserServiceImpl implements UserService {
@Autowired
private WxLoginManager wxLoginManager;
@Autowired
private AlipayLoginManager alipayLoginManager;
@Autowired
private TikTokLoginManager tikTokLoginManager;
@Autowired
private RedisUtil redisUtil;
@Value("${avatar-url}")
......@@ -68,45 +75,6 @@ public class UserServiceImpl implements UserService {
private AliSmsSender aliSmsSender;
@Transactional
@Override
public Result loginByWx(UserRequestDto dto, HttpServletRequest request) {
try {
String mobile = "";
try {
mobile = wxLoginManager.getPhone(dto);
if (StringUtils.equals("false", mobile)) {
return Result.failed("获取access_token失败");
}
if (StringUtils.equals("sessionFalse", mobile)) {
return Result.failed("获取sessionKey失败");
}
if (StringUtils.equals("phoneFalse", mobile)) {
return Result.failed("获取手机号失败");
}
if (StringUtils.equals("decryptFalse", mobile)) {
return Result.failed(ResultCode.FAILED.getCode(), "用户信息解密失败");
}
} catch (Exception e) {
logger.error("获取微信用户手机号失败", e);
return Result.failed("获取微信用户手机号失败");
}
if (StringUtils.isBlank(mobile)) {
logger.error("获取微信用户手机号失败");
return Result.failed("获取微信用户手机号失败");
}
// 获取登录结果
Map<String, Object> result = getLoginResult(mobile, request);
logger.info("【请求结束】手机号登录,响应结果:{}", JSONObject.toJSONString(result));
return Result.success(result);
} catch (Exception e) {
logger.error("微信快捷登录失败", e);
TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
return Result.failed("微信快捷登录失败");
}
}
@Override
public Result regCaptcha(UserRequestDto dto) {
try {
......@@ -172,6 +140,98 @@ public class UserServiceImpl implements UserService {
}
}
@Transactional
@Override
public Result login(UserRequestDto dto, HttpServletRequest request) {
try {
String mobile = "";
try {
if (dto.getLoginType().equals(LoginTypeEnum.WECHAT.getCode())) {
mobile = wxLoginManager.getPhone(dto);
if (StringUtils.equals("false", mobile)) {
return Result.failed("获取access_token失败");
}
if (StringUtils.equals("sessionFalse", mobile)) {
return Result.failed("获取sessionKey失败");
}
if (StringUtils.equals("phoneFalse", mobile)) {
return Result.failed("获取手机号失败");
}
if (StringUtils.equals("decryptFalse", mobile)) {
return Result.failed(ResultCode.FAILED.getCode(), "用户信息解密失败");
}
}
if (dto.getLoginType().equals(LoginTypeEnum.ALIPAY.getCode())) {
mobile = alipayLoginManager.getPhone(dto.getEncryptedData());
if (StringUtils.equals("false", mobile)) {
return Result.failed("用户信息解密失败");
}
}
if (dto.getLoginType().equals(LoginTypeEnum.TIKTOK.getCode())) {
String sessionKey = tikTokLoginManager.getSessionKey(dto.getCode());
if (StringUtils.isBlank(sessionKey)) {
return Result.failed("获取sessionKey失败");
}
mobile = tikTokLoginManager.getPhone(dto.getEncryptedData(), sessionKey, dto.getIv());
if (StringUtils.equals("false", mobile)) {
return Result.failed("用户信息解密失败");
}
}
} catch (Exception e) {
logger.error("获取用户手机号异常", e);
return Result.failed("获取用户手机号失败");
}
// 获取登录结果
Map<String, Object> result = getLoginResult(mobile, request);
logger.info("【请求结束】快捷登录成功,响应结果:{}", JSONObject.toJSONString(result));
return Result.success(result);
} catch (Exception e) {
logger.error("快捷登录失败", e);
TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
return Result.failed("快捷登录失败");
}
}
@Transactional
@Override
public Result loginByWx(UserRequestDto dto, HttpServletRequest request) {
try {
String mobile = "";
try {
mobile = wxLoginManager.getPhone(dto);
if (StringUtils.equals("false", mobile)) {
return Result.failed("获取access_token失败");
}
if (StringUtils.equals("sessionFalse", mobile)) {
return Result.failed("获取sessionKey失败");
}
if (StringUtils.equals("phoneFalse", mobile)) {
return Result.failed("获取手机号失败");
}
if (StringUtils.equals("decryptFalse", mobile)) {
return Result.failed(ResultCode.FAILED.getCode(), "用户信息解密失败");
}
} catch (Exception e) {
logger.error("获取微信用户手机号失败", e);
return Result.failed("获取微信用户手机号失败");
}
if (StringUtils.isBlank(mobile)) {
logger.error("获取微信用户手机号失败");
return Result.failed("获取微信用户手机号失败");
}
// 获取登录结果
Map<String, Object> result = getLoginResult(mobile, request);
logger.info("【请求结束】手机号登录,响应结果:{}", JSONObject.toJSONString(result));
return Result.success(result);
} catch (Exception e) {
logger.error("微信快捷登录失败", e);
TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
return Result.failed("微信快捷登录失败");
}
}
@Transactional(rollbackFor = Exception.class)
@Override
public Result updateProfile(UserRequestDto dto) {
......
package com.wwdz.ch.wx.manager;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.TypeReference;
import com.alibaba.fastjson.parser.Feature;
import com.alipay.api.AlipayApiException;
import com.alipay.api.AlipayClient;
import com.alipay.api.DefaultAlipayClient;
import com.alipay.api.internal.util.AlipayEncrypt;
import com.alipay.api.internal.util.AlipaySignature;
import com.alipay.api.request.AlipayOpenAppQrcodeCreateRequest;
import com.alipay.api.response.AlipayOpenAppQrcodeCreateResponse;
import com.xxdxxs.utils.JsonUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import java.net.URLEncoder;
import java.util.Map;
/**
* 支付宝小程序服务
*/
@Service
public class AlipayLoginManager {
private static final Logger logger = LoggerFactory.getLogger(AlipayLoginManager.class);
// 支付宝小程序对应的appid
private static final String appid = "2021004108672867";
// 支付宝小程序对应的支付宝公钥
private static final String signVeriKey = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAgUwrLm4n13ixVgq1nUS3Aggieny0yxl8uiwNEKNNoL8MZnvrKmZSFAgr8m7384OLuElo2CXTTMZWCNeGo7If+qb1whCBsrGBfWAjrEdFlTNirWINaoS9F/fvJPRQ/biFryvhvP/AJewkAA2NuxZwbYpelw6zc+lNF0bGiSBujAawFs1Ok2SQMMk4javXvUwibx7u+aiSCDOy7IaZW+Rv6wVfeHT2uHIDKvOYyitdmjiJikuIzvILeZs4sZwlZvWEbEa1bPmAhi5ZZsh62Nt7Xd3OnMvcj9VK9xkJGJ3Dgx3MmAC54kDl0CST9a4sdRRbMi4gd7v+K8e484TQdHjQMwIDAQAB";
// 支付宝小程序对应的加解密密钥
private static final String decryptKey = "kpeGeMSDTQZWyheHWt4Iwg==";
// 支付宝小程序对应的应用私钥
private static final String privateKey = "MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQDltXUqBWcnmTt8O/vc8Br9hF87mKB3+9KQ5jN9Oh8FCs0J+0mED+ggBKLhNCsBb+uyu+MHqs5kBYDTwqp5fDPTyW37RklvfpHcf9HO9o1V7+C+t7qA2GLaXl/G5JDjpIipd+sHLj/yPw5DsTuMi8HUwb+ninSoil0Bg2QqTYL/2TiAfJ3+3s7nKIrjuEUmd47qFfpoyyPP0ZY+3E57M+vkklEvFWy8dCCvEh9bZY4ebVS4IUMLyhATpCqn8ESOjlkaIC4rAuTLhr52+hNsQUGzeVcKmpKGYm4YEhKaiwGW0MecjFd5wLj/ThPNnHNk23CwVfgN74ISu5UwibSHNzydAgMBAAECggEANw2tXfvbhD8SZa0OqR4Wqen+1Q64buk4xyeU8Y9rfc7f42OJdBBH5tyVmPni0L5dNAIZ4G2Md6ZmANqn9uPQnBKrvExVL1abaMhtpXer2gvaxnrMRTMXRhTWSZngK970LgGin57zDoEUTx78EawxMWeaInJpkTdQIRu3dvgKzHxz2uuWPXvRWTsgHrOcya7tjB05aQDJvPmZIfduER170kRw+nkhNLYoaYnfvlG5lBS+Nbw9wJmIt1VziET+anBEjCiQAxZdefsw2O9+N27MR8dToOyY2/03rzByuSZav204D6BG9Ggs47ogfvoszFYzXxedqj8WNXmtW59za++XNQKBgQD8q6WzgKdFp9mdZp0O9WfbYwUnrTnijRIJo6if2YMUipN/nbsEo50MDeWMEVfxrW+JYkgcL5xU6FDtPwoR5uN31NaFluuqSCoOdVtTUgpdNIMIDKbmplr5b8WuF7Ng0mSi9FYhRqbkQS0Lk412/eUxvXWIcyhUnbb3cqGPart/ZwKBgQDovFods6BF1gdfKDIWNZB4wTCUkQ7KOHmHfuHdAhZVMjC0R+TqjXMi6Xgt6N/D4wbJSk00iX3qGDynAxcltPjieER9Nsafm1vb7br+P+mcIz2j61GrDPZ2MvraUq3XJHxzM7BC7xGpISyukTY4UsSjW9r2sENyKYqsfK74HwaVWwKBgFuPxBNBStx2D+j3F3ElQwaAYozXPEO5xVCS6vdKNjMKaJr1SKFMvQtyOb3BRzJAHEwXvnPgWPF34mOm1XpZRhLVoQt1/l6Nmhf1NSwDbdgKwHT5SL4KiKsdcvA8jHdIpslaa5/RX4cVi0JHrRrytMyKkH3q5TGMmZIgCyXSkrF/AoGAa7KVZP81YHu9Z4xbOSnKVAbaKzXBCVT+7/OII1SO7xfNr+9BAEU6jWJKibwkqCoLfuRSO8iQKt7SWlq0wG8xaONMlkDdwwgKhwhIqtT6jpVENfF0FlpmRqYqrRLrfQ5WRJ0bqK2ml4RRf+qUk5XBhvK/rb49R7vvfwgnk4wP6NcCgYBnyaWUQU4tImWXBsIZ8OPZLcjYRmELg43BwYYU3S4vh2NIQAZnPXS56yobTPFGSntDUA3ESxsls60eKeBc1PSPPFOnTuXHs+tx/7AfuvG+pebRKauVXu9hcASvrBZcJoAirYhMKaMmoxdsodMhAc2ttzZyomLpplia1VcmI8NQ4A==";
// 支付宝小程序链接前缀
private static final String linkPrefix = "alipays://platformapi/startapp?appId=%s";
// 支付宝小程序调起前缀
private static final String openUrlPrefix = "https://ds.alipay.com/?scheme=%s";
/**
* 解密获取手机号
*
* @param response
* @return
*/
public String getPhone(String response) {
logger.info("开始解密获取支付宝小程序手机号");
// 获取验签和解密所需要的参数
Map<String, String> openapiResult = JSON.parseObject(response,new TypeReference<Map<String, String>>() {}, Feature.OrderedField);
String signType = "RSA2";
String charset = "UTF-8";
String encryptType = "AES";
String sign = openapiResult.get("sign");
String content = openapiResult.get("response");
// 判断是否为加密内容
boolean isDataEncrypted = !content.startsWith("{");
if (!isDataEncrypted) {
logger.info("支付宝解密失败,不是加密内容");
return "false";
}
boolean signCheckPass = false;
// 验签
String signContent = "\"" + content + "\"";
try {
signCheckPass = AlipaySignature.rsaCheck(signContent, sign, signVeriKey, charset, signType);
} catch (AlipayApiException e) {
logger.error("支付宝解密失败,验签异常", e);
return "false";
}
if (!signCheckPass) {
logger.info("支付宝解密失败,验签不通过");
return "false";
}
// 解密
String plainData = null;
try {
plainData = AlipayEncrypt.decryptContent(content, encryptType, decryptKey, charset);
} catch (AlipayApiException e) {
logger.error("支付宝解密失败,解密异常", e);
return "false";
}
if (StringUtils.isBlank(plainData) || !plainData.contains("mobile")) {
logger.info("支付宝解密失败,解密不通过");
return "false";
}
return JsonUtils.getValueByPath(plainData, "mobile");
}
/**
* 获取二维码
*
* @param page
* @param scene
* @return
*/
public String getAcode(String page, String scene) {
logger.info("开始调用支付宝生成小程序码接口");
AlipayClient alipayClient = new DefaultAlipayClient("https://openapi.alipay.com/gateway.do", appid, privateKey,"json","UTF8", signVeriKey,"RSA2");
AlipayOpenAppQrcodeCreateRequest request = new AlipayOpenAppQrcodeCreateRequest();
request.setBizContent("{" +
" \"url_param\":\"" + page + "\"," +
" \"query_param\":\"" + scene +"\"," +
" \"describe\":\"藏品分享\"," +
" \"color\":\"0x00BFFF\"," +
" \"size\":\"m\"" +
"}");
try {
AlipayOpenAppQrcodeCreateResponse response = alipayClient.execute(request);
logger.info("调用支付宝生成小程序码接口的结果:" + JSON.toJSONString(response));
if (response.isSuccess()) {
logger.info("调用支付宝生成小程序码成功");
return response.getQrCodeUrlCircleBlue();
}
} catch (Exception e) {
logger.error("调用支付宝生成小程序码失败", e);
}
logger.info("调用支付宝生成小程序码失败");
return null;
}
/**
* 获取链接
*
* @param pageUrl
* @return
*/
public String getLink(String pageUrl) {
try {
String[] page = pageUrl.split("\\?");
String encodeQuery = URLEncoder.encode(page[1], "UTF-8");
String link = String.format(linkPrefix, appid + "&page=" + page[0] + "?" + encodeQuery);
return String.format(openUrlPrefix, URLEncoder.encode(link, "UTF-8"));
} catch (Exception e) {
logger.info("获取支付宝小程序链接失败");
}
return null;
}
}
package com.wwdz.ch.wx.manager;
import com.alibaba.fastjson.JSON;
import com.wwdz.ch.core.util.OkHttpUtil;
import com.xxdxxs.utils.JsonUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Service;
import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.net.URLEncoder;
import java.util.Base64;
import java.util.Calendar;
import java.util.HashMap;
import java.util.Map;
/**
* 抖音小程序服务
*/
@Service
public class TikTokLoginManager {
private static final Logger logger = LoggerFactory.getLogger(TikTokLoginManager.class);
@Autowired
private ApplicationContext applicationContext;
// appid
private static final String appid = "ttc1fcb7415ec18f6f01";
// appSecret
private static final String appSecret = "1a248c43d69c4bcba48779efac2c6f3ade573ec7";
// 抖音小程序获取session_key的api正式环境
private static final String SANDBOX_SESSION_KEY_URL = "https://developer.toutiao.com/api/apps/v2/jscode2session";
// 抖音小程序获取session_key的api沙箱环境
private static final String PROD_SESSION_KEY_URL = "https://open-sandbox.douyin.com/api/apps/v2/jscode2session";
// 抖音小程序获取client_token的api正式环境
private static final String SANDBOX_CLIENT_TOKEN_URL = "https://open-sandbox.douyin.com/oauth/client_token/";
// 抖音小程序获取client_token的api沙箱环境
private static final String PROD_CLIENT_TOKEN_URL = "https://open.douyin.com/oauth/client_token/";
// 抖音小程序二维码地址
private static final String GET_ACODE_URL = "https://open.douyin.com/api/apps/v1/qrcode/create/";
// 抖音小程序链接地址
private static final String GET_LINK_URL = "https://open.douyin.com/api/apps/v1/url_link/generate";
/**
* 获取用户登录后的session_key
*
* @param code
* @return
*/
public String getSessionKey(String code) {
try {
logger.info("开始获取抖音小程序的session_key");
String activeProfile = applicationContext.getEnvironment().getActiveProfiles()[0];
String url = SANDBOX_SESSION_KEY_URL;
if (!StringUtils.equals("dev", activeProfile)) {
url = PROD_SESSION_KEY_URL;
}
Map<String, Object> param = new HashMap<>();
param.put("appid", appid);
param.put("secret", appSecret);
param.put("code", code);
String result = OkHttpUtil.builder().url(url)
.addParams(param)
.post(true).sync();
logger.info("获取抖音小程序session_key的结果:" + result);
if (!StringUtils.equals("0", JsonUtils.getValueByPath(result, "err_no"))) {
logger.info("获取抖音小程序session_key失败");
return null;
}
return JsonUtils.getValueByPath(result, "data/session_key");
} catch (Exception e) {
logger.error("获取抖音小程序session_key异常", e);
return null;
}
}
/**
* 解密获取手机号
*
* @param encryptedData
* @param sessionKey
* @param iv
* @return
*/
public String getPhone (String encryptedData, String sessionKey, String iv) {
try {
logger.info("开始进行抖音解密手机号");
Base64.Decoder decoder = Base64.getDecoder();
byte[] sessionKeyBytes = decoder.decode(sessionKey);
byte[] ivBytes = decoder.decode(iv);
byte[] encryptedBytes = decoder.decode(encryptedData);
// JDK does not support PKCS7Padding, use PKCS5Padding instead
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
SecretKeySpec skeySpec = new SecretKeySpec(sessionKeyBytes, "AES");
IvParameterSpec ivSpec = new IvParameterSpec(ivBytes);
cipher.init(Cipher.DECRYPT_MODE, skeySpec, ivSpec);
byte[] ret = cipher.doFinal(encryptedBytes);
String result = new String(ret);
logger.info("抖音解密手机号结果:" + result);
if (!result.contains("phoneNumber")) {
logger.info("抖音解密手机号失败");
return "false";
}
return JsonUtils.getValueByPath(result, "phoneNumber");
} catch (Exception e) {
logger.error("抖音解密手机号异常", e);
return "false";
}
}
/**
* 获取无需用户授权的接口调用凭证client_token
*
* @return
*/
public String getClientToken() {
try {
logger.info("开始获取抖音小程序的client_token");
String activeProfile = applicationContext.getEnvironment().getActiveProfiles()[0];
String url = SANDBOX_CLIENT_TOKEN_URL;
if (!StringUtils.equals("dev", activeProfile)) {
url = PROD_CLIENT_TOKEN_URL;
}
Map<String, Object> param = new HashMap<>();
param.put("client_key", appid);
param.put("client_secret", appSecret);
param.put("grant_type", "client_credential");
String result = OkHttpUtil.builder().url(url)
.addHeader("Content-Type", "multipart/form-data").addParams(param)
.post(true).sync();
logger.info("获取抖音小程序的client_token结果:" + result);
if (!result.contains("access_token")) {
logger.info("获取抖音小程序的client_token失败");
return null;
}
return JsonUtils.getValueByPath(result, "data/access_token");
} catch (Exception e) {
logger.error("获取抖音小程序的client_token异常", e);
return null;
}
}
/**
* 获取二维码
*
* @param clientToken
* @param page
* @param scene
* @return
*/
public String getAcode(String clientToken, String page, String scene) {
try {
logger.info("开始获取抖音小程序的二维码");
// 请求头
Map<String, String> headers = new HashMap<>();
headers.put("content-type", "application/json");
headers.put("access-token", clientToken);
// 参数
Map<String, Object> param = new HashMap<>();
param.put("app_name", "douyin");
param.put("appid", appid);
String path = URLEncoder.encode(page + "?" + scene, "UTF-8");
param.put("path", path);
param.put("set_icon", true);
// 发送请求
String result = OkHttpUtil.builder().url(GET_ACODE_URL)
.addHeaders(headers).addParams(param)
.post(true).sync();
logger.info("获取抖音小程序二维码的结果:" + result);
if (!result.contains("img")) {
logger.info("获取抖音小程序的二维码失败");
return null;
}
return JsonUtils.getValueByPath(result, "data/img");
} catch (Exception e) {
logger.info("获取抖音小程序的二维码异常", e);
return null;
}
}
/**
* 获取链接
*
* @param pageUrl
* @return
*/
public String getLink(String clientToken, String pageUrl) {
try {
logger.info("开始获取抖音小程序的链接");
// 请求头
Map<String, String> headers = new HashMap<>();
headers.put("content-type", "application/json");
headers.put("access-token", clientToken);
// 参数
Map<String, Object> param = new HashMap<>();
param.put("app_name", "douyin");
param.put("appid", appid);
String[] page = pageUrl.split("\\?");
param.put("path", page[0]);
// 包装query
String[] query = page[1].split("=");
Map<String, Object> queryMap = new HashMap<>();
queryMap.put(query[0], Integer.parseInt(query[1]));
param.put("query", JSON.toJSONString(queryMap));
Calendar calendar = Calendar.getInstance();
calendar.add(Calendar.DAY_OF_MONTH, 7);
param.put("expire_time", calendar.getTimeInMillis());
// 发送请求
String result = OkHttpUtil.builder().url(GET_LINK_URL)
.addHeaders(headers).addParams(param)
.post(true).sync();
logger.info("获取抖音小程序链接的结果:" + result);
if (!result.contains("url_link")) {
logger.info("获取抖音小程序的链接失败");
return null;
}
return JsonUtils.getValueByPath(result, "data/url_link");
} catch (Exception e) {
logger.error("获取抖音小程序的链接异常", e);
return null;
}
}
}
package com.wwdz.ch.wx.manager;
import cn.binarywang.wx.miniapp.api.WxMaService;
import cn.binarywang.wx.miniapp.api.impl.WxMaServiceImpl;
import cn.binarywang.wx.miniapp.bean.WxMaJscode2SessionResult;
import cn.binarywang.wx.miniapp.bean.WxMaPhoneNumberInfo;
import com.alibaba.fastjson.JSON;
......@@ -18,15 +17,24 @@ import java.io.InputStream;
import java.util.HashMap;
import java.util.Map;
/**
* 微信小程序服务
*/
@Service
public class WxLoginManager {
private static final Logger logger = LoggerFactory.getLogger(WxMaServiceImpl.class);
private static final Logger logger = LoggerFactory.getLogger(WxLoginManager.class);
// 微信小程序appid
private static final String appid = "wx5b4409448bf2c72b";
// 微信小程序secret
private static final String secret = "6fee0d7b2197845fed0a3fe8f5a9bd66";
// 微信小程序获取access_token地址
private static final String GET_ACCESS_TOKEN_URL = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=%s&secret=%s";
// 微信小程序获取用户手机号地址
private static final String GET_PHONE_URL = "https://api.weixin.qq.com/wxa/business/getuserphonenumber?access_token=%s";
// 微信小程序获取小程序码地址
private static final String GET_WXACODE_URL = "https://api.weixin.qq.com/wxa/getwxacodeunlimit?access_token=%s";
// 微信小程序获取短链接地址
private static final String GET_LINK_URL = "https://api.weixin.qq.com/wxa/genwxashortlink?access_token=%s";
@Autowired
......@@ -66,7 +74,7 @@ public class WxLoginManager {
return "sessionFalse";
}
if (StringUtils.isBlank(sessionKey)) {
logger.error("微信登录,调用官方接口失败:{}", dto.getCode());
logger.info("微信登录,调用官方接口失败:{}", dto.getCode());
return "sessionFalse";
}
......@@ -117,7 +125,7 @@ public class WxLoginManager {
}
}
public String getLink (String pageUrl) {
public String getLink(String pageUrl) {
try {
String accessToken = getAccessToken();
String url = String.format(GET_LINK_URL, accessToken);
......
......@@ -81,6 +81,16 @@ public interface ItemService {
*/
Result getWxacode(String page, String scene, HttpServletResponse response);
/**
* 获取小程序码
*
* @param page
* @param scene
* @param response
* @return
*/
Result getAcode(String page, String scene, Integer loginType, HttpServletResponse response);
/**
* 获取微信小程序短链接
*
......@@ -89,6 +99,14 @@ public interface ItemService {
*/
Result getWxLink(String pageUrl);
/**
* 获取小程序链接
*
* @param pageUrl
* @return
*/
Result getLink(String pageUrl, Integer loginType);
/**
* 上传图片
*
......
......@@ -7,30 +7,39 @@ import javax.servlet.http.HttpServletRequest;
public interface UserService {
/**
* 微信登录
* 发送手机验证码
*
* @param dto
* @return
*/
Result regCaptcha(UserRequestDto dto);
/**
* 手机号登录
*
* @param dto
* @param request
* @return
*/
Result loginByWx(UserRequestDto dto, HttpServletRequest request);
Result loginByMobile(UserRequestDto dto, HttpServletRequest request);
/**
* 发送手机验证码
* 快捷登录
*
* @param dto
* @param request
* @return
*/
Result regCaptcha(UserRequestDto dto);
Result login(UserRequestDto dto, HttpServletRequest request);
/**
* 手机号登录
* 微信登录
*
* @param dto
* @param request
* @return
*/
Result loginByMobile(UserRequestDto dto, HttpServletRequest request);
Result loginByWx(UserRequestDto dto, HttpServletRequest request);
/**
* 修改个性签名
......
......@@ -137,15 +137,46 @@ public class WxItemController {
@ApiOperation(value = "小程序码")
@GetMapping("/getWxacode")
public Result getWxacode(String page, String scene, HttpServletResponse response) {
logger.info("【请求开始】获取微信小程序码,请求参数:{}", "page=" + page +",scene=" + scene);
return itemService.getWxacode(page, scene, response);
}
@ApiOperation(value = "小程序码")
@GetMapping("/getAcode")
public Result getAcode(String page, String scene, Integer loginType, HttpServletResponse response) {
logger.info("【请求开始】获小程序码,请求参数:{}", "page=" + page + ",scene=" + scene + ",loginType=" + loginType);
if (StringUtils.isBlank(page)) {
return Result.failed("页面路径不能为空");
}
if (StringUtils.isBlank(scene)) {
return Result.failed("路径参数不能为空");
}
if (Objects.isNull(loginType)) {
return Result.failed("请提供请求的环境类型");
}
return itemService.getAcode(page, scene, loginType, response);
}
@ApiOperation(value = "小程序链接")
@PostMapping("/getWxLink")
public Result getWxLink(@RequestBody ItemRequestDto dto) {
logger.info("【请求开始】获取小程序链接,请求参数:{}", JSON.toJSONString(dto));
return itemService.getWxLink(dto.getPageUrl());
}
@ApiOperation(value = "小程序链接")
@PostMapping("/getLink")
public Result getLink(@RequestBody ItemRequestDto dto) {
logger.info("【请求开始】获取小程序链接,请求参数:{}", JSON.toJSONString(dto));
if (StringUtils.isBlank(dto.getPageUrl())) {
return Result.failed("页面路径不能为空");
}
if (Objects.isNull(dto.getLoginType())) {
return Result.failed("请提供请求的环境类型");
}
return itemService.getLink(dto.getPageUrl(), dto.getLoginType());
}
@ApiOperation("图片上传")
@PostMapping(value ="/uploadImage")
public Result uploadImage(@RequestParam("image") MultipartFile file) {
......
......@@ -4,6 +4,7 @@ package com.wwdz.ch.wx.web;
import com.alibaba.fastjson.JSON;
import com.wwdz.ch.core.type.Result;
import com.wwdz.ch.wx.constant.CacheCodeConstants;
import com.wwdz.ch.wx.constant.LoginTypeEnum;
import com.wwdz.ch.wx.entity.request.UserRequestDto;
import com.wwdz.ch.wx.service.UserService;
import io.swagger.annotations.ApiOperation;
......@@ -32,6 +33,39 @@ public class WxUserController {
private UserService userService;
@ApiOperation(value = "快捷登录")
@PostMapping("/login")
public Result login(@RequestBody UserRequestDto dto, HttpServletRequest request) {
logger.info("【请求开始】快捷登录,请求参数:{}", JSON.toJSONString(dto));
if (Objects.isNull(dto.getLoginType())) {
return Result.failed("请提供快捷登录的方式");
}
if (dto.getLoginType().equals(LoginTypeEnum.WECHAT.getCode())) {
if (StringUtils.isBlank(dto.getCode())) {
return Result.failed("授权码不能为空");
}
if (Objects.isNull(dto.getType())) {
return Result.failed("版本类型不能为空");
}
if (dto.getType() == 2) {
if (StringUtils.isBlank(dto.getEncryptedData()) || StringUtils.isBlank(dto.getIv())) {
return Result.failed("encryptedData或iv不能为空");
}
}
}
if (dto.getLoginType().equals(LoginTypeEnum.ALIPAY.getCode())) {
if (StringUtils.isBlank(dto.getEncryptedData())) {
return Result.failed("encryptedData不能为空");
}
}
if (dto.getLoginType().equals(LoginTypeEnum.TIKTOK.getCode())) {
if (StringUtils.isBlank(dto.getEncryptedData()) || StringUtils.isBlank(dto.getIv())) {
return Result.failed("encryptedData或iv不能为空");
}
}
return userService.login(dto, request);
}
@ApiOperation(value = "微信登录")
@PostMapping("/loginByWx")
public Result loginByWx(@RequestBody UserRequestDto dto, HttpServletRequest request) {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment