feat: 业务逻辑补全 — 佣金待审记录、C端订单重构、支付抽象、富友支付、卡设备状态联动
Some checks failed
构建并部署到测试环境(无 SSH) / build-and-deploy (push) Has been cancelled

F-1: 佣金链断裂时创建 status=99 零额待审记录,新增修正接口 POST /commission-records/:id/resolve
F-4: C端订单查询从 Handler 迁移至 Service 层,移除 SkipPermissionCtx
J-1: 富友支付 JSAPI/MiniApp 预下单实现,回调补全签名验证
J-2: 平台钱包代购支持(buyerType 为空时使用资产所属代理钱包)
J-3: 套餐激活后自动更新卡/设备 status=3,最后套餐过期后更新 status=4
支付抽象: 引入 PaymentProvider 接口 + 微信/富友适配器,CreateOrder 支持多支付渠道
修复: 设备/IoT卡响应 DTO 移除 omitempty,空值字段返回 null 而非省略
This commit is contained in:
2026-03-28 16:57:39 +08:00
parent 65e461eff7
commit 623a622298
26 changed files with 970 additions and 447 deletions

View File

@@ -80,7 +80,7 @@ type AssetRealtimeStatusResponse struct {
LastSyncTime *time.Time `json:"last_sync_time,omitempty" description:"最后同步时间asset_type=card时有效"`
DeviceProtectStatus string `json:"device_protect_status,omitempty" description:"保护期状态asset_type=device时有效none/stop/start"`
Cards []BoundCardInfo `json:"cards,omitempty" description:"绑定卡状态列表asset_type=device时有效"`
DeviceRealtime *DeviceGatewayInfo `json:"device_realtime,omitempty" description:"设备实时状态(来自 Gateway sync-infoGateway 失败时为 null"`
DeviceRealtime *DeviceGatewayInfo `json:"device_realtime" description:"设备实时状态(来自 Gateway sync-info始终返回,失败时仅含 gateway_msg"`
}
// AssetPackageResponse 资产套餐信息
@@ -144,8 +144,11 @@ type CardICCIDRequest struct {
// DeviceGatewayInfo B端设备实时状态信息来自 Gateway sync-info
// 与 C 端 DeviceRealtimeInfo 独立,未来可展示更多技术字段
// 所有字段均为可选Gateway 调用失败时整体为 null
// 所有字段均为可选Gateway 调用失败时仅填充 GatewayMsg
type DeviceGatewayInfo struct {
// Gateway 上游消息(成功时为 null失败时为错误信息
GatewayMsg *string `json:"gateway_msg" description:"Gateway 上游消息(成功时为 null失败时为错误信息"`
// 设备状态
OnlineStatus *int `json:"online_status,omitempty" description:"在线状态1=在线2=离线"`
BatteryLevel *int `json:"battery_level,omitempty" description:"电池电量百分比无电池时为null"`

View File

@@ -58,14 +58,16 @@ type AssetInfoResponse struct {
BoundDeviceNo string `json:"bound_device_no,omitempty" description:"绑定的设备虚拟号"`
BoundDeviceName string `json:"bound_device_name,omitempty" description:"绑定的设备名称"`
// === 设备实时状态(来自 Gateway同步接口对接后自动填充,当前返回 null ===
DeviceRealtime *DeviceRealtimeInfo `json:"device_realtime,omitempty" description:"设备实时状态Gateway 同步接口对接后填充,当前为 null"`
// === 设备实时状态(来自 Gateway始终返回,失败时仅含 gateway_msg ===
DeviceRealtime *DeviceRealtimeInfo `json:"device_realtime" description:"设备实时状态(始终返回,Gateway 失败时仅含 gateway_msg"`
}
// DeviceRealtimeInfo 设备实时状态信息
// 全量映射 Gateway DeviceInfoDetail 结构,所有字段均为可选
// 当前 Gateway 同步接口尚未对接,预留结构待后续填充
type DeviceRealtimeInfo struct {
GatewayMsg *string `json:"gateway_msg" description:"Gateway 上游消息(成功时为 null失败时为错误信息"`
// === 设备状态 ===
OnlineStatus *int64 `json:"online_status,omitempty" description:"在线状态1:在线, 2:离线)"`
BatteryLevel *int64 `json:"battery_level,omitempty" description:"电池电量百分比"`

View File

@@ -14,7 +14,7 @@ type CommissionRecordResponse struct {
CommissionSource string `json:"commission_source" description:"佣金来源 (cost_diff:成本价差, one_time:一次性佣金)"`
Amount int64 `json:"amount" description:"佣金金额(分)"`
BalanceAfter int64 `json:"balance_after" description:"入账后钱包余额(分)"`
Status int `json:"status" description:"状态 (1:已入账, 2:已失效)"`
Status int `json:"status" description:"状态 (1:已入账, 2:已失效, 99:待人工修正)"`
ReleasedAt string `json:"released_at" description:"入账时间"`
Remark string `json:"remark" description:"备注"`
CreatedAt string `json:"created_at" description:"创建时间"`
@@ -28,7 +28,7 @@ type CommissionRecordListRequest struct {
CommissionSource *string `json:"commission_source" query:"commission_source" validate:"omitempty,oneof=cost_diff one_time" description:"佣金来源 (cost_diff:成本价差, one_time:一次性佣金)"`
StartTime *string `json:"start_time" query:"start_time" validate:"omitempty" description:"开始时间"`
EndTime *string `json:"end_time" query:"end_time" validate:"omitempty" description:"结束时间"`
Status *int `json:"status" query:"status" validate:"omitempty,oneof=1 2" description:"状态 (1:已入账, 2:已失效)"`
Status *int `json:"status" query:"status" validate:"omitempty,oneof=1 2 99" description:"状态 (1:已入账, 2:已失效, 99:待人工修正)"`
}
// CommissionRecordPageResult 佣金记录分页结果
@@ -73,3 +73,10 @@ type DailyCommissionStatsRequest struct {
EndDate *string `json:"end_date" query:"end_date" validate:"omitempty" description:"结束日期YYYY-MM-DD"`
Days *int `json:"days" query:"days" validate:"omitempty,min=1,max=365" minimum:"1" maximum:"365" description:"查询天数默认30天"`
}
// CommissionRecordResolveRequest 佣金记录修正请求
type CommissionRecordResolveRequest struct {
Action string `json:"action" validate:"required,oneof=release invalidate" required:"true" description:"操作 (release:入账, invalidate:作废)"`
Amount *int64 `json:"amount" validate:"omitempty,min=1" minimum:"1" description:"佣金金额release 时必填"`
Remark string `json:"remark" validate:"omitempty,max=500" maxLength:"500" description:"处理备注"`
}

View File

@@ -28,24 +28,24 @@ type DeviceResponse struct {
MaxSimSlots int `json:"max_sim_slots" description:"最大插槽数"`
Manufacturer string `json:"manufacturer" description:"制造商"`
BatchNo string `json:"batch_no" description:"批次号"`
ShopID *uint `json:"shop_id,omitempty" description:"店铺ID"`
ShopName string `json:"shop_name,omitempty" description:"店铺名称"`
ShopID *uint `json:"shop_id" description:"店铺ID"`
ShopName string `json:"shop_name" description:"店铺名称"`
Status int `json:"status" description:"状态 (1:在库, 2:已分销, 3:已激活, 4:已停用)"`
StatusName string `json:"status_name" description:"状态名称"`
BoundCardCount int `json:"bound_card_count" description:"已绑定卡数量"`
SeriesID *uint `json:"series_id,omitempty" description:"套餐系列ID"`
SeriesName string `json:"series_name,omitempty" description:"套餐系列名称"`
SeriesID *uint `json:"series_id" description:"套餐系列ID"`
SeriesName string `json:"series_name" description:"套餐系列名称"`
FirstCommissionPaid bool `json:"first_commission_paid" description:"一次性佣金是否已发放"`
AccumulatedRecharge int64 `json:"accumulated_recharge" description:"累计充值金额(分)"`
ActivatedAt *time.Time `json:"activated_at,omitempty" description:"激活时间"`
ActivatedAt *time.Time `json:"activated_at" description:"激活时间"`
CreatedAt time.Time `json:"created_at" description:"创建时间"`
UpdatedAt time.Time `json:"updated_at" description:"更新时间"`
// 设备实时同步字段(由 sync-info 接口写入)
OnlineStatus int `json:"online_status" description:"在线状态0未知 1在线 2离线"`
LastOnlineTime *time.Time `json:"last_online_time,omitempty" description:"最后在线时间"`
LastOnlineTime *time.Time `json:"last_online_time" description:"最后在线时间"`
SoftwareVersion string `json:"software_version" description:"固件版本号"`
SwitchMode string `json:"switch_mode" description:"切卡模式0=自动1=手动"`
LastGatewaySyncAt *time.Time `json:"last_gateway_sync_at,omitempty" description:"最后 sync-info 同步时间"`
LastGatewaySyncAt *time.Time `json:"last_gateway_sync_at" description:"最后 sync-info 同步时间"`
}
type ListDeviceResponse struct {
@@ -78,10 +78,10 @@ type DeviceCardBindingResponse struct {
SlotPosition int `json:"slot_position" description:"插槽位置 (1-4)"`
IotCardID uint `json:"iot_card_id" description:"IoT卡ID"`
ICCID string `json:"iccid" description:"ICCID"`
MSISDN string `json:"msisdn,omitempty" description:"接入号"`
CarrierName string `json:"carrier_name,omitempty" description:"运营商名称"`
MSISDN string `json:"msisdn" description:"接入号"`
CarrierName string `json:"carrier_name" description:"运营商名称"`
Status int `json:"status" description:"卡状态 (1:在库, 2:已分销, 3:已激活, 4:已停用)"`
BindTime *time.Time `json:"bind_time,omitempty" description:"绑定时间"`
BindTime *time.Time `json:"bind_time" description:"绑定时间"`
IsCurrent bool `json:"is_current" description:"是否为当前使用的卡"`
}

View File

@@ -23,31 +23,31 @@ type ListStandaloneIotCardRequest struct {
type StandaloneIotCardResponse struct {
ID uint `json:"id" description:"卡ID"`
ICCID string `json:"iccid" description:"ICCID"`
VirtualNo string `json:"virtual_no,omitempty" description:"卡虚拟号(用于客服查找资产)"`
VirtualNo string `json:"virtual_no" description:"卡虚拟号(用于客服查找资产)"`
CardCategory string `json:"card_category" description:"卡业务类型 (normal:普通卡, industry:行业卡)"`
CarrierID uint `json:"carrier_id" description:"运营商ID"`
CarrierType string `json:"carrier_type,omitempty" description:"运营商类型 (CMCC:中国移动, CUCC:中国联通, CTCC:中国电信, CBN:中国广电)"`
CarrierName string `json:"carrier_name,omitempty" description:"运营商名称"`
IMSI string `json:"imsi,omitempty" description:"IMSI"`
MSISDN string `json:"msisdn,omitempty" description:"卡接入号"`
BatchNo string `json:"batch_no,omitempty" description:"批次号"`
Supplier string `json:"supplier,omitempty" description:"供应商"`
CarrierType string `json:"carrier_type" description:"运营商类型 (CMCC:中国移动, CUCC:中国联通, CTCC:中国电信, CBN:中国广电)"`
CarrierName string `json:"carrier_name" description:"运营商名称"`
IMSI string `json:"imsi" description:"IMSI"`
MSISDN string `json:"msisdn" description:"卡接入号"`
BatchNo string `json:"batch_no" description:"批次号"`
Supplier string `json:"supplier" description:"供应商"`
Status int `json:"status" description:"状态 (1:在库, 2:已分销, 3:已激活, 4:已停用)"`
ShopID *uint `json:"shop_id,omitempty" description:"店铺ID"`
ShopName string `json:"shop_name,omitempty" description:"店铺名称"`
ActivatedAt *time.Time `json:"activated_at,omitempty" description:"激活时间"`
ShopID *uint `json:"shop_id" description:"店铺ID"`
ShopName string `json:"shop_name" description:"店铺名称"`
ActivatedAt *time.Time `json:"activated_at" description:"激活时间"`
ActivationStatus int `json:"activation_status" description:"激活状态 (0:未激活, 1:已激活)"`
RealNameStatus int `json:"real_name_status" description:"实名状态 (0:未实名, 1:已实名)"`
NetworkStatus int `json:"network_status" description:"网络状态 (0:停机, 1:开机)"`
DataUsageMB int64 `json:"data_usage_mb" description:"累计流量使用(MB)"`
CurrentMonthUsageMB float64 `json:"current_month_usage_mb" description:"本月已用流量(MB)"`
CurrentMonthStartDate *time.Time `json:"current_month_start_date,omitempty" description:"本月开始日期"`
CurrentMonthStartDate *time.Time `json:"current_month_start_date" description:"本月开始日期"`
LastMonthTotalMB float64 `json:"last_month_total_mb" description:"上月流量总量(MB)"`
LastDataCheckAt *time.Time `json:"last_data_check_at,omitempty" description:"最后流量检查时间"`
LastRealNameCheckAt *time.Time `json:"last_real_name_check_at,omitempty" description:"最后实名检查时间"`
LastDataCheckAt *time.Time `json:"last_data_check_at" description:"最后流量检查时间"`
LastRealNameCheckAt *time.Time `json:"last_real_name_check_at" description:"最后实名检查时间"`
EnablePolling bool `json:"enable_polling" description:"是否参与轮询"`
SeriesID *uint `json:"series_id,omitempty" description:"套餐系列ID"`
SeriesName string `json:"series_name,omitempty" description:"套餐系列名称"`
SeriesID *uint `json:"series_id" description:"套餐系列ID"`
SeriesName string `json:"series_name" description:"套餐系列名称"`
FirstCommissionPaid bool `json:"first_commission_paid" description:"一次性佣金是否已发放"`
AccumulatedRecharge int64 `json:"accumulated_recharge" description:"累计充值金额(分)"`
CreatedAt time.Time `json:"created_at" description:"创建时间"`

View File

@@ -19,6 +19,15 @@ type WechatPayJSAPIResponse struct {
PayConfig map[string]interface{} `json:"pay_config" description:"JSSDK支付配置"`
}
type FuiouPayJSAPIResponse struct {
AppID string `json:"app_id" description:"应用ID"`
TimeStamp string `json:"time_stamp" description:"时间戳"`
NonceStr string `json:"nonce_str" description:"随机字符串"`
Package string `json:"package" description:"预支付参数包"`
SignType string `json:"sign_type" description:"签名类型"`
PaySign string `json:"pay_sign" description:"支付签名"`
}
type WechatPayH5Request struct {
SceneInfo WechatH5SceneInfo `json:"scene_info" validate:"required" required:"true" description:"场景信息"`
}