mirror of https://github.com/cloudreve/Cloudreve
Feat: payjs payment
parent
f8c14b3826
commit
0253b4e5b6
1
go.mod
1
go.mod
|
@ -25,6 +25,7 @@ require (
|
||||||
github.com/mojocn/base64Captcha v0.0.0-20190801020520-752b1cd608b2
|
github.com/mojocn/base64Captcha v0.0.0-20190801020520-752b1cd608b2
|
||||||
github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646
|
github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646
|
||||||
github.com/pkg/errors v0.8.0
|
github.com/pkg/errors v0.8.0
|
||||||
|
github.com/qingwg/payjs v0.0.0-20190928033402-c53dbe16b371
|
||||||
github.com/qiniu/api.v7/v7 v7.4.0
|
github.com/qiniu/api.v7/v7 v7.4.0
|
||||||
github.com/rafaeljusto/redigomock v0.0.0-20191117212112-00b2509252a1
|
github.com/rafaeljusto/redigomock v0.0.0-20191117212112-00b2509252a1
|
||||||
github.com/robfig/cron/v3 v3.0.1
|
github.com/robfig/cron/v3 v3.0.1
|
||||||
|
|
2
go.sum
2
go.sum
|
@ -160,6 +160,8 @@ github.com/prometheus/client_model v0.0.0-20190115171406-56726106282f/go.mod h1:
|
||||||
github.com/prometheus/common v0.2.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
|
github.com/prometheus/common v0.2.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
|
||||||
github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
|
github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
|
||||||
github.com/prometheus/procfs v0.0.0-20190117184657-bf6a532e95b1/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
|
github.com/prometheus/procfs v0.0.0-20190117184657-bf6a532e95b1/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
|
||||||
|
github.com/qingwg/payjs v0.0.0-20190928033402-c53dbe16b371 h1:8VWtyY2IwjEQZSNT4Kyyct9zv9hoegD5GQhFr+TMdCI=
|
||||||
|
github.com/qingwg/payjs v0.0.0-20190928033402-c53dbe16b371/go.mod h1:9UFrQveqNm3ELF6HSvMtDR3KYpJ7Ib9s0WVmYhaUBlU=
|
||||||
github.com/qiniu/api.v7/v7 v7.4.0 h1:9dZMVQifh31QGFLVaHls6akCaS2rlj3du8MnEFd7XjQ=
|
github.com/qiniu/api.v7/v7 v7.4.0 h1:9dZMVQifh31QGFLVaHls6akCaS2rlj3du8MnEFd7XjQ=
|
||||||
github.com/qiniu/api.v7/v7 v7.4.0/go.mod h1:VE5oC5rkE1xul0u1S2N0b2Uxq9/6hZzhyqjgK25XDcM=
|
github.com/qiniu/api.v7/v7 v7.4.0/go.mod h1:VE5oC5rkE1xul0u1S2N0b2Uxq9/6hZzhyqjgK25XDcM=
|
||||||
github.com/quasoft/memstore v0.0.0-20180925164028-84a050167438 h1:jnz/4VenymvySjE+Ez511s0pqVzkUOmr1fwCVytNNWk=
|
github.com/quasoft/memstore v0.0.0-20180925164028-84a050167438 h1:jnz/4VenymvySjE+Ez511s0pqVzkUOmr1fwCVytNNWk=
|
||||||
|
|
|
@ -140,6 +140,8 @@ Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 14px; verti
|
||||||
{Name: "database_version", Value: `6`, Type: "version"},
|
{Name: "database_version", Value: `6`, Type: "version"},
|
||||||
{Name: "alipay_enabled", Value: `0`, Type: "payment"},
|
{Name: "alipay_enabled", Value: `0`, Type: "payment"},
|
||||||
{Name: "payjs_enabled", Value: `0`, Type: "payment"},
|
{Name: "payjs_enabled", Value: `0`, Type: "payment"},
|
||||||
|
{Name: "payjs_id", Value: ``, Type: "payment"},
|
||||||
|
{Name: "payjs_secret", Value: ``, Type: "payment"},
|
||||||
{Name: "appid", Value: ``, Type: "payment"},
|
{Name: "appid", Value: ``, Type: "payment"},
|
||||||
{Name: "appkey", Value: ``, Type: "payment"},
|
{Name: "appkey", Value: ``, Type: "payment"},
|
||||||
{Name: "shopid", Value: ``, Type: "payment"},
|
{Name: "shopid", Value: ``, Type: "payment"},
|
||||||
|
|
|
@ -4,8 +4,10 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
model "github.com/HFO4/cloudreve/models"
|
model "github.com/HFO4/cloudreve/models"
|
||||||
"github.com/HFO4/cloudreve/pkg/serializer"
|
"github.com/HFO4/cloudreve/pkg/serializer"
|
||||||
|
"github.com/qingwg/payjs"
|
||||||
"github.com/smartwalle/alipay/v3"
|
"github.com/smartwalle/alipay/v3"
|
||||||
"math/rand"
|
"math/rand"
|
||||||
|
"net/url"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -41,10 +43,9 @@ type Pay interface {
|
||||||
|
|
||||||
// OrderCreateRes 订单创建结果
|
// OrderCreateRes 订单创建结果
|
||||||
type OrderCreateRes struct {
|
type OrderCreateRes struct {
|
||||||
Payment bool `json:"payment"` // 是否需要支付
|
Payment bool `json:"payment"` // 是否需要支付
|
||||||
ID string `json:"id,omitempty"` // 订单号
|
ID string `json:"id,omitempty"` // 订单号
|
||||||
QRCode string `json:"qr_code,omitempty"` // 支付二维码指向的地址
|
QRCode string `json:"qr_code,omitempty"` // 支付二维码指向的地址
|
||||||
Redirect string `json:"redirect,omitempty"` // 支付跳转连接,和二维码二选一,不需要的留空
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewPaymentInstance 获取新的支付实例
|
// NewPaymentInstance 获取新的支付实例
|
||||||
|
@ -71,6 +72,21 @@ func NewPaymentInstance(method string) (Pay, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
return &Alipay{Client: client}, nil
|
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:
|
default:
|
||||||
return nil, ErrUnknownPaymentMethod
|
return nil, ErrUnknownPaymentMethod
|
||||||
}
|
}
|
||||||
|
@ -124,8 +140,8 @@ func NewOrder(pack *serializer.PackProduct, group *serializer.GroupProducts, num
|
||||||
}
|
}
|
||||||
|
|
||||||
func orderID() string {
|
func orderID() string {
|
||||||
return fmt.Sprintf("%s%d%d",
|
return fmt.Sprintf("%s%d",
|
||||||
time.Now().Format("20060102150405"),
|
time.Now().Format("20060102150405"),
|
||||||
10000+rand.Intn(90000),
|
100000+rand.Intn(900000),
|
||||||
time.Now().UnixNano())
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,31 @@
|
||||||
|
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
|
||||||
|
}
|
|
@ -5,6 +5,7 @@ import (
|
||||||
"github.com/HFO4/cloudreve/pkg/util"
|
"github.com/HFO4/cloudreve/pkg/util"
|
||||||
"github.com/HFO4/cloudreve/service/vas"
|
"github.com/HFO4/cloudreve/service/vas"
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
|
"github.com/qingwg/payjs/notify"
|
||||||
"github.com/smartwalle/alipay/v3"
|
"github.com/smartwalle/alipay/v3"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -100,3 +101,33 @@ func AlipayCallback(c *gin.Context) {
|
||||||
// 确认收到通知消息
|
// 确认收到通知消息
|
||||||
alipay.AckNotification(c.Writer)
|
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()
|
||||||
|
|
||||||
|
}
|
||||||
|
|
|
@ -127,6 +127,11 @@ func InitMasterRouter() *gin.Engine {
|
||||||
// 回调接口
|
// 回调接口
|
||||||
callback := v3.Group("callback")
|
callback := v3.Group("callback")
|
||||||
{
|
{
|
||||||
|
// PAYJS回调
|
||||||
|
callback.POST(
|
||||||
|
"payjs",
|
||||||
|
controllers.PayJSCallback,
|
||||||
|
)
|
||||||
// 支付宝回调
|
// 支付宝回调
|
||||||
callback.POST(
|
callback.POST(
|
||||||
"alipay",
|
"alipay",
|
||||||
|
|
Loading…
Reference in New Issue