mirror of
https://github.com/casdoor/casdoor.git
synced 2025-07-08 00:50:28 +08:00
Add gc provider.
This commit is contained in:
@ -164,12 +164,15 @@ func BuyProduct(id string, providerId string, user *User, host string) (string,
|
|||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
|
|
||||||
cert := getCert(product.Owner, provider.Cert)
|
cert := &Cert{}
|
||||||
if cert == nil {
|
if provider.Cert != "" {
|
||||||
return "", fmt.Errorf("the cert: %s does not exist", provider.Cert)
|
cert = getCert(product.Owner, provider.Cert)
|
||||||
|
if cert == nil {
|
||||||
|
return "", fmt.Errorf("the cert: %s does not exist", provider.Cert)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pProvider := pp.GetPaymentProvider(provider.Type, provider.ClientId, cert.PublicKey, cert.PrivateKey, cert.AuthorityPublicKey, cert.AuthorityRootPublicKey)
|
pProvider := pp.GetPaymentProvider(provider.Type, provider.ClientId, provider.ClientSecret, provider.Host, cert.PublicKey, cert.PrivateKey, cert.AuthorityPublicKey, cert.AuthorityRootPublicKey)
|
||||||
if pProvider == nil {
|
if pProvider == nil {
|
||||||
return "", fmt.Errorf("the payment provider type: %s is not supported", provider.Type)
|
return "", fmt.Errorf("the payment provider type: %s is not supported", provider.Type)
|
||||||
}
|
}
|
||||||
|
@ -29,7 +29,7 @@ func TestProduct(t *testing.T) {
|
|||||||
product := GetProduct("admin/product_123")
|
product := GetProduct("admin/product_123")
|
||||||
provider := getProvider(product.Owner, "provider_pay_alipay")
|
provider := getProvider(product.Owner, "provider_pay_alipay")
|
||||||
cert := getCert(product.Owner, "cert-pay-alipay")
|
cert := getCert(product.Owner, "cert-pay-alipay")
|
||||||
pProvider := pp.GetPaymentProvider(provider.Type, provider.ClientId, cert.PublicKey, cert.PrivateKey, cert.AuthorityPublicKey, cert.AuthorityRootPublicKey)
|
pProvider := pp.GetPaymentProvider(provider.Type, provider.ClientId, provider.ClientSecret, provider.Host, cert.PublicKey, cert.PrivateKey, cert.AuthorityPublicKey, cert.AuthorityRootPublicKey)
|
||||||
|
|
||||||
paymentId := util.GenerateTimeId()
|
paymentId := util.GenerateTimeId()
|
||||||
returnUrl := ""
|
returnUrl := ""
|
||||||
|
@ -16,8 +16,6 @@ package pp
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
"github.com/go-pay/gopay"
|
"github.com/go-pay/gopay"
|
||||||
"github.com/go-pay/gopay/alipay"
|
"github.com/go-pay/gopay/alipay"
|
||||||
@ -47,8 +45,6 @@ func NewAlipayPaymentProvider(appId string, appPublicKey string, appPrivateKey s
|
|||||||
func (pp *AlipayPaymentProvider) Pay(productName string, productId string, providerId string, paymentId string, price float64, returnUrl string, notifyUrl string) (string, error) {
|
func (pp *AlipayPaymentProvider) Pay(productName string, productId string, providerId string, paymentId string, price float64, returnUrl string, notifyUrl string) (string, error) {
|
||||||
//pp.Client.DebugSwitch = gopay.DebugOn
|
//pp.Client.DebugSwitch = gopay.DebugOn
|
||||||
|
|
||||||
priceString := strings.TrimRight(strings.TrimRight(fmt.Sprintf("%.2f", price), "0"), ".")
|
|
||||||
|
|
||||||
bm := gopay.BodyMap{}
|
bm := gopay.BodyMap{}
|
||||||
|
|
||||||
bm.Set("return_url", returnUrl)
|
bm.Set("return_url", returnUrl)
|
||||||
@ -56,7 +52,7 @@ func (pp *AlipayPaymentProvider) Pay(productName string, productId string, provi
|
|||||||
|
|
||||||
bm.Set("subject", productName)
|
bm.Set("subject", productName)
|
||||||
bm.Set("out_trade_no", paymentId)
|
bm.Set("out_trade_no", paymentId)
|
||||||
bm.Set("total_amount", priceString)
|
bm.Set("total_amount", getPriceString(price))
|
||||||
bm.Set("productId", productId)
|
bm.Set("productId", productId)
|
||||||
bm.Set("providerId", productId)
|
bm.Set("providerId", productId)
|
||||||
|
|
||||||
|
174
pp/gc.go
Normal file
174
pp/gc.go
Normal file
@ -0,0 +1,174 @@
|
|||||||
|
// Copyright 2022 The Casdoor 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.
|
||||||
|
|
||||||
|
package pp
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"encoding/base64"
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"io/ioutil"
|
||||||
|
"net/http"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/casdoor/casdoor/util"
|
||||||
|
)
|
||||||
|
|
||||||
|
type GcPaymentProvider struct {
|
||||||
|
Xmpch string
|
||||||
|
SecretKey string
|
||||||
|
Host string
|
||||||
|
}
|
||||||
|
|
||||||
|
type GcPayReqInfo struct {
|
||||||
|
OrderDate string `json:"orderdate"`
|
||||||
|
OrderNo string `json:"orderno"`
|
||||||
|
Amount string `json:"amount"`
|
||||||
|
PayerId string `json:"payerid"`
|
||||||
|
PayerName string `json:"payername"`
|
||||||
|
Xmpch string `json:"xmpch"`
|
||||||
|
ReturnUrl string `json:"return_url"`
|
||||||
|
NotifyUrl string `json:"notify_url"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type GcPayRespInfo struct {
|
||||||
|
Jylsh string `json:"jylsh"`
|
||||||
|
Amount string `json:"amount"`
|
||||||
|
PayerId string `json:"payerid"`
|
||||||
|
PayerName string `json:"payername"`
|
||||||
|
PayUrl string `json:"payurl"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type GcRequestBody struct {
|
||||||
|
Op string `json:"op"`
|
||||||
|
Xmpch string `json:"xmpch"`
|
||||||
|
Version string `json:"version"`
|
||||||
|
Data string `json:"data"`
|
||||||
|
RequestTime string `json:"requesttime"`
|
||||||
|
Sign string `json:"sign"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type GcResponseBody struct {
|
||||||
|
Op string `json:"op"`
|
||||||
|
Xmpch string `json:"xmpch"`
|
||||||
|
Version string `json:"version"`
|
||||||
|
ReturnCode string `json:"return_code"`
|
||||||
|
ReturnMsg string `json:"return_msg"`
|
||||||
|
Data string `json:"data"`
|
||||||
|
NotifyTime string `json:"notifytime"`
|
||||||
|
Sign string `json:"sign"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewGcPaymentProvider(clientId string, clientSecret string, host string) *GcPaymentProvider {
|
||||||
|
pp := &GcPaymentProvider{}
|
||||||
|
|
||||||
|
pp.Xmpch = clientId
|
||||||
|
pp.SecretKey = clientSecret
|
||||||
|
pp.Host = host
|
||||||
|
return pp
|
||||||
|
}
|
||||||
|
|
||||||
|
func (pp *GcPaymentProvider) doPost(postBytes []byte) ([]byte, error) {
|
||||||
|
client := &http.Client{}
|
||||||
|
|
||||||
|
var resp *http.Response
|
||||||
|
var err error
|
||||||
|
|
||||||
|
contentType := "text/plain;charset=UTF-8"
|
||||||
|
body := bytes.NewReader(postBytes)
|
||||||
|
|
||||||
|
req, err := http.NewRequest("POST", pp.Host, body)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
req.Header.Set("Content-Type", contentType)
|
||||||
|
|
||||||
|
resp, err = client.Do(req)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
defer func(Body io.ReadCloser) {
|
||||||
|
err := Body.Close()
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}(resp.Body)
|
||||||
|
|
||||||
|
respBytes, err := ioutil.ReadAll(resp.Body)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return respBytes, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (pp *GcPaymentProvider) Pay(productName string, productId string, providerId string, paymentId string, price float64, returnUrl string, notifyUrl string) (string, error) {
|
||||||
|
payReqInfo := GcPayReqInfo{
|
||||||
|
OrderDate: util.GenerateSimpleTimeId(),
|
||||||
|
OrderNo: util.GenerateTimeId(),
|
||||||
|
Amount: getPriceString(price),
|
||||||
|
PayerId: "",
|
||||||
|
PayerName: "",
|
||||||
|
Xmpch: pp.Xmpch,
|
||||||
|
ReturnUrl: returnUrl,
|
||||||
|
NotifyUrl: notifyUrl,
|
||||||
|
}
|
||||||
|
|
||||||
|
b, err := json.Marshal(payReqInfo)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
body := GcRequestBody{
|
||||||
|
Op: "OrderCreate",
|
||||||
|
Xmpch: pp.Xmpch,
|
||||||
|
Version: "1.4",
|
||||||
|
Data: base64.StdEncoding.EncodeToString(b),
|
||||||
|
RequestTime: util.GenerateSimpleTimeId(),
|
||||||
|
}
|
||||||
|
|
||||||
|
params := fmt.Sprintf("data=%s&op=%s&requesttime=%s&version=%s&xmpch=%s%s", body.Data, body.Op, body.RequestTime, body.Version, body.Xmpch, pp.SecretKey)
|
||||||
|
body.Sign = strings.ToUpper(util.GetMd5Hash(params))
|
||||||
|
|
||||||
|
bodyBytes, err := json.Marshal(body)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
respBytes, err := pp.doPost(bodyBytes)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
var respBody GcResponseBody
|
||||||
|
err = json.Unmarshal(respBytes, &respBody)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
payRespInfoBytes, err := base64.StdEncoding.DecodeString(respBody.Data)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
var payRespInfo GcPayRespInfo
|
||||||
|
err = json.Unmarshal(payRespInfoBytes, &payRespInfo)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
return payRespInfo.PayUrl, nil
|
||||||
|
}
|
@ -18,9 +18,11 @@ type PaymentProvider interface {
|
|||||||
Pay(productName string, productId string, providerId string, paymentId string, price float64, returnUrl string, notifyUrl string) (string, error)
|
Pay(productName string, productId string, providerId string, paymentId string, price float64, returnUrl string, notifyUrl string) (string, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetPaymentProvider(typ string, appId string, appPublicKey string, appPrivateKey string, authorityPublicKey string, authorityRootPublicKey string) PaymentProvider {
|
func GetPaymentProvider(typ string, appId string, clientSecret string, host string, appPublicKey string, appPrivateKey string, authorityPublicKey string, authorityRootPublicKey string) PaymentProvider {
|
||||||
if typ == "Alipay" {
|
if typ == "Alipay" {
|
||||||
return NewAlipayPaymentProvider(appId, appPublicKey, appPrivateKey, authorityPublicKey, authorityRootPublicKey)
|
return NewAlipayPaymentProvider(appId, appPublicKey, appPrivateKey, authorityPublicKey, authorityRootPublicKey)
|
||||||
|
} else if typ == "GC" {
|
||||||
|
return NewGcPaymentProvider(appId, clientSecret, host)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
25
pp/util.go
Normal file
25
pp/util.go
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
// Copyright 2022 The Casdoor 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.
|
||||||
|
|
||||||
|
package pp
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
func getPriceString(price float64) string {
|
||||||
|
priceString := strings.TrimRight(strings.TrimRight(fmt.Sprintf("%.2f", price), "0"), ".")
|
||||||
|
return priceString
|
||||||
|
}
|
@ -109,6 +109,14 @@ func GenerateTimeId() string {
|
|||||||
return res
|
return res
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func GenerateSimpleTimeId() string {
|
||||||
|
timestamp := time.Now().Unix()
|
||||||
|
tm := time.Unix(timestamp, 0)
|
||||||
|
t := tm.Format("20060102150405")
|
||||||
|
|
||||||
|
return t
|
||||||
|
}
|
||||||
|
|
||||||
func GetId(name string) string {
|
func GetId(name string) string {
|
||||||
return fmt.Sprintf("admin/%s", name)
|
return fmt.Sprintf("admin/%s", name)
|
||||||
}
|
}
|
||||||
|
@ -444,6 +444,7 @@ export function getProviderTypeOptions(category) {
|
|||||||
{id: 'Alipay', name: 'Alipay'},
|
{id: 'Alipay', name: 'Alipay'},
|
||||||
{id: 'WeChat Pay', name: 'WeChat Pay'},
|
{id: 'WeChat Pay', name: 'WeChat Pay'},
|
||||||
{id: 'PayPal', name: 'PayPal'},
|
{id: 'PayPal', name: 'PayPal'},
|
||||||
|
{id: 'GC', name: 'GC'},
|
||||||
]);
|
]);
|
||||||
} else {
|
} else {
|
||||||
return [];
|
return [];
|
||||||
|
@ -160,6 +160,10 @@ const otherProviderInfo = {
|
|||||||
logo: `${StaticBaseUrl}/img/payment_paypal.png`,
|
logo: `${StaticBaseUrl}/img/payment_paypal.png`,
|
||||||
url: "https://www.paypal.com/"
|
url: "https://www.paypal.com/"
|
||||||
},
|
},
|
||||||
|
"GC": {
|
||||||
|
logo: `${StaticBaseUrl}/img/payment_gc.png`,
|
||||||
|
url: "https://gc.org"
|
||||||
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user