Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for the Capability resource and APIs #855

Merged
merged 1 commit into from
May 14, 2019
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
2 changes: 1 addition & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ cache:
env:
global:
# If changing this number, please also change it in `testing/testing.go`.
- STRIPE_MOCK_VERSION=0.54.0
- STRIPE_MOCK_VERSION=0.56.0

go:
- "1.9.x"
Expand Down
88 changes: 88 additions & 0 deletions capability.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
package stripe

import "encoding/json"

// CapabilityDisabledReason describes why a capability is disabled.
type CapabilityDisabledReason string

// List of values that CapabilityDisabledReason can take.
const (
CapabilityDisabledReasonPendingOnboarding CapabilityDisabledReason = "pending.onboarding"
CapabilityDisabledReasonPendingReview CapabilityDisabledReason = "pending.review"
CapabilityDisabledReasonRejectedFraud CapabilityDisabledReason = "rejected_fraud"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oof, it looks like this isn't a mistake (as it's in the API), but we use an underscore in rejected_fraud and a dot everywhere else (i.e. rejected.listed)?

Think it's okay to merge it given it's ubiquitous, but will follow up elsewhere.

CapabilityDisabledReasonRejectedListed CapabilityDisabledReason = "rejected.listed"
CapabilityDisabledReasonRejectedOther CapabilityDisabledReason = "rejected.other"
CapabilityDisabledReasonRequirementsFieldsNeeded CapabilityDisabledReason = "requirement.fields_needed"
)

// CapabilityStatus describes the different statuses for a capability's status.
type CapabilityStatus string

// List of values that CapabilityStatus can take.
const (
CapabilityStatusActive CapabilityStatus = "active"
CapabilityStatusInactive CapabilityStatus = "inactive"
CapabilityStatusPending CapabilityStatus = "pending"
CapabilityStatusUnrequested CapabilityStatus = "unrequested"
)

// CapabilityParams is the set of parameters that can be used when updating a capability.
// For more details see https://stripe.com/docs/api/capabilities/update
type CapabilityParams struct {
Params `form:"*"`
Account *string `form:"-"` // Included in URL
Requested *bool `form:"requested"`
}

// CapabilityListParams is the set of parameters that can be used when listing capabilities.
// For more detail see https://stripe.com/docs/api/capabilities/list
type CapabilityListParams struct {
ListParams `form:"*"`
Account *string `form:"-"` // Included in URL
}

// CapabilityRequirements represents information that needs to be collected for a capability.
type CapabilityRequirements struct {
CurrentDeadline int64 `json:"current_deadline"`
CurrentlyDue []string `json:"currently_due"`
DisabledReason CapabilityDisabledReason `json:"disabled_reason"`
EventuallyDue []string `json:"eventually_due"`
PastDue []string `json:"past_due"`
}

// Capability is the resource representing a Stripe capability.
// For more details see https://stripe.com/docs/api/capabilities
type Capability struct {
Account *Account `json:"account"`
ID string `json:"id"`
Object string `json:"object"`
Requested bool `json:"requested"`
RequestedAt int64 `json:"requested_at"`
Requirements *CapabilityRequirements `json:"requirements"`
Status CapabilityStatus `json:"status"`
}

// CapabilityList is a list of capabilities as retrieved from a list endpoint.
type CapabilityList struct {
ListMeta
Data []*Capability `json:"data"`
}

// UnmarshalJSON handles deserialization of a Capability.
// This custom unmarshaling is needed because the resulting
// property may be an id or the full struct if it was expanded.
func (c *Capability) UnmarshalJSON(data []byte) error {
if id, ok := ParseID(data); ok {
c.ID = id
return nil
}

type capability Capability
var v capability
if err := json.Unmarshal(data, &v); err != nil {
return err
}

*c = Capability(v)
return nil
}
84 changes: 84 additions & 0 deletions capability/client.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
// Package capability provides the /accounts/capabilities APIs
package capability

import (
"fmt"
"net/http"

stripe "github.com/stripe/stripe-go"
"github.com/stripe/stripe-go/form"
)

// Client is used to invoke /accounts/capabilities APIs.
type Client struct {
B stripe.Backend
Key string
}

// Get returns the details of a account capability.
func Get(id string, params *stripe.CapabilityParams) (*stripe.Capability, error) {
return getC().Get(id, params)
}

// Get returns the details of a account capability.
func (c Client) Get(id string, params *stripe.CapabilityParams) (*stripe.Capability, error) {
if params == nil {
return nil, fmt.Errorf("params cannot be nil, and params.Account must be set")
}

path := stripe.FormatURLPath("/v1/accounts/%s/capabilities/%s",
stripe.StringValue(params.Account), id)
capability := &stripe.Capability{}
err := c.B.Call(http.MethodGet, path, c.Key, params, capability)
return capability, err
}

// Update updates a account capability's properties.
func Update(id string, params *stripe.CapabilityParams) (*stripe.Capability, error) {
return getC().Update(id, params)
}

// Update updates a account capability's properties.
func (c Client) Update(id string, params *stripe.CapabilityParams) (*stripe.Capability, error) {
path := stripe.FormatURLPath("/v1/accounts/%s/capabilities/%s",
stripe.StringValue(params.Account), id)
capability := &stripe.Capability{}
err := c.B.Call(http.MethodPost, path, c.Key, params, capability)
return capability, err
}

// List returns a list of account capabilities.
func List(params *stripe.CapabilityListParams) *Iter {
return getC().List(params)
}

// List returns a list of account capabilities.
func (c Client) List(listParams *stripe.CapabilityListParams) *Iter {
path := stripe.FormatURLPath("/v1/accounts/%s/capabilities", stripe.StringValue(listParams.Account))

return &Iter{stripe.GetIter(listParams, func(p *stripe.Params, b *form.Values) ([]interface{}, stripe.ListMeta, error) {
list := &stripe.CapabilityList{}
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 capabilities.
type Iter struct {
*stripe.Iter
}

// Capability returns the account capability which the iterator is currently pointing to.
func (i *Iter) Capability() *stripe.Capability {
return i.Current().(*stripe.Capability)
}

func getC() Client {
return Client{stripe.GetBackend(stripe.APIBackend), stripe.Key}
}
37 changes: 37 additions & 0 deletions capability/client_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package capability

import (
"testing"

assert "github.com/stretchr/testify/require"
stripe "github.com/stripe/stripe-go"
_ "github.com/stripe/stripe-go/testing"
)

func TestCapabilityGet(t *testing.T) {
capability, err := Get("acap_123", &stripe.CapabilityParams{
Account: stripe.String("acct_123"),
})
assert.Nil(t, err)
assert.NotNil(t, capability)
}

func TestCapabilityList(t *testing.T) {
i := List(&stripe.CapabilityListParams{
Account: stripe.String("acct_123"),
})

// Verify that we can get at least one capability
assert.True(t, i.Next())
assert.Nil(t, i.Err())
assert.NotNil(t, i.Capability())
}

func TestCapabilityUpdate(t *testing.T) {
capability, err := Update("acap_123", &stripe.CapabilityParams{
Account: stripe.String("acct_123"),
Requested: stripe.Bool(true),
})
assert.Nil(t, err)
assert.NotNil(t, capability)
}
4 changes: 4 additions & 0 deletions client/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import (
"github.com/stripe/stripe-go/bankaccount"
"github.com/stripe/stripe-go/bitcoinreceiver"
"github.com/stripe/stripe-go/bitcointransaction"
"github.com/stripe/stripe-go/capability"
"github.com/stripe/stripe-go/card"
"github.com/stripe/stripe-go/charge"
checkoutsession "github.com/stripe/stripe-go/checkout/session"
Expand Down Expand Up @@ -90,6 +91,8 @@ type API struct {
BitcoinReceivers *bitcoinreceiver.Client
// BitcoinTransactions is the client used to invoke /bitcoin/transactions APIs.
BitcoinTransactions *bitcointransaction.Client
// Capabilities is the client used to invoke capability related APIs.
Capabilities *capability.Client
// Cards is the client used to invoke card related APIs.
Cards *card.Client
// Charges is the client used to invoke /charges APIs.
Expand Down Expand Up @@ -233,6 +236,7 @@ func (a *API) Init(key string, backends *stripe.Backends) {
a.BankAccounts = &bankaccount.Client{B: backends.API, Key: key}
a.BitcoinReceivers = &bitcoinreceiver.Client{B: backends.API, Key: key}
a.BitcoinTransactions = &bitcointransaction.Client{B: backends.API, Key: key}
a.Capabilities = &capability.Client{B: backends.API, Key: key}
a.Cards = &card.Client{B: backends.API, Key: key}
a.Charges = &charge.Client{B: backends.API, Key: key}
a.CheckoutSessions = &checkoutsession.Client{B: backends.API, Key: key}
Expand Down
2 changes: 1 addition & 1 deletion testing/testing.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ const (
// added in a more recent version of stripe-mock, we can show people a
// better error message instead of the test suite crashing with a bunch of
// confusing 404 errors or the like.
MockMinimumVersion = "0.54.0"
MockMinimumVersion = "0.56.0"

// TestMerchantID is a token that can be used to represent a merchant ID in
// simple tests.
Expand Down