package alipay import ( "errors" alipay2 "git.oa00.com/go/alipay" "github.com/smartwalle/alipay/v3" "recook/internal/api/mobile/pay/public" "recook/internal/back" "recook/internal/dbc" "recook/internal/model/order" "recook/internal/model/pay" "recook/tools" "time" "github.com/gin-gonic/gin" "github.com/golangkit/formatime" "github.com/jinzhu/gorm" "github.com/shopspring/decimal" ) type CreateOrderBizContentParam struct { TimeExpire string `json:"time_expire"` // 绝对超时时间 yyyy-MM-dd HH:mm TotalAmount string `json:"total_amount"` // 订单总金额,单位为元,精确到小数点后两位,取值范围[0.01,100000000] Subject string `json:"subject"` // 商品的标题/交易标题/订单标题/订单关键字等。 OutTradeNo string `json:"out_trade_no"` // 商户网站唯一订单号 ProductCode string `json:"product_code"` // "product_code":"QUICK_MSECURITY_PAY" } func (*CreateOrderBizContentParam) GetMethod() string { return "alipay.trade.app.pay" } type appCreateOrderParam struct { UserID uint `json:"userId" validate:"required"` OrderID uint `json:"orderId" validate:"required"` } func createOrder(virtualID uint, ip string, userID uint) (error, string) { var od []order.Information if err := dbc.DB.Find(&od, "virtual_id = ?", virtualID).Error; err != nil { return err, "" } if len(od) != 0 { if !od[0].CanPay && od[0].OrderType == 2 { return errors.New("批发订单运费未确定无法支付"), "" } } if err := public.UpdateVirtualPay(virtualID); err != nil { return err, "" } now := time.Now().Unix() amount := decimal.Zero for _, v := range od { if err := public.ValidateOrderInfo(&v, now); err != nil { return err, "" } amount = amount.Add(v.ActualTotalAmount) } if amount.IsZero() { return errors.New("接口调用错误"), "" } var detail pay.AliPayDetail if err := dbc.DB.First(&detail, "order_id = ?", virtualID).Error; err != nil && err != gorm.ErrRecordNotFound { return err, "" } if detail.ID > 0 { tx := dbc.DB.Begin() { for _, v := range od { if v.PayMethod != order.AlipayForOrderInfo { if err := tx.Model(&v).Updates(order.Information{ PayIP: ip, TradeNo: detail.TradeNo, PayMethod: order.AlipayForOrderInfo, }).Error; err != nil { tx.Rollback() return err, "" } } } } tx.Commit() return nil, detail.CreateOrderSign } else { outTradeNo, orderSignResult := genSign( od[0].ExpireTime, userID, virtualID, amount, od[0].Title, ) detail = pay.AliPayDetail{ OrderID: virtualID, TradeNo: outTradeNo, CreateOrderSign: orderSignResult, } tx := dbc.DB.Begin() { err := tx.Create(&detail).Error if err != nil { tx.Rollback() return err, "" } for _, v := range od { err = dbc.DB.Model(&v).Updates(order.Information{ PayIP: ip, TradeNo: detail.TradeNo, PayMethod: order.AlipayForOrderInfo, }).Error if err != nil { tx.Rollback() return err, "" } } } tx.Commit() return nil, orderSignResult } } func PayOrder(c *gin.Context) { var p appCreateOrderParam err := tools.ParseParams(&p, c) if err != nil { back.Fail(c, err.Error()) return } if !public.Judge(p.OrderID) { if err, sign := createOrder(p.OrderID, c.ClientIP(), p.UserID); err != nil { back.Err(c, err.Error()) } else { back.Suc(c, "", gin.H{ "orderString": sign, }) } return } if err = public.UpdateNormalPay(p.OrderID); err != nil { back.Err(c, err.Error()) return } now := time.Now().Unix() var orderInfo order.Information if !orderInfo.CanPay && orderInfo.OrderType == 2 { err = errors.New("批发订单运费未确定无法支付") back.Fail(c, err.Error()) return } err = dbc.DB.First(&orderInfo, "id = ?", p.OrderID).Error if err != nil { back.Err(c, err.Error()) return } err = public.ValidateOrderInfo(&orderInfo, now) if err != nil { back.Fail(c, err.Error()) return } // 应该调用零支付 if orderInfo.ActualTotalAmount.Equal(decimal.NewFromFloat(0.0)) { back.Fail(c, "接口调用错误") return } var detail pay.AliPayDetail err = dbc.DB.First(&detail, "order_id = ?", orderInfo.ID).Error if err != nil && !gorm.IsRecordNotFoundError(err) { back.Err(c, err.Error()) return } if detail.ID > 0 { // 如果生成过记录了 back.Suc(c, "", gin.H{ "orderString": detail.CreateOrderSign, }) if orderInfo.PayMethod != 2 { err = dbc.DB.Model(&orderInfo).Updates(order.Information{ PayIP: c.ClientIP(), TradeNo: detail.TradeNo, PayMethod: order.AlipayForOrderInfo, }).Error if err != nil { back.Err(c, err.Error()) return } } } else { outTradeNo, orderSignResult := genSign( orderInfo.ExpireTime, p.UserID, orderInfo.ID, orderInfo.ActualTotalAmount, orderInfo.Title, ) detail = pay.AliPayDetail{ OrderID: orderInfo.ID, TradeNo: outTradeNo, CreateOrderSign: orderSignResult, } tx := dbc.DB.Begin() { err = tx.Create(&detail).Error if err != nil { back.Err(c, err.Error()) tx.Rollback() return } err = dbc.DB.Model(&orderInfo).Updates(order.Information{ PayIP: c.ClientIP(), TradeNo: detail.TradeNo, PayMethod: order.AlipayForOrderInfo, }).Error if err != nil { back.Err(c, err.Error()) tx.Rollback() return } } tx.Commit() back.Suc(c, "", gin.H{ "orderString": orderSignResult, }) } } func genSign(expire formatime.Second, userID uint, orderID uint, amount decimal.Decimal, title string) (string, string) { afterTime, _ := time.ParseDuration(public.TimeExpireDuration) expireTime := expire.Time.Add(afterTime) outTradeNo := public.GenerateOrderAliPayOutTradeNo(userID, orderID) param := alipay.TradeAppPay{} param.OutTradeNo = outTradeNo param.TotalAmount = amount.Truncate(2).String() param.Subject = title param.TimeExpire = expireTime.Format("2006-01-02 15:04:05") param.NotifyURL = PayCallbackUrl orderSignResult, _ := alipay2.Alipay.TradeAppPay(param) return outTradeNo, orderSignResult }