开发文档

Android 客户端接入 API 文档

基础信息

基础URLhttps://photobooth.show
认证方式Session / Cookie 认证(PHPSESSID)
字符编码UTF-8
内容格式JSON

1. 用户登录

POST /auth/doLogin

用户登录接口,支持用户名或邮箱登录。登录成功后服务端会设置 PHPSESSID Cookie,后续请求需携带此 Cookie 进行身份认证。

请求参数(application/x-www-form-urlencoded)

参数类型必填说明
usernamestring用户名或邮箱
passwordstring明文密码

请求示例

POST /auth/doLogin
Content-Type: application/x-www-form-urlencoded

username=admin&password=123456

响应说明

字段类型说明
codeint1 成功,0 失败
msgstring提示信息

响应示例

登录成功:

{
    "code": 1,
    "msg": "登录成功"
}

用户名或密码错误:

{
    "code": 0,
    "msg": "用户名或密码错误"
}

账号已被禁用:

{
    "code": 0,
    "msg": "账号已被禁用"
}

2. 用户注册

POST /auth/doRegister

请求参数

参数类型必填说明
usernamestring用户名(唯一)
emailstring邮箱(唯一)
passwordstring密码
repasswordstring确认密码(需与 password 一致)

响应示例

// 注册成功
{"code": 1, "msg": "注册成功,请登录"}

// 两次密码不一致
{"code": 0, "msg": "两次密码不一致"}

// 用户名已存在
{"code": 0, "msg": "用户名已存在"}

// 邮箱已被注册
{"code": 0, "msg": "邮箱已被注册"}

3. 退出登录

GET /auth/logout

清除服务端会话,客户端也需清除本地 Cookie。

4. Android 接入指南

4.1 Session/Cookie 管理

登录成功后服务端在 Set-Cookie 响应头返回 PHPSESSID,Android 客户端需使用 CookieJar(如 OkHttp 的 PersistentCookieJar)自动管理 Cookie,后续所有请求都需携带此 Cookie 才能通过认证。

4.2 推荐依赖

// build.gradle (app)
implementation 'com.squareup.okhttp3:okhttp:4.12.0'
implementation 'com.github.franmontiel:PersistentCookieJar:v1.0.1'

4.3 OkHttp 实现示例(Kotlin)

val cookieJar = PersistentCookieJar(
    SetCookieCache(),
    SharedPrefsCookiePersistor(context)
)

val client = OkHttpClient.Builder()
    .cookieJar(cookieJar)
    .build()

// 登录请求
val formBody = FormBody.Builder()
    .add("username", "admin")
    .add("password", "123456")
    .build()

val request = Request.Builder()
    .url("https://photobooth.show/auth/doLogin")
    .post(formBody)
    .build()

client.newCall(request).enqueue(object : Callback {
    override fun onResponse(call: Call, response: Response) {
        val body = JSONObject(response.body?.string() ?: "{}")
        val code = body.getInt("code")
        val msg = body.getString("msg")
        // Cookie 已由 CookieJar 自动保存,后续请求自动附带
    }

    override fun onFailure(call: Call, e: IOException) {
        // 网络异常处理
    }
})

5. 活动数据上传(Android → 服务器)

Android 端拍照机需要将活动数据同步到服务器,以下接口用于数据上传与同步。推荐在每次拍照结束后自动调用上传接口。

5.1 上传活动(POST /api/uploadEvent)

POST /api/uploadEvent

将 Android 端创建的活动上传到服务器。

请求参数(application/x-www-form-urlencoded 或 JSON)
参数类型必填说明
namestring活动名称
template_pathstring模板路径,多个用逗号拼接
countdown_secondsint倒计时秒数,默认 5
is_paidint是否付费(0/1),默认 0
time_slotsstring/array时间段 JSON 数组(见下方说明)
time_slots 格式
[
    {
        "slot_date": "2026-07-03",
        "start_time": "09:00",
        "end_time": "18:00"
    }
]
请求示例(JSON)
POST /api/uploadEvent
Content-Type: application/json

{
    "name": "暑期嘉年华",
    "template_path": "tpl_summer.png,tpl_fun.png",
    "countdown_seconds": 5,
    "is_paid": 0,
    "time_slots": [
        {"slot_date": "2026-07-10", "start_time": "09:00", "end_time": "12:00"},
        {"slot_date": "2026-07-10", "start_time": "14:00", "end_time": "18:00"}
    ]
}
响应示例
{
    "code": 1,
    "msg": "活动上传成功",
    "data": {
        "event_id": 1
    }
}

5.2 上传拍摄记录(POST /api/uploadRecord)

POST /api/uploadRecord

上传一次完整的拍摄记录,包含拍摄时间段和照片。照片通过 photos[] multipart 文件字段上传。

请求参数(multipart/form-data)
参数类型必填说明
event_idint关联的活动 ID
start_timestring开始拍摄时间(yyyy-MM-dd HH:mm:ss)
end_timestring结束拍摄时间(yyyy-MM-dd HH:mm:ss)
print_countint累计打印张数
photos[]file[]照片文件数组
请求示例
POST /api/uploadRecord
Content-Type: multipart/form-data; boundary=----boundary

--boundary
Content-Disposition: form-data; name="event_id"

1
--boundary
Content-Disposition: form-data; name="start_time"

2026-07-10 10:00:00
--boundary
Content-Disposition: form-data; name="end_time"

2026-07-10 10:30:00
--boundary
Content-Disposition: form-data; name="print_count"

3
--boundary
Content-Disposition: form-data; name="photos[]"; filename="photo1.jpg"
Content-Type: image/jpeg

(binary data)
--boundary
Content-Disposition: form-data; name="photos[]"; filename="photo2.jpg"
Content-Type: image/jpeg

(binary data)
--boundary--
Android (OkHttp) 实现示例
val requestBody = MultipartBody.Builder()
    .setType(MultipartBody.FORM)
    .addFormDataPart("event_id", eventId.toString())
    .addFormDataPart("start_time", startTime)
    .addFormDataPart("end_time", endTime ?: "")
    .addFormDataPart("print_count", printCount.toString())

photoFiles.forEach { file ->
    requestBody.addFormDataPart(
        "photos[]",
        file.name,
        file.asRequestBody("image/jpeg".toMediaType())
    )
}

val request = Request.Builder()
    .url("https://photobooth.show/api/uploadRecord")
    .post(requestBody.build())
    .build()
响应示例
{
    "code": 1,
    "msg": "拍摄记录上传成功",
    "data": {
        "record_id": 1,
        "photo_count": 2
    }
}

5.3 上传单张照片(POST /api/uploadPhoto)

POST /api/uploadPhoto

通过 multipart/form-data 上传单张照片文件到已有拍摄记录。适用于先创建记录再逐张上传照片的场景。

请求参数(multipart/form-data)
参数类型必填说明
record_idint拍摄记录 ID
photofile照片文件
Android (OkHttp) 实现示例
val requestBody = MultipartBody.Builder()
    .setType(MultipartBody.FORM)
    .addFormDataPart("record_id", recordId.toString())
    .addFormDataPart("photo", file.name, file.asRequestBody("image/jpeg".toMediaType()))
    .build()

val request = Request.Builder()
    .url("https://photobooth.show/api/uploadPhoto")
    .post(requestBody)
    .build()
响应示例
{
    "code": 1,
    "msg": "上传成功",
    "data": {
        "photo_url": "/uploads/photos/abc123.jpg"
    }
}

5.4 批量上传照片(POST /api/uploadPhotos)

POST /api/uploadPhotos

通过 multipart/form-data 一次性上传多张照片到已有拍摄记录。

请求参数(multipart/form-data)
参数类型必填说明
record_idint拍摄记录 ID
photos[]file[]照片文件数组,可传多个
Android (OkHttp) 实现示例
val builder = MultipartBody.Builder()
    .setType(MultipartBody.FORM)
    .addFormDataPart("record_id", recordId.toString())

photoFiles.forEach { file ->
    builder.addFormDataPart(
        "photos[]",
        file.name,
        file.asRequestBody("image/jpeg".toMediaType())
    )
}

val request = Request.Builder()
    .url("https://photobooth.show/api/uploadPhotos")
    .post(builder.build())
    .build()
响应示例
{
    "code": 1,
    "msg": "上传成功",
    "data": {
        "uploaded": 3,
        "photos": [
            "/uploads/photos/abc.jpg",
            "/uploads/photos/def.jpg",
            "/uploads/photos/ghi.jpg"
        ]
    }
}

5.5 同步拍摄记录(POST /api/syncRecords)

POST /api/syncRecords

获取指定活动的所有拍摄记录及照片列表,用于 Android 端数据恢复。

请求参数
参数类型必填说明
event_idint活动 ID
响应示例
{
    "code": 1,
    "data": [
        {
            "id": 1,
            "event_id": 1,
            "start_time": "2026-07-10 10:00:00",
            "end_time": "2026-07-10 10:30:00",
            "print_count": 3,
            "photo_count": 2,
            "photos": [
                {"photo_url": "/uploads/photos/001.jpg"},
                {"photo_url": "/uploads/photos/002.jpg"}
            ]
        }
    ]
}

5.6 获取活动列表(GET /api/getEvents)

GET /api/getEvents

获取服务器上所有启用状态的活动列表,含时间段信息。

5.7 获取活动详情(GET /api/getEventDetail)

GET /api/getEventDetail?id=1

获取单个活动的完整信息,包含时间段、拍摄记录及照片。

请求参数
参数类型必填说明
idint活动 ID

5.8 获取分享链接(POST /api/getShareUrl)

POST /api/getShareUrl

为指定拍摄记录生成分享链接。首次调用自动生成唯一 token,后续调用返回相同链接(幂等)。分享页面可查看该记录的所有照片及活动信息。

请求参数(application/x-www-form-urlencoded)
参数类型必填说明
record_idint拍摄记录 ID
响应示例
{
    "code": 1,
    "msg": "获取成功",
    "data": {
        "share_url": "https://photobooth.show/share/55dd90208f9244b53d10eba5952544be",
        "share_token": "55dd90208f9244b53d10eba5952544be"
    }
}
分享页面

生成的 share_url 可直接在浏览器中打开,展示该拍摄记录的所有照片及活动信息,无需登录即可查看。

6. 数据表结构(Android SQLite ↔ 服务器 MySQL)

Android 端本地存储结构与服务器数据库一致,便于双向同步。

events — 活动表

字段类型说明
idint主键
namestring活动名称
template_pathstring模板路径,多个用逗号拼接
countdown_secondsint倒计时秒数
is_paidint是否付费(0/1)

time_slots — 活动时间段

字段类型说明
idint主键
event_idint关联 events.id
slot_datedate日期(yyyy-MM-dd)
start_timetime开始时间(HH:mm)
end_timetime结束时间(HH:mm)

records — 拍摄记录

字段类型说明
idint主键
event_idint关联 events.id
start_timedatetime开始拍摄时间
end_timedatetime结束拍摄时间
print_countint累计打印张数
photo_countint照片数量
sync_statustinyint同步状态
share_tokenstring分享链接 token(唯一)

record_photos — 记录中的照片

字段类型说明
idint主键
record_idint关联 records.id
photo_urlstring照片 URL
thumbnail_urlstring缩略图 URL

注意事项

  • 服务器密码使用 bcrypt 加密存储,传输过程建议启用 HTTPS 避免明文泄露。
  • Session 有效期默认 24 分钟(1440 秒),过期后需重新登录。
  • 前端 JS 提交地址为 /auth/do_login(下划线),但服务端路由定义为 /auth/doLogin(驼峰)。Android 端请使用驼峰路径 /auth/doLogin,如 404 请联系后端确认。
  • 照片通过 multipart photos[] 字段上传,上传后保存在 /uploads/photos/ 目录,文件名使用 md5(microtime + 原文件名).原扩展名 生成。