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), ) }