feat: add TenantLedger model and query generation

- Introduced TenantLedger model with fields for managing tenant transactions, including ID, TenantID, UserID, OrderID, transaction Type, Amount, and balance details.
- Implemented CRUD operations for TenantLedger with methods for Create, Update, Delete, and Reload.
- Generated query methods for TenantLedger to facilitate database interactions, including filtering, pagination, and aggregation functions.
- Established relationships with Order model for foreign key references.
This commit is contained in:
2025-12-18 13:12:26 +08:00
parent f93caefcb2
commit 1da84f2af3
42 changed files with 6468 additions and 265 deletions

View File

@@ -603,6 +603,176 @@ const docTemplate = `{
}
}
},
"/t/{tenantCode}/v1/admin/orders": {
"get": {
"consumes": [
"application/json"
],
"produces": [
"application/json"
],
"tags": [
"Tenant"
],
"summary": "订单列表(租户管理)",
"parameters": [
{
"type": "string",
"description": "Tenant Code",
"name": "tenantCode",
"in": "path",
"required": true
},
{
"type": "integer",
"description": "Limit is page size; only values in {10,20,50,100} are accepted (otherwise defaults to 10).",
"name": "limit",
"in": "query"
},
{
"type": "integer",
"description": "Page is 1-based page index; values \u003c= 0 are normalized to 1.",
"name": "page",
"in": "query"
},
{
"enum": [
"created",
"paid",
"refunding",
"refunded",
"canceled",
"failed"
],
"type": "string",
"x-enum-varnames": [
"OrderStatusCreated",
"OrderStatusPaid",
"OrderStatusRefunding",
"OrderStatusRefunded",
"OrderStatusCanceled",
"OrderStatusFailed"
],
"description": "Status filters orders by order status.",
"name": "status",
"in": "query"
},
{
"type": "integer",
"description": "UserID filters orders by buyer user id.",
"name": "user_id",
"in": "query"
}
],
"responses": {
"200": {
"description": "OK",
"schema": {
"allOf": [
{
"$ref": "#/definitions/requests.Pager"
},
{
"type": "object",
"properties": {
"items": {
"$ref": "#/definitions/models.Order"
}
}
}
]
}
}
}
}
},
"/t/{tenantCode}/v1/admin/orders/{orderID}": {
"get": {
"consumes": [
"application/json"
],
"produces": [
"application/json"
],
"tags": [
"Tenant"
],
"summary": "订单详情(租户管理)",
"parameters": [
{
"type": "string",
"description": "Tenant Code",
"name": "tenantCode",
"in": "path",
"required": true
},
{
"type": "integer",
"format": "int64",
"description": "OrderID",
"name": "orderID",
"in": "path",
"required": true
}
],
"responses": {
"200": {
"description": "OK",
"schema": {
"$ref": "#/definitions/dto.AdminOrderDetail"
}
}
}
}
},
"/t/{tenantCode}/v1/admin/orders/{orderID}/refund": {
"post": {
"consumes": [
"application/json"
],
"produces": [
"application/json"
],
"tags": [
"Tenant"
],
"summary": "订单退款(租户管理)",
"parameters": [
{
"type": "string",
"description": "Tenant Code",
"name": "tenantCode",
"in": "path",
"required": true
},
{
"type": "integer",
"format": "int64",
"description": "OrderID",
"name": "orderID",
"in": "path",
"required": true
},
{
"description": "Form",
"name": "form",
"in": "body",
"required": true,
"schema": {
"$ref": "#/definitions/dto.AdminOrderRefundForm"
}
}
],
"responses": {
"200": {
"description": "OK",
"schema": {
"$ref": "#/definitions/models.Order"
}
}
}
}
},
"/t/{tenantCode}/v1/contents": {
"get": {
"consumes": [
@@ -781,6 +951,54 @@ const docTemplate = `{
}
}
},
"/t/{tenantCode}/v1/contents/{contentID}/purchase": {
"post": {
"consumes": [
"application/json"
],
"produces": [
"application/json"
],
"tags": [
"Tenant"
],
"summary": "购买内容(余额支付)",
"parameters": [
{
"type": "string",
"description": "Tenant Code",
"name": "tenantCode",
"in": "path",
"required": true
},
{
"type": "integer",
"format": "int64",
"description": "ContentID",
"name": "contentID",
"in": "path",
"required": true
},
{
"description": "Form",
"name": "form",
"in": "body",
"required": true,
"schema": {
"$ref": "#/definitions/dto.PurchaseContentForm"
}
}
],
"responses": {
"200": {
"description": "OK",
"schema": {
"$ref": "#/definitions/dto.PurchaseContentResponse"
}
}
}
}
},
"/t/{tenantCode}/v1/me": {
"get": {
"consumes": [
@@ -811,9 +1029,138 @@ const docTemplate = `{
}
}
}
},
"/t/{tenantCode}/v1/orders": {
"get": {
"consumes": [
"application/json"
],
"produces": [
"application/json"
],
"tags": [
"Tenant"
],
"summary": "我的订单列表(当前租户)",
"parameters": [
{
"type": "string",
"description": "Tenant Code",
"name": "tenantCode",
"in": "path",
"required": true
},
{
"type": "integer",
"description": "Limit is page size; only values in {10,20,50,100} are accepted (otherwise defaults to 10).",
"name": "limit",
"in": "query"
},
{
"type": "integer",
"description": "Page is 1-based page index; values \u003c= 0 are normalized to 1.",
"name": "page",
"in": "query"
},
{
"enum": [
"created",
"paid",
"refunding",
"refunded",
"canceled",
"failed"
],
"type": "string",
"x-enum-varnames": [
"OrderStatusCreated",
"OrderStatusPaid",
"OrderStatusRefunding",
"OrderStatusRefunded",
"OrderStatusCanceled",
"OrderStatusFailed"
],
"description": "Status filters orders by order status.",
"name": "status",
"in": "query"
}
],
"responses": {
"200": {
"description": "OK",
"schema": {
"allOf": [
{
"$ref": "#/definitions/requests.Pager"
},
{
"type": "object",
"properties": {
"items": {
"$ref": "#/definitions/models.Order"
}
}
}
]
}
}
}
}
},
"/t/{tenantCode}/v1/orders/{orderID}": {
"get": {
"consumes": [
"application/json"
],
"produces": [
"application/json"
],
"tags": [
"Tenant"
],
"summary": "我的订单详情(当前租户)",
"parameters": [
{
"type": "string",
"description": "Tenant Code",
"name": "tenantCode",
"in": "path",
"required": true
},
{
"type": "integer",
"format": "int64",
"description": "OrderID",
"name": "orderID",
"in": "path",
"required": true
}
],
"responses": {
"200": {
"description": "OK",
"schema": {
"$ref": "#/definitions/models.Order"
}
}
}
}
}
},
"definitions": {
"consts.ContentAccessStatus": {
"type": "string",
"enum": [
"active",
"revoked",
"expired"
],
"x-enum-varnames": [
"ContentAccessStatusActive",
"ContentAccessStatusRevoked",
"ContentAccessStatusExpired"
]
},
"consts.ContentAssetRole": {
"type": "string",
"enum": [
@@ -909,6 +1256,36 @@ const docTemplate = `{
"MediaAssetTypeImage"
]
},
"consts.OrderStatus": {
"type": "string",
"enum": [
"created",
"paid",
"refunding",
"refunded",
"canceled",
"failed"
],
"x-enum-varnames": [
"OrderStatusCreated",
"OrderStatusPaid",
"OrderStatusRefunding",
"OrderStatusRefunded",
"OrderStatusCanceled",
"OrderStatusFailed"
]
},
"consts.OrderType": {
"type": "string",
"enum": [
"content_purchase",
"topup"
],
"x-enum-varnames": [
"OrderTypeContentPurchase",
"OrderTypeTopup"
]
},
"consts.Role": {
"type": "string",
"enum": [
@@ -957,6 +1334,36 @@ const docTemplate = `{
"UserStatusBanned"
]
},
"dto.AdminOrderDetail": {
"type": "object",
"properties": {
"order": {
"description": "Order is the order with items preloaded.",
"allOf": [
{
"$ref": "#/definitions/models.Order"
}
]
}
}
},
"dto.AdminOrderRefundForm": {
"type": "object",
"properties": {
"force": {
"description": "Force indicates bypassing the default refund window check (paid_at + 24h).\n强制退款true 表示绕过默认退款时间窗限制(需审计)。",
"type": "boolean"
},
"idempotency_key": {
"description": "IdempotencyKey ensures refund request is processed at most once.\n幂等键同一笔退款重复请求时返回一致结果避免重复退款/重复回滚。",
"type": "string"
},
"reason": {
"description": "Reason is the human-readable refund reason used for audit.\n退款原因建议必填由业务侧校验用于审计与追责。",
"type": "string"
}
}
},
"dto.ContentAssetAttachForm": {
"type": "object",
"properties": {
@@ -1195,6 +1602,48 @@ const docTemplate = `{
}
}
},
"dto.PurchaseContentForm": {
"type": "object",
"properties": {
"idempotency_key": {
"description": "IdempotencyKey is used to ensure the purchase request is processed at most once.\n建议由客户端生成并保持稳定同一笔购买重复请求时返回相同结果避免重复扣款/重复下单。",
"type": "string"
}
}
},
"dto.PurchaseContentResponse": {
"type": "object",
"properties": {
"access": {
"description": "Access is the content access record after purchase grant.",
"allOf": [
{
"$ref": "#/definitions/models.ContentAccess"
}
]
},
"amount_paid": {
"description": "AmountPaid is the final paid amount in cents (CNY 分).",
"type": "integer"
},
"item": {
"description": "Item is the single order item of this purchase (current implementation is 1 order -\u003e 1 content).",
"allOf": [
{
"$ref": "#/definitions/models.OrderItem"
}
]
},
"order": {
"description": "Order is the created or existing order record (may be nil for owner/free-path without order).",
"allOf": [
{
"$ref": "#/definitions/models.Order"
}
]
}
}
},
"dto.TenantExpireUpdateForm": {
"type": "object",
"required": [
@@ -1387,43 +1836,113 @@ const docTemplate = `{
"type": "object",
"properties": {
"created_at": {
"description": "创建时间:默认 now();用于审计与排序",
"type": "string"
},
"deleted_at": {
"$ref": "#/definitions/gorm.DeletedAt"
"description": "软删除时间:非空表示已删除;对外接口需过滤",
"allOf": [
{
"$ref": "#/definitions/gorm.DeletedAt"
}
]
},
"description": {
"description": "描述:用于详情页展示;可为空字符串",
"type": "string"
},
"id": {
"description": "主键ID自增用于内容引用",
"type": "integer"
},
"preview_downloadable": {
"description": "试看是否允许下载:默认 false当前策略固定为不允许下载仅 streaming",
"type": "boolean"
},
"preview_seconds": {
"description": "试看秒数:默认 60只对 preview 资源生效;必须为正整数",
"type": "integer"
},
"published_at": {
"description": "发布时间:首次发布时写入;用于时间窗与排序",
"type": "string"
},
"status": {
"$ref": "#/definitions/consts.ContentStatus"
"description": "状态draft/reviewing/published/unpublished/blockedpublished 才对外展示",
"allOf": [
{
"$ref": "#/definitions/consts.ContentStatus"
}
]
},
"tenant_id": {
"description": "租户ID多租户隔离关键字段所有查询/写入必须限定 tenant_id",
"type": "integer"
},
"title": {
"description": "标题:用于列表展示与搜索;建议限制长度(由业务校验)",
"type": "string"
},
"updated_at": {
"description": "更新时间:默认 now();编辑内容时写入",
"type": "string"
},
"user_id": {
"description": "用户ID内容创建者/发布者;用于权限与审计(例如私有内容仅作者可见)",
"type": "integer"
},
"visibility": {
"$ref": "#/definitions/consts.ContentVisibility"
"description": "可见性public/tenant_only/private仅控制详情可见正片资源仍需按价格/权益校验",
"allOf": [
{
"$ref": "#/definitions/consts.ContentVisibility"
}
]
}
}
},
"models.ContentAccess": {
"type": "object",
"properties": {
"content_id": {
"description": "内容ID权益对应内容唯一约束 (tenant_id, user_id, content_id)",
"type": "integer"
},
"created_at": {
"description": "创建时间:默认 now();用于审计",
"type": "string"
},
"id": {
"description": "主键ID自增",
"type": "integer"
},
"order_id": {
"description": "订单ID产生该权益的订单可为空例如后台补发/迁移)",
"type": "integer"
},
"revoked_at": {
"description": "撤销时间:当 status=revoked 时写入;用于审计与追责",
"type": "string"
},
"status": {
"description": "权益状态active/revoked/expiredrevoked 表示立即失效(例如退款/违规)",
"allOf": [
{
"$ref": "#/definitions/consts.ContentAccessStatus"
}
]
},
"tenant_id": {
"description": "租户ID多租户隔离与内容、用户归属一致",
"type": "integer"
},
"updated_at": {
"description": "更新时间:默认 now();更新 status 时写入",
"type": "string"
},
"user_id": {
"description": "用户ID权益所属用户用于访问校验",
"type": "integer"
}
}
},
@@ -1431,30 +1950,43 @@ const docTemplate = `{
"type": "object",
"properties": {
"asset_id": {
"description": "资源ID关联 media_assets.id用于查询资源归属内容",
"type": "integer"
},
"content_id": {
"description": "内容ID关联 contents.id用于查询内容下资源列表",
"type": "integer"
},
"created_at": {
"description": "创建时间:默认 now();用于审计",
"type": "string"
},
"id": {
"description": "主键ID自增",
"type": "integer"
},
"role": {
"$ref": "#/definitions/consts.ContentAssetRole"
"description": "资源角色main/cover/previewpreview 必须为独立资源以满足禁下载与防绕过",
"allOf": [
{
"$ref": "#/definitions/consts.ContentAssetRole"
}
]
},
"sort": {
"description": "排序:同一 role 下的展示顺序,数值越小越靠前",
"type": "integer"
},
"tenant_id": {
"description": "租户ID多租户隔离必须与 content_id、asset_id 所属租户一致",
"type": "integer"
},
"updated_at": {
"description": "更新时间:默认 now();更新 sort/role 时写入",
"type": "string"
},
"user_id": {
"description": "用户ID操作人/绑定人;用于审计(通常为租户管理员或作者)",
"type": "integer"
}
}
@@ -1463,39 +1995,59 @@ const docTemplate = `{
"type": "object",
"properties": {
"content_id": {
"description": "内容ID唯一约束 (tenant_id, content_id);一个内容在一个租户内仅一份定价",
"type": "integer"
},
"created_at": {
"description": "创建时间:默认 now();用于审计",
"type": "string"
},
"currency": {
"$ref": "#/definitions/consts.Currency"
"description": "币种:当前固定 CNY金额单位为分",
"allOf": [
{
"$ref": "#/definitions/consts.Currency"
}
]
},
"discount_end_at": {
"description": "折扣结束时间:可为空;为空表示长期有效(由业务逻辑解释)",
"type": "string"
},
"discount_start_at": {
"description": "折扣开始时间:可为空;为空表示立即生效(由业务逻辑解释)",
"type": "string"
},
"discount_type": {
"$ref": "#/definitions/consts.DiscountType"
"description": "折扣类型none/percent/amount仅影响下单时成交价需写入订单快照",
"allOf": [
{
"$ref": "#/definitions/consts.DiscountType"
}
]
},
"discount_value": {
"description": "折扣值percent=0-100按业务校验amount=分none 时忽略",
"type": "integer"
},
"id": {
"description": "主键ID自增",
"type": "integer"
},
"price_amount": {
"description": "基础价格0 表示免费(可直接访问正片资源)",
"type": "integer"
},
"tenant_id": {
"description": "租户ID多租户隔离与内容归属一致",
"type": "integer"
},
"updated_at": {
"description": "更新时间:默认 now();更新价格/折扣时写入",
"type": "string"
},
"user_id": {
"description": "用户ID设置/更新价格的操作人(通常为 tenant_admin用于审计",
"type": "integer"
}
}
@@ -1504,42 +2056,218 @@ const docTemplate = `{
"type": "object",
"properties": {
"bucket": {
"description": "存储桶:对象所在 bucket与 provider 组合确定存储定位",
"type": "string"
},
"created_at": {
"description": "创建时间:默认 now();用于审计与排序",
"type": "string"
},
"deleted_at": {
"$ref": "#/definitions/gorm.DeletedAt"
"description": "软删除时间:非空表示已删除;对外接口需过滤",
"allOf": [
{
"$ref": "#/definitions/gorm.DeletedAt"
}
]
},
"id": {
"description": "主键ID自增仅用于内部关联",
"type": "integer"
},
"meta": {
"description": "元数据JSON包含 hash、duration、width、height、bitrate、codec 等;用于展示与计费/风控",
"type": "array",
"items": {
"type": "integer"
}
},
"object_key": {
"description": "对象键:对象在 bucket 内的 key不得暴露可长期复用的直链通过签名URL/token下发",
"type": "string"
},
"provider": {
"description": "存储提供方:例如 s3/minio/oss便于多存储扩展",
"type": "string"
},
"status": {
"$ref": "#/definitions/consts.MediaAssetStatus"
"description": "处理状态uploaded/processing/ready/failed/deletedready 才可被内容引用对外提供",
"allOf": [
{
"$ref": "#/definitions/consts.MediaAssetStatus"
}
]
},
"tenant_id": {
"description": "租户ID多租户隔离关键字段所有查询/写入必须限定 tenant_id",
"type": "integer"
},
"type": {
"$ref": "#/definitions/consts.MediaAssetType"
"description": "资源类型video/audio/image决定后续处理流程转码/缩略图/封面等)",
"allOf": [
{
"$ref": "#/definitions/consts.MediaAssetType"
}
]
},
"updated_at": {
"description": "更新时间:默认 now();更新状态/元数据时写入",
"type": "string"
},
"user_id": {
"description": "用户ID资源上传者用于审计与权限控制",
"type": "integer"
}
}
},
"models.Order": {
"type": "object",
"properties": {
"amount_discount": {
"description": "优惠金额amount_paid = amount_original - amount_discount下单时快照",
"type": "integer"
},
"amount_original": {
"description": "原价金额:分;未折扣前金额(用于展示与对账)",
"type": "integer"
},
"amount_paid": {
"description": "实付金额:分;从租户内余额扣款的金额(下单时快照)",
"type": "integer"
},
"created_at": {
"description": "创建时间:默认 now();用于审计与排序",
"type": "string"
},
"currency": {
"description": "币种:当前固定 CNY金额单位为分",
"allOf": [
{
"$ref": "#/definitions/consts.Currency"
}
]
},
"id": {
"description": "主键ID自增用于关联订单明细、账本流水、权益等",
"type": "integer"
},
"idempotency_key": {
"description": "幂等键:同一租户同一用户同一业务请求可用;用于防重复下单/重复扣款(建议由客户端生成)",
"type": "string"
},
"items": {
"type": "array",
"items": {
"$ref": "#/definitions/models.OrderItem"
}
},
"paid_at": {
"description": "支付/扣款完成时间:余额支付在 debit_purchase 成功后写入",
"type": "string"
},
"refund_forced": {
"description": "是否强制退款true 表示租户管理侧绕过时间窗执行退款(需审计)",
"type": "boolean"
},
"refund_operator_user_id": {
"description": "退款操作人用户ID租户管理员/系统;用于审计与追责",
"type": "integer"
},
"refund_reason": {
"description": "退款原因:后台/用户发起退款的原因说明;用于审计",
"type": "string"
},
"refunded_at": {
"description": "退款完成时间:退款落账成功后写入",
"type": "string"
},
"snapshot": {
"description": "订单快照JSON建议包含 content 标题/定价/折扣、请求来源等,避免改价影响历史展示",
"type": "array",
"items": {
"type": "integer"
}
},
"status": {
"description": "订单状态created/paid/refunding/refunded/canceled/failed状态变更需与账本/权益保持一致",
"allOf": [
{
"$ref": "#/definitions/consts.OrderStatus"
}
]
},
"tenant_id": {
"description": "租户ID多租户隔离关键字段所有查询/写入必须限定 tenant_id",
"type": "integer"
},
"type": {
"description": "订单类型content_purchase购买内容/topup充值当前默认 content_purchase",
"allOf": [
{
"$ref": "#/definitions/consts.OrderType"
}
]
},
"updated_at": {
"description": "更新时间:默认 now();状态变更/退款写入时更新",
"type": "string"
},
"user_id": {
"description": "用户ID下单用户buyer余额扣款与权益归属以该 user_id 为准",
"type": "integer"
}
}
},
"models.OrderItem": {
"type": "object",
"properties": {
"amount_paid": {
"description": "该行实付金额:分;通常等于订单 amount_paid单内容场景",
"type": "integer"
},
"content": {
"$ref": "#/definitions/models.Content"
},
"content_id": {
"description": "内容ID关联 contents.id用于生成/撤销 content_access",
"type": "integer"
},
"content_user_id": {
"description": "内容作者用户ID用于后续分成/对账扩展;当前可为 0 或写入内容创建者",
"type": "integer"
},
"created_at": {
"description": "创建时间:默认 now()",
"type": "string"
},
"id": {
"description": "主键ID自增",
"type": "integer"
},
"order": {
"$ref": "#/definitions/models.Order"
},
"order_id": {
"description": "订单ID关联 orders.id用于聚合订单明细",
"type": "integer"
},
"snapshot": {
"description": "内容快照JSON建议包含 title/price/discount 等,用于历史展示与审计",
"type": "array",
"items": {
"type": "integer"
}
},
"tenant_id": {
"description": "租户ID多租户隔离关键字段必须与 orders.tenant_id 一致",
"type": "integer"
},
"updated_at": {
"description": "更新时间:默认 now()",
"type": "string"
},
"user_id": {
"description": "用户ID下单用户buyer冗余字段用于查询加速与审计",
"type": "integer"
}
}
@@ -1594,6 +2322,10 @@ const docTemplate = `{
"balance": {
"type": "integer"
},
"balance_frozen": {
"description": "冻结余额:分/最小货币单位;下单冻结时从可用余额转入,最终扣款或回滚时转出;默认 0",
"type": "integer"
},
"created_at": {
"type": "string"
},
@@ -1718,7 +2450,7 @@ const docTemplate = `{
var SwaggerInfo = &swag.Spec{
Version: "1.0",
Host: "localhost:8080",
BasePath: "/t/{tenantCode}/v1",
BasePath: "/",
Schemes: []string{},
Title: "ApiDoc",
Description: "Multi-tenant media platform backend API.",

View File

@@ -16,7 +16,7 @@
"version": "1.0"
},
"host": "localhost:8080",
"basePath": "/t/{tenantCode}/v1",
"basePath": "/",
"paths": {
"/super/v1/auth/login": {
"post": {
@@ -597,6 +597,176 @@
}
}
},
"/t/{tenantCode}/v1/admin/orders": {
"get": {
"consumes": [
"application/json"
],
"produces": [
"application/json"
],
"tags": [
"Tenant"
],
"summary": "订单列表(租户管理)",
"parameters": [
{
"type": "string",
"description": "Tenant Code",
"name": "tenantCode",
"in": "path",
"required": true
},
{
"type": "integer",
"description": "Limit is page size; only values in {10,20,50,100} are accepted (otherwise defaults to 10).",
"name": "limit",
"in": "query"
},
{
"type": "integer",
"description": "Page is 1-based page index; values \u003c= 0 are normalized to 1.",
"name": "page",
"in": "query"
},
{
"enum": [
"created",
"paid",
"refunding",
"refunded",
"canceled",
"failed"
],
"type": "string",
"x-enum-varnames": [
"OrderStatusCreated",
"OrderStatusPaid",
"OrderStatusRefunding",
"OrderStatusRefunded",
"OrderStatusCanceled",
"OrderStatusFailed"
],
"description": "Status filters orders by order status.",
"name": "status",
"in": "query"
},
{
"type": "integer",
"description": "UserID filters orders by buyer user id.",
"name": "user_id",
"in": "query"
}
],
"responses": {
"200": {
"description": "OK",
"schema": {
"allOf": [
{
"$ref": "#/definitions/requests.Pager"
},
{
"type": "object",
"properties": {
"items": {
"$ref": "#/definitions/models.Order"
}
}
}
]
}
}
}
}
},
"/t/{tenantCode}/v1/admin/orders/{orderID}": {
"get": {
"consumes": [
"application/json"
],
"produces": [
"application/json"
],
"tags": [
"Tenant"
],
"summary": "订单详情(租户管理)",
"parameters": [
{
"type": "string",
"description": "Tenant Code",
"name": "tenantCode",
"in": "path",
"required": true
},
{
"type": "integer",
"format": "int64",
"description": "OrderID",
"name": "orderID",
"in": "path",
"required": true
}
],
"responses": {
"200": {
"description": "OK",
"schema": {
"$ref": "#/definitions/dto.AdminOrderDetail"
}
}
}
}
},
"/t/{tenantCode}/v1/admin/orders/{orderID}/refund": {
"post": {
"consumes": [
"application/json"
],
"produces": [
"application/json"
],
"tags": [
"Tenant"
],
"summary": "订单退款(租户管理)",
"parameters": [
{
"type": "string",
"description": "Tenant Code",
"name": "tenantCode",
"in": "path",
"required": true
},
{
"type": "integer",
"format": "int64",
"description": "OrderID",
"name": "orderID",
"in": "path",
"required": true
},
{
"description": "Form",
"name": "form",
"in": "body",
"required": true,
"schema": {
"$ref": "#/definitions/dto.AdminOrderRefundForm"
}
}
],
"responses": {
"200": {
"description": "OK",
"schema": {
"$ref": "#/definitions/models.Order"
}
}
}
}
},
"/t/{tenantCode}/v1/contents": {
"get": {
"consumes": [
@@ -775,6 +945,54 @@
}
}
},
"/t/{tenantCode}/v1/contents/{contentID}/purchase": {
"post": {
"consumes": [
"application/json"
],
"produces": [
"application/json"
],
"tags": [
"Tenant"
],
"summary": "购买内容(余额支付)",
"parameters": [
{
"type": "string",
"description": "Tenant Code",
"name": "tenantCode",
"in": "path",
"required": true
},
{
"type": "integer",
"format": "int64",
"description": "ContentID",
"name": "contentID",
"in": "path",
"required": true
},
{
"description": "Form",
"name": "form",
"in": "body",
"required": true,
"schema": {
"$ref": "#/definitions/dto.PurchaseContentForm"
}
}
],
"responses": {
"200": {
"description": "OK",
"schema": {
"$ref": "#/definitions/dto.PurchaseContentResponse"
}
}
}
}
},
"/t/{tenantCode}/v1/me": {
"get": {
"consumes": [
@@ -805,9 +1023,138 @@
}
}
}
},
"/t/{tenantCode}/v1/orders": {
"get": {
"consumes": [
"application/json"
],
"produces": [
"application/json"
],
"tags": [
"Tenant"
],
"summary": "我的订单列表(当前租户)",
"parameters": [
{
"type": "string",
"description": "Tenant Code",
"name": "tenantCode",
"in": "path",
"required": true
},
{
"type": "integer",
"description": "Limit is page size; only values in {10,20,50,100} are accepted (otherwise defaults to 10).",
"name": "limit",
"in": "query"
},
{
"type": "integer",
"description": "Page is 1-based page index; values \u003c= 0 are normalized to 1.",
"name": "page",
"in": "query"
},
{
"enum": [
"created",
"paid",
"refunding",
"refunded",
"canceled",
"failed"
],
"type": "string",
"x-enum-varnames": [
"OrderStatusCreated",
"OrderStatusPaid",
"OrderStatusRefunding",
"OrderStatusRefunded",
"OrderStatusCanceled",
"OrderStatusFailed"
],
"description": "Status filters orders by order status.",
"name": "status",
"in": "query"
}
],
"responses": {
"200": {
"description": "OK",
"schema": {
"allOf": [
{
"$ref": "#/definitions/requests.Pager"
},
{
"type": "object",
"properties": {
"items": {
"$ref": "#/definitions/models.Order"
}
}
}
]
}
}
}
}
},
"/t/{tenantCode}/v1/orders/{orderID}": {
"get": {
"consumes": [
"application/json"
],
"produces": [
"application/json"
],
"tags": [
"Tenant"
],
"summary": "我的订单详情(当前租户)",
"parameters": [
{
"type": "string",
"description": "Tenant Code",
"name": "tenantCode",
"in": "path",
"required": true
},
{
"type": "integer",
"format": "int64",
"description": "OrderID",
"name": "orderID",
"in": "path",
"required": true
}
],
"responses": {
"200": {
"description": "OK",
"schema": {
"$ref": "#/definitions/models.Order"
}
}
}
}
}
},
"definitions": {
"consts.ContentAccessStatus": {
"type": "string",
"enum": [
"active",
"revoked",
"expired"
],
"x-enum-varnames": [
"ContentAccessStatusActive",
"ContentAccessStatusRevoked",
"ContentAccessStatusExpired"
]
},
"consts.ContentAssetRole": {
"type": "string",
"enum": [
@@ -903,6 +1250,36 @@
"MediaAssetTypeImage"
]
},
"consts.OrderStatus": {
"type": "string",
"enum": [
"created",
"paid",
"refunding",
"refunded",
"canceled",
"failed"
],
"x-enum-varnames": [
"OrderStatusCreated",
"OrderStatusPaid",
"OrderStatusRefunding",
"OrderStatusRefunded",
"OrderStatusCanceled",
"OrderStatusFailed"
]
},
"consts.OrderType": {
"type": "string",
"enum": [
"content_purchase",
"topup"
],
"x-enum-varnames": [
"OrderTypeContentPurchase",
"OrderTypeTopup"
]
},
"consts.Role": {
"type": "string",
"enum": [
@@ -951,6 +1328,36 @@
"UserStatusBanned"
]
},
"dto.AdminOrderDetail": {
"type": "object",
"properties": {
"order": {
"description": "Order is the order with items preloaded.",
"allOf": [
{
"$ref": "#/definitions/models.Order"
}
]
}
}
},
"dto.AdminOrderRefundForm": {
"type": "object",
"properties": {
"force": {
"description": "Force indicates bypassing the default refund window check (paid_at + 24h).\n强制退款true 表示绕过默认退款时间窗限制(需审计)。",
"type": "boolean"
},
"idempotency_key": {
"description": "IdempotencyKey ensures refund request is processed at most once.\n幂等键同一笔退款重复请求时返回一致结果避免重复退款/重复回滚。",
"type": "string"
},
"reason": {
"description": "Reason is the human-readable refund reason used for audit.\n退款原因建议必填由业务侧校验用于审计与追责。",
"type": "string"
}
}
},
"dto.ContentAssetAttachForm": {
"type": "object",
"properties": {
@@ -1189,6 +1596,48 @@
}
}
},
"dto.PurchaseContentForm": {
"type": "object",
"properties": {
"idempotency_key": {
"description": "IdempotencyKey is used to ensure the purchase request is processed at most once.\n建议由客户端生成并保持稳定同一笔购买重复请求时返回相同结果避免重复扣款/重复下单。",
"type": "string"
}
}
},
"dto.PurchaseContentResponse": {
"type": "object",
"properties": {
"access": {
"description": "Access is the content access record after purchase grant.",
"allOf": [
{
"$ref": "#/definitions/models.ContentAccess"
}
]
},
"amount_paid": {
"description": "AmountPaid is the final paid amount in cents (CNY 分).",
"type": "integer"
},
"item": {
"description": "Item is the single order item of this purchase (current implementation is 1 order -\u003e 1 content).",
"allOf": [
{
"$ref": "#/definitions/models.OrderItem"
}
]
},
"order": {
"description": "Order is the created or existing order record (may be nil for owner/free-path without order).",
"allOf": [
{
"$ref": "#/definitions/models.Order"
}
]
}
}
},
"dto.TenantExpireUpdateForm": {
"type": "object",
"required": [
@@ -1381,43 +1830,113 @@
"type": "object",
"properties": {
"created_at": {
"description": "创建时间:默认 now();用于审计与排序",
"type": "string"
},
"deleted_at": {
"$ref": "#/definitions/gorm.DeletedAt"
"description": "软删除时间:非空表示已删除;对外接口需过滤",
"allOf": [
{
"$ref": "#/definitions/gorm.DeletedAt"
}
]
},
"description": {
"description": "描述:用于详情页展示;可为空字符串",
"type": "string"
},
"id": {
"description": "主键ID自增用于内容引用",
"type": "integer"
},
"preview_downloadable": {
"description": "试看是否允许下载:默认 false当前策略固定为不允许下载仅 streaming",
"type": "boolean"
},
"preview_seconds": {
"description": "试看秒数:默认 60只对 preview 资源生效;必须为正整数",
"type": "integer"
},
"published_at": {
"description": "发布时间:首次发布时写入;用于时间窗与排序",
"type": "string"
},
"status": {
"$ref": "#/definitions/consts.ContentStatus"
"description": "状态draft/reviewing/published/unpublished/blockedpublished 才对外展示",
"allOf": [
{
"$ref": "#/definitions/consts.ContentStatus"
}
]
},
"tenant_id": {
"description": "租户ID多租户隔离关键字段所有查询/写入必须限定 tenant_id",
"type": "integer"
},
"title": {
"description": "标题:用于列表展示与搜索;建议限制长度(由业务校验)",
"type": "string"
},
"updated_at": {
"description": "更新时间:默认 now();编辑内容时写入",
"type": "string"
},
"user_id": {
"description": "用户ID内容创建者/发布者;用于权限与审计(例如私有内容仅作者可见)",
"type": "integer"
},
"visibility": {
"$ref": "#/definitions/consts.ContentVisibility"
"description": "可见性public/tenant_only/private仅控制详情可见正片资源仍需按价格/权益校验",
"allOf": [
{
"$ref": "#/definitions/consts.ContentVisibility"
}
]
}
}
},
"models.ContentAccess": {
"type": "object",
"properties": {
"content_id": {
"description": "内容ID权益对应内容唯一约束 (tenant_id, user_id, content_id)",
"type": "integer"
},
"created_at": {
"description": "创建时间:默认 now();用于审计",
"type": "string"
},
"id": {
"description": "主键ID自增",
"type": "integer"
},
"order_id": {
"description": "订单ID产生该权益的订单可为空例如后台补发/迁移)",
"type": "integer"
},
"revoked_at": {
"description": "撤销时间:当 status=revoked 时写入;用于审计与追责",
"type": "string"
},
"status": {
"description": "权益状态active/revoked/expiredrevoked 表示立即失效(例如退款/违规)",
"allOf": [
{
"$ref": "#/definitions/consts.ContentAccessStatus"
}
]
},
"tenant_id": {
"description": "租户ID多租户隔离与内容、用户归属一致",
"type": "integer"
},
"updated_at": {
"description": "更新时间:默认 now();更新 status 时写入",
"type": "string"
},
"user_id": {
"description": "用户ID权益所属用户用于访问校验",
"type": "integer"
}
}
},
@@ -1425,30 +1944,43 @@
"type": "object",
"properties": {
"asset_id": {
"description": "资源ID关联 media_assets.id用于查询资源归属内容",
"type": "integer"
},
"content_id": {
"description": "内容ID关联 contents.id用于查询内容下资源列表",
"type": "integer"
},
"created_at": {
"description": "创建时间:默认 now();用于审计",
"type": "string"
},
"id": {
"description": "主键ID自增",
"type": "integer"
},
"role": {
"$ref": "#/definitions/consts.ContentAssetRole"
"description": "资源角色main/cover/previewpreview 必须为独立资源以满足禁下载与防绕过",
"allOf": [
{
"$ref": "#/definitions/consts.ContentAssetRole"
}
]
},
"sort": {
"description": "排序:同一 role 下的展示顺序,数值越小越靠前",
"type": "integer"
},
"tenant_id": {
"description": "租户ID多租户隔离必须与 content_id、asset_id 所属租户一致",
"type": "integer"
},
"updated_at": {
"description": "更新时间:默认 now();更新 sort/role 时写入",
"type": "string"
},
"user_id": {
"description": "用户ID操作人/绑定人;用于审计(通常为租户管理员或作者)",
"type": "integer"
}
}
@@ -1457,39 +1989,59 @@
"type": "object",
"properties": {
"content_id": {
"description": "内容ID唯一约束 (tenant_id, content_id);一个内容在一个租户内仅一份定价",
"type": "integer"
},
"created_at": {
"description": "创建时间:默认 now();用于审计",
"type": "string"
},
"currency": {
"$ref": "#/definitions/consts.Currency"
"description": "币种:当前固定 CNY金额单位为分",
"allOf": [
{
"$ref": "#/definitions/consts.Currency"
}
]
},
"discount_end_at": {
"description": "折扣结束时间:可为空;为空表示长期有效(由业务逻辑解释)",
"type": "string"
},
"discount_start_at": {
"description": "折扣开始时间:可为空;为空表示立即生效(由业务逻辑解释)",
"type": "string"
},
"discount_type": {
"$ref": "#/definitions/consts.DiscountType"
"description": "折扣类型none/percent/amount仅影响下单时成交价需写入订单快照",
"allOf": [
{
"$ref": "#/definitions/consts.DiscountType"
}
]
},
"discount_value": {
"description": "折扣值percent=0-100按业务校验amount=分none 时忽略",
"type": "integer"
},
"id": {
"description": "主键ID自增",
"type": "integer"
},
"price_amount": {
"description": "基础价格0 表示免费(可直接访问正片资源)",
"type": "integer"
},
"tenant_id": {
"description": "租户ID多租户隔离与内容归属一致",
"type": "integer"
},
"updated_at": {
"description": "更新时间:默认 now();更新价格/折扣时写入",
"type": "string"
},
"user_id": {
"description": "用户ID设置/更新价格的操作人(通常为 tenant_admin用于审计",
"type": "integer"
}
}
@@ -1498,42 +2050,218 @@
"type": "object",
"properties": {
"bucket": {
"description": "存储桶:对象所在 bucket与 provider 组合确定存储定位",
"type": "string"
},
"created_at": {
"description": "创建时间:默认 now();用于审计与排序",
"type": "string"
},
"deleted_at": {
"$ref": "#/definitions/gorm.DeletedAt"
"description": "软删除时间:非空表示已删除;对外接口需过滤",
"allOf": [
{
"$ref": "#/definitions/gorm.DeletedAt"
}
]
},
"id": {
"description": "主键ID自增仅用于内部关联",
"type": "integer"
},
"meta": {
"description": "元数据JSON包含 hash、duration、width、height、bitrate、codec 等;用于展示与计费/风控",
"type": "array",
"items": {
"type": "integer"
}
},
"object_key": {
"description": "对象键:对象在 bucket 内的 key不得暴露可长期复用的直链通过签名URL/token下发",
"type": "string"
},
"provider": {
"description": "存储提供方:例如 s3/minio/oss便于多存储扩展",
"type": "string"
},
"status": {
"$ref": "#/definitions/consts.MediaAssetStatus"
"description": "处理状态uploaded/processing/ready/failed/deletedready 才可被内容引用对外提供",
"allOf": [
{
"$ref": "#/definitions/consts.MediaAssetStatus"
}
]
},
"tenant_id": {
"description": "租户ID多租户隔离关键字段所有查询/写入必须限定 tenant_id",
"type": "integer"
},
"type": {
"$ref": "#/definitions/consts.MediaAssetType"
"description": "资源类型video/audio/image决定后续处理流程转码/缩略图/封面等)",
"allOf": [
{
"$ref": "#/definitions/consts.MediaAssetType"
}
]
},
"updated_at": {
"description": "更新时间:默认 now();更新状态/元数据时写入",
"type": "string"
},
"user_id": {
"description": "用户ID资源上传者用于审计与权限控制",
"type": "integer"
}
}
},
"models.Order": {
"type": "object",
"properties": {
"amount_discount": {
"description": "优惠金额amount_paid = amount_original - amount_discount下单时快照",
"type": "integer"
},
"amount_original": {
"description": "原价金额:分;未折扣前金额(用于展示与对账)",
"type": "integer"
},
"amount_paid": {
"description": "实付金额:分;从租户内余额扣款的金额(下单时快照)",
"type": "integer"
},
"created_at": {
"description": "创建时间:默认 now();用于审计与排序",
"type": "string"
},
"currency": {
"description": "币种:当前固定 CNY金额单位为分",
"allOf": [
{
"$ref": "#/definitions/consts.Currency"
}
]
},
"id": {
"description": "主键ID自增用于关联订单明细、账本流水、权益等",
"type": "integer"
},
"idempotency_key": {
"description": "幂等键:同一租户同一用户同一业务请求可用;用于防重复下单/重复扣款(建议由客户端生成)",
"type": "string"
},
"items": {
"type": "array",
"items": {
"$ref": "#/definitions/models.OrderItem"
}
},
"paid_at": {
"description": "支付/扣款完成时间:余额支付在 debit_purchase 成功后写入",
"type": "string"
},
"refund_forced": {
"description": "是否强制退款true 表示租户管理侧绕过时间窗执行退款(需审计)",
"type": "boolean"
},
"refund_operator_user_id": {
"description": "退款操作人用户ID租户管理员/系统;用于审计与追责",
"type": "integer"
},
"refund_reason": {
"description": "退款原因:后台/用户发起退款的原因说明;用于审计",
"type": "string"
},
"refunded_at": {
"description": "退款完成时间:退款落账成功后写入",
"type": "string"
},
"snapshot": {
"description": "订单快照JSON建议包含 content 标题/定价/折扣、请求来源等,避免改价影响历史展示",
"type": "array",
"items": {
"type": "integer"
}
},
"status": {
"description": "订单状态created/paid/refunding/refunded/canceled/failed状态变更需与账本/权益保持一致",
"allOf": [
{
"$ref": "#/definitions/consts.OrderStatus"
}
]
},
"tenant_id": {
"description": "租户ID多租户隔离关键字段所有查询/写入必须限定 tenant_id",
"type": "integer"
},
"type": {
"description": "订单类型content_purchase购买内容/topup充值当前默认 content_purchase",
"allOf": [
{
"$ref": "#/definitions/consts.OrderType"
}
]
},
"updated_at": {
"description": "更新时间:默认 now();状态变更/退款写入时更新",
"type": "string"
},
"user_id": {
"description": "用户ID下单用户buyer余额扣款与权益归属以该 user_id 为准",
"type": "integer"
}
}
},
"models.OrderItem": {
"type": "object",
"properties": {
"amount_paid": {
"description": "该行实付金额:分;通常等于订单 amount_paid单内容场景",
"type": "integer"
},
"content": {
"$ref": "#/definitions/models.Content"
},
"content_id": {
"description": "内容ID关联 contents.id用于生成/撤销 content_access",
"type": "integer"
},
"content_user_id": {
"description": "内容作者用户ID用于后续分成/对账扩展;当前可为 0 或写入内容创建者",
"type": "integer"
},
"created_at": {
"description": "创建时间:默认 now()",
"type": "string"
},
"id": {
"description": "主键ID自增",
"type": "integer"
},
"order": {
"$ref": "#/definitions/models.Order"
},
"order_id": {
"description": "订单ID关联 orders.id用于聚合订单明细",
"type": "integer"
},
"snapshot": {
"description": "内容快照JSON建议包含 title/price/discount 等,用于历史展示与审计",
"type": "array",
"items": {
"type": "integer"
}
},
"tenant_id": {
"description": "租户ID多租户隔离关键字段必须与 orders.tenant_id 一致",
"type": "integer"
},
"updated_at": {
"description": "更新时间:默认 now()",
"type": "string"
},
"user_id": {
"description": "用户ID下单用户buyer冗余字段用于查询加速与审计",
"type": "integer"
}
}
@@ -1588,6 +2316,10 @@
"balance": {
"type": "integer"
},
"balance_frozen": {
"description": "冻结余额:分/最小货币单位;下单冻结时从可用余额转入,最终扣款或回滚时转出;默认 0",
"type": "integer"
},
"created_at": {
"type": "string"
},

View File

@@ -1,5 +1,15 @@
basePath: /t/{tenantCode}/v1
basePath: /
definitions:
consts.ContentAccessStatus:
enum:
- active
- revoked
- expired
type: string
x-enum-varnames:
- ContentAccessStatusActive
- ContentAccessStatusRevoked
- ContentAccessStatusExpired
consts.ContentAssetRole:
enum:
- main
@@ -74,6 +84,30 @@ definitions:
- MediaAssetTypeVideo
- MediaAssetTypeAudio
- MediaAssetTypeImage
consts.OrderStatus:
enum:
- created
- paid
- refunding
- refunded
- canceled
- failed
type: string
x-enum-varnames:
- OrderStatusCreated
- OrderStatusPaid
- OrderStatusRefunding
- OrderStatusRefunded
- OrderStatusCanceled
- OrderStatusFailed
consts.OrderType:
enum:
- content_purchase
- topup
type: string
x-enum-varnames:
- OrderTypeContentPurchase
- OrderTypeTopup
consts.Role:
enum:
- user
@@ -110,6 +144,31 @@ definitions:
- UserStatusPendingVerify
- UserStatusVerified
- UserStatusBanned
dto.AdminOrderDetail:
properties:
order:
allOf:
- $ref: '#/definitions/models.Order'
description: Order is the order with items preloaded.
type: object
dto.AdminOrderRefundForm:
properties:
force:
description: |-
Force indicates bypassing the default refund window check (paid_at + 24h).
强制退款true 表示绕过默认退款时间窗限制(需审计)。
type: boolean
idempotency_key:
description: |-
IdempotencyKey ensures refund request is processed at most once.
幂等键:同一笔退款重复请求时返回一致结果,避免重复退款/重复回滚。
type: string
reason:
description: |-
Reason is the human-readable refund reason used for audit.
退款原因:建议必填(由业务侧校验);用于审计与追责。
type: string
type: object
dto.ContentAssetAttachForm:
properties:
asset_id:
@@ -261,6 +320,34 @@ definitions:
- $ref: '#/definitions/models.User'
description: User is the authenticated user derived from JWT `user_id`.
type: object
dto.PurchaseContentForm:
properties:
idempotency_key:
description: |-
IdempotencyKey is used to ensure the purchase request is processed at most once.
建议由客户端生成并保持稳定:同一笔购买重复请求时返回相同结果,避免重复扣款/重复下单。
type: string
type: object
dto.PurchaseContentResponse:
properties:
access:
allOf:
- $ref: '#/definitions/models.ContentAccess'
description: Access is the content access record after purchase grant.
amount_paid:
description: AmountPaid is the final paid amount in cents (CNY 分).
type: integer
item:
allOf:
- $ref: '#/definitions/models.OrderItem'
description: Item is the single order item of this purchase (current implementation
is 1 order -> 1 content).
order:
allOf:
- $ref: '#/definitions/models.Order'
description: Order is the created or existing order record (may be nil for
owner/free-path without order).
type: object
dto.TenantExpireUpdateForm:
properties:
duration:
@@ -386,107 +473,298 @@ definitions:
models.Content:
properties:
created_at:
description: 创建时间:默认 now();用于审计与排序
type: string
deleted_at:
$ref: '#/definitions/gorm.DeletedAt'
allOf:
- $ref: '#/definitions/gorm.DeletedAt'
description: 软删除时间:非空表示已删除;对外接口需过滤
description:
description: 描述:用于详情页展示;可为空字符串
type: string
id:
description: 主键ID自增用于内容引用
type: integer
preview_downloadable:
description: 试看是否允许下载:默认 false当前策略固定为不允许下载仅 streaming
type: boolean
preview_seconds:
description: 试看秒数:默认 60只对 preview 资源生效;必须为正整数
type: integer
published_at:
description: 发布时间:首次发布时写入;用于时间窗与排序
type: string
status:
$ref: '#/definitions/consts.ContentStatus'
allOf:
- $ref: '#/definitions/consts.ContentStatus'
description: 状态draft/reviewing/published/unpublished/blockedpublished 才对外展示
tenant_id:
description: 租户ID多租户隔离关键字段所有查询/写入必须限定 tenant_id
type: integer
title:
description: 标题:用于列表展示与搜索;建议限制长度(由业务校验)
type: string
updated_at:
description: 更新时间:默认 now();编辑内容时写入
type: string
user_id:
description: 用户ID内容创建者/发布者;用于权限与审计(例如私有内容仅作者可见)
type: integer
visibility:
$ref: '#/definitions/consts.ContentVisibility'
allOf:
- $ref: '#/definitions/consts.ContentVisibility'
description: 可见性public/tenant_only/private仅控制详情可见正片资源仍需按价格/权益校验
type: object
models.ContentAccess:
properties:
content_id:
description: 内容ID权益对应内容唯一约束 (tenant_id, user_id, content_id)
type: integer
created_at:
description: 创建时间:默认 now();用于审计
type: string
id:
description: 主键ID自增
type: integer
order_id:
description: 订单ID产生该权益的订单可为空例如后台补发/迁移)
type: integer
revoked_at:
description: 撤销时间:当 status=revoked 时写入;用于审计与追责
type: string
status:
allOf:
- $ref: '#/definitions/consts.ContentAccessStatus'
description: 权益状态active/revoked/expiredrevoked 表示立即失效(例如退款/违规)
tenant_id:
description: 租户ID多租户隔离与内容、用户归属一致
type: integer
updated_at:
description: 更新时间:默认 now();更新 status 时写入
type: string
user_id:
description: 用户ID权益所属用户用于访问校验
type: integer
type: object
models.ContentAsset:
properties:
asset_id:
description: 资源ID关联 media_assets.id用于查询资源归属内容
type: integer
content_id:
description: 内容ID关联 contents.id用于查询内容下资源列表
type: integer
created_at:
description: 创建时间:默认 now();用于审计
type: string
id:
description: 主键ID自增
type: integer
role:
$ref: '#/definitions/consts.ContentAssetRole'
allOf:
- $ref: '#/definitions/consts.ContentAssetRole'
description: 资源角色main/cover/previewpreview 必须为独立资源以满足禁下载与防绕过
sort:
description: 排序:同一 role 下的展示顺序,数值越小越靠前
type: integer
tenant_id:
description: 租户ID多租户隔离必须与 content_id、asset_id 所属租户一致
type: integer
updated_at:
description: 更新时间:默认 now();更新 sort/role 时写入
type: string
user_id:
description: 用户ID操作人/绑定人;用于审计(通常为租户管理员或作者)
type: integer
type: object
models.ContentPrice:
properties:
content_id:
description: 内容ID唯一约束 (tenant_id, content_id);一个内容在一个租户内仅一份定价
type: integer
created_at:
description: 创建时间:默认 now();用于审计
type: string
currency:
$ref: '#/definitions/consts.Currency'
allOf:
- $ref: '#/definitions/consts.Currency'
description: 币种:当前固定 CNY金额单位为分
discount_end_at:
description: 折扣结束时间:可为空;为空表示长期有效(由业务逻辑解释)
type: string
discount_start_at:
description: 折扣开始时间:可为空;为空表示立即生效(由业务逻辑解释)
type: string
discount_type:
$ref: '#/definitions/consts.DiscountType'
allOf:
- $ref: '#/definitions/consts.DiscountType'
description: 折扣类型none/percent/amount仅影响下单时成交价需写入订单快照
discount_value:
description: 折扣值percent=0-100按业务校验amount=分none 时忽略
type: integer
id:
description: 主键ID自增
type: integer
price_amount:
description: 基础价格0 表示免费(可直接访问正片资源)
type: integer
tenant_id:
description: 租户ID多租户隔离与内容归属一致
type: integer
updated_at:
description: 更新时间:默认 now();更新价格/折扣时写入
type: string
user_id:
description: 用户ID设置/更新价格的操作人(通常为 tenant_admin用于审计
type: integer
type: object
models.MediaAsset:
properties:
bucket:
description: 存储桶:对象所在 bucket与 provider 组合确定存储定位
type: string
created_at:
description: 创建时间:默认 now();用于审计与排序
type: string
deleted_at:
$ref: '#/definitions/gorm.DeletedAt'
allOf:
- $ref: '#/definitions/gorm.DeletedAt'
description: 软删除时间:非空表示已删除;对外接口需过滤
id:
description: 主键ID自增仅用于内部关联
type: integer
meta:
description: 元数据JSON包含 hash、duration、width、height、bitrate、codec 等;用于展示与计费/风控
items:
type: integer
type: array
object_key:
description: 对象键:对象在 bucket 内的 key不得暴露可长期复用的直链通过签名URL/token下发
type: string
provider:
description: 存储提供方:例如 s3/minio/oss便于多存储扩展
type: string
status:
$ref: '#/definitions/consts.MediaAssetStatus'
allOf:
- $ref: '#/definitions/consts.MediaAssetStatus'
description: 处理状态uploaded/processing/ready/failed/deletedready 才可被内容引用对外提供
tenant_id:
description: 租户ID多租户隔离关键字段所有查询/写入必须限定 tenant_id
type: integer
type:
$ref: '#/definitions/consts.MediaAssetType'
allOf:
- $ref: '#/definitions/consts.MediaAssetType'
description: 资源类型video/audio/image决定后续处理流程转码/缩略图/封面等)
updated_at:
description: 更新时间:默认 now();更新状态/元数据时写入
type: string
user_id:
description: 用户ID资源上传者用于审计与权限控制
type: integer
type: object
models.Order:
properties:
amount_discount:
description: 优惠金额amount_paid = amount_original - amount_discount下单时快照
type: integer
amount_original:
description: 原价金额:分;未折扣前金额(用于展示与对账)
type: integer
amount_paid:
description: 实付金额:分;从租户内余额扣款的金额(下单时快照)
type: integer
created_at:
description: 创建时间:默认 now();用于审计与排序
type: string
currency:
allOf:
- $ref: '#/definitions/consts.Currency'
description: 币种:当前固定 CNY金额单位为分
id:
description: 主键ID自增用于关联订单明细、账本流水、权益等
type: integer
idempotency_key:
description: 幂等键:同一租户同一用户同一业务请求可用;用于防重复下单/重复扣款(建议由客户端生成)
type: string
items:
items:
$ref: '#/definitions/models.OrderItem'
type: array
paid_at:
description: 支付/扣款完成时间:余额支付在 debit_purchase 成功后写入
type: string
refund_forced:
description: 是否强制退款true 表示租户管理侧绕过时间窗执行退款(需审计)
type: boolean
refund_operator_user_id:
description: 退款操作人用户ID租户管理员/系统;用于审计与追责
type: integer
refund_reason:
description: 退款原因:后台/用户发起退款的原因说明;用于审计
type: string
refunded_at:
description: 退款完成时间:退款落账成功后写入
type: string
snapshot:
description: 订单快照JSON建议包含 content 标题/定价/折扣、请求来源等,避免改价影响历史展示
items:
type: integer
type: array
status:
allOf:
- $ref: '#/definitions/consts.OrderStatus'
description: 订单状态created/paid/refunding/refunded/canceled/failed状态变更需与账本/权益保持一致
tenant_id:
description: 租户ID多租户隔离关键字段所有查询/写入必须限定 tenant_id
type: integer
type:
allOf:
- $ref: '#/definitions/consts.OrderType'
description: 订单类型content_purchase购买内容/topup充值当前默认 content_purchase
updated_at:
description: 更新时间:默认 now();状态变更/退款写入时更新
type: string
user_id:
description: 用户ID下单用户buyer余额扣款与权益归属以该 user_id 为准
type: integer
type: object
models.OrderItem:
properties:
amount_paid:
description: 该行实付金额:分;通常等于订单 amount_paid单内容场景
type: integer
content:
$ref: '#/definitions/models.Content'
content_id:
description: 内容ID关联 contents.id用于生成/撤销 content_access
type: integer
content_user_id:
description: 内容作者用户ID用于后续分成/对账扩展;当前可为 0 或写入内容创建者
type: integer
created_at:
description: 创建时间:默认 now()
type: string
id:
description: 主键ID自增
type: integer
order:
$ref: '#/definitions/models.Order'
order_id:
description: 订单ID关联 orders.id用于聚合订单明细
type: integer
snapshot:
description: 内容快照JSON建议包含 title/price/discount 等,用于历史展示与审计
items:
type: integer
type: array
tenant_id:
description: 租户ID多租户隔离关键字段必须与 orders.tenant_id 一致
type: integer
updated_at:
description: 更新时间:默认 now()
type: string
user_id:
description: 用户ID下单用户buyer冗余字段用于查询加速与审计
type: integer
type: object
models.Tenant:
@@ -522,6 +800,9 @@ definitions:
properties:
balance:
type: integer
balance_frozen:
description: 冻结余额:分/最小货币单位;下单冻结时从可用余额转入,最终扣款或回滚时转出;默认 0
type: integer
created_at:
type: string
id:
@@ -992,6 +1273,120 @@ paths:
summary: 设置内容价格与折扣
tags:
- Tenant
/t/{tenantCode}/v1/admin/orders:
get:
consumes:
- application/json
parameters:
- description: Tenant Code
in: path
name: tenantCode
required: true
type: string
- description: Limit is page size; only values in {10,20,50,100} are accepted
(otherwise defaults to 10).
in: query
name: limit
type: integer
- description: Page is 1-based page index; values <= 0 are normalized to 1.
in: query
name: page
type: integer
- description: Status filters orders by order status.
enum:
- created
- paid
- refunding
- refunded
- canceled
- failed
in: query
name: status
type: string
x-enum-varnames:
- OrderStatusCreated
- OrderStatusPaid
- OrderStatusRefunding
- OrderStatusRefunded
- OrderStatusCanceled
- OrderStatusFailed
- description: UserID filters orders by buyer user id.
in: query
name: user_id
type: integer
produces:
- application/json
responses:
"200":
description: OK
schema:
allOf:
- $ref: '#/definitions/requests.Pager'
- properties:
items:
$ref: '#/definitions/models.Order'
type: object
summary: 订单列表(租户管理)
tags:
- Tenant
/t/{tenantCode}/v1/admin/orders/{orderID}:
get:
consumes:
- application/json
parameters:
- description: Tenant Code
in: path
name: tenantCode
required: true
type: string
- description: OrderID
format: int64
in: path
name: orderID
required: true
type: integer
produces:
- application/json
responses:
"200":
description: OK
schema:
$ref: '#/definitions/dto.AdminOrderDetail'
summary: 订单详情(租户管理)
tags:
- Tenant
/t/{tenantCode}/v1/admin/orders/{orderID}/refund:
post:
consumes:
- application/json
parameters:
- description: Tenant Code
in: path
name: tenantCode
required: true
type: string
- description: OrderID
format: int64
in: path
name: orderID
required: true
type: integer
- description: Form
in: body
name: form
required: true
schema:
$ref: '#/definitions/dto.AdminOrderRefundForm'
produces:
- application/json
responses:
"200":
description: OK
schema:
$ref: '#/definitions/models.Order'
summary: 订单退款(租户管理)
tags:
- Tenant
/t/{tenantCode}/v1/contents:
get:
consumes:
@@ -1108,6 +1503,38 @@ paths:
summary: 获取试看资源preview role
tags:
- Tenant
/t/{tenantCode}/v1/contents/{contentID}/purchase:
post:
consumes:
- application/json
parameters:
- description: Tenant Code
in: path
name: tenantCode
required: true
type: string
- description: ContentID
format: int64
in: path
name: contentID
required: true
type: integer
- description: Form
in: body
name: form
required: true
schema:
$ref: '#/definitions/dto.PurchaseContentForm'
produces:
- application/json
responses:
"200":
description: OK
schema:
$ref: '#/definitions/dto.PurchaseContentResponse'
summary: 购买内容(余额支付)
tags:
- Tenant
/t/{tenantCode}/v1/me:
get:
consumes:
@@ -1128,6 +1555,84 @@ paths:
summary: 当前租户上下文信息
tags:
- Tenant
/t/{tenantCode}/v1/orders:
get:
consumes:
- application/json
parameters:
- description: Tenant Code
in: path
name: tenantCode
required: true
type: string
- description: Limit is page size; only values in {10,20,50,100} are accepted
(otherwise defaults to 10).
in: query
name: limit
type: integer
- description: Page is 1-based page index; values <= 0 are normalized to 1.
in: query
name: page
type: integer
- description: Status filters orders by order status.
enum:
- created
- paid
- refunding
- refunded
- canceled
- failed
in: query
name: status
type: string
x-enum-varnames:
- OrderStatusCreated
- OrderStatusPaid
- OrderStatusRefunding
- OrderStatusRefunded
- OrderStatusCanceled
- OrderStatusFailed
produces:
- application/json
responses:
"200":
description: OK
schema:
allOf:
- $ref: '#/definitions/requests.Pager'
- properties:
items:
$ref: '#/definitions/models.Order'
type: object
summary: 我的订单列表(当前租户)
tags:
- Tenant
/t/{tenantCode}/v1/orders/{orderID}:
get:
consumes:
- application/json
parameters:
- description: Tenant Code
in: path
name: tenantCode
required: true
type: string
- description: OrderID
format: int64
in: path
name: orderID
required: true
type: integer
produces:
- application/json
responses:
"200":
description: OK
schema:
$ref: '#/definitions/models.Order'
summary: 我的订单详情(当前租户)
tags:
- Tenant
securityDefinitions:
BasicAuth:
type: basic