package service import ( "context" "encoding/json" "errors" "fmt" "math" "os" "shop-api/initialize/api" "shop-api/model/response" "strconv" "strings" "sync/atomic" "time" "shop-api/dto" "shop-api/global" "shop-api/model" "shop-api/model/request" "shop-api/utils" "github.com/plutov/paypal" "github.com/spf13/cast" "github.com/w3liu/go-common/constant/timeformat" "gorm.io/gorm" ) func GetUserOrderData(userId string) (response.OrderData, error) { var ( err error result response.OrderData ) result.All, _ = getOrderCount(userId, &request.SearchOrderList{Status: 0}) result.Unpaid, _ = getOrderCount(userId, &request.SearchOrderList{Status: 1}) result.Unship, _ = getOrderCount(userId, &request.SearchOrderList{Status: 2}) result.Shipped, _ = getOrderCount(userId, &request.SearchOrderList{Status: 3}) result.Finished, _ = getOrderCount(userId, &request.SearchOrderList{Status: 4}) result.Cancel, _ = getOrderCount(userId, &request.SearchOrderList{Status: 5}) result.PostSale, _ = getOrderCount(userId, &request.SearchOrderList{Status: 10}) return result, err } func getOrderCount(userId string, info *request.SearchOrderList) (int64, error) { var ( err error result int64 ) db := global.MG_DB.Model(&model.Order{}).Where("`order`.user_id = ?", userId) if info.Status == 10 { //退货 db = db.Joins("LEFT JOIN `order_post_sale` ON `order_post_sale`.order_id = `order`.order_id").Where("`order_post_sale`.id IS NOT NULL AND `order_post_sale`.`status` != 4") } else { if info.Status != 0 { db = db.Where("`order`.`status` = ?", info.Status) } } if info.Code != "" { db = db.Where("`order`.`code` = ?", info.Code) } err = db.Count(&result).Error return result, err } func GetUserOrderList(userID string, info *request.SearchOrderList) (error, interface{}, int64) { var ( err error data []model.OrderList total int64 orderIds []string ) limit := info.PageSize offset := info.PageSize * (info.Page - 1) db := global.MG_DB.Model(&model.Order{}).Where("`order`.user_id = ?", userID) if info.Status == 10 { //退货 db = db.Joins("LEFT JOIN `order_post_sale` ON `order_post_sale`.order_id = `order`.order_id").Where("`order_post_sale`.id IS NOT NULL AND `order_post_sale`.`status` != 4") } else { if info.Status != 0 { db = db.Where("`order`.`status` = ?", info.Status) } } if info.Code != "" { db = db.Where("`order`.`code` = ?", info.Code) } err = db.Select("`order`.*").Order("`order`.id DESC").Offset(offset).Limit(limit).Find(&data).Error if err != nil { return errors.New("获取订单失败"), data, total } if len(data) == 0 { return nil, data, total } for i := 0; i < len(data); i++ { orderIds = append(orderIds, data[i].OrderID) now := time.Now() if data[i].Status == 1 { // 待付款 计算付款倒计时 tmp := data[i].CreatedAt.Add(time.Duration(global.MG_CONFIG.Paypal.OrderBack) * time.Hour) if tmp.Unix() >= now.Unix() { data[i].NextCountdown = tmp.Unix() - now.Unix() } } else if data[i].Status == 3 && data[i].ExpressStatus == 1 { tmp := data[i].ExpressTime.AddDate(0, 0, 15) if tmp.Unix() >= now.Unix() { data[i].NextCountdown = tmp.Unix() - now.Unix() } } } var ( orderGoodsList []model.OrderGoodsDetail goodsMap = make(map[string]model.OrderGoodsDetail) ) err = global.MG_DB.Model(&model.OrderGoods{}).Where("order_id IN (?)", orderIds).Find(&orderGoodsList).Error if err != nil { return errors.New("获取订单商品信息失败"), data, total } for _, goods := range orderGoodsList { goodsMap[goods.OrderID] = goods } var ( postSales []model.PostSale postSaleMap = make(map[string]model.PostSale) ) _ = global.MG_DB.Model(&model.OrderPostSale{}).Select("id,order_id,status,refund_status").Where("order_id IN (?) AND status IN (1,2,3)", orderIds).Find(&postSales).Error for _, sale := range postSales { postSaleMap[sale.OrderID] = sale } for v := range data { if val, ok := goodsMap[data[v].OrderID]; ok { data[v].Goods = val } // todo 判断订单状态?? if val, ok := postSaleMap[data[v].OrderID]; ok { data[v].PostSale = val } } return nil, data, total } func GetUserOrderDetail(userID string, info *request.SearchOrderDetail) (error, interface{}) { var ( err error data model.OrderDetail tCommod model.TbGoods ) db := global.MG_DB.Model(&model.Order{}) if info.OrderID != "" { db = db.Where("order_id = ?", info.OrderID) } err = db.Where("user_id = ?", userID).Find(&data).Error if err != nil { return errors.New("获取订单失败"), data } { now := time.Now() if data.Status == 1 { // 待付款 计算付款倒计时 tmp := data.CreatedAt.Add(time.Duration(global.MG_CONFIG.Paypal.OrderBack) * time.Hour) if tmp.Unix() >= now.Unix() { data.NextCountdown = tmp.Unix() - now.Unix() } } else if data.Status == 3 && data.ExpressStatus == 1 { tmp := data.ExpressTime.AddDate(0, 0, 15) if tmp.Unix() >= now.Unix() { data.NextCountdown = tmp.Unix() - now.Unix() } } } err = global.MG_DB.Model(&model.OrderAddress{}).Where("order_id=?", info.OrderID).Find(&data.Address).Error if err != nil { return errors.New("获取订单地址失败"), data } err = global.MG_DB.Model(&model.OrderGoods{}).Where("order_id=?", info.OrderID).Find(&data.Goods).Error if err != nil { return errors.New("获取订单商品信息失败"), data } err = global.MG_DB.Model(&model.OrderDeliver{}).Where("order_id=?", info.OrderID).Find(&data.Deliver).Error if err != nil { return errors.New("获取发货信息失败"), data } global.MG_DB.Model(&model.TbGoods{}).Where("id=?", data.CommodID).Find(&tCommod) global.MG_DB.Model(&model.SellerStore{}).Select("store_no,`type`,email").Where("store_no = ?", tCommod.StoreNo).Find(&data.Store) _ = global.MG_DB.Model(&model.OrderPostSale{}).Select("id,order_id,status,remark,examine_time,refund_time,refund_status,created_at").Where("order_id = ? AND status IN (1,2,3)", data.OrderID).Order("id DESC").First(&data.PostSale).Error if data.PayTime != nil { data.Bill, _ = getBillView(data.OrderID) } data.Chain = model.Chain{Address: "b714e5508531a7b50d0696abdc83d2333bd896db24f68eb1470bb9529390ef3e"} return nil, data } func AddUserOrder(userId string, req *request.CreateOrderParams) (error, interface{}) { var ( err error //user model.User result bool goods model.TbGoods gSpecs model.TbGoodsSpecs address model.Address //mission model.MissionClaim mission model.Mission ) //// todo 判断用户状态 //user, err = getUser(userId) //if err != nil { // return errors.New("get user info error"), nil //} //if user.IDForbidden { // return errors.New("user disabled"), nil //} // 开始交易 for { err, result = utils.RedisSetNX("commod-"+cast.ToString(req.SkuID), "used", 10*time.Second) if result && err == nil { // 获取成功 break } } defer func() { // 释放锁 _, _ = utils.RedisDel("commod-" + cast.ToString(req.SkuID)) }() // 校验code if req.Code != "" { tx := global.MG_DB.Begin() err = tx.Model(&model.MissionClaim{}).Joins("INNER JOIN mission ON mission.id = mission_claim.mission_id").Where("mission_claim.claim_no = ?", req.Code).Select("mission.*").Find(&mission).Error if err != nil || mission.ID == 0 { return errors.New("任务码错误,请确认链接是否正确"), nil } } err = global.MG_DB.Model(&model.TbGoodsSpecs{}).Where("id = ?", req.SkuID).Find(&gSpecs).Error if err != nil { return errors.New("获取规格信息失败"), nil } if gSpecs.Stock < int64(req.Number) { return errors.New("商品库存不足"), nil } err = global.MG_DB.Model(&model.TbGoods{}).Where("id = ?", gSpecs.GoodsId).Find(&goods).Error if err != nil { return errors.New("获取商品信息失败"), nil } if goods.Online == "off" || goods.ID == 0 { return errors.New("商品已下架,不可购买"), nil } // 校验任务码和商品关联 if mission.GoodsId != goods.ID { // 若任务领取码和下单商品不一致则将code置空 req.Code = "" } err = global.MG_DB.Model(&model.Address{}).Where("user_id = ? AND id = ?", userId, req.AddressID).Find(&address).Error if err != nil { return errors.New("获取地址信息失败"), nil } if address.ID == 0 { return errors.New("请选择正确的收货地址"), nil } tx := global.MG_DB.Begin() // 生成订单 var order model.Order order.OrderID = Generate() order.StoreNo = goods.StoreNo order.CommodID = gSpecs.GoodsId order.SkuNo = gSpecs.SkuNo order.SkuID = req.SkuID order.Code = req.Code if req.Platform != "" { order.Platform = getSysDictDataValue("release_channel", req.Platform) } order.Number = req.Number order.Price = gSpecs.Price order.PaidPrice = order.Price * float64(order.Number) order.Type = 1 order.UserID = userId order.Status = 1 // 调起支付方法 获取paysign //err, payOrder := CreateOrderPayer(strconv.FormatFloat(order.Money, 'f', 2, 64), goods.SpuNo, req.Code) err, payOrder := CreateOrderPayer(strconv.FormatFloat(0.01, 'f', 2, 64), &request.CreatePayOrderParams{OrderId: order.OrderID, SpuNo: goods.SpuNo, ClaimNo: req.Code}) if err != nil { return errors.New("paypal下单失败"), nil } order.PaypalID = payOrder.ID err = tx.Create(&order).Error if err != nil { tx.Rollback() return errors.New("创建订单失败"), nil } var oGoods model.OrderGoods oGoods.OrderID = order.OrderID oGoods.SpuNo = goods.SpuNo oGoods.SkuNo = gSpecs.SkuNo oGoods.Specs = gSpecs.Specs oGoods.TbGoodsBase = goods.TbGoodsBase err = tx.Create(&oGoods).Error if err != nil { tx.Rollback() return errors.New("save goods snapshot failed"), nil } // 快照记录商品所有规格 { var ( gSpecsList []model.TbGoodsSpecs oGoodsSpecs []model.OrderGoodsSpecs ) err = global.MG_DB.Model(&model.TbGoodsSpecs{}).Where("goods_id = ?", goods.ID).Find(&gSpecsList).Error if err != nil { tx.Rollback() return errors.New("get goods spec snapshot failed"), nil } for _, spec := range gSpecsList { oGoodsSpecs = append(oGoodsSpecs, model.OrderGoodsSpecs{ TbGoodsSpecsBase: spec.TbGoodsSpecsBase, OrderID: order.OrderID, OrderGoodsId: oGoods.ID, }) } err = tx.Create(&oGoodsSpecs).Error if err != nil { tx.Rollback() return errors.New("save goods spec snapshot failed"), nil } } var oAddress model.OrderAddress oAddress.Address = address oAddress.OrderID = order.OrderID oAddress.ID = 0 err = tx.Create(&oAddress).Error if err != nil { tx.Rollback() return errors.New("创建订单相关地址失败"), nil } // 扣减商品库存 err = tx.Model(&model.TbGoodsSpecs{}).Where("id=?", req.SkuID).Update("stock", gorm.Expr("stock-?", req.Number)).Error if err != nil { tx.Rollback() return errors.New("扣减商品库存失败"), nil } err = tx.Model(&model.TbGoods{}).Where("id=?", gSpecs.GoodsId).Update("stock", gorm.Expr("stock-?", req.Number)).Error if err != nil { tx.Rollback() return errors.New("扣减商品库存失败"), nil } tx.Commit() // 付款超时自动取消订单 utils.RedisSet("orderBack-"+order.OrderID, order.Number, time.Duration(global.MG_CONFIG.Paypal.OrderBack)*time.Hour) // if result1 == "" { // //err = errors.New("reids创建失败") // //通知或记录 // } return nil, payOrder } func AddUserOrderV1(userId string, device *request.Device, req *dto.CreateOrderRequest) (error, interface{}) { var ( err error //user model.User goods model.TbGoods gSpecs model.TbGoodsSpecs address model.Address //mission model.MissionClaim mission model.Mission result response.CreateOrder ) // 开始交易 for { err, ok := utils.RedisSetNX("commod-"+cast.ToString(req.SkuID), "used", 10*time.Second) if ok && err == nil { // 获取成功 break } } defer func() { // 释放锁 _, _ = utils.RedisDel("commod-" + cast.ToString(req.SkuID)) }() // 校验code if req.Code != "" { tx := global.MG_DB.Begin() err = tx.Model(&model.MissionClaim{}).Joins("INNER JOIN mission ON mission.id = mission_claim.mission_id").Where("mission_claim.claim_no = ?", req.Code).Select("mission.*").Find(&mission).Error if err != nil || mission.ID == 0 { return errors.New("任务码错误,请确认链接是否正确"), nil } } err = global.MG_DB.Model(&model.TbGoodsSpecs{}).Where("id = ?", req.SkuID).Find(&gSpecs).Error if err != nil { return errors.New("获取规格信息失败"), nil } if gSpecs.Stock < int64(req.Number) { return errors.New("商品库存不足"), nil } err = global.MG_DB.Model(&model.TbGoods{}).Where("id = ?", gSpecs.GoodsId).Find(&goods).Error if err != nil { return errors.New("获取商品信息失败"), nil } if goods.Online == "off" || goods.ID == 0 { return errors.New("商品已下架,不可购买"), nil } // 校验任务码和商品关联 if mission.GoodsId != goods.ID { // 若任务领取码和下单商品不一致则将code置空 req.Code = "" } err = global.MG_DB.Model(&model.Address{}).Where("user_id = ? AND id = ?", userId, req.AddressID).Find(&address).Error if err != nil { return errors.New("获取地址信息失败"), nil } if address.ID == 0 { return errors.New("请选择正确的收货地址"), nil } tx := global.MG_DB.Begin() // 生成订单 var order model.Order order.OrderID = Generate() order.StoreNo = goods.StoreNo order.CommodID = gSpecs.GoodsId order.SkuNo = gSpecs.SkuNo order.SkuID = int(req.SkuID) order.Code = req.Code order.PayMode = int(req.PayMode) if req.Platform != "" { order.Platform = getSysDictDataValue("release_channel", req.Platform) } order.Number = int(req.Number) order.Price = gSpecs.Price order.PaidPrice = order.Price * float64(order.Number) order.Type = 1 order.UserID = userId order.Status = 1 //order.PaypalID = payOrder.PayId err = tx.Create(&order).Error if err != nil { tx.Rollback() return errors.New("创建订单失败"), nil } var oGoods model.OrderGoods oGoods.OrderID = order.OrderID oGoods.SpuNo = goods.SpuNo oGoods.SkuNo = gSpecs.SkuNo oGoods.Specs = gSpecs.Specs oGoods.TbGoodsBase = goods.TbGoodsBase err = tx.Create(&oGoods).Error if err != nil { tx.Rollback() return errors.New("save goods snapshot failed"), nil } var oGoodsSpec model.OrderGoodsSpecs oGoodsSpec.TbGoodsSpecsBase = gSpecs.TbGoodsSpecsBase oGoodsSpec.OrderID = order.OrderID oGoodsSpec.OrderGoodsId = oGoods.ID err = tx.Create(&oGoodsSpec).Error if err != nil { tx.Rollback() return errors.New("save goods spec snapshot failed"), nil } var oAddress model.OrderAddress oAddress.Address = address oAddress.OrderID = order.OrderID oAddress.AddressId = address.ID oAddress.ID = 0 err = tx.Create(&oAddress).Error if err != nil { tx.Rollback() return errors.New("创建订单相关地址失败"), nil } // 扣减商品库存 err = tx.Model(&model.TbGoodsSpecs{}).Where("id=?", req.SkuID).Update("stock", gorm.Expr("stock-?", req.Number)).Error if err != nil { tx.Rollback() return errors.New("扣减商品库存失败"), nil } err = tx.Model(&model.TbGoods{}).Where("id=?", gSpecs.GoodsId).Update("stock", gorm.Expr("stock-?", req.Number)).Error if err != nil { tx.Rollback() return errors.New("扣减商品库存失败"), nil } tx.Commit() go calculateCreateOrderStatistics(request.OrderStatistic{ OrderId: order.OrderID, SaleVolume: 0, SkuNo: order.SkuNo, SpuNo: goods.SpuNo, UserId: order.UserID, ClaimNo: order.Code, StoreNo: order.StoreNo, Money: order.Price, }) // 调用支付方法 var payChannel string switch order.PayMode { case 1: payChannel = "alipay-g" case 2: payChannel = "paypal" default: payChannel = "alipay-g" } attach, _ := json.Marshal(map[string]string{"orderId": order.OrderID}) payOrder, err := api.NewGreeterClient(global.PAY_CONN).PayTransactionWebUrl(context.Background(), &api.PayTransRequest{ Appid: "bkb5918273465092837", Mchid: "11000001", OutTradeNo: order.OrderID, Attach: string(attach), NotifyUrl: global.MG_CONFIG.Payment.NotifyUrl, Amount: order.PaidPrice, Currency: "USD", PayChannel: payChannel, ReturnUrl: global.MG_CONFIG.Payment.ReturnUrl + "?order_id=" + order.OrderID + "&spu_no=" + goods.SpuNo + "&claim_no=" + order.Code, // 回调链接, CancelUrl: global.MG_CONFIG.Payment.CancelUrl + "?order_id=" + order.OrderID + "&spu_no=" + goods.SpuNo + "&claim_no=" + order.Code, // 取消链接, Description: "BKB-" + goods.Title, OsType: device.OsType, TerminalType: device.TerminalType, PaymentMethod: req.PaymentMethod, }) if err != nil { return errors.New("调起支付服务失败"), nil } _ = global.MG_DB.Model(&model.Order{}).Where("order_id = ?", order.OrderID).UpdateColumn("paypal_id", payOrder.PayId).Error // 订单支付倒计时 utils.RedisSet("orderBack-"+order.OrderID, order.Number, time.Duration(global.MG_CONFIG.Paypal.OrderBack)*time.Hour) result.PayChannel = payOrder.PayChannel result.PayId = payOrder.PayId result.PayReturn = payOrder.PayReturn result.PayStatus = payOrder.PayStatus result.OrderId = order.OrderID return nil, result } func UpdateUserOrderStatus(userID string, info *request.UpdateUserOrderStatus) error { var ( err error order model.Order ) err = global.MG_DB.Model(&model.Order{}).Where("user_id = ? and order_id = ?", userID, info.OrderID).First(&order).Error if err != nil { return errors.New("获取订单数据失败") } if order.CaptureID == "" && order.Status >= 2 { return errors.New("正在付款途中,请稍后再试") } switch info.Status { case 4: // 确认收货 完成订单 if order.Status != 3 { return errors.New("order unship cannot receipt") } err = UserOrderConfirm(info.OrderID) if err != nil { return err } case 5: // 取消订单 // 删除定时取消任务 _, _ = utils.RedisDel("orderBack-" + info.OrderID) // 释放库存 tx := global.MG_DB.Begin() err = tx.Model(&model.TbGoodsSpecs{}).Where("id = ?", order.SkuID).Update("stock", gorm.Expr("stock + ?", order.Number)).Error if err != nil { tx.Rollback() return errors.New("释放sku库存失败") } err = tx.Model(&model.TbGoods{}).Where("id = ?", order.CommodID).Update("stock", gorm.Expr("stock + ?", order.Number)).Error if err != nil { tx.Rollback() return errors.New("释放spu库存失败") } // 退款 if order.Status == 2 && order.CaptureID != "" { // 账单中取消在途金额 attach, _ := json.Marshal(Attach{OrderId: order.OrderID}) err, _ = orderRefund(tx, order.OrderID, "订单取消", string(attach), order.PaidPrice) if err != nil { tx.Rollback() return err } } err = tx.Model(&model.Order{}).Where("id = ?", order.ID).Update("status", info.Status).Error if err != nil { tx.Rollback() return errors.New("修改订单状态失败") } tx.Commit() } return nil } func UpdateOrderAddress(userId string, info *request.UpdateOrderAddress) error { var ( err error order model.Order ) err = global.MG_DB.Model(&model.Order{}).Where("user_id = ? AND order_id = ?", userId, info.OrderID).First(&order).Error if err != nil { return errors.New("get order failed") } if order.Status != 1 && order.Status != 2 { return errors.New("order not operable") } var orderAddress model.OrderAddress err = global.MG_DB.Model(&model.OrderAddress{}).Where("order_id = ?", info.OrderID).Find(&orderAddress).Error if err != nil { return errors.New("get order address failed") } var oAddress model.OrderAddress oAddress.Address = model.Address{ FirstName: info.FirstName, LastName: info.LastName, Street: info.Street, Phone: info.Phone, Bldg: info.Bldg, City: info.City, State: info.State, ZipCode: info.ZipCode, } oAddress.OrderID = order.OrderID err = global.MG_DB.Model(&model.OrderAddress{}).Where("order_id = ?", info.OrderID).Updates(&oAddress).Error if err != nil { return errors.New("operable failed") } // 更新用户收货地址管理 if orderAddress.AddressId != 0 { _ = global.MG_DB.Model(&model.Address{}).Where("user_id = ? AND id = ?", userId, orderAddress.AddressId).Updates(&oAddress.Address).Error } return err } func DeleteUserOrderStatus(userID string, info *request.DeleteUserORder) error { var ( err error order model.Order ) err = global.MG_DB.Model(&model.Order{}).Where("user_id=? and order_id=?", userID, info.OrderID).Find(&order).Error if err != nil { return errors.New("获取订单数据失败") } if order.Status != 5 { return errors.New("订单状态不允许删除") } err = global.MG_DB.Model(&model.Order{}).Where("user_id=? and order_id=?", userID, info.OrderID).Delete(&model.Order{}).Error if err != nil { return errors.New("订单删除失败") } return nil } func GetPayOrderSign(userID string, info *request.SearchOrderDetail) (error, interface{}) { var ( err error order model.Order goods model.TbGoods ) err = global.MG_DB.Model(&model.Order{}).Where("user_id=? and order_id=?", userID, info.OrderID).Find(&order).Error if err != nil { return errors.New("获取订单数据失败"), nil } if order.Status != 1 { return errors.New("订单状态不允许支付"), nil } err = global.MG_DB.Model(&model.TbGoods{}).Where("id=?", order.CommodID).Find(&goods).Error if err != nil { return errors.New("获取商品失败"), nil } //err, payOrder := CreateOrderPayer(strconv.FormatFloat(order.PaidPrice, 'f', 2, 64), &request.CreatePayOrderParams{OrderId: order.OrderID, SpuNo: goods.SpuNo, ClaimNo: order.Code}) err, payOrder := CreateOrderPayer(strconv.FormatFloat(0.01, 'f', 2, 64), &request.CreatePayOrderParams{OrderId: order.OrderID, SpuNo: goods.SpuNo, ClaimNo: order.Code}) // 调用支付方法 if err != nil { fmt.Println(err) return errors.New("调取支付失败"), nil } //global.MG_DB.Model(&model.Order{}).Where("user_id=? and order_id=?", userID, info.OrderID).Update("paypal_id", payOrder.ID) tx := global.MG_DB.Begin() err = tx.Model(&model.Order{}).Where("user_id=? and order_id=?", userID, info.OrderID).Update("paypal_id", payOrder.ID).Error if err != nil { tx.Rollback() return err, nil } tx.Commit() return nil, payOrder } func GetPayOrderSign1(userID string, device *request.Device, info *request.OrderPay) (error, interface{}) { var ( err error order model.Order goods model.TbGoods result response.CreateOrder ) err = global.MG_DB.Model(&model.Order{}).Where("user_id = ? and order_id = ?", userID, info.OrderID).First(&order).Error if err != nil { return errors.New("获取订单数据失败"), nil } if order.Status != 1 { return errors.New("订单状态不允许支付"), nil } err = global.MG_DB.Model(&model.TbGoods{}).Where("id = ?", order.CommodID).First(&goods).Error if err != nil { return errors.New("获取商品失败"), nil } // 调用支付方法 var payChannel string switch info.PayMode { case 1: payChannel = "alipay-g" case 2: payChannel = "paypal" default: payChannel = "alipay-g" } attach, _ := json.Marshal(map[string]string{"orderId": order.OrderID}) payOrder, err := api.NewGreeterClient(global.PAY_CONN).PayTransactionWebUrl(context.Background(), &api.PayTransRequest{ Appid: "bkb5918273465092837", Mchid: "11000001", OutTradeNo: order.OrderID, Attach: string(attach), NotifyUrl: global.MG_CONFIG.Payment.NotifyUrl, Amount: order.PaidPrice, Currency: "USD", PayChannel: payChannel, ReturnUrl: global.MG_CONFIG.Payment.ReturnUrl + "?order_id=" + info.OrderID + "&spu_no=" + goods.SpuNo + "&claim_no=" + order.Code, // 回调链接, CancelUrl: global.MG_CONFIG.Payment.CancelUrl + "?order_id=" + info.OrderID + "&spu_no=" + goods.SpuNo + "&claim_no=" + order.Code, // 取消链接, Description: "BKB-" + goods.Title, OsType: device.OsType, TerminalType: device.TerminalType, PaymentMethod: info.PayMethod, }) if err != nil { return errors.New("open " + payChannel + " failed"), nil } tx := global.MG_DB.Begin() err = tx.Model(&model.Order{}).Where("user_id = ? and order_id = ?", userID, info.OrderID).Update("paypal_id", payOrder.PayId).Error if err != nil { tx.Rollback() return err, nil } tx.Commit() result.PayChannel = payOrder.PayChannel result.PayId = payOrder.PayId result.PayReturn = payOrder.PayReturn result.PayStatus = payOrder.PayStatus result.OrderId = order.OrderID return nil, result } func PaypalCallback(paypalID, status string) error { var ( err error c *paypal.Client ) if global.MG_CONFIG.Paypal.Env == "SandBox" { c, err = paypal.NewClient(global.MG_CONFIG.Paypal.ClientID, global.MG_CONFIG.Paypal.Secret, paypal.APIBaseSandBox) if err != nil { return err } } else { c, err = paypal.NewClient(global.MG_CONFIG.Paypal.ClientID, global.MG_CONFIG.Paypal.Secret, paypal.APIBaseLive) if err != nil { return err } } _, err = c.GetAccessToken() if err != nil { return err } ctor := paypal.CaptureOrderRequest{} order, err := c.CaptureOrder(paypalID, ctor) if err != nil { return err } // 查看回调完成后订单状态是否支付完成。 if (*order).Status == "FAILED" || (*order).Status == "DENIED" || status == "FAILED" || status == "DENIED" { // 失败 global.MG_DB.Model(&model.Order{}).Where("paypal_id=?", paypalID).Update("status", 1) return nil } if (*order).Status != "COMPLETED" { return errors.New("pay fail") } orderstr, _ := json.Marshal(order) println("-----", string(orderstr)) captureID := "" if len((*order).PurchaseUnits) > 0 && len((*order).PurchaseUnits[0].Payments.Captures) > 0 { captureID = (*order).PurchaseUnits[0].Payments.Captures[0].ID } _ = OrderCapture2("", paypalID, captureID) return nil } type Attach struct { OrderId string `json:"order_id"` PostSaleId int `json:"post_sale_id"` } func PaypalCallback1(params *dto.PaybackBody) error { switch params.ResourceType { case "pay": if params.Status != "SUCCESS" { global.MG_DB.Model(&model.Order{}).Where("paypal_id = ?", params.PayId).Update("status", 1) return nil } else { _ = OrderCapture2(params.OutTradeNo, params.PayId, params.CaptureId) } case "refund": var ( err error attach Attach ) _ = json.Unmarshal([]byte(params.Attach), &attach) tx := global.MG_DB.Begin() if params.Status != "SUCCESS" { if attach.PostSaleId != 0 { var postSale model.OrderPostSale err = global.MG_DB.Model(&model.OrderPostSale{}).Where("id = ?", attach.PostSaleId).First(&postSale).Error if err != nil { tx.Rollback() return err } err = tx.Model(&model.OrderPostSale{}).Where("id = ?", postSale.ID).Updates(map[string]interface{}{"refund_status": "3"}).Error if err != nil { tx.Rollback() return err } } } else { err = orderRefundSuccess(tx, params.OutTradeNo) if err != nil { tx.Rollback() return err } if attach.PostSaleId != 0 { var postSale model.OrderPostSale err = global.MG_DB.Model(&model.OrderPostSale{}).Where("id = ?", attach.PostSaleId).First(&postSale).Error if err != nil { tx.Rollback() return err } err = tx.Model(&model.OrderPostSale{}).Where("id = ?", postSale.ID).Updates(map[string]interface{}{"refund_status": "2"}).Error if err != nil { tx.Rollback() return err } } } tx.Commit() } return nil } func CreateOrderPayer(amount string, params *request.CreatePayOrderParams) (error, *paypal.Order) { var ( err error c *paypal.Client ) if global.MG_CONFIG.Paypal.Env == "SandBox" { c, err = paypal.NewClient(global.MG_CONFIG.Paypal.ClientID, global.MG_CONFIG.Paypal.Secret, paypal.APIBaseSandBox) if err != nil { return err, nil } } else { c, err = paypal.NewClient(global.MG_CONFIG.Paypal.ClientID, global.MG_CONFIG.Paypal.Secret, paypal.APIBaseLive) if err != nil { return err, nil } } _, err = c.GetAccessToken() if err != nil { return err, nil } purchaseUnits := make([]paypal.PurchaseUnitRequest, 1) purchaseUnits[0] = paypal.PurchaseUnitRequest{ Amount: &paypal.PurchaseUnitAmount{ Currency: "USD", // 收款类型 Value: amount, // 收款数量 }, } payer := &paypal.CreateOrderPayer{} appContext := &paypal.ApplicationContext{ ReturnURL: global.MG_CONFIG.Paypal.ReturnUrl + "?order_id=" + params.OrderId + "&spu_no=" + params.SpuNo + "&claim_no=" + params.ClaimNo, // 回调链接 CancelURL: global.MG_CONFIG.Paypal.CancelUrl + "?order_id=" + params.OrderId + "spu_no=" + params.SpuNo + "&claim_no=" + params.ClaimNo, // 取消链接, } order, err := c.CreateOrder("CAPTURE", purchaseUnits, payer, appContext) if err != nil { fmt.Println(err) return err, nil } return nil, order //(*order).Links[1].Href就是支付的链接 } // 用户提现 func CreatePayOutPayer(paypalName, amount, withdID string) (error, *paypal.PayoutResponse) { var ( err error c *paypal.Client ) if global.MG_CONFIG.Paypal.Env == "SandBox" { c, err = paypal.NewClient(global.MG_CONFIG.Paypal.ClientID, global.MG_CONFIG.Paypal.Secret, paypal.APIBaseSandBox) if err != nil { return err, nil } } else { c, err = paypal.NewClient(global.MG_CONFIG.Paypal.ClientID, global.MG_CONFIG.Paypal.Secret, paypal.APIBaseLive) if err != nil { return err, nil } } _, err = c.GetAccessToken() if err != nil { return err, nil } payout := paypal.Payout{} send := &paypal.SenderBatchHeader{ SenderBatchID: withdID, } item := make([]paypal.PayoutItem, 1) fmt.Println(amount) item[0] = paypal.PayoutItem{ RecipientType: "EMAIL", Receiver: paypalName, Amount: &paypal.AmountPayout{ Currency: "USD", // 收款类型 Value: amount, // 收款数量 }, Note: "打款", } payout.SenderBatchHeader = send payout.Items = item fmt.Println(payout.Items[0].Amount) resp, err := c.CreateSinglePayout(payout) if err != nil { fmt.Println(err.Error()) fmt.Println(resp) return err, nil } return err, resp } func UserOrderMessage(info *model.PaypalWebhookDetail) error { switch info.ResourceType { case "checkout-order": // 订单付款 // 确认收款 PaypalCallback(info.Resource.ID, info.Resource.Status) case "capture": // 付款确认 case "payouts": // 提现 UserWithdrawalHandle(info) case "refund": // 退款(待处理) } return nil } func UserWithdrawalHandle(info *model.PaypalWebhookDetail) { var ( err error bills []model.Bill ) switch info.Resource.BatchHeader.BatchStatus { case "SUCCESS": uMap := make(map[string]interface{}) uMap["receipt"] = 1 uMap["withdrawal_status"] = 1 uMap["remark"] = "提现完成" global.MG_DB.Model(&model.Bill{}).Where("withd_id=?", info.Resource.BatchHeader.SenderBatchHeader.SenderBatchID).Updates(uMap) case "PROCESSING": default: // 失败 err = global.MG_DB.Model(&model.Bill{}).Where("withd_id=?", info.Resource.BatchHeader.SenderBatchHeader.SenderBatchID).Find(&bills).Error if err != nil { return } tx := global.MG_DB.Begin() for v := range bills { err = tx.Model(&model.Wallet{}).Where("user_id=?", bills[v].UserID).Update("balance", gorm.Expr("balance+?", bills[v].Price)).Error if err != nil { break } } if err != nil { tx.Rollback() return } uMap := make(map[string]interface{}) uMap["receipt"] = 1 uMap["withdrawal_status"] = 2 uMap["remark"] = "提现失败,金额已返还到余额中" err = global.MG_DB.Model(&model.Bill{}).Where("withd_id=?", info.Resource.BatchHeader.SenderBatchHeader.SenderBatchID).Updates(uMap).Error if err != nil { tx.Rollback() return } tx.Commit() } } func OrderCapture2(orderId, paypalId, captureId string) error { // 开始交易 for { err, result := utils.RedisSetNX("commod-settle-"+paypalId, "used", 10*time.Second) if result && err == nil { // 获取成功 break } } defer func() { // 释放锁 _, _ = utils.RedisDel("commod-settle-" + paypalId) }() var ( err error order model.Order orderGoods model.OrderGoods ) if orderId != "" { err = global.MG_DB.Model(&model.Order{}).Where("order_id = ?", orderId).First(&order).Error if err != nil { return errors.New("获取订单数据失败") } } else { err = global.MG_DB.Model(&model.Order{}).Where("paypal_id = ?", paypalId).First(&order).Error if err != nil { return errors.New("获取订单数据失败") } } if order.PayTime != nil { fmt.Println("重复通知:", paypalId) return errors.New("订单已支付") } err = global.MG_DB.Model(&model.OrderGoods{}).Where("order_id = ?", order.OrderID).First(&orderGoods).Error if err != nil { return errors.New("获取订单商品失败") } tx := global.MG_DB.Begin() // 用户账单 var ( uBill model.Bill iBill model.Bill sBill model.Bill ) uBill.UserID = order.UserID uBill.Type = "2" uBill.Title = "" uBill.OrderID = order.OrderID uBill.Price = order.PaidPrice uBill.Balance = 0 uBill.Status = 1 uBill.Receipt = 1 uBill.Platform = "customer" uBill.TransactionId = "B" + Generate() err = tx.Create(&uBill).Error if err != nil { tx.Rollback() return err } // 网红账单 if order.Code != "" { var ( claim model.MissionClaim mission model.Mission wallet model.Wallet ) err = global.MG_DB.Model(&model.MissionClaim{}).Where("claim_no = ?", order.Code).First(&claim).Error if err != nil { return errors.New("获取任务失败") } // 只会有比例抽成的任务存在订单 err = global.MG_DB.Model(&model.Mission{}).Where("id = ? AND hire_type = 2", claim.MissionId).Find(&mission).Error if err != nil { tx.Rollback() return errors.New("获取任务失败") } // 网红账户 err, wallet = getWallet("influencer", claim.CreateBy) if err != nil { tx.Rollback() return errors.New("获取网红钱包失败") } iBill.UserID = claim.CreateBy iBill.Type = "1" iBill.OrderID = order.OrderID iBill.Price = math.Round(order.PaidPrice*(mission.HireRatio/100)*100) / 100 iBill.Balance = wallet.Balance iBill.Status = 2 iBill.Receipt = 2 iBill.Platform = "influencer" iBill.Title = "订单" + order.OrderID iBill.TransactionId = "B" + Generate() err = tx.Create(&iBill).Error if err != nil { tx.Rollback() return errors.New("添加网红账单失败") } // 领取任务订单统计数据 err = tx.Model(&model.MissionClaim{}).Where("id = ?", claim.ID).UpdateColumns(map[string]interface{}{"achieve_num": gorm.Expr("achieve_num + ?", order.Number), "order_num": gorm.Expr("order_num + 1"), "order_money": gorm.Expr("order_money + ?", order.Price), "reward_unfinished": gorm.Expr("reward_unfinished + ?", iBill.Price)}).Error if err != nil { tx.Rollback() return errors.New("更新任务领取在途佣金统计失败") } err = tx.Model(&model.Wallet{}).Where("user_id = ?", claim.CreateBy).Update("transit_balance", gorm.Expr("transit_balance + ?", iBill.Price)).Error if err != nil { tx.Rollback() return errors.New("网红钱包添加在途金额失败") } } var wallet model.Wallet // 商家账户 err, wallet = getWallet("seller", order.StoreNo) if err != nil { tx.Rollback() return errors.New("获取商家钱包失败") } sBill.UserID = order.StoreNo sBill.Type = "2" sBill.Title = "" sBill.OrderID = order.OrderID sBill.Price = uBill.Price - iBill.Price // 商家收入=用户支付-网红佣金 sBill.Balance = wallet.Balance sBill.Status = 2 sBill.Receipt = 2 sBill.Platform = "seller" sBill.TransactionId = "B" + Generate() err = tx.Create(&sBill).Error if err != nil { tx.Rollback() return errors.New("添加卖家账单失败") } err = tx.Model(&model.Wallet{}).Where("user_id = ?", order.StoreNo).Update("transit_balance", gorm.Expr("transit_balance + ?", sBill.Price)).Error if err != nil { tx.Rollback() return errors.New("卖家钱包添加在途金额失败") } err = tx.Model(&model.Order{}).Where("order_id = ?", order.OrderID).Updates(map[string]interface{}{"status": 2, "capture_id": captureId, "pay_time": time.Now()}).Error if err != nil { tx.Rollback() return errors.New("订单状态变更失败") } tx.Commit() go updateTbGoodsSalesByGoodsId(order.CommodID, order.Number) // 统计商品总销售量 // 删除定时取消任务 _, _ = utils.RedisDel("orderBack-" + order.OrderID) // 添加定时确认收货 utils.RedisSet("orderConfirm-"+order.OrderID, order.Number, time.Duration(global.MG_CONFIG.Paypal.OrderConfirm)*24*time.Hour) go calculatePayOrderStatistics(request.OrderStatistic{ OrderId: order.OrderID, SaleVolume: int64(order.Number), SkuNo: order.SkuNo, SpuNo: orderGoods.SpuNo, UserId: order.UserID, ClaimNo: order.Code, StoreNo: order.StoreNo, Money: order.PaidPrice, Reward: iBill.Price, }) return nil } func UserOrderBack(orderID string) error { var ( err error order model.Order ) // 获取订单数据 err = global.MG_DB.Model(&model.Order{}).Where("order_id=?", orderID).Find(&order).Error if err != nil { return errors.New("获取订单数据失败") } if order.Status != 1 { return errors.New("订单状态不可取消") } // 释放库存? tx := global.MG_DB.Begin() err = tx.Model(&model.TbGoodsSpecs{}).Where("id=?", order.SkuID).Update("stock", gorm.Expr("stock+?", order.Number)).Error if err != nil { tx.Rollback() return errors.New("释放库存失败") } err = tx.Model(&model.TbGoods{}).Where("id=?", order.CommodID).Update("stock", gorm.Expr("stock+?", order.Number)).Error if err != nil { tx.Rollback() return errors.New("释放库存失败") } err = tx.Model(&model.Order{}).Where("order_id=?", orderID).Update("status", 5).Error if err != nil { tx.Rollback() return errors.New("修改订单状态失败") } tx.Commit() return nil } func UserOrderConfirm(orderID string) error { var ( err error order model.Order billList []model.Bill storeNo string influencer string sellerM float64 influencerM float64 ) err = global.MG_DB.Model(&model.Order{}).Where("order_id = ?", orderID).First(&order).Error if err != nil { return errors.New("获取订单失败") } err = global.MG_DB.Model(&model.Bill{}).Where("order_id = ?", orderID).Find(&billList).Error if err != nil { return errors.New("获取在途账单失败") } for v := range billList { switch billList[v].Status { case 1: // 支出 if billList[v].Platform == "seller" { storeNo = billList[v].UserID sellerM -= billList[v].Price } else if billList[v].Platform == "influencer" { influencer = billList[v].UserID influencerM -= billList[v].Price } case 2: // 收入 if billList[v].Platform == "seller" { storeNo = billList[v].UserID sellerM += billList[v].Price } else if billList[v].Platform == "influencer" { influencer = billList[v].UserID influencerM += billList[v].Price } } } tx := global.MG_DB.Begin() if storeNo != "" { err = tx.Model(&model.Wallet{}).Where("user_id = ?", storeNo). Updates(map[string]interface{}{"balance": gorm.Expr("balance + ?", sellerM), "transit_balance": gorm.Expr("transit_balance - ?", sellerM)}).Error if err != nil { tx.Rollback() return errors.New("卖家钱包更新失败") } } if influencer != "" { // 更新任务订单统计数据 if order.Code != "" { err = tx.Model(&model.MissionClaim{}).Where("claim_no = ?", order.Code).UpdateColumns(map[string]interface{}{"reward_finished": gorm.Expr("reward_finished + ?", influencerM), "reward_unfinished": gorm.Expr("reward_unfinished - ?", influencerM)}).Error if err != nil { tx.Rollback() return errors.New("订单完成更新任务领取在途佣金统计失败") } } err = tx.Model(&model.Wallet{}).Where("user_id = ?", influencer).Updates(map[string]interface{}{"balance": gorm.Expr("balance + ?", influencerM), "transit_balance": gorm.Expr("transit_balance - ?", influencerM)}).Error if err != nil { tx.Rollback() return errors.New("订单完成网红钱包结算失败") } } err = tx.Model(&model.Bill{}).Where("order_id = ?", orderID).Update("receipt", 1).Error if err != nil { tx.Rollback() return errors.New("账单状态更新失败") } // 订单状态变更 err = tx.Model(&model.Order{}).Where("order_id = ?", orderID).Updates(map[string]interface{}{"status": 4, "confirm_time": time.Now()}).Error if err != nil { tx.Rollback() return errors.New("订单状态更新失败") } tx.Commit() // 删除定时收款任务 _, _ = utils.RedisDel("orderConfirm-" + orderID) go calculateFinishOrderStatistics(request.OrderStatistic{ OrderId: order.OrderID, UserId: order.UserID, ClaimNo: order.Code, StoreNo: order.StoreNo, Money: order.PaidPrice, Reward: influencerM, }) return nil } // 生成24位订单号 // 前面17位代表时间精确到毫秒,中间3位代表进程id,最后4位代表序号 var num int64 func Generate() string { t := time.Now() s := t.Format(timeformat.Continuity) m := t.UnixNano()/1e6 - t.UnixNano()/1e9*1e3 ms := sup(m, 3) p := os.Getpid() % 1000 ps := sup(int64(p), 3) i := atomic.AddInt64(&num, 1) r := i % 10000 rs := sup(r, 4) n := fmt.Sprintf("%s%s%s%s", s, ms, ps, rs) return n } // 对长度不足n的数字前面补0 func sup(i int64, n int) string { m := fmt.Sprintf("%d", i) for len(m) < n { m = fmt.Sprintf("0%s", m) } return m } func CreateWebhookRecord(body []byte) (error, interface{}) { var ( err error info model.PaypalWebhook ) info.Value = string(body) err = global.MG_DB.Create(&info).Error if err != nil { fmt.Println(err) return err, nil } return nil, info } // 用户取消订单退款 func RefundPayOrderPayer(CaptureID string) (error, *paypal.PayoutResponse) { var ( err error data []byte c *paypal.Client ) if global.MG_CONFIG.Paypal.Env == "SandBox" { c, err = paypal.NewClient(global.MG_CONFIG.Paypal.ClientID, global.MG_CONFIG.Paypal.Secret, paypal.APIBaseSandBox) if err != nil { return err, nil } } else { c, err = paypal.NewClient(global.MG_CONFIG.Paypal.ClientID, global.MG_CONFIG.Paypal.Secret, paypal.APIBaseLive) if err != nil { return err, nil } } _, err = c.GetAccessToken() if err != nil { return err, nil } req, err := c.NewRequest("POST", fmt.Sprintf("%s%s", c.APIBase, "/v2/payments/captures/"+CaptureID+"/refund"), nil) resp := &paypal.PayoutResponse{} if err != nil { return err, resp } if err = c.SendWithAuth(req, resp); err != nil { return err, resp } json.Unmarshal(data, resp) fmt.Println(string(data)) return err, resp } func CheckOrderStatus(userID string, info *request.CheckOrderParams) error { var err error // 确认订单 uMap := make(map[string]interface{}) uMap["status"] = 2 err = global.MG_DB.Model(&model.Order{}).Where("user_id=? and paypal_id=?", userID, info.Token).Updates(uMap).Error if err != nil { return errors.New("确认订单失败") } return nil } //func GetUserOrderGoods(userId string, info *request.OrderIDParams) (error, model.OrderGoodsDetail) { // var ( // err error // order model.Order // result model.OrderGoodsDetail // ) // err = global.MG_DB.Model(&model.Order{}).Joins("INNER JOIN mission_claim ON mission_claim.claim_no = `order`.`code`"). // Where("mission_claim.create_by = ? AND order_id = ?", userId, info.OrderID).Find(&order).Error // if err != nil { // return errors.New("获取订单失败"), result // } // err = global.MG_DB.Model(&model.OrderGoods{}).Where("order_id = ?", info.OrderID).Preload("OrderGoodsSpecs").Find(&result).Error // if err != nil { // return errors.New("获取订单商品信息失败"), result // } // var goodsSpecs []model.OrderGoodsSpecsView // for _, spec := range result.OrderGoodsSpecs { // goodsSpecs = append(goodsSpecs, model.OrderGoodsSpecsView{ID: spec.ID, Specs: spec.Specs, Image: spec.Image}) // } // return err, result //} func GetOrderGoods(userId string, info *request.SearchOrderDetail) (error, model.OrderGoodsDetail) { var ( err error order model.Order result model.OrderGoodsDetail ) err = global.MG_DB.Model(&model.Order{}).Joins("INNER JOIN mission_claim ON mission_claim.claim_no = `order`.`code`"). Where("mission_claim.create_by = ? AND order_id = ?", userId, info.OrderID).Find(&order).Error if err != nil { return errors.New("获取订单失败"), result } err = global.MG_DB.Model(&model.OrderGoods{}).Where("order_id = ?", info.OrderID).Find(&result).Error if err != nil { return errors.New("获取订单商品信息失败"), result } err = global.MG_DB.Model(&model.OrderGoodsSpecs{}).Where("order_goods_id = ?", result.ID).Find(&result.GoodsSpecs).Error if err != nil { return errors.New("获取订单商品规格信息失败"), result } attributeValues := make(map[uint]*model.TbAttributeValueJson) for i := 0; i < len(result.GoodsSpecs); i++ { var attributeList []model.TbAttributeDetail err = json.Unmarshal([]byte(result.GoodsSpecs[i].Specs), &attributeList) if err != nil { return err, result } if i == 0 { var attributes []uint for j := 0; j < len(attributeList); j++ { attributes = append(attributes, attributeList[j].AttributeId) } orderSql := "FIELD(id" for _, attribute := range attributes { orderSql += fmt.Sprintf(",'%v'", attribute) } orderSql += ")" err = global.MG_DB.Model(&model.TbAttribute{}).Select("id,`name`").Where("id IN (?)", attributes).Order(orderSql).Find(&result.Attributes).Error if err != nil { return err, result } } for _, attribute := range attributeList { if _, ok := attributeValues[attribute.AttributeId]; ok { if !strings.Contains(attributeValues[attribute.AttributeId].Str, attribute.Value) { attributeValues[attribute.AttributeId].Str += attribute.Value + "," attributeValues[attribute.AttributeId].Items = append(attributeValues[attribute.AttributeId].Items, model.TbAttributeValueItem{Id: attribute.ValueId, Name: attribute.Value, Image: result.GoodsSpecs[i].Image}) } } else { attributeValues[attribute.AttributeId] = &model.TbAttributeValueJson{Items: []model.TbAttributeValueItem{{Id: attribute.ValueId, Name: attribute.Value, Image: result.GoodsSpecs[i].Image}}, Str: attribute.Value + ","} } } } for i := 0; i < len(result.Attributes); i++ { if val, ok := attributeValues[result.Attributes[i].ID]; ok { result.Attributes[i].Values = val.Items } } return err, result } func GetOrderPostSale(userId string, params *request.IdReq) (model.OrderPostSale, error) { var ( err error result model.OrderPostSale ) err = global.MG_DB.Model(&model.OrderPostSale{}).Where("user_id = ? AND id = ? ", userId, params.ID).First(&result).Error return result, err } func OrderPostSale(userId string, params *request.PostSaleParams) (string, error) { var ( err error order model.Order oldPS, postSale model.OrderPostSale result string ) ok, err := global.MG_REDIS.SetNX("postSale-"+params.OrderId, "used", 0).Result() if !ok || err != nil { return "", errors.New("request error") } defer func() { // 释放锁 _, _ = utils.RedisDel("postSale-" + params.OrderId) }() // 校验申请原因数据字典取值 if !checkSysDictData("return_goods_reason", params.Reason) { return "", errors.New("post-sale reason value error") } err = global.MG_DB.Model(&model.Order{}).Where("user_id = ? AND order_id = ?", userId, params.OrderId).First(&order).Error if err != nil { return "", errors.New("get order error") } // todo 1、订单状态未发货,已发货,已收货等下都可以申请退款 2、订单时长过长可以是否可以退款,待支付公司确认后再定。 if order.Status != 2 && order.Status != 3 && order.Status != 4 { return "", errors.New("order status not operable") } if order.CaptureID == "" { return "", errors.New("order in the process of payment") } // 校验退款 if params.Amount <= 0 || params.Amount > order.PaidPrice { return "", errors.New("post-sale fund amount invalid") } err = global.MG_DB.Model(&model.OrderPostSale{}).Where("user_id = ? AND order_id = ? AND status IN (1,2)", userId, params.OrderId).Find(&oldPS).Error if err != nil { return "", err } if oldPS.ID != 0 { return "", errors.New("repeated submission post-sale") } tx := global.MG_DB.Begin() postSale.Type = 1 postSale.OrderID = params.OrderId postSale.StoreNo = order.StoreNo postSale.UserID = userId postSale.Amount = params.Amount postSale.Reason = params.Reason postSale.Images = params.Images postSale.Videos = params.Videos if order.Status == 2 { // 未发货 全额退款 attach, _ := json.Marshal(Attach{OrderId: order.OrderID, PostSaleId: int(postSale.ID)}) err, _ = orderRefund(tx, order.OrderID, "订单退款", string(attach), postSale.Amount) if err != nil { tx.Rollback() return "", err } postSale.Status = 2 postSale.RefundStatus = 1 } else { postSale.Status = 1 } err = tx.Model(&model.OrderPostSale{}).Create(&postSale).Error if err != nil { tx.Rollback() return result, err } tx.Commit() return result, err } func CancelOrderPostSale(userId string, params *request.IdReq) (string, error) { var ( err error postSale model.OrderPostSale result string ) err = global.MG_DB.Model(&model.OrderPostSale{}).Where("user_id = ? AND id = ?", userId, params.ID).First(&postSale).Error if err != nil { return "", err } if postSale.Status != 1 { return "", errors.New("post-sale non cancellable") } tx := global.MG_DB.Begin() err = tx.Model(&model.OrderPostSale{}).Where("user_id = ? AND id = ?", userId, params.ID).Update("status", "4").Error if err != nil { tx.Rollback() return result, err } // todo 订单状态 tx.Commit() return result, err } // 计算创建订单统计 func calculateCreateOrderStatistics(info request.OrderStatistic) { var err error defer func() { if err != nil { fmt.Println("calculateCreateOrderStatistics:", err.Error()) } }() now := time.Now().Format("060102") + "0000" tx := global.MG_DB.Begin() // 用户维度统计 var userOrder model.DtStatisticOrder _ = global.MG_DB.Model(&model.DtStatisticOrder{}).Where("`value` = ? AND relation_id = ? AND `type` = 1", now, info.UserId).First(&userOrder).Error if userOrder.ID == 0 { userOrder.Value = now userOrder.Unit = "" userOrder.Type = 1 userOrder.RelationId = info.UserId userOrder.NewOrderNum = 1 userOrder.NewOrderMoney = info.Money err = tx.Model(&model.DtStatisticOrder{}).Create(&userOrder).Error if err != nil { tx.Rollback() return } } else { var updateMap = make(map[string]interface{}) updateMap["new_order_num"] = gorm.Expr("new_order_num + 1") updateMap["new_order_money"] = gorm.Expr("new_order_money + ?", info.Money) err = tx.Model(&model.DtStatisticOrder{}).Where("id = ?", userOrder.ID).Updates(&updateMap).Error if err != nil { tx.Rollback() return } } if info.ClaimNo != "" { // 网红领取任务维度统计 var influenceOrder model.DtStatisticOrder _ = global.MG_DB.Model(&model.DtStatisticOrder{}).Where("`value` = ? AND relation_id = ? AND `type` = 2", now, info.ClaimNo).First(&influenceOrder).Error if influenceOrder.ID == 0 { influenceOrder.Value = now influenceOrder.Unit = "" influenceOrder.Type = 2 influenceOrder.RelationId = info.ClaimNo influenceOrder.NewOrderNum = 1 influenceOrder.NewOrderMoney = info.Money err = tx.Model(&model.DtStatisticOrder{}).Create(&influenceOrder).Error if err != nil { tx.Rollback() return } } else { var updateMap = make(map[string]interface{}) updateMap["new_order_num"] = gorm.Expr("new_order_num + 1") updateMap["new_order_money"] = gorm.Expr("new_order_money + ?", info.Money) err = tx.Model(&model.DtStatisticOrder{}).Where("id = ?", influenceOrder.ID).Updates(&updateMap).Error if err != nil { tx.Rollback() return } } } if info.StoreNo != "" { // 店铺维度统计 var storeOrder model.DtStatisticOrder _ = global.MG_DB.Model(&model.DtStatisticOrder{}).Where("`value` = ? AND relation_id = ? AND `type` = 3", now, info.StoreNo).First(&storeOrder).Error if storeOrder.ID == 0 { storeOrder.Value = now storeOrder.Unit = "" storeOrder.Type = 3 storeOrder.RelationId = info.StoreNo storeOrder.NewOrderNum = 1 storeOrder.NewOrderMoney = info.Money err = tx.Model(&model.DtStatisticOrder{}).Create(&storeOrder).Error if err != nil { tx.Rollback() return } } else { var updateMap = make(map[string]interface{}) updateMap["new_order_num"] = gorm.Expr("new_order_num + 1") updateMap["new_order_money"] = gorm.Expr("new_order_money + ?", info.Money) err = tx.Model(&model.DtStatisticOrder{}).Where("id = ?", storeOrder.ID).Updates(&updateMap).Error if err != nil { tx.Rollback() return } } } // 商品spu维度统计 // 平台维度统计 var bkbOrder model.DtStatisticOrder _ = global.MG_DB.Model(&model.DtStatisticOrder{}).Where("`value` = ? AND relation_id = ?", now, "bkb").First(&bkbOrder).Error if bkbOrder.ID == 0 { bkbOrder.Value = now bkbOrder.Unit = "" bkbOrder.RelationId = "bkb" bkbOrder.NewOrderNum = 1 bkbOrder.NewOrderMoney = info.Money err = tx.Model(&model.DtStatisticOrder{}).Create(&bkbOrder).Error if err != nil { tx.Rollback() return } } else { var updateMap = make(map[string]interface{}) updateMap["new_order_num"] = gorm.Expr("new_order_num + 1") updateMap["new_order_money"] = gorm.Expr("new_order_money + ?", info.Money) err = tx.Model(&model.DtStatisticOrder{}).Where("id = ?", bkbOrder.ID).Updates(&updateMap).Error if err != nil { tx.Rollback() return } } tx.Commit() } // 计算支付订单统计 func calculatePayOrderStatistics(info request.OrderStatistic) { var err error defer func() { if err != nil { fmt.Println("calculatePayOrderStatistics:", err.Error()) } }() now := time.Now().Format("060102") + "0000" tx := global.MG_DB.Begin() // 用户维度统计 var userOrder model.DtStatisticOrder _ = global.MG_DB.Model(&model.DtStatisticOrder{}).Where("`value` = ? AND relation_id = ? AND `type` = 1", now, info.UserId).First(&userOrder).Error if userOrder.ID == 0 { userOrder.Value = now userOrder.Unit = "" userOrder.Type = 1 userOrder.RelationId = info.UserId userOrder.OrderNum = 1 userOrder.OrderMoney = info.Money userOrder.SaleVolume = info.SaleVolume err = tx.Model(&model.DtStatisticOrder{}).Create(&userOrder).Error if err != nil { tx.Rollback() return } } else { var updateMap = make(map[string]interface{}) updateMap["order_num"] = gorm.Expr("order_num + 1") updateMap["order_money"] = gorm.Expr("order_money + ?", info.Money) updateMap["sale_volume"] = gorm.Expr("sale_volume + ?", info.SaleVolume) err = tx.Model(&model.DtStatisticOrder{}).Where("id = ?", userOrder.ID).Updates(&updateMap).Error if err != nil { tx.Rollback() return } } if info.ClaimNo != "" { // 网红领取任务维度统计 var influenceOrder model.DtStatisticOrder _ = global.MG_DB.Model(&model.DtStatisticOrder{}).Where("`value` = ? AND relation_id = ? AND `type` = 2", now, info.ClaimNo).First(&influenceOrder).Error if influenceOrder.ID == 0 { influenceOrder.Value = now influenceOrder.Unit = "" influenceOrder.Type = 2 influenceOrder.RelationId = info.ClaimNo influenceOrder.OrderNum = 1 influenceOrder.OrderMoney = info.Money influenceOrder.SaleVolume = info.SaleVolume influenceOrder.TransitReward = info.Reward err = tx.Model(&model.DtStatisticOrder{}).Create(&influenceOrder).Error if err != nil { tx.Rollback() return } } else { var updateMap = make(map[string]interface{}) updateMap["order_num"] = gorm.Expr("order_num + 1") updateMap["order_money"] = gorm.Expr("order_money + ?", info.Money) updateMap["sale_volume"] = gorm.Expr("sale_volume + ?", info.SaleVolume) updateMap["transit_reward"] = gorm.Expr("transit_reward + ?", info.Reward) err = tx.Model(&model.DtStatisticOrder{}).Where("id = ?", influenceOrder.ID).Updates(&updateMap).Error if err != nil { tx.Rollback() return } } } if info.StoreNo != "" { // 店铺维度统计 var storeOrder model.DtStatisticOrder _ = global.MG_DB.Model(&model.DtStatisticOrder{}).Where("`value` = ? AND relation_id = ? AND `type` = 3", now, info.StoreNo).First(&storeOrder).Error if storeOrder.ID == 0 { storeOrder.Value = now storeOrder.Unit = "" storeOrder.Type = 3 storeOrder.RelationId = info.StoreNo storeOrder.OrderNum = 1 storeOrder.OrderMoney = info.Money storeOrder.SaleVolume = info.SaleVolume storeOrder.TransitReward = info.Money - info.Reward err = tx.Model(&model.DtStatisticOrder{}).Create(&storeOrder).Error if err != nil { tx.Rollback() return } } else { var updateMap = make(map[string]interface{}) updateMap["order_num"] = gorm.Expr("order_num + 1") updateMap["order_money"] = gorm.Expr("order_money + ?", info.Money) updateMap["sale_volume"] = gorm.Expr("sale_volume + ?", info.SaleVolume) updateMap["transit_reward"] = gorm.Expr("transit_reward + ?", info.Money-info.Reward) err = tx.Model(&model.DtStatisticOrder{}).Where("id = ?", storeOrder.ID).Updates(&updateMap).Error if err != nil { tx.Rollback() return } } } { // 商品sku维度统计 var skuOrder model.DtStatisticOrder _ = global.MG_DB.Model(&model.DtStatisticOrder{}).Where("`value` = ? AND relation_id = ? AND `type` = 4", now, info.SkuNo).First(&skuOrder).Error if skuOrder.ID == 0 { skuOrder.Value = now skuOrder.Unit = "" skuOrder.Type = 4 skuOrder.RelationId = info.SkuNo skuOrder.OrderNum = 1 skuOrder.OrderMoney = info.Money skuOrder.SaleVolume = info.SaleVolume err = tx.Model(&model.DtStatisticOrder{}).Create(&skuOrder).Error if err != nil { tx.Rollback() return } } else { var updateMap = make(map[string]interface{}) updateMap["order_num"] = gorm.Expr("order_num + 1") updateMap["order_money"] = gorm.Expr("order_money + ?", info.Money) updateMap["sale_volume"] = gorm.Expr("sale_volume + ?", info.SaleVolume) err = tx.Model(&model.DtStatisticOrder{}).Where("id = ?", skuOrder.ID).Updates(&updateMap).Error if err != nil { tx.Rollback() return } } } { // 商品spu维度统计 var spuOrder model.DtStatisticOrder _ = global.MG_DB.Model(&model.DtStatisticOrder{}).Where("`value` = ? AND relation_id = ? AND `type` = 5", now, info.SpuNo).First(&spuOrder).Error if spuOrder.ID == 0 { spuOrder.Value = now spuOrder.Unit = "" spuOrder.Type = 5 spuOrder.RelationId = info.SpuNo spuOrder.OrderNum = 1 spuOrder.OrderMoney = info.Money spuOrder.SaleVolume = info.SaleVolume err = tx.Model(&model.DtStatisticOrder{}).Create(&spuOrder).Error if err != nil { tx.Rollback() return } } else { var updateMap = make(map[string]interface{}) updateMap["order_num"] = gorm.Expr("order_num + 1") updateMap["order_money"] = gorm.Expr("order_money + ?", info.Money) updateMap["sale_volume"] = gorm.Expr("sale_volume + ?", info.SaleVolume) err = tx.Model(&model.DtStatisticOrder{}).Where("id = ?", spuOrder.ID).Updates(&updateMap).Error if err != nil { tx.Rollback() return } } } // 平台维度统计 var bkbOrder model.DtStatisticOrder _ = global.MG_DB.Model(&model.DtStatisticOrder{}).Where("`value` = ? AND relation_id = ?", now, "bkb").First(&bkbOrder).Error if bkbOrder.ID == 0 { bkbOrder.Value = now bkbOrder.Unit = "" bkbOrder.RelationId = "bkb" bkbOrder.OrderNum = 1 bkbOrder.OrderMoney = info.Money bkbOrder.SaleVolume = info.SaleVolume err = tx.Model(&model.DtStatisticOrder{}).Create(&bkbOrder).Error if err != nil { tx.Rollback() return } } else { var updateMap = make(map[string]interface{}) updateMap["order_num"] = gorm.Expr("order_num + 1") updateMap["order_money"] = gorm.Expr("order_money + ?", info.Money) updateMap["sale_volume"] = gorm.Expr("sale_volume + ?", info.SaleVolume) err = tx.Model(&model.DtStatisticOrder{}).Where("id = ?", bkbOrder.ID).Updates(&updateMap).Error if err != nil { tx.Rollback() return } } tx.Commit() } // 计算完成订单统计 func calculateFinishOrderStatistics(info request.OrderStatistic) { var err error defer func() { if err != nil { fmt.Println("calculatePayOrderStatistics:", err.Error()) } }() now := time.Now().Format("060102") + "0000" tx := global.MG_DB.Begin() var userOrder model.DtStatisticOrder _ = global.MG_DB.Model(&model.DtStatisticOrder{}).Where("`value` = ? AND relation_id = ? AND `type` = 1", now, info.UserId).First(&userOrder).Error if userOrder.ID == 0 { userOrder.Value = now userOrder.Unit = "" userOrder.Type = 1 userOrder.RelationId = info.UserId userOrder.OrderDoneNum = 1 userOrder.SettleReward = info.Reward err = tx.Model(&model.DtStatisticOrder{}).Create(&userOrder).Error if err != nil { tx.Rollback() return } } else { var updateMap = make(map[string]interface{}) updateMap["order_done_num"] = gorm.Expr("order_done_num + 1") updateMap["settle_reward"] = gorm.Expr("settle_reward + ?", info.Reward) err = tx.Model(&model.DtStatisticOrder{}).Where("id = ?", userOrder.ID).Updates(&updateMap).Error if err != nil { tx.Rollback() return } } if info.ClaimNo != "" { // 网红维度统计 var influenceOrder model.DtStatisticOrder _ = global.MG_DB.Model(&model.DtStatisticOrder{}).Where("`value` = ? AND relation_id = ? AND `type` = 2", now, info.ClaimNo).First(&influenceOrder).Error if influenceOrder.ID == 0 { influenceOrder.Value = now influenceOrder.Unit = "" influenceOrder.Type = 2 influenceOrder.RelationId = info.ClaimNo influenceOrder.OrderDoneNum = 1 influenceOrder.SettleReward = info.Reward err = tx.Model(&model.DtStatisticOrder{}).Create(&influenceOrder).Error if err != nil { tx.Rollback() return } } else { var updateMap = make(map[string]interface{}) updateMap["order_done_num"] = gorm.Expr("order_done_num + 1") updateMap["settle_reward"] = gorm.Expr("settle_reward + ?", info.Reward) err = tx.Model(&model.DtStatisticOrder{}).Where("id = ?", influenceOrder.ID).Updates(&updateMap).Error if err != nil { tx.Rollback() return } } } if info.StoreNo != "" { // 店铺维度统计 var storeOrder model.DtStatisticOrder _ = global.MG_DB.Model(&model.DtStatisticOrder{}).Where("`value` = ? AND relation_id = ? AND `type` = 3", now, info.StoreNo).First(&storeOrder).Error if storeOrder.ID == 0 { storeOrder.Value = now storeOrder.Unit = "" storeOrder.Type = 3 storeOrder.RelationId = info.StoreNo storeOrder.OrderDoneNum = 1 storeOrder.SettleReward = info.Reward err = tx.Model(&model.DtStatisticOrder{}).Create(&storeOrder).Error if err != nil { tx.Rollback() return } } else { var updateMap = make(map[string]interface{}) updateMap["order_done_num"] = gorm.Expr("order_done_num + 1") updateMap["settle_reward"] = gorm.Expr("settle_reward + ?", info.Reward) err = tx.Model(&model.DtStatisticOrder{}).Where("id = ?", storeOrder.ID).Updates(&updateMap).Error if err != nil { tx.Rollback() return } } } { // 商品sku维度统计 var goodsOrder model.DtStatisticOrder _ = global.MG_DB.Model(&model.DtStatisticOrder{}).Where("`value` = ? AND relation_id = ? AND `type` = 4", now, info.SkuNo).First(&goodsOrder).Error if goodsOrder.ID == 0 { goodsOrder.Value = now goodsOrder.Unit = "" goodsOrder.Type = 4 goodsOrder.RelationId = info.SkuNo goodsOrder.OrderNum = 1 goodsOrder.OrderMoney = info.Money err = tx.Model(&model.DtStatisticOrder{}).Create(&goodsOrder).Error if err != nil { tx.Rollback() return } } else { var updateMap = make(map[string]interface{}) updateMap["order_done_num"] = gorm.Expr("order_done_num + 1") updateMap["settle_reward"] = gorm.Expr("settle_reward + ?", info.Reward) err = tx.Model(&model.DtStatisticOrder{}).Where("id = ?", goodsOrder.ID).Updates(&updateMap).Error if err != nil { tx.Rollback() return } } } { // 商品spu维度统计 var goodsOrder model.DtStatisticOrder _ = global.MG_DB.Model(&model.DtStatisticOrder{}).Where("`value` = ? AND relation_id = ? AND `type` = 5", now, info.SpuNo).First(&goodsOrder).Error if goodsOrder.ID == 0 { goodsOrder.Value = now goodsOrder.Unit = "" goodsOrder.Type = 5 goodsOrder.RelationId = info.SpuNo goodsOrder.OrderNum = 1 goodsOrder.OrderMoney = info.Money err = tx.Model(&model.DtStatisticOrder{}).Create(&goodsOrder).Error if err != nil { tx.Rollback() return } } else { var updateMap = make(map[string]interface{}) updateMap["order_done_num"] = gorm.Expr("order_done_num + 1") updateMap["settle_reward"] = gorm.Expr("settle_reward + ?", info.Reward) err = tx.Model(&model.DtStatisticOrder{}).Where("id = ?", goodsOrder.ID).Updates(&updateMap).Error if err != nil { tx.Rollback() return } } } // 平台维度统计 var bkbOrder model.DtStatisticOrder _ = global.MG_DB.Model(&model.DtStatisticOrder{}).Where("`value` = ? AND relation_id = ?", now, "bkb").First(&bkbOrder).Error if bkbOrder.ID == 0 { bkbOrder.Value = now bkbOrder.Unit = "" bkbOrder.RelationId = "bkb" bkbOrder.OrderDoneNum = 1 bkbOrder.SettleReward = info.Reward err = tx.Model(&model.DtStatisticOrder{}).Create(&bkbOrder).Error if err != nil { tx.Rollback() return } } else { var updateMap = make(map[string]interface{}) updateMap["order_done_num"] = gorm.Expr("order_done_num + 1") updateMap["settle_reward"] = gorm.Expr("settle_reward + ?", info.Reward) err = tx.Model(&model.DtStatisticOrder{}).Where("id = ?", bkbOrder.ID).Updates(&updateMap).Error if err != nil { tx.Rollback() return } } tx.Commit() } func specsToAttributes(specs *[]model.TbOrderGoodsSpecsDetail) (error, []model.TbAttributeWithValues) { var ( err error attributeIds []uint attributeMap = make(map[uint]string) result []model.TbAttributeWithValues ) attributeValues := make(map[uint]*model.TbAttributeValueJson) for i := 0; i < len(*specs); i++ { var attributes []model.TbAttributeDetail err = json.Unmarshal([]byte((*specs)[i].Specs), &attributes) if err != nil { return err, nil } if i == 0 { for _, attribute := range attributes { attributeIds = append(attributeIds, attribute.AttributeId) result = append(result, model.TbAttributeWithValues{ TbAttributeView: model.TbAttributeView{ID: attribute.AttributeId, Name: ""}, Values: []model.TbAttributeValueItem{}, }) } } for _, attribute := range attributes { if _, ok := attributeValues[attribute.AttributeId]; ok { if !strings.Contains(attributeValues[attribute.AttributeId].Str, attribute.Value) { attributeValues[attribute.AttributeId].Str += attribute.Value + "," attributeValues[attribute.AttributeId].Items = append(attributeValues[attribute.AttributeId].Items, model.TbAttributeValueItem{Name: attribute.Value, Image: (*specs)[i].Image}) } (*specs)[i].Code += fmt.Sprintf("#%v-%v", attribute.AttributeId, len(attributeValues[attribute.AttributeId].Items)-1) } else { attributeValues[attribute.AttributeId] = &model.TbAttributeValueJson{Items: []model.TbAttributeValueItem{{Name: attribute.Value, Image: (*specs)[i].Image}}, Str: attribute.Value + ","} (*specs)[i].Code += fmt.Sprintf("#%v-0", attribute.AttributeId) } } } { var attributeList []model.TbAttributeWithValues err = global.MG_DB.Model(&model.TbAttribute{}).Select("id,`name`").Where("id IN (?)", attributeIds).Find(&attributeList).Error if err != nil { return err, nil } for _, attribute := range attributeList { attributeMap[attribute.ID] = attribute.Name } } for i := 0; i < len(result); i++ { if val, ok := attributeMap[result[i].ID]; ok { result[i].Name = val } if val, ok := attributeValues[result[i].ID]; ok { result[i].Values = val.Items } } return nil, result } func orderRefund(tx *gorm.DB, orderId, title, attach string, amount float64) (error, string) { var ( err error order model.Order ) ok, err := global.MG_REDIS.SetNX("orderRefund-"+orderId, "used", 0).Result() if !ok || err != nil { return errors.New("request error"), "" } err = tx.Model(&model.Order{}).Where("order_id = ?", orderId).First(&order).Error if order.Status != 2 { err = errors.New("订单状态错误") return err, "" } if amount > order.PaidPrice { err = errors.New("退款金额错误") return err, "" } { // 用户付款账单处理 var bill model.Bill err = tx.Model(&model.Bill{}).Where("platform = 'customer' AND order_id = ? AND type = '2' AND `status` = 1", order.OrderID).UpdateColumn("receipt", 3).Error if err != nil { return err, "" } bill.UserID = order.UserID bill.Type = "2" bill.Title = title + "-订单" + order.OrderID bill.OrderID = order.OrderID bill.Price = amount bill.Status = 2 bill.Receipt = 2 bill.Platform = "customer" bill.TransactionId = "R" + Generate() err = tx.Create(&bill).Error if err != nil { return err, "" } } { if order.Code != "" { var ( oldBill model.Bill bill model.Bill wallet model.Wallet ) err = tx.Model(&model.Bill{}).Where("platform = 'influencer' AND order_id = ? AND type = '1' AND `status` = 2", order.OrderID).Find(&oldBill).Error if err != nil { return err, "" } // 扣除领取任务订单统计数据 err = tx.Model(&model.MissionClaim{}).Where("claim_no = ?", order.Code).UpdateColumns(map[string]interface{}{"order_num": gorm.Expr("order_num - 1"), "order_money": gorm.Expr("order_money - ?", order.Price), "reward_unfinished": gorm.Expr("reward_unfinished - ?", oldBill.Price)}).Error if err != nil { return err, "" } err = tx.Model(&model.Wallet{}).Where("user_id = ? AND platform = 'seller'", oldBill.UserID).Update("transit_balance", gorm.Expr("transit_balance - ?", oldBill.Price)).Error if err != nil { return err, "" } err, wallet = getWallet("influencer", oldBill.UserID) if err != nil { return err, "" } bill.UserID = oldBill.UserID bill.Type = "1" bill.Title = title + "-订单" + oldBill.OrderID bill.OrderID = oldBill.OrderID bill.Price = oldBill.Price bill.Balance = wallet.Balance bill.Status = 1 bill.Receipt = 2 bill.Platform = oldBill.Platform bill.TransactionId = "R" + Generate() bill.Remark = "订单取消" err = tx.Create(&bill).Error if err != nil { return err, "" } } } { var ( oldBill model.Bill bill model.Bill wallet model.Wallet ) err = tx.Model(&model.Bill{}).Where("platform = 'seller' AND order_id = ? AND type = '2' AND `status` = 2", order.OrderID).Find(&oldBill).Error if err != nil { return err, "" } err = tx.Model(&model.Wallet{}).Where("user_id = ?", oldBill.UserID).Update("transit_balance", gorm.Expr("transit_balance - ?", oldBill.Price)).Error if err != nil { return err, "" } err, wallet = getWallet("seller", oldBill.UserID) if err != nil { return err, "" } bill.UserID = oldBill.UserID bill.Type = "2" bill.Title = "交易退款-订单" + oldBill.OrderID bill.OrderID = oldBill.OrderID bill.Price = oldBill.Price bill.Balance = wallet.Balance bill.Status = 1 bill.Receipt = 2 bill.Platform = oldBill.Platform bill.TransactionId = "R" + Generate() bill.Remark = "订单取消" err = tx.Create(&bill).Error if err != nil { return err, "" } } params1 := api.RefundRequest{ Appid: "bkb5918273465092837", Mchid: "11000001", OutTradeNo: order.OrderID, PayId: order.PaypalID, Attach: attach, NotifyUrl: global.MG_CONFIG.Payment.NotifyUrl, Amount: amount, Description: "订单退款-" + order.OrderID, } refundResp, err := api.NewGreeterClient(global.PAY_CONN).RefundBill(context.Background(), ¶ms1) if err != nil { return err, "" } if refundResp.RefundStatus != "SUCCESS" { err = errors.New("refund failed") return err, "" } return err, refundResp.RefundId } func orderRefundSuccess(tx *gorm.DB, orderId string) error { var ( err error order model.Order ) err = tx.Model(&model.Order{}).Where("order_id = ?", orderId).First(&order).Error if err != nil { return err } { err = tx.Model(&model.Bill{}).Where("platform = 'customer' AND order_id = ? AND type = '2' AND `status` = 2 AND receipt = 2", orderId).Update("receipt", 1).Error if err != nil { return err } } { if order.Code != "" { err = tx.Model(&model.Bill{}).Where("platform = 'influencer' AND order_id = ? AND type = '1' AND `status` = 1 AND receipt = 2", orderId).Update("receipt", 1).Error if err != nil { return err } } } { err = tx.Model(&model.Bill{}).Where("platform = 'seller' AND order_id = ? AND type = '2' AND `status` = 1 AND receipt = 2", orderId).Update("receipt", 1).Error if err != nil { return err } } return err }