微信开发文档:http://mp.weixin.qq.com/wiki/17/c0f37d5704f0b64713d5d2c37b468d75.html
构造到授权的网页链接
使用方式:例
// new baseservice().BuildAuthCallbackUrl("/mydemo/product/ProductDetails?id="+product.getId(), EnumScopeType.snsapi_userinfo);
package com.star.wxservice;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.log4j.Logger;
import com.fasterxml.jackson.core.JsonParseException;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.star.etmvcfilters.BaseServcie;
import com.star.model.UserSessionUtil;
import com.star.model.Wechat_User;
import com.star.utils.Cache;
import com.star.utils.CacheManager;
import com.star.utils.HttpRequestUtil;
import com.star.utils.JsonMapper;
import com.star.wxmessagemodel.EnumScopeType;
import com.star.wxmessagemodel.OpenIdResult;
import com.star.wxmessagemodel.RefreshtokenResult;
import com.star.wxmessagemodel.TokenJsonResult;
import com.star.wxmessagemodel.WechatUserInfo;
import config.Property;
public class baseservice {
private static Logger logger = Logger.getLogger(baseservice.class);
private static final String WECHAR_PATH = "/config/wechat.properties";
public static final String WECHAT_APPID = Property.GetXMLValuesByKey(WECHAR_PATH, "WECHAT_APPID");
public static final String WECHAT_SECRET = Property.GetXMLValuesByKey(WECHAR_PATH, "WECHAT_SECRET");
private static final String Web_PATH = "/config/web.properties";
/**
* 当前域名
*/
public static String ServerName = Property.GetXMLValuesByKey(Web_PATH, "ServerName");
/**
* 获取每次操作微信API的Token访问令牌
*
* @return <param name="appid">应用ID</param>
* <param name="secret">开发者凭据</param>
* @throws Exception
*/
public String GetAccessToken() throws Exception {
String key = "weixin.accesstoken";
// 正常情况下access_token有效期为7200秒,这里使用缓存设置短于这个时间即可
String token = "";
if (CacheManager.getCacheInfo(key) == null) {
String grant_type = "client_credential";
String url = "https://api.weixin.qq.com/cgi-bin/token";
String para = String.format("grant_type=%s&appid=%s&secret=%s", grant_type, WECHAT_APPID, WECHAT_SECRET);
String jsonStr = HttpRequestUtil.sendGet(url, para);
TokenJsonResult jsonObject = JsonMapper.json2Bean(jsonStr, TokenJsonResult.class);
Cache cache = new Cache();
cache.setKey("accesstoken");
cache.setValue(jsonObject.getAccess_token());
cache.setTimeOut(7000);
cache.setExpired(false);
CacheManager.putCache(key, cache);
return jsonObject.getAccess_token();
} else {
return CacheManager.getCacheInfo(key).getValue().toString();
}
}
/**
* 获取openId
*
* @param code
* @return
* @throws Exception
*/
public OpenIdResult GetOpenId(String code) throws Exception {
String url = "https://api.weixin.qq.com/sns/oauth2/access_token";
String para = String.format("appid=%s&secret=%s&code=%s&grant_type=authorization_code", WECHAT_APPID,
WECHAT_SECRET, code);
String jsonStr = HttpRequestUtil.sendGet(url, para);
OpenIdResult result = JsonMapper.json2Bean(jsonStr, OpenIdResult.class);
return result;
}
/**
* 获取微信用户基本信息 -静默授权
*
* @param openId
* @return
* @throws Exception
*/
public WechatUserInfo GetUserInfo(String openId) throws Exception {
logger.error("OPENID=============================================" + openId);
String url = "https://api.weixin.qq.com/cgi-bin/user/info";
String para = String.format("access_token=%s&openid=%s&lang=zh_CN", GetAccessToken(), openId);
String jsonStr = HttpRequestUtil.sendGet(url, para);
// jsonStr = new String(jsonStr.getBytes("ISO-8859-1"), "UTF-8");
logger.error("OPENID---jsonStr =============================================" + jsonStr);
WechatUserInfo model = JsonMapper.json2Bean(jsonStr, WechatUserInfo.class);
return model;
}
/// <summary>
/// 构造URL
/// </summary>
/// <param name="pathAndQuery"></param>
/// <returns></returns>
public String GetUrl(String pathAndQuery) {
return String.format("%s%s", ServerName, pathAndQuery);// pathAndQuery.TrimStart('/')
}
/**
* 构造微信通用授权URL
*
* @param redirectUrl
* 授权后跳转的页面
* @param state
* 自定义函数
* @param scope
* 授权类型 :snsapi_base 静默授权, snsapi_userinfo手动同意授权
* @return
*/
public String BuildAuthUrl(String redirectUrl, String state, String scope) {
String apiUrl = "https://open.weixin.qq.com/connect/oauth2/authorize?appid=%s&redirect_uri=%s&response_type=code&scope=%s&state=%s#wechat_redirect";
try {
redirectUrl = java.net.URLEncoder.encode(redirectUrl, "utf-8");
} catch (UnsupportedEncodingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return String.format(apiUrl, WECHAT_APPID, redirectUrl, scope, state);
}
/**
* 构造授权回调地址
*
* @param type
* 页面类型
* @param scope
* 授权类型 :snsapi_base 静默授权, snsapi_userinfo手动同意授权
* @return
*/
public String BuildAuthCallbackUrl(String returnUrl, EnumScopeType scope) {
String url = BuildAuthUrl(GetUrl(String.format("/yeewii.m/WXApi/Auth?action=%s", returnUrl)), "state",
scope.toString());// Guid.NewGuid().ToString().Replace("-",
System.out.println("============================="); // "") // //
System.out.println(url); // "")
return url;
}
/// <summary>
/// 登录,若用户存在,则返回登录后的用户信息,否则返回null
/// </summary>
/// <param name="openId"></param>
/// <returns></returns>
public Wechat_User LoginInternal(HttpServletRequest request, HttpServletResponse response, String openId,
WechatUserInfo wxUser) throws Exception {
UserSessionUtil session = new UserSessionUtil();
session.setHeadimgurl(wxUser != null ? wxUser.headimgurl : "");
session.setNickname(wxUser != null ? wxUser.nickname : "");
session.setOpenId(wxUser != null ? wxUser.openid : "");
request.getSession().setAttribute("wxUser", session);
Wechat_User webchatuser = Wechat_User.findFirst(Wechat_User.class, "openid=?", new Object[] { openId });
if (webchatuser != null) {
BaseServcie.sendAutoLoginCookie(request, response, webchatuser);
}
return webchatuser;
}
/**
* 刷新access_token(如果需要)
*
* @param refresh_token
* @return
* @throws JsonParseException
* @throws JsonMappingException
* @throws IOException
*/
public RefreshtokenResult Refreshtoken(String refresh_token)
throws JsonParseException, JsonMappingException, IOException {
String url = "https://api.weixin.qq.com/sns/oauth2/refresh_token";
String para = String.format("appid=%s&grant_type=refresh_token&refresh_token=%s", WECHAT_APPID, refresh_token);
String jsonStr = HttpRequestUtil.sendGet(url, para);
RefreshtokenResult result = JsonMapper.json2Bean(jsonStr, RefreshtokenResult.class);
return result;
}
/**
* 获取微信用户基本信息 -手动授权
*
* @param openId
* @param accessToken
* @param refresh_token
* @return
* @throws Exception
* @throws JsonMappingException
* @throws IOException
*/
public WechatUserInfo GetSnsapiUserinfo(String openId, String accessToken, String refresh_token)
throws Exception, JsonMappingException, IOException {
String url = "https://api.weixin.qq.com/sns/userinfo";
RefreshtokenResult toRefreshtokenResult = Refreshtoken(refresh_token);
String para = String.format("access_token=%s&openid=%s&lang=zh_CN", accessToken, openId);
String jsonStr = HttpRequestUtil.sendGet(url, para);
WechatUserInfo result = JsonMapper.json2Bean(jsonStr, WechatUserInfo.class);
return result;
// 在获取用户信息时,提示,"errcode": 48001, 接口未被授权
// 需要用户提升为服务号,并且进行认证缴交每年300元
}
/**
* 最底层字符串编码转换的实现方法
*
* @param str
* 待转换的字符串
* @param oldCharset
* 源字符集
* @param newCharset
* 目标字符集
* @return 转换后的字符串
*/
public String changeCharset(String str, String oldCharset, String newCharset) {
if (str != null) {
// 用源字符编码解码字符串
try {
return new String(str.getBytes(oldCharset), newCharset);
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
}
return null;
}
}
相关转换实体类
package com.star.wxmessagemodel;
public enum EnumScopeType {
/**
* 静默授权
*/
snsapi_base,
/**
* 需手动同意授权
*/
snsapi_userinfo,
}
package com.star.wxmessagemodel;
public class OpenIdResult {
public String access_token;
public String getAccess_token() {
return access_token;
}
public void setAccess_token(String access_token) {
this.access_token = access_token;
}
public String getExpires_in() {
return expires_in;
}
public void setExpires_in(String expires_in) {
this.expires_in = expires_in;
}
public String getRefresh_token() {
return refresh_token;
}
public void setRefresh_token(String refresh_token) {
this.refresh_token = refresh_token;
}
public String getOpenid() {
return openid;
}
public void setOpenid(String openid) {
this.openid = openid;
}
public String getScope() {
return scope;
}
public void setScope(String scope) {
this.scope = scope;
}
public String getErrcode() {
return errcode;
}
public void setErrcode(String errcode) {
this.errcode = errcode;
}
public String getErrmsg() {
return errmsg;
}
public void setErrmsg(String errmsg) {
this.errmsg = errmsg;
}
public String expires_in;
public String refresh_token;
public String openid;
public String scope;
public String errcode;
public String errmsg;
public String unionid;
public String getUnionid() {
return unionid;
}
public void setUnionid(String unionid) {
this.unionid = unionid;
}
}
package com.star.wxmessagemodel;
/**
* 刷新access_token(如果需要)
* 由于access_token拥有较短的有效期,当access_token超时后,可以使用refresh_token进行刷新,refresh_token拥有较长的有效期(7天、30天、60天、90天),当refresh_token失效的后,需要用户重新授权。
*
* @author Administrator
*
*/
public class RefreshtokenResult {
public String access_token;
public String getAccess_token() {
return access_token;
}
public void setAccess_token(String access_token) {
this.access_token = access_token;
}
public String getExpires_in() {
return expires_in;
}
public void setExpires_in(String expires_in) {
this.expires_in = expires_in;
}
public String getRefresh_token() {
return refresh_token;
}
public void setRefresh_token(String refresh_token) {
this.refresh_token = refresh_token;
}
public String getOpenid() {
return openid;
}
public void setOpenid(String openid) {
this.openid = openid;
}
public String getScope() {
return scope;
}
public void setScope(String scope) {
this.scope = scope;
}
public String expires_in;
public String refresh_token;
public String openid;
public String scope;
}
package com.star.wxmessagemodel;
public class TicketResult {
public String errcode;
public String getErrcode() {
return errcode;
}
public void setErrcode(String errcode) {
this.errcode = errcode;
}
public String getErrmsg() {
return errmsg;
}
public void setErrmsg(String errmsg) {
this.errmsg = errmsg;
}
public String getTicket() {
return ticket;
}
public void setTicket(String ticket) {
this.ticket = ticket;
}
public String getExpires_in() {
return expires_in;
}
public void setExpires_in(String expires_in) {
this.expires_in = expires_in;
}
public String errmsg;
public String ticket;
public String expires_in;
}
package com.star.wxmessagemodel;
public class TokenJsonResult {
public String access_token;
public String getAccess_token() {
return access_token;
}
public void setAccess_token(String access_token) {
this.access_token = access_token;
}
public String getExpires_in() {
return expires_in;
}
public void setExpires_in(String expires_in) {
this.expires_in = expires_in;
}
public String getErrcode() {
return errcode;
}
public void setErrcode(String errcode) {
this.errcode = errcode;
}
public String getErrmsg() {
return errmsg;
}
public void setErrmsg(String errmsg) {
this.errmsg = errmsg;
}
public String expires_in;
public String errcode;
public String errmsg;
}
cache
package com.star.utils;
public class Cache {
private String key;// 缓存ID
private Object value;// 缓存数据
private long timeOut;// 更新时间
private boolean expired; // 是否终止
public Cache() {
super();
}
public Cache(String key, Object value, long timeOut, boolean expired) {
this.key = key;
this.value = value;
this.timeOut = timeOut;
this.expired = expired;
}
public String getKey() {
return key;
}
public long getTimeOut() {
return timeOut;
}
public Object getValue() {
return value;
}
public void setKey(String string) {
key = string;
}
public void setTimeOut(long l) {
timeOut = l;
}
public void setValue(Object object) {
value = object;
}
public boolean isExpired() {
return expired;
}
public void setExpired(boolean b) {
expired = b;
}
}
回调地址 (获取用户信息) 返回到指定页面
/**
* 回调地址 (登录操作,获取用户信息) 返回到指定页面
*
* @param code
* @param state
* @return
* @throws Exception
*/
public JspView Auth(String code, String state) throws Exception {
String targetUrl = "";
Wechat_User user = new Wechat_User();
String openId = "";
try {
targetUrl = request.getParameter("action");
// String actionValue = request.getParameter("action");
// // 也可以这样判断 是否在其中
// //
// Arrays.asList(EnumWechatMenuType.values()).contains(actionValue);
// if (!EnumWechatMenuType.IsIndexfoNo(actionValue)) {
// // String.format("微信授权回调错误,未知的动作:{0}.", actionValue)
// }
baseservice baseService = new baseservice();
OpenIdResult openresult = baseService.GetOpenId(code);
openId = openresult.getOpenid();
String accessToken = openresult.getAccess_token();
String refresh_token = openresult.getRefresh_token();
// WechatUserInfo wxUser = baseService.GetUserInfo(openId);//
// //
// 以snsapi_base为scope发起的网页授权,是用来获取进入页面的用户的openid的,并且是静默授权并自动跳转到回调页的。用户感知的就是直接进入了回调页(往往是业务页面)
WechatUserInfo wxUser = baseService.GetSnsapiUserinfo(openId, accessToken, refresh_token);
//
// 以snsapi_userinfo为scope发起的网页授权,是用来获取用户的基本信息的。但这种授权需要用户手动同意,并且由于用户同意过,所以无须关注,就可在授权后获取该用户的基本信息。
user = baseService.LoginInternal(request, response, openId, wxUser);
// for (EnumWechatMenuType name : EnumWechatMenuType.values()) {
// if (name.toString().equals(actionValue)) {
// targetUrl = name.getReturnurl();
// break;
// }
// }
if (user == null) {
Map<String, Object> map = new Wechat_UserDao().do_Wechatreg(request, response, openId, wxUser.nickname,
wxUser.headimgurl, "", "");
if (!map.get("result").equals(true) && !map.get("result").equals("true")) {
// 做失败操作
logger.error("回调地址 (登录操作,获取用户信息) 返回到指定页面==获取用户信息失败");
}
}
} catch (Exception ex) {
// 异常操作
logger.error("回调地址 (登录操作,获取用户信息) 返回到指定页面==获取用户信息异常" + ex);
}
redirect(targetUrl);
JspView view = new JspView(targetUrl);
view.setAttribute("user", user);
return view;
}