braintree 2.10.0 → 4.26.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 (353) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE +1 -1
  3. data/braintree.gemspec +24 -0
  4. data/lib/braintree/account_updater_daily_report.rb +20 -0
  5. data/lib/braintree/ach_mandate.rb +14 -0
  6. data/lib/braintree/add_on.rb +4 -0
  7. data/lib/braintree/add_on_gateway.rb +17 -0
  8. data/lib/braintree/address/country_names.rb +4 -1
  9. data/lib/braintree/address.rb +35 -43
  10. data/lib/braintree/address_gateway.rb +24 -11
  11. data/lib/braintree/advanced_search.rb +26 -11
  12. data/lib/braintree/apple_pay.rb +29 -0
  13. data/lib/braintree/apple_pay_card.rb +66 -0
  14. data/lib/braintree/apple_pay_gateway.rb +37 -0
  15. data/lib/braintree/apple_pay_options.rb +19 -0
  16. data/lib/braintree/authorization_adjustment.rb +23 -0
  17. data/lib/braintree/base_module.rb +11 -1
  18. data/lib/braintree/bin_data.rb +34 -0
  19. data/lib/braintree/client_token.rb +11 -0
  20. data/lib/braintree/client_token_gateway.rb +45 -0
  21. data/lib/braintree/configuration.rb +231 -39
  22. data/lib/braintree/connected_merchant_paypal_status_changed.rb +22 -0
  23. data/lib/braintree/connected_merchant_status_transitioned.rb +22 -0
  24. data/lib/braintree/credentials_parser.rb +44 -0
  25. data/lib/braintree/credit_card.rb +107 -132
  26. data/lib/braintree/credit_card_gateway.rb +90 -41
  27. data/lib/braintree/credit_card_verification.rb +90 -17
  28. data/lib/braintree/credit_card_verification_gateway.rb +87 -0
  29. data/lib/braintree/credit_card_verification_search.rb +20 -0
  30. data/lib/braintree/customer.rb +80 -118
  31. data/lib/braintree/customer_gateway.rb +66 -39
  32. data/lib/braintree/customer_search.rb +5 -2
  33. data/lib/braintree/customer_session_gateway.rb +194 -0
  34. data/lib/braintree/descriptor.rb +4 -2
  35. data/lib/braintree/digest.rb +16 -3
  36. data/lib/braintree/disbursement.rb +63 -0
  37. data/lib/braintree/discount.rb +4 -0
  38. data/lib/braintree/discount_gateway.rb +17 -0
  39. data/lib/braintree/dispute/evidence.rb +24 -0
  40. data/lib/braintree/dispute/paypal_message.rb +15 -0
  41. data/lib/braintree/dispute/status_history.rb +18 -0
  42. data/lib/braintree/dispute/transaction.rb +20 -0
  43. data/lib/braintree/dispute/transaction_details.rb +15 -0
  44. data/lib/braintree/dispute.rb +165 -0
  45. data/lib/braintree/dispute_gateway.rb +142 -0
  46. data/lib/braintree/dispute_search.rb +31 -0
  47. data/lib/braintree/document_upload.rb +37 -0
  48. data/lib/braintree/document_upload_gateway.rb +38 -0
  49. data/lib/braintree/enriched_customer_data.rb +21 -0
  50. data/lib/braintree/error_codes.rb +680 -15
  51. data/lib/braintree/error_result.rb +13 -6
  52. data/lib/braintree/errors.rb +5 -5
  53. data/lib/braintree/exceptions.rb +14 -20
  54. data/lib/braintree/exchange_rate.rb +13 -0
  55. data/lib/braintree/exchange_rate_quote.rb +24 -0
  56. data/lib/braintree/exchange_rate_quote_gateway.rb +35 -0
  57. data/lib/braintree/exchange_rate_quote_input.rb +21 -0
  58. data/lib/braintree/exchange_rate_quote_request.rb +18 -0
  59. data/lib/braintree/exchange_rate_quote_response.rb +18 -0
  60. data/lib/braintree/facilitated_details.rb +21 -0
  61. data/lib/braintree/facilitator_details.rb +20 -0
  62. data/lib/braintree/gateway.rb +104 -6
  63. data/lib/braintree/google_pay_card.rb +62 -0
  64. data/lib/braintree/granted_payment_instrument_update.rb +23 -0
  65. data/lib/braintree/graphql/enums/recommendations.rb +7 -0
  66. data/lib/braintree/graphql/enums/recommended_payment_option.rb +8 -0
  67. data/lib/braintree/graphql/inputs/create_customer_session_input.rb +35 -0
  68. data/lib/braintree/graphql/inputs/customer_recommendations_input.rb +41 -0
  69. data/lib/braintree/graphql/inputs/customer_session_input.rb +39 -0
  70. data/lib/braintree/graphql/inputs/phone_input.rb +32 -0
  71. data/lib/braintree/graphql/inputs/update_customer_session_input.rb +37 -0
  72. data/lib/braintree/graphql/types/customer_recommendations_payload.rb +32 -0
  73. data/lib/braintree/graphql/types/payment_options.rb +33 -0
  74. data/lib/braintree/graphql/unions/customer_recommendations.rb +34 -0
  75. data/lib/braintree/graphql_client.rb +50 -0
  76. data/lib/braintree/http.rb +119 -25
  77. data/lib/braintree/local_payment_completed/blik_alias.rb +23 -0
  78. data/lib/braintree/local_payment_completed.rb +28 -0
  79. data/lib/braintree/local_payment_expired.rb +21 -0
  80. data/lib/braintree/local_payment_funded.rb +22 -0
  81. data/lib/braintree/local_payment_reversed.rb +19 -0
  82. data/lib/braintree/merchant.rb +34 -0
  83. data/lib/braintree/merchant_account/address_details.rb +16 -0
  84. data/lib/braintree/merchant_account/business_details.rb +17 -0
  85. data/lib/braintree/merchant_account/funding_details.rb +18 -0
  86. data/lib/braintree/merchant_account/individual_details.rb +20 -0
  87. data/lib/braintree/merchant_account.rb +76 -0
  88. data/lib/braintree/merchant_account_gateway.rb +130 -0
  89. data/lib/braintree/merchant_gateway.rb +38 -0
  90. data/lib/braintree/meta_checkout_card.rb +90 -0
  91. data/lib/braintree/meta_checkout_token.rb +89 -0
  92. data/lib/braintree/modification.rb +16 -5
  93. data/lib/braintree/oauth_credentials.rb +22 -0
  94. data/lib/braintree/oauth_gateway.rb +73 -0
  95. data/lib/braintree/paginated_collection.rb +25 -0
  96. data/lib/braintree/paginated_result.rb +15 -0
  97. data/lib/braintree/payment_instrument_type.rb +18 -0
  98. data/lib/braintree/payment_method.rb +37 -0
  99. data/lib/braintree/payment_method_customer_data_updated_metadata.rb +24 -0
  100. data/lib/braintree/payment_method_gateway.rb +221 -0
  101. data/lib/braintree/payment_method_nonce.rb +49 -0
  102. data/lib/braintree/payment_method_nonce_details.rb +40 -0
  103. data/lib/braintree/payment_method_nonce_details_payer_info.rb +32 -0
  104. data/lib/braintree/payment_method_nonce_gateway.rb +38 -0
  105. data/lib/braintree/payment_method_parser.rb +29 -0
  106. data/lib/braintree/paypal_account.rb +60 -0
  107. data/lib/braintree/paypal_account_gateway.rb +73 -0
  108. data/lib/braintree/paypal_payment_resource.rb +22 -0
  109. data/lib/braintree/paypal_payment_resource_gateway.rb +36 -0
  110. data/lib/braintree/plan.rb +62 -0
  111. data/lib/braintree/plan_gateway.rb +117 -0
  112. data/lib/braintree/processor_response_types.rb +7 -0
  113. data/lib/braintree/resource_collection.rb +12 -5
  114. data/lib/braintree/revoked_payment_method_metadata.rb +22 -0
  115. data/lib/braintree/risk_data/liability_shift.rb +22 -0
  116. data/lib/braintree/risk_data.rb +29 -0
  117. data/lib/braintree/samsung_pay_card.rb +85 -0
  118. data/lib/braintree/sepa_direct_debit_account.rb +60 -0
  119. data/lib/braintree/sepa_direct_debit_account_gateway.rb +25 -0
  120. data/lib/braintree/sepa_direct_debit_account_nonce_details.rb +28 -0
  121. data/lib/braintree/settlement_batch_summary.rb +25 -0
  122. data/lib/braintree/settlement_batch_summary_gateway.rb +27 -0
  123. data/lib/braintree/sha256_digest.rb +13 -0
  124. data/lib/braintree/signature_service.rb +19 -0
  125. data/lib/braintree/subscription/status_details.rb +20 -0
  126. data/lib/braintree/subscription.rb +67 -47
  127. data/lib/braintree/subscription_gateway.rb +43 -16
  128. data/lib/braintree/subscription_search.rb +2 -2
  129. data/lib/braintree/successful_result.rb +30 -10
  130. data/lib/braintree/test/authentication_id.rb +21 -0
  131. data/lib/braintree/test/credit_card.rb +76 -0
  132. data/lib/braintree/test/merchant_account.rb +12 -0
  133. data/lib/braintree/test/nonce.rb +81 -0
  134. data/lib/braintree/test/transaction_amounts.rb +3 -5
  135. data/lib/braintree/test/venmo_sdk.rb +21 -0
  136. data/lib/braintree/test_transaction.rb +19 -0
  137. data/lib/braintree/testing_gateway.rb +43 -0
  138. data/lib/braintree/three_d_secure_info.rb +53 -0
  139. data/lib/braintree/transaction/address_details.rb +27 -5
  140. data/lib/braintree/transaction/apple_pay_details.rb +35 -0
  141. data/lib/braintree/transaction/credit_card_details.rb +55 -4
  142. data/lib/braintree/transaction/customer_details.rb +11 -3
  143. data/lib/braintree/transaction/disbursement_details.rb +28 -0
  144. data/lib/braintree/transaction/google_pay_details.rb +42 -0
  145. data/lib/braintree/transaction/installment/adjustment.rb +33 -0
  146. data/lib/braintree/transaction/installment.rb +28 -0
  147. data/lib/braintree/transaction/local_payment_details.rb +27 -0
  148. data/lib/braintree/transaction/meta_checkout_card_details.rb +55 -0
  149. data/lib/braintree/transaction/meta_checkout_token_details.rb +58 -0
  150. data/lib/braintree/transaction/package_details.rb +19 -0
  151. data/lib/braintree/transaction/payment_receipt/card_present_data.rb +36 -0
  152. data/lib/braintree/transaction/payment_receipt/merchant_address.rb +19 -0
  153. data/lib/braintree/transaction/payment_receipt.rb +31 -0
  154. data/lib/braintree/transaction/paypal_details.rb +40 -0
  155. data/lib/braintree/transaction/paypal_here_details.rb +23 -0
  156. data/lib/braintree/transaction/samsung_pay_card_details.rb +50 -0
  157. data/lib/braintree/transaction/sepa_direct_debit_account_details.rb +27 -0
  158. data/lib/braintree/transaction/status_details.rb +6 -2
  159. data/lib/braintree/transaction/subscription_details.rb +5 -2
  160. data/lib/braintree/transaction/us_bank_account_details.rb +22 -0
  161. data/lib/braintree/transaction/venmo_account_details.rb +17 -0
  162. data/lib/braintree/transaction/visa_checkout_card_details.rb +51 -0
  163. data/lib/braintree/transaction.rb +293 -150
  164. data/lib/braintree/transaction_gateway.rb +303 -59
  165. data/lib/braintree/transaction_line_item.rb +43 -0
  166. data/lib/braintree/transaction_line_item_gateway.rb +19 -0
  167. data/lib/braintree/transaction_review.rb +18 -0
  168. data/lib/braintree/transaction_search.rb +17 -9
  169. data/lib/braintree/unknown_payment_method.rb +26 -0
  170. data/lib/braintree/us_bank_account.rb +57 -0
  171. data/lib/braintree/us_bank_account_gateway.rb +17 -0
  172. data/lib/braintree/us_bank_account_verification.rb +89 -0
  173. data/lib/braintree/us_bank_account_verification_gateway.rb +51 -0
  174. data/lib/braintree/us_bank_account_verification_search.rb +19 -0
  175. data/lib/braintree/util.rb +91 -11
  176. data/lib/braintree/validation_error.rb +14 -5
  177. data/lib/braintree/validation_error_collection.rb +5 -5
  178. data/lib/braintree/venmo_account.rb +34 -0
  179. data/lib/braintree/venmo_profile_data.rb +25 -0
  180. data/lib/braintree/version.rb +2 -2
  181. data/lib/braintree/visa_checkout_card.rb +90 -0
  182. data/lib/braintree/webhook_notification.rb +146 -0
  183. data/lib/braintree/webhook_notification_gateway.rb +46 -0
  184. data/lib/braintree/webhook_testing.rb +7 -0
  185. data/lib/braintree/webhook_testing_gateway.rb +1239 -0
  186. data/lib/braintree/xml/generator.rb +18 -10
  187. data/lib/braintree/xml/libxml.rb +1 -1
  188. data/lib/braintree/xml/parser.rb +24 -36
  189. data/lib/braintree/xml/rexml.rb +6 -7
  190. data/lib/braintree/xml.rb +1 -2
  191. data/lib/braintree.rb +186 -52
  192. data/lib/ssl/api_braintreegateway_com.ca.crt +474 -0
  193. data/spec/fixtures/files/bt_logo.png +0 -0
  194. data/spec/fixtures/files/gif_extension_bt_logo.gif +0 -0
  195. data/spec/fixtures/files/malformed_pdf.pdf +1 -0
  196. data/spec/fixtures/files/too_long.pdf +0 -0
  197. data/spec/integration/braintree/add_on_spec.rb +46 -0
  198. data/spec/integration/braintree/address_spec.rb +101 -178
  199. data/spec/integration/braintree/advanced_search_spec.rb +100 -97
  200. data/spec/integration/braintree/apple_pay_spec.rb +63 -0
  201. data/spec/integration/braintree/braintree_gateway_spec.rb +72 -0
  202. data/spec/integration/braintree/client_api/client_token_spec.rb +407 -0
  203. data/spec/integration/braintree/client_api/spec_helper.rb +300 -0
  204. data/spec/integration/braintree/credit_card_spec.rb +885 -654
  205. data/spec/integration/braintree/credit_card_verification_search_spec.rb +193 -0
  206. data/spec/integration/braintree/credit_card_verification_spec.rb +473 -0
  207. data/spec/integration/braintree/customer_search_spec.rb +69 -21
  208. data/spec/integration/braintree/customer_session_spec.rb +143 -0
  209. data/spec/integration/braintree/customer_spec.rb +1437 -518
  210. data/spec/integration/braintree/disbursement_spec.rb +31 -0
  211. data/spec/integration/braintree/discount_spec.rb +34 -0
  212. data/spec/integration/braintree/dispute_search_spec.rb +165 -0
  213. data/spec/integration/braintree/dispute_spec.rb +333 -0
  214. data/spec/integration/braintree/document_upload_spec.rb +87 -0
  215. data/spec/integration/braintree/error_codes_spec.rb +3 -3
  216. data/spec/integration/braintree/exchange_rate_quote_spec.rb +97 -0
  217. data/spec/integration/braintree/graphql_client_spec.rb +72 -0
  218. data/spec/integration/braintree/http_spec.rb +106 -56
  219. data/spec/integration/braintree/merchant_account_spec.rb +603 -0
  220. data/spec/integration/braintree/merchant_spec.rb +227 -0
  221. data/spec/integration/braintree/oauth_spec.rb +225 -0
  222. data/spec/integration/braintree/package_tracking_spec.rb +130 -0
  223. data/spec/integration/braintree/payment_method_nonce_spec.rb +345 -0
  224. data/spec/integration/braintree/payment_method_spec.rb +2146 -0
  225. data/spec/integration/braintree/payment_method_us_bank_account_spec.rb +325 -0
  226. data/spec/integration/braintree/paypal_account_spec.rb +299 -0
  227. data/spec/integration/braintree/paypal_payment_resource_spec.rb +141 -0
  228. data/spec/integration/braintree/plan_spec.rb +136 -0
  229. data/spec/integration/braintree/samsung_pay_card_spec.rb +146 -0
  230. data/spec/integration/braintree/sepa_direct_debit_account_spec.rb +194 -0
  231. data/spec/integration/braintree/settlement_batch_summary_spec.rb +62 -0
  232. data/spec/integration/braintree/subscription_spec.rb +785 -431
  233. data/spec/integration/braintree/test/transaction_amounts_spec.rb +4 -4
  234. data/spec/integration/braintree/test_transaction_spec.rb +145 -0
  235. data/spec/integration/braintree/transaction_line_item_spec.rb +44 -0
  236. data/spec/integration/braintree/transaction_search_spec.rb +745 -156
  237. data/spec/integration/braintree/transaction_spec.rb +7452 -1288
  238. data/spec/integration/braintree/transaction_us_bank_account_spec.rb +196 -0
  239. data/spec/integration/braintree/us_bank_account_spec.rb +113 -0
  240. data/spec/integration/braintree/us_bank_account_verification_search_spec.rb +178 -0
  241. data/spec/integration/braintree/us_bank_account_verification_spec.rb +240 -0
  242. data/spec/integration/braintree/visa_checkout_card_spec.rb +110 -0
  243. data/spec/integration/spec_helper.rb +61 -5
  244. data/spec/oauth_test_helper.rb +17 -0
  245. data/spec/script/httpsd.rb +6 -6
  246. data/spec/spec.opts +4 -0
  247. data/spec/spec_helper.rb +77 -21
  248. data/spec/ssl/certificate.crt +17 -0
  249. data/spec/ssl/geotrust_global.crt +20 -0
  250. data/spec/ssl/privateKey.key +15 -0
  251. data/spec/unit/braintree/address_spec.rb +27 -16
  252. data/spec/unit/braintree/apple_pay_card_spec.rb +133 -0
  253. data/spec/unit/braintree/base_module_spec.rb +4 -4
  254. data/spec/unit/braintree/client_token_spec.rb +37 -0
  255. data/spec/unit/braintree/configuration_spec.rb +293 -43
  256. data/spec/unit/braintree/credentials_parser_spec.rb +81 -0
  257. data/spec/unit/braintree/credit_card_spec.rb +138 -47
  258. data/spec/unit/braintree/credit_card_verification_gateway_spec.rb +56 -0
  259. data/spec/unit/braintree/credit_card_verification_search_spec.rb +79 -0
  260. data/spec/unit/braintree/credit_card_verification_spec.rb +132 -6
  261. data/spec/unit/braintree/customer_session_gateway_spec.rb +120 -0
  262. data/spec/unit/braintree/customer_spec.rb +196 -40
  263. data/spec/unit/braintree/digest_spec.rb +16 -3
  264. data/spec/unit/braintree/disbursement_spec.rb +131 -0
  265. data/spec/unit/braintree/dispute_search_spec.rb +66 -0
  266. data/spec/unit/braintree/dispute_spec.rb +479 -0
  267. data/spec/unit/braintree/document_upload_spec.rb +35 -0
  268. data/spec/unit/braintree/enriched_customer_data_spec.rb +41 -0
  269. data/spec/unit/braintree/error_result_spec.rb +11 -11
  270. data/spec/unit/braintree/errors_spec.rb +17 -17
  271. data/spec/unit/braintree/exchange_rate_quote_input_spec.rb +42 -0
  272. data/spec/unit/braintree/exchange_rate_quote_request_spec.rb +82 -0
  273. data/spec/unit/braintree/exchange_rate_quote_response_spec.rb +52 -0
  274. data/spec/unit/braintree/exchange_rate_quote_spec.rb +42 -0
  275. data/spec/unit/braintree/exchange_rate_spec.rb +23 -0
  276. data/spec/unit/braintree/google_pay_card_spec.rb +8 -0
  277. data/spec/unit/braintree/graphql/create_customer_session_input_spec.rb +81 -0
  278. data/spec/unit/braintree/graphql/customer_recommendations_input_spec.rb +110 -0
  279. data/spec/unit/braintree/graphql/customer_session_input_spec.rb +81 -0
  280. data/spec/unit/braintree/graphql/phone_input_spec.rb +51 -0
  281. data/spec/unit/braintree/graphql/update_customer_session_input_spec.rb +93 -0
  282. data/spec/unit/braintree/graphql_client_spec.rb +37 -0
  283. data/spec/unit/braintree/http_spec.rb +164 -2
  284. data/spec/unit/braintree/local_payment_completed_spec.rb +90 -0
  285. data/spec/unit/braintree/local_payment_expired_spec.rb +24 -0
  286. data/spec/unit/braintree/local_payment_funded_spec.rb +34 -0
  287. data/spec/unit/braintree/merchant_account_spec.rb +33 -0
  288. data/spec/unit/braintree/meta_checkout_card_details_spec.rb +60 -0
  289. data/spec/unit/braintree/meta_checkout_card_spec.rb +62 -0
  290. data/spec/unit/braintree/meta_checkout_token_details_spec.rb +63 -0
  291. data/spec/unit/braintree/meta_checkout_token_spec.rb +65 -0
  292. data/spec/unit/braintree/modification_spec.rb +7 -0
  293. data/spec/unit/braintree/package_tracking_spec.rb +77 -0
  294. data/spec/unit/braintree/payment_method_customer_data_updated_metadata_spec.rb +45 -0
  295. data/spec/unit/braintree/payment_method_nonce_details_payer_info_spec.rb +31 -0
  296. data/spec/unit/braintree/payment_method_nonce_details_spec.rb +51 -0
  297. data/spec/unit/braintree/payment_method_nonce_spec.rb +43 -0
  298. data/spec/unit/braintree/payment_method_spec.rb +135 -0
  299. data/spec/unit/braintree/paypal_account_spec.rb +53 -0
  300. data/spec/unit/braintree/paypal_payment_resource_spec.rb +125 -0
  301. data/spec/unit/braintree/resource_collection_spec.rb +44 -3
  302. data/spec/unit/braintree/risk_data/liability_shift.rb +26 -0
  303. data/spec/unit/braintree/risk_data_spec.rb +55 -0
  304. data/spec/unit/braintree/sepa_debit_account_nonce_details_spec.rb +29 -0
  305. data/spec/unit/braintree/sepa_debit_account_spec.rb +86 -0
  306. data/spec/unit/braintree/sha256_digest_spec.rb +11 -0
  307. data/spec/unit/braintree/signature_service_spec.rb +23 -0
  308. data/spec/unit/braintree/subscription_search_spec.rb +25 -18
  309. data/spec/unit/braintree/subscription_spec.rb +34 -7
  310. data/spec/unit/braintree/successful_result_spec.rb +9 -9
  311. data/spec/unit/braintree/three_d_secure_info_spec.rb +69 -0
  312. data/spec/unit/braintree/transaction/apple_pay_details_spec.rb +8 -0
  313. data/spec/unit/braintree/transaction/credit_card_details_spec.rb +34 -6
  314. data/spec/unit/braintree/transaction/customer_details_spec.rb +3 -2
  315. data/spec/unit/braintree/transaction/deposit_details_spec.rb +18 -0
  316. data/spec/unit/braintree/transaction/google_pay_details_spec.rb +8 -0
  317. data/spec/unit/braintree/transaction/installment_spec.rb +25 -0
  318. data/spec/unit/braintree/transaction/local_payment_details_spec.rb +36 -0
  319. data/spec/unit/braintree/transaction/meta_checkout_card_details_spec.rb +8 -0
  320. data/spec/unit/braintree/transaction/meta_checkout_token_details_spec.rb +8 -0
  321. data/spec/unit/braintree/transaction/payment_receipt_spec.rb +73 -0
  322. data/spec/unit/braintree/transaction/paypal_details_spec.rb +68 -0
  323. data/spec/unit/braintree/transaction/sepa_direct_debit_account_details_spec.rb +33 -0
  324. data/spec/unit/braintree/transaction/visa_checkout_card_details_spec.rb +8 -0
  325. data/spec/unit/braintree/transaction_gateway_spec.rb +150 -0
  326. data/spec/unit/braintree/transaction_search_spec.rb +12 -12
  327. data/spec/unit/braintree/transaction_spec.rb +366 -52
  328. data/spec/unit/braintree/unknown_payment_method_spec.rb +33 -0
  329. data/spec/unit/braintree/us_bank_account_spec.rb +13 -0
  330. data/spec/unit/braintree/us_bank_account_verification_search_spec.rb +60 -0
  331. data/spec/unit/braintree/us_bank_account_verification_spec.rb +98 -0
  332. data/spec/unit/braintree/util_spec.rb +199 -39
  333. data/spec/unit/braintree/validation_error_collection_spec.rb +336 -133
  334. data/spec/unit/braintree/validation_error_spec.rb +4 -4
  335. data/spec/unit/braintree/venmo_profile_data_spec.rb +43 -0
  336. data/spec/unit/braintree/visa_checkout_card_spec.rb +8 -0
  337. data/spec/unit/braintree/webhook_notification_spec.rb +977 -0
  338. data/spec/unit/braintree/xml/libxml_spec.rb +5 -5
  339. data/spec/unit/braintree/xml/parser_spec.rb +39 -5
  340. data/spec/unit/braintree/xml/rexml_spec.rb +5 -5
  341. data/spec/unit/braintree/xml_spec.rb +39 -32
  342. data/spec/unit/braintree_spec.rb +3 -2
  343. data/spec/unit/credit_card_details_spec.rb +8 -0
  344. metadata +314 -73
  345. data/README.rdoc +0 -80
  346. data/lib/braintree/test/credit_card_numbers.rb +0 -52
  347. data/lib/braintree/transparent_redirect.rb +0 -51
  348. data/lib/braintree/transparent_redirect_gateway.rb +0 -105
  349. data/lib/ssl/sandbox_braintreegateway_com.ca.crt +0 -19
  350. data/lib/ssl/www_braintreegateway_com.ca.crt +0 -202
  351. data/spec/hacks/tcp_socket.rb +0 -18
  352. data/spec/integration/braintree/transparent_redirect_spec.rb +0 -236
  353. data/spec/unit/braintree/transparent_redirect_spec.rb +0 -160
@@ -0,0 +1,32 @@
1
+ # Phone number input for PayPal customer session.
2
+
3
+ module Braintree
4
+ class PhoneInput
5
+ include BaseModule
6
+
7
+ attr_reader :attrs
8
+ attr_reader :country_phone_code
9
+ attr_reader :phone_number
10
+ attr_reader :extension_number
11
+
12
+ def initialize(attributes)
13
+ @attrs = attributes.keys
14
+ set_instance_variables_from_hash(attributes)
15
+ end
16
+
17
+ def inspect
18
+ inspected_attributes = @attrs.map { |attr| "#{attr}:#{send(attr).inspect}" }
19
+ "#<#{self.class} #{inspected_attributes.join(" ")}>"
20
+ end
21
+
22
+ def to_graphql_variables
23
+ variables = {}
24
+ variables["countryPhoneCode"] = country_phone_code if country_phone_code
25
+ variables["phoneNumber"] = phone_number if phone_number
26
+ variables["extensionNumber"] = extension_number if extension_number
27
+ variables
28
+ end
29
+ end
30
+ end
31
+
32
+
@@ -0,0 +1,37 @@
1
+ # Represents the input to request an update to a PayPal customer session.
2
+
3
+ module Braintree
4
+ class UpdateCustomerSessionInput
5
+ include BaseModule
6
+
7
+ attr_reader :attrs
8
+ attr_reader :merchant_account_id
9
+ attr_reader :session_id
10
+ attr_reader :customer
11
+
12
+ def initialize(attributes)
13
+ unless attributes[:session_id]
14
+ raise ArgumentError, "Expected hash to contain a :session_id"
15
+ end
16
+ @attrs = attributes.keys
17
+ set_instance_variables_from_hash(attributes)
18
+ @customer = attributes[:customer] ? CustomerSessionInput.new(attributes[:customer]) : nil
19
+ end
20
+
21
+ def inspect
22
+ inspected_attributes = @attrs.map { |attr| "#{attr}:#{send(attr).inspect}" }
23
+ "#<#{self.class} #{inspected_attributes.join(" ")}>"
24
+ end
25
+
26
+ def to_graphql_variables
27
+ variables = {}
28
+ variables["merchantAccountId"] = merchant_account_id if merchant_account_id
29
+ variables["sessionId"] = session_id if session_id
30
+ variables["customer"] = customer.to_graphql_variables if customer
31
+ variables
32
+ end
33
+
34
+ end
35
+ end
36
+
37
+
@@ -0,0 +1,32 @@
1
+ # Represents the customer recommendations information associated with a PayPal customer session.
2
+
3
+ module Braintree
4
+ class CustomerRecommendationsPayload
5
+ include BaseModule
6
+
7
+ attr_reader :attrs
8
+ attr_reader :is_in_paypal_network
9
+ attr_reader :recommendations
10
+
11
+ def initialize(attributes)
12
+ @attrs = [:is_in_paypal_network, :recommendations]
13
+ @is_in_paypal_network = attributes[:isInPayPalNetwork] if attributes[:isInPayPalNetwork]
14
+ @recommendations = CustomerRecommendations._new(attributes[:recommendations]) if attributes[:recommendations]
15
+ end
16
+
17
+ def inspect
18
+ inspected_attributes = @attrs.map { |attr| "#{attr}:#{send(attr).inspect}" }
19
+ "#<#{self.class} #{inspected_attributes.join(" ")}>"
20
+ end
21
+
22
+ class << self
23
+ protected :new
24
+ end
25
+
26
+ def self._new(*args)
27
+ self.new(*args)
28
+ end
29
+ end
30
+ end
31
+
32
+
@@ -0,0 +1,33 @@
1
+ # Represents the payment method and priority associated with a PayPal customer session.
2
+
3
+ module Braintree
4
+ class PaymentOptions
5
+ include BaseModule
6
+
7
+ attr_reader :attrs
8
+ attr_reader :payment_option
9
+ attr_reader :recommended_priority
10
+
11
+ def initialize(attributes)
12
+ @attrs = [:payment_option, :recommended_priority]
13
+ @payment_option = attributes[:paymentOption] if attributes[:paymentOption]
14
+ @recommended_priority = attributes[:recommendedPriority] if attributes[:recommendedPriority]
15
+
16
+ end
17
+
18
+ def inspect
19
+ inspected_attributes = @attrs.map { |attr| "#{attr}:#{send(attr).inspect}" }
20
+ "#<#{self.class} #{inspected_attributes.join(" ")}>"
21
+ end
22
+
23
+ class << self
24
+ protected :new
25
+ end
26
+
27
+ def self._new(*args)
28
+ self.new(*args)
29
+ end
30
+ end
31
+ end
32
+
33
+
@@ -0,0 +1,34 @@
1
+ # A union of all possible customer recommendations associated with a PayPal customer session.
2
+
3
+ module Braintree
4
+ class CustomerRecommendations
5
+ include BaseModule
6
+
7
+ attr_reader :attrs
8
+ attr_reader :payment_options
9
+
10
+ def initialize(attributes)
11
+ @attrs = [:payment_options]
12
+ if attributes.nil?
13
+ @payment_options = []
14
+ else
15
+ @payment_options = (attributes[:paymentOptions] || []).map { |payment_options_hash| PaymentOptions._new(payment_options_hash) }
16
+ end
17
+ end
18
+
19
+ def inspect
20
+ inspected_attributes = @attrs.map { |attr| "#{attr}:#{send(attr).inspect}" }
21
+ "#<#{self.class} #{inspected_attributes.join(" ")}>"
22
+ end
23
+
24
+ class << self
25
+ protected :new
26
+ end
27
+
28
+ def self._new(*args)
29
+ self.new(*args)
30
+ end
31
+ end
32
+ end
33
+
34
+
@@ -0,0 +1,50 @@
1
+ module Braintree
2
+ class GraphQLClient < Http
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
+
34
+ def self.get_validation_errors(response)
35
+ return nil unless response.key?(:errors) && response[:errors].is_a?(Array)
36
+ validation_errors = response[:errors].map do |error|
37
+ {
38
+ :attribute => "",
39
+ :code => get_validation_error_code(error),
40
+ :message => error[:message]
41
+ }
42
+ end
43
+ {errors: validation_errors}
44
+ end
45
+
46
+ def self.get_validation_error_code(error)
47
+ error[:extensions] && error[:extensions][:legacyCode] rescue nil
48
+ end
49
+ end
50
+ end
@@ -1,30 +1,38 @@
1
1
  module Braintree
2
- class Http # :nodoc:
2
+ class Http
3
+
4
+ LINE_FEED = "\r\n"
3
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 = {})
9
11
  response = _http_do Net::HTTP::Delete, path
10
- if response.code.to_i == 200
12
+ if response.code.to_i == 200 || response.code.to_i == 204
11
13
  true
14
+ elsif response.code.to_i == 422
15
+ Xml.hash_from_xml(_body(response))
12
16
  else
13
17
  Util.raise_exception_for_status_code(response.code)
14
18
  end
15
19
  end
16
20
 
17
- def get(path)
21
+ def get(path, query_params = {})
18
22
  response = _http_do Net::HTTP::Get, path
19
- if response.code.to_i == 200
23
+ if response.code.to_i == 200 || response.code.to_i == 422
20
24
  Xml.hash_from_xml(_body(response))
21
25
  else
22
26
  Util.raise_exception_for_status_code(response.code)
23
27
  end
24
28
  end
25
29
 
26
- def post(path, params = nil)
27
- response = _http_do Net::HTTP::Post, path, _build_xml(params)
30
+ def post(path, params = nil, file = nil)
31
+ body = params
32
+ if !file
33
+ body = _build_xml(params)
34
+ end
35
+ response = _http_do Net::HTTP::Post, path, body, file
28
36
  if response.code.to_i == 200 || response.code.to_i == 201 || response.code.to_i == 422
29
37
  Xml.hash_from_xml(_body(response))
30
38
  else
@@ -42,31 +50,87 @@ module Braintree
42
50
  end
43
51
 
44
52
  def _build_xml(params)
45
- return nil if params.nil?
53
+ return "" if params.nil?
46
54
  Braintree::Xml.hash_to_xml params
47
55
  end
48
56
 
49
- def _http_do(http_verb, path, body = nil)
50
- connection = Net::HTTP.new(@config.server, @config.port)
51
- connection.read_timeout = 60
57
+ def _build_query_string(params)
58
+ if params.empty?
59
+ ""
60
+ else
61
+ "?" + params.map do |x, y|
62
+ raise(ArgumentError, "Nested hashes aren't supported in query parameters") if y.respond_to?(:to_hash)
63
+ "#{x}=#{y}"
64
+ end.join("&")
65
+ end
66
+ end
67
+
68
+ def _setup_connection(server = @config.server, port = @config.port)
69
+ if @config.proxy_address
70
+ Net::HTTP.new(
71
+ server,
72
+ port,
73
+ @config.proxy_address,
74
+ @config.proxy_port,
75
+ @config.proxy_user,
76
+ @config.proxy_pass,
77
+ )
78
+ else
79
+ Net::HTTP.new(server, port)
80
+ end
81
+ end
82
+
83
+ def _compose_headers(header_overrides = {})
84
+ headers = {}
85
+ headers["Accept"] = "application/xml"
86
+ headers["User-Agent"] = @config.user_agent
87
+ headers["Accept-Encoding"] = "gzip"
88
+ headers["X-ApiVersion"] = @config.api_version
89
+ headers["Content-Type"] = "application/xml"
90
+
91
+ headers.merge(header_overrides)
92
+ end
93
+
94
+ def _http_do(http_verb, path, body = nil, file = nil, connection = nil, header_overrides = {})
95
+ connection ||= _setup_connection
96
+
97
+ connection.open_timeout = @config.http_open_timeout
98
+ connection.read_timeout = @config.http_read_timeout
52
99
  if @config.ssl?
53
100
  connection.use_ssl = true
101
+ connection.ssl_version = @config.ssl_version if @config.ssl_version
54
102
  connection.verify_mode = OpenSSL::SSL::VERIFY_PEER
55
103
  connection.ca_file = @config.ca_file
56
104
  connection.verify_callback = proc { |preverify_ok, ssl_context| _verify_ssl_certificate(preverify_ok, ssl_context) }
57
105
  end
106
+
58
107
  connection.start do |http|
59
- request = http_verb.new("#{@config.base_merchant_path}#{path}")
60
- request["Accept"] = "application/xml"
61
- request["User-Agent"] = @config.user_agent
62
- request["Accept-Encoding"] = "gzip"
63
- request["X-ApiVersion"] = @config.api_version
64
- request.basic_auth @config.public_key, @config.private_key
108
+ request = http_verb.new(path)
109
+ _compose_headers(header_overrides).each { |header, value| request[header] = value }
110
+ if @config.client_credentials?
111
+ request.basic_auth @config.client_id, @config.client_secret
112
+ elsif @config.access_token
113
+ request["Authorization"] = "Bearer #{@config.access_token}"
114
+ else
115
+ request.basic_auth @config.public_key, @config.private_key
116
+ end
65
117
  @config.logger.debug "[Braintree] [#{_current_time}] #{request.method} #{path}"
66
118
  if body
67
- request["Content-Type"] = "application/xml"
68
- request.body = body
69
- @config.logger.debug _format_and_sanitize_body_for_log(body)
119
+ if file
120
+ boundary = DateTime.now.strftime("%Q")
121
+ request["Content-Type"] = "multipart/form-data; boundary=#{boundary}"
122
+
123
+ form_params = []
124
+ body.each do |k, v|
125
+ form_params.push(_add_form_field(k, v))
126
+ end
127
+ form_params.push(_add_file_part("file", file))
128
+ request.body = form_params.collect { |p| "--" + boundary + "#{LINE_FEED}" + p }.join("") + "--" + boundary + "--"
129
+ @config.logger.debug _format_and_sanitize_body_for_log(_build_xml(body))
130
+ else
131
+ request.body = body
132
+ @config.logger.debug _format_and_sanitize_body_for_log(body)
133
+ end
70
134
  end
71
135
  response = http.request(request)
72
136
  @config.logger.info "[Braintree] [#{_current_time}] #{request.method} #{path} #{response.code}"
@@ -76,11 +140,39 @@ module Braintree
76
140
  end
77
141
  response
78
142
  end
143
+ rescue OpenSSL::SSL::SSLError
144
+ raise Braintree::SSLCertificateError
145
+ end
146
+
147
+ def _add_form_field(key, value)
148
+ return "Content-Disposition: form-data; name=\"#{key}\"#{LINE_FEED}#{LINE_FEED}#{value}#{LINE_FEED}"
149
+ end
150
+
151
+ def _add_file_part(key, file)
152
+ mime_type = _mime_type_for_file_name(file.path)
153
+ return "Content-Disposition: form-data; name=\"#{key}\"; filename=\"#{file.path}\"#{LINE_FEED}" +
154
+ "Content-Type: #{mime_type}#{LINE_FEED}#{LINE_FEED}#{file.read}#{LINE_FEED}"
155
+ end
156
+
157
+ def _mime_type_for_file_name(filename)
158
+ file_extension = File.extname(filename).strip.downcase[1..-1]
159
+ if file_extension == "jpeg" || file_extension == "jpg"
160
+ return "image/jpeg"
161
+ elsif file_extension == "png"
162
+ return "image/png"
163
+ elsif file_extension == "pdf"
164
+ return "application/pdf"
165
+ else
166
+ return "application/octet-stream"
167
+ end
79
168
  end
80
169
 
81
170
  def _body(response)
82
- if response.header["Content-Encoding"] == "gzip"
171
+ content_encoding = response.header["Content-Encoding"]
172
+ if content_encoding == "gzip"
83
173
  Zlib::GzipReader.new(StringIO.new(response.body)).read
174
+ elsif content_encoding.nil?
175
+ ""
84
176
  else
85
177
  raise UnexpectedError, "expected a gzipped response"
86
178
  end
@@ -92,8 +184,9 @@ module Braintree
92
184
 
93
185
  def _format_and_sanitize_body_for_log(input_xml)
94
186
  formatted_xml = input_xml.gsub(/^/, "[Braintree] ")
95
- formatted_xml = formatted_xml.gsub(/<number>(.{6}).+?(.{4})<\/number>/, '<number>\1******\2</number>')
96
- formatted_xml = formatted_xml.gsub(/<cvv>.+?<\/cvv>/, '<cvv>***</cvv>')
187
+ formatted_xml = formatted_xml.gsub(/<number>(.{6}).+?(.{4})<\/number>/m, '<number>\1******\2</number>')
188
+ formatted_xml = formatted_xml.gsub(/<cvv>.+?<\/cvv>/m, "<cvv>***</cvv>")
189
+ formatted_xml = formatted_xml.gsub(/<encrypted-card-data>.+?<\/encrypted-card-data>/m, "<encrypted-card-data>***</encrypted-card-data>")
97
190
  formatted_xml
98
191
  end
99
192
 
@@ -101,9 +194,10 @@ module Braintree
101
194
  if preverify_ok != true || ssl_context.error != 0
102
195
  err_msg = "SSL Verification failed -- Preverify: #{preverify_ok}, Error: #{ssl_context.error_string} (#{ssl_context.error})"
103
196
  @config.logger.error err_msg
104
- raise SSLCertificateError.new(err_msg)
197
+ false
198
+ else
199
+ true
105
200
  end
106
- true
107
201
  end
108
202
  end
109
203
  end
@@ -0,0 +1,23 @@
1
+ module Braintree
2
+ class LocalPaymentCompleted
3
+ class BlikAlias
4
+ include BaseModule
5
+
6
+ attr_reader :key
7
+ attr_reader :label
8
+
9
+ def initialize(attributes)
10
+ set_instance_variables_from_hash attributes unless attributes.nil?
11
+ end
12
+
13
+ def inspect
14
+ attrs = [:key, :label]
15
+ formatted_attrs = attrs.map do |attr|
16
+ "#{attr}: #{send(attr).inspect}"
17
+ end
18
+
19
+ "#<#{formatted_attrs.join(", ")}>"
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,28 @@
1
+ module Braintree
2
+ class LocalPaymentCompleted
3
+ include BaseModule
4
+
5
+ attr_reader :bic
6
+ attr_reader :blik_aliases
7
+ attr_reader :iban_last_chars
8
+ attr_reader :payer_id
9
+ attr_reader :payer_name
10
+ attr_reader :payment_id
11
+ attr_reader :payment_method_nonce
12
+ attr_reader :transaction
13
+
14
+ def initialize(attributes)
15
+ set_instance_variables_from_hash(attributes)
16
+ @transaction = Transaction._new(Configuration.gateway, transaction) unless transaction.nil?
17
+ blik_aliases.map { |attrs| BlikAlias.new(attrs) } if blik_aliases
18
+ end
19
+
20
+ class << self
21
+ protected :new
22
+ end
23
+
24
+ def self._new(*args)
25
+ self.new(*args)
26
+ end
27
+ end
28
+ 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)
9
+ set_instance_variables_from_hash(attributes)
10
+ end
11
+
12
+ class << self
13
+ protected :new
14
+ end
15
+
16
+ def self._new(*args)
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)
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)
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)
8
+ set_instance_variables_from_hash(attributes)
9
+ end
10
+
11
+ class << self
12
+ protected :new
13
+ end
14
+
15
+ def self._new(*args)
16
+ self.new(*args)
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,34 @@
1
+ module Braintree
2
+ class Merchant
3
+ include BaseModule
4
+
5
+ attr_reader :company_name
6
+ attr_reader :country_code_alpha2
7
+ attr_reader :country_code_alpha3
8
+ attr_reader :country_code_numeric
9
+ attr_reader :country_name
10
+ attr_reader :email
11
+ attr_reader :id
12
+ attr_reader :merchant_accounts
13
+
14
+ def initialize(gateway, attributes)
15
+ @merchant_accounts = attributes.delete(:merchant_accounts).map do |merchant_account|
16
+ MerchantAccount._new(gateway, merchant_account)
17
+ end
18
+
19
+ set_instance_variables_from_hash(attributes)
20
+ end
21
+
22
+ class << self
23
+ protected :new
24
+ end
25
+
26
+ def self._new(*args)
27
+ self.new(*args)
28
+ end
29
+
30
+ def self.provision_raw_apple_pay
31
+ Configuration.gateway.merchant.provision_raw_apple_pay
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,16 @@
1
+ module Braintree
2
+ class MerchantAccount
3
+ class AddressDetails
4
+ include BaseModule
5
+
6
+ attr_reader :locality
7
+ attr_reader :postal_code
8
+ attr_reader :region
9
+ attr_reader :street_address
10
+
11
+ def initialize(attributes)
12
+ set_instance_variables_from_hash attributes unless attributes.nil?
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,17 @@
1
+ module Braintree
2
+ class MerchantAccount
3
+ class BusinessDetails
4
+ include BaseModule
5
+
6
+ attr_reader :address_details
7
+ attr_reader :dba_name
8
+ attr_reader :legal_name
9
+ attr_reader :tax_id
10
+
11
+ def initialize(attributes)
12
+ set_instance_variables_from_hash attributes unless attributes.nil?
13
+ @address_details = MerchantAccount::AddressDetails.new(@address)
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,18 @@
1
+ module Braintree
2
+ class MerchantAccount
3
+ class FundingDetails
4
+ include BaseModule
5
+
6
+ attr_reader :account_number_last_4
7
+ attr_reader :descriptor
8
+ attr_reader :destination
9
+ attr_reader :email
10
+ attr_reader :mobile_phone
11
+ attr_reader :routing_number
12
+
13
+ def initialize(attributes)
14
+ set_instance_variables_from_hash attributes unless attributes.nil?
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,20 @@
1
+ module Braintree
2
+ class MerchantAccount
3
+ class IndividualDetails
4
+ include BaseModule
5
+
6
+ attr_reader :address_details
7
+ attr_reader :date_of_birth
8
+ attr_reader :email
9
+ attr_reader :first_name
10
+ attr_reader :last_name
11
+ attr_reader :phone
12
+ attr_reader :ssn_last_4
13
+
14
+ def initialize(attributes)
15
+ set_instance_variables_from_hash attributes unless attributes.nil?
16
+ @address_details = MerchantAccount::AddressDetails.new(@address)
17
+ end
18
+ end
19
+ end
20
+ end