mirror of
https://github.com/songquanpeng/one-api.git
synced 2025-11-17 13:43:42 +08:00
80
payment/gateway/epay/client.go
Normal file
80
payment/gateway/epay/client.go
Normal file
@@ -0,0 +1,80 @@
|
||||
package epay
|
||||
|
||||
import (
|
||||
"crypto/md5"
|
||||
"encoding/hex"
|
||||
"sort"
|
||||
"strings"
|
||||
|
||||
"github.com/mitchellh/mapstructure"
|
||||
)
|
||||
|
||||
type Client struct {
|
||||
PayDomain string `json:"pay_domain"`
|
||||
PartnerID string `json:"partner_id"`
|
||||
Key string `json:"key"`
|
||||
}
|
||||
|
||||
// FormPay 表单支付
|
||||
func (c *Client) FormPay(args *PayArgs) (string, map[string]string, error) {
|
||||
formPayArgs := map[string]string{
|
||||
"type": string(args.Type),
|
||||
"pid": c.PartnerID,
|
||||
"out_trade_no": args.OutTradeNo,
|
||||
"notify_url": args.NotifyUrl,
|
||||
"return_url": args.ReturnUrl,
|
||||
"name": args.Name,
|
||||
"money": args.Money,
|
||||
// "device": string(args.Device),
|
||||
}
|
||||
|
||||
formPayArgs["sign"] = c.Sign(formPayArgs)
|
||||
formPayArgs["sign_type"] = FormArgsSignType
|
||||
|
||||
domain := strings.TrimSuffix(c.PayDomain, "/")
|
||||
|
||||
return domain + FormSubmitUrl, formPayArgs, nil
|
||||
|
||||
}
|
||||
|
||||
func (c *Client) Verify(params map[string]string) (*PaymentResult, bool) {
|
||||
sign := params["sign"]
|
||||
tradeStatus := params["trade_status"]
|
||||
|
||||
if sign == "" || tradeStatus != TradeStatusSuccess {
|
||||
return nil, false
|
||||
}
|
||||
|
||||
if sign != c.Sign(params) {
|
||||
return nil, false
|
||||
}
|
||||
|
||||
var paymentResult PaymentResult
|
||||
mapstructure.Decode(params, &paymentResult)
|
||||
|
||||
return &paymentResult, true
|
||||
}
|
||||
|
||||
// Sign 签名
|
||||
func (c *Client) Sign(args map[string]string) string {
|
||||
keys := make([]string, 0, len(args))
|
||||
for k := range args {
|
||||
if k != "sign" && k != "sign_type" && args[k] != "" {
|
||||
keys = append(keys, k)
|
||||
}
|
||||
}
|
||||
|
||||
sort.Strings(keys)
|
||||
|
||||
signStrs := make([]string, len(keys))
|
||||
for i, k := range keys {
|
||||
signStrs[i] = k + "=" + args[k]
|
||||
}
|
||||
|
||||
signStr := strings.Join(signStrs, "&") + c.Key
|
||||
|
||||
h := md5.New()
|
||||
h.Write([]byte(signStr))
|
||||
|
||||
return hex.EncodeToString(h.Sum(nil))
|
||||
}
|
||||
91
payment/gateway/epay/payment.go
Normal file
91
payment/gateway/epay/payment.go
Normal file
@@ -0,0 +1,91 @@
|
||||
package epay
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"one-api/payment/types"
|
||||
"strconv"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
type Epay struct{}
|
||||
|
||||
type EpayConfig struct {
|
||||
PayType PayType `json:"pay_type"`
|
||||
Client
|
||||
}
|
||||
|
||||
func (e *Epay) Name() string {
|
||||
return "易支付"
|
||||
}
|
||||
|
||||
func (e *Epay) Pay(config *types.PayConfig, gatewayConfig string) (*types.PayRequest, error) {
|
||||
epayConfig, err := getEpayConfig(gatewayConfig)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
payArgs := &PayArgs{
|
||||
Type: epayConfig.PayType,
|
||||
OutTradeNo: config.TradeNo,
|
||||
NotifyUrl: config.NotifyURL,
|
||||
ReturnUrl: config.ReturnURL,
|
||||
Name: config.TradeNo,
|
||||
Money: strconv.FormatFloat(config.Money, 'f', 2, 64),
|
||||
}
|
||||
|
||||
formPayURL, formPayArgs, err := epayConfig.FormPay(payArgs)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
payRequest := &types.PayRequest{
|
||||
Type: 1,
|
||||
Data: types.PayRequestData{
|
||||
URL: formPayURL,
|
||||
Params: &formPayArgs,
|
||||
Method: http.MethodPost,
|
||||
},
|
||||
}
|
||||
|
||||
return payRequest, nil
|
||||
}
|
||||
|
||||
func (e *Epay) HandleCallback(c *gin.Context, gatewayConfig string) (*types.PayNotify, error) {
|
||||
queryMap := make(map[string]string)
|
||||
if err := c.ShouldBindQuery(&queryMap); err != nil {
|
||||
c.Writer.Write([]byte("fail"))
|
||||
return nil, err
|
||||
}
|
||||
|
||||
epayConfig, err := getEpayConfig(gatewayConfig)
|
||||
if err != nil {
|
||||
c.Writer.Write([]byte("fail"))
|
||||
return nil, fmt.Errorf("tradeNo: %s, PaymentNo: %s, err: %v", queryMap["out_trade_no"], queryMap["trade_no"], err)
|
||||
}
|
||||
|
||||
paymentResult, success := epayConfig.Verify(queryMap)
|
||||
if paymentResult != nil && success {
|
||||
c.Writer.Write([]byte("success"))
|
||||
payNotify := &types.PayNotify{
|
||||
TradeNo: paymentResult.OutTradeNo,
|
||||
GatewayNo: paymentResult.TradeNo,
|
||||
}
|
||||
return payNotify, nil
|
||||
}
|
||||
|
||||
c.Writer.Write([]byte("fail"))
|
||||
return nil, fmt.Errorf("tradeNo: %s, PaymentNo: %s, Verify Sign failed", queryMap["out_trade_no"], queryMap["trade_no"])
|
||||
}
|
||||
|
||||
func getEpayConfig(gatewayConfig string) (*EpayConfig, error) {
|
||||
var epayConfig EpayConfig
|
||||
if err := json.Unmarshal([]byte(gatewayConfig), &epayConfig); err != nil {
|
||||
return nil, errors.New("config error")
|
||||
}
|
||||
|
||||
return &epayConfig, nil
|
||||
}
|
||||
45
payment/gateway/epay/type.go
Normal file
45
payment/gateway/epay/type.go
Normal file
@@ -0,0 +1,45 @@
|
||||
package epay
|
||||
|
||||
type PayType string
|
||||
|
||||
var (
|
||||
EpayPay PayType = "" // 网关
|
||||
Alipay PayType = "alipay" // 支付宝
|
||||
Wechat PayType = "wxpay" // 微信
|
||||
QQ PayType = "qqpay" // QQ
|
||||
Bank PayType = "bank" // 银行
|
||||
JD PayType = "jdpay" // 京东
|
||||
PayPal PayType = "paypal" // PayPal
|
||||
USDT PayType = "usdt" // USDT
|
||||
)
|
||||
|
||||
// type DeviceType string
|
||||
|
||||
// var (
|
||||
// PC DeviceType = "pc" // PC
|
||||
// Mobile DeviceType = "mobile" // 移动端
|
||||
// )
|
||||
|
||||
const (
|
||||
FormArgsSignType = "MD5"
|
||||
FormSubmitUrl = "/submit.php"
|
||||
TradeStatusSuccess = "TRADE_SUCCESS"
|
||||
)
|
||||
|
||||
type PayArgs struct {
|
||||
Type PayType `json:"type,omitempty"`
|
||||
OutTradeNo string `json:"out_trade_no"`
|
||||
NotifyUrl string `json:"notify_url"`
|
||||
ReturnUrl string `json:"return_url"`
|
||||
Name string `json:"name"`
|
||||
Money string `json:"money"`
|
||||
}
|
||||
|
||||
type PaymentResult struct {
|
||||
Type PayType `mapstructure:"type"`
|
||||
TradeNo string `mapstructure:"trade_no"`
|
||||
OutTradeNo string `mapstructure:"out_trade_no"`
|
||||
Name string `mapstructure:"name"`
|
||||
Money string `mapstructure:"money"`
|
||||
TradeStatus string `mapstructure:"trade_status"`
|
||||
}
|
||||
Reference in New Issue
Block a user