~evanj/cms

ref: 99a3bb7fc511e3f448a358691896ba1300f73a93 cms/vendor/github.com/stripe/stripe-go/v71/bankaccount.go -rw-r--r-- 6.9 KiB
99a3bb7fEvan M Jones WIP(rbac): Decorator object complete. TODO: Specify role in invite. 1 year, 1 month ago
                                                                                
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
package stripe

import (
	"encoding/json"
	"strconv"

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

// BankAccountStatus is the list of allowed values for the bank account's status.
type BankAccountStatus string

// List of values that BankAccountStatus can take.
const (
	BankAccountStatusErrored            BankAccountStatus = "errored"
	BankAccountStatusNew                BankAccountStatus = "new"
	BankAccountStatusValidated          BankAccountStatus = "validated"
	BankAccountStatusVerificationFailed BankAccountStatus = "verification_failed"
	BankAccountStatusVerified           BankAccountStatus = "verified"
)

// BankAccountAccountHolderType is the list of allowed values for the bank account holder type.
type BankAccountAccountHolderType string

// List of values that BankAccountAccountHolderType can take.
const (
	BankAccountAccountHolderTypeCompany    BankAccountAccountHolderType = "company"
	BankAccountAccountHolderTypeIndividual BankAccountAccountHolderType = "individual"
)

// BankAccountParams is the set of parameters that can be used when updating a
// bank account.
//
// Note that while form annotations are used for updates, bank accounts have
// some unusual logic on creates that necessitates manual handling of all
// parameters. See AppendToAsSourceOrExternalAccount.
type BankAccountParams struct {
	Params `form:"*"`

	// Account is the identifier of the parent account under which bank
	// accounts are nested.
	Account *string `form:"-"`

	AccountHolderName  *string `form:"account_holder_name"`
	AccountHolderType  *string `form:"account_holder_type"`
	AccountNumber      *string `form:"account_number"`
	Country            *string `form:"country"`
	Currency           *string `form:"currency"`
	Customer           *string `form:"-"`
	DefaultForCurrency *bool   `form:"default_for_currency"`
	RoutingNumber      *string `form:"routing_number"`

	// Token is a token referencing an external account like one returned from
	// Stripe.js.
	Token *string `form:"-"`

	// ID is used when tokenizing a bank account for shared customers
	ID *string `form:"*"`
}

// AppendToAsSourceOrExternalAccount appends the given BankAccountParams as
// either a source or external account.
//
// It may look like an AppendTo from the form package, but it's not, and is
// only used in the special case where we use `bankaccount.New`. It's needed
// because we have some weird encoding logic here that can't be handled by the
// form package (and it's special enough that it wouldn't be desirable to have
// it do so).
//
// This is not a pattern that we want to push forward, and this largely exists
// because the bank accounts endpoint is a little unusual. There is one other
// resource like it, which is cards.
func (a *BankAccountParams) AppendToAsSourceOrExternalAccount(body *form.Values) {
	// Rather than being called in addition to `AppendTo`, this function
	// *replaces* `AppendTo`, so we must also make sure to handle the encoding
	// of `Params` so metadata and the like is included in the encoded payload.
	form.AppendTo(body, a.Params)

	isCustomer := a.Customer != nil

	var sourceType string
	if isCustomer {
		sourceType = "source"
	} else {
		sourceType = "external_account"
	}

	// Use token (if exists) or a dictionary containing a user’s bank account details.
	if a.Token != nil {
		body.Add(sourceType, StringValue(a.Token))

		if a.DefaultForCurrency != nil {
			body.Add("default_for_currency", strconv.FormatBool(BoolValue(a.DefaultForCurrency)))
		}
	} else {
		body.Add(sourceType+"[object]", "bank_account")
		body.Add(sourceType+"[country]", StringValue(a.Country))
		body.Add(sourceType+"[account_number]", StringValue(a.AccountNumber))
		body.Add(sourceType+"[currency]", StringValue(a.Currency))

		// These are optional and the API will fail if we try to send empty
		// values in for them, so make sure to check that they're actually set
		// before encoding them.
		if a.AccountHolderName != nil {
			body.Add(sourceType+"[account_holder_name]", StringValue(a.AccountHolderName))
		}

		if a.AccountHolderType != nil {
			body.Add(sourceType+"[account_holder_type]", StringValue(a.AccountHolderType))
		}

		if a.RoutingNumber != nil {
			body.Add(sourceType+"[routing_number]", StringValue(a.RoutingNumber))
		}

		if a.DefaultForCurrency != nil {
			body.Add(sourceType+"[default_for_currency]", strconv.FormatBool(BoolValue(a.DefaultForCurrency)))
		}
	}
}

// BankAccountListParams is the set of parameters that can be used when listing bank accounts.
type BankAccountListParams struct {
	ListParams `form:"*"`

	// The identifier of the parent account under which the bank accounts are
	// nested. Either Account or Customer should be populated.
	Account *string `form:"-"`

	// The identifier of the parent customer under which the bank accounts are
	// nested. Either Account or Customer should be populated.
	Customer *string `form:"-"`
}

// AppendTo implements custom encoding logic for BankAccountListParams
// so that we can send the special required `object` field up along with the
// other specified parameters.
func (p *BankAccountListParams) AppendTo(body *form.Values, keyParts []string) {
	body.Add(form.FormatKey(append(keyParts, "object")), "bank_account")
}

// BankAccount represents a Stripe bank account.
type BankAccount struct {
	APIResource
	Account            *Account                     `json:"account"`
	AccountHolderName  string                       `json:"account_holder_name"`
	AccountHolderType  BankAccountAccountHolderType `json:"account_holder_type"`
	BankName           string                       `json:"bank_name"`
	Country            string                       `json:"country"`
	Currency           Currency                     `json:"currency"`
	Customer           *Customer                    `json:"customer"`
	DefaultForCurrency bool                         `json:"default_for_currency"`
	Deleted            bool                         `json:"deleted"`
	Fingerprint        string                       `json:"fingerprint"`
	ID                 string                       `json:"id"`
	Last4              string                       `json:"last4"`
	Metadata           map[string]string            `json:"metadata"`
	Object             string                       `json:"object"`
	RoutingNumber      string                       `json:"routing_number"`
	Status             BankAccountStatus            `json:"status"`
}

// BankAccountList is a list object for bank accounts.
type BankAccountList struct {
	APIResource
	ListMeta
	Data []*BankAccount `json:"data"`
}

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

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

	*b = BankAccount(v)
	return nil
}