提交 c8334a8a 编写于 作者: F fancy

微信公众号基础功能

上级 0992ecc0
......@@ -24,6 +24,9 @@ public class MPweixin extends ConfigObject {
private String token = "";
@FieldDescribe("微信公众号配的encodingAesKey")
private String encodingAesKey="";
@FieldDescribe("微信公众号测试菜单的门户地址")
private String portalId = "";
......@@ -41,6 +44,7 @@ public class MPweixin extends ConfigObject {
this.appSecret = "";
this.token = "";
this.encodingAesKey = "";
this.portalId = "";
}
/**
......@@ -126,6 +130,14 @@ public class MPweixin extends ConfigObject {
this.encodingAesKey = encodingAesKey;
}
public String getPortalId() {
return portalId;
}
public void setPortalId(String portalId) {
this.portalId = portalId;
}
/**
* 微信使用code获取accessToken openid 等数据
*/
......
......@@ -9,6 +9,7 @@ import com.x.base.core.project.jaxrs.WrapBoolean;
import com.x.base.core.project.logger.Logger;
import com.x.base.core.project.logger.LoggerFactory;
import org.apache.commons.lang3.BooleanUtils;
import org.apache.commons.lang3.StringUtils;
/**
* Created by fancyLou on 3/4/21.
......@@ -33,20 +34,43 @@ public class ActionCreateMenu extends BaseAction {
String createUrl = MPweixin.default_apiAddress + "/cgi-bin/menu/create?access_token="+accessToken;
logger.info("url: "+createUrl);
String appId = Config.mPweixin().getAppid();
String baseUrl = "https://open.weixin.qq.com/connect/oauth2/authorize?appid="+appId;
String httpProtocol = Config.currentNode().getCenter().getHttpProtocol();
if (StringUtils.isEmpty(httpProtocol)) {
throw new ExceptionNoConfigArguments("对外http访问协议为空!");
}
String host = Config.currentNode().getWeb().getProxyHost();
if (StringUtils.isEmpty(host)) {
throw new ExceptionNoConfigArguments("代理Host为空!");
}
Integer port = Config.currentNode().getWeb().getProxyPort() == null? 80: Config.currentNode().getWeb().getProxyPort();
//"%3A"+port+ 有没有端口 是不同的安全域名
String ssoUrl = httpProtocol+"%3A%2F%2F"+host+"%2Fx_desktop%2Fmpweixinsso.html%3Ftype%3D";
String ssoOpenUrl = ssoUrl + "login";
String ssoBindUrl = ssoUrl + "bind";
String portalId = Config.mPweixin().getPortalId();
String openUrl = baseUrl;
if (StringUtils.isEmpty(portalId)) {
openUrl += "&redirect_uri="+ssoOpenUrl+"&response_type=code&scope=snsapi_userinfo&state=STATE#wechat_redirect";
}else {
openUrl += "&redirect_uri="+ssoOpenUrl+"%26redirect%3Dportalmobile.html%3Fid%3D"+portalId+"&response_type=code&scope=snsapi_userinfo&state=STATE#wechat_redirect";
}
String bindUrl = baseUrl+"&redirect_uri="+ssoBindUrl+"&response_type=code&scope=snsapi_userinfo&state=STATE#wechat_redirect";
String body = "{" +
"\"button\":[" +
" {" +
" \"type\":\"view\"," +
" \"name\":\"测试打开\"," +
" \"url\":\"https://open.weixin.qq.com/connect/oauth2/authorize?appid="+appId+"&redirect_uri=http%3A%2F%2Fqywx.o2oa.net%2Fx_desktop%2Fmpweixinsso.html%3Ftype%3Dlogin%26redirect%3Dportalmobile.html%3Fid%3Dxxxxxx&response_type=code&scope=snsapi_userinfo&state=STATE#wechat_redirect\"" +
" \"url\":\""+openUrl+"\"" +
" }," +
" { " +
" \"type\":\"view\"," +
" \"name\":\"测试绑定\"," +
" \"url\":\"https://open.weixin.qq.com/connect/oauth2/authorize?appid="+appId+"&redirect_uri=http%3A%2F%2Fqywx.o2oa.net%2Fx_desktop%2Fmpweixinsso.html%3Ftype%3Dbind%26redirect%3Dportalmobile.html%3Fid%3Dxxxxxx&response_type=code&scope=snsapi_userinfo&state=STATE#wechat_redirect\"" +
" \"url\":\""+bindUrl+"\"" +
" }" +
" ]" +
"}";
logger.info("测试菜单:" + body);
WeixinResp resp = HttpConnection.postAsObject(createUrl, null, body, WeixinResp.class);
if (resp.getErrcode() != null && resp.getErrcode() == 0) {
logger.info("保存菜单成功!");
......
package com.x.organization.assemble.authentication.jaxrs.mpweixin;
import com.x.base.core.project.exception.PromptException;
/**
* Created by fancyLou on 3/3/21.
* Copyright © 2021 O2. All rights reserved.
*/
public class ExceptionNoConfigArguments extends PromptException {
private static final long serialVersionUID = 1151495856256067183L;
public ExceptionNoConfigArguments(String error) {
super(error);
}
}
......@@ -67,7 +67,7 @@ public class MPweixinAction extends StandardJaxrsAction {
asyncResponse.resume(ResponseFactory.getEntityTagActionResultResponse(request, result));
}
@JaxrsMethodDescribe(value = "创建测试菜单", action = ActionCreateMenu.class)
@JaxrsMethodDescribe(value = "创建测试菜单, 【注意这个接口会把公众号菜单全部替换掉!】", action = ActionCreateMenu.class)
@GET
@Path("menu/create")
@Produces(HttpMediaType.APPLICATION_JSON_UTF_8)
......
/**
* 微信公众号单点登录
* 目前这个页面有两个功能 一个是绑定账号 一个是单点登录
*/
layout = window.layout || {};
var locate = window.location;
layout.protocol = locate.protocol;
var href = locate.href;
if (href.indexOf("debugger") != -1) layout.debugger = true;
layout.desktop = layout;
layout.session = layout.session || {};
o2.xDesktop = o2.xDesktop || {};
o2.addReady(function () {
// loading
var loadingNode = $("loaddingArea");
var loadeds = 0;
var loadCount = 16;
var size = document.body.getSize();
var _closeLoadingNode = function () {
if (loadingNode) {
loadingNode.destroy();
loadingNode = null;
}
};
var _loadProgressBar = function (complete) {
if (loadingNode) {
if (complete) {
loadingNode.setStyles({ "width": "" + size.x + "px" });
//loadingNode.set('morph', {duration: 100}).morph({"width": ""+size.x+"px"});
window.setTimeout(_closeLoadingNode, 500);
} else {
loadeds++;
var p = (loadeds / loadCount) * size.x;
loadingNode.setStyles({ "width": "" + p + "px" });
//loadingNode.set('morph', {duration: 100}).morph({"width": ""+p+"px"});
if (loadeds >= loadCount) window.setTimeout(_closeLoadingNode, 500);
}
}
};
o2.load(["../o2_lib/mootools/plugin/mBox.Notice.js", "../o2_lib/mootools/plugin/mBox.Tooltip.js"], { "sequence": true }, function () {
MWF.loadLP("zh-cn");
MWF.require("MWF.xDesktop.Layout", function () {
MWF.require("MWF.xDesktop.Authentication", null, false);
(function () {
layout.load = function () {
var uri = href.toURI();
var redirect = uri.getData("redirect"); //登录成功后跳转地址
var code = uri.getData("code"); //微信code
console.log("code:" + code)
var type = uri.getData("type"); // bind 是绑定
console.log("type:" + type)
if (type && type === "bind") {
layout._authForm();
}else { // code 登录
layout.showLoading();
o2.Actions.load("x_organization_assemble_authentication").MPweixinAction.loginWithCode(code, function(json) {
console.log(json);
layout.hideLoading();
layout.session.user = json.data;
if (redirect) {
history.replaceState(null, "page", redirect);
redirect.toURI().go();
} else {
history.replaceState(null, "page", "../x_desktop/appMobile.html?app=process.TaskCenter");
"appMobile.html?app=process.TaskCenter".toURI().go();
}
}, function(err) {
layout.hideLoading();
console.log(err)
layout.notice('单点登录失败', 'error');
});
}
};
/**
* 认证表单
*/
layout._authForm = function () {
//加载资源
var css = "../x_desktop/template/_mpwxssoLogin.css";
var html = "../x_desktop/template/_mpwxssoLogin.html";
var myBody = $(document.body);
myBody.loadAll({ "css": [css], "html": [html] }, { "bind": layout, "module": layout }, function () {
// 密码登录模式
layout.loginPwdModeNode.addEvents({
"click": function (e) {
e.target.addClass("mode-active");
layout.loginCodeModeNode.removeClass("mode-active");
layout.loginCodeBoxNode.setStyles({ "display": "none" });
layout.loginInputPasswordNode.setStyles({ "display": "" });
layout.loginMode = "password";
}
});
// 验证码登录模式
layout.loginCodeModeNode.addEvents({
"click": function (e) {
e.target.addClass("mode-active");
layout.loginPwdModeNode.removeClass("mode-active");
layout.loginCodeBoxNode.setStyles({ "display": "" });
layout.loginInputPasswordNode.setStyles({ "display": "none" });
layout.loginMode = "code";
}
});
layout.getCodeBtnNode.addEvents({
"click": function(e) {
layout._getCodeForLogin();
}
});
//登录
layout.loginBtnNode.addEvents({
"click": function (e) {
var username = layout.loginInputUsernameNode.get('value');
if (!username || username === '') {
layout.notice('请先输入用户名或手机号码!', "error")
return
}
if (layout.loginMode && layout.loginMode === 'code') { // 验证码登录
var code = layout.loginInputCodeNode.get('value');
if (!code || code === '') {
layout.notice('请先输入验证码!', "error")
return
}
var data = {
credential: username,
codeAnswer: code
}
layout.showLoading();
o2.Actions.load("x_organization_assemble_authentication").AuthenticationAction.codeLogin(data, function(json) {
console.log('登录成功。。。。。。。');
layout.session.user = json.data;
//绑定用户
layout._bindWeixin2User();
}, function(err) {
layout.hideLoading();
console.log(err)
layout.notice('登录失败!', "error")
});
}else { //密码登录
var password = layout.loginInputPasswordNode.get('value');
if (!password || password === '') {
layout.notice('请先输入密码!', "error")
return
}
var data = {
credential: username,
password: password
}
layout.showLoading();
o2.Actions.load("x_organization_assemble_authentication").AuthenticationAction. login(data, function(json) {
console.log('登录成功。。。。。。。');
layout.session.user = json.data;
//删除登录窗口
layout.loginBoxNode.destroy();
//绑定用户
layout._bindWeixin2User();
}, function(err) {
layout.hideLoading();
console.log(err)
layout.notice('登录失败!', "error")
});
}
}
})
}.bind(layout));
};
//绑定微信openid到用户信息
layout._bindWeixin2User = function() {
var uri = href.toURI();
var code = uri.getData("code"); //微信code
if (code) {
o2.Actions.load("x_organization_assemble_authentication").MPweixinAction.bindWithCode(code, function(json) {
layout.hideLoading();
//绑定成功
var box = new Element("div", {"style": "text-align: center;"}).inject($(document.body));
new Element("h2", {"text": "绑定成功!"}).inject(box);
}, function(err) {
layout.hideLoading();
console.log(err)
layout.notice('绑定账号失败', 'error');
})
}else {
layout.hideLoading();
layout.notice('没有传入微信code无法绑定', 'error');
}
};
// 获取验证码
layout._getCodeForLogin = function() {
var username = layout.loginInputUsernameNode.get('value');
if (!username || username === '') {
layout.notice('请先输入用户名或手机号码!', "error")
return
}
layout.countDownTime = 60;
// 修改按钮样式
layout.getCodeBtnNode.removeClass("code-btn");
layout.getCodeBtnNode.addClass("code-btn-sending");
layout.countDownTime--;
layout.getCodeBtnNode.set('text', layout.countDownTime + '秒后可重新获取');
layout.countDownFun = setInterval(()=> {
layout._countDownSendCode();
}, 1000)
o2.Actions.load("x_organization_assemble_authentication").AuthenticationAction.code(username, function(json) {
layout.notice('验证码已经发送,请注意查收!', 'success');
}, function(err){
console.log(err);
layout.notice('发送验证码失败!', 'error');
});
};
// countdown 定时器
layout._countDownSendCode = function() {
if (layout.countDownTime === 0) {
layout.getCodeBtnNode.removeClass("code-btn-sending");
layout.getCodeBtnNode.addClass("code-btn");
layout.getCodeBtnNode.set('text', '获取验证码');
layout.countDownTime = 60
if (layout.countDownFun) {
clearInterval(layout.countDownFun)
layout.countDownFun = null
}
}else {
layout.countDownTime--
layout.getCodeBtnNode.set('text', layout.countDownTime + '秒后可重新获取');
}
};
layout.showLoading = function() {
layout.loadingGif = new Element("div", {"sytle": "position:fixed;left:0;right:0;top:0;text-align: center;margin: 60px;"}).inject($(document.body));
new Element("img", {"src": "../x_desktop/img/loading2.gif", "style": "width: 96px; height: 96px;"}).inject(layout.loadingGif);
};
layout.hideLoading = function() {
if (layout.loadingGif) {
layout.loadingGif.destroy()
layout.loadingGif = null
}
};
// 通知
layout.notice = function (content, type, target, where, offset) {
if (!where) where = { "x": "right", "y": "top" };
if (!target) target = this.content;
if (!type) type = "ok";
var noticeTarget = target || $(document.body);
var off = offset;
if (!off) {
off = {
x: 10,
y: where.y.toString().toLowerCase() == "bottom" ? 10 : 10
};
}
new mBox.Notice({
type: type,
position: where,
move: false,
target: noticeTarget,
delayClose: (type == "error") ? 10000 : 5000,
offset: off,
content: content
});
};
//异步载入必要模块
layout.config = null;
var configLoaded = false;
var lpLoaded = false;
var commonLoaded = false;
var lp = o2.session.path + "/lp/" + o2.language + ".js";
o2.load(lp, function () {
_loadProgressBar();
lpLoaded = true;
var modules = ["o2.xDesktop.$all"];
o2.require(modules, {
"onSuccess": function () {
commonLoaded = true;
if (configLoaded && commonLoaded && lpLoaded) _getDistribute(function () { layout.load(); });
},
"onEvery": function () {
_loadProgressBar();
}
});
});
o2.getJSON("../x_desktop/res/config/config.json", function (config) {
_loadProgressBar();
layout.config = config;
configLoaded = true
if (configLoaded && commonLoaded && lpLoaded) _getDistribute(function () { layout.load(); });
});
var _getDistribute = function (callback) {
if (layout.config.app_protocol === "auto") {
layout.config.app_protocol = window.location.protocol;
}
o2.xDesktop.getServiceAddress(layout.config, function (service, center) {
layout.serviceAddressList = service;
layout.centerServer = center;
_loadProgressBar();
if (callback) callback();
}.bind(this));
};
// MWF.getJSON("res/config/config.json", function (config) {
// layout.config = config;
// MWF.xDesktop.getServiceAddress(layout.config, function (service, center) {
// layout.serviceAddressList = service;
// layout.centerServer = center;
// layout.load();
// }.bind(this));
// });
// o2.getJSON("../x_desktop/res/config/config.json", function (config) {
// _loadProgressBar();
// layout.config = config;
// configLoaded = true
// if (configLoaded && commonLoaded && lpLoaded) _getDistribute(function () { _load(); });
// });
})();
});
});
});
\ No newline at end of file
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<link rel="stylesheet" type="text/css" href="css/style.css" charset="UTF-8" />
<link rel="stylesheet" href="css/mBoxNotice.css" charset="UTF-8" />
<link rel="stylesheet" href="css/mBoxTooltip.css" charset="UTF-8" />
<script src="../o2_core/o2.min.js"></script>
<script src="js/mpweixinsso.js"></script>
<script src="../o2_lib/Decimal.js"></script>
<title>微信公众号sso</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<meta content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0" name="viewport" />
<meta content="yes" name="apple-mobile-web-app-capable" />
<meta content="black" name="apple-mobile-web-app-status-bar-style" />
<meta content="telephone=no" name="format-detection" />
</head>
<body style="overflow: hidden; margin:0px;height: 100%;width: 100%;">
</body>
</html>
.login-box {
height: 100%;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
padding: 32px;
box-sizing: border-box;
}
.form {
display: flex;
flex-direction: column;
width: 100%;
}
.login-mode {
height: 42px;
}
.login-mode .mode-sp {
margin: 0 10px;
font-size: 1.2em;
line-height: 46px;
}
.login-mode .mode-text {
color: #999999;
font-size: 1em;
line-height: 42px;
cursor: pointer;
}
.login-mode .mode-active {
color: #333333;
}
.input {
width: 100%;
height: 50px;
border-top: 0;
border-left: 0;
border-right: 0;
border-bottom: 1px #EEEEEE solid;
margin-top: 10px;
font-size: 1em;
}
.input-code-box {
width: 100%;
height: 50px;
margin-top: 10px;
display: flex;
flex-direction: row;
}
.input-code-box input {
border: 0;
border-bottom: 1px #EEEEEE solid;
font-size: 1em;
}
.code-btn {
width: 50%;
height: 40px;
line-height: 40px;
line-height: 40px;
background-color: #fb4747;
color: white;
font-size: 1em;
border: 0;
border-radius: 20px;
}
.code-btn-sending {
width: 50%;
height: 40px;
line-height: 40px;
line-height: 40px;
background-color: #c8c8c8;
color: white;
font-size: 1em;
border: 0;
border-radius: 20px;
}
.login-btn {
width: 100%;
height: 40px;
line-height: 40px;
background-color: #fb4747;
color: white;
border: 0;
border-radius: 20px;
margin-top: 60px;
text-align: center;
font-size: 1.2em;
}
\ No newline at end of file
<div class="login-box" data-o2-element="loginBoxNode">
<div class="form">
<div class="login-mode">
<span class="mode-text mode-active" data-o2-element="loginPwdModeNode">密码登录</span>
<span class="mode-sp">|</span>
<span class="mode-text" data-o2-element="loginCodeModeNode">短信验证登录</span>
</div>
<input type="text" class="input" placeholder="手机号/用户名" data-o2-element="loginInputUsernameNode" />
<input type="password" class="input" placeholder="密码" data-o2-element="loginInputPasswordNode" />
<div class="input-code-box" style="display: none;" data-o2-element="loginCodeBoxNode">
<input type="text" placeholder="验证码" data-o2-element="loginInputCodeNode" />
<button class="code-btn" data-o2-element="getCodeBtnNode">获取验证码</button>
</div>
<button class="login-btn" data-o2-element="loginBtnNode">登录</button>
</div>
</div>
\ No newline at end of file
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册