braintree 2.74.0 → 4.12.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (286) hide show
  1. checksums.yaml +5 -5
  2. data/LICENSE +1 -1
  3. data/braintree.gemspec +13 -7
  4. data/lib/braintree/account_updater_daily_report.rb +2 -2
  5. data/lib/braintree/ach_mandate.rb +2 -1
  6. data/lib/braintree/address/country_names.rb +4 -1
  7. data/lib/braintree/address.rb +30 -38
  8. data/lib/braintree/address_gateway.rb +12 -2
  9. data/lib/braintree/advanced_search.rb +8 -0
  10. data/lib/braintree/apple_pay.rb +29 -0
  11. data/lib/braintree/apple_pay_card.rb +28 -4
  12. data/lib/braintree/apple_pay_gateway.rb +37 -0
  13. data/lib/braintree/apple_pay_options.rb +19 -0
  14. data/lib/braintree/authorization_adjustment.rb +23 -0
  15. data/lib/braintree/base_module.rb +10 -0
  16. data/lib/braintree/bin_data.rb +33 -0
  17. data/lib/braintree/client_token.rb +3 -3
  18. data/lib/braintree/client_token_gateway.rb +3 -1
  19. data/lib/braintree/configuration.rb +57 -10
  20. data/lib/braintree/connected_merchant_paypal_status_changed.rb +6 -2
  21. data/lib/braintree/connected_merchant_status_transitioned.rb +6 -2
  22. data/lib/braintree/credentials_parser.rb +5 -1
  23. data/lib/braintree/credit_card.rb +53 -107
  24. data/lib/braintree/credit_card_gateway.rb +43 -30
  25. data/lib/braintree/credit_card_verification.rb +61 -21
  26. data/lib/braintree/credit_card_verification_gateway.rb +19 -6
  27. data/lib/braintree/credit_card_verification_search.rb +1 -1
  28. data/lib/braintree/customer.rb +51 -98
  29. data/lib/braintree/customer_gateway.rb +30 -23
  30. data/lib/braintree/customer_search.rb +1 -1
  31. data/lib/braintree/descriptor.rb +3 -1
  32. data/lib/braintree/disbursement.rb +24 -2
  33. data/lib/braintree/dispute/evidence.rb +24 -0
  34. data/lib/braintree/{transaction/coinbase_details.rb → dispute/paypal_message.rb} +5 -3
  35. data/lib/braintree/dispute/status_history.rb +18 -0
  36. data/lib/braintree/dispute/transaction.rb +20 -0
  37. data/lib/braintree/dispute/transaction_details.rb +2 -1
  38. data/lib/braintree/dispute.rb +114 -10
  39. data/lib/braintree/dispute_gateway.rb +142 -0
  40. data/lib/braintree/dispute_search.rb +31 -0
  41. data/lib/braintree/document_upload.rb +37 -0
  42. data/lib/braintree/document_upload_gateway.rb +38 -0
  43. data/lib/braintree/enriched_customer_data.rb +21 -0
  44. data/lib/braintree/error_codes.rb +328 -109
  45. data/lib/braintree/error_result.rb +8 -1
  46. data/lib/braintree/exceptions.rb +5 -3
  47. data/lib/braintree/exchange_rate.rb +13 -0
  48. data/lib/braintree/exchange_rate_quote.rb +24 -0
  49. data/lib/braintree/exchange_rate_quote_gateway.rb +35 -0
  50. data/lib/braintree/exchange_rate_quote_input.rb +21 -0
  51. data/lib/braintree/exchange_rate_quote_request.rb +18 -0
  52. data/lib/braintree/exchange_rate_quote_response.rb +18 -0
  53. data/lib/braintree/facilitated_details.rb +21 -0
  54. data/lib/braintree/facilitator_details.rb +2 -1
  55. data/lib/braintree/gateway.rb +29 -11
  56. data/lib/braintree/google_pay_card.rb +61 -0
  57. data/lib/braintree/granted_payment_instrument_update.rb +23 -0
  58. data/lib/braintree/graphql_client.rb +34 -0
  59. data/lib/braintree/http.rb +81 -20
  60. data/lib/braintree/local_payment_completed.rb +23 -0
  61. data/lib/braintree/local_payment_expired.rb +21 -0
  62. data/lib/braintree/local_payment_funded.rb +22 -0
  63. data/lib/braintree/local_payment_reversed.rb +19 -0
  64. data/lib/braintree/merchant.rb +11 -4
  65. data/lib/braintree/merchant_account/address_details.rb +4 -1
  66. data/lib/braintree/merchant_account/business_details.rb +4 -1
  67. data/lib/braintree/merchant_account/funding_details.rb +6 -1
  68. data/lib/braintree/merchant_account/individual_details.rb +7 -2
  69. data/lib/braintree/merchant_account.rb +23 -10
  70. data/lib/braintree/merchant_account_gateway.rb +13 -1
  71. data/lib/braintree/merchant_gateway.rb +2 -2
  72. data/lib/braintree/modification.rb +1 -1
  73. data/lib/braintree/oauth_credentials.rb +5 -2
  74. data/lib/braintree/oauth_gateway.rb +8 -14
  75. data/lib/braintree/paginated_result.rb +3 -1
  76. data/lib/braintree/payment_instrument_type.rb +11 -11
  77. data/lib/braintree/payment_method.rb +20 -12
  78. data/lib/braintree/payment_method_customer_data_updated_metadata.rb +24 -0
  79. data/lib/braintree/payment_method_gateway.rb +82 -54
  80. data/lib/braintree/payment_method_nonce.rb +22 -8
  81. data/lib/braintree/payment_method_nonce_details.rb +40 -0
  82. data/lib/braintree/payment_method_nonce_details_payer_info.rb +32 -0
  83. data/lib/braintree/payment_method_nonce_gateway.rb +19 -2
  84. data/lib/braintree/payment_method_parser.rb +28 -0
  85. data/lib/braintree/paypal_account.rb +10 -1
  86. data/lib/braintree/plan.rb +25 -5
  87. data/lib/braintree/plan_gateway.rb +100 -0
  88. data/lib/braintree/processor_response_types.rb +7 -0
  89. data/lib/braintree/resource_collection.rb +8 -3
  90. data/lib/braintree/revoked_payment_method_metadata.rb +22 -0
  91. data/lib/braintree/risk_data/liability_shift.rb +22 -0
  92. data/lib/braintree/risk_data.rb +12 -2
  93. data/lib/braintree/samsung_pay_card.rb +83 -0
  94. data/lib/braintree/sepa_direct_debit_account.rb +60 -0
  95. data/lib/braintree/sepa_direct_debit_account_gateway.rb +25 -0
  96. data/lib/braintree/sepa_direct_debit_account_nonce_details.rb +28 -0
  97. data/lib/braintree/settlement_batch_summary.rb +2 -1
  98. data/lib/braintree/settlement_batch_summary_gateway.rb +2 -0
  99. data/lib/braintree/subscription/status_details.rb +8 -1
  100. data/lib/braintree/subscription.rb +56 -41
  101. data/lib/braintree/subscription_gateway.rb +25 -2
  102. data/lib/braintree/successful_result.rb +23 -1
  103. data/lib/braintree/test/authentication_id.rb +21 -0
  104. data/lib/braintree/test/credit_card.rb +13 -0
  105. data/lib/braintree/test/nonce.rb +28 -20
  106. data/lib/braintree/test/transaction_amounts.rb +1 -0
  107. data/lib/braintree/three_d_secure_info.rb +34 -2
  108. data/lib/braintree/transaction/address_details.rb +24 -4
  109. data/lib/braintree/transaction/apple_pay_details.rb +20 -2
  110. data/lib/braintree/transaction/credit_card_details.rb +45 -6
  111. data/lib/braintree/transaction/customer_details.rb +8 -1
  112. data/lib/braintree/transaction/disbursement_details.rb +6 -1
  113. data/lib/braintree/transaction/google_pay_details.rb +41 -0
  114. data/lib/braintree/transaction/installment/adjustment.rb +33 -0
  115. data/lib/braintree/transaction/installment.rb +28 -0
  116. data/lib/braintree/transaction/local_payment_details.rb +24 -0
  117. data/lib/braintree/transaction/paypal_details.rb +26 -4
  118. data/lib/braintree/transaction/paypal_here_details.rb +23 -0
  119. data/lib/braintree/transaction/{masterpass_card_details.rb → samsung_pay_card_details.rb} +21 -6
  120. data/lib/braintree/transaction/sepa_direct_debit_account_details.rb +27 -0
  121. data/lib/braintree/transaction/status_details.rb +5 -1
  122. data/lib/braintree/transaction/subscription_details.rb +4 -1
  123. data/lib/braintree/transaction/us_bank_account_details.rb +8 -1
  124. data/lib/braintree/transaction/venmo_account_details.rb +5 -1
  125. data/lib/braintree/transaction/visa_checkout_card_details.rb +19 -4
  126. data/lib/braintree/transaction.rb +201 -188
  127. data/lib/braintree/transaction_gateway.rb +124 -30
  128. data/lib/braintree/transaction_line_item.rb +40 -0
  129. data/lib/braintree/transaction_line_item_gateway.rb +19 -0
  130. data/lib/braintree/transaction_review.rb +18 -0
  131. data/lib/braintree/transaction_search.rb +6 -3
  132. data/lib/braintree/unknown_payment_method.rb +3 -2
  133. data/lib/braintree/us_bank_account.rb +24 -8
  134. data/lib/braintree/us_bank_account_gateway.rb +0 -1
  135. data/lib/braintree/us_bank_account_verification.rb +81 -0
  136. data/lib/braintree/us_bank_account_verification_gateway.rb +51 -0
  137. data/lib/braintree/us_bank_account_verification_search.rb +19 -0
  138. data/lib/braintree/util.rb +79 -9
  139. data/lib/braintree/validation_error.rb +13 -3
  140. data/lib/braintree/validation_error_collection.rb +2 -1
  141. data/lib/braintree/venmo_account.rb +11 -4
  142. data/lib/braintree/venmo_profile_data.rb +23 -0
  143. data/lib/braintree/version.rb +2 -2
  144. data/lib/braintree/visa_checkout_card.rb +29 -13
  145. data/lib/braintree/webhook_notification.rb +66 -26
  146. data/lib/braintree/webhook_notification_gateway.rb +5 -3
  147. data/lib/braintree/webhook_testing.rb +2 -2
  148. data/lib/braintree/webhook_testing_gateway.rb +721 -55
  149. data/lib/braintree/xml/generator.rb +6 -4
  150. data/lib/braintree/xml/parser.rb +22 -35
  151. data/lib/braintree/xml/rexml.rb +4 -5
  152. data/lib/braintree.rb +60 -22
  153. data/lib/ssl/api_braintreegateway_com.ca.crt +50 -0
  154. data/spec/fixtures/files/bt_logo.png +0 -0
  155. data/spec/fixtures/files/gif_extension_bt_logo.gif +0 -0
  156. data/spec/fixtures/files/malformed_pdf.pdf +1 -0
  157. data/spec/fixtures/files/too_long.pdf +0 -0
  158. data/spec/integration/braintree/add_on_spec.rb +3 -3
  159. data/spec/integration/braintree/address_spec.rb +30 -113
  160. data/spec/integration/braintree/advanced_search_spec.rb +45 -45
  161. data/spec/integration/braintree/apple_pay_spec.rb +63 -0
  162. data/spec/integration/braintree/braintree_gateway_spec.rb +72 -0
  163. data/spec/integration/braintree/client_api/client_token_spec.rb +14 -32
  164. data/spec/integration/braintree/client_api/spec_helper.rb +104 -65
  165. data/spec/integration/braintree/credit_card_spec.rb +460 -615
  166. data/spec/integration/braintree/credit_card_verification_search_spec.rb +2 -2
  167. data/spec/integration/braintree/credit_card_verification_spec.rb +222 -6
  168. data/spec/integration/braintree/customer_search_spec.rb +8 -8
  169. data/spec/integration/braintree/customer_spec.rb +810 -498
  170. data/spec/integration/braintree/discount_spec.rb +1 -1
  171. data/spec/integration/braintree/dispute_search_spec.rb +167 -0
  172. data/spec/integration/braintree/dispute_spec.rb +333 -0
  173. data/spec/integration/braintree/document_upload_spec.rb +87 -0
  174. data/spec/integration/braintree/error_codes_spec.rb +1 -1
  175. data/spec/integration/braintree/exchange_rate_quote_spec.rb +97 -0
  176. data/spec/integration/braintree/graphql_client_spec.rb +72 -0
  177. data/spec/integration/braintree/http_spec.rb +12 -4
  178. data/spec/integration/braintree/merchant_account_spec.rb +74 -26
  179. data/spec/integration/braintree/merchant_spec.rb +39 -13
  180. data/spec/integration/braintree/oauth_spec.rb +18 -25
  181. data/spec/integration/braintree/payment_method_nonce_spec.rb +239 -5
  182. data/spec/integration/braintree/payment_method_spec.rb +882 -300
  183. data/spec/integration/braintree/payment_method_us_bank_account_spec.rb +416 -0
  184. data/spec/integration/braintree/paypal_account_spec.rb +32 -31
  185. data/spec/integration/braintree/plan_spec.rb +82 -0
  186. data/spec/integration/braintree/samsung_pay_card_spec.rb +144 -0
  187. data/spec/integration/braintree/sepa_direct_debit_account_spec.rb +196 -0
  188. data/spec/integration/braintree/settlement_batch_summary_spec.rb +8 -8
  189. data/spec/integration/braintree/subscription_spec.rb +274 -180
  190. data/spec/integration/braintree/test/transaction_amounts_spec.rb +2 -2
  191. data/spec/integration/braintree/test_transaction_spec.rb +18 -18
  192. data/spec/integration/braintree/transaction_line_item_spec.rb +38 -0
  193. data/spec/integration/braintree/transaction_search_spec.rb +280 -152
  194. data/spec/integration/braintree/transaction_spec.rb +3709 -1175
  195. data/spec/integration/braintree/transaction_us_bank_account_spec.rb +438 -0
  196. data/spec/integration/braintree/us_bank_account_spec.rb +38 -17
  197. data/spec/integration/braintree/us_bank_account_verification_search_spec.rb +178 -0
  198. data/spec/integration/braintree/us_bank_account_verification_spec.rb +240 -0
  199. data/spec/integration/braintree/visa_checkout_card_spec.rb +5 -5
  200. data/spec/integration/spec_helper.rb +27 -6
  201. data/spec/oauth_test_helper.rb +1 -1
  202. data/spec/script/httpsd.rb +6 -6
  203. data/spec/spec_helper.rb +26 -23
  204. data/spec/unit/braintree/address_spec.rb +1 -9
  205. data/spec/unit/braintree/apple_pay_card_spec.rb +104 -4
  206. data/spec/unit/braintree/client_token_spec.rb +2 -2
  207. data/spec/unit/braintree/configuration_spec.rb +108 -33
  208. data/spec/unit/braintree/credit_card_spec.rb +62 -33
  209. data/spec/unit/braintree/credit_card_verification_gateway_spec.rb +51 -0
  210. data/spec/unit/braintree/credit_card_verification_search_spec.rb +1 -1
  211. data/spec/unit/braintree/credit_card_verification_spec.rb +39 -6
  212. data/spec/unit/braintree/customer_spec.rb +107 -27
  213. data/spec/unit/braintree/disbursement_spec.rb +59 -7
  214. data/spec/unit/braintree/dispute_search_spec.rb +66 -0
  215. data/spec/unit/braintree/dispute_spec.rb +472 -8
  216. data/spec/unit/braintree/document_upload_spec.rb +35 -0
  217. data/spec/unit/braintree/enriched_customer_data_spec.rb +32 -0
  218. data/spec/unit/braintree/error_result_spec.rb +5 -5
  219. data/spec/unit/braintree/errors_spec.rb +8 -8
  220. data/spec/unit/braintree/exchange_rate_quote_input_spec.rb +42 -0
  221. data/spec/unit/braintree/exchange_rate_quote_request_spec.rb +82 -0
  222. data/spec/unit/braintree/exchange_rate_quote_response_spec.rb +52 -0
  223. data/spec/unit/braintree/exchange_rate_quote_spec.rb +42 -0
  224. data/spec/unit/braintree/exchange_rate_spec.rb +23 -0
  225. data/spec/unit/braintree/http_spec.rb +93 -5
  226. data/spec/unit/braintree/local_payment_completed_spec.rb +50 -0
  227. data/spec/unit/braintree/local_payment_expired_spec.rb +24 -0
  228. data/spec/unit/braintree/local_payment_funded_spec.rb +34 -0
  229. data/spec/unit/braintree/merchant_account_spec.rb +1 -1
  230. data/spec/unit/braintree/modification_spec.rb +1 -1
  231. data/spec/unit/braintree/payment_method_customer_data_updated_metadata_spec.rb +45 -0
  232. data/spec/unit/braintree/payment_method_nonce_details_payer_info_spec.rb +31 -0
  233. data/spec/unit/braintree/payment_method_nonce_details_spec.rb +51 -0
  234. data/spec/unit/braintree/payment_method_nonce_spec.rb +40 -0
  235. data/spec/unit/braintree/payment_method_spec.rb +1 -1
  236. data/spec/unit/braintree/paypal_account_spec.rb +2 -2
  237. data/spec/unit/braintree/resource_collection_spec.rb +30 -1
  238. data/spec/unit/braintree/risk_data/liability_shift.rb +26 -0
  239. data/spec/unit/braintree/risk_data_spec.rb +40 -6
  240. data/spec/unit/braintree/sepa_debit_account_nonce_details_spec.rb +29 -0
  241. data/spec/unit/braintree/sepa_debit_account_spec.rb +86 -0
  242. data/spec/unit/braintree/subscription_search_spec.rb +1 -1
  243. data/spec/unit/braintree/subscription_spec.rb +2 -2
  244. data/spec/unit/braintree/successful_result_spec.rb +1 -1
  245. data/spec/unit/braintree/three_d_secure_info_spec.rb +34 -6
  246. data/spec/unit/braintree/transaction/credit_card_details_spec.rb +19 -3
  247. data/spec/unit/braintree/transaction/customer_details_spec.rb +1 -1
  248. data/spec/unit/braintree/transaction/deposit_details_spec.rb +2 -2
  249. data/spec/unit/braintree/transaction/installment_spec.rb +25 -0
  250. data/spec/unit/braintree/transaction/paypal_details_spec.rb +63 -0
  251. data/spec/unit/braintree/transaction/sepa_direct_debit_account_details_spec.rb +33 -0
  252. data/spec/unit/braintree/transaction_gateway_spec.rb +111 -0
  253. data/spec/unit/braintree/transaction_search_spec.rb +12 -12
  254. data/spec/unit/braintree/transaction_spec.rb +171 -55
  255. data/spec/unit/braintree/us_bank_account_verification_search_spec.rb +60 -0
  256. data/spec/unit/braintree/us_bank_account_verification_spec.rb +93 -0
  257. data/spec/unit/braintree/util_spec.rb +162 -19
  258. data/spec/unit/braintree/validation_error_collection_spec.rb +336 -133
  259. data/spec/unit/braintree/venmo_profile_data_spec.rb +32 -0
  260. data/spec/unit/braintree/webhook_notification_spec.rb +546 -114
  261. data/spec/unit/braintree/xml/parser_spec.rb +21 -16
  262. data/spec/unit/braintree/xml_spec.rb +31 -24
  263. data/spec/unit/braintree_spec.rb +1 -0
  264. metadata +290 -198
  265. data/README.rdoc +0 -93
  266. data/lib/braintree/amex_express_checkout_card.rb +0 -26
  267. data/lib/braintree/android_pay_card.rb +0 -35
  268. data/lib/braintree/coinbase_account.rb +0 -25
  269. data/lib/braintree/europe_bank_account.rb +0 -34
  270. data/lib/braintree/europe_bank_account_gateway.rb +0 -17
  271. data/lib/braintree/ideal_payment.rb +0 -46
  272. data/lib/braintree/ideal_payment_gateway.rb +0 -18
  273. data/lib/braintree/masterpass_card.rb +0 -66
  274. data/lib/braintree/settlement_batch.rb +0 -0
  275. data/lib/braintree/transaction/amex_express_checkout_details.rb +0 -14
  276. data/lib/braintree/transaction/android_pay_details.rb +0 -17
  277. data/lib/braintree/transaction/ideal_payment_details.rb +0 -13
  278. data/lib/braintree/transparent_redirect.rb +0 -40
  279. data/lib/braintree/transparent_redirect_gateway.rb +0 -105
  280. data/spec/hacks/tcp_socket.rb +0 -18
  281. data/spec/httpsd.pid +0 -1
  282. data/spec/integration/braintree/coinbase_spec.rb +0 -31
  283. data/spec/integration/braintree/ideal_payment_spec.rb +0 -87
  284. data/spec/integration/braintree/masterpass_card_spec.rb +0 -97
  285. data/spec/integration/braintree/transparent_redirect_spec.rb +0 -268
  286. data/spec/unit/braintree/transparent_redirect_spec.rb +0 -223
@@ -1,7 +1,14 @@
1
1
  module Braintree
2
2
  class ErrorResult
3
3
 
4
- attr_reader :credit_card_verification, :merchant_account, :transaction, :subscription, :errors, :params, :message, :verification
4
+ attr_reader :credit_card_verification
5
+ attr_reader :errors
6
+ attr_reader :merchant_account
7
+ attr_reader :message
8
+ attr_reader :params
9
+ attr_reader :subscription
10
+ attr_reader :transaction
11
+ attr_reader :verification
5
12
 
6
13
  def initialize(gateway, data) # :nodoc:
7
14
  @gateway = gateway
@@ -8,9 +8,7 @@ module Braintree # :nodoc:
8
8
 
9
9
  class ConfigurationError < BraintreeError; end
10
10
 
11
- class DownForMaintenanceError < BraintreeError; end
12
-
13
- class ForgedQueryString < BraintreeError; end
11
+ class GatewayTimeoutError < BraintreeError; end
14
12
 
15
13
  class InvalidSignature < BraintreeError; end
16
14
 
@@ -18,8 +16,12 @@ module Braintree # :nodoc:
18
16
 
19
17
  class NotFoundError < BraintreeError; end
20
18
 
19
+ class RequestTimeoutError < BraintreeError; end
20
+
21
21
  class ServerError < BraintreeError; end
22
22
 
23
+ class ServiceUnavailableError < BraintreeError; end
24
+
23
25
  class SSLCertificateError < BraintreeError; end
24
26
 
25
27
  class TooManyRequestsError < BraintreeError; end
@@ -0,0 +1,13 @@
1
+ module Braintree
2
+ class ExchangeRate
3
+ include BaseModule # :nodoc:
4
+
5
+ def initialize(gateway, attributes) # :nodoc:
6
+ set_instance_variables_from_hash(attributes)
7
+ end
8
+
9
+ def self.generate(exchange_rate_quote_request)
10
+ Configuration.gateway.exchange_rate_quote.generate(exchange_rate_quote_request)
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,24 @@
1
+ module Braintree
2
+ class ExchangeRateQuote
3
+ include BaseModule # :nodoc:
4
+
5
+ attr_reader :attrs
6
+ attr_reader :base_amount
7
+ attr_reader :exchange_rate
8
+ attr_reader :expires_at
9
+ attr_reader :id
10
+ attr_reader :quote_amount
11
+ attr_reader :refreshes_at
12
+ attr_reader :trade_rate
13
+
14
+ def initialize(attributes) # :nodoc:
15
+ @attrs = attributes.keys
16
+ set_instance_variables_from_hash(attributes)
17
+ end
18
+
19
+ def inspect # :nodoc:
20
+ inspected_attributes = @attrs.map { |attr| "#{attr}:#{send(attr).inspect}" }
21
+ "#<#{self.class} #{inspected_attributes.join(" ")}>"
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,35 @@
1
+ module Braintree
2
+ class ExchangeRateQuoteGateway # :nodoc
3
+ def initialize(gateway)
4
+ @gateway = gateway
5
+ end
6
+
7
+ DEFINITION = <<-GRAPHQL
8
+ mutation GenerateExchangeRateQuoteInput($input: GenerateExchangeRateQuoteInput!) {
9
+ generateExchangeRateQuote(input: $input) {
10
+ quotes {
11
+ id
12
+ baseAmount {value, currencyCode}
13
+ quoteAmount {value, currencyCode}
14
+ exchangeRate
15
+ tradeRate
16
+ expiresAt
17
+ refreshesAt
18
+ }
19
+ }
20
+ }
21
+ GRAPHQL
22
+
23
+ def generate(params)
24
+ response = @gateway.config.graphql_client.query(DEFINITION, {input: params})
25
+
26
+ if response.has_key?(:data) && response[:data][:generateExchangeRateQuote]
27
+ response[:data][:generateExchangeRateQuote]
28
+ elsif response[:errors]
29
+ ErrorResult.new(@gateway, response[:errors])
30
+ else
31
+ raise UnexpectedError, "expected :generateExchangeRateQuote or :api_error_response in GraphQL response"
32
+ end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,21 @@
1
+ module Braintree
2
+ class ExchangeRateQuoteInput
3
+ include BaseModule # :nodoc:
4
+
5
+ attr_reader :attrs
6
+ attr_reader :base_currency
7
+ attr_reader :base_amount
8
+ attr_reader :markup
9
+ attr_reader :quote_currency
10
+
11
+ def initialize(attributes) # :nodoc:
12
+ @attrs = attributes.keys
13
+ set_instance_variables_from_hash(attributes)
14
+ end
15
+
16
+ def inspect # :nodoc:
17
+ inspected_attributes = @attrs.map { |attr| "#{attr}:#{send(attr).inspect}" }
18
+ "#<#{self.class} #{inspected_attributes.join(" ")}>"
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,18 @@
1
+ module Braintree
2
+ class ExchangeRateQuoteRequest
3
+ include BaseModule # :nodoc:
4
+
5
+ attr_reader :quotes
6
+
7
+ def initialize(attributes) # :nodoc:
8
+ @attrs = attributes.keys
9
+ set_instance_variables_from_hash(attributes)
10
+ @quotes = (@quotes || []).map { |quote_hash| ExchangeRateQuoteInput.new(quote_hash) }
11
+ end
12
+
13
+ def inspect # :nodoc:
14
+ inspected_attributes = @attrs.map { |attr| "#{attr}:#{send(attr).inspect}" }
15
+ "#<#{self.class} #{inspected_attributes.join(" ")}>"
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,18 @@
1
+ module Braintree
2
+ class ExchangeRateQuoteResponse
3
+ include BaseModule # :nodoc:
4
+
5
+ attr_reader :quotes
6
+
7
+ def initialize(attributes) # :nodoc:
8
+ @attrs = attributes.keys
9
+ set_instance_variables_from_hash(attributes)
10
+ @quotes = (@quotes || []).map { |quote_hash| ExchangeRateQuote.new(quote_hash) }
11
+ end
12
+
13
+ def inspect # :nodoc:
14
+ inspected_attributes = @attrs.map { |attr| "#{attr}:#{send(attr).inspect}" }
15
+ "#<#{self.class} #{inspected_attributes.join(" ")}>"
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,21 @@
1
+ module Braintree
2
+ class FacilitatedDetails # :nodoc:
3
+ include BaseModule
4
+
5
+ attr_reader :merchant_id
6
+ attr_reader :merchant_name
7
+ attr_reader :payment_method_nonce
8
+
9
+ def initialize(attributes)
10
+ set_instance_variables_from_hash attributes unless attributes.nil?
11
+ end
12
+
13
+ def inspect
14
+ attr_order = [:merchant_id, :merchant_name, :payment_method_nonce]
15
+ formatted_attrs = attr_order.map do |attr|
16
+ "#{attr}: #{send(attr).inspect}"
17
+ end
18
+ "#<FacilitatorDetails #{formatted_attrs.join(", ")}>"
19
+ end
20
+ end
21
+ end
@@ -2,7 +2,8 @@ module Braintree
2
2
  class FacilitatorDetails # :nodoc:
3
3
  include BaseModule
4
4
 
5
- attr_reader :oauth_application_client_id, :oauth_application_name
5
+ attr_reader :oauth_application_client_id
6
+ attr_reader :oauth_application_name
6
7
 
7
8
  def initialize(attributes)
8
9
  set_instance_variables_from_hash attributes unless attributes.nil?
@@ -1,6 +1,6 @@
1
1
  module Braintree
2
2
  class Gateway
3
- attr_reader :config
3
+ attr_reader :config, :graphql_client
4
4
 
5
5
  def initialize(config)
6
6
  if config.is_a?(Hash)
@@ -10,6 +10,8 @@ module Braintree
10
10
  else
11
11
  raise ArgumentError, "config is an invalid type"
12
12
  end
13
+
14
+ @graphql_client = GraphQLClient.new(@config)
13
15
  end
14
16
 
15
17
  def add_on
@@ -20,6 +22,10 @@ module Braintree
20
22
  AddressGateway.new(self)
21
23
  end
22
24
 
25
+ def apple_pay
26
+ ApplePayGateway.new(self)
27
+ end
28
+
23
29
  def client_token
24
30
  ClientTokenGateway.new(self)
25
31
  end
@@ -36,6 +42,18 @@ module Braintree
36
42
  DiscountGateway.new(self)
37
43
  end
38
44
 
45
+ def dispute
46
+ DisputeGateway.new(self)
47
+ end
48
+
49
+ def document_upload
50
+ DocumentUploadGateway.new(self)
51
+ end
52
+
53
+ def exchange_rate_quote
54
+ ExchangeRateQuoteGateway.new(self)
55
+ end
56
+
39
57
  def oauth
40
58
  OAuthGateway.new(self)
41
59
  end
@@ -60,8 +78,8 @@ module Braintree
60
78
  UsBankAccountGateway.new(self)
61
79
  end
62
80
 
63
- def ideal_payment
64
- IdealPaymentGateway.new(self)
81
+ def sepa_direct_debit_account
82
+ SepaDirectDebitAccountGateway.new(self)
65
83
  end
66
84
 
67
85
  def merchant
@@ -72,10 +90,6 @@ module Braintree
72
90
  MerchantAccountGateway.new(self)
73
91
  end
74
92
 
75
- def europe_bank_account
76
- EuropeBankAccountGateway.new(self)
77
- end
78
-
79
93
  def settlement_batch_summary
80
94
  SettlementBatchSummaryGateway.new(self)
81
95
  end
@@ -84,18 +98,22 @@ module Braintree
84
98
  SubscriptionGateway.new(self)
85
99
  end
86
100
 
87
- def transparent_redirect
88
- TransparentRedirectGateway.new(self)
89
- end
90
-
91
101
  def transaction
92
102
  TransactionGateway.new(self)
93
103
  end
94
104
 
105
+ def transaction_line_item
106
+ TransactionLineItemGateway.new(self)
107
+ end
108
+
95
109
  def testing
96
110
  TestingGateway.new(self)
97
111
  end
98
112
 
113
+ def us_bank_account_verification
114
+ UsBankAccountVerificationGateway.new(self)
115
+ end
116
+
99
117
  def verification
100
118
  CreditCardVerificationGateway.new(self)
101
119
  end
@@ -0,0 +1,61 @@
1
+ module Braintree
2
+ class GooglePayCard
3
+ include BaseModule # :nodoc:
4
+
5
+ attr_reader :bin
6
+ attr_reader :commercial
7
+ attr_reader :country_of_issuance
8
+ attr_reader :created_at
9
+ attr_reader :customer_id
10
+ attr_reader :debit
11
+ attr_reader :default
12
+ attr_reader :durbin_regulated
13
+ attr_reader :expiration_month
14
+ attr_reader :expiration_year
15
+ attr_reader :google_transaction_id
16
+ attr_reader :healthcare
17
+ attr_reader :image_url
18
+ attr_reader :issuing_bank
19
+ attr_reader :payroll
20
+ attr_reader :prepaid
21
+ attr_reader :product_id
22
+ attr_reader :source_card_last_4
23
+ attr_reader :source_card_type
24
+ attr_reader :source_description
25
+ attr_reader :subscriptions
26
+ attr_reader :token
27
+ attr_reader :updated_at
28
+ attr_reader :virtual_card_last_4
29
+ attr_reader :virtual_card_type
30
+
31
+ def initialize(gateway, attributes) # :nodoc:
32
+ @gateway = gateway
33
+ set_instance_variables_from_hash(attributes)
34
+ @subscriptions = (@subscriptions || []).map { |subscription_hash| Subscription._new(@gateway, subscription_hash) }
35
+ end
36
+
37
+ def default?
38
+ @default
39
+ end
40
+
41
+ def is_network_tokenized?
42
+ @is_network_tokenized
43
+ end
44
+
45
+ def card_type
46
+ virtual_card_type
47
+ end
48
+
49
+ def last_4
50
+ virtual_card_last_4
51
+ end
52
+
53
+ class << self
54
+ protected :new
55
+ end
56
+
57
+ def self._new(*args) # :nodoc:
58
+ self.new(*args)
59
+ end
60
+ end
61
+ end
@@ -0,0 +1,23 @@
1
+ module Braintree
2
+ class GrantedPaymentInstrumentUpdate
3
+ include BaseModule
4
+
5
+ attr_reader :grant_owner_merchant_id
6
+ attr_reader :grant_recipient_merchant_id
7
+ attr_reader :payment_method_nonce
8
+ attr_reader :token
9
+ attr_reader :updated_fields
10
+
11
+ def initialize(attributes)
12
+ set_instance_variables_from_hash(attributes)
13
+ @payment_method_nonce = attributes[:payment_method_nonce][:nonce]
14
+ end
15
+
16
+ class << self
17
+ protected :new
18
+ def _new(*args) # :nodoc:
19
+ self.new(*args)
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,34 @@
1
+ module Braintree
2
+ class GraphQLClient < Http # :nodoc:
3
+
4
+ def initialize(config)
5
+ @config = config
6
+ @graphql_headers = {
7
+ "Accept" => "application/json",
8
+ "Braintree-Version" => @config.graphql_api_version,
9
+ "Content-Type" => "application/json"
10
+ }
11
+ end
12
+
13
+ def query(definition, variables = {}, operationName = nil)
14
+ graphql_connection = _setup_connection(@config.graphql_server, @config.graphql_port)
15
+
16
+ request = {}
17
+ request["query"] = definition
18
+ request["operationName"] = operationName if operationName
19
+ request["variables"] = variables
20
+
21
+ response = _http_do Net::HTTP::Post, @config.graphql_base_url, request.to_json, nil, graphql_connection, @graphql_headers
22
+ data = _parse_response(response)
23
+ Util.raise_exception_for_graphql_error(data)
24
+
25
+ data
26
+ end
27
+
28
+ def _parse_response(response)
29
+ body = response.body
30
+ body = Zlib::GzipReader.new(StringIO.new(body)).read if response.header["Content-Encoding"] == "gzip"
31
+ JSON.parse(body, :symbolize_names => true)
32
+ end
33
+ end
34
+ end
@@ -1,20 +1,25 @@
1
1
  module Braintree
2
2
  class Http # :nodoc:
3
3
 
4
+ LINE_FEED = "\r\n"
5
+
4
6
  def initialize(config)
5
7
  @config = config
6
8
  end
7
9
 
8
- def delete(path)
10
+ def delete(_path, query_params = {})
11
+ path = _path + _build_query_string(query_params)
9
12
  response = _http_do Net::HTTP::Delete, path
10
- if response.code.to_i == 200
13
+ if response.code.to_i == 200 || response.code.to_i == 204
11
14
  true
15
+ elsif response.code.to_i == 422
16
+ Xml.hash_from_xml(_body(response))
12
17
  else
13
18
  Util.raise_exception_for_status_code(response.code)
14
19
  end
15
20
  end
16
21
 
17
- def get(_path, query_params={})
22
+ def get(_path, query_params = {})
18
23
  path = _path + _build_query_string(query_params)
19
24
  response = _http_do Net::HTTP::Get, path
20
25
  if response.code.to_i == 200 || response.code.to_i == 422
@@ -24,8 +29,12 @@ module Braintree
24
29
  end
25
30
  end
26
31
 
27
- def post(path, params = nil)
28
- response = _http_do Net::HTTP::Post, path, _build_xml(params)
32
+ def post(path, params = nil, file = nil)
33
+ body = params
34
+ if !file
35
+ body = _build_xml(params)
36
+ end
37
+ response = _http_do Net::HTTP::Post, path, body, file
29
38
  if response.code.to_i == 200 || response.code.to_i == 201 || response.code.to_i == 422
30
39
  Xml.hash_from_xml(_body(response))
31
40
  else
@@ -58,19 +67,34 @@ module Braintree
58
67
  end
59
68
  end
60
69
 
61
- def _http_do(http_verb, path, body = nil)
70
+ def _setup_connection(server = @config.server, port = @config.port)
62
71
  if @config.proxy_address
63
72
  connection = Net::HTTP.new(
64
- @config.server,
65
- @config.port,
73
+ server,
74
+ port,
66
75
  @config.proxy_address,
67
76
  @config.proxy_port,
68
77
  @config.proxy_user,
69
- @config.proxy_pass
78
+ @config.proxy_pass,
70
79
  )
71
80
  else
72
- connection = Net::HTTP.new(@config.server, @config.port)
81
+ connection = Net::HTTP.new(server, port)
73
82
  end
83
+ end
84
+
85
+ def _compose_headers(header_overrides = {})
86
+ headers = {}
87
+ headers["Accept"] = "application/xml"
88
+ headers["User-Agent"] = @config.user_agent
89
+ headers["Accept-Encoding"] = "gzip"
90
+ headers["X-ApiVersion"] = @config.api_version
91
+ headers["Content-Type"] = "application/xml"
92
+
93
+ headers.merge(header_overrides)
94
+ end
95
+
96
+ def _http_do(http_verb, path, body = nil, file = nil, connection = nil, header_overrides = {})
97
+ connection ||= _setup_connection
74
98
 
75
99
  connection.open_timeout = @config.http_open_timeout
76
100
  connection.read_timeout = @config.http_read_timeout
@@ -81,12 +105,10 @@ module Braintree
81
105
  connection.ca_file = @config.ca_file
82
106
  connection.verify_callback = proc { |preverify_ok, ssl_context| _verify_ssl_certificate(preverify_ok, ssl_context) }
83
107
  end
108
+
84
109
  connection.start do |http|
85
110
  request = http_verb.new(path)
86
- request["Accept"] = "application/xml"
87
- request["User-Agent"] = @config.user_agent
88
- request["Accept-Encoding"] = "gzip"
89
- request["X-ApiVersion"] = @config.api_version
111
+ _compose_headers(header_overrides).each { |header, value| request[header] = value }
90
112
  if @config.client_credentials?
91
113
  request.basic_auth @config.client_id, @config.client_secret
92
114
  elsif @config.access_token
@@ -96,9 +118,21 @@ module Braintree
96
118
  end
97
119
  @config.logger.debug "[Braintree] [#{_current_time}] #{request.method} #{path}"
98
120
  if body
99
- request["Content-Type"] = "application/xml"
100
- request.body = body
101
- @config.logger.debug _format_and_sanitize_body_for_log(body)
121
+ if file
122
+ boundary = DateTime.now.strftime("%Q")
123
+ request["Content-Type"] = "multipart/form-data; boundary=#{boundary}"
124
+
125
+ form_params = []
126
+ body.each do |k, v|
127
+ form_params.push(_add_form_field(k, v))
128
+ end
129
+ form_params.push(_add_file_part("file", file))
130
+ request.body = form_params.collect { |p| "--" + boundary + "#{LINE_FEED}" + p }.join("") + "--" + boundary + "--"
131
+ @config.logger.debug _format_and_sanitize_body_for_log(_build_xml(body))
132
+ else
133
+ request.body = body
134
+ @config.logger.debug _format_and_sanitize_body_for_log(body)
135
+ end
102
136
  end
103
137
  response = http.request(request)
104
138
  @config.logger.info "[Braintree] [#{_current_time}] #{request.method} #{path} #{response.code}"
@@ -112,9 +146,35 @@ module Braintree
112
146
  raise Braintree::SSLCertificateError
113
147
  end
114
148
 
149
+ def _add_form_field(key, value)
150
+ return "Content-Disposition: form-data; name=\"#{key}\"#{LINE_FEED}#{LINE_FEED}#{value}#{LINE_FEED}"
151
+ end
152
+
153
+ def _add_file_part(key, file)
154
+ mime_type = _mime_type_for_file_name(file.path)
155
+ return "Content-Disposition: form-data; name=\"#{key}\"; filename=\"#{file.path}\"#{LINE_FEED}" +
156
+ "Content-Type: #{mime_type}#{LINE_FEED}#{LINE_FEED}#{file.read}#{LINE_FEED}"
157
+ end
158
+
159
+ def _mime_type_for_file_name(filename)
160
+ file_extension = File.extname(filename).strip.downcase[1..-1]
161
+ if file_extension == "jpeg" || file_extension == "jpg"
162
+ return "image/jpeg"
163
+ elsif file_extension == "png"
164
+ return "image/png"
165
+ elsif file_extension == "pdf"
166
+ return "application/pdf"
167
+ else
168
+ return "application/octet-stream"
169
+ end
170
+ end
171
+
115
172
  def _body(response)
116
- if response.header["Content-Encoding"] == "gzip"
173
+ content_encoding = response.header["Content-Encoding"]
174
+ if content_encoding == "gzip"
117
175
  Zlib::GzipReader.new(StringIO.new(response.body)).read
176
+ elsif content_encoding.nil?
177
+ ""
118
178
  else
119
179
  raise UnexpectedError, "expected a gzipped response"
120
180
  end
@@ -126,8 +186,9 @@ module Braintree
126
186
 
127
187
  def _format_and_sanitize_body_for_log(input_xml)
128
188
  formatted_xml = input_xml.gsub(/^/, "[Braintree] ")
129
- formatted_xml = formatted_xml.gsub(/<number>(.{6}).+?(.{4})<\/number>/, '<number>\1******\2</number>')
130
- formatted_xml = formatted_xml.gsub(/<cvv>.+?<\/cvv>/, '<cvv>***</cvv>')
189
+ formatted_xml = formatted_xml.gsub(/<number>(.{6}).+?(.{4})<\/number>/m, '<number>\1******\2</number>')
190
+ formatted_xml = formatted_xml.gsub(/<cvv>.+?<\/cvv>/m, "<cvv>***</cvv>")
191
+ formatted_xml = formatted_xml.gsub(/<encrypted-card-data>.+?<\/encrypted-card-data>/m, "<encrypted-card-data>***</encrypted-card-data>")
131
192
  formatted_xml
132
193
  end
133
194
 
@@ -0,0 +1,23 @@
1
+ module Braintree
2
+ class LocalPaymentCompleted
3
+ include BaseModule
4
+
5
+ attr_reader :payment_id
6
+ attr_reader :payer_id
7
+ attr_reader :payment_method_nonce
8
+ attr_reader :transaction
9
+
10
+ def initialize(attributes) # :nodoc:
11
+ set_instance_variables_from_hash(attributes)
12
+ @transaction = Transaction._new(Configuration.gateway, transaction) unless transaction.nil?
13
+ end
14
+
15
+ class << self
16
+ protected :new
17
+ end
18
+
19
+ def self._new(*args) # :nodoc:
20
+ self.new(*args)
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,21 @@
1
+ module Braintree
2
+ class LocalPaymentExpired
3
+ include BaseModule
4
+
5
+ attr_reader :payment_id
6
+ attr_reader :payment_context_id
7
+
8
+ def initialize(attributes) # :nodoc:
9
+ set_instance_variables_from_hash(attributes)
10
+ end
11
+
12
+ class << self
13
+ protected :new
14
+ end
15
+
16
+ def self._new(*args) # :nodoc:
17
+ self.new(*args)
18
+ end
19
+ end
20
+ end
21
+
@@ -0,0 +1,22 @@
1
+ module Braintree
2
+ class LocalPaymentFunded
3
+ include BaseModule
4
+
5
+ attr_reader :payment_id
6
+ attr_reader :payment_context_id
7
+ attr_reader :transaction
8
+
9
+ def initialize(attributes) # :nodoc:
10
+ set_instance_variables_from_hash(attributes)
11
+ @transaction = Transaction._new(Configuration.gateway, transaction)
12
+ end
13
+
14
+ class << self
15
+ protected :new
16
+ end
17
+
18
+ def self._new(*args) # :nodoc:
19
+ self.new(*args)
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,19 @@
1
+ module Braintree
2
+ class LocalPaymentReversed
3
+ include BaseModule
4
+
5
+ attr_reader :payment_id
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