braintree 2.45.0 → 2.46.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (52) hide show
  1. data/lib/braintree.rb +5 -0
  2. data/lib/braintree/add_on_gateway.rb +2 -1
  3. data/lib/braintree/address_gateway.rb +5 -4
  4. data/lib/braintree/client_token_gateway.rb +2 -1
  5. data/lib/braintree/configuration.rb +59 -7
  6. data/lib/braintree/credentials_parser.rb +40 -0
  7. data/lib/braintree/credit_card_gateway.rb +12 -11
  8. data/lib/braintree/credit_card_verification_gateway.rb +4 -3
  9. data/lib/braintree/customer_gateway.rb +12 -11
  10. data/lib/braintree/discount_gateway.rb +2 -1
  11. data/lib/braintree/error_codes.rb +9 -0
  12. data/lib/braintree/europe_bank_account_gateway.rb +2 -1
  13. data/lib/braintree/exceptions.rb +1 -5
  14. data/lib/braintree/gateway.rb +8 -0
  15. data/lib/braintree/http.rb +8 -2
  16. data/lib/braintree/merchant.rb +19 -0
  17. data/lib/braintree/merchant_account_gateway.rb +6 -5
  18. data/lib/braintree/merchant_gateway.rb +27 -0
  19. data/lib/braintree/oauth_credentials.rb +19 -0
  20. data/lib/braintree/oauth_gateway.rb +68 -0
  21. data/lib/braintree/payment_method_gateway.rb +7 -6
  22. data/lib/braintree/payment_method_nonce_gateway.rb +3 -2
  23. data/lib/braintree/paypal_account_gateway.rb +5 -4
  24. data/lib/braintree/plan_gateway.rb +2 -1
  25. data/lib/braintree/settlement_batch_summary_gateway.rb +2 -1
  26. data/lib/braintree/subscription_gateway.rb +8 -7
  27. data/lib/braintree/successful_result.rb +1 -1
  28. data/lib/braintree/testing_gateway.rb +5 -4
  29. data/lib/braintree/transaction.rb +1 -0
  30. data/lib/braintree/transaction_gateway.rb +12 -11
  31. data/lib/braintree/transaction_search.rb +3 -0
  32. data/lib/braintree/transparent_redirect_gateway.rb +1 -0
  33. data/lib/braintree/version.rb +1 -1
  34. data/lib/braintree/webhook_notification_gateway.rb +1 -0
  35. data/lib/braintree/webhook_testing_gateway.rb +1 -0
  36. data/spec/httpsd.pid +1 -1
  37. data/spec/integration/braintree/add_on_spec.rb +12 -0
  38. data/spec/integration/braintree/customer_spec.rb +31 -0
  39. data/spec/integration/braintree/http_spec.rb +10 -6
  40. data/spec/integration/braintree/merchant_account_spec.rb +0 -7
  41. data/spec/integration/braintree/merchant_spec.rb +55 -0
  42. data/spec/integration/braintree/oauth_spec.rb +191 -0
  43. data/spec/integration/braintree/plan_spec.rb +2 -1
  44. data/spec/integration/braintree/transaction_search_spec.rb +63 -0
  45. data/spec/integration/braintree/transaction_spec.rb +73 -4
  46. data/spec/integration/spec_helper.rb +1 -1
  47. data/spec/oauth_test_helper.rb +17 -0
  48. data/spec/spec_helper.rb +8 -4
  49. data/spec/unit/braintree/configuration_spec.rb +23 -0
  50. data/spec/unit/braintree/credentials_parser_spec.rb +81 -0
  51. metadata +161 -148
  52. checksums.yaml +0 -15
@@ -2,7 +2,7 @@ module Braintree
2
2
  class SuccessfulResult
3
3
  include BaseModule
4
4
 
5
- attr_reader :address, :credit_card, :customer, :merchant_account, :payment_method, :settlement_batch_summary, :subscription, :new_transaction, :transaction, :payment_method_nonce
5
+ attr_reader :address, :credit_card, :customer, :merchant_account, :payment_method, :settlement_batch_summary, :subscription, :new_transaction, :transaction, :payment_method_nonce, :credentials, :merchant
6
6
 
7
7
  def initialize(attributes = {}) # :nodoc:
8
8
  @attrs = attributes.keys
@@ -4,34 +4,35 @@ module Braintree
4
4
  def initialize(gateway)
5
5
  @gateway = gateway
6
6
  @config = gateway.config
7
+ @config.assert_has_access_token_or_keys
7
8
  @transaction_gateway = TransactionGateway.new(gateway)
8
9
  end
9
10
 
10
11
  def settle(transaction_id)
11
12
  check_environment
12
13
 
13
- response = @config.http.put "/transactions/#{transaction_id}/settle"
14
+ response = @config.http.put("#{@config.base_merchant_path}/transactions/#{transaction_id}/settle")
14
15
  @transaction_gateway._handle_transaction_response(response)
15
16
  end
16
17
 
17
18
  def settlement_confirm(transaction_id)
18
19
  check_environment
19
20
 
20
- response = @config.http.put "/transactions/#{transaction_id}/settlement_confirm"
21
+ response = @config.http.put("#{@config.base_merchant_path}/transactions/#{transaction_id}/settlement_confirm")
21
22
  @transaction_gateway._handle_transaction_response(response)
22
23
  end
23
24
 
24
25
  def settlement_decline(transaction_id)
25
26
  check_environment
26
27
 
27
- response = @config.http.put "/transactions/#{transaction_id}/settlement_decline"
28
+ response = @config.http.put("#{@config.base_merchant_path}/transactions/#{transaction_id}/settlement_decline")
28
29
  @transaction_gateway._handle_transaction_response(response)
29
30
  end
30
31
 
31
32
  def settlement_pending(transaction_id)
32
33
  check_environment
33
34
 
34
- response = @config.http.put "/transactions/#{transaction_id}/settlement_pending"
35
+ response = @config.http.put("#{@config.base_merchant_path}/transactions/#{transaction_id}/settlement_pending")
35
36
  @transaction_gateway._handle_transaction_response(response)
36
37
  end
37
38
 
@@ -18,6 +18,7 @@ module Braintree
18
18
  end
19
19
 
20
20
  module GatewayRejectionReason
21
+ ApplicationIncomplete = "application_incomplete"
21
22
  AVS = "avs"
22
23
  AVSAndCVV = "avs_and_cvv"
23
24
  CVV = "cvv"
@@ -3,6 +3,7 @@ module Braintree
3
3
  def initialize(gateway)
4
4
  @gateway = gateway
5
5
  @config = gateway.config
6
+ @config.assert_has_access_token_or_keys
6
7
  end
7
8
 
8
9
  def create(attributes)
@@ -12,13 +13,13 @@ module Braintree
12
13
 
13
14
  def cancel_release(transaction_id)
14
15
  raise ArgumentError, "transaction_id is invalid" unless transaction_id =~ /\A[0-9a-z]+\z/
15
- response = @config.http.put "/transactions/#{transaction_id}/cancel_release"
16
+ response = @config.http.put("#{@config.base_merchant_path}/transactions/#{transaction_id}/cancel_release")
16
17
  _handle_transaction_response(response)
17
18
  end
18
19
 
19
20
  def hold_in_escrow(transaction_id)
20
21
  raise ArgumentError, "transaction_id is invalid" unless transaction_id =~ /\A[0-9a-z]+\z/
21
- response = @config.http.put "/transactions/#{transaction_id}/hold_in_escrow"
22
+ response = @config.http.put("#{@config.base_merchant_path}/transactions/#{transaction_id}/hold_in_escrow")
22
23
  _handle_transaction_response(response)
23
24
  end
24
25
 
@@ -54,14 +55,14 @@ module Braintree
54
55
 
55
56
  def find(id)
56
57
  raise ArgumentError if id.nil? || id.strip.to_s == ""
57
- response = @config.http.get "/transactions/#{id}"
58
+ response = @config.http.get("#{@config.base_merchant_path}/transactions/#{id}")
58
59
  Transaction._new(@gateway, response[:transaction])
59
60
  rescue NotFoundError
60
61
  raise NotFoundError, "transaction with id #{id.inspect} not found"
61
62
  end
62
63
 
63
64
  def refund(transaction_id, amount = nil)
64
- response = @config.http.post "/transactions/#{transaction_id}/refund", :transaction => {:amount => amount}
65
+ response = @config.http.post("#{@config.base_merchant_path}/transactions/#{transaction_id}/refund", :transaction => {:amount => amount})
65
66
  _handle_transaction_response(response)
66
67
  end
67
68
 
@@ -82,7 +83,7 @@ module Braintree
82
83
  search = TransactionSearch.new
83
84
  block.call(search) if block
84
85
 
85
- response = @config.http.post "/transactions/advanced_search_ids", {:search => search.to_hash}
86
+ response = @config.http.post("#{@config.base_merchant_path}/transactions/advanced_search_ids", {:search => search.to_hash})
86
87
 
87
88
  if response.has_key?(:search_results)
88
89
  ResourceCollection.new(response) { |ids| _fetch_transactions(search, ids) }
@@ -93,18 +94,18 @@ module Braintree
93
94
 
94
95
  def release_from_escrow(transaction_id)
95
96
  raise ArgumentError, "transaction_id is invalid" unless transaction_id =~ /\A[0-9a-z]+\z/
96
- response = @config.http.put "/transactions/#{transaction_id}/release_from_escrow"
97
+ response = @config.http.put("#{@config.base_merchant_path}/transactions/#{transaction_id}/release_from_escrow")
97
98
  _handle_transaction_response(response)
98
99
  end
99
100
 
100
101
  def submit_for_settlement(transaction_id, amount = nil)
101
102
  raise ArgumentError, "transaction_id is invalid" unless transaction_id =~ /\A[0-9a-z]+\z/
102
- response = @config.http.put "/transactions/#{transaction_id}/submit_for_settlement", :transaction => {:amount => amount}
103
+ response = @config.http.put("#{@config.base_merchant_path}/transactions/#{transaction_id}/submit_for_settlement", :transaction => {:amount => amount})
103
104
  _handle_transaction_response(response)
104
105
  end
105
106
 
106
107
  def void(transaction_id)
107
- response = @config.http.put "/transactions/#{transaction_id}/void"
108
+ response = @config.http.put("#{@config.base_merchant_path}/transactions/#{transaction_id}/void")
108
109
  _handle_transaction_response(response)
109
110
  end
110
111
 
@@ -146,14 +147,14 @@ module Braintree
146
147
  ]
147
148
  end
148
149
 
149
- def _do_create(url, params=nil) # :nodoc:
150
- response = @config.http.post url, params
150
+ def _do_create(path, params=nil) # :nodoc:
151
+ response = @config.http.post("#{@config.base_merchant_path}#{path}", params)
151
152
  _handle_transaction_response(response)
152
153
  end
153
154
 
154
155
  def _fetch_transactions(search, ids) # :nodoc:
155
156
  search.ids.in ids
156
- response = @config.http.post "/transactions/advanced_search", {:search => search.to_hash}
157
+ response = @config.http.post("#{@config.base_merchant_path}/transactions/advanced_search", {:search => search.to_hash})
157
158
  attributes = response[:credit_card_transactions]
158
159
  Util.extract_attribute_as_array(attributes, :transaction).map { |attrs| Transaction._new(@gateway, attrs) }
159
160
  end
@@ -11,6 +11,7 @@ module Braintree
11
11
  :billing_region,
12
12
  :billing_street_address,
13
13
  :credit_card_cardholder_name,
14
+ :credit_card_unique_identifier,
14
15
  :currency,
15
16
  :customer_company,
16
17
  :customer_email,
@@ -53,6 +54,8 @@ module Braintree
53
54
  CreditCard::CustomerLocation::US
54
55
  ]
55
56
  multiple_value_field :ids
57
+ multiple_value_field :payment_instrument_type
58
+ multiple_value_field :user
56
59
  multiple_value_field :merchant_account_id
57
60
  multiple_value_field :status, :allows => Transaction::Status::All
58
61
  multiple_value_field :source, :allows => [
@@ -10,6 +10,7 @@ module Braintree
10
10
  def initialize(gateway)
11
11
  @gateway = gateway
12
12
  @config = gateway.config
13
+ @config.assert_has_access_token_or_keys
13
14
  end
14
15
 
15
16
  def confirm(query_string)
@@ -1,7 +1,7 @@
1
1
  module Braintree
2
2
  module Version
3
3
  Major = 2
4
- Minor = 45
4
+ Minor = 46
5
5
  Tiny = 0
6
6
 
7
7
  String = "#{Major}.#{Minor}.#{Tiny}"
@@ -3,6 +3,7 @@ module Braintree
3
3
  def initialize(gateway)
4
4
  @gateway = gateway
5
5
  @config = gateway.config
6
+ @config.assert_has_access_token_or_keys
6
7
  end
7
8
 
8
9
  def parse(signature_string, payload)
@@ -3,6 +3,7 @@ module Braintree
3
3
  def initialize(gateway)
4
4
  @gateway = gateway
5
5
  @config = gateway.config
6
+ @config.assert_has_access_token_or_keys
6
7
  end
7
8
 
8
9
  def sample_notification(kind, id)
@@ -1 +1 @@
1
- 12094
1
+ 19187
@@ -30,5 +30,17 @@ describe Braintree::AddOn do
30
30
  add_on.number_of_billing_cycles.should == expected[:number_of_billing_cycles]
31
31
  add_on.updated_at.should_not be_nil
32
32
  end
33
+
34
+ it "raises with a helpful error if public_key and private_key are not set" do
35
+ gateway = Braintree::Gateway.new(
36
+ :client_id => "client_id$development$integration_client_id",
37
+ :client_secret => "client_secret$development$integration_client_secret",
38
+ :logger => Logger.new("/dev/null")
39
+ )
40
+
41
+ expect do
42
+ gateway.add_on.all
43
+ end.to raise_error(Braintree::ConfigurationError, /public_key and private_key are required/)
44
+ end
33
45
  end
34
46
  end
@@ -54,6 +54,37 @@ describe Braintree::Customer do
54
54
  result.customer.updated_at.between?(Time.now - 10, Time.now).should == true
55
55
  end
56
56
 
57
+ it "returns a successful result if successful using an access token" do
58
+ oauth_gateway = Braintree::Gateway.new(
59
+ :client_id => "client_id$development$integration_client_id",
60
+ :client_secret => "client_secret$development$integration_client_secret",
61
+ :logger => Logger.new("/dev/null")
62
+ )
63
+ access_token = Braintree::OAuthTestHelper.create_token(oauth_gateway, {
64
+ :merchant_public_id => "integration_merchant_id",
65
+ :scope => "read_write"
66
+ }).credentials.access_token
67
+
68
+ gateway = Braintree::Gateway.new(
69
+ :access_token => access_token,
70
+ :logger => Logger.new("/dev/null")
71
+ )
72
+
73
+ result = gateway.customer.create(
74
+ :first_name => "Joe",
75
+ :last_name => "Brown",
76
+ :company => "ExampleCo",
77
+ :email => "joe@example.com",
78
+ :phone => "312.555.1234",
79
+ :fax => "614.555.5678",
80
+ :website => "www.example.com"
81
+ )
82
+ result.success?.should == true
83
+ result.customer.id.should =~ /^\d{6}$/
84
+ result.customer.first_name.should == "Joe"
85
+ result.customer.last_name.should == "Brown"
86
+ end
87
+
57
88
  it "supports creation with a device session ID and (optional) fraud_merchant_id" do
58
89
  result = Braintree::Customer.create(
59
90
  :credit_card => {
@@ -7,7 +7,8 @@ describe Braintree::Http do
7
7
  original_key = Braintree::Configuration.public_key
8
8
  Braintree::Configuration.public_key = "invalid_public_key"
9
9
  expect do
10
- Braintree::Configuration.instantiate.http.get "/customers"
10
+ config = Braintree::Configuration.instantiate
11
+ config.http.get("#{config.base_merchant_path}/customers")
11
12
  end.to raise_error(Braintree::AuthenticationError)
12
13
  ensure
13
14
  Braintree::Configuration.public_key = original_key
@@ -16,7 +17,8 @@ describe Braintree::Http do
16
17
 
17
18
  it "raises an AuthorizationError if authorization fails" do
18
19
  expect do
19
- Braintree::Configuration.instantiate.http.get "/users"
20
+ config = Braintree::Configuration.instantiate
21
+ config.http.get("#{config.base_merchant_path}/users")
20
22
  end.to raise_error(Braintree::AuthorizationError)
21
23
  end
22
24
  end
@@ -32,7 +34,7 @@ describe Braintree::Http do
32
34
  Braintree::Configuration.logger.level = Logger::INFO
33
35
  Braintree::Customer.all
34
36
  utc_or_gmt = Time.now.utc.strftime("%Z")
35
- output.string.should include("[Braintree] [10/Oct/2009 13:55:36 #{utc_or_gmt}] POST /customers/advanced_search_ids 200")
37
+ output.string.should include("[Braintree] [10/Oct/2009 13:55:36 #{utc_or_gmt}] POST /merchants/integration_merchant_id/customers/advanced_search_ids 200")
36
38
  end
37
39
  ensure
38
40
  Braintree::Configuration.logger = old_logger
@@ -56,7 +58,7 @@ describe Braintree::Http do
56
58
  )
57
59
  result.success?.should == true
58
60
  utc_or_gmt = Time.now.utc.strftime("%Z")
59
- output.string.should include("[Braintree] [10/Oct/2009 13:55:36 #{utc_or_gmt}] POST /payment_methods")
61
+ output.string.should include("[Braintree] [10/Oct/2009 13:55:36 #{utc_or_gmt}] POST /merchants/integration_merchant_id/payment_methods")
60
62
  output.string.should include("[Braintree] <cardholder-name>Sam Jones</cardholder-name>")
61
63
  output.string.should include("[Braintree] <number>401288******1881</number>")
62
64
  output.string.should include("[Braintree] [10/Oct/2009 13:55:36 #{utc_or_gmt}] 201 Created")
@@ -73,13 +75,15 @@ describe Braintree::Http do
73
75
  end
74
76
 
75
77
  it "sets the User-Agent header using the default user agent" do
76
- response = Braintree::Configuration.instantiate.http.get "/test/headers"
78
+ config = Braintree::Configuration.instantiate
79
+ response = config.http.get("#{config.base_merchant_path}/test/headers")
77
80
  response[:headers][:HTTP_USER_AGENT].should == "Braintree Ruby Gem #{Braintree::Version::String}"
78
81
  end
79
82
 
80
83
  it "sets the User-Agent header using a customer user agent" do
81
84
  Braintree::Configuration.custom_user_agent = "ActiveMerchant 1.2.3"
82
- response = Braintree::Configuration.instantiate.http.get "/test/headers"
85
+ config = Braintree::Configuration.instantiate
86
+ response = config.http.get("#{config.base_merchant_path}/test/headers")
83
87
  response[:headers][:HTTP_USER_AGENT].should == "Braintree Ruby Gem #{Braintree::Version::String} (ActiveMerchant 1.2.3)"
84
88
  end
85
89
  end
@@ -109,7 +109,6 @@ describe Braintree::MerchantAccount do
109
109
  context "funding destination" do
110
110
  it "accepts a bank" do
111
111
  params = VALID_APPLICATION_PARAMS.dup
112
- params[:funding] = VALID_APPLICATION_PARAMS[:funding].dup
113
112
  params[:funding][:destination] = ::Braintree::MerchantAccount::FundingDestination::Bank
114
113
  result = Braintree::MerchantAccount.create(params)
115
114
 
@@ -118,9 +117,6 @@ describe Braintree::MerchantAccount do
118
117
 
119
118
  it "accepts an email" do
120
119
  params = VALID_APPLICATION_PARAMS.dup
121
- params[:funding] = VALID_APPLICATION_PARAMS[:funding].dup
122
- params[:funding].delete(:routing_number)
123
- params[:funding].delete(:account_number)
124
120
  params[:funding][:destination] = ::Braintree::MerchantAccount::FundingDestination::Email
125
121
  params[:funding][:email] = "joebloggs@compuserve.com"
126
122
  result = Braintree::MerchantAccount.create(params)
@@ -130,9 +126,6 @@ describe Braintree::MerchantAccount do
130
126
 
131
127
  it "accepts a mobile_phone" do
132
128
  params = VALID_APPLICATION_PARAMS.dup
133
- params[:funding] = VALID_APPLICATION_PARAMS[:funding].dup
134
- params[:funding].delete(:routing_number)
135
- params[:funding].delete(:account_number)
136
129
  params[:funding][:destination] = ::Braintree::MerchantAccount::FundingDestination::MobilePhone
137
130
  params[:funding][:mobile_phone] = "3125882300"
138
131
  result = Braintree::MerchantAccount.create(params)
@@ -0,0 +1,55 @@
1
+ require File.expand_path(File.dirname(__FILE__) + "/../spec_helper")
2
+
3
+ describe Braintree::MerchantGateway do
4
+ describe "create" do
5
+ it "creates a merchant" do
6
+ gateway = Braintree::Gateway.new(
7
+ :client_id => "client_id$development$integration_client_id",
8
+ :client_secret => "client_secret$development$integration_client_secret",
9
+ :logger => Logger.new("/dev/null")
10
+ )
11
+
12
+ result = gateway.merchant.create(
13
+ :email => "name@email.com",
14
+ :country_code_alpha3 => "USA",
15
+ :payment_methods => ["credit_card", "paypal"]
16
+ )
17
+
18
+ result.should be_success
19
+
20
+ merchant = result.merchant
21
+ merchant.id.should_not be_nil
22
+ merchant.email.should == "name@email.com"
23
+ merchant.company_name.should == "name@email.com"
24
+ merchant.country_code_alpha3.should == "USA"
25
+ merchant.country_code_alpha2.should == "US"
26
+ merchant.country_code_numeric.should == "840"
27
+ merchant.country_name.should == "United States of America"
28
+
29
+ credentials = result.credentials
30
+ credentials.access_token.should start_with("access_token$")
31
+ credentials.expires_at.should_not be_nil
32
+ credentials.token_type.should == "bearer"
33
+ credentials.refresh_token.should be_nil
34
+ end
35
+
36
+ it "gives an error when using invalid payment_methods" do
37
+ gateway = Braintree::Gateway.new(
38
+ :client_id => "client_id$development$integration_client_id",
39
+ :client_secret => "client_secret$development$integration_client_secret",
40
+ :logger => Logger.new("/dev/null")
41
+ )
42
+
43
+ result = gateway.merchant.create(
44
+ :email => "name@email.com",
45
+ :country_code_alpha3 => "USA",
46
+ :payment_methods => ["fake_money"]
47
+ )
48
+
49
+ result.should_not be_success
50
+ errors = result.errors.for(:merchant).on(:payment_methods)
51
+
52
+ errors[0].code.should == Braintree::ErrorCodes::Merchant::PaymentMethodsAreInvalid
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,191 @@
1
+ require File.expand_path(File.dirname(__FILE__) + "/../spec_helper")
2
+
3
+ describe "OAuth" do
4
+ before(:each) do
5
+ @gateway = Braintree::Gateway.new(
6
+ :client_id => "client_id$development$integration_client_id",
7
+ :client_secret => "client_secret$development$integration_client_secret",
8
+ :logger => Logger.new("/dev/null")
9
+ )
10
+ end
11
+
12
+ describe "create_token_from_code" do
13
+ it "creates an access token given a grant code" do
14
+ code = Braintree::OAuthTestHelper.create_grant(@gateway, {
15
+ :merchant_public_id => "integration_merchant_id",
16
+ :scope => "read_write"
17
+ })
18
+
19
+ result = @gateway.oauth.create_token_from_code(
20
+ :code => code,
21
+ :scope => "read_write"
22
+ )
23
+
24
+ result.should be_success
25
+ credentials = result.credentials
26
+ credentials.access_token.should_not be_nil
27
+ credentials.refresh_token.should_not be_nil
28
+ credentials.expires_at.should_not be_nil
29
+ credentials.token_type.should == "bearer"
30
+ end
31
+
32
+ it "returns validation errors for bad params" do
33
+ result = @gateway.oauth.create_token_from_code(
34
+ :code => "bad_code",
35
+ :scope => "read_write"
36
+ )
37
+
38
+ result.should_not be_success
39
+ errors = result.errors.for(:credentials).on(:code)[0].code.should == Braintree::ErrorCodes::OAuth::InvalidGrant
40
+ result.message.should =~ /Invalid grant: code not found/
41
+ end
42
+
43
+ it "raises with a helpful error if client_id and client_secret are not set" do
44
+ gateway = Braintree::Gateway.new(
45
+ :access_token => "access_token$development$integration_merchant_id$fb27c79dd",
46
+ :logger => Logger.new("/dev/null")
47
+ )
48
+
49
+ expect do
50
+ gateway.oauth.create_token_from_code(
51
+ :code => "some code",
52
+ :scope => "read_write"
53
+ )
54
+ end.to raise_error(Braintree::ConfigurationError, /client_id and client_secret are required/);
55
+ end
56
+ end
57
+
58
+ describe "create_token_from_refresh_token" do
59
+ it "creates an access token given a refresh token" do
60
+ code = Braintree::OAuthTestHelper.create_grant(@gateway, {
61
+ :merchant_public_id => "integration_merchant_id",
62
+ :scope => "read_write"
63
+ })
64
+ refresh_token = @gateway.oauth.create_token_from_code(
65
+ :code => code,
66
+ :scope => "read_write"
67
+ ).credentials.refresh_token
68
+
69
+ result = @gateway.oauth.create_token_from_refresh_token(
70
+ :refresh_token => refresh_token,
71
+ :scope => "read_write"
72
+ )
73
+
74
+ result.should be_success
75
+ credentials = result.credentials
76
+ credentials.access_token.should_not be_nil
77
+ credentials.refresh_token.should_not be_nil
78
+ credentials.expires_at.should_not be_nil
79
+ credentials.token_type.should == "bearer"
80
+ end
81
+ end
82
+
83
+ describe "connect_url" do
84
+ it "builds a connect url" do
85
+ url = @gateway.oauth.connect_url(
86
+ :merchant_id => "integration_merchant_id",
87
+ :redirect_uri => "http://bar.example.com",
88
+ :scope => "read_write",
89
+ :state => "baz_state",
90
+ :user => {
91
+ :country => "USA",
92
+ :email => "foo@example.com",
93
+ :first_name => "Bob",
94
+ :last_name => "Jones",
95
+ :phone => "555-555-5555",
96
+ :dob_year => "1970",
97
+ :dob_month => "01",
98
+ :dob_day => "01",
99
+ :street_address => "222 W Merchandise Mart",
100
+ :locality => "Chicago",
101
+ :region => "IL",
102
+ :postal_code => "60606"
103
+ },
104
+ :business => {
105
+ :name => "14 Ladders",
106
+ :registered_as => "14.0 Ladders",
107
+ :industry => "Ladders",
108
+ :description => "We sell the best ladders",
109
+ :street_address => "111 N Canal",
110
+ :locality => "Chicago",
111
+ :region => "IL",
112
+ :postal_code => "60606",
113
+ :country => "USA",
114
+ :annual_volume_amount => "1000000",
115
+ :average_transaction_amount => "100",
116
+ :maximum_transaction_amount => "10000",
117
+ :ship_physical_goods => true,
118
+ :fulfillment_completed_in => 7,
119
+ :currency => "USD",
120
+ :website => "http://example.com"
121
+ },
122
+ :payment_methods => ["credit_card", "paypal"]
123
+ )
124
+
125
+ uri = URI.parse(url)
126
+ uri.host.should == "localhost"
127
+ uri.path.should == "/oauth/connect"
128
+
129
+ query = CGI.parse(CGI.unescape(uri.query))
130
+ query["merchant_id"].should == ["integration_merchant_id"]
131
+ query["client_id"].should == ["client_id$development$integration_client_id"]
132
+ query["redirect_uri"].should == ["http://bar.example.com"]
133
+ query["scope"].should == ["read_write"]
134
+ query["state"].should == ["baz_state"]
135
+
136
+ query["user[country]"].should == ["USA"]
137
+ query["business[name]"].should == ["14 Ladders"]
138
+
139
+ query["user[email]"].should == ["foo@example.com"]
140
+ query["user[first_name]"].should == ["Bob"]
141
+ query["user[last_name]"].should == ["Jones"]
142
+ query["user[phone]"].should == ["555-555-5555"]
143
+ query["user[dob_year]"].should == ["1970"]
144
+ query["user[dob_month]"].should == ["01"]
145
+ query["user[dob_day]"].should == ["01"]
146
+ query["user[street_address]"].should == ["222 W Merchandise Mart"]
147
+ query["user[locality]"].should == ["Chicago"]
148
+ query["user[region]"].should == ["IL"]
149
+ query["user[postal_code]"].should == ["60606"]
150
+
151
+ query["business[name]"].should == ["14 Ladders"]
152
+ query["business[registered_as]"].should == ["14.0 Ladders"]
153
+ query["business[industry]"].should == ["Ladders"]
154
+ query["business[description]"].should == ["We sell the best ladders"]
155
+ query["business[street_address]"].should == ["111 N Canal"]
156
+ query["business[locality]"].should == ["Chicago"]
157
+ query["business[region]"].should == ["IL"]
158
+ query["business[postal_code]"].should == ["60606"]
159
+ query["business[country]"].should == ["USA"]
160
+ query["business[annual_volume_amount]"].should == ["1000000"]
161
+ query["business[average_transaction_amount]"].should == ["100"]
162
+ query["business[maximum_transaction_amount]"].should == ["10000"]
163
+ query["business[ship_physical_goods]"].should == ["true"]
164
+ query["business[fulfillment_completed_in]"].should == ["7"]
165
+ query["business[currency]"].should == ["USD"]
166
+ query["business[website]"].should == ["http://example.com"]
167
+
168
+ query["signature"][0].length.should == 64
169
+ query["algorithm"].should == ["SHA256"]
170
+ end
171
+
172
+ it "builds the query string with multiple payment_methods" do
173
+ url = @gateway.oauth.connect_url(
174
+ :merchant_id => "integration_merchant_id",
175
+ :redirect_uri => "http://bar.example.com",
176
+ :scope => "read_write",
177
+ :state => "baz_state",
178
+ :payment_methods => ["credit_card", "paypal"]
179
+ )
180
+
181
+ uri = URI.parse(url)
182
+ uri.host.should == "localhost"
183
+ uri.path.should == "/oauth/connect"
184
+
185
+ query = CGI.parse(CGI.unescape(uri.query))
186
+ query["payment_methods[]"].length.should == 2
187
+ query["payment_methods[]"].should include("paypal")
188
+ query["payment_methods[]"].should include("credit_card")
189
+ end
190
+ end
191
+ end