init: 1.0.0
This commit is contained in:
@@ -0,0 +1,114 @@
|
||||
package alipay
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net/url"
|
||||
|
||||
"github.com/perfect-panel/ppanel-server/pkg/logger"
|
||||
"github.com/perfect-panel/ppanel-server/pkg/tool"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/smartwalle/alipay/v3"
|
||||
)
|
||||
|
||||
type Config struct {
|
||||
AppId string
|
||||
PrivateKey string
|
||||
PublicKey string
|
||||
InvoiceName string
|
||||
NotifyURL string
|
||||
Sandbox bool
|
||||
}
|
||||
|
||||
type Notification struct {
|
||||
OrderNo string
|
||||
Amount int64
|
||||
Status Status
|
||||
}
|
||||
|
||||
type Status string
|
||||
|
||||
const (
|
||||
Success Status = "TRADE_SUCCESS"
|
||||
Pending Status = "WAIT_BUYER_PAY"
|
||||
Closed Status = "TRADE_CLOSED"
|
||||
Finished Status = "TRADE_FINISHED"
|
||||
Error Status = "TRADE_ERROR"
|
||||
)
|
||||
|
||||
type Client struct {
|
||||
Config
|
||||
client *alipay.Client
|
||||
}
|
||||
type Order struct {
|
||||
OrderNo string
|
||||
Amount int64
|
||||
}
|
||||
|
||||
func NewClient(c Config) *Client {
|
||||
client, err := alipay.New(c.AppId, c.PrivateKey, c.Sandbox)
|
||||
if err != nil {
|
||||
logger.Error("[Alipay] NewClient failed: ", logger.Field("errors", err), logger.Field("config", c))
|
||||
return nil
|
||||
}
|
||||
err = client.LoadAliPayPublicKey(c.PublicKey)
|
||||
if err != nil {
|
||||
logger.Error("[Alipay] NewClient failed: ", logger.Field("errors", err), logger.Field("config", c))
|
||||
}
|
||||
return &Client{
|
||||
Config: c,
|
||||
client: client,
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Client) PreCreateTrade(ctx context.Context, order Order) (string, error) {
|
||||
amountString := tool.FormatFloat(float64(order.Amount)/float64(100), 2)
|
||||
trade, err := c.client.TradePreCreate(ctx, alipay.TradePreCreate{
|
||||
Trade: alipay.Trade{
|
||||
OutTradeNo: order.OrderNo,
|
||||
TotalAmount: amountString,
|
||||
Subject: c.InvoiceName,
|
||||
NotifyURL: c.NotifyURL,
|
||||
},
|
||||
})
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
if trade.Code != alipay.CodeSuccess {
|
||||
return "", errors.New("PreCreateTrade failed: " + trade.Msg)
|
||||
}
|
||||
return trade.QRCode, nil
|
||||
}
|
||||
|
||||
func (c *Client) QueryTrade(ctx context.Context, orderNo string) (Status, error) {
|
||||
trade, err := c.client.TradeQuery(ctx, alipay.TradeQuery{
|
||||
OutTradeNo: orderNo,
|
||||
})
|
||||
if err != nil {
|
||||
return Error, err
|
||||
}
|
||||
switch trade.TradeStatus {
|
||||
case alipay.TradeStatusSuccess:
|
||||
return Success, nil
|
||||
case alipay.TradeStatusWaitBuyerPay:
|
||||
return Pending, nil
|
||||
case alipay.TradeStatusClosed:
|
||||
return Closed, nil
|
||||
case alipay.TradeStatusFinished:
|
||||
return Finished, nil
|
||||
default:
|
||||
return Error, errors.New("QueryTrade failed: " + trade.Msg)
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Client) DecodeNotification(form url.Values) (*Notification, error) {
|
||||
notify, err := c.client.DecodeNotification(form)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &Notification{
|
||||
OrderNo: notify.OutTradeNo,
|
||||
Amount: int64(tool.FormatStringToFloat(notify.TotalAmount) * 100),
|
||||
Status: Status(notify.TradeStatus),
|
||||
}, nil
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
package alipay
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestClientPreCreateTrade(t *testing.T) {
|
||||
t.Skipf("Skip TestClientPreCreateTrade")
|
||||
cfg := Config{
|
||||
InvoiceName: "XrayR",
|
||||
NotifyURL: "https://example.com/alipay/notify",
|
||||
Sandbox: true,
|
||||
}
|
||||
c := NewClient(cfg)
|
||||
order := Order{
|
||||
OrderNo: "20210701000001",
|
||||
Amount: 100,
|
||||
}
|
||||
qr, err := c.PreCreateTrade(context.Background(), order)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
t.Log(qr)
|
||||
}
|
||||
@@ -0,0 +1,122 @@
|
||||
package epay
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"io"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"sort"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/perfect-panel/ppanel-server/pkg/logger"
|
||||
"github.com/perfect-panel/ppanel-server/pkg/tool"
|
||||
)
|
||||
|
||||
type Client struct {
|
||||
Pid string
|
||||
Url string
|
||||
Key string
|
||||
}
|
||||
|
||||
type Order struct {
|
||||
Name string
|
||||
OrderNo string
|
||||
Amount float64
|
||||
SignType string
|
||||
NotifyUrl string
|
||||
ReturnUrl string
|
||||
}
|
||||
|
||||
type queryOrderStatusResponse struct {
|
||||
Code int `json:"code"`
|
||||
Msg string `json:"msg"`
|
||||
TradeNo string `json:"trade_no"`
|
||||
OutTradeNo string `json:"out_trade_no"`
|
||||
Type string `json:"type"`
|
||||
Status int `json:"status"`
|
||||
}
|
||||
|
||||
func NewClient(pid, url, key string) *Client {
|
||||
return &Client{
|
||||
Pid: pid,
|
||||
Url: url,
|
||||
Key: key,
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Client) CreatePayUrl(order Order) string {
|
||||
// Prepare URL values
|
||||
params := url.Values{}
|
||||
params.Set("name", order.Name)
|
||||
params.Set("money", tool.FormatFloat(order.Amount, 2))
|
||||
params.Set("notify_url", order.NotifyUrl)
|
||||
params.Set("out_trade_no", order.OrderNo)
|
||||
params.Set("pid", c.Pid)
|
||||
params.Set("return_url", order.ReturnUrl)
|
||||
|
||||
// Generate the sign using the CreateSign function
|
||||
sign := c.createSign(c.structToMap(order))
|
||||
params.Set("sign", sign)
|
||||
|
||||
// Add sign_type manually
|
||||
params.Set("sign_type", "MD5")
|
||||
return c.Url + "/submit.php?" + params.Encode()
|
||||
}
|
||||
|
||||
func (c *Client) createSign(params map[string]string) string {
|
||||
keys := make([]string, 0, len(params))
|
||||
for k := range params {
|
||||
if params[k] != "" && k != "sign" && k != "sign_type" {
|
||||
keys = append(keys, k)
|
||||
}
|
||||
}
|
||||
sort.Strings(keys)
|
||||
var parts []string
|
||||
for _, k := range keys {
|
||||
parts = append(parts, k+"="+params[k])
|
||||
}
|
||||
queryString := strings.Join(parts, "&")
|
||||
text := queryString + c.Key
|
||||
return tool.Md5Encode(text, false)
|
||||
}
|
||||
|
||||
func (c *Client) VerifySign(params map[string]string) bool {
|
||||
return c.createSign(params) == params["sign"]
|
||||
}
|
||||
|
||||
func (c *Client) QueryOrderStatus(orderNo string) bool {
|
||||
client := http.Client{
|
||||
Timeout: 5 * time.Second,
|
||||
}
|
||||
resp, err := client.Get(c.Url + "/api.php" + "?act=order" + "&pid=" + c.Pid + "&key=" + c.Key + "&out_trade_no=" + orderNo)
|
||||
if err != nil {
|
||||
logger.Error("[Epay] QueryOrderStatus error", logger.Field("orderNo", orderNo), logger.Field("error", err.Error()))
|
||||
return false
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
value, err := io.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
logger.Error("[Epay] QueryOrderStatus error", logger.Field("orderNo", orderNo), logger.Field("error", err.Error()))
|
||||
return false
|
||||
}
|
||||
var response queryOrderStatusResponse
|
||||
err = json.Unmarshal(value, &response)
|
||||
if err != nil {
|
||||
logger.Error("[Epay] QueryOrderStatus error", logger.Field("orderNo", orderNo), logger.Field("error", err.Error()))
|
||||
return false
|
||||
}
|
||||
return response.Status == 1
|
||||
}
|
||||
|
||||
// StructToMap converts a struct to map[string]string
|
||||
func (c *Client) structToMap(order Order) map[string]string {
|
||||
result := make(map[string]string)
|
||||
result["money"] = tool.FormatFloat(order.Amount, 2)
|
||||
result["name"] = order.Name
|
||||
result["notify_url"] = order.NotifyUrl
|
||||
result["out_trade_no"] = order.OrderNo
|
||||
result["pid"] = c.Pid
|
||||
result["return_url"] = order.ReturnUrl
|
||||
return result
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
package epay
|
||||
|
||||
import "testing"
|
||||
|
||||
func TestEpay(t *testing.T) {
|
||||
client := NewClient("", "http://127.0.0.1", "")
|
||||
order := Order{
|
||||
Name: "测试",
|
||||
OrderNo: "123456789",
|
||||
Amount: 1000,
|
||||
SignType: "md5",
|
||||
NotifyUrl: "http://127.0.0.1",
|
||||
ReturnUrl: "http://127.0.0.1",
|
||||
}
|
||||
url := client.CreatePayUrl(order)
|
||||
t.Logf("PayUrl: %s\n", url)
|
||||
|
||||
}
|
||||
|
||||
func TestQueryOrderStatus(t *testing.T) {
|
||||
t.Skipf("Skip TestQueryOrderStatus test")
|
||||
client := NewClient("Pid", "Url", "Key")
|
||||
orderNo := "123456789"
|
||||
status := client.QueryOrderStatus(orderNo)
|
||||
t.Logf("OrderNo: %s, Status: %v\n", orderNo, status)
|
||||
}
|
||||
|
||||
func TestVerifySign(t *testing.T) {
|
||||
t.Skipf("Skip TestVerifySign test")
|
||||
params := map[string]string{
|
||||
"pid": "1654",
|
||||
"trade_no": "2024121521150860990",
|
||||
"out_trade_no": "202412152115078262977262254",
|
||||
"type": "alipay",
|
||||
"name": "product",
|
||||
"money": "10",
|
||||
"trade_status": "TRADE_SUCCESS",
|
||||
"sign": "d3181f18ebdf9821f0ab6ee93faa82d1",
|
||||
"sign_type": "MD5",
|
||||
}
|
||||
|
||||
key := "LbTabbB580zWyhXhyyww7wwvy5u8k0wl"
|
||||
c := NewClient("Pid", "Url", key)
|
||||
if c.VerifySign(params) {
|
||||
t.Logf("Sign verification success!")
|
||||
} else {
|
||||
t.Error("Sign verification failed!")
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
package payment
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"testing"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
func TestHttp(t *testing.T) {
|
||||
t.Skipf("Skip TestHttp test")
|
||||
router := gin.Default()
|
||||
router.LoadHTMLGlob("./*")
|
||||
router.GET("/stripe", func(c *gin.Context) {
|
||||
c.HTML(http.StatusOK, "stripe.html", gin.H{
|
||||
"title": "Gin HTML Example",
|
||||
"message": "Hello, Gin!",
|
||||
})
|
||||
})
|
||||
_ = router.Run(":8989")
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
package payment
|
||||
|
||||
import "github.com/perfect-panel/ppanel-server/internal/types"
|
||||
|
||||
type Platform int
|
||||
|
||||
const (
|
||||
Stripe Platform = iota
|
||||
AlipayF2F
|
||||
EPay
|
||||
Balance
|
||||
UNSUPPORTED
|
||||
)
|
||||
|
||||
var platformNames = map[string]Platform{
|
||||
"Stripe": Stripe,
|
||||
"AlipayF2F": AlipayF2F,
|
||||
"EPay": EPay,
|
||||
"balance": Balance,
|
||||
"unsupported": UNSUPPORTED,
|
||||
}
|
||||
|
||||
func (p Platform) String() string {
|
||||
for k, v := range platformNames {
|
||||
if v == p {
|
||||
return k
|
||||
}
|
||||
}
|
||||
return "unsupported"
|
||||
}
|
||||
|
||||
func ParsePlatform(s string) Platform {
|
||||
if p, ok := platformNames[s]; ok {
|
||||
return p
|
||||
}
|
||||
return UNSUPPORTED
|
||||
}
|
||||
|
||||
func GetSupportedPlatforms() []types.PlatformInfo {
|
||||
return []types.PlatformInfo{
|
||||
{
|
||||
Platform: Stripe.String(),
|
||||
PlatformUrl: "https://stripe.com",
|
||||
PlatformFieldDescription: map[string]string{
|
||||
"public_key": "Publishable key",
|
||||
"secret_key": "Secret key",
|
||||
"webhook_secret": "Webhook secret",
|
||||
"payment": "Payment Method, only supported card/alipay/wechat_pay",
|
||||
},
|
||||
},
|
||||
{
|
||||
Platform: AlipayF2F.String(),
|
||||
PlatformUrl: "https://alipay.com",
|
||||
PlatformFieldDescription: map[string]string{
|
||||
"app_id": "App ID",
|
||||
"private_key": "Private Key",
|
||||
"public_key": "Public Key",
|
||||
"invoice_name": "Invoice Name",
|
||||
"sandbox": "Sandbox Mode",
|
||||
},
|
||||
},
|
||||
{
|
||||
Platform: EPay.String(),
|
||||
PlatformUrl: "",
|
||||
PlatformFieldDescription: map[string]string{
|
||||
"pid": "PID",
|
||||
"url": "URL",
|
||||
"key": "Key",
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Title</title>
|
||||
<script src="https://js.stripe.com/v3/"></script>
|
||||
</head>
|
||||
<body>
|
||||
<button id="payment">提交</button>
|
||||
<script>
|
||||
const stripe = Stripe('pk_test_51L4gYuHqdC7TVcHRMpjoxpdlNM3MwlcWHFYHmSSUjkjzE9x0IlKqxcYvSxnPXD5ahxdxSxVf6kJf7AEwpwmTqATx005M6v5QDe');
|
||||
const btn = document.getElementById('payment');
|
||||
btn.addEventListener('click',async ()=>{
|
||||
try {
|
||||
// wechat:pi_3Q8kM5HqdC7TVcHR10ESkDJD_secret_sEJxtzWruoYEPjLbpKIC4Z0Ae
|
||||
// alipay:pi_3Q8kTxHqdC7TVcHR08NCtdE5_secret_wpc54Pa1EXxoccznERFjKvxHr
|
||||
const {error, paymentIntent}= await stripe.confirmAlipayPayment('',
|
||||
{
|
||||
payment_method_options: {
|
||||
wechat_pay: {
|
||||
client: 'web',
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
handleActions: false,
|
||||
}
|
||||
)
|
||||
if (error) {
|
||||
console.error(error)
|
||||
} else {
|
||||
console.log(paymentIntent)
|
||||
}
|
||||
}catch (e) {
|
||||
console.log(e)
|
||||
}
|
||||
})
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,210 @@
|
||||
package stripe
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"strconv"
|
||||
|
||||
"github.com/stripe/stripe-go/v81/webhookendpoint"
|
||||
|
||||
"github.com/perfect-panel/ppanel-server/pkg/logger"
|
||||
"github.com/stripe/stripe-go/v81"
|
||||
"github.com/stripe/stripe-go/v81/customer"
|
||||
"github.com/stripe/stripe-go/v81/ephemeralkey"
|
||||
"github.com/stripe/stripe-go/v81/paymentintent"
|
||||
"github.com/stripe/stripe-go/v81/paymentmethod"
|
||||
"github.com/stripe/stripe-go/v81/webhook"
|
||||
)
|
||||
|
||||
const APIVersion = "2024-04-10"
|
||||
|
||||
type Config struct {
|
||||
PublicKey string
|
||||
SecretKey string
|
||||
WebhookSecret string
|
||||
}
|
||||
|
||||
type User struct {
|
||||
UserId int64
|
||||
Email string
|
||||
}
|
||||
type NotifyResult struct {
|
||||
EventType string
|
||||
OrderNo string
|
||||
TradeNo string
|
||||
Method string
|
||||
UserId int64
|
||||
Amount int64
|
||||
}
|
||||
type Order struct {
|
||||
OrderNo string
|
||||
Subscribe string
|
||||
Amount int64
|
||||
Currency string
|
||||
Payment string
|
||||
}
|
||||
|
||||
type Client struct {
|
||||
Config
|
||||
}
|
||||
|
||||
type PaymentSheet struct {
|
||||
ClientSecret string
|
||||
EphemeralKey string
|
||||
Customer string
|
||||
PublishableKey string
|
||||
TradeNo string
|
||||
}
|
||||
|
||||
func NewClient(config Config) *Client {
|
||||
return &Client{
|
||||
Config: config,
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Client) CreatePaymentSheet(order *Order, user *User) (*PaymentSheet, error) {
|
||||
stripe.Key = c.SecretKey
|
||||
// Create a new Stripe customer if it does not exist
|
||||
customerDataRes, err := c.SearchStripeCustomer(user)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if customerDataRes == nil {
|
||||
customerDataRes, err = c.CreateCustomer(user)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
// Create Ephemeral Key
|
||||
ekParams := &stripe.EphemeralKeyParams{
|
||||
Customer: stripe.String(customerDataRes.ID),
|
||||
StripeVersion: stripe.String(APIVersion),
|
||||
}
|
||||
ek, err := ephemeralkey.New(ekParams)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// Create Payment Intent
|
||||
params := &stripe.PaymentIntentParams{
|
||||
Amount: stripe.Int64(order.Amount),
|
||||
Customer: stripe.String(customerDataRes.ID),
|
||||
Currency: stripe.String(order.Currency),
|
||||
PaymentMethodTypes: []*string{
|
||||
stripe.String(order.Payment),
|
||||
},
|
||||
Metadata: map[string]string{
|
||||
"order_no": order.OrderNo,
|
||||
"user_id": strconv.FormatInt(user.UserId, 10),
|
||||
"subscribe": order.Subscribe,
|
||||
},
|
||||
}
|
||||
result, err := paymentintent.New(params)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &PaymentSheet{
|
||||
ClientSecret: result.ClientSecret,
|
||||
EphemeralKey: ek.Secret,
|
||||
Customer: customerDataRes.ID,
|
||||
PublishableKey: c.PublicKey,
|
||||
TradeNo: result.ID,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// SearchStripeCustomer Search for a Stripe customer by email or user ID
|
||||
func (c *Client) SearchStripeCustomer(user *User) (*stripe.Customer, error) {
|
||||
stripe.Key = c.SecretKey
|
||||
params := &stripe.CustomerSearchParams{}
|
||||
if user.Email != "" {
|
||||
params.SearchParams.Query = fmt.Sprintf("email:'%s'", user.Email)
|
||||
} else {
|
||||
params.SearchParams.Query = fmt.Sprintf("metadata['user_id']:'%d'", user.UserId)
|
||||
}
|
||||
result := customer.Search(params)
|
||||
if result.Err() != nil {
|
||||
fmt.Printf("Error: %v\n", result.Err().Error())
|
||||
return nil, result.Err()
|
||||
}
|
||||
|
||||
if len(result.CustomerSearchResult().Data) != 0 {
|
||||
return result.CustomerSearchResult().Data[0], nil
|
||||
}
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
// CreateCustomer Create a new Stripe customer
|
||||
func (c *Client) CreateCustomer(user *User) (*stripe.Customer, error) {
|
||||
stripe.Key = c.SecretKey
|
||||
customerData := &stripe.CustomerParams{}
|
||||
if user.Email != "" {
|
||||
customerData.Email = &user.Email
|
||||
}
|
||||
customerData.AddMetadata("user_id", strconv.FormatInt(user.UserId, 10))
|
||||
return customer.New(customerData)
|
||||
}
|
||||
|
||||
// QueryOrderStatus Query the status of the order
|
||||
func (c *Client) QueryOrderStatus(orderNo string) (bool, error) {
|
||||
stripe.Key = c.SecretKey
|
||||
intent, err := paymentintent.Get(orderNo, nil)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
return intent.Status == "succeeded", err
|
||||
}
|
||||
|
||||
// ParseNotify
|
||||
func (c *Client) ParseNotify(payload []byte, signature string) (*NotifyResult, error) {
|
||||
event, err := webhook.ConstructEvent(payload, signature, c.Config.WebhookSecret)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var paymentIntent stripe.PaymentIntent
|
||||
err = json.Unmarshal(event.Data.Raw, &paymentIntent)
|
||||
if err != nil {
|
||||
logger.Error("Failed to unmarshal payment intent", logger.Field("error", err.Error()))
|
||||
return nil, err
|
||||
}
|
||||
orderNo := paymentIntent.Metadata["order_no"]
|
||||
userId := paymentIntent.Metadata["user_id"]
|
||||
var method string
|
||||
if paymentIntent.PaymentMethod != nil && paymentIntent.PaymentMethod.ID != "" {
|
||||
fmt.Println("paymentMethod:", paymentIntent.PaymentMethod.ID)
|
||||
result, err := c.RetrievePaymentMethod(paymentIntent.PaymentMethod.ID)
|
||||
if err != nil {
|
||||
logger.Error("[stripe] Payment callback query payment method error", logger.Field("errors", err.Error()))
|
||||
}
|
||||
if result != nil {
|
||||
method = string(result.Type)
|
||||
}
|
||||
}
|
||||
// userId string 转 int64
|
||||
uid, _ := strconv.ParseInt(userId, 10, 64)
|
||||
return &NotifyResult{
|
||||
EventType: string(event.Type),
|
||||
OrderNo: orderNo,
|
||||
TradeNo: paymentIntent.ID,
|
||||
UserId: uid,
|
||||
Method: method,
|
||||
Amount: paymentIntent.Amount,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// RetrievePaymentMethod 查询支付方式
|
||||
func (c *Client) RetrievePaymentMethod(id string) (*stripe.PaymentMethod, error) {
|
||||
stripe.Key = c.SecretKey
|
||||
return paymentmethod.Get(id, nil)
|
||||
}
|
||||
|
||||
// CreateWebhookEndpoint 创建 webhook endpoint
|
||||
func (c *Client) CreateWebhookEndpoint(url string) (*stripe.WebhookEndpoint, error) {
|
||||
stripe.Key = c.SecretKey
|
||||
params := &stripe.WebhookEndpointParams{
|
||||
URL: stripe.String(url),
|
||||
EnabledEvents: []*string{
|
||||
stripe.String("payment_intent.succeeded"),
|
||||
stripe.String("payment_intent.payment_failed"),
|
||||
},
|
||||
}
|
||||
return webhookendpoint.New(params)
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
package stripe
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stripe/stripe-go/v81"
|
||||
)
|
||||
|
||||
func TestStripeAlipay(t *testing.T) {
|
||||
t.Skipf("Skip TestStripeAlipay test")
|
||||
client := NewClient(Config{
|
||||
WebhookSecret: "",
|
||||
})
|
||||
order := Order{
|
||||
OrderNo: "JS20210719123456789",
|
||||
Subscribe: "测试",
|
||||
Amount: 100,
|
||||
Currency: string(stripe.CurrencyGBP),
|
||||
Payment: "alipay",
|
||||
}
|
||||
user := User{
|
||||
UserId: 1,
|
||||
Email: "tension@ppanel.dev",
|
||||
}
|
||||
result, err := client.CreatePaymentSheet(&order, &user)
|
||||
if err != nil {
|
||||
t.Error(err.Error())
|
||||
}
|
||||
t.Logf("TradeNo: %s\n", result.ClientSecret)
|
||||
}
|
||||
|
||||
func TestStripeWechat(t *testing.T) {
|
||||
t.Skipf("Skip TestStripeWechat test")
|
||||
client := NewClient(Config{
|
||||
SecretKey: "SecretKey",
|
||||
PublicKey: "PublicKey",
|
||||
WebhookSecret: "",
|
||||
})
|
||||
order := Order{
|
||||
OrderNo: "JS20210719123456789",
|
||||
Subscribe: "测试",
|
||||
Amount: 100,
|
||||
Currency: string(stripe.CurrencyGBP),
|
||||
Payment: "wechat_pay",
|
||||
}
|
||||
user := User{
|
||||
UserId: 1,
|
||||
Email: "tension@ppanel.dev",
|
||||
}
|
||||
result, err := client.CreatePaymentSheet(&order, &user)
|
||||
if err != nil {
|
||||
t.Error(err.Error())
|
||||
}
|
||||
t.Logf("TradeNo: %s\n", result.ClientSecret)
|
||||
}
|
||||
Reference in New Issue
Block a user