braintree 2.76.0 → 2.77.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (45) hide show
  1. checksums.yaml +4 -4
  2. data/lib/braintree.rb +12 -0
  3. data/lib/braintree/apple_pay.rb +29 -0
  4. data/lib/braintree/apple_pay_card.rb +1 -1
  5. data/lib/braintree/apple_pay_gateway.rb +37 -0
  6. data/lib/braintree/apple_pay_options.rb +19 -0
  7. data/lib/braintree/authorization_adjustment.rb +20 -0
  8. data/lib/braintree/dispute.rb +78 -9
  9. data/lib/braintree/dispute/evidence.rb +18 -0
  10. data/lib/braintree/dispute/history_event.rb +14 -0
  11. data/lib/braintree/dispute/transaction.rb +18 -0
  12. data/lib/braintree/dispute_gateway.rb +118 -0
  13. data/lib/braintree/dispute_search.rb +30 -0
  14. data/lib/braintree/document_upload.rb +34 -0
  15. data/lib/braintree/document_upload_gateway.rb +32 -0
  16. data/lib/braintree/error_codes.rb +17 -0
  17. data/lib/braintree/facilitated_details.rb +19 -0
  18. data/lib/braintree/gateway.rb +12 -0
  19. data/lib/braintree/http.rb +60 -12
  20. data/lib/braintree/successful_result.rb +1 -1
  21. data/lib/braintree/test/credit_card.rb +6 -0
  22. data/lib/braintree/transaction.rb +4 -0
  23. data/lib/braintree/version.rb +1 -1
  24. data/lib/braintree/webhook_testing_gateway.rb +196 -19
  25. data/spec/fixtures/files/bt_logo.png +0 -0
  26. data/spec/fixtures/files/gif_extension_bt_logo.gif +0 -0
  27. data/spec/fixtures/files/malformed_pdf.pdf +1 -0
  28. data/spec/httpsd.pid +1 -1
  29. data/spec/integration/braintree/apple_pay_spec.rb +92 -0
  30. data/spec/integration/braintree/coinbase_spec.rb +15 -12
  31. data/spec/integration/braintree/dispute_search_spec.rb +49 -0
  32. data/spec/integration/braintree/dispute_spec.rb +216 -0
  33. data/spec/integration/braintree/document_upload_spec.rb +55 -0
  34. data/spec/integration/braintree/http_spec.rb +8 -0
  35. data/spec/integration/braintree/payment_method_spec.rb +5 -16
  36. data/spec/integration/braintree/transaction_spec.rb +21 -4
  37. data/spec/spec_helper.rb +3 -2
  38. data/spec/unit/braintree/apple_pay_card_spec.rb +6 -0
  39. data/spec/unit/braintree/dispute_search_spec.rb +59 -0
  40. data/spec/unit/braintree/dispute_spec.rb +331 -8
  41. data/spec/unit/braintree/document_upload_spec.rb +35 -0
  42. data/spec/unit/braintree/http_spec.rb +21 -0
  43. data/spec/unit/braintree/transaction_spec.rb +17 -0
  44. data/spec/unit/braintree/webhook_notification_spec.rb +74 -51
  45. metadata +24 -3
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: f42a6a1794be0f659dc3cea9f5e84bff6e1d4e75
4
- data.tar.gz: efdb9c09c2b5961fc4358af6f7d397ac4a304c53
3
+ metadata.gz: f91adc9f9c4c198e0a23a83d154ed5dec5c1a90e
4
+ data.tar.gz: fe219448f54a560983e11cd15062abe6c89da036
5
5
  SHA512:
6
- metadata.gz: aaea5122d23bf61d943af46e50bd768b70efcfb2aede98c857e2ae36c84851b9871dffccafbfadeafca384101ec0b9dee2a5d69bd7ec3c664228836a5ef2da0d
7
- data.tar.gz: e10e87bb06504b7119ff25ae558422a12d6ff88f614580a30af194eb8985b9b6655fb94b3c5fe8d65d5be8d96ccb3fead07214a73e2c3ec289fc09946c4cf7df
6
+ metadata.gz: d337708211ff819d6db66faa86e5b60a06bf8e539de8df21b5f38cff8dfbd941908c628155dbbb69b63b13ad25d778dfae72f876e4fcbe97afd8c665c5901bff
7
+ data.tar.gz: fcdeb5b27036b32e6c3f0380e4885ef38640ed94d0e8486b624cf7908dd33a8c12dbcc0082a1c3456fc03ab2df90b4ee2d6b117fbb81e74bdd61fc4bcabebbcf
@@ -30,7 +30,11 @@ require "braintree/address_gateway"
30
30
  require "braintree/advanced_search"
31
31
  require "braintree/android_pay_card"
32
32
  require "braintree/amex_express_checkout_card"
33
+ require "braintree/apple_pay"
33
34
  require "braintree/apple_pay_card"
35
+ require "braintree/apple_pay_gateway"
36
+ require "braintree/apple_pay_options"
37
+ require "braintree/authorization_adjustment"
34
38
  require "braintree/client_token"
35
39
  require "braintree/client_token_gateway"
36
40
  require "braintree/coinbase_account"
@@ -51,7 +55,13 @@ require "braintree/digest"
51
55
  require "braintree/discount"
52
56
  require "braintree/discount_gateway"
53
57
  require "braintree/dispute"
58
+ require "braintree/dispute_gateway"
59
+ require "braintree/dispute/evidence"
60
+ require "braintree/dispute/history_event"
61
+ require "braintree/dispute/transaction"
54
62
  require "braintree/dispute/transaction_details"
63
+ require "braintree/document_upload"
64
+ require "braintree/document_upload_gateway"
55
65
  require "braintree/error_codes"
56
66
  require "braintree/error_result"
57
67
  require "braintree/errors"
@@ -80,6 +90,7 @@ require "braintree/paypal_account_gateway"
80
90
  require "braintree/plan"
81
91
  require "braintree/plan_gateway"
82
92
  require "braintree/risk_data"
93
+ require "braintree/facilitated_details"
83
94
  require "braintree/facilitator_details"
84
95
  require "braintree/three_d_secure_info"
85
96
  require "braintree/settlement_batch_summary"
@@ -125,6 +136,7 @@ require "braintree/transaction/visa_checkout_card_details"
125
136
  require "braintree/transaction/masterpass_card_details"
126
137
  require "braintree/unknown_payment_method"
127
138
  require "braintree/disbursement"
139
+ require "braintree/dispute_search"
128
140
  require "braintree/transparent_redirect"
129
141
  require "braintree/transparent_redirect_gateway"
130
142
  require "braintree/util"
@@ -0,0 +1,29 @@
1
+ module Braintree
2
+ class ApplePay
3
+ include BaseModule # :nodoc:
4
+
5
+ def initialize(gateway, attributes) # :nodoc:
6
+ set_instance_variables_from_hash(attributes)
7
+ end
8
+
9
+ class << self
10
+ protected :new
11
+ end
12
+
13
+ def self._new(*args) # :nodoc:
14
+ self.new *args
15
+ end
16
+
17
+ def self.register_domain(domain)
18
+ Configuration.gateway.apple_pay.register_domain(domain)
19
+ end
20
+
21
+ def self.unregister_domain(domain)
22
+ Configuration.gateway.apple_pay.unregister_domain(domain)
23
+ end
24
+
25
+ def self.registered_domains
26
+ Configuration.gateway.apple_pay.registered_domains
27
+ end
28
+ end
29
+ end
@@ -10,7 +10,7 @@ module Braintree
10
10
  All = constants.map { |c| const_get(c) }
11
11
  end
12
12
 
13
- attr_reader :card_type, :created_at, :customer_id, :default, :expiration_month,
13
+ attr_reader :bin, :card_type, :created_at, :customer_id, :default, :expiration_month,
14
14
  :expiration_year, :expired, :image_url, :last_4, :payment_instrument_name,
15
15
  :source_description, :subscriptions, :token, :updated_at
16
16
 
@@ -0,0 +1,37 @@
1
+ module Braintree
2
+ class ApplePayGateway
3
+ def initialize(gateway)
4
+ @gateway = gateway
5
+ @config = gateway.config
6
+ end
7
+
8
+ def register_domain(domain)
9
+ response = @config.http.post("#{@config.base_merchant_path}/processing/apple_pay/validate_domains", :url => domain)
10
+
11
+ if response.has_key?(:response) && response[:response][:success]
12
+ Braintree::SuccessfulResult.new
13
+ elsif response[:api_error_response]
14
+ ErrorResult.new(@gateway, response[:api_error_response])
15
+ else
16
+ raise "expected :response or :api_error_response"
17
+ end
18
+ end
19
+
20
+ def unregister_domain(domain)
21
+ @config.http.delete("#{@config.base_merchant_path}/processing/apple_pay/unregister_domain", :url => CGI.escape(domain))
22
+ SuccessfulResult.new
23
+ end
24
+
25
+ def registered_domains
26
+ response = @config.http.get("#{@config.base_merchant_path}/processing/apple_pay/registered_domains")
27
+
28
+ if response.has_key?(:response)
29
+ Braintree::SuccessfulResult.new(:apple_pay_options => ApplePayOptions._new(response[:response]))
30
+ elsif response[:api_error_response]
31
+ ErrorResult.new(@gateway, response[:api_error_response])
32
+ else
33
+ raise "expected :response or :api_error_response"
34
+ end
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,19 @@
1
+ module Braintree
2
+ class ApplePayOptions
3
+ include BaseModule # :nodoc:
4
+
5
+ attr_reader :domains
6
+
7
+ def initialize(attributes) # :nodoc:
8
+ set_instance_variables_from_hash(attributes)
9
+ end
10
+
11
+ class << self
12
+ protected :new
13
+ end
14
+
15
+ def self._new(*args) # :nodoc:
16
+ self.new *args
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,20 @@
1
+ module Braintree
2
+ class AuthorizationAdjustment # :nodoc:
3
+ include BaseModule
4
+
5
+ attr_reader :amount
6
+ attr_reader :success
7
+ attr_reader :timestamp
8
+
9
+ class << self
10
+ protected :new
11
+ def _new(*args) # :nodoc:
12
+ self.new *args
13
+ end
14
+ end
15
+
16
+ def initialize(attributes) # :nodoc:
17
+ set_instance_variables_from_hash(attributes)
18
+ end
19
+ end
20
+ end
@@ -3,21 +3,40 @@ module Braintree
3
3
  include BaseModule
4
4
 
5
5
  attr_reader :amount
6
+ attr_reader :amount_disputed
7
+ attr_reader :amount_won
8
+ attr_reader :case_number
9
+ attr_reader :created_at
10
+ attr_reader :currency_iso_code
11
+ attr_reader :date_opened
12
+ attr_reader :date_won
13
+ attr_reader :evidence
14
+ attr_reader :forwarded_comments
15
+ attr_reader :id
16
+ attr_reader :kind
17
+ attr_reader :merchant_account_id
18
+ attr_reader :original_dispute_id
19
+ attr_reader :reason
20
+ attr_reader :reason_code
21
+ attr_reader :reason_description
6
22
  attr_reader :received_date
23
+ attr_reader :reference_number
7
24
  attr_reader :reply_by_date
8
25
  attr_reader :status
9
- attr_reader :reason
10
- attr_reader :currency_iso_code
11
- attr_reader :id
26
+ attr_reader :status_history
27
+ attr_reader :transaction
12
28
  attr_reader :transaction_details
13
- attr_reader :kind
14
- attr_reader :date_opened
15
- attr_reader :date_won
29
+ attr_reader :updated_at
16
30
 
17
31
  module Status
32
+ Accepted = "accepted"
33
+ Disputed = "disputed"
34
+ Expired = "expired"
18
35
  Open = "open"
19
36
  Lost = "lost"
20
37
  Won = "won"
38
+
39
+ All = constants.map { |c| const_get(c) }
21
40
  end
22
41
 
23
42
  module Reason
@@ -32,12 +51,16 @@ module Braintree
32
51
  ProductUnsatisfactory = "product_unsatisfactory"
33
52
  TransactionAmountDiffers = "transaction_amount_differs"
34
53
  Retrieval = "retrieval"
54
+
55
+ All = constants.map { |c| const_get(c) }
35
56
  end
36
57
 
37
58
  module Kind
38
59
  Chargeback = "chargeback"
39
60
  PreArbitration = "pre_arbitration"
40
61
  Retrieval = "retrieval"
62
+
63
+ All = constants.map { |c| const_get(c) }
41
64
  end
42
65
 
43
66
  class << self
@@ -47,14 +70,60 @@ module Braintree
47
70
  end
48
71
  end
49
72
 
73
+ def self.accept(dispute_id)
74
+ Configuration.gateway.dispute.accept(dispute_id)
75
+ end
76
+
77
+ def self.add_file_evidence(dispute_id, document_upload_id)
78
+ Configuration.gateway.dispute.add_file_evidence(dispute_id, document_upload_id)
79
+ end
80
+
81
+ def self.add_text_evidence(dispute_id, content)
82
+ Configuration.gateway.dispute.add_text_evidence(dispute_id, content)
83
+ end
84
+
85
+ def self.finalize(dispute_id)
86
+ Configuration.gateway.dispute.finalize(dispute_id)
87
+ end
88
+
89
+ def self.find(dispute_id)
90
+ Configuration.gateway.dispute.find(dispute_id)
91
+ end
92
+
93
+ def self.remove_evidence(dispute_id, evidence_id)
94
+ Configuration.gateway.dispute.remove_evidence(dispute_id, evidence_id)
95
+ end
96
+
97
+ def self.search(&block)
98
+ Configuration.gateway.dispute.search(&block)
99
+ end
100
+
50
101
  def initialize(attributes) # :nodoc:
51
102
  set_instance_variables_from_hash(attributes)
103
+ @date_opened = Date.parse(date_opened) unless date_opened.nil?
104
+ @date_won = Date.parse(date_won) unless date_won.nil?
52
105
  @received_date = Date.parse(received_date)
53
106
  @reply_by_date = Date.parse(reply_by_date) unless reply_by_date.nil?
54
107
  @amount = Util.to_big_decimal(amount)
55
- @transaction_details = TransactionDetails.new(@transaction)
56
- @date_opened = Date.parse(date_opened) unless date_opened.nil?
57
- @date_won = Date.parse(date_won) unless date_won.nil?
108
+ @amount_disputed = Util.to_big_decimal(amount_disputed)
109
+ @amount_won = Util.to_big_decimal(amount_won)
110
+
111
+ @evidence = evidence.map do |record|
112
+ Braintree::Dispute::Evidence.new(record)
113
+ end unless evidence.nil?
114
+
115
+ @transaction_details = TransactionDetails.new(transaction)
116
+ @transaction = Transaction.new(transaction)
117
+
118
+ @status_history = status_history.map do |event|
119
+ Braintree::Dispute::HistoryEvent.new(event)
120
+ end unless status_history.nil?
121
+ end
122
+
123
+ # Returns true if +other+ is a Dispute with the same id
124
+ def ==(other)
125
+ return false unless other.is_a?(Dispute)
126
+ id == other.id
58
127
  end
59
128
  end
60
129
  end
@@ -0,0 +1,18 @@
1
+ module Braintree
2
+ class Dispute
3
+ class Evidence # :nodoc:
4
+ include BaseModule
5
+
6
+ attr_reader :comment
7
+ attr_reader :created_at
8
+ attr_reader :id
9
+ attr_reader :sent_to_processor_at
10
+ attr_reader :url
11
+
12
+ def initialize(attributes)
13
+ set_instance_variables_from_hash attributes unless attributes.nil?
14
+ @sent_to_processor_at = Date.parse(sent_to_processor_at) unless sent_to_processor_at.nil?
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,14 @@
1
+ module Braintree
2
+ class Dispute
3
+ class HistoryEvent # :nodoc:
4
+ include BaseModule
5
+
6
+ attr_reader :status
7
+ attr_reader :timestamp
8
+
9
+ def initialize(attributes)
10
+ set_instance_variables_from_hash attributes unless attributes.nil?
11
+ end
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,18 @@
1
+ module Braintree
2
+ class Dispute
3
+ class Transaction # :nodoc:
4
+ include BaseModule
5
+
6
+ attr_reader :amount
7
+ attr_reader :id
8
+ attr_reader :order_id
9
+ attr_reader :purchase_order_number
10
+ attr_reader :payment_instrument_subtype
11
+
12
+ def initialize(attributes)
13
+ set_instance_variables_from_hash attributes unless attributes.nil?
14
+ @amount = Util.to_big_decimal(amount)
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,118 @@
1
+ module Braintree
2
+ class DisputeGateway # :nodoc:
3
+ def initialize(gateway)
4
+ @gateway = gateway
5
+ @config = gateway.config
6
+ @config.assert_has_access_token_or_keys
7
+ end
8
+
9
+ def accept(dispute_id)
10
+ raise ArgumentError, "dispute_id contains invalid characters" unless dispute_id.to_s =~ /\A[\w-]+\z/
11
+ raise ArgumentError, "dispute_id cannot be blank" if dispute_id.nil? || dispute_id.to_s.strip == ""
12
+
13
+ response = @config.http.put("#{@config.base_merchant_path}/disputes/#{dispute_id}/accept")
14
+ if response[:api_error_response]
15
+ ErrorResult.new(@gateway, response[:api_error_response])
16
+ else
17
+ SuccessfulResult.new
18
+ end
19
+ rescue NotFoundError
20
+ raise NotFoundError, "dispute with id #{dispute_id} not found"
21
+ end
22
+
23
+ def add_file_evidence(dispute_id, document_upload_id)
24
+ raise ArgumentError, "dispute_id contains invalid characters" unless dispute_id.to_s =~ /\A[\w-]+\z/
25
+ raise ArgumentError, "dispute_id cannot be blank" if dispute_id.nil? || dispute_id.to_s.strip == ""
26
+ raise ArgumentError, "document_upload_id contains invalid characters" unless document_upload_id.to_s =~ /\A[\w-]+\z/
27
+ raise ArgumentError, "document_upload_id cannot be blank" if document_upload_id.nil? || dispute_id.to_s.strip == ""
28
+
29
+ params = {document_upload_id: document_upload_id}
30
+ response = @config.http.post("#{@config.base_merchant_path}/disputes/#{dispute_id}/evidence", params)
31
+
32
+ if response[:evidence]
33
+ SuccessfulResult.new(:evidence => Dispute::Evidence.new(response[:evidence]))
34
+ elsif response[:api_error_response]
35
+ ErrorResult.new(@gateway, response[:api_error_response])
36
+ else
37
+ raise "expected :evidence or :api_error_response"
38
+ end
39
+ rescue NotFoundError
40
+ raise NotFoundError, "dispute with id #{dispute_id} not found"
41
+ end
42
+
43
+ def add_text_evidence(dispute_id, content)
44
+ raise ArgumentError, "dispute_id contains invalid characters" unless dispute_id.to_s =~ /\A[\w-]+\z/
45
+ raise ArgumentError, "dispute_id cannot be blank" if dispute_id.nil? || dispute_id.to_s.strip == ""
46
+ raise ArgumentError, "content cannot be blank" if content.nil? || content.to_s.strip == ""
47
+
48
+ params = {comments: content}
49
+ response = @config.http.post("#{@config.base_merchant_path}/disputes/#{dispute_id}/evidence", params)
50
+
51
+ if response[:evidence]
52
+ SuccessfulResult.new(:evidence => Dispute::Evidence.new(response[:evidence]))
53
+ elsif response[:api_error_response]
54
+ ErrorResult.new(@gateway, response[:api_error_response])
55
+ else
56
+ raise "expected :evidence or :api_error_response"
57
+ end
58
+ rescue NotFoundError
59
+ raise NotFoundError, "dispute with id #{dispute_id} not found"
60
+ end
61
+
62
+ def finalize(dispute_id)
63
+ raise ArgumentError, "dispute_id contains invalid characters" unless dispute_id.to_s =~ /\A[\w-]+\z/
64
+ raise ArgumentError, "dispute_id cannot be blank" if dispute_id.nil? || dispute_id.to_s.strip == ""
65
+
66
+ response = @config.http.put("#{@config.base_merchant_path}/disputes/#{dispute_id}/finalize")
67
+ if response[:api_error_response]
68
+ ErrorResult.new(@gateway, response[:api_error_response])
69
+ else
70
+ SuccessfulResult.new
71
+ end
72
+ rescue NotFoundError
73
+ raise NotFoundError, "dispute with id #{dispute_id} not found"
74
+ end
75
+
76
+ def find(dispute_id)
77
+ raise ArgumentError, "dispute_id contains invalid characters" unless dispute_id.to_s =~ /\A[\w-]+\z/
78
+ raise ArgumentError, "dispute_id cannot be blank" if dispute_id.nil? || dispute_id.to_s.strip == ""
79
+ response = @config.http.get("#{@config.base_merchant_path}/disputes/#{dispute_id}")
80
+ Dispute._new(response[:dispute])
81
+ rescue NotFoundError
82
+ raise NotFoundError, "dispute with id #{dispute_id} not found"
83
+ end
84
+
85
+ def remove_evidence(dispute_id, evidence_id)
86
+ raise ArgumentError, "dispute_id contains invalid characters" unless dispute_id.to_s =~ /\A[\w-]+\z/
87
+ raise ArgumentError, "dispute_id cannot be blank" if dispute_id.nil? || dispute_id.to_s.strip == ""
88
+ raise ArgumentError, "evidence_id contains invalid characters" unless evidence_id.to_s =~ /\A[\w-]+\z/
89
+ raise ArgumentError, "evidence_id cannot be blank" if evidence_id.nil? || evidence_id.to_s.strip == ""
90
+
91
+ response = @config.http.delete("#{@config.base_merchant_path}/disputes/#{dispute_id}/evidence/#{evidence_id}")
92
+
93
+ if response.respond_to?(:to_hash) && response[:api_error_response]
94
+ ErrorResult.new(@gateway, response[:api_error_response])
95
+ else
96
+ SuccessfulResult.new
97
+ end
98
+ rescue NotFoundError
99
+ raise NotFoundError, "evidence with id #{evidence_id} for dispute with id #{dispute_id} not found"
100
+ end
101
+
102
+ def search(&block)
103
+ search = DisputeSearch.new
104
+ block.call(search) if block
105
+
106
+ paginated_results = PaginatedCollection.new { |page| _fetch_disputes(search, page) }
107
+ SuccessfulResult.new(:disputes => paginated_results)
108
+ end
109
+
110
+ def _fetch_disputes(search, page)
111
+ response = @config.http.post("#{@config.base_merchant_path}/disputes/advanced_search?page=#{page}", {:search => search.to_hash, :page => page})
112
+ body = response[:disputes]
113
+ disputes = Util.extract_attribute_as_array(body, :dispute).map { |d| Dispute._new(d) }
114
+
115
+ PaginatedResult.new(body[:total_items], body[:page_size], disputes)
116
+ end
117
+ end
118
+ end