diff --git a/README.md b/README.md index a271ef82..fea4b783 100644 --- a/README.md +++ b/README.md @@ -317,6 +317,35 @@ You can disable this behavior if you prefer: Stripe.enable_telemetry = false ``` +### Types + +In [v14.0.0](https://github.com/stripe/stripe-python/releases/tag/v7.1.0) and newer, the library provides RBI +static type annotations. See [the wiki](https://github.com/stripe/stripe-ruby/wiki/Static-Type-Annotations) +for an detailed guide. + +Please note that these types are available only for static analysis and we only support RBIs at the moment. +Please [report an issue](https://github.com/stripe/stripe-ruby/issues/new/choose) +if you find discrepancies or have issues using types. + +The RBIs can be found in the `rbi/stripe/` directory, and to decrease `Tapioca` loading time we pack the gem with the +combined RBI at `rbi/stripe.rbi`. + +#### Types and the Versioning Policy + +We release type changes in minor releases. While stripe-ruby follows semantic versioning, our semantic +versions describe the runtime behavior of the library alone. Our type annotations are not reflected in the +semantic version. That is, upgrading to a new minor version of `stripe-ruby` might result in your type checker +producing a type error that it didn't before. You can use `~> x.x` or `x.x.x` constrain the version +of `stripe-ruby` in your Gemfile to a certain version or range of `stripe-ruby`. + +#### Types and API Versions + +The types describe the [Stripe API version](https://stripe.com/docs/api/versioning) +that was the latest at the time of release. This is the version that your library sends +by default. If you are overriding `Stripe.api_version` / `stripe_version` on the StripeClient, +or using a webhook endpoint tied to an older version, be aware that the data +you see at runtime may not match the types. + ### Beta SDKs Stripe has features in the beta phase that can be accessed via the beta version of this package. diff --git a/lib/stripe/api_requestor.rb b/lib/stripe/api_requestor.rb index 78d35ebd..0339f343 100644 --- a/lib/stripe/api_requestor.rb +++ b/lib/stripe/api_requestor.rb @@ -222,6 +222,7 @@ module Stripe params: {}, opts: {}, usage: []) opts = RequestOptions.combine_opts(object.instance_variable_get(:@opts), opts) opts = Util.normalize_opts(opts) + params = params.to_h if params.is_a?(RequestParams) http_resp, req_opts = execute_request_internal( method, path, base_address, params, opts, usage ) @@ -271,6 +272,7 @@ module Stripe "execute_request_stream requires a read_body_chunk_block" end + params = params.to_h if params.is_a?(RequestParams) http_resp, api_key = execute_request_internal( method, path, base_address, params, opts, usage, &read_body_chunk_block ) diff --git a/lib/stripe/stripe_client.rb b/lib/stripe/stripe_client.rb index b98e868d..5aa54bce 100644 --- a/lib/stripe/stripe_client.rb +++ b/lib/stripe/stripe_client.rb @@ -74,6 +74,7 @@ module Stripe opts = Util.normalize_opts(opts) req_opts = RequestOptions.extract_opts_from_hash(opts) + params = params.to_h if params.is_a?(Stripe::RequestParams) resp, = @requestor.send(:execute_request_internal, method, url, base_address, params, req_opts, usage: ["raw_request"]) @requestor.interpret_response(resp) diff --git a/test/stripe/request_params_test.rb b/test/stripe/request_params_test.rb index b1321881..a36540d2 100644 --- a/test/stripe/request_params_test.rb +++ b/test/stripe/request_params_test.rb @@ -51,5 +51,87 @@ module Stripe assert cus.is_a?(Stripe::Customer) end end + + context "different request types" do + should "create a customer with params class" do + stub_request(:post, "#{Stripe.api_base}/v1/customers") + .with(body: "name=foo") + .to_return(body: JSON.generate(object: "customer", id: "cus_123", name: "foo")) + + params = Stripe::Customer::CreateParams.new(name: "foo") + customer = Stripe::Customer.create(params) + + assert customer.is_a?(Stripe::Customer) + assert_equal "cus_123", customer.id + assert_equal "foo", customer.name + end + + should "update a customer with params class" do + stub_request(:post, "#{Stripe.api_base}/v1/customers/cus_123") + .with(body: "name=bar") + .to_return(body: JSON.generate(object: "customer", id: "cus_123", name: "bar")) + + params = Stripe::Customer::UpdateParams.new(name: "bar") + customer = Stripe::Customer.update("cus_123", params) + + assert customer.is_a?(Stripe::Customer) + assert_equal "cus_123", customer.id + assert_equal "bar", customer.name + end + + # NOTE: Resource-based retrieve expand is a special case... + should "retrieve a customer with params class" do + stub_request(:get, "#{Stripe::DEFAULT_API_BASE}/v1/customers/cus_123?expand[]=foo") + .to_return(body: JSON.generate(object: "customer", id: "cus_123", name: "foo")) + + @client = Stripe::StripeClient.new("sk_test_123") + customer = @client.v1.customers.retrieve("cus_123", CustomerService::RetrieveParams.new(expand: [:foo])) + + assert customer.is_a?(Stripe::Customer) + end + + should "list customers with params class" do + stub_request(:get, "#{Stripe.api_base}/v1/customers") + .to_return(body: JSON.generate(object: "list", data: [{ id: "cus_123", name: "foo" }, { id: "cus_456", name: "bar" }])) + + customers = Stripe::Customer.list + + assert customers.is_a?(Stripe::ListObject) + assert_equal 2, customers.data.size + assert_equal "cus_123", customers.data[0].id + assert_equal "foo", customers.data[0].name + assert_equal "cus_456", customers.data[1].id + assert_equal "bar", customers.data[1].name + end + + should "search customers with params class" do + stub_request(:get, "#{Stripe.api_base}/v1/customers/search") + .with(query: { query: "name:'foo'" }) + .to_return(body: JSON.generate(object: "search_result", data: [{ id: "cus_123", name: "foo" }])) + + params = Stripe::Customer::SearchParams.new(query: "name:'foo'") + customers = Stripe::Customer.search(params) + + assert customers.is_a?(Stripe::SearchResultObject) + assert_equal 1, customers.data.size + assert_equal "cus_123", customers.data[0].id + assert_equal "foo", customers.data[0].name + end + + should "request params work in raw request" do + expected_body = JSON.generate(id: "cus_123", name: "foo") + req = nil + + stub_request(:post, "#{Stripe::DEFAULT_API_BASE}/v1/customers") + .with(body: "name=foo") + .with { |request| req = request } + .to_return(body: expected_body) + + @client = Stripe::StripeClient.new("sk_test_123") + resp = @client.raw_request(:post, "/v1/customers", params: Customer::CreateParams.new(name: "foo")) + + assert_equal expected_body, resp.http_body + end + end end end