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.
268 lines
6.4 KiB
268 lines
6.4 KiB
package alipay
|
|
|
|
import (
|
|
"errors"
|
|
"fmt"
|
|
"os"
|
|
"path/filepath"
|
|
"recook/internal/api/mobile/pay/public"
|
|
"recook/internal/back"
|
|
"recook/internal/dbc"
|
|
"recook/internal/domain"
|
|
"recook/internal/model/order"
|
|
"recook/internal/model/pay"
|
|
"recook/internal/service/comFunc"
|
|
"recook/tools"
|
|
"strconv"
|
|
"time"
|
|
|
|
"github.com/gin-gonic/gin"
|
|
"github.com/jinzhu/gorm"
|
|
"github.com/shopspring/decimal"
|
|
"github.com/smartwalle/alipay/v3"
|
|
)
|
|
|
|
type createH5AlipayReq struct {
|
|
UserID uint `json:"userId" validate:"required,numeric"`
|
|
OrderID uint `json:"orderId" validate:"required,numeric"`
|
|
}
|
|
|
|
func createH5Order(orderID uint, ip string, userID uint) (error, string) {
|
|
now := time.Now().Unix()
|
|
|
|
var od []order.Information
|
|
if err := dbc.DB.Find(&od, "virtual_id = ?", orderID).Error; err != nil {
|
|
return err, ""
|
|
}
|
|
|
|
if err := public.UpdateVirtualPay(orderID); err != nil {
|
|
return err, ""
|
|
}
|
|
|
|
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.AlipayH5Detail
|
|
if err := dbc.DB.First(&detail, "order_id = ?", orderID).Error; err != nil && err != gorm.ErrRecordNotFound {
|
|
return err, ""
|
|
}
|
|
|
|
if detail.ID > 0 {
|
|
tx := dbc.DB.Begin()
|
|
{
|
|
for _, v := range od {
|
|
if v.PayMethod != order.AlipayH5ForOrderInfo {
|
|
if err := tx.Model(&v).Updates(order.Information{
|
|
PayIP: ip,
|
|
TradeNo: detail.TradeNo,
|
|
PayMethod: order.AlipayH5ForOrderInfo,
|
|
}).Error; err != nil {
|
|
tx.Rollback()
|
|
return err, ""
|
|
}
|
|
}
|
|
}
|
|
}
|
|
tx.Commit()
|
|
return nil, detail.CreateOrderSign
|
|
} else {
|
|
if url, tradeNo, err := genUrl(od[0].Title, userID, orderID, amount); err != nil {
|
|
return errors.New("失败"), ""
|
|
} else {
|
|
tx := dbc.DB.Begin()
|
|
{
|
|
for _, v := range od {
|
|
if err = dbc.DB.Model(&v).Updates(order.Information{
|
|
PayIP: ip,
|
|
TradeNo: tradeNo,
|
|
PayMethod: order.AlipayH5ForOrderInfo,
|
|
}).Error; err != nil {
|
|
tx.Rollback()
|
|
return err, ""
|
|
}
|
|
}
|
|
|
|
detail = pay.AlipayH5Detail{
|
|
OrderId: int64(orderID),
|
|
TradeNo: tradeNo,
|
|
CreateOrderSign: url,
|
|
}
|
|
if err = tx.Create(&detail).Error; err != nil {
|
|
tx.Rollback()
|
|
return err, ""
|
|
}
|
|
}
|
|
tx.Commit()
|
|
return nil, url
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
逻辑处理从之前的app支付过来的
|
|
*/
|
|
func CreateH5Alipay(c *gin.Context) {
|
|
var p createH5AlipayReq
|
|
err := tools.ParseParams(&p, c)
|
|
if err != nil {
|
|
back.Fail(c, err.Error())
|
|
return
|
|
}
|
|
|
|
if !public.Judge(p.OrderID) {
|
|
if err, result := createH5Order(p.OrderID, c.ClientIP(), p.UserID); err != nil {
|
|
back.Err(c, err.Error())
|
|
return
|
|
} else {
|
|
back.Suc(c, "操作成功", gin.H{
|
|
"payUrl": result,
|
|
})
|
|
return
|
|
}
|
|
}
|
|
|
|
if err = public.UpdateNormalPay(p.OrderID); err != nil {
|
|
back.Err(c, err.Error())
|
|
return
|
|
}
|
|
|
|
now := time.Now().Unix()
|
|
|
|
var orderInfo order.Information
|
|
err = dbc.DB.First(&orderInfo, "id = ?", p.OrderID).Error
|
|
if err != nil {
|
|
back.Err(c, err.Error())
|
|
return
|
|
}
|
|
|
|
// 零支付
|
|
if orderInfo.ActualTotalAmount.Equal(decimal.NewFromFloat(0.0)) {
|
|
back.Fail(c, "接口调用错误")
|
|
return
|
|
}
|
|
|
|
err = public.ValidateOrderInfo(&orderInfo, now)
|
|
if err != nil {
|
|
back.Fail(c, err.Error())
|
|
return
|
|
}
|
|
|
|
var detail pay.AlipayH5Detail
|
|
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{
|
|
"payUrl": detail.CreateOrderSign,
|
|
})
|
|
|
|
if orderInfo.PayMethod != order.AlipayH5ForOrderInfo {
|
|
err = dbc.DB.Model(&orderInfo).Updates(order.Information{
|
|
PayIP: c.ClientIP(),
|
|
TradeNo: detail.TradeNo,
|
|
PayMethod: order.AlipayH5ForOrderInfo,
|
|
}).Error
|
|
if err != nil {
|
|
back.Err(c, err.Error())
|
|
return
|
|
}
|
|
}
|
|
|
|
} else {
|
|
if url, tradeNo, err := genUrl(orderInfo.Title, p.UserID, orderInfo.ID, orderInfo.ActualTotalAmount); err != nil {
|
|
back.Fail(c, "失败")
|
|
} else {
|
|
err = dbc.DB.Model(&orderInfo).Updates(order.Information{
|
|
PayIP: c.ClientIP(),
|
|
TradeNo: tradeNo,
|
|
PayMethod: order.AlipayH5ForOrderInfo,
|
|
}).Error
|
|
if err != nil {
|
|
back.Err(c, err.Error())
|
|
return
|
|
}
|
|
|
|
detail = pay.AlipayH5Detail{
|
|
OrderId: int64(orderInfo.ID),
|
|
TradeNo: tradeNo,
|
|
CreateOrderSign: url,
|
|
}
|
|
dbc.DB.Create(&detail)
|
|
back.Suc(c, "", gin.H{
|
|
"payUrl": url,
|
|
})
|
|
}
|
|
}
|
|
}
|
|
|
|
func genUrl(title string, userID uint, orderID uint, actualAmount decimal.Decimal) (string, string, error) {
|
|
var privateKey = RecookToAliPayPrivateKeyForTest
|
|
client, err := alipay.New(AppID0602, privateKey, true)
|
|
|
|
if err != nil {
|
|
errMsg := fmt.Sprintf("加载出现错误%s,", err)
|
|
comFunc.PrintErr(errMsg)
|
|
return "", "", err
|
|
}
|
|
|
|
dir, _ := os.Executable()
|
|
exPath := filepath.Dir(dir)
|
|
alipayH5Path := exPath + "/credentials/alipay_h5/"
|
|
|
|
err = client.LoadAppPublicCertFromFile(alipayH5Path + "appCertPublicKey_2021001152664931.crt") // 加载应用公钥证书
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
err = client.LoadAliPayRootCertFromFile(alipayH5Path + "alipayRootCert.crt") // 加载支付宝根证书
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
err = client.LoadAliPayPublicCertFromFile(alipayH5Path + "alipayCertPublicKey_RSA2.crt") // 加载支付宝公钥证书
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
|
|
var pa = alipay.TradeWapPay{}
|
|
// 回调地址
|
|
pa.NotifyURL = domain.GetName() + "/api/v1/pay/alipay/h5_callback"
|
|
// 跳转页面
|
|
pa.ReturnURL = "https://h5.reecook.cn/app/paydone.html"
|
|
// 应该是商城名称
|
|
pa.Subject = title
|
|
// 生成唯一订单号
|
|
outTradeNo := public.GenerateOrderAliPayOutTradeNo(userID, orderID)
|
|
pa.OutTradeNo = outTradeNo
|
|
amount, _ := strconv.ParseFloat(actualAmount.String(), 2)
|
|
pa.TotalAmount = strconv.FormatFloat(amount, 'f', 2, 64)
|
|
pa.ProductCode = "AlipayH5"
|
|
// pa.ProductCode = "QUICK_WAP_WAY"
|
|
pa.TimeExpire = time.Now().Add(60 * time.Minute).Format("2006-01-02 15:04")
|
|
pa.TimeoutExpress = time.Now().Add(15 * time.Minute).Format("2006-01-02 15:04:05")
|
|
// bs, _ := json.Marshal(pa)
|
|
// beego.Info(string(bs))
|
|
payUrl, err := client.TradeWapPay(pa)
|
|
if err != nil {
|
|
errMsg := fmt.Sprintf("alipay-h5 支付出现错误%s,", err)
|
|
comFunc.PrintErr(errMsg)
|
|
return "", "", err
|
|
}
|
|
|
|
var payURL = payUrl.String()
|
|
|
|
return payURL, outTradeNo, nil
|
|
}
|