You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
265 lines
6.0 KiB
265 lines
6.0 KiB
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
|
|
}
|