diff --git a/bankaccount/client_test.go b/bankaccount/client_test.go index 6e6e064ab9..6387f8ed7b 100644 --- a/bankaccount/client_test.go +++ b/bankaccount/client_test.go @@ -9,31 +9,31 @@ import ( ) func TestBankAccountDel_ByAccount(t *testing.T) { - bankAcount, err := Del("ba_123", &stripe.BankAccountParams{ + bankaccount, err := Del("ba_123", &stripe.BankAccountParams{ Account: stripe.String("acct_123"), }) assert.Nil(t, err) - assert.NotNil(t, bankAcount) + assert.NotNil(t, bankaccount) } func TestBankAccountDel_ByCustomer(t *testing.T) { - bankAcount, err := Del("ba_123", &stripe.BankAccountParams{ + bankaccount, err := Del("ba_123", &stripe.BankAccountParams{ Customer: stripe.String("cus_123"), }) assert.Nil(t, err) - assert.NotNil(t, bankAcount) + assert.NotNil(t, bankaccount) } func TestBankAccountGet_ByAccount(t *testing.T) { - bankAcount, err := Get("ba_123", &stripe.BankAccountParams{Account: stripe.String("acct_123")}) + bankaccount, err := Get("ba_123", &stripe.BankAccountParams{Account: stripe.String("acct_123")}) assert.Nil(t, err) - assert.NotNil(t, bankAcount) + assert.NotNil(t, bankaccount) } func TestBankAccountGet_ByCustomer(t *testing.T) { - bankAcount, err := Get("ba_123", &stripe.BankAccountParams{Customer: stripe.String("cus_123")}) + bankaccount, err := Get("ba_123", &stripe.BankAccountParams{Customer: stripe.String("cus_123")}) assert.Nil(t, err) - assert.NotNil(t, bankAcount) + assert.NotNil(t, bankaccount) } func TestBankAccountList_ByCustomer(t *testing.T) { @@ -46,38 +46,38 @@ func TestBankAccountList_ByCustomer(t *testing.T) { } func TestBankAccountNew_ByAccount(t *testing.T) { - bankAcount, err := New(&stripe.BankAccountParams{ + bankaccount, err := New(&stripe.BankAccountParams{ Account: stripe.String("acct_123"), DefaultForCurrency: stripe.Bool(true), Token: stripe.String("tok_123"), }) assert.Nil(t, err) - assert.NotNil(t, bankAcount) + assert.NotNil(t, bankaccount) } func TestBankAccountNew_ByCustomer(t *testing.T) { - bankAcount, err := New(&stripe.BankAccountParams{ + bankaccount, err := New(&stripe.BankAccountParams{ Customer: stripe.String("cus_123"), Token: stripe.String("tok_123"), }) assert.Nil(t, err) - assert.NotNil(t, bankAcount) + assert.NotNil(t, bankaccount) } func TestBankAccountUpdate_ByAccount(t *testing.T) { - bankAcount, err := Update("ba_123", &stripe.BankAccountParams{ + bankaccount, err := Update("ba_123", &stripe.BankAccountParams{ Account: stripe.String("acct_123"), DefaultForCurrency: stripe.Bool(true), }) assert.Nil(t, err) - assert.NotNil(t, bankAcount) + assert.NotNil(t, bankaccount) } func TestBankAccountUpdate_ByCustomer(t *testing.T) { - bankAcount, err := Update("ba_123", &stripe.BankAccountParams{ + bankaccount, err := Update("ba_123", &stripe.BankAccountParams{ AccountHolderName: stripe.String("New Name"), Customer: stripe.String("cus_123"), }) assert.Nil(t, err) - assert.NotNil(t, bankAcount) + assert.NotNil(t, bankaccount) } diff --git a/issuing/cardholder/client_test.go b/issuing/cardholder/client_test.go index b55715e544..2ed2dbcc3e 100644 --- a/issuing/cardholder/client_test.go +++ b/issuing/cardholder/client_test.go @@ -47,7 +47,11 @@ func TestIssuingCardholderNew(t *testing.T) { func TestIssuingCardholderUpdate(t *testing.T) { cardholder, err := Update("ich_123", &stripe.IssuingCardholderParams{ - Name: stripe.String("Updated name"), + Params: stripe.Params{ + Metadata: map[string]string{ + "foo": "bar", + }, + }, }) assert.Nil(t, err) assert.NotNil(t, cardholder) diff --git a/issuing_cardholder.go b/issuing_cardholder.go index 8fa8d97813..c62ae0e169 100644 --- a/issuing_cardholder.go +++ b/issuing_cardholder.go @@ -9,6 +9,7 @@ type IssuingCardholderStatus string const ( IssuingCardholderStatusActive IssuingCardholderStatus = "active" IssuingCardholderStatusInactive IssuingCardholderStatus = "inactive" + IssuingCardholderStatusPending IssuingCardholderStatus = "pending" ) // IssuingCardholderType is the type of an issuing cardholder. diff --git a/order/client_test.go b/order/client_test.go index a7a6d579bf..78e4567114 100644 --- a/order/client_test.go +++ b/order/client_test.go @@ -48,12 +48,7 @@ func TestOrderPay(t *testing.T) { } func TestOrderReturn(t *testing.T) { - order, err := Return("or_123", &stripe.OrderReturnParams{ - Items: []*stripe.OrderItemParams{ - {Amount: stripe.Int64(1), Description: stripe.String("Item 1")}, - {Amount: stripe.Int64(1), Description: stripe.String("Item 2")}, - }, - }) + order, err := Return("or_123", &stripe.OrderReturnParams{}) assert.Nil(t, err) assert.NotNil(t, order) } diff --git a/person.go b/person.go new file mode 100644 index 0000000000..72ecbddd4a --- /dev/null +++ b/person.go @@ -0,0 +1,124 @@ +package stripe + +import "encoding/json" + +// RelationshipParams is used to set the relationship between an account and a person. +type RelationshipParams struct { + AccountOpener *bool `form:"account_opener"` + Director *bool `form:"director"` + Executive *bool `form:"executive"` + Owner *bool `form:"owner"` + PercentOwnership *float64 `form:"percent_ownership"` + Title *string `form:"title"` +} + +// PersonParams is the set of parameters that can be used when creating or updating a person. +// For more details see https://stripe.com/docs/api#create_person. +type PersonParams struct { + Params `form:"*"` + Account *string `form:"-"` // Included in URL + Address *AccountAddressParams `form:"address"` + AddressKana *AccountAddressParams `form:"address_kana"` + AddressKanji *AccountAddressParams `form:"address_kanji"` + DOB *DOBParams `form:"dob"` + Email *string `form:"email"` + FirstName *string `form:"first_name"` + FirstNameKana *string `form:"first_name_kana"` + FirstNameKanji *string `form:"first_name_kanji"` + Gender *string `form:"gender"` + IDNumber *string `form:"id_number"` + LastName *string `form:"last_name"` + LastNameKana *string `form:"last_name_kana"` + LastNameKanji *string `form:"last_name_kanji"` + MaidenName *string `form:"maiden_name"` + Phone *string `form:"phone"` + Relationship *RelationshipParams `form:"relationship"` + SSNLast4 *string `form:"ssn_last_4"` +} + +// RelationshipListParams is used to filter persons by the relationship +type RelationshipListParams struct { + AccountOpener *bool `form:"account_opener"` + Director *bool `form:"director"` + Executive *bool `form:"executive"` + Owner *bool `form:"owner"` +} + +// PersonListParams is the set of parameters that can be used when listing persons. +// For more detail see https://stripe.com/docs/api#list_persons. +type PersonListParams struct { + ListParams `form:"*"` + Account *string `form:"-"` // Included in URL + Relationship *RelationshipListParams `form:"relationship"` +} + +// Relationship represents extra information needed for a Person. +type Relationship struct { + AccountOpener bool `json:"account_opener"` + Director bool `json:"director"` + Executive bool `json:"executive"` + Owner bool `json:"owner"` + PercentOwnership float64 `json:"percent_ownership"` + Title string `json:"title"` +} + +// Requirements represents what's missing to verify a Person. +type Requirements struct { + CurrentlyDue []string `json:"currently_due"` + EventuallyDue []string `json:"eventually_due"` + PastDue []string `json:"past_due"` +} + +// Person is the resource representing a Stripe person. +// For more details see https://stripe.com/docs/api#persons. +type Person struct { + Account string `json:"account"` + Address *AccountAddress `json:"address"` + AddressKana *AccountAddress `json:"address_kana"` + AddressKanji *AccountAddress `json:"address_kanji"` + Deleted bool `json:"deleted"` + DOB *DOB `json:"dob"` + Email string `json:"email"` + FirstName string `json:"first_name"` + FirstNameKana string `json:"first_name_kana"` + FirstNameKanji string `json:"first_name_kanji"` + Gender string `json:"gender"` + ID string `json:"id"` + IDNumberProvided bool `json:"id_number_provided"` + LastName string `json:"last_name"` + LastNameKana string `json:"last_name_kana"` + LastNameKanji string `json:"last_name_kanji"` + MaidenName string `json:"maiden_name"` + Metadata map[string]string `json:"metadata"` + Object string `json:"object"` + Phone string `json:"phone"` + Relationship *Relationship `json:"relationship"` + Requirements *Requirements `json:"requirements"` + SSNLast4Provided bool `json:"ssn_last_4_provided"` + Verification *IdentityVerification `json:"verification"` +} + +// PersonList is a list of persons as retrieved from a list endpoint. +type PersonList struct { + ListMeta + Data []*Person `json:"data"` +} + +// UnmarshalJSON handles deserialization of a Person. +// This custom unmarshaling is needed because the resulting +// property may be an id or the full struct if it was expanded. +func (c *Person) UnmarshalJSON(data []byte) error { + if id, ok := ParseID(data); ok { + c.ID = id + return nil + } + + type person Person + var v person + if err := json.Unmarshal(data, &v); err != nil { + return err + } + + *c = Person(v) + return nil +} diff --git a/person/client.go b/person/client.go new file mode 100644 index 0000000000..30ad3f0c38 --- /dev/null +++ b/person/client.go @@ -0,0 +1,111 @@ +// Package person provides the /accounts/persons APIs +package person + +import ( + "fmt" + "net/http" + + stripe "github.com/stripe/stripe-go" + "github.com/stripe/stripe-go/form" +) + +// Client is used to invoke /accounts/persons APIs. +type Client struct { + B stripe.Backend + Key string +} + +// New creates a new account person. +func New(params *stripe.PersonParams) (*stripe.Person, error) { + return getC().New(params) +} + +// New creates a new account person. +func (c Client) New(params *stripe.PersonParams) (*stripe.Person, error) { + path := stripe.FormatURLPath("/accounts/%s/persons", stripe.StringValue(params.Account)) + person := &stripe.Person{} + err := c.B.Call(http.MethodPost, path, c.Key, params, person) + return person, err +} + +// Get returns the details of a account person. +func Get(id string, params *stripe.PersonParams) (*stripe.Person, error) { + return getC().Get(id, params) +} + +// Get returns the details of a account person. +func (c Client) Get(id string, params *stripe.PersonParams) (*stripe.Person, error) { + if params == nil { + return nil, fmt.Errorf("params cannot be nil, and params.Account must be set") + } + + path := stripe.FormatURLPath("/accounts/%s/persons/%s", + stripe.StringValue(params.Account), id) + person := &stripe.Person{} + err := c.B.Call(http.MethodGet, path, c.Key, params, person) + return person, err +} + +// Update updates a account person's properties. +func Update(id string, params *stripe.PersonParams) (*stripe.Person, error) { + return getC().Update(id, params) +} + +// Update updates a account person's properties. +func (c Client) Update(id string, params *stripe.PersonParams) (*stripe.Person, error) { + path := stripe.FormatURLPath("/accounts/%s/persons/%s", + stripe.StringValue(params.Account), id) + person := &stripe.Person{} + err := c.B.Call(http.MethodPost, path, c.Key, params, person) + return person, err +} + +// Del removes a person. +func Del(id string, params *stripe.PersonParams) (*stripe.Person, error) { + return getC().Del(id, params) +} + +// Del removes a person. +func (c Client) Del(id string, params *stripe.PersonParams) (*stripe.Person, error) { + path := stripe.FormatURLPath("/accounts/%s/persons/%s", + stripe.StringValue(params.Account), id) + person := &stripe.Person{} + err := c.B.Call(http.MethodDelete, path, c.Key, params, person) + return person, err +} + +// List returns a list of account persons. +func List(params *stripe.PersonListParams) *Iter { + return getC().List(params) +} + +// List returns a list of account persons. +func (c Client) List(listParams *stripe.PersonListParams) *Iter { + path := stripe.FormatURLPath("/accounts/%s/persons", stripe.StringValue(listParams.Account)) + + return &Iter{stripe.GetIter(listParams, func(p *stripe.Params, b *form.Values) ([]interface{}, stripe.ListMeta, error) { + list := &stripe.PersonList{} + err := c.B.CallRaw(http.MethodGet, path, c.Key, b, p, list) + + ret := make([]interface{}, len(list.Data)) + for i, v := range list.Data { + ret[i] = v + } + + return ret, list.ListMeta, err + })} +} + +// Iter is an iterator for account persons. +type Iter struct { + *stripe.Iter +} + +// Person returns the account person which the iterator is currently pointing to. +func (i *Iter) Person() *stripe.Person { + return i.Current().(*stripe.Person) +} + +func getC() Client { + return Client{stripe.GetBackend(stripe.APIBackend), stripe.Key} +} diff --git a/person/client_test.go b/person/client_test.go new file mode 100644 index 0000000000..0f3932377e --- /dev/null +++ b/person/client_test.go @@ -0,0 +1,60 @@ +package person + +import ( + "testing" + + assert "github.com/stretchr/testify/require" + stripe "github.com/stripe/stripe-go" + _ "github.com/stripe/stripe-go/testing" +) + +func TestPersonDel(t *testing.T) { + person, err := Del("person_123", &stripe.PersonParams{ + Account: stripe.String("acct_123"), + }) + assert.Nil(t, err) + assert.NotNil(t, person) +} + +func TestPersonGet(t *testing.T) { + person, err := Get("person_123", &stripe.PersonParams{ + Account: stripe.String("acct_123"), + }) + assert.Nil(t, err) + assert.NotNil(t, person) +} + +func TestPersonList(t *testing.T) { + i := List(&stripe.PersonListParams{ + Account: stripe.String("acct_123"), + Relationship: &stripe.RelationshipListParams{ + Owner: stripe.Bool(true), + }, + }) + + // Verify that we can get at least one person + assert.True(t, i.Next()) + assert.Nil(t, i.Err()) + assert.NotNil(t, i.Person()) +} + +func TestPersonNew(t *testing.T) { + person, err := New(&stripe.PersonParams{ + Account: stripe.String("acct_123"), + FirstName: stripe.String("John"), + Relationship: &stripe.RelationshipParams{ + Owner: stripe.Bool(true), + }, + }) + assert.Nil(t, err) + assert.NotNil(t, person) +} + +func TestPersonUpdate(t *testing.T) { + person, err := Update("person_123", &stripe.PersonParams{ + Account: stripe.String("acct_123"), + FirstName: stripe.String("John"), + }) + assert.Nil(t, err) + assert.NotNil(t, person) +} diff --git a/person_test.go b/person_test.go new file mode 100644 index 0000000000..2a7e3af78a --- /dev/null +++ b/person_test.go @@ -0,0 +1,29 @@ +package stripe + +import ( + "encoding/json" + "testing" + + assert "github.com/stretchr/testify/require" +) + +func TestPerson_UnmarshalJSON(t *testing.T) { + // Unmarshals from a JSON string + { + var v Person + err := json.Unmarshal([]byte(`"person_123"`), &v) + assert.NoError(t, err) + assert.Equal(t, "person_123", v.ID) + } + + // Unmarshals from a JSON object + { + v := Person{ID: "person_123"} + data, err := json.Marshal(&v) + assert.NoError(t, err) + + err = json.Unmarshal(data, &v) + assert.NoError(t, err) + assert.Equal(t, "person_123", v.ID) + } +}