本文介绍了将苍穹开发的H5页面挂载到微信、钉钉等OA应用中心的方法,但无法直接转为不同APP的小程序。解决方案包括使用uni-app和HBuilderX快速搭建小程序,通过web-view挂载H5页面,自定义Filter处理微信登录code,获取用户手机号码后进行用户匹配和session创建,最后重定向到目标页面。文中还提供了小程序创建和Filter开发的代码示例。
# 业务场景
在苍穹开发完成的H5页面已经非常方便的挂载微信、钉钉等OA的应用中心,直接配置相关应用参数即可。
**但是不能直接转换成对应微信小程序、支付宝小程序等不同APP的小程序**
# 解决方案
1. uni-app 和 HBuilderX 快速搭建小程序应用架构,2. 通过web-view 组件挂载苍穹的H5的URL
3. 自定义Filter接收微信小程序登录code参数,把code转换为session_key。然后在前端引导用户授权获取手机号码,在后端进行解密获取真实手机号码
4. 通过手机号码匹配查找用户,进行创建session,然后页面重定向到需要登录的目标页面
# 开发过程
## 创建小程序
1. 在微信小程序后台创建小程序,获取到appid和secret;安装微信开发者工具,开启服务端口2. 安装HBuilderX 开发工具,创建uniapp,填写微信小程序信息
index.vue代码参考
<template> <div> <!-- Dynamically load the web view --> <web-view v-if="webUrl" :src="webUrl"></web-view> </div> </template> <script> export default { data() { return { jsCode: '', // Code received from wx.login webUrl: '', // Target URL to be loaded in web-view }; }, mounted() { this.loginAndRedirect(); }, methods: { /** * Login and fetch session data, then set the redirect URL. */ loginAndRedirect() { uni.login({ success: (res) => { if (res.code) { this.jsCode = res.code; this.fetchSessionData(res.code); } else { console.error('登录失败!' + res.errMsg); } }, fail: (error) => { console.error('wx.login failed:', error); }, }); }, /** * Fetch session data from the server. * @param {string} code - Code from wx.login */ fetchSessionData(code) { this.webUrl = "http://127.0.0.1:8881/ierp/wx_uni.do?redirect=http://127.0.0.1:8881/ierp/mobile.html?form=kded_meeting_mob_index&js_code="+code }, }, }; </script> <style scoped> /* Center the web-view for better UX */ div { display: flex; align-items: center; justify-content: center; height: 100vh; } </style>
获取手机号码逻辑参考https://blog.csdn.net/weixin_58034343/article/details/138784567
## 苍穹过滤器Filter开发
通过Filter方式开发,Filter开发参考 https://developer.kingdee.com/article/318801864630167296?productLineId=29&isKnowledge=2&lang=zh-CN
public class WxUniFilter implements Filter { private static final Log logger = LogFactory.getLog(WxUniFilter.class); @Override public void init(FilterConfig filterConfig) throws ServletException { Filter.super.init(filterConfig); } @Override public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { HttpServletRequest request = (HttpServletRequest) servletRequest; HttpServletResponse response = (HttpServletResponse) servletResponse; String tenantId = RevProxyUtil.getTenantCode(request); LoginUtils.handleGenernal(request, response); String accountIdParameter = request.getParameter("accountId"); Account currentCenter = AccountUtils.getCorrectAccount(accountIdParameter, tenantId); Lang lang = LoginLangUtils.getLoginLanguage(request); LoginLangUtils.setLang(lang); //微信小程序前端code String code = request.getParameter("js_code"); String urlBase = "https://api.weixin.qq.com/sns/jscode2session"; urlBase += "?appid=wxdd32d5b481a8a7d4&secret=250231d3474a8bc02b3be63e5ca43416&js_code=" + code + "&grant_type=authorization_code"; String codeResult = HttpUtils.request(urlBase); JSONObject jsonObject = JSONObject.parseObject(codeResult); //获取用户信息,openid String openid = jsonObject.getString("openid"); //ActionUtil.writeResponseJson(response, "{"session_key":"jQ1TLLeS3R8YVxAUhmtZPw==","openid":"oY7C45U6B6baSuYhJupNSWoSnpzM"}"); //TODO 正常应该把相关信息返回前端,让用户点击授权获取手机号码,再继续进行完成下面的重定向逻辑 if (StringUtils.isEmpty(openid)) { response.sendRedirect("http://127.0.0.1:8881/ierp/mobile.html?form=kded_meeting_mob_index"); return; } //根据关键信息匹配查找用户手机号码 QFilter filter = new QFilter("kded_wx_openid", QFilter.equals, openid); DynamicObject bosUser = BusinessDataServiceHelper.loadSingle("bos_user", "phone", filter.toArray()); Map<String, String> userInfo = LoginUserService.getErpUserInfoByPhone(null, bosUser.getString("phone"), lang.getLangTag()); String randomCode = this.loginFromDefaultTenant(request, response, lang, currentCenter, userInfo); JSONObject jsonObject1 = JSONObject.parseObject(randomCode); if (jsonObject1.getInteger("errorcode") == 0){ response.sendRedirect(jsonObject1.getString("RedirectURL")); }else { response.sendRedirect("http://127.0.0.1:8881/ierp/mobile.html?form=kded_meeting_mob_index"); } } @Override public void destroy() { Filter.super.destroy(); } /** * 用户重定向处理 */ private String loginFromDefaultTenant(HttpServletRequest request, HttpServletResponse response, Lang lang, Account currentCenter, Map<String, String> userInfo) throws IOException { String user = userInfo.get("ftruename"); logger.info(String.format("用户%s登录默认租户。", user)); if (!"0".equalsIgnoreCase(userInfo.get("success"))) { String userName = userInfo.get("ftruename"); String userorgId = userInfo.getOrDefault("forgid", "0"); userInfo.put("ftruename", userName); userInfo.put("forgid", userorgId); Map<String, Object> map = new HashMap<>(8); String redirect; //创建用户session SessionUtils.createNewSession(request, response, currentCenter, lang, NetAddressUtils.getRemoteHost(request), userInfo, LoginClientEnum.MOBILE); // if (StringUtils.isNotEmpty(request.getParameter("isMobile"))) { // // } else { // redirect = SessionUtils.createNewSession(request, response, currentCenter, lang, NetAddressUtils.getRemoteHost(request), userInfo, LoginClientEnum.WEB); // } logger.info("客户 端类型 :" + AgentUtil.getClienyId(request) + ",用户名:" + request.getRemoteHost() + ",访问地址:" + request.getRemoteAddr()); LoginUtils.setCachkeyData(currentCenter); LoginUtils.clearSmsSendTimes(currentCenter.getAccountId(), user); redirect = request.getParameter("redirect"); if (StringUtils.isEmpty(redirect)) { redirect = UrlService.getDomainContextUrl() + "/index.html"; } else if (LoginUtils.isSelfEnvironment(redirect, request, response) && !SecurityUtils.checkXss(redirect)) { String qs = request.getQueryString(); if (qs != null) { redirect = qs.replace("redirect=", ""); } } else if (StringUtils.isNotEmpty(request.getParameter("isMobile"))) { redirect = "mobile.html"; } else { redirect = "index.html"; } map.put("errorcode", 0); String randomCode; redirect = URLUtils.securityFilterRedirectUrl(redirect); map.put("RedirectURL", redirect); map.put("username", userName); map.put("userId", userInfo.get("fid")); return JSONUtils.toString(map); } else { throw new KDException(LoginErrorCode.loginBizException, ResManager.loadKDString("您的账号在系统中不存在!", "LoginAction_11", "bos-login")); } } }
通过Java代码解密微信加密过的用户手机号码信息 参考 https://blog.csdn.net/m0_72958694/article/details/139890088
# 实现效果
本地代码调试效果推荐阅读