Commit 8bdc4b7b authored by zhouqian's avatar zhouqian

log

parent 1fd43fad
package cn.quantgroup.xyqb.controller.external.user;
import cn.quantgroup.xyqb.entity.WebChatUserInfo;
import cn.quantgroup.xyqb.entity.Merchant;
import cn.quantgroup.xyqb.entity.WechatUserInfo;
import cn.quantgroup.xyqb.model.JsonResult;
import cn.quantgroup.xyqb.model.webchat.AccessTokenResponse;
import cn.quantgroup.xyqb.service.http.IHttpService;
import cn.quantgroup.xyqb.service.merchant.IMerchantService;
import cn.quantgroup.xyqb.service.user.IUserService;
import com.alibaba.fastjson.JSON;
import cn.quantgroup.xyqb.service.wechat.IWechatService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Arrays;
......@@ -26,26 +31,30 @@ import java.util.Arrays;
public class WeChatController {
// todo: 配置文件
public static final String TOKEN = "5YihkluEo5QuWAWpFwzvA";
private static final String TOKEN = "5YihkluEo5QuWAWpFwzvA";
@Autowired
private IHttpService httpService;
private IWechatService wechatService;
@Autowired
private IUserService userService;
//todo: 配置文件相关
private String access_token_url = "https://api.weixin.qq.com/sns/oauth2/access_token?appid=wxcdf6077af8127559&secret=16eaec16084d0d9c52d4114f359cc72c&code=%s&grant_type=authorization_code";
private String access_userinfo_url = "https://api.weixin.qq.com/sns/userinfo?access_token=%s&openid=%s&lang=zh_CN";
private IMerchantService merchantService;
// https://passport.xyqb.com/landing?key=xxx&target=cashTarget5&registerFrom=198&channelId=%d
@Value("${xyqb-user.ui}")
private String userUIAddr;
/**
* 开发者资质认证,有必要吗?
*
* @param request
* @return
*/
@RequestMapping("/checkValid")
public String valid(HttpServletRequest request) {
String echoStr = request.getParameter("echostr");
if(checkSignature(request)){
if (checkSignature(request)) {
return echoStr;
}
return "";
......@@ -53,6 +62,7 @@ public class WeChatController {
/**
* 微信登录
*
* @param name 姓名
* @param idNo 身份证号
* @param phoneNo 手机号
......@@ -63,11 +73,11 @@ public class WeChatController {
* @return
*/
public JsonResult webChatLogin(String name, String idNo, String phoneNo, String registerFrom,
String channelId, String appChannel, String key){
if(StringUtils.isBlank(name) || StringUtils.isBlank(idNo) || StringUtils.isBlank(phoneNo)){
String channelId, String appChannel, String key) {
if (StringUtils.isBlank(name) || StringUtils.isBlank(idNo) || StringUtils.isBlank(phoneNo)) {
return JsonResult.buildErrorStateResult("请填写完整的用户信息.", null);
}
if(StringUtils.isBlank(key)){
if (StringUtils.isBlank(key)) {
return JsonResult.buildErrorStateResult("无效的商户信息.", null);
}
return null;
......@@ -80,6 +90,7 @@ public class WeChatController {
* 2.用timestamp, nonce, token三个参数做字符升序排列
* 3.将排列好的字符串进行sha1加密,和signature参数做比较
* 4.相等返回true,否则返回false
*
* @param request
* @return
*/
......@@ -97,6 +108,7 @@ public class WeChatController {
/**
* sha1加密算法,
*
* @param decript
* @return 返回40位16进制字符串
*/
......@@ -125,12 +137,13 @@ public class WeChatController {
/**
* 数组分割为字符串
*
* @param arr
* @return
*/
private String joinArray(String[] arr) {
StringBuilder builder = new StringBuilder();
for(String str : arr){
for (String str : arr) {
builder.append(str);
}
return builder.toString();
......@@ -138,47 +151,50 @@ public class WeChatController {
/**
* 通过redirect_url获取code
* @param request
*
* @param response
* @return
*/
@RequestMapping("/receiveCode")
public String receiveCode(HttpServletRequest request) {
String code = request.getParameter("code");
receiveAccessToken(code);
return null;
@RequestMapping("/receiveCode/{key}")
public void receiveCode(String code, @PathVariable(value = "key") String systemKey, HttpServletResponse response) {
// 从code获取token
Merchant merchant = merchantService.findMerchantByName(systemKey);
AccessTokenResponse token = wechatService.getToken(code);
if (token == null) {
// todo: 让用户登录,不关联微信, 构造不关联微信的url
response.setHeader("Location", redirectUrl);
response.setStatus(301);
return;
}
WechatUserInfo userInfo = wechatService.getWechatUserInfoFromWechatServer(token.getAccessToken(), token.getOpenId());
if (userInfo == null) {
// todo: 让用户登录,不关联微信, 构造不关联微信的url
response.setHeader("Location", redirectUrl);
response.setStatus(301);
return;
}
WechatUserInfo userInfoInDb = wechatService.findWechatUserInfoFromDb(userInfo.getOpenId());
// welcome 首次登录
if (userInfoInDb == null) {
// todo: 微信用户首次登录界面, 首先保存userInfo, 跳入到微信注册登录界面
userInfo = wechatService.saveWechatUserInfo(userInfo);
response.setHeader("Location", redirectUrl);
response.setStatus(301);
return;
}
if (userInfoInDb.getUserId() == null) {
// todo: 用户已经微信登录了,但是没有关联信用钱包,跳转到注册页面
response.setHeader("Location", redirectUrl);
response.setStatus(301);
return;
}
// 已经关联了用户
// todo: create session, 登进去,该怎么玩怎么玩。
createUserSession(userInfo, merchant);
response.setHeader("Location", redirectUrl);
response.setStatus(301);
}
/**
* 拿到access_token,openId,获取用户信息,入库
* @param code
* @return
*/
private JsonResult receiveAccessToken(String code) {
String finalAccessTokenUrl = String.format(access_token_url, code);
String response = httpService.get(finalAccessTokenUrl);
AccessTokenResponse accessTokenResponse = null;
try {
accessTokenResponse = JSON.parseObject(response, AccessTokenResponse.class);
} catch (Exception e){
log.error("获取access_token出错{}:", e);
return JsonResult.buildErrorStateResult("获取access_token出错", null);
}
//从AccessTokenResponse中获取access_token, openid
String access_token = accessTokenResponse.getAccessToken();
String openId = accessTokenResponse.getOpenId();
String finalUserInfoUrl = String.format(access_userinfo_url, access_token, openId);
//拉取用户信息
String userInfo = httpService.get(finalUserInfoUrl);
saveWebChatUserInfo(userInfo);
return JsonResult.buildSuccessResult("success", null);
}
/**
* 保存微信用户信息
* @param userInfo
*/
private void saveWebChatUserInfo(String userInfo) {
WebChatUserInfo webChatUserInfo = JSON.parseObject(userInfo, WebChatUserInfo.class);
userService.saveWebChatUserInfo(webChatUserInfo);
}
}
......@@ -13,9 +13,9 @@ import java.io.Serializable;
* 微信关联的用户信息
*/
@Entity
@Table(name = "webchat_userinfo")
@Table(name = "wechat_userinfo")
@Data
public class WebChatUserInfo implements Serializable{
public class WechatUserInfo implements Serializable{
private static final long serialVersionUID = -1L;
@Id
......
......@@ -16,4 +16,6 @@ public class AccessTokenResponse implements Serializable{
private String refreshToken;
private String openId;
private String scope;
private Long initialTime;
}
package cn.quantgroup.xyqb.repository;
import cn.quantgroup.xyqb.entity.WebChatUserInfo;
import cn.quantgroup.xyqb.entity.WechatUserInfo;
import org.springframework.data.jpa.repository.JpaRepository;
/**
* Created by 11 on 2017/1/18.
*/
public interface IWebChatUserRepository extends JpaRepository<WebChatUserInfo, Long> {
public interface IWeChatUserRepository extends JpaRepository<WechatUserInfo, Long> {
WechatUserInfo findByOpenId(String openId);
}
package cn.quantgroup.xyqb.service.user;
import cn.quantgroup.xyqb.entity.User;
import cn.quantgroup.xyqb.entity.WebChatUserInfo;
import cn.quantgroup.xyqb.entity.WechatUserInfo;
/**
* Created by Miraculous on 15/7/5.
......@@ -28,5 +28,4 @@ public interface IUserService {
User findById(Long userId);
WebChatUserInfo saveWebChatUserInfo(WebChatUserInfo webChatUserInfo);
}
......@@ -2,9 +2,7 @@ package cn.quantgroup.xyqb.service.user.impl;
import cn.quantgroup.xyqb.Constants;
import cn.quantgroup.xyqb.entity.User;
import cn.quantgroup.xyqb.entity.WebChatUserInfo;
import cn.quantgroup.xyqb.repository.IUserRepository;
import cn.quantgroup.xyqb.repository.IWebChatUserRepository;
import cn.quantgroup.xyqb.service.sms.ISmsService;
import cn.quantgroup.xyqb.service.user.ILkbUserService;
import cn.quantgroup.xyqb.service.user.IUserService;
......@@ -38,9 +36,6 @@ public class UserServiceImpl implements IUserService {
@Autowired
private ISmsService smsService;
@Autowired
private IWebChatUserRepository webChatUserRepository;
@Override
public User findByPhoneInDb(String phone) {
return userRepository.findByPhoneNo(phone);
......@@ -61,10 +56,6 @@ public class UserServiceImpl implements IUserService {
return userRepository.findById(userId);
}
@Override
public WebChatUserInfo saveWebChatUserInfo(WebChatUserInfo webChatUserInfo) {
return webChatUserRepository.save(webChatUserInfo);
}
@Override
public User registerAndReturn(String phoneNo, String password, Long registerFrom) {
......
package cn.quantgroup.xyqb.service.wechat;
import cn.quantgroup.xyqb.entity.WechatUserInfo;
import cn.quantgroup.xyqb.model.webchat.AccessTokenResponse;
/**
* Created by Miraculous on 2017/1/19.
*/
public interface IWechatService {
AccessTokenResponse getToken(String code);
WechatUserInfo getWechatUserInfoFromWechatServer(String token, String openId);
WechatUserInfo findWechatUserInfoFromDb(String openId);
WechatUserInfo saveWechatUserInfo(WechatUserInfo userInfo);
}
package cn.quantgroup.xyqb.service.wechat.impl;
import cn.quantgroup.cloudconfig.SafeValue;
import cn.quantgroup.xyqb.entity.WechatUserInfo;
import cn.quantgroup.xyqb.model.webchat.AccessTokenResponse;
import cn.quantgroup.xyqb.repository.IWeChatUserRepository;
import cn.quantgroup.xyqb.service.http.IHttpService;
import cn.quantgroup.xyqb.service.wechat.IWechatService;
import com.alibaba.fastjson.JSONObject;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import javax.annotation.PostConstruct;
import java.util.concurrent.TimeUnit;
/**
* Created by Miraculous on 2017/1/19.
*/
@Service
public class WechatServiceImpl implements IWechatService {
@Autowired
private IHttpService httpService;
@Autowired
@Qualifier("stringRedisTemplate")
private RedisTemplate<String, String> redisTemplate;
@SafeValue("wechat.appid")
private String appId;
@SafeValue("wechat.secret")
private String secret;
@Autowired
private IWeChatUserRepository weChatUserRepository;
private String accessTokenUrl;
private String refreshTokenUrl = "https://api.weixin.qq.com/sns/oauth2/refresh_token?appid=%s&grant_type=refresh_token&refresh_token=%s";
private static final String WECHAT_TOKEN_KEY_PREFIX = "wechat:token:";
@PostConstruct
private void init() {
accessTokenUrl = String.format("https://api.weixin.qq.com/sns/oauth2/access_token?appid=%s&secret=%s&grant_type=authorization_code&code=", appId, secret) + "%s";
refreshTokenUrl = String.format("https://api.weixin.qq.com/sns/oauth2/refresh_token?appid=%s&grant_type=refresh_token&refresh_token=", appId) + "%s";
}
@Override
public AccessTokenResponse getToken(String code) {
if (StringUtils.isEmpty(code)) {
return null;
}
String key = WECHAT_TOKEN_KEY_PREFIX + code;
String resultStr = redisTemplate.opsForValue().get(key);
if (StringUtils.isEmpty(resultStr)) {
String response = getTokenFromWechatServer(code);
if (StringUtils.isEmpty(response)) {
return null;
}
try {
AccessTokenResponse accessTokenResponse = JSONObject.parseObject(response,
AccessTokenResponse.class);
if (accessTokenResponse == null) {
return null;
}
accessTokenResponse.setInitialTime(System.currentTimeMillis() - 10000);
redisTemplate.opsForValue().set(key, JSONObject.toJSONString(accessTokenResponse), accessTokenResponse.getExpiresIn() + 1000, TimeUnit.SECONDS);
return accessTokenResponse;
} catch (Exception ex) {
return null;
}
} else {
try {
AccessTokenResponse response = JSONObject.parseObject(resultStr, AccessTokenResponse.class);
// 刷新
if (response.getInitialTime() + response.getExpiresIn()*1000 > System.currentTimeMillis()) {
String refreshTokenStr = refreshToken(response.getRefreshToken());
response = JSONObject.parseObject(refreshTokenStr, AccessTokenResponse.class);
if (response == null) {
return null;
}
response.setInitialTime(System.currentTimeMillis() - 10000);
}
redisTemplate.opsForValue().set(key, JSONObject.toJSONString(response), response.getExpiresIn() + 1000, TimeUnit.SECONDS);
return response;
} catch (Exception ex) {
return null;
}
}
}
@Override
public WechatUserInfo getWechatUserInfoFromWechatServer(String token, String openId) {
if (StringUtils.isEmpty(token) || StringUtils.isEmpty(openId)) {
return null;
}
String accessUserInfoUrl = "https://api.weixin.qq.com/sns/userinfo?access_token=%s&openid=%s&lang=zh_CN";
String url = String.format(accessUserInfoUrl, token, openId);
String result = httpService.get(url);
return JSONObject.parseObject(result, WechatUserInfo.class);
}
@Override
public WechatUserInfo findWechatUserInfoFromDb(String openId) {
return weChatUserRepository.findByOpenId(openId);
}
@Override
@Transactional
public WechatUserInfo saveWechatUserInfo(WechatUserInfo userInfo) {
return weChatUserRepository.save(userInfo);
}
private String getTokenFromWechatServer(String code) {
if (StringUtils.isEmpty(code)) {
return null;
}
String finalAccessTokenUrl = String.format(accessTokenUrl, code);
return httpService.get(finalAccessTokenUrl);
}
private String refreshToken(String refreshToken) {
if (StringUtils.isEmpty(refreshToken)) {
return null;
}
return httpService.get(String.format(refreshTokenUrl, refreshToken));
}
}
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