mirror of
https://github.com/casdoor/casdoor.git
synced 2025-05-24 08:20:31 +08:00
feat: Add PayPal pay function
Signed-off-by: MRGUOKING <420919469@qq.com> Add PayPal pay function Signed-off-by: MRGUOKING <420919469@qq.com>
This commit is contained in:
parent
b93a29fbc6
commit
6ad8f9fa0b
@ -93,6 +93,9 @@ p, *, *, POST, /api/send-verification-code, *, *
|
|||||||
p, *, *, GET, /api/get-human-check, *, *
|
p, *, *, GET, /api/get-human-check, *, *
|
||||||
p, *, *, POST, /api/reset-email-or-phone, *, *
|
p, *, *, POST, /api/reset-email-or-phone, *, *
|
||||||
p, *, *, POST, /api/upload-resource, *, *
|
p, *, *, POST, /api/upload-resource, *, *
|
||||||
|
p, *, *, POST, /api/paypal, *, *
|
||||||
|
p, *, *, GET, /api/success-pay, *, *
|
||||||
|
p, *, *, GET, /api/get-application-clientId, *, *
|
||||||
`
|
`
|
||||||
|
|
||||||
sa := stringadapter.NewAdapter(ruleText)
|
sa := stringadapter.NewAdapter(ruleText)
|
||||||
|
@ -16,6 +16,7 @@ package controllers
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
|
||||||
"github.com/casbin/casdoor/object"
|
"github.com/casbin/casdoor/object"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -116,3 +117,10 @@ func (c *ApiController) DeleteApplication() {
|
|||||||
c.Data["json"] = wrapActionResponse(object.DeleteApplication(&application))
|
c.Data["json"] = wrapActionResponse(object.DeleteApplication(&application))
|
||||||
c.ServeJSON()
|
c.ServeJSON()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *ApiController) GetApplicationByClientId() {
|
||||||
|
clientId := c.Input().Get("clientId")
|
||||||
|
|
||||||
|
c.Data["json"] = object.GetApplicationByClientId(clientId)
|
||||||
|
c.ServeJSON()
|
||||||
|
}
|
||||||
|
45
controllers/payment.go
Normal file
45
controllers/payment.go
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
package controllers
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
|
||||||
|
"github.com/casbin/casdoor/object"
|
||||||
|
"github.com/casbin/casdoor/payment"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (c *ApiController) PaypalPay() {
|
||||||
|
clientId := c.Input().Get("clientId")
|
||||||
|
redirectUri := c.Input().Get("redirectUri")
|
||||||
|
var payItem object.PayItem
|
||||||
|
err := json.Unmarshal(c.Ctx.Input.RequestBody, &payItem)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
msg := payment.Paypal(payItem, clientId, redirectUri)
|
||||||
|
|
||||||
|
c.Data["json"] = msg
|
||||||
|
c.ServeJSON()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *ApiController) GetPayments() {
|
||||||
|
c.Data["json"] = object.GetPayments()
|
||||||
|
c.ServeJSON()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *ApiController) DeletePayment() {
|
||||||
|
var payment object.Payment
|
||||||
|
err := json.Unmarshal(c.Ctx.Input.RequestBody, &payment)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
c.Data["json"] = wrapActionResponse(object.DeletePayment(&payment))
|
||||||
|
c.ServeJSON()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *ApiController) SuccessPay() {
|
||||||
|
token := c.Input().Get("paymentId")
|
||||||
|
c.Data["json"] = payment.SuccessPay(token)
|
||||||
|
c.ServeJSON()
|
||||||
|
}
|
3
go.mod
3
go.mod
@ -18,6 +18,7 @@ require (
|
|||||||
github.com/google/uuid v1.2.0
|
github.com/google/uuid v1.2.0
|
||||||
github.com/jinzhu/configor v1.2.1 // indirect
|
github.com/jinzhu/configor v1.2.1 // indirect
|
||||||
github.com/mileusna/crontab v1.0.1
|
github.com/mileusna/crontab v1.0.1
|
||||||
|
github.com/plutov/paypal/v4 v4.3.7 // indirect
|
||||||
github.com/qiangmzsx/string-adapter/v2 v2.1.0
|
github.com/qiangmzsx/string-adapter/v2 v2.1.0
|
||||||
github.com/qor/oss v0.0.0-20191031055114-aef9ba66bf76
|
github.com/qor/oss v0.0.0-20191031055114-aef9ba66bf76
|
||||||
github.com/satori/go.uuid v1.2.0 // indirect
|
github.com/satori/go.uuid v1.2.0 // indirect
|
||||||
@ -30,5 +31,5 @@ require (
|
|||||||
gopkg.in/gomail.v2 v2.0.0-20160411212932-81ebce5c23df // indirect
|
gopkg.in/gomail.v2 v2.0.0-20160411212932-81ebce5c23df // indirect
|
||||||
gopkg.in/ini.v1 v1.62.0 // indirect
|
gopkg.in/ini.v1 v1.62.0 // indirect
|
||||||
xorm.io/core v0.7.2
|
xorm.io/core v0.7.2
|
||||||
xorm.io/xorm v1.0.3
|
xorm.io/xorm v1.0.6
|
||||||
)
|
)
|
||||||
|
28
go.sum
28
go.sum
@ -38,6 +38,7 @@ github.com/Azure/go-ntlmssp v0.0.0-20200615164410-66371956d46c/go.mod h1:chxPXzS
|
|||||||
github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ=
|
github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ=
|
||||||
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
||||||
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
|
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
|
||||||
|
github.com/DataDog/zstd v1.4.5/go.mod h1:1jcaCB/ufaK+sKp1NBhlGmpz41jOoPQ35bpF36t7BBo=
|
||||||
github.com/Knetic/govaluate v3.0.0+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0=
|
github.com/Knetic/govaluate v3.0.0+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0=
|
||||||
github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible h1:1G1pk05UrOh0NlF1oeaaix1x8XzrfjIDK47TY0Zehcw=
|
github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible h1:1G1pk05UrOh0NlF1oeaaix1x8XzrfjIDK47TY0Zehcw=
|
||||||
github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0=
|
github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0=
|
||||||
@ -158,8 +159,9 @@ github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw
|
|||||||
github.com/golang/protobuf v1.4.3 h1:JjCZWpVbqXDqFVmTfYWEVTMIYrL/NPdPSCHPJ0T/raM=
|
github.com/golang/protobuf v1.4.3 h1:JjCZWpVbqXDqFVmTfYWEVTMIYrL/NPdPSCHPJ0T/raM=
|
||||||
github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
|
github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
|
||||||
github.com/golang/snappy v0.0.0-20170215233205-553a64147049/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
|
github.com/golang/snappy v0.0.0-20170215233205-553a64147049/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
|
||||||
github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db h1:woRePGFeVFfLKN/pOkfl+p/TAqKOfFu+7KPlMVpok/w=
|
|
||||||
github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
|
github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
|
||||||
|
github.com/golang/snappy v0.0.2 h1:aeE13tS0IiQgFjYdoL8qN3K1N2bXXtI6Vi51/y7BpMw=
|
||||||
|
github.com/golang/snappy v0.0.2/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
|
||||||
github.com/gomodule/redigo v2.0.0+incompatible h1:K/R+8tc58AaqLkqG2Ol3Qk+DR/TlNuhuh457pBFPtt0=
|
github.com/gomodule/redigo v2.0.0+incompatible h1:K/R+8tc58AaqLkqG2Ol3Qk+DR/TlNuhuh457pBFPtt0=
|
||||||
github.com/gomodule/redigo v2.0.0+incompatible/go.mod h1:B4C85qUVwatsJoIUNIfCRsp7qO0iAmpGFZ4EELWSbC4=
|
github.com/gomodule/redigo v2.0.0+incompatible/go.mod h1:B4C85qUVwatsJoIUNIfCRsp7qO0iAmpGFZ4EELWSbC4=
|
||||||
github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
|
github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
|
||||||
@ -170,8 +172,9 @@ github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMyw
|
|||||||
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||||
github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||||
github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||||
github.com/google/go-cmp v0.5.1 h1:JFrFEBb2xKufg6XkJsJr+WbKb4FQlURi5RUcBveYu9k=
|
|
||||||
github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||||
|
github.com/google/go-cmp v0.5.2 h1:X2ev0eStA3AbceY54o37/0PQ/UWqKEiiO2dKL5OPaFM=
|
||||||
|
github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||||
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||||
github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
|
github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
|
||||||
github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0=
|
github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0=
|
||||||
@ -256,6 +259,8 @@ github.com/peterh/liner v1.0.1-0.20171122030339-3681c2a91233/go.mod h1:xIteQHvHu
|
|||||||
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||||
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||||
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||||
|
github.com/plutov/paypal/v4 v4.3.7 h1:wPvhAJ3RkDkV+UDrGX/UivXAl5JEPOOJuzsdgnTMJHc=
|
||||||
|
github.com/plutov/paypal/v4 v4.3.7/go.mod h1:D56boafCRGcF/fEM0w282kj0fCDKIyrwOPX/Te1jCmw=
|
||||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||||
github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
|
github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
|
||||||
@ -288,6 +293,8 @@ github.com/siddontang/goredis v0.0.0-20150324035039-760763f78400/go.mod h1:DDcKz
|
|||||||
github.com/siddontang/rdb v0.0.0-20150307021120-fc89ed2e418d/go.mod h1:AMEsy7v5z92TR1JKMkLLoaOQk++LVnOKL3ScbJ8GNGA=
|
github.com/siddontang/rdb v0.0.0-20150307021120-fc89ed2e418d/go.mod h1:AMEsy7v5z92TR1JKMkLLoaOQk++LVnOKL3ScbJ8GNGA=
|
||||||
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
|
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
|
||||||
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
|
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
|
||||||
|
github.com/smartwalle/paypal v1.0.1 h1:ND+oaF6RLQUkZkKidZfpxSwF+2hwNRtqnxg5Uh0IAMA=
|
||||||
|
github.com/smartwalle/paypal v1.0.1/go.mod h1:ekWe8RJjRGCkdpzpRsFRwFe5AvrN3DV4l6ySGLxBl+w=
|
||||||
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d h1:zE9ykElWQ6/NYmHa3jpm/yHnI4xSofP+UP6SpjHcSeM=
|
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d h1:zE9ykElWQ6/NYmHa3jpm/yHnI4xSofP+UP6SpjHcSeM=
|
||||||
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
|
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
|
||||||
github.com/smartystreets/goconvey v0.0.0-20190330032615-68dc04aab96a/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
|
github.com/smartystreets/goconvey v0.0.0-20190330032615-68dc04aab96a/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
|
||||||
@ -300,6 +307,7 @@ github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXf
|
|||||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||||
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
||||||
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
|
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
|
||||||
|
github.com/stretchr/testify v1.6.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||||
github.com/stretchr/testify v1.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd0=
|
github.com/stretchr/testify v1.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd0=
|
||||||
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||||
github.com/syndtr/goleveldb v0.0.0-20160425020131-cfa635847112/go.mod h1:Z4AUp2Km+PwemOoO/VB5AOx9XSsIItzFjoJlOSiYmn0=
|
github.com/syndtr/goleveldb v0.0.0-20160425020131-cfa635847112/go.mod h1:Z4AUp2Km+PwemOoO/VB5AOx9XSsIItzFjoJlOSiYmn0=
|
||||||
@ -310,20 +318,30 @@ github.com/tencentcloud/tencentcloud-sdk-go v1.0.154 h1:THBgwGwUQtsw6L53cSSA2wwL
|
|||||||
github.com/tencentcloud/tencentcloud-sdk-go v1.0.154/go.mod h1:asUz5BPXxgoPGaRgZaVm1iGcUAuHyYUo1nXqKa83cvI=
|
github.com/tencentcloud/tencentcloud-sdk-go v1.0.154/go.mod h1:asUz5BPXxgoPGaRgZaVm1iGcUAuHyYUo1nXqKa83cvI=
|
||||||
github.com/thanhpk/randstr v1.0.4 h1:IN78qu/bR+My+gHCvMEXhR/i5oriVHcTB/BJJIRTsNo=
|
github.com/thanhpk/randstr v1.0.4 h1:IN78qu/bR+My+gHCvMEXhR/i5oriVHcTB/BJJIRTsNo=
|
||||||
github.com/thanhpk/randstr v1.0.4/go.mod h1:M/H2P1eNLZzlDwAzpkkkUvoyNNMbzRGhESZuEQk3r0U=
|
github.com/thanhpk/randstr v1.0.4/go.mod h1:M/H2P1eNLZzlDwAzpkkkUvoyNNMbzRGhESZuEQk3r0U=
|
||||||
|
github.com/tidwall/pretty v1.0.2/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk=
|
||||||
github.com/ugorji/go v0.0.0-20171122102828-84cb69a8af83/go.mod h1:hnLbHMwcvSihnDhEfx2/BzKp2xb0Y+ErdfYcrs9tkJQ=
|
github.com/ugorji/go v0.0.0-20171122102828-84cb69a8af83/go.mod h1:hnLbHMwcvSihnDhEfx2/BzKp2xb0Y+ErdfYcrs9tkJQ=
|
||||||
github.com/volcengine/volc-sdk-golang v1.0.19 h1:jJp+aJgK0e//rZ9I0K2Y7ufJwvuZRo/AQsYDynXMNgA=
|
github.com/volcengine/volc-sdk-golang v1.0.19 h1:jJp+aJgK0e//rZ9I0K2Y7ufJwvuZRo/AQsYDynXMNgA=
|
||||||
github.com/volcengine/volc-sdk-golang v1.0.19/go.mod h1:+GGi447k4p1I5PNdbpG2GLaF0Ui9vIInTojMM0IfSS4=
|
github.com/volcengine/volc-sdk-golang v1.0.19/go.mod h1:+GGi447k4p1I5PNdbpG2GLaF0Ui9vIInTojMM0IfSS4=
|
||||||
|
github.com/w3liu/go-common v0.0.0-20210108072342-826b2f3582be h1:NW489IqqgOz/+fV4oDC2NJqQFH+gYYQt8WRLj4v94Ok=
|
||||||
|
github.com/w3liu/go-common v0.0.0-20210108072342-826b2f3582be/go.mod h1:yHAS/DWXivtrBrO4K45DpIFjQ6LgOi4bUBz7A1iClsE=
|
||||||
github.com/wendal/errors v0.0.0-20130201093226-f66c77a7882b/go.mod h1:Q12BUT7DqIlHRmgv3RskH+UCM/4eqVMgI0EMmlSpAXc=
|
github.com/wendal/errors v0.0.0-20130201093226-f66c77a7882b/go.mod h1:Q12BUT7DqIlHRmgv3RskH+UCM/4eqVMgI0EMmlSpAXc=
|
||||||
|
github.com/xdg/scram v0.0.0-20180814205039-7eeb5667e42c/go.mod h1:lB8K/P019DLNhemzwFU4jHLhdvlE6uDZjXFejJXr49I=
|
||||||
|
github.com/xdg/stringprep v1.0.0/go.mod h1:Jhud4/sHMO4oL310DaZAKk9ZaJ08SJfe+sJh0HrGL1Y=
|
||||||
github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||||
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||||
github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||||
github.com/yuin/gopher-lua v0.0.0-20171031051903-609c9cd26973/go.mod h1:aEV29XrmTYFr3CiRxZeGHpkvbwq+prZduBqMaascyCU=
|
github.com/yuin/gopher-lua v0.0.0-20171031051903-609c9cd26973/go.mod h1:aEV29XrmTYFr3CiRxZeGHpkvbwq+prZduBqMaascyCU=
|
||||||
github.com/ziutek/mymysql v1.5.4/go.mod h1:LMSpPZ6DbqWFxNCHW77HeMg9I646SAhApZ/wKdgO/C0=
|
github.com/ziutek/mymysql v1.5.4/go.mod h1:LMSpPZ6DbqWFxNCHW77HeMg9I646SAhApZ/wKdgO/C0=
|
||||||
|
go.mongodb.org/mongo-driver v1.2.0/go.mod h1:u7ryQJ+DOzQmeO7zB6MHyr8jkEQvC8vH7qLUO4lqsUM=
|
||||||
go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
|
go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
|
||||||
go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8=
|
go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8=
|
||||||
go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
|
go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
|
||||||
go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
|
go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
|
||||||
go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
|
go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
|
||||||
|
go.uber.org/atomic v1.6.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ=
|
||||||
|
go.uber.org/multierr v1.5.0/go.mod h1:FeouvMocqHpRaaGuG9EjoKcStLC43Zu/fmqdUMPcKYU=
|
||||||
|
go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9Ejo0C68/HhF8uaILCdgjnY+goOA=
|
||||||
|
go.uber.org/zap v1.16.0/go.mod h1:MA8QOfq0BHJwdXa996Y4dYkAqRKB8/1K1QMMZVaNZjQ=
|
||||||
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||||
golang.org/x/crypto v0.0.0-20190325154230-a5d413f7728c/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
golang.org/x/crypto v0.0.0-20190325154230-a5d413f7728c/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||||
@ -475,6 +493,8 @@ golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgw
|
|||||||
golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||||
golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||||
golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||||
|
golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||||
|
golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||||
golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||||
golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||||
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||||
@ -598,6 +618,7 @@ gopkg.in/ini.v1 v1.42.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
|
|||||||
gopkg.in/ini.v1 v1.62.0 h1:duBzk771uxoUuOlyRLkHsygud9+5lrlGjdFBb4mSKDU=
|
gopkg.in/ini.v1 v1.62.0 h1:duBzk771uxoUuOlyRLkHsygud9+5lrlGjdFBb4mSKDU=
|
||||||
gopkg.in/ini.v1 v1.62.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
|
gopkg.in/ini.v1 v1.62.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
|
||||||
gopkg.in/mgo.v2 v2.0.0-20190816093944-a6b53ec6cb22/go.mod h1:yeKp02qBN3iKW1OzL3MGk2IdtZzaj7SFntXj72NppTA=
|
gopkg.in/mgo.v2 v2.0.0-20190816093944-a6b53ec6cb22/go.mod h1:yeKp02qBN3iKW1OzL3MGk2IdtZzaj7SFntXj72NppTA=
|
||||||
|
gopkg.in/natefinch/lumberjack.v2 v2.0.0/go.mod h1:l0ndWWf7gzL7RNwBG7wST/UCcT4T24xpD6X8LsfU/+k=
|
||||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=
|
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=
|
||||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
|
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
|
||||||
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
@ -622,5 +643,6 @@ xorm.io/builder v0.3.7 h1:2pETdKRK+2QG4mLX4oODHEhn5Z8j1m8sXa7jfu+/SZI=
|
|||||||
xorm.io/builder v0.3.7/go.mod h1:aUW0S9eb9VCaPohFCH3j7czOx1PMW3i1HrSzbLYGBSE=
|
xorm.io/builder v0.3.7/go.mod h1:aUW0S9eb9VCaPohFCH3j7czOx1PMW3i1HrSzbLYGBSE=
|
||||||
xorm.io/core v0.7.2 h1:mEO22A2Z7a3fPaZMk6gKL/jMD80iiyNwRrX5HOv3XLw=
|
xorm.io/core v0.7.2 h1:mEO22A2Z7a3fPaZMk6gKL/jMD80iiyNwRrX5HOv3XLw=
|
||||||
xorm.io/core v0.7.2/go.mod h1:jJfd0UAEzZ4t87nbQYtVjmqpIODugN6PD2D9E+dJvdM=
|
xorm.io/core v0.7.2/go.mod h1:jJfd0UAEzZ4t87nbQYtVjmqpIODugN6PD2D9E+dJvdM=
|
||||||
xorm.io/xorm v1.0.3 h1:3dALAohvINu2mfEix5a5x5ZmSVGSljinoSGgvGbaZp0=
|
|
||||||
xorm.io/xorm v1.0.3/go.mod h1:uF9EtbhODq5kNWxMbnBEj8hRRZnlcNSz2t2N7HW/+A4=
|
xorm.io/xorm v1.0.3/go.mod h1:uF9EtbhODq5kNWxMbnBEj8hRRZnlcNSz2t2N7HW/+A4=
|
||||||
|
xorm.io/xorm v1.0.6 h1:7eco1c8QUpGz+3dztpLDj9gU1bTiQdFC/KtmPaLxUJk=
|
||||||
|
xorm.io/xorm v1.0.6/go.mod h1:uF9EtbhODq5kNWxMbnBEj8hRRZnlcNSz2t2N7HW/+A4=
|
||||||
|
@ -147,4 +147,9 @@ func (a *Adapter) createTable() {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
err = a.Engine.Sync2(new(Payment))
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -46,6 +46,10 @@ func (application *Application) GetStorageProvider() *Provider {
|
|||||||
return application.GetProviderByCategory("Storage")
|
return application.GetProviderByCategory("Storage")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (application *Application) GetPayProvider() *Provider {
|
||||||
|
return application.GetProviderByCategory("Pay")
|
||||||
|
}
|
||||||
|
|
||||||
func (application *Application) getSignupItem(itemName string) *SignupItem {
|
func (application *Application) getSignupItem(itemName string) *SignupItem {
|
||||||
for _, signupItem := range application.SignupItems {
|
for _, signupItem := range application.SignupItems {
|
||||||
if signupItem.Name == itemName {
|
if signupItem.Name == itemName {
|
||||||
|
8
object/pay_item.go
Normal file
8
object/pay_item.go
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
package object
|
||||||
|
|
||||||
|
type PayItem struct {
|
||||||
|
Invoice string `json:"invoice"`
|
||||||
|
Price string `json:"price"`
|
||||||
|
Description string `json:"description"`
|
||||||
|
Currency string `json:"currency"`
|
||||||
|
}
|
74
object/payment.go
Normal file
74
object/payment.go
Normal file
@ -0,0 +1,74 @@
|
|||||||
|
package object
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/plutov/paypal/v4"
|
||||||
|
"xorm.io/core"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Payment struct {
|
||||||
|
Id string `xorm:"varchar(100) notnull pk" json:"id"`
|
||||||
|
Invoice string `xorm:"varchar(100)" json:"invoice"`
|
||||||
|
Application string `xorm:"varchar(100)" json:"application"`
|
||||||
|
PayItem PayItem `xorm:"json varchar(1000)" json:"pay_item"`
|
||||||
|
Payer *paypal.PayerWithNameAndPhone `xorm:"json varchar(1000)" json:"payer"`
|
||||||
|
Purchase []paypal.CapturedPurchaseUnit `xorm:"varchar(10000)" json:"purchase"`
|
||||||
|
Status string `xorm:"varchar(100)" json:"status"`
|
||||||
|
CreateTime string `xorm:"varchar(100) created" json:"create_time"`
|
||||||
|
UpdateTime string `xorm:"varchar(100) updated" json:"update_time"`
|
||||||
|
Callback string `xorm:"varchar(1000)" json:"callback"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func AddPayment(pay *Payment) bool {
|
||||||
|
affected, err := adapter.Engine.Insert(pay)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return affected != 0
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetPayments() []*Payment {
|
||||||
|
pays := []*Payment{}
|
||||||
|
err := adapter.Engine.Desc("create_time").Find(&pays)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return pays
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetPayment(id string) *Payment {
|
||||||
|
pay := Payment{Id: id}
|
||||||
|
existed, err := adapter.Engine.Get(&pay)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if existed {
|
||||||
|
return &pay
|
||||||
|
} else {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func DeletePayment(payment *Payment) bool {
|
||||||
|
affected, err := adapter.Engine.ID(core.PK{payment.Id}).Delete(&Payment{})
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return affected != 0
|
||||||
|
}
|
||||||
|
|
||||||
|
func UpdatePay(id string, pay *Payment) bool {
|
||||||
|
if GetPayment(id) == nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
affected, err := adapter.Engine.ID(core.PK{id}).AllCols().Update(pay)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return affected != 0
|
||||||
|
}
|
105
payment/paypal.go
Normal file
105
payment/paypal.go
Normal file
@ -0,0 +1,105 @@
|
|||||||
|
package payment
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/astaxie/beego"
|
||||||
|
"github.com/casbin/casdoor/object"
|
||||||
|
"github.com/plutov/paypal/v4"
|
||||||
|
)
|
||||||
|
|
||||||
|
var client = GetClient()
|
||||||
|
|
||||||
|
func GetClient() *paypal.Client {
|
||||||
|
c, err := paypal.NewClient(beego.AppConfig.String("paypalClientId"), beego.AppConfig.String("paypalSecret"), paypal.APIBaseSandBox)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
return c
|
||||||
|
}
|
||||||
|
|
||||||
|
func Paypal(payItem object.PayItem, clientId string, redirectUri string) string {
|
||||||
|
|
||||||
|
application := object.GetApplicationByClientId(clientId)
|
||||||
|
if application == nil {
|
||||||
|
return "Invalid client_id"
|
||||||
|
}
|
||||||
|
applicationName := fmt.Sprintf("%s/%s", application.Owner, application.Name)
|
||||||
|
if payItem.Currency == "" {
|
||||||
|
payItem.Currency = "USD"
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err := client.GetAccessToken(context.Background())
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
appContext := &paypal.ApplicationContext{
|
||||||
|
ReturnURL: "http://localhost:7001/pay/success", //回调链接
|
||||||
|
CancelURL: "https://www.baidu.com",
|
||||||
|
}
|
||||||
|
|
||||||
|
purchaseUnits := make([]paypal.PurchaseUnitRequest, 1)
|
||||||
|
purchaseUnits[0] = paypal.PurchaseUnitRequest{
|
||||||
|
Amount: &paypal.PurchaseUnitAmount{
|
||||||
|
Currency: payItem.Currency, //收款类型
|
||||||
|
Value: payItem.Price, //收款数量
|
||||||
|
},
|
||||||
|
InvoiceID: payItem.Invoice,
|
||||||
|
Description: payItem.Description,
|
||||||
|
}
|
||||||
|
|
||||||
|
order, err := client.CreateOrder(context.Background(),
|
||||||
|
paypal.OrderIntentCapture,
|
||||||
|
purchaseUnits,
|
||||||
|
&paypal.CreateOrderPayer{},
|
||||||
|
appContext)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
newPay := object.Payment{
|
||||||
|
Id: order.ID,
|
||||||
|
Invoice: payItem.Invoice,
|
||||||
|
PayItem: payItem,
|
||||||
|
Application: applicationName,
|
||||||
|
Status: order.Status,
|
||||||
|
Callback: redirectUri,
|
||||||
|
}
|
||||||
|
|
||||||
|
success := object.AddPayment(&newPay)
|
||||||
|
if success {
|
||||||
|
links := order.Links
|
||||||
|
for _, link := range links {
|
||||||
|
fmt.Println(link.Rel)
|
||||||
|
if link.Rel == "approve" {
|
||||||
|
return link.Href
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return "Add Order to Database false"
|
||||||
|
}
|
||||||
|
|
||||||
|
func SuccessPay(token string) string {
|
||||||
|
_, err := client.GetAccessToken(context.Background())
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
captureOrder, err := client.CaptureOrder(context.Background(), token, paypal.CaptureOrderRequest{})
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
pay := object.GetPayment(captureOrder.ID)
|
||||||
|
pay.Purchase = captureOrder.PurchaseUnits
|
||||||
|
pay.Payer = captureOrder.Payer
|
||||||
|
pay.UpdateTime = time.Now().String()
|
||||||
|
pay.Status = captureOrder.Status
|
||||||
|
object.UpdatePay(captureOrder.ID, pay)
|
||||||
|
if captureOrder.Status == "COMPLETED" {
|
||||||
|
return fmt.Sprintf("%s?paymentId=%s", pay.Callback, token)
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
|
||||||
|
}
|
@ -49,6 +49,7 @@ func initAPI() {
|
|||||||
|
|
||||||
beego.Router("/api/get-organizations", &controllers.ApiController{}, "GET:GetOrganizations")
|
beego.Router("/api/get-organizations", &controllers.ApiController{}, "GET:GetOrganizations")
|
||||||
beego.Router("/api/get-organization", &controllers.ApiController{}, "GET:GetOrganization")
|
beego.Router("/api/get-organization", &controllers.ApiController{}, "GET:GetOrganization")
|
||||||
|
beego.Router("/api/get-application-clientId", &controllers.ApiController{}, "Get:GetApplicationByClientId")
|
||||||
beego.Router("/api/update-organization", &controllers.ApiController{}, "POST:UpdateOrganization")
|
beego.Router("/api/update-organization", &controllers.ApiController{}, "POST:UpdateOrganization")
|
||||||
beego.Router("/api/add-organization", &controllers.ApiController{}, "POST:AddOrganization")
|
beego.Router("/api/add-organization", &controllers.ApiController{}, "POST:AddOrganization")
|
||||||
beego.Router("/api/delete-organization", &controllers.ApiController{}, "POST:DeleteOrganization")
|
beego.Router("/api/delete-organization", &controllers.ApiController{}, "POST:DeleteOrganization")
|
||||||
@ -108,4 +109,9 @@ func initAPI() {
|
|||||||
|
|
||||||
beego.Router("/api/send-email", &controllers.ApiController{}, "POST:SendEmail")
|
beego.Router("/api/send-email", &controllers.ApiController{}, "POST:SendEmail")
|
||||||
beego.Router("/api/send-sms", &controllers.ApiController{}, "POST:SendSms")
|
beego.Router("/api/send-sms", &controllers.ApiController{}, "POST:SendSms")
|
||||||
|
|
||||||
|
beego.Router("/api/paypal", &controllers.ApiController{}, "POST:PaypalPay")
|
||||||
|
beego.Router("/api/success-pay", &controllers.ApiController{}, "GET:SuccessPay")
|
||||||
|
beego.Router("/api/get-payments", &controllers.ApiController{}, "Get:GetPayments")
|
||||||
|
beego.Router("/api/delete-payment", &controllers.ApiController{}, "POST:DeletePayment")
|
||||||
}
|
}
|
||||||
|
116
web/src/App.js
116
web/src/App.js
@ -50,6 +50,9 @@ import AuthCallback from "./auth/AuthCallback";
|
|||||||
import SelectLanguageBox from './SelectLanguageBox';
|
import SelectLanguageBox from './SelectLanguageBox';
|
||||||
import i18next from 'i18next';
|
import i18next from 'i18next';
|
||||||
import PromptPage from "./auth/PromptPage";
|
import PromptPage from "./auth/PromptPage";
|
||||||
|
import PaySuccessCallback from "./PaySuccessCallback";
|
||||||
|
import Pay from "./Pay";
|
||||||
|
import PaymentListPage from "./PaymentListPage";
|
||||||
|
|
||||||
const { Header, Footer } = Layout;
|
const { Header, Footer } = Layout;
|
||||||
|
|
||||||
@ -112,6 +115,8 @@ class App extends Component {
|
|||||||
this.setState({ selectedMenuKey: '/login' });
|
this.setState({ selectedMenuKey: '/login' });
|
||||||
} else if (uri.includes('/result')) {
|
} else if (uri.includes('/result')) {
|
||||||
this.setState({ selectedMenuKey: '/result' });
|
this.setState({ selectedMenuKey: '/result' });
|
||||||
|
}else if (uri.includes('/payment')) {
|
||||||
|
this.setState({ selectedMenuKey: '/payment' });
|
||||||
} else {
|
} else {
|
||||||
this.setState({ selectedMenuKey: -1 });
|
this.setState({ selectedMenuKey: -1 });
|
||||||
}
|
}
|
||||||
@ -354,6 +359,13 @@ class App extends Component {
|
|||||||
</Link>
|
</Link>
|
||||||
</Menu.Item>
|
</Menu.Item>
|
||||||
);
|
);
|
||||||
|
res.push(
|
||||||
|
<Menu.Item key="/payment">
|
||||||
|
<Link to="/payment">
|
||||||
|
{"Payment"}
|
||||||
|
</Link>
|
||||||
|
</Menu.Item>
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
res.push(
|
res.push(
|
||||||
@ -416,6 +428,9 @@ class App extends Component {
|
|||||||
<Route exact path="/tokens" render={(props) => this.renderLoginIfNotLoggedIn(<TokenListPage account={this.state.account} {...props} />)}/>
|
<Route exact path="/tokens" render={(props) => this.renderLoginIfNotLoggedIn(<TokenListPage account={this.state.account} {...props} />)}/>
|
||||||
<Route exact path="/tokens/:tokenName" render={(props) => this.renderLoginIfNotLoggedIn(<TokenEditPage account={this.state.account} {...props} />)}/>
|
<Route exact path="/tokens/:tokenName" render={(props) => this.renderLoginIfNotLoggedIn(<TokenEditPage account={this.state.account} {...props} />)}/>
|
||||||
<Route exact path="/records" render={(props) => this.renderLoginIfNotLoggedIn(<RecordListPage account={this.state.account} {...props} />)}/>
|
<Route exact path="/records" render={(props) => this.renderLoginIfNotLoggedIn(<RecordListPage account={this.state.account} {...props} />)}/>
|
||||||
|
<Route exact path="/payment" render={(props) => this.renderLoginIfNotLoggedIn(<PaymentListPage account={this.state.account} {...props} />)} />
|
||||||
|
<Route exact path="/pay" render={(props) => <Pay account={this.state.account} {...props}/>}/>
|
||||||
|
<Route exact path="/pay/success" render={(props) => <PaySuccessCallback account={this.state.account} {...props}/>}/>
|
||||||
<Route path="" render={() => <Result status="404" title="404 NOT FOUND" subTitle={i18next.t("general:Sorry, the page you visited does not exist.")}
|
<Route path="" render={() => <Result status="404" title="404 NOT FOUND" subTitle={i18next.t("general:Sorry, the page you visited does not exist.")}
|
||||||
extra={<a href="/"><Button type="primary">{i18next.t("general:Back Home")}</Button></a>} />} />
|
extra={<a href="/"><Button type="primary">{i18next.t("general:Back Home")}</Button></a>} />} />
|
||||||
</Switch>
|
</Switch>
|
||||||
@ -428,31 +443,35 @@ class App extends Component {
|
|||||||
return (
|
return (
|
||||||
<div style={{display: 'flex', flex: 'auto',width:"100%",flexDirection: 'column'}}>
|
<div style={{display: 'flex', flex: 'auto',width:"100%",flexDirection: 'column'}}>
|
||||||
<Layout style={{display: 'flex', alignItems: 'stretch'}}>
|
<Layout style={{display: 'flex', alignItems: 'stretch'}}>
|
||||||
<Header style={{ padding: '0', marginBottom: '3px'}}>
|
|
||||||
{
|
{window.location.pathname.indexOf("/pay") != -1 && window.location.pathname.indexOf("/payment") == -1 ?
|
||||||
Setting.isMobile() ? null : (
|
null :
|
||||||
<Link to={"/"}>
|
(<Header style={{ padding: '0', marginBottom: '3px'}}>
|
||||||
<div className="logo" />
|
|
||||||
</Link>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
<Menu
|
|
||||||
// theme="dark"
|
|
||||||
mode={(Setting.isMobile() && this.isStartPages()) ? "inline" : "horizontal"}
|
|
||||||
selectedKeys={[`${this.state.selectedMenuKey}`]}
|
|
||||||
style={{ lineHeight: '64px'}}
|
|
||||||
>
|
|
||||||
{
|
{
|
||||||
this.renderMenu()
|
Setting.isMobile() ? null : (
|
||||||
|
<Link to={"/"}>
|
||||||
|
<div className="logo" />
|
||||||
|
</Link>
|
||||||
|
)
|
||||||
}
|
}
|
||||||
<div style = {{float: 'right'}}>
|
<Menu
|
||||||
{
|
// theme="dark"
|
||||||
this.renderAccount()
|
mode={(Setting.isMobile() && this.isStartPages()) ? "inline" : "horizontal"}
|
||||||
}
|
selectedKeys={[`${this.state.selectedMenuKey}`]}
|
||||||
<SelectLanguageBox/>
|
style={{ lineHeight: '64px'}}
|
||||||
</div>
|
>
|
||||||
</Menu>
|
{
|
||||||
</Header>
|
this.renderMenu()
|
||||||
|
}
|
||||||
|
<div style = {{float: 'right'}}>
|
||||||
|
{
|
||||||
|
this.renderAccount()
|
||||||
|
}
|
||||||
|
<SelectLanguageBox/>
|
||||||
|
</div>
|
||||||
|
</Menu>
|
||||||
|
</Header>)
|
||||||
|
}
|
||||||
<Layout style={{backgroundColor: "#f5f5f5", alignItems: 'stretch'}}>
|
<Layout style={{backgroundColor: "#f5f5f5", alignItems: 'stretch'}}>
|
||||||
<Card className="content-warp-card">
|
<Card className="content-warp-card">
|
||||||
{
|
{
|
||||||
@ -466,31 +485,34 @@ class App extends Component {
|
|||||||
} else {
|
} else {
|
||||||
return(
|
return(
|
||||||
<div>
|
<div>
|
||||||
<Header style={{ padding: '0', marginBottom: '3px'}}>
|
{window.location.pathname.indexOf("/pay") != -1 && window.location.pathname.indexOf("/payment") == -1 ?
|
||||||
{
|
null :
|
||||||
Setting.isMobile() ? null : (
|
<Header style={{ padding: '0', marginBottom: '3px'}}>
|
||||||
<Link to={"/"}>
|
{
|
||||||
<div className="logo" />
|
Setting.isMobile() ? null : (
|
||||||
</Link>
|
<Link to={"/"}>
|
||||||
)
|
<div className="logo" />
|
||||||
|
</Link>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
<Menu
|
||||||
|
// theme="dark"
|
||||||
|
mode={(Setting.isMobile() && this.isStartPages()) ? "inline" : "horizontal"}
|
||||||
|
selectedKeys={[`${this.state.selectedMenuKey}`]}
|
||||||
|
style={{ lineHeight: '64px' }}
|
||||||
|
>
|
||||||
|
{
|
||||||
|
this.renderMenu()
|
||||||
|
}
|
||||||
|
<div style = {{float: 'right'}}>
|
||||||
|
{
|
||||||
|
this.renderAccount()
|
||||||
|
}
|
||||||
|
<SelectLanguageBox/>
|
||||||
|
</div>
|
||||||
|
</Menu>
|
||||||
|
</Header>
|
||||||
}
|
}
|
||||||
<Menu
|
|
||||||
// theme="dark"
|
|
||||||
mode={(Setting.isMobile() && this.isStartPages()) ? "inline" : "horizontal"}
|
|
||||||
selectedKeys={[`${this.state.selectedMenuKey}`]}
|
|
||||||
style={{ lineHeight: '64px' }}
|
|
||||||
>
|
|
||||||
{
|
|
||||||
this.renderMenu()
|
|
||||||
}
|
|
||||||
<div style = {{float: 'right'}}>
|
|
||||||
{
|
|
||||||
this.renderAccount()
|
|
||||||
}
|
|
||||||
<SelectLanguageBox/>
|
|
||||||
</div>
|
|
||||||
</Menu>
|
|
||||||
</Header>
|
|
||||||
{
|
{
|
||||||
this.renderRouter()
|
this.renderRouter()
|
||||||
}
|
}
|
||||||
|
176
web/src/Pay.js
Normal file
176
web/src/Pay.js
Normal file
@ -0,0 +1,176 @@
|
|||||||
|
// Copyright 2021 The casbin Authors. All Rights Reserved.
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
import React from "react";
|
||||||
|
import {Button, Result, Spin, Form, Input,} from "antd";
|
||||||
|
import {withRouter} from "react-router-dom";
|
||||||
|
import * as PaymentBackend from "./backend/PaymentBackend"
|
||||||
|
import * as ApplicationBackend from "./backend/ApplicationBackend"
|
||||||
|
|
||||||
|
class Pay extends React.Component {
|
||||||
|
constructor(props) {
|
||||||
|
super(props);
|
||||||
|
this.state = {
|
||||||
|
msg: null,
|
||||||
|
classes: props,
|
||||||
|
clientId: this.GetQueryString("clientId"),
|
||||||
|
invoice: this.GetQueryString("invoice"),
|
||||||
|
price: this.GetQueryString("price"),
|
||||||
|
currency: this.GetQueryString("currency"),
|
||||||
|
description: this.GetQueryString("description"),
|
||||||
|
redirectUri: this.GetQueryString("redirectUri"),
|
||||||
|
waiting: false,
|
||||||
|
applicationName: "",
|
||||||
|
wrongMsg: "",
|
||||||
|
spinMsg: "正在生成订单..."
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
UNSAFE_componentWillMount() {
|
||||||
|
this.getApplication();
|
||||||
|
}
|
||||||
|
|
||||||
|
getApplication(){
|
||||||
|
ApplicationBackend.getApplicationByClientId(this.state.clientId).then(res => {
|
||||||
|
if(res == null){
|
||||||
|
this.setState({
|
||||||
|
wrongMsg: "Invalid clientID"
|
||||||
|
})
|
||||||
|
}else {
|
||||||
|
console.log("res")
|
||||||
|
console.log(res)
|
||||||
|
this.setState({
|
||||||
|
applicationName : res.displayName
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
GetQueryString(key){
|
||||||
|
let reg = new RegExp("(^|&)"+ key +"=([^&]*)(&|$)");
|
||||||
|
let r = window.location.search.substr(1).match(reg);
|
||||||
|
if(r!=null)return unescape(r[2]); return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
getCurrencyString(currency){
|
||||||
|
if(currency === "USD"){
|
||||||
|
return "$"
|
||||||
|
}else if (currency === "CNY"){
|
||||||
|
return "¥"
|
||||||
|
}else if (currency === "EUR"){
|
||||||
|
return "€"
|
||||||
|
}
|
||||||
|
return "$"
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
pay(){
|
||||||
|
let payItem = {
|
||||||
|
invoice: this.state.invoice,
|
||||||
|
price : this.state.price,
|
||||||
|
currency : this.state.currency,
|
||||||
|
description : this.state.description
|
||||||
|
}
|
||||||
|
this.setState({
|
||||||
|
waiting: true
|
||||||
|
})
|
||||||
|
|
||||||
|
PaymentBackend.PaypalPal(payItem, this.state.clientId, this.state.redirectUri).then(res => {
|
||||||
|
console.log(res)
|
||||||
|
if (res.indexOf("http") !== -1){
|
||||||
|
this.setState({
|
||||||
|
spinMsg: "前往支付页面"
|
||||||
|
})
|
||||||
|
window.location.replace(res);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
this.setState({
|
||||||
|
wrongMsg : res
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const data = [
|
||||||
|
{
|
||||||
|
title: 'Invoice',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'Amount',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'Description',
|
||||||
|
}
|
||||||
|
];
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
{
|
||||||
|
(this.state.wrongMsg === "") ?
|
||||||
|
(<div style={{textAlign: "center"}}>
|
||||||
|
{
|
||||||
|
(this.state.waiting) ? (
|
||||||
|
<Spin size="large" tip={this.state.spinMsg} style={{paddingTop: "10%"}} />
|
||||||
|
) : (
|
||||||
|
<div style={{display: "inline"}}>
|
||||||
|
<p style={{fontSize: 20}}>{`尊敬的用户,您正在通过 casdoor 向 ${this.state.applicationName} 进行付款,请确认`}</p>
|
||||||
|
<Form
|
||||||
|
size="large"
|
||||||
|
name="pay"
|
||||||
|
labelCol={{ span: 8 }}
|
||||||
|
wrapperCol={{ span: 8 }}
|
||||||
|
initialValues={{ remember: true }}
|
||||||
|
autoComplete="off"
|
||||||
|
>
|
||||||
|
<Form.Item
|
||||||
|
label="Invoice"
|
||||||
|
>
|
||||||
|
<Input style={{color: "black"}} value={this.state.invoice} bordered={false} disabled />
|
||||||
|
</Form.Item>
|
||||||
|
|
||||||
|
<Form.Item
|
||||||
|
label="Account"
|
||||||
|
>
|
||||||
|
<Input style={{color: "black"}} disabled bordered={false} value={`${this.getCurrencyString(this.state.currency)} ${this.state.price}`}/>
|
||||||
|
</Form.Item>
|
||||||
|
|
||||||
|
<Form.Item
|
||||||
|
label="Description"
|
||||||
|
>
|
||||||
|
<Input style={{color: "black"}} bordered={false} disabled value={`${this.state.description}`}/>
|
||||||
|
</Form.Item>
|
||||||
|
|
||||||
|
<Form.Item wrapperCol={{ offset: 8, span: 8 }}>
|
||||||
|
<Button size="large" type="primary" onClick={() => this.pay()}>
|
||||||
|
确认付款
|
||||||
|
</Button>
|
||||||
|
</Form.Item>
|
||||||
|
</Form>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
</div>) :
|
||||||
|
( <div style={{display: "inline"}}>
|
||||||
|
<Result
|
||||||
|
status="error"
|
||||||
|
title="Pay Error"
|
||||||
|
subTitle={this.state.wrongMsg}
|
||||||
|
/>
|
||||||
|
</div>)
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default withRouter(Pay);
|
71
web/src/PaySuccessCallback.js
Normal file
71
web/src/PaySuccessCallback.js
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
// Copyright 2021 The casbin Authors. All Rights Reserved.
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
import React from "react";
|
||||||
|
import {Button, Result, Spin} from "antd";
|
||||||
|
import {withRouter} from "react-router-dom";
|
||||||
|
import * as PaymentBackend from "./backend/PaymentBackend"
|
||||||
|
|
||||||
|
class PaySuccessCallback extends React.Component {
|
||||||
|
constructor(props) {
|
||||||
|
super(props);
|
||||||
|
this.state = {
|
||||||
|
classes: props,
|
||||||
|
msg: null,
|
||||||
|
paymentId: this.GetQueryString("token"),
|
||||||
|
payerId: this.GetQueryString("PayerID")
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// eslint-disable-next-line react/no-deprecated
|
||||||
|
componentWillMount() {
|
||||||
|
PaymentBackend.PaySuccess(this.state.paymentId, this.state.payerId).then(res => {
|
||||||
|
window.location.href = res
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
GetQueryString(key){
|
||||||
|
let reg = new RegExp("(^|&)"+ key +"=([^&]*)(&|$)");
|
||||||
|
let r = window.location.search.substr(1).match(reg);
|
||||||
|
if(r!=null)return unescape(r[2]); return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
return (
|
||||||
|
<div style={{textAlign: "center"}}>
|
||||||
|
{
|
||||||
|
(this.state.msg === null) ? (
|
||||||
|
<Spin size="large" tip="支付完成,正在跳转..." style={{paddingTop: "10%"}} />
|
||||||
|
) : (
|
||||||
|
<div style={{display: "inline"}}>
|
||||||
|
<Result
|
||||||
|
status="error"
|
||||||
|
title="Login Error"
|
||||||
|
subTitle={this.state.msg}
|
||||||
|
extra={[
|
||||||
|
<Button type="primary" key="details">
|
||||||
|
Details
|
||||||
|
</Button>,
|
||||||
|
<Button key="help">Help</Button>,
|
||||||
|
]}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default withRouter(PaySuccessCallback);
|
208
web/src/PaymentListPage.js
Normal file
208
web/src/PaymentListPage.js
Normal file
@ -0,0 +1,208 @@
|
|||||||
|
// Copyright 2021 The casbin Authors. All Rights Reserved.
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
import React from "react";
|
||||||
|
import {Link} from "react-router-dom";
|
||||||
|
import {Button, Popconfirm, Table} from 'antd';
|
||||||
|
import moment from "moment";
|
||||||
|
import * as Setting from "./Setting";
|
||||||
|
import * as PaymentBackend from "./backend/PaymentBackend";
|
||||||
|
import i18next from "i18next";
|
||||||
|
|
||||||
|
class PaymentListPage extends React.Component {
|
||||||
|
constructor(props) {
|
||||||
|
super(props);
|
||||||
|
this.state = {
|
||||||
|
classes: props,
|
||||||
|
payments: [],
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
UNSAFE_componentWillMount() {
|
||||||
|
this.getPayments();
|
||||||
|
}
|
||||||
|
|
||||||
|
getPayments() {
|
||||||
|
PaymentBackend.getPayments().then(res => {
|
||||||
|
this.setState({
|
||||||
|
payments: res
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
deletePayment(i) {
|
||||||
|
PaymentBackend.deletePayment(this.state.payments[i]).then(res => {
|
||||||
|
Setting.showMessage("success", `Payment deleted successfully`);
|
||||||
|
this.setState({
|
||||||
|
payments: Setting.deleteRow(this.state.payments, i),
|
||||||
|
});
|
||||||
|
}).catch(error => {
|
||||||
|
Setting.showMessage("error", `Payment failed to delete: ${error}`);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
renderTable(payments) {
|
||||||
|
const columns = [
|
||||||
|
{
|
||||||
|
title: "Id",
|
||||||
|
dataIndex: 'id',
|
||||||
|
key: 'id',
|
||||||
|
width: (Setting.isMobile()) ? "100px" : "170px",
|
||||||
|
fixed: 'left',
|
||||||
|
sorter: (a, b) => a.id.localeCompare(b.id),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "invoice",
|
||||||
|
dataIndex: 'invoice',
|
||||||
|
key: 'invoice',
|
||||||
|
width: '150px',
|
||||||
|
sorter: (a, b) => a.invoice.localeCompare(b.invoice),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "Application",
|
||||||
|
dataIndex: 'application',
|
||||||
|
key: 'application',
|
||||||
|
width: '120px',
|
||||||
|
sorter: (a, b) => a.application.localeCompare(b.application),
|
||||||
|
render: (text, record, index) => {
|
||||||
|
return (
|
||||||
|
<Link to={`/applications/${text.substring(text.indexOf("/")+1)}`}>
|
||||||
|
{text}
|
||||||
|
</Link>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "Amount",
|
||||||
|
dataIndex: 'pay_item',
|
||||||
|
key: 'pay_item',
|
||||||
|
width: '150px',
|
||||||
|
ellipsis: true,
|
||||||
|
render: (text, record, index) => {
|
||||||
|
return (
|
||||||
|
`amount: ${text.currency} ${text.price}`
|
||||||
|
)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "Status",
|
||||||
|
dataIndex: 'status',
|
||||||
|
key: 'status',
|
||||||
|
width: '120px',
|
||||||
|
sorter: (a, b) => a.status.localeCompare(b.status),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "Payer",
|
||||||
|
dataIndex: 'payer',
|
||||||
|
key: 'payer',
|
||||||
|
width: '120px',
|
||||||
|
render: (text, record, index) => {
|
||||||
|
return (
|
||||||
|
text === null ? "" : (
|
||||||
|
`${text?.name.surname} ${text?.name.given_name}`
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "Payer Email",
|
||||||
|
dataIndex: 'payer',
|
||||||
|
key: 'payer',
|
||||||
|
width: '160px',
|
||||||
|
ellipsis: true,
|
||||||
|
render: (text, record, index) => {
|
||||||
|
return (
|
||||||
|
text === null ? "" : text.email_address
|
||||||
|
)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "Create_time",
|
||||||
|
dataIndex: 'create_time',
|
||||||
|
key: 'create_time',
|
||||||
|
width: '150px',
|
||||||
|
sorter: (a, b) => a.create_time.localeCompare(b.create_time),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "update_time",
|
||||||
|
dataIndex: 'update_time',
|
||||||
|
key: 'update_time',
|
||||||
|
width: '150px',
|
||||||
|
sorter: (a, b) => a.update_time.localeCompare(b.update_time),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "description",
|
||||||
|
dataIndex: 'pay_item',
|
||||||
|
key: 'pay_item',
|
||||||
|
ellipsis: true,
|
||||||
|
width: '150px',
|
||||||
|
render: (text, record, index) => {
|
||||||
|
return (
|
||||||
|
text.description
|
||||||
|
)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "Callback",
|
||||||
|
dataIndex: 'callback',
|
||||||
|
key: 'callback',
|
||||||
|
width: '100px',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: i18next.t("general:Action"),
|
||||||
|
dataIndex: '',
|
||||||
|
key: 'op',
|
||||||
|
width: '80px',
|
||||||
|
fixed: (Setting.isMobile()) ? "false" : "right",
|
||||||
|
render: (text, record, index) => {
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<Popconfirm
|
||||||
|
title={`Sure to delete this payment ?`}
|
||||||
|
onConfirm={() => this.deletePayment(index)}
|
||||||
|
>
|
||||||
|
<Button style={{marginBottom: '10px'}} type="danger">{i18next.t("general:Delete")}</Button>
|
||||||
|
</Popconfirm>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<Table scroll={{x: 'max-content'}} columns={columns} dataSource={payments} rowKey="name" size="middle" bordered pagination={{pageSize: 100}}
|
||||||
|
title={() => (
|
||||||
|
<div>
|
||||||
|
{"Payments"}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
loading={payments === null}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
{
|
||||||
|
this.renderTable(this.state.payments)
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default PaymentListPage;
|
@ -102,6 +102,12 @@ class ProviderEditPage extends React.Component {
|
|||||||
{id: 'Aliyun OSS', name: 'Aliyun OSS'},
|
{id: 'Aliyun OSS', name: 'Aliyun OSS'},
|
||||||
]
|
]
|
||||||
);
|
);
|
||||||
|
} else if (provider.category === "Payment") {
|
||||||
|
return (
|
||||||
|
[
|
||||||
|
{id: 'Paypal', name: 'PayPay'}
|
||||||
|
]
|
||||||
|
)
|
||||||
} else {
|
} else {
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
@ -201,6 +207,8 @@ class ProviderEditPage extends React.Component {
|
|||||||
} else if (value === "Storage") {
|
} else if (value === "Storage") {
|
||||||
this.updateProviderField('type', 'Local File System');
|
this.updateProviderField('type', 'Local File System');
|
||||||
this.updateProviderField('domain', Setting.getFullServerUrl());
|
this.updateProviderField('domain', Setting.getFullServerUrl());
|
||||||
|
} else if (value === "Pay") {
|
||||||
|
this.updateProviderField('type', 'Paypal')
|
||||||
}
|
}
|
||||||
})}>
|
})}>
|
||||||
{
|
{
|
||||||
@ -209,6 +217,7 @@ class ProviderEditPage extends React.Component {
|
|||||||
{id: 'Email', name: 'Email'},
|
{id: 'Email', name: 'Email'},
|
||||||
{id: 'SMS', name: 'SMS'},
|
{id: 'SMS', name: 'SMS'},
|
||||||
{id: 'Storage', name: 'Storage'},
|
{id: 'Storage', name: 'Storage'},
|
||||||
|
{id: 'Payment', name: 'Payment'}
|
||||||
].map((providerCategory, index) => <Option key={index} value={providerCategory.id}>{providerCategory.name}</Option>)
|
].map((providerCategory, index) => <Option key={index} value={providerCategory.id}>{providerCategory.name}</Option>)
|
||||||
}
|
}
|
||||||
</Select>
|
</Select>
|
||||||
|
@ -151,6 +151,7 @@ class ProviderTable extends React.Component {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
// {
|
// {
|
||||||
// title: i18next.t("provider:alertType"),
|
// title: i18next.t("provider:alertType"),
|
||||||
// dataIndex: 'alertType',
|
// dataIndex: 'alertType',
|
||||||
|
@ -62,3 +62,10 @@ export function deleteApplication(application) {
|
|||||||
body: JSON.stringify(newApplication),
|
body: JSON.stringify(newApplication),
|
||||||
}).then(res => res.json());
|
}).then(res => res.json());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function getApplicationByClientId(clientId){
|
||||||
|
return fetch(`${Setting.ServerUrl}/api/get-application-clientId?clientId=${clientId}`, {
|
||||||
|
method: "GET",
|
||||||
|
credentials: "include"
|
||||||
|
}).then(res => res.json());
|
||||||
|
}
|
||||||
|
47
web/src/backend/PaymentBackend.js
Normal file
47
web/src/backend/PaymentBackend.js
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
// Copyright 2021 The casbin Authors. All Rights Reserved.
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
import * as Setting from "../Setting";
|
||||||
|
|
||||||
|
export function PaySuccess(paymentId, payerID){
|
||||||
|
return fetch(`${Setting.ServerUrl}/api/success-pay?paymentId=${paymentId}&payerId=${payerID}`, {
|
||||||
|
method: "GET",
|
||||||
|
credentials: "include",
|
||||||
|
}).then(res => res.json())
|
||||||
|
}
|
||||||
|
|
||||||
|
export function PaypalPal(payItem,clientId, redirectUri) {
|
||||||
|
return fetch(`http://localhost:8000/api/paypal?clientId=${clientId}&redirectUri=${redirectUri}`, {
|
||||||
|
method: "POST",
|
||||||
|
credentials: "include",
|
||||||
|
body: JSON.stringify(payItem),
|
||||||
|
}).then(res => res.json());
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getPayments(){
|
||||||
|
return fetch(`${Setting.ServerUrl}/api/get-payments?`, {
|
||||||
|
method: "GET",
|
||||||
|
credentials: "include"
|
||||||
|
}).then(res => res.json());
|
||||||
|
}
|
||||||
|
|
||||||
|
export function deletePayment(payment){
|
||||||
|
let newPayment = Setting.deepCopy(payment);
|
||||||
|
return fetch(`${Setting.ServerUrl}/api/delete-payment`, {
|
||||||
|
method: 'POST',
|
||||||
|
credentials: 'include',
|
||||||
|
body: JSON.stringify(newPayment),
|
||||||
|
}).then(res => res.json());
|
||||||
|
}
|
||||||
|
|
Loading…
x
Reference in New Issue
Block a user