Commit ef6c1beb authored by 曾水平's avatar 曾水平

引入首页

parent 9772b2a7
......@@ -23,6 +23,7 @@ dependencies {
implementation 'org.springframework.boot:spring-boot-starter-jdbc'
implementation 'org.springframework.boot:spring-boot-starter-validation'
implementation 'org.springframework.boot:spring-boot-starter-web'
implementation 'org.springframework.boot:spring-boot-starter-thymeleaf'
implementation 'org.mybatis.spring.boot:mybatis-spring-boot-starter:2.1.4'
runtimeOnly 'mysql:mysql-connector-java'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
......
......@@ -5,13 +5,14 @@ package cn.com.duiba.jdactivity.common.utils;
* @date 2021/5/17 18:44
*/
public class RequestLocal {
private static final ThreadLocal<Object> user = new ThreadLocal<>();
private static final ThreadLocal<Object> USER = new ThreadLocal<>();
public static void setUser(Object dto) {
user.set(dto);
USER.set(dto);
}
public static void removeUser() {
user.remove();
USER.remove();
}
}
package cn.com.duiba.jdactivity.common.utils;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;
......@@ -366,4 +371,34 @@ public class RequestTool {
}
return request.getHeader("referer");
}
/**
* 提取request中的参数
*
* @param request
* @return
*/
public static Map<String, String> getRequestParamMap(HttpServletRequest request) {
Map<String, String[]> map = request.getParameterMap();
Map<String, String> resultMap = new HashMap<>();
for (Map.Entry<String, String[]> entry : map.entrySet()) {
resultMap.put(entry.getKey(), entry.getValue()[0]);
}
return resultMap;
}
/**
* 工具方法,获取HttpServletRequest 线程安全
*/
private static HttpServletRequest getHttpServletRequest() {
return ((ServletRequestAttributes) (RequestContextHolder.currentRequestAttributes())).getRequest();
}
/**
* 工具方法,获取HttpServletRequest 线程安全
*/
private static HttpServletResponse getHttpServletResponse() {
return ((ServletRequestAttributes) (RequestContextHolder.currentRequestAttributes())).getResponse();
}
}
......@@ -2,6 +2,8 @@ package cn.com.duiba.jdactivity.common.utils;
import com.alibaba.fastjson.JSON;
import org.apache.commons.lang3.StringUtils;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
......@@ -155,4 +157,22 @@ public final class UrlUtils {
}
return mapRequest;
}
/**
* 为url添加http或https协议
*
* @param url
* @return
*/
public static String getFullUrl(String url) {
url = StringUtils.trimToEmpty(url);
String requestScheme = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest().getScheme();
if (url.startsWith("http")) {
return url;
} else if (url.startsWith("//")) {
return requestScheme + ":" + url;
} else {
return requestScheme + "://" + url;
}
}
}
......@@ -5,7 +5,10 @@ package cn.com.duiba.jdactivity.common.utils.user;
* @date 2021/5/17 18:52
*/
public class UserCookieDto {
private long time;//登录时间
/**
* 登录时间
*/
private long time;
private String userId;
public long getTime() {
......
......@@ -49,7 +49,7 @@ public class UserUtils {
}
public UserCookieDto getUserCookieDto(HttpServletRequest request) {
public static UserCookieDto getUserCookieDto(HttpServletRequest request) {
String cookie = RequestTool.getCookie(request, USER_COOKIE);
if (cookie == null || cookie.isEmpty()) {
return null;
......
......@@ -3,8 +3,9 @@ package cn.com.duiba.jdactivity.controller;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.bind.annotation.ResponseBody;
import javax.annotation.Resource;
......@@ -13,31 +14,21 @@ import javax.annotation.Resource;
* @author zsp (zengshuiping@duiba.com.cn)
* @date 2021/5/12 15:26
*/
@RestController
@Controller
@RequestMapping("/hello")
public class HelloController {
public static final Logger LOGGER = LoggerFactory.getLogger(HelloController.class);
@Resource(name = "stringRedisTemplate")
private StringRedisTemplate stringRedisTemplate;
@RequestMapping("/")
public String index() {
LOGGER.info("有人访问了index");
stringRedisTemplate.opsForValue().set("test_key", "1");
stringRedisTemplate.opsForValue().get("test_key");
LOGGER.info("有人访问了index");
return "Greetings from Spring Boot!";
}
@RequestMapping("/testRedis")
public String testRedis() {
@ResponseBody
public String testRedis(String value) {
LOGGER.info("testRedis");
stringRedisTemplate.opsForValue().set("test_key", "1");
stringRedisTemplate.opsForValue().get("test_key");
return "testRedis";
stringRedisTemplate.opsForValue().set("test_key", value);
return stringRedisTemplate.opsForValue().get("test_key");
}
}
\ No newline at end of file
package cn.com.duiba.jdactivity.controller;
import cn.com.duiba.jdactivity.common.vo.Result;
import cn.com.duiba.jdactivity.developer.jd.AppEnum;
import cn.com.duiba.jdactivity.developer.jd.utils.AccessTokenUtils;
import cn.com.duiba.jdactivity.developer.jd.utils.ApiUtil;
import cn.com.duiba.jdactivity.dto.TbShopAccessTokenDto;
import cn.com.duiba.jdactivity.interceptor.UnloginAccess;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
/**
* @author zsp (zengshuiping@duiba.com.cn)
* @date 2021/5/18 08:49
*/
@RestController
@RequestMapping("/login")
public class LoginController {
public static final Logger LOGGER = LoggerFactory.getLogger(LoginController.class);
public static final String REDIRECT = "redirect";
@Resource
private ApiUtil apiUtil;
@Resource
private AccessTokenUtils accessTokenUtils;
@UnloginAccess
@RequestMapping(value = "", method = {RequestMethod.GET, RequestMethod.POST})
public String login(
Long venderId,
Long shopId,
@RequestParam(required = false) String token,
@RequestParam(required = false) String source,
@RequestParam(required = false) String redirect) {
TbShopAccessTokenDto accessToken = accessTokenUtils.getAccessToken(venderId, shopId);
if (accessToken == null) {
return "未授权";
}
AppEnum appByAppKey = AppEnum.getAppByAppKey(accessToken.getAppKey());
Result<String> pinByToken = apiUtil.getPinByToken(appByAppKey, accessToken.getAccessToken(), source, token);
if (StringUtils.isBlank(token)) {
return "不能为空";
}
return "redirect:";
}
}
......@@ -35,33 +35,29 @@ public class ShopController {
private ApiUtil apiUtil;
@RequestMapping("/login")
public String login(@RequestParam(required = false, defaultValue = "B0F491866BC8C8BA5954B4DFCCF283CC") String appKey,
String code,
@RequestParam(required = false) String state) {
if (StringUtils.isBlank(code)) {
return "code参数缺失";
public String login(
String code,
String state) {
LOGGER.info("login,code={},state={}", code, state);
if (StringUtils.isAnyBlank(code, state)) {
return "参数缺失";
}
AppEnum appEnum = AppEnum.getAppByAppKey(appKey);
JosParameters josParameters = LoginUtils.getStateParam(state);
AppEnum appEnum = AppEnum.getAppByAppKey(josParameters.getApp_key());
if (appEnum == null) {
return "appKey参数不合法";
}
if (StringUtils.isNoneBlank(state)) {
JosParameters josParameters = LoginUtils.getStateParam(state);
}
AccessTokenResponse accessTokenByCode = accessTokenUtils.getAccessTokenByCode(appEnum, code);
if (!accessTokenByCode.isOk()) {
Result<ShopJosResult> shopJosResultResult = apiUtil.venderShopQuery(appEnum, accessTokenByCode.getAccess_token());
if (shopJosResultResult.getSuccess()) {
ShopJosResult data = shopJosResultResult.getData();
Long id = accessTokenUtils.saveAccessToken(appEnum, accessTokenByCode, data);
}
// 保存入库
......
......@@ -11,11 +11,14 @@ import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.JSONValidator;
import com.jd.open.api.sdk.domain.seller.ShopSafService.response.query.ShopJosResult;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
import java.util.Comparator;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;
......@@ -89,6 +92,26 @@ public class AccessTokenUtils {
return tbShopAccessTokenDto;
}
public TbShopAccessTokenDto getAccessToken(Long venderId, Long shopId) {
Date now = new Date();
List<TbShopAccessTokenDto> tbShopAccessTokenDtos = tbShopAccessTokenService.queryByVenderIdShopId(venderId, shopId);
if (CollectionUtils.isEmpty(tbShopAccessTokenDtos)) {
return null;
}
tbShopAccessTokenDtos.sort(Comparator.comparing(TbShopAccessTokenDto::getExpiresTime));
for (int i = tbShopAccessTokenDtos.size() - 1; i >= 0; i--) {
TbShopAccessTokenDto tbShopAccessTokenDto = tbShopAccessTokenDtos.get(i);
if (tbShopAccessTokenDto.getExpiresTime().after(now)) {
return tbShopAccessTokenDto;
}
}
return null;
}
/*
{"error_response":{"code":"19","en_desc":"Invalid access_token(Solution reference: https://jos.jd.com/commondoc?listId=171)","zh_desc":"token已过期或者不存在,请重新授权,access_token:c99865d29305423b87693b8c511c6799zdi5(解决方案参考: https://jos.jd.com/commondoc?listId=171)"}}
*/
......
......@@ -7,11 +7,23 @@ import cn.com.duiba.jdactivity.developer.jd.UrlConstants;
import com.alibaba.fastjson.JSON;
import com.jd.open.api.sdk.DefaultJdClient;
import com.jd.open.api.sdk.JdClient;
import com.jd.open.api.sdk.domain.crm.VenderCustomerClientJsfService.response.getCustomer.EssentialCustomerInfo;
import com.jd.open.api.sdk.domain.seller.ShopSafService.response.query.ShopJosResult;
import com.jd.open.api.sdk.domain.user.UserRelatedRpcService.response.getUserInfoByOpenId.OAuthUserInfo;
import com.jd.open.api.sdk.request.crm.PopCrmCustomerGetCustomerRequest;
import com.jd.open.api.sdk.request.openid.JosTokenSourceToOpenIdRequest;
import com.jd.open.api.sdk.request.seller.VenderShopQueryRequest;
import com.jd.open.api.sdk.request.user.FollowVenderReadIsFollowByPinAndVidRequest;
import com.jd.open.api.sdk.request.user.PopJmCenterUserGetEncryptPinNewRequest;
import com.jd.open.api.sdk.request.user.PopJmCenterUserGetOpenIdRequest;
import com.jd.open.api.sdk.request.user.UserGetUserInfoByOpenIdRequest;
import com.jd.open.api.sdk.response.crm.PopCrmCustomerGetCustomerResponse;
import com.jd.open.api.sdk.response.openid.JosTokenSourceToOpenIdResponse;
import com.jd.open.api.sdk.response.seller.VenderShopQueryResponse;
import com.jd.open.api.sdk.response.user.FollowVenderReadIsFollowByPinAndVidResponse;
import com.jd.open.api.sdk.response.user.PopJmCenterUserGetEncryptPinNewResponse;
import com.jd.open.api.sdk.response.user.PopJmCenterUserGetOpenIdResponse;
import com.jd.open.api.sdk.response.user.UserGetUserInfoByOpenIdResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
......@@ -49,6 +61,103 @@ public class ApiUtil {
}
/**
* 查询用户明文PIN
*
* @param source 01: 京东 App,02:微信
*/
public Result<String> getPinByToken(AppEnum appEnum, String accessToken, String source, String token) {
try {
JdClient client = getJdClient(appEnum, accessToken);
PopJmCenterUserGetOpenIdRequest request = new PopJmCenterUserGetOpenIdRequest();
request.setSource(source);
request.setToken(token);
PopJmCenterUserGetOpenIdResponse response = client.execute(request);
return ResultBuilder.success(response.getReturnType().getPin());
} catch (Exception e) {
LOGGER.warn("venderShopQuery,exception", e);
return ResultBuilder.fail("发生异常");
}
}
/**
* 查询用户加密PIN
*
* @param source 01: 京东 App,02:微信
*/
public Result<String> getEncryptPinNewByToken(AppEnum appEnum, String accessToken, String source, String token) {
try {
JdClient client = getJdClient(appEnum, accessToken);
PopJmCenterUserGetEncryptPinNewRequest request = new PopJmCenterUserGetEncryptPinNewRequest();
request.setSource(source);
request.setToken(token);
PopJmCenterUserGetEncryptPinNewResponse response = client.execute(request);
return ResultBuilder.success(response.getReturnType().getPin());
} catch (Exception e) {
LOGGER.warn("venderShopQuery,exception", e);
return ResultBuilder.fail("发生异常");
}
}
/**
* 查询用户openId
*
* @param source 01: 京东 App,02:微信
*/
public Result<String> getOpenIdByToken(AppEnum appEnum, String source, String token) {
try {
JdClient client = getJdClient(appEnum, "");
JosTokenSourceToOpenIdRequest request = new JosTokenSourceToOpenIdRequest();
request.setToken(token);
request.setSource(source);
request.setAppKey(appEnum.getAppKey());
JosTokenSourceToOpenIdResponse response = client.execute(request);
return ResultBuilder.success(response.getResult().getOpenId());
} catch (Exception e) {
LOGGER.warn("venderShopQuery,exception", e);
return ResultBuilder.fail("发生异常");
}
}
/**
* 根据 openId 获取用户信息
* 性别 (0: 男,1: 女)
*/
public Result<OAuthUserInfo> getUserInfoByOpenId(AppEnum appEnum, String accessToken, String openId) {
try {
JdClient client = getJdClient(appEnum, accessToken);
UserGetUserInfoByOpenIdRequest request = new UserGetUserInfoByOpenIdRequest();
request.setOpenId(openId);
UserGetUserInfoByOpenIdResponse response = client.execute(request);
return ResultBuilder.success(response.getGetuserinfobyappidandopenidResult().getData());
} catch (Exception e) {
LOGGER.warn("venderShopQuery,exception", e);
return ResultBuilder.fail("发生异常");
}
}
/**
* 查询 pin 在商家下的会员信息
* 性别 (0: 男,1: 女)
*/
public Result<EssentialCustomerInfo> getCustomer(AppEnum appEnum, String accessToken, String pin) {
try {
JdClient client = getJdClient(appEnum, accessToken);
PopCrmCustomerGetCustomerRequest request = new PopCrmCustomerGetCustomerRequest();
request.setCustomerPin(pin);
request.setOpenIdBuyer(pin);
PopCrmCustomerGetCustomerResponse response = client.execute(request);
return ResultBuilder.success(response.getReturnResult().getData());
} catch (Exception e) {
LOGGER.warn("venderShopQuery,exception", e);
return ResultBuilder.fail("发生异常");
}
}
private DefaultJdClient getJdClient(AppEnum appEnum, String accessToken) {
return new DefaultJdClient(urlConstants.getApiServerUrl(), accessToken, appEnum.getAppKey(), appEnum.getAppSecret());
}
......
package cn.com.duiba.jdactivity.interceptor;
import cn.com.duiba.jdactivity.common.utils.RequestLocal;
import cn.com.duiba.jdactivity.common.utils.user.UserCookieDto;
import cn.com.duiba.jdactivity.common.utils.user.UserUtils;
import cn.com.duiba.jdactivity.common.vo.ResultBuilder;
import com.alibaba.fastjson.JSONObject;
import org.springframework.stereotype.Component;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.PrintWriter;
/**
* @author zsp (zengshuiping@duiba.com.cn)
......@@ -14,11 +20,27 @@ import javax.servlet.http.HttpServletResponse;
*/
@Component
public class LoginInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
RequestLocal.removeUser();
return HandlerInterceptor.super.preHandle(request, response, handler);
if (handler instanceof HandlerMethod) {
HandlerMethod handlerMethod = (HandlerMethod) handler;
UnloginAccess unloginAccess = handlerMethod.getMethod().getAnnotation(UnloginAccess.class);
if (unloginAccess != null) {
return true;
}
}
try {
UserCookieDto userCookieDto = UserUtils.getUserCookieDto(request);
RequestLocal.setUser(userCookieDto);
} catch (Exception e) {
String message = JSONObject.toJSONString(ResultBuilder.fail(e.getMessage()));
writeResult(response, message);
return false;
}
return true;
}
@Override
......@@ -30,4 +52,21 @@ public class LoginInterceptor implements HandlerInterceptor {
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
HandlerInterceptor.super.afterCompletion(request, response, handler, ex);
}
/**
* 返回信息
*
* @param response
* @param result
*/
private void writeResult(HttpServletResponse response, String result) {
response.setCharacterEncoding("UTF-8");
response.setContentType("application/json; charset=utf-8");
try (PrintWriter out = response.getWriter()) {
out.write(result);
out.flush();
} catch (Exception e) {
//ignore
}
}
}
package cn.com.duiba.jdactivity.interceptor;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* 使用此注解表示该controller方法不需要登录即可调用
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface UnloginAccess {
}
......@@ -25,7 +25,6 @@ mybatis.mapper-locations=classpath:mybatis/*/*.xml
#spring.redis.host=redis-x4n822igaxnu-proxy-nlb.jvessel-open-hb.jdcloud.com
#spring.redis.password=kP6oWdeYU78tHee
spring.redis.host=localhost
spring.redis.password=mypassword
spring.redis.timeout=1000
spring.redis.jedis.pool.max-wait=100
spring.redis.jedis.pool.min-idle=1
......
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>测试页面</title>
<meta content="width=device-width,initial-scale=1, minimum-scale=1, maximum-scale=1, user-scalable=no"
name="viewport"/>
<meta content="yes" name="apple-mobile-web-app-capable"/>
<meta content="true" name="full-screen"/>
<meta content="portrait" name="screen-orientation"/>
<meta content="true" name="x5-fullscreen"/>
<meta content="true" name="360-fullscreen"/>
<!-- <script src="./jssdk.min.js"></script>-->
<script src="//yun.duiba.com.cn/aurora/assets/4c37d75a75d8e7534d9e3b056911ba06ac5bf8f8.js"></script>
<script src="//yun.duiba.com.cn/js-libs/vConsole/3.3.4/vconsole.min.js"></script>
<script>
new VConsole();
</script>
<style>
html,
body {
padding: 0;
margin: 0;
border: 0;
width: 100%;
height: 100%;
overflow: hidden;
position: absolute;
background-color: white;
}
div {
width: 160px;
height: 30px;
line-height: 30px;
text-align: center;
border: 2px solid #ccc;
margin: 5px 0;
}
</style>
</head>
<body>
<div onclick="login()">是否登录</div>
<div onclick="openLoginPanel()">登录面板</div>
<div onclick="shareConfig()">分享设置</div>
<div onclick="getToken()">获取混淆token</div>
<div onclick="isInJd()">是否在京东APP内</div>
<div onclick="isInWx()">是否在微信内</div>
<script language="javascript">
console.log("JSSDK", JSSDK)
function login() {
JSSDK.Login.isLogin({
from: window.location.host
}, isLogin);
}
function isLogin(res) {
console.log(res)
setTimeout(function () {
console.log(res.data)
}, 0);
}
function openLoginPanel() {
console.log("登录面板")
JSSDK.Isv.isAppLogin(callback);
}
function callback(res) {
console.log("登录面板返回", res)
}
function shareConfig() {
console.log("分享配置")
JSSDK.WebView.callHeaderSharePanel({
title: "京东超值购",
content: "来京东,更超值",
shareUrl: window.location.href,
channel: "",
iconUrl: ""
});
}
function getToken() {
console.log("获取token", window.location.href)
JSSDK.Isv.requestIsvToken({
url: window.location.href
}, callBackToken);
}
function callBackToken(res) {
console.log("获取token的返回", res)
}
function isInJd() {
var inJd = JSSDK.Client.isJDApp();
console.log("是否在京东内", inJd)
}
function isInWx() {
var inWx = JSSDK.Client.isWeixin();
console.log("是否在微信内", inWx)
}
</script>
</body>
</html>
\ No newline at end of file
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