123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449 |
- // Copyright 2021 Tencent Inc. All rights reserved.
- package core_test
- import (
- "bytes"
- "context"
- "crypto"
- "crypto/rsa"
- "crypto/sha256"
- "crypto/x509"
- "encoding/base64"
- "encoding/json"
- "fmt"
- "io"
- "io/ioutil"
- "math/rand"
- "mime/multipart"
- "net/http"
- "net/http/httptest"
- "net/url"
- "strconv"
- "strings"
- "testing"
- "time"
- "git.nanodreamtech.com/sg/wechatpay-go/core"
- "git.nanodreamtech.com/sg/wechatpay-go/core/auth"
- "git.nanodreamtech.com/sg/wechatpay-go/core/auth/signers"
- "git.nanodreamtech.com/sg/wechatpay-go/core/auth/verifiers"
- "git.nanodreamtech.com/sg/wechatpay-go/core/option"
- "git.nanodreamtech.com/sg/wechatpay-go/utils"
- "github.com/stretchr/testify/assert"
- "github.com/stretchr/testify/require"
- )
- const (
- testMchID = "example-mchid"
- testCertificateSerialNumber = "example-sn"
- // NOTE: 以下是随机生成的测试密钥,请勿用于生产环境
- testPrivateKey = "-----BEGIN TESTING KEY-----\nMIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCkxOav8p5RFFmN\n7hjLGrNtXPYgCd0Zuvxabv+IWl1HVkWi/1iVqac+XwKH/ZeCYDURqZ6P0iiq8NBd\npygoeJiQM+qzaTV3alNXdLcpcaQSNqJ16a7Z2Co5LgOkBJHIF1qUWf+BpAtyLqo5\niGUQ47w3IWQHtfpW7RrECiNsI7kGKuSc4U2JX/gxrFG7ugpRA9Gp1eF0/wBMWSKV\nmKveKERvAueaTKEujpN4lctoO1wsMW93nuFNH1gtHPYmkaZaJS88GEp0VYJIcOpX\n2HlVPPiWx+0KAndcqMLVQ+qTk21tivpjuqPDstxcT9cXn/3CzSEkYrKkMLpjpSl/\nIn+amHddAgMBAAECggEADtQRlsAU82MLdDR7UrwCbdMx60w387raPyFCKflH78WZ\n2sN0K3PrMzfFuItf+UHDROWo+XSGaGvntKX4fTvtLv0dICxVvXt6KKK+YSJzC5iT\nIl13eO91TVQQy9AFdqZzZmp7DiW/SfVdKHRX9B8qryN4JyF/eBc6k23+JhtI6X8J\nrPeXGcw/Muo2cvoZ6oarRvzKU7pDivZADavAsgGwi+QwZUtrpUhDbJxWxoasCrWz\n6X24D+JbKndf/AeyHC2mqoAwTYdQgkkPHLJWGsqAt/GHtHLmZHIPc0dXfksP5omX\nOIii34YNud1j2/X0ryxoRBKPGIolV5Tyyh9PX75UAQKBgQDa/oPFUNsBo+NkfE4r\nMry+mnAeBM06vZh65acbHu3prqzn7tzfQR5rF9nIEUjNkach+ZeTnUxKfX4TwfiL\nibbM1Epb+yhEpSlA9HhY1AGhdNKpFbq63oVzS+lwpmLcXFLHhOYw8GrnYH9lcE+E\nYCqFcuk4t/y3rU/8Y5GhZKZ53QKBgQDAnKk6CEgnSkXfZLmzVtoM/5hnI0GEDOUo\nV35alqvgdJtCiPs4C03snYLVHqHjAknGzLGONAQ6h9au2qwcHy1qH/noq151u92b\nbCrKmghnm2SoIgCaZ7i2scWm6NM9Da60H662WxjaKcZMnUClm+G+Irl9m5cm1i3V\n56ZU63nbgQKBgHyAlFO6mzg8f4via+J9TvciADngyvjpT2YXaECv/dyL9TtK/oFi\nmTOTdLocsYJFm3piVv2SQQxcejArZ+2U1rtuufO/P25/Y4vNMRp3NZIgQ5/jfay9\n06rv7oCf57aWOm26LdCG7pAquWLnTh3ZOnNyGAup9mBKhR3dUa8q9MZ1AoGATZGJ\n0VYugKw3sXymEKRkkiGJJdgb9WsgCnwZ5a+SLoWnVUdHLM3YpvbUDrIUbhCo14ft\n5Z/rKAs2mRp1f6nKp1eTVHFXTEDJQWNxZEBeLCN3iQKQjZ5B1EmJmOtgztCoz9+G\ng+fx/UIfmxElTMyXP/RKEVzMpZZRxThSUxa174ECgYEAsviAmgBskM2ibtrA8tNW\njHdgut0xAtIJIIHlYmtksWgAWD4cPtCg7HPurXqBKxMogH/ZsZc6/5PpOIRYBNl0\nEebH0MZ/yiEOrmgsFJ1gKWk3fx8/yLQBlhn32AIhj7wmcFwzi/4hcwihHRCjS7t5\nQhVpKswxQyxqeIdQw0CgKZY=\n-----END TESTING KEY-----"
- testWechatPrivateKeyStr = "-----BEGIN TESTING KEY-----\nMIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDzbMaiMbCzJ11sZ2r7/XisolGu1pVpWvnv1PVOAWZZAWr/WcNNuLni8ddJkIs8NdTz+iAHtb9XMNG4hj7d10cy8QE6QG8YUef1fGb47Wee3DjJRk8N9lWyPDAy9AW70yYWItl/05XgkGt2eJuoU5CcZ+Cy0u2nAXxEGs2Z4Fg/100Ylcyq4GrimjngIyUFLnowOcZltJUQSw/Iu63V0BEh9PMNnXhKkwS2xfkA2nZRzSgzpMvX74v8F7Zf+HkyrHHzwY/7YUWg3pSj3GD0xKsJOwzz0MLlS8uIdLj1lKGzzt1ROgwe0sM5LL5XMfmbjDhcVBmyxQI80WiNaC281tVhAgMBAAECggEBAJ134Wrs0Ayky2ej4u5OAvFSM5rxj0fPJV3DGkiy2R18sFWtII03kXBA1+7rxVZW0IJfbLbwGG3z08cVeLeTWqiWhR/ErNlDqtT/+7DOCrkWZtm1VNCIaNla3Ccp+keNiNbLBn4NRqg1ZH8H+FHEdQjonc+waTIe4N9Bo30GRrBMeMbAgN8mwQhZ+6R23j3GsrJOViFpPRgGhih4aEAORxU+DWl22vklxO8lnDzSwfnXvNDvapnPaA8VXekkThxABq3p/ggv5MI1QPYl8BU5PWd6AJlPs/u2nzFGmCgVufHMjdszWYd3hbj5EmhlL1VMs4uxhCC8OM+ypbnx0CmBB5ECgYEA+W3KJciw4qG6XqWgjK9hkgiZrO8z3tu6tQ6ge28f3BxYEbGUab8bKKzacbYODRiRCM5oKcrXfTqP6IbqUoESiuoz0CUPbShp7k00wXKd7BH8LoIECDbctz77NG0KBE31OGEJw4hm762M14V9nU0KDHGuud1CH1fqivTGG0g2HiUCgYEA+dZ+e5iSvin+omXkr3Vhwf3kutX+GNkKm5LrWZNmWybOKw/K1YFvESpfl1b6YgjA/qUXj0tbOumFQw6e/OLfxIvK/dtkd+7pbSC4T9w8rH7zgjYdJ030Nyv3UGfHDbES+z9MDMo5h+3RKsLN2bp1JcXp6vht9CiXDYm1df3O340CgYB118Qg08+WU1iM7O2MajPL3dpVFPJJwUBV2GJDzv2bbZzCR0baKxr2vau6+4tp7ohfQ718uUPT+34QGuXMMwUCsqHmHgxKw0RA/SMGnlM0PE8L3gtvohPnU481dqq72+UWTOpjAie35yPak0wErGgp9u/ZCkr6Kfw6yGhsbVJ8LQKBgEBLxS1FrK4n3JIqqtnE2a21C4JRxBzc7m/vNYZN+s+GgxRt8gNUViMSxpsKFVHZcuGV1yRXflkA8/y37I6kTHYmi80dAxQidgxRmV1kDnFOEpj2GDafRzRTqkgVDRMm+P2T4pyABqJGv8fDbnqUE8Xu0y5XVOS69XTUddCxyuWZAoGAbpF6JOh6B7OV4XRTDm98Z8OPYmYd9JQ4xt8bqsG9LdzvhU/PI4zwIaKDqZ8vzCI+r8TOrC6SBEfjAe6o2FEExmFWTjBAVCp+Qvnz+Pj7d+WP3kCX/B62IZckVhdV3a2frMTBPvAh8XdENdvsu4DsWJBCA54GLU3wdUa/FO0RUsA=\n-----END TESTING KEY-----\n"
- testWechatCertificateStr = "-----BEGIN CERTIFICATE-----\nMIID1TCCAr2gAwIBAgIRAJ8qZJYAQUwUheimQ8sQNZMwDQYJKoZIhvcNAQELBQAw\nXjELMAkGA1UEBhMCQ04xDjAMBgNVBAoTBU15U1NMMSswKQYDVQQLEyJNeVNTTCBU\nZXN0IFJTQSAtIEZvciB0ZXN0IHVzZSBvbmx5MRIwEAYDVQQDEwlNeVNTTC5jb20w\nHhcNMjEwNjI3MTMwNTM2WhcNMjIwNjI3MTMwNTM2WjAkMQswCQYDVQQGEwJDTjEV\nMBMGA1UEAxMMd2VjaGF0cGF5LWdvMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB\nCgKCAQEA82zGojGwsyddbGdq+/14rKJRrtaVaVr579T1TgFmWQFq/1nDTbi54vHX\nSZCLPDXU8/ogB7W/VzDRuIY+3ddHMvEBOkBvGFHn9Xxm+O1nntw4yUZPDfZVsjww\nMvQFu9MmFiLZf9OV4JBrdnibqFOQnGfgstLtpwF8RBrNmeBYP9dNGJXMquBq4po5\n4CMlBS56MDnGZbSVEEsPyLut1dARIfTzDZ14SpMEtsX5ANp2Uc0oM6TL1++L/Be2\nX/h5Mqxx88GP+2FFoN6Uo9xg9MSrCTsM89DC5UvLiHS49ZShs87dUToMHtLDOSy+\nVzH5m4w4XFQZssUCPNFojWgtvNbVYQIDAQABo4HHMIHEMA4GA1UdDwEB/wQEAwIH\ngDATBgNVHSUEDDAKBggrBgEFBQcDAzAfBgNVHSMEGDAWgBQogSYF0TQaP8FzD7uT\nzxUcPwO/fzBjBggrBgEFBQcBAQRXMFUwIQYIKwYBBQUHMAGGFWh0dHA6Ly9vY3Nw\nLm15c3NsLmNvbTAwBggrBgEFBQcwAoYkaHR0cDovL2NhLm15c3NsLmNvbS9teXNz\nbHRlc3Ryc2EuY3J0MBcGA1UdEQQQMA6CDHdlY2hhdHBheS1nbzANBgkqhkiG9w0B\nAQsFAAOCAQEAjh4oxMcJqsVaN5/aA+4+NSfV9wR4uzTVtAyL/dApymZn6Wjknd85\nDltekcTflNP84bDiFEE3Ls3RYatjRx9pWeW7QbpdYvfDtWuxL5dhzRYtUO83z8wT\n+/sceeyNOQAWGD6Gt7Aw7yb7bIZ5slcZYepqdKSHyMnn06CCNRZtDVTuQYRqnmoh\nCaK5RNe4lYM/hncMgddE/DugTxzh5NUMpAY4xAsqOofkVmptX3trVZVILPglJ6nQ\n5dALCpp2UCuxikwFdEpvvGIC2qZQv5jmemFLCDIQZ227GUZ/EcbuTtAdQYHUnGJT\nvrFBSDe4FbKwljUmrccD/LkR9FmPn6gWKA==\n-----END CERTIFICATE-----\n"
- fileName = "picture.jpeg"
- responseBody = `{"hello":"client"}`
- testRequestUri = "/v3/resource?first=this+is+a+field&second=was+it+clear+%28already%29%3F"
- )
- var (
- privateKey *rsa.PrivateKey
- wechatPayPrivateKey *rsa.PrivateKey
- wechatPayCertificate *x509.Certificate
- signer auth.Signer
- verifier auth.Verifier
- ctx context.Context
- )
- type signParameter map[string]string
- func init() {
- ctx = context.Background()
- var err error
- privateKey, err = utils.LoadPrivateKey(testingKey(testPrivateKey))
- if err != nil {
- panic(fmt.Errorf("load merchant testing key err:%s", err.Error()))
- }
- wechatPayCertificate, err = utils.LoadCertificate(testWechatCertificateStr)
- if err != nil {
- panic(fmt.Errorf("generate wechatpay testing certificate err:%s", err.Error()))
- }
- wechatPayPrivateKey, err = utils.LoadPrivateKey(testingKey(testWechatPrivateKeyStr))
- if err != nil {
- panic(fmt.Errorf("generate wechatpay testing key err:%s", err.Error()))
- }
- }
- func writeResponse(w http.ResponseWriter) {
- writeSignature(w, responseBody)
- w.WriteHeader(http.StatusOK)
- fmt.Fprint(w, responseBody)
- }
- func writeSignature(w http.ResponseWriter, body string) {
- w.Header().Set("Request-Id", "0")
- w.Header().Set("Wechatpay-Serial", utils.GetCertificateSerialNumber(*wechatPayCertificate))
- nonce := "this-is-a-nonce"
- w.Header().Set("Wechatpay-Nonce", nonce)
- timestamp := strconv.FormatInt(time.Now().Unix(), 10)
- w.Header().Set("Wechatpay-Timestamp", timestamp)
- signature, _ := utils.SignSHA256WithRSA(
- fmt.Sprintf("%s\n%s\n%s\n", timestamp, nonce, body), wechatPayPrivateKey)
- w.Header().Set("Wechatpay-Signature", signature)
- }
- func parseAuthorization(t *testing.T, authorization string) (schema string, param signParameter) {
- m := make(signParameter)
- s1 := strings.Split(authorization, " ")
- assert.Equal(t, len(s1), 2)
- s2 := strings.Split(s1[1], ",")
- assert.Equal(t, len(s2), 5)
- for _, v := range s2 {
- s3 := strings.SplitN(v, "=", 2)
- assert.Equal(t, len(s3), 2)
- pk := s3[0]
- pv := strings.Trim(s3[1], "\"")
- m[pk] = pv
- }
- return s1[0], m
- }
- func assertAuthorization(t *testing.T, schema, method, uri string, params signParameter, body []byte) {
- assert.Equal(t, schema, "WECHATPAY2-SHA256-RSA2048")
- assert.Equal(t, params["mchid"], testMchID)
- assert.Equal(t, params["serial_no"], testCertificateSerialNumber)
- message := fmt.Sprintf("%s\n%s\n%s\n%s\n%s\n",
- method,
- uri,
- params["timestamp"],
- params["nonce_str"],
- body)
- hashed := sha256.Sum256([]byte(message))
- signBytes, err := base64.StdEncoding.DecodeString(params["signature"])
- assert.NoError(t, err)
- assert.NoError(t, rsa.VerifyPKCS1v15(&privateKey.PublicKey, crypto.SHA256, hashed[:], signBytes))
- }
- func TestGet(t *testing.T) {
- opts := []core.ClientOption{
- option.WithMerchantCredential(testMchID, testCertificateSerialNumber, privateKey),
- option.WithWechatPayCertificate([]*x509.Certificate{wechatPayCertificate}),
- }
- client, err := core.NewClient(ctx, opts...)
- require.NoError(t, err)
- ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
- assert.Equal(t, r.Method, "GET")
- assert.Equal(t, r.RequestURI, testRequestUri)
- schema, params := parseAuthorization(t, r.Header.Get("Authorization"))
- assertAuthorization(t, schema, r.Method, r.RequestURI, params, make([]byte, 0))
- writeResponse(w)
- }))
- defer ts.Close()
- result, err := client.Get(ctx, ts.URL+testRequestUri)
- assert.NoError(t, err)
- body, err := ioutil.ReadAll(result.Response.Body)
- assert.NoError(t, err)
- assert.Equal(t, string(body), responseBody)
- }
- type testData struct {
- StockID string `json:"stock_id"`
- StockCreatorMchID string `json:"stock_creator_mchid"`
- OutRequestNo string `json:"out_request_no"`
- AppID string `json:"appid"`
- }
- func TestPost(t *testing.T) {
- opts := []core.ClientOption{
- option.WithMerchantCredential(testMchID, testCertificateSerialNumber, privateKey),
- option.WithWechatPayCertificate([]*x509.Certificate{wechatPayCertificate}),
- }
- client, err := core.NewClient(ctx, opts...)
- require.NoError(t, err)
- data := &testData{
- StockID: "xxx",
- StockCreatorMchID: "xxx",
- OutRequestNo: "xxx",
- AppID: "xxx",
- }
- ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
- assert.Equal(t, r.Method, "POST")
- assert.Equal(t, r.RequestURI, testRequestUri)
- schema, params := parseAuthorization(t, r.Header.Get("Authorization"))
- body, _ := ioutil.ReadAll(r.Body)
- assertAuthorization(t, schema, r.Method, r.RequestURI, params, body)
- writeResponse(w)
- }))
- defer ts.Close()
- result, err := client.Post(ctx, ts.URL+testRequestUri, data)
- assert.NoError(t, err)
- body, err := ioutil.ReadAll(result.Response.Body)
- assert.NoError(t, err)
- assert.Equal(t, string(body), responseBody)
- }
- func TestRequest(t *testing.T) {
- opts := []core.ClientOption{
- option.WithMerchantCredential(testMchID, testCertificateSerialNumber, privateKey),
- option.WithWechatPayCertificate([]*x509.Certificate{wechatPayCertificate}),
- }
- client, err := core.NewClient(ctx, opts...)
- require.NoError(t, err)
- data := &testData{
- StockID: "xxx",
- StockCreatorMchID: "xxx",
- OutRequestNo: "xxx",
- AppID: "xxx",
- }
- tt := []struct {
- method string
- uri string
- contentType string
- body interface{}
- header http.Header
- }{
- {
- http.MethodGet,
- "/v3/get",
- "",
- nil,
- http.Header{"My-Id": {"1234"}},
- },
- {
- http.MethodPost,
- testRequestUri,
- "application/json",
- data,
- http.Header{"My-Id": {"1234"}},
- },
- {
- http.MethodDelete,
- "/v3/delete",
- "",
- nil,
- nil,
- },
- {
- http.MethodPut,
- "/v3/put",
- "",
- data,
- http.Header{"My-Id": {"1234"}},
- },
- {
- http.MethodPatch,
- "/v3/patch",
- "",
- data,
- nil,
- },
- }
- for _, test := range tt {
- ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
- assert.Equal(t, test.method, r.Method)
- assert.Equal(t, test.uri, r.RequestURI)
- if test.header != nil {
- assert.Equal(t, "1234", r.Header.Get("My-Id"))
- }
- schema, params := parseAuthorization(t, r.Header.Get("Authorization"))
- body, _ := ioutil.ReadAll(r.Body)
- assertAuthorization(t, schema, r.Method, r.RequestURI, params, body)
- assert.Equal(t, "9F2A649600414C1485E8A643CB103593", r.Header.Get("Wechatpay-Serial"))
- if test.body != nil {
- assert.Equal(t, "application/json", r.Header.Get("Content-Type"))
- var req testData
- err = json.Unmarshal(body, &req)
- assert.NoError(t, err)
- assert.Equal(t, data, &req)
- }
- writeResponse(w)
- }))
- testUrl, err := url.Parse(ts.URL + test.uri)
- assert.NoError(t, err)
- result, err := client.Request(
- ctx,
- test.method,
- ts.URL+testUrl.Path,
- test.header,
- testUrl.Query(),
- test.body,
- test.contentType,
- )
- assert.NoError(t, err)
- body, err := ioutil.ReadAll(result.Response.Body)
- assert.NoError(t, err)
- assert.Equal(t, http.StatusOK, result.Response.StatusCode)
- assert.Equal(t, responseBody, string(body))
- ts.Close()
- }
- }
- func TestClientVerifyFail(t *testing.T) {
- opts := []core.ClientOption{
- option.WithMerchantCredential(testMchID, testCertificateSerialNumber, privateKey),
- option.WithWechatPayCertificate([]*x509.Certificate{wechatPayCertificate}),
- }
- client, err := core.NewClient(ctx, opts...)
- require.NoError(t, err)
- ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) {
- w.Header().Set("Request-Id", "0")
- w.Header().Set("Wechatpay-Serial", utils.GetCertificateSerialNumber(*wechatPayCertificate))
- nonce := "this-is-a-nonce"
- w.Header().Set("Wechatpay-Nonce", nonce)
- timestamp := strconv.FormatInt(time.Now().Unix(), 10)
- w.Header().Set("Wechatpay-Timestamp", timestamp)
- w.Header().Set("Wechatpay-Signature", "AABB")
- w.WriteHeader(http.StatusOK)
- }))
- defer ts.Close()
- _, err = client.Get(ctx, ts.URL+testRequestUri)
- assert.Contains(t, err.Error(), "verify fail")
- }
- func TestClientNoAuth(t *testing.T) {
- opts := []core.ClientOption{
- option.WithMerchantCredential(testMchID, testCertificateSerialNumber, privateKey),
- option.WithWechatPayCertificate([]*x509.Certificate{wechatPayCertificate}),
- }
- client, err := core.NewClient(ctx, opts...)
- require.NoError(t, err)
- ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) {
- w.WriteHeader(401)
- w.Header().Set("Request-Id", "0")
- fmt.Fprint(w, `{"code":"SIGN_ERROR","message":"sign error"}`)
- }))
- defer ts.Close()
- _, err = client.Get(ctx, ts.URL+testRequestUri)
- apiError, ok := err.(*core.APIError)
- assert.True(t, ok)
- assert.Equal(t, 401, apiError.StatusCode)
- assert.Equal(t, "SIGN_ERROR", apiError.Code)
- assert.Equal(t, "sign error", apiError.Message)
- }
- type meta struct {
- FileName string `json:"filename" binding:"required"` // 商户上传的媒体图片的名称,商户自定义,必须以JPG、BMP、PNG为后缀。
- Sha256 string `json:"sha256" binding:"required"` // 图片文件的文件摘要,即对图片文件的二进制内容进行sha256计算得到的值。
- }
- func TestClient_Upload(t *testing.T) {
- // 如果你有自定义的Signer或者Verifier
- signer = &signers.SHA256WithRSASigner{
- MchID: testMchID,
- PrivateKey: privateKey,
- CertificateSerialNo: testCertificateSerialNumber,
- }
- verifier = verifiers.NewSHA256WithRSAVerifier(
- core.NewCertificateMap(
- map[string]*x509.Certificate{utils.GetCertificateSerialNumber(*wechatPayCertificate): wechatPayCertificate},
- ),
- )
- client, err := core.NewClient(ctx, option.WithSigner(signer), option.WithVerifier(verifier))
- require.NoError(t, err)
- pictureBytes := make([]byte, 1024)
- // 随机的数据充当图片数据
- rand.Read(pictureBytes)
- // 计算文件序列化后的sha256
- h := sha256.New()
- _, err = h.Write(pictureBytes)
- assert.NoError(t, err)
- metaObject := &meta{}
- pictureSha256 := h.Sum(nil)
- metaObject.FileName = fileName
- metaObject.Sha256 = fmt.Sprintf("%x", string(pictureSha256))
- metaByte, _ := json.Marshal(metaObject)
- reqBody := &bytes.Buffer{}
- writer := multipart.NewWriter(reqBody)
- err = core.CreateFormField(writer, "meta", "application/json", metaByte)
- assert.NoError(t, err)
- err = core.CreateFormFile(writer, fileName, "image/jpg", pictureBytes)
- assert.NoError(t, err)
- err = writer.Close()
- assert.NoError(t, err)
- ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
- assert.Equal(t, r.Method, "POST")
- assert.Equal(t, r.RequestURI, testRequestUri)
- mr, err := r.MultipartReader()
- assert.NoError(t, err)
- var body []byte
- for {
- p, err := mr.NextPart()
- if err == io.EOF {
- break
- }
- assert.NoError(t, err)
- if p.FormName() == "meta" {
- body, _ = ioutil.ReadAll(p)
- assert.Equal(t, metaByte, body)
- } else if p.FormName() == "file" {
- slurp, _ := ioutil.ReadAll(p)
- assert.Equal(t, pictureBytes, slurp)
- }
- }
- schema, params := parseAuthorization(t, r.Header.Get("Authorization"))
- assertAuthorization(t, schema, r.Method, r.RequestURI, params, body)
- writeResponse(w)
- }))
- defer ts.Close()
- result, err := client.Upload(
- ctx,
- ts.URL+testRequestUri,
- string(metaByte),
- reqBody.String(),
- writer.FormDataContentType())
- assert.NoError(t, err)
- if result.Response.Body != nil {
- defer result.Response.Body.Close()
- }
- body, err := ioutil.ReadAll(result.Response.Body)
- assert.NoError(t, err)
- t.Log(string(body))
- assert.Equal(t, string(body), responseBody)
- }
- func testingKey(s string) string { return strings.ReplaceAll(s, "TESTING KEY", "PRIVATE KEY") }
|