继上次幼儿园发的微信接龙打卡破解版后,现金牛区指定打卡地点,必须到教育局公众号打卡,其实既然都是程序,那么实现自动化的东西肯定是可以的,就看能不能爬出的接口了,通过Fiddler分析,发现接口既没加密、又没做限制,唯一需要有点遗憾的就是与微信OpenId绑定,但既然都能拿到Token了,还担心这个干嘛,跳过这步直接Token请求就完事。
先看看分析出来的API地址:
const URLS = {
PATH: {
base_api_post: "/base/api/request/http/post",
platform_api_post: "/platform/api/request/http/post",
},
API: {
authorize: "http://172.34.46.165:40003/api/user_relation/authorize",
get_user_info: "http://172.34.46.165:40003/api/user/get_user_info",
get_sign: "http://172.34.46.165:40002/api/minio/get_sign",
get_record: "http://172.34.46.165:40002/api/health_records/get_record",
add_record: "http://172.34.46.165:40002/api/health_records/add_record"
}
}
请求参数都是统一封装形式:
const params = {
method: "POST",
protocol: "https:",
host: "smartedu.jnei.cn",
path,
https: {
rejectUnauthorized: false // 网站数字证书设置不正确会导致验证失败
},
headers: {
"Content-Type": "application/json"
},
json: {
method,
url,
dataType: "json",
headers: {
token: this.token
},
body
}
}
话不多说,直接上代码:
async init() {
// this.auth()
// this.getUserInfo()
// this.getRecord()
const images = await this.genImage()
const health = [], trip = []
for (const idx in images.health) {
health[idx] = await this.getUploadUrl()
await this.uploadImg(images.health[idx], health[idx])
}
for (const idx in images.trip) {
trip[idx] = await this.getUploadUrl(2)
await this.uploadImg(images.trip[idx], trip[idx])
}
console.log(images, health, trip)
this.addRecord(health, trip)
}
private async genImage(): Promise<{ health: string[], trip: string[] }> {
const health = [
path.join(__dirname, "tmp/health1.png"),
path.join(__dirname, "tmp/health2.png"),
]
const trip = [
path.join(__dirname, "tmp/trip.png")
]
const generator = new ImageGenerator()
await generator.init()
generator.health(health[0], false)
// generator.health(health[1])
await generator.owner(health[1])
generator.trip(trip[0])
return {health, trip}
}
/**
* 通过微信code获取token、用户信息等
*/
private async auth(code: string, userType: 1 | 2 | 3): Promise<object> {
const result = await this.request({code, userType}, URLS.API.authorize, URLS.PATH.base_api_post)
this.token = result.data.token
return result.data
}
/**
* 获取用户班级信息
* @returns
*/
private async getUserInfo(): Promise<object> {
const result = await this.request(null, URLS.API.get_user_info, URLS.PATH.base_api_post, "GET")
this.userInfo = result.data
return this.userInfo
}
/**
* 获取已打卡记录信息
*/
private async getRecord(): Promise<object> {
const param = {
"createDay": dayjs().format('yyyy-MM-dd'),
"userId": "学生身份证号"
}
const result = await this.request(param, URLS.API.get_record)
return result.data
}
/**
* 获取上传路径
*/
private async getUploadUrl(type: 1 | 2 = 1): Promise<string> {
const result = await this.request({"name": `${randomUUID()}.png`, type}, URLS.API.get_sign)
return result.data.replace('http://ocr.jnei.cn:19000/', 'https://smartedu.jnei.cn/upload/');
}
/**
* 上传图片
*/
private async uploadImg(imgPath: string, uploadUrl: string) {
const pipeline = promisify(stream.pipeline);
await pipeline(
fs.createReadStream(imgPath),
got.stream.put(uploadUrl, {
protocol: "https:",
https: {
rejectUnauthorized: false
},
}),
new stream.PassThrough()
);
}
/**
* 添加打卡信息
*/
private async addRecord(healthUrls: string[], tripUrls: string[]): Promise<any> {
let param = {
"contactFlag": 0,
"createDay": dayjs().format("YYYY-MM-DD"), // new Date().Format('yyyy-MM-dd')
"healthFlag": 0,
"healthUrl1": "", // 本人健康码
"healthUrl2": "", // 同住人健康码
"healthUrl3": "", // 同住人健康码
"healthUrl4": "", // 同住人健康码
"healthUrl5": "", // 同住人健康码
"idcard": "学生身份证号", // user.idCard,
"idcardUS": "6位前缀****4位后缀",
"name": "学生名字", // user.userName
"otherSymptomFlag": 0,
"temperature": `36.${getRandomInt(9)}`, // 体温
"tripDays": "",
"tripFlag": 0,
"tripUrl1": "", // 本人行程卡
"tripUrl2": "", // 同住人行程卡
"tripUrl3": "", // 同住人行程卡
"tripUrl4": "", // 同住人行程卡
"tripUrl5": "", // 同住人行程卡
"userId": "626ba46c795a706c7f5c4499", // user.userId,
"userType": 2 // userType
}
// @ts-ignore
healthUrls.forEach((it: string, idx: number) => param[`healthUrl${idx + 1}`] = it.split("?")[0])
// @ts-ignore
tripUrls.forEach((it: string, idx: number) => param[`tripUrl${idx + 2}`] = it.split("?")[0])
const result = await this.request(param, URLS.API.add_record)
console.log("返回信息", result)
}