开放接口
This commit is contained in:
@@ -193,7 +193,7 @@ func initServices(s *stores, deps *Dependencies) *services {
|
|||||||
packageService := packageSvc.New(s.Package, s.PackageSeries, s.ShopPackageAllocation, s.ShopSeriesAllocation)
|
packageService := packageSvc.New(s.Package, s.PackageSeries, s.ShopPackageAllocation, s.ShopSeriesAllocation)
|
||||||
orderService := orderSvc.New(deps.DB, deps.Redis, s.Order, s.OrderItem, s.AgentWallet, s.AssetWallet, s.Payment, purchaseValidation, s.ShopPackageAllocation, s.ShopSeriesAllocation, s.IotCard, s.Device, s.PackageSeries, s.PackageUsage, s.Package, wechatConfig, deps.WechatPayment, paymentLoader, deps.QueueClient, deps.Logger, s.AssetIdentifier, s.PersonalCustomer, s.PersonalCustomerPhone)
|
orderService := orderSvc.New(deps.DB, deps.Redis, s.Order, s.OrderItem, s.AgentWallet, s.AssetWallet, s.Payment, purchaseValidation, s.ShopPackageAllocation, s.ShopSeriesAllocation, s.IotCard, s.Device, s.PackageSeries, s.PackageUsage, s.Package, wechatConfig, deps.WechatPayment, paymentLoader, deps.QueueClient, deps.Logger, s.AssetIdentifier, s.PersonalCustomer, s.PersonalCustomerPhone)
|
||||||
assetService := assetSvc.New(deps.DB, s.Device, s.IotCard, s.PackageUsage, s.Package, s.PackageSeries, s.DeviceSimBinding, s.Shop, deps.Redis, iotCard, deps.GatewayClient, s.AssetIdentifier, s.Order, s.OrderItem, s.ExchangeOrder)
|
assetService := assetSvc.New(deps.DB, s.Device, s.IotCard, s.PackageUsage, s.Package, s.PackageSeries, s.DeviceSimBinding, s.Shop, deps.Redis, iotCard, deps.GatewayClient, s.AssetIdentifier, s.Order, s.OrderItem, s.ExchangeOrder)
|
||||||
agentOpenAPI := agentOpenAPISvc.New(assetService, packageService, orderService, shopCommission, stopResumeService, s.IotCard, s.PackageUsage, s.Package, s.PackageSeries, s.AgentWallet)
|
agentOpenAPI := agentOpenAPISvc.New(assetService, packageService, orderService, shopCommission, stopResumeService, device, s.IotCard, s.PackageUsage, s.Package, s.PackageSeries, s.AgentWallet)
|
||||||
|
|
||||||
return &services{
|
return &services{
|
||||||
Account: account,
|
Account: account,
|
||||||
|
|||||||
@@ -160,6 +160,75 @@ func (h *Handler) ListWalletTransactions(c *fiber.Ctx) error {
|
|||||||
return response.SuccessWithPagination(c, result.Items, result.Total, result.Page, result.Size)
|
return response.SuccessWithPagination(c, result.Items, result.Total, result.Page, result.Size)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetDeviceTraffic 查询设备套餐内流量
|
||||||
|
// GET /api/open/v1/devices/traffic
|
||||||
|
func (h *Handler) GetDeviceTraffic(c *fiber.Ctx) error {
|
||||||
|
var req dto.AgentOpenAPIDeviceQueryRequest
|
||||||
|
if err := c.QueryParser(&req); err != nil {
|
||||||
|
return errors.New(errors.CodeInvalidParam)
|
||||||
|
}
|
||||||
|
if err := h.validate(&req); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
resp, err := h.service.GetDeviceTraffic(c.UserContext(), &req)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return response.Success(c, resp)
|
||||||
|
}
|
||||||
|
|
||||||
|
// SwitchDeviceCard 切网(多卡设备切换到指定 ICCID)
|
||||||
|
// POST /api/open/v1/devices/switch-card
|
||||||
|
func (h *Handler) SwitchDeviceCard(c *fiber.Ctx) error {
|
||||||
|
var req dto.AgentOpenAPIDeviceSwitchCardRequest
|
||||||
|
if err := c.BodyParser(&req); err != nil {
|
||||||
|
return errors.New(errors.CodeInvalidParam)
|
||||||
|
}
|
||||||
|
if err := h.validate(&req); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := h.service.SwitchDeviceCard(c.UserContext(), &req); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return response.Success(c, nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
// RebootDevice 重启设备
|
||||||
|
// POST /api/open/v1/devices/reboot
|
||||||
|
func (h *Handler) RebootDevice(c *fiber.Ctx) error {
|
||||||
|
var req dto.AgentOpenAPIDeviceOperationRequest
|
||||||
|
if err := c.BodyParser(&req); err != nil {
|
||||||
|
return errors.New(errors.CodeInvalidParam)
|
||||||
|
}
|
||||||
|
if err := h.validate(&req); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := h.service.RebootDevice(c.UserContext(), &req); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return response.Success(c, nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ResetDevice 恢复出厂设置
|
||||||
|
// POST /api/open/v1/devices/reset
|
||||||
|
func (h *Handler) ResetDevice(c *fiber.Ctx) error {
|
||||||
|
var req dto.AgentOpenAPIDeviceOperationRequest
|
||||||
|
if err := c.BodyParser(&req); err != nil {
|
||||||
|
return errors.New(errors.CodeInvalidParam)
|
||||||
|
}
|
||||||
|
if err := h.validate(&req); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := h.service.ResetDevice(c.UserContext(), &req); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return response.Success(c, nil)
|
||||||
|
}
|
||||||
|
|
||||||
func (h *Handler) validate(req any) error {
|
func (h *Handler) validate(req any) error {
|
||||||
if h.validator == nil {
|
if h.validator == nil {
|
||||||
return nil
|
return nil
|
||||||
|
|||||||
@@ -131,3 +131,30 @@ type AgentOpenAPIWalletPackageOrderResponse struct {
|
|||||||
Orders []AgentOpenAPIWalletPackageOrderItem `json:"orders" description:"成功订单列表"`
|
Orders []AgentOpenAPIWalletPackageOrderItem `json:"orders" description:"成功订单列表"`
|
||||||
FailedCards []AgentOpenAPIWalletPackageOrderFailure `json:"failed_cards" description:"失败卡列表"`
|
FailedCards []AgentOpenAPIWalletPackageOrderFailure `json:"failed_cards" description:"失败卡列表"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// AgentOpenAPIDeviceQueryRequest 开放接口设备查询请求
|
||||||
|
type AgentOpenAPIDeviceQueryRequest struct {
|
||||||
|
DeviceNo string `json:"device_no" query:"device_no" validate:"required,min=1,max=100" required:"true" minLength:"1" maxLength:"100" description:"设备标识(支持虚拟号、IMEI)"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// AgentOpenAPIDeviceSwitchCardRequest 开放接口设备切网请求
|
||||||
|
type AgentOpenAPIDeviceSwitchCardRequest struct {
|
||||||
|
DeviceNo string `json:"device_no" validate:"required,min=1,max=100" required:"true" minLength:"1" maxLength:"100" description:"设备标识(支持虚拟号、IMEI)"`
|
||||||
|
ICCID string `json:"iccid" validate:"required,min=1,max=100" required:"true" minLength:"1" maxLength:"100" description:"目标卡 ICCID"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// AgentOpenAPIDeviceOperationRequest 开放接口设备操作请求(重启/恢复出厂)
|
||||||
|
type AgentOpenAPIDeviceOperationRequest struct {
|
||||||
|
DeviceNo string `json:"device_no" validate:"required,min=1,max=100" required:"true" minLength:"1" maxLength:"100" description:"设备标识(支持虚拟号、IMEI)"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// AgentOpenAPIDeviceTrafficResponse 开放接口设备流量响应
|
||||||
|
type AgentOpenAPIDeviceTrafficResponse struct {
|
||||||
|
DeviceNo string `json:"device_no" description:"设备标识"`
|
||||||
|
ActiveRemainingFlowMB int64 `json:"active_remaining_flow_mb" description:"当前生效套餐剩余流量(MB)"`
|
||||||
|
ActiveTotalFlowMB int64 `json:"active_total_flow_mb" description:"当前生效套餐总流量(MB)"`
|
||||||
|
ActiveUsedFlowMB int64 `json:"active_used_flow_mb" description:"当前生效套餐已用流量(MB)"`
|
||||||
|
ActivePackages []AgentOpenAPIPackageTrafficItem `json:"active_packages" description:"当前生效套餐列表"`
|
||||||
|
PendingPackages []AgentOpenAPIPackageTrafficItem `json:"pending_packages" description:"待生效套餐列表"`
|
||||||
|
ActiveExpiresAt *time.Time `json:"active_expires_at,omitempty" description:"当前生效套餐最晚过期时间"`
|
||||||
|
}
|
||||||
|
|||||||
@@ -144,4 +144,37 @@ function buildAgentSign({ method, path, query, body, timestamp, nonce, account,
|
|||||||
Auth: true,
|
Auth: true,
|
||||||
SecurityScheme: openapi.SecuritySchemeAgentOpenAPI,
|
SecurityScheme: openapi.SecuritySchemeAgentOpenAPI,
|
||||||
})
|
})
|
||||||
|
Register(router, doc, basePath, "GET", "/devices/traffic", handler.GetDeviceTraffic, RouteSpec{
|
||||||
|
Summary: "查询设备套餐内流量",
|
||||||
|
Description: authDescription + "\n\n按 device_no 查询设备套餐内流量、当前套餐和待生效套餐。device_no 支持虚拟号、IMEI。",
|
||||||
|
Input: new(dto.AgentOpenAPIDeviceQueryRequest),
|
||||||
|
Output: new(dto.AgentOpenAPIDeviceTrafficResponse),
|
||||||
|
Tags: []string{tag},
|
||||||
|
Auth: true,
|
||||||
|
SecurityScheme: openapi.SecuritySchemeAgentOpenAPI,
|
||||||
|
})
|
||||||
|
Register(router, doc, basePath, "POST", "/devices/switch-card", handler.SwitchDeviceCard, RouteSpec{
|
||||||
|
Summary: "切网(多卡设备切换 ICCID)",
|
||||||
|
Description: authDescription + "\n\n按 device_no 将多卡设备切换到指定 ICCID 的卡。",
|
||||||
|
Input: new(dto.AgentOpenAPIDeviceSwitchCardRequest),
|
||||||
|
Tags: []string{tag},
|
||||||
|
Auth: true,
|
||||||
|
SecurityScheme: openapi.SecuritySchemeAgentOpenAPI,
|
||||||
|
})
|
||||||
|
Register(router, doc, basePath, "POST", "/devices/reboot", handler.RebootDevice, RouteSpec{
|
||||||
|
Summary: "重启设备",
|
||||||
|
Description: authDescription + "\n\n按 device_no 远程重启设备。",
|
||||||
|
Input: new(dto.AgentOpenAPIDeviceOperationRequest),
|
||||||
|
Tags: []string{tag},
|
||||||
|
Auth: true,
|
||||||
|
SecurityScheme: openapi.SecuritySchemeAgentOpenAPI,
|
||||||
|
})
|
||||||
|
Register(router, doc, basePath, "POST", "/devices/reset", handler.ResetDevice, RouteSpec{
|
||||||
|
Summary: "恢复出厂设置",
|
||||||
|
Description: authDescription + "\n\n按 device_no 远程恢复设备出厂设置。",
|
||||||
|
Input: new(dto.AgentOpenAPIDeviceOperationRequest),
|
||||||
|
Tags: []string{tag},
|
||||||
|
Auth: true,
|
||||||
|
SecurityScheme: openapi.SecuritySchemeAgentOpenAPI,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ import (
|
|||||||
"github.com/break/junhong_cmp_fiber/internal/model"
|
"github.com/break/junhong_cmp_fiber/internal/model"
|
||||||
"github.com/break/junhong_cmp_fiber/internal/model/dto"
|
"github.com/break/junhong_cmp_fiber/internal/model/dto"
|
||||||
assetSvc "github.com/break/junhong_cmp_fiber/internal/service/asset"
|
assetSvc "github.com/break/junhong_cmp_fiber/internal/service/asset"
|
||||||
|
deviceSvc "github.com/break/junhong_cmp_fiber/internal/service/device"
|
||||||
iotCardSvc "github.com/break/junhong_cmp_fiber/internal/service/iot_card"
|
iotCardSvc "github.com/break/junhong_cmp_fiber/internal/service/iot_card"
|
||||||
orderSvc "github.com/break/junhong_cmp_fiber/internal/service/order"
|
orderSvc "github.com/break/junhong_cmp_fiber/internal/service/order"
|
||||||
packageSvc "github.com/break/junhong_cmp_fiber/internal/service/package"
|
packageSvc "github.com/break/junhong_cmp_fiber/internal/service/package"
|
||||||
@@ -28,6 +29,7 @@ type Service struct {
|
|||||||
orderService *orderSvc.Service
|
orderService *orderSvc.Service
|
||||||
shopCommissionService *shopCommissionSvc.Service
|
shopCommissionService *shopCommissionSvc.Service
|
||||||
stopResumeService *iotCardSvc.StopResumeService
|
stopResumeService *iotCardSvc.StopResumeService
|
||||||
|
deviceService *deviceSvc.Service
|
||||||
iotCardStore *postgres.IotCardStore
|
iotCardStore *postgres.IotCardStore
|
||||||
packageUsageStore *postgres.PackageUsageStore
|
packageUsageStore *postgres.PackageUsageStore
|
||||||
packageStore *postgres.PackageStore
|
packageStore *postgres.PackageStore
|
||||||
@@ -42,6 +44,7 @@ func New(
|
|||||||
orderService *orderSvc.Service,
|
orderService *orderSvc.Service,
|
||||||
shopCommissionService *shopCommissionSvc.Service,
|
shopCommissionService *shopCommissionSvc.Service,
|
||||||
stopResumeService *iotCardSvc.StopResumeService,
|
stopResumeService *iotCardSvc.StopResumeService,
|
||||||
|
deviceService *deviceSvc.Service,
|
||||||
iotCardStore *postgres.IotCardStore,
|
iotCardStore *postgres.IotCardStore,
|
||||||
packageUsageStore *postgres.PackageUsageStore,
|
packageUsageStore *postgres.PackageUsageStore,
|
||||||
packageStore *postgres.PackageStore,
|
packageStore *postgres.PackageStore,
|
||||||
@@ -54,6 +57,7 @@ func New(
|
|||||||
orderService: orderService,
|
orderService: orderService,
|
||||||
shopCommissionService: shopCommissionService,
|
shopCommissionService: shopCommissionService,
|
||||||
stopResumeService: stopResumeService,
|
stopResumeService: stopResumeService,
|
||||||
|
deviceService: deviceService,
|
||||||
iotCardStore: iotCardStore,
|
iotCardStore: iotCardStore,
|
||||||
packageUsageStore: packageUsageStore,
|
packageUsageStore: packageUsageStore,
|
||||||
packageStore: packageStore,
|
packageStore: packageStore,
|
||||||
@@ -302,6 +306,112 @@ func (s *Service) CreateWalletPackageOrders(ctx context.Context, req *dto.AgentO
|
|||||||
return resp, nil
|
return resp, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// resolveOpenAPIDevice 将开放接口设备标识解析为当前代理可见的设备
|
||||||
|
// 设备不存在或不属于代理管辖店铺时统一返回 CodeForbidden,避免信息泄露
|
||||||
|
func (s *Service) resolveOpenAPIDevice(ctx context.Context, deviceNo string) (*model.Device, error) {
|
||||||
|
identifier := strings.TrimSpace(deviceNo)
|
||||||
|
if identifier == "" {
|
||||||
|
return nil, errors.New(errors.CodeInvalidParam)
|
||||||
|
}
|
||||||
|
if s.deviceService == nil {
|
||||||
|
return nil, errors.New(errors.CodeInternalError, "开放接口设备解析依赖未配置")
|
||||||
|
}
|
||||||
|
|
||||||
|
device, err := s.deviceService.GetDeviceByIdentifier(ctx, identifier)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.New(errors.CodeForbidden, "无权限操作该资源或资源不存在")
|
||||||
|
}
|
||||||
|
|
||||||
|
if device.ShopID == nil {
|
||||||
|
return nil, errors.New(errors.CodeForbidden, "无权限操作该资源或资源不存在")
|
||||||
|
}
|
||||||
|
|
||||||
|
subordinateIDs := middleware.GetSubordinateShopIDs(ctx)
|
||||||
|
found := false
|
||||||
|
for _, id := range subordinateIDs {
|
||||||
|
if id == *device.ShopID {
|
||||||
|
found = true
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if !found {
|
||||||
|
return nil, errors.New(errors.CodeForbidden, "无权限操作该资源或资源不存在")
|
||||||
|
}
|
||||||
|
|
||||||
|
return device, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetDeviceTraffic 查询开放接口设备套餐内流量
|
||||||
|
func (s *Service) GetDeviceTraffic(ctx context.Context, req *dto.AgentOpenAPIDeviceQueryRequest) (*dto.AgentOpenAPIDeviceTrafficResponse, error) {
|
||||||
|
device, err := s.resolveOpenAPIDevice(ctx, req.DeviceNo)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
activeStatus := constants.PackageUsageStatusActive
|
||||||
|
pendingStatus := constants.PackageUsageStatusPending
|
||||||
|
activeUsages, err := s.packageUsageStore.ListByCarrier(ctx, "device", device.ID, &activeStatus)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrap(errors.CodeInternalError, err, "查询生效套餐失败")
|
||||||
|
}
|
||||||
|
pendingUsages, err := s.packageUsageStore.ListByCarrier(ctx, "device", device.ID, &pendingStatus)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrap(errors.CodeInternalError, err, "查询待生效套餐失败")
|
||||||
|
}
|
||||||
|
|
||||||
|
packageMap, seriesMap, err := s.loadUsagePackageContext(ctx, append(activeUsages, pendingUsages...))
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
resp := &dto.AgentOpenAPIDeviceTrafficResponse{
|
||||||
|
DeviceNo: req.DeviceNo,
|
||||||
|
ActivePackages: make([]dto.AgentOpenAPIPackageTrafficItem, 0, len(activeUsages)),
|
||||||
|
PendingPackages: make([]dto.AgentOpenAPIPackageTrafficItem, 0, len(pendingUsages)),
|
||||||
|
}
|
||||||
|
for _, usage := range activeUsages {
|
||||||
|
item := s.buildTrafficItem(usage, packageMap, seriesMap, true)
|
||||||
|
resp.ActivePackages = append(resp.ActivePackages, item)
|
||||||
|
resp.ActiveTotalFlowMB += item.TotalFlowMB
|
||||||
|
resp.ActiveUsedFlowMB += item.UsedFlowMB
|
||||||
|
resp.ActiveRemainingFlowMB += item.RemainingFlowMB
|
||||||
|
if item.ExpiresAt != nil && (resp.ActiveExpiresAt == nil || item.ExpiresAt.After(*resp.ActiveExpiresAt)) {
|
||||||
|
resp.ActiveExpiresAt = item.ExpiresAt
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for _, usage := range pendingUsages {
|
||||||
|
resp.PendingPackages = append(resp.PendingPackages, s.buildTrafficItem(usage, packageMap, seriesMap, false))
|
||||||
|
}
|
||||||
|
|
||||||
|
return resp, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// SwitchDeviceCard 开放接口切网(多卡设备切换到指定 ICCID)
|
||||||
|
func (s *Service) SwitchDeviceCard(ctx context.Context, req *dto.AgentOpenAPIDeviceSwitchCardRequest) error {
|
||||||
|
if _, err := s.resolveOpenAPIDevice(ctx, req.DeviceNo); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return s.deviceService.GatewaySwitchCard(ctx, req.DeviceNo, &dto.SwitchCardRequest{
|
||||||
|
TargetICCID: req.ICCID,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// RebootDevice 开放接口重启设备
|
||||||
|
func (s *Service) RebootDevice(ctx context.Context, req *dto.AgentOpenAPIDeviceOperationRequest) error {
|
||||||
|
if _, err := s.resolveOpenAPIDevice(ctx, req.DeviceNo); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return s.deviceService.GatewayRebootDevice(ctx, req.DeviceNo)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ResetDevice 开放接口恢复出厂设置
|
||||||
|
func (s *Service) ResetDevice(ctx context.Context, req *dto.AgentOpenAPIDeviceOperationRequest) error {
|
||||||
|
if _, err := s.resolveOpenAPIDevice(ctx, req.DeviceNo); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return s.deviceService.GatewayResetDevice(ctx, req.DeviceNo)
|
||||||
|
}
|
||||||
|
|
||||||
// resolveOpenAPICard 将开放接口卡标识解析为当前代理可见的 IoT 卡
|
// resolveOpenAPICard 将开放接口卡标识解析为当前代理可见的 IoT 卡
|
||||||
func (s *Service) resolveOpenAPICard(ctx context.Context, cardNo string) (*model.IotCard, error) {
|
func (s *Service) resolveOpenAPICard(ctx context.Context, cardNo string) (*model.IotCard, error) {
|
||||||
identifier := strings.TrimSpace(cardNo)
|
identifier := strings.TrimSpace(cardNo)
|
||||||
|
|||||||
@@ -3,16 +3,16 @@
|
|||||||
"provider": {
|
"provider": {
|
||||||
"anthropic": {
|
"anthropic": {
|
||||||
"options": {
|
"options": {
|
||||||
"baseURL": "http://45.155.220.179:8317/v1",
|
"baseURL": "https://relay.apirelay.co/v1",
|
||||||
"apiKey": "sk-ZBGcMXCdwtSK7G35s"
|
"apiKey": "sk-f7176eb7ae4c39ed5e6f2946a1876d9bec38c54b60cb6fb2c13d639e77c4d7a5"
|
||||||
}
|
|
||||||
},
|
|
||||||
"openai": {
|
|
||||||
"options": {
|
|
||||||
"baseURL": "http://45.155.220.179:8317/v1",
|
|
||||||
"apiKey": "sk-ZBGcMXCdwtSK7G35s"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// "openai": {
|
||||||
|
// "options": {
|
||||||
|
// "baseURL": "https://relay.apirelay.co/v1",
|
||||||
|
// "apiKey": "sk-f7176eb7ae4c39ed5e6f2946a1876d9bec38c54b60cb6fb2c13d639e77c4d7a5"
|
||||||
|
// }
|
||||||
|
// }
|
||||||
},
|
},
|
||||||
"mcp": {
|
"mcp": {
|
||||||
"context7": {
|
"context7": {
|
||||||
|
|||||||
@@ -41,6 +41,22 @@ type walletPackageOrderRequest struct {
|
|||||||
PackageCode string `json:"package_code"`
|
PackageCode string `json:"package_code"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// cardResumeRequest 是"机卡分离卡复机"的请求体。
|
||||||
|
type cardResumeRequest struct {
|
||||||
|
CardNo string `json:"card_no"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// deviceSwitchCardRequest 是"设备切网"的请求体。
|
||||||
|
type deviceSwitchCardRequest struct {
|
||||||
|
DeviceNo string `json:"device_no"`
|
||||||
|
ICCID string `json:"iccid"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// deviceOperationRequest 是设备操作(重启/恢复出厂)的请求体。
|
||||||
|
type deviceOperationRequest struct {
|
||||||
|
DeviceNo string `json:"device_no"`
|
||||||
|
}
|
||||||
|
|
||||||
// client 是第三方调用方视角的独立客户端,不依赖当前项目内部代码。
|
// client 是第三方调用方视角的独立客户端,不依赖当前项目内部代码。
|
||||||
type client struct {
|
type client struct {
|
||||||
baseURL string
|
baseURL string
|
||||||
@@ -53,8 +69,10 @@ func main() {
|
|||||||
baseURL := flag.String("base-url", envOrDefault("AGENT_OPEN_API_BASE_URL", defaultBaseURL), "接口服务地址")
|
baseURL := flag.String("base-url", envOrDefault("AGENT_OPEN_API_BASE_URL", defaultBaseURL), "接口服务地址")
|
||||||
account := flag.String("account", envOrDefault("AGENT_OPEN_API_ACCOUNT", defaultAccount), "代理账号用户名或手机号")
|
account := flag.String("account", envOrDefault("AGENT_OPEN_API_ACCOUNT", defaultAccount), "代理账号用户名或手机号")
|
||||||
password := flag.String("password", envOrDefault("AGENT_OPEN_API_PASSWORD", defaultPassword), "代理账号登录密码")
|
password := flag.String("password", envOrDefault("AGENT_OPEN_API_PASSWORD", defaultPassword), "代理账号登录密码")
|
||||||
action := flag.String("action", "wallet-balance", "调用动作:realname-status、card-status、card-traffic、packages、wallet-balance、package-order、wallet-transactions")
|
action := flag.String("action", "wallet-balance", "调用动作:realname-status、card-status、card-traffic、card-resume、packages、wallet-balance、package-order、wallet-transactions、device-traffic、device-switch-card、device-reboot、device-reset")
|
||||||
cardNo := flag.String("card-no", "", "卡标识,支持 ICCID、虚拟号、MSISDN")
|
cardNo := flag.String("card-no", "", "卡标识,支持 ICCID、虚拟号、MSISDN")
|
||||||
|
deviceNo := flag.String("device-no", "", "设备标识,支持虚拟号、IMEI")
|
||||||
|
iccid := flag.String("iccid", "", "目标卡 ICCID,device-switch-card 时使用")
|
||||||
cardNos := flag.String("card-nos", "", "卡标识列表,多个值用英文逗号分隔")
|
cardNos := flag.String("card-nos", "", "卡标识列表,多个值用英文逗号分隔")
|
||||||
packageCode := flag.String("package-code", "", "套餐编码")
|
packageCode := flag.String("package-code", "", "套餐编码")
|
||||||
page := flag.Int("page", 0, "页码,不传或 0 表示省略")
|
page := flag.Int("page", 0, "页码,不传或 0 表示省略")
|
||||||
@@ -91,6 +109,8 @@ func main() {
|
|||||||
transactionType: *transactionType,
|
transactionType: *transactionType,
|
||||||
startDate: *startDate,
|
startDate: *startDate,
|
||||||
endDate: *endDate,
|
endDate: *endDate,
|
||||||
|
deviceNo: *deviceNo,
|
||||||
|
iccid: *iccid,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Fprintf(os.Stderr, "调用失败:%v\n", err)
|
fmt.Fprintf(os.Stderr, "调用失败:%v\n", err)
|
||||||
@@ -118,6 +138,8 @@ type runOptions struct {
|
|||||||
transactionType string
|
transactionType string
|
||||||
startDate string
|
startDate string
|
||||||
endDate string
|
endDate string
|
||||||
|
deviceNo string
|
||||||
|
iccid string
|
||||||
}
|
}
|
||||||
|
|
||||||
func dispatch(ctx context.Context, c *client, opts runOptions) (int, []byte, error) {
|
func dispatch(ctx context.Context, c *client, opts runOptions) (int, []byte, error) {
|
||||||
@@ -137,6 +159,11 @@ func dispatch(ctx context.Context, c *client, opts runOptions) (int, []byte, err
|
|||||||
return 0, nil, errors.New("card-traffic 需要传入 -card-no")
|
return 0, nil, errors.New("card-traffic 需要传入 -card-no")
|
||||||
}
|
}
|
||||||
return c.queryCardTraffic(ctx, opts.cardNo)
|
return c.queryCardTraffic(ctx, opts.cardNo)
|
||||||
|
case "card-resume":
|
||||||
|
if opts.cardNo == "" {
|
||||||
|
return 0, nil, errors.New("card-resume 需要传入 -card-no")
|
||||||
|
}
|
||||||
|
return c.resumeCard(ctx, opts.cardNo)
|
||||||
case "packages":
|
case "packages":
|
||||||
return c.queryPackages(ctx, packageQuery(opts))
|
return c.queryPackages(ctx, packageQuery(opts))
|
||||||
case "wallet-balance":
|
case "wallet-balance":
|
||||||
@@ -152,6 +179,29 @@ func dispatch(ctx context.Context, c *client, opts runOptions) (int, []byte, err
|
|||||||
return 0, nil, err
|
return 0, nil, err
|
||||||
}
|
}
|
||||||
return c.queryWalletTransactions(ctx, walletTransactionQuery(opts))
|
return c.queryWalletTransactions(ctx, walletTransactionQuery(opts))
|
||||||
|
case "device-traffic":
|
||||||
|
if opts.deviceNo == "" {
|
||||||
|
return 0, nil, errors.New("device-traffic 需要传入 -device-no")
|
||||||
|
}
|
||||||
|
return c.queryDeviceTraffic(ctx, opts.deviceNo)
|
||||||
|
case "device-switch-card":
|
||||||
|
if opts.deviceNo == "" {
|
||||||
|
return 0, nil, errors.New("device-switch-card 需要传入 -device-no")
|
||||||
|
}
|
||||||
|
if opts.iccid == "" {
|
||||||
|
return 0, nil, errors.New("device-switch-card 需要传入 -iccid")
|
||||||
|
}
|
||||||
|
return c.switchDeviceCard(ctx, opts.deviceNo, opts.iccid)
|
||||||
|
case "device-reboot":
|
||||||
|
if opts.deviceNo == "" {
|
||||||
|
return 0, nil, errors.New("device-reboot 需要传入 -device-no")
|
||||||
|
}
|
||||||
|
return c.rebootDevice(ctx, opts.deviceNo)
|
||||||
|
case "device-reset":
|
||||||
|
if opts.deviceNo == "" {
|
||||||
|
return 0, nil, errors.New("device-reset 需要传入 -device-no")
|
||||||
|
}
|
||||||
|
return c.resetDevice(ctx, opts.deviceNo)
|
||||||
default:
|
default:
|
||||||
return 0, nil, fmt.Errorf("未知 action:%s", opts.action)
|
return 0, nil, fmt.Errorf("未知 action:%s", opts.action)
|
||||||
}
|
}
|
||||||
@@ -191,6 +241,28 @@ func (c *client) queryWalletTransactions(ctx context.Context, query url.Values)
|
|||||||
return c.get(ctx, "/api/open/v1/wallet/transactions", query)
|
return c.get(ctx, "/api/open/v1/wallet/transactions", query)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *client) resumeCard(ctx context.Context, cardNo string) (int, []byte, error) {
|
||||||
|
return c.postJSON(ctx, "/api/open/v1/cards/resume", cardResumeRequest{CardNo: cardNo})
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *client) queryDeviceTraffic(ctx context.Context, deviceNo string) (int, []byte, error) {
|
||||||
|
query := url.Values{}
|
||||||
|
query.Add("device_no", deviceNo)
|
||||||
|
return c.get(ctx, "/api/open/v1/devices/traffic", query)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *client) switchDeviceCard(ctx context.Context, deviceNo string, iccid string) (int, []byte, error) {
|
||||||
|
return c.postJSON(ctx, "/api/open/v1/devices/switch-card", deviceSwitchCardRequest{DeviceNo: deviceNo, ICCID: iccid})
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *client) rebootDevice(ctx context.Context, deviceNo string) (int, []byte, error) {
|
||||||
|
return c.postJSON(ctx, "/api/open/v1/devices/reboot", deviceOperationRequest{DeviceNo: deviceNo})
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *client) resetDevice(ctx context.Context, deviceNo string) (int, []byte, error) {
|
||||||
|
return c.postJSON(ctx, "/api/open/v1/devices/reset", deviceOperationRequest{DeviceNo: deviceNo})
|
||||||
|
}
|
||||||
|
|
||||||
func (c *client) get(ctx context.Context, path string, query url.Values) (int, []byte, error) {
|
func (c *client) get(ctx context.Context, path string, query url.Values) (int, []byte, error) {
|
||||||
return c.do(ctx, http.MethodGet, path, query, nil)
|
return c.do(ctx, http.MethodGet, path, query, nil)
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user