This commit is contained in:
李子铭 2025-03-03 18:03:19 +08:00
parent 505d744bf5
commit b62bf1c793
22 changed files with 282 additions and 172 deletions

View File

@ -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;
}

View File

@ -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:"*"
};
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}];
}
rpc Query (QueryRequest) returns (QueryReply) {
option (google.api.http) = {
post: "/openapi/v1/voucher/query",
body:"*"
};
}
}
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 {
}

View File

@ -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,

View File

@ -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)

View File

@ -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
}

19
internal/biz/cmb.go Normal file
View File

@ -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
}

View File

@ -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)
}

View File

@ -1,4 +0,0 @@
package repository
type OrderRepo interface {
}

View File

@ -1,4 +1,4 @@
package thirdrepository
package thirdrepo
import (
"context"

View File

@ -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
}

View File

@ -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
}

View File

@ -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
}

View File

@ -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:收单

View File

@ -12,7 +12,7 @@ const TableNameOrder = "order"
// Order mapped from table <order>
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

View File

@ -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 待实现

View File

@ -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,
}

View File

@ -1,4 +1,4 @@
package thirdrepositoryimpl
package thirdrepoimpl
import (
"github.com/google/wire"

View File

@ -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
}

34
internal/service/base.go Normal file
View File

@ -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,
})
}

49
internal/service/cmb.go Normal file
View File

@ -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)
}

View File

@ -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")
}

View File

@ -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: {}