Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
59 changes: 59 additions & 0 deletions client.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ import (
"github.com/google/go-querystring/query"
)

const pushTokensParameter = "pushTokens"

// New initialize client.
func New(url string, key string) *Client {
return &Client{
Expand Down Expand Up @@ -934,6 +936,63 @@ func (c *Client) CustomersUpload(customers []Customer, site ...string) (Customer
return resp, status, nil
}

// CustomersPushTokensBatch creates or edits customer mobile application push tokens in batch.
//
// For more information see https://docs.retailcrm.ru/Developers/API/APIMethods#post--api-v5-customers-push-tokens-batch
//
// Example:
//
// var client = retailcrm.New("https://demo.url", "09jIJ")
//
// data, status, err := client.CustomersPushTokensBatch([]retailcrm.PushTokenInput{
// {
// Customer: retailcrm.PushTokenCustomer{
// ExternalID: "customer-1",
// Site: "main",
// },
// FID: "firebase-installation-id",
// Type: "firebase-project",
// DeviceType: "android",
// Categories: []string{"news"},
// },
// })
//
// if err != nil {
// if apiErr, ok := retailcrm.AsAPIError(err); ok {
// log.Fatalf("http status: %d, %s", status, apiErr.String())
// }
//
// log.Fatalf("http status: %d, error: %s", status, err)
// }
//
// for _, pushToken := range data.PushTokens {
// log.Printf("%v\n", pushToken)
// }
func (c *Client) CustomersPushTokensBatch(pushTokens []PushTokenInput) (CustomersPushTokensBatchResponse, int, error) {
var resp CustomersPushTokensBatchResponse

pushTokensJSON, err := marshalToString(&pushTokens)
if err != nil {
return resp, 0, err
}

p := url.Values{
pushTokensParameter: {pushTokensJSON},
}

data, status, err := c.PostRequest("/customers/push-tokens/batch", p)
if err != nil {
return resp, status, err
}

err = json.Unmarshal(data, &resp)
if err != nil {
return resp, status, err
}

return resp, status, nil
}

// Customer returns information about customer
//
// For more information see http://www.simla.com/docs/Developers/API/APIVersions/APIv5#get--api-v5-customers-externalId
Expand Down
68 changes: 68 additions & 0 deletions client_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -801,6 +801,74 @@ func TestClient_CustomersUpload_Fail(t *testing.T) {
assert.Equal(t, "Something went wrong", err.(APIError).Errors()["managerId"]) //nolint:errorlint
}

func TestClient_CustomersPushTokensBatch(t *testing.T) {
defer gock.Off()

pushTokens := []PushTokenInput{{
Customer: PushTokenCustomer{ExternalID: "customer-1", Site: "main"},
FID: "firebase-installation-id",
Type: "firebase-project",
DeviceType: "android",
Categories: []string{"news"},
}}
pushTokensJSON, err := json.Marshal(pushTokens)
require.NoError(t, err)

p := url.Values{pushTokensParameter: {string(pushTokensJSON)}}

gock.New(crmURL).
Post(prefix + "/customers/push-tokens/batch").
BodyString(p.Encode()).
Reply(http.StatusOK).
JSON(`{
"success": true,
"pushTokens": [{
"id": 123,
"customer": {"externalId": "customer-1"},
"fid": "firebase-installation-id",
"type": "firebase-project",
"deviceType": "android",
"categories": [{"id": 1, "name": "News", "code": "news", "active": true}]
}]
}`)

resp, status, err := client().CustomersPushTokensBatch(pushTokens)
require.NoError(t, err)
assert.Equal(t, http.StatusOK, status)
assert.True(t, resp.Success)
require.Len(t, resp.PushTokens, 1)
assert.Equal(t, 123, resp.PushTokens[0].ID)
assert.Equal(t, "firebase-installation-id", resp.PushTokens[0].FID)
require.Len(t, resp.PushTokens[0].Categories, 1)
assert.Equal(t, "news", resp.PushTokens[0].Categories[0].Code)
}

func TestClient_CustomersPushTokensBatchFail(t *testing.T) {
defer gock.Off()

pushTokens := []PushTokenInput{{
Customer: PushTokenCustomer{ID: 123},
FID: "firebase-installation-id",
Type: "firebase-project",
DeviceType: "ios",
}}
pushTokensJSON, err := json.Marshal(pushTokens)
require.NoError(t, err)

p := url.Values{pushTokensParameter: {string(pushTokensJSON)}}

gock.New(crmURL).
Post(prefix + "/customers/push-tokens/batch").
BodyString(p.Encode()).
Reply(http.StatusBadRequest).
JSON(`{"success":false,"errorMsg":"Invalid push token"}`)

resp, status, err := client().CustomersPushTokensBatch(pushTokens)
require.Error(t, err)
assert.Equal(t, http.StatusBadRequest, status)
assert.False(t, resp.Success)
}

func TestClient_CustomersCombine(t *testing.T) {
c := client()

Expand Down
6 changes: 6 additions & 0 deletions response.go
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,12 @@ type CustomersResponse struct {
Customers []Customer `json:"customers,omitempty"`
}

// CustomersPushTokensBatchResponse type.
type CustomersPushTokensBatchResponse struct {
Success bool `json:"success"`
PushTokens []PushToken `json:"pushTokens,omitempty"`
}

// CorporateCustomersResponse type.
type CorporateCustomersResponse struct {
Success bool `json:"success"`
Expand Down
39 changes: 39 additions & 0 deletions types.go
Original file line number Diff line number Diff line change
Expand Up @@ -212,6 +212,45 @@ type Customer struct {
MainCompany *IdentifiersPair `json:"mainCompany,omitempty"`
}

// PushTokenCustomer identifies the customer who owns a mobile application push token.
type PushTokenCustomer struct {
ID int `json:"id,omitempty"`
ExternalID string `json:"externalId,omitempty"`
BrowserID string `json:"browserId,omitempty"`
Site string `json:"site,omitempty"`
}

// PushTokenInput contains mobile application push token data for batch creation or editing.
type PushTokenInput struct {
Customer PushTokenCustomer `json:"customer"`
Token string `json:"token,omitempty"` // Deprecated: use FID.
FID string `json:"fid,omitempty"`
Type string `json:"type"`
DeviceType string `json:"deviceType"`
Categories []string `json:"categories,omitempty"`
}

// PushCategory describes a mobile push notification category.
type PushCategory struct {
ID int `json:"id,omitempty"`
Name string `json:"name,omitempty"`
Code string `json:"code,omitempty"`
Active bool `json:"active,omitempty"`
CreatedAt string `json:"createdAt,omitempty"`
}

// PushToken describes a customer's mobile application push token.
type PushToken struct {
ID int `json:"id,omitempty"`
Customer PushTokenCustomer `json:"customer,omitempty"`
Token string `json:"token,omitempty"` // Deprecated: use FID.
FID string `json:"fid,omitempty"`
Type string `json:"type,omitempty"`
DeviceType string `json:"deviceType,omitempty"`
Categories []PushCategory `json:"categories,omitempty"`
CreatedAt string `json:"createdAt,omitempty"`
}

// MGCustomer type.
type MGCustomer struct {
ID int `json:"id,omitempty"`
Expand Down
Loading