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.PlainText = config.GetConf().YouChu.MchtNo + "|" + order.OrderNo + "|" + order.Price data.Sign = utils.HmacSha256To16(config.GetConf().YouChu.Sha, data.PlainText) 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,b.brand"). Desc("id").Limit(OrderRequest.PageSize, (OrderRequest.Page-1)*OrderRequest.PageSize).FindAndCount(&data) code = handErr(err) return } func OrderDetailService(order *ordersmodel.OrdersProductsList) (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{"a.id": order.Id}) } if order.OrderNo != "" { conn = conn.And(builder.Eq{"order_no": order.OrderNo}) } return repo.Where(conn).Alias("a").Join("INNER", "products b", "a.product_id = b.id").Select("a.*,b.main_image,b.brand").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.OrdersProductsList{} order.Id = orderId has, err := OrderDetailService(&order) if err != nil || !has { return errorcode.NotFound } if order.State == common.ORDER_STATUS_ReFUNDEND { return errorcode.OrderNOTAuthREFUND } if order.State != common.ORDER_STATUS_FAIL { return errorcode.OrderNOTAuthREFUND } code, response := YouChuOrderRefund(order.Orders) utils.Log(nil, "code", code, response) if code != errorcode.Success { return code } else { if response.RefundOrderSta == "03" || response.RespCode == "719035" { 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 } } else { return errorcode.OrderRefundFail } } } 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 }