Feat: vas alipay

This commit is contained in:
HFO4
2020-02-17 12:33:54 +08:00
parent 41f9f3497f
commit f8c14b3826
9 changed files with 225 additions and 4 deletions

42
pkg/payment/alipay.go Normal file
View File

@@ -0,0 +1,42 @@
package payment
import (
"fmt"
model "github.com/HFO4/cloudreve/models"
"github.com/HFO4/cloudreve/pkg/serializer"
alipay "github.com/smartwalle/alipay/v3"
"net/url"
)
// Alipay 支付宝当面付支付处理
type Alipay struct {
Client *alipay.Client
}
// Create 创建订单
func (pay *Alipay) Create(order *model.Order, pack *serializer.PackProduct, group *serializer.GroupProducts, user *model.User) (*OrderCreateRes, error) {
gateway, _ := url.Parse("/api/v3/callback/alipay")
var p = alipay.TradePreCreate{
Trade: alipay.Trade{
NotifyURL: model.GetSiteURL().ResolveReference(gateway).String(),
Subject: order.Name,
OutTradeNo: order.OrderNo,
TotalAmount: fmt.Sprintf("%.2f", float64(order.Price*order.Num)/100),
},
}
if _, err := order.Create(); err != nil {
return nil, ErrInsertOrder.WithError(err)
}
res, err := pay.Client.TradePreCreate(p)
if err != nil {
return nil, ErrIssueOrder.WithError(err)
}
return &OrderCreateRes{
Payment: true,
QRCode: res.Content.QRCode,
ID: order.OrderNo,
}, nil
}

View File

@@ -4,6 +4,9 @@ import (
"fmt"
model "github.com/HFO4/cloudreve/models"
"github.com/HFO4/cloudreve/pkg/serializer"
"github.com/smartwalle/alipay/v3"
"math/rand"
"time"
)
var (
@@ -23,6 +26,12 @@ var (
ErrGroupInvalid = serializer.NewError(serializer.CodeNoPermissionErr, "用户组不可用", nil)
// ErrUpgradeGroup 用户组冲突
ErrUpgradeGroup = serializer.NewError(serializer.CodeDBError, "无法升级用户组", nil)
// ErrUInitPayment 无法初始化支付实例
ErrUInitPayment = serializer.NewError(serializer.CodeInternalSetting, "无法初始化支付实例", nil)
// ErrIssueOrder 订单接口请求失败
ErrIssueOrder = serializer.NewError(serializer.CodeInternalSetting, "无法创建订单", nil)
// ErrOrderNotFound 订单不存在
ErrOrderNotFound = serializer.NewError(serializer.CodeNotFound, "订单不存在", nil)
)
// Pay 支付处理接口
@@ -32,16 +41,39 @@ type Pay interface {
// OrderCreateRes 订单创建结果
type OrderCreateRes struct {
Payment bool `json:"payment"` // 是否需要支付
Payment bool `json:"payment"` // 是否需要支付
ID string `json:"id,omitempty"` // 订单号
QRCode string `json:"qr_code,omitempty"` // 支付二维码指向的地址
Redirect string `json:"redirect,omitempty"` // 支付跳转连接,和二维码二选一,不需要的留空
}
// NewPaymentInstance 获取新的支付实例
func NewPaymentInstance(method string) (Pay, error) {
if method == "score" {
switch method {
case "score":
return &ScorePayment{}, nil
}
case "alipay":
options := model.GetSettingByNames("alipay_enabled", "appid", "appkey", "shopid")
if options["alipay_enabled"] != "1" {
return nil, ErrUnknownPaymentMethod
}
return nil, ErrUnknownPaymentMethod
// 初始化支付宝客户端
var client, err = alipay.New(options["appid"], options["appkey"], true)
if err != nil {
return nil, ErrUInitPayment.WithError(err)
}
// 加载支付宝公钥
err = client.LoadAliPayPublicKey(options["shopid"])
if err != nil {
return nil, ErrUInitPayment.WithError(err)
}
return &Alipay{Client: client}, nil
default:
return nil, ErrUnknownPaymentMethod
}
}
// NewOrder 创建新订单
@@ -78,6 +110,7 @@ func NewOrder(pack *serializer.PackProduct, group *serializer.GroupProducts, num
// 创建订单记录
order := &model.Order{
UserID: user.ID,
OrderNo: orderID(),
Type: orderType,
Method: method,
ProductID: productID,
@@ -89,3 +122,10 @@ func NewOrder(pack *serializer.PackProduct, group *serializer.GroupProducts, num
return pay.Create(order, pack, group, user)
}
func orderID() string {
return fmt.Sprintf("%s%d%d",
time.Now().Format("20060102150405"),
10000+rand.Intn(90000),
time.Now().UnixNano())
}

View File

@@ -1,6 +1,8 @@
package payment
import (
"encoding/json"
"errors"
model "github.com/HFO4/cloudreve/models"
"github.com/HFO4/cloudreve/pkg/serializer"
"time"
@@ -69,3 +71,58 @@ func GiveProduct(user *model.User, pack *serializer.PackProduct, group *serializ
return GiveScore(user, num)
}
}
// OrderPaid 订单已支付处理
func OrderPaid(orderNo string) error {
order, err := model.GetOrderByNo(orderNo)
if err != nil {
return ErrOrderNotFound.WithError(err)
}
// 更新订单状态为 已支付
order.UpdateStatus(model.OrderPaid)
user, err := model.GetActiveUserByID(order.UserID)
if err != nil {
return errors.New("用户不存在")
}
// 查询商品
options := model.GetSettingByNames("pack_data", "group_sell_data")
var (
packs []serializer.PackProduct
groups []serializer.GroupProducts
)
if err := json.Unmarshal([]byte(options["pack_data"]), &packs); err != nil {
return err
}
if err := json.Unmarshal([]byte(options["group_sell_data"]), &groups); err != nil {
return err
}
// 查找要购买的商品
var (
pack *serializer.PackProduct
group *serializer.GroupProducts
)
if order.Type == model.GroupOrderType {
for _, v := range groups {
if v.ID == order.ProductID {
group = &v
break
}
}
} else if order.Type == model.PackOrderType {
for _, v := range packs {
if v.ID == order.ProductID {
pack = &v
break
}
}
}
// "发货"
return GiveProduct(&user, pack, group, order.Num)
}