Skip to content

Commit

Permalink
Add support for the Person resource
Browse files Browse the repository at this point in the history
  • Loading branch information
remi-stripe committed Oct 12, 2018
1 parent 5d00b1a commit 4bf4916
Show file tree
Hide file tree
Showing 4 changed files with 312 additions and 0 deletions.
114 changes: 114 additions & 0 deletions person.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
package stripe

import "encoding/json"

// RelationshipParams is used to set the relationship between an acount and a person.
type RelationshipParams struct {
Controller *bool `form:"controller"`
Director *bool `form:"director"`
Email *string `form:"email"`
Owner *bool `form:"owner"`
PercentOwnership *float64 `form:"percent_ownership"`
Phone *string `form:"phone"`
Representative *bool `form:"representative"`
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"`
FirstName *string `form:"first_name"`
FirstNameKana *string `form:"first_name_kana"`
FirstNameKanji *string `form:"first_name_kanji"`
Gender *string `form:"gender"`
LastName *string `form:"last_name"`
LastNameKana *string `form:"last_name_kana"`
LastNameKanji *string `form:"last_name_kanji"`
MaidenName *string `form:"maiden_name"`
PersonalIDNumber *string `form:"personal_id_number"`
Relationship *RelationshipParams `form:"relationship"`
SSNLast4 *string `form:"ssn_last_4"`
}

// 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
Director *bool `form:"director"`
Executive *bool `form:"executive"`
Owner *bool `form:"owner"`
}

// Relationship represents extra information needed for a Person.
type Relationship struct {
Controller bool `json:"controller"`
Director bool `json:"director"`
Email string `json:"email"`
Owner bool `json:"owner"`
PercentOwnership float64 `json:"percent_ownership"`
Phone string `json:"phone"`
Representative bool `json:"representative"`
Title string `json:"title"`
}

// Relationship represents the relationship between a Person and an Account.
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"`
DOB *DOB `json:"dob"`
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"`
LastName string `json:"last_name"`
LastNameKana string `json:"last_name_kana"`
LastNameKanji string `json:"last_name_kanji"`
MaidenName string `json:"maiden_name"`
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
}
111 changes: 111 additions & 0 deletions person/client.go
Original file line number Diff line number Diff line change
@@ -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}
}
58 changes: 58 additions & 0 deletions person/client_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
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"),
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)
}
29 changes: 29 additions & 0 deletions person_test.go
Original file line number Diff line number Diff line change
@@ -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)
}
}

0 comments on commit 4bf4916

Please sign in to comment.