YouChuKoffee/app/services/OrderService.go

290 lines
10 KiB
Go

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"
"strconv"
"time"
"xorm.io/builder"
)
func CreateOrderService(userId int, productId int) (code int, data front.InsertOrderResponse) {
var err error
{ // redis保证用户当前抽奖结束才能开始下次抽奖
key := utils.GetRealKey("lottery_code:" + strconv.Itoa(userId) + strconv.Itoa(productId))
ok, err := redis_util.AcquireLock(key, time.Second*10)
if ok {
defer redis_util.Del(key)
} else {
if err != nil {
utils.Log(nil, "CreateOrderService", err.Error())
}
code = errorcode.OrderLottery
return code, data
}
}
session := ordersmodel.GetInstance().GetDb().NewSession()
defer func() {
if err != nil {
_ = session.Rollback()
return
}
_ = session.Close()
}()
var product productsmodel.Products
has, err := productsmodel.GetInstance().GetDb().Where("id = ? and status = 1", productId).Get(&product)
if !has {
return errorcode.ProdcutDiscard, data
}
if err != nil {
return errorcode.SystemError, data
}
if !has {
return errorcode.UserNotExist, data
}
stock, _ := strconv.Atoi(product.Stock)
if stock <= 0 {
return errorcode.ProductStockFAIL, data
}
var user usersmodel.Users
has, err = usersmodel.GetInstance().GetDb().Where("id =?", userId).Get(&user)
if err != nil {
return errorcode.SystemError, data
}
order := ordersmodel.Orders{
OrderNo: utils.GenerateOrderNumber(),
UserId: userId,
ProductId: productId,
ProductName: product.Name,
CustNo: user.CustNo,
Price: product.Price,
VoucherId: product.ThirdProductId,
State: common.STATUSABLED,
CreateTime: time.Now(),
}
if err = session.Begin(); err != nil {
return errorcode.SystemError, data
}
if _, err := session.Insert(order); err != nil {
utils.Log(nil, "CreateOrderService", err.Error())
return errorcode.SystemError, data
} else {
rs, err := session.Exec("update Products set stock = stock-1 where stock >= 1 and id = ?", product.Id)
var affect, _ = rs.RowsAffected()
if err != nil || affect < 1 {
session.Rollback()
return errorcode.ProductStockFAIL, data
} else {
_ = session.Commit()
}
}
data.OrderNo = order.OrderNo
data.NotifyUrl = config.GetConf().YouChu.NotifyUrl
return errorcode.Success, data
}
func OrderQueryService(userId int, OrderRequest *front.OrderListRequest) (code int, data []ordersmodel.OrdersProductsList, count int64) {
repo := ordersmodel.GetInstance().GetDb()
conn := builder.NewCond()
conn = conn.And(builder.IsNull{"a.Deleted"})
if config.GetConf().Debug == false {
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
}
func OrderDetailService(order *ordersmodel.Orders) (has bool, err error) {
repo := ordersmodel.GetInstance().GetDb()
conn := builder.NewCond()
if config.GetConf().Debug == false {
conn.And(builder.Eq{"user_id": order.UserId})
}
if order.Id != 0 {
conn = conn.And(builder.Eq{"id": order.Id})
}
if order.OrderNo != "" {
conn = conn.And(builder.Eq{"order_no": order.OrderNo})
}
return repo.Where(conn).Get(order)
}
func OrdersUpdateService(req front.OrdersUpdateRequest) (err error) {
repo := ordersmodel.GetInstance().GetDb()
var order ordersmodel.Orders
if req.Id != 0 {
order.Id = req.Id
}
if req.Status != 0 {
order.State = req.Status
}
if req.VoucherLink != "" {
order.VoucherLink = req.VoucherLink
}
if req.OrgTxnSeq != "" {
order.OrgTxnSeq = req.OrgTxnSeq
}
_, err = repo.Where("Id = ?", req.Id).Update(&order)
return
}
func OrderRefundService(userId int, orderId int) (code int) {
{ // redis保证用户当前抽奖结束才能开始下次抽奖
key := utils.GetRealKey("lottery_code:" + strconv.Itoa(userId) + strconv.Itoa(orderId))
ok, err := redis_util.AcquireLock(key, time.Second*10)
if ok {
defer redis_util.Del(key)
} else {
if err != nil {
utils.Log(nil, "CreateOrderService", err.Error())
}
return errorcode.SystemError
}
}
order := ordersmodel.Orders{}
order.Id = orderId
has, err := OrderDetailService(&order)
if err != nil || !has {
return errorcode.NotFound
}
if order.State != common.ORDER_STATUS_FAIL {
return errorcode.OrderNOTAuthREFUND
}
code, response := YouChuOrderRefund(order)
if code != errorcode.Success {
return code
} else {
if response.RefundOrderSta != "03" {
return errorcode.OrderRefundFail
} else {
order.State = common.ORDER_STATUS_ReFUNDEND
order.RefundOrderNo = response.RefundOrderNo
order.RefundOrderSta = response.RefundOrderSta
order.RefundTime = time.Now()
_, err := ordersmodel.GetInstance().GetDb().Where("id = ?", order.Id).Update(order)
//增加库存
if err == nil {
_, err = ordersmodel.GetInstance().GetDb().Exec("update Products set stock=stock+1 where id = " + strconv.Itoa(order.ProductId))
return errorcode.Success
} else {
return errorcode.OrderRefundUpdateFail
}
}
}
}
func OrderDelete(id string) error {
_, err := ordersmodel.GetInstance().GetDb().Where("id = ?", id).Update(ordersmodel.Orders{Deleted: time.Now()})
return err
}
func OrderNotify(request front.YouChuRequest) (NotifyResponse front.YouChuOrderNotifyResponse) {
requestStr, _ := json.Marshal(request)
utils.Log(nil, "订单回调请求--原始数据:", string(requestStr))
response := youchu.DecryptResponse(string(requestStr), true)
utils.Log(nil, "订单回调请求--解密数据:", response)
var YouChuOrderNotifyRequest front.YouChuOrderNotifyRequest
err := json.Unmarshal([]byte(response), &YouChuOrderNotifyRequest)
if err != nil {
return front.YouChuOrderNotifyResponse{RespCode: "000001", RespMsg: "解析失败"}
}
// 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("voucher_link = ?", "").Where("order_no = ?", YouChuOrderNotifyRequest.ReqTraceId).Get(&orderDetail)
if err != nil || !has {
utils.Log(nil, "notify err", err, YouChuOrderNotifyRequest.ReqTraceId, YouChuOrderNotifyRequest.OrderNo)
return front.YouChuOrderNotifyResponse{RespCode: "000003", RespMsg: "订单不存在"}
}
_, err = ordersmodel.GetInstance().GetDb().Where("id = ?", orderDetail.Id).Update(ordersmodel.Orders{ExchangeTime: time.Now()})
order.ExchangeTime = time.Now()
utils.Log(nil, "更新订单err", orderDetail.Id, err)
var productDetail productsmodel.Products
has, err = productsmodel.GetInstance().GetDb().Where("id = ?", orderDetail.ProductId).Get(&productDetail)
if err != nil || !has {
_, err = ordersmodel.GetInstance().GetDb().Where("id = ?", orderDetail.Id).Update(ordersmodel.Orders{State: common.ORDER_STATUS_FAIL})
utils.Log(nil, "notify err", err, orderDetail.ProductId)
return front.YouChuOrderNotifyResponse{RespCode: "000003", RespMsg: "商品不存在"}
}
session := ordersmodel.GetInstance().GetDb().NewSession()
defer func() {
if err != nil {
_, err = ordersmodel.GetInstance().GetDb().Where("id = ?", orderDetail.Id).Update(ordersmodel.Orders{State: common.ORDER_STATUS_FAIL})
utils.Log(nil, "notify err", err)
_ = session.Rollback()
return
}
_ = session.Close()
}()
//01-消费 03-退货
if YouChuOrderNotifyRequest.TxnFlag == "01" {
_, err = session.Where("id = ?", orderDetail.ProductId).Where("stock >= ?", common.ORDER_STATUS_DEFAULT).Update(&productDetail)
if err = session.Begin(); err != nil {
utils.Log(nil, "notify err", err)
return front.YouChuOrderNotifyResponse{RespCode: "000004", RespMsg: "库存不足"}
}
client := market.NewMarketClient(config.GetConf().OpenApiMarketConfig)
send, err := client.MarketSend(orderDetail.OrderNo, orderDetail.VoucherId, "", "2")
utils.Log(nil, "OrderNotify-MarketSend", send, err)
if err != nil {
_, err = ordersmodel.GetInstance().GetDb().Where("id = ?", orderDetail.Id).Update(ordersmodel.Orders{State: common.ORDER_STATUS_FAIL})
utils.Log(nil, "notify err", err)
return front.YouChuOrderNotifyResponse{RespCode: "000004", RespMsg: "充值失败"}
}
order.OrgTxnSeq = YouChuOrderNotifyRequest.OrderNo
if send.ErrCode != "00" || send.Data.ShortUrl == "" {
order.State = common.ORDER_STATUS_FAIL
} else {
order.State = common.ORDER_STATUS_FINISH
order.VoucherLink = send.Data.ShortUrl
order.ExchangeTime = time.Now()
utils.Log(nil, "nitifydata", send.Data.ShortUrl, "***", send.Data.VoucherId)
//Stock, _ := strconv.Atoi(productDetail.Stock)
//productDetail.Stock = strconv.Itoa(Stock - 1)
}
} else {
//order.RefundOrderNo = YouChuOrderNotifyRequest.OrgTxnSeq
//order.RefundOrderSta = YouChuOrderNotifyRequest.OrderSta
_, err = ordersmodel.GetInstance().GetDb().Where("id = ?", orderDetail.Id).Update(ordersmodel.Orders{State: common.ORDER_STATUS_FAIL})
return front.YouChuOrderNotifyResponse{RespCode: "000005", RespMsg: "订单标识错误"}
}
_, err = session.Cols("stock,state,voucher_link,orgTxnSeq,exchange_time").Where("order_no = ?", YouChuOrderNotifyRequest.ReqTraceId).Update(&order)
if err != nil {
_, err = ordersmodel.GetInstance().GetDb().Where("id = ?", orderDetail.Id).Update(ordersmodel.Orders{State: common.ORDER_STATUS_FAIL})
utils.Log(nil, "OrderNotify-MarketSend", err.Error())
_ = session.Rollback()
return front.YouChuOrderNotifyResponse{RespCode: "000004", RespMsg: "操作失败"}
} else {
_ = session.Commit()
NotifyResponse.RespCode = "000000"
NotifyResponse.RespMsg = "交易成功"
}
}
return
}