获取验证码
- 接口:https://m-center-prod-linli.timesgroup.cn/times/pub-center/verifycode/api/v1/send
- 请求方法:POST
- 请求参数
// 只需要修改 phoneNumber 为自己的手机号码 {"phoneNumber":"1342341234","areaCode":"86"}
- 返回结果
{ "code":200, "data":"验证码发送成功", "message":"success" }
根据验证码获取 token
- 接口:https://m-center-prod-linli.timesgroup.cn/times/times-bff/bff/api-c/v1/oauth/token
- 请求方法:POST
- 请求参数
// 修改 username 为自己的手机号码 // 修改 password 为收到的验证码 { "grant_type":"sms_code", "scope":"all", "client_id":"mini_charge", "client_secret":"times", "username":"13412341234", "password":"123456", "areaCode":"86" }
- 返回结果
{ "code":200, "data":{ "authUserDTO":{ "expiresIn":86399, "refreshToken":"eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9", "token":"eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9", "tokenHead":"Bearer " }, "userDTO":{ "eWechatOpenId":"", "eWechatUnionId":"", "extUserId":1, "id":1, "isCancel":0, "isEnable":0, "isShowRealName":0, "isSupplement":0, "phone":"13412341234", "phoneAreaCode":"86", "projectId":1, "projectName":"", "sex":0, "storeType":1, "storeUrl":"https://mall-prod-app-linli.timesgroup.cn/app/index", "updateTime":1, "userImage":"https://thirdwx.qlogo.cn/", "userName":"", "wxMinipOpenId":"", "wxOpenId":"", "wxUnionId":"" }, "userProjectHistoryDTOS":[ { "projectId":1, "projectName":"", "storeType":1, "storeUrl":"https://mall-prod-app-linli.timesgroup.cn/app/index" } ] }, "message":"success" }
获取会员 id - memberId
- 接口:https://m-center-prod-linli.timesgroup.cn/times/member-bff/member/api-c/v1/member/detailByPhone?phone=13412341234&phoneArea=86
- 请求方法:GET
- 请求参数
// 把 url 中的 phone 值替换为自己的手机号码
- 请求头加入上一步返回来的 token 拼接在
Bearer
后,如下:{ headers: { Authorization: "Bearer eyJhbGciOiJSU" } }
- 返回结果,只需要拿到结果中的 memberId
{ "code": 200, "data": { "cardNo": "", "cardType": "111", "couponNum": 0, "createTime": 1702007451000, "createUser": 2, "email": "", "grow": 0, "integral": 1, "integralTotal": 1, "isDeleted": 0, "isEnable": 0, "isShowRealName": 0, "memberCardRelats": [ { "createTime": 1702007451000, "createUser": 2, "expirationTime": 1, "grow": 300, "id": 1, "isDeleted": 0, "levelId": 1, "levelName": "普通会员", "memberCardId": 3, "memberCardImage": "", "memberCardName": "时代邻里会员卡", "memberCode": "", "memberId": 1, "rangeBegin": 0, "rangeEnd": 5000, "updateTime": 1702187857000, "updateUser": 2, "upgradedTime": 1702007451000 } ], "memberCode": "1", "memberId": 1, "memberIdStr": "1", "memberImage": "https://thirdwx.qlogo.cn/mmopen/vi_32", "memberName": "", "memberSources": [ { "createTime": 1702007451000, "createUser": 2, "id": 1, "isDeleted": 0, "memberId": 1, "sourceCode": "linlipro", "updateTime": 1702007451000, "updateUser": 2 } ], "memberType": 0, "memo": "", "phone": "", "phoneAreaCode": "86", "realName": "微信用户", "sex": 0, "updateTime": 1735185253000, "updateUser": 2 }, "message": "success" }
签到
- 接口:https://m-center-prod-linli.timesgroup.cn/times/member-bff/user-behaviour//api-c/v1/user-behaviour/collect
- 请求方法:POST
- 请求头
// 第二步返回来的 token 拼接在 `Bearer `后 { headers: { Authorization: 'Bearer eyJhbGciOiJSU', Content-Type: 'application/json' } }
- 请求参数
// memberId 为第三步返回的 memberId // createTime、sign为当前时间 格式:YYYY-MM-DD HH:mm:ss { "behaviourId": 10, "clientCode": "sys_linlibang", "createTime": "2024-11-27 08:19:45", "mapPamater": { "sign": "2024-11-27 08:19:45" }, "memberId": "12332131232133" }
- 返回结果
{ code: 200, data: true, message: 'success' }
自动刷新 token
token 过期时间,当前测试为 8 小时过期,需要在过期前刷新 token,下次签到就不用重新获取验证码登录(理论上可以无限续期)
接口:https://m-center-prod-linli.timesgroup.cn/times/auth/oauth/token
请求方法:POST
请求参数(FormData 格式)
// grant_type=refresh_token&client_secret=times&client_id=app_c&scope=all&refresh_token=eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2iMava32uw // 第一次刷新:refresh_token 需要设置为第二步获取返回来的 refreshToken // 第一次以后的刷新:refresh_token 获取本接口返回来的 refreshToken 即可 let formData = new FormData() formData.append("grant_type", "refresh_token") formData.append("client_secret", "times") formData.append("client_id", "app_c") formData.append("scope", "all") formData.append("refresh_token", "")
返回结果
{ "code":200, "data":{ "expiresIn":86399, "refreshToken":"eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2", "token":"eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX25", "tokenHead":"Bearer " }, "message":"操作成功" }
青龙脚本使用(手动导入)
代码
- 打开青龙面板 - 脚本管理 - 新建文件夹
times_script
- 在
times_script
下新建如下几个文件
// config.json
{
"token": "",
"refreshToken": ""
}
// times_get_code.js
const axios = require("axios")
// 获取配置文件,手机号和验证码 {"phone":"13412341234","code":"123456"}
// 如果 token 和 refreshToken 都为空时就获取 或者 isNweOne 为 true 时获取
function getTimesConfig() {
try {
const timesConfig = process.env.TIMES_CONFIG
if (timesConfig) {
console.log("获取到的API_KEY环境变量值为:", timesConfig)
console.log("API_KEY环境变量值转为JSON格式:", JSON.parse(timesConfig))
return JSON.parse(timesConfig)
} else {
console.log("未获取到API_KEY环境变量")
return ""
}
} catch (error) {
console.log("获取timesConfig时出错:", error.message)
}
}
// 获取验证码
async function getVerifyCode() {
try {
let timesConfig = getTimesConfig()
let params = {
phoneNumber: timesConfig.phone,
areaCode: "86",
}
console.log("请求参数:", params)
let { data } = await axios.post(
"https://m-center-prod-linli.timesgroup.cn/times/pub-center/verifycode/api/v1/send",
params,
{}
)
console.log("获取验证码结果:", data)
} catch (error) {
console.log("获取验证码时出错:", error.message)
}
}
// 获取验证码
getVerifyCode()
// times_get_token.js
const fs = require("fs")
const path = require("path")
const axios = require("axios")
// 获取配置文件,手机号和验证码 {"phone":"13412341234","code":"123456"}
function getTimesConfig() {
try {
const timesConfig = process.env.TIMES_CONFIG
if (timesConfig) {
console.log("获取到的API_KEY环境变量值为:", timesConfig)
console.log("API_KEY环境变量值转为JSON格式:", JSON.parse(timesConfig))
return JSON.parse(timesConfig)
} else {
console.log("未获取到API_KEY环境变量")
return ""
}
} catch (error) {
console.log("获取timesConfig时出错:", error.message)
}
}
// 定义config.json文件的路径,假设它与脚本在同一目录下
const configPath = path.join(__dirname, "config.json")
// 读取文件
function readConfigFile() {
let existingData = JSON.parse(fs.readFileSync(configPath, "utf8"))
console.log("读取config.json数据:", existingData)
return existingData
}
// 写入数据
function writeConfigFile(data) {
try {
let { token, refreshToken } = data
console.log("token", token, refreshToken)
let configData = readConfigFile()
if (token !== "") {
configData.token = token
}
if (refreshToken !== "") {
configData.refreshToken = refreshToken
}
fs.writeFileSync(configPath, JSON.stringify(configData, null, 2), "utf8")
console.log("修改后的config.json数据:", readConfigFile())
} catch (error) {
console.log("修改config.json时出错:", error.message)
}
}
// 通过验证码获取token
async function getNewToken() {
let timesConfig = getTimesConfig()
let params = {
grant_type: "sms_code",
scope: "all",
client_id: "mini_charge",
client_secret: "times",
username: timesConfig.phone,
password: timesConfig.code,
areaCode: "86",
}
let { data } = await axios.post(
"https://m-center-prod-linli.timesgroup.cn/times/times-bff/bff/api-c/v1/oauth/token",
params,
{}
)
console.log("获取token结果:", data)
if (data.code === 200) {
writeConfigFile({
token: data.data.authUserDTO.token,
refreshToken: data.data.authUserDTO.refreshToken,
})
} else {
console.log("获取token时出错:", data.message)
}
}
// 获取token
getNewToken()
// times_refresh_token.js
const fs = require("fs")
const path = require("path")
const axios = require("axios")
const FormData = require("form-data")
// 定义config.json文件的路径,与脚本在同一目录下
const configPath = path.join(__dirname, "config.json")
// 读取文件
function readConfigFile() {
let existingData = JSON.parse(fs.readFileSync(configPath, "utf8"))
console.log("读取config.json数据:", existingData)
return existingData
}
// 写入数据
function writeConfigFile(data) {
try {
let { token, refreshToken } = data
console.log("token", token, refreshToken)
let configData = readConfigFile()
if (token !== "") {
configData.token = token
}
if (refreshToken !== "") {
configData.refreshToken = refreshToken
}
fs.writeFileSync(configPath, JSON.stringify(configData, null, 2), "utf8")
console.log("修改后的config.json数据:", readConfigFile())
} catch (error) {
console.log("读取或修改config.json时出错:", error.message)
}
}
// 刷新token
async function startRefreshToken() {
let configData = readConfigFile()
console.log("获取configData:", configData)
if (configData.token) {
let formData = new FormData()
formData.append("grant_type", "refresh_token")
formData.append("client_secret", "times")
formData.append("client_id", "app_c")
formData.append("scope", "all")
formData.append("refresh_token", configData.refreshToken)
let config = {
headers: {
"Content-type": "multipart/form-data",
},
}
console.log("请求参数:", formData)
let { data } = await axios.post(
"https://m-center-prod-linli.timesgroup.cn/times/auth/oauth/token",
formData,
config
)
console.log("刷新token结果:", data)
if (data.code === 200) {
writeConfigFile({
token: data.data.token,
refreshToken: data.data.refreshToken,
})
} else {
console.log("刷新tokenn时出错:", data.message)
}
}
}
// 刷新token
startRefreshToken()
// times_signin.js
const fs = require("fs")
const path = require("path")
const axios = require("axios")
// 定义config.json文件的路径,假设它与脚本在同一目录下
const configPath = path.join(__dirname, "config.json")
// 读取文件
function readConfigFile() {
let existingData = JSON.parse(fs.readFileSync(configPath, "utf8"))
console.log("读取config.json数据:", existingData)
return existingData
}
function getFormattedDateTime() {
const now = new Date()
const year = now.getFullYear()
const month = (now.getMonth() + 1).toString().padStart(2, "0")
const day = now.getDate().toString().padStart(2, "0")
const hour = now.getHours().toString().padStart(2, "0")
const minute = now.getMinutes().toString().padStart(2, "0")
const second = now.getSeconds().toString().padStart(2, "0")
return `${year}-${month}-${day} ${hour}:${minute}:${second}`
}
// 签到
async function startSignin() {
let configData = readConfigFile()
let currentTime = getFormattedDateTime()
console.log(currentTime)
if (configData.token) {
let params = {
behaviourId: 10,
clientCode: "sys_linlibang",
createTime: currentTime,
mapPamater: {
sign: currentTime,
},
memberId: "3884010548647428143", //
}
let config = {
headers: {
Authorization: "Bearer " + configData.token,
"Content-type": "application/json",
},
}
try {
console.log("请求参数:", params)
let { data } = await axios.post(
"https://m-center-prod-linli.timesgroup.cn/times/member-bff/user-behaviour//api-c/v1/user-behaviour/collect",
params,
config
)
console.log("签到结果:", data)
if (data.code === 200) {
console.log("签到成功!")
} else {
console.log("签到n时出错:", data.message)
}
} catch (err) {
console.log("err", err)
}
}
}
// 签到
startSignin()
配置
- 青龙面板 - 环境变量 - 创建变量 - 填入如下信息,phone 为自己已经注册邻里邦的手机号码(必填),code 为稍后运行
times_get_code.js
脚本后发送到手机上的验证码(首次配置时可为空,待获取验证码后再填写)- 名称:
TIMES_CONFIG
- 值:
{"phone":"13412341234","code":"103282"}
- 名称:
- 注意:当前配置只针对
+86
的号码,非+86
请自行在代码中修改区号
添加定时任务
任务一
- 名称:
邻里邦获取验证码
- 命令/脚本:
task times_script/times_get_code.js
- 定时规则:
0 0 1 12 *
- 名称:
任务二
- 名称:
邻里邦获取token
- 命令/脚本:
task times_script/times_get_token.js
- 定时规则:
0 0 1 12 *
- 名称:
任务三
- 名称:
邻里邦刷新token(每三小时执行一次)
- 命令/脚本:
task times_script/times_refresh_token.js
- 定时规则:
0 */3 * * *
- 名称:
任务四
- 名称:
邻里邦签到
- 命令/脚本:
task times_script/times_signin.js
- 定时规则:
5 9 * * *
- 名称:
使用步骤
- 运行前确认
配置
中的TIMES_CONFIG
配置已填写phone
- 运行
任务一
获取验证码,把手机上获取到的验证码填写到配置
中的TIMES_CONFIG
的code
中 - 运行
任务二
获取 token,token 会自动填写到 config.json 中 - 运行
任务三
刷新 token,任务会每隔三小时自动刷新一次 - 运行
任务四
进行签到,任务会在每天早上 9 点 5 分自动签到 - 到此不出意外的话签到任务会每天自动运行,不再需要人工干涉
- 如果出先签到不成功,请按照
使用步骤
在运行一次,如果还不行那就是接口改变了,需要重新调试代码