diff --git a/CHANGELOG.md b/CHANGELOG.md index 7e1800d..fe0aa23 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,6 @@ +# 1.2.8 +* 增加`#原神充值` 原神离线充值 +* 增加`#商品列表` # 1.2.7 * 增加`#扫码登录`支持扫码获取sk以及ck * 增加`#账号密码登录`支持获取sk以及ck diff --git a/apps/mhyTopUpLogin.js b/apps/mhyTopUpLogin.js index 8551c1a..f58ce5d 100644 --- a/apps/mhyTopUpLogin.js +++ b/apps/mhyTopUpLogin.js @@ -5,7 +5,7 @@ import mys from "../model/mhyTopUpLogin.js" import Common from "../components/Common.js"; import { bindStoken } from './user.js' import utils from '../model/mys/utils.js'; -import {segment} from 'oicq' +import { segment } from 'oicq' const _path = process.cwd(); export const rule = { qrCodeLogin: { @@ -22,38 +22,34 @@ export const rule = { }, payOrder: { /** 命令正则匹配 */ - reg: '^#?原神(微信)?充值(微信)?(.*)$', + reg: '^#?((原神(微信)?充值(微信)?(.*))|(#?商品列表)|(#?订单查询))$', /** 执行方法 */ describe: '原神充值(离线)' - }, payOrder: { - reg: "^#?商品列表", - describe: '原神充值商品列表' - },payOrder:{ - reg:'^#?订单查询', - describe:'充值订单查询' } } -export async function payOrder(e){ +export async function payOrder(e, { render }) { let Mys = new mys(e) - if(/商品列表/.test(e.msg)){ + if (/商品列表/.test(e.msg)) { return await Mys.showgoods() - }else if (/订单查询/.test(e.msg)) { - return await Mys.checkOrder() - }else if(e.msg.includes('充值')){ - return await Mys.GetCode() + } else if (/订单查询/.test(e.msg)) { + //容我摆烂会 + e.reply('作者还在咕咕咕~~~~') + //return await Mys.checkOrder() + } else if (e.msg.includes('充值')) { + return await Mys.GetCode({ render }) } return false; -} +} export async function qrCodeLogin(e, { render }) { let Mys = new mys(e) let res = await Mys.qrCodeLogin() if (!res?.data) return false; - e._reply=e.reply - let sendMsg=[segment.at(e.user_id),'\n请扫码以完成绑定\n'] - e.reply=(msg)=>{ + e._reply = e.reply + let sendMsg = [segment.at(e.user_id), '\n请扫码以完成绑定\n'] + e.reply = (msg) => { sendMsg.push(msg) } await Common.render(`qrCode/index`, { @@ -61,14 +57,14 @@ export async function qrCodeLogin(e, { render }) { }, { e, render, - scale: 1.2,retMsgId: true + scale: 1.2, retMsgId: true }) - let r= await e._reply(sendMsg) - utils.recallMsg(e,r,30) //默认30,有需要请自行修改 - e.reply=e._reply + let r = await e._reply(sendMsg) + utils.recallMsg(e, r, 30) //默认30,有需要请自行修改 + e.reply = e._reply res = await Mys.GetQrCode(res.data.ticket) if (!res) return true; - await bindSkCK(e,res) + await bindSkCK(e, res) return true; } diff --git a/model/mhyTopUpLogin.js b/model/mhyTopUpLogin.js index b37c004..d788a21 100644 --- a/model/mhyTopUpLogin.js +++ b/model/mhyTopUpLogin.js @@ -1,6 +1,7 @@ import User from "./user.js"; import utils from './mys/utils.js'; import { segment } from 'oicq' +import Common from "../components/Common.js"; export default class mysTopLogin { constructor(e) { this.e = e; @@ -14,9 +15,9 @@ export default class mysTopLogin { } // async qrCodeLogin() { - let RedisData=await utils.redisGet(this.e.user_id,"GetQrCode") - if(RedisData){ - this.e.reply([segment.at(this.e.user_id),`前置二维码未扫描,请勿重复触发指令`]) + let RedisData = await utils.redisGet(this.e.user_id, "GetQrCode") + if (RedisData) { + this.e.reply([segment.at(this.e.user_id), `前置二维码未扫描,请勿重复触发指令`]) return false; } this.device = await utils.randomString(64) @@ -31,15 +32,15 @@ export default class mysTopLogin { return res } async GetQrCode(ticket) { - await utils.redisSet(this.e.user_id,"GetQrCode",{GetQrCode:1},60*5) //设置5分钟缓存避免重复触发 + await utils.redisSet(this.e.user_id, "GetQrCode", { GetQrCode: 1 }, 60 * 5) //设置5分钟缓存避免重复触发 let res; - let RedisData=await utils.redisGet(this.e.user_id,"GetQrCode") + let RedisData = await utils.redisGet(this.e.user_id, "GetQrCode") for (let n = 1; n < 60; n++) { await utils.sleepAsync(5000) res = await this.user.getData("qrCodeQuery", { device: this.device, ticket }) - if (res?.data?.stat == "Scanned"&&RedisData.GetQrCode==1) { + if (res?.data?.stat == "Scanned" && RedisData.GetQrCode == 1) { Bot.logger.mark(`[米哈游登录] ${Bot.logger.blue(JSON.stringify(res))}`) await this.e.reply("二维码已扫描,请确认登录", true) RedisData.GetQrCode++; @@ -49,7 +50,7 @@ export default class mysTopLogin { break } } - await utils.redisDel(this.e.user_id,'GetQrCode') + await utils.redisDel(this.e.user_id, 'GetQrCode') if (!res?.data?.payload?.raw) { await this.e.reply("验证超时", true) return false @@ -89,7 +90,7 @@ export default class mysTopLogin { this.e.reply('接口效验失败,请重新尝试~') return false } - let validate =vlData?.data?.geetest_seccode.replace("|jordan",'') + let validate = vlData?.data?.geetest_seccode.replace("|jordan", '') let aigis = res.aigis_data.session_id + ";" + Buffer.from(JSON.stringify({ geetest_challenge: vlData?.data?.geetest_challenge, geetest_seccode: validate + "|jordan", @@ -103,12 +104,12 @@ export default class mysTopLogin { } if (res.retcode == 0) { let cookies = `stoken=${res.data.token.token}&mid=${res.data.user_info.mid}` - let cookie_token =await this.user.getData("bbsGetCookie", { cookies }) + let cookie_token = await this.user.getData("bbsGetCookie", { cookies }) let ltoken = await this.user.getData('getLtoken', { cookies: `${cookies}` }, false) Bot.logger.mark(`[米哈游登录] ${Bot.logger.blue(JSON.stringify(cookie_token))}`) return { cookie: `ltoken=${ltoken?.data?.ltoken};ltuid=${res.data.user_info.aid};cookie_token=${cookie_token?.data?.cookie_token};`, - stoken: `${cookies.replace('&',';')};stuid=${res.data.user_info.aid};` + stoken: `${cookies.replace('&', ';')};stuid=${res.data.user_info.aid};` } } else { await this.e.reply(`错误:${JSON.stringify(res)}`, true) @@ -116,7 +117,7 @@ export default class mysTopLogin { } } async crack_geetest() { - let res =""; //await this.user.getData("microgg", this.aigis_captcha_data, false) + let res = ""; //await this.user.getData("microgg", this.aigis_captcha_data, false) Bot.logger.mark(`[米哈游登录] ${Bot.logger.blue(JSON.stringify(res))}`) await this.e.reply(`请完成验证:https://challenge.minigg.cn/manual/index.html?gt=${this.aigis_captcha_data.gt}&challenge=${this.aigis_captcha_data.challenge}`, true) for (let n = 1; n < 60; n++) { @@ -148,25 +149,64 @@ export default class mysTopLogin { return true; } - async GetCode() { + async GetCode({render}) { try { let msg = this.e.msg.replace(/,|,|\|/g, ' ').split(' ') - if (msg.length != 3) { + if (msg.length != 2) { this.e.reply(`格式参考:#原神充值 6(商品ID) 120065390(uid)\n 可通过【#商品列表】获取可操作商品`) return true; } let iswx = msg[0].includes('微信') ? 'weixin' : 'alipay' - if (msg[2].length != 9) { - this.e.reply('uid格式不对!') - return true; + // if (msg[2].length != 9) { + // this.e.reply('uid格式不对!') + // return true; + // } + let goods = (await this.goodsList())[msg[1]] + // let ckData=this.e.user.ckData + let device_id = utils.randomString(4) + let order = { + "account": "196576671", + "region": utils.getServer(this.e.uid), + "uid": this.e.uid, + "delivery_url": "", + "device": device_id, + "channel_id": 1, + "client_ip": "", + "client_type": 4, + "game": this.e.uid[0] * 1 > 5 ? 'hk4e_global' : "hk4e_cn", + "amount": goods.price, + "goods_num": 1, + "goods_id": goods?.goods_id, + "goods_title": goods?.goods_name + (Number(goods.goods_unit) > 0 ? "×" + goods.goods_unit : ""), + "price_tier": goods?.tier_id, + "currency": "CNY", + "pay_plat": iswx, } - let res = await this.user.getData('GetCode', { msg: this.e.msg.replace('#', '') }) + if (iswx != 'weixin') { + order["pay_type"] = iswx + order["pay_vendor"] = iswx + } + let res = await this.user.getData('createOrder', { order, headers: { "x-rpc-device_id": device_id } }) if (!res) return false; if (res?.code != 200 && res?.retcode != 0) { + this.e.reply('生成充值订单失败:' + res.message) return true } - this.e.reply([`uid:${res.data.uid},请使用${iswx == 'weixin' ? '微信' : "支付宝"}扫码支付:`, segment.image(res.data.base64.replace("data:image/png;base64,", "base64://")), `\n订单号:${res['data']['order_no']}\n 价格:${(res['data']['amount']) / 100}元`]) + //记录操作日志 + logger.mark(`当前操作用户:${this.e.user_id},操作uid:${this.e.uid},操作商品id:${goods?.goods_id},操作商品:${goods?.goods_name + (Number(goods.goods_unit) > 0 ? "×" + goods.goods_unit : "")}`) + logger.mark(`支付链接:${res['data']['encode_order']}\n订单号:${res['data']['order_no']}\n 价格:${(res['data']['amount']) / 100}元`) + let r= await Common.render(`pay/index`, { + url: res.data.encode_order, + data:res.data,uid:this.e.uid, + goods, + }, { + e:this.e, + render, + scale: 1.2, retMsgId: true + }) + return true } catch (error) { + console.log(error) this.e.reply('出问题了捏') } return true; @@ -174,8 +214,11 @@ export default class mysTopLogin { async goodsList() { let goods = await this.user.getData("goodsList") - if (!goods) return false; - return goods; + if (goods?.retcode != 0) { + this.e.reply(goods.message) + return false; + } + return goods?.data?.goods_list; } async checkOrder() { let msg, uid, order_no diff --git a/model/mys/mihoyoApi.js b/model/mys/mihoyoApi.js index 14bba0b..0e579e9 100644 --- a/model/mys/mihoyoApi.js +++ b/model/mys/mihoyoApi.js @@ -241,8 +241,9 @@ export default class miHoYoApi { authKey: { ///account/auth/api/genAuthKey url: `${this.apiMap.apiWeb}/binding/api/genAuthKey`, + // url:`https://gameapi-account.mihoyo.com/binding/api/genAuthKey`, body: { - 'auth_appid': 'webview_gacha', + 'auth_appid':'webview_gacha',//'apicdkey',// 'webview_gacha', 'game_biz': this.isOs ? 'hk4e_global' : 'hk4e_cn', 'game_uid': this.e.uid * 1, 'region': this.e.region, @@ -297,17 +298,30 @@ export default class miHoYoApi { url: `${mys.web_api}/auth/api/getCookieAccountInfoByGameToken`, query: `account_id=${data.uid}&game_token=${data.token}` }, - GetCode:{ - url:``, - query:`` + createOrder:{ + url:`https://hk4e-sdk.mihoyo.com/hk4e_cn/mdk/atropos/api/createOrder`, + body: { + // "special_info": "topup_center", + "order": data.order, + "sign": this.gen_sign(data.order) + }, + types:'web' }, goodsList:{ - url:``, - query:`` + url:`https://hk4e-sdk.mihoyo.com/hk4e_cn/mdk/shopwindow/shopwindow/fetchGoods`, + body:{ + "released_flag": true, + "game": "hk4e_cn", + "region": "cn_gf01", + "uid": "1", + "account": "1" + }, + types:'web' }, checkOrder:{ - url:``, - body:{} + url:`https://hk4e-sdk.mihoyo.com/hk4e_cn/mdk/atropos/api/checkOrder`, + query:`game=hk4e_cn®ion=${utils.getServer(data.uid)}&order_no=${data.order_no}&uid=${data.uid}`, + types:'web' } } if (!urlMap[type]) return false @@ -473,12 +487,46 @@ export default class miHoYoApi { Cookie: this.cookies, } break; + case "web": + header={ + "Accept": "application/json, text/plain, */*", + "Accept-Encoding": "gzip, deflate, br", + "Accept-Language": "zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6", + "Cache-Control": "no-cache", + "Connection": "keep-alive", + "Content-Type": "application/json;charset=UTF-8", + "Pragma": "no-cache", + "Referer": "https://webstatic.mihoyo.com/", + "sec-ch-ua": '"Not?A_Brand";v="8", "Chromium";v="108", "Microsoft Edge";v="108"', + "sec-ch-ua-mobile": "?0", + "sec-ch-ua-platform": '"Windows"', + "Sec-Fetch-Dest": "empty", + "Sec-Fetch-Mode": "cors", + "Sec-Fetch-Site": "same-site", + "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36 Edg/108.0.1462.54", + "x-rpc-client_type": "4", + "x-rpc-device_id": "3b401c79-e221-46b9-8ca5-2e072e367333", + "x-rpc-language": "zh-cn", + Cookie: this.cookie, + } + break default: header = {} break; } return header; } + gen_sign(data) { + if(!data) return '' + let d = Object.keys(data).sort() + let news = {} + for (const item of d) { + news[item] = data[item] + } + // let sign = this.HMCASHA256(Object.values(news).join('')) + let sign = crypto.createHmac('sha256','6bdc3982c25f3f3c38668a32d287d16b').update(Object.values(news).join('')).digest('hex') + return sign + } getStoken(userId) { let file = `${yamlDataUrl}/${userId}.yaml` try { diff --git a/model/user.js b/model/user.js index bdaf477..f87e464 100644 --- a/model/user.js +++ b/model/user.js @@ -126,15 +126,11 @@ export default class user { } message += `${item.nickname}-${item.game_uid}:今日已签到~\n`; } else { - let isgt = false let signMsg = ''; for (let i = 0; i < 2; i++) { //循环请求 await utils.sleepAsync(2000) res = await this.getData("sign", data, false) if (res?.data?.gt) { - if (!isgt) { - isgt = true; - } let validate = await this.geetest(res.data) if (validate) { let header = {} @@ -144,14 +140,14 @@ export default class user { data.headers = header res = await this.getData("sign", data, false) if (!res?.data?.gt) { - if (this.allSign && !isgt) { + if (this.allSign) { this.allSign[forum.name].sign++; } signMsg = `${item.nickname}-${item.game_uid}:验证码签到成功~\n` item.total_sign_day++; break; } else { - if (this.allSign && !isgt) { + if (this.allSign) { this.allSign[forum.name].error++; } item.is_sign = false; @@ -159,7 +155,7 @@ export default class user { `${item.nickname}-${item.game_uid}:签到出现验证码~\n请晚点后重试,或者手动上米游社签到\n`; } } else { - if (this.allSign && !isgt) { + if (this.allSign ) { this.allSign[forum.name].error++; } signMsg = `${item.nickname}-${item.game_uid}:验证码失败~\n` @@ -344,7 +340,7 @@ export default class user { if (res?.message && res?.retcode == 0) { Share++; } - message += `共读取帖子记录${20 * sumcount}\n浏览成功:${trueDetail}\n点赞成功:${Vote}\n分享成功:${Share}`; + message += `共读取帖子记录${20 * sumcount}\n浏览:${trueDetail} 点赞:${Vote} 分享:${Share}`; Bot.logger.mark(`\n用户${this.e.user_id}:\n${message}`) await utils.randomSleepAsync(3); } @@ -787,7 +783,7 @@ export default class user { if (res?.retcode != 0) { return false; } - console.log(res,this.e.sk) + // console.log(res,this.e.sk) let uids = [] for (let s of res.data.list) { let datalist = {}