Skip to content

Commit 9f51f2f

Browse files
authored
Merge pull request #12 from OrderMyGear/document-uploads
carrier document uploads
2 parents ade2e9e + ab415ce commit 9f51f2f

File tree

6 files changed

+88
-14
lines changed

6 files changed

+88
-14
lines changed

.gitignore

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
/pkg/
22
/vendor/
3-
.idea
3+
.idea
4+
.tool-versions

VERSION

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
1.5.0
1+
1.6.0

client/carrier_account.go

Lines changed: 44 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,26 @@
11
package client
22

33
import (
4+
"bytes"
45
"encoding/json"
56
"errors"
67
"fmt"
8+
"io"
9+
"mime/multipart"
710
"net/http"
811

912
"github.com/OrderMyGear/go-shippo/models"
1013
)
1114

15+
var (
16+
ErrEmptyObjectID = errors.New("empty object ID")
17+
ErrNilInput = errors.New("nil input")
18+
)
19+
1220
// CreateCarrierAccount creates a new carrier account object.
1321
func (c *Client) CreateCarrierAccount(input *models.CarrierAccountInput, shippoSubAccountID string) (*models.CarrierAccount, error) {
1422
if input == nil {
15-
return nil, errors.New("nil input")
23+
return nil, ErrNilInput
1624
}
1725

1826
output := &models.CarrierAccount{}
@@ -22,7 +30,7 @@ func (c *Client) CreateCarrierAccount(input *models.CarrierAccountInput, shippoS
2230

2331
func (c *Client) RegisterCarrierAccount(input *models.CarrierAccountInput, shippoSubAccountID string) (*models.CarrierAccount, error) {
2432
if input == nil {
25-
return nil, errors.New("nil input")
33+
return nil, ErrNilInput
2634
}
2735

2836
output := &models.CarrierAccount{}
@@ -33,7 +41,7 @@ func (c *Client) RegisterCarrierAccount(input *models.CarrierAccountInput, shipp
3341
// RetrieveCarrierAccount retrieves an existing carrier account by object id.
3442
func (c *Client) RetrieveCarrierAccount(objectID string, shippoSubAccountID string) (*models.CarrierAccount, error) {
3543
if objectID == "" {
36-
return nil, errors.New("Empty object ID")
44+
return nil, ErrEmptyObjectID
3745
}
3846

3947
output := &models.CarrierAccount{}
@@ -60,10 +68,10 @@ func (c *Client) ListAllCarrierAccounts(shippoSubAccountID string) ([]*models.Ca
6068
// AccountID and Carrier cannot be updated because they form the unique identifier together.
6169
func (c *Client) UpdateCarrierAccount(objectID string, input *models.CarrierAccountInput, shippoSubAccountID string) (*models.CarrierAccount, error) {
6270
if objectID == "" {
63-
return nil, errors.New("Empty object ID")
71+
return nil, ErrEmptyObjectID
6472
}
6573
if input == nil {
66-
return nil, errors.New("nil input")
74+
return nil, ErrNilInput
6775
}
6876

6977
output := &models.CarrierAccount{}
@@ -73,7 +81,7 @@ func (c *Client) UpdateCarrierAccount(objectID string, input *models.CarrierAcco
7381

7482
func (c *Client) ConnectCarrierAccount(objectID, redirectUrl, state string, shippoSubAccountID string) (string, error) {
7583
if objectID == "" {
76-
return "", errors.New("Empty object ID")
84+
return "", ErrEmptyObjectID
7785
}
7886

7987
url := fmt.Sprintf("/carrier_accounts/%s/signin/initiate?redirect_uri=%s&state=%s&redirect=false", objectID, redirectUrl, state)
@@ -86,3 +94,33 @@ func (c *Client) ConnectCarrierAccount(objectID, redirectUrl, state string, ship
8694

8795
return output.RedirectUri, nil
8896
}
97+
98+
func (c *Client) UploadCarrierAccountDocument(objectID string, input *models.CarrierAccountDocumentInput, shippoSubAccountID string) error {
99+
if objectID == "" {
100+
return ErrEmptyObjectID
101+
}
102+
if input == nil {
103+
return ErrNilInput
104+
}
105+
106+
var buf bytes.Buffer
107+
mw := multipart.NewWriter(&buf)
108+
109+
if err := mw.WriteField("document_type", input.DocumentType); err != nil {
110+
return fmt.Errorf("Error writing document_type field: %s", err.Error())
111+
}
112+
113+
fw, err := mw.CreateFormFile("file", input.Filename)
114+
if err != nil {
115+
return fmt.Errorf("Error creating file field: %s", err.Error())
116+
}
117+
if _, err := io.Copy(fw, input.File); err != nil {
118+
return fmt.Errorf("Error writing file content: %s", err.Error())
119+
}
120+
121+
if err := mw.Close(); err != nil {
122+
return fmt.Errorf("Error closing multipart writer: %s", err.Error())
123+
}
124+
125+
return c.doRaw(http.MethodPost, "/carrier_accounts/"+objectID+"/documents", &buf, mw.FormDataContentType(), nil, c.subAccountHeader(shippoSubAccountID))
126+
}

client/client.go

Lines changed: 32 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,36 @@ func (c *Client) _do(baseUrl, method, path string, input, output interface{}, he
6969
return nil
7070
}
7171

72+
func (c *Client) doRaw(method, path string, body io.Reader, contentType string, output interface{}, headers map[string]string) error {
73+
url := shippoAPIBaseURL + path
74+
75+
req, err := http.NewRequest(method, url, body)
76+
if err != nil {
77+
return fmt.Errorf("Error creating HTTP request: %s", err.Error())
78+
}
79+
80+
req.Header.Set("Content-Type", contentType)
81+
req.Header.Set("Authorization", "ShippoToken "+c.privateToken)
82+
if c.apiVersion != "" {
83+
req.Header.Set("Shippo-API-Version", c.apiVersion)
84+
}
85+
req.Header.Set("Connection", "close")
86+
req.Close = true
87+
88+
for k, v := range headers {
89+
req.Header.Set(k, v)
90+
}
91+
92+
if err := c.executeRequest(req, output); err != nil {
93+
if aerr, ok := err.(*errors.APIError); ok {
94+
return aerr
95+
}
96+
return fmt.Errorf("Error executing request: %s", err.Error())
97+
}
98+
99+
return nil
100+
}
101+
72102
func (c *Client) doList(method, path string, input interface{}, outputCallback listOutputCallback, headers map[string]string) error {
73103
nextURL := shippoAPIBaseURL + path + "?results=25"
74104

@@ -161,11 +191,8 @@ func (c *Client) createRequest(method, url string, bodyObject interface{}, heade
161191
req.Header.Set("Connection", "close")
162192
req.Close = true
163193

164-
// add any passed in headers
165-
if headers != nil {
166-
for k, v := range headers {
167-
req.Header.Set(k, v)
168-
}
194+
for k, v := range headers {
195+
req.Header.Set(k, v)
169196
}
170197

171198
return req, nil

go.mod

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
module github.com/OrderMyGear/go-shippo
22

3-
go 1.19
3+
go 1.24

models/carrier_account.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
package models
22

3+
import "io"
4+
35
// See https://goshippo.com/docs/reference#carrier-accounts
46
type CarrierAccountInput struct {
57
Carrier string `json:"carrier"`
@@ -28,3 +30,9 @@ type Authentication struct {
2830
type ConnectOauth struct {
2931
RedirectUri string `json:"redirect_uri"`
3032
}
33+
34+
type CarrierAccountDocumentInput struct {
35+
DocumentType string
36+
Filename string
37+
File io.Reader
38+
}

0 commit comments

Comments
 (0)