stripe 5.55.0 → 13.5.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (380) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +567 -4
  3. data/Gemfile +12 -4
  4. data/Makefile +18 -3
  5. data/OPENAPI_VERSION +1 -0
  6. data/README.md +93 -21
  7. data/Rakefile +3 -6
  8. data/VERSION +1 -1
  9. data/examples/README.md +16 -0
  10. data/examples/example_template.rb +36 -0
  11. data/examples/meter_event_stream.rb +57 -0
  12. data/examples/thinevent_webhook_handler.rb +39 -0
  13. data/{bin → exe}/stripe-console +1 -1
  14. data/justfile +43 -0
  15. data/lib/data/ca-certificates.crt +1241 -1937
  16. data/lib/stripe/api_operations/create.rb +6 -2
  17. data/lib/stripe/api_operations/delete.rb +12 -7
  18. data/lib/stripe/api_operations/list.rb +6 -9
  19. data/lib/stripe/api_operations/nested_resource.rb +63 -35
  20. data/lib/stripe/api_operations/request.rb +29 -65
  21. data/lib/stripe/api_operations/save.rb +20 -10
  22. data/lib/stripe/api_operations/search.rb +11 -9
  23. data/lib/stripe/api_operations/singleton_save.rb +90 -0
  24. data/lib/stripe/api_requestor.rb +1131 -0
  25. data/lib/stripe/api_resource.rb +48 -18
  26. data/lib/stripe/api_resource_test_helpers.rb +9 -3
  27. data/lib/stripe/api_version.rb +8 -0
  28. data/lib/stripe/connection_manager.rb +5 -7
  29. data/lib/stripe/errors.rb +11 -13
  30. data/lib/stripe/event_types.rb +14 -0
  31. data/lib/stripe/events/v1_billing_meter_error_report_triggered_event.rb +23 -0
  32. data/lib/stripe/events/v1_billing_meter_no_meter_found_event.rb +13 -0
  33. data/lib/stripe/instrumentation.rb +37 -15
  34. data/lib/stripe/list_object.rb +5 -3
  35. data/lib/stripe/multipart_encoder.rb +7 -7
  36. data/lib/stripe/oauth.rb +14 -21
  37. data/lib/stripe/object_types.rb +151 -103
  38. data/lib/stripe/request_options.rb +129 -0
  39. data/lib/stripe/resources/account.rb +129 -25
  40. data/lib/stripe/resources/account_link.rb +12 -0
  41. data/lib/stripe/resources/account_session.rb +25 -0
  42. data/lib/stripe/resources/alipay_account.rb +1 -1
  43. data/lib/stripe/resources/apple_pay_domain.rb +38 -0
  44. data/lib/stripe/resources/application_fee.rb +9 -2
  45. data/lib/stripe/resources/application_fee_refund.rb +9 -2
  46. data/lib/stripe/resources/apps/secret.rb +55 -0
  47. data/lib/stripe/resources/balance.rb +14 -0
  48. data/lib/stripe/resources/balance_transaction.rb +19 -0
  49. data/lib/stripe/resources/bank_account.rb +53 -4
  50. data/lib/stripe/resources/billing/alert.rb +87 -0
  51. data/lib/stripe/resources/billing/credit_balance_summary.rb +14 -0
  52. data/lib/stripe/resources/billing/credit_balance_transaction.rb +26 -0
  53. data/lib/stripe/resources/billing/credit_grant.rb +90 -0
  54. data/lib/stripe/resources/billing/meter.rb +85 -0
  55. data/lib/stripe/resources/billing/meter_event.rb +26 -0
  56. data/lib/stripe/resources/billing/meter_event_adjustment.rb +26 -0
  57. data/lib/stripe/resources/billing/meter_event_summary.rb +17 -0
  58. data/lib/stripe/resources/billing_portal/configuration.rb +34 -0
  59. data/lib/stripe/resources/billing_portal/session.rb +27 -0
  60. data/lib/stripe/resources/capability.rb +7 -2
  61. data/lib/stripe/resources/card.rb +34 -3
  62. data/lib/stripe/resources/cash_balance.rb +4 -0
  63. data/lib/stripe/resources/charge.rb +52 -3
  64. data/lib/stripe/resources/checkout/session.rb +83 -5
  65. data/lib/stripe/resources/climate/order.rb +67 -0
  66. data/lib/stripe/resources/climate/product.rb +27 -0
  67. data/lib/stripe/resources/climate/supplier.rb +26 -0
  68. data/lib/stripe/resources/confirmation_token.rb +39 -0
  69. data/lib/stripe/resources/country_spec.rb +14 -0
  70. data/lib/stripe/resources/coupon.rb +48 -0
  71. data/lib/stripe/resources/credit_note.rb +67 -9
  72. data/lib/stripe/resources/credit_note_line_item.rb +4 -0
  73. data/lib/stripe/resources/customer.rb +172 -28
  74. data/lib/stripe/resources/customer_balance_transaction.rb +9 -1
  75. data/lib/stripe/resources/customer_cash_balance_transaction.rb +15 -0
  76. data/lib/stripe/resources/customer_session.rb +29 -0
  77. data/lib/stripe/resources/discount.rb +7 -0
  78. data/lib/stripe/resources/dispute.rb +41 -3
  79. data/lib/stripe/resources/entitlements/active_entitlement.rb +26 -0
  80. data/lib/stripe/resources/entitlements/feature.rb +49 -0
  81. data/lib/stripe/resources/ephemeral_key.rb +23 -0
  82. data/lib/stripe/resources/event.rb +38 -0
  83. data/lib/stripe/resources/exchange_rate.rb +34 -0
  84. data/lib/stripe/resources/file.rb +37 -15
  85. data/lib/stripe/resources/file_link.rb +26 -0
  86. data/lib/stripe/resources/financial_connections/account.rb +101 -6
  87. data/lib/stripe/resources/financial_connections/account_owner.rb +4 -0
  88. data/lib/stripe/resources/financial_connections/account_ownership.rb +4 -0
  89. data/lib/stripe/resources/financial_connections/session.rb +14 -0
  90. data/lib/stripe/resources/financial_connections/transaction.rb +26 -0
  91. data/lib/stripe/resources/forwarding/request.rb +52 -0
  92. data/lib/stripe/resources/funding_instructions.rb +8 -0
  93. data/lib/stripe/resources/identity/verification_report.rb +24 -0
  94. data/lib/stripe/resources/identity/verification_session.rb +117 -5
  95. data/lib/stripe/resources/invoice.rb +247 -20
  96. data/lib/stripe/resources/invoice_item.rb +54 -0
  97. data/lib/stripe/resources/invoice_line_item.rb +22 -1
  98. data/lib/stripe/resources/invoice_rendering_template.rb +65 -0
  99. data/lib/stripe/resources/issuing/authorization.rb +210 -5
  100. data/lib/stripe/resources/issuing/card.rb +128 -4
  101. data/lib/stripe/resources/issuing/cardholder.rb +36 -0
  102. data/lib/stripe/resources/issuing/dispute.rb +47 -2
  103. data/lib/stripe/resources/issuing/personalization_design.rb +119 -0
  104. data/lib/stripe/resources/issuing/physical_bundle.rb +26 -0
  105. data/lib/stripe/resources/issuing/token.rb +32 -0
  106. data/lib/stripe/resources/issuing/transaction.rb +79 -0
  107. data/lib/stripe/resources/line_item.rb +4 -0
  108. data/lib/stripe/resources/login_link.rb +4 -0
  109. data/lib/stripe/resources/mandate.rb +4 -0
  110. data/lib/stripe/resources/payment_intent.rb +238 -15
  111. data/lib/stripe/resources/payment_link.rb +39 -2
  112. data/lib/stripe/resources/payment_method.rb +78 -5
  113. data/lib/stripe/resources/payment_method_configuration.rb +59 -0
  114. data/lib/stripe/resources/payment_method_domain.rb +79 -0
  115. data/lib/stripe/resources/payout.rb +63 -5
  116. data/lib/stripe/resources/person.rb +8 -1
  117. data/lib/stripe/resources/plan.rb +51 -0
  118. data/lib/stripe/resources/price.rb +30 -1
  119. data/lib/stripe/resources/product.rb +55 -1
  120. data/lib/stripe/resources/product_feature.rb +13 -0
  121. data/lib/stripe/resources/promotion_code.rb +25 -0
  122. data/lib/stripe/resources/quote.rb +97 -39
  123. data/lib/stripe/resources/radar/early_fraud_warning.rb +17 -0
  124. data/lib/stripe/resources/radar/value_list.rb +56 -0
  125. data/lib/stripe/resources/radar/value_list_item.rb +46 -0
  126. data/lib/stripe/resources/refund.rb +70 -5
  127. data/lib/stripe/resources/reporting/report_run.rb +31 -0
  128. data/lib/stripe/resources/reporting/report_type.rb +21 -1
  129. data/lib/stripe/resources/reversal.rb +17 -2
  130. data/lib/stripe/resources/review.rb +24 -3
  131. data/lib/stripe/resources/setup_attempt.rb +12 -0
  132. data/lib/stripe/resources/setup_intent.rb +113 -7
  133. data/lib/stripe/resources/shipping_rate.rb +25 -0
  134. data/lib/stripe/resources/sigma/scheduled_query_run.rb +17 -0
  135. data/lib/stripe/resources/source.rb +52 -10
  136. data/lib/stripe/resources/source_transaction.rb +7 -0
  137. data/lib/stripe/resources/subscription.rb +118 -5
  138. data/lib/stripe/resources/subscription_item.rb +54 -6
  139. data/lib/stripe/resources/subscription_schedule.rb +60 -5
  140. data/lib/stripe/resources/tax/calculation.rb +48 -0
  141. data/lib/stripe/resources/tax/calculation_line_item.rb +13 -0
  142. data/lib/stripe/resources/tax/registration.rb +54 -0
  143. data/lib/stripe/resources/tax/settings.rb +17 -0
  144. data/lib/stripe/resources/tax/transaction.rb +56 -0
  145. data/lib/stripe/resources/tax/transaction_line_item.rb +13 -0
  146. data/lib/stripe/resources/tax_code.rb +9 -0
  147. data/lib/stripe/resources/tax_id.rb +34 -12
  148. data/lib/stripe/resources/tax_rate.rb +26 -0
  149. data/lib/stripe/resources/terminal/configuration.rb +54 -0
  150. data/lib/stripe/resources/terminal/connection_token.rb +16 -0
  151. data/lib/stripe/resources/terminal/location.rb +57 -0
  152. data/lib/stripe/resources/terminal/reader.rb +138 -11
  153. data/lib/stripe/resources/test_helpers/test_clock.rb +58 -3
  154. data/lib/stripe/resources/token.rb +29 -0
  155. data/lib/stripe/resources/topup.rb +40 -3
  156. data/lib/stripe/resources/transfer.rb +29 -6
  157. data/lib/stripe/resources/treasury/credit_reversal.rb +37 -0
  158. data/lib/stripe/resources/treasury/debit_reversal.rb +37 -0
  159. data/lib/stripe/resources/treasury/financial_account.rb +109 -0
  160. data/lib/stripe/resources/treasury/financial_account_features.rb +15 -0
  161. data/lib/stripe/resources/treasury/inbound_transfer.rb +130 -0
  162. data/lib/stripe/resources/treasury/outbound_payment.rb +152 -0
  163. data/lib/stripe/resources/treasury/outbound_transfer.rb +152 -0
  164. data/lib/stripe/resources/treasury/received_credit.rb +47 -0
  165. data/lib/stripe/resources/treasury/received_debit.rb +47 -0
  166. data/lib/stripe/resources/treasury/transaction.rb +26 -0
  167. data/lib/stripe/resources/treasury/transaction_entry.rb +30 -0
  168. data/lib/stripe/resources/usage_record.rb +9 -0
  169. data/lib/stripe/resources/usage_record_summary.rb +4 -0
  170. data/lib/stripe/resources/v2/billing/meter_event.rb +16 -0
  171. data/lib/stripe/resources/v2/billing/meter_event_adjustment.rb +15 -0
  172. data/lib/stripe/resources/v2/billing/meter_event_session.rb +15 -0
  173. data/lib/stripe/resources/v2/event.rb +13 -0
  174. data/lib/stripe/resources/v2/event_destination.rb +13 -0
  175. data/lib/stripe/resources/webhook_endpoint.rb +55 -0
  176. data/lib/stripe/resources.rb +51 -10
  177. data/lib/stripe/search_result_object.rb +5 -2
  178. data/lib/stripe/services/account_capability_service.rb +39 -0
  179. data/lib/stripe/services/account_external_account_service.rb +68 -0
  180. data/lib/stripe/services/account_link_service.rb +17 -0
  181. data/lib/stripe/services/account_login_link_service.rb +19 -0
  182. data/lib/stripe/services/account_person_service.rb +61 -0
  183. data/lib/stripe/services/account_service.rb +100 -0
  184. data/lib/stripe/services/account_session_service.rb +17 -0
  185. data/lib/stripe/services/apple_pay_domain_service.rb +50 -0
  186. data/lib/stripe/services/application_fee_refund_service.rb +60 -0
  187. data/lib/stripe/services/application_fee_service.rb +35 -0
  188. data/lib/stripe/services/apps/secret_service.rb +52 -0
  189. data/lib/stripe/services/apps_service.rb +13 -0
  190. data/lib/stripe/services/balance_service.rb +12 -0
  191. data/lib/stripe/services/balance_transaction_service.rb +32 -0
  192. data/lib/stripe/services/billing/alert_service.rb +74 -0
  193. data/lib/stripe/services/billing/credit_balance_summary_service.rb +19 -0
  194. data/lib/stripe/services/billing/credit_balance_transaction_service.rb +30 -0
  195. data/lib/stripe/services/billing/credit_grant_service.rb +74 -0
  196. data/lib/stripe/services/billing/meter_event_adjustment_service.rb +19 -0
  197. data/lib/stripe/services/billing/meter_event_service.rb +19 -0
  198. data/lib/stripe/services/billing/meter_event_summary_service.rb +19 -0
  199. data/lib/stripe/services/billing/meter_service.rb +81 -0
  200. data/lib/stripe/services/billing_portal/configuration_service.rb +52 -0
  201. data/lib/stripe/services/billing_portal/session_service.rb +19 -0
  202. data/lib/stripe/services/billing_portal_service.rb +14 -0
  203. data/lib/stripe/services/billing_service.rb +20 -0
  204. data/lib/stripe/services/charge_service.rb +69 -0
  205. data/lib/stripe/services/checkout/session_line_item_service.rb +19 -0
  206. data/lib/stripe/services/checkout/session_service.rb +72 -0
  207. data/lib/stripe/services/checkout_service.rb +13 -0
  208. data/lib/stripe/services/climate/order_service.rb +68 -0
  209. data/lib/stripe/services/climate/product_service.rb +30 -0
  210. data/lib/stripe/services/climate/supplier_service.rb +30 -0
  211. data/lib/stripe/services/climate_service.rb +15 -0
  212. data/lib/stripe/services/confirmation_token_service.rb +17 -0
  213. data/lib/stripe/services/country_spec_service.rb +28 -0
  214. data/lib/stripe/services/coupon_service.rb +51 -0
  215. data/lib/stripe/services/credit_note_line_item_service.rb +17 -0
  216. data/lib/stripe/services/credit_note_preview_lines_service.rb +17 -0
  217. data/lib/stripe/services/credit_note_service.rb +93 -0
  218. data/lib/stripe/services/customer_balance_transaction_service.rb +50 -0
  219. data/lib/stripe/services/customer_cash_balance_service.rb +28 -0
  220. data/lib/stripe/services/customer_cash_balance_transaction_service.rb +28 -0
  221. data/lib/stripe/services/customer_funding_instructions_service.rb +19 -0
  222. data/lib/stripe/services/customer_payment_method_service.rb +28 -0
  223. data/lib/stripe/services/customer_payment_source_service.rb +76 -0
  224. data/lib/stripe/services/customer_service.rb +89 -0
  225. data/lib/stripe/services/customer_session_service.rb +17 -0
  226. data/lib/stripe/services/customer_tax_id_service.rb +50 -0
  227. data/lib/stripe/services/dispute_service.rb +48 -0
  228. data/lib/stripe/services/entitlements/active_entitlement_service.rb +30 -0
  229. data/lib/stripe/services/entitlements/feature_service.rb +52 -0
  230. data/lib/stripe/services/entitlements_service.rb +14 -0
  231. data/lib/stripe/services/ephemeral_key_service.rb +28 -0
  232. data/lib/stripe/services/event_service.rb +22 -0
  233. data/lib/stripe/services/exchange_rate_service.rb +28 -0
  234. data/lib/stripe/services/file_link_service.rb +38 -0
  235. data/lib/stripe/services/file_service.rb +35 -0
  236. data/lib/stripe/services/financial_connections/account_owner_service.rb +19 -0
  237. data/lib/stripe/services/financial_connections/account_service.rb +81 -0
  238. data/lib/stripe/services/financial_connections/session_service.rb +30 -0
  239. data/lib/stripe/services/financial_connections/transaction_service.rb +30 -0
  240. data/lib/stripe/services/financial_connections_service.rb +15 -0
  241. data/lib/stripe/services/forwarding/request_service.rb +41 -0
  242. data/lib/stripe/services/forwarding_service.rb +13 -0
  243. data/lib/stripe/services/identity/verification_report_service.rb +30 -0
  244. data/lib/stripe/services/identity/verification_session_service.rb +106 -0
  245. data/lib/stripe/services/identity_service.rb +14 -0
  246. data/lib/stripe/services/invoice_item_service.rb +61 -0
  247. data/lib/stripe/services/invoice_line_item_service.rb +31 -0
  248. data/lib/stripe/services/invoice_rendering_template_service.rb +50 -0
  249. data/lib/stripe/services/invoice_service.rb +202 -0
  250. data/lib/stripe/services/invoice_upcoming_lines_service.rb +17 -0
  251. data/lib/stripe/services/issuing/authorization_service.rb +65 -0
  252. data/lib/stripe/services/issuing/card_service.rb +52 -0
  253. data/lib/stripe/services/issuing/cardholder_service.rb +52 -0
  254. data/lib/stripe/services/issuing/dispute_service.rb +63 -0
  255. data/lib/stripe/services/issuing/personalization_design_service.rb +52 -0
  256. data/lib/stripe/services/issuing/physical_bundle_service.rb +30 -0
  257. data/lib/stripe/services/issuing/token_service.rb +41 -0
  258. data/lib/stripe/services/issuing/transaction_service.rb +41 -0
  259. data/lib/stripe/services/issuing_service.rb +20 -0
  260. data/lib/stripe/services/mandate_service.rb +17 -0
  261. data/lib/stripe/services/oauth_service.rb +63 -0
  262. data/lib/stripe/services/payment_intent_service.rb +204 -0
  263. data/lib/stripe/services/payment_link_line_item_service.rb +17 -0
  264. data/lib/stripe/services/payment_link_service.rb +57 -0
  265. data/lib/stripe/services/payment_method_configuration_service.rb +50 -0
  266. data/lib/stripe/services/payment_method_domain_service.rb +66 -0
  267. data/lib/stripe/services/payment_method_service.rb +86 -0
  268. data/lib/stripe/services/payout_service.rb +66 -0
  269. data/lib/stripe/services/plan_service.rb +49 -0
  270. data/lib/stripe/services/price_service.rb +52 -0
  271. data/lib/stripe/services/product_feature_service.rb +50 -0
  272. data/lib/stripe/services/product_service.rb +70 -0
  273. data/lib/stripe/services/promotion_code_service.rb +50 -0
  274. data/lib/stripe/services/quote_computed_upfront_line_items_service.rb +17 -0
  275. data/lib/stripe/services/quote_line_item_service.rb +17 -0
  276. data/lib/stripe/services/quote_service.rb +92 -0
  277. data/lib/stripe/services/radar/early_fraud_warning_service.rb +32 -0
  278. data/lib/stripe/services/radar/value_list_item_service.rb +52 -0
  279. data/lib/stripe/services/radar/value_list_service.rb +63 -0
  280. data/lib/stripe/services/radar_service.rb +15 -0
  281. data/lib/stripe/services/refund_service.rb +63 -0
  282. data/lib/stripe/services/reporting/report_run_service.rb +41 -0
  283. data/lib/stripe/services/reporting/report_type_service.rb +30 -0
  284. data/lib/stripe/services/reporting_service.rb +14 -0
  285. data/lib/stripe/services/review_service.rb +33 -0
  286. data/lib/stripe/services/setup_attempt_service.rb +17 -0
  287. data/lib/stripe/services/setup_intent_service.rb +105 -0
  288. data/lib/stripe/services/shipping_rate_service.rb +50 -0
  289. data/lib/stripe/services/sigma/scheduled_query_run_service.rb +30 -0
  290. data/lib/stripe/services/sigma_service.rb +13 -0
  291. data/lib/stripe/services/source_service.rb +64 -0
  292. data/lib/stripe/services/source_transaction_service.rb +17 -0
  293. data/lib/stripe/services/subscription_item_service.rb +69 -0
  294. data/lib/stripe/services/subscription_item_usage_record_service.rb +23 -0
  295. data/lib/stripe/services/subscription_item_usage_record_summary_service.rb +19 -0
  296. data/lib/stripe/services/subscription_schedule_service.rb +72 -0
  297. data/lib/stripe/services/subscription_service.rb +127 -0
  298. data/lib/stripe/services/tax/calculation_line_item_service.rb +19 -0
  299. data/lib/stripe/services/tax/calculation_service.rb +37 -0
  300. data/lib/stripe/services/tax/registration_service.rb +54 -0
  301. data/lib/stripe/services/tax/settings_service.rb +30 -0
  302. data/lib/stripe/services/tax/transaction_line_item_service.rb +19 -0
  303. data/lib/stripe/services/tax/transaction_service.rb +48 -0
  304. data/lib/stripe/services/tax_code_service.rb +22 -0
  305. data/lib/stripe/services/tax_id_service.rb +38 -0
  306. data/lib/stripe/services/tax_rate_service.rb +38 -0
  307. data/lib/stripe/services/tax_service.rb +16 -0
  308. data/lib/stripe/services/terminal/configuration_service.rb +63 -0
  309. data/lib/stripe/services/terminal/connection_token_service.rb +19 -0
  310. data/lib/stripe/services/terminal/location_service.rb +64 -0
  311. data/lib/stripe/services/terminal/reader_service.rb +118 -0
  312. data/lib/stripe/services/terminal_service.rb +16 -0
  313. data/lib/stripe/services/test_helpers/confirmation_token_service.rb +19 -0
  314. data/lib/stripe/services/test_helpers/customer_service.rb +19 -0
  315. data/lib/stripe/services/test_helpers/issuing/authorization_service.rb +87 -0
  316. data/lib/stripe/services/test_helpers/issuing/card_service.rb +65 -0
  317. data/lib/stripe/services/test_helpers/issuing/personalization_design_service.rb +43 -0
  318. data/lib/stripe/services/test_helpers/issuing/transaction_service.rb +43 -0
  319. data/lib/stripe/services/test_helpers/issuing_service.rb +19 -0
  320. data/lib/stripe/services/test_helpers/refund_service.rb +19 -0
  321. data/lib/stripe/services/test_helpers/terminal/reader_service.rb +21 -0
  322. data/lib/stripe/services/test_helpers/terminal_service.rb +15 -0
  323. data/lib/stripe/services/test_helpers/test_clock_service.rb +63 -0
  324. data/lib/stripe/services/test_helpers/treasury/inbound_transfer_service.rb +43 -0
  325. data/lib/stripe/services/test_helpers/treasury/outbound_payment_service.rb +54 -0
  326. data/lib/stripe/services/test_helpers/treasury/outbound_transfer_service.rb +54 -0
  327. data/lib/stripe/services/test_helpers/treasury/received_credit_service.rb +21 -0
  328. data/lib/stripe/services/test_helpers/treasury/received_debit_service.rb +21 -0
  329. data/lib/stripe/services/test_helpers/treasury_service.rb +19 -0
  330. data/lib/stripe/services/test_helpers_service.rb +19 -0
  331. data/lib/stripe/services/token_service.rb +23 -0
  332. data/lib/stripe/services/topup_service.rb +49 -0
  333. data/lib/stripe/services/transfer_reversal_service.rb +56 -0
  334. data/lib/stripe/services/transfer_service.rb +47 -0
  335. data/lib/stripe/services/treasury/credit_reversal_service.rb +41 -0
  336. data/lib/stripe/services/treasury/debit_reversal_service.rb +41 -0
  337. data/lib/stripe/services/treasury/financial_account_features_service.rb +30 -0
  338. data/lib/stripe/services/treasury/financial_account_service.rb +70 -0
  339. data/lib/stripe/services/treasury/inbound_transfer_service.rb +52 -0
  340. data/lib/stripe/services/treasury/outbound_payment_service.rb +52 -0
  341. data/lib/stripe/services/treasury/outbound_transfer_service.rb +52 -0
  342. data/lib/stripe/services/treasury/received_credit_service.rb +30 -0
  343. data/lib/stripe/services/treasury/received_debit_service.rb +30 -0
  344. data/lib/stripe/services/treasury/transaction_entry_service.rb +30 -0
  345. data/lib/stripe/services/treasury/transaction_service.rb +30 -0
  346. data/lib/stripe/services/treasury_service.rb +22 -0
  347. data/lib/stripe/services/v1_services.rb +89 -0
  348. data/lib/stripe/services/v2/billing/meter_event_adjustment_service.rb +21 -0
  349. data/lib/stripe/services/v2/billing/meter_event_service.rb +21 -0
  350. data/lib/stripe/services/v2/billing/meter_event_session_service.rb +21 -0
  351. data/lib/stripe/services/v2/billing/meter_event_stream_service.rb +23 -0
  352. data/lib/stripe/services/v2/billing_service.rb +18 -0
  353. data/lib/stripe/services/v2/core/event_destination_service.rb +98 -0
  354. data/lib/stripe/services/v2/core/event_service.rb +32 -0
  355. data/lib/stripe/services/v2/core_service.rb +16 -0
  356. data/lib/stripe/services/v2_services.rb +14 -0
  357. data/lib/stripe/services/webhook_endpoint_service.rb +61 -0
  358. data/lib/stripe/services.rb +182 -0
  359. data/lib/stripe/singleton_api_resource.rb +3 -3
  360. data/lib/stripe/stripe_client.rb +55 -1028
  361. data/lib/stripe/stripe_configuration.rb +63 -42
  362. data/lib/stripe/stripe_object.rb +60 -38
  363. data/lib/stripe/stripe_response.rb +1 -3
  364. data/lib/stripe/stripe_service.rb +32 -0
  365. data/lib/stripe/thin_event.rb +37 -0
  366. data/lib/stripe/util.rb +109 -45
  367. data/lib/stripe/v2_list_object.rb +84 -0
  368. data/lib/stripe/version.rb +1 -1
  369. data/lib/stripe/webhook.rb +3 -2
  370. data/lib/stripe.rb +39 -0
  371. data/stripe.gemspec +7 -4
  372. metadata +252 -13
  373. data/lib/stripe/resources/bitcoin_receiver.rb +0 -24
  374. data/lib/stripe/resources/bitcoin_transaction.rb +0 -16
  375. data/lib/stripe/resources/issuing/card_details.rb +0 -10
  376. data/lib/stripe/resources/order.rb +0 -33
  377. data/lib/stripe/resources/order_return.rb +0 -10
  378. data/lib/stripe/resources/recipient.rb +0 -14
  379. data/lib/stripe/resources/sku.rb +0 -13
  380. data/lib/stripe/resources/three_d_secure.rb +0 -14
@@ -1,1060 +1,87 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "stripe/instrumentation"
3
+ require "json"
4
4
 
5
5
  module Stripe
6
- # StripeClient executes requests against the Stripe API and allows a user to
7
- # recover both a resource a call returns as well as a response object that
8
- # contains information on the HTTP call.
9
6
  class StripeClient
10
- # A set of all known thread contexts across all threads and a mutex to
11
- # synchronize global access to them.
12
- @thread_contexts_with_connection_managers = Set.new
13
- @thread_contexts_with_connection_managers_mutex = Mutex.new
14
- @last_connection_manager_gc = Util.monotonic_time
7
+ # attr_readers: The beginning of the section generated from our OpenAPI spec
8
+ attr_reader :v1
9
+ attr_reader :v2
15
10
 
16
- # Initializes a new StripeClient
17
- def initialize(config_arg = {})
18
- @system_profiler = SystemProfiler.new
19
- @last_request_metrics = nil
20
-
21
- @config = case config_arg
22
- when Hash
23
- Stripe.config.reverse_duplicate_merge(config_arg)
24
- when Stripe::ConnectionManager
25
- # Supports accepting a connection manager object for backwards
26
- # compatibility only, and that use is DEPRECATED.
27
- Stripe.config.dup
28
- when Stripe::StripeConfiguration
29
- config_arg
30
- when String
31
- Stripe.config.reverse_duplicate_merge(
32
- { api_key: config_arg }
33
- )
34
- else
35
- raise ArgumentError, "Can't handle argument: #{config_arg}"
36
- end
37
- end
38
-
39
- attr_reader :config
40
- attr_reader :options
41
-
42
- # Gets a currently active `StripeClient`. Set for the current thread when
43
- # `StripeClient#request` is being run so that API operations being executed
44
- # inside of that block can find the currently active client. It's reset to
45
- # the original value (hopefully `nil`) after the block ends.
46
- #
47
- # For internal use only. Does not provide a stable API and may be broken
48
- # with future non-major changes.
49
- def self.active_client
50
- current_thread_context.active_client || default_client
51
- end
52
-
53
- # Finishes any active connections by closing their TCP connection and
54
- # clears them from internal tracking in all connection managers across all
55
- # threads.
56
- #
57
- # If passed a `config` object, only clear connection managers for that
58
- # particular configuration.
59
- #
60
- # For internal use only. Does not provide a stable API and may be broken
61
- # with future non-major changes.
62
- def self.clear_all_connection_managers(config: nil)
63
- # Just a quick path for when configuration is being set for the first
64
- # time before any connections have been opened. There is technically some
65
- # potential for thread raciness here, but not in a practical sense.
66
- return if @thread_contexts_with_connection_managers.empty?
67
-
68
- @thread_contexts_with_connection_managers_mutex.synchronize do
69
- pruned_contexts = Set.new
70
-
71
- @thread_contexts_with_connection_managers.each do |thread_context|
72
- # Note that the thread context itself is not destroyed, but we clear
73
- # its connection manager and remove our reference to it. If it ever
74
- # makes a new request we'll give it a new connection manager and
75
- # it'll go back into `@thread_contexts_with_connection_managers`.
76
- thread_context.default_connection_managers.reject! do |cm_config, cm|
77
- if config.nil? || config.key == cm_config
78
- cm.clear
79
- true
80
- end
81
- end
82
-
83
- if thread_context.default_connection_managers.empty?
84
- pruned_contexts << thread_context
85
- end
86
- end
87
-
88
- @thread_contexts_with_connection_managers.subtract(pruned_contexts)
89
- end
90
- end
91
-
92
- # A default client for the current thread.
93
- def self.default_client
94
- current_thread_context.default_client ||= StripeClient.new(Stripe.config)
95
- end
96
-
97
- # A default connection manager for the current thread scoped to the
98
- # configuration object that may be provided.
99
- def self.default_connection_manager(config = Stripe.config)
100
- current_thread_context.default_connection_managers[config.key] ||= begin
101
- connection_manager = ConnectionManager.new(config)
102
-
103
- @thread_contexts_with_connection_managers_mutex.synchronize do
104
- maybe_gc_connection_managers
105
- @thread_contexts_with_connection_managers << current_thread_context
106
- end
107
-
108
- connection_manager
109
- end
110
- end
111
-
112
- # Checks if an error is a problem that we should retry on. This includes
113
- # both socket errors that may represent an intermittent problem and some
114
- # special HTTP statuses.
115
- def self.should_retry?(error,
116
- method:, num_retries:, config: Stripe.config)
117
- return false if num_retries >= config.max_network_retries
118
-
119
- case error
120
- when Net::OpenTimeout, Net::ReadTimeout
121
- # Retry on timeout-related problems (either on open or read).
122
- true
123
- when EOFError, Errno::ECONNREFUSED, Errno::ECONNRESET,
124
- Errno::EHOSTUNREACH, Errno::ETIMEDOUT, SocketError
125
- # Destination refused the connection, the connection was reset, or a
126
- # variety of other connection failures. This could occur from a single
127
- # saturated server, so retry in case it's intermittent.
128
- true
129
- when Stripe::StripeError
130
- # The API may ask us not to retry (e.g. if doing so would be a no-op),
131
- # or advise us to retry (e.g. in cases of lock timeouts). Defer to
132
- # those instructions if given.
133
- return false if error.http_headers["stripe-should-retry"] == "false"
134
- return true if error.http_headers["stripe-should-retry"] == "true"
135
-
136
- # 409 Conflict
137
- return true if error.http_status == 409
138
-
139
- # 429 Too Many Requests
140
- #
141
- # There are a few different problems that can lead to a 429. The most
142
- # common is rate limiting, on which we *don't* want to retry because
143
- # that'd likely contribute to more contention problems. However, some
144
- # 429s are lock timeouts, which is when a request conflicted with
145
- # another request or an internal process on some particular object.
146
- # These 429s are safe to retry.
147
- return true if error.http_status == 429 && error.code == "lock_timeout"
148
-
149
- # 500 Internal Server Error
150
- #
151
- # We only bother retrying these for non-POST requests. POSTs end up
152
- # being cached by the idempotency layer so there's no purpose in
153
- # retrying them.
154
- return true if error.http_status == 500 && method != :post
155
-
156
- # 503 Service Unavailable
157
- error.http_status == 503
158
- else
159
- false
160
- end
161
- end
162
-
163
- def self.sleep_time(num_retries, config: Stripe.config)
164
- # Apply exponential backoff with initial_network_retry_delay on the
165
- # number of num_retries so far as inputs. Do not allow the number to
166
- # exceed max_network_retry_delay.
167
- sleep_seconds = [
168
- config.initial_network_retry_delay * (2**(num_retries - 1)),
169
- config.max_network_retry_delay,
170
- ].min
171
-
172
- # Apply some jitter by randomizing the value in the range of
173
- # (sleep_seconds / 2) to (sleep_seconds).
174
- sleep_seconds *= (0.5 * (1 + rand))
175
-
176
- # But never sleep less than the base sleep seconds.
177
- [config.initial_network_retry_delay, sleep_seconds].max
178
- end
179
-
180
- # Gets the connection manager in use for the current `StripeClient`.
181
- #
182
- # This method is DEPRECATED and for backwards compatibility only.
183
- def connection_manager
184
- self.class.default_connection_manager
185
- end
186
- extend Gem::Deprecate
187
- deprecate :connection_manager, :none, 2020, 9
188
-
189
- # Executes the API call within the given block. Usage looks like:
190
- #
191
- # client = StripeClient.new
192
- # charge, resp = client.request { Charge.create }
193
- #
194
- def request
195
- old_stripe_client = self.class.current_thread_context.active_client
196
- self.class.current_thread_context.active_client = self
197
-
198
- if self.class.current_thread_context.last_responses&.key?(object_id)
199
- raise "calls to StripeClient#request cannot be nested within a thread"
200
- end
201
-
202
- self.class.current_thread_context.last_responses ||= {}
203
- self.class.current_thread_context.last_responses[object_id] = nil
204
-
205
- begin
206
- res = yield
207
- [res, self.class.current_thread_context.last_responses[object_id]]
208
- ensure
209
- self.class.current_thread_context.active_client = old_stripe_client
210
- self.class.current_thread_context.last_responses.delete(object_id)
211
- end
212
- end
213
-
214
- def execute_request(method, path,
215
- api_base: nil, api_key: nil, headers: {}, params: {})
216
- http_resp, api_key = execute_request_internal(
217
- method, path, api_base, api_key, headers, params
218
- )
219
-
220
- begin
221
- resp = StripeResponse.from_net_http(http_resp)
222
- rescue JSON::ParserError
223
- raise general_api_error(http_resp.code.to_i, http_resp.body)
224
- end
225
-
226
- # If being called from `StripeClient#request`, put the last response in
227
- # thread-local memory so that it can be returned to the user. Don't store
228
- # anything otherwise so that we don't leak memory.
229
- store_last_response(object_id, resp)
230
-
231
- [resp, api_key]
232
- end
233
-
234
- # Executes a request and returns the body as a stream instead of converting
235
- # it to a StripeObject. This should be used for any request where we expect
236
- # an arbitrary binary response.
237
- #
238
- # A `read_body_chunk` block can be passed, which will be called repeatedly
239
- # with the body chunks read from the socket.
240
- #
241
- # If a block is passed, a StripeHeadersOnlyResponse is returned as the
242
- # block is expected to do all the necessary body processing. If no block is
243
- # passed, then a StripeStreamResponse is returned containing an IO stream
244
- # with the response body.
245
- def execute_request_stream(method, path,
246
- api_base: nil, api_key: nil,
247
- headers: {}, params: {},
248
- &read_body_chunk_block)
249
- unless block_given?
250
- raise ArgumentError,
251
- "execute_request_stream requires a read_body_chunk_block"
252
- end
11
+ # attr_readers: The end of the section generated from our OpenAPI spec
253
12
 
254
- http_resp, api_key = execute_request_internal(
255
- method, path, api_base, api_key, headers, params, &read_body_chunk_block
256
- )
257
-
258
- # When the read_body_chunk_block is given, we no longer have access to the
259
- # response body at this point and so return a response object containing
260
- # only the headers. This is because the body was consumed by the block.
261
- resp = StripeHeadersOnlyResponse.from_net_http(http_resp)
262
-
263
- [resp, api_key]
264
- end
265
-
266
- def store_last_response(object_id, resp)
267
- return unless last_response_has_key?(object_id)
268
-
269
- self.class.current_thread_context.last_responses[object_id] = resp
270
- end
271
-
272
- def last_response_has_key?(object_id)
273
- self.class.current_thread_context.last_responses&.key?(object_id)
274
- end
275
-
276
- #
277
- # private
278
- #
279
-
280
- # Time (in seconds) that a connection manager has not been used before it's
281
- # eligible for garbage collection.
282
- CONNECTION_MANAGER_GC_LAST_USED_EXPIRY = 120
283
-
284
- # How often to check (in seconds) for connection managers that haven't been
285
- # used in a long time and which should be garbage collected.
286
- CONNECTION_MANAGER_GC_PERIOD = 60
287
-
288
- ERROR_MESSAGE_CONNECTION =
289
- "Unexpected error communicating when trying to connect to " \
290
- "Stripe (%s). You may be seeing this message because your DNS is not " \
291
- "working or you don't have an internet connection. To check, try " \
292
- "running `host stripe.com` from the command line."
293
- ERROR_MESSAGE_SSL =
294
- "Could not establish a secure connection to Stripe (%s), you " \
295
- "may need to upgrade your OpenSSL version. To check, try running " \
296
- "`openssl s_client -connect api.stripe.com:443` from the command " \
297
- "line."
298
-
299
- # Common error suffix sared by both connect and read timeout messages.
300
- ERROR_MESSAGE_TIMEOUT_SUFFIX =
301
- "Please check your internet connection and try again. " \
302
- "If this problem persists, you should check Stripe's service " \
303
- "status at https://status.stripe.com, or let us know at " \
304
- "support@stripe.com."
305
-
306
- ERROR_MESSAGE_TIMEOUT_CONNECT = (
307
- "Timed out connecting to Stripe (%s). " +
308
- ERROR_MESSAGE_TIMEOUT_SUFFIX
309
- ).freeze
310
-
311
- ERROR_MESSAGE_TIMEOUT_READ = (
312
- "Timed out communicating with Stripe (%s). " +
313
- ERROR_MESSAGE_TIMEOUT_SUFFIX
314
- ).freeze
315
-
316
- # Maps types of exceptions that we're likely to see during a network
317
- # request to more user-friendly messages that we put in front of people.
318
- # The original error message is also appended onto the final exception for
319
- # full transparency.
320
- NETWORK_ERROR_MESSAGES_MAP = {
321
- EOFError => ERROR_MESSAGE_CONNECTION,
322
- Errno::ECONNREFUSED => ERROR_MESSAGE_CONNECTION,
323
- Errno::ECONNRESET => ERROR_MESSAGE_CONNECTION,
324
- Errno::EHOSTUNREACH => ERROR_MESSAGE_CONNECTION,
325
- Errno::ETIMEDOUT => ERROR_MESSAGE_TIMEOUT_CONNECT,
326
- SocketError => ERROR_MESSAGE_CONNECTION,
327
-
328
- Net::OpenTimeout => ERROR_MESSAGE_TIMEOUT_CONNECT,
329
- Net::ReadTimeout => ERROR_MESSAGE_TIMEOUT_READ,
330
-
331
- OpenSSL::SSL::SSLError => ERROR_MESSAGE_SSL,
332
- }.freeze
333
- private_constant :NETWORK_ERROR_MESSAGES_MAP
334
-
335
- # A record representing any data that `StripeClient` puts into
336
- # `Thread.current`. Making it a class likes this gives us a little extra
337
- # type safety and lets us document what each field does.
338
- #
339
- # For internal use only. Does not provide a stable API and may be broken
340
- # with future non-major changes.
341
- class ThreadContext
342
- # A `StripeClient` that's been flagged as currently active within a
343
- # thread by `StripeClient#request`. A client stays active until the
344
- # completion of the request block.
345
- attr_accessor :active_client
346
-
347
- # A default `StripeClient` object for the thread. Used in all cases where
348
- # the user hasn't specified their own.
349
- attr_accessor :default_client
350
-
351
- # A temporary map of object IDs to responses from last executed API
352
- # calls. Used to return a responses from calls to `StripeClient#request`.
353
- #
354
- # Stored in the thread data to make the use of a single `StripeClient`
355
- # object safe across multiple threads. Stored as a map so that multiple
356
- # `StripeClient` objects can run concurrently on the same thread.
357
- #
358
- # Responses are only left in as long as they're needed, which means
359
- # they're removed as soon as a call leaves `StripeClient#request`, and
360
- # because that's wrapped in an `ensure` block, they should never leave
361
- # garbage in `Thread.current`.
362
- attr_accessor :last_responses
363
-
364
- # A map of connection mangers for the thread. Normally shared between
365
- # all `StripeClient` objects on a particular thread, and created so as to
366
- # minimize the number of open connections that an application needs.
367
- def default_connection_managers
368
- @default_connection_managers ||= {}
369
- end
370
-
371
- def reset_connection_managers
372
- @default_connection_managers = {}
373
- end
374
- end
375
-
376
- # Access data stored for `StripeClient` within the thread's current
377
- # context. Returns `ThreadContext`.
378
- #
379
13
  # For internal use only. Does not provide a stable API and may be broken
380
14
  # with future non-major changes.
381
- def self.current_thread_context
382
- Thread.current[:stripe_client__internal_use_only] ||= ThreadContext.new
383
- end
384
-
385
- # Garbage collects connection managers that haven't been used in some time,
386
- # with the idea being that we want to remove old connection managers that
387
- # belong to dead threads and the like.
388
- #
389
- # Prefixed with `maybe_` because garbage collection will only run
390
- # periodically so that we're not constantly engaged in busy work. If
391
- # connection managers live a little passed their useful age it's not
392
- # harmful, so it's not necessary to get them right away.
393
- #
394
- # For testability, returns `nil` if it didn't run and the number of
395
- # connection managers that were garbage collected otherwise.
396
- #
397
- # IMPORTANT: This method is not thread-safe and expects to be called inside
398
- # a lock on `@thread_contexts_with_connection_managers_mutex`.
399
- #
400
- # For internal use only. Does not provide a stable API and may be broken
401
- # with future non-major changes.
402
- def self.maybe_gc_connection_managers
403
- next_gc_time = @last_connection_manager_gc + CONNECTION_MANAGER_GC_PERIOD
404
- return nil if next_gc_time > Util.monotonic_time
405
-
406
- last_used_threshold =
407
- Util.monotonic_time - CONNECTION_MANAGER_GC_LAST_USED_EXPIRY
408
-
409
- pruned_contexts = []
410
- @thread_contexts_with_connection_managers.each do |thread_context|
411
- thread_context
412
- .default_connection_managers
413
- .each do |config_key, connection_manager|
414
- next if connection_manager.last_used > last_used_threshold
415
-
416
- connection_manager.clear
417
- thread_context.default_connection_managers.delete(config_key)
418
- end
419
- end
420
-
421
- @thread_contexts_with_connection_managers.each do |thread_context|
422
- next unless thread_context.default_connection_managers.empty?
423
-
424
- pruned_contexts << thread_context
425
- end
426
-
427
- @thread_contexts_with_connection_managers -= pruned_contexts
428
- @last_connection_manager_gc = Util.monotonic_time
429
-
430
- pruned_contexts.count
431
- end
432
-
433
- private def execute_request_internal(method, path,
434
- api_base, api_key, headers, params,
435
- &read_body_chunk_block)
436
- raise ArgumentError, "method should be a symbol" \
437
- unless method.is_a?(Symbol)
438
- raise ArgumentError, "path should be a string" \
439
- unless path.is_a?(String)
440
-
441
- api_base ||= config.api_base
442
- api_key ||= config.api_key
443
- params = Util.objects_to_ids(params)
444
-
445
- check_api_key!(api_key)
446
-
447
- body_params = nil
448
- query_params = nil
449
- case method
450
- when :get, :head, :delete
451
- query_params = params
452
- else
453
- body_params = params
454
- end
455
-
456
- query_params, path = merge_query_params(query_params, path)
457
-
458
- headers = request_headers(api_key, method)
459
- .update(Util.normalize_headers(headers))
460
- url = api_url(path, api_base)
461
-
462
- # Merge given query parameters with any already encoded in the path.
463
- query = query_params ? Util.encode_parameters(query_params) : nil
464
-
465
- # Encoding body parameters is a little more complex because we may have
466
- # to send a multipart-encoded body. `body_log` is produced separately as
467
- # a log-friendly variant of the encoded form. File objects are displayed
468
- # as such instead of as their file contents.
469
- body, body_log =
470
- body_params ? encode_body(body_params, headers) : [nil, nil]
471
-
472
- # stores information on the request we're about to make so that we don't
473
- # have to pass as many parameters around for logging.
474
- context = RequestLogContext.new
475
- context.account = headers["Stripe-Account"]
476
- context.api_key = api_key
477
- context.api_version = headers["Stripe-Version"]
478
- context.body = body_log
479
- context.idempotency_key = headers["Idempotency-Key"]
480
- context.method = method
481
- context.path = path
482
- context.query = query
483
-
484
- # A block can be passed in to read the content directly from the response.
485
- # We want to execute this block only when the response was actually
486
- # successful. When it wasn't, we defer to the standard error handling as
487
- # we have to read the body and parse the error JSON.
488
- response_block =
489
- if block_given?
490
- lambda do |response|
491
- unless should_handle_as_error(response.code.to_i)
492
- response.read_body(&read_body_chunk_block)
493
- end
494
- end
495
- end
15
+ CLIENT_OPTIONS = Set.new(%i[api_key stripe_account stripe_context api_version api_base uploads_base connect_base meter_events_base client_id])
496
16
 
497
- http_resp = execute_request_with_rescues(method, api_base, context) do
498
- self.class
499
- .default_connection_manager(config)
500
- .execute_request(method, url,
501
- body: body,
502
- headers: headers,
503
- query: query,
504
- &response_block)
505
- end
506
-
507
- [http_resp, api_key]
508
- end
509
-
510
- private def api_url(url = "", api_base = nil)
511
- (api_base || config.api_base) + url
512
- end
513
-
514
- private def check_api_key!(api_key)
17
+ # Initializes a new StripeClient
18
+ def initialize(api_key, # rubocop:todo Metrics/ParameterLists
19
+ stripe_account: nil,
20
+ stripe_context: nil,
21
+ stripe_version: nil,
22
+ api_base: nil,
23
+ uploads_base: nil,
24
+ connect_base: nil,
25
+ meter_events_base: nil,
26
+ client_id: nil)
515
27
  unless api_key
516
28
  raise AuthenticationError, "No API key provided. " \
517
- 'Set your API key using "Stripe.api_key = <API-KEY>". ' \
518
- "You can generate API keys from the Stripe web interface. " \
519
- "See https://stripe.com/api for details, or email " \
520
- "support@stripe.com if you have any questions."
521
- end
522
-
523
- return unless api_key =~ /\s/
524
-
525
- raise AuthenticationError, "Your API key is invalid, as it contains " \
526
- "whitespace. (HINT: You can double-check your API key from the " \
527
- "Stripe web interface. See https://stripe.com/api for details, or " \
528
- "email support@stripe.com if you have any questions.)"
529
- end
530
-
531
- # Encodes a set of body parameters using multipart if `Content-Type` is set
532
- # for that, or standard form-encoding otherwise. Returns the encoded body
533
- # and a version of the encoded body that's safe to be logged.
534
- private def encode_body(body_params, headers)
535
- body = nil
536
- flattened_params = Util.flatten_params(body_params)
537
-
538
- if headers["Content-Type"] == MultipartEncoder::MULTIPART_FORM_DATA
539
- body, content_type = MultipartEncoder.encode(flattened_params)
540
-
541
- # Set a new content type that also includes the multipart boundary.
542
- # See `MultipartEncoder` for details.
543
- headers["Content-Type"] = content_type
544
-
545
- # `#to_s` any complex objects like files and the like to build output
546
- # that's more condusive to logging.
547
- flattened_params =
548
- flattened_params.map { |k, v| [k, v.is_a?(String) ? v : v.to_s] }.to_h
549
-
550
- else
551
- body = Util.encode_parameters(body_params)
552
- end
553
-
554
- # We don't use `Util.encode_parameters` partly as an optimization (to not
555
- # redo work we've already done), and partly because the encoded forms of
556
- # certain characters introduce a lot of visual noise and it's nice to
557
- # have a clearer format for logs.
558
- body_log = flattened_params.map { |k, v| "#{k}=#{v}" }.join("&")
559
-
560
- [body, body_log]
561
- end
562
-
563
- private def should_handle_as_error(http_status)
564
- http_status >= 400
565
- end
566
-
567
- private def execute_request_with_rescues(method, api_base, context)
568
- num_retries = 0
569
-
570
- begin
571
- request_start = nil
572
- user_data = nil
573
-
574
- log_request(context, num_retries)
575
- user_data = notify_request_begin(context)
576
-
577
- request_start = Util.monotonic_time
578
- resp = yield
579
- request_duration = Util.monotonic_time - request_start
580
-
581
- http_status = resp.code.to_i
582
- context = context.dup_from_response_headers(resp)
583
-
584
- if should_handle_as_error(http_status)
585
- handle_error_response(resp, context)
586
- end
587
-
588
- log_response(context, request_start, http_status, resp.body, resp)
589
- notify_request_end(context, request_duration, http_status,
590
- num_retries, user_data)
591
-
592
- if config.enable_telemetry? && context.request_id
593
- request_duration_ms = (request_duration * 1000).to_i
594
- @last_request_metrics =
595
- StripeRequestMetrics.new(context.request_id, request_duration_ms)
596
- end
597
-
598
- # We rescue all exceptions from a request so that we have an easy spot to
599
- # implement our retry logic across the board. We'll re-raise if it's a
600
- # type of exception that we didn't expect to handle.
601
- rescue StandardError => e
602
- # If we modify context we copy it into a new variable so as not to
603
- # taint the original on a retry.
604
- error_context = context
605
- http_status = nil
606
- request_duration = Util.monotonic_time - request_start if request_start
607
-
608
- if e.is_a?(Stripe::StripeError)
609
- error_context = context.dup_from_response_headers(e.http_headers)
610
- http_status = resp.code.to_i
611
- log_response(error_context, request_start,
612
- e.http_status, e.http_body, resp)
613
- else
614
- log_response_error(error_context, request_start, e)
615
- end
616
- notify_request_end(context, request_duration, http_status, num_retries,
617
- user_data)
618
-
619
- if self.class.should_retry?(e,
620
- method: method,
621
- num_retries: num_retries,
622
- config: config)
623
- num_retries += 1
624
- sleep self.class.sleep_time(num_retries, config: config)
625
- retry
626
- end
627
-
628
- case e
629
- when Stripe::StripeError
630
- raise
631
- when *NETWORK_ERROR_MESSAGES_MAP.keys
632
- handle_network_error(e, error_context, num_retries, api_base)
633
-
634
- # Only handle errors when we know we can do so, and re-raise otherwise.
635
- # This should be pretty infrequent.
636
- else
637
- raise
638
- end
639
- end
640
-
641
- resp
642
- end
643
-
644
- private def notify_request_begin(context)
645
- return unless Instrumentation.any_subscribers?(:request_begin)
646
-
647
- event = Instrumentation::RequestBeginEvent.new(
648
- method: context.method,
649
- path: context.path,
650
- user_data: {}
651
- )
652
- Stripe::Instrumentation.notify(:request_begin, event)
653
-
654
- # This field may be set in the `request_begin` callback. If so, we'll
655
- # forward it onto `request_end`.
656
- event.user_data
657
- end
658
-
659
- private def notify_request_end(context, duration, http_status, num_retries,
660
- user_data)
661
- return if !Instrumentation.any_subscribers?(:request_end) &&
662
- !Instrumentation.any_subscribers?(:request)
663
-
664
- event = Instrumentation::RequestEndEvent.new(
665
- duration: duration,
666
- http_status: http_status,
667
- method: context.method,
668
- num_retries: num_retries,
669
- path: context.path,
670
- request_id: context.request_id,
671
- user_data: user_data || {}
672
- )
673
- Stripe::Instrumentation.notify(:request_end, event)
674
-
675
- # The name before `request_begin` was also added. Provided for backwards
676
- # compatibility.
677
- Stripe::Instrumentation.notify(:request, event)
678
- end
679
-
680
- private def general_api_error(status, body)
681
- APIError.new("Invalid response object from API: #{body.inspect} " \
682
- "(HTTP response code was #{status})",
683
- http_status: status, http_body: body)
684
- end
685
-
686
- # Formats a plugin "app info" hash into a string that we can tack onto the
687
- # end of a User-Agent string where it'll be fairly prominent in places like
688
- # the Dashboard. Note that this formatting has been implemented to match
689
- # other libraries, and shouldn't be changed without universal consensus.
690
- private def format_app_info(info)
691
- str = info[:name]
692
- str = "#{str}/#{info[:version]}" unless info[:version].nil?
693
- str = "#{str} (#{info[:url]})" unless info[:url].nil?
694
- str
695
- end
696
-
697
- private def handle_error_response(http_resp, context)
698
- begin
699
- resp = StripeResponse.from_net_http(http_resp)
700
- error_data = resp.data[:error]
701
-
702
- raise StripeError, "Indeterminate error" unless error_data
703
- rescue JSON::ParserError, StripeError
704
- raise general_api_error(http_resp.code.to_i, http_resp.body)
705
- end
706
-
707
- error = if error_data.is_a?(String)
708
- specific_oauth_error(resp, error_data, context)
709
- else
710
- specific_api_error(resp, error_data, context)
711
- end
712
-
713
- error.response = resp
714
- raise(error)
715
- end
716
-
717
- # Works around an edge case where we end up with both query parameters from
718
- # parameteers and query parameters that were appended onto the end of the
719
- # given path.
720
- #
721
- # Decode any parameters that were added onto the end of a path and add them
722
- # to a unified query parameter hash so that all parameters end up in one
723
- # place and all of them are correctly included in the final request.
724
- private def merge_query_params(query_params, path)
725
- u = URI.parse(path)
726
-
727
- # Return original results if there was nothing to be found.
728
- return query_params, path if u.query.nil?
729
-
730
- query_params ||= {}
731
- query_params = Hash[URI.decode_www_form(u.query)].merge(query_params)
732
-
733
- # Reset the path minus any query parameters that were specified.
734
- path = u.path
735
-
736
- [query_params, path]
737
- end
738
-
739
- private def specific_api_error(resp, error_data, context)
740
- Util.log_error("Stripe API error",
741
- status: resp.http_status,
742
- error_code: error_data[:code],
743
- error_message: error_data[:message],
744
- error_param: error_data[:param],
745
- error_type: error_data[:type],
746
- idempotency_key: context.idempotency_key,
747
- request_id: context.request_id,
748
- config: config)
749
-
750
- # The standard set of arguments that can be used to initialize most of
751
- # the exceptions.
752
- opts = {
753
- http_body: resp.http_body,
754
- http_headers: resp.http_headers,
755
- http_status: resp.http_status,
756
- json_body: resp.data,
757
- code: error_data[:code],
758
- }
759
-
760
- case resp.http_status
761
- when 400, 404
762
- case error_data[:type]
763
- when "idempotency_error"
764
- IdempotencyError.new(error_data[:message], **opts)
765
- else
766
- InvalidRequestError.new(
767
- error_data[:message], error_data[:param],
768
- **opts
769
- )
770
- end
771
- when 401
772
- AuthenticationError.new(error_data[:message], **opts)
773
- when 402
774
- CardError.new(
775
- error_data[:message], error_data[:param],
776
- **opts
777
- )
778
- when 403
779
- PermissionError.new(error_data[:message], **opts)
780
- when 429
781
- RateLimitError.new(error_data[:message], **opts)
782
- else
783
- APIError.new(error_data[:message], **opts)
784
- end
785
- end
786
-
787
- # Attempts to look at a response's error code and return an OAuth error if
788
- # one matches. Will return `nil` if the code isn't recognized.
789
- private def specific_oauth_error(resp, error_code, context)
790
- description = resp.data[:error_description] || error_code
791
-
792
- Util.log_error("Stripe OAuth error",
793
- status: resp.http_status,
794
- error_code: error_code,
795
- error_description: description,
796
- idempotency_key: context.idempotency_key,
797
- request_id: context.request_id,
798
- config: config)
799
-
800
- args = {
801
- http_status: resp.http_status, http_body: resp.http_body,
802
- json_body: resp.data, http_headers: resp.http_headers,
803
- }
804
-
805
- case error_code
806
- when "invalid_client"
807
- OAuth::InvalidClientError.new(error_code, description, **args)
808
- when "invalid_grant"
809
- OAuth::InvalidGrantError.new(error_code, description, **args)
810
- when "invalid_request"
811
- OAuth::InvalidRequestError.new(error_code, description, **args)
812
- when "invalid_scope"
813
- OAuth::InvalidScopeError.new(error_code, description, **args)
814
- when "unsupported_grant_type"
815
- OAuth::UnsupportedGrantTypeError.new(error_code, description, **args)
816
- when "unsupported_response_type"
817
- OAuth::UnsupportedResponseTypeError.new(error_code, description, **args)
818
- else
819
- # We'd prefer that all errors are typed, but we create a generic
820
- # OAuthError in case we run into a code that we don't recognize.
821
- OAuth::OAuthError.new(error_code, description, **args)
822
- end
823
- end
824
-
825
- private def handle_network_error(error, context, num_retries,
826
- api_base = nil)
827
- Util.log_error("Stripe network error",
828
- error_message: error.message,
829
- idempotency_key: context.idempotency_key,
830
- request_id: context.request_id,
831
- config: config)
832
-
833
- errors, message = NETWORK_ERROR_MESSAGES_MAP.detect do |(e, _)|
834
- error.is_a?(e)
835
- end
836
-
837
- if errors.nil?
838
- message = "Unexpected error #{error.class.name} communicating " \
839
- "with Stripe. Please let us know at support@stripe.com."
840
- end
841
-
842
- api_base ||= config.api_base
843
- message = message % api_base
844
-
845
- message += " Request was retried #{num_retries} times." if num_retries > 0
846
-
847
- raise APIConnectionError,
848
- message + "\n\n(Network error: #{error.message})"
849
- end
850
-
851
- private def request_headers(api_key, method)
852
- user_agent = "Stripe/v1 RubyBindings/#{Stripe::VERSION}"
853
- unless Stripe.app_info.nil?
854
- user_agent += " " + format_app_info(Stripe.app_info)
855
- end
856
-
857
- headers = {
858
- "User-Agent" => user_agent,
859
- "Authorization" => "Bearer #{api_key}",
860
- "Content-Type" => "application/x-www-form-urlencoded",
861
- }
862
-
863
- if config.enable_telemetry? && !@last_request_metrics.nil?
864
- headers["X-Stripe-Client-Telemetry"] = JSON.generate(
865
- last_request_metrics: @last_request_metrics.payload
866
- )
867
- end
868
-
869
- # It is only safe to retry network failures on post and delete
870
- # requests if we add an Idempotency-Key header
871
- if %i[post delete].include?(method) && config.max_network_retries > 0
872
- headers["Idempotency-Key"] ||= SecureRandom.uuid
29
+ 'Set your API key using "client = Stripe::StripeClient.new(<API-KEY>)". ' \
30
+ "You can generate API keys from the Stripe web interface. " \
31
+ "See https://stripe.com/api for details, or email " \
32
+ "support@stripe.com if you have any questions."
873
33
  end
874
34
 
875
- headers["Stripe-Version"] = config.api_version if config.api_version
876
- headers["Stripe-Account"] = config.stripe_account if config.stripe_account
35
+ config_opts = {
36
+ api_key: api_key,
37
+ stripe_account: stripe_account,
38
+ stripe_context: stripe_context,
39
+ api_version: stripe_version,
40
+ api_base: api_base,
41
+ uploads_base: uploads_base,
42
+ connect_base: connect_base,
43
+ meter_events_base: meter_events_base,
44
+ client_id: client_id,
45
+ }.reject { |_k, v| v.nil? }
877
46
 
878
- user_agent = @system_profiler.user_agent
879
- begin
880
- headers.update(
881
- "X-Stripe-Client-User-Agent" => JSON.generate(user_agent)
882
- )
883
- rescue StandardError => e
884
- headers.update(
885
- "X-Stripe-Client-Raw-User-Agent" => user_agent.inspect,
886
- :error => "#{e} (#{e.class})"
887
- )
888
- end
47
+ config = StripeConfiguration.client_init(config_opts)
48
+ @requestor = APIRequestor.new(config)
889
49
 
890
- headers
50
+ # top-level services: The beginning of the section generated from our OpenAPI spec
51
+ @v1 = Stripe::V1Services.new(@requestor)
52
+ @v2 = Stripe::V2Services.new(@requestor)
53
+ # top-level services: The end of the section generated from our OpenAPI spec
891
54
  end
892
55
 
893
- private def log_request(context, num_retries)
894
- Util.log_info("Request to Stripe API",
895
- account: context.account,
896
- api_version: context.api_version,
897
- idempotency_key: context.idempotency_key,
898
- method: context.method,
899
- num_retries: num_retries,
900
- path: context.path,
901
- config: config)
902
- Util.log_debug("Request details",
903
- body: context.body,
904
- idempotency_key: context.idempotency_key,
905
- query: context.query,
906
- config: config,
907
- process_id: Process.pid,
908
- thread_object_id: Thread.current.object_id,
909
- log_timestamp: Util.monotonic_time)
56
+ def request(&block)
57
+ @requestor.request(&block)
910
58
  end
59
+ extend Gem::Deprecate
60
+ deprecate :request, :raw_request, 2024, 9
911
61
 
912
- private def log_response(context, request_start, status, body, resp)
913
- Util.log_info("Response from Stripe API",
914
- account: context.account,
915
- api_version: context.api_version,
916
- elapsed: Util.monotonic_time - request_start,
917
- idempotency_key: context.idempotency_key,
918
- method: context.method,
919
- path: context.path,
920
- request_id: context.request_id,
921
- status: status,
922
- config: config)
923
- Util.log_debug("Response details",
924
- body: body,
925
- idempotency_key: context.idempotency_key,
926
- request_id: context.request_id,
927
- config: config,
928
- process_id: Process.pid,
929
- thread_object_id: Thread.current.object_id,
930
- response_object_id: resp.object_id,
931
- log_timestamp: Util.monotonic_time)
62
+ def parse_thin_event(payload, sig_header, secret, tolerance: Webhook::DEFAULT_TOLERANCE)
63
+ payload = payload.force_encoding("UTF-8") if payload.respond_to?(:force_encoding)
932
64
 
933
- return unless context.request_id
65
+ # v2 events use the same signing mechanism as v1 events
66
+ Webhook::Signature.verify_header(payload, sig_header, secret, tolerance: tolerance)
934
67
 
935
- Util.log_debug("Dashboard link for request",
936
- idempotency_key: context.idempotency_key,
937
- request_id: context.request_id,
938
- url: Util.request_id_dashboard_url(context.request_id,
939
- context.api_key),
940
- config: config)
941
- end
68
+ parsed = JSON.parse(payload, symbolize_names: true)
942
69
 
943
- private def log_response_error(context, request_start, error)
944
- elapsed = request_start ? Util.monotonic_time - request_start : nil
945
- Util.log_error("Request error",
946
- elapsed: elapsed,
947
- error_message: error.message,
948
- idempotency_key: context.idempotency_key,
949
- method: context.method,
950
- path: context.path,
951
- config: config)
70
+ Stripe::ThinEvent.new(parsed)
952
71
  end
953
72
 
954
- # RequestLogContext stores information about a request that's begin made so
955
- # that we can log certain information. It's useful because it means that we
956
- # don't have to pass around as many parameters.
957
- class RequestLogContext
958
- attr_accessor :body
959
- attr_accessor :account
960
- attr_accessor :api_key
961
- attr_accessor :api_version
962
- attr_accessor :idempotency_key
963
- attr_accessor :method
964
- attr_accessor :path
965
- attr_accessor :query
966
- attr_accessor :request_id
73
+ def raw_request(method, url, base_address: :api, params: {}, opts: {})
74
+ opts = Util.normalize_opts(opts)
75
+ req_opts = RequestOptions.extract_opts_from_hash(opts)
967
76
 
968
- # The idea with this method is that we might want to update some of
969
- # context information because a response that we've received from the API
970
- # contains information that's more authoritative than what we started
971
- # with for a request. For example, we should trust whatever came back in
972
- # a `Stripe-Version` header beyond what configuration information that we
973
- # might have had available.
974
- def dup_from_response_headers(headers)
975
- context = dup
976
- context.account = headers["Stripe-Account"]
977
- context.api_version = headers["Stripe-Version"]
978
- context.idempotency_key = headers["Idempotency-Key"]
979
- context.request_id = headers["Request-Id"]
980
- context
981
- end
982
- end
983
-
984
- # SystemProfiler extracts information about the system that we're running
985
- # in so that we can generate a rich user agent header to help debug
986
- # integrations.
987
- class SystemProfiler
988
- def self.uname
989
- if ::File.exist?("/proc/version")
990
- ::File.read("/proc/version").strip
991
- else
992
- case RbConfig::CONFIG["host_os"]
993
- when /linux|darwin|bsd|sunos|solaris|cygwin/i
994
- uname_from_system
995
- when /mswin|mingw/i
996
- uname_from_system_ver
997
- else
998
- "unknown platform"
999
- end
1000
- end
1001
- end
77
+ resp, = @requestor.send(:execute_request_internal, method, url, base_address, params, req_opts, usage: ["raw_request"])
1002
78
 
1003
- def self.uname_from_system
1004
- (`uname -a 2>/dev/null` || "").strip
1005
- rescue Errno::ENOENT
1006
- "uname executable not found"
1007
- rescue Errno::ENOMEM # couldn't create subprocess
1008
- "uname lookup failed"
1009
- end
1010
-
1011
- def self.uname_from_system_ver
1012
- (`ver` || "").strip
1013
- rescue Errno::ENOENT
1014
- "ver executable not found"
1015
- rescue Errno::ENOMEM # couldn't create subprocess
1016
- "uname lookup failed"
1017
- end
1018
-
1019
- def initialize
1020
- @uname = self.class.uname
1021
- end
1022
-
1023
- def user_agent
1024
- lang_version = "#{RUBY_VERSION} p#{RUBY_PATCHLEVEL} " \
1025
- "(#{RUBY_RELEASE_DATE})"
1026
-
1027
- {
1028
- application: Stripe.app_info,
1029
- bindings_version: Stripe::VERSION,
1030
- lang: "ruby",
1031
- lang_version: lang_version,
1032
- platform: RUBY_PLATFORM,
1033
- engine: defined?(RUBY_ENGINE) ? RUBY_ENGINE : "",
1034
- publisher: "stripe",
1035
- uname: @uname,
1036
- hostname: Socket.gethostname,
1037
- }.delete_if { |_k, v| v.nil? }
1038
- end
79
+ @requestor.interpret_response(resp)
1039
80
  end
1040
81
 
1041
- # StripeRequestMetrics tracks metadata to be reported to stripe for metrics
1042
- # collection
1043
- class StripeRequestMetrics
1044
- # The Stripe request ID of the response.
1045
- attr_accessor :request_id
1046
-
1047
- # Request duration in milliseconds
1048
- attr_accessor :request_duration_ms
1049
-
1050
- def initialize(request_id, request_duration_ms)
1051
- self.request_id = request_id
1052
- self.request_duration_ms = request_duration_ms
1053
- end
1054
-
1055
- def payload
1056
- { request_id: request_id, request_duration_ms: request_duration_ms }
1057
- end
82
+ def deserialize(data, api_mode: :v1)
83
+ data = JSON.parse(data) if data.is_a?(String)
84
+ Util.convert_to_stripe_object(data, {}, api_mode: api_mode, requestor: @requestor)
1058
85
  end
1059
86
  end
1060
87
  end