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 OAuth #879

Merged
merged 1 commit into from
Jul 30, 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
7 changes: 6 additions & 1 deletion client/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ import (
issuingdispute "github.com/stripe/stripe-go/issuing/dispute"
"github.com/stripe/stripe-go/issuing/transaction"
"github.com/stripe/stripe-go/loginlink"
"github.com/stripe/stripe-go/oauth"
"github.com/stripe/stripe-go/order"
"github.com/stripe/stripe-go/orderreturn"
"github.com/stripe/stripe-go/paymentintent"
Expand Down Expand Up @@ -148,6 +149,8 @@ type API struct {
IssuingTransactions *transaction.Client
// LoginLinks is the client used to invoke login link related APIs.
LoginLinks *loginlink.Client
// OAuth is the client used to invoke /oauth APIs.
OAuth *oauth.Client
brandur-stripe marked this conversation as resolved.
Show resolved Hide resolved
// Orders is the client used to invoke /orders APIs.
Orders *order.Client
// OrderReturns is the client used to invoke /order_returns APIs.
Expand Down Expand Up @@ -234,6 +237,7 @@ func (a *API) Init(key string, backends *stripe.Backends) {
if backends == nil {
backends = &stripe.Backends{
API: stripe.GetBackend(stripe.APIBackend),
Connect: stripe.GetBackend(stripe.ConnectBackend),
Uploads: stripe.GetBackend(stripe.UploadsBackend),
}
}
Expand Down Expand Up @@ -272,8 +276,9 @@ func (a *API) Init(key string, backends *stripe.Backends) {
a.IssuingDisputes = &issuingdispute.Client{B: backends.API, Key: key}
a.IssuingTransactions = &transaction.Client{B: backends.API, Key: key}
a.LoginLinks = &loginlink.Client{B: backends.API, Key: key}
a.Orders = &order.Client{B: backends.API, Key: key}
a.OAuth = &oauth.Client{B: backends.Connect, Key: key}
a.OrderReturns = &orderreturn.Client{B: backends.API, Key: key}
a.Orders = &order.Client{B: backends.API, Key: key}
Copy link
Contributor

Choose a reason for hiding this comment

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

Thanks for fixing :)

a.PaymentIntents = &paymentintent.Client{B: backends.API, Key: key}
a.PaymentMethods = &paymentmethod.Client{B: backends.API, Key: key}
a.PaymentSource = &paymentsource.Client{B: backends.API, Key: key}
Expand Down
4 changes: 4 additions & 0 deletions error.go
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,10 @@ type Error struct {
SetupIntent *SetupIntent `json:"setup_intent,omitempty"`
Source *PaymentSource `json:"source,omitempty"`
Type ErrorType `json:"type"`

// OAuth specific Error properties. Named OAuthError because of name conflict.
OAuthError string `json:"error,omitempty"`
OAuthErrorDescription string `json:"error_description,omitempty"`
Copy link
Contributor

Choose a reason for hiding this comment

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

I actually like the "OAuth" prefix anyway — it makes it harder to use these outside of an OAuth context by accident (it's clear they're specifically for OAuth and nothing else).

Copy link
Contributor Author

Choose a reason for hiding this comment

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

This was actually required because we use Error as a method on this object elsewhere.

}

// Error serializes the error object to JSON and returns it as a string.
Expand Down
8 changes: 6 additions & 2 deletions form/form.go
Original file line number Diff line number Diff line change
Expand Up @@ -538,14 +538,18 @@ func (f *Values) Add(key, val string) {
f.values = append(f.values, formValue{key, val})
}

// Encode encodes the values into “URL encoded” form ("bar=baz&foo=quux").
// Encode encodes the keys and values into “URL encoded” form
// ("bar=baz&foo=quux").
func (f *Values) Encode() string {
var buf bytes.Buffer
for _, v := range f.values {
if buf.Len() > 0 {
buf.WriteByte('&')
}
buf.WriteString(url.QueryEscape(v.Key))
key := url.QueryEscape(v.Key)
key = strings.Replace(key, "%5B", "[", -1)
key = strings.Replace(key, "%5D", "]", -1)
buf.WriteString(key)
buf.WriteString("=")
buf.WriteString(url.QueryEscape(v.Value))
}
Expand Down
2 changes: 1 addition & 1 deletion issuing_cardholder.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ const (
IssuingCardholderTypeIndividual IssuingCardholderType = "individual"
)

// IssuingBillingParams isis the set of parameters that can be used for billing with the Issuing APIs.
// IssuingBillingParams is the set of parameters that can be used for billing with the Issuing APIs.
type IssuingBillingParams struct {
Address *AddressParams `form:"address"`
Name *string `form:"name"`
Expand Down
129 changes: 129 additions & 0 deletions oauth.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
package stripe

// OAuthScopeType is the type of OAuth scope.
type OAuthScopeType string

// List of possible values for OAuth scopes.
const (
OAuthScopeTypeReadOnly OAuthScopeType = "read_only"
OAuthScopeTypeReadWrite OAuthScopeType = "read_write"
)

// OAuthTokenType is the type of token. This will always be "bearer."
type OAuthTokenType string

// List of possible OAuthTokenType values.
const (
OAuthTokenTypeBearer OAuthTokenType = "bearer"
)

// OAuthStripeUserBusinessType is the business type for the Stripe oauth user.
type OAuthStripeUserBusinessType string

// List of supported values for business type.
const (
OAuthStripeUserBusinessTypeCorporation OAuthStripeUserBusinessType = "corporation"
OAuthStripeUserBusinessTypeLLC OAuthStripeUserBusinessType = "llc"
OAuthStripeUserBusinessTypeNonProfit OAuthStripeUserBusinessType = "non_profit"
OAuthStripeUserBusinessTypePartnership OAuthStripeUserBusinessType = "partnership"
OAuthStripeUserBusinessTypeSoleProp OAuthStripeUserBusinessType = "sole_prop"
)

// OAuthStripeUserGender of the person who will be filling out a Stripe
// application. (International regulations require either male or female.)
type OAuthStripeUserGender string

// The gender of the person who will be filling out a Stripe application.
// (International regulations require either male or female.)
const (
OAuthStripeUserGenderFemale OAuthStripeUserGender = "female"
OAuthStripeUserGenderMale OAuthStripeUserGender = "male"
)

// OAuthStripeUserParams for the stripe_user OAuth Authorize params.
type OAuthStripeUserParams struct {
BlockKana *string `form:"block_kana"`
BlockKanji *string `form:"block_kanji"`
BuildingKana *string `form:"building_kana"`
BuildingKanji *string `form:"building_kanji"`
BusinessName *string `form:"business_name"`
BusinessType *string `form:"business_type"`
City *string `form:"city"`
Country *string `form:"country"`
Currency *string `form:"currency"`
DOBDay *int64 `form:"dob_day"`
DOBMonth *int64 `form:"dob_month"`
DOBYear *int64 `form:"dob_year"`
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"`
LastName *string `form:"last_name"`
LastNameKana *string `form:"last_name_kana"`
LastNameKanji *string `form:"last_name_kanji"`
PhoneNumber *string `form:"phone_number"`
PhysicalProduct *bool `form:"physical_product"`
ProductDescription *string `form:"product_description"`
State *string `form:"state"`
StreetAddress *string `form:"street_address"`
URL *string `form:"url"`
Zip *string `form:"zip"`
}

// AuthorizeURLParams for creating OAuth AuthorizeURLs.
type AuthorizeURLParams struct {
Params `form:"*"`
AlwaysPrompt *bool `form:"always_prompt"`
ClientID *string `form:"client_id"`
RedirectURI *string `form:"redirect_uri"`
ResponseType *string `form:"response_type"`
Scope *string `form:"scope"`
State *string `form:"state"`
StripeLanding *string `form:"stripe_landing"`
StripeUser *OAuthStripeUserParams `form:"stripe_user"`
SuggestedCapabilities []*string `form:"suggested_capabilities"`

// Express is not sent as a parameter, but is used to modify the authorize URL
// path to use the express OAuth path.
Express *bool `form:"-"`
}

// DeauthorizeParams for deauthorizing an account.
type DeauthorizeParams struct {
Params `form:"*"`
ClientID *string `form:"client_id"`
StripeUserID *string `form:"stripe_user_id"`
}
cjavilla-stripe marked this conversation as resolved.
Show resolved Hide resolved

// OAuthTokenParams is the set of paramaters that can be used to request
// OAuthTokens.
type OAuthTokenParams struct {
Params `form:"*"`
AssertCapabilities []*string `form:"assert_capabilities"`
ClientSecret *string `form:"client_secret"`
Code *string `form:"code"`
GrantType *string `form:"grant_type"`
RefreshToken *string `form:"refresh_token"`
Scope *string `form:"scope"`
}

// OAuthToken is the value of the OAuthToken from OAuth flow.
// https://stripe.com/docs/connect/oauth-reference#post-token
type OAuthToken struct {
Livemode bool `json:"livemode"`
Scope OAuthScopeType `json:"scope"`
StripeUserID string `json:"stripe_user_id"`
TokenType OAuthTokenType `json:"token_type"`

// Deprecated, please use StripeUserID
AccessToken string `json:"access_token"`
RefreshToken string `json:"refresh_token"`
StripePublishableKey string `json:"stripe_publishable_key"`
}

// Deauthorize is the value of the return from deauthorizing.
// https://stripe.com/docs/connect/oauth-reference#post-deauthorize
type Deauthorize struct {
StripeUserID string `json:"stripe_user_id"`
}
77 changes: 77 additions & 0 deletions oauth/client.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
// Package oauth provides the OAuth APIs
package oauth

import (
"fmt"
"net/http"

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

// Client is used to invoke /oauth and related APIs.
type Client struct {
B stripe.Backend
Key string
}

// AuthorizeURL builds an OAuth authorize URL.
func AuthorizeURL(params *stripe.AuthorizeURLParams) string {
cjavilla-stripe marked this conversation as resolved.
Show resolved Hide resolved
return getC().AuthorizeURL(params)
}

// AuthorizeURL builds an OAuth authorize URL.
func (c Client) AuthorizeURL(params *stripe.AuthorizeURLParams) string {
express := ""
if stripe.BoolValue(params.Express) {
express = "/express"
}
qs := &form.Values{}
form.AppendTo(qs, params)
return fmt.Sprintf(
"%s%s/oauth/authorize?%s",
stripe.ConnectURL,
express,
qs.Encode(),
)
}

// New creates an OAuth token using a code after successful redirection back.
func New(params *stripe.OAuthTokenParams) (*stripe.OAuthToken, error) {
return getC().New(params)
}

// New creates an OAuth token using a code after successful redirection back.
func (c Client) New(params *stripe.OAuthTokenParams) (*stripe.OAuthToken, error) {
// client_secret is sent in the post body for this endpoint.
if stripe.StringValue(params.ClientSecret) == "" {
params.ClientSecret = stripe.String(stripe.Key)
}

oauthToken := &stripe.OAuthToken{}
err := c.B.Call(http.MethodPost, "/oauth/token", c.Key, params, oauthToken)

return oauthToken, err
}

// Del deauthorizes a connected account.
func Del(params *stripe.DeauthorizeParams) (*stripe.Deauthorize, error) {
return getC().Del(params)
}

// Del deauthorizes a connected account.
func (c Client) Del(params *stripe.DeauthorizeParams) (*stripe.Deauthorize, error) {
deauthorization := &stripe.Deauthorize{}
err := c.B.Call(
http.MethodPost,
"/oauth/deauthorize",
c.Key,
params,
deauthorization,
)
return deauthorization, err
}

func getC() Client {
return Client{stripe.GetBackend(stripe.ConnectBackend), stripe.Key}
}
Loading