diff --git a/api/v1/common.proto b/api/v1/common.proto deleted file mode 100644 index 8573024..0000000 --- a/api/v1/common.proto +++ /dev/null @@ -1,47 +0,0 @@ -syntax = "proto3"; - -package api.v1; -option go_package = "voucher/api/v1;v1"; - -// 空请求或返回 -message Empty {} - -// 空参数请求 -message ReqEmpty {} - -// 空返回 -message RespEmpty {} - -// 响应选项数据 -message RespOption { - // 名称 - string label = 1; - // 值 - string value = 2; - // 是否选择 - bool select = 3; - // 禁止操作 - bool disable = 4; - //下级选项数据 - repeated RespOption children = 5; -} - -// 响应选项数据列表 -message RespOptions { - // 选项列表 - repeated RespOption list = 1; -} - -// ReqPage 分页响应参数 -message RespPage { - //页码 - int32 page = 1; - //每页数量 - int32 limit = 2; - //总数 - int32 total = 3; -} - - - - diff --git a/api/v1/order.proto b/api/v1/order.proto index 954cb52..25ae413 100644 --- a/api/v1/order.proto +++ b/api/v1/order.proto @@ -3,38 +3,34 @@ syntax = "proto3"; package api.v1; option go_package = "voucher/api/v1;v1"; -import "google/api/annotations.proto"; import "validate/validate.proto"; -import "v1/common.proto"; -service Order { - rpc Order (OrderRequest) returns (OrderReply) { - option (google.api.http) = { - post: "/openapi/v1/voucher/order", - body:"*" - }; - } - - rpc Query (QueryRequest) returns (QueryReply) { - option (google.api.http) = { - post: "/openapi/v1/voucher/query", - body:"*" - }; - } +message OrderCmbRequest { + // 唯一流水号,需支持14天内幂等 + string transactionId = 1 [json_name = "transactionId", (validate.rules).string = {min_len: 1,max_len: 50}]; + // 外部合作方权益批次号 + string activityId = 2 [json_name = "activityId", (validate.rules).string = {min_len: 1,max_len: 32}]; + // 招商银行用户号 用户标识,比如手机号、支付宝openId + string cmbUid = 3 [json_name = "cmbUid", (validate.rules).string = {min_len: 1,max_len: 100}]; + // 用户标识类型,0-手机号,1-支付宝openId + string cmbUidType = 4 [json_name = "cmbUidType", (validate.rules).string = {min_len: 1,max_len: 10}]; + // 时间戳,长度为13位,精度为毫秒 + string timestamp = 5 [json_name = "timestamp", (validate.rules).string = {min_len: 1,max_len: 20}]; } - -message OrderRequest { - -} -message OrderReply { - +message OrderCmbReply { + // 接口调用返回码,1000 成功,1001 失败 + string respCode = 1 [json_name = "respCode"]; + // 返回信息,失败信息落此字段 + string respMsg = 2 [json_name = "respMsg"]; + // 权益标识,优惠券券码,最大长度为50位 + string codeNo = 3 [json_name = "codeNo"]; } -message QueryRequest { +message QueryCmbRequest { } -message QueryReply { +message QueryCmbReply { } \ No newline at end of file diff --git a/cmd/server/wire.go b/cmd/server/wire.go index c9ece51..e4ac70a 100644 --- a/cmd/server/wire.go +++ b/cmd/server/wire.go @@ -13,7 +13,7 @@ import ( "voucher/internal/conf" "voucher/internal/data" "voucher/internal/data/repositoryimpl" - "voucher/internal/data/thirdrepositoryimpl" + "voucher/internal/data/thirdrepoimpl" log2 "voucher/internal/pkg/log" "voucher/internal/server" "voucher/internal/service" @@ -26,7 +26,7 @@ func wireApp(*conf.Bootstrap, log.Logger, *log2.AccessLogger) (*kratos.App, func service.ProviderSetService, biz.ProviderSetBiz, repositoryimpl.ProviderRepoImplSet, - thirdrepositoryimpl.ProviderThirdRepositoryImplSet, + thirdrepoimpl.ProviderThirdRepositoryImplSet, data.ProviderDataSet, log2.NewLogHelper, newApp, diff --git a/cmd/server/wire_gen.go b/cmd/server/wire_gen.go index c62ab22..bd255f4 100644 --- a/cmd/server/wire_gen.go +++ b/cmd/server/wire_gen.go @@ -13,7 +13,7 @@ import ( "voucher/internal/conf" "voucher/internal/data" "voucher/internal/data/repositoryimpl" - "voucher/internal/data/thirdrepositoryimpl" + "voucher/internal/data/thirdrepoimpl" log2 "voucher/internal/pkg/log" "voucher/internal/server" "voucher/internal/service" @@ -36,7 +36,7 @@ func wireApp(bootstrap *conf.Bootstrap, logger log.Logger, accessLogger *log2.Ac cleanup() return nil, nil, err } - thirdMQSend := thirdrepositoryimpl.NewMQSendImpl(rocketMQ) + thirdMQSend := thirdrepoimpl.NewMQSendImpl(rocketMQ) voucherBiz := biz.NewVoucherBiz(orderRepo, thirdMQSend) voucherService := service.NewVoucherService(voucherBiz) httpServer := server.NewHTTPServer(bootstrap, helper, accessLogger, voucherService) diff --git a/internal/biz/bo/order_bo.go b/internal/biz/bo/order_bo.go index d46632c..66cbd5f 100644 --- a/internal/biz/bo/order_bo.go +++ b/internal/biz/bo/order_bo.go @@ -1,18 +1,34 @@ package bo -import "time" +import ( + "time" + "voucher/internal/biz/vo" +) // OrderBo 领域实体Bo结构,字段和模型字段保持一致 type OrderBo struct { - ID int32 + ID uint64 OrderNo string OutBizNo string ProductNo string Account string - AccountType bool - Status bool + AccountType vo.OrderAccountType + Status vo.OrderStatus AppID string MerchantNo string - Channel bool - CreateTime time.Time + Channel vo.OrderChannel + CreateTime *time.Time + UpdateTime *time.Time +} + +type OrderCreateReqBo struct { + OutBizNo string + ProductNo string + Account string + AccountType vo.OrderAccountType + Channel vo.OrderChannel +} + +type OrderCreateRepBo struct { + OrderNo string } diff --git a/internal/biz/cmb.go b/internal/biz/cmb.go new file mode 100644 index 0000000..38034d3 --- /dev/null +++ b/internal/biz/cmb.go @@ -0,0 +1,19 @@ +package biz + +import ( + "context" + "fmt" + "time" + "voucher/internal/biz/bo" + "voucher/internal/pkg/lock" +) + +func (v *VoucherBiz) CmbOrder(ctx context.Context, req *bo.OrderCreateReqBo) (reps *bo.OrderCreateRepBo, err error) { + + err = lock.NewMutex(v.rdb.Rdb, time.Second*30).Lock(ctx, fmt.Sprintf("cmb_order_%s", req.OutBizNo), func(ctx context.Context) error { + + return nil + }) + + return +} diff --git a/internal/biz/repo/order_repo.go b/internal/biz/repo/order_repo.go index 501150a..cba40a9 100644 --- a/internal/biz/repo/order_repo.go +++ b/internal/biz/repo/order_repo.go @@ -6,8 +6,8 @@ import ( ) type OrderRepo interface { - // Create 创建 Order + // Create 创建 CmbOrder Create(ctx context.Context, req *bo.OrderBo) (*bo.OrderBo, error) - // GetByID 根据 ID 获取 Order + // GetByID 根据 ID 获取 CmbOrder GetByID(ctx context.Context, id int32) (*bo.OrderBo, error) } diff --git a/internal/biz/repository/order.go b/internal/biz/repository/order.go deleted file mode 100644 index b6c730e..0000000 --- a/internal/biz/repository/order.go +++ /dev/null @@ -1,4 +0,0 @@ -package repository - -type OrderRepo interface { -} diff --git a/internal/biz/thirdrepository/send.go b/internal/biz/thirdrepo/send.go similarity index 96% rename from internal/biz/thirdrepository/send.go rename to internal/biz/thirdrepo/send.go index df056de..1570b86 100644 --- a/internal/biz/thirdrepository/send.go +++ b/internal/biz/thirdrepo/send.go @@ -1,4 +1,4 @@ -package thirdrepository +package thirdrepo import ( "context" diff --git a/internal/biz/vo/order_account_type.go b/internal/biz/vo/order_account_type.go new file mode 100644 index 0000000..f5ceb92 --- /dev/null +++ b/internal/biz/vo/order_account_type.go @@ -0,0 +1,32 @@ +package vo + +type OrderAccountType uint8 + +const ( + OrderAccountTypeOpenId OrderAccountType = iota + 1 + OrderAccountTypePhone +) + +var OrderAccountTypeMap = map[OrderAccountType]string{ + OrderAccountTypeOpenId: "openid/userid", + OrderAccountTypePhone: "手机号", +} + +func (s OrderAccountType) GetText() string { + if t, ok := OrderAccountTypeMap[s]; ok { + return t + } + return "" +} + +func (s OrderAccountType) GetValue() uint8 { + return uint8(s) +} + +func (s OrderAccountType) IsOpenId() bool { + return s == OrderAccountTypeOpenId +} + +func (s OrderAccountType) IsPhone() bool { + return s == OrderAccountTypePhone +} diff --git a/internal/biz/vo/order_channel.go b/internal/biz/vo/order_channel.go new file mode 100644 index 0000000..ba48d51 --- /dev/null +++ b/internal/biz/vo/order_channel.go @@ -0,0 +1,32 @@ +package vo + +type OrderChannel uint8 + +const ( + OrderChannelWechat OrderChannel = iota + 1 + OrderChannelAlipay +) + +var OrderChannelMap = map[OrderChannel]string{ + OrderChannelWechat: "微信", + OrderChannelAlipay: "支付宝", +} + +func (s OrderChannel) GetText() string { + if t, ok := OrderChannelMap[s]; ok { + return t + } + return "" +} + +func (s OrderChannel) GetValue() uint8 { + return uint8(s) +} + +func (s OrderChannel) IsWeChat() bool { + return s == OrderChannelWechat +} + +func (s OrderChannel) IsAlipay() bool { + return s == OrderChannelAlipay +} diff --git a/internal/biz/vo/order_status.go b/internal/biz/vo/order_status.go index d685e69..c351dc4 100644 --- a/internal/biz/vo/order_status.go +++ b/internal/biz/vo/order_status.go @@ -1 +1,44 @@ package vo + +type OrderStatus uint8 + +const ( + OrderStatusWait OrderStatus = iota + 1 + OrderStatusIng + OrderStatusSuccess + OrderStatusFail +) + +var OrderStatusMap = map[OrderStatus]string{ + OrderStatusWait: "待发放", + OrderStatusIng: "发放中", + OrderStatusSuccess: "发放成功", + OrderStatusFail: "发放失败", +} + +func (s OrderStatus) GetText() string { + if t, ok := OrderStatusMap[s]; ok { + return t + } + return "" +} + +func (s OrderStatus) GetValue() uint8 { + return uint8(s) +} + +func (s OrderStatus) IsWait() bool { + return s == OrderStatusWait +} + +func (s OrderStatus) IsIng() bool { + return s == OrderStatusIng +} + +func (s OrderStatus) IsSuccess() bool { + return s == OrderStatusSuccess +} + +func (s OrderStatus) IsFail() bool { + return s == OrderStatusFail +} diff --git a/internal/biz/voucher.go b/internal/biz/voucher.go index dc78caa..97fb3d5 100644 --- a/internal/biz/voucher.go +++ b/internal/biz/voucher.go @@ -1,17 +1,17 @@ package biz import ( - "voucher/internal/biz/repository" - "voucher/internal/biz/thirdrepository" + "voucher/internal/biz/repo" + "voucher/internal/biz/thirdrepo" + "voucher/internal/data" ) type VoucherBiz struct { - OrderRepo repository.OrderRepo - ThirdMQSend thirdrepository.ThirdMQSend + rdb *data.Rdb + OrderRepo repo.OrderRepo + ThirdMQSend thirdrepo.ThirdMQSend } -func NewVoucherBiz(orderRepo repository.OrderRepo, thirdMQSend thirdrepository.ThirdMQSend) *VoucherBiz { - return &VoucherBiz{OrderRepo: orderRepo, ThirdMQSend: thirdMQSend} +func NewVoucherBiz(rdb *data.Rdb, orderRepo repo.OrderRepo, thirdMQSend thirdrepo.ThirdMQSend) *VoucherBiz { + return &VoucherBiz{rdb: rdb, OrderRepo: orderRepo, ThirdMQSend: thirdMQSend} } - -// 1:收单 diff --git a/internal/data/model/order.gen.go b/internal/data/model/order.gen.go index 4d84e10..aabd36b 100644 --- a/internal/data/model/order.gen.go +++ b/internal/data/model/order.gen.go @@ -12,7 +12,7 @@ const TableNameOrder = "order" // Order mapped from table type Order struct { - ID int64 `gorm:"column:id;primaryKey;autoIncrement:true" json:"id"` + ID uint64 `gorm:"column:id;primaryKey;autoIncrement:true" json:"id"` OrderNo string `gorm:"column:order_no;not null" json:"order_no"` OutBizNo string `gorm:"column:out_biz_no;not null;comment:外部交易号" json:"out_biz_no"` // 外部交易号 ProductNo string `gorm:"column:product_no;not null;comment:商品编号" json:"product_no"` // 商品编号 @@ -23,6 +23,7 @@ type Order struct { MerchantNo string `gorm:"column:merchant_no;not null;comment:创建批次号的商户号" json:"merchant_no"` // 创建批次号的商户号 Channel uint8 `gorm:"column:channel;not null;comment:1:微信 2:支付宝" json:"channel"` // 1:微信 2:支付宝 CreateTime *time.Time `gorm:"column:create_time" json:"create_time"` + UpdateTime *time.Time `gorm:"column:update_time" json:"update_time"` } // TableName Order's table name diff --git a/internal/data/repoimpl/order_repoImpl.go b/internal/data/repoimpl/order_repoImpl.go index a5df071..806dc3f 100644 --- a/internal/data/repoimpl/order_repoImpl.go +++ b/internal/data/repoimpl/order_repoImpl.go @@ -7,7 +7,7 @@ import ( "voucher/internal/data/model" ) -// OrderRepoImpl 定义了针对 Order 表的 CRUD 操作 +// OrderRepoImpl 定义了针对 CmbOrder 表的 CRUD 操作 type OrderRepoImpl struct { Base[model.Order, bo.OrderBo] } @@ -22,7 +22,7 @@ func (r *OrderRepoImpl) Create(ctx context.Context, req *bo.OrderBo) (*bo.OrderB return nil, nil } -// GetByID 根据 ID 获取 Order +// GetByID 根据 ID 获取 CmbOrder func (r *OrderRepoImpl) GetByID(ctx context.Context, id int32) (*bo.OrderBo, error) { var item model.Order // todo 待实现 diff --git a/internal/data/thirdrepositoryimpl/mq.go b/internal/data/thirdrepoimpl/mq.go similarity index 89% rename from internal/data/thirdrepositoryimpl/mq.go rename to internal/data/thirdrepoimpl/mq.go index 008c220..e40b1a0 100644 --- a/internal/data/thirdrepositoryimpl/mq.go +++ b/internal/data/thirdrepoimpl/mq.go @@ -1,9 +1,9 @@ -package thirdrepositoryimpl +package thirdrepoimpl import ( "context" "github.com/go-kratos/kratos/v2/log" - "voucher/internal/biz/thirdrepository" + "voucher/internal/biz/thirdrepo" "voucher/internal/data" "voucher/internal/pkg/mq" ) @@ -12,7 +12,7 @@ type ThirdMQSendImpl struct { mq *data.RocketMQ } -func NewMQSendImpl(mq *data.RocketMQ) thirdrepository.ThirdMQSend { +func NewMQSendImpl(mq *data.RocketMQ) thirdrepo.ThirdMQSend { return &ThirdMQSendImpl{ mq: mq, } diff --git a/internal/data/thirdrepositoryimpl/provider_set.go b/internal/data/thirdrepoimpl/provider_set.go similarity index 84% rename from internal/data/thirdrepositoryimpl/provider_set.go rename to internal/data/thirdrepoimpl/provider_set.go index 57245cf..356f26a 100644 --- a/internal/data/thirdrepositoryimpl/provider_set.go +++ b/internal/data/thirdrepoimpl/provider_set.go @@ -1,4 +1,4 @@ -package thirdrepositoryimpl +package thirdrepoimpl import ( "github.com/google/wire" diff --git a/internal/server/http.go b/internal/server/http.go index e226098..f88f280 100644 --- a/internal/server/http.go +++ b/internal/server/http.go @@ -32,8 +32,11 @@ func NewHTTPServer( return ctx.String(http2.StatusOK, "pong") }) - //v1 := srv.Route("/v1") - //v1.POST("/order", pluginService.Upload) + v1 := srv.Route("/voucher") + + cmb := v1.Group("/cmb") + cmb.POST("/v1/order", voucherService.CmbOrder) + cmb.POST("/v1/product_query", voucherService.CmbProductQuery) return srv } diff --git a/internal/service/base.go b/internal/service/base.go new file mode 100644 index 0000000..d890fcc --- /dev/null +++ b/internal/service/base.go @@ -0,0 +1,34 @@ +package service + +import ( + "github.com/go-kratos/kratos/v2/transport/http" + http2 "net/http" +) + +// BaseService order 公共方法 +type BaseService struct { +} + +type BaseResponse struct { + Code int `json:"code"` + Data interface{} `json:"data"` + Message string `json:"message"` +} + +// ResponseOK 返回 json 成功 +func (b *BaseService) ResponseOK(ctx http.Context, data interface{}) error { + return ctx.JSON(http2.StatusOK, &BaseResponse{ + Code: http2.StatusOK, + Data: data, + Message: "", + }) +} + +// ResponseError 返回 json 错误 +func (b *BaseService) ResponseError(ctx http.Context, error string) error { + return ctx.JSON(http2.StatusOK, &BaseResponse{ + Code: 4001, + Data: nil, + Message: error, + }) +} diff --git a/internal/service/cmb.go b/internal/service/cmb.go new file mode 100644 index 0000000..4dc176e --- /dev/null +++ b/internal/service/cmb.go @@ -0,0 +1,49 @@ +package service + +import ( + "github.com/go-kratos/kratos/v2/transport/http" + v1 "voucher/api/v1" + "voucher/internal/biz/bo" + "voucher/internal/biz/vo" +) + +func (s *VoucherService) CmbOrder(ctx http.Context) error { + + var req v1.OrderCmbRequest + if err := ctx.BindForm(&req); err != nil { + return err + } + + boReq := &bo.OrderCreateReqBo{ + OutBizNo: req.TransactionId, + ProductNo: req.ActivityId, + Account: req.CmbUid, + AccountType: vo.OrderAccountTypeOpenId, + Channel: vo.OrderChannelWechat, + } + + boRep, err := s.VoucherBiz.CmbOrder(ctx, boReq) + if err != nil { + return err + } + + rep := &v1.OrderCmbReply{ + RespCode: "", + RespMsg: "", + CodeNo: boRep.OrderNo, + } + + return ctx.JSON(200, rep) +} + +func (s *VoucherService) CmbProductQuery(ctx http.Context) error { + + var req v1.QueryCmbRequest + if err := ctx.BindForm(&req); err != nil { + return err + } + + rep := &v1.QueryCmbReply{} + + return ctx.JSON(200, rep) +} diff --git a/internal/service/voucher.go b/internal/service/voucher.go index e553ec1..628692a 100644 --- a/internal/service/voucher.go +++ b/internal/service/voucher.go @@ -1,13 +1,9 @@ package service import ( - "context" - v1 "voucher/api/v1" "voucher/internal/biz" ) -var _ v1.OrderHTTPServer = (*VoucherService)(nil) - type VoucherService struct { VoucherBiz *biz.VoucherBiz } @@ -15,13 +11,3 @@ type VoucherService struct { func NewVoucherService(VoucherBiz *biz.VoucherBiz) *VoucherService { return &VoucherService{VoucherBiz: VoucherBiz} } - -func (v VoucherService) Order(ctx context.Context, request *v1.OrderRequest) (*v1.OrderReply, error) { - //TODO implement me - panic("implement me") -} - -func (v VoucherService) Query(ctx context.Context, request *v1.QueryRequest) (*v1.QueryReply, error) { - //TODO implement me - panic("implement me") -} diff --git a/third_party/swagger_ui/openapi.yaml b/third_party/swagger_ui/openapi.yaml index a1372e0..f8f3735 100644 --- a/third_party/swagger_ui/openapi.yaml +++ b/third_party/swagger_ui/openapi.yaml @@ -3,58 +3,8 @@ openapi: 3.0.3 info: - title: Order API + title: "" version: 0.0.1 -paths: - /openapi/v1/voucher/order: - post: - tags: - - Order - operationId: Order_Order - requestBody: - content: - application/json: - schema: - $ref: '#/components/schemas/api.v1.OrderRequest' - required: true - responses: - "200": - description: OK - content: - application/json: - schema: - $ref: '#/components/schemas/api.v1.OrderReply' - /openapi/v1/voucher/query: - post: - tags: - - Order - operationId: Order_Query - requestBody: - content: - application/json: - schema: - $ref: '#/components/schemas/api.v1.QueryRequest' - required: true - responses: - "200": - description: OK - content: - application/json: - schema: - $ref: '#/components/schemas/api.v1.QueryReply' +paths: {} components: - schemas: - api.v1.OrderReply: - type: object - properties: {} - api.v1.OrderRequest: - type: object - properties: {} - api.v1.QueryReply: - type: object - properties: {} - api.v1.QueryRequest: - type: object - properties: {} -tags: - - name: Order + schemas: {}