微信公众号企业号小程序研发框架搭建 公众号开发
微信公众企业号在研发的时候,有一些基础通用功能是必须的,为此特地搭建了企业号微信小程序研发框架, 此框架运行图如下:
接下来介绍一下各个步骤及各个步骤的代码(java版):
系统初始化信息:
导入企业号微信的员工信息 userid为员工编号; 具体如何导入请参考企业号公众号说明。
新建立小程序 微信小程序 wxoa 小程序的各个系统属性参数 小程序界面会提供。
参数汇总如下:
String token = "************";
String EncodingAESKey = "**************";
// 企业ID
static String CorpID = "***";
// secret 测试小程序的 访问密令
static String Secret = "*************";
String backAuthUri = "http://***.com/dyoa/wx_enter/action/oauth";
小程序菜单初始化 3个主菜单 从左到右依次编号为 1_x, 2_x , 3_x 二级菜单 从上倒下也按照顺序编码 1_1, 1_2 ,.., 2_1 , 2_2,..等等,二级菜单配置URI: http://xx.com/weixin/xxx.do?menuno=x_x 如此准备条件完毕
第一步骤 企业号人员点击菜单进入系统
第二步骤 首先进入过滤器 过滤器的功能主要描述如下:
1当用户第一次进入过滤器 过滤器验证用户是否是企业号的用户获取用户USERID等信息,
2 第二次重新进入过滤器 过滤器处理当前登录企业用户的菜单权限 数据权限 判断出是否有权限,是否可以进入某个菜单等
过滤器代码:
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException,
ServletException {
HttpServletRequest hRequest = (HttpServletRequest) request;
// 请求的路径
String contextPath = hRequest.getContextPath();
// 获取前台的 菜单编码
String menuNo = hRequest.getParameter("menu");
hRequest.getSession().setAttribute("menuNo", menuNo);
// 这里读取文件获取 访问权限
String tokenFromFile = this.getTokenFromFile();
// 获取了 token的话, 同步到系统级别的缓存中
if (!"no".equals(tokenFromFile)) {
request.getServletContext().setAttribute("accessToken", tokenFromFile);
// 标记为已经读取
} else {
System.out.println("token from file fail ");
}
// 对ACCTOKEN进行获取并通过系统级参数进行传递 共享整个小应用范围内
String accessToken = (String) request.getServletContext().getAttribute("accessToken");
if (accessToken == null || "".equals(accessToken) || menuNo == null) {
// 若更新 令牌失败,则将URI定位到错误 处理函数 这里测试成功 return 必须存在
((HttpServletResponse) response).sendRedirect(contextPath + "/wx_enter/action/error.do?code=tokenIsNull");
return;
}
HttpSession session = hRequest.getSession();
String userId = (String) session.getAttribute("userId");
if (null == userId || "".equals(userId)) {
String resultUrl = hRequest.getRequestURL().toString();
String param = hRequest.getQueryString();
if (param != null) {
resultUrl += "?" + param;
}
try {
resultUrl = java.net.URLEncoder.encode(resultUrl, "utf-8");
} catch (Exception e) {
e.printStackTrace();
}
((HttpServletResponse) response).sendRedirect(contextPath + "/wx_enter/action/userEnter.do?returnBackUrl="+ resultUrl);
// 避免下面的代码 继续执行
return;
}
// 若 USERID为空 , 则通过微信后台接口 获取当前微信用户信息
else {
// userId 及 OA系统的员工 编号
System.out.println("filter userid =" + userId);
// 第二次登录开始
SessionModel model = (SessionModel) hRequest.getSession().getAttribute("sessionInfo");
Map<String, Map
Map
Map
if (jspRights != null) {
String jspRight = jspRights.get(menuNo);
String dataRight = dataRights.get(menuNo);
if (null == jspRight) {
System.out.println(userId + "filter 您无权登录菜单" + menuNo);
((HttpServletResponse) response).sendRedirect(contextPath
+ "/wx_enter/action/error.do?code=hasNoRightToEnter_" + menuNo);
return;
} else {
String shenhe = jspRight.split("_")[0];
String caozuo = jspRight.split("_")[1];
System.out.println("菜单=" + menuNo + " ;shenhe=" + shenhe + " ;caozuo=" + caozuo
+ ";this-dataRight:" + dataRight + " ;dataRights=" + dataRights);
/ 针对菜单 的角色配置 做数据权限 转LEVEL处理, 可以同时用于界面与后台的数据处理 现金支领审核菜单
// 进入这里说明 用户的ID不为空
if (userId != null && menuNo != null) {
// 根据用户ID获取审核当前菜单的审核级别
。。。。。。。。
}
request.setAttribute("shenhe", shenhe);
request.setAttribute("caozuo", caozuo);
}
}
}
chain.doFilter(request, response);
}
/**
* 用户第一次进入系统 转向到微信接口验证用户 , 且获取最初请求URI
*/
@RequestMapping(value = "/wx_enter/action/userEnter", method = RequestMethod.GET)
public void userEnter(HttpServletRequest request, HttpServletResponse response) {
try {
// 获取回调界面的URI //此URI 已经 encode
String returnBackUrl = request.getParameter("returnBackUrl");
String uri = "https://open.weixin.qq.com/connect/oauth2/authorize?appid=CORPID&redirect_uri=REDIRECT_URI&response_type=code&scope=SCOPE&state=STATE#wechat_redirect";
// 赋值
uri = uri.replace("CORPID", CorpID);
uri = uri.replace("REDIRECT_URI", WeixinUtil.urlEncode(backAuthUri + "?returnBackUrl=") + returnBackUrl); // 需要encoder
uri = uri.replace("SCOPE", "snsapi_base"); // 用户基础信息
uri = uri.replace("STATE", "123456");
// 重定向
response.sendRedirect(uri);
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* 获取微信用户的 信息 , 只有第一次登录的时候 才会走此验证 *
* @企业成员授权时返回示例如下: { "UserId":"USERID", "DeviceId":"DEVICEID" "user_ticket":
* "USER_TICKET", "expires_in":7200 }
* @非企业成员授权时返回示例如下: { "OpenId":"OPENID", "DeviceId":"DEVICEID" }
* @info 重定向的URI 为 redirect_uri?code=CODE&state=STATE
*/
@RequestMapping(value = "/wx_enter/action/oauth", method = RequestMethod.GET)
public void weixinOAuth(HttpServletRequest request, HttpServletResponse response) {
String menuNo = (String) request.getSession().getAttribute("menuNo");
// 获取传递过来的 回调界面的URI
String returnBackUrl = request.getParameter("returnBackUrl");
String access_token = (String) request.getServletContext().getAttribute("accessToken");
// 获取重定向传递的CODE与STATE
String code = request.getParameter("code");
String state = request.getParameter("state");
// 根据CODE与ACCESS_TOKEN 获取用户的信息 重点为 userid
if (code != null && !"".equals(code) && !"".equals(access_token)) {
// 获取的用户信息JSON
// ={"UserId":"N1","DeviceId":"545445353453453453455434534",
// "errcode":0,"errmsg":"ok"}
WxUser user = WeixinUtil.getLoginUserInfo(access_token, code);
// 这里代表 系统获取了 当前微信用户的 userid ,微信验证为 当前用户为 员工
if (null != user.getUserId() && !"".equals(user.getUserId())) {
System.out.println("微信登录成功" + user.getUserId());
// 这里需要触发同步登录函数
try {
SessionModel a = this.wxService.wxLogin(user);
if (a == null) {
System.out.println(user.getUserId() + "后台登录失败");
response.sendRedirect(request.getContextPath() + "/wx_enter/action/error.do?code=errorUserNull");
// return;
} else {
// 对菜单进行验证过滤
。。。。。。。。。。。
}
request.getSession().setAttribute("userId", user.getUserId());
// 此字段为 核心字段 用于同步手机段与服务器之间数据
request.getSession().setAttribute("sessionInfo", a);
try {
// 重定向到页面回调URI 路径是正确的 已经确认
response.sendRedirect(returnBackUrl);
// request.getRequestDispatcher(returnBackUrl).forward(request,
// response);
} catch (IOException e) {
e.printStackTrace();
}
}
} catch (Exception e1) {
e1.printStackTrace();
}
} else {
try {
System.out.println("您无权登录系统");
response.getWriter().write("您无权登录系统,请确认");
response.getWriter().flush();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
微信重新回来的时候, 会调用上面的函数, 函数的操作是 对用户进行后台隐式登录到系统,并将请求重新定向到过滤器上(第二次进入过滤器) 对其能否进入系统某个菜单及 对某个界面 的操作按钮权限进行控制。
企业号 accessToken控制模块如何设计 请参考下一篇文章
下面是两个工具函数 获取用户基础信息 获取令牌信息
/**
* 获取企业号登录用户信息
* @param corpid
* @param corpsecret
* https://qyapi.weixin.qq.com/cgi-bin/
* user/getuserinfo?access_token=ACCESS_TOKEN&code=CODE
*/
public static WxUser getLoginUserInfo(String access_token, String auth_code) {
String token_url = "https://qyapi.weixin.qq.com/cgi-bin/user/getuserinfo?access_token=ACCESS_TOKEN&code=CODE";
token_url = token_url.replace("ACCESS_TOKEN", access_token);
token_url = token_url.replace("CODE", auth_code);
// System.out.println("new userInfoURI = " + token_url);
WxUser wu = null;
try {
URL url = new URL(token_url);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setDoInput(true);
conn.setRequestMethod("GET");
InputStream inputStream = conn.getInputStream();
Reader in = new InputStreamReader(inputStream);
BufferedReader reader = new BufferedReader(in);
StringBuffer buffer = new StringBuffer();
String str = null;
while ((str = reader.readLine()) != null) {
buffer.append(str);
}
inputStream.close();
in.close();
reader.close();
conn.disconnect();
JSONObject json = JSONObject.fromObject(buffer.toString());
System.out.println("获取的用户信息JSON =" + json);
// {"UserId":"N33","DeviceId":"34343434343434343434322","errcode":0,"errmsg":"ok"}
String errcode = json.getString("errcode");
String errmsg = json.getString("errmsg");
if ("0".equals(errcode) || "ok".equals(errmsg)) {
wu = new WxUser();
wu.setDeviceId(json.getString("DeviceId"));
wu.setUserId(json.getString("UserId"));
wu.setErrcode(errcode);
wu.setErrmsg(json.getString("errmsg"));
}
} catch (Exception e) {
e.printStackTrace();
}
return wu;
}
/**
* 获取AccessToken; 每个secret代表了对应用、通讯录的不同权限;不同的管理组拥有不同的secret。
*
* @param corpid
* 企业Id
* @param corpsecret
* 管理组的凭证密钥
*/
public static String getAccessToken(String corpid, String corpsecret) throws Exception {
String token_url = "https://qyapi.weixin.qq.com/cgi-bin/gettoken?corpid=" + corpid + "&corpsecret="
+ corpsecret;
String access_token = null;
URL url = new URL(token_url);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setDoInput(true);
conn.setRequestMethod("GET");
InputStream inputStream = conn.getInputStream();
Reader in = new InputStreamReader(inputStream);
BufferedReader reader = new BufferedReader(in);
StringBuffer buffer = new StringBuffer();
String str = null;
while ((str = reader.readLine()) != null) {
buffer.append(str);
}
inputStream.close();
in.close();
reader.close();
conn.disconnect();
JSONObject json = JSONObject.fromObject(buffer.toString());
access_token = json.getString("access_token");
if (access_token != null) {
// System.out.println("访问令牌:" + access_token);
} else {
System.out.println("token获取失败!");
}
return access_token;
/*注:企业号融合过程中该接口输出参数可能略有不同,以下情况均视作获取token成功:
1、能获取到access_token,接口无返回errcode
2、能获取到access_token,接口返回errcode为0, errmsg为空或者"ok"
正确的Json返回结果:
{
"access_token": "accesstoken000001",
"expires_in": 7200
}
b)错误的Json返回示例:
{
"errcode": 43003,
"errmsg": "require https"
}*/
}
如有疑问 请留言 欢迎提供建议
评论已有 0 条