UNPKG

@thu-info/lib

Version:

The JavaScript library that provides a program-friendly interface to Tsinghua web portal

1,057 lines (921 loc) 36.9 kB
import { countdown, getAssessmentForm, getAssessmentList, getClassroomList, getClassroomState, getUserInfo, getPhysicalExamResult, getReport, postAssessmentForm, // getBankPayment, getCalendar, getInvoiceList, getInvoicePDF, switchLang, naiveSendMail, getCalendarImageUrl, getSchoolCalendarYear, getGraduateIncome, getBankPaymentParellize, getMadModelToken, } from "./lib/basics"; import {forgetDevice, login, logout} from "./lib/core"; import {getDormScore, getElePayRecord, getEleRechargePayCode, getEleRemainder, resetDormPassword} from "./lib/dorm"; import { LibBookRecord, LibFuzzySearchResult, Library, LibraryFloor, LibrarySeat, LibrarySection, LibRoomBookRecord, LibRoomRes, SocketStatus, } from "./models/home/library"; import { bookLibraryRoom, bookLibrarySeat, cancelBooking, cancelLibraryRoomBooking, fuzzySearchLibraryId, getBookingRecords, getLibraryFloorList, getLibraryList, getLibraryRoomBookingInfoList, getLibraryRoomBookingRecord, getLibraryRoomBookingResourceList, getLibrarySeatList, getLibrarySectionList, getAccNo, cabLogin, toggleSocketState, updateLibraryRoomEmail, } from "./lib/library"; import { addNewsSubscription, addNewsToFavor, getFavorNewsList, getNewsChannelList, getNewsDetail, getNewsList, getNewsListBySubscription, getNewsSourceList, getNewsSubscriptionList, removeNewsFromFavor, removeNewsSubscription, searchNewsList, } from "./lib/news"; import {getSchedule} from "./lib/schedule"; import {Course} from "./models/home/report"; import {Form} from "./models/home/assessment"; import {NewsSlice, NewsSubscription, ChannelTag} from "./models/news/news"; import { getSportsCaptchaUrlMethod, getSportsReservationRecords, getSportsResources, makeSportsReservation, paySportsReservation, unsubscribeSportsReservation, updateSportsPhoneNumber, ValidReceiptTypes, } from "./lib/sports"; import { getCrTimetable, getCrCaptchaUrl, getCoursePlan, loginCr, searchCrRemaining, searchCrPrimaryOpen, searchCrCourses, getCrAvailableSemesters, selectCourse, Priority, deleteCourse, getSelectedCourses, changeCourseWill, searchCoursePriorityInformation, searchCoursePriorityMeta, getCrCurrentStage, getQueueInfo, cancelCoursePF, setCoursePF, } from "./lib/cr"; import {CrTimetable, SearchCoursePriorityQuery, SearchParams} from "./models/cr/cr"; import {BankPaymentByMonth, GraduateIncome} from "./models/home/bank"; import { getNamespaces, getPersonalProjects, getProjectBranches, getProjectDetail, getProjectFileBlob, getProjectTree, getRecentProjects, getStarredProjects, renderMarkdown, searchProjects, } from "./lib/gitlab"; import {CalendarData} from "./models/schedule/calendar"; import {bookDetail, downloadChapters, searchReservesLib} from "./lib/reserves-lib"; import {BookChapter} from "./models/home/reserves-lib"; import {Invoice} from "./models/home/invoice"; import {LoginError} from "./utils/error"; import {getDegreeProgramCompletion, getFullDegreeProgram} from "./lib/program"; import {Classroom, ClassroomStateResult} from "./models/home/classroom"; import { appStartupStat, appUsageStat, getFeedbackReplies, getLatestAnnounces, getLatestVersion, getPrivacyUrl, getWeChatGroupQRCodeContent, submitFeedback, } from "./lib/app"; import {MOCK_LATEST_VERSION} from "./mocks/app"; import { getNetworkBalance, getNetworkAccountInfo, getNetworkVerificationImageUrl, getOnlineDevices, loginNetwork, logoutNetwork, loginUsereg, } from "./lib/network"; import {getScoreByCourseId} from "./lib/thos"; import { canRechargeCampusCard, cardCancelLoss, cardChangeTransactionPassword, cardGetInfo, cardGetPhotoUrl, cardGetTransactions, cardLogin, cardModifyMaxTransactionAmount, cardRechargeFromBank, cardRechargeFromWechatAlipay, cardReportLoss, } from "./lib/card"; import {CardTransactionType} from "./models/card/transaction"; import {CardRechargeType} from "./models/card/recharge"; import { Device } from "./models/network/device"; import { SportsReservationRecord } from "./models/home/sports"; export class InfoHelper { public userId = ""; public password = ""; public fingerprint = ""; /** * Mock account and password. * * Due to various reasons, consumers of this library might hope to get * some fake data, without literally making a request to the school * website. * * We make this possible by creating an internal mocking account. The * default userId and password of this account are both "8888", while you * can change this behavior by modifying `helper.MOCK`. * * After you have logged in with the mocking account, almost every * operation will respond with a fake value. * * You can easily get whether the user is using a mocking account by * invoking `helper.mocked()`. */ public MOCK = "8888"; /** * We consider an account to be mocked if its userId and password are both "8888". */ public mocked = () => this.userId === this.MOCK && this.password === this.MOCK; /** * Returns whether the user is graduate. * * We detect a user's graduation status through the fifth digit (index 4) of his/her student ID. * * That is, we think a user is graduate iff the fifth digit of his/her student ID is 2 or 3. */ public graduate = () => this.userId.length > 4 ? (this.userId[4] === "2" || this.userId[4] === "3") : false; /** * Invoked before logging in. * * Override this value to customize. */ public clearCookieHandler = async () => { }; /** * Invoked when a login error occurs. * * Override this value to customize. */ public loginErrorHook: ((e: LoginError) => any) | undefined = undefined; /** * Invoked when 2FA method selection is required. * * Override this value to customize. */ public twoFactorMethodHook: ((hasWeChatBool: boolean, phone: string | null, hasTotp: boolean) => Promise<"wechat" | "mobile" | "totp" | undefined>) | undefined = undefined; /** * Invoked when 2FA is required. * * Override this value to customize. */ public twoFactorAuthHook: (() => Promise<string | undefined>) | undefined = undefined; /** * Invoked when 2FA over limit is detected. * * Override this value to customize. */ public twoFactorAuthLimitHook: (() => Promise<void>) | undefined = undefined; /** * Invoked when it has to be decided whether to trust the current fingerprint. * * Override this value to customize. */ public trustFingerprintHook: (() => Promise<boolean>) | undefined = undefined; /** * Invoked to get a trusted device name for the fingerprint. * * Override this value to customize. */ public trustFingerprintNameHook: (() => Promise<string>) = async () => "THU Info Lib"; /** * Login with userId and password. */ public login = async ( auth: { userId?: string; password?: string; }, ): Promise<void> => login(this, auth.userId ?? this.userId, auth.password ?? this.password); /** * Log out and clear fields `userId` and `password` of this `InfoHelper` instance */ public logout = async (): Promise<void> => logout(this); /** * THIS METHOD IS INTENDED FOR APP USE ONLY. */ public forgetDevice = async (): Promise<void> => forgetDevice(this); /** * THIS METHOD IS INTENDED FOR APP USE ONLY. * * ANY BREAKING CHANGES SHALL NOT BE DOCUMENTED. */ public appStartUp = async (platform: "ios" | "android", uuid: string, version?: string) => { if (this.userId === "") { return { bookingRecords: [], sportsReservationRecords: [], crTimetable: [], balance: 0, latestAnnounces: [], latestVersion: MOCK_LATEST_VERSION, }; } const latestAnnounces = await getLatestAnnounces(this, version); const latestVersion = await getLatestVersion(this, platform); let bookingRecords: LibBookRecord[] = []; const sportsReservationRecords: SportsReservationRecord[] = []; let balance: number = 0; let crTimetable: CrTimetable[] = []; try { bookingRecords = await getBookingRecords(this); balance = (await cardGetInfo(this)).balance; crTimetable = await getCrTimetable(this); } catch { // no-op } appStartupStat(this, uuid).catch(() => { }); return {bookingRecords, sportsReservationRecords, crTimetable, balance, latestAnnounces, latestVersion}; }; public appUsageStat = async (usage: number, uuid: string) => { await appUsageStat(this, usage, uuid); }; public getLatestAnnounces = async (version?: string) => getLatestAnnounces(this, version); public getLatestVersion = async (platform: "ios" | "android") => getLatestVersion(this, platform); public submitFeedback = async ( content: string, appversion: string, os: string, nickname: string, contact: string, phonemodel: string, ) => submitFeedback(this, content, appversion, os, nickname, contact, phonemodel); public getFeedbackReplies = async () => getFeedbackReplies(this); public getWeChatGroupQRCodeContent = async () => getWeChatGroupQRCodeContent(this); public getPrivacyUrl = () => getPrivacyUrl(this); /** * Switch the language. * * This will affect the language of data returned from some APIs. * * @param lang either "zh" or "en" */ public switchLang = async (lang: "zh" | "en"): Promise<void> => switchLang(this, lang); /** * Get the user's full name and email name (i.e. username for email * account) */ public getUserInfo = async () => getUserInfo(this); /** * A naive API that sends an email from the user's Tsinghua mail. * @param subject Subject of email * @param content Content of email * @param recipient Recipient of email. Sending an email to multiple * recipients is not supported yet. */ public naiveSendMail = async (subject: string, content: string, recipient: string) => naiveSendMail(this, subject, content, recipient); /** * Get the school report of the user. * * @param bx a boolean indicating whether to contain only required and * restricted courses (and omit elective courses) * @param newGPA a boolean indicating whether to adopt the new GPA policy * @param flag switch between first degree (1), second degree (2) and * minor courses (3), defaults to 1 * * Note that `bx` takes effect only if `flag` equals to `1` */ public getReport = ( bx: boolean, newGPA: boolean, flag = 1, ): Promise<Course[]> => getReport(this, bx, newGPA, flag); /** * Get the assessment list of teaching evaluation. * * @return An array of courses. Each course is represented with a * three-element tuple, referring to name of course, whether * the course has been evaluated and the url of its evaluation * form (which can then be passed into `getAssessmentForm`. */ public getAssessmentList = (): Promise<[string, boolean, string][]> => getAssessmentList(this); /** * Get the evaluation form of a course from its url. * @param url the corresponding form url to the course to evaluate */ public getAssessmentForm = (url: string): Promise<Form> => getAssessmentForm(this, url); /** * Submit the evaluation form. */ public postAssessmentForm = (form: Form): Promise<void> => postAssessmentForm(this, form); /** * Get the physical exam score of the user. * * @return Returns a [string, string][], where the first string refers to * the exam item, and the second refers to the exam score. */ public getPhysicalExamResult = (): Promise<[string, string][]> => getPhysicalExamResult(this); /** * Get all classroom buildings available for querying for classroom status. * * Note that you should use `searchName` from the returned struct for * future querying. */ public getClassroomList = (): Promise<Classroom[]> => getClassroomList(this); /** * Get the classroom state of specific classroom building and week number. * @param building a string representing the queried building * @param week a number representing the queried week number */ public getClassroomState = ( building: string, week: number, ): Promise<ClassroomStateResult> => getClassroomState(this, building, week); /** * Get the list of invoices. * * This API is paginated. * * @param page page number, starting from 1 */ public getInvoiceList = async (page: number): Promise<{ data: Invoice[]; count: number }> => getInvoiceList(this, page); /** * Get the invoice PDF in base64 format. */ public getInvoicePDF = async (uuid: string): Promise<string> => getInvoicePDF(this, uuid); /** * Get the bank payment records of the user. * @param foundation whether to get bank payment result by 基金会 or not * @param loadPartial whether to load only the recent three months */ public getBankPayment = async (foundation = false, loadPartial = false): Promise<BankPaymentByMonth[]> => getBankPaymentParellize(this, foundation, loadPartial); /** * Get the graduate income records of the user according to the date range * @param begin YYYYMMDD * @param end YYYYMMDD */ public getGraduateIncome = async ( begin: string, // YYYYMMDD end: string, // YYYYMMDD ): Promise<GraduateIncome[]> => getGraduateIncome(this, begin, end); /** * Get the school calendar data. */ public getCalendar = async (): Promise<CalendarData> => getCalendar(this); /** * Get the latest school calendar year (from THUInfo backend). * `2024` means that 2024-2025 school year is available. */ public getCalendarYear = async (): Promise<number> => getSchoolCalendarYear(); /** * Get the school calendar image url */ public getCalendarImageUrl = async (year: number, semester: "spring" | "autumn", lang: "zh" | "en") => getCalendarImageUrl(this, year, semester, lang); /** * Get the current countdown notifications from INFO. */ public getCountdown = async (): Promise<string[]> => countdown(this); public getMadModelToken = async (): Promise<string> => getMadModelToken(this); /** * Get the dorm score image, in base64 format. */ public getDormScore = async (): Promise<string> => getDormScore(this); /** * Make an electricity recharge payment order, and get the pay-code of the * order. * * If you want to use the pay-code on mobile devices, the url link to the * Alipay payment page will be * `"alipayqr://platformapi/startapp?saId=10000007&qrcode=https%3A%2F%2Fqr.alipay.com%2F" + payCode` * * You can also call `genAlipayUrl(payCode)` in `dist/utils/alipay` to get * the Alipay url. * * @param money a number representing the amount of money to be paid * <b>(in yuan, must be integer)</b> */ public getEleRechargePayCode = async (money: number): Promise<string> => { if (!await canRechargeCampusCard(this)) { throw new Error("暂不支持宿舍电费充值,请升级应用程序。"); } return getEleRechargePayCode(this, money); }; /** * Get the recent ele-recharge records. * * @return Returns `[string, string, string, string, string, string][]`, * where the six strings represent name, id, time, channel, value * and status respectively. */ public getElePayRecord = async (): Promise<[string, string, string, string, string, string][]> => getElePayRecord(this); /** * Get the current remainder of electricity. * * @return Returns a number. The return value can be NaN when the remainder * info cannot be parsed. */ public getEleRemainder = async (): Promise<{ remainder: number; updateTime: string }> => getEleRemainder(this); /** * Reset dorm password. * * This method works on the basis that myhome.tsinghua.edu.cn can be logged * in with INFO account, and the dorm password can therefore be reset, * without the need of a original password. * * @param newPassword The new dorm password */ public resetDormPassword = async (newPassword: string): Promise<void> => resetDormPassword(this, newPassword); public getLibraryList = async (): Promise<Library[]> => getLibraryList(this); public getLibrarySectionList = async ( libraryFloor: LibraryFloor, dateChoice: 0 | 1, // 0 for today and 1 for tomorrow ): Promise<LibrarySection[]> => getLibrarySectionList(this, libraryFloor, dateChoice); public getLibraryFloorList = async ( library: Library, dateChoice: 0 | 1, // 0 for today and 1 for tomorrow ): Promise<LibraryFloor[]> => getLibraryFloorList(this, library, dateChoice); public getLibrarySeatList = async ( librarySection: LibrarySection, dateChoice: 0 | 1, // 0 for today and 1 for tomorrow ): Promise<LibrarySeat[]> => getLibrarySeatList(this, librarySection, dateChoice); public toggleSocketState = async ( seatId: number, target: SocketStatus, ): Promise<void> => toggleSocketState(this, seatId, target); /** * Use this API to book library seats. */ public bookLibrarySeat = async ( librarySeat: LibrarySeat, section: LibrarySection, dateChoice: 0 | 1, // 0 for today and 1 for tomorrow ): Promise<{ status: number; msg: string }> => bookLibrarySeat(this, librarySeat, section, dateChoice); /** * Use this API to get booking records. */ public getBookingRecords = async (): Promise<LibBookRecord[]> => getBookingRecords(this); /** * Use this API to cancel booking. * @param id the `id` from `LibBookRecord` */ public cancelBooking = async (id: string): Promise<void> => cancelBooking(this, id); /** * DEPRECATED. */ public getLibraryRoomBookingCaptchaUrl = () => Promise.resolve(""); /** * Use this API to get the account number of current user. * * The account number is used to book rooms. */ public getLibraryRoomAccNo = () => getAccNo(); /** * Login cab.hs.lib.tsinghua.edu.cn */ public loginLibraryRoomBooking = async () => cabLogin(this); /** * Gets all available room information */ public getLibraryRoomBookingInfoList = async () => getLibraryRoomBookingInfoList(this); /** * Gets all available room resources * @param date yyyyMMdd * @param kindId * @return Returns a list of all available room resources of a specific * date, along with when and for whom each room is reserved. */ public getLibraryRoomBookingResourceList = async ( date: string, // yyyyMMdd kindId: number, ): Promise<LibRoomRes[]> => getLibraryRoomBookingResourceList(this, date, kindId); /** * Passes a student's name as keyword and returns the student's ID. * * FUZZY SEARCH IS NO LONGER SUPPORTED. Method name remains unchanged only * for compatability reasons. * * @param keyword a string that serves as the search keyword */ public fuzzySearchLibraryId = async ( keyword: string ): Promise<LibFuzzySearchResult[]> => fuzzySearchLibraryId(this, keyword); /** * Performs a booking request of a library room. * * @param roomRes a `LibRoomRes` object referring to the room that is requested for booking * @param start the beginning time of booking, <b>in format `yyyy-MM-dd HH:mm:SS` where `mm` should be a multiple of 5 and `SS` should be `00`</b> * @param end the ending time of booking, <b>in format `yyyy-MM-dd HH:mm:SS` where `mm` should be a multiple of 5 and `SS` should be `00`</b> * @param memberList a list of strings */ public bookLibraryRoom = async ( roomRes: LibRoomRes, start: string, // yyyy-MM-dd HH:mm end: string, // yyyy-MM-dd HH:mm memberList: number[], // student id's, empty for single user ) => bookLibraryRoom(this, roomRes, start, end, memberList); /** * Returns all active booking records. */ public getLibraryRoomBookingRecord = async (): Promise<LibRoomBookRecord[]> => getLibraryRoomBookingRecord(this); /** * Cancels a specific library booking record. * @param uuid `uuid` of `LibRoomBookRecord` */ public cancelLibraryRoomBooking = async (uuid: string) => cancelLibraryRoomBooking(this, uuid); /** * Updates email for library room booking system. * @param email email */ public updateLibraryRoomEmail = async (email: string) => updateLibraryRoomEmail(this, email); /** * Get the news list of all channels or a specific channel. * * This API is paginated. */ public getNewsList = async ( page: number, length: number, channel?: ChannelTag ): Promise<NewsSlice[]> => getNewsList(this, page, length, channel); /** * Search the news list with a keyword. * * This API is paginated. */ public searchNewsList = async ( page: number, key: string, channel?: ChannelTag ): Promise<NewsSlice[]> => searchNewsList(this, page, key, channel, true); /** * Get all news subscription items. */ public getNewsSubscriptionList = async (): Promise<NewsSubscription[]> => getNewsSubscriptionList(this); /** * Get all available news sources for subscription. */ public getNewsSourceList = async (): Promise<{ sourceId: string, sourceName: string }[]> => getNewsSourceList(this); /** * Get all available news channels for subscription. * @param needEnglish */ public getNewsChannelList = async (needEnglish: boolean): Promise<{ id: ChannelTag, title: string }[]> => getNewsChannelList(this, needEnglish); /** * if channelId and sourceId is null or undefined at the same time, this function will terminate and return false. * @param channelId channel id * @param sourceId source id * @param keyword news keyword * @returns */ public addNewsSubscription = async (channelId?: ChannelTag, sourceId?: string, keyword?: string): Promise<boolean> => addNewsSubscription(this, channelId, sourceId, keyword); /** * Remove a news subscription. * @param subscriptionId */ public removeNewsSubscription = async (subscriptionId: string): Promise<boolean> => removeNewsSubscription(this, subscriptionId); /** * Gets the news list by a specific subscription. * * This API is paginated. */ public getNewsListBySubscription = async (page = 1, subscriptionId?: string) => getNewsListBySubscription(this, page, subscriptionId ?? ""); /** * Get the detailed news with the url provided. * @param url the url of the queried news * @return Returns `[string, string, string][]`, where the three `string`s * represent title, content and abstract respectively. */ public getNewsDetail = async ( url: string, ): Promise<[string, string, string]> => getNewsDetail(this, url); /** * Adds a specific piece of news to fav list. * @param news */ public addNewsToFavor = async (news: NewsSlice): Promise<boolean> => addNewsToFavor(this, news); /** * Remove a specific piece of news from fav list. * @param news */ public removeNewsFromFavor = async (news: NewsSlice): Promise<boolean> => removeNewsFromFavor(this, news); /** * if the page is out of range, the NewsSlice will be a 0 length array. * @param page page of favor list * @returns [array of NewsSlice,total pages] */ public getFavorNewsList = async (page: number): Promise<[NewsSlice[], number]> => getFavorNewsList(this, page); /** * Get the schedules of the user. * @param nextSemesterIndex if provided, specifies a semester from the `nextSemesterList` * @return Returns `Schedule[]`, containing all the schedules(including * exams) of the user. */ public getSchedule = async (nextSemesterIndex?: number) => getSchedule(this, nextSemesterIndex); /** * Gets the timetable for course registration. */ public getCrTimetable = async () => getCrTimetable(this); /** * Gets the login captcha url for the course registration system. */ public getCrCaptchaUrl = async () => getCrCaptchaUrl(this); /** * Log in to the course registration system with the captcha. */ public loginCr = async () => loginCr(this); /** * Get all semesters available for course registration. */ public getCrAvailableSemesters = async () => getCrAvailableSemesters(this); /** * Get the course plan of a given semester. * @param semester */ public getCrCoursePlan = async (semester: string) => getCoursePlan(this, semester); /** * Search courses for registration remaining data * @param params */ public searchCrRemaining = async (params: SearchParams) => searchCrRemaining(this, params); /** * Search primary courses * @param params */ public searchCrPrimaryOpen = async (params: SearchParams) => searchCrPrimaryOpen(this, params); /** * Search courses for registration * @param params */ public searchCrCourses = async (params: SearchParams) => searchCrCourses(this, params); /** * Select a course. * @param semesterId semester id * @param priority "bx" | "xx" | "rx" | "ty" | "cx" * @param courseId course id * @param courseSeq course seq number * @param will 1 | 2 | 3 */ public selectCourse = async ( semesterId: string, priority: Priority, courseId: string, courseSeq: string, will: 1 | 2 | 3, ) => selectCourse(this, semesterId, priority, courseId, courseSeq, will); /** * Delete a course * @param semesterId * @param courseId * @param courseSeq */ public deleteCourse = async ( semesterId: string, courseId: string, courseSeq: string, ) => deleteCourse(this, semesterId, courseId, courseSeq); /** * Get all selected courses * @param semesterId */ public getSelectedCourses = async (semesterId: string) => getSelectedCourses(this, semesterId); /** * Change a will of a course * @param semesterId * @param courseId * @param courseSeq * @param will */ public changeCourseWill = async ( semesterId: string, courseId: string, courseSeq: string, will: 1 | 2 | 3, ) => changeCourseWill(this, semesterId, courseId, courseSeq, will); /** * Get current course registration stage * @param semesterId */ public getCrCurrentStage = async (semesterId: string) => getCrCurrentStage(this, semesterId); /** * Gets when is the latest course registration queue info released, and * when is the next time for release. * @param semesterId */ public searchCoursePriorityMeta = async (semesterId: string) => searchCoursePriorityMeta(this, semesterId); /** * Gets the course registration data for remaining position * @param semesterId * @param query */ public searchCoursePriorityInformation = async ( semesterId: string, query: SearchCoursePriorityQuery, ) => searchCoursePriorityInformation(this, semesterId, query); /** * Gets course registration queue info * @param semesterId */ public getQueueInfo = async (semesterId: string) => getQueueInfo(this, semesterId); /** * Cancel PF registration for a course * @param semesterId * @param courseId */ public cancelCoursePF = async (semesterId: string, courseId: string) => cancelCoursePF(this, semesterId, courseId); /** * Set PF mark for a course * @param semesterId * @param courseId */ public setCoursePF = async (semesterId: string, courseId: string) => setCoursePF(this, semesterId, courseId); /** * Gets all available sports resources. * * `gymId` and `itemId` can be found in `sportsIdInfoList` from `dist/lib/sports`. * * @param gymId * @param itemId * @param date yyyy-MM-dd */ public getSportsResources = async ( gymId: string, itemId: string, date: string, // yyyy-MM-dd ) => getSportsResources(this, gymId, itemId, date); /** * Saves the phone number in the sports reservation system * @param phone */ public updateSportsPhoneNumber = async (phone: string) => updateSportsPhoneNumber(this, phone); /** * Gets the url to the captcha for sports reservation */ public getSportsCaptchaUrl = () => getSportsCaptchaUrlMethod(); /** * Makes a sports reservation and gets the alipay pay-code if payment is * required. * * If you want to use the pay-code on mobile devices, the url link to the * Alipay payment page will be * `"alipayqr://platformapi/startapp?saId=10000007&qrcode=https%3A%2F%2Fqr.alipay.com%2F" + payCode` * * You can also call `genAlipayUrl(payCode)` in `dist/utils/alipay` to get * the Alipay url. * * @param totalCost a number indicating the total cost of the reservation * @param phone a string representing the user's phone number * @param receiptTitle a string representing the title of the receipt, or `undefined` if a receipt is not needed * @param gymId a string representing the ID of the gym * @param itemId a string representing the ID of the item * @param date a string in the format of `yyyy-MM-dd` * @param captcha a string representing the captcha * @param resHashId a string representing the hash of the resource * @param skipPayment whether to skip payment (and pay later) * @return Returns a string representing the alipay payment code if payment is required, or `undefined` if no payment is needed. */ public makeSportsReservation = async ( totalCost: number, phone: string, receiptTitle: ValidReceiptTypes | undefined, gymId: string, itemId: string, date: string, // yyyy-MM-dd captcha: string, resHashId: string, skipPayment = false, ) => makeSportsReservation(this, totalCost, phone, receiptTitle, gymId, itemId, date, captcha, resHashId, skipPayment); /** * Gets all active sports reservation records. */ public getSportsReservationRecords = async () => getSportsReservationRecords(this); /** * Make sports reservation payment with a payId. */ public paySportsReservation = async ( payId: string, receiptTitle: ValidReceiptTypes | undefined, ): Promise<string> => paySportsReservation(this, payId, receiptTitle); /** * Cancel a sports reservation <b>if payment has not been made</b> * @param bookId a string representing the ID of the reservation */ public unsubscribeSportsReservation = async (bookId: string) => unsubscribeSportsReservation(this, bookId); public getGitNamespaces = async (page: number) => getNamespaces(this, page); public getGitRecentProjects = async (page: number) => getRecentProjects(this, page); public getGitOwnedProjects = async (name: string, page: number) => getPersonalProjects(this, name, page); public searchGitProjects = async (search: string, page: number) => searchProjects(this, search, page); public getGitStarredProjects = async (page: number) => getStarredProjects(this, page); public getGitProjectDetail = async (id: number) => getProjectDetail(this, id); public getGitProjectTree = async ( id: number, path: string, ref: string, page: number, ) => getProjectTree(this, id, path, ref, page); public getGitProjectBranches = async (id: number) => getProjectBranches(this, id); public getGitProjectFileBlob = async (id: number, sha: string) => getProjectFileBlob(this, id, sha); public renderGitMarkdown = async (text: string) => renderMarkdown(this, text); public searchReservesLib = async (bookName: string, page?: number) => searchReservesLib(this, bookName, page); public getReservesLibBookDetail = async (bookId: string) => bookDetail(this, bookId); public reservesLibDownloadChapters = async (chapters: BookChapter[], setCompletion?: (total: number, complete: number) => void) => downloadChapters(chapters, setCompletion); public getDegreeProgramCompletion = async () => getDegreeProgramCompletion(this); public getFullDegreeProgram = async (degreeId?: number, skippedSet?: string[]) => getFullDegreeProgram(this, degreeId, skippedSet); public getNetworkVerificationImageUrl = async () => getNetworkVerificationImageUrl(this); public loginUsereg = async (code: string) => loginUsereg(this, code); public getOnlineDevices = async () => getOnlineDevices(this); public getNetworkBalance = async () => getNetworkBalance(this); public getNetworkAccountInfo = async () => getNetworkAccountInfo(this); public logoutNetworkDevice = async (device: Device) => logoutNetwork(device); public loginNetworkDevice = async (ip: string, internet: boolean) => loginNetwork(this, ip, internet); public getScoreByCourseId = async (courseId: string) => getScoreByCourseId(this, courseId); public loginCampusCard = async () => cardLogin(this); public getCampusCardInfo = async () => cardGetInfo(this); public getCampusCardPhotoUrl = async () => cardGetPhotoUrl(); /** * Get the campus card transactions. * @param start YYYY-MM-DD * @param end YYYY-MM-DD * @param type -1 for all (1-3), 1 for consumption, 2 for recharge, 3 for subsidy, 0 for ALL (?) */ public getCampusCardTransactions = async (start: string, end: string, type: CardTransactionType) => cardGetTransactions(this, start, end, type); public changeCampusCardPassword = async (oldPassword: string, newPassword: string) => cardChangeTransactionPassword(this, oldPassword, newPassword); public modifyCampusCardMaxTransactionAmount = async (transactionPassword: string, maxDailyAmount: number, maxOneTimeAmount: number) => cardModifyMaxTransactionAmount(this, transactionPassword, maxDailyAmount, maxOneTimeAmount); public reportCampusCardLoss = async (transactionPassword: string) => cardReportLoss(this, transactionPassword); public cancelCampusCardLoss = async (transactionPassword: string) => cardCancelLoss(this, transactionPassword); /** * Recharge the campus card. * @param amount in yuan * @param transactionPassword * @param type 0 for Bank Card, 1 for Alipay, 2 for Wechat Pay * @return Uri to request to complete the payment process, undefined for Bank */ public rechargeCampusCard = async (amount: number, transactionPassword: string, type: CardRechargeType) => { if (!await canRechargeCampusCard(this)) { throw new Error("暂不支持校园卡充值,请升级应用程序。"); } if (type === CardRechargeType.Bank) { return cardRechargeFromBank(this, transactionPassword, amount); } return cardRechargeFromWechatAlipay(this, amount, type === CardRechargeType.Alipay); }; }