This commit is contained in:
李子铭 2024-12-10 13:49:47 +08:00
parent 2016395646
commit c5c809a019
20 changed files with 324 additions and 102 deletions

View File

@ -5,7 +5,7 @@ go 1.22.2
replace plugins/utils => ../../utils
require (
gitea.cdlsxd.cn/sdk/plugin v1.0.17
gitea.cdlsxd.cn/sdk/plugin v1.0.19
github.com/go-playground/validator/v10 v10.22.0
github.com/hashicorp/go-plugin v1.6.1
github.com/stretchr/testify v1.9.0

View File

@ -1,5 +1,7 @@
gitea.cdlsxd.cn/sdk/plugin v1.0.17 h1:agk+9iA1ZI6fLVLtxEnuOWxcDzSq9QH7VBFvhlZZsbw=
gitea.cdlsxd.cn/sdk/plugin v1.0.17/go.mod h1:O/bYQWg1o9g/cBq9qNA3kLIpuPt7VDZqj1bPE6s04NM=
gitea.cdlsxd.cn/sdk/plugin v1.0.19 h1:j0Ifn3q+C7ibxSTfL1KbmnX1k/VO9e0XMDJSuPutixU=
gitea.cdlsxd.cn/sdk/plugin v1.0.19/go.mod h1:O/bYQWg1o9g/cBq9qNA3kLIpuPt7VDZqj1bPE6s04NM=
github.com/bufbuild/protocompile v0.4.0 h1:LbFKd2XowZvQ/kajzguUp2DC9UEIQhIq77fZZlaQsNA=
github.com/bufbuild/protocompile v0.4.0/go.mod h1:3v93+mbWn/v3xzN+31nwkJfrEpAUwp+BagBSZWx+TP8=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=

View File

@ -99,5 +99,5 @@ func (s *AlipayCpnService) Notify(_ context.Context, request *proto.NotifyReques
if !b {
return nil, proto.ErrorSignFail("验签失败")
}
return notifyResp(n), nil
return notifyResp(n)
}

View File

@ -6,6 +6,7 @@ import (
"gitea.cdlsxd.cn/sdk/plugin/proto"
"github.com/go-playground/validator/v10"
"html"
"net/http"
"plugins/alipay_cpn/internal/po"
"plugins/alipay_cpn/internal/vo"
"time"
@ -134,10 +135,11 @@ func notifyReq(in *proto.NotifyRequest) *po.Notify {
return n
}
func notifyResp(n *po.Notify) *proto.NotifyResponse {
func notifyResp(n *po.Notify) (*proto.NotifyResponse, error) {
var b po.NotifyBizContent
_ = json.Unmarshal([]byte(n.BizContent), &b)
return &proto.NotifyResponse{
pb := &proto.NotifyResponse{
Result: &proto.Result{
Status: b.BizType.GetOrderStatus(),
OrderNo: b.OrderID,
@ -146,4 +148,15 @@ func notifyResp(n *po.Notify) *proto.NotifyResponse {
},
Return: "success",
}
headers := make(http.Header)
headers.Set("Content-Type", "text/plain")
headersBytes, err := json.Marshal(headers)
if err != nil {
return nil, err
}
pb.Headers = string(headersBytes)
return pb, nil
}

View File

@ -5,7 +5,7 @@ go 1.22.2
replace plugins/utils => ../../utils
require (
gitea.cdlsxd.cn/sdk/plugin v1.0.17
gitea.cdlsxd.cn/sdk/plugin v1.0.19
github.com/go-playground/validator/v10 v10.22.0
github.com/hashicorp/go-plugin v1.6.1
github.com/stretchr/testify v1.9.0

View File

@ -1,5 +1,7 @@
gitea.cdlsxd.cn/sdk/plugin v1.0.17 h1:agk+9iA1ZI6fLVLtxEnuOWxcDzSq9QH7VBFvhlZZsbw=
gitea.cdlsxd.cn/sdk/plugin v1.0.17/go.mod h1:O/bYQWg1o9g/cBq9qNA3kLIpuPt7VDZqj1bPE6s04NM=
gitea.cdlsxd.cn/sdk/plugin v1.0.19 h1:j0Ifn3q+C7ibxSTfL1KbmnX1k/VO9e0XMDJSuPutixU=
gitea.cdlsxd.cn/sdk/plugin v1.0.19/go.mod h1:O/bYQWg1o9g/cBq9qNA3kLIpuPt7VDZqj1bPE6s04NM=
github.com/bufbuild/protocompile v0.4.0 h1:LbFKd2XowZvQ/kajzguUp2DC9UEIQhIq77fZZlaQsNA=
github.com/bufbuild/protocompile v0.4.0/go.mod h1:3v93+mbWn/v3xzN+31nwkJfrEpAUwp+BagBSZWx+TP8=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=

View File

@ -103,5 +103,5 @@ func (s *AlipayRedPackService) Notify(_ context.Context, request *proto.NotifyRe
if !b {
return nil, proto.ErrorSignFail("验签失败")
}
return notifyResp(n), nil
return notifyResp(n)
}

View File

@ -6,6 +6,7 @@ import (
"gitea.cdlsxd.cn/sdk/plugin/proto"
"github.com/go-playground/validator/v10"
"html"
"net/http"
"plugins/alipay_redpack/internal/po"
"plugins/alipay_redpack/internal/vo"
"plugins/utils/alipay"
@ -151,10 +152,11 @@ func notifyReq(in *proto.NotifyRequest) *po.Notify {
return n
}
func notifyResp(n *po.Notify) *proto.NotifyResponse {
func notifyResp(n *po.Notify) (*proto.NotifyResponse, error) {
var b po.NotifyBizContent
_ = json.Unmarshal([]byte(n.BizContent), &b)
return &proto.NotifyResponse{
pb := &proto.NotifyResponse{
Result: &proto.Result{
Status: b.Status.GetOrderStatus(),
OrderNo: b.OutBizNo,
@ -163,4 +165,15 @@ func notifyResp(n *po.Notify) *proto.NotifyResponse {
},
Return: "success",
}
headers := make(http.Header)
headers.Set("Content-Type", "text/plain")
headersBytes, err := json.Marshal(headers)
if err != nil {
return nil, err
}
pb.Headers = string(headersBytes)
return pb, nil
}

View File

@ -5,7 +5,7 @@ go 1.22.2
replace plugins/utils => ../../utils
require (
gitea.cdlsxd.cn/sdk/plugin v1.0.17
gitea.cdlsxd.cn/sdk/plugin v1.0.19
github.com/carlmjohnson/requests v0.24.2
github.com/go-playground/validator/v10 v10.22.0
github.com/hashicorp/go-plugin v1.6.1

View File

@ -1,6 +1,8 @@
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
gitea.cdlsxd.cn/sdk/plugin v1.0.17 h1:agk+9iA1ZI6fLVLtxEnuOWxcDzSq9QH7VBFvhlZZsbw=
gitea.cdlsxd.cn/sdk/plugin v1.0.17/go.mod h1:O/bYQWg1o9g/cBq9qNA3kLIpuPt7VDZqj1bPE6s04NM=
gitea.cdlsxd.cn/sdk/plugin v1.0.19 h1:j0Ifn3q+C7ibxSTfL1KbmnX1k/VO9e0XMDJSuPutixU=
gitea.cdlsxd.cn/sdk/plugin v1.0.19/go.mod h1:O/bYQWg1o9g/cBq9qNA3kLIpuPt7VDZqj1bPE6s04NM=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/bufbuild/protocompile v0.4.0 h1:LbFKd2XowZvQ/kajzguUp2DC9UEIQhIq77fZZlaQsNA=
github.com/bufbuild/protocompile v0.4.0/go.mod h1:3v93+mbWn/v3xzN+31nwkJfrEpAUwp+BagBSZWx+TP8=

View File

@ -3,6 +3,7 @@ package po
import (
"encoding/json"
"fmt"
"gitea.cdlsxd.cn/sdk/plugin/proto"
"github.com/go-playground/validator/v10"
)
@ -20,7 +21,7 @@ func (req *OrderReq) Validate() error {
err := validator.New().Struct(req)
if err != nil {
for _, err = range err.(validator.ValidationErrors) {
return fmt.Errorf("参数有误:" + err.Error())
return proto.ErrorParamFail(fmt.Sprintf("参数有误: %v", err))
}
}
return nil
@ -39,7 +40,7 @@ func (req *QueryReq) Validate() error {
err := validator.New().Struct(req)
if err != nil {
for _, err = range err.(validator.ValidationErrors) {
return fmt.Errorf("参数有误:" + err.Error())
return proto.ErrorParamFail(fmt.Sprintf("参数有误: %v", err))
}
}
return nil
@ -58,7 +59,7 @@ func (req *Notify) Validate() error {
err := validator.New().Struct(req)
if err != nil {
for _, err = range err.(validator.ValidationErrors) {
return fmt.Errorf("参数有误:" + err.Error())
return proto.ErrorParamFail(fmt.Sprintf("参数有误: %v", err))
}
}
return nil

View File

@ -1,13 +1,18 @@
package internal
import (
"context"
"encoding/json"
"fmt"
"gitea.cdlsxd.cn/sdk/plugin/proto"
sdkutils "gitea.cdlsxd.cn/sdk/plugin/utils"
"net/http"
"plugins/union_pay_cpn/internal/po"
"plugins/union_pay_cpn/internal/vo"
request "plugins/utils/request/v2"
"plugins/utils/union_pay"
"strings"
"time"
)
type Config struct {
@ -23,19 +28,78 @@ func transConfig(config []byte) (*Config, error) {
var c Config
err := json.Unmarshal(config, &c)
if err != nil {
return nil, err
return nil, proto.ErrorConfigFail(fmt.Sprintf("配置参数有误:%s", err.Error()))
}
return &c, nil
}
func (c *Config) verify(req *po.Notify, notifyBizMethod string) error {
if req.Headers.SignMethod != vo.SignMethod {
return fmt.Errorf("签名方式不匹配")
}
if req.Headers.AppId != c.AppId {
return fmt.Errorf("appId不匹配")
}
if req.Headers.BizMethod != notifyBizMethod {
return fmt.Errorf("业务方法不匹配")
}
rehash := union_pay.Sha(req.Headers.Version, c.AppId, req.Headers.BizMethod, req.GetReId(), string(req.ToJson()))
lowerStr := strings.ToLower(rehash)
if union_pay.Verify(lowerStr, req.Headers.Sign, []byte(sdkutils.NewPublic().Build(c.Npk))) {
return nil
}
return fmt.Errorf("验签失败")
}
func (c *Config) headers(bizMethod string, req po.Req) http.Header {
h := make(http.Header)
h.Add("Content-type", vo.ContentType)
h.Add("version", vo.Version)
h.Add("appType", vo.AppType)
h.Add("signMethod", vo.SignMethod)
h.Add("appId", c.AppId)
h.Add("bizMethod", bizMethod)
h.Add("reqId", req.GetReId())
now := time.Now()
milliseconds := now.Unix()*1000 + int64(now.Nanosecond())/1e6
h.Add("reqTs", fmt.Sprintf("%d", milliseconds))
rehash := union_pay.Sha(vo.Version, c.AppId, bizMethod, req.GetReId(), string(req.ToJson()))
signValue, err := union_pay.Sign(rehash, []byte(sdkutils.NewPrivate().Build(c.Prk)))
if err != nil {
return nil
}
h.Add("sign", signValue)
return h
}
func (c *Config) Request(ctx context.Context, req po.Req, method, bizMethod string) (http.Header, []byte, error) {
respHeader, respBody, err := request.Post(
ctx,
fmt.Sprintf("%s%s", baseUri, method),
req.ToJson(),
request.WithHeaders(c.headers(bizMethod, req)),
request.WithTimeout(15*time.Second),
request.WithStatusCodeFunc(func(code int) bool {
return code == http.StatusOK
}),
)
if err != nil {
return nil, nil, proto.ErrorRequestFail(err.Error())
}
return respHeader, respBody, nil
}
func (c *Config) orderReq(in *proto.OrderRequest) (*po.OrderReq, error) {
type OrderExtra struct {
OrderDt string `json:"orderDt"`
}
var e OrderExtra
err := json.Unmarshal(in.Order.Extra, &e)
if err != nil {
return nil, fmt.Errorf("订单拓展参数 json unmarshal error: %v", err)
if err := json.Unmarshal(in.Order.Extra, &e); err != nil {
return nil, fmt.Errorf("订单拓展参数fail: %w", err)
}
mobile, err := union_pay.Encrypt([]byte(in.Order.Account), []byte(c.KEY), []byte(c.IV))
@ -119,8 +183,8 @@ func notifyReq(in *proto.NotifyRequest) *po.Notify {
}
}
func notifyResp(request *proto.NotifyRequest, n *po.Notify) *proto.NotifyResponse {
return &proto.NotifyResponse{
func notifyResp(request *proto.NotifyRequest, n *po.Notify) (*proto.NotifyResponse, error) {
pb := &proto.NotifyResponse{
Result: &proto.Result{
OrderNo: n.Body.TransSeq,
TradeNo: n.Body.CouponCd,
@ -130,4 +194,15 @@ func notifyResp(request *proto.NotifyRequest, n *po.Notify) *proto.NotifyRespons
},
Return: "success",
}
headers := make(http.Header)
headers.Set("Content-Type", "text/plain")
headersBytes, err := json.Marshal(headers)
if err != nil {
return nil, err
}
pb.Headers = string(headersBytes)
return pb, err
}

View File

@ -2,9 +2,8 @@ package internal
import (
"context"
"fmt"
"encoding/json"
"gitea.cdlsxd.cn/sdk/plugin/proto"
"github.com/carlmjohnson/requests"
"plugins/union_pay_cpn/internal/po"
)
@ -37,56 +36,64 @@ func (p *UnionPayCpnService) Order(ctx context.Context, request *proto.OrderRequ
if err != nil {
return nil, err
}
uv, err := c.orderReq(request)
req, err := c.orderReq(request)
if err != nil {
return nil, proto.ErrorParamFail(err.Error())
}
if err = req.Validate(); err != nil {
return nil, err
}
_, bodyBytes, err := c.Request(ctx, req, orderMethod, orderBizMethod)
if err != nil {
return nil, err
}
if err = uv.Validate(); err != nil {
return nil, err
}
var response po.OrderResp
url := fmt.Sprintf("%s%s", baseUri, orderMethod)
err = requests.URL(url).Headers(headers(c, uv, orderBizMethod)).BodyJSON(uv).ToJSON(&response).Fetch(ctx)
if err != nil {
return nil, fmt.Errorf("请求异常msg:" + err.Error())
if err = json.Unmarshal(bodyBytes, &response); err != nil {
return nil, proto.ErrorResponseFail(err.Error())
}
return orderResp(request, response), nil
}
func (p *UnionPayCpnService) Query(ctx context.Context, request *proto.QueryRequest) (*proto.QueryResponse, error) {
conf, err := transConfig(request.Config)
c, err := transConfig(request.Config)
if err != nil {
return nil, err
}
uv := queryReq(request, conf.ChNlId)
if err = uv.Validate(); err != nil {
req := queryReq(request, c.ChNlId)
if err = req.Validate(); err != nil {
return nil, err
}
_, bodyBytes, err := c.Request(ctx, req, queryMethod, queryBizMethod)
if err != nil {
return nil, err
}
var response po.QueryResp
url := fmt.Sprintf("%s%s", baseUri, queryMethod)
err = requests.URL(url).Headers(headers(conf, uv, queryBizMethod)).BodyJSON(uv).ToJSON(&response).Fetch(ctx)
if err != nil {
return nil, fmt.Errorf("请求异常msg:" + err.Error())
if err = json.Unmarshal(bodyBytes, &response); err != nil {
return nil, proto.ErrorResponseFail(err.Error())
}
return queryResp(request, response), nil
}
func (p *UnionPayCpnService) Notify(_ context.Context, request *proto.NotifyRequest) (*proto.NotifyResponse, error) {
uv := notifyReq(request)
if err := uv.Validate(); err != nil {
req := notifyReq(request)
if err := req.Validate(); err != nil {
return nil, err
}
conf, err := transConfig(request.Config)
c, err := transConfig(request.Config)
if err != nil {
return nil, err
}
if err = verify(conf, uv, notifyBizMethod); err != nil {
if err = c.verify(req, notifyBizMethod); err != nil {
return nil, err
}
return notifyResp(request, uv), nil
return notifyResp(request, req)
}

View File

@ -1,55 +0,0 @@
package internal
import (
"fmt"
sdkutils "gitea.cdlsxd.cn/sdk/plugin/utils"
"net/http"
"plugins/union_pay_cpn/internal/po"
"plugins/union_pay_cpn/internal/vo"
"plugins/utils/union_pay"
"strings"
"time"
)
func headers(config *Config, req po.Req, bizMethod string) map[string][]string {
h := make(http.Header)
h.Add("Content-type", vo.ContentType)
h.Add("version", vo.Version)
h.Add("appType", vo.AppType)
h.Add("signMethod", vo.SignMethod)
h.Add("appId", config.AppId)
h.Add("bizMethod", bizMethod)
h.Add("reqId", req.GetReId())
now := time.Now()
milliseconds := now.Unix()*1000 + int64(now.Nanosecond())/1e6
h.Add("reqTs", fmt.Sprintf("%d", milliseconds))
rehash := union_pay.Sha(vo.Version, config.AppId, bizMethod, req.GetReId(), string(req.ToJson()))
signValue, err := union_pay.Sign(rehash, []byte(sdkutils.NewPrivate().Build(config.Prk)))
if err != nil {
return nil
}
h.Add("sign", signValue)
return h
}
func verify(config *Config, req *po.Notify, notifyBizMethod string) error {
if req.Headers.SignMethod != vo.SignMethod {
return fmt.Errorf("签名方式不匹配")
}
if req.Headers.AppId != config.AppId {
return fmt.Errorf("appId不匹配")
}
if req.Headers.BizMethod != notifyBizMethod {
return fmt.Errorf("业务方法不匹配")
}
rehash := union_pay.Sha(req.Headers.Version, config.AppId, req.Headers.BizMethod, req.GetReId(), string(req.ToJson()))
lowerStr := strings.ToLower(rehash)
if union_pay.Verify(lowerStr, req.Headers.Sign, []byte(sdkutils.NewPublic().Build(config.Npk))) {
return nil
}
return fmt.Errorf("验签失败")
}

View File

@ -5,7 +5,7 @@ go 1.22.2
replace plugins/utils => ../../utils
require (
gitea.cdlsxd.cn/sdk/plugin v1.0.17
gitea.cdlsxd.cn/sdk/plugin v1.0.19
github.com/carlmjohnson/requests v0.24.2
github.com/go-playground/validator/v10 v10.22.0
github.com/hashicorp/go-plugin v1.6.1

View File

@ -1,6 +1,8 @@
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
gitea.cdlsxd.cn/sdk/plugin v1.0.17 h1:agk+9iA1ZI6fLVLtxEnuOWxcDzSq9QH7VBFvhlZZsbw=
gitea.cdlsxd.cn/sdk/plugin v1.0.17/go.mod h1:O/bYQWg1o9g/cBq9qNA3kLIpuPt7VDZqj1bPE6s04NM=
gitea.cdlsxd.cn/sdk/plugin v1.0.19 h1:j0Ifn3q+C7ibxSTfL1KbmnX1k/VO9e0XMDJSuPutixU=
gitea.cdlsxd.cn/sdk/plugin v1.0.19/go.mod h1:O/bYQWg1o9g/cBq9qNA3kLIpuPt7VDZqj1bPE6s04NM=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/bufbuild/protocompile v0.4.0 h1:LbFKd2XowZvQ/kajzguUp2DC9UEIQhIq77fZZlaQsNA=
github.com/bufbuild/protocompile v0.4.0/go.mod h1:3v93+mbWn/v3xzN+31nwkJfrEpAUwp+BagBSZWx+TP8=

View File

@ -6,7 +6,6 @@ import (
"gitea.cdlsxd.cn/sdk/plugin/proto"
"github.com/wechatpay-apiv3/wechatpay-go/core"
"github.com/wechatpay-apiv3/wechatpay-go/services/cashcoupons"
"go/types"
"plugins/utils/wechat"
"plugins/wechat_cpn/internal/vo"
)
@ -89,10 +88,6 @@ func queryResp(request *proto.QueryRequest, resp *cashcoupons.Coupon) *proto.Que
}
}
func notifyReq(in *proto.NotifyRequest) *types.Nil {
return nil
}
func notifyResp() *proto.NotifyResponse {
return &proto.NotifyResponse{
Result: &proto.Result{

View File

@ -25,7 +25,7 @@ func config() []byte {
// AppKey: "95E7EC7D4A394FF8D11788E5E436DE99",
// BaseUri: "https://openapi.1688sup.com",
// NotifyUrl: "https://gateway.dev.cdlsxd.cn/yxh5api/v1/order/direct/notify",
// MerchantId: 25537,
// MerchantId: 25715,
//}
marshal, _ := json.Marshal(c)
return marshal

View File

@ -0,0 +1,99 @@
package v2
import (
"bytes"
"context"
"fmt"
"io"
"net/http"
"time"
)
// RequestOptions 用于配置请求的各种选项
type RequestOptions struct {
Headers http.Header
Timeout time.Duration
StatusCodeFunc func(int) bool
}
// RequestOption 是一个函数类型用于设置RequestOptions的各个字段
type RequestOption func(*RequestOptions)
// WithTimeout 设置请求超时时间的选项函数
func WithTimeout(timeout time.Duration) RequestOption {
return func(options *RequestOptions) {
options.Timeout = timeout
}
}
// WithHeaders 设置请求头的选项函数
func WithHeaders(headers http.Header) RequestOption {
return func(options *RequestOptions) {
options.Headers = headers
}
}
// WithStatusCodeFunc 设置自定义状态码处理函数的选项函数
func WithStatusCodeFunc(statusCodeFunc func(int) bool) RequestOption {
return func(options *RequestOptions) {
options.StatusCodeFunc = statusCodeFunc
}
}
func Post(ctx context.Context, url string, body []byte, options ...RequestOption) (http.Header, []byte, error) {
return Request(ctx, http.MethodPost, url, body, options...)
}
func Get(ctx context.Context, url string, options ...RequestOption) (http.Header, []byte, error) {
return Request(ctx, http.MethodGet, url, nil, options...)
}
func Put(ctx context.Context, url string, body []byte, options ...RequestOption) (http.Header, []byte, error) {
return Request(ctx, http.MethodPut, url, body, options...)
}
// Request 封装的HTTP请求函数使用选项模式进行配置
func Request(_ context.Context, method, url string, body []byte, options ...RequestOption) (http.Header, []byte, error) {
// 设置默认选项
defaultOptions := &RequestOptions{
Headers: http.Header{
"Content-Type": []string{"application/json"},
},
Timeout: 15 * time.Second,
StatusCodeFunc: func(code int) bool {
return code == http.StatusOK
},
}
// 根据传入的选项更新默认选项
for _, option := range options {
option(defaultOptions)
}
req, err := http.NewRequest(method, url, bytes.NewBuffer(body))
if err != nil {
return nil, nil, fmt.Errorf("创建HTTP请求失败: %w", err)
}
httpClient := &http.Client{
Timeout: defaultOptions.Timeout,
}
resp, err := httpClient.Do(req)
if err != nil {
return nil, nil, fmt.Errorf("发送HTTP请求失败: %w", err)
}
defer resp.Body.Close()
bodyBytes, err := io.ReadAll(resp.Body)
if err != nil {
return nil, nil, fmt.Errorf("读取响应体失败: %w", err)
}
if !defaultOptions.StatusCodeFunc(resp.StatusCode) {
return nil, nil, fmt.Errorf("请求异常:%s", resp.Status)
}
return resp.Header, bodyBytes, nil
}

View File

@ -0,0 +1,66 @@
package v2
import (
"context"
"net/http"
"net/url"
"testing"
"time"
)
func Test_Get(t *testing.T) {
uri := "https://gateway.dev.cdlsxd.cn/adminyx/admin/v1/key_batch/list"
uv := url.Values{}
uv.Set("page", "1")
uv.Set("limit", "2")
h := http.Header{
"Content-Type": []string{"application/x-www-form-urlencoded"},
}
respHeader, respBody, err := Get(context.Background(), uri+"?"+uv.Encode(), WithHeaders(h))
if err != nil {
t.Error(err)
return
}
t.Logf("响应体:", string(respBody))
t.Logf("响应头:", respHeader)
}
func Test_RequestHeaders(t *testing.T) {
uri := "http://example.com/api"
body := []byte("request body")
h := http.Header{
"Content-Type": []string{"application/json"},
"Authorization": []string{"Bearer token"},
}
respHeader, respBody, err := Post(context.Background(), uri, body, WithTimeout(10*time.Second), WithHeaders(h))
if err != nil {
t.Error(err)
return
}
t.Logf("响应体:", string(respBody))
t.Logf("响应头:", respHeader)
}
func Test_RequestStatusCode(t *testing.T) {
uri := "http://example.com/api/update"
body := []byte("update data")
isSuccess := func(code int) bool {
return code == http.StatusOK || code == http.StatusCreated
}
respHeader, respBody, err := Put(context.Background(), uri, body, WithStatusCodeFunc(isSuccess))
if err != nil {
t.Error(err)
return
}
t.Logf("响应体:", string(respBody))
t.Logf("响应头:", respHeader)
}