{
  "openapi": "3.1.0",
  "info": {
    "title": "XJIT 平台统一接口",
    "version": "0.1.0",
    "description": "统一封装学校 CAS、教务、新卡片等系统。先通过 /api/v1/auth/login 或 /api/v1/auth/wechat/* 获取 accessToken，再用 POST /api/v1/run 调业务功能。"
  },
  "servers": [
    {
      "url": "/"
    }
  ],
  "paths": {
    "/health": {
      "get": {
        "summary": "健康检查",
        "responses": {
          "200": {
            "description": "服务正常"
          }
        }
      }
    },
    "/api/v1/features": {
      "get": {
        "summary": "功能名列表",
        "responses": {
          "200": {
            "description": "可用功能名",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "features": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    }
                  }
                },
                "example": {
                  "features": [
                    "newcard.campus_code.qrcode",
                    "newcard.recharge.config",
                    "newcard.recharge.create_order",
                    "newcard.electricity.account",
                    "newcard.electricity.recharge.config",
                    "newcard.electricity.recharge.pay",
                    "jw.schedule",
                    "jw.profile",
                    "jw.grades",
                    "jw.exams",
                    "jw.training",
                    "newcard.balance",
                    "newcard.transactions"
                  ]
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/features/detail": {
      "get": {
        "summary": "功能详情",
        "parameters": [
          {
            "name": "feature",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            },
            "description": "功能名；不传返回全部功能详情"
          }
        ],
        "responses": {
          "200": {
            "description": "功能详情 JSON"
          }
        }
      }
    },
    "/api/v1/openapi.json": {
      "get": {
        "summary": "OpenAPI 文档",
        "responses": {
          "200": {
            "description": "OpenAPI 3.1 JSON"
          }
        }
      }
    },
    "/api/v1/auth/login": {
      "post": {
        "summary": "账号密码登录",
        "description": "使用 CAS 账号密码登录一次，服务端返回有效期约 30 天的 API accessToken。账号密码登录产生的 session 会在学校 idToken 过期时自动重新登录。",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/LoginRequest"
              },
              "example": {
                "username": "学号",
                "password": "CAS密码"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "登录成功",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AuthSessionResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/auth/session": {
      "get": {
        "summary": "查询当前登录态",
        "description": "请求头传 Authorization: Bearer <accessToken>。",
        "security": [
          {
            "ApiBearerAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "登录态信息"
          }
        }
      }
    },
    "/api/v1/auth/prewarm": {
      "get": {
        "summary": "查询登录预热状态",
        "description": "登录成功后服务端会后台并行预热 newcard、PC 教务和移动教务；该接口返回每个系统的预热状态。",
        "security": [
          {
            "ApiBearerAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "预热状态",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AuthPrewarmResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/auth/refresh": {
      "post": {
        "summary": "刷新 API accessToken",
        "description": "轮换 API accessToken，并把 API session 有效期顺延约 30 天。账号密码登录产生的 session 会在学校 idToken 过期时自动重新登录。",
        "security": [
          {
            "ApiBearerAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "刷新成功",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AuthSessionResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/auth/logout": {
      "post": {
        "summary": "退出登录",
        "description": "撤销当前 API accessToken。",
        "security": [
          {
            "ApiBearerAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "已退出"
          }
        }
      }
    },
    "/api/v1/auth/wechat/start": {
      "post": {
        "summary": "发起微信扫码登录",
        "description": "创建一次微信联合登录会话，返回 CAS openweixin 授权入口。CAS service 使用学校已登记的 superapp.xjit.edu.cn；App/WebView 拦截回跳 URL 里的 ticket 后调用 /api/v1/auth/wechat/complete。",
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/WechatStartRequest"
              },
              "example": {
                "apiBaseUrl": "https://api.example.com"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "登录会话已创建",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WechatAuthResponse"
                },
                "example": {
                  "ok": true,
                  "data": {
                    "state": "随机状态",
                    "status": "pending",
                    "authUrl": "https://cas.xjit.edu.cn/cas/federatedRedirect?...",
                    "serviceUrl": "https://superapp.xjit.edu.cn/pages/tab/index/index?xjitApiState=随机状态",
                    "statusUrl": "https://api.example.com/api/v1/auth/wechat/status?state=随机状态",
                    "completeUrl": "https://api.example.com/api/v1/auth/wechat/complete",
                    "expiresInSeconds": 600
                  }
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/auth/wechat/status": {
      "get": {
        "summary": "查询微信扫码登录状态",
        "parameters": [
          {
            "name": "state",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "登录状态；status=success 时返回 accessToken",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WechatAuthResponse"
                },
                "example": {
                  "ok": true,
                  "data": {
                    "state": "随机状态",
                    "status": "success",
                    "tokenType": "Bearer",
                    "accessToken": "API accessToken",
                    "expiresInSeconds": 534
                  }
                }
              }
            }
          }
        }
      },
      "post": {
        "summary": "查询微信扫码登录状态",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "state"
                ],
                "properties": {
                  "state": {
                    "type": "string"
                  }
                }
              },
              "example": {
                "state": "随机状态"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "登录状态；status=success 时返回 accessToken"
          }
        }
      }
    },
    "/api/v1/auth/wechat/complete": {
      "post": {
        "summary": "完成微信扫码登录",
        "description": "App/WebView 从 superapp 回跳 URL 中取 ticket，或直接提交完整 redirectUrl；服务端从 ticket 解出学校 idToken 并创建 API accessToken。",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/WechatCompleteRequest"
              },
              "example": {
                "state": "随机状态",
                "redirectUrl": "https://superapp.xjit.edu.cn/pages/tab/index/index?xjitApiState=随机状态&ticket=..."
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "登录完成；返回 accessToken",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WechatAuthResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/auth/wechat/callback": {
      "get": {
        "summary": "微信/CAS 登录回调",
        "description": "仅保留给已被 CAS 白名单允许的部署域名使用。普通第三方域名和 127.0.0.1 会被 CAS 拒绝；App 推荐使用 /api/v1/auth/wechat/complete。",
        "parameters": [
          {
            "name": "state",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "ticket",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "回调处理成功"
          }
        }
      }
    },
    "/api/v1/run": {
      "post": {
        "summary": "运行功能",
        "description": "统一业务入口。请求头传 Authorization: Bearer <accessToken>，body 只传 feature 和 params。",
        "security": [
          {
            "ApiBearerAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/RunRequest"
              },
              "examples": {
                "newcard.campus_code.qrcode": {
                  "summary": "校园付款码",
                  "value": {
                    "feature": "newcard.campus_code.qrcode",
                    "params": {}
                  }
                },
                "newcard.recharge.config": {
                  "summary": "一卡通充值配置",
                  "value": {
                    "feature": "newcard.recharge.config",
                    "params": {}
                  }
                },
                "newcard.recharge.create_order": {
                  "summary": "一卡通充值下单",
                  "value": {
                    "feature": "newcard.recharge.create_order",
                    "params": {
                      "amount": "50",
                      "payCode": "01",
                      "tradeType": "WAP"
                    }
                  }
                },
                "newcard.electricity.account": {
                  "summary": "宿舍电费/剩余电量查询",
                  "value": {
                    "feature": "newcard.electricity.account",
                    "params": {
                      "roomQuery": "9#312"
                    }
                  }
                },
                "newcard.electricity.recharge.config": {
                  "summary": "宿舍电费充值配置",
                  "value": {
                    "feature": "newcard.electricity.recharge.config",
                    "params": {
                      "roomQuery": "9#312"
                    }
                  }
                },
                "newcard.electricity.recharge.pay": {
                  "summary": "宿舍电费充值支付",
                  "value": {
                    "feature": "newcard.electricity.recharge.pay",
                    "params": {
                      "roomQuery": "9#312",
                      "amount": "30",
                      "payCode": "06",
                      "paymentPassword": "一卡通支付密码"
                    }
                  }
                },
                "jw.schedule": {
                  "summary": "教务课表查询",
                  "value": {
                    "feature": "jw.schedule",
                    "params": {}
                  }
                },
                "jw.profile": {
                  "summary": "教务个人信息",
                  "value": {
                    "feature": "jw.profile",
                    "params": {}
                  }
                },
                "jw.grades": {
                  "summary": "教务成绩/学分绩点查询",
                  "value": {
                    "feature": "jw.grades",
                    "params": {}
                  }
                },
                "jw.exams": {
                  "summary": "教务考试安排",
                  "value": {
                    "feature": "jw.exams",
                    "params": {}
                  }
                },
                "jw.training": {
                  "summary": "教务培养/毕业完成情况",
                  "value": {
                    "feature": "jw.training",
                    "params": {}
                  }
                },
                "newcard.balance": {
                  "summary": "校园卡余额",
                  "value": {
                    "feature": "newcard.balance",
                    "params": {}
                  }
                },
                "newcard.transactions": {
                  "summary": "校园卡流水",
                  "value": {
                    "feature": "newcard.transactions",
                    "params": {
                      "pageSize": 20
                    }
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "调用成功",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RunResponse"
                },
                "examples": {
                  "newcard.campus_code.qrcode": {
                    "summary": "校园付款码",
                    "value": {
                      "ok": true,
                      "data": {
                        "mode": "online",
                        "qrcode": "付款码字符串，App 用它生成二维码",
                        "qrcodeType": "",
                        "expiresInSeconds": 30,
                        "balance": "0.00",
                        "idSerial": "学号",
                        "userName": "姓名",
                        "displayInfo": true,
                        "displayBalance": true
                      }
                    }
                  },
                  "newcard.recharge.config": {
                    "summary": "一卡通充值配置",
                    "value": {
                      "ok": true,
                      "data": {
                        "balance": "118.00",
                        "idSerial": "学号",
                        "username": "姓名",
                        "amountOptions": [
                          {
                            "id": "配置编号",
                            "amount": "50",
                            "name": "50元"
                          },
                          {
                            "id": "配置编号",
                            "amount": "100",
                            "name": "100元"
                          }
                        ],
                        "payMethods": [
                          {
                            "code": "01",
                            "tradeType": "WAP",
                            "name": "支付宝",
                            "h5": true,
                            "successToHome": false,
                            "signBind": null
                          },
                          {
                            "code": "02",
                            "tradeType": "WAP",
                            "name": "微信",
                            "h5": true,
                            "successToHome": false,
                            "signBind": null
                          }
                        ],
                        "canPayOther": true,
                        "hostApp": true,
                        "daLianPayEnable": true,
                        "wapPayEnable": false
                      }
                    }
                  },
                  "newcard.recharge.create_order": {
                    "summary": "一卡通充值下单",
                    "value": {
                      "ok": true,
                      "data": {
                        "amount": "50",
                        "payMethod": {
                          "code": "01",
                          "tradeType": "WAP",
                          "name": "支付宝"
                        },
                        "partnerJourno": "学校支付订单号",
                        "payResult": {
                          "type": "html_post",
                          "payCode": "01",
                          "partnerJourno": "学校支付订单号",
                          "h5Url": null,
                          "htmlPost": "<form>支付表单 HTML</form>",
                          "wechatJsapi": null
                        }
                      }
                    }
                  },
                  "newcard.electricity.account": {
                    "summary": "宿舍电费/剩余电量查询",
                    "value": {
                      "ok": true,
                      "data": {
                        "remainingElectricity": {
                          "value": "28.15",
                          "unit": "度"
                        },
                        "room": {
                          "query": "9#312",
                          "buildingName": "9号宿舍楼",
                          "levelName": "3层",
                          "roomName": "312房间"
                        }
                      }
                    }
                  },
                  "newcard.electricity.recharge.config": {
                    "summary": "宿舍电费充值配置",
                    "value": {
                      "ok": true,
                      "data": {
                        "room": {
                          "query": "9#312",
                          "buildingName": "9号宿舍楼",
                          "levelName": "3层",
                          "roomName": "312房间"
                        },
                        "account": {
                          "utilityAccount": "电费账号",
                          "utilityUsername": "户名",
                          "utilityStatusName": "正常",
                          "accStatusName": "正常"
                        },
                        "remainingElectricity": {
                          "value": "3.27",
                          "unit": "度"
                        },
                        "cardBalance": {
                          "value": "135.66",
                          "unit": "元"
                        },
                        "price": {
                          "value": "0.39",
                          "unit": "元/度"
                        },
                        "amountOptions": [
                          {
                            "id": "1",
                            "amount": "30",
                            "name": "30元"
                          },
                          {
                            "id": "2",
                            "amount": "50",
                            "name": "50元"
                          },
                          {
                            "id": "3",
                            "amount": "60",
                            "name": "60元"
                          }
                        ],
                        "payMethods": [
                          {
                            "code": "06",
                            "tradeType": null,
                            "name": "余额支付",
                            "h5": false,
                            "successToHome": false,
                            "signBind": null
                          }
                        ],
                        "needPaymentPassword": true,
                        "canPayOther": false,
                        "confirm": true,
                        "daLianPayEnable": false,
                        "hostApp": true,
                        "amtInputDisabled": false,
                        "tip": ""
                      }
                    }
                  },
                  "newcard.electricity.recharge.pay": {
                    "summary": "宿舍电费充值支付",
                    "value": {
                      "ok": true,
                      "data": {
                        "amount": "30",
                        "room": {
                          "query": "9#312",
                          "buildingName": "9号宿舍楼",
                          "levelName": "3层",
                          "roomName": "312房间"
                        },
                        "account": {
                          "utilityAccount": "电费账号",
                          "utilityUsername": "户名",
                          "utilityStatusName": "正常",
                          "accStatusName": "正常"
                        },
                        "payMethod": {
                          "code": "06",
                          "tradeType": null,
                          "name": "余额支付"
                        },
                        "partnerJourno": null,
                        "payResult": {
                          "type": "balance_payment",
                          "payCode": "06",
                          "partnerJourno": null
                        }
                      }
                    }
                  },
                  "jw.schedule": {
                    "summary": "教务课表查询",
                    "value": {
                      "ok": true,
                      "data": {
                        "term": "当前学期",
                        "courses": [
                          {
                            "day": "星期一",
                            "slot": "第一大节",
                            "title": "课程名",
                            "teacher": "教师",
                            "weeks": "1-16周",
                            "sections": "1-2节",
                            "location": "教室"
                          }
                        ]
                      }
                    }
                  },
                  "jw.profile": {
                    "summary": "教务个人信息",
                    "value": {
                      "ok": true,
                      "data": {
                        "studentId": "学号",
                        "name": "姓名",
                        "college": "学院",
                        "major": "专业",
                        "className": "班级",
                        "grade": "年级",
                        "gender": "性别"
                      }
                    }
                  },
                  "jw.grades": {
                    "summary": "教务成绩/学分绩点查询",
                    "value": {
                      "ok": true,
                      "data": {
                        "mode": "best_by_course",
                        "summary": {
                          "courseCount": 42,
                          "totalCredits": 91.75,
                          "gpaCredits": 91.75,
                          "weightedGradePoint": 2.25,
                          "failedCourseCount": 3,
                          "failedCredits": 13
                        },
                        "rawSummary": {
                          "courseCount": 48,
                          "totalCredits": 112,
                          "gpaCredits": 112,
                          "weightedGradePoint": 1.85,
                          "failedCourseCount": 9,
                          "failedCredits": 33.25
                        },
                        "terms": [
                          {
                            "term": "2025-2026-2",
                            "courseCount": 8,
                            "totalCredits": 18,
                            "gpaCredits": 18,
                            "weightedGradePoint": 3.12,
                            "failedCourseCount": 0,
                            "failedCredits": 0
                          }
                        ],
                        "normalGrades": [
                          {
                            "term": "2025-2026-2",
                            "courseCode": "课程编号",
                            "courseName": "课程名称",
                            "score": "成绩",
                            "credit": "学分",
                            "gradePoint": "绩点",
                            "examNature": "正常考试"
                          }
                        ],
                        "makeupGrades": [
                          {
                            "term": "2023-2024-1",
                            "courseCode": "课程编号",
                            "courseName": "课程名称",
                            "score": "补考成绩",
                            "scoreFlag": "成绩标识",
                            "credit": "学分",
                            "gradePoint": "绩点",
                            "makeupTerm": "补重学期",
                            "examNature": "补考一"
                          }
                        ],
                        "failedCourses": [
                          {
                            "term": "2023-2024-1",
                            "courseCode": "课程编号",
                            "courseName": "课程名称",
                            "score": "成绩",
                            "credit": "学分",
                            "gradePoint": "绩点"
                          }
                        ]
                      }
                    }
                  },
                  "jw.exams": {
                    "summary": "教务考试安排",
                    "value": {
                      "ok": true,
                      "data": {
                        "exams": [
                          {
                            "courseName": "课程名称",
                            "teacher": "教师",
                            "examTime": "考试时间",
                            "examPlace": "考试地点",
                            "seatNo": "座位号",
                            "courseCode": "课程编号",
                            "examSession": "考试场次",
                            "campus": "校区"
                          }
                        ]
                      }
                    }
                  },
                  "jw.training": {
                    "summary": "教务培养/毕业完成情况",
                    "value": {
                      "ok": true,
                      "data": {
                        "training": [
                          {
                            "graduationYear": "毕业届别",
                            "graduationType": "毕业类型",
                            "graduationConclusion": "毕业结论",
                            "graduationTime": "毕业时间",
                            "certificateNo": "毕业证书编号"
                          }
                        ]
                      }
                    }
                  },
                  "newcard.balance": {
                    "summary": "校园卡余额",
                    "value": {
                      "ok": true,
                      "data": {
                        "accounts": [
                          {
                            "typeCode": "账户类型编号",
                            "typeName": "账户名称",
                            "balance": "余额",
                            "unit": "元"
                          }
                        ]
                      }
                    }
                  },
                  "newcard.transactions": {
                    "summary": "校园卡流水",
                    "value": {
                      "ok": true,
                      "data": {
                        "fromDate": "2026-05-01",
                        "toDate": "2026-06-02",
                        "tradeType": "1,2,3",
                        "pageNo": 1,
                        "pageSize": 20,
                        "transactions": [
                          {
                            "date": "交易时间",
                            "summary": "摘要",
                            "merchantName": "商户",
                            "amount": "金额",
                            "isRefund": "是否退款",
                            "operation": false,
                            "journo": "流水号"
                          }
                        ]
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "参数错误、登录失败或学校接口错误"
          }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "ApiBearerAuth": {
        "type": "http",
        "scheme": "bearer",
        "bearerFormat": "XJIT accessToken",
        "description": "通过 /api/v1/auth/login 或 /api/v1/auth/wechat/* 获取的 API accessToken"
      }
    },
    "schemas": {
      "RunRequest": {
        "type": "object",
        "required": [
          "feature"
        ],
        "properties": {
          "feature": {
            "type": "string",
            "description": "功能名"
          },
          "params": {
            "type": "object",
            "description": "功能参数；不同 feature 结构不同"
          }
        }
      },
      "RunResponse": {
        "type": "object",
        "required": [
          "ok"
        ],
        "properties": {
          "ok": {
            "type": "boolean"
          },
          "data": {
            "type": "object",
            "description": "功能返回数据；不同 feature 结构不同"
          },
          "error": {
            "type": "string",
            "description": "错误信息"
          }
        }
      },
      "LoginRequest": {
        "type": "object",
        "required": [
          "username",
          "password"
        ],
        "properties": {
          "username": {
            "type": "string"
          },
          "password": {
            "type": "string"
          },
          "captcha": {
            "type": "string"
          },
          "rememberMe": {
            "type": "boolean"
          }
        }
      },
      "AuthSessionResponse": {
        "type": "object",
        "required": [
          "ok"
        ],
        "properties": {
          "ok": {
            "type": "boolean"
          },
          "data": {
            "$ref": "#/components/schemas/AuthSession"
          },
          "error": {
            "type": "string"
          }
        }
      },
      "AuthSession": {
        "type": "object",
        "properties": {
          "tokenType": {
            "type": "string",
            "example": "Bearer"
          },
          "accessToken": {
            "type": "string"
          },
          "source": {
            "type": "string",
            "enum": [
              "password",
              "wechat"
            ]
          },
          "username": {
            "type": "string"
          },
          "expiresInSeconds": {
            "type": "integer"
          },
          "createdAt": {
            "type": "integer"
          },
          "expiresAt": {
            "type": "integer"
          },
          "idTokenExpiresAt": {
            "type": "integer",
            "nullable": true,
            "description": "内部学校 idToken 的过期时间；仅用于调试，不是 API accessToken 的过期时间"
          }
        }
      },
      "AuthPrewarmResponse": {
        "type": "object",
        "properties": {
          "ok": {
            "type": "boolean"
          },
          "data": {
            "type": "object",
            "properties": {
              "status": {
                "type": "string",
                "enum": [
                  "none",
                  "running",
                  "ok",
                  "partial"
                ]
              },
              "startedAt": {
                "type": "integer"
              },
              "finishedAt": {
                "type": [
                  "integer",
                  "null"
                ]
              },
              "durationMs": {
                "type": "integer"
              },
              "systems": {
                "type": "object",
                "properties": {
                  "newcard": {
                    "$ref": "#/components/schemas/AuthPrewarmSystem"
                  },
                  "jw": {
                    "$ref": "#/components/schemas/AuthPrewarmSystem"
                  },
                  "jw_mobile": {
                    "$ref": "#/components/schemas/AuthPrewarmSystem"
                  }
                }
              }
            }
          },
          "error": {
            "type": "string"
          }
        }
      },
      "AuthPrewarmSystem": {
        "type": "object",
        "properties": {
          "status": {
            "type": "string",
            "enum": [
              "pending",
              "running",
              "ok",
              "error"
            ]
          },
          "startedAt": {
            "type": "integer"
          },
          "durationMs": {
            "type": "integer"
          },
          "error": {
            "type": "string"
          }
        }
      },
      "WechatStartRequest": {
        "type": "object",
        "properties": {
          "apiBaseUrl": {
            "type": "string",
            "description": "公网 API 根地址；不传时按当前请求 Host 推断，用来生成 statusUrl 和 completeUrl"
          },
          "serviceUrl": {
            "type": "string",
            "description": "CAS service 地址；默认使用学校已登记的 https://superapp.xjit.edu.cn/pages/tab/index/index"
          }
        }
      },
      "WechatCompleteRequest": {
        "type": "object",
        "required": [
          "state"
        ],
        "properties": {
          "state": {
            "type": "string"
          },
          "redirectUrl": {
            "type": "string",
            "description": "CAS 回跳到 superapp 的完整 URL，里面包含 ticket 参数"
          },
          "ticket": {
            "type": "string",
            "description": "也可以直接提交 CAS ticket；优先级高于 redirectUrl"
          }
        }
      },
      "WechatAuthResponse": {
        "type": "object",
        "required": [
          "ok"
        ],
        "properties": {
          "ok": {
            "type": "boolean"
          },
          "data": {
            "type": "object",
            "properties": {
              "state": {
                "type": "string"
              },
              "status": {
                "type": "string",
                "enum": [
                  "pending",
                  "success",
                  "expired",
                  "error"
                ]
              },
              "authUrl": {
                "type": "string"
              },
              "serviceUrl": {
                "type": "string"
              },
              "statusUrl": {
                "type": "string"
              },
              "completeUrl": {
                "type": "string"
              },
              "callbackUrl": {
                "type": "string",
                "description": "仅兼容白名单 callback 部署"
              },
              "expiresInSeconds": {
                "type": "integer"
              },
              "tokenType": {
                "type": "string"
              },
              "accessToken": {
                "type": "string"
              },
              "source": {
                "type": "string"
              },
              "username": {
                "type": "string"
              },
              "error": {
                "type": "string"
              }
            }
          },
          "error": {
            "type": "string"
          }
        }
      }
    }
  },
  "x-feature-docs": [
    {
      "name": "newcard.campus_code.qrcode",
      "title": "校园付款码",
      "system": "newcard",
      "method": "POST",
      "path": "/api/v1/run",
      "description": "获取新卡片在线校园付款码。返回的 qrcode 是可消费凭证，App 需要按 expiresInSeconds 定时刷新。",
      "paramsSchema": {
        "type": "object",
        "properties": {
          "qrcodeType": {
            "type": "string",
            "description": "付款码类型；不传时使用学校配置的默认类型，当前可传空字符串",
            "default": ""
          },
          "devCode": {
            "type": "string",
            "description": "设备标识；不传时使用 xjit-api",
            "default": "xjit-api"
          }
        }
      },
      "requestExample": {
        "feature": "newcard.campus_code.qrcode",
        "params": {}
      },
      "responseExample": {
        "ok": true,
        "data": {
          "mode": "online",
          "qrcode": "付款码字符串，App 用它生成二维码",
          "qrcodeType": "",
          "expiresInSeconds": 30,
          "balance": "0.00",
          "idSerial": "学号",
          "userName": "姓名",
          "displayInfo": true,
          "displayBalance": true
        }
      }
    },
    {
      "name": "newcard.recharge.config",
      "title": "一卡通充值配置",
      "system": "newcard",
      "method": "POST",
      "path": "/api/v1/run",
      "description": "获取一卡通充值页配置，包括当前校园卡余额、可选充值金额和支付方式。创建充值订单前应先调用这个功能。",
      "paramsSchema": {
        "type": "object",
        "properties": {}
      },
      "requestExample": {
        "feature": "newcard.recharge.config",
        "params": {}
      },
      "responseExample": {
        "ok": true,
        "data": {
          "balance": "118.00",
          "idSerial": "学号",
          "username": "姓名",
          "amountOptions": [
            {
              "id": "配置编号",
              "amount": "50",
              "name": "50元"
            },
            {
              "id": "配置编号",
              "amount": "100",
              "name": "100元"
            }
          ],
          "payMethods": [
            {
              "code": "01",
              "tradeType": "WAP",
              "name": "支付宝",
              "h5": true,
              "successToHome": false,
              "signBind": null
            },
            {
              "code": "02",
              "tradeType": "WAP",
              "name": "微信",
              "h5": true,
              "successToHome": false,
              "signBind": null
            }
          ],
          "canPayOther": true,
          "hostApp": true,
          "daLianPayEnable": true,
          "wapPayEnable": false
        }
      }
    },
    {
      "name": "newcard.recharge.create_order",
      "title": "一卡通充值下单",
      "system": "newcard",
      "method": "POST",
      "path": "/api/v1/run",
      "description": "创建一卡通充值支付订单，返回支付入口。调用这个功能会在学校支付系统生成一笔待支付订单，但不会自动扣款。微信 WAP 支付优先打开 payResult.officialTransferUrl，或在 WebView 加载 payResult.h5Url 时带 Referer=https://newcard.xjit.edu.cn/。",
      "paramsSchema": {
        "type": "object",
        "required": [
          "amount",
          "payCode"
        ],
        "properties": {
          "amount": {
            "type": "string",
            "description": "充值金额，必须大于 0，最多两位小数，例如 50"
          },
          "payCode": {
            "type": "string",
            "description": "支付方式编码，来自 newcard.recharge.config 的 payMethods.code，例如支付宝 01、微信 02"
          },
          "tradeType": {
            "type": "string",
            "default": "WAP",
            "description": "支付交易类型，来自 newcard.recharge.config 的 payMethods.tradeType"
          },
          "returnUrl": {
            "type": "string",
            "description": "支付完成后的跳转地址；App 可以传自己的 H5 回跳页"
          },
          "otherIdserial": {
            "type": "string",
            "description": "给他人一卡通充值时传对方学号；学校配置允许时才有效"
          },
          "subOpenId": {
            "type": "string",
            "description": "微信 JSAPI 支付需要时传"
          },
          "subAppId": {
            "type": "string",
            "description": "微信 JSAPI 支付需要时传"
          },
          "signReturnUrl": {
            "type": "string",
            "description": "签约/免密流程回跳地址"
          },
          "raw": {
            "type": "boolean",
            "default": false,
            "description": "是否返回学校支付接口原始 resultData"
          }
        }
      },
      "requestExample": {
        "feature": "newcard.recharge.create_order",
        "params": {
          "amount": "50",
          "payCode": "01",
          "tradeType": "WAP"
        }
      },
      "responseExample": {
        "ok": true,
        "data": {
          "amount": "50",
          "payMethod": {
            "code": "01",
            "tradeType": "WAP",
            "name": "支付宝"
          },
          "partnerJourno": "学校支付订单号",
          "payResult": {
            "type": "html_post",
            "payCode": "01",
            "partnerJourno": "学校支付订单号",
            "h5Url": null,
            "htmlPost": "<form>支付表单 HTML</form>",
            "wechatJsapi": null
          }
        }
      }
    },
    {
      "name": "newcard.electricity.account",
      "title": "宿舍电费/剩余电量查询",
      "system": "newcard",
      "method": "POST",
      "path": "/api/v1/run",
      "description": "按宿舍号查询剩余电量。调用方登录后只传 roomQuery，不需要处理 newcard tid 或学校系统 Authorization。",
      "paramsSchema": {
        "type": "object",
        "properties": {
          "roomQuery": {
            "type": "string",
            "description": "宿舍号简写，例如 5#524、3#312、9#312、5号楼524",
            "examples": [
              "9#312"
            ]
          },
          "raw": {
            "type": "boolean",
            "default": false,
            "description": "是否返回学校接口原始 JSON"
          },
          "location": {
            "type": "object",
            "description": "宿舍定位参数；通常不用传，优先用 roomQuery 查询静态映射表",
            "properties": {
              "bigArea": {
                "type": "string"
              },
              "area": {
                "type": "string"
              },
              "building": {
                "type": "string"
              },
              "unit": {
                "type": "string"
              },
              "level": {
                "type": "string"
              },
              "room": {
                "type": "string"
              },
              "subArea": {
                "type": "string"
              }
            }
          }
        }
      },
      "requestExample": {
        "feature": "newcard.electricity.account",
        "params": {
          "roomQuery": "9#312"
        }
      },
      "responseExample": {
        "ok": true,
        "data": {
          "remainingElectricity": {
            "value": "28.15",
            "unit": "度"
          },
          "room": {
            "query": "9#312",
            "buildingName": "9号宿舍楼",
            "levelName": "3层",
            "roomName": "312房间"
          }
        }
      }
    },
    {
      "name": "newcard.electricity.recharge.config",
      "title": "宿舍电费充值配置",
      "system": "newcard",
      "method": "POST",
      "path": "/api/v1/run",
      "description": "按宿舍号获取电费充值配置、当前剩余电量、校园卡余额、快捷金额和支付方式。创建电费充值支付前应先调用这个功能。",
      "paramsSchema": {
        "type": "object",
        "properties": {
          "roomQuery": {
            "type": "string",
            "description": "宿舍号简写，例如 5#524、3#312、9#312、5号楼524",
            "examples": [
              "9#312"
            ]
          },
          "location": {
            "type": "object",
            "description": "宿舍定位参数；通常不用传，优先用 roomQuery 查询静态映射表"
          }
        }
      },
      "requestExample": {
        "feature": "newcard.electricity.recharge.config",
        "params": {
          "roomQuery": "9#312"
        }
      },
      "responseExample": {
        "ok": true,
        "data": {
          "room": {
            "query": "9#312",
            "buildingName": "9号宿舍楼",
            "levelName": "3层",
            "roomName": "312房间"
          },
          "account": {
            "utilityAccount": "电费账号",
            "utilityUsername": "户名",
            "utilityStatusName": "正常",
            "accStatusName": "正常"
          },
          "remainingElectricity": {
            "value": "3.27",
            "unit": "度"
          },
          "cardBalance": {
            "value": "135.66",
            "unit": "元"
          },
          "price": {
            "value": "0.39",
            "unit": "元/度"
          },
          "amountOptions": [
            {
              "id": "1",
              "amount": "30",
              "name": "30元"
            },
            {
              "id": "2",
              "amount": "50",
              "name": "50元"
            },
            {
              "id": "3",
              "amount": "60",
              "name": "60元"
            }
          ],
          "payMethods": [
            {
              "code": "06",
              "tradeType": null,
              "name": "余额支付",
              "h5": false,
              "successToHome": false,
              "signBind": null
            }
          ],
          "needPaymentPassword": true,
          "canPayOther": false,
          "confirm": true,
          "daLianPayEnable": false,
          "hostApp": true,
          "amtInputDisabled": false,
          "tip": ""
        }
      }
    },
    {
      "name": "newcard.electricity.recharge.pay",
      "title": "宿舍电费充值支付",
      "system": "newcard",
      "method": "POST",
      "path": "/api/v1/run",
      "description": "按宿舍号发起电费充值支付。当前学校电费配置通常只开放 payCode=06 余额支付；传入 paymentPassword 后会直接从校园卡余额扣款。内部会按官方 H5 流程调用 getEncrypt，并用 SM4/SM2 加密后请求学校支付接口。",
      "paramsSchema": {
        "type": "object",
        "required": [
          "roomQuery",
          "amount",
          "payCode"
        ],
        "properties": {
          "roomQuery": {
            "type": "string",
            "description": "宿舍号简写，例如 9#312",
            "examples": [
              "9#312"
            ]
          },
          "amount": {
            "type": "string",
            "description": "充值金额，必须大于 0，最多两位小数，例如 30"
          },
          "payCode": {
            "type": "string",
            "description": "支付方式编码，来自 newcard.electricity.recharge.config 的 payMethods.code；余额支付为 06"
          },
          "tradeType": {
            "type": "string",
            "description": "支付交易类型；支付方式返回 tradeType 时传入"
          },
          "paymentPassword": {
            "type": "string",
            "description": "一卡通支付密码；payCode=06 且 needPaymentPassword=true 时必填"
          },
          "returnUrl": {
            "type": "string",
            "description": "支付宝/微信等 H5 支付完成后的跳转地址；余额支付通常不用"
          },
          "customfield": {
            "type": "object",
            "description": "学校电费配置要求的自定义字段；当前通常为空对象"
          },
          "raw": {
            "type": "boolean",
            "default": false,
            "description": "是否返回学校接口原始 resultData"
          }
        }
      },
      "requestExample": {
        "feature": "newcard.electricity.recharge.pay",
        "params": {
          "roomQuery": "9#312",
          "amount": "30",
          "payCode": "06",
          "paymentPassword": "一卡通支付密码"
        }
      },
      "responseExample": {
        "ok": true,
        "data": {
          "amount": "30",
          "room": {
            "query": "9#312",
            "buildingName": "9号宿舍楼",
            "levelName": "3层",
            "roomName": "312房间"
          },
          "account": {
            "utilityAccount": "电费账号",
            "utilityUsername": "户名",
            "utilityStatusName": "正常",
            "accStatusName": "正常"
          },
          "payMethod": {
            "code": "06",
            "tradeType": null,
            "name": "余额支付"
          },
          "partnerJourno": null,
          "payResult": {
            "type": "balance_payment",
            "payCode": "06",
            "partnerJourno": null
          }
        }
      }
    },
    {
      "name": "jw.schedule",
      "title": "教务课表查询",
      "system": "jw",
      "method": "POST",
      "path": "/api/v1/run",
      "description": "查询当前或指定学期课表。",
      "paramsSchema": {
        "type": "object",
        "properties": {
          "term": {
            "type": "string",
            "description": "学期，例如 2025-2026-2；不传使用教务默认当前学期"
          }
        }
      },
      "requestExample": {
        "feature": "jw.schedule",
        "params": {}
      },
      "responseExample": {
        "ok": true,
        "data": {
          "term": "当前学期",
          "courses": [
            {
              "day": "星期一",
              "slot": "第一大节",
              "title": "课程名",
              "teacher": "教师",
              "weeks": "1-16周",
              "sections": "1-2节",
              "location": "教室"
            }
          ]
        }
      }
    },
    {
      "name": "jw.profile",
      "title": "教务个人信息",
      "system": "jw",
      "method": "POST",
      "path": "/api/v1/run",
      "description": "查询教务系统个人基础信息。",
      "paramsSchema": {
        "type": "object",
        "properties": {}
      },
      "requestExample": {
        "feature": "jw.profile",
        "params": {}
      },
      "responseExample": {
        "ok": true,
        "data": {
          "studentId": "学号",
          "name": "姓名",
          "college": "学院",
          "major": "专业",
          "className": "班级",
          "grade": "年级",
          "gender": "性别"
        }
      }
    },
    {
      "name": "jw.grades",
      "title": "教务成绩/学分绩点查询",
      "system": "jw",
      "method": "POST",
      "path": "/api/v1/run",
      "description": "查询成绩，并返回按课程去重后的学分绩点汇总、正常成绩、补考/重修成绩。",
      "paramsSchema": {
        "type": "object",
        "properties": {
          "term": {
            "type": "string",
            "description": "按学期过滤，例如 2025-2026-2"
          },
          "mode": {
            "type": "string",
            "enum": [
              "best_by_course",
              "raw"
            ],
            "default": "best_by_course",
            "description": "summary 统计模式；默认同一课程取绩点/分数最高的一条"
          }
        }
      },
      "requestExample": {
        "feature": "jw.grades",
        "params": {}
      },
      "responseExample": {
        "ok": true,
        "data": {
          "mode": "best_by_course",
          "summary": {
            "courseCount": 42,
            "totalCredits": 91.75,
            "gpaCredits": 91.75,
            "weightedGradePoint": 2.25,
            "failedCourseCount": 3,
            "failedCredits": 13
          },
          "rawSummary": {
            "courseCount": 48,
            "totalCredits": 112,
            "gpaCredits": 112,
            "weightedGradePoint": 1.85,
            "failedCourseCount": 9,
            "failedCredits": 33.25
          },
          "terms": [
            {
              "term": "2025-2026-2",
              "courseCount": 8,
              "totalCredits": 18,
              "gpaCredits": 18,
              "weightedGradePoint": 3.12,
              "failedCourseCount": 0,
              "failedCredits": 0
            }
          ],
          "normalGrades": [
            {
              "term": "2025-2026-2",
              "courseCode": "课程编号",
              "courseName": "课程名称",
              "score": "成绩",
              "credit": "学分",
              "gradePoint": "绩点",
              "examNature": "正常考试"
            }
          ],
          "makeupGrades": [
            {
              "term": "2023-2024-1",
              "courseCode": "课程编号",
              "courseName": "课程名称",
              "score": "补考成绩",
              "scoreFlag": "成绩标识",
              "credit": "学分",
              "gradePoint": "绩点",
              "makeupTerm": "补重学期",
              "examNature": "补考一"
            }
          ],
          "failedCourses": [
            {
              "term": "2023-2024-1",
              "courseCode": "课程编号",
              "courseName": "课程名称",
              "score": "成绩",
              "credit": "学分",
              "gradePoint": "绩点"
            }
          ]
        }
      }
    },
    {
      "name": "jw.exams",
      "title": "教务考试安排",
      "system": "jw_mobile",
      "method": "POST",
      "path": "/api/v1/run",
      "description": "通过移动教务 CAS SSO 查询考试安排。",
      "paramsSchema": {
        "type": "object",
        "properties": {}
      },
      "requestExample": {
        "feature": "jw.exams",
        "params": {}
      },
      "responseExample": {
        "ok": true,
        "data": {
          "exams": [
            {
              "courseName": "课程名称",
              "teacher": "教师",
              "examTime": "考试时间",
              "examPlace": "考试地点",
              "seatNo": "座位号",
              "courseCode": "课程编号",
              "examSession": "考试场次",
              "campus": "校区"
            }
          ]
        }
      }
    },
    {
      "name": "jw.training",
      "title": "教务培养/毕业完成情况",
      "system": "jw",
      "method": "POST",
      "path": "/api/v1/run",
      "description": "查询教务培养或毕业完成情况；无数据时返回空数组。",
      "paramsSchema": {
        "type": "object",
        "properties": {}
      },
      "requestExample": {
        "feature": "jw.training",
        "params": {}
      },
      "responseExample": {
        "ok": true,
        "data": {
          "training": [
            {
              "graduationYear": "毕业届别",
              "graduationType": "毕业类型",
              "graduationConclusion": "毕业结论",
              "graduationTime": "毕业时间",
              "certificateNo": "毕业证书编号"
            }
          ]
        }
      }
    },
    {
      "name": "newcard.balance",
      "title": "校园卡余额",
      "system": "newcard",
      "method": "POST",
      "path": "/api/v1/run",
      "description": "查询校园卡账户余额。",
      "paramsSchema": {
        "type": "object",
        "properties": {}
      },
      "requestExample": {
        "feature": "newcard.balance",
        "params": {}
      },
      "responseExample": {
        "ok": true,
        "data": {
          "accounts": [
            {
              "typeCode": "账户类型编号",
              "typeName": "账户名称",
              "balance": "余额",
              "unit": "元"
            }
          ]
        }
      }
    },
    {
      "name": "newcard.transactions",
      "title": "校园卡流水",
      "system": "newcard",
      "method": "POST",
      "path": "/api/v1/run",
      "description": "查询校园卡交易流水。",
      "paramsSchema": {
        "type": "object",
        "properties": {
          "fromDate": {
            "type": "string",
            "format": "date",
            "description": "起始日期，不传默认最近 30 天"
          },
          "toDate": {
            "type": "string",
            "format": "date",
            "description": "截止日期，不传默认今天"
          },
          "tradeType": {
            "type": "string",
            "default": "1,2,3",
            "description": "交易类型，默认全部"
          },
          "pageNo": {
            "type": "integer",
            "default": 1,
            "minimum": 0,
            "description": "对外页码按 1 起算；内部自动转换成学校接口的 0 起始页码。传 0 也兼容为第一页。"
          },
          "pageSize": {
            "type": "integer",
            "default": 20,
            "minimum": 1,
            "maximum": 100
          }
        }
      },
      "requestExample": {
        "feature": "newcard.transactions",
        "params": {
          "pageSize": 20
        }
      },
      "responseExample": {
        "ok": true,
        "data": {
          "fromDate": "2026-05-01",
          "toDate": "2026-06-02",
          "tradeType": "1,2,3",
          "pageNo": 1,
          "pageSize": 20,
          "transactions": [
            {
              "date": "交易时间",
              "summary": "摘要",
              "merchantName": "商户",
              "amount": "金额",
              "isRefund": "是否退款",
              "operation": false,
              "journo": "流水号"
            }
          ]
        }
      }
    }
  ]
}