130 lines
4.3 KiB
Go
130 lines
4.3 KiB
Go
package taptap
|
||
|
||
import (
|
||
"bytes"
|
||
"context"
|
||
"encoding/json"
|
||
"errors"
|
||
"fmt"
|
||
"github.com/gogf/gf/v2/encoding/gjson"
|
||
"github.com/gogf/gf/v2/frame/g"
|
||
"github.com/gogf/gf/v2/net/gclient"
|
||
"github.com/gogf/gf/v2/os/gctx"
|
||
"github.com/gogf/gf/v2/os/gtime"
|
||
"github.com/gogf/gf/v2/util/grand"
|
||
"io"
|
||
"net/http"
|
||
)
|
||
|
||
type GetPayData struct {
|
||
Data struct {
|
||
Order struct {
|
||
Order
|
||
} `json:"order"`
|
||
} `json:"data"`
|
||
Success bool `json:"success"`
|
||
}
|
||
|
||
type Order struct {
|
||
OrderID string `json:"order_id"` // 订单唯一 ID
|
||
PurchaseToken string `json:"purchase_token"` // 用于订单核销的 token
|
||
ClientID string `json:"client_id"` // 应用的 Client ID
|
||
OpenID string `json:"open_id"` // 用户的开放平台 ID
|
||
UserRegion string `json:"user_region"` // 用户地区
|
||
GoodsOpenID string `json:"goods_open_id"` // 商品唯一 ID
|
||
GoodsName string `json:"goods_name"` // 商品名称
|
||
Status PaymentStatus `json:"status"` // 订单状态
|
||
Amount string `json:"amount"` // 金额(本币金额 x 1,000,000)
|
||
Currency string `json:"currency"` // 币种
|
||
CreateTime string `json:"create_time"` // 创建时间
|
||
PayTime string `json:"pay_time"` // 支付时间
|
||
Extra string `json:"extra"` // 商户自定义数据,如角色信息等,长度不超过 255 UTF-8 字符
|
||
}
|
||
type PaymentStatus string
|
||
|
||
const (
|
||
ChargePending PaymentStatus = "charge.pending" // 待支付
|
||
ChargeSucceeded PaymentStatus = "charge.succeeded" //支付成功
|
||
ChargeConfirmed PaymentStatus = "charge.confirmed" //已核销
|
||
ChargeOverdue PaymentStatus = "charge.overdue" //支付超时关闭
|
||
RefundPending PaymentStatus = "refund.pending" //退款中
|
||
RefundSucceeded PaymentStatus = "refund.succeeded" //退款成功
|
||
RefundFailed PaymentStatus = "refund.failed" //退款失败
|
||
RefundRejected PaymentStatus = "refund.rejected" //退款被拒绝
|
||
)
|
||
|
||
// 查询订单信息
|
||
func (p *pTapTap) Info(ctx context.Context, order string) (getPayData *GetPayData, err error) {
|
||
url := fmt.Sprintf("https://cloud-payment.tapapis.cn/order/v1/info?client_id=%v&order_id=%v", p.ClientId, order)
|
||
getPayData, err = p.get(ctx, url)
|
||
if err != nil {
|
||
return
|
||
}
|
||
return
|
||
}
|
||
|
||
// 验证并核销订单
|
||
func (p *pTapTap) Verify(ctx context.Context, req any) (getPayData *GetPayData, err error) {
|
||
url := fmt.Sprintf("https://cloud-payment.tapapis.cn/order/v1/verify?client_id=%v", p.ClientId)
|
||
getPayData, err = p.get(ctx, url, req)
|
||
if err != nil {
|
||
return
|
||
}
|
||
return
|
||
}
|
||
|
||
func (p *pTapTap) get(ctx context.Context, url string, _data ...any) (getPayData *GetPayData, err error) {
|
||
|
||
var _get *gclient.Response
|
||
|
||
var header = map[string]string{
|
||
"Content-Type": "Content-Type: application/json; charset=utf-8",
|
||
"X-Tap-Nonce": grand.S(6),
|
||
"X-Tap-Ts": gtime.Now().TimestampStr(),
|
||
}
|
||
ctx2 := context.Background()
|
||
var method = "GET"
|
||
if len(_data) > 0 {
|
||
method = "POST"
|
||
|
||
}
|
||
|
||
//temp := []byte(`{"event_type":"charge.succeeded","order":{"order_id":"1790288650833465345","purchase_token":"rT2Et9p0cfzq4fwjrTsGSacq0jQExFDqf5gTy1alp+Y=","client_id":"o6nD4iNavjQj75zPQk","open_id":"4+Axcl2RFgXbt6MZwdh++w==","user_region":"US","goods_open_id":"com.goods.open_id","goods_name":"TestGoodsName","status":"charge.succeeded","amount":"19000000000","currency":"USD","create_time":"1716168000","pay_time":"1716168000","extra":"1111111111111111111"}}`)
|
||
var body io.Reader
|
||
if len(_data) > 0 {
|
||
body = bytes.NewBuffer(gjson.MustEncode(_data[0]))
|
||
} else {
|
||
body = bytes.NewBuffer([]byte{})
|
||
}
|
||
req, _ := http.NewRequestWithContext(ctx2, method, url, body)
|
||
for k, v := range header {
|
||
req.Header.Set(k, v)
|
||
}
|
||
sign, err2 := p.Sign(req, p.Secret)
|
||
if err2 != nil {
|
||
err = err2
|
||
return
|
||
}
|
||
req.Header.Set("X-Tap-Sign", sign)
|
||
header["X-Tap-Sign"] = sign
|
||
if len(_data) == 0 {
|
||
_get, err = g.Client().Header(header).ContentJson().Get(gctx.New(), url)
|
||
} else {
|
||
_get, err = g.Client().Header(header).ContentJson().Post(gctx.New(), url, _data[0])
|
||
}
|
||
|
||
if err != nil {
|
||
return
|
||
}
|
||
getPayData = &GetPayData{}
|
||
resData := _get.ReadAll()
|
||
g.Dump(resData)
|
||
if err = json.Unmarshal(resData, &getPayData); err != nil {
|
||
return
|
||
}
|
||
if !getPayData.Success {
|
||
err = errors.New(string(resData))
|
||
}
|
||
return
|
||
}
|