订单回调
This commit is contained in:
parent
ee7a93f73d
commit
046418534a
|
@ -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"]
|
|
@ -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}
|
||||
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
}
|
|
@ -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 {
|
||||
|
|
|
@ -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")
|
||||
}
|
||||
|
|
|
@ -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"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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{}) {
|
||||
|
|
|
@ -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) },
|
||||
//订单列表
|
||||
|
|
|
@ -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")
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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" {
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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"`
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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}"
|
|
@ -0,0 +1,9 @@
|
|||
#!/bin/bash
|
||||
|
||||
# supervisord
|
||||
supervisord -c /etc/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
|
|
@ -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
|
|
@ -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 用户已授权远程登录。"
|
Loading…
Reference in New Issue