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

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
}