init
This commit is contained in:
commit
144c1788f7
8
.idea/.gitignore
generated
vendored
Normal file
8
.idea/.gitignore
generated
vendored
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
# 默认忽略的文件
|
||||||
|
/shelf/
|
||||||
|
/workspace.xml
|
||||||
|
# 基于编辑器的 HTTP 客户端请求
|
||||||
|
/httpRequests/
|
||||||
|
# Datasource local storage ignored files
|
||||||
|
/dataSources/
|
||||||
|
/dataSources.local.xml
|
18
.idea/dataSources.xml
generated
Normal file
18
.idea/dataSources.xml
generated
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="DataSourceManagerImpl" format="xml" multifile-model="true">
|
||||||
|
<data-source source="LOCAL" name="110.40.44.75" uuid="2a0dbdb2-3d96-4e1b-bb48-f766f88518a6">
|
||||||
|
<driver-ref>mysql.8</driver-ref>
|
||||||
|
<synchronize>true</synchronize>
|
||||||
|
<jdbc-driver>com.mysql.cj.jdbc.Driver</jdbc-driver>
|
||||||
|
<jdbc-url>jdbc:mysql://110.40.44.75:3306</jdbc-url>
|
||||||
|
<jdbc-additional-properties>
|
||||||
|
<property name="com.intellij.clouds.kubernetes.db.host.port" />
|
||||||
|
<property name="com.intellij.clouds.kubernetes.db.enabled" value="false" />
|
||||||
|
<property name="com.intellij.clouds.kubernetes.db.resource.type" value="Deployment" />
|
||||||
|
<property name="com.intellij.clouds.kubernetes.db.container.port" />
|
||||||
|
</jdbc-additional-properties>
|
||||||
|
<working-dir>$ProjectFileDir$</working-dir>
|
||||||
|
</data-source>
|
||||||
|
</component>
|
||||||
|
</project>
|
9
.idea/hk.iml
generated
Normal file
9
.idea/hk.iml
generated
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<module type="WEB_MODULE" version="4">
|
||||||
|
<component name="Go" enabled="true" />
|
||||||
|
<component name="NewModuleRootManager">
|
||||||
|
<content url="file://$MODULE_DIR$" />
|
||||||
|
<orderEntry type="inheritedJdk" />
|
||||||
|
<orderEntry type="sourceFolder" forTests="false" />
|
||||||
|
</component>
|
||||||
|
</module>
|
8
.idea/modules.xml
generated
Normal file
8
.idea/modules.xml
generated
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="ProjectModuleManager">
|
||||||
|
<modules>
|
||||||
|
<module fileurl="file://$PROJECT_DIR$/.idea/hk.iml" filepath="$PROJECT_DIR$/.idea/hk.iml" />
|
||||||
|
</modules>
|
||||||
|
</component>
|
||||||
|
</project>
|
6
.idea/sqldialects.xml
generated
Normal file
6
.idea/sqldialects.xml
generated
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="SqlDialectMappings">
|
||||||
|
<file url="PROJECT" dialect="MySQL" />
|
||||||
|
</component>
|
||||||
|
</project>
|
6
.idea/vcs.xml
generated
Normal file
6
.idea/vcs.xml
generated
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="VcsDirectoryMappings">
|
||||||
|
<mapping directory="$PROJECT_DIR$" vcs="Git" />
|
||||||
|
</component>
|
||||||
|
</project>
|
103
doc/api.api
Normal file
103
doc/api.api
Normal file
@ -0,0 +1,103 @@
|
|||||||
|
syntax = "v1"
|
||||||
|
|
||||||
|
info (
|
||||||
|
title: "type title here"
|
||||||
|
desc: "type desc here"
|
||||||
|
author: "DevTTL"
|
||||||
|
email: "admin@devttl.com"
|
||||||
|
version: "v0.1"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Order172 {
|
||||||
|
OrderNo string `json:"OrderNo"` // Y 合作方订单号
|
||||||
|
OrderNo172 string `json:"OrderNo172"` // Y 172平台订单号,请求头sign里加密的是这个号码。
|
||||||
|
OrderStatus string `json:"OrderStatus"` // Y 订单状态:已发货,已完成,审核不通过,已取消,已撤单
|
||||||
|
ThirdPhone string `json:"ThirdPhone"` // N 办理号码
|
||||||
|
ExpressName string `json:"ExpressName"` // N 物流公司
|
||||||
|
ExpressCode string `json:"ExpressCode"` // N 物流单号
|
||||||
|
CardStatus string `json:"CardStatus"` // N 激活状态:已激活,未激活,可能为Null
|
||||||
|
ActiveTime string `json:"ActiveTime"` // N 激活时间格式yyyy-MM-dd HH:mm:ss,可能为Null
|
||||||
|
Remark string `json:"Remark"` // N 备注失败原因
|
||||||
|
}
|
||||||
|
|
||||||
|
type PushReq {
|
||||||
|
RequidId string `json:"RequidId"` // Y 推送请求唯一ID
|
||||||
|
Data Order172 `json:"Data"` // Y 返回订单信息
|
||||||
|
}
|
||||||
|
|
||||||
|
type Push172Resp {
|
||||||
|
Code int64 `json:"code",options=-1|0` // Y 响应码 -1错误 0正常
|
||||||
|
Msg string `json:"message"` // Y 错误信息
|
||||||
|
}
|
||||||
|
|
||||||
|
type GoodsItem {
|
||||||
|
Id int64 `json:"id"` // Y 商品ID
|
||||||
|
Name string `json:"name"` // Y 商品信息
|
||||||
|
MainPic string `json:"mainPic"` // Y 主图
|
||||||
|
DisableAge string `json:"disableAge"` // Y 年龄限制
|
||||||
|
UniFlow string `json:"uniFlow"` // Y 通用流量
|
||||||
|
DirFlow string `json:"dirFlow"` // Y 定向流量
|
||||||
|
TalkTime string `json:"talkTime"` // Y 通话时长
|
||||||
|
Remarks string `json:"remarks"` // Y 备注
|
||||||
|
}
|
||||||
|
|
||||||
|
type (
|
||||||
|
GoodsListReq {
|
||||||
|
Type string `json:"type":"type,default=0"` // Y 运营商 0:全部 1:电信 2:联通 3:移动 4:光电
|
||||||
|
}
|
||||||
|
GoodsListResp {
|
||||||
|
Data []GoodsItem `json:"data"`
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
type (
|
||||||
|
GoodsDetailsReq {
|
||||||
|
Id int64 `path:"id"`
|
||||||
|
}
|
||||||
|
GoodsDetailsResp {
|
||||||
|
Data GoodsItem `json:"data"` // Y 商品详情
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
type (
|
||||||
|
TiktokReq {
|
||||||
|
VideoUrl string `from:"videoUrl"` // 视频地址
|
||||||
|
}
|
||||||
|
TiktokResp {
|
||||||
|
AuthorID string `json:"authorId"` // 作者ID
|
||||||
|
AuthorUniqueID string `json:"authorUniqueId"` // 作者账号
|
||||||
|
AuthorAvatar string `json:"authorAvatar"` // 作者头像
|
||||||
|
AuthorNickname string `json:"authorNickname"` // 作者昵称
|
||||||
|
VideoID string `json:"videoId"` // 视频ID
|
||||||
|
VideoTitle string `json:"videoTitle"` // 作品描述
|
||||||
|
OriginCover string `json:"originCover"` // 静态封面
|
||||||
|
DynamicCover string `json:"dynamicCover"` // 动态封面
|
||||||
|
DestinationURL string `json:"destinationUrl"` // 无水印下载地址
|
||||||
|
WatermarkVideoURL string `json:"watermarkVideoUrl"` // 有水印下载地址
|
||||||
|
MusicURL string `json:"musicUrl"` // 背景音乐链接
|
||||||
|
OriginalURL string `json:"originalUrl"` // 原始下载链接
|
||||||
|
DownloaderURL string `json:"downloaderUrl"` // 解析后下载地址
|
||||||
|
CreateTime string `json:"createTime"` // 创建时间
|
||||||
|
Result bool `json:"result"` // 结果
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
@server (
|
||||||
|
group: api
|
||||||
|
prefix: api
|
||||||
|
middleware: RealIPMiddleware
|
||||||
|
)
|
||||||
|
service api {
|
||||||
|
@handler tiktokInfo
|
||||||
|
post /tiktok/getVideoInfo (TiktokReq) returns (TiktokResp)
|
||||||
|
|
||||||
|
@handler order172
|
||||||
|
post /push/order172 (PushReq) returns (Push172Resp)
|
||||||
|
|
||||||
|
@handler goodsList
|
||||||
|
get /goods/list (GoodsListReq) returns (GoodsListResp)
|
||||||
|
|
||||||
|
@handler goodsDetails
|
||||||
|
get /goods/:id (GoodsDetailsReq) returns (GoodsDetailsResp)
|
||||||
|
}
|
||||||
|
|
8
doc/sql/config_api.sql
Normal file
8
doc/sql/config_api.sql
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
CREATE TABLE `config_api`
|
||||||
|
(
|
||||||
|
`id` bigint auto_increment NOT NULL COMMENT '主键ID',
|
||||||
|
`type` varchar(255) NOT NULL COMMENT '接口类型 0:172',
|
||||||
|
`key` varchar(20) DEFAULT NULL COMMENT 'key',
|
||||||
|
`secret` varchar(100) DEFAULT NULL COMMENT '密钥',
|
||||||
|
primary key (id)
|
||||||
|
) COMMENT ='API配置表';
|
28
doc/sql/goods_info.sql
Normal file
28
doc/sql/goods_info.sql
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
CREATE TABLE `goods_info`
|
||||||
|
(
|
||||||
|
`id` bigint NOT NULL auto_increment COMMENT '主键ID',
|
||||||
|
`type` char(1) NOT NULL default '0' COMMENT '运营商 0:未标注 1:电信 2:联通 3:移动 4:光电',
|
||||||
|
`name` varchar(255) NOT NULL COMMENT '商品名',
|
||||||
|
`main_pic` varchar(1000) NOT NULL COMMENT '主图',
|
||||||
|
`little_picture` varchar(1000) DEFAULT '' COMMENT '详情图',
|
||||||
|
`netAddr` VARCHAR(255) DEFAULT '' COMMENT '商品套餐资料介绍地址',
|
||||||
|
`area` VARCHAR(10) DEFAULT '' COMMENT '归属地',
|
||||||
|
|
||||||
|
`uni_flow` VARCHAR(10) DEFAULT '' COMMENT '通用流量',
|
||||||
|
`dir_flow` VARCHAR(10) DEFAULT '' COMMENT '定向流量',
|
||||||
|
`talk_time` VARCHAR(10) DEFAULT '' COMMENT '通话时间',
|
||||||
|
|
||||||
|
`disable_area` VARCHAR(1000) DEFAULT '' COMMENT '禁发地区',
|
||||||
|
`disable_age` VARCHAR(100) DEFAULT '' COMMENT '年龄限制',
|
||||||
|
`disable_contract` VARCHAR(10) DEFAULT '' COMMENT '合约期',
|
||||||
|
`notes` text COMMENT '商品说明',
|
||||||
|
|
||||||
|
`api_id` bigint DEFAULT NULL COMMENT '三方接口',
|
||||||
|
`api_product_id` bigint DEFAULT NULL COMMENT '三方商品id',
|
||||||
|
`number_sel` char(1) NOT NULL DEFAULT '0' COMMENT '是否选号 0:不支持 1:收货地不是归属地 2:收货地是归属地',
|
||||||
|
`status` char(1) NOT NULL DEFAULT '0' COMMENT '状态 0:上架 1:下架',
|
||||||
|
`create_time` datetime NOT NULL default current_timestamp() comment '创建时间',
|
||||||
|
`update_time` datetime NOT NULL default current_timestamp() on update current_timestamp() comment '更新时间',
|
||||||
|
`remarks` VARCHAR(255) DEFAULT NULL COMMENT '备注',
|
||||||
|
primary key (id)
|
||||||
|
) COMMENT '商品列表 ';
|
8
doc/sql/goods_status.sql
Normal file
8
doc/sql/goods_status.sql
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
CREATE TABLE `goods_status`
|
||||||
|
(
|
||||||
|
`id` int(10) NOT NULL AUTO_INCREMENT COMMENT 'id',
|
||||||
|
`api_id` int(255) DEFAULT NULL COMMENT '三方接口',
|
||||||
|
`api_product_id` int(255) DEFAULT NULL COMMENT '三方商品id',
|
||||||
|
`status` int(10) DEFAULT NULL COMMENT '商品状态 0=上架 1=下架',
|
||||||
|
primary key (id)
|
||||||
|
) COMMENT '商品状态';
|
22
doc/sql/oder_info.sql
Normal file
22
doc/sql/oder_info.sql
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
CREATE TABLE `oder_info`
|
||||||
|
(
|
||||||
|
`id` bigint NOT NULL COMMENT '订单id',
|
||||||
|
`oder_id` varchar(50) NOT NULL COMMENT '订单id',
|
||||||
|
`goods_id` varchar(50) NOT NULL COMMENT '下单产品ID',
|
||||||
|
`name` varchar(30) NOT NULL COMMENT '姓名',
|
||||||
|
`id_card` varchar(18) NOT NULL COMMENT '身份证号',
|
||||||
|
`phone` varchar(15) NOT NULL COMMENT '手机号码',
|
||||||
|
`province` varchar(20) NOT NULL COMMENT '省',
|
||||||
|
`city` varchar(20) NOT NULL COMMENT '城市',
|
||||||
|
`area` varchar(20) NOT NULL COMMENT '区/县/镇',
|
||||||
|
`address` varchar(100) NOT NULL COMMENT '详细地址',
|
||||||
|
`status` char(1) NOT NULL DEFAULT '0' COMMENT '发货处理状态:0=未处理,1=已下单 2=已发货 3已完成 4失败',
|
||||||
|
`api_id` varchar(255) DEFAULT NULL COMMENT '接口来源',
|
||||||
|
`api_oder_id` varchar(255) DEFAULT NULL COMMENT '第三方订单',
|
||||||
|
`third_phone` varchar(255) DEFAULT NULL COMMENT '用户办理的号码',
|
||||||
|
`card_status` char(1) DEFAULT '0' COMMENT '号码状态',
|
||||||
|
`create_time` datetime NOT NULL default current_timestamp() comment '创建时间',
|
||||||
|
`update_time` datetime NOT NULL default current_timestamp() on update current_timestamp() comment '更新时间',
|
||||||
|
`remarks` varchar(255) DEFAULT NULL COMMENT '备注',
|
||||||
|
primary key (id)
|
||||||
|
) COMMENT '订单列表';
|
53
go.mod
Normal file
53
go.mod
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
module hk
|
||||||
|
|
||||||
|
go 1.23.4
|
||||||
|
|
||||||
|
require (
|
||||||
|
github.com/robfig/cron/v3 v3.0.1
|
||||||
|
github.com/zeromicro/go-zero v1.8.0
|
||||||
|
)
|
||||||
|
|
||||||
|
require (
|
||||||
|
filippo.io/edwards25519 v1.1.0 // indirect
|
||||||
|
github.com/beorn7/perks v1.0.1 // indirect
|
||||||
|
github.com/cenkalti/backoff/v4 v4.3.0 // indirect
|
||||||
|
github.com/cespare/xxhash/v2 v2.3.0 // indirect
|
||||||
|
github.com/fatih/color v1.18.0 // indirect
|
||||||
|
github.com/go-logr/logr v1.4.2 // indirect
|
||||||
|
github.com/go-logr/stdr v1.2.2 // indirect
|
||||||
|
github.com/go-sql-driver/mysql v1.8.1 // indirect
|
||||||
|
github.com/golang-jwt/jwt/v4 v4.5.1 // indirect
|
||||||
|
github.com/google/uuid v1.6.0 // indirect
|
||||||
|
github.com/grpc-ecosystem/grpc-gateway/v2 v2.20.0 // indirect
|
||||||
|
github.com/klauspost/compress v1.17.9 // indirect
|
||||||
|
github.com/mattn/go-colorable v0.1.13 // indirect
|
||||||
|
github.com/mattn/go-isatty v0.0.20 // indirect
|
||||||
|
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
|
||||||
|
github.com/openzipkin/zipkin-go v0.4.3 // indirect
|
||||||
|
github.com/pelletier/go-toml/v2 v2.2.2 // indirect
|
||||||
|
github.com/prometheus/client_golang v1.20.5 // indirect
|
||||||
|
github.com/prometheus/client_model v0.6.1 // indirect
|
||||||
|
github.com/prometheus/common v0.55.0 // indirect
|
||||||
|
github.com/prometheus/procfs v0.15.1 // indirect
|
||||||
|
github.com/spaolacci/murmur3 v1.1.0 // indirect
|
||||||
|
go.opentelemetry.io/otel v1.24.0 // indirect
|
||||||
|
go.opentelemetry.io/otel/exporters/jaeger v1.17.0 // indirect
|
||||||
|
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.24.0 // indirect
|
||||||
|
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.24.0 // indirect
|
||||||
|
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.24.0 // indirect
|
||||||
|
go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.24.0 // indirect
|
||||||
|
go.opentelemetry.io/otel/exporters/zipkin v1.24.0 // indirect
|
||||||
|
go.opentelemetry.io/otel/metric v1.24.0 // indirect
|
||||||
|
go.opentelemetry.io/otel/sdk v1.24.0 // indirect
|
||||||
|
go.opentelemetry.io/otel/trace v1.24.0 // indirect
|
||||||
|
go.opentelemetry.io/proto/otlp v1.3.1 // indirect
|
||||||
|
go.uber.org/automaxprocs v1.6.0 // indirect
|
||||||
|
golang.org/x/net v0.34.0 // indirect
|
||||||
|
golang.org/x/sys v0.29.0 // indirect
|
||||||
|
golang.org/x/text v0.21.0 // indirect
|
||||||
|
google.golang.org/genproto/googleapis/api v0.0.0-20240711142825-46eb208f015d // indirect
|
||||||
|
google.golang.org/genproto/googleapis/rpc v0.0.0-20240701130421-f6361c86f094 // indirect
|
||||||
|
google.golang.org/grpc v1.65.0 // indirect
|
||||||
|
google.golang.org/protobuf v1.36.4 // indirect
|
||||||
|
gopkg.in/yaml.v2 v2.4.0 // indirect
|
||||||
|
)
|
136
go.sum
Normal file
136
go.sum
Normal file
@ -0,0 +1,136 @@
|
|||||||
|
filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA=
|
||||||
|
filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4=
|
||||||
|
github.com/DATA-DOG/go-sqlmock v1.5.2 h1:OcvFkGmslmlZibjAjaHm3L//6LiuBgolP7OputlJIzU=
|
||||||
|
github.com/DATA-DOG/go-sqlmock v1.5.2/go.mod h1:88MAG/4G7SMwSE3CeA0ZKzrT5CiOU3OJ+JlNzwDqpNU=
|
||||||
|
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
|
||||||
|
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
|
||||||
|
github.com/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8=
|
||||||
|
github.com/cenkalti/backoff/v4 v4.3.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE=
|
||||||
|
github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs=
|
||||||
|
github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
||||||
|
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
|
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||||
|
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
|
github.com/fatih/color v1.18.0 h1:S8gINlzdQ840/4pfAwic/ZE0djQEH3wM94VfqLTZcOM=
|
||||||
|
github.com/fatih/color v1.18.0/go.mod h1:4FelSpRwEGDpQ12mAdzqdOukCy4u8WUtOY6lkT/6HfU=
|
||||||
|
github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
|
||||||
|
github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY=
|
||||||
|
github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
|
||||||
|
github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
|
||||||
|
github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
|
||||||
|
github.com/go-sql-driver/mysql v1.8.1 h1:LedoTUt/eveggdHS9qUFC1EFSa8bU2+1pZjSRpvNJ1Y=
|
||||||
|
github.com/go-sql-driver/mysql v1.8.1/go.mod h1:wEBSXgmK//2ZFJyE+qWnIsVGmvmEKlqwuVSjsCm7DZg=
|
||||||
|
github.com/golang-jwt/jwt/v4 v4.5.1 h1:JdqV9zKUdtaa9gdPlywC3aeoEsR681PlKC+4F5gQgeo=
|
||||||
|
github.com/golang-jwt/jwt/v4 v4.5.1/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0=
|
||||||
|
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
|
||||||
|
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||||
|
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
|
||||||
|
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||||
|
github.com/grpc-ecosystem/grpc-gateway/v2 v2.20.0 h1:bkypFPDjIYGfCYD5mRBvpqxfYX1YCS1PXdKYWi8FsN0=
|
||||||
|
github.com/grpc-ecosystem/grpc-gateway/v2 v2.20.0/go.mod h1:P+Lt/0by1T8bfcF3z737NnSbmxQAppXMRziHUxPOC8k=
|
||||||
|
github.com/h2non/parth v0.0.0-20190131123155-b4df798d6542 h1:2VTzZjLZBgl62/EtslCrtky5vbi9dd7HrQPQIx6wqiw=
|
||||||
|
github.com/h2non/parth v0.0.0-20190131123155-b4df798d6542/go.mod h1:Ow0tF8D4Kplbc8s8sSb3V2oUCygFHVp8gC3Dn6U4MNI=
|
||||||
|
github.com/klauspost/compress v1.17.9 h1:6KIumPrER1LHsvBVuDa0r5xaG0Es51mhhB9BQB2qeMA=
|
||||||
|
github.com/klauspost/compress v1.17.9/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw=
|
||||||
|
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
|
||||||
|
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
|
||||||
|
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
||||||
|
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
|
||||||
|
github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc=
|
||||||
|
github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw=
|
||||||
|
github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
|
||||||
|
github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
|
||||||
|
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
|
||||||
|
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
|
||||||
|
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
|
||||||
|
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA=
|
||||||
|
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
|
||||||
|
github.com/openzipkin/zipkin-go v0.4.3 h1:9EGwpqkgnwdEIJ+Od7QVSEIH+ocmm5nPat0G7sjsSdg=
|
||||||
|
github.com/openzipkin/zipkin-go v0.4.3/go.mod h1:M9wCJZFWCo2RiY+o1eBCEMe0Dp2S5LDHcMZmk3RmK7c=
|
||||||
|
github.com/pelletier/go-toml/v2 v2.2.2 h1:aYUidT7k73Pcl9nb2gScu7NSrKCSHIDE89b3+6Wq+LM=
|
||||||
|
github.com/pelletier/go-toml/v2 v2.2.2/go.mod h1:1t835xjRzz80PqgE6HHgN2JOsmgYu/h4qDAS4n929Rs=
|
||||||
|
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||||
|
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||||
|
github.com/prashantv/gostub v1.1.0 h1:BTyx3RfQjRHnUWaGF9oQos79AlQ5k8WNktv7VGvVH4g=
|
||||||
|
github.com/prashantv/gostub v1.1.0/go.mod h1:A5zLQHz7ieHGG7is6LLXLz7I8+3LZzsrV0P1IAHhP5U=
|
||||||
|
github.com/prometheus/client_golang v1.20.5 h1:cxppBPuYhUnsO6yo/aoRol4L7q7UFfdm+bR9r+8l63Y=
|
||||||
|
github.com/prometheus/client_golang v1.20.5/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE=
|
||||||
|
github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E=
|
||||||
|
github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY=
|
||||||
|
github.com/prometheus/common v0.55.0 h1:KEi6DK7lXW/m7Ig5i47x0vRzuBsHuvJdi5ee6Y3G1dc=
|
||||||
|
github.com/prometheus/common v0.55.0/go.mod h1:2SECS4xJG1kd8XF9IcM1gMX6510RAEL65zxzNImwdc8=
|
||||||
|
github.com/prometheus/procfs v0.15.1 h1:YagwOFzUgYfKKHX6Dr+sHT7km/hxC76UB0learggepc=
|
||||||
|
github.com/prometheus/procfs v0.15.1/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoGhij/e3PBqk=
|
||||||
|
github.com/robfig/cron/v3 v3.0.1 h1:WdRxkvbJztn8LMz/QEvLN5sBU+xKpSqwwUO1Pjr4qDs=
|
||||||
|
github.com/robfig/cron/v3 v3.0.1/go.mod h1:eQICP3HwyT7UooqI/z+Ov+PtYAWygg1TEWWzGIFLtro=
|
||||||
|
github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ=
|
||||||
|
github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog=
|
||||||
|
github.com/spaolacci/murmur3 v1.1.0 h1:7c1g84S4BPRrfL5Xrdp6fOJ206sU9y293DDHaoy0bLI=
|
||||||
|
github.com/spaolacci/murmur3 v1.1.0/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
|
||||||
|
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||||
|
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
|
||||||
|
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
|
||||||
|
github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY=
|
||||||
|
github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA=
|
||||||
|
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||||
|
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
|
||||||
|
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
|
||||||
|
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
||||||
|
github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
|
||||||
|
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
||||||
|
github.com/zeromicro/go-zero v1.8.0 h1:4g/8VW+fOyM51HZYPeI3mXIZdEX+Fl6SsdYX2H5PYw4=
|
||||||
|
github.com/zeromicro/go-zero v1.8.0/go.mod h1:xDBF+/iDzj30zPvu6HNUIbpz1J6+/g3Sx9D/DytJfss=
|
||||||
|
go.opentelemetry.io/otel v1.24.0 h1:0LAOdjNmQeSTzGBzduGe/rU4tZhMwL5rWgtp9Ku5Jfo=
|
||||||
|
go.opentelemetry.io/otel v1.24.0/go.mod h1:W7b9Ozg4nkF5tWI5zsXkaKKDjdVjpD4oAt9Qi/MArHo=
|
||||||
|
go.opentelemetry.io/otel/exporters/jaeger v1.17.0 h1:D7UpUy2Xc2wsi1Ras6V40q806WM07rqoCWzXu7Sqy+4=
|
||||||
|
go.opentelemetry.io/otel/exporters/jaeger v1.17.0/go.mod h1:nPCqOnEH9rNLKqH/+rrUjiMzHJdV1BlpKcTwRTyKkKI=
|
||||||
|
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.24.0 h1:t6wl9SPayj+c7lEIFgm4ooDBZVb01IhLB4InpomhRw8=
|
||||||
|
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.24.0/go.mod h1:iSDOcsnSA5INXzZtwaBPrKp/lWu/V14Dd+llD0oI2EA=
|
||||||
|
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.24.0 h1:Mw5xcxMwlqoJd97vwPxA8isEaIoxsta9/Q51+TTJLGE=
|
||||||
|
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.24.0/go.mod h1:CQNu9bj7o7mC6U7+CA/schKEYakYXWr79ucDHTMGhCM=
|
||||||
|
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.24.0 h1:Xw8U6u2f8DK2XAkGRFV7BBLENgnTGX9i4rQRxJf+/vs=
|
||||||
|
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.24.0/go.mod h1:6KW1Fm6R/s6Z3PGXwSJN2K4eT6wQB3vXX6CVnYX9NmM=
|
||||||
|
go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.24.0 h1:s0PHtIkN+3xrbDOpt2M8OTG92cWqUESvzh2MxiR5xY8=
|
||||||
|
go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.24.0/go.mod h1:hZlFbDbRt++MMPCCfSJfmhkGIWnX1h3XjkfxZUjLrIA=
|
||||||
|
go.opentelemetry.io/otel/exporters/zipkin v1.24.0 h1:3evrL5poBuh1KF51D9gO/S+N/1msnm4DaBqs/rpXUqY=
|
||||||
|
go.opentelemetry.io/otel/exporters/zipkin v1.24.0/go.mod h1:0EHgD8R0+8yRhUYJOGR8Hfg2dpiJQxDOszd5smVO9wM=
|
||||||
|
go.opentelemetry.io/otel/metric v1.24.0 h1:6EhoGWWK28x1fbpA4tYTOWBkPefTDQnb8WSGXlc88kI=
|
||||||
|
go.opentelemetry.io/otel/metric v1.24.0/go.mod h1:VYhLe1rFfxuTXLgj4CBiyz+9WYBA8pNGJgDcSFRKBco=
|
||||||
|
go.opentelemetry.io/otel/sdk v1.24.0 h1:YMPPDNymmQN3ZgczicBY3B6sf9n62Dlj9pWD3ucgoDw=
|
||||||
|
go.opentelemetry.io/otel/sdk v1.24.0/go.mod h1:KVrIYw6tEubO9E96HQpcmpTKDVn9gdv35HoYiQWGDFg=
|
||||||
|
go.opentelemetry.io/otel/trace v1.24.0 h1:CsKnnL4dUAr/0llH9FKuc698G04IrpWV0MQA/Y1YELI=
|
||||||
|
go.opentelemetry.io/otel/trace v1.24.0/go.mod h1:HPc3Xr/cOApsBI154IU0OI0HJexz+aw5uPdbs3UCjNU=
|
||||||
|
go.opentelemetry.io/proto/otlp v1.3.1 h1:TrMUixzpM0yuc/znrFTP9MMRh8trP93mkCiDVeXrui0=
|
||||||
|
go.opentelemetry.io/proto/otlp v1.3.1/go.mod h1:0X1WI4de4ZsLrrJNLAQbFeLCm3T7yBkR0XqQ7niQU+8=
|
||||||
|
go.uber.org/automaxprocs v1.6.0 h1:O3y2/QNTOdbF+e/dpXNNW7Rx2hZ4sTIPyybbxyNqTUs=
|
||||||
|
go.uber.org/automaxprocs v1.6.0/go.mod h1:ifeIMSnPZuznNm6jmdzmU3/bfk01Fe2fotchwEFJ8r8=
|
||||||
|
go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
|
||||||
|
go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE=
|
||||||
|
golang.org/x/net v0.34.0 h1:Mb7Mrk043xzHgnRM88suvJFwzVrRfHEHJEl5/71CKw0=
|
||||||
|
golang.org/x/net v0.34.0/go.mod h1:di0qlW3YNM5oh6GqDGQr92MyTozJPmybPK4Ev/Gm31k=
|
||||||
|
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/sys v0.29.0 h1:TPYlXGxvx1MGTn2GiZDhnjPA9wZzZeGKHHmKhHYvgaU=
|
||||||
|
golang.org/x/sys v0.29.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||||
|
golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo=
|
||||||
|
golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ=
|
||||||
|
google.golang.org/genproto/googleapis/api v0.0.0-20240711142825-46eb208f015d h1:kHjw/5UfflP/L5EbledDrcG4C2597RtymmGRZvHiCuY=
|
||||||
|
google.golang.org/genproto/googleapis/api v0.0.0-20240711142825-46eb208f015d/go.mod h1:mw8MG/Qz5wfgYr6VqVCiZcHe/GJEfI+oGGDCohaVgB0=
|
||||||
|
google.golang.org/genproto/googleapis/rpc v0.0.0-20240701130421-f6361c86f094 h1:BwIjyKYGsK9dMCBOorzRri8MQwmi7mT9rGHsCEinZkA=
|
||||||
|
google.golang.org/genproto/googleapis/rpc v0.0.0-20240701130421-f6361c86f094/go.mod h1:Ue6ibwXGpU+dqIcODieyLOcgj7z8+IcskoNIgZxtrFY=
|
||||||
|
google.golang.org/grpc v1.65.0 h1:bs/cUb4lp1G5iImFFd3u5ixQzweKizoZJAwBNLR42lc=
|
||||||
|
google.golang.org/grpc v1.65.0/go.mod h1:WgYC2ypjlB0EiQi6wdKixMqukr6lBc0Vo+oOgjrM5ZQ=
|
||||||
|
google.golang.org/protobuf v1.36.4 h1:6A3ZDJHn/eNqc1i+IdefRzy/9PokBTPvcqMySR7NNIM=
|
||||||
|
google.golang.org/protobuf v1.36.4/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE=
|
||||||
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
|
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
|
||||||
|
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
|
||||||
|
gopkg.in/h2non/gock.v1 v1.1.2 h1:jBbHXgGBK/AoPVfJh5x4r/WxIrElvbLel8TCZkkZJoY=
|
||||||
|
gopkg.in/h2non/gock.v1 v1.1.2/go.mod h1:n7UGz/ckNChHiK05rDoiC4MYSunEC/lyaUm2WWaDva0=
|
||||||
|
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
|
||||||
|
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
|
||||||
|
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
|
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||||
|
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
|
k8s.io/utils v0.0.0-20240711033017-18e509b52bc8 h1:pUdcCO1Lk/tbT5ztQWOBi5HBgbBP1J8+AsQnQCKsi8A=
|
||||||
|
k8s.io/utils v0.0.0-20240711033017-18e509b52bc8/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0=
|
50
model/config_api/configapimodel.go
Normal file
50
model/config_api/configapimodel.go
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
package config_api
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
"github.com/zeromicro/go-zero/core/stores/sqlx"
|
||||||
|
)
|
||||||
|
|
||||||
|
var _ ConfigApiModel = (*customConfigApiModel)(nil)
|
||||||
|
|
||||||
|
type (
|
||||||
|
// ConfigApiModel is an interface to be customized, add more methods here,
|
||||||
|
// and implement the added methods in customConfigApiModel.
|
||||||
|
ConfigApiModel interface {
|
||||||
|
configApiModel
|
||||||
|
withSession(session sqlx.Session) ConfigApiModel
|
||||||
|
FindList(ctx context.Context) ([]ConfigApi, error)
|
||||||
|
}
|
||||||
|
|
||||||
|
customConfigApiModel struct {
|
||||||
|
*defaultConfigApiModel
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
func (m *customConfigApiModel) FindList(ctx context.Context) ([]ConfigApi, error) {
|
||||||
|
|
||||||
|
query := fmt.Sprintf("select %s from %s", configApiRows, m.table)
|
||||||
|
var resp []ConfigApi
|
||||||
|
err := m.conn.QueryRowsCtx(ctx, &resp, query)
|
||||||
|
switch err {
|
||||||
|
case nil:
|
||||||
|
return resp, nil
|
||||||
|
case sqlx.ErrNotFound:
|
||||||
|
return nil, ErrNotFound
|
||||||
|
default:
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewConfigApiModel returns a model for the database table.
|
||||||
|
func NewConfigApiModel(conn sqlx.SqlConn) ConfigApiModel {
|
||||||
|
return &customConfigApiModel{
|
||||||
|
defaultConfigApiModel: newConfigApiModel(conn),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *customConfigApiModel) withSession(session sqlx.Session) ConfigApiModel {
|
||||||
|
return NewConfigApiModel(sqlx.NewSqlConnFromSession(session))
|
||||||
|
}
|
87
model/config_api/configapimodel_gen.go
Normal file
87
model/config_api/configapimodel_gen.go
Normal file
@ -0,0 +1,87 @@
|
|||||||
|
// Code generated by goctl. DO NOT EDIT.
|
||||||
|
// versions:
|
||||||
|
// goctl version: 1.7.6
|
||||||
|
|
||||||
|
package config_api
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"database/sql"
|
||||||
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/zeromicro/go-zero/core/stores/builder"
|
||||||
|
"github.com/zeromicro/go-zero/core/stores/sqlx"
|
||||||
|
"github.com/zeromicro/go-zero/core/stringx"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
configApiFieldNames = builder.RawFieldNames(&ConfigApi{})
|
||||||
|
configApiRows = strings.Join(configApiFieldNames, ",")
|
||||||
|
configApiRowsExpectAutoSet = strings.Join(stringx.Remove(configApiFieldNames, "`id`", "`create_at`", "`create_time`", "`created_at`", "`update_at`", "`update_time`", "`updated_at`"), ",")
|
||||||
|
configApiRowsWithPlaceHolder = strings.Join(stringx.Remove(configApiFieldNames, "`id`", "`create_at`", "`create_time`", "`created_at`", "`update_at`", "`update_time`", "`updated_at`"), "=?,") + "=?"
|
||||||
|
)
|
||||||
|
|
||||||
|
type (
|
||||||
|
configApiModel interface {
|
||||||
|
Insert(ctx context.Context, data *ConfigApi) (sql.Result, error)
|
||||||
|
FindOne(ctx context.Context, id int64) (*ConfigApi, error)
|
||||||
|
Update(ctx context.Context, data *ConfigApi) error
|
||||||
|
Delete(ctx context.Context, id int64) error
|
||||||
|
}
|
||||||
|
|
||||||
|
defaultConfigApiModel struct {
|
||||||
|
conn sqlx.SqlConn
|
||||||
|
table string
|
||||||
|
}
|
||||||
|
|
||||||
|
ConfigApi struct {
|
||||||
|
Id int64 `db:"id"` // 主键ID
|
||||||
|
Type string `db:"type"` // 接口类型 0:172
|
||||||
|
Key sql.NullString `db:"key"` // key
|
||||||
|
Secret sql.NullString `db:"secret"` // 密钥
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
func newConfigApiModel(conn sqlx.SqlConn) *defaultConfigApiModel {
|
||||||
|
return &defaultConfigApiModel{
|
||||||
|
conn: conn,
|
||||||
|
table: "`config_api`",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *defaultConfigApiModel) Delete(ctx context.Context, id int64) error {
|
||||||
|
query := fmt.Sprintf("delete from %s where `id` = ?", m.table)
|
||||||
|
_, err := m.conn.ExecCtx(ctx, query, id)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *defaultConfigApiModel) FindOne(ctx context.Context, id int64) (*ConfigApi, error) {
|
||||||
|
query := fmt.Sprintf("select %s from %s where `id` = ? limit 1", configApiRows, m.table)
|
||||||
|
var resp ConfigApi
|
||||||
|
err := m.conn.QueryRowCtx(ctx, &resp, query, id)
|
||||||
|
switch err {
|
||||||
|
case nil:
|
||||||
|
return &resp, nil
|
||||||
|
case sqlx.ErrNotFound:
|
||||||
|
return nil, ErrNotFound
|
||||||
|
default:
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *defaultConfigApiModel) Insert(ctx context.Context, data *ConfigApi) (sql.Result, error) {
|
||||||
|
query := fmt.Sprintf("insert into %s (%s) values (?, ?, ?)", m.table, configApiRowsExpectAutoSet)
|
||||||
|
ret, err := m.conn.ExecCtx(ctx, query, data.Type, data.Key, data.Secret)
|
||||||
|
return ret, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *defaultConfigApiModel) Update(ctx context.Context, data *ConfigApi) error {
|
||||||
|
query := fmt.Sprintf("update %s set %s where `id` = ?", m.table, configApiRowsWithPlaceHolder)
|
||||||
|
_, err := m.conn.ExecCtx(ctx, query, data.Type, data.Key, data.Secret, data.Id)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *defaultConfigApiModel) tableName() string {
|
||||||
|
return m.table
|
||||||
|
}
|
5
model/config_api/vars.go
Normal file
5
model/config_api/vars.go
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
package config_api
|
||||||
|
|
||||||
|
import "github.com/zeromicro/go-zero/core/stores/sqlx"
|
||||||
|
|
||||||
|
var ErrNotFound = sqlx.ErrNotFound
|
54
model/goods_info/goodsinfomodel.go
Normal file
54
model/goods_info/goodsinfomodel.go
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
package goods_info
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
"github.com/zeromicro/go-zero/core/stores/sqlx"
|
||||||
|
)
|
||||||
|
|
||||||
|
var _ GoodsInfoModel = (*customGoodsInfoModel)(nil)
|
||||||
|
|
||||||
|
type (
|
||||||
|
// GoodsInfoModel is an interface to be customized, add more methods here,
|
||||||
|
// and implement the added methods in customGoodsInfoModel.
|
||||||
|
GoodsInfoModel interface {
|
||||||
|
goodsInfoModel
|
||||||
|
withSession(session sqlx.Session) GoodsInfoModel
|
||||||
|
GetGoodsIndex(ctx context.Context, value string) ([]GoodsInfo, error)
|
||||||
|
}
|
||||||
|
|
||||||
|
customGoodsInfoModel struct {
|
||||||
|
*defaultGoodsInfoModel
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
func (m *customGoodsInfoModel) GetGoodsIndex(ctx context.Context, value string) ([]GoodsInfo, error) {
|
||||||
|
var resp []GoodsInfo
|
||||||
|
var err error
|
||||||
|
if len(value) > 1 || value != "0" {
|
||||||
|
query := fmt.Sprintf("select %s from %s where status = 1 and type = ? order by id desc", goodsInfoRows, m.table)
|
||||||
|
err = m.conn.QueryRowsCtx(ctx, &resp, query, value)
|
||||||
|
} else {
|
||||||
|
query := fmt.Sprintf("select %s from %s where status = 1 order by id desc", goodsInfoRows, m.table)
|
||||||
|
err = m.conn.QueryRowsCtx(ctx, &resp, query)
|
||||||
|
}
|
||||||
|
switch err {
|
||||||
|
case nil:
|
||||||
|
return resp, nil
|
||||||
|
case sqlx.ErrNotFound:
|
||||||
|
return nil, ErrNotFound
|
||||||
|
default:
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewGoodsInfoModel returns a model for the database table.
|
||||||
|
func NewGoodsInfoModel(conn sqlx.SqlConn) GoodsInfoModel {
|
||||||
|
return &customGoodsInfoModel{
|
||||||
|
defaultGoodsInfoModel: newGoodsInfoModel(conn),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *customGoodsInfoModel) withSession(session sqlx.Session) GoodsInfoModel {
|
||||||
|
return NewGoodsInfoModel(sqlx.NewSqlConnFromSession(session))
|
||||||
|
}
|
105
model/goods_info/goodsinfomodel_gen.go
Normal file
105
model/goods_info/goodsinfomodel_gen.go
Normal file
@ -0,0 +1,105 @@
|
|||||||
|
// Code generated by goctl. DO NOT EDIT.
|
||||||
|
// versions:
|
||||||
|
// goctl version: 1.7.6
|
||||||
|
|
||||||
|
package goods_info
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"database/sql"
|
||||||
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/zeromicro/go-zero/core/stores/builder"
|
||||||
|
"github.com/zeromicro/go-zero/core/stores/sqlx"
|
||||||
|
"github.com/zeromicro/go-zero/core/stringx"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
goodsInfoFieldNames = builder.RawFieldNames(&GoodsInfo{})
|
||||||
|
goodsInfoRows = strings.Join(goodsInfoFieldNames, ",")
|
||||||
|
goodsInfoRowsExpectAutoSet = strings.Join(stringx.Remove(goodsInfoFieldNames, "`id`", "`create_at`", "`create_time`", "`created_at`", "`update_at`", "`update_time`", "`updated_at`"), ",")
|
||||||
|
goodsInfoRowsWithPlaceHolder = strings.Join(stringx.Remove(goodsInfoFieldNames, "`id`", "`create_at`", "`create_time`", "`created_at`", "`update_at`", "`update_time`", "`updated_at`"), "=?,") + "=?"
|
||||||
|
)
|
||||||
|
|
||||||
|
type (
|
||||||
|
goodsInfoModel interface {
|
||||||
|
Insert(ctx context.Context, data *GoodsInfo) (sql.Result, error)
|
||||||
|
FindOne(ctx context.Context, id int64) (*GoodsInfo, error)
|
||||||
|
Update(ctx context.Context, data *GoodsInfo) error
|
||||||
|
Delete(ctx context.Context, id int64) error
|
||||||
|
}
|
||||||
|
|
||||||
|
defaultGoodsInfoModel struct {
|
||||||
|
conn sqlx.SqlConn
|
||||||
|
table string
|
||||||
|
}
|
||||||
|
|
||||||
|
GoodsInfo struct {
|
||||||
|
Id int64 `db:"id"` // 主键ID
|
||||||
|
Type string `db:"type"` // 运营商 0:未标注 1:电信 2:联通 3:移动 4:光电
|
||||||
|
Name string `db:"name"` // 商品名
|
||||||
|
MainPic string `db:"main_pic"` // 主图
|
||||||
|
LittlePicture string `db:"little_picture"` // 详情图
|
||||||
|
NetAddr string `db:"netAddr"` // 商品套餐资料介绍地址
|
||||||
|
Area string `db:"area"` // 归属地
|
||||||
|
UniFlow string `db:"uni_flow"` // 通用流量
|
||||||
|
DirFlow string `db:"dir_flow"` // 定向流量
|
||||||
|
TalkTime string `db:"talk_time"` // 通话时间
|
||||||
|
DisableArea string `db:"disable_area"` // 禁发地区
|
||||||
|
DisableAge string `db:"disable_age"` // 年龄限制
|
||||||
|
DisableContract string `db:"disable_contract"` // 合约期
|
||||||
|
Notes sql.NullString `db:"notes"` // 商品说明
|
||||||
|
ApiId sql.NullInt64 `db:"api_id"` // 三方接口
|
||||||
|
ApiProductId sql.NullInt64 `db:"api_product_id"` // 三方商品id
|
||||||
|
NumberSel string `db:"number_sel"` // 是否选号 0:不支持 1:收货地不是归属地 2:收货地是归属地
|
||||||
|
Status string `db:"status"` // 状态 0:上架 1:下架
|
||||||
|
CreateTime time.Time `db:"create_time"` // 创建时间
|
||||||
|
UpdateTime time.Time `db:"update_time"` // 更新时间
|
||||||
|
Remarks sql.NullString `db:"remarks"` // 备注
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
func newGoodsInfoModel(conn sqlx.SqlConn) *defaultGoodsInfoModel {
|
||||||
|
return &defaultGoodsInfoModel{
|
||||||
|
conn: conn,
|
||||||
|
table: "`goods_info`",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *defaultGoodsInfoModel) Delete(ctx context.Context, id int64) error {
|
||||||
|
query := fmt.Sprintf("delete from %s where `id` = ?", m.table)
|
||||||
|
_, err := m.conn.ExecCtx(ctx, query, id)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *defaultGoodsInfoModel) FindOne(ctx context.Context, id int64) (*GoodsInfo, error) {
|
||||||
|
query := fmt.Sprintf("select %s from %s where `id` = ? limit 1", goodsInfoRows, m.table)
|
||||||
|
var resp GoodsInfo
|
||||||
|
err := m.conn.QueryRowCtx(ctx, &resp, query, id)
|
||||||
|
switch err {
|
||||||
|
case nil:
|
||||||
|
return &resp, nil
|
||||||
|
case sqlx.ErrNotFound:
|
||||||
|
return nil, ErrNotFound
|
||||||
|
default:
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *defaultGoodsInfoModel) Insert(ctx context.Context, data *GoodsInfo) (sql.Result, error) {
|
||||||
|
query := fmt.Sprintf("insert into %s (%s) values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", m.table, goodsInfoRowsExpectAutoSet)
|
||||||
|
ret, err := m.conn.ExecCtx(ctx, query, data.Type, data.Name, data.MainPic, data.LittlePicture, data.NetAddr, data.Area, data.UniFlow, data.DirFlow, data.TalkTime, data.DisableArea, data.DisableAge, data.DisableContract, data.Notes, data.ApiId, data.ApiProductId, data.NumberSel, data.Status, data.Remarks)
|
||||||
|
return ret, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *defaultGoodsInfoModel) Update(ctx context.Context, data *GoodsInfo) error {
|
||||||
|
query := fmt.Sprintf("update %s set %s where `id` = ?", m.table, goodsInfoRowsWithPlaceHolder)
|
||||||
|
_, err := m.conn.ExecCtx(ctx, query, data.Type, data.Name, data.MainPic, data.LittlePicture, data.NetAddr, data.Area, data.UniFlow, data.DirFlow, data.TalkTime, data.DisableArea, data.DisableAge, data.DisableContract, data.Notes, data.ApiId, data.ApiProductId, data.NumberSel, data.Status, data.Remarks, data.Id)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *defaultGoodsInfoModel) tableName() string {
|
||||||
|
return m.table
|
||||||
|
}
|
5
model/goods_info/vars.go
Normal file
5
model/goods_info/vars.go
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
package goods_info
|
||||||
|
|
||||||
|
import "github.com/zeromicro/go-zero/core/stores/sqlx"
|
||||||
|
|
||||||
|
var ErrNotFound = sqlx.ErrNotFound
|
92
model/goods_status/goodsstatusmodel.go
Normal file
92
model/goods_status/goodsstatusmodel.go
Normal file
@ -0,0 +1,92 @@
|
|||||||
|
package goods_status
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
"github.com/zeromicro/go-zero/core/stores/sqlx"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
var _ GoodsStatusModel = (*customGoodsStatusModel)(nil)
|
||||||
|
|
||||||
|
type (
|
||||||
|
// GoodsStatusModel is an interface to be customized, add more methods here,
|
||||||
|
// and implement the added methods in customGoodsStatusModel.
|
||||||
|
GoodsStatusModel interface {
|
||||||
|
goodsStatusModel
|
||||||
|
withSession(session sqlx.Session) GoodsStatusModel
|
||||||
|
DeleteByApiId(ctx context.Context, id int64) error
|
||||||
|
FindUpList(ctx context.Context, apiId int64) ([]int64, error)
|
||||||
|
UpdateDownByIds(ctx context.Context, ids []int64) error
|
||||||
|
FindNotIdOne(ctx context.Context, apiId int64) (int64, error)
|
||||||
|
}
|
||||||
|
|
||||||
|
customGoodsStatusModel struct {
|
||||||
|
*defaultGoodsStatusModel
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
func (m *customGoodsStatusModel) FindNotIdOne(ctx context.Context, apiId int64) (int64, error) {
|
||||||
|
query := fmt.Sprintf("select gs.`api_product_id` from %s gs left join `goods_info` gi on gs.`api_id` = gi.`api_id` where gs.`api_id` = ? and gs.`api_product_id` not in (select gs.api_product_id from `goods_status` gs join `goods_info` gi on gs.`api_id` = gi.`api_id` and gi.api_product_id = gs.api_product_id where gs.`api_id` = ?) limit 1", m.table)
|
||||||
|
var resp int64
|
||||||
|
err := m.conn.QueryRowCtx(ctx, &resp, query, apiId, apiId)
|
||||||
|
switch err {
|
||||||
|
case nil:
|
||||||
|
return resp, nil
|
||||||
|
case sqlx.ErrNotFound:
|
||||||
|
return 0, ErrNotFound
|
||||||
|
default:
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *customGoodsStatusModel) UpdateDownByIds(ctx context.Context, ids []int64) error {
|
||||||
|
// 动态构造 IN 子句中的占位符
|
||||||
|
placeholders := make([]string, len(ids))
|
||||||
|
for i := range ids {
|
||||||
|
placeholders[i] = "?"
|
||||||
|
}
|
||||||
|
query := fmt.Sprintf("update %s set `status` = 0 where `id` in (%s)", m.table, strings.Join(placeholders, ","))
|
||||||
|
_, err := m.conn.ExecCtx(ctx, query, convertToInterface(ids)...)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *customGoodsStatusModel) FindUpList(ctx context.Context, apiId int64) ([]int64, error) {
|
||||||
|
query := fmt.Sprintf("select g.`id` from %s g join `config_api` c on g.`api_id` = c.id where g.status = 0 and c.id = ?", m.table)
|
||||||
|
var resp []int64
|
||||||
|
err := m.conn.QueryRowsCtx(ctx, &resp, query, apiId)
|
||||||
|
switch err {
|
||||||
|
case nil:
|
||||||
|
return resp, nil
|
||||||
|
case sqlx.ErrNotFound:
|
||||||
|
return nil, ErrNotFound
|
||||||
|
default:
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *customGoodsStatusModel) DeleteByApiId(ctx context.Context, id int64) error {
|
||||||
|
query := fmt.Sprintf("delete from %s where `api_id` = ?", m.table)
|
||||||
|
_, err := m.conn.ExecCtx(ctx, query, id)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewGoodsStatusModel returns a model for the database table.
|
||||||
|
func NewGoodsStatusModel(conn sqlx.SqlConn) GoodsStatusModel {
|
||||||
|
return &customGoodsStatusModel{
|
||||||
|
defaultGoodsStatusModel: newGoodsStatusModel(conn),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *customGoodsStatusModel) withSession(session sqlx.Session) GoodsStatusModel {
|
||||||
|
return NewGoodsStatusModel(sqlx.NewSqlConnFromSession(session))
|
||||||
|
}
|
||||||
|
|
||||||
|
// convertToInterface 将 int64 切片转换为接口切片
|
||||||
|
func convertToInterface(ids []int64) []interface{} {
|
||||||
|
result := make([]interface{}, len(ids))
|
||||||
|
for i, id := range ids {
|
||||||
|
result[i] = id
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
87
model/goods_status/goodsstatusmodel_gen.go
Normal file
87
model/goods_status/goodsstatusmodel_gen.go
Normal file
@ -0,0 +1,87 @@
|
|||||||
|
// Code generated by goctl. DO NOT EDIT.
|
||||||
|
// versions:
|
||||||
|
// goctl version: 1.7.6
|
||||||
|
|
||||||
|
package goods_status
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"database/sql"
|
||||||
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/zeromicro/go-zero/core/stores/builder"
|
||||||
|
"github.com/zeromicro/go-zero/core/stores/sqlx"
|
||||||
|
"github.com/zeromicro/go-zero/core/stringx"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
goodsStatusFieldNames = builder.RawFieldNames(&GoodsStatus{})
|
||||||
|
goodsStatusRows = strings.Join(goodsStatusFieldNames, ",")
|
||||||
|
goodsStatusRowsExpectAutoSet = strings.Join(stringx.Remove(goodsStatusFieldNames, "`id`", "`create_at`", "`create_time`", "`created_at`", "`update_at`", "`update_time`", "`updated_at`"), ",")
|
||||||
|
goodsStatusRowsWithPlaceHolder = strings.Join(stringx.Remove(goodsStatusFieldNames, "`id`", "`create_at`", "`create_time`", "`created_at`", "`update_at`", "`update_time`", "`updated_at`"), "=?,") + "=?"
|
||||||
|
)
|
||||||
|
|
||||||
|
type (
|
||||||
|
goodsStatusModel interface {
|
||||||
|
Insert(ctx context.Context, data *GoodsStatus) (sql.Result, error)
|
||||||
|
FindOne(ctx context.Context, id int64) (*GoodsStatus, error)
|
||||||
|
Update(ctx context.Context, data *GoodsStatus) error
|
||||||
|
Delete(ctx context.Context, id int64) error
|
||||||
|
}
|
||||||
|
|
||||||
|
defaultGoodsStatusModel struct {
|
||||||
|
conn sqlx.SqlConn
|
||||||
|
table string
|
||||||
|
}
|
||||||
|
|
||||||
|
GoodsStatus struct {
|
||||||
|
Id int64 `db:"id"` // id
|
||||||
|
ApiId sql.NullInt64 `db:"api_id"` // 三方接口
|
||||||
|
ApiProductId sql.NullInt64 `db:"api_product_id"` // 三方商品id
|
||||||
|
Status sql.NullInt64 `db:"status"` // 商品状态 0=上架 1=下架
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
func newGoodsStatusModel(conn sqlx.SqlConn) *defaultGoodsStatusModel {
|
||||||
|
return &defaultGoodsStatusModel{
|
||||||
|
conn: conn,
|
||||||
|
table: "`goods_status`",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *defaultGoodsStatusModel) Delete(ctx context.Context, id int64) error {
|
||||||
|
query := fmt.Sprintf("delete from %s where `id` = ?", m.table)
|
||||||
|
_, err := m.conn.ExecCtx(ctx, query, id)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *defaultGoodsStatusModel) FindOne(ctx context.Context, id int64) (*GoodsStatus, error) {
|
||||||
|
query := fmt.Sprintf("select %s from %s where `id` = ? limit 1", goodsStatusRows, m.table)
|
||||||
|
var resp GoodsStatus
|
||||||
|
err := m.conn.QueryRowCtx(ctx, &resp, query, id)
|
||||||
|
switch err {
|
||||||
|
case nil:
|
||||||
|
return &resp, nil
|
||||||
|
case sqlx.ErrNotFound:
|
||||||
|
return nil, ErrNotFound
|
||||||
|
default:
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *defaultGoodsStatusModel) Insert(ctx context.Context, data *GoodsStatus) (sql.Result, error) {
|
||||||
|
query := fmt.Sprintf("insert into %s (%s) values (?, ?, ?)", m.table, goodsStatusRowsExpectAutoSet)
|
||||||
|
ret, err := m.conn.ExecCtx(ctx, query, data.ApiId, data.ApiProductId, data.Status)
|
||||||
|
return ret, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *defaultGoodsStatusModel) Update(ctx context.Context, data *GoodsStatus) error {
|
||||||
|
query := fmt.Sprintf("update %s set %s where `id` = ?", m.table, goodsStatusRowsWithPlaceHolder)
|
||||||
|
_, err := m.conn.ExecCtx(ctx, query, data.ApiId, data.ApiProductId, data.Status, data.Id)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *defaultGoodsStatusModel) tableName() string {
|
||||||
|
return m.table
|
||||||
|
}
|
5
model/goods_status/vars.go
Normal file
5
model/goods_status/vars.go
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
package goods_status
|
||||||
|
|
||||||
|
import "github.com/zeromicro/go-zero/core/stores/sqlx"
|
||||||
|
|
||||||
|
var ErrNotFound = sqlx.ErrNotFound
|
29
model/order_info/oderinfomodel.go
Normal file
29
model/order_info/oderinfomodel.go
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
package order_info
|
||||||
|
|
||||||
|
import "github.com/zeromicro/go-zero/core/stores/sqlx"
|
||||||
|
|
||||||
|
var _ OderInfoModel = (*customOderInfoModel)(nil)
|
||||||
|
|
||||||
|
type (
|
||||||
|
// OderInfoModel is an interface to be customized, add more methods here,
|
||||||
|
// and implement the added methods in customOderInfoModel.
|
||||||
|
OderInfoModel interface {
|
||||||
|
oderInfoModel
|
||||||
|
withSession(session sqlx.Session) OderInfoModel
|
||||||
|
}
|
||||||
|
|
||||||
|
customOderInfoModel struct {
|
||||||
|
*defaultOderInfoModel
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
// NewOderInfoModel returns a model for the database table.
|
||||||
|
func NewOderInfoModel(conn sqlx.SqlConn) OderInfoModel {
|
||||||
|
return &customOderInfoModel{
|
||||||
|
defaultOderInfoModel: newOderInfoModel(conn),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *customOderInfoModel) withSession(session sqlx.Session) OderInfoModel {
|
||||||
|
return NewOderInfoModel(sqlx.NewSqlConnFromSession(session))
|
||||||
|
}
|
102
model/order_info/oderinfomodel_gen.go
Normal file
102
model/order_info/oderinfomodel_gen.go
Normal file
@ -0,0 +1,102 @@
|
|||||||
|
// Code generated by goctl. DO NOT EDIT.
|
||||||
|
// versions:
|
||||||
|
// goctl version: 1.7.6
|
||||||
|
|
||||||
|
package order_info
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"database/sql"
|
||||||
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/zeromicro/go-zero/core/stores/builder"
|
||||||
|
"github.com/zeromicro/go-zero/core/stores/sqlx"
|
||||||
|
"github.com/zeromicro/go-zero/core/stringx"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
oderInfoFieldNames = builder.RawFieldNames(&OderInfo{})
|
||||||
|
oderInfoRows = strings.Join(oderInfoFieldNames, ",")
|
||||||
|
oderInfoRowsExpectAutoSet = strings.Join(stringx.Remove(oderInfoFieldNames, "`create_at`", "`create_time`", "`created_at`", "`update_at`", "`update_time`", "`updated_at`"), ",")
|
||||||
|
oderInfoRowsWithPlaceHolder = strings.Join(stringx.Remove(oderInfoFieldNames, "`id`", "`create_at`", "`create_time`", "`created_at`", "`update_at`", "`update_time`", "`updated_at`"), "=?,") + "=?"
|
||||||
|
)
|
||||||
|
|
||||||
|
type (
|
||||||
|
oderInfoModel interface {
|
||||||
|
Insert(ctx context.Context, data *OderInfo) (sql.Result, error)
|
||||||
|
FindOne(ctx context.Context, id int64) (*OderInfo, error)
|
||||||
|
Update(ctx context.Context, data *OderInfo) error
|
||||||
|
Delete(ctx context.Context, id int64) error
|
||||||
|
}
|
||||||
|
|
||||||
|
defaultOderInfoModel struct {
|
||||||
|
conn sqlx.SqlConn
|
||||||
|
table string
|
||||||
|
}
|
||||||
|
|
||||||
|
OderInfo struct {
|
||||||
|
Id int64 `db:"id"` // 订单id
|
||||||
|
OderId string `db:"oder_id"` // 订单id
|
||||||
|
GoodsId string `db:"goods_id"` // 下单产品ID
|
||||||
|
Name string `db:"name"` // 姓名
|
||||||
|
IdCard string `db:"id_card"` // 身份证号
|
||||||
|
Phone string `db:"phone"` // 手机号码
|
||||||
|
Province string `db:"province"` // 省
|
||||||
|
City string `db:"city"` // 城市
|
||||||
|
Area string `db:"area"` // 区/县/镇
|
||||||
|
Address string `db:"address"` // 详细地址
|
||||||
|
Status string `db:"status"` // 发货处理状态:0=未处理,1=已下单 2=已发货 3已完成 4失败
|
||||||
|
ApiId sql.NullString `db:"api_id"` // 接口来源
|
||||||
|
ApiOderId sql.NullString `db:"api_oder_id"` // 第三方订单
|
||||||
|
ThirdPhone sql.NullString `db:"third_phone"` // 用户办理的号码
|
||||||
|
CardStatus string `db:"card_status"` // 号码状态
|
||||||
|
CreateTime time.Time `db:"create_time"` // 创建时间
|
||||||
|
UpdateTime time.Time `db:"update_time"` // 更新时间
|
||||||
|
Remarks sql.NullString `db:"remarks"` // 备注
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
func newOderInfoModel(conn sqlx.SqlConn) *defaultOderInfoModel {
|
||||||
|
return &defaultOderInfoModel{
|
||||||
|
conn: conn,
|
||||||
|
table: "`oder_info`",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *defaultOderInfoModel) Delete(ctx context.Context, id int64) error {
|
||||||
|
query := fmt.Sprintf("delete from %s where `id` = ?", m.table)
|
||||||
|
_, err := m.conn.ExecCtx(ctx, query, id)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *defaultOderInfoModel) FindOne(ctx context.Context, id int64) (*OderInfo, error) {
|
||||||
|
query := fmt.Sprintf("select %s from %s where `id` = ? limit 1", oderInfoRows, m.table)
|
||||||
|
var resp OderInfo
|
||||||
|
err := m.conn.QueryRowCtx(ctx, &resp, query, id)
|
||||||
|
switch err {
|
||||||
|
case nil:
|
||||||
|
return &resp, nil
|
||||||
|
case sqlx.ErrNotFound:
|
||||||
|
return nil, ErrNotFound
|
||||||
|
default:
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *defaultOderInfoModel) Insert(ctx context.Context, data *OderInfo) (sql.Result, error) {
|
||||||
|
query := fmt.Sprintf("insert into %s (%s) values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", m.table, oderInfoRowsExpectAutoSet)
|
||||||
|
ret, err := m.conn.ExecCtx(ctx, query, data.Id, data.OderId, data.GoodsId, data.Name, data.IdCard, data.Phone, data.Province, data.City, data.Area, data.Address, data.Status, data.ApiId, data.ApiOderId, data.ThirdPhone, data.CardStatus, data.Remarks)
|
||||||
|
return ret, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *defaultOderInfoModel) Update(ctx context.Context, data *OderInfo) error {
|
||||||
|
query := fmt.Sprintf("update %s set %s where `id` = ?", m.table, oderInfoRowsWithPlaceHolder)
|
||||||
|
_, err := m.conn.ExecCtx(ctx, query, data.OderId, data.GoodsId, data.Name, data.IdCard, data.Phone, data.Province, data.City, data.Area, data.Address, data.Status, data.ApiId, data.ApiOderId, data.ThirdPhone, data.CardStatus, data.Remarks, data.Id)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *defaultOderInfoModel) tableName() string {
|
||||||
|
return m.table
|
||||||
|
}
|
5
model/order_info/vars.go
Normal file
5
model/order_info/vars.go
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
package order_info
|
||||||
|
|
||||||
|
import "github.com/zeromicro/go-zero/core/stores/sqlx"
|
||||||
|
|
||||||
|
var ErrNotFound = sqlx.ErrNotFound
|
82
pkg/middleware/getRealIP.go
Normal file
82
pkg/middleware/getRealIP.go
Normal file
@ -0,0 +1,82 @@
|
|||||||
|
package middleware
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"net"
|
||||||
|
"net/http"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
// GetRealIP 提取客户端真实 IP 地址
|
||||||
|
func GetRealIP(r *http.Request) string {
|
||||||
|
headers := []string{"x-forwarded-for", "X-Forwarded-For", "Proxy-Client-IP", "WL-Proxy-Client-IP", "X-Real-IP"}
|
||||||
|
|
||||||
|
// 遍历头信息,找到第一个有效 IP
|
||||||
|
for _, header := range headers {
|
||||||
|
ip := extractIP(r.Header.Get(header))
|
||||||
|
if ip != "" {
|
||||||
|
return ip
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取 RemoteAddr,如果经过代理则是代理 IP
|
||||||
|
ip, _, err := net.SplitHostPort(r.RemoteAddr)
|
||||||
|
if err == nil && ip != "" {
|
||||||
|
return ip
|
||||||
|
}
|
||||||
|
|
||||||
|
// 检查是否是本地地址
|
||||||
|
if strings.HasPrefix(ip, "127.0.0.1") || strings.HasPrefix(ip, "[::1]") {
|
||||||
|
if externalIP, err := getExternalIP(); err == nil {
|
||||||
|
return externalIP.String()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
// 提取 IP 地址并返回第一个非空部分
|
||||||
|
func extractIP(ips string) string {
|
||||||
|
if ips == "" || strings.EqualFold(ips, "unknown") {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
// 返回第一个有效 IP
|
||||||
|
return strings.TrimSpace(strings.Split(ips, ",")[0])
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取非 127.0.0.1 的局域网 IP
|
||||||
|
func getExternalIP() (net.IP, error) {
|
||||||
|
ifaces, err := net.Interfaces()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
for _, iface := range ifaces {
|
||||||
|
if iface.Flags&net.FlagUp == 0 || iface.Flags&net.FlagLoopback != 0 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
addrs, err := iface.Addrs()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
for _, addr := range addrs {
|
||||||
|
ip := getIPFromAddr(addr)
|
||||||
|
if ip != nil {
|
||||||
|
return ip, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil, errors.New("not connected to the network")
|
||||||
|
}
|
||||||
|
|
||||||
|
func getIPFromAddr(addr net.Addr) net.IP {
|
||||||
|
var ip net.IP
|
||||||
|
switch v := addr.(type) {
|
||||||
|
case *net.IPNet:
|
||||||
|
ip = v.IP
|
||||||
|
case *net.IPAddr:
|
||||||
|
ip = v.IP
|
||||||
|
}
|
||||||
|
if ip != nil && !ip.IsLoopback() {
|
||||||
|
return ip.To4()
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
72
pkg/util/172/172.go
Normal file
72
pkg/util/172/172.go
Normal file
@ -0,0 +1,72 @@
|
|||||||
|
package _72
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"hk/pkg/util/httpUtil"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
productsUrl = "https://haokaopenapi.lot-ml.com/api/order/GetProducts" // 商品列表查询Url
|
||||||
|
productsV2Url = "https://haokaopenapi.lot-ml.com/api/order/GetProductsV2" // 商品信息查询Url
|
||||||
|
pickNumberUrl = "https://haokaopenapi.lot-ml.com/api/order/PickNumber" // 商品选号Url
|
||||||
|
blackUserUrl = "https://haokaopenapi.lot-ml.com/api/black/BlackCheckCus" // 用户黑名单Url
|
||||||
|
blackAgentUrl = "https://haokaopenapi.lot-ml.com/api/black/BlackCheckAgent" // 代理黑名单Url
|
||||||
|
upFileUrl = "https://haokaopenapi.lot-ml.com/api/order/UpPicFile" // 证件照上传Url
|
||||||
|
addOrderUrl = "https://haokaopenapi.lot-ml.com/api/order/ApiToOrder" // 下单Url
|
||||||
|
orderInfoUrl = "https://haokaopenapi.lot-ml.com/api/order/GetOrderInfo" // 订单查询Url
|
||||||
|
)
|
||||||
|
|
||||||
|
type BaseParams struct {
|
||||||
|
Timestamp string `json:"Timestamp"` // Y 时间戳
|
||||||
|
UserID string `json:"user_id"` // Y 用户ID
|
||||||
|
UserSign string `json:"user_sign"` // Y 密钥
|
||||||
|
}
|
||||||
|
|
||||||
|
// GoodsReq 商品请求参数
|
||||||
|
type GoodsReq struct {
|
||||||
|
ProductID string `json:"ProductID"`
|
||||||
|
BaseParams
|
||||||
|
// Timestamp string `json:"Timestamp"` // Y 时间戳
|
||||||
|
// UserID string `json:"user_id"` // Y 用户ID
|
||||||
|
// UserSign string `json:"user_sign"` // Y 密钥
|
||||||
|
}
|
||||||
|
|
||||||
|
// ProductResp 定义产品信息的结构体
|
||||||
|
type ProductResp struct {
|
||||||
|
ProductID int64 `json:"productID"`
|
||||||
|
ProductName string `json:"productName"`
|
||||||
|
Flag string `json:"flag"` // 上架中
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetProduct 获取上架中商品列表
|
||||||
|
func GetProduct(params GoodsReq) (ApiResponse[[]ProductResp], error) {
|
||||||
|
// 设置时间戳
|
||||||
|
timestamp := fmt.Sprintf("%d", time.Now().Unix()) // 当前时间戳,长度为10位
|
||||||
|
params.Timestamp = timestamp
|
||||||
|
// 生成 MD5 签名
|
||||||
|
userSign := generateMD5SignV2(params, params.UserSign)
|
||||||
|
|
||||||
|
formParams := map[string]string{
|
||||||
|
"ProductID": params.ProductID,
|
||||||
|
"Timestamp": params.Timestamp,
|
||||||
|
"user_sign": userSign,
|
||||||
|
"user_id": params.UserID,
|
||||||
|
}
|
||||||
|
|
||||||
|
body, err := httpUtil.NewRequest().SendFormData(productsUrl, nil, formParams)
|
||||||
|
if err != nil {
|
||||||
|
return ApiResponse[[]ProductResp]{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// 解析 JSON 响应
|
||||||
|
var apiResponse ApiResponse[[]ProductResp]
|
||||||
|
err = json.Unmarshal([]byte(body), &apiResponse)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println("解析响应体时发生错误:", err)
|
||||||
|
return ApiResponse[[]ProductResp]{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return apiResponse, nil
|
||||||
|
}
|
198
pkg/util/172/172_test.go
Normal file
198
pkg/util/172/172_test.go
Normal file
@ -0,0 +1,198 @@
|
|||||||
|
package _72
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"testing"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestGetProduct(t *testing.T) {
|
||||||
|
key := "devttl"
|
||||||
|
secret := "2eed544990ff898cf4fe47ef90b1ce3a"
|
||||||
|
productID := ""
|
||||||
|
timestamp := fmt.Sprintf("%d", time.Now().Unix()) // 当前时间戳,长度为10位
|
||||||
|
|
||||||
|
// 创建请求参数
|
||||||
|
params := GoodsReq{
|
||||||
|
ProductID: productID,
|
||||||
|
BaseParams: BaseParams{
|
||||||
|
Timestamp: timestamp,
|
||||||
|
UserID: key,
|
||||||
|
UserSign: secret,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
// 发送 POST 请求
|
||||||
|
apiResponse, err := GetProduct(params)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// 如果成功,处理 data 中的数据
|
||||||
|
if apiResponse.Code == 0 {
|
||||||
|
for index, item := range apiResponse.Data {
|
||||||
|
fmt.Printf("------------------%d\n", index)
|
||||||
|
fmt.Printf("产品ID: %v\n", item.ProductID)
|
||||||
|
fmt.Printf("产品名称: %v\n", item.ProductName)
|
||||||
|
fmt.Printf("产品状态: %v\n", item.Flag)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestGetProductV2(t *testing.T) {
|
||||||
|
key := "devttl"
|
||||||
|
secret := "2eed544990ff898cf4fe47ef90b1ce3a"
|
||||||
|
productID := "1128"
|
||||||
|
timestamp := fmt.Sprintf("%d", time.Now().Unix()) // 当前时间戳,长度为10位
|
||||||
|
|
||||||
|
// 创建请求参数
|
||||||
|
params := GoodsReq{
|
||||||
|
ProductID: productID,
|
||||||
|
BaseParams: BaseParams{
|
||||||
|
Timestamp: timestamp,
|
||||||
|
UserID: key,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
// 生成 MD5 签名
|
||||||
|
userSign := generateMD5SignV2(params, secret)
|
||||||
|
|
||||||
|
params.UserSign = userSign
|
||||||
|
|
||||||
|
fmt.Print(params)
|
||||||
|
|
||||||
|
// 发送 POST 请求
|
||||||
|
apiResponse, err := getProductV2(params)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// 如果成功,处理 data 中的数据
|
||||||
|
if apiResponse.Code == 0 {
|
||||||
|
for index, item := range apiResponse.Data {
|
||||||
|
fmt.Printf("------------------%d\n", index)
|
||||||
|
fmt.Printf("产品ID: %v\n", item.ProductID)
|
||||||
|
fmt.Printf("产品名称: %v\n", item.ProductName)
|
||||||
|
fmt.Printf("产品主图: %v\n", item.MainPic)
|
||||||
|
fmt.Printf("发货地区: %v\n", item.Area)
|
||||||
|
fmt.Printf("禁发地区: %v\n", item.DisableArea)
|
||||||
|
fmt.Printf("详情图片: %v\n", item.LittlePicture)
|
||||||
|
fmt.Printf("详情链接: %v\n", item.NetAddr)
|
||||||
|
fmt.Printf("产品状态: %v\n", item.Flag)
|
||||||
|
fmt.Printf("是否选号: %v\n", item.NumberSel)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestGetPickNumber(t *testing.T) {
|
||||||
|
key := "devttl"
|
||||||
|
secret := "2eed544990ff898cf4fe47ef90b1ce3a"
|
||||||
|
productID := "1128"
|
||||||
|
timestamp := fmt.Sprintf("%d", time.Now().Unix()) // 当前时间戳,长度为10位
|
||||||
|
|
||||||
|
// 创建请求参数
|
||||||
|
params := PickNumberReq{
|
||||||
|
ProductID: productID,
|
||||||
|
SearchCategory: "3",
|
||||||
|
BaseParams: BaseParams{
|
||||||
|
UserID: key,
|
||||||
|
Timestamp: timestamp,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
// 生成 MD5 签名
|
||||||
|
userSign := generateMD5SignV2(params, secret)
|
||||||
|
|
||||||
|
params.UserSign = userSign
|
||||||
|
|
||||||
|
fmt.Println(params)
|
||||||
|
|
||||||
|
// 发送 POST 请求
|
||||||
|
apiResponse, err := GetPickNumber(params)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// 如果成功,处理 data 中的数据
|
||||||
|
if apiResponse.Code == 0 {
|
||||||
|
for index, item := range apiResponse.Data {
|
||||||
|
fmt.Printf("------------------%d\n", index)
|
||||||
|
fmt.Printf("号码: %v\n", item.Number)
|
||||||
|
fmt.Printf("号码类型: %v\n", item.Type)
|
||||||
|
fmt.Printf("号码ID: %v\n", item.NumberId)
|
||||||
|
fmt.Printf("号码池ID: %v\n", item.NumberPoolId)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestCheckUserBlack(t *testing.T) {
|
||||||
|
key := "devttl"
|
||||||
|
secret := "2eed544990ff898cf4fe47ef90b1ce3a"
|
||||||
|
number := "15538654901"
|
||||||
|
numberType := "1"
|
||||||
|
timestamp := fmt.Sprintf("%d", time.Now().Unix()) // 当前时间戳,长度为10位
|
||||||
|
|
||||||
|
// 创建请求参数
|
||||||
|
params := BlackReq{
|
||||||
|
Number: number,
|
||||||
|
Type: numberType,
|
||||||
|
Timestamp: timestamp,
|
||||||
|
UserID: key,
|
||||||
|
UserSign: secret,
|
||||||
|
}
|
||||||
|
|
||||||
|
// 发送 POST 请求
|
||||||
|
apiResponse, err := CheckBlackUser(params)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// 如果成功,处理 data 中的数据
|
||||||
|
if apiResponse.Code == 0 {
|
||||||
|
fmt.Println("此用户是黑名单")
|
||||||
|
}
|
||||||
|
if apiResponse.Code == 1 {
|
||||||
|
fmt.Println("此用户不是黑名单")
|
||||||
|
}
|
||||||
|
if apiResponse.Code == -1 {
|
||||||
|
fmt.Println("请输入正确的手机号")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestCheckAgentBlack(t *testing.T) {
|
||||||
|
key := "devttl"
|
||||||
|
secret := "2eed544990ff898cf4fe47ef90b1ce3a"
|
||||||
|
number := "15538654901"
|
||||||
|
numberType := "1"
|
||||||
|
|
||||||
|
// 创建请求参数
|
||||||
|
params := BlackReq{
|
||||||
|
Number: number,
|
||||||
|
Type: numberType,
|
||||||
|
UserID: key,
|
||||||
|
}
|
||||||
|
|
||||||
|
// 生成 MD5 签名
|
||||||
|
userSign := generateMD5SignV2(params, secret)
|
||||||
|
|
||||||
|
params.UserSign = userSign
|
||||||
|
|
||||||
|
fmt.Println(params)
|
||||||
|
|
||||||
|
// 发送 POST 请求
|
||||||
|
apiResponse, err := CheckBlackAgent(params)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// 如果成功,处理 data 中的数据
|
||||||
|
if apiResponse.Code == 0 {
|
||||||
|
fmt.Println("此用户是黑名单代理")
|
||||||
|
}
|
||||||
|
if apiResponse.Code == 1 {
|
||||||
|
fmt.Println("此用户不是黑名单代理")
|
||||||
|
}
|
||||||
|
if apiResponse.Code == -1 {
|
||||||
|
fmt.Println("请输入正确的代理手机号")
|
||||||
|
}
|
||||||
|
}
|
70
pkg/util/172/api_result.go
Normal file
70
pkg/util/172/api_result.go
Normal file
@ -0,0 +1,70 @@
|
|||||||
|
package _72
|
||||||
|
|
||||||
|
import (
|
||||||
|
"crypto/md5"
|
||||||
|
"encoding/hex"
|
||||||
|
"fmt"
|
||||||
|
"reflect"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
// ApiResponse 定义响应体的结构体
|
||||||
|
type ApiResponse[T any] struct {
|
||||||
|
Code int `json:"code"`
|
||||||
|
Message string `json:"message"`
|
||||||
|
Errs *string `json:"errs"`
|
||||||
|
Data T `json:"data"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// 优化后的 generateMD5Sign 方法
|
||||||
|
func generateMD5SignV2(params interface{}, secret string) string {
|
||||||
|
// 获取结构体中的字段信息
|
||||||
|
var strBuilder strings.Builder
|
||||||
|
|
||||||
|
// 获取参数类型
|
||||||
|
v := reflect.ValueOf(params)
|
||||||
|
|
||||||
|
// 遍历结构体中的字段
|
||||||
|
for i := 0; i < v.NumField(); i++ {
|
||||||
|
// 获取字段名和值
|
||||||
|
field := v.Type().Field(i)
|
||||||
|
jsonTag := field.Tag.Get("json") // 获取 json 标签
|
||||||
|
value := v.Field(i)
|
||||||
|
// 如果字段是嵌套结构体,跳过
|
||||||
|
if value.Kind() == reflect.Struct {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
// 获取字段值
|
||||||
|
fieldValue := value.String()
|
||||||
|
|
||||||
|
// 排除 user_id 和空字符串字段
|
||||||
|
if field.Name != "UserID" && field.Name != "UserSign" {
|
||||||
|
// 拼接字段名和值
|
||||||
|
strBuilder.WriteString(fmt.Sprintf("%s=%s&", jsonTag, fieldValue))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 使用反射获取字段并拼接
|
||||||
|
timestamp := v.FieldByName("Timestamp")
|
||||||
|
if timestamp.IsValid() {
|
||||||
|
timestampTag, _ := v.Type().FieldByName("Timestamp")
|
||||||
|
strBuilder.WriteString(fmt.Sprintf("%s=%s&", timestampTag.Tag.Get("json"), timestamp.String()))
|
||||||
|
}
|
||||||
|
userID := v.FieldByName("UserID")
|
||||||
|
if userID.IsValid() {
|
||||||
|
userIDTag, _ := v.Type().FieldByName("UserID")
|
||||||
|
strBuilder.WriteString(fmt.Sprintf("%s=%s", userIDTag.Tag.Get("json"), userID.String()))
|
||||||
|
}
|
||||||
|
|
||||||
|
// 拼接 secret 到最后
|
||||||
|
strBuilder.WriteString(secret)
|
||||||
|
|
||||||
|
// 获取拼接后的字符串
|
||||||
|
concatenatedStr := strBuilder.String()
|
||||||
|
|
||||||
|
fmt.Println(concatenatedStr)
|
||||||
|
// 计算 MD5 哈希
|
||||||
|
hash := md5.New()
|
||||||
|
hash.Write([]byte(concatenatedStr))
|
||||||
|
return hex.EncodeToString(hash.Sum(nil))
|
||||||
|
}
|
69
pkg/util/172/black_user.go
Normal file
69
pkg/util/172/black_user.go
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
package _72
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"hk/pkg/util/httpUtil"
|
||||||
|
)
|
||||||
|
|
||||||
|
// BlackReq 黑名单请求
|
||||||
|
type BlackReq struct {
|
||||||
|
Number string `json:"number"` // Y 手机号或身份证号
|
||||||
|
Type string `json:"type"` // Y 查询类别 1:手机号 2:身份证号
|
||||||
|
Timestamp string `json:"Timestamp"` // Y 时间戳
|
||||||
|
UserID string `json:"username"` // Y 用户ID
|
||||||
|
UserSign string `json:"sign"` // Y 密钥
|
||||||
|
}
|
||||||
|
|
||||||
|
// CheckBlackUser 判断用户是否为黑名单用户
|
||||||
|
func CheckBlackUser(params BlackReq) (ApiResponse[any], error) {
|
||||||
|
|
||||||
|
formParams := map[string]string{
|
||||||
|
"number": params.Number,
|
||||||
|
"type": params.Type,
|
||||||
|
"Timestamp": params.Timestamp,
|
||||||
|
"username": params.UserID,
|
||||||
|
"sign": params.UserSign,
|
||||||
|
}
|
||||||
|
|
||||||
|
body, err := httpUtil.NewRequest().SendFormData(blackUserUrl, nil, formParams)
|
||||||
|
if err != nil {
|
||||||
|
return ApiResponse[any]{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// 解析 JSON 响应
|
||||||
|
var apiResponse ApiResponse[any]
|
||||||
|
err = json.Unmarshal([]byte(body), &apiResponse)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println("解析响应体时发生错误:", err)
|
||||||
|
return ApiResponse[any]{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return apiResponse, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// CheckBlackAgent 判断用户是否为黑名单代理
|
||||||
|
func CheckBlackAgent(params BlackReq) (ApiResponse[any], error) {
|
||||||
|
|
||||||
|
formParams := map[string]string{
|
||||||
|
"number": params.Number,
|
||||||
|
"type": params.Type,
|
||||||
|
"username": params.UserID,
|
||||||
|
"sign": params.UserSign,
|
||||||
|
}
|
||||||
|
|
||||||
|
body, err := httpUtil.NewRequest().SendFormData(blackAgentUrl, nil, formParams)
|
||||||
|
if err != nil {
|
||||||
|
return ApiResponse[any]{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// 解析 JSON 响应
|
||||||
|
var apiResponse ApiResponse[any]
|
||||||
|
err = json.Unmarshal([]byte(body), &apiResponse)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println("解析响应体时发生错误:", err)
|
||||||
|
return ApiResponse[any]{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return apiResponse, nil
|
||||||
|
}
|
50
pkg/util/172/goods_v2.go
Normal file
50
pkg/util/172/goods_v2.go
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
package _72
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"hk/pkg/util/httpUtil"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
const ()
|
||||||
|
|
||||||
|
// ProductV2Resp 定义商品套餐的结构
|
||||||
|
type ProductV2Resp struct {
|
||||||
|
ProductID int64 `json:"productID"`
|
||||||
|
ProductName string `json:"productName"`
|
||||||
|
MainPic string `json:"mainPic"`
|
||||||
|
Area string `json:"area"`
|
||||||
|
DisableArea string `json:"disableArea"`
|
||||||
|
LittlePicture string `json:"littlepicture"`
|
||||||
|
NetAddr string `json:"netAddr"`
|
||||||
|
Flag bool `json:"flag"`
|
||||||
|
NumberSel int `json:"numberSel"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetProductV2 获取单个商品信息
|
||||||
|
func GetProductV2(params GoodsReq) (ApiResponse[[]ProductV2Resp], error) {
|
||||||
|
// 设置时间戳
|
||||||
|
timestamp := fmt.Sprintf("%d", time.Now().Unix()) // 当前时间戳,长度为10位
|
||||||
|
params.Timestamp = timestamp
|
||||||
|
// 生成 MD5 签名
|
||||||
|
userSign := generateMD5SignV2(params, params.UserSign)
|
||||||
|
formParams := map[string]string{
|
||||||
|
"ProductID": params.ProductID,
|
||||||
|
"user_id": params.UserID,
|
||||||
|
"Timestamp": params.Timestamp,
|
||||||
|
"user_sign": userSign,
|
||||||
|
}
|
||||||
|
|
||||||
|
body, err := httpUtil.NewRequest().SendFormData(productsV2Url, nil, formParams)
|
||||||
|
|
||||||
|
// 解析 JSON 响应
|
||||||
|
var apiResponse ApiResponse[[]ProductV2Resp]
|
||||||
|
err = json.Unmarshal([]byte(body), &apiResponse)
|
||||||
|
if err != nil {
|
||||||
|
return ApiResponse[[]ProductV2Resp]{}, fmt.Errorf("解析响应体时发生错误: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 返回解析后的响应
|
||||||
|
return apiResponse, nil
|
||||||
|
}
|
53
pkg/util/172/pick_number.go
Normal file
53
pkg/util/172/pick_number.go
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
package _72
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"hk/pkg/util/httpUtil"
|
||||||
|
)
|
||||||
|
|
||||||
|
const ()
|
||||||
|
|
||||||
|
type PickNumberReq struct {
|
||||||
|
City string `json:"city"` // 市
|
||||||
|
ProductID string `json:"prodID"` // Y 商品ID
|
||||||
|
Province string `json:"province"` // 省
|
||||||
|
SearchCategory string `json:"searchCategory"` // 查询分类 默认3
|
||||||
|
SearchValue string `json:"searchValue"` // 查询关键字2-4位
|
||||||
|
BaseParams
|
||||||
|
}
|
||||||
|
|
||||||
|
type PickNumberResp struct {
|
||||||
|
Type string `json:"type"` // 号码类型 普通
|
||||||
|
Number string `json:"number"` // 号码
|
||||||
|
NumberId string `json:"numberId"` // 号码ID
|
||||||
|
NumberPoolId string `json:"numberPoolId"` // 号码池ID
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetPickNumber 商品选号
|
||||||
|
func GetPickNumber(params PickNumberReq) (ApiResponse[[]PickNumberResp], error) {
|
||||||
|
|
||||||
|
formParams := map[string]string{
|
||||||
|
"city": params.City,
|
||||||
|
"prodID": params.ProductID,
|
||||||
|
"province": params.Province,
|
||||||
|
"searchCategory": "3",
|
||||||
|
"searchValue": params.SearchValue,
|
||||||
|
"Timestamp": params.Timestamp,
|
||||||
|
"user_id": params.UserID,
|
||||||
|
"user_sign": params.UserSign,
|
||||||
|
}
|
||||||
|
|
||||||
|
body, err := httpUtil.NewRequest().SendFormData(pickNumberUrl, nil, formParams)
|
||||||
|
|
||||||
|
// 解析 JSON 响应
|
||||||
|
var apiResponse ApiResponse[[]PickNumberResp]
|
||||||
|
err = json.Unmarshal([]byte(body), &apiResponse)
|
||||||
|
if err != nil {
|
||||||
|
return ApiResponse[[]PickNumberResp]{}, fmt.Errorf("解析响应体时发生错误: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 返回解析后的响应
|
||||||
|
return apiResponse, nil
|
||||||
|
}
|
140
pkg/util/httpUtil/post_request.go
Normal file
140
pkg/util/httpUtil/post_request.go
Normal file
@ -0,0 +1,140 @@
|
|||||||
|
package httpUtil
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"io/ioutil"
|
||||||
|
"net/http"
|
||||||
|
"net/url"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Request 封装的 POST 请求工具类
|
||||||
|
type Request struct {
|
||||||
|
client *http.Client
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewRequest 创建一个新的 PostRequest 实例
|
||||||
|
func NewRequest() *Request {
|
||||||
|
return &Request{
|
||||||
|
client: &http.Client{
|
||||||
|
Timeout: 10 * time.Second, // 设置请求超时时间
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// SendJSON 发送一个 JSON 格式的 POST 请求
|
||||||
|
func (p *Request) SendJSON(urlPath string, headers map[string]string, body interface{}) (string, error) {
|
||||||
|
// 将请求体转为 JSON
|
||||||
|
requestBody, err := json.Marshal(body)
|
||||||
|
if err != nil {
|
||||||
|
return "", fmt.Errorf("无法编码 JSON 请求体: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 创建 HTTP 请求
|
||||||
|
req, err := http.NewRequest("POST", urlPath, bytes.NewBuffer(requestBody))
|
||||||
|
if err != nil {
|
||||||
|
return "", fmt.Errorf("无法创建请求: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 设置请求头
|
||||||
|
req.Header.Set("Content-Type", "application/json")
|
||||||
|
for key, value := range headers {
|
||||||
|
req.Header.Set(key, value)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 发送请求
|
||||||
|
resp, err := p.client.Do(req)
|
||||||
|
if err != nil {
|
||||||
|
return "", fmt.Errorf("发送请求失败: %v", err)
|
||||||
|
}
|
||||||
|
defer resp.Body.Close()
|
||||||
|
|
||||||
|
// 读取响应内容
|
||||||
|
respBody, err := ioutil.ReadAll(resp.Body)
|
||||||
|
if err != nil {
|
||||||
|
return "", fmt.Errorf("读取响应体失败: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 返回响应内容
|
||||||
|
return string(respBody), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// SendFormData 发送一个 form-data 格式的 POST 请求
|
||||||
|
func (p *Request) SendFormData(urlPath string, headers map[string]string, params map[string]string) (string, error) {
|
||||||
|
// 将参数拼接为表单数据
|
||||||
|
formData := url.Values{}
|
||||||
|
for key, value := range params {
|
||||||
|
formData.Set(key, value)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 创建 HTTP 请求
|
||||||
|
req, err := http.NewRequest("POST", urlPath, strings.NewReader(formData.Encode()))
|
||||||
|
if err != nil {
|
||||||
|
return "", fmt.Errorf("无法创建请求: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 设置请求头
|
||||||
|
req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
|
||||||
|
for key, value := range headers {
|
||||||
|
req.Header.Set(key, value)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 发送请求
|
||||||
|
resp, err := p.client.Do(req)
|
||||||
|
if err != nil {
|
||||||
|
return "", fmt.Errorf("发送请求失败: %v", err)
|
||||||
|
}
|
||||||
|
defer resp.Body.Close()
|
||||||
|
|
||||||
|
// 读取响应内容
|
||||||
|
respBody, err := io.ReadAll(resp.Body)
|
||||||
|
if err != nil {
|
||||||
|
return "", fmt.Errorf("读取响应体失败: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 返回响应内容
|
||||||
|
return string(respBody), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// SendGET 发送一个 GET 请求
|
||||||
|
func (p *Request) SendGET(urlPath string, headers map[string]string, params map[string]string) (string, error) {
|
||||||
|
// 如果有查询参数,拼接到 URL 中
|
||||||
|
if len(params) > 0 {
|
||||||
|
urlValues := url.Values{}
|
||||||
|
for key, value := range params {
|
||||||
|
urlValues.Set(key, value)
|
||||||
|
}
|
||||||
|
urlPath = fmt.Sprintf("%s?%s", urlPath, urlValues.Encode())
|
||||||
|
}
|
||||||
|
|
||||||
|
// 创建 HTTP GET 请求
|
||||||
|
req, err := http.NewRequest("GET", urlPath, nil)
|
||||||
|
if err != nil {
|
||||||
|
return "", fmt.Errorf("无法创建请求: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 设置请求头
|
||||||
|
for key, value := range headers {
|
||||||
|
req.Header.Set(key, value)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 发送请求
|
||||||
|
resp, err := p.client.Do(req)
|
||||||
|
if err != nil {
|
||||||
|
return "", fmt.Errorf("发送请求失败: %v", err)
|
||||||
|
}
|
||||||
|
defer resp.Body.Close()
|
||||||
|
|
||||||
|
// 读取响应内容
|
||||||
|
respBody, err := io.ReadAll(resp.Body)
|
||||||
|
if err != nil {
|
||||||
|
return "", fmt.Errorf("读取响应体失败: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 返回响应内容
|
||||||
|
return string(respBody), nil
|
||||||
|
}
|
43
pkg/util/httpUtil/post_request_test.go
Normal file
43
pkg/util/httpUtil/post_request_test.go
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
package httpUtil
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestRequest(t *testing.T) {
|
||||||
|
// 创建 PostRequest 实例
|
||||||
|
postRequest := NewRequest()
|
||||||
|
|
||||||
|
// 示例:发送 JSON 请求
|
||||||
|
url := "https://example.com/api"
|
||||||
|
headers := map[string]string{
|
||||||
|
"Authorization": "Bearer your_token",
|
||||||
|
}
|
||||||
|
body := map[string]interface{}{
|
||||||
|
"key1": "value1",
|
||||||
|
"key2": "value2",
|
||||||
|
}
|
||||||
|
|
||||||
|
// 发送 JSON 请求
|
||||||
|
resp, err := postRequest.SendJSON(url, headers, body)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println("发送请求失败:", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Println("响应内容:", resp)
|
||||||
|
|
||||||
|
// 示例:发送 form-data 请求
|
||||||
|
formParams := map[string]string{
|
||||||
|
"user_id": "your_user_id",
|
||||||
|
"product_id": "12345",
|
||||||
|
}
|
||||||
|
resp2, err := postRequest.SendFormData(url, headers, formParams)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println("发送 form-data 请求失败:", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Println("响应内容:", resp2)
|
||||||
|
}
|
58
pkg/util/strUtil/strUtil.go
Normal file
58
pkg/util/strUtil/strUtil.go
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
package strUtil
|
||||||
|
|
||||||
|
import (
|
||||||
|
"database/sql"
|
||||||
|
"regexp"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
// JoinStrings 字符串拼接
|
||||||
|
func JoinStrings(separator string, elems ...string) string {
|
||||||
|
return strings.Join(elems, separator)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ValidString sql.NullString 转 string
|
||||||
|
func ValidString(sqlString sql.NullString) string {
|
||||||
|
if sqlString.Valid {
|
||||||
|
return sqlString.String
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
// StringToNullString string 转 sql.NullString
|
||||||
|
func StringToNullString(str string) sql.NullString {
|
||||||
|
return sql.NullString{
|
||||||
|
String: str,
|
||||||
|
Valid: str != "",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ValidInt64 sql.NullInt64 转 int64
|
||||||
|
func ValidInt64(sqlInt sql.NullInt64) int64 {
|
||||||
|
if sqlInt.Valid {
|
||||||
|
return sqlInt.Int64
|
||||||
|
}
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// Int64ToNullInt64 StringToNullString int64 转 sql.NullInt64
|
||||||
|
func Int64ToNullInt64(value int64) sql.NullInt64 {
|
||||||
|
return sql.NullInt64{
|
||||||
|
Int64: value,
|
||||||
|
Valid: value >= 0,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ValidBool sql.NullBool 转 bool
|
||||||
|
func ValidBool(sqlBool sql.NullBool) bool {
|
||||||
|
if sqlBool.Valid {
|
||||||
|
return sqlBool.Bool
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// MatchRegexp 正则匹配
|
||||||
|
func MatchRegexp(pattern string, value string) bool {
|
||||||
|
r := regexp.MustCompile(pattern)
|
||||||
|
return r.MatchString(value)
|
||||||
|
}
|
151
pkg/util/tiktok/tiktok.go
Normal file
151
pkg/util/tiktok/tiktok.go
Normal file
@ -0,0 +1,151 @@
|
|||||||
|
package tiktok
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"hk/pkg/util/httpUtil"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
type tiktokResp struct {
|
||||||
|
Code int64 `json:"code"`
|
||||||
|
Data tiktokData `json:"data"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type tiktokData struct {
|
||||||
|
ID string `json:"id"`
|
||||||
|
AwesomeID string `json:"aweme_id"`
|
||||||
|
Region string `json:"region"`
|
||||||
|
Title string `json:"title"`
|
||||||
|
Cover string `json:"cover"`
|
||||||
|
AiDynamicCover string `json:"ai_dynamic_cover"` // 动态封面
|
||||||
|
OriginCover string `json:"origin_cover"` // 静态封面
|
||||||
|
Duration int `json:"duration"`
|
||||||
|
Play string `json:"play"` // 无水印视频
|
||||||
|
Wmplay string `json:"wmplay"` // 有水印视频
|
||||||
|
Size int `json:"size"`
|
||||||
|
WmSize int `json:"wm_size"`
|
||||||
|
Music string `json:"music"`
|
||||||
|
MusicInfo musicInfo `json:"music_info"`
|
||||||
|
PlayCount int `json:"play_count"`
|
||||||
|
DiggCount int `json:"digg_count"`
|
||||||
|
CommentCount int `json:"comment_count"`
|
||||||
|
ShareCount int `json:"share_count"`
|
||||||
|
DownloadCount int `json:"download_count"`
|
||||||
|
CollectCount int `json:"collect_count"`
|
||||||
|
CreateTime int `json:"create_time"`
|
||||||
|
AnchorsExtras string `json:"anchors_extras"`
|
||||||
|
IsAd bool `json:"is_ad"`
|
||||||
|
CommercialVideoInfo string `json:"commercial_video_info"`
|
||||||
|
ItemCommentSettings int `json:"item_comment_settings"`
|
||||||
|
Author authorDTO `json:"author"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type musicInfo struct {
|
||||||
|
ID string `json:"id"`
|
||||||
|
Title string `json:"title"`
|
||||||
|
Play string `json:"play"` // 背景音乐
|
||||||
|
Cover string `json:"cover"`
|
||||||
|
Author string `json:"author"`
|
||||||
|
Original bool `json:"original"`
|
||||||
|
Duration int `json:"duration"`
|
||||||
|
Album string `json:"album"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type authorDTO struct {
|
||||||
|
ID string `json:"id"`
|
||||||
|
UniqueID string `json:"unique_id"`
|
||||||
|
Nickname string `json:"nickname"`
|
||||||
|
Avatar string `json:"avatar"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type VideoInfoResponse struct {
|
||||||
|
AuthorID string `json:"authorId"` // 作者ID
|
||||||
|
AuthorUniqueID string `json:"authorUniqueId"` // 作者账号
|
||||||
|
AuthorAvatar string `json:"authorAvatar"` // 作者头像
|
||||||
|
AuthorNickname string `json:"authorNickname"` // 作者昵称
|
||||||
|
|
||||||
|
VideoID string `json:"videoId"` // 视频ID
|
||||||
|
VideoTitle string `json:"videoTitle"` // 作品描述
|
||||||
|
OriginCover string `json:"originCover"` // 静态封面
|
||||||
|
DynamicCover string `json:"dynamicCover"` // 动态封面
|
||||||
|
DestinationURL string `json:"destinationUrl"` // 无水印下载地址
|
||||||
|
WatermarkVideoURL string `json:"watermarkVideoUrl"` // 有水印下载地址
|
||||||
|
|
||||||
|
MusicURL string `json:"musicUrl"` // 背景音乐链接
|
||||||
|
|
||||||
|
OriginalURL string `json:"originalUrl"` // 原始下载链接
|
||||||
|
DownloaderURL string `json:"downloaderUrl"` // 解析后下载地址
|
||||||
|
CreateTime string `json:"createTime"` // 创建时间
|
||||||
|
Result bool `json:"result"` // 结果
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetTiktokVideoInfo(videoUrl string) (*VideoInfoResponse, error) {
|
||||||
|
if len(videoUrl) <= 0 {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// 解析视频地址
|
||||||
|
// 定义需要匹配的前缀
|
||||||
|
prefixes := []string{
|
||||||
|
"https://www.tiktok.com/t/",
|
||||||
|
"https://m.tiktok.com/v/",
|
||||||
|
"https://vm.tiktok.com/",
|
||||||
|
"https://vt.tiktok.com/",
|
||||||
|
"https://dltik.com/",
|
||||||
|
}
|
||||||
|
|
||||||
|
// 检查是否有匹配的前缀
|
||||||
|
for _, prefix := range prefixes {
|
||||||
|
if strings.HasPrefix(videoUrl, prefix) {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取视频信息
|
||||||
|
var url = "https://tiktok-download-without-watermark.p.rapidapi.com/analysis?url=" + videoUrl
|
||||||
|
headers := map[string]string{
|
||||||
|
"x-rapidapi-host": "tiktok-download-without-watermark.p.rapidapi.com",
|
||||||
|
"x-rapidapi-key": "4a5bbe21bfmshbd98e7404b74063p19ba22jsne87a37e3b675",
|
||||||
|
}
|
||||||
|
|
||||||
|
body, err := httpUtil.NewRequest().SendGET(url, headers, nil)
|
||||||
|
if err != nil || len(body) <= 0 {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
var tiktokResp tiktokResp
|
||||||
|
err = json.Unmarshal([]byte(body), &tiktokResp)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println("解析响应体时发生错误:", err)
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
// 比对 statusCode 是否等于0
|
||||||
|
if tiktokResp.Code != 0 {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
var videoInfo = VideoInfoResponse{}
|
||||||
|
|
||||||
|
// 作者信息
|
||||||
|
videoInfo.AuthorID = tiktokResp.Data.Author.ID
|
||||||
|
videoInfo.AuthorAvatar = tiktokResp.Data.Author.Avatar
|
||||||
|
videoInfo.AuthorUniqueID = tiktokResp.Data.Author.UniqueID
|
||||||
|
videoInfo.AuthorNickname = tiktokResp.Data.Author.Nickname
|
||||||
|
|
||||||
|
videoInfo.VideoID = tiktokResp.Data.ID
|
||||||
|
videoInfo.VideoTitle = tiktokResp.Data.Title
|
||||||
|
videoInfo.OriginCover = tiktokResp.Data.OriginCover
|
||||||
|
videoInfo.DynamicCover = tiktokResp.Data.AiDynamicCover
|
||||||
|
videoInfo.DestinationURL = tiktokResp.Data.Play
|
||||||
|
videoInfo.WatermarkVideoURL = tiktokResp.Data.Wmplay
|
||||||
|
|
||||||
|
videoInfo.MusicURL = tiktokResp.Data.MusicInfo.Play
|
||||||
|
|
||||||
|
videoInfo.OriginalURL = videoUrl
|
||||||
|
videoInfo.DownloaderURL = videoUrl
|
||||||
|
|
||||||
|
//videoInfo.CreateTime = tiktokResp.Data.CreateTime
|
||||||
|
|
||||||
|
videoInfo.Result = true
|
||||||
|
return &videoInfo, nil
|
||||||
|
}
|
7
pkg/util/tiktok/tiktok_test.go
Normal file
7
pkg/util/tiktok/tiktok_test.go
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
package tiktok
|
||||||
|
|
||||||
|
import "testing"
|
||||||
|
|
||||||
|
func TestTikTok(test *testing.T) {
|
||||||
|
GetTiktokVideoInfo("https://www.tiktok.com/@baotramthieu/video/6887554215598689538")
|
||||||
|
}
|
33
service/api/Dockerfile
Normal file
33
service/api/Dockerfile
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
FROM golang:alpine as builder
|
||||||
|
# 设置工作目录
|
||||||
|
WORKDIR /hk
|
||||||
|
# 将当前目录内容拷到工作目录 (相对路径)
|
||||||
|
COPY ../../../ .
|
||||||
|
|
||||||
|
# 配置 golang 环境
|
||||||
|
RUN go env -w GO111MODULE=on \
|
||||||
|
&& go env -w GOPROXY=https://goproxy.cn,https://goproxy.io,direct \
|
||||||
|
&& go mod tidy \
|
||||||
|
&& go build -o main ./service/api/api.go
|
||||||
|
|
||||||
|
# 使用更小的基础镜像
|
||||||
|
FROM alpine:latest
|
||||||
|
|
||||||
|
# 设置工作目录
|
||||||
|
WORKDIR /hk
|
||||||
|
ENV WORK_PATH /hk
|
||||||
|
|
||||||
|
WORKDIR ${WORK_PATH}
|
||||||
|
|
||||||
|
# 从构建阶段复制二进制文件
|
||||||
|
COPY --from=builder ${WORK_PATH}/main .
|
||||||
|
COPY --from=0 ${WORK_PATH}/service/api/etc/api.yaml ./config/
|
||||||
|
|
||||||
|
# 暴露端口
|
||||||
|
EXPOSE 8888
|
||||||
|
|
||||||
|
# 如果不使用上面的方式需要打开下面这行注释
|
||||||
|
# ENTRYPOINT ./main -c config.docker.toml
|
||||||
|
|
||||||
|
###############################################
|
||||||
|
CMD ["./main","-f","./config/api.yaml"]
|
34
service/api/api.go
Normal file
34
service/api/api.go
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"flag"
|
||||||
|
"fmt"
|
||||||
|
"hk/service/api/internal/cmd"
|
||||||
|
"hk/service/api/internal/config"
|
||||||
|
"hk/service/api/internal/handler"
|
||||||
|
"hk/service/api/internal/svc"
|
||||||
|
|
||||||
|
"github.com/zeromicro/go-zero/core/conf"
|
||||||
|
"github.com/zeromicro/go-zero/rest"
|
||||||
|
)
|
||||||
|
|
||||||
|
var configFile = flag.String("f", "service/api/etc/api.yaml", "the config file")
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
flag.Parse()
|
||||||
|
|
||||||
|
var c config.Config
|
||||||
|
conf.MustLoad(*configFile, &c)
|
||||||
|
|
||||||
|
server := rest.MustNewServer(c.RestConf)
|
||||||
|
|
||||||
|
defer server.Stop()
|
||||||
|
|
||||||
|
ctx := svc.NewServiceContext(c)
|
||||||
|
handler.RegisterHandlers(server, ctx)
|
||||||
|
|
||||||
|
cmd.Execute(ctx)
|
||||||
|
|
||||||
|
fmt.Printf("Starting server at %s:%d...\n", c.Host, c.Port)
|
||||||
|
server.Start()
|
||||||
|
}
|
22
service/api/etc/api.yaml
Normal file
22
service/api/etc/api.yaml
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
Name: HK
|
||||||
|
Host: 0.0.0.0
|
||||||
|
Port: 8888
|
||||||
|
|
||||||
|
# 控制go-zero提供的中间件是否启用
|
||||||
|
# Middlewares:
|
||||||
|
# Breaker: false
|
||||||
|
# Shedding: false
|
||||||
|
# Metrics: false
|
||||||
|
Log:
|
||||||
|
Stat: false
|
||||||
|
|
||||||
|
Mysql:
|
||||||
|
DataSource: root:G6fB2okoPstKvA6R@tcp(110.40.44.75:3306)/hk?charset=utf8mb4&parseTime=true&loc=Asia%2FShanghai
|
||||||
|
|
||||||
|
Auth:
|
||||||
|
AccessSecret: uOvKLmVfztaXGpNYd4Z0I1SiT7MweJhl
|
||||||
|
AccessExpire: 86400
|
||||||
|
|
||||||
|
Redis:
|
||||||
|
Host: 192.168.1.13:6379
|
||||||
|
Type: node
|
145
service/api/internal/cmd/config_api_list.go
Normal file
145
service/api/internal/cmd/config_api_list.go
Normal file
@ -0,0 +1,145 @@
|
|||||||
|
package cmd
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"database/sql"
|
||||||
|
"fmt"
|
||||||
|
"hk/model/config_api"
|
||||||
|
"hk/model/goods_info"
|
||||||
|
"hk/model/goods_status"
|
||||||
|
_73 "hk/pkg/util/172"
|
||||||
|
"hk/pkg/util/strUtil"
|
||||||
|
"strconv"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
func configApiList() {
|
||||||
|
configApiInfo, err := svcCtx.ConfigApiModel.FindList(context.Background())
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println(err)
|
||||||
|
}
|
||||||
|
if configApiInfo == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
for _, item := range configApiInfo {
|
||||||
|
switch item.Type {
|
||||||
|
case "0":
|
||||||
|
getGoodsStatus(item)
|
||||||
|
updateGoodsStatus(item)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func configApiListv1() {
|
||||||
|
configApiInfo, err := svcCtx.ConfigApiModel.FindList(context.Background())
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println(err)
|
||||||
|
}
|
||||||
|
if configApiInfo == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
for _, item := range configApiInfo {
|
||||||
|
switch item.Type {
|
||||||
|
case "0":
|
||||||
|
addGoodsInfo(item)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func addGoodsInfo(configApi config_api.ConfigApi) {
|
||||||
|
ids, err := svcCtx.GoodsStatusModel.FindNotIdOne(context.Background(), configApi.Id)
|
||||||
|
if err != nil || ids <= 0 {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
req := _73.GoodsReq{
|
||||||
|
ProductID: strconv.FormatInt(ids, 10),
|
||||||
|
BaseParams: _73.BaseParams{
|
||||||
|
UserID: strUtil.ValidString(configApi.Key),
|
||||||
|
UserSign: strUtil.ValidString(configApi.Secret),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
result, err := _73.GetProductV2(req)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if result.Code != 0 || len(result.Data) <= 0 {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
data := result.Data[0]
|
||||||
|
status := "0"
|
||||||
|
if data.Flag {
|
||||||
|
status = "1"
|
||||||
|
}
|
||||||
|
goodsStatus := goods_info.GoodsInfo{
|
||||||
|
Name: data.ProductName,
|
||||||
|
Type: "0",
|
||||||
|
MainPic: data.MainPic,
|
||||||
|
LittlePicture: data.LittlePicture,
|
||||||
|
NetAddr: data.NetAddr,
|
||||||
|
Area: data.Area,
|
||||||
|
DisableArea: data.DisableArea,
|
||||||
|
DisableAge: "",
|
||||||
|
DisableContract: "",
|
||||||
|
Notes: sql.NullString{},
|
||||||
|
ApiId: strUtil.Int64ToNullInt64(configApi.Id),
|
||||||
|
ApiProductId: strUtil.Int64ToNullInt64(data.ProductID),
|
||||||
|
NumberSel: strconv.Itoa(data.NumberSel),
|
||||||
|
Status: status,
|
||||||
|
CreateTime: time.Now(),
|
||||||
|
UpdateTime: time.Now(),
|
||||||
|
Remarks: sql.NullString{},
|
||||||
|
}
|
||||||
|
svcCtx.GoodsInfoModel.Insert(context.Background(), &goodsStatus)
|
||||||
|
}
|
||||||
|
|
||||||
|
func updateGoodsStatus(item config_api.ConfigApi) {
|
||||||
|
ids, err := svcCtx.GoodsStatusModel.FindUpList(context.Background(), item.Id)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if len(ids) <= 0 {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
svcCtx.GoodsStatusModel.UpdateDownByIds(context.Background(), ids)
|
||||||
|
}
|
||||||
|
|
||||||
|
func getGoodsStatus(configApi config_api.ConfigApi) {
|
||||||
|
req := _73.GoodsReq{
|
||||||
|
ProductID: "",
|
||||||
|
BaseParams: _73.BaseParams{
|
||||||
|
UserID: strUtil.ValidString(configApi.Key),
|
||||||
|
UserSign: strUtil.ValidString(configApi.Secret),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
result, err := _73.GetProduct(req)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if result.Code == 0 {
|
||||||
|
var goodsStatusList []goods_status.GoodsStatus
|
||||||
|
if len(result.Data) > 0 {
|
||||||
|
err = svcCtx.GoodsStatusModel.DeleteByApiId(context.Background(), configApi.Id)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for _, item := range result.Data {
|
||||||
|
var status int64 = 0
|
||||||
|
if item.Flag == "上架中" {
|
||||||
|
status = 1
|
||||||
|
}
|
||||||
|
goodsStatus := goods_status.GoodsStatus{
|
||||||
|
ApiId: strUtil.Int64ToNullInt64(configApi.Id),
|
||||||
|
ApiProductId: strUtil.Int64ToNullInt64(item.ProductID),
|
||||||
|
Status: strUtil.Int64ToNullInt64(status),
|
||||||
|
}
|
||||||
|
svcCtx.GoodsStatusModel.Insert(context.Background(), &goodsStatus)
|
||||||
|
goodsStatusList = append(goodsStatusList, goodsStatus)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
46
service/api/internal/cmd/cronx/time.go
Normal file
46
service/api/internal/cmd/cronx/time.go
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
package cronx
|
||||||
|
|
||||||
|
// 每5秒
|
||||||
|
func Every5s() string {
|
||||||
|
return "*/5 * * * * *"
|
||||||
|
}
|
||||||
|
|
||||||
|
// 每10秒
|
||||||
|
func Every10s() string {
|
||||||
|
return "*/10 * * * * *"
|
||||||
|
}
|
||||||
|
|
||||||
|
// 每分钟
|
||||||
|
func EveryMinute() string {
|
||||||
|
return "0 */1 * * * *"
|
||||||
|
}
|
||||||
|
|
||||||
|
// 每五分钟
|
||||||
|
func EveryFiveMinute() string {
|
||||||
|
return "0 */5 * * * *"
|
||||||
|
}
|
||||||
|
|
||||||
|
// 每十分钟
|
||||||
|
func EveryTenMinute() string {
|
||||||
|
return "0 */10 * * * *"
|
||||||
|
}
|
||||||
|
|
||||||
|
// 每半小时
|
||||||
|
func EveryHalfHour() string {
|
||||||
|
return "0 0,30 * * * *"
|
||||||
|
}
|
||||||
|
|
||||||
|
// EveryHour 每小时
|
||||||
|
func EveryHour() string {
|
||||||
|
return "0 0 * * * *"
|
||||||
|
}
|
||||||
|
|
||||||
|
// 每几分钟执行 1,2,3,26
|
||||||
|
func Hourly(m string) string {
|
||||||
|
return "0 " + m + " * * * *"
|
||||||
|
}
|
||||||
|
|
||||||
|
// 每天几点执行
|
||||||
|
func Daily(h string) string {
|
||||||
|
return "0 0 " + h + " * * *"
|
||||||
|
}
|
20
service/api/internal/cmd/root.go
Normal file
20
service/api/internal/cmd/root.go
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
package cmd
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/robfig/cron/v3"
|
||||||
|
"hk/service/api/internal/svc"
|
||||||
|
)
|
||||||
|
|
||||||
|
var svcCtx *svc.ServiceContext
|
||||||
|
|
||||||
|
func Execute(ctx *svc.ServiceContext) {
|
||||||
|
svcCtx = ctx
|
||||||
|
c := cron.New(cron.WithSeconds())
|
||||||
|
|
||||||
|
ScheduleRun(c)
|
||||||
|
fmt.Println("定时任务启动...")
|
||||||
|
go c.Start()
|
||||||
|
defer c.Stop()
|
||||||
|
//select {}
|
||||||
|
}
|
11
service/api/internal/cmd/schedule.go
Normal file
11
service/api/internal/cmd/schedule.go
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
package cmd
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/robfig/cron/v3"
|
||||||
|
"hk/service/api/internal/cmd/cronx"
|
||||||
|
)
|
||||||
|
|
||||||
|
func ScheduleRun(c *cron.Cron) {
|
||||||
|
c.AddFunc(cronx.EveryHour(), configApiList)
|
||||||
|
c.AddFunc(cronx.EveryTenMinute(), configApiListv1)
|
||||||
|
}
|
21
service/api/internal/config/config.go
Normal file
21
service/api/internal/config/config.go
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
package config
|
||||||
|
|
||||||
|
import "github.com/zeromicro/go-zero/rest"
|
||||||
|
|
||||||
|
type Config struct {
|
||||||
|
rest.RestConf
|
||||||
|
|
||||||
|
Auth struct {
|
||||||
|
AccessSecret string
|
||||||
|
AccessExpire int64
|
||||||
|
}
|
||||||
|
|
||||||
|
Mysql struct {
|
||||||
|
DataSource string
|
||||||
|
}
|
||||||
|
|
||||||
|
Redis struct {
|
||||||
|
Host string
|
||||||
|
Type string
|
||||||
|
}
|
||||||
|
}
|
28
service/api/internal/handler/api/goodsdetailshandler.go
Normal file
28
service/api/internal/handler/api/goodsdetailshandler.go
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
package api
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
"github.com/zeromicro/go-zero/rest/httpx"
|
||||||
|
"hk/service/api/internal/logic/api"
|
||||||
|
"hk/service/api/internal/svc"
|
||||||
|
"hk/service/api/internal/types"
|
||||||
|
)
|
||||||
|
|
||||||
|
func GoodsDetailsHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
|
||||||
|
return func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
var req types.GoodsDetailsReq
|
||||||
|
if err := httpx.Parse(r, &req); err != nil {
|
||||||
|
httpx.ErrorCtx(r.Context(), w, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
l := api.NewGoodsDetailsLogic(r.Context(), svcCtx)
|
||||||
|
resp, err := l.GoodsDetails(&req)
|
||||||
|
if err != nil {
|
||||||
|
httpx.ErrorCtx(r.Context(), w, err)
|
||||||
|
} else {
|
||||||
|
httpx.OkJsonCtx(r.Context(), w, resp)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
28
service/api/internal/handler/api/goodslisthandler.go
Normal file
28
service/api/internal/handler/api/goodslisthandler.go
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
package api
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
"github.com/zeromicro/go-zero/rest/httpx"
|
||||||
|
"hk/service/api/internal/logic/api"
|
||||||
|
"hk/service/api/internal/svc"
|
||||||
|
"hk/service/api/internal/types"
|
||||||
|
)
|
||||||
|
|
||||||
|
func GoodsListHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
|
||||||
|
return func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
var req types.GoodsListReq
|
||||||
|
if err := httpx.Parse(r, &req); err != nil {
|
||||||
|
httpx.ErrorCtx(r.Context(), w, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
l := api.NewGoodsListLogic(r.Context(), svcCtx)
|
||||||
|
resp, err := l.GoodsList(&req)
|
||||||
|
if err != nil {
|
||||||
|
httpx.ErrorCtx(r.Context(), w, err)
|
||||||
|
} else {
|
||||||
|
httpx.OkJsonCtx(r.Context(), w, resp)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
28
service/api/internal/handler/api/order172handler.go
Normal file
28
service/api/internal/handler/api/order172handler.go
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
package api
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
"github.com/zeromicro/go-zero/rest/httpx"
|
||||||
|
"hk/service/api/internal/logic/api"
|
||||||
|
"hk/service/api/internal/svc"
|
||||||
|
"hk/service/api/internal/types"
|
||||||
|
)
|
||||||
|
|
||||||
|
func Order172Handler(svcCtx *svc.ServiceContext) http.HandlerFunc {
|
||||||
|
return func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
var req types.PushReq
|
||||||
|
if err := httpx.Parse(r, &req); err != nil {
|
||||||
|
httpx.ErrorCtx(r.Context(), w, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
l := api.NewOrder172Logic(r.Context(), svcCtx)
|
||||||
|
resp, err := l.Order172(&req)
|
||||||
|
if err != nil {
|
||||||
|
httpx.ErrorCtx(r.Context(), w, err)
|
||||||
|
} else {
|
||||||
|
httpx.OkJsonCtx(r.Context(), w, resp)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
28
service/api/internal/handler/api/tiktokinfohandler.go
Normal file
28
service/api/internal/handler/api/tiktokinfohandler.go
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
package api
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
"github.com/zeromicro/go-zero/rest/httpx"
|
||||||
|
"hk/service/api/internal/logic/api"
|
||||||
|
"hk/service/api/internal/svc"
|
||||||
|
"hk/service/api/internal/types"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TiktokInfoHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
|
||||||
|
return func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
var req types.TiktokReq
|
||||||
|
if err := httpx.Parse(r, &req); err != nil {
|
||||||
|
httpx.ErrorCtx(r.Context(), w, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
l := api.NewTiktokInfoLogic(r.Context(), svcCtx)
|
||||||
|
resp, err := l.TiktokInfo(&req)
|
||||||
|
if err != nil {
|
||||||
|
httpx.ErrorCtx(r.Context(), w, err)
|
||||||
|
} else {
|
||||||
|
httpx.OkJsonCtx(r.Context(), w, resp)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
44
service/api/internal/handler/routes.go
Normal file
44
service/api/internal/handler/routes.go
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
// Code generated by goctl. DO NOT EDIT.
|
||||||
|
// goctl 1.7.6
|
||||||
|
|
||||||
|
package handler
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
api "hk/service/api/internal/handler/api"
|
||||||
|
"hk/service/api/internal/svc"
|
||||||
|
|
||||||
|
"github.com/zeromicro/go-zero/rest"
|
||||||
|
)
|
||||||
|
|
||||||
|
func RegisterHandlers(server *rest.Server, serverCtx *svc.ServiceContext) {
|
||||||
|
server.AddRoutes(
|
||||||
|
rest.WithMiddlewares(
|
||||||
|
[]rest.Middleware{serverCtx.RealIPMiddleware},
|
||||||
|
[]rest.Route{
|
||||||
|
{
|
||||||
|
Method: http.MethodGet,
|
||||||
|
Path: "/goods/:id",
|
||||||
|
Handler: api.GoodsDetailsHandler(serverCtx),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Method: http.MethodGet,
|
||||||
|
Path: "/goods/list",
|
||||||
|
Handler: api.GoodsListHandler(serverCtx),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Method: http.MethodPost,
|
||||||
|
Path: "/push/order172",
|
||||||
|
Handler: api.Order172Handler(serverCtx),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Method: http.MethodPost,
|
||||||
|
Path: "/tiktok/getVideoInfo",
|
||||||
|
Handler: api.TiktokInfoHandler(serverCtx),
|
||||||
|
},
|
||||||
|
}...,
|
||||||
|
),
|
||||||
|
rest.WithPrefix("/api"),
|
||||||
|
)
|
||||||
|
}
|
48
service/api/internal/logic/api/goodsdetailslogic.go
Normal file
48
service/api/internal/logic/api/goodsdetailslogic.go
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
package api
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"hk/pkg/util/strUtil"
|
||||||
|
|
||||||
|
"hk/service/api/internal/svc"
|
||||||
|
"hk/service/api/internal/types"
|
||||||
|
|
||||||
|
"github.com/zeromicro/go-zero/core/logx"
|
||||||
|
)
|
||||||
|
|
||||||
|
type GoodsDetailsLogic struct {
|
||||||
|
logx.Logger
|
||||||
|
ctx context.Context
|
||||||
|
svcCtx *svc.ServiceContext
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewGoodsDetailsLogic(ctx context.Context, svcCtx *svc.ServiceContext) *GoodsDetailsLogic {
|
||||||
|
return &GoodsDetailsLogic{
|
||||||
|
Logger: logx.WithContext(ctx),
|
||||||
|
ctx: ctx,
|
||||||
|
svcCtx: svcCtx,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *GoodsDetailsLogic) GoodsDetails(req *types.GoodsDetailsReq) (resp *types.GoodsDetailsResp, err error) {
|
||||||
|
if req.Id <= 0 {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
goods, err := l.svcCtx.GoodsInfoModel.FindOne(l.ctx, req.Id)
|
||||||
|
if err != nil || goods == nil || goods.Status == "0" {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
resp = &types.GoodsDetailsResp{
|
||||||
|
Data: types.GoodsItem{
|
||||||
|
Id: goods.Id,
|
||||||
|
Name: goods.Name,
|
||||||
|
MainPic: goods.MainPic,
|
||||||
|
DisableAge: goods.DisableAge,
|
||||||
|
UniFlow: goods.UniFlow,
|
||||||
|
DirFlow: goods.DirFlow,
|
||||||
|
TalkTime: goods.TalkTime,
|
||||||
|
Remarks: strUtil.ValidString(goods.Remarks),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
return resp, nil
|
||||||
|
}
|
50
service/api/internal/logic/api/goodslistlogic.go
Normal file
50
service/api/internal/logic/api/goodslistlogic.go
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
package api
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"hk/pkg/util/strUtil"
|
||||||
|
|
||||||
|
"hk/service/api/internal/svc"
|
||||||
|
"hk/service/api/internal/types"
|
||||||
|
|
||||||
|
"github.com/zeromicro/go-zero/core/logx"
|
||||||
|
)
|
||||||
|
|
||||||
|
type GoodsListLogic struct {
|
||||||
|
logx.Logger
|
||||||
|
ctx context.Context
|
||||||
|
svcCtx *svc.ServiceContext
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewGoodsListLogic(ctx context.Context, svcCtx *svc.ServiceContext) *GoodsListLogic {
|
||||||
|
return &GoodsListLogic{
|
||||||
|
Logger: logx.WithContext(ctx),
|
||||||
|
ctx: ctx,
|
||||||
|
svcCtx: svcCtx,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *GoodsListLogic) GoodsList(req *types.GoodsListReq) (resp *types.GoodsListResp, err error) {
|
||||||
|
goods, err := l.svcCtx.GoodsInfoModel.GetGoodsIndex(l.ctx, req.Type)
|
||||||
|
if err != nil || len(goods) == 0 {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
var goodsList []types.GoodsItem
|
||||||
|
for _, item := range goods {
|
||||||
|
good := types.GoodsItem{
|
||||||
|
Id: item.Id,
|
||||||
|
Name: item.Name,
|
||||||
|
MainPic: item.MainPic,
|
||||||
|
DisableAge: item.DisableAge,
|
||||||
|
UniFlow: item.UniFlow,
|
||||||
|
DirFlow: item.DirFlow,
|
||||||
|
TalkTime: item.TalkTime,
|
||||||
|
Remarks: strUtil.ValidString(item.Remarks),
|
||||||
|
}
|
||||||
|
goodsList = append(goodsList, good)
|
||||||
|
}
|
||||||
|
resp = &types.GoodsListResp{
|
||||||
|
Data: goodsList,
|
||||||
|
}
|
||||||
|
return resp, nil
|
||||||
|
}
|
30
service/api/internal/logic/api/order172logic.go
Normal file
30
service/api/internal/logic/api/order172logic.go
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
package api
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
|
"hk/service/api/internal/svc"
|
||||||
|
"hk/service/api/internal/types"
|
||||||
|
|
||||||
|
"github.com/zeromicro/go-zero/core/logx"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Order172Logic struct {
|
||||||
|
logx.Logger
|
||||||
|
ctx context.Context
|
||||||
|
svcCtx *svc.ServiceContext
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewOrder172Logic(ctx context.Context, svcCtx *svc.ServiceContext) *Order172Logic {
|
||||||
|
return &Order172Logic{
|
||||||
|
Logger: logx.WithContext(ctx),
|
||||||
|
ctx: ctx,
|
||||||
|
svcCtx: svcCtx,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *Order172Logic) Order172(req *types.PushReq) (resp *types.Push172Resp, err error) {
|
||||||
|
// todo: add your logic here and delete this line
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
53
service/api/internal/logic/api/tiktokinfologic.go
Normal file
53
service/api/internal/logic/api/tiktokinfologic.go
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
package api
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"hk/pkg/util/tiktok"
|
||||||
|
|
||||||
|
"hk/service/api/internal/svc"
|
||||||
|
"hk/service/api/internal/types"
|
||||||
|
|
||||||
|
"github.com/zeromicro/go-zero/core/logx"
|
||||||
|
)
|
||||||
|
|
||||||
|
type TiktokInfoLogic struct {
|
||||||
|
logx.Logger
|
||||||
|
ctx context.Context
|
||||||
|
svcCtx *svc.ServiceContext
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewTiktokInfoLogic(ctx context.Context, svcCtx *svc.ServiceContext) *TiktokInfoLogic {
|
||||||
|
return &TiktokInfoLogic{
|
||||||
|
Logger: logx.WithContext(ctx),
|
||||||
|
ctx: ctx,
|
||||||
|
svcCtx: svcCtx,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *TiktokInfoLogic) TiktokInfo(req *types.TiktokReq) (resp *types.TiktokResp, err error) {
|
||||||
|
if len(req.VideoUrl) <= 0 {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
tiktokInfo, err := tiktok.GetTiktokVideoInfo(req.VideoUrl)
|
||||||
|
if err != nil || tiktokInfo == nil {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
resp = &types.TiktokResp{
|
||||||
|
AuthorID: tiktokInfo.AuthorID,
|
||||||
|
AuthorAvatar: tiktokInfo.AuthorAvatar,
|
||||||
|
AuthorUniqueID: tiktokInfo.AuthorUniqueID,
|
||||||
|
AuthorNickname: tiktokInfo.AuthorNickname,
|
||||||
|
VideoID: tiktokInfo.VideoID,
|
||||||
|
VideoTitle: tiktokInfo.VideoTitle,
|
||||||
|
OriginCover: tiktokInfo.OriginCover,
|
||||||
|
DynamicCover: tiktokInfo.DynamicCover,
|
||||||
|
DestinationURL: tiktokInfo.DestinationURL,
|
||||||
|
WatermarkVideoURL: tiktokInfo.WatermarkVideoURL,
|
||||||
|
MusicURL: tiktokInfo.MusicURL,
|
||||||
|
OriginalURL: tiktokInfo.OriginalURL,
|
||||||
|
DownloaderURL: tiktokInfo.DownloaderURL,
|
||||||
|
CreateTime: tiktokInfo.CreateTime,
|
||||||
|
Result: true,
|
||||||
|
}
|
||||||
|
return resp, nil
|
||||||
|
}
|
22
service/api/internal/middleware/realipmiddleware.go
Normal file
22
service/api/internal/middleware/realipmiddleware.go
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
package middleware
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"hk/pkg/middleware"
|
||||||
|
"net/http"
|
||||||
|
)
|
||||||
|
|
||||||
|
type RealIPMiddleware struct {
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewRealIPMiddleware() *RealIPMiddleware {
|
||||||
|
return &RealIPMiddleware{}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *RealIPMiddleware) Handle(next http.HandlerFunc) http.HandlerFunc {
|
||||||
|
return func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
ipaddress := middleware.GetRealIP(r)
|
||||||
|
ctx := context.WithValue(r.Context(), "ip", ipaddress)
|
||||||
|
next(w, r.WithContext(ctx))
|
||||||
|
}
|
||||||
|
}
|
29
service/api/internal/svc/servicecontext.go
Normal file
29
service/api/internal/svc/servicecontext.go
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
package svc
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/zeromicro/go-zero/core/stores/sqlx"
|
||||||
|
"github.com/zeromicro/go-zero/rest"
|
||||||
|
"hk/model/config_api"
|
||||||
|
"hk/model/goods_info"
|
||||||
|
"hk/model/goods_status"
|
||||||
|
"hk/service/api/internal/config"
|
||||||
|
"hk/service/api/internal/middleware"
|
||||||
|
)
|
||||||
|
|
||||||
|
type ServiceContext struct {
|
||||||
|
Config config.Config
|
||||||
|
RealIPMiddleware rest.Middleware
|
||||||
|
ConfigApiModel config_api.ConfigApiModel
|
||||||
|
GoodsStatusModel goods_status.GoodsStatusModel
|
||||||
|
GoodsInfoModel goods_info.GoodsInfoModel
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewServiceContext(c config.Config) *ServiceContext {
|
||||||
|
return &ServiceContext{
|
||||||
|
Config: c,
|
||||||
|
RealIPMiddleware: middleware.NewRealIPMiddleware().Handle,
|
||||||
|
ConfigApiModel: config_api.NewConfigApiModel(sqlx.NewMysql(c.Mysql.DataSource)),
|
||||||
|
GoodsStatusModel: goods_status.NewGoodsStatusModel(sqlx.NewMysql(c.Mysql.DataSource)),
|
||||||
|
GoodsInfoModel: goods_info.NewGoodsInfoModel(sqlx.NewMysql(c.Mysql.DataSource)),
|
||||||
|
}
|
||||||
|
}
|
75
service/api/internal/types/types.go
Normal file
75
service/api/internal/types/types.go
Normal file
@ -0,0 +1,75 @@
|
|||||||
|
// Code generated by goctl. DO NOT EDIT.
|
||||||
|
// goctl 1.7.6
|
||||||
|
|
||||||
|
package types
|
||||||
|
|
||||||
|
type GoodsDetailsReq struct {
|
||||||
|
Id int64 `path:"id"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type GoodsDetailsResp struct {
|
||||||
|
Data GoodsItem `json:"data"` // Y 商品详情
|
||||||
|
}
|
||||||
|
|
||||||
|
type GoodsItem struct {
|
||||||
|
Id int64 `json:"id"` // Y 商品ID
|
||||||
|
Name string `json:"name"` // Y 商品信息
|
||||||
|
MainPic string `json:"mainPic"` // Y 主图
|
||||||
|
DisableAge string `json:"disableAge"` // Y 年龄限制
|
||||||
|
UniFlow string `json:"uniFlow"` // Y 通用流量
|
||||||
|
DirFlow string `json:"dirFlow"` // Y 定向流量
|
||||||
|
TalkTime string `json:"talkTime"` // Y 通话时长
|
||||||
|
Remarks string `json:"remarks"` // Y 备注
|
||||||
|
}
|
||||||
|
|
||||||
|
type GoodsListReq struct {
|
||||||
|
Type string `json:"type":"type,default=0"` // Y 运营商 0:全部 1:电信 2:联通 3:移动 4:光电
|
||||||
|
}
|
||||||
|
|
||||||
|
type GoodsListResp struct {
|
||||||
|
Data []GoodsItem `json:"data"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type Order172 struct {
|
||||||
|
OrderNo string `json:"OrderNo"` // Y 合作方订单号
|
||||||
|
OrderNo172 string `json:"OrderNo172"` // Y 172平台订单号,请求头sign里加密的是这个号码。
|
||||||
|
OrderStatus string `json:"OrderStatus"` // Y 订单状态:已发货,已完成,审核不通过,已取消,已撤单
|
||||||
|
ThirdPhone string `json:"ThirdPhone"` // N 办理号码
|
||||||
|
ExpressName string `json:"ExpressName"` // N 物流公司
|
||||||
|
ExpressCode string `json:"ExpressCode"` // N 物流单号
|
||||||
|
CardStatus string `json:"CardStatus"` // N 激活状态:已激活,未激活,可能为Null
|
||||||
|
ActiveTime string `json:"ActiveTime"` // N 激活时间格式yyyy-MM-dd HH:mm:ss,可能为Null
|
||||||
|
Remark string `json:"Remark"` // N 备注失败原因
|
||||||
|
}
|
||||||
|
|
||||||
|
type Push172Resp struct {
|
||||||
|
Code int64 `json:"code",options=-1|0` // Y 响应码 -1错误 0正常
|
||||||
|
Msg string `json:"message"` // Y 错误信息
|
||||||
|
}
|
||||||
|
|
||||||
|
type PushReq struct {
|
||||||
|
RequidId string `json:"RequidId"` // Y 推送请求唯一ID
|
||||||
|
Data Order172 `json:"Data"` // Y 返回订单信息
|
||||||
|
}
|
||||||
|
|
||||||
|
type TiktokReq struct {
|
||||||
|
VideoUrl string `json:"videoUrl"` // 视频地址
|
||||||
|
}
|
||||||
|
|
||||||
|
type TiktokResp struct {
|
||||||
|
AuthorID string `json:"authorId"` // 作者ID
|
||||||
|
AuthorUniqueID string `json:"authorUniqueId"` // 作者账号
|
||||||
|
AuthorAvatar string `json:"authorAvatar"` // 作者头像
|
||||||
|
AuthorNickname string `json:"authorNickname"` // 作者昵称
|
||||||
|
VideoID string `json:"videoId"` // 视频ID
|
||||||
|
VideoTitle string `json:"videoTitle"` // 作品描述
|
||||||
|
OriginCover string `json:"originCover"` // 静态封面
|
||||||
|
DynamicCover string `json:"dynamicCover"` // 动态封面
|
||||||
|
DestinationURL string `json:"destinationUrl"` // 无水印下载地址
|
||||||
|
WatermarkVideoURL string `json:"watermarkVideoUrl"` // 有水印下载地址
|
||||||
|
MusicURL string `json:"musicUrl"` // 背景音乐链接
|
||||||
|
OriginalURL string `json:"originalUrl"` // 原始下载链接
|
||||||
|
DownloaderURL string `json:"downloaderUrl"` // 解析后下载地址
|
||||||
|
CreateTime string `json:"createTime"` // 创建时间
|
||||||
|
Result bool `json:"result"` // 结果
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user