Update oauth library

This commit is contained in:
Jumpei Tsuji
2015-05-26 17:29:34 +09:00
parent e8ad410a77
commit 87cea6c590
3 changed files with 93 additions and 82 deletions

View File

@@ -11,6 +11,13 @@ Current API Documents:
* AppStore: [![GoDoc](https://godoc.org/github.com/dogenzaka/go-iap/appstore?status.svg)](https://godoc.org/github.com/dogenzaka/go-iap/appstore) * AppStore: [![GoDoc](https://godoc.org/github.com/dogenzaka/go-iap/appstore?status.svg)](https://godoc.org/github.com/dogenzaka/go-iap/appstore)
* GooglePlay: [![GoDoc](https://godoc.org/github.com/dogenzaka/go-iap/playstore?status.svg)](https://godoc.org/github.com/dogenzaka/go-iap/playstore) * GooglePlay: [![GoDoc](https://godoc.org/github.com/dogenzaka/go-iap/playstore?status.svg)](https://godoc.org/github.com/dogenzaka/go-iap/playstore)
# Dependencies
```
go get github.com/parnurzeal/gorequest
go get golang.org/x/net/context
go get golang.org/x/oauth2
go get google.golang.org/api/androidpublisher/v2
```
# Installation # Installation
``` ```
@@ -41,19 +48,19 @@ func main() {
``` ```
import( import(
"code.google.com/p/goauth2/oauth" "golang.org/x/oauth2"
"github.com/dogenzaka/go-iap/playstore" "github.com/dogenzaka/go-iap/playstore"
) )
func main() { func main() {
// You need to prepare an authorization code or a refresh token // You need to prepare an authorization code or a refresh token.
// If you have a refresh token, you can generate an oauth token like this // If you have a refresh token, you can generate an oauth token like this.
oauth := &oauth.Token{ token := &oauth2.Token{
RefreshToken: "your refresh token", RefreshToken: "your refresh token",
} }
client := playstore.New(oauth) client := playstore.New(token)
resp, err := client.VerifySubscription("package", "subscriptionID", "purchaseToken") resp, err := client.VerifySubscription("package", "subscriptionID", "purchaseToken")
} }
``` ```

View File

@@ -2,13 +2,13 @@ package playstore
import ( import (
"errors" "errors"
"net"
"net/http" "net/http"
"os" "os"
"time" "time"
"code.google.com/p/goauth2/oauth" "golang.org/x/net/context"
"code.google.com/p/google-api-go-client/androidpublisher/v2" "golang.org/x/oauth2"
androidpublisher "google.golang.org/api/androidpublisher/v2"
) )
const ( const (
@@ -19,22 +19,24 @@ const (
timeout = time.Second * 5 timeout = time.Second * 5
) )
var defaultConfig *oauth.Config var defaultConfig *oauth2.Config
var defaultTimeout = timeout var defaultTimeout = timeout
// Init initializes the global configuration // Init initializes the global configuration
func Init() error { func Init() error {
defaultConfig = &oauth.Config{ defaultConfig = &oauth2.Config{
Scope: scope, Scopes: []string{scope},
Endpoint: oauth2.Endpoint{
AuthURL: authURL, AuthURL: authURL,
TokenURL: tokenURL, TokenURL: tokenURL,
},
} }
clientID := os.Getenv("IAB_CLIENT_ID") clientID := os.Getenv("IAB_CLIENT_ID")
if clientID != "" { if clientID != "" {
defaultConfig.ClientId = clientID defaultConfig.ClientID = clientID
} }
if defaultConfig.ClientId == "" { if defaultConfig.ClientID == "" {
return errors.New("Client ID is required") return errors.New("Client ID is required")
} }
@@ -50,8 +52,8 @@ func Init() error {
} }
// InitWithConfig initializes the global configuration with parameters // InitWithConfig initializes the global configuration with parameters
func InitWithConfig(config *oauth.Config) error { func InitWithConfig(config *oauth2.Config) error {
if config.ClientId == "" { if config.ClientID == "" {
return errors.New("Client ID is required") return errors.New("Client ID is required")
} }
@@ -59,16 +61,16 @@ func InitWithConfig(config *oauth.Config) error {
return errors.New("Client Secret Key is required") return errors.New("Client Secret Key is required")
} }
if config.Scope == "" { if len(config.Scopes) == 0 {
config.Scope = scope config.Scopes = []string{scope}
} }
if config.AuthURL == "" { if config.Endpoint.AuthURL == "" {
config.AuthURL = authURL config.Endpoint.AuthURL = authURL
} }
if config.TokenURL == "" { if config.Endpoint.TokenURL == "" {
config.TokenURL = tokenURL config.Endpoint.TokenURL = tokenURL
} }
defaultConfig = config defaultConfig = config
@@ -84,6 +86,7 @@ func SetTimeout(t time.Duration) {
// The IABClient type is an interface to verify purchase token // The IABClient type is an interface to verify purchase token
type IABClient interface { type IABClient interface {
VerifySubscription(string, string, string) (*androidpublisher.SubscriptionPurchase, error) VerifySubscription(string, string, string) (*androidpublisher.SubscriptionPurchase, error)
VerifyProduct(string, string, string) (*androidpublisher.ProductPurchase, error)
} }
// The Client type implements VerifySubscription method // The Client type implements VerifySubscription method
@@ -92,16 +95,13 @@ type Client struct {
} }
// New returns http client which has oauth token // New returns http client which has oauth token
func New(token *oauth.Token) Client { func New(token *oauth2.Token) Client {
t := &oauth.Transport{ ctx := context.WithValue(oauth2.NoContext, oauth2.HTTPClient, &http.Client{
Token: token, Timeout: defaultTimeout,
Config: defaultConfig, })
Transport: &http.Transport{
Dial: dialTimeout, httpClient := defaultConfig.Client(ctx, token)
},
}
httpClient := t.Client()
return Client{httpClient} return Client{httpClient}
} }
@@ -138,7 +138,3 @@ func (c *Client) VerifyProduct(
return result, err return result, err
} }
func dialTimeout(network, addr string) (net.Conn, error) {
return net.DialTimeout(network, addr, defaultTimeout)
}

View File

@@ -7,16 +7,18 @@ import (
"testing" "testing"
"time" "time"
"code.google.com/p/goauth2/oauth" "golang.org/x/oauth2"
) )
func TestInit(t *testing.T) { func TestInit(t *testing.T) {
expected := &oauth.Config{ expected := &oauth2.Config{
ClientId: "dummyId", ClientID: "dummyId",
ClientSecret: "dummySecret", ClientSecret: "dummySecret",
Scope: "https://www.googleapis.com/auth/androidpublisher", Scopes: []string{"https://www.googleapis.com/auth/androidpublisher"},
Endpoint: oauth2.Endpoint{
AuthURL: "https://accounts.google.com/o/oauth2/auth", AuthURL: "https://accounts.google.com/o/oauth2/auth",
TokenURL: "https://accounts.google.com/o/oauth2/token", TokenURL: "https://accounts.google.com/o/oauth2/token",
},
} }
os.Setenv("IAB_CLIENT_ID", "dummyId") os.Setenv("IAB_CLIENT_ID", "dummyId")
os.Setenv("IAB_CLIENT_SECRET", "dummySecret") os.Setenv("IAB_CLIENT_SECRET", "dummySecret")
@@ -41,21 +43,21 @@ func TestInitWithoutClientSecret(t *testing.T) {
} }
func TestInitWithConfig(t *testing.T) { func TestInitWithConfig(t *testing.T) {
expected := &oauth.Config{ expected := &oauth2.Config{
ClientId: "dummyId", ClientID: "dummyId",
ClientSecret: "dummySecret", ClientSecret: "dummySecret",
Scope: "https://www.googleapis.com/auth/androidpublisher", Scopes: []string{"https://www.googleapis.com/auth/androidpublisher"},
Endpoint: oauth2.Endpoint{
AuthURL: "https://accounts.google.com/o/oauth2/auth", AuthURL: "https://accounts.google.com/o/oauth2/auth",
TokenURL: "https://accounts.google.com/o/oauth2/token", TokenURL: "https://accounts.google.com/o/oauth2/token",
},
} }
config := &oauth.Config{ config := &oauth2.Config{
ClientId: "dummyId", ClientID: "dummyId",
ClientSecret: "dummySecret", ClientSecret: "dummySecret",
Scope: "https://www.googleapis.com/auth/androidpublisher",
AuthURL: "https://accounts.google.com/o/oauth2/auth",
TokenURL: "https://accounts.google.com/o/oauth2/token",
} }
InitWithConfig(config) InitWithConfig(config)
actual := defaultConfig actual := defaultConfig
if !reflect.DeepEqual(actual, expected) { if !reflect.DeepEqual(actual, expected) {
@@ -66,10 +68,12 @@ func TestInitWithConfig(t *testing.T) {
func TestInitWithConfigErrors(t *testing.T) { func TestInitWithConfigErrors(t *testing.T) {
expected := errors.New("Client ID is required") expected := errors.New("Client ID is required")
config := &oauth.Config{ config := &oauth2.Config{
Scope: "https://www.googleapis.com/auth/androidpublisher", Scopes: []string{"https://www.googleapis.com/auth/androidpublisher"},
Endpoint: oauth2.Endpoint{
AuthURL: "https://accounts.google.com/o/oauth2/auth", AuthURL: "https://accounts.google.com/o/oauth2/auth",
TokenURL: "https://accounts.google.com/o/oauth2/token", TokenURL: "https://accounts.google.com/o/oauth2/token",
},
} }
actual := InitWithConfig(config) actual := InitWithConfig(config)
@@ -78,11 +82,13 @@ func TestInitWithConfigErrors(t *testing.T) {
} }
expected = errors.New("Client Secret Key is required") expected = errors.New("Client Secret Key is required")
config = &oauth.Config{ config = &oauth2.Config{
ClientId: "dummyId", ClientID: "dummyId",
Scope: "https://www.googleapis.com/auth/androidpublisher", Scopes: []string{"https://www.googleapis.com/auth/androidpublisher"},
Endpoint: oauth2.Endpoint{
AuthURL: "https://accounts.google.com/o/oauth2/auth", AuthURL: "https://accounts.google.com/o/oauth2/auth",
TokenURL: "https://accounts.google.com/o/oauth2/token", TokenURL: "https://accounts.google.com/o/oauth2/token",
},
} }
actual = InitWithConfig(config) actual = InitWithConfig(config)
@@ -93,27 +99,29 @@ func TestInitWithConfigErrors(t *testing.T) {
func TestNew(t *testing.T) { func TestNew(t *testing.T) {
// Initialize config // Initialize config
_config := &oauth.Config{ _config := &oauth2.Config{
ClientId: "dummyId", ClientID: "dummyId",
ClientSecret: "dummySecret", ClientSecret: "dummySecret",
RedirectURL: "REDIRECT_URL",
Scopes: []string{"scope1", "scope2"},
Endpoint: oauth2.Endpoint{
AuthURL: "http://example.com/auth",
TokenURL: "http://example.com/token",
},
} }
InitWithConfig(_config) InitWithConfig(_config)
token := &oauth.Token{ _token := &oauth2.Token{
AccessToken: "accessToken", AccessToken: "accessToken",
RefreshToken: "refreshToken", RefreshToken: "refreshToken",
Expiry: time.Unix(1234567890, 0).UTC(), Expiry: time.Unix(2234567890, 0).UTC(),
} }
actual := New(token) actual := New(_token)
val, _ := actual.httpClient.Transport.(*oauth.Transport) val := actual.httpClient.Transport.(*oauth2.Transport)
token, _ := val.Source.Token()
if !reflect.DeepEqual(val.Config, _config) { if !reflect.DeepEqual(token, _token) {
t.Errorf("got %v\nwant %v", val.Config, _config) t.Errorf("got %v\nwant %v", token, _token)
}
if !reflect.DeepEqual(val.Token, token) {
t.Errorf("got %v\nwant %v", val.Token, token)
} }
} }
@@ -130,21 +138,21 @@ func TestVerifySubscription(t *testing.T) {
Init() Init()
// Exception scenario // Exception scenario
token := &oauth.Token{ token := &oauth2.Token{
AccessToken: "accessToken", AccessToken: "accessToken",
RefreshToken: "refreshToken", RefreshToken: "refreshToken",
Expiry: time.Unix(1234567890, 0).UTC(), Expiry: time.Unix(2234567890, 0).UTC(),
} }
client := New(token) client := New(token)
expected := "Get https://www.googleapis.com/androidpublisher/v2/applications/package/purchases/subscriptions/subscriptionID/tokens/purchaseToken?alt=json: OAuthError: updateToken: Unexpected HTTP status 400 Bad Request" expected := "googleapi: Error 401: Invalid Credentials, authError"
_, err := client.VerifySubscription("package", "subscriptionID", "purchaseToken") _, err := client.VerifySubscription("package", "subscriptionID", "purchaseToken")
if err.Error() != expected { if err.Error() != expected {
t.Errorf("got %v", err) t.Errorf("got %v", err)
} }
// TODO Nomal scenario // TODO Normal scenario
} }
func TestVerifySubscriptionAndroidPublisherError(t *testing.T) { func TestVerifySubscriptionAndroidPublisherError(t *testing.T) {
@@ -161,21 +169,21 @@ func TestVerifyProduct(t *testing.T) {
Init() Init()
// Exception scenario // Exception scenario
token := &oauth.Token{ token := &oauth2.Token{
AccessToken: "accessToken", AccessToken: "accessToken",
RefreshToken: "refreshToken", RefreshToken: "refreshToken",
Expiry: time.Unix(1234567890, 0).UTC(), Expiry: time.Unix(2234567890, 0).UTC(),
} }
client := New(token) client := New(token)
expected := "Get https://www.googleapis.com/androidpublisher/v2/applications/package/purchases/products/productID/tokens/purchaseToken?alt=json: OAuthError: updateToken: Unexpected HTTP status 400 Bad Request" expected := "googleapi: Error 401: Invalid Credentials, authError"
_, err := client.VerifyProduct("package", "productID", "purchaseToken") _, err := client.VerifyProduct("package", "productID", "purchaseToken")
if err.Error() != expected { if err.Error() != expected {
t.Errorf("got %v", err) t.Errorf("got %v", err)
} }
// TODO Nomal scenario // TODO Normal scenario
} }
func TestVerifyProductAndroidPublisherError(t *testing.T) { func TestVerifyProductAndroidPublisherError(t *testing.T) {