Skip to content

Commit

Permalink
Add gc provider.
Browse files Browse the repository at this point in the history
  • Loading branch information
hsluoyz committed Mar 13, 2022
1 parent bf24594 commit 5de417e
Show file tree
Hide file tree
Showing 9 changed files with 224 additions and 11 deletions.
11 changes: 7 additions & 4 deletions object/product.go
Original file line number Diff line number Diff line change
Expand Up @@ -164,12 +164,15 @@ func BuyProduct(id string, providerId string, user *User, host string) (string,
return "", err
}

cert := getCert(product.Owner, provider.Cert)
if cert == nil {
return "", fmt.Errorf("the cert: %s does not exist", provider.Cert)
cert := &Cert{}
if 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 {
return "", fmt.Errorf("the payment provider type: %s is not supported", provider.Type)
}
Expand Down
2 changes: 1 addition & 1 deletion object/product_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ func TestProduct(t *testing.T) {
product := GetProduct("admin/product_123")
provider := getProvider(product.Owner, "provider_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()
returnUrl := ""
Expand Down
6 changes: 1 addition & 5 deletions pp/alipay.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,6 @@ package pp

import (
"context"
"fmt"
"strings"

"github.com/go-pay/gopay"
"github.com/go-pay/gopay/alipay"
Expand Down Expand Up @@ -47,16 +45,14 @@ 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) {
//pp.Client.DebugSwitch = gopay.DebugOn

priceString := strings.TrimRight(strings.TrimRight(fmt.Sprintf("%.2f", price), "0"), ".")

bm := gopay.BodyMap{}

bm.Set("return_url", returnUrl)
bm.Set("notify_url", notifyUrl)

bm.Set("subject", productName)
bm.Set("out_trade_no", paymentId)
bm.Set("total_amount", priceString)
bm.Set("total_amount", getPriceString(price))
bm.Set("productId", productId)
bm.Set("providerId", productId)

Expand Down
174 changes: 174 additions & 0 deletions pp/gc.go
Original file line number Diff line number Diff line change
@@ -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
}
4 changes: 3 additions & 1 deletion pp/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,11 @@ type PaymentProvider interface {
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" {
return NewAlipayPaymentProvider(appId, appPublicKey, appPrivateKey, authorityPublicKey, authorityRootPublicKey)
} else if typ == "GC" {
return NewGcPaymentProvider(appId, clientSecret, host)
}
return nil
}
25 changes: 25 additions & 0 deletions pp/util.go
Original file line number Diff line number Diff line change
@@ -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
}
8 changes: 8 additions & 0 deletions util/string.go
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,14 @@ func GenerateTimeId() string {
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 {
return fmt.Sprintf("admin/%s", name)
}
Expand Down
1 change: 1 addition & 0 deletions web/src/Setting.js
Original file line number Diff line number Diff line change
Expand Up @@ -444,6 +444,7 @@ export function getProviderTypeOptions(category) {
{id: 'Alipay', name: 'Alipay'},
{id: 'WeChat Pay', name: 'WeChat Pay'},
{id: 'PayPal', name: 'PayPal'},
{id: 'GC', name: 'GC'},
]);
} else {
return [];
Expand Down
4 changes: 4 additions & 0 deletions web/src/auth/Provider.js
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,10 @@ const otherProviderInfo = {
logo: `${StaticBaseUrl}/img/payment_paypal.png`,
url: "https://www.paypal.com/"
},
"GC": {
logo: `${StaticBaseUrl}/img/payment_gc.png`,
url: "https://gc.org"
},
},
};

Expand Down

0 comments on commit 5de417e

Please sign in to comment.