确保你的服务器已经安装了docker
云服务器部署/群晖部署
1.创建文件夹
云服务器
mkdir -p $(pwd)/bbk-qr/{conf,logs,static} && cd $(pwd)/bbk-qr
此时已cd进bbk-qr文件夹
群晖建议手动创建文件夹,每个人的路径不一样
手动新建3个文件夹
cd到docker文件夹
conf
logs
static
这是我的
cd /volume1/docker/Wskey转换/BBKWSkey扫码
2.启动容器
群晖手动替换$PWD
自己挂载的路径
docker run -dit \
-v $PWD/conf:/data/conf \
-v $PWD/logs:/data/logs \
-p 2081:81 \
--restart=always \
--name bbk-qr \
neuynp8oido4ejj/qr:latest
如果页面上想显示wskey出来
可以用下面的命令
同时conf.json文件内的 "loginReturnCK": true 需要设置 true
然后把下面的index.html下载下来,替换成显示wskey的网页,也可以复制下面显示wskey的index.html替换里面的代码
目录static/index.html
群晖手动替换$PWD
自己挂载的路径
docker run -dit \
-v $PWD/conf:/data/conf \
-v $PWD/logs:/data/logs \
-v $PWD/static:/data/static \
-p 2081:81 \
--restart=always \
--name bbk-qr \
neuynp8oido4ejj/qr:latest
3.修改conf.json文件内容(每次修改conf.json需要重启容器)
$(pwd)/conf 目录下的conf.json文件 填写token等信息
4. 重启容器
docker restart bbk-qr
5. 浏览器访问:http://你的IP:2081
云服务器记得放行端口
二维码只能用后置摄像头扫码,微信内部识别不到
显示wskey的index.html文件
可以用这个替换容器内的 static/index.html 文件:点击下载
也可以手动替换static/index.html内容
显示wskey的index.html
<!DOCTYPE html>
<html lang="zh-cn">
<head>
<meta charset="utf-8">
<meta content="width=device-width,initial-scale=1,user-scalable=no" name="viewport" />
<meta name="apple-mobile-web-app-capable" content="yes" />
<meta name="apple-touch-fullscreen" content="yes" />
<meta name="format-detection" content="telephone=no,address=no" />
<meta name="apple-mobile-web-app-status-bar-style" content="white" />
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
<title>qr</title>
<style>
body,
html {
margin: 0;
padding: 0;
}
.container {
display: flex;
flex-direction: column;
justify-content: space-around;
height: calc(100vh - 430px);
}
.qr {
display: flex;
justify-content: center;
align-items: center;
text-align: center;
position: fixed;
top: 0;
left: 0;
width: 100%;
inset: 0px;
height: 100%;
/* background-color: rgba(0, 0, 0, 0.45); */
z-index: 1001;
}
.qrcontainer {
position: relative;
width: 256px;
padding: 16px;
border-radius: 8px;
border: 1px solid rgb(109, 138, 136);
background-color: rgb(255, 255, 255);
box-shadow: rgb(0 0 0 / 20%) 0px 0px 7px 3px;
box-sizing: content-box;
}
#tip {
display: none;
justify-content: center;
align-items: center;
position: absolute;
top: 47px;
left: 16px;
width: 256px;
height: 256px;
color: rgb(255, 255, 255);
background-color: rgba(0, 0, 0, 0.5);
}
.desTitle {
word-break: break-word;
padding-bottom: 10px;
}
.des {
word-break: break-word;
padding-top: 10px;
}
</style>
</head>
<body>
<div class="container">
</div>
<div id="qr" class="qr">
<div class="qrcontainer">
<div class="desTitle">
<span id="tipt">loading...</span>|<a href="javascript:void(0)" id="refresh123" >手动刷新</a>
</div>
<div id="qrbox">
<img alt="" id="qrCode"/>
</div>
<div id="tip">
<h3>二维码已失效,请刷新</h3>
</div>
<div id="des" class="des"></div><!--tip-->
</div>
</div>
</body>
<script type="text/javascript">
document.getElementById("des").style.display = 'none';
document.getElementById('refresh123').addEventListener('click', function () {
let timeStamp = new Date().getTime();
ajax({
url: '/d/getQR?force=1&t=' + timeStamp,
method: 'get',
success: function (data) {
if (data.code !== 200) {
if (data.errMsg) {
showTips(data.errMsg);
} else {
showTips("获取二维码出错了,请刷新页面");
}
} else {
if (data.data.qr && data.data.timeout) {
i = parseInt(data.data.timeout);
location.reload();
}
}
},
});
});
get_code();
let a={}, i=180;
function qrExpire() {
document.getElementById("tip").style.display = 'flex';
window.clearInterval(a.ib)
}
function showTips(tip) {
document.getElementById("des").style.display = 'flex';
document.getElementById("des").innerHTML = tip;
}
function get_code() {
let timeStamp = new Date().getTime();
ajax({
url: '/d/getQR?t=' + timeStamp,
method: 'get',
success: function (data) {
if (data.code !== 200) {
if (data.errorMsg) {
showTips(data.errorMsg);
} else {
showTips("获取二维码出错了,请手动刷新页面");
}
// location.reload();
} else {
if (data.data.qr && data.data.timeout) {
i = parseInt(data.data.timeout);
document.getElementById("qrCode").setAttribute("src",data.data.qr);
document.getElementById("tipt").innerHTML = `有效期剩余${--i}秒`;
a.ib = setInterval(() => {
if (i <= 0) {
qrExpire();
// location.reload();
} else {
document.getElementById("tipt").innerHTML = `有效期剩余${--i}秒`;
}
}, 1000);
checkLogin();
}
}
},
});
}
function checkLogin() {
let timeStamp = new Date().getTime();
ajax({
url: '/d/status?t=' + timeStamp,
method: 'get',
success: function (data) {
console.log(JSON.stringify(data));
if (data.code == 500 || data.code == 202) {
qrExpire();
showTips(data.errorMsg);
} else if (data.code == 408) {
qrExpire()
// location.reload();
} else if (data.code == 410 && data.data) {
window.clearInterval(a.ib)
showTips(data.data.wskey);
qrExpire();
} else {
setTimeout(checkLogin, 1000)
}
}
});
}
function ajax(options) {
var url = options.url;
var method = options.method;
var data = options.data;
var success = options.success;
var ajax = new XMLHttpRequest();
ajax.open(method, url);
if (method == 'post') {
ajax.setRequestHeader('Content-type', 'application/json');
}
ajax.send(JSON.stringify(data));
ajax.onreadystatechange = function () {
if (ajax.readyState == 4 && ajax.status == 200) {
success(JSON.parse(ajax.responseText));
}
};
}
</script>
</html>
如下是conf.json文件参数介绍:
{
"server": {
// 机器人获取的token(必填参数)
"token": "",
// 扫码成功后页面检测状态接口是否返回wskey true:返回 false不返回(可选参数)
// 页面替换了显示wskey后此栏需设置true
"loginReturnCK": false,
// wskey安全考虑 推荐配置该加密秘钥,可手动设置(必须8-32位字符),如果enableEncrypt参数为true启用了wskey加密 此参数没设置时会随机生成一个,此秘钥需妥善保存 不能泄露!!!(可选参数)
// 页面替换了显示wskey后此栏不需要设置
"encryptKey": "",
// 推荐配置true。true:启用wskey安全加密 false:不启用wskey安全加密 (可选参数)
// 页面替换了显示wskey后此栏需设置false
"enableEncrypt": false
// 获取wskey之后是否将其转换app_open(JD_COOKIE)上传至青龙 true:上传 false:不上传
"convertWskey": true
},
// 青龙相关配置(可选参数对象 可全部不填 如果填了 则以下参数都需要填写)
"qinglong": {
// 青龙面板ip(必须填写)
"ip": "",
//青龙面板端口(必须填写)
"port": 0,
// 青龙面板clientId (必须填写)
"clientId": "",
// 青龙面板clientSecret (必须填写)
"clientSecret": "",
},
// 扫码成功通知配置(可选参数对象)
"notify": {
"tgBot": {
// telegram机器人token (可选参数)
"botToken": "",
// 接收消息的用户ID (可选参数)
"userId": "",
// http代理,留空则不使用 格式:http://127.0.0.1:1080 (可选参数)
"proxyUrl": ""
},
// 扫码成功后 主动以POST方式推送wskey到以下url接口 接收的参数格式:{"pin":"xx","wskey":"xx"},留空则不推送(可选参数对象)
"custom": {
// 推送wskey地址 格式: http://ip/xxx (可选参数)
"url": "",
"headers": {
// 推送的同时携带的请求头 比如认证信息 以下auth是例子可删(可选参数)
"auth": "123123123"
}
}
}
}