Modify: clean useless codes
parent
09de05548f
commit
45b54b3455
|
|
@ -6,20 +6,6 @@ import (
|
||||||
"github.com/HFO4/cloudreve/pkg/util"
|
"github.com/HFO4/cloudreve/pkg/util"
|
||||||
)
|
)
|
||||||
|
|
||||||
// NewOveruseNotification 新建超额提醒邮件
|
|
||||||
func NewOveruseNotification(userName, reason string) (string, string) {
|
|
||||||
options := model.GetSettingByNames("siteName", "siteURL", "siteTitle", "over_used_template")
|
|
||||||
replace := map[string]string{
|
|
||||||
"{siteTitle}": options["siteName"],
|
|
||||||
"{userName}": userName,
|
|
||||||
"{notifyReason}": reason,
|
|
||||||
"{siteUrl}": options["siteURL"],
|
|
||||||
"{siteSecTitle}": options["siteTitle"],
|
|
||||||
}
|
|
||||||
return fmt.Sprintf("【%s】空间容量超额提醒", options["siteName"]),
|
|
||||||
util.Replace(replace, options["over_used_template"])
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewActivationEmail 新建激活邮件
|
// NewActivationEmail 新建激活邮件
|
||||||
func NewActivationEmail(userName, activateURL string) (string, string) {
|
func NewActivationEmail(userName, activateURL string) (string, string) {
|
||||||
options := model.GetSettingByNames("siteName", "siteURL", "siteTitle", "mail_activation_template")
|
options := model.GetSettingByNames("siteName", "siteURL", "siteTitle", "mail_activation_template")
|
||||||
|
|
|
||||||
|
|
@ -1,42 +0,0 @@
|
||||||
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
|
|
||||||
}
|
|
||||||
|
|
@ -1,147 +0,0 @@
|
||||||
package payment
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
model "github.com/HFO4/cloudreve/models"
|
|
||||||
"github.com/HFO4/cloudreve/pkg/serializer"
|
|
||||||
"github.com/qingwg/payjs"
|
|
||||||
"github.com/smartwalle/alipay/v3"
|
|
||||||
"math/rand"
|
|
||||||
"net/url"
|
|
||||||
"time"
|
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
|
||||||
// ErrUnknownPaymentMethod 未知支付方式
|
|
||||||
ErrUnknownPaymentMethod = serializer.NewError(serializer.CodeNotFound, "未知支付方式", nil)
|
|
||||||
// ErrUnsupportedPaymentMethod 未知支付方式
|
|
||||||
ErrUnsupportedPaymentMethod = serializer.NewError(serializer.CodeNotFound, "此订单不支持此支付方式", nil)
|
|
||||||
// ErrInsertOrder 无法插入订单记录
|
|
||||||
ErrInsertOrder = serializer.NewError(serializer.CodeDBError, "无法插入订单记录", nil)
|
|
||||||
// ErrScoreNotEnough 积分不足
|
|
||||||
ErrScoreNotEnough = serializer.NewError(serializer.CodeNoPermissionErr, "积分不足", nil)
|
|
||||||
// ErrCreateStoragePack 无法创建容量包
|
|
||||||
ErrCreateStoragePack = serializer.NewError(serializer.CodeNoPermissionErr, "无法创建容量包", nil)
|
|
||||||
// ErrGroupConflict 用户组冲突
|
|
||||||
ErrGroupConflict = serializer.NewError(serializer.CodeNoPermissionErr, "当前用户组仍未过期,请前往个人设置手动解约后继续", nil)
|
|
||||||
// ErrGroupInvalid 用户组冲突
|
|
||||||
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 支付处理接口
|
|
||||||
type Pay interface {
|
|
||||||
Create(order *model.Order, pack *serializer.PackProduct, group *serializer.GroupProducts, user *model.User) (*OrderCreateRes, error)
|
|
||||||
}
|
|
||||||
|
|
||||||
// OrderCreateRes 订单创建结果
|
|
||||||
type OrderCreateRes struct {
|
|
||||||
Payment bool `json:"payment"` // 是否需要支付
|
|
||||||
ID string `json:"id,omitempty"` // 订单号
|
|
||||||
QRCode string `json:"qr_code,omitempty"` // 支付二维码指向的地址
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewPaymentInstance 获取新的支付实例
|
|
||||||
func NewPaymentInstance(method string) (Pay, error) {
|
|
||||||
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
|
|
||||||
}
|
|
||||||
|
|
||||||
// 初始化支付宝客户端
|
|
||||||
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
|
|
||||||
case "payjs":
|
|
||||||
options := model.GetSettingByNames("payjs_enabled", "payjs_secret", "payjs_id")
|
|
||||||
if options["payjs_enabled"] != "1" {
|
|
||||||
return nil, ErrUnknownPaymentMethod
|
|
||||||
}
|
|
||||||
|
|
||||||
callback, _ := url.Parse("/api/v3/callback/payjs")
|
|
||||||
payjsConfig := &payjs.Config{
|
|
||||||
Key: options["payjs_secret"],
|
|
||||||
MchID: options["payjs_id"],
|
|
||||||
NotifyUrl: model.GetSiteURL().ResolveReference(callback).String(),
|
|
||||||
}
|
|
||||||
|
|
||||||
return &PayJSClient{Client: payjs.New(payjsConfig)}, nil
|
|
||||||
|
|
||||||
default:
|
|
||||||
return nil, ErrUnknownPaymentMethod
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewOrder 创建新订单
|
|
||||||
func NewOrder(pack *serializer.PackProduct, group *serializer.GroupProducts, num int, method string, user *model.User) (*OrderCreateRes, error) {
|
|
||||||
// 获取支付实例
|
|
||||||
pay, err := NewPaymentInstance(method)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
var (
|
|
||||||
orderType int
|
|
||||||
productID int64
|
|
||||||
title string
|
|
||||||
price int
|
|
||||||
)
|
|
||||||
if pack != nil {
|
|
||||||
orderType = model.PackOrderType
|
|
||||||
productID = pack.ID
|
|
||||||
title = pack.Name
|
|
||||||
price = pack.Price
|
|
||||||
} else if group != nil {
|
|
||||||
orderType = model.GroupOrderType
|
|
||||||
productID = group.ID
|
|
||||||
title = group.Name
|
|
||||||
price = group.Price
|
|
||||||
} else {
|
|
||||||
orderType = model.ScoreOrderType
|
|
||||||
productID = 0
|
|
||||||
title = fmt.Sprintf("%d 积分", num)
|
|
||||||
price = model.GetIntSetting("score_price", 1)
|
|
||||||
}
|
|
||||||
|
|
||||||
// 创建订单记录
|
|
||||||
order := &model.Order{
|
|
||||||
UserID: user.ID,
|
|
||||||
OrderNo: orderID(),
|
|
||||||
Type: orderType,
|
|
||||||
Method: method,
|
|
||||||
ProductID: productID,
|
|
||||||
Num: num,
|
|
||||||
Name: fmt.Sprintf("%s - %s", model.GetSettingByName("siteName"), title),
|
|
||||||
Price: price,
|
|
||||||
Status: model.OrderUnpaid,
|
|
||||||
}
|
|
||||||
|
|
||||||
return pay.Create(order, pack, group, user)
|
|
||||||
}
|
|
||||||
|
|
||||||
func orderID() string {
|
|
||||||
return fmt.Sprintf("%s%d",
|
|
||||||
time.Now().Format("20060102150405"),
|
|
||||||
100000+rand.Intn(900000),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
@ -1,31 +0,0 @@
|
||||||
package payment
|
|
||||||
|
|
||||||
import (
|
|
||||||
model "github.com/HFO4/cloudreve/models"
|
|
||||||
"github.com/HFO4/cloudreve/pkg/serializer"
|
|
||||||
"github.com/qingwg/payjs"
|
|
||||||
)
|
|
||||||
|
|
||||||
// PayJSClient PayJS支付处理
|
|
||||||
type PayJSClient struct {
|
|
||||||
Client *payjs.PayJS
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create 创建订单
|
|
||||||
func (pay *PayJSClient) Create(order *model.Order, pack *serializer.PackProduct, group *serializer.GroupProducts, user *model.User) (*OrderCreateRes, error) {
|
|
||||||
if _, err := order.Create(); err != nil {
|
|
||||||
return nil, ErrInsertOrder.WithError(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
PayNative := pay.Client.GetNative()
|
|
||||||
res, err := PayNative.Create(int64(order.Price*order.Num), order.Name, order.OrderNo, "", "")
|
|
||||||
if err != nil {
|
|
||||||
return nil, ErrIssueOrder.WithError(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
return &OrderCreateRes{
|
|
||||||
Payment: true,
|
|
||||||
QRCode: res.CodeUrl,
|
|
||||||
ID: order.OrderNo,
|
|
||||||
}, nil
|
|
||||||
}
|
|
||||||
|
|
@ -1,127 +0,0 @@
|
||||||
package payment
|
|
||||||
|
|
||||||
import (
|
|
||||||
"encoding/json"
|
|
||||||
"errors"
|
|
||||||
model "github.com/HFO4/cloudreve/models"
|
|
||||||
"github.com/HFO4/cloudreve/pkg/serializer"
|
|
||||||
"time"
|
|
||||||
)
|
|
||||||
|
|
||||||
// GivePack 创建容量包
|
|
||||||
func GivePack(user *model.User, packInfo *serializer.PackProduct, num int) error {
|
|
||||||
timeNow := time.Now()
|
|
||||||
expires := timeNow.Add(time.Duration(packInfo.Time*int64(num)) * time.Second)
|
|
||||||
pack := model.StoragePack{
|
|
||||||
Name: packInfo.Name,
|
|
||||||
UserID: user.ID,
|
|
||||||
ActiveTime: &timeNow,
|
|
||||||
ExpiredTime: &expires,
|
|
||||||
Size: packInfo.Size,
|
|
||||||
}
|
|
||||||
if _, err := pack.Create(); err != nil {
|
|
||||||
return ErrCreateStoragePack.WithError(err)
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func checkGroupUpgrade(user *model.User, groupInfo *serializer.GroupProducts) error {
|
|
||||||
// 检查用户是否已有未过期用户
|
|
||||||
if user.PreviousGroupID != 0 {
|
|
||||||
return ErrGroupConflict
|
|
||||||
}
|
|
||||||
|
|
||||||
// 用户组不能相同
|
|
||||||
if user.GroupID == groupInfo.GroupID {
|
|
||||||
return ErrGroupInvalid
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// GiveGroup 升级用户组
|
|
||||||
func GiveGroup(user *model.User, groupInfo *serializer.GroupProducts, num int) error {
|
|
||||||
if err := checkGroupUpgrade(user, groupInfo); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
timeNow := time.Now()
|
|
||||||
expires := timeNow.Add(time.Duration(groupInfo.Time*int64(num)) * time.Second)
|
|
||||||
|
|
||||||
if err := user.UpgradeGroup(groupInfo.GroupID, &expires); err != nil {
|
|
||||||
return ErrUpgradeGroup.WithError(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// GiveScore 积分充值
|
|
||||||
func GiveScore(user *model.User, num int) error {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// GiveProduct “发货”
|
|
||||||
func GiveProduct(user *model.User, pack *serializer.PackProduct, group *serializer.GroupProducts, num int) error {
|
|
||||||
if pack != nil {
|
|
||||||
return GivePack(user, pack, num)
|
|
||||||
} else if group != nil {
|
|
||||||
return GiveGroup(user, group, num)
|
|
||||||
} else {
|
|
||||||
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)
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -1,34 +0,0 @@
|
||||||
package payment
|
|
||||||
|
|
||||||
import (
|
|
||||||
model "github.com/HFO4/cloudreve/models"
|
|
||||||
"github.com/HFO4/cloudreve/pkg/serializer"
|
|
||||||
)
|
|
||||||
|
|
||||||
// ScorePayment 积分支付处理
|
|
||||||
type ScorePayment struct {
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create 创建新订单
|
|
||||||
func (pay *ScorePayment) Create(order *model.Order, pack *serializer.PackProduct, group *serializer.GroupProducts, user *model.User) (*OrderCreateRes, error) {
|
|
||||||
if pack != nil {
|
|
||||||
order.Price = pack.Score
|
|
||||||
} else {
|
|
||||||
order.Price = group.Score
|
|
||||||
}
|
|
||||||
|
|
||||||
// 检查此订单是否可用积分支付
|
|
||||||
if order.Price == 0 {
|
|
||||||
return nil, ErrUnsupportedPaymentMethod
|
|
||||||
}
|
|
||||||
|
|
||||||
// 创建订单记录
|
|
||||||
order.Status = model.OrderPaid
|
|
||||||
if _, err := order.Create(); err != nil {
|
|
||||||
return nil, ErrInsertOrder.WithError(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
return &OrderCreateRes{
|
|
||||||
Payment: false,
|
|
||||||
}, nil
|
|
||||||
}
|
|
||||||
|
|
@ -1,211 +0,0 @@
|
||||||
package qq
|
|
||||||
|
|
||||||
import (
|
|
||||||
"crypto/md5"
|
|
||||||
"encoding/json"
|
|
||||||
"errors"
|
|
||||||
"fmt"
|
|
||||||
model "github.com/HFO4/cloudreve/models"
|
|
||||||
"github.com/HFO4/cloudreve/pkg/request"
|
|
||||||
"github.com/HFO4/cloudreve/pkg/serializer"
|
|
||||||
"github.com/gofrs/uuid"
|
|
||||||
"net/url"
|
|
||||||
"strings"
|
|
||||||
)
|
|
||||||
|
|
||||||
// LoginPage 登陆页面描述
|
|
||||||
type LoginPage struct {
|
|
||||||
URL string
|
|
||||||
SecretKey string
|
|
||||||
}
|
|
||||||
|
|
||||||
// UserCredentials 登陆成功后的凭证
|
|
||||||
type UserCredentials struct {
|
|
||||||
OpenID string
|
|
||||||
AccessToken string
|
|
||||||
}
|
|
||||||
|
|
||||||
// UserInfo 用户信息
|
|
||||||
type UserInfo struct {
|
|
||||||
Nick string
|
|
||||||
Avatar string
|
|
||||||
}
|
|
||||||
|
|
||||||
var (
|
|
||||||
// ErrNotEnabled 未开启登录功能
|
|
||||||
ErrNotEnabled = serializer.NewError(serializer.CodeNoPermissionErr, "QQ登录功能未开启", nil)
|
|
||||||
// ErrObtainAccessToken 无法获取AccessToken
|
|
||||||
ErrObtainAccessToken = serializer.NewError(serializer.CodeParamErr, "无法获取AccessToken", nil)
|
|
||||||
// ErrObtainOpenID 无法获取OpenID
|
|
||||||
ErrObtainOpenID = serializer.NewError(serializer.CodeParamErr, "无法获取OpenID", nil)
|
|
||||||
//ErrDecodeResponse 无法解析服务端响应
|
|
||||||
ErrDecodeResponse = serializer.NewError(serializer.CodeInternalSetting, "无法解析服务端响应", nil)
|
|
||||||
)
|
|
||||||
|
|
||||||
// NewLoginRequest 新建登录会话
|
|
||||||
func NewLoginRequest() (*LoginPage, error) {
|
|
||||||
// 获取相关设定
|
|
||||||
options := model.GetSettingByNames("qq_login", "qq_login_id")
|
|
||||||
if options["qq_login"] == "0" {
|
|
||||||
return nil, ErrNotEnabled
|
|
||||||
}
|
|
||||||
|
|
||||||
// 生成唯一ID
|
|
||||||
u2, err := uuid.NewV4()
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
secret := fmt.Sprintf("%x", md5.Sum(u2.Bytes()))
|
|
||||||
|
|
||||||
// 生成登录地址
|
|
||||||
loginURL, _ := url.Parse("https://graph.qq.com/oauth2.0/authorize?response_type=code")
|
|
||||||
queries := loginURL.Query()
|
|
||||||
queries.Add("client_id", options["qq_login_id"])
|
|
||||||
queries.Add("redirect_uri", getCallbackURL())
|
|
||||||
queries.Add("state", secret)
|
|
||||||
loginURL.RawQuery = queries.Encode()
|
|
||||||
|
|
||||||
return &LoginPage{
|
|
||||||
URL: loginURL.String(),
|
|
||||||
SecretKey: secret,
|
|
||||||
}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func getCallbackURL() string {
|
|
||||||
//return "https://drive.aoaoao.me/Callback/QQ"
|
|
||||||
// 生成回调地址
|
|
||||||
gateway, _ := url.Parse("/#/login/qq")
|
|
||||||
callback := model.GetSiteURL().ResolveReference(gateway).String()
|
|
||||||
|
|
||||||
return callback
|
|
||||||
}
|
|
||||||
|
|
||||||
func getAccessTokenURL(code string) string {
|
|
||||||
// 获取相关设定
|
|
||||||
options := model.GetSettingByNames("qq_login_id", "qq_login_key")
|
|
||||||
|
|
||||||
api, _ := url.Parse("https://graph.qq.com/oauth2.0/token?grant_type=authorization_code")
|
|
||||||
queries := api.Query()
|
|
||||||
queries.Add("client_id", options["qq_login_id"])
|
|
||||||
queries.Add("redirect_uri", getCallbackURL())
|
|
||||||
queries.Add("client_secret", options["qq_login_key"])
|
|
||||||
queries.Add("code", code)
|
|
||||||
api.RawQuery = queries.Encode()
|
|
||||||
|
|
||||||
return api.String()
|
|
||||||
}
|
|
||||||
|
|
||||||
func getUserInfoURL(openid, ak string) string {
|
|
||||||
// 获取相关设定
|
|
||||||
options := model.GetSettingByNames("qq_login_id", "qq_login_key")
|
|
||||||
|
|
||||||
api, _ := url.Parse("https://graph.qq.com/user/get_user_info")
|
|
||||||
queries := api.Query()
|
|
||||||
queries.Add("oauth_consumer_key", options["qq_login_id"])
|
|
||||||
queries.Add("openid", openid)
|
|
||||||
queries.Add("access_token", ak)
|
|
||||||
api.RawQuery = queries.Encode()
|
|
||||||
|
|
||||||
return api.String()
|
|
||||||
}
|
|
||||||
|
|
||||||
func getResponse(body string) (map[string]interface{}, error) {
|
|
||||||
var res map[string]interface{}
|
|
||||||
|
|
||||||
if !strings.Contains(body, "callback") {
|
|
||||||
return res, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
body = strings.TrimPrefix(body, "callback(")
|
|
||||||
body = strings.TrimSuffix(body, ");\n")
|
|
||||||
|
|
||||||
err := json.Unmarshal([]byte(body), &res)
|
|
||||||
|
|
||||||
return res, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Callback 处理回调,返回openid和access key
|
|
||||||
func Callback(code string) (*UserCredentials, error) {
|
|
||||||
// 获取相关设定
|
|
||||||
options := model.GetSettingByNames("qq_login")
|
|
||||||
if options["qq_login"] == "0" {
|
|
||||||
return nil, ErrNotEnabled
|
|
||||||
}
|
|
||||||
|
|
||||||
api := getAccessTokenURL(code)
|
|
||||||
|
|
||||||
// 获取AccessToken
|
|
||||||
client := request.HTTPClient{}
|
|
||||||
res := client.Request("GET", api, nil)
|
|
||||||
resp, err := res.GetResponse()
|
|
||||||
if err != nil {
|
|
||||||
return nil, ErrObtainAccessToken.WithError(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// 如果服务端返回错误
|
|
||||||
errResp, err := getResponse(resp)
|
|
||||||
if msg, ok := errResp["error_description"]; err == nil && ok {
|
|
||||||
return nil, ErrObtainAccessToken.WithError(errors.New(msg.(string)))
|
|
||||||
}
|
|
||||||
|
|
||||||
// 获取AccessToken
|
|
||||||
vals, err := url.ParseQuery(resp)
|
|
||||||
if err != nil {
|
|
||||||
return nil, ErrDecodeResponse.WithError(err)
|
|
||||||
}
|
|
||||||
accessToken := vals.Get("access_token")
|
|
||||||
|
|
||||||
// 用 AccessToken 换取OpenID
|
|
||||||
res = client.Request("GET", "https://graph.qq.com/oauth2.0/me?access_token="+accessToken, nil)
|
|
||||||
resp, err = res.GetResponse()
|
|
||||||
if err != nil {
|
|
||||||
return nil, ErrObtainOpenID.WithError(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// 解析服务端响应
|
|
||||||
errResp, err = getResponse(resp)
|
|
||||||
if msg, ok := errResp["error_description"]; err == nil && ok {
|
|
||||||
return nil, ErrObtainOpenID.WithError(errors.New(msg.(string)))
|
|
||||||
}
|
|
||||||
|
|
||||||
if openid, ok := errResp["openid"]; ok {
|
|
||||||
return &UserCredentials{
|
|
||||||
OpenID: openid.(string),
|
|
||||||
AccessToken: accessToken,
|
|
||||||
}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil, ErrDecodeResponse
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetUserInfo 使用凭证获取用户信息
|
|
||||||
func GetUserInfo(credential *UserCredentials) (*UserInfo, error) {
|
|
||||||
api := getUserInfoURL(credential.OpenID, credential.AccessToken)
|
|
||||||
|
|
||||||
// 获取用户信息
|
|
||||||
client := request.HTTPClient{}
|
|
||||||
res := client.Request("GET", api, nil)
|
|
||||||
resp, err := res.GetResponse()
|
|
||||||
if err != nil {
|
|
||||||
return nil, ErrObtainAccessToken.WithError(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
var resSerialized map[string]interface{}
|
|
||||||
if err := json.Unmarshal([]byte(resp), &resSerialized); err != nil {
|
|
||||||
return nil, ErrDecodeResponse.WithError(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// 如果服务端返回错误
|
|
||||||
if msg, ok := resSerialized["msg"]; ok && msg.(string) != "" {
|
|
||||||
return nil, ErrObtainAccessToken.WithError(errors.New(msg.(string)))
|
|
||||||
}
|
|
||||||
|
|
||||||
if avatar, ok := resSerialized["figureurl_qq_2"]; ok {
|
|
||||||
return &UserInfo{
|
|
||||||
Nick: resSerialized["nickname"].(string),
|
|
||||||
Avatar: avatar.(string),
|
|
||||||
}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil, ErrDecodeResponse
|
|
||||||
}
|
|
||||||
|
|
@ -9,7 +9,6 @@ type SiteConfig struct {
|
||||||
RegCaptcha bool `json:"regCaptcha"`
|
RegCaptcha bool `json:"regCaptcha"`
|
||||||
ForgetCaptcha bool `json:"forgetCaptcha"`
|
ForgetCaptcha bool `json:"forgetCaptcha"`
|
||||||
EmailActive bool `json:"emailActive"`
|
EmailActive bool `json:"emailActive"`
|
||||||
QQLogin bool `json:"QQLogin"`
|
|
||||||
Themes string `json:"themes"`
|
Themes string `json:"themes"`
|
||||||
DefaultTheme string `json:"defaultTheme"`
|
DefaultTheme string `json:"defaultTheme"`
|
||||||
HomepageViewMethod string `json:"home_view_method"`
|
HomepageViewMethod string `json:"home_view_method"`
|
||||||
|
|
@ -67,7 +66,6 @@ func BuildSiteConfig(settings map[string]string, user *model.User) Response {
|
||||||
RegCaptcha: model.IsTrueVal(checkSettingValue(settings, "reg_captcha")),
|
RegCaptcha: model.IsTrueVal(checkSettingValue(settings, "reg_captcha")),
|
||||||
ForgetCaptcha: model.IsTrueVal(checkSettingValue(settings, "forget_captcha")),
|
ForgetCaptcha: model.IsTrueVal(checkSettingValue(settings, "forget_captcha")),
|
||||||
EmailActive: model.IsTrueVal(checkSettingValue(settings, "email_active")),
|
EmailActive: model.IsTrueVal(checkSettingValue(settings, "email_active")),
|
||||||
QQLogin: model.IsTrueVal(checkSettingValue(settings, "qq_login")),
|
|
||||||
Themes: checkSettingValue(settings, "themes"),
|
Themes: checkSettingValue(settings, "themes"),
|
||||||
DefaultTheme: checkSettingValue(settings, "defaultTheme"),
|
DefaultTheme: checkSettingValue(settings, "defaultTheme"),
|
||||||
HomepageViewMethod: checkSettingValue(settings, "home_view_method"),
|
HomepageViewMethod: checkSettingValue(settings, "home_view_method"),
|
||||||
|
|
|
||||||
|
|
@ -44,7 +44,6 @@ type group struct {
|
||||||
AllowShare bool `json:"allowShare"`
|
AllowShare bool `json:"allowShare"`
|
||||||
AllowRemoteDownload bool `json:"allowRemoteDownload"`
|
AllowRemoteDownload bool `json:"allowRemoteDownload"`
|
||||||
AllowArchiveDownload bool `json:"allowArchiveDownload"`
|
AllowArchiveDownload bool `json:"allowArchiveDownload"`
|
||||||
ShareFreeEnabled bool `json:"shareFree"`
|
|
||||||
ShareDownload bool `json:"shareDownload"`
|
ShareDownload bool `json:"shareDownload"`
|
||||||
CompressEnabled bool `json:"compress"`
|
CompressEnabled bool `json:"compress"`
|
||||||
WebDAVEnabled bool `json:"webdav"`
|
WebDAVEnabled bool `json:"webdav"`
|
||||||
|
|
@ -127,7 +126,7 @@ func BuildUserResponse(user model.User) Response {
|
||||||
|
|
||||||
// BuildUserStorageResponse 序列化用户存储概况响应
|
// BuildUserStorageResponse 序列化用户存储概况响应
|
||||||
func BuildUserStorageResponse(user model.User) Response {
|
func BuildUserStorageResponse(user model.User) Response {
|
||||||
total := user.Group.MaxStorage + user.GetAvailablePackSize()
|
total := user.Group.MaxStorage
|
||||||
storageResp := storage{
|
storageResp := storage{
|
||||||
Used: user.Storage,
|
Used: user.Storage,
|
||||||
Free: total - user.Storage,
|
Free: total - user.Storage,
|
||||||
|
|
|
||||||
|
|
@ -1,120 +0,0 @@
|
||||||
package serializer
|
|
||||||
|
|
||||||
import (
|
|
||||||
model "github.com/HFO4/cloudreve/models"
|
|
||||||
"github.com/HFO4/cloudreve/pkg/hashid"
|
|
||||||
"github.com/HFO4/cloudreve/pkg/util"
|
|
||||||
)
|
|
||||||
|
|
||||||
type quota struct {
|
|
||||||
Base uint64 `json:"base"`
|
|
||||||
Pack uint64 `json:"pack"`
|
|
||||||
Used uint64 `json:"used"`
|
|
||||||
Total uint64 `json:"total"`
|
|
||||||
Packs []storagePacks `json:"packs"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type storagePacks struct {
|
|
||||||
Name string `json:"name"`
|
|
||||||
Size uint64 `json:"size"`
|
|
||||||
ActivateDate string `json:"activate_date"`
|
|
||||||
Expiration int `json:"expiration"`
|
|
||||||
ExpirationDate string `json:"expiration_date"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// MountedFolders 已挂载的目录
|
|
||||||
type MountedFolders struct {
|
|
||||||
ID string `json:"id"`
|
|
||||||
Name string `json:"name"`
|
|
||||||
PolicyName string `json:"policy_name"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type policyOptions struct {
|
|
||||||
Name string `json:"name"`
|
|
||||||
ID string `json:"id"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// BuildPolicySettingRes 构建存储策略选项选择
|
|
||||||
func BuildPolicySettingRes(policies []model.Policy, current *model.Policy) Response {
|
|
||||||
options := make([]policyOptions, 0, len(policies))
|
|
||||||
for _, policy := range policies {
|
|
||||||
options = append(options, policyOptions{
|
|
||||||
Name: policy.Name,
|
|
||||||
ID: hashid.HashID(policy.ID, hashid.PolicyID),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
return Response{
|
|
||||||
Data: map[string]interface{}{
|
|
||||||
"options": options,
|
|
||||||
"current": policyOptions{
|
|
||||||
Name: current.Name,
|
|
||||||
ID: hashid.HashID(current.ID, hashid.PolicyID),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// BuildUserQuotaResponse 序列化用户存储配额概况响应
|
|
||||||
func BuildUserQuotaResponse(user *model.User, packs []model.StoragePack) Response {
|
|
||||||
packSize := user.GetAvailablePackSize()
|
|
||||||
res := quota{
|
|
||||||
Base: user.Group.MaxStorage,
|
|
||||||
Pack: packSize,
|
|
||||||
Used: user.Storage,
|
|
||||||
Total: packSize + user.Group.MaxStorage,
|
|
||||||
Packs: make([]storagePacks, 0, len(packs)),
|
|
||||||
}
|
|
||||||
for _, pack := range packs {
|
|
||||||
res.Packs = append(res.Packs, storagePacks{
|
|
||||||
Name: pack.Name,
|
|
||||||
Size: pack.Size,
|
|
||||||
ActivateDate: pack.ActiveTime.Format("2006-01-02 15:04:05"),
|
|
||||||
Expiration: int(pack.ExpiredTime.Sub(*pack.ActiveTime).Seconds()),
|
|
||||||
ExpirationDate: pack.ExpiredTime.Format("2006-01-02 15:04:05"),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
return Response{
|
|
||||||
Data: res,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// PackProduct 容量包商品
|
|
||||||
type PackProduct struct {
|
|
||||||
ID int64 `json:"id"`
|
|
||||||
Name string `json:"name"`
|
|
||||||
Size uint64 `json:"size"`
|
|
||||||
Time int64 `json:"time"`
|
|
||||||
Price int `json:"price"`
|
|
||||||
Score int `json:"score"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// GroupProducts 用户组商品
|
|
||||||
type GroupProducts struct {
|
|
||||||
ID int64 `json:"id"`
|
|
||||||
Name string `json:"name"`
|
|
||||||
GroupID uint `json:"group_id"`
|
|
||||||
Time int64 `json:"time"`
|
|
||||||
Price int `json:"price"`
|
|
||||||
Score int `json:"score"`
|
|
||||||
Des []string `json:"des"`
|
|
||||||
Highlight bool `json:"highlight"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// BuildProductResponse 构建增值服务商品响应
|
|
||||||
func BuildProductResponse(groups []GroupProducts, packs []PackProduct, alipay, payjs bool, scorePrice int) Response {
|
|
||||||
// 隐藏响应中的用户组ID
|
|
||||||
for i := 0; i < len(groups); i++ {
|
|
||||||
groups[i].GroupID = 0
|
|
||||||
}
|
|
||||||
return Response{
|
|
||||||
Data: map[string]interface{}{
|
|
||||||
"packs": packs,
|
|
||||||
"groups": groups,
|
|
||||||
"alipay": alipay,
|
|
||||||
"payjs": payjs,
|
|
||||||
"score_price": scorePrice,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -87,39 +87,6 @@ func AdminSendTestMail(c *gin.Context) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// AdminListRedeems 列出激活码
|
|
||||||
func AdminListRedeems(c *gin.Context) {
|
|
||||||
var service admin.AdminListService
|
|
||||||
if err := c.ShouldBindJSON(&service); err == nil {
|
|
||||||
res := service.Redeems()
|
|
||||||
c.JSON(200, res)
|
|
||||||
} else {
|
|
||||||
c.JSON(200, ErrorResponse(err))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// AdminGenerateRedeems 生成激活码
|
|
||||||
func AdminGenerateRedeems(c *gin.Context) {
|
|
||||||
var service admin.GenerateRedeemsService
|
|
||||||
if err := c.ShouldBindJSON(&service); err == nil {
|
|
||||||
res := service.Generate()
|
|
||||||
c.JSON(200, res)
|
|
||||||
} else {
|
|
||||||
c.JSON(200, ErrorResponse(err))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// AdminDeleteRedeem 删除激活码
|
|
||||||
func AdminDeleteRedeem(c *gin.Context) {
|
|
||||||
var service admin.SingleIDService
|
|
||||||
if err := c.ShouldBindUri(&service); err == nil {
|
|
||||||
res := service.DeleteRedeem()
|
|
||||||
c.JSON(200, res)
|
|
||||||
} else {
|
|
||||||
c.JSON(200, ErrorResponse(err))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// AdminTestAria2 测试aria2连接
|
// AdminTestAria2 测试aria2连接
|
||||||
func AdminTestAria2(c *gin.Context) {
|
func AdminTestAria2(c *gin.Context) {
|
||||||
var service admin.Aria2TestService
|
var service admin.Aria2TestService
|
||||||
|
|
@ -392,28 +359,6 @@ func AdminDeleteShare(c *gin.Context) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// AdminListOrder 列出订单
|
|
||||||
func AdminListOrder(c *gin.Context) {
|
|
||||||
var service admin.AdminListService
|
|
||||||
if err := c.ShouldBindJSON(&service); err == nil {
|
|
||||||
res := service.Orders()
|
|
||||||
c.JSON(200, res)
|
|
||||||
} else {
|
|
||||||
c.JSON(200, ErrorResponse(err))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// AdminDeleteOrder 批量删除订单
|
|
||||||
func AdminDeleteOrder(c *gin.Context) {
|
|
||||||
var service admin.OrderBatchService
|
|
||||||
if err := c.ShouldBindJSON(&service); err == nil {
|
|
||||||
res := service.Delete(c)
|
|
||||||
c.JSON(200, res)
|
|
||||||
} else {
|
|
||||||
c.JSON(200, ErrorResponse(err))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// AdminListDownload 列出离线下载任务
|
// AdminListDownload 列出离线下载任务
|
||||||
func AdminListDownload(c *gin.Context) {
|
func AdminListDownload(c *gin.Context) {
|
||||||
var service admin.AdminListService
|
var service admin.AdminListService
|
||||||
|
|
|
||||||
|
|
@ -172,17 +172,6 @@ func GetShareDocPreview(c *gin.Context) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// SaveShare 转存他人分享
|
|
||||||
func SaveShare(c *gin.Context) {
|
|
||||||
var service share.Service
|
|
||||||
if err := c.ShouldBindJSON(&service); err == nil {
|
|
||||||
res := service.SaveToMyFile(c)
|
|
||||||
c.JSON(200, res)
|
|
||||||
} else {
|
|
||||||
c.JSON(200, ErrorResponse(err))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// ListSharedFolder 列出分享的目录下的对象
|
// ListSharedFolder 列出分享的目录下的对象
|
||||||
func ListSharedFolder(c *gin.Context) {
|
func ListSharedFolder(c *gin.Context) {
|
||||||
var service share.Service
|
var service share.Service
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,6 @@ func SiteConfig(c *gin.Context) {
|
||||||
siteConfig := model.GetSettingByNames(
|
siteConfig := model.GetSettingByNames(
|
||||||
"siteName",
|
"siteName",
|
||||||
"login_captcha",
|
"login_captcha",
|
||||||
"qq_login",
|
|
||||||
"reg_captcha",
|
"reg_captcha",
|
||||||
"email_active",
|
"email_active",
|
||||||
"forget_captcha",
|
"forget_captcha",
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,6 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
model "github.com/HFO4/cloudreve/models"
|
model "github.com/HFO4/cloudreve/models"
|
||||||
"github.com/HFO4/cloudreve/pkg/authn"
|
"github.com/HFO4/cloudreve/pkg/authn"
|
||||||
"github.com/HFO4/cloudreve/pkg/qq"
|
|
||||||
"github.com/HFO4/cloudreve/pkg/request"
|
"github.com/HFO4/cloudreve/pkg/request"
|
||||||
"github.com/HFO4/cloudreve/pkg/serializer"
|
"github.com/HFO4/cloudreve/pkg/serializer"
|
||||||
"github.com/HFO4/cloudreve/pkg/thumb"
|
"github.com/HFO4/cloudreve/pkg/thumb"
|
||||||
|
|
@ -213,24 +212,6 @@ func UserActivate(c *gin.Context) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// UserQQLogin 初始化QQ登录
|
|
||||||
func UserQQLogin(c *gin.Context) {
|
|
||||||
// 新建绑定
|
|
||||||
res, err := qq.NewLoginRequest()
|
|
||||||
if err != nil {
|
|
||||||
c.JSON(200, serializer.Err(serializer.CodeNotSet, "无法使用QQ登录", err))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// 设定QQ登录会话Secret
|
|
||||||
util.SetSession(c, map[string]interface{}{"qq_login_secret": res.SecretKey})
|
|
||||||
|
|
||||||
c.JSON(200, serializer.Response{
|
|
||||||
Data: res.URL,
|
|
||||||
})
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
// UserSignOut 用户退出登录
|
// UserSignOut 用户退出登录
|
||||||
func UserSignOut(c *gin.Context) {
|
func UserSignOut(c *gin.Context) {
|
||||||
util.DeleteSession(c, "user_id")
|
util.DeleteSession(c, "user_id")
|
||||||
|
|
@ -251,17 +232,6 @@ func UserStorage(c *gin.Context) {
|
||||||
c.JSON(200, res)
|
c.JSON(200, res)
|
||||||
}
|
}
|
||||||
|
|
||||||
// UserAvailablePolicies 用户存储策略设置
|
|
||||||
func UserAvailablePolicies(c *gin.Context) {
|
|
||||||
var service user.SettingService
|
|
||||||
if err := c.ShouldBindUri(&service); err == nil {
|
|
||||||
res := service.Policy(c, CurrentUser(c))
|
|
||||||
c.JSON(200, res)
|
|
||||||
} else {
|
|
||||||
c.JSON(200, ErrorResponse(err))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// UserTasks 获取任务队列
|
// UserTasks 获取任务队列
|
||||||
func UserTasks(c *gin.Context) {
|
func UserTasks(c *gin.Context) {
|
||||||
var service user.SettingListService
|
var service user.SettingListService
|
||||||
|
|
@ -368,12 +338,6 @@ func UpdateOption(c *gin.Context) {
|
||||||
switch service.Option {
|
switch service.Option {
|
||||||
case "nick":
|
case "nick":
|
||||||
subService = &user.ChangerNick{}
|
subService = &user.ChangerNick{}
|
||||||
case "vip":
|
|
||||||
subService = &user.VIPUnsubscribe{}
|
|
||||||
case "qq":
|
|
||||||
subService = &user.QQBind{}
|
|
||||||
case "policy":
|
|
||||||
subService = &user.PolicyChange{}
|
|
||||||
case "homepage":
|
case "homepage":
|
||||||
subService = &user.HomePage{}
|
subService = &user.HomePage{}
|
||||||
case "password":
|
case "password":
|
||||||
|
|
|
||||||
|
|
@ -1,144 +0,0 @@
|
||||||
package controllers
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/HFO4/cloudreve/pkg/payment"
|
|
||||||
"github.com/HFO4/cloudreve/pkg/util"
|
|
||||||
"github.com/HFO4/cloudreve/service/vas"
|
|
||||||
"github.com/gin-gonic/gin"
|
|
||||||
"github.com/qingwg/payjs/notify"
|
|
||||||
"github.com/smartwalle/alipay/v3"
|
|
||||||
)
|
|
||||||
|
|
||||||
// GetQuota 获取容量配额信息
|
|
||||||
func GetQuota(c *gin.Context) {
|
|
||||||
var service vas.GeneralVASService
|
|
||||||
if err := c.ShouldBindUri(&service); err == nil {
|
|
||||||
res := service.Quota(c, CurrentUser(c))
|
|
||||||
c.JSON(200, res)
|
|
||||||
} else {
|
|
||||||
c.JSON(200, ErrorResponse(err))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetProduct 获取商品信息
|
|
||||||
func GetProduct(c *gin.Context) {
|
|
||||||
var service vas.GeneralVASService
|
|
||||||
if err := c.ShouldBindUri(&service); err == nil {
|
|
||||||
res := service.Products(c, CurrentUser(c))
|
|
||||||
c.JSON(200, res)
|
|
||||||
} else {
|
|
||||||
c.JSON(200, ErrorResponse(err))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewOrder 新建支付订单
|
|
||||||
func NewOrder(c *gin.Context) {
|
|
||||||
var service vas.CreateOrderService
|
|
||||||
if err := c.ShouldBindJSON(&service); err == nil {
|
|
||||||
res := service.Create(c, CurrentUser(c))
|
|
||||||
c.JSON(200, res)
|
|
||||||
} else {
|
|
||||||
c.JSON(200, ErrorResponse(err))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// OrderStatus 查询订单状态
|
|
||||||
func OrderStatus(c *gin.Context) {
|
|
||||||
var service vas.OrderService
|
|
||||||
if err := c.ShouldBindUri(&service); err == nil {
|
|
||||||
res := service.Status(c, CurrentUser(c))
|
|
||||||
c.JSON(200, res)
|
|
||||||
} else {
|
|
||||||
c.JSON(200, ErrorResponse(err))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetRedeemInfo 获取兑换码信息
|
|
||||||
func GetRedeemInfo(c *gin.Context) {
|
|
||||||
var service vas.RedeemService
|
|
||||||
if err := c.ShouldBindUri(&service); err == nil {
|
|
||||||
res := service.Query(c)
|
|
||||||
c.JSON(200, res)
|
|
||||||
} else {
|
|
||||||
c.JSON(200, ErrorResponse(err))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// DoRedeem 获取兑换码信息
|
|
||||||
func DoRedeem(c *gin.Context) {
|
|
||||||
var service vas.RedeemService
|
|
||||||
if err := c.ShouldBindUri(&service); err == nil {
|
|
||||||
res := service.Redeem(c, CurrentUser(c))
|
|
||||||
c.JSON(200, res)
|
|
||||||
} else {
|
|
||||||
c.JSON(200, ErrorResponse(err))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// AlipayCallback 支付宝回调
|
|
||||||
func AlipayCallback(c *gin.Context) {
|
|
||||||
pay, err := payment.NewPaymentInstance("alipay")
|
|
||||||
if err != nil {
|
|
||||||
util.Log().Debug("[支付宝回调] 无法创建支付宝客户端, %s", err)
|
|
||||||
c.Status(400)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
res, err := pay.(*payment.Alipay).Client.GetTradeNotification(c.Request)
|
|
||||||
if err != nil {
|
|
||||||
util.Log().Debug("[支付宝回调] 回调验证失败, %s", err)
|
|
||||||
c.Status(403)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if res != nil && res.TradeStatus == "TRADE_SUCCESS" {
|
|
||||||
// 支付成功
|
|
||||||
if err := payment.OrderPaid(res.OutTradeNo); err != nil {
|
|
||||||
util.Log().Debug("[支付宝回调] 支付处理失败, %s", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 确认收到通知消息
|
|
||||||
alipay.AckNotification(c.Writer)
|
|
||||||
}
|
|
||||||
|
|
||||||
// PayJSCallback PayJS回调
|
|
||||||
func PayJSCallback(c *gin.Context) {
|
|
||||||
pay, err := payment.NewPaymentInstance("payjs")
|
|
||||||
if err != nil {
|
|
||||||
util.Log().Debug("[PayJS回调] 无法创建支付宝客户端, %s", err)
|
|
||||||
c.Status(400)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
payNotify := pay.(*payment.PayJSClient).Client.GetNotify(c.Request, c.Writer)
|
|
||||||
|
|
||||||
//设置接收消息的处理方法
|
|
||||||
payNotify.SetMessageHandler(func(msg notify.Message) {
|
|
||||||
if err := payment.OrderPaid(msg.OutTradeNo); err != nil {
|
|
||||||
util.Log().Debug("[PayJS回调] 支付处理失败, %s", err)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
//处理消息接收以及回复
|
|
||||||
err = payNotify.Serve()
|
|
||||||
if err != nil {
|
|
||||||
util.Log().Debug("[PayJS回调] 回调处理失败, %s", err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
//发送回复的消息
|
|
||||||
payNotify.SendResponseMsg()
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
// QQCallback QQ互联回调
|
|
||||||
func QQCallback(c *gin.Context) {
|
|
||||||
var service vas.QQCallbackService
|
|
||||||
if err := c.ShouldBindJSON(&service); err == nil {
|
|
||||||
res := service.Callback(c, CurrentUser(c))
|
|
||||||
c.JSON(200, res)
|
|
||||||
} else {
|
|
||||||
c.JSON(200, ErrorResponse(err))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -64,17 +64,6 @@ func DeleteWebDAVAccounts(c *gin.Context) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// DeleteWebDAVMounts 删除WebDAV挂载
|
|
||||||
func DeleteWebDAVMounts(c *gin.Context) {
|
|
||||||
var service setting.WebDAVListService
|
|
||||||
if err := c.ShouldBindUri(&service); err == nil {
|
|
||||||
res := service.Unmount(c, CurrentUser(c))
|
|
||||||
c.JSON(200, res)
|
|
||||||
} else {
|
|
||||||
c.JSON(200, ErrorResponse(err))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// CreateWebDAVAccounts 创建WebDAV账户
|
// CreateWebDAVAccounts 创建WebDAV账户
|
||||||
func CreateWebDAVAccounts(c *gin.Context) {
|
func CreateWebDAVAccounts(c *gin.Context) {
|
||||||
var service setting.WebDAVAccountCreateService
|
var service setting.WebDAVAccountCreateService
|
||||||
|
|
@ -85,14 +74,3 @@ func CreateWebDAVAccounts(c *gin.Context) {
|
||||||
c.JSON(200, ErrorResponse(err))
|
c.JSON(200, ErrorResponse(err))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// CreateWebDAVMounts 创建WebDAV目录挂载
|
|
||||||
func CreateWebDAVMounts(c *gin.Context) {
|
|
||||||
var service setting.WebDAVMountCreateService
|
|
||||||
if err := c.ShouldBindJSON(&service); err == nil {
|
|
||||||
res := service.Create(c, CurrentUser(c))
|
|
||||||
c.JSON(200, res)
|
|
||||||
} else {
|
|
||||||
c.JSON(200, ErrorResponse(err))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -132,8 +132,6 @@ func InitMasterRouter() *gin.Engine {
|
||||||
middleware.HashID(hashid.UserID),
|
middleware.HashID(hashid.UserID),
|
||||||
controllers.UserActivate,
|
controllers.UserActivate,
|
||||||
)
|
)
|
||||||
// 初始化QQ登录
|
|
||||||
user.POST("qq", controllers.UserQQLogin)
|
|
||||||
// WebAuthn登陆初始化
|
// WebAuthn登陆初始化
|
||||||
user.GET("authn/:username",
|
user.GET("authn/:username",
|
||||||
middleware.IsFunctionEnabled("authn_enabled"),
|
middleware.IsFunctionEnabled("authn_enabled"),
|
||||||
|
|
@ -174,21 +172,6 @@ func InitMasterRouter() *gin.Engine {
|
||||||
// 回调接口
|
// 回调接口
|
||||||
callback := v3.Group("callback")
|
callback := v3.Group("callback")
|
||||||
{
|
{
|
||||||
// QQ互联回调
|
|
||||||
callback.POST(
|
|
||||||
"qq",
|
|
||||||
controllers.QQCallback,
|
|
||||||
)
|
|
||||||
// PAYJS回调
|
|
||||||
callback.POST(
|
|
||||||
"payjs",
|
|
||||||
controllers.PayJSCallback,
|
|
||||||
)
|
|
||||||
// 支付宝回调
|
|
||||||
callback.POST(
|
|
||||||
"alipay",
|
|
||||||
controllers.AlipayCallback,
|
|
||||||
)
|
|
||||||
// 远程策略上传回调
|
// 远程策略上传回调
|
||||||
callback.POST(
|
callback.POST(
|
||||||
"remote/:key",
|
"remote/:key",
|
||||||
|
|
@ -312,17 +295,6 @@ func InitMasterRouter() *gin.Engine {
|
||||||
// 重新加载子服务
|
// 重新加载子服务
|
||||||
admin.POST("mailTest", controllers.AdminSendTestMail)
|
admin.POST("mailTest", controllers.AdminSendTestMail)
|
||||||
|
|
||||||
// 兑换码相关
|
|
||||||
redeem := admin.Group("redeem")
|
|
||||||
{
|
|
||||||
// 列出激活码
|
|
||||||
redeem.POST("list", controllers.AdminListRedeems)
|
|
||||||
// 生成激活码
|
|
||||||
redeem.POST("", controllers.AdminGenerateRedeems)
|
|
||||||
// 删除激活码
|
|
||||||
redeem.DELETE(":id", controllers.AdminDeleteRedeem)
|
|
||||||
}
|
|
||||||
|
|
||||||
// 离线下载相关
|
// 离线下载相关
|
||||||
aria2 := admin.Group("aria2")
|
aria2 := admin.Group("aria2")
|
||||||
{
|
{
|
||||||
|
|
@ -398,14 +370,6 @@ func InitMasterRouter() *gin.Engine {
|
||||||
share.POST("delete", controllers.AdminDeleteShare)
|
share.POST("delete", controllers.AdminDeleteShare)
|
||||||
}
|
}
|
||||||
|
|
||||||
order := admin.Group("order")
|
|
||||||
{
|
|
||||||
// 列出订单
|
|
||||||
order.POST("list", controllers.AdminListOrder)
|
|
||||||
// 删除
|
|
||||||
order.POST("delete", controllers.AdminDeleteOrder)
|
|
||||||
}
|
|
||||||
|
|
||||||
download := admin.Group("download")
|
download := admin.Group("download")
|
||||||
{
|
{
|
||||||
// 列出任务
|
// 列出任务
|
||||||
|
|
@ -445,8 +409,6 @@ func InitMasterRouter() *gin.Engine {
|
||||||
// 用户设置
|
// 用户设置
|
||||||
setting := user.Group("setting")
|
setting := user.Group("setting")
|
||||||
{
|
{
|
||||||
// 获取用户可选存储策略
|
|
||||||
setting.GET("policies", controllers.UserAvailablePolicies)
|
|
||||||
// 任务队列
|
// 任务队列
|
||||||
setting.GET("tasks", controllers.UserTasks)
|
setting.GET("tasks", controllers.UserTasks)
|
||||||
// 获取当前用户设定
|
// 获取当前用户设定
|
||||||
|
|
@ -541,13 +503,6 @@ func InitMasterRouter() *gin.Engine {
|
||||||
share.GET("", controllers.ListShare)
|
share.GET("", controllers.ListShare)
|
||||||
// 搜索公共分享
|
// 搜索公共分享
|
||||||
share.GET("search", controllers.SearchShare)
|
share.GET("search", controllers.SearchShare)
|
||||||
// 转存他人分享
|
|
||||||
share.POST("save/:id",
|
|
||||||
middleware.ShareAvailable(),
|
|
||||||
middleware.CheckShareUnlocked(),
|
|
||||||
middleware.BeforeShareDownload(),
|
|
||||||
controllers.SaveShare,
|
|
||||||
)
|
|
||||||
// 更新分享属性
|
// 更新分享属性
|
||||||
share.PATCH(":id",
|
share.PATCH(":id",
|
||||||
middleware.ShareAvailable(),
|
middleware.ShareAvailable(),
|
||||||
|
|
@ -571,23 +526,6 @@ func InitMasterRouter() *gin.Engine {
|
||||||
tag.DELETE(":id", middleware.HashID(hashid.TagID), controllers.DeleteTag)
|
tag.DELETE(":id", middleware.HashID(hashid.TagID), controllers.DeleteTag)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 增值服务相关
|
|
||||||
vas := auth.Group("vas")
|
|
||||||
{
|
|
||||||
// 获取容量包及配额信息
|
|
||||||
vas.GET("pack", controllers.GetQuota)
|
|
||||||
// 获取商品信息,同时返回支付信息
|
|
||||||
vas.GET("product", controllers.GetProduct)
|
|
||||||
// 新建支付订单
|
|
||||||
vas.POST("order", controllers.NewOrder)
|
|
||||||
// 查询订单状态
|
|
||||||
vas.GET("order/:id", controllers.OrderStatus)
|
|
||||||
// 获取兑换码信息
|
|
||||||
vas.GET("redeem/:code", controllers.GetRedeemInfo)
|
|
||||||
// 执行兑换
|
|
||||||
vas.POST("redeem/:code", controllers.DoRedeem)
|
|
||||||
}
|
|
||||||
|
|
||||||
// WebDAV管理相关
|
// WebDAV管理相关
|
||||||
webdav := auth.Group("webdav")
|
webdav := auth.Group("webdav")
|
||||||
{
|
{
|
||||||
|
|
@ -597,13 +535,6 @@ func InitMasterRouter() *gin.Engine {
|
||||||
webdav.POST("accounts", controllers.CreateWebDAVAccounts)
|
webdav.POST("accounts", controllers.CreateWebDAVAccounts)
|
||||||
// 删除账号
|
// 删除账号
|
||||||
webdav.DELETE("accounts/:id", controllers.DeleteWebDAVAccounts)
|
webdav.DELETE("accounts/:id", controllers.DeleteWebDAVAccounts)
|
||||||
// 删除目录挂载
|
|
||||||
webdav.DELETE("mount/:id",
|
|
||||||
middleware.HashID(hashid.FolderID),
|
|
||||||
controllers.DeleteWebDAVMounts,
|
|
||||||
)
|
|
||||||
// 创建目录挂载
|
|
||||||
webdav.POST("mount", controllers.CreateWebDAVMounts)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,75 +0,0 @@
|
||||||
package admin
|
|
||||||
|
|
||||||
import (
|
|
||||||
model "github.com/HFO4/cloudreve/models"
|
|
||||||
"github.com/HFO4/cloudreve/pkg/serializer"
|
|
||||||
"github.com/gin-gonic/gin"
|
|
||||||
"strings"
|
|
||||||
)
|
|
||||||
|
|
||||||
// OrderBatchService 订单批量操作服务
|
|
||||||
type OrderBatchService struct {
|
|
||||||
ID []uint `json:"id" binding:"min=1"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// Delete 删除订单
|
|
||||||
func (service *OrderBatchService) Delete(c *gin.Context) serializer.Response {
|
|
||||||
if err := model.DB.Where("id in (?)", service.ID).Delete(&model.Order{}).Error; err != nil {
|
|
||||||
return serializer.DBErr("无法删除订单", err)
|
|
||||||
}
|
|
||||||
return serializer.Response{}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Orders 列出订单
|
|
||||||
func (service *AdminListService) Orders() serializer.Response {
|
|
||||||
var res []model.Order
|
|
||||||
total := 0
|
|
||||||
|
|
||||||
tx := model.DB.Model(&model.Order{})
|
|
||||||
if service.OrderBy != "" {
|
|
||||||
tx = tx.Order(service.OrderBy)
|
|
||||||
}
|
|
||||||
|
|
||||||
for k, v := range service.Conditions {
|
|
||||||
tx = tx.Where(k+" = ?", v)
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(service.Searches) > 0 {
|
|
||||||
search := ""
|
|
||||||
for k, v := range service.Searches {
|
|
||||||
search += k + " like '%" + v + "%' OR "
|
|
||||||
}
|
|
||||||
search = strings.TrimSuffix(search, " OR ")
|
|
||||||
tx = tx.Where(search)
|
|
||||||
}
|
|
||||||
|
|
||||||
// 计算总数用于分页
|
|
||||||
tx.Count(&total)
|
|
||||||
|
|
||||||
// 查询记录
|
|
||||||
tx.Limit(service.PageSize).Offset((service.Page - 1) * service.PageSize).Find(&res)
|
|
||||||
|
|
||||||
// 查询对应用户,同时计算HashID
|
|
||||||
users := make(map[uint]model.User)
|
|
||||||
for _, file := range res {
|
|
||||||
users[file.UserID] = model.User{}
|
|
||||||
}
|
|
||||||
|
|
||||||
userIDs := make([]uint, 0, len(users))
|
|
||||||
for k := range users {
|
|
||||||
userIDs = append(userIDs, k)
|
|
||||||
}
|
|
||||||
|
|
||||||
var userList []model.User
|
|
||||||
model.DB.Where("id in (?)", userIDs).Find(&userList)
|
|
||||||
|
|
||||||
for _, v := range userList {
|
|
||||||
users[v.ID] = v
|
|
||||||
}
|
|
||||||
|
|
||||||
return serializer.Response{Data: map[string]interface{}{
|
|
||||||
"total": total,
|
|
||||||
"items": res,
|
|
||||||
"users": users,
|
|
||||||
}}
|
|
||||||
}
|
|
||||||
|
|
@ -71,10 +71,7 @@ func (service *PolicyService) Delete() serializer.Response {
|
||||||
// 检查用户组使用
|
// 检查用户组使用
|
||||||
var groups []model.Group
|
var groups []model.Group
|
||||||
model.DB.Model(&model.Group{}).Where(
|
model.DB.Model(&model.Group{}).Where(
|
||||||
"policies like ? OR policies like ? OR policies like ? OR policies like ?",
|
"policies like ?",
|
||||||
fmt.Sprintf("[%d,%%", service.ID),
|
|
||||||
fmt.Sprintf("%%,%d]", service.ID),
|
|
||||||
fmt.Sprintf("%%,%d,%%", service.ID),
|
|
||||||
fmt.Sprintf("%%[%d]%%", service.ID),
|
fmt.Sprintf("%%[%d]%%", service.ID),
|
||||||
).Find(&groups)
|
).Find(&groups)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -71,12 +71,6 @@ func (service *UserBatchService) Delete() serializer.Response {
|
||||||
model.DB.Where("user_id = ?", uid).Delete(&model.Download{})
|
model.DB.Where("user_id = ?", uid).Delete(&model.Download{})
|
||||||
model.DB.Where("user_id = ?", uid).Delete(&model.Task{})
|
model.DB.Where("user_id = ?", uid).Delete(&model.Task{})
|
||||||
|
|
||||||
// 删除订单记录
|
|
||||||
model.DB.Where("user_id = ?", uid).Delete(&model.Order{})
|
|
||||||
|
|
||||||
// 删除容量包
|
|
||||||
model.DB.Where("user_id = ?", uid).Delete(&model.StoragePack{})
|
|
||||||
|
|
||||||
// 删除标签
|
// 删除标签
|
||||||
model.DB.Where("user_id = ?", uid).Delete(&model.Tag{})
|
model.DB.Where("user_id = ?", uid).Delete(&model.Tag{})
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,98 +0,0 @@
|
||||||
package admin
|
|
||||||
|
|
||||||
import (
|
|
||||||
model "github.com/HFO4/cloudreve/models"
|
|
||||||
"github.com/HFO4/cloudreve/pkg/serializer"
|
|
||||||
"github.com/gofrs/uuid"
|
|
||||||
)
|
|
||||||
|
|
||||||
// GenerateRedeemsService 兑换码生成服务
|
|
||||||
type GenerateRedeemsService struct {
|
|
||||||
Num int `json:"num" binding:"required,min=1,max=100"`
|
|
||||||
ID int64 `json:"id"`
|
|
||||||
Time int `json:"time" binding:"required,min=1"`
|
|
||||||
Type int `json:"type" binding:"min=0,max=2"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// SingleIDService 单ID服务
|
|
||||||
type SingleIDService struct {
|
|
||||||
ID uint `uri:"id" binding:"required"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// DeleteRedeem 删除兑换码
|
|
||||||
func (service *SingleIDService) DeleteRedeem() serializer.Response {
|
|
||||||
if err := model.DB.Where("id = ?", service.ID).Delete(&model.Redeem{}).Error; err != nil {
|
|
||||||
return serializer.DBErr("无法删除兑换码", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
return serializer.Response{}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Generate 生成兑换码
|
|
||||||
func (service *GenerateRedeemsService) Generate() serializer.Response {
|
|
||||||
res := make([]string, service.Num)
|
|
||||||
redeem := model.Redeem{}
|
|
||||||
|
|
||||||
// 开始事务
|
|
||||||
tx := model.DB.Begin()
|
|
||||||
if err := tx.Error; err != nil {
|
|
||||||
return serializer.DBErr("无法开启事务", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// 创建每个兑换码
|
|
||||||
for i := 0; i < service.Num; i++ {
|
|
||||||
redeem.Model.ID = 0
|
|
||||||
redeem.Num = service.Time
|
|
||||||
redeem.Type = service.Type
|
|
||||||
redeem.ProductID = service.ID
|
|
||||||
redeem.Used = false
|
|
||||||
|
|
||||||
// 生成唯一兑换码
|
|
||||||
u2, err := uuid.NewV4()
|
|
||||||
if err != nil {
|
|
||||||
tx.Rollback()
|
|
||||||
return serializer.Err(serializer.CodeInternalSetting, "无法生成兑换码", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
redeem.Code = u2.String()
|
|
||||||
if err := tx.Create(&redeem).Error; err != nil {
|
|
||||||
tx.Rollback()
|
|
||||||
return serializer.DBErr("无法创建兑换码记录", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
res[i] = redeem.Code
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := tx.Commit().Error; err != nil {
|
|
||||||
return serializer.DBErr("无法创建兑换码记录", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
return serializer.Response{Data: res}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
// Redeems 列出激活码
|
|
||||||
func (service *AdminListService) Redeems() serializer.Response {
|
|
||||||
var res []model.Redeem
|
|
||||||
total := 0
|
|
||||||
|
|
||||||
tx := model.DB.Model(&model.Redeem{})
|
|
||||||
if service.OrderBy != "" {
|
|
||||||
tx = tx.Order(service.OrderBy)
|
|
||||||
}
|
|
||||||
|
|
||||||
for k, v := range service.Conditions {
|
|
||||||
tx = tx.Where("? = ?", k, v)
|
|
||||||
}
|
|
||||||
|
|
||||||
// 计算总数用于分页
|
|
||||||
tx.Count(&total)
|
|
||||||
|
|
||||||
// 查询记录
|
|
||||||
tx.Limit(service.PageSize).Offset((service.Page - 1) * service.PageSize).Find(&res)
|
|
||||||
|
|
||||||
return serializer.Response{Data: map[string]interface{}{
|
|
||||||
"total": total,
|
|
||||||
"items": res,
|
|
||||||
}}
|
|
||||||
}
|
|
||||||
|
|
@ -2,8 +2,6 @@ package setting
|
||||||
|
|
||||||
import (
|
import (
|
||||||
model "github.com/HFO4/cloudreve/models"
|
model "github.com/HFO4/cloudreve/models"
|
||||||
"github.com/HFO4/cloudreve/pkg/filesystem"
|
|
||||||
"github.com/HFO4/cloudreve/pkg/hashid"
|
|
||||||
"github.com/HFO4/cloudreve/pkg/serializer"
|
"github.com/HFO4/cloudreve/pkg/serializer"
|
||||||
"github.com/HFO4/cloudreve/pkg/util"
|
"github.com/HFO4/cloudreve/pkg/util"
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
|
|
@ -30,59 +28,6 @@ type WebDAVMountCreateService struct {
|
||||||
Policy string `json:"policy" binding:"required,min=1"`
|
Policy string `json:"policy" binding:"required,min=1"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create 创建目录挂载
|
|
||||||
func (service *WebDAVMountCreateService) Create(c *gin.Context, user *model.User) serializer.Response {
|
|
||||||
// 创建文件系统
|
|
||||||
fs, err := filesystem.NewFileSystem(user)
|
|
||||||
if err != nil {
|
|
||||||
return serializer.Err(serializer.CodePolicyNotAllowed, err.Error(), err)
|
|
||||||
}
|
|
||||||
defer fs.Recycle()
|
|
||||||
|
|
||||||
// 检索要挂载的目录
|
|
||||||
exist, folder := fs.IsPathExist(service.Path)
|
|
||||||
if !exist {
|
|
||||||
return serializer.Err(serializer.CodeNotFound, "路径不存在", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// 检索要挂载的存储策略
|
|
||||||
policyID, err := hashid.DecodeHashID(service.Policy, hashid.PolicyID)
|
|
||||||
if err != nil {
|
|
||||||
return serializer.Err(serializer.CodeNotFound, "存储策略不存在", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// 检查存储策略是否可用
|
|
||||||
if policy, err := model.GetPolicyByID(policyID); err != nil || !util.ContainsUint(user.Group.PolicyList, policy.ID) {
|
|
||||||
return serializer.Err(serializer.CodeNotFound, "存储策略不可用", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// 挂载
|
|
||||||
if err := folder.Mount(policyID); err != nil {
|
|
||||||
return serializer.Err(serializer.CodeDBError, "挂载失败", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
return serializer.Response{
|
|
||||||
Data: map[string]interface{}{
|
|
||||||
"id": hashid.HashID(folder.ID, hashid.FolderID),
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Unmount 取消目录挂载
|
|
||||||
func (service *WebDAVListService) Unmount(c *gin.Context, user *model.User) serializer.Response {
|
|
||||||
folderID, _ := c.Get("object_id")
|
|
||||||
folder, err := model.GetFoldersByIDs([]uint{folderID.(uint)}, user.ID)
|
|
||||||
if err != nil || len(folder) == 0 {
|
|
||||||
return serializer.Err(serializer.CodeNotFound, "目录不存在", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := folder[0].Mount(0); err != nil {
|
|
||||||
return serializer.Err(serializer.CodeDBError, "取消挂载失败", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
return serializer.Response{}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create 创建WebDAV账户
|
// Create 创建WebDAV账户
|
||||||
func (service *WebDAVAccountCreateService) Create(c *gin.Context, user *model.User) serializer.Response {
|
func (service *WebDAVAccountCreateService) Create(c *gin.Context, user *model.User) serializer.Response {
|
||||||
account := model.Webdav{
|
account := model.Webdav{
|
||||||
|
|
|
||||||
|
|
@ -223,39 +223,6 @@ func (service *Service) CreateDocPreviewSession(c *gin.Context) serializer.Respo
|
||||||
return subService.CreateDocPreviewSession(ctx, c)
|
return subService.CreateDocPreviewSession(ctx, c)
|
||||||
}
|
}
|
||||||
|
|
||||||
// SaveToMyFile 将此分享转存到自己的网盘
|
|
||||||
func (service *Service) SaveToMyFile(c *gin.Context) serializer.Response {
|
|
||||||
shareCtx, _ := c.Get("share")
|
|
||||||
share := shareCtx.(*model.Share)
|
|
||||||
userCtx, _ := c.Get("user")
|
|
||||||
user := userCtx.(*model.User)
|
|
||||||
|
|
||||||
// 不能转存自己的文件
|
|
||||||
if share.UserID == user.ID {
|
|
||||||
return serializer.Err(serializer.CodePolicyNotAllowed, "不能转存自己的分享", nil)
|
|
||||||
}
|
|
||||||
|
|
||||||
// 创建文件系统
|
|
||||||
fs, err := filesystem.NewFileSystem(user)
|
|
||||||
if err != nil {
|
|
||||||
return serializer.Err(serializer.CodePolicyNotAllowed, err.Error(), err)
|
|
||||||
}
|
|
||||||
defer fs.Recycle()
|
|
||||||
|
|
||||||
// 重设文件系统处理目标为源文件
|
|
||||||
err = fs.SetTargetByInterface(share.Source())
|
|
||||||
if err != nil {
|
|
||||||
return serializer.Err(serializer.CodePolicyNotAllowed, "源文件不存在", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
err = fs.SaveTo(context.Background(), service.Path)
|
|
||||||
if err != nil {
|
|
||||||
return serializer.Err(serializer.CodeNotSet, err.Error(), err)
|
|
||||||
}
|
|
||||||
|
|
||||||
return serializer.Response{}
|
|
||||||
}
|
|
||||||
|
|
||||||
// List 列出分享的目录下的对象
|
// List 列出分享的目录下的对象
|
||||||
func (service *Service) List(c *gin.Context) serializer.Response {
|
func (service *Service) List(c *gin.Context) serializer.Response {
|
||||||
shareCtx, _ := c.Get("share")
|
shareCtx, _ := c.Get("share")
|
||||||
|
|
|
||||||
|
|
@ -135,7 +135,6 @@ func (service *UserLoginService) Login(c *gin.Context) serializer.Response {
|
||||||
expectedUser, err := model.GetUserByEmail(service.UserName)
|
expectedUser, err := model.GetUserByEmail(service.UserName)
|
||||||
|
|
||||||
if model.IsTrueVal(isCaptchaRequired) {
|
if model.IsTrueVal(isCaptchaRequired) {
|
||||||
// TODO 验证码校验
|
|
||||||
captchaID := util.GetSession(c, "captchaID")
|
captchaID := util.GetSession(c, "captchaID")
|
||||||
util.DeleteSession(c, "captchaID")
|
util.DeleteSession(c, "captchaID")
|
||||||
if captchaID == nil || !base64Captcha.VerifyCaptcha(captchaID.(string), service.CaptchaCode) {
|
if captchaID == nil || !base64Captcha.VerifyCaptcha(captchaID.(string), service.CaptchaCode) {
|
||||||
|
|
|
||||||
|
|
@ -4,8 +4,6 @@ import (
|
||||||
"crypto/md5"
|
"crypto/md5"
|
||||||
"fmt"
|
"fmt"
|
||||||
model "github.com/HFO4/cloudreve/models"
|
model "github.com/HFO4/cloudreve/models"
|
||||||
"github.com/HFO4/cloudreve/pkg/hashid"
|
|
||||||
"github.com/HFO4/cloudreve/pkg/qq"
|
|
||||||
"github.com/HFO4/cloudreve/pkg/serializer"
|
"github.com/HFO4/cloudreve/pkg/serializer"
|
||||||
"github.com/HFO4/cloudreve/pkg/util"
|
"github.com/HFO4/cloudreve/pkg/util"
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
|
|
@ -14,8 +12,6 @@ import (
|
||||||
"net/url"
|
"net/url"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strings"
|
|
||||||
"time"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// SettingService 通用设置服务
|
// SettingService 通用设置服务
|
||||||
|
|
@ -47,14 +43,6 @@ type ChangerNick struct {
|
||||||
Nick string `json:"nick" binding:"required,min=1,max=255"`
|
Nick string `json:"nick" binding:"required,min=1,max=255"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// VIPUnsubscribe 用户组解约服务
|
|
||||||
type VIPUnsubscribe struct {
|
|
||||||
}
|
|
||||||
|
|
||||||
// QQBind QQ互联服务
|
|
||||||
type QQBind struct {
|
|
||||||
}
|
|
||||||
|
|
||||||
// PolicyChange 更改存储策略
|
// PolicyChange 更改存储策略
|
||||||
type PolicyChange struct {
|
type PolicyChange struct {
|
||||||
ID string `json:"id" binding:"required"`
|
ID string `json:"id" binding:"required"`
|
||||||
|
|
@ -173,77 +161,6 @@ func (service *HomePage) Update(c *gin.Context, user *model.User) serializer.Res
|
||||||
return serializer.Response{}
|
return serializer.Response{}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update 更改用户偏好的存储策略
|
|
||||||
func (service *PolicyChange) Update(c *gin.Context, user *model.User) serializer.Response {
|
|
||||||
// 取得存储策略的ID
|
|
||||||
rawID, err := hashid.DecodeHashID(service.ID, hashid.PolicyID)
|
|
||||||
if err != nil {
|
|
||||||
return serializer.Err(serializer.CodeNotFound, "存储策略不存在", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// 用户是否可以切换到此存储策略
|
|
||||||
if !util.ContainsUint(user.Group.PolicyList, rawID) {
|
|
||||||
return serializer.Err(serializer.CodeNoPermissionErr, "存储策略不可用", nil)
|
|
||||||
}
|
|
||||||
|
|
||||||
// 查找存储策略
|
|
||||||
if _, err := model.GetPolicyByID(rawID); err != nil {
|
|
||||||
return serializer.Err(serializer.CodeNoPermissionErr, "存储策略不可用", nil)
|
|
||||||
}
|
|
||||||
|
|
||||||
// 切换存储策略
|
|
||||||
user.OptionsSerialized.PreferredPolicy = rawID
|
|
||||||
if err := user.UpdateOptions(); err != nil {
|
|
||||||
return serializer.DBErr("存储策略切换失败", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
return serializer.Response{}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update 绑定或解绑QQ
|
|
||||||
func (service *QQBind) Update(c *gin.Context, user *model.User) serializer.Response {
|
|
||||||
// 解除绑定
|
|
||||||
if user.OpenID != "" {
|
|
||||||
// 只通过QQ登录的用户无法解除绑定
|
|
||||||
if strings.HasSuffix(user.Email, "@login.qq.com") {
|
|
||||||
return serializer.Err(serializer.CodeNoPermissionErr, "无法解绑此账号", nil)
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := user.Update(map[string]interface{}{"open_id": ""}); err != nil {
|
|
||||||
return serializer.DBErr("接除绑定失败", err)
|
|
||||||
}
|
|
||||||
return serializer.Response{
|
|
||||||
Data: "",
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 新建绑定
|
|
||||||
res, err := qq.NewLoginRequest()
|
|
||||||
if err != nil {
|
|
||||||
return serializer.Err(serializer.CodeNotSet, "无法使用QQ登录", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// 设定QQ登录会话Secret
|
|
||||||
util.SetSession(c, map[string]interface{}{"qq_login_secret": res.SecretKey})
|
|
||||||
|
|
||||||
return serializer.Response{
|
|
||||||
Data: res.URL,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update 用户组解约
|
|
||||||
func (service *VIPUnsubscribe) Update(c *gin.Context, user *model.User) serializer.Response {
|
|
||||||
if user.GroupExpires != nil {
|
|
||||||
timeNow := time.Now()
|
|
||||||
if time.Now().Before(*user.GroupExpires) {
|
|
||||||
if err := user.Update(map[string]interface{}{"group_expires": &timeNow}); err != nil {
|
|
||||||
return serializer.DBErr("解约失败", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return serializer.Response{}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update 更改昵称
|
// Update 更改昵称
|
||||||
func (service *ChangerNick) Update(c *gin.Context, user *model.User) serializer.Response {
|
func (service *ChangerNick) Update(c *gin.Context, user *model.User) serializer.Response {
|
||||||
if err := user.Update(map[string]interface{}{"nick": service.Nick}); err != nil {
|
if err := user.Update(map[string]interface{}{"nick": service.Nick}); err != nil {
|
||||||
|
|
@ -322,45 +239,15 @@ func (service *SettingListService) ListTasks(c *gin.Context, user *model.User) s
|
||||||
return serializer.BuildTaskList(tasks, total)
|
return serializer.BuildTaskList(tasks, total)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Policy 获取用户存储策略设置
|
|
||||||
func (service *SettingService) Policy(c *gin.Context, user *model.User) serializer.Response {
|
|
||||||
// 取得用户可用存储策略
|
|
||||||
available := make([]model.Policy, 0, len(user.Group.PolicyList))
|
|
||||||
for _, id := range user.Group.PolicyList {
|
|
||||||
if policy, err := model.GetPolicyByID(id); err == nil {
|
|
||||||
available = append(available, policy)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 取得用户当前策略
|
|
||||||
current := user.Policy
|
|
||||||
|
|
||||||
return serializer.BuildPolicySettingRes(available, ¤t)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Settings 获取用户设定
|
// Settings 获取用户设定
|
||||||
func (service *SettingService) Settings(c *gin.Context, user *model.User) serializer.Response {
|
func (service *SettingService) Settings(c *gin.Context, user *model.User) serializer.Response {
|
||||||
// 取得存储策略设定
|
|
||||||
policy := service.Policy(c, user)
|
|
||||||
|
|
||||||
// 用户组有效期
|
|
||||||
var groupExpires int64
|
|
||||||
if user.GroupExpires != nil {
|
|
||||||
if expires := user.GroupExpires.Unix() - time.Now().Unix(); expires > 0 {
|
|
||||||
groupExpires = user.GroupExpires.Unix()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return serializer.Response{
|
return serializer.Response{
|
||||||
Data: map[string]interface{}{
|
Data: map[string]interface{}{
|
||||||
"policy": policy.Data.(map[string]interface{}),
|
|
||||||
"uid": user.ID,
|
"uid": user.ID,
|
||||||
"qq": user.OpenID != "",
|
|
||||||
"homepage": !user.OptionsSerialized.ProfileOff,
|
"homepage": !user.OptionsSerialized.ProfileOff,
|
||||||
"two_factor": user.TwoFactor != "",
|
"two_factor": user.TwoFactor != "",
|
||||||
"prefer_theme": user.OptionsSerialized.PreferredTheme,
|
"prefer_theme": user.OptionsSerialized.PreferredTheme,
|
||||||
"themes": model.GetSettingByName("themes"),
|
"themes": model.GetSettingByName("themes"),
|
||||||
"group_expires": groupExpires,
|
|
||||||
"authn": serializer.BuildWebAuthnList(user.WebAuthnCredentials()),
|
"authn": serializer.BuildWebAuthnList(user.WebAuthnCredentials()),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,219 +0,0 @@
|
||||||
package vas
|
|
||||||
|
|
||||||
import (
|
|
||||||
"encoding/json"
|
|
||||||
model "github.com/HFO4/cloudreve/models"
|
|
||||||
"github.com/HFO4/cloudreve/pkg/payment"
|
|
||||||
"github.com/HFO4/cloudreve/pkg/serializer"
|
|
||||||
"github.com/gin-gonic/gin"
|
|
||||||
)
|
|
||||||
|
|
||||||
// CreateOrderService 创建订单服务
|
|
||||||
type CreateOrderService struct {
|
|
||||||
Action string `json:"action" binding:"required,eq=group|eq=pack|eq=score"`
|
|
||||||
Method string `json:"method" binding:"required,eq=alipay|eq=score|eq=payjs"`
|
|
||||||
ID int64 `json:"id" binding:"required"`
|
|
||||||
Num int `json:"num" binding:"required,min=1"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// RedeemService 兑换服务
|
|
||||||
type RedeemService struct {
|
|
||||||
Code string `uri:"code" binding:"required,max=64"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// OrderService 订单查询
|
|
||||||
type OrderService struct {
|
|
||||||
ID string `uri:"id" binding:"required"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// Status 查询订单状态
|
|
||||||
func (service *OrderService) Status(c *gin.Context, user *model.User) serializer.Response {
|
|
||||||
order, _ := model.GetOrderByNo(service.ID)
|
|
||||||
if order == nil || order.UserID != user.ID {
|
|
||||||
return serializer.Err(serializer.CodeNotFound, "订单不存在", nil)
|
|
||||||
}
|
|
||||||
|
|
||||||
return serializer.Response{Data: order.Status}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Redeem 开始兑换
|
|
||||||
func (service *RedeemService) Redeem(c *gin.Context, user *model.User) serializer.Response {
|
|
||||||
redeem, err := model.GetAvailableRedeem(service.Code)
|
|
||||||
if err != nil {
|
|
||||||
return serializer.Err(serializer.CodeDBError, "兑换码无效", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// 取得当前商品信息
|
|
||||||
packs, groups, err := decodeProductInfo()
|
|
||||||
if err != nil {
|
|
||||||
return serializer.Err(serializer.CodeInternalSetting, "无法解析商品设置", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// 查找要购买的商品
|
|
||||||
var (
|
|
||||||
pack *serializer.PackProduct
|
|
||||||
group *serializer.GroupProducts
|
|
||||||
)
|
|
||||||
if redeem.Type == model.GroupOrderType {
|
|
||||||
for _, v := range groups {
|
|
||||||
if v.ID == redeem.ProductID {
|
|
||||||
group = &v
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if group == nil {
|
|
||||||
return serializer.Err(serializer.CodeNotFound, "商品已失效", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
} else if redeem.Type == model.PackOrderType {
|
|
||||||
for _, v := range packs {
|
|
||||||
if v.ID == redeem.ProductID {
|
|
||||||
pack = &v
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if pack == nil {
|
|
||||||
return serializer.Err(serializer.CodeNotFound, "商品已失效", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
err = payment.GiveProduct(user, pack, group, redeem.Num)
|
|
||||||
if err != nil {
|
|
||||||
return serializer.Err(serializer.CodeNotSet, "兑换失败", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
redeem.Use()
|
|
||||||
|
|
||||||
return serializer.Response{}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
// Query 检查兑换码信息
|
|
||||||
func (service *RedeemService) Query(c *gin.Context) serializer.Response {
|
|
||||||
redeem, err := model.GetAvailableRedeem(service.Code)
|
|
||||||
if err != nil {
|
|
||||||
return serializer.Err(serializer.CodeDBError, "兑换码无效", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
var (
|
|
||||||
name = "积分"
|
|
||||||
productTime int64
|
|
||||||
)
|
|
||||||
if redeem.Type != model.ScoreOrderType {
|
|
||||||
packs, groups, err := decodeProductInfo()
|
|
||||||
if err != nil {
|
|
||||||
return serializer.Err(serializer.CodeInternalSetting, "无法解析商品设置", err)
|
|
||||||
}
|
|
||||||
if redeem.Type == model.GroupOrderType {
|
|
||||||
for _, v := range groups {
|
|
||||||
if v.ID == redeem.ProductID {
|
|
||||||
name = v.Name
|
|
||||||
productTime = v.Time
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
for _, v := range packs {
|
|
||||||
if v.ID == redeem.ProductID {
|
|
||||||
name = v.Name
|
|
||||||
productTime = v.Time
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if name == "积分" {
|
|
||||||
return serializer.Err(serializer.CodeNotFound, "商品已失效", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
return serializer.Response{
|
|
||||||
Data: struct {
|
|
||||||
Name string `json:"name"`
|
|
||||||
Type int `json:"type"`
|
|
||||||
Num int `json:"num"`
|
|
||||||
Time int64 `json:"time"`
|
|
||||||
}{
|
|
||||||
name, redeem.Type, redeem.Num, productTime,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create 创建新订单
|
|
||||||
func (service *CreateOrderService) Create(c *gin.Context, user *model.User) serializer.Response {
|
|
||||||
// 取得当前商品信息
|
|
||||||
packs, groups, err := decodeProductInfo()
|
|
||||||
if err != nil {
|
|
||||||
return serializer.Err(serializer.CodeInternalSetting, "无法解析商品设置", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// 查找要购买的商品
|
|
||||||
var (
|
|
||||||
pack *serializer.PackProduct
|
|
||||||
group *serializer.GroupProducts
|
|
||||||
)
|
|
||||||
if service.Action == "group" {
|
|
||||||
for _, v := range groups {
|
|
||||||
if v.ID == service.ID {
|
|
||||||
group = &v
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if service.Action == "pack" {
|
|
||||||
for _, v := range packs {
|
|
||||||
if v.ID == service.ID {
|
|
||||||
pack = &v
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 购买积分
|
|
||||||
if pack == nil && group == nil {
|
|
||||||
if service.Method == "score" {
|
|
||||||
return serializer.Err(serializer.CodeNotFound, "不支持此支付方式", nil)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 创建订单
|
|
||||||
res, err := payment.NewOrder(pack, group, service.Num, service.Method, user)
|
|
||||||
if err != nil {
|
|
||||||
return serializer.Err(serializer.CodeNotSet, err.Error(), err)
|
|
||||||
}
|
|
||||||
|
|
||||||
return serializer.Response{Data: res}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
// Products 获取商品信息
|
|
||||||
func (service *GeneralVASService) Products(c *gin.Context, user *model.User) serializer.Response {
|
|
||||||
options := model.GetSettingByNames("alipay_enabled", "payjs_enabled", "score_price")
|
|
||||||
scorePrice := model.GetIntSetting("score_price", 0)
|
|
||||||
packs, groups, err := decodeProductInfo()
|
|
||||||
if err != nil {
|
|
||||||
return serializer.Err(serializer.CodeInternalSetting, "无法解析商品设置", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
return serializer.BuildProductResponse(groups, packs, options["alipay_enabled"] == "1", options["payjs_enabled"] == "1", scorePrice)
|
|
||||||
}
|
|
||||||
|
|
||||||
func decodeProductInfo() ([]serializer.PackProduct, []serializer.GroupProducts, error) {
|
|
||||||
options := model.GetSettingByNames("pack_data", "group_sell_data", "alipay_enabled", "payjs_enabled")
|
|
||||||
|
|
||||||
var (
|
|
||||||
packs []serializer.PackProduct
|
|
||||||
groups []serializer.GroupProducts
|
|
||||||
)
|
|
||||||
if err := json.Unmarshal([]byte(options["pack_data"]), &packs); err != nil {
|
|
||||||
return nil, nil, err
|
|
||||||
}
|
|
||||||
if err := json.Unmarshal([]byte(options["group_sell_data"]), &groups); err != nil {
|
|
||||||
return nil, nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return packs, groups, nil
|
|
||||||
}
|
|
||||||
|
|
@ -1,107 +0,0 @@
|
||||||
package vas
|
|
||||||
|
|
||||||
import (
|
|
||||||
model "github.com/HFO4/cloudreve/models"
|
|
||||||
"github.com/HFO4/cloudreve/pkg/qq"
|
|
||||||
"github.com/HFO4/cloudreve/pkg/request"
|
|
||||||
"github.com/HFO4/cloudreve/pkg/serializer"
|
|
||||||
"github.com/HFO4/cloudreve/pkg/thumb"
|
|
||||||
"github.com/HFO4/cloudreve/pkg/util"
|
|
||||||
"github.com/gin-gonic/gin"
|
|
||||||
)
|
|
||||||
|
|
||||||
// QQCallbackService QQ互联回调处理服务
|
|
||||||
type QQCallbackService struct {
|
|
||||||
Code string `json:"code" binding:"required"`
|
|
||||||
State string `json:"state" binding:"required"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// Callback 处理QQ互联回调
|
|
||||||
func (service *QQCallbackService) Callback(c *gin.Context, user *model.User) serializer.Response {
|
|
||||||
|
|
||||||
state := util.GetSession(c, "qq_login_secret")
|
|
||||||
if stateStr, ok := state.(string); !ok || stateStr != service.State {
|
|
||||||
return serializer.Err(serializer.CodeSignExpired, "请求过期,请重试", nil)
|
|
||||||
}
|
|
||||||
util.DeleteSession(c, "qq_login_secret")
|
|
||||||
|
|
||||||
// 获取OpenID
|
|
||||||
credential, err := qq.Callback(service.Code)
|
|
||||||
if err != nil {
|
|
||||||
return serializer.Err(serializer.CodeNotSet, "无法获取登录状态", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// 如果已登录,则绑定已有用户
|
|
||||||
if user != nil {
|
|
||||||
|
|
||||||
if user.OpenID != "" {
|
|
||||||
return serializer.Err(serializer.CodeCallbackError, "您已绑定了QQ账号,请先解除绑定", nil)
|
|
||||||
}
|
|
||||||
if err := user.Update(map[string]interface{}{"open_id": credential.OpenID}); err != nil {
|
|
||||||
return serializer.DBErr("绑定失败", err)
|
|
||||||
}
|
|
||||||
return serializer.Response{
|
|
||||||
Data: "/setting",
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
// 未登录,尝试查找用户
|
|
||||||
if expectedUser, err := model.GetActiveUserByOpenID(credential.OpenID); err == nil {
|
|
||||||
// 用户绑定了此QQ,设定为登录状态
|
|
||||||
util.SetSession(c, map[string]interface{}{
|
|
||||||
"user_id": expectedUser.ID,
|
|
||||||
})
|
|
||||||
res := serializer.BuildUserResponse(expectedUser)
|
|
||||||
res.Code = 203
|
|
||||||
return res
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
// 无匹配用户,创建新用户
|
|
||||||
if !model.IsTrueVal(model.GetSettingByName("qq_direct_login")) {
|
|
||||||
return serializer.Err(serializer.CodeNoPermissionErr, "此QQ号未绑定任何账号", nil)
|
|
||||||
}
|
|
||||||
|
|
||||||
// 获取用户信息
|
|
||||||
userInfo, err := qq.GetUserInfo(credential)
|
|
||||||
if err != nil {
|
|
||||||
return serializer.Err(serializer.CodeNotSet, "无法获取用户信息", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// 生成邮箱地址
|
|
||||||
fakeEmail := util.RandStringRunes(16) + "@login.qq.com"
|
|
||||||
|
|
||||||
// 创建用户
|
|
||||||
defaultGroup := model.GetIntSetting("default_group", 2)
|
|
||||||
|
|
||||||
newUser := model.NewUser()
|
|
||||||
newUser.Email = fakeEmail
|
|
||||||
newUser.Nick = userInfo.Nick
|
|
||||||
newUser.SetPassword("")
|
|
||||||
newUser.Status = model.Active
|
|
||||||
newUser.GroupID = uint(defaultGroup)
|
|
||||||
newUser.OpenID = credential.OpenID
|
|
||||||
newUser.Avatar = "file"
|
|
||||||
|
|
||||||
// 创建用户
|
|
||||||
if err := model.DB.Create(&newUser).Error; err != nil {
|
|
||||||
return serializer.DBErr("此邮箱已被使用", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// 下载头像
|
|
||||||
r := request.HTTPClient{}
|
|
||||||
rawAvatar := r.Request("GET", userInfo.Avatar, nil)
|
|
||||||
if avatar, err := thumb.NewThumbFromFile(rawAvatar.Response.Body, "avatar.jpg"); err == nil {
|
|
||||||
avatar.CreateAvatar(newUser.ID)
|
|
||||||
}
|
|
||||||
|
|
||||||
// 登录
|
|
||||||
util.SetSession(c, map[string]interface{}{"user_id": newUser.ID})
|
|
||||||
|
|
||||||
newUser, _ = model.GetActiveUserByID(newUser.ID)
|
|
||||||
|
|
||||||
res := serializer.BuildUserResponse(newUser)
|
|
||||||
res.Code = 203
|
|
||||||
return res
|
|
||||||
}
|
|
||||||
|
|
@ -1,17 +0,0 @@
|
||||||
package vas
|
|
||||||
|
|
||||||
import (
|
|
||||||
model "github.com/HFO4/cloudreve/models"
|
|
||||||
"github.com/HFO4/cloudreve/pkg/serializer"
|
|
||||||
"github.com/gin-gonic/gin"
|
|
||||||
)
|
|
||||||
|
|
||||||
// GeneralVASService 通用增值服务
|
|
||||||
type GeneralVASService struct {
|
|
||||||
}
|
|
||||||
|
|
||||||
// Quota 获取容量配额信息
|
|
||||||
func (service *GeneralVASService) Quota(c *gin.Context, user *model.User) serializer.Response {
|
|
||||||
packs := user.GetAvailableStoragePacks()
|
|
||||||
return serializer.BuildUserQuotaResponse(user, packs)
|
|
||||||
}
|
|
||||||
Loading…
Reference in New Issue