braintree 2.31.0 → 2.32.1
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.
- data/README.rdoc +2 -2
- data/lib/braintree.rb +12 -0
- data/lib/braintree/client_token.rb +5 -0
- data/lib/braintree/client_token_gateway.rb +2 -1
- data/lib/braintree/configuration.rb +1 -1
- data/lib/braintree/credit_card.rb +1 -1
- data/lib/braintree/credit_card_gateway.rb +3 -3
- data/lib/braintree/customer.rb +18 -4
- data/lib/braintree/customer_gateway.rb +2 -2
- data/lib/braintree/customer_search.rb +1 -0
- data/lib/braintree/error_codes.rb +81 -14
- data/lib/braintree/exceptions.rb +2 -0
- data/lib/braintree/gateway.rb +16 -0
- data/lib/braintree/payment_instrument_type.rb +7 -0
- data/lib/braintree/payment_method.rb +17 -0
- data/lib/braintree/payment_method_gateway.rb +58 -0
- data/lib/braintree/paypal_account.rb +47 -0
- data/lib/braintree/paypal_account_gateway.rb +41 -0
- data/lib/braintree/sepa_bank_account.rb +34 -0
- data/lib/braintree/sepa_bank_account_gateway.rb +16 -0
- data/lib/braintree/successful_result.rb +1 -1
- data/lib/braintree/test/nonce.rb +10 -0
- data/lib/braintree/test_transaction.rb +15 -0
- data/lib/braintree/testing_gateway.rb +35 -0
- data/lib/braintree/transaction.rb +6 -0
- data/lib/braintree/transaction/paypal_details.rb +14 -0
- data/lib/braintree/transaction_gateway.rb +3 -1
- data/lib/braintree/transaction_search.rb +4 -0
- data/lib/braintree/unknown_payment_method.rb +20 -0
- data/lib/braintree/version.rb +2 -2
- data/lib/braintree/webhook_testing_gateway.rb +1 -1
- data/spec/integration/braintree/client_api/client_token_spec.rb +80 -17
- data/spec/integration/braintree/client_api/spec_helper.rb +93 -10
- data/spec/integration/braintree/credit_card_spec.rb +28 -27
- data/spec/integration/braintree/customer_search_spec.rb +23 -0
- data/spec/integration/braintree/customer_spec.rb +83 -1
- data/spec/integration/braintree/payment_method_spec.rb +315 -0
- data/spec/integration/braintree/paypal_account_spec.rb +188 -0
- data/spec/integration/braintree/subscription_spec.rb +50 -20
- data/spec/integration/braintree/test_transaction_spec.rb +104 -0
- data/spec/integration/braintree/transaction_search_spec.rb +60 -0
- data/spec/integration/braintree/transaction_spec.rb +583 -8
- data/spec/integration/spec_helper.rb +22 -0
- data/spec/spec_helper.rb +8 -2
- data/spec/unit/braintree/customer_spec.rb +24 -4
- data/spec/unit/braintree/payment_method_spec.rb +25 -0
- data/spec/unit/braintree/paypal_account_spec.rb +31 -0
- data/spec/unit/braintree/unknown_payment_method_spec.rb +29 -0
- metadata +141 -120
- checksums.yaml +0 -7
- data/spec/httpsd.pid +0 -1
|
@@ -1,22 +1,58 @@
|
|
|
1
1
|
require 'json'
|
|
2
2
|
|
|
3
|
-
def
|
|
3
|
+
def decode_client_token(raw_client_token)
|
|
4
|
+
decoded_client_token_string = Base64.decode64(raw_client_token)
|
|
5
|
+
JSON.parse(decoded_client_token_string)
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
def nonce_for_new_payment_method(options)
|
|
9
|
+
client = _initialize_client(options)
|
|
10
|
+
response = client.add_payment_method(options)
|
|
11
|
+
|
|
12
|
+
_nonce_from_response(response)
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def _initialize_client(options)
|
|
4
16
|
client_token_options = options.delete(:client_token_options) || {}
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
17
|
+
raw_client_token = Braintree::ClientToken.generate(client_token_options)
|
|
18
|
+
client_token = decode_client_token(raw_client_token)
|
|
19
|
+
|
|
20
|
+
ClientApiHttp.new(Braintree::Configuration.instantiate,
|
|
21
|
+
:authorization_fingerprint => client_token["authorizationFingerprint"],
|
|
8
22
|
:shared_customer_identifier => "fake_identifier",
|
|
9
23
|
:shared_customer_identifier_type => "testing"
|
|
10
24
|
)
|
|
25
|
+
end
|
|
11
26
|
|
|
12
|
-
|
|
27
|
+
def _nonce_from_response(response)
|
|
13
28
|
body = JSON.parse(response.body)
|
|
14
29
|
|
|
15
30
|
if body["errors"] != nil
|
|
16
31
|
raise body["errors"].inspect
|
|
17
32
|
end
|
|
18
33
|
|
|
19
|
-
body
|
|
34
|
+
if body.has_key?("paypalAccounts")
|
|
35
|
+
body["paypalAccounts"][0]["nonce"]
|
|
36
|
+
else
|
|
37
|
+
body["creditCards"][0]["nonce"]
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def nonce_for_paypal_account(paypal_account_details)
|
|
42
|
+
raw_client_token = Braintree::ClientToken.generate
|
|
43
|
+
client_token = decode_client_token(raw_client_token)
|
|
44
|
+
client = ClientApiHttp.new(Braintree::Configuration.instantiate,
|
|
45
|
+
:authorization_fingerprint => client_token["authorizationFingerprint"]
|
|
46
|
+
)
|
|
47
|
+
|
|
48
|
+
response = client.create_paypal_account(paypal_account_details)
|
|
49
|
+
body = JSON.parse(response.body)
|
|
50
|
+
|
|
51
|
+
if body["errors"] != nil
|
|
52
|
+
raise body["errors"].inspect
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
body["paypalAccounts"][0]["nonce"]
|
|
20
56
|
end
|
|
21
57
|
|
|
22
58
|
class ClientApiHttp
|
|
@@ -35,6 +71,10 @@ class ClientApiHttp
|
|
|
35
71
|
_http_do(Net::HTTP::Post, path, params.to_json)
|
|
36
72
|
end
|
|
37
73
|
|
|
74
|
+
def put(path, params)
|
|
75
|
+
_http_do(Net::HTTP::Put, path, params.to_json)
|
|
76
|
+
end
|
|
77
|
+
|
|
38
78
|
def fingerprint=(fingerprint)
|
|
39
79
|
@options[:authorization_fingerprint] = fingerprint
|
|
40
80
|
end
|
|
@@ -59,9 +99,9 @@ class ClientApiHttp
|
|
|
59
99
|
raise Braintree::SSLCertificateError
|
|
60
100
|
end
|
|
61
101
|
|
|
62
|
-
def
|
|
102
|
+
def get_payment_methods
|
|
63
103
|
encoded_fingerprint = Braintree::Util.url_encode(@options[:authorization_fingerprint])
|
|
64
|
-
url = "/merchants/#{@config.merchant_id}/client_api/
|
|
104
|
+
url = "/merchants/#{@config.merchant_id}/client_api/v1/payment_methods?"
|
|
65
105
|
url += "authorizationFingerprint=#{encoded_fingerprint}"
|
|
66
106
|
url += "&sharedCustomerIdentifier=#{@options[:shared_customer_identifier]}"
|
|
67
107
|
url += "&sharedCustomerIdentifierType=#{@options[:shared_customer_identifier_type]}"
|
|
@@ -69,12 +109,55 @@ class ClientApiHttp
|
|
|
69
109
|
get(url)
|
|
70
110
|
end
|
|
71
111
|
|
|
72
|
-
def
|
|
112
|
+
def add_payment_method(params)
|
|
73
113
|
fingerprint = @options[:authorization_fingerprint]
|
|
74
114
|
params[:authorizationFingerprint] = fingerprint
|
|
75
115
|
params[:sharedCustomerIdentifier] = @options[:shared_customer_identifier]
|
|
76
116
|
params[:sharedCustomerIdentifierType] = @options[:shared_customer_identifier_type]
|
|
77
117
|
|
|
78
|
-
|
|
118
|
+
payment_method_type = nil
|
|
119
|
+
if params.has_key?(:paypal_account)
|
|
120
|
+
payment_method_type = "paypal_accounts"
|
|
121
|
+
else
|
|
122
|
+
payment_method_type = "credit_cards"
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
post("/merchants/#{@config.merchant_id}/client_api/v1/payment_methods/#{payment_method_type}", params)
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
def create_credit_card(params)
|
|
129
|
+
params = {:credit_card => params}
|
|
130
|
+
params.merge!(
|
|
131
|
+
:authorization_fingerprint => @options[:authorization_fingerprint],
|
|
132
|
+
:shared_customer_identifier => "fake_identifier",
|
|
133
|
+
:shared_customer_identifier_type => "testing"
|
|
134
|
+
)
|
|
135
|
+
|
|
136
|
+
post("/merchants/#{config.merchant_id}/client_api/v1/payment_methods/credit_cards", params)
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
def create_paypal_account(params)
|
|
140
|
+
params = {:paypal_account => params}
|
|
141
|
+
params.merge!(
|
|
142
|
+
:authorization_fingerprint => @options[:authorization_fingerprint]
|
|
143
|
+
)
|
|
144
|
+
|
|
145
|
+
post("/merchants/#{config.merchant_id}/client_api/v1/payment_methods/paypal_accounts", params)
|
|
146
|
+
end
|
|
147
|
+
|
|
148
|
+
def create_sepa_bank_account_nonce(params)
|
|
149
|
+
foo = {
|
|
150
|
+
:authorization_fingerprint => @options[:authorization_fingerprint],
|
|
151
|
+
:shared_customer_identifier => "fake_identifier",
|
|
152
|
+
:shared_customer_identifier_type => "testing",
|
|
153
|
+
|
|
154
|
+
:sepa_mandate => params
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
response = post("/merchants/#{config.merchant_id}/client_api/v1/sepa_mandates", foo)
|
|
158
|
+
|
|
159
|
+
mrn = JSON.parse(response.body)['sepaMandates'][0]['mandateReferenceNumber']
|
|
160
|
+
accept_response = put("/merchants/#{config.merchant_id}/client_api/v1/sepa_mandates/#{mrn}/accept.json",foo)
|
|
161
|
+
JSON.parse(accept_response.body)['sepaBankAccounts'][0]['nonce']
|
|
79
162
|
end
|
|
80
163
|
end
|
|
@@ -456,7 +456,7 @@ describe Braintree::CreditCard do
|
|
|
456
456
|
|
|
457
457
|
context "client API" do
|
|
458
458
|
it "adds credit card to an existing customer using a payment method nonce" do
|
|
459
|
-
nonce =
|
|
459
|
+
nonce = nonce_for_new_payment_method(
|
|
460
460
|
:credit_card => {
|
|
461
461
|
:number => "4111111111111111",
|
|
462
462
|
:expiration_month => "11",
|
|
@@ -1050,24 +1050,6 @@ describe Braintree::CreditCard do
|
|
|
1050
1050
|
end
|
|
1051
1051
|
end
|
|
1052
1052
|
|
|
1053
|
-
describe "delete" do
|
|
1054
|
-
it "deletes the credit card" do
|
|
1055
|
-
customer = Braintree::Customer.create.customer
|
|
1056
|
-
result = Braintree::CreditCard.create(
|
|
1057
|
-
:customer_id => customer.id,
|
|
1058
|
-
:number => Braintree::Test::CreditCardNumbers::Visa,
|
|
1059
|
-
:expiration_date => "05/2012"
|
|
1060
|
-
)
|
|
1061
|
-
|
|
1062
|
-
result.success?.should == true
|
|
1063
|
-
credit_card = result.credit_card
|
|
1064
|
-
credit_card.delete.should == true
|
|
1065
|
-
expect do
|
|
1066
|
-
Braintree::CreditCard.find(credit_card.token)
|
|
1067
|
-
end.to raise_error(Braintree::NotFoundError)
|
|
1068
|
-
end
|
|
1069
|
-
end
|
|
1070
|
-
|
|
1071
1053
|
describe "self.expired" do
|
|
1072
1054
|
it "can iterate over all items, and make sure they are all expired" do
|
|
1073
1055
|
customer = Braintree::Customer.all.first
|
|
@@ -1161,12 +1143,30 @@ describe Braintree::CreditCard do
|
|
|
1161
1143
|
Braintree::CreditCard.find("invalid-token")
|
|
1162
1144
|
end.to raise_error(Braintree::NotFoundError, 'payment method with token "invalid-token" not found')
|
|
1163
1145
|
end
|
|
1146
|
+
|
|
1147
|
+
it "raises a NotFoundError exception if searching for a PayPalAccount token" do
|
|
1148
|
+
customer = Braintree::Customer.create!
|
|
1149
|
+
paypal_account_token = "PAYPAL_ACCOUNT_TOKEN_#{rand(36**3).to_s(36)}"
|
|
1150
|
+
paypal_nonce = nonce_for_paypal_account({
|
|
1151
|
+
:consent_code => "PAYPAL_CONSENT_CODE",
|
|
1152
|
+
:token => paypal_account_token
|
|
1153
|
+
})
|
|
1154
|
+
|
|
1155
|
+
Braintree::PaymentMethod.create({
|
|
1156
|
+
:payment_method_nonce => paypal_nonce,
|
|
1157
|
+
:customer_id => customer.id
|
|
1158
|
+
})
|
|
1159
|
+
|
|
1160
|
+
expect do
|
|
1161
|
+
Braintree::CreditCard.find(paypal_account_token)
|
|
1162
|
+
end.to raise_error(Braintree::NotFoundError, "payment method with token \"#{paypal_account_token}\" not found")
|
|
1163
|
+
end
|
|
1164
1164
|
end
|
|
1165
1165
|
|
|
1166
1166
|
describe "self.from_nonce" do
|
|
1167
1167
|
it "finds the payment method with the given nonce" do
|
|
1168
1168
|
customer = Braintree::Customer.create!
|
|
1169
|
-
nonce =
|
|
1169
|
+
nonce = nonce_for_new_payment_method(
|
|
1170
1170
|
:credit_card => {
|
|
1171
1171
|
:number => "4111111111111111",
|
|
1172
1172
|
:expiration_month => "11",
|
|
@@ -1181,7 +1181,7 @@ describe Braintree::CreditCard do
|
|
|
1181
1181
|
end
|
|
1182
1182
|
|
|
1183
1183
|
it "does not find a payment method for an unlocked nonce that points to a shared credit card" do
|
|
1184
|
-
nonce =
|
|
1184
|
+
nonce = nonce_for_new_payment_method(
|
|
1185
1185
|
:credit_card => {
|
|
1186
1186
|
:number => "4111111111111111",
|
|
1187
1187
|
:expiration_month => "11",
|
|
@@ -1194,14 +1194,15 @@ describe Braintree::CreditCard do
|
|
|
1194
1194
|
end
|
|
1195
1195
|
|
|
1196
1196
|
it "does not find the payment method for a locked nonce" do
|
|
1197
|
-
|
|
1197
|
+
raw_client_token = Braintree::ClientToken.generate
|
|
1198
|
+
client_token = decode_client_token(raw_client_token)
|
|
1198
1199
|
client = ClientApiHttp.new(Braintree::Configuration.instantiate,
|
|
1199
|
-
:authorization_fingerprint =>
|
|
1200
|
+
:authorization_fingerprint => client_token["authorizationFingerprint"],
|
|
1200
1201
|
:shared_customer_identifier => "fake_identifier",
|
|
1201
1202
|
:shared_customer_identifier_type => "testing"
|
|
1202
1203
|
)
|
|
1203
1204
|
|
|
1204
|
-
client.
|
|
1205
|
+
client.add_payment_method(
|
|
1205
1206
|
:credit_card => {
|
|
1206
1207
|
:number => "4111111111111111",
|
|
1207
1208
|
:expiration_month => "11",
|
|
@@ -1210,9 +1211,9 @@ describe Braintree::CreditCard do
|
|
|
1210
1211
|
:share => true
|
|
1211
1212
|
)
|
|
1212
1213
|
|
|
1213
|
-
response = client.
|
|
1214
|
+
response = client.get_payment_methods
|
|
1214
1215
|
body = JSON.parse(response.body)
|
|
1215
|
-
nonce = body["
|
|
1216
|
+
nonce = body["paymentMethods"].first["nonce"]
|
|
1216
1217
|
|
|
1217
1218
|
expect do
|
|
1218
1219
|
Braintree::CreditCard.from_nonce(nonce)
|
|
@@ -1221,7 +1222,7 @@ describe Braintree::CreditCard do
|
|
|
1221
1222
|
|
|
1222
1223
|
it "does not find the payment method for a consumednonce" do
|
|
1223
1224
|
customer = Braintree::Customer.create!
|
|
1224
|
-
nonce =
|
|
1225
|
+
nonce = nonce_for_new_payment_method(
|
|
1225
1226
|
:credit_card => {
|
|
1226
1227
|
:number => "4111111111111111",
|
|
1227
1228
|
:expiration_month => "11",
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
require File.expand_path(File.dirname(__FILE__) + "/../spec_helper")
|
|
2
|
+
require File.expand_path(File.dirname(__FILE__) + "/client_api/spec_helper")
|
|
2
3
|
|
|
3
4
|
describe Braintree::Transaction, "search" do
|
|
4
5
|
context "advanced" do
|
|
@@ -169,4 +170,26 @@ describe Braintree::Transaction, "search" do
|
|
|
169
170
|
collection.first.company.should == customer.company
|
|
170
171
|
end
|
|
171
172
|
end
|
|
173
|
+
|
|
174
|
+
it "can search by paypal_account_email" do
|
|
175
|
+
paypal_token = rand(36**3).to_s(36)
|
|
176
|
+
nonce = nonce_for_paypal_account(
|
|
177
|
+
:consent_code => "PAYPAL_CONSENT_CODE",
|
|
178
|
+
:token => paypal_token
|
|
179
|
+
)
|
|
180
|
+
|
|
181
|
+
customer_id = "UNIQUE_CUSTOMER_ID_" + rand(36**3).to_s(36)
|
|
182
|
+
customer = Braintree::Customer.create!(
|
|
183
|
+
:payment_method_nonce => nonce,
|
|
184
|
+
:id => customer_id
|
|
185
|
+
)
|
|
186
|
+
|
|
187
|
+
collection = Braintree::Customer.search do |search|
|
|
188
|
+
search.paypal_account_email.is "jane.doe@example.com"
|
|
189
|
+
search.id.is customer_id
|
|
190
|
+
end
|
|
191
|
+
|
|
192
|
+
collection.maximum_size.should == 1
|
|
193
|
+
collection.first.should == customer
|
|
194
|
+
end
|
|
172
195
|
end
|
|
@@ -383,7 +383,7 @@ describe Braintree::Customer do
|
|
|
383
383
|
|
|
384
384
|
context "client API" do
|
|
385
385
|
it "can create a customer with a payment method nonce" do
|
|
386
|
-
nonce =
|
|
386
|
+
nonce = nonce_for_new_payment_method(
|
|
387
387
|
:credit_card => {
|
|
388
388
|
:number => "4111111111111111",
|
|
389
389
|
:expiration_month => "11",
|
|
@@ -1135,4 +1135,86 @@ describe Braintree::Customer do
|
|
|
1135
1135
|
customer.default_credit_card.should == default_credit_card
|
|
1136
1136
|
end
|
|
1137
1137
|
end
|
|
1138
|
+
|
|
1139
|
+
describe "paypal" do
|
|
1140
|
+
context "future" do
|
|
1141
|
+
it "creates a customer with a future paypal account" do
|
|
1142
|
+
result = Braintree::Customer.create(
|
|
1143
|
+
:payment_method_nonce => Braintree::Test::Nonce::PayPalFuturePayment
|
|
1144
|
+
)
|
|
1145
|
+
|
|
1146
|
+
result.should be_success
|
|
1147
|
+
end
|
|
1148
|
+
|
|
1149
|
+
it "updates a customer with a future paypal account" do
|
|
1150
|
+
customer = Braintree::Customer.create!(
|
|
1151
|
+
:credit_card => {
|
|
1152
|
+
:number => Braintree::Test::CreditCardNumbers::Visa,
|
|
1153
|
+
:expiration_date => "12/2015",
|
|
1154
|
+
:options => {
|
|
1155
|
+
:make_default => true
|
|
1156
|
+
}
|
|
1157
|
+
}
|
|
1158
|
+
)
|
|
1159
|
+
|
|
1160
|
+
paypal_account_token = "PAYPAL_ACCOUNT_TOKEN_#{rand(36**3).to_s(36)}"
|
|
1161
|
+
nonce = nonce_for_paypal_account(
|
|
1162
|
+
:consent_code => "PAYPAL_CONSENT_CODE",
|
|
1163
|
+
:token => paypal_account_token,
|
|
1164
|
+
:options => {
|
|
1165
|
+
:make_default => true
|
|
1166
|
+
}
|
|
1167
|
+
)
|
|
1168
|
+
|
|
1169
|
+
result = Braintree::Customer.update(
|
|
1170
|
+
customer.id,
|
|
1171
|
+
:payment_method_nonce => nonce
|
|
1172
|
+
)
|
|
1173
|
+
|
|
1174
|
+
result.should be_success
|
|
1175
|
+
result.customer.default_payment_method.token.should == paypal_account_token
|
|
1176
|
+
end
|
|
1177
|
+
end
|
|
1178
|
+
|
|
1179
|
+
context "onetime" do
|
|
1180
|
+
it "does not create a customer with a onetime paypal account" do
|
|
1181
|
+
result = Braintree::Customer.create(
|
|
1182
|
+
:payment_method_nonce => Braintree::Test::Nonce::PayPalOneTimePayment
|
|
1183
|
+
)
|
|
1184
|
+
|
|
1185
|
+
result.should_not be_success
|
|
1186
|
+
end
|
|
1187
|
+
|
|
1188
|
+
it "does not update a customer with a onetime paypal account" do
|
|
1189
|
+
credit_card_token = rand(36**3).to_s(36)
|
|
1190
|
+
customer = Braintree::Customer.create!(
|
|
1191
|
+
:credit_card => {
|
|
1192
|
+
:token => credit_card_token,
|
|
1193
|
+
:number => Braintree::Test::CreditCardNumbers::Visa,
|
|
1194
|
+
:expiration_date => "12/2015",
|
|
1195
|
+
:options => {
|
|
1196
|
+
:make_default => true
|
|
1197
|
+
}
|
|
1198
|
+
}
|
|
1199
|
+
)
|
|
1200
|
+
|
|
1201
|
+
paypal_account_token = "PAYPAL_ACCOUNT_TOKEN_#{rand(36**3).to_s(36)}"
|
|
1202
|
+
nonce = nonce_for_paypal_account(
|
|
1203
|
+
:access_token => "PAYPAL_ACCESS_TOKEN",
|
|
1204
|
+
:token => paypal_account_token,
|
|
1205
|
+
:options => {
|
|
1206
|
+
:make_default => true
|
|
1207
|
+
}
|
|
1208
|
+
)
|
|
1209
|
+
|
|
1210
|
+
result = Braintree::Customer.update(
|
|
1211
|
+
customer.id,
|
|
1212
|
+
:payment_method_nonce => nonce
|
|
1213
|
+
)
|
|
1214
|
+
|
|
1215
|
+
result.should_not be_success
|
|
1216
|
+
customer.default_payment_method.token.should == credit_card_token
|
|
1217
|
+
end
|
|
1218
|
+
end
|
|
1219
|
+
end
|
|
1138
1220
|
end
|
|
@@ -0,0 +1,315 @@
|
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + "/../spec_helper")
|
|
2
|
+
require File.expand_path(File.dirname(__FILE__) + "/client_api/spec_helper")
|
|
3
|
+
|
|
4
|
+
describe Braintree::PaymentMethod do
|
|
5
|
+
describe "self.create" do
|
|
6
|
+
it "creates a payment method from a vaulted credit card nonce" do
|
|
7
|
+
config = Braintree::Configuration.instantiate
|
|
8
|
+
customer = Braintree::Customer.create.customer
|
|
9
|
+
raw_client_token = Braintree::ClientToken.generate(:customer_id => customer.id)
|
|
10
|
+
client_token = decode_client_token(raw_client_token)
|
|
11
|
+
authorization_fingerprint = client_token["authorizationFingerprint"]
|
|
12
|
+
http = ClientApiHttp.new(
|
|
13
|
+
config,
|
|
14
|
+
:authorization_fingerprint => authorization_fingerprint,
|
|
15
|
+
:shared_customer_identifier => "fake_identifier",
|
|
16
|
+
:shared_customer_identifier_type => "testing"
|
|
17
|
+
)
|
|
18
|
+
|
|
19
|
+
response = http.create_credit_card(
|
|
20
|
+
:number => 4111111111111111,
|
|
21
|
+
:expirationMonth => 12,
|
|
22
|
+
:expirationYear => 2020
|
|
23
|
+
)
|
|
24
|
+
response.code.should == "201"
|
|
25
|
+
|
|
26
|
+
nonce = JSON.parse(response.body)["creditCards"].first["nonce"]
|
|
27
|
+
result = Braintree::PaymentMethod.create(
|
|
28
|
+
:payment_method_nonce => nonce,
|
|
29
|
+
:customer_id => customer.id
|
|
30
|
+
)
|
|
31
|
+
|
|
32
|
+
result.should be_success
|
|
33
|
+
result.payment_method.should be_a(Braintree::CreditCard)
|
|
34
|
+
token = result.payment_method.token
|
|
35
|
+
|
|
36
|
+
found_credit_card = Braintree::CreditCard.find(token)
|
|
37
|
+
found_credit_card.should_not be_nil
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
it "creates a payment method from an unvalidated credit card nonce" do
|
|
41
|
+
config = Braintree::Configuration.instantiate
|
|
42
|
+
customer = Braintree::Customer.create.customer
|
|
43
|
+
raw_client_token = Braintree::ClientToken.generate(:customer_id => customer.id)
|
|
44
|
+
client_token = decode_client_token(raw_client_token)
|
|
45
|
+
authorization_fingerprint = client_token["authorizationFingerprint"]
|
|
46
|
+
http = ClientApiHttp.new(
|
|
47
|
+
config,
|
|
48
|
+
:authorization_fingerprint => authorization_fingerprint,
|
|
49
|
+
:shared_customer_identifier => "fake_identifier",
|
|
50
|
+
:shared_customer_identifier_type => "testing"
|
|
51
|
+
)
|
|
52
|
+
|
|
53
|
+
response = http.create_credit_card(
|
|
54
|
+
:number => "4111111111111111",
|
|
55
|
+
:expirationMonth => "12",
|
|
56
|
+
:expirationYear => "2020",
|
|
57
|
+
:options => {:validate => false}
|
|
58
|
+
)
|
|
59
|
+
response.code.should == "202"
|
|
60
|
+
|
|
61
|
+
nonce = JSON.parse(response.body)["creditCards"].first["nonce"]
|
|
62
|
+
result = Braintree::PaymentMethod.create(
|
|
63
|
+
:payment_method_nonce => nonce,
|
|
64
|
+
:customer_id => customer.id
|
|
65
|
+
)
|
|
66
|
+
|
|
67
|
+
result.should be_success
|
|
68
|
+
result.payment_method.should be_a(Braintree::CreditCard)
|
|
69
|
+
token = result.payment_method.token
|
|
70
|
+
|
|
71
|
+
found_credit_card = Braintree::CreditCard.find(token)
|
|
72
|
+
found_credit_card.should_not be_nil
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
it "allows passing the make_default option alongside the nonce" do
|
|
76
|
+
customer = Braintree::Customer.create!
|
|
77
|
+
result = Braintree::CreditCard.create(
|
|
78
|
+
:customer_id => customer.id,
|
|
79
|
+
:number => Braintree::Test::CreditCardNumbers::Visa,
|
|
80
|
+
:expiration_date => "05/2009",
|
|
81
|
+
:cvv => "100"
|
|
82
|
+
)
|
|
83
|
+
result.success?.should == true
|
|
84
|
+
original_payment_method = result.credit_card
|
|
85
|
+
original_payment_method.should be_default
|
|
86
|
+
|
|
87
|
+
nonce = nonce_for_paypal_account(:consent_code => "PAYPAL_CONSENT_CODE")
|
|
88
|
+
result = Braintree::PaymentMethod.create(
|
|
89
|
+
:payment_method_nonce => nonce,
|
|
90
|
+
:customer_id => customer.id,
|
|
91
|
+
:options => {:make_default => true}
|
|
92
|
+
)
|
|
93
|
+
|
|
94
|
+
result.should be_success
|
|
95
|
+
new_payment_method = result.payment_method
|
|
96
|
+
new_payment_method.should be_default
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
it "overrides the token in the nonce" do
|
|
100
|
+
customer = Braintree::Customer.create!
|
|
101
|
+
|
|
102
|
+
first_token = "FIRST_TOKEN_#{rand(36**3).to_s(36)}"
|
|
103
|
+
second_token = "SECOND_TOKEN_#{rand(36**3).to_s(36)}"
|
|
104
|
+
nonce = nonce_for_paypal_account(
|
|
105
|
+
:consent_code => "PAYPAL_CONSENT_CODE",
|
|
106
|
+
:token => first_token
|
|
107
|
+
)
|
|
108
|
+
result = Braintree::PaymentMethod.create(
|
|
109
|
+
:payment_method_nonce => nonce,
|
|
110
|
+
:customer_id => customer.id,
|
|
111
|
+
:token => second_token
|
|
112
|
+
)
|
|
113
|
+
|
|
114
|
+
result.should be_success
|
|
115
|
+
payment_method = result.payment_method
|
|
116
|
+
payment_method.token.should == second_token
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
context "paypal" do
|
|
120
|
+
it "creates a payment method from an unvalidated future paypal account nonce" do
|
|
121
|
+
nonce = nonce_for_paypal_account(:consent_code => "PAYPAL_CONSENT_CODE")
|
|
122
|
+
customer = Braintree::Customer.create.customer
|
|
123
|
+
result = Braintree::PaymentMethod.create(
|
|
124
|
+
:payment_method_nonce => nonce,
|
|
125
|
+
:customer_id => customer.id
|
|
126
|
+
)
|
|
127
|
+
|
|
128
|
+
result.should be_success
|
|
129
|
+
result.payment_method.should be_a(Braintree::PayPalAccount)
|
|
130
|
+
result.payment_method.image_url.should_not be_nil
|
|
131
|
+
token = result.payment_method.token
|
|
132
|
+
|
|
133
|
+
found_paypal_account = Braintree::PayPalAccount.find(token)
|
|
134
|
+
found_paypal_account.should_not be_nil
|
|
135
|
+
end
|
|
136
|
+
|
|
137
|
+
it "does not create a payment method from an unvalidated onetime paypal account nonce" do
|
|
138
|
+
customer = Braintree::Customer.create.customer
|
|
139
|
+
nonce = nonce_for_paypal_account(:access_token => "PAYPAL_ACCESS_TOKEN")
|
|
140
|
+
result = Braintree::PaymentMethod.create(
|
|
141
|
+
:payment_method_nonce => nonce,
|
|
142
|
+
:customer_id => customer.id
|
|
143
|
+
)
|
|
144
|
+
|
|
145
|
+
result.should_not be_success
|
|
146
|
+
result.errors.first.code.should == "82902"
|
|
147
|
+
end
|
|
148
|
+
|
|
149
|
+
it "returns appropriate validation errors" do
|
|
150
|
+
customer = Braintree::Customer.create.customer
|
|
151
|
+
nonce = nonce_for_paypal_account(:token => "PAYPAL_TOKEN")
|
|
152
|
+
result = Braintree::PaymentMethod.create(
|
|
153
|
+
:payment_method_nonce => nonce,
|
|
154
|
+
:customer_id => customer.id
|
|
155
|
+
)
|
|
156
|
+
|
|
157
|
+
result.should_not be_success
|
|
158
|
+
errors = result.errors.map(&:code)
|
|
159
|
+
errors.should include("82901")
|
|
160
|
+
errors.should include("82902")
|
|
161
|
+
end
|
|
162
|
+
end
|
|
163
|
+
|
|
164
|
+
context "SEPA" do
|
|
165
|
+
it "returns the SEPA bank account behind the nonce" do
|
|
166
|
+
config = Braintree::Configuration.instantiate
|
|
167
|
+
customer = Braintree::Customer.create.customer
|
|
168
|
+
raw_client_token = Braintree::ClientToken.generate(:customer_id => customer.id, :sepa_mandate_type => Braintree::SEPABankAccount::MandateType::Business)
|
|
169
|
+
client_token = decode_client_token(raw_client_token)
|
|
170
|
+
authorization_fingerprint = client_token["authorizationFingerprint"]
|
|
171
|
+
http = ClientApiHttp.new(
|
|
172
|
+
config,
|
|
173
|
+
:authorization_fingerprint => authorization_fingerprint
|
|
174
|
+
)
|
|
175
|
+
|
|
176
|
+
nonce = http.create_sepa_bank_account_nonce(
|
|
177
|
+
:accountHolderName => "Bob Holder",
|
|
178
|
+
:iban => "DE89370400440532013000",
|
|
179
|
+
:bic => "DEUTDEFF",
|
|
180
|
+
:locale => "en-US",
|
|
181
|
+
:billingAddress => {
|
|
182
|
+
:region => "Hesse",
|
|
183
|
+
:country_name => "Germany"
|
|
184
|
+
}
|
|
185
|
+
)
|
|
186
|
+
nonce.should_not == nil
|
|
187
|
+
result = Braintree::PaymentMethod.create(
|
|
188
|
+
:payment_method_nonce => nonce,
|
|
189
|
+
:customer_id => customer.id
|
|
190
|
+
)
|
|
191
|
+
|
|
192
|
+
result.should be_success
|
|
193
|
+
result.payment_method.token.should_not == nil
|
|
194
|
+
result.payment_method.image_url.should_not be_nil
|
|
195
|
+
end
|
|
196
|
+
end
|
|
197
|
+
end
|
|
198
|
+
|
|
199
|
+
describe "self.find" do
|
|
200
|
+
context "credit cards" do
|
|
201
|
+
it "finds the payment method with the given token" do
|
|
202
|
+
customer = Braintree::Customer.create.customer
|
|
203
|
+
result = Braintree::CreditCard.create(
|
|
204
|
+
:customer_id => customer.id,
|
|
205
|
+
:number => Braintree::Test::CreditCardNumbers::Visa,
|
|
206
|
+
:expiration_date => "05/2012"
|
|
207
|
+
)
|
|
208
|
+
result.success?.should == true
|
|
209
|
+
|
|
210
|
+
credit_card = Braintree::PaymentMethod.find(result.credit_card.token)
|
|
211
|
+
credit_card.bin.should == Braintree::Test::CreditCardNumbers::Visa[0, 6]
|
|
212
|
+
credit_card.last_4.should == Braintree::Test::CreditCardNumbers::Visa[-4..-1]
|
|
213
|
+
credit_card.token.should == result.credit_card.token
|
|
214
|
+
credit_card.expiration_date.should == "05/2012"
|
|
215
|
+
end
|
|
216
|
+
|
|
217
|
+
it "returns associated subscriptions with the credit card" do
|
|
218
|
+
customer = Braintree::Customer.create.customer
|
|
219
|
+
credit_card = Braintree::CreditCard.create(
|
|
220
|
+
:customer_id => customer.id,
|
|
221
|
+
:number => Braintree::Test::CreditCardNumbers::Visa,
|
|
222
|
+
:expiration_date => "05/2012"
|
|
223
|
+
).credit_card
|
|
224
|
+
|
|
225
|
+
subscription = Braintree::Subscription.create(
|
|
226
|
+
:payment_method_token => credit_card.token,
|
|
227
|
+
:plan_id => "integration_trialless_plan",
|
|
228
|
+
:price => "1.00"
|
|
229
|
+
).subscription
|
|
230
|
+
|
|
231
|
+
found_card = Braintree::PaymentMethod.find(credit_card.token)
|
|
232
|
+
found_card.subscriptions.first.id.should == subscription.id
|
|
233
|
+
found_card.subscriptions.first.plan_id.should == "integration_trialless_plan"
|
|
234
|
+
found_card.subscriptions.first.payment_method_token.should == credit_card.token
|
|
235
|
+
found_card.subscriptions.first.price.should == BigDecimal.new("1.00")
|
|
236
|
+
end
|
|
237
|
+
end
|
|
238
|
+
|
|
239
|
+
context "paypal accounts" do
|
|
240
|
+
it "finds the payment method with the given token" do
|
|
241
|
+
customer = Braintree::Customer.create!
|
|
242
|
+
payment_method_token = "PAYMENT_METHOD_TOKEN_#{rand(36**3).to_s(36)}"
|
|
243
|
+
nonce = nonce_for_paypal_account(
|
|
244
|
+
:consent_code => "consent-code",
|
|
245
|
+
:token => payment_method_token
|
|
246
|
+
)
|
|
247
|
+
result = Braintree::PaymentMethod.create(
|
|
248
|
+
:payment_method_nonce => nonce,
|
|
249
|
+
:customer_id => customer.id
|
|
250
|
+
)
|
|
251
|
+
result.should be_success
|
|
252
|
+
|
|
253
|
+
paypal_account = Braintree::PaymentMethod.find(payment_method_token)
|
|
254
|
+
paypal_account.should be_a(Braintree::PayPalAccount)
|
|
255
|
+
paypal_account.token.should == payment_method_token
|
|
256
|
+
paypal_account.email.should == "jane.doe@example.com"
|
|
257
|
+
end
|
|
258
|
+
end
|
|
259
|
+
|
|
260
|
+
it "raises a NotFoundError exception if payment method cannot be found" do
|
|
261
|
+
expect do
|
|
262
|
+
Braintree::PaymentMethod.find("invalid-token")
|
|
263
|
+
end.to raise_error(Braintree::NotFoundError, 'payment method with token "invalid-token" not found')
|
|
264
|
+
end
|
|
265
|
+
end
|
|
266
|
+
|
|
267
|
+
describe "self.delete" do
|
|
268
|
+
it "deletes a paypal account" do
|
|
269
|
+
customer = Braintree::Customer.create!
|
|
270
|
+
paypal_account_token = "PAYPAL_ACCOUNT_TOKEN_#{rand(36**3).to_s(36)}"
|
|
271
|
+
nonce = nonce_for_paypal_account(
|
|
272
|
+
:consent_code => "PAYPAL_CONSENT_CODE",
|
|
273
|
+
:token => paypal_account_token
|
|
274
|
+
)
|
|
275
|
+
Braintree::PaymentMethod.create(
|
|
276
|
+
:payment_method_nonce => nonce,
|
|
277
|
+
:customer_id => customer.id
|
|
278
|
+
)
|
|
279
|
+
|
|
280
|
+
paypal_account = Braintree::PaymentMethod.find(paypal_account_token)
|
|
281
|
+
paypal_account.should be_a(Braintree::PayPalAccount)
|
|
282
|
+
|
|
283
|
+
result = Braintree::PaymentMethod.delete(paypal_account_token)
|
|
284
|
+
|
|
285
|
+
expect do
|
|
286
|
+
Braintree::PaymentMethod.find(paypal_account_token)
|
|
287
|
+
end.to raise_error(Braintree::NotFoundError, "payment method with token \"#{paypal_account_token}\" not found")
|
|
288
|
+
end
|
|
289
|
+
|
|
290
|
+
it "deletes a credit card" do
|
|
291
|
+
token = "CREDIT_CARD_#{rand(36**3).to_s(36)}"
|
|
292
|
+
customer = Braintree::Customer.create!
|
|
293
|
+
nonce = nonce_for_new_payment_method({
|
|
294
|
+
:credit_card => {
|
|
295
|
+
:number => "4111111111111111",
|
|
296
|
+
:expiration_month => "11",
|
|
297
|
+
:expiration_year => "2099",
|
|
298
|
+
:token => token
|
|
299
|
+
},
|
|
300
|
+
:client_token_options => {:customer_id => customer.id}
|
|
301
|
+
})
|
|
302
|
+
|
|
303
|
+
Braintree::PaymentMethod.create(
|
|
304
|
+
:payment_method_nonce => nonce,
|
|
305
|
+
:customer_id => customer.id
|
|
306
|
+
)
|
|
307
|
+
|
|
308
|
+
Braintree::PaymentMethod.delete(token)
|
|
309
|
+
|
|
310
|
+
expect do
|
|
311
|
+
Braintree::PaymentMethod.find(token)
|
|
312
|
+
end.to raise_error(Braintree::NotFoundError, "payment method with token \"#{token}\" not found")
|
|
313
|
+
end
|
|
314
|
+
end
|
|
315
|
+
end
|