From 046418534a8cdb5fe00f3299715d0906dffd1d06 Mon Sep 17 00:00:00 2001 From: wuchao <1272174216@qq.com> Date: Mon, 24 Jun 2024 11:44:38 +0800 Subject: [PATCH] =?UTF-8?q?=E8=AE=A2=E5=8D=95=E5=9B=9E=E8=B0=83?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Dockerfile | 39 +++++++++ app/constants/errorcode/error_code.go | 3 + app/http/controllers/front/OrderController.go | 16 ++-- .../controllers/front/ProductController.go | 16 ++++ app/http/entities/front/Order.go | 30 +++++++ app/http/entities/front/Products.go | 27 +++++++ app/http/entities/front/Voucher.go | 12 ++- app/http/entities/front/Youchu.go | 36 +++++++++ app/http/requestmapping/front.go | 5 +- app/http/routes/route.go | 4 +- app/models/ordersmodel/orders.go | 7 +- app/services/OrderService.go | 79 ++++++++++++++++++- app/services/ProductService.go | 20 ++++- app/services/UserService.go | 4 +- app/third/youchu/config.go | 9 --- app/third/youchu/youchu_api.go | 75 ++++++++++++++---- config/config.go | 3 +- sh/create.sh | 15 ++++ sh/startup.sh | 9 +++ sh/supervisord.conf | 29 +++++++ sh/supervisord_include/start.conf | 44 +++++++++++ start.sh | 32 ++++++++ 22 files changed, 472 insertions(+), 42 deletions(-) create mode 100644 Dockerfile create mode 100644 app/http/controllers/front/ProductController.go create mode 100644 sh/create.sh create mode 100644 sh/startup.sh create mode 100644 sh/supervisord.conf create mode 100644 sh/supervisord_include/start.conf create mode 100644 start.sh diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..07a8111 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,39 @@ + +# 使用官方Go镜像作为构建环境 +FROM golang:1.21.0 AS builder + +# 设置环境变量的默认值 +ENV SERVER=api + +# 设置工作目录 +WORKDIR /app + +# 设置环境变量 +ENV GOPROXY=https://goproxy.cn,direct + +# 复制项目源码 +COPY . . +# 安装snow-core +RUN go get github.com/qit-team/snow-core/kernel/server@v0.1.28 +# 安装go模块依赖 +RUN go mod tidy + +# 编译Go应用程序,生成静态链接的二进制文件 +RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -o server main.go + +# 创建最终镜像,用于运行编译后的Go程序 +FROM alpine + +WORKDIR /app +# 将编译好的二进制文件从构建阶段复制到运行阶段 +COPY --from=builder /app/server /app/server +COPY --from=builder /app/.env /app/.env +RUN chmod +x /app/server + + + +# 暴露容器的端口 +EXPOSE 443 8083 8082 + +# 设置容器启动时运行的命令 +ENTRYPOINT ["/app/server", "-a", "api"] \ No newline at end of file diff --git a/app/constants/errorcode/error_code.go b/app/constants/errorcode/error_code.go index fa0ce9f..f789dec 100644 --- a/app/constants/errorcode/error_code.go +++ b/app/constants/errorcode/error_code.go @@ -28,6 +28,8 @@ const ( OrderProductNotExist = 1002 //兴业下单失败 XINYEOrderFAIL = 1003 + //商品库存不足 + ProductStockFAIL = 1004 //订单不允许退款 OrderNOTAuthREFUND = 2001 @@ -62,6 +64,7 @@ var MsgZH = map[int]string{ OrderRefundUpdateFail: "订单更新失败", OrderRefundFail: "退款失败", YouChuOrderRefundFail: "邮储服务异常", + ProductStockFAIL: "库存不足", } var MsgMap map[string]map[int]string = map[string]map[int]string{"en": MsgZH} diff --git a/app/http/controllers/front/OrderController.go b/app/http/controllers/front/OrderController.go index 0256992..113efd2 100644 --- a/app/http/controllers/front/OrderController.go +++ b/app/http/controllers/front/OrderController.go @@ -3,6 +3,7 @@ package front import ( "github.com/ahmetb/go-linq/v3" "github.com/gin-gonic/gin" + "net/http" "qteam/app/constants/common" "qteam/app/constants/errorcode" "qteam/app/http/controllers" @@ -28,9 +29,9 @@ func OrderList(c *gin.Context) { //userId := controllers.GetUserId(c) userId := 1 code, orderList, count := services.OrderQueryService(userId, request) - var rsp []front.OrderQueryResponse + var rsp []front.OrderListResponse if count > 0 { - linq.From(orderList).SelectT(func(in ordersmodel.Orders) (out front.OrderQueryResponse) { + linq.From(orderList).SelectT(func(in ordersmodel.OrdersProductsList) (out front.OrderListResponse) { out.ResponseFromDb(in) return out }).ToSlice(&rsp) @@ -41,7 +42,8 @@ func OrderList(c *gin.Context) { func OrderQuery(c *gin.Context) { var request = controllers.GetRequest(c).(*front.OrderQueryRequest) orderId, _ := strconv.Atoi(request.OrderId) - order := ordersmodel.Orders{Id: orderId} + order := ordersmodel.Orders{} + order.Id = orderId var OrderQueryResponse front.OrderQueryResponse has, err := services.OrderDetailService(&order) if err != nil { @@ -79,13 +81,15 @@ func OrderQuery(c *gin.Context) { func OrderRefund(c *gin.Context) { var request = controllers.GetRequest(c).(*front.OrderQueryRequest) - //userId := controllers.GetUserId(c) - userId := 1 + userId := controllers.GetUserId(c) + //userId := 1 OrderId, _ := strconv.Atoi(request.OrderId) code := services.OrderRefundService(userId, OrderId) controllers.HandCodeRes(c, nil, code) } func OrderNotify(c *gin.Context) { - + var request = controllers.GetRequest(c).(*front.YouChuRequest) + response := services.OrderNotify(*request) + c.JSON(http.StatusOK, response) } diff --git a/app/http/controllers/front/ProductController.go b/app/http/controllers/front/ProductController.go new file mode 100644 index 0000000..7b7b739 --- /dev/null +++ b/app/http/controllers/front/ProductController.go @@ -0,0 +1,16 @@ +package front + +import ( + "github.com/gin-gonic/gin" + "qteam/app/http/controllers" + "qteam/app/http/entities/front" + "qteam/app/services" +) + +func ProductDetail(c *gin.Context) { + var request = controllers.GetRequest(c).(*front.ProductDetailRequest) + code, product := services.ProductDetail(*request) + var response = front.ProductDetailResponse{} + response.ResponseFromDb(product) + controllers.HandCodeRes(c, response, code) +} diff --git a/app/http/entities/front/Order.go b/app/http/entities/front/Order.go index 1b90e63..f214e8f 100644 --- a/app/http/entities/front/Order.go +++ b/app/http/entities/front/Order.go @@ -15,6 +15,36 @@ type OrderQueryRequest struct { type OrderListRequest struct { PageRequest + State int `form:"state"` +} + +type OrderListResponse struct { + Id int `json:"id"` + OrderNo string `json:"order_no"` + MainImage string `json:"main_image"` + UserId int `json:"user_id"` + UserName string `json:"user_name"` + Mobile string `json:"mobile"` + ProductId int `json:"product_id"` + ProductName string `json:"product_name"` + State int `json:"state"` + VoucherLink string `json:"voucher_link"` + CreateTime string `json:"create_time"` +} + +func (p *OrderListResponse) ResponseFromDb(l ordersmodel.OrdersProductsList) { + p.Id = l.Id + p.OrderNo = l.OrderNo + p.MainImage = l.MainImage + p.UserId = l.UserId + p.UserName = l.UserName + p.Mobile = l.Mobile + p.ProductId = l.ProductId + p.ProductName = l.ProductName + p.State = l.State + p.VoucherLink = l.VoucherLink + p.CreateTime = l.CreateTime.Format("2006-01-02 15:04:05") + return } type OrderQueryResponse struct { diff --git a/app/http/entities/front/Products.go b/app/http/entities/front/Products.go index 9bad7d0..891700e 100644 --- a/app/http/entities/front/Products.go +++ b/app/http/entities/front/Products.go @@ -1 +1,28 @@ package front + +import ( + "qteam/app/models/productsmodel" + "qteam/app/utils" +) + +type ProductDetailRequest struct { + ProductId int `form:"product_id" validate:"required"` +} + +type ProductDetailResponse struct { + Id string `json:"id"` + Name string `json:"name"` + MainImage string `json:"main_image"` + Brand string `json:"brand"` + Stock string `json:"stock"` + ShowPrice string `json:"show_price"` + Price string `json:"price"` + CreateTime string `json:"create_time"` + Status string `json:"status"` + Description string `json:"description"` +} + +func (this *ProductDetailResponse) ResponseFromDb(in productsmodel.Products) { + utils.EntityCopy(this, &in) + this.CreateTime = in.CreateTime.Format("2006-01-02 15:04:05") +} diff --git a/app/http/entities/front/Voucher.go b/app/http/entities/front/Voucher.go index f2be248..9e0b91d 100644 --- a/app/http/entities/front/Voucher.go +++ b/app/http/entities/front/Voucher.go @@ -4,6 +4,7 @@ import ( "qteam/app/models/brandmodel" "qteam/app/models/productsmodel" "qteam/config" + "strconv" ) type VoucherListResponse struct { @@ -23,6 +24,7 @@ func (this *MilkList) ResponseFromDb(in brandmodel.Brand) { } type MilkVoucherList struct { + ProductId string `json:"ProductId"` BrandFlag string `json:"brandFlag"` VoucherTitle string `json:"voucherTitle"` VoucherUrl string `json:"voucherUrl"` @@ -33,11 +35,17 @@ type MilkVoucherList struct { } func (this *MilkVoucherList) ResponseFromDb(in productsmodel.MilkProductsList) { + this.ProductId = in.Id this.BrandFlag = in.Flag this.VoucherTitle = in.Name - this.VoucherUrl = config.GetConf().YouChu.MilkUrl + "?voucher_id=" + in.Id + this.VoucherUrl = config.GetConf().YouChu.VoucherUrl + "?product_id=" + in.Id this.VoucherIcon = in.MainImage this.VoucherAmount = in.ShowPrice this.VoucherOriginalPrice = in.Price - this.VoucherStatus = in.Status + stock, _ := strconv.Atoi(in.Stock) + if stock > 0 { + this.VoucherStatus = "1" + } else { + this.VoucherStatus = "0" + } } diff --git a/app/http/entities/front/Youchu.go b/app/http/entities/front/Youchu.go index 61cdeff..204982b 100644 --- a/app/http/entities/front/Youchu.go +++ b/app/http/entities/front/Youchu.go @@ -9,6 +9,26 @@ type YouChuRequest struct { EncryptKey string `json:"encryptKey"` } +type YouChuLoginRequest struct { + Body YouChuLoginBody `json:"body"` + Head YouChuRequestHeader `json:"head"` +} + +type YouChuLoginResponse struct { + RespCode string `json:"respCode"` //000000-成功 069801-系统繁忙,请稍后重试 820007-未查询到客户号 + RespMsg string `json:"respMsg"` //描 述 (失败时必填) + Phone string `json:"phone"` + IdtLastFour string `json:"idtLastFour"` + CustName string `json:"custName"` + CustFlag string `json:"custFlag"` +} + +type YouChuLoginBody struct { + CustNo string `json:"custNo"` + ReqTransTime string `json:"reqTransTime"` + Code string `json:"code"` +} + type YouChuRequestBody struct { Body YouChuOrderRequest `json:"body"` Head YouChuRequestHeader `json:"head"` @@ -92,6 +112,22 @@ type RefundRequestData struct { } type YouChuOrderNotifyRequest struct { + TxnCode string `json:"txnCode"` + SourceId string `json:"sourceId"` + ReqDate string `json:"reqDate"` + ReqTraceId string `json:"reqTraceId"` + OrderNo string `json:"orderNo"` + TxnAmt string `json:"txnAmt"` + OrderSta string `json:"orderSta"` //03-支付成功 04-支付失败05-检查失败 + MchtNo string `json:"mchtNo"` + TermId string `json:"termId"` + TxnFlag string `json:"txnFlag"` //01-消费 03-退货 + TxnKind string `json:"txnKind"` //01-银行卡 02-微信 03-支付宝 +} + +type YouChuOrderNotifyResponse struct { + RespCode string `json:"respCode"` //000000 表示通知成功 + RespMsg string `json:"respMsg"` } func (this *YouChuOrderRequest) ToMap() (resultMap map[string]interface{}) { diff --git a/app/http/requestmapping/front.go b/app/http/requestmapping/front.go index 9a0b851..526914d 100644 --- a/app/http/requestmapping/front.go +++ b/app/http/requestmapping/front.go @@ -10,7 +10,10 @@ var FrontRequestMap = map[string]func() interface{}{ common.FRONT_API_V1 + "/VoucherList": func() interface{} { return new(struct{}) }, //联合登录 common.FRONT_API_V1 + "/UnionLogin": func() interface{} { return new(front.UnionLoginRequest) }, - + //商品详情 + common.FRONT_API_V1 + "/product/detail": func() interface{} { return new(front.ProductDetailRequest) }, + //订单回调 + common.FRONT_API_V1 + "/order/notify": func() interface{} { return new(front.YouChuRequest) }, // 生成订单 common.FRONT_API_V1_Auth + "/order/create": func() interface{} { return new(front.OrderCreateRequest) }, //订单列表 diff --git a/app/http/routes/route.go b/app/http/routes/route.go index 54f29d5..e92ca13 100644 --- a/app/http/routes/route.go +++ b/app/http/routes/route.go @@ -52,8 +52,10 @@ func RegisterRoute(router *gin.Engine) { v1.POST("/VoucherList", front.VoucherList) // 联合登录 v1.POST("/UnionLogin", front.UnionLogin) - + // 订单回调 v1.POST("/order/notify", front.OrderNotify) + //商品详情 + v1.POST("/product/detail", front.ProductDetail) //auth auth := v1.Group("auth") diff --git a/app/models/ordersmodel/orders.go b/app/models/ordersmodel/orders.go index 9d23128..43d72bd 100644 --- a/app/models/ordersmodel/orders.go +++ b/app/models/ordersmodel/orders.go @@ -27,13 +27,18 @@ type Orders struct { VoucherLink string `xorm:"'voucher_link' varchar(255)"` RefundOrderNo string `xorm:"'refundOrderNo' varchar(255)"` RefundOrderSta string `xorm:"'refundOrderSta' varchar(20)"` - RefundTime time.Time `xorm:"'create_time' datetime"` + RefundTime time.Time `xorm:"'refund_time' datetime"` CreateTime time.Time `xorm:"'create_time' datetime"` UpdateTime time.Time `xorm:"'update_time' datetime"` ExchangeTime time.Time `xorm:"'exchange_time' datetime"` Deleted time.Time `xorm:"'Deleted' datetime"` } +type OrdersProductsList struct { + Orders `xorm:"extends"` + MainImage string `xorm:"'main_image' varchar(255)"` +} + // 表名 func (m *Orders) TableName() string { return "Orders" diff --git a/app/services/OrderService.go b/app/services/OrderService.go index bb8cc15..fc14b84 100644 --- a/app/services/OrderService.go +++ b/app/services/OrderService.go @@ -1,12 +1,15 @@ package services import ( + "encoding/json" "qteam/app/constants/common" "qteam/app/constants/errorcode" "qteam/app/http/entities/front" "qteam/app/models/ordersmodel" "qteam/app/models/productsmodel" "qteam/app/models/usersmodel" + "qteam/app/third/market" + "qteam/app/third/youchu" "qteam/app/utils" redis_util "qteam/app/utils/redis" "qteam/config" @@ -46,6 +49,10 @@ func CreateOrderService(userId int, productId int) (code int, data front.InsertO if !has { return errorcode.OrderProductNotExist, data } + stock, _ := strconv.Atoi(product.Stock) + if stock <= 0 { + return errorcode.ProductStockFAIL, data + } var user usersmodel.Users _, err = usersmodel.GetInstance().GetDb().Where("id =?", userId).Get(&user) if err != nil { @@ -77,9 +84,15 @@ func CreateOrderService(userId int, productId int) (code int, data front.InsertO return errorcode.Success, data } -func OrderQueryService(userId int, OrderRequest *front.OrderListRequest) (code int, data []ordersmodel.Orders, count int64) { +func OrderQueryService(userId int, OrderRequest *front.OrderListRequest) (code int, data []ordersmodel.OrdersProductsList, count int64) { repo := ordersmodel.GetInstance().GetDb() - count, err := repo.Where("user_id = ?", userId). + conn := builder.NewCond() + conn = conn.And(builder.Eq{"a.user_id": userId}) + if OrderRequest.State != 0 { + conn = conn.And(builder.Eq{"a.state": OrderRequest.State}) + } + count, err := repo.Where(conn).Alias("a"). + Join("INNER", "Products b", "a.product_id = b.id").Select("a.*,b.main_image"). Desc("id").Limit(OrderRequest.PageSize, (OrderRequest.Page-1)*OrderRequest.PageSize).FindAndCount(&data) code = handErr(err) return @@ -126,7 +139,8 @@ func OrderRefundService(userId int, orderId int) (code int) { return errorcode.SystemError } } - order := ordersmodel.Orders{Id: orderId, UserId: userId} + order := ordersmodel.Orders{} + order.Id = orderId has, err := OrderDetailService(&order) if err != nil || !has { return errorcode.NotFound @@ -153,3 +167,62 @@ func OrderRefundService(userId int, orderId int) (code int) { } } } + +func OrderNotify(request front.YouChuRequest) (NotifyResponse front.YouChuOrderNotifyResponse) { + requestStr, _ := json.Marshal(request) + utils.Log(nil, "OrderNotify", string(requestStr)) + response := youchu.DecryptResponse(string(requestStr)) + var YouChuOrderNotifyRequest front.YouChuOrderNotifyRequest + err := json.Unmarshal([]byte(response), &YouChuOrderNotifyRequest) + if err != nil { + return front.YouChuOrderNotifyResponse{RespCode: "000001", RespMsg: "解析失败"} + } + utils.Log(nil, "YouChuOrderNotifyRequest", YouChuOrderNotifyRequest) + // 03-支付成功 04-支付失败 05-检查失败 + if YouChuOrderNotifyRequest.OrderSta != "03" { + return front.YouChuOrderNotifyResponse{RespCode: "000002", RespMsg: "交易失败"} + } else { + //支付成功 + utils.Log(nil, "OrderNotify-success", YouChuOrderNotifyRequest) + var orderDetail ordersmodel.Orders + var order ordersmodel.Orders + has, err := ordersmodel.GetInstance().GetDb().Where("state = ?", common.ORDER_STATUS_DEFAULT).Where("order_no = ?", YouChuOrderNotifyRequest.ReqTraceId).Get(&orderDetail) + if err != nil || !has { + return front.YouChuOrderNotifyResponse{RespCode: "000003", RespMsg: "订单不存在"} + } + var productDetail productsmodel.Products + has, err = productsmodel.GetInstance().GetDb().Where("id = ?", orderDetail.ProductId).Get(&productDetail) + if err != nil || !has { + return front.YouChuOrderNotifyResponse{RespCode: "000003", RespMsg: "商品不存在"} + } + //01-消费 03-退货 + if YouChuOrderNotifyRequest.TxnFlag == "01" { + client := market.NewMarketClient(config.GetConf().OpenApiMarketConfig) + send, err := client.MarketSend(orderDetail.OrderNo, strconv.Itoa(orderDetail.VoucherId), "", "1") + utils.Log(nil, "OrderNotify-MarketSend", send) + if err != nil { + return front.YouChuOrderNotifyResponse{RespCode: "000004", RespMsg: "充值失败"} + } + order.OrgTxnSeq = YouChuOrderNotifyRequest.OrderNo + if send.ErrCode != "00" { + order.State = common.ORDER_STATUS_FAIL + } else { + order.State = common.ORDER_STATUS_FINISH + order.VoucherLink = send.Data.ShortUrl + Stock, _ := strconv.Atoi(productDetail.Stock) + productDetail.Stock = strconv.Itoa(Stock - 1) + } + } else { + //order.RefundOrderNo = YouChuOrderNotifyRequest.OrgTxnSeq + //order.RefundOrderSta = YouChuOrderNotifyRequest.OrderSta + return front.YouChuOrderNotifyResponse{RespCode: "000005", RespMsg: "订单标识错误"} + } + _, err = ordersmodel.GetInstance().GetDb().Where("order_no = ?", YouChuOrderNotifyRequest.ReqTraceId).Update(&order) + _, err = productsmodel.GetInstance().GetDb().Where("id = ?", orderDetail.ProductId).Update(&productDetail) + if err != nil { + utils.Log(nil, "OrderNotify-MarketSend", err.Error()) + return front.YouChuOrderNotifyResponse{RespCode: "000004", RespMsg: "操作失败"} + } + } + return +} diff --git a/app/services/ProductService.go b/app/services/ProductService.go index d5361a8..94cccf8 100644 --- a/app/services/ProductService.go +++ b/app/services/ProductService.go @@ -1,6 +1,11 @@ package services -import "qteam/app/models/productsmodel" +import ( + "qteam/app/constants/errorcode" + "qteam/app/http/entities/front" + "qteam/app/models/productsmodel" + "xorm.io/builder" +) func MilkProductList() (code int, productList []productsmodel.MilkProductsList) { err := productsmodel.GetInstance().GetDb().Alias("a"). @@ -8,3 +13,16 @@ func MilkProductList() (code int, productList []productsmodel.MilkProductsList) Where("a.status = ?", 1).Find(&productList) return handErr(err), productList } + +func ProductDetail(request front.ProductDetailRequest) (code int, product productsmodel.Products) { + repo := productsmodel.GetInstance().GetDb() + conn := builder.NewCond() + if request.ProductId != 0 { + conn = conn.And(builder.Eq{"id": request.ProductId}) + } + has, err := repo.Where(conn).Get(&product) + if !has { + return errorcode.NotFound, product + } + return handErr(err), product +} diff --git a/app/services/UserService.go b/app/services/UserService.go index 57967a2..103880a 100644 --- a/app/services/UserService.go +++ b/app/services/UserService.go @@ -12,8 +12,8 @@ import ( func YouChuLogin(req *front.UnionLoginRequest) (code int, login front.LoginResponse) { client := youchu.NewYouChuClient(config.GetConf().YouChu) - YouChuResponse, err := client.Login(req.Code) - if err != nil { + Code, YouChuResponse := client.Login(req.Code) + if Code != errorcode.Success { return } if YouChuResponse.RespCode == "000000" { diff --git a/app/third/youchu/config.go b/app/third/youchu/config.go index 6a4442f..dfd81bc 100644 --- a/app/third/youchu/config.go +++ b/app/third/youchu/config.go @@ -20,15 +20,6 @@ type YouChuSendRequest struct { Code string `json:"code"` } -type YouChuResponse struct { - RespCode string `json:"respCode"` //000000-成功 069801-系统繁忙,请稍后重试 820007-未查询到客户号 - RespMsg string `json:"respMsg"` //描 述 (失败时必填) - Phone string `json:"phone"` - IdtLastFour string `json:"idtLastFour"` - CustName string `json:"custName"` - CustFlag string `json:"custFlag"` -} - func (this *YouChuSendRequest) toMap() (resultMap map[string]interface{}) { // Marshal the struct to JSON, ignoring omitempty fields. jsonBytes, err := json.Marshal(this) diff --git a/app/third/youchu/youchu_api.go b/app/third/youchu/youchu_api.go index 5efb546..826cea8 100644 --- a/app/third/youchu/youchu_api.go +++ b/app/third/youchu/youchu_api.go @@ -19,24 +19,41 @@ func NewYouChuClient(cfg config.YouChuConfig) *YouChuClient { } } -func (this *YouChuClient) Login(code string) (res YouChuResponse, err error) { +func (this *YouChuClient) Login(code string) (Code int, response front.YouChuLoginResponse) { partnerTxSriNo := time.Now().Format("20060102150405") + fmt.Sprintf("%10d", mrand.Intn(10000)) url := this.cfg.MerchantId + ".html?partnerTxSriNo=" + partnerTxSriNo - request := YouChuSendRequest{ - CustNo: this.cfg.MerchantId, - ReqTransTime: time.Now().Format("20060102150405"), - Code: code, + request := front.YouChuLoginRequest{ + Head: front.YouChuRequestHeader{ + PartnerTxSriNo: partnerTxSriNo, + AccessType: "API", + Reserve: "", + Method: "crecard.getCustomerInfo", + Version: "1", + MerchantId: config.GetConf().YouChu.MerchantId, + AppID: config.GetConf().YouChu.AppID, + }, + Body: front.YouChuLoginBody{ + Code: code, + CustNo: "000000", + ReqTransTime: time.Now().Format("20060102150405"), + }, } - bytes, err := json.Marshal(request) + requestData := EncryptRequest(request) + bytes, err := json.Marshal(requestData) if err != nil { - return res, err + return errorcode.SystemError, response } - data, err := this.doPost(url, partnerTxSriNo, "crecard.getCustomerInfo", bytes) + post, err := this.doPost(url, partnerTxSriNo, "crecard.getCustomerInfo", bytes) if err != nil { - return res, err + return errorcode.SystemError, response } - err = json.Unmarshal(data, &res) - return + responseData := DecryptResponse(string(post)) + utils.Log(nil, "YouChuLogin", responseData) + err = json.Unmarshal([]byte(responseData), &response) + if err != nil { + return errorcode.SystemError, response + } + return errorcode.Success, response } func (this *YouChuClient) OrderQuery(order ordersmodel.Orders) (code int, response front.YouChuOrderQueryResponse) { @@ -75,9 +92,10 @@ func (this *YouChuClient) OrderQuery(order ordersmodel.Orders) (code int, respon if err != nil { return errorcode.SystemError, response } - err = json.Unmarshal(post, &response) + responseData := DecryptResponse(string(post)) + err = json.Unmarshal([]byte(responseData), &response) if err != nil { - return errorcode.SystemError, front.YouChuOrderQueryResponse{} + return errorcode.SystemError, response } return errorcode.Success, response } @@ -121,7 +139,8 @@ func (this *YouChuClient) OrderRefund(order ordersmodel.Orders) (code int, respo if err != nil { return errorcode.YouChuOrderRefundFail, response } - err = json.Unmarshal(post, &response) + responseData := DecryptResponse(string(post)) + err = json.Unmarshal(post, &responseData) if err != nil { return errorcode.SystemError, front.YouChuOrderRefundResponse{} } @@ -132,7 +151,7 @@ func EncryptRequest(request interface{}) (RequestData front.YouChuRequest) { input, _ := json.Marshal(request) MerchantId := config.GetConf().YouChu.MerchantId PrivateKey := config.GetConf().Sm2.PrivateKey - PublicKey := config.GetConf().Sm2.PublicKey + PublicKey := config.GetConf().YouChu.SopPublicKey encrypt, err := postbank.Encrypt(MerchantId, PrivateKey, PublicKey, string(input), "", true) if err != nil { return front.YouChuRequest{} @@ -143,3 +162,29 @@ func EncryptRequest(request interface{}) (RequestData front.YouChuRequest) { } return RequestData } + +func DecryptResponse(response string) (Rsponse string) { + MerchantId := config.GetConf().YouChu.MerchantId + PrivateKey := config.GetConf().Sm2.PrivateKey + PublicKey := config.GetConf().YouChu.SopPublicKey + encrypt, err := postbank.Decrypt(MerchantId, PrivateKey, PublicKey, response, true) + if err != nil { + return "" + } + var RsponseData map[string]string + err = json.Unmarshal([]byte(encrypt), &RsponseData) + if err != nil { + return "" + } else { + if RsponseData["body"] != "" { + Rsponse = RsponseData["body"] + } + } + utils.Log(nil, "DecryptResponse-body", Rsponse) + return Rsponse +} + +type T struct { + Head string `json:"head"` + Body string `json:"body"` +} diff --git a/config/config.go b/config/config.go index 140fa27..87a24ed 100644 --- a/config/config.go +++ b/config/config.go @@ -42,7 +42,8 @@ type Config struct { type YouChuConfig struct { Host string NotifyUrl string - MilkUrl string + MilkUrl string //奶茶专区跳转链接 + VoucherUrl string //代金券链接 MerchantId string //合作方编号 MchtNo string //上单商户号 AppID string //appid diff --git a/sh/create.sh b/sh/create.sh new file mode 100644 index 0000000..21c899d --- /dev/null +++ b/sh/create.sh @@ -0,0 +1,15 @@ +#!/bin/bash + +IMAGE="msg:v1" +RPC_CONTAINER="msg" +RPC_PORT="9000" +API_PORT="8000" +V_REFLECT="" + + +docker build -t "${IMAGE}" . --no-cache +docker stop "${RPC_CONTAINER}" + +docker rm "${RPC_CONTAINER}" + +docker run -it -p "${RPC_PORT}:${RPC_PORT}" -p "${API_PORT}:${API_PORT}" --name "$RPC_CONTAINER" "${IMAGE}" \ No newline at end of file diff --git a/sh/startup.sh b/sh/startup.sh new file mode 100644 index 0000000..8397062 --- /dev/null +++ b/sh/startup.sh @@ -0,0 +1,9 @@ +#!/bin/bash + +# supervisord +supervisord -c /etc/supervisord.conf + + + + + diff --git a/sh/supervisord.conf b/sh/supervisord.conf new file mode 100644 index 0000000..d5bbf85 --- /dev/null +++ b/sh/supervisord.conf @@ -0,0 +1,29 @@ +; supervisor config file + +[unix_http_server] +file=/var/run/supervisor.sock ; (the path to the socket file) +chmod=0700 ; sockef file mode (default 0700) + +[supervisord] +logfile=/var/log/supervisor/supervisord.log ; (main log file;default $CWD/supervisord.log) +pidfile=/var/run/supervisord.pid ; (supervisord pidfile;default supervisord.pid) +childlogdir=/var/log/supervisor ; ('AUTO' child log dir, default $TEMP) + +; the below section must remain in the config file for RPC +; (supervisorctl/web interface) to work, additional interfaces may be +; added by defining them in separate rpcinterface: sections +[rpcinterface:supervisor] +supervisor.rpcinterface_factory = supervisor.rpcinterface:make_main_rpcinterface + +[supervisorctl] +serverurl=unix:///var/run/supervisor.sock ; use a unix:// URL for a unix socket + +; The [include] section can just contain the "files" setting. This +; setting can list multiple files (separated by whitespace or +; newlines). It can also contain wildcards. The filenames are +; interpreted as relative to this file. Included files *cannot* +; include files themselves. + + +[include] +files = /msgc/sh/supervisord_include/*.conf \ No newline at end of file diff --git a/sh/supervisord_include/start.conf b/sh/supervisord_include/start.conf new file mode 100644 index 0000000..589a2d6 --- /dev/null +++ b/sh/supervisord_include/start.conf @@ -0,0 +1,44 @@ + +[program:rpc] +directory=/msgc/cmd/rpc +# 执行的命令 +command=/msgc/cmd/rpc/msgcenter +#在 supervisord 启动的时候也自动启动 +autorstart=false +#程序异常退出后自动重启 +autorestart=true +#启动 5 秒后没有异常退出,就当作已经正常启动了 +startsecs=5 +#启动失败自动重试次数,默认是 3 +startretries=3 +#把 stderr 重定向到 stdout,默认 false +redirect_stderr=false +#stdout 日志文件大小,默认 50MB +stdout_logfile_maxbytes = 20MB +#stdout 日志文件备份数 +stdout_logfile_backups = 20 +#stdout 日志文件,需要注意当指定目录不存在时无法正常启动,所以需要手动创建目录(supervisord 会自动创建日志文件) +stdout_logfile=/var/log/supervisor_swoole_http_out.log +stderr_logfile=/var/log/supervisor_swoole_http_err.log + +[program:api] +directory=/msgc/cmd/api +# 执行的命令 +command=/msgc/cmd/api/msgcenter +#在 supervisord 启动的时候也自动启动 +autorstart=false +#程序异常退出后自动重启 +autorestart=true +#启动 5 秒后没有异常退出,就当作已经正常启动了 +startsecs=5 +#启动失败自动重试次数,默认是 3 +startretries=3 +#把 stderr 重定向到 stdout,默认 false +redirect_stderr=false +#stdout 日志文件大小,默认 50MB +stdout_logfile_maxbytes = 20MB +#stdout 日志文件备份数 +stdout_logfile_backups = 20 +#stdout 日志文件,需要注意当指定目录不存在时无法正常启动,所以需要手动创建目录(supervisord 会自动创建日志文件) +stdout_logfile=/var/log/supervisor_swoole_http_out.log +stderr_logfile=/var/log/supervisor_swoole_http_err.log diff --git a/start.sh b/start.sh new file mode 100644 index 0000000..9594c30 --- /dev/null +++ b/start.sh @@ -0,0 +1,32 @@ +#!/bin/bash + +# 检测 MySQL 容器是否在运行 +if [ "$(docker ps -q -f name=mysql-container)" ] && [ "$(docker ps -q -f name=redis-container)" ]; then + echo "MySQL 容器已经在运行,退出脚本。" + exit +fi + +# 下载 MySQL 8.0.33 镜像 +docker pull mysql:8.0.33 + +# 下载 Redis Alpine 3.10 镜像 +docker pull redis:alpine3.10 + +# 挂载 Redis 和 MySQL 配置目录以及数据存储目录到 /var/www 目录 +mkdir -p /var/www/redis/config +mkdir -p /var/www/mysql/config +mkdir -p /var/www/mysql/data + +# 启动 MySQL Docker 容器,并挂载配置目录和数据存储目录,设置 root 密码为 lansexiongdi@666,并开启远程连接 +# 在容器内部创建新的 MySQL 配置目录 +docker run -d --name mysql-container -v /var/www/mysql/data:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=lansexiongdi@666 -e MYSQL_ROOT_HOST='%' -p 3306:3306 mysql:8.0.33 +# 等待 MySQL 容器启动 +echo "等待 MySQL 容器启动..." + +# 给 MySQL 的 root 用户授权远程登录 +docker exec -it mysql-container mysql -uroot -p lansexiongdi@666 -e "GRANT ALL PRIVILEGES ON *.* TO 'root'@'%' IDENTIFIED BY 'lansexiongdi@666';SET GLOBAL log_bin = 'mysql-bin'; FLUSH PRIVILEGES;" + +# 启动 Redis Docker 容器,并挂载配置目录,设置密码为 lansexiongdi@666 +docker run -d --name redis-container -v /var/www/redis/redis.conf:/etc/redis.conf -v /var/www/redis/data:/var/lib/redis -e REDIS_PASSWORD=lansexiongdi@666 -p 6379:6379 redis:alpine3.10 + +echo "MySQL 和 Redis 容器已启动,并配置目录已挂载到 /var/www 目录。MySQL root 用户已授权远程登录。"