299 lines
11 KiB
Go
299 lines
11 KiB
Go
package services
|
|
|
|
import (
|
|
"encoding/json"
|
|
"github.com/gin-gonic/gin"
|
|
"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"})
|
|
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, c *gin.Context) (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 orderDetail.Price != YouChuOrderNotifyRequest.TxnAmt {
|
|
ip, _ := c.RemoteIP()
|
|
_, err = ordersmodel.GetInstance().GetDb().Where("id = ?", orderDetail.Id).Update(ordersmodel.Orders{State: common.ORDER_STATUS_TIMEOUT})
|
|
if ip != nil {
|
|
utils.Log(nil, "OrderNotify-fail", ip.String())
|
|
}
|
|
return front.YouChuOrderNotifyResponse{RespCode: "000004", RespMsg: "金额不匹配"}
|
|
}
|
|
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
|
|
}
|