diff --git a/sourcetransaction.go b/sourcetransaction.go new file mode 100644 index 0000000000..155b0fcd3a --- /dev/null +++ b/sourcetransaction.go @@ -0,0 +1,55 @@ +package stripe + +import "encoding/json" + +// SourceTransactionListParams is the set of parameters that can be used when listing SourceTransactions. +type SourceTransactionListParams struct { + ListParams `form:"*"` + Source string `form:"-"` // Sent in with the URL +} + +// SourceTransactionList is a list object for SourceTransactions. +type SourceTransactionList struct { + ListMeta + Values []*SourceTransaction `json:"data"` +} + +// SourceTransaction is the resource representing a Stripe source transaction. +type SourceTransaction struct { + Amount int64 `json:"amount"` + Created int64 `json:"created"` + Currency Currency `json:"currency"` + CustomerData string `json:"customer_data"` + ID string `json:"id"` + Live bool `json:"livemode"` + Source string `json:"source"` + Type string `json:"type"` + TypeData map[string]interface{} +} + +// UnmarshalJSON handles deserialization of a SourceTransaction. This custom +// unmarshaling is needed to extract the type specific data (accessible under +// `TypeData`) but stored in JSON under a hash named after the `type` of the +// source transaction. +func (t *SourceTransaction) UnmarshalJSON(data []byte) error { + type sourceTransaction SourceTransaction + var st sourceTransaction + err := json.Unmarshal(data, &st) + if err != nil { + return err + } + *t = SourceTransaction(st) + + var raw map[string]interface{} + err = json.Unmarshal(data, &raw) + if err != nil { + return err + } + if d, ok := raw[t.Type]; ok { + if m, ok := d.(map[string]interface{}); ok { + t.TypeData = m + } + } + + return nil +} diff --git a/sourcetransaction/client.go b/sourcetransaction/client.go new file mode 100644 index 0000000000..954b411c89 --- /dev/null +++ b/sourcetransaction/client.go @@ -0,0 +1,67 @@ +// Package sourcetransaction provides the /source/transactions APIs. +package sourcetransaction + +import ( + "errors" + "fmt" + + stripe "github.com/stripe/stripe-go" + "github.com/stripe/stripe-go/form" +) + +// Client is used to invoke /sources/:source_id/transactions APIs. +type Client struct { + B stripe.Backend + Key string +} + +// List returns a list of source transactions. +// For more details see https://stripe.com/docs/api#retrieve_source. +func List(params *stripe.SourceTransactionListParams) *Iter { + return getC().List(params) +} + +func (c Client) List(params *stripe.SourceTransactionListParams) *Iter { + body := &form.Values{} + var lp *stripe.ListParams + var p *stripe.Params + + form.AppendTo(body, params) + lp = ¶ms.ListParams + p = params.ToParams() + + return &Iter{stripe.GetIter(lp, body, func(b *form.Values) ([]interface{}, stripe.ListMeta, error) { + list := &stripe.SourceTransactionList{} + var err error + + if params != nil && len(params.Source) > 0 { + err = c.B.Call("GET", fmt.Sprintf("/sources/%v/source_transactions", params.Source), c.Key, b, p, list) + } else { + err = errors.New("Invalid source transaction params: Source needs to be set") + } + + ret := make([]interface{}, len(list.Values)) + for i, v := range list.Values { + ret[i] = v + } + + return ret, list.ListMeta, err + })} +} + +// Iter is an iterator for lists of SourceTransactions. +// The embedded Iter carries methods with it; +// see its documentation for details. +type Iter struct { + *stripe.Iter +} + +// SourceTransaction returns the most recent SourceTransaction +// visited by a call to Next. +func (i *Iter) SourceTransaction() *stripe.SourceTransaction { + return i.Current().(*stripe.SourceTransaction) +} + +func getC() Client { + return Client{stripe.GetBackend(stripe.APIBackend), stripe.Key} +} diff --git a/sourcetransaction/client_test.go b/sourcetransaction/client_test.go new file mode 100644 index 0000000000..ee45bf7463 --- /dev/null +++ b/sourcetransaction/client_test.go @@ -0,0 +1,23 @@ +package sourcetransaction + +import ( + "testing" + + assert "github.com/stretchr/testify/require" + stripe "github.com/stripe/stripe-go" + _ "github.com/stripe/stripe-go/testing" +) + +func TestSourceTransactionList(t *testing.T) { + // TODO: unskip the test once stripe-mock supports the /v1/sources/src_.../source_transactions endpoint + t.Skip("not yet supported by stripe-mock") + + i := List(&stripe.SourceTransactionListParams{ + Source: "src_123", + }) + + // Verify that we can get at least one transaction + assert.True(t, i.Next()) + assert.Nil(t, i.Err()) + assert.NotNil(t, i.SourceTransaction()) +}