yoomoney 0.4.1 → 0.5.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 5a9dd0aa982a39414ab87a649a2c640d6ded44640cb26a816d9c2a007611a886
4
- data.tar.gz: 20abe4c00231561b2d7e5dc856c36865198f79e2c561c6623b6be5f4a1dcc0f0
3
+ metadata.gz: 116b577dd94dc89b2d69be97dc4d82df0193d712a2d1f8cf30ab64766f779a27
4
+ data.tar.gz: 897f850b6bc8dd6589fe8ff6863d256c5c2e4ecbff4a2b70bdb94e9954058fe2
5
5
  SHA512:
6
- metadata.gz: c7948b62da23b4d1ef45daec6d7fd89b38cc685dbf1b677d02f48bf6f3d25fd8510782bfa09953e645de0c9d952cb1e45365ab70321d01aac014428260678814
7
- data.tar.gz: a7d33fa092c2651fa73100150415450e0f00567e7998ca4b74f8cfee7b924c85405f679cd9309a590db10414eb19569236a25f7a3b73496c80e6bbabae9b1226
6
+ metadata.gz: 512e4744d0456924bf05dec0897c3f47ffe8c60395c5e1937e22084e83e32e237ce09adf4f19ea27913ce2b7fe3f013d87c01165436ffc292e6a399e670c5b45
7
+ data.tar.gz: 9a0e7dfc0421721ecc623869def7a7eb1a3402a663015f5323ba65dff7c9c8f9658b93ee574a2b4ddb601c68e047b2c11cf3134716943bc5204c4e14980d0612
data/CHANGELOG.md CHANGED
@@ -1,5 +1,31 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.5.0 (2026-05-14)
4
+
5
+ Full Changelog: [v0.4.1...v0.5.0](https://github.com/Hexlet/yoomoney-ruby/compare/v0.4.1...v0.5.0)
6
+
7
+ ### Features
8
+
9
+ * support setting headers via env ([56d1e96](https://github.com/Hexlet/yoomoney-ruby/commit/56d1e963c6df51152c0d93f8211f158378949339))
10
+
11
+
12
+ ### Bug Fixes
13
+
14
+ * align path encoding with RFC 3986 section 3.3 ([9bd4272](https://github.com/Hexlet/yoomoney-ruby/commit/9bd4272cb3ac8f124da75aa27ec3a39f7c8b0666))
15
+ * **client:** elide content type header on requests without body ([437bba0](https://github.com/Hexlet/yoomoney-ruby/commit/437bba09741612ee2bdf1cd4c7b550bbfa9c37c2))
16
+ * **internal:** correct multipart form field name encoding ([c92d15c](https://github.com/Hexlet/yoomoney-ruby/commit/c92d15c3f6eed70c96278d9f43bfa96e6a0e951b))
17
+ * multipart encoding for file arrays ([b8e11b9](https://github.com/Hexlet/yoomoney-ruby/commit/b8e11b90d5985fcb84a7dcc96ad06d22ea6c9fad))
18
+ * variable name typo ([7470296](https://github.com/Hexlet/yoomoney-ruby/commit/7470296ce37a30019e968a86b72fa910b045702d))
19
+
20
+
21
+ ### Chores
22
+
23
+ * **ci:** skip lint on metadata-only changes ([9f29e5b](https://github.com/Hexlet/yoomoney-ruby/commit/9f29e5b7f76fa07d4c03220b203563f2d0e6b026))
24
+ * **ci:** support opting out of skipping builds on metadata-only commits ([823e1af](https://github.com/Hexlet/yoomoney-ruby/commit/823e1af5ed00238d318236fb6f13d0d35380a53e))
25
+ * **internal:** more robust bootstrap script ([9813a57](https://github.com/Hexlet/yoomoney-ruby/commit/9813a5744c83c44425e6b43267c500ec09e6bd29))
26
+ * **internal:** tweak CI branches ([f732219](https://github.com/Hexlet/yoomoney-ruby/commit/f7322192ae33c7a63dcda5ee362df4144cc65598))
27
+ * **internal:** update gitignore ([25dfa03](https://github.com/Hexlet/yoomoney-ruby/commit/25dfa03491acfe4fc43aa3745101e2add214cbe4))
28
+
3
29
  ## 0.4.1 (2026-03-07)
4
30
 
5
31
  Full Changelog: [v0.4.0...v0.4.1](https://github.com/Hexlet/yoomoney-ruby/compare/v0.4.0...v0.4.1)
data/README.md CHANGED
@@ -15,7 +15,7 @@ To use this gem, install via Bundler by adding the following to your application
15
15
  <!-- x-release-please-start-version -->
16
16
 
17
17
  ```ruby
18
- gem "yoomoney", "~> 0.4.1"
18
+ gem "yoomoney", "~> 0.5.0"
19
19
  ```
20
20
 
21
21
  <!-- x-release-please-end -->
@@ -95,6 +95,19 @@ module Yoomoney
95
95
  )
96
96
  base_url ||= "https://api.yookassa.ru/v3"
97
97
 
98
+ headers = {}
99
+ custom_headers_env = ENV["YOOMONEY_CUSTOM_HEADERS"]
100
+ unless custom_headers_env.nil?
101
+ parsed = {}
102
+ custom_headers_env.split("\n").each do |line|
103
+ colon = line.index(":")
104
+ unless colon.nil?
105
+ parsed[line[0...colon].strip] = line[(colon + 1)..].strip
106
+ end
107
+ end
108
+ headers = parsed.merge(headers)
109
+ end
110
+
98
111
  @username = username&.to_s
99
112
  @password = password&.to_s
100
113
 
@@ -103,7 +116,8 @@ module Yoomoney
103
116
  timeout: timeout,
104
117
  max_retries: max_retries,
105
118
  initial_retry_delay: initial_retry_delay,
106
- max_retry_delay: max_retry_delay
119
+ max_retry_delay: max_retry_delay,
120
+ headers: headers
107
121
  )
108
122
 
109
123
  @payments = Yoomoney::Resources::Payments.new(client: self)
@@ -306,6 +306,8 @@ module Yoomoney
306
306
  Yoomoney::Internal::Util.deep_merge(*[req[:body], opts[:extra_body]].compact)
307
307
  end
308
308
 
309
+ headers.delete("content-type") if body.nil?
310
+
309
311
  url = Yoomoney::Internal::Util.join_parsed_uri(
310
312
  @base_url_components,
311
313
  {**req, path: path, query: query}
@@ -157,7 +157,7 @@ module Yoomoney
157
157
  in Hash | nil => coerced
158
158
  coerced
159
159
  else
160
- message = "Expected a #{Hash} or #{Yoomoney::Internal::Type::BaseModel}, got #{data.inspect}"
160
+ message = "Expected a #{Hash} or #{Yoomoney::Internal::Type::BaseModel}, got #{input.inspect}"
161
161
  raise ArgumentError.new(message)
162
162
  end
163
163
  end
@@ -237,6 +237,11 @@ module Yoomoney
237
237
  end
238
238
  end
239
239
 
240
+ # @type [Regexp]
241
+ #
242
+ # https://www.rfc-editor.org/rfc/rfc3986.html#section-3.3
243
+ RFC_3986_NOT_PCHARS = /[^A-Za-z0-9\-._~!$&'()*+,;=:@]+/
244
+
240
245
  class << self
241
246
  # @api private
242
247
  #
@@ -247,6 +252,15 @@ module Yoomoney
247
252
  "#{uri.scheme}://#{uri.host}#{":#{uri.port}" unless uri.port == uri.default_port}"
248
253
  end
249
254
 
255
+ # @api private
256
+ #
257
+ # @param path [String, Integer]
258
+ #
259
+ # @return [String]
260
+ def encode_path(path)
261
+ path.to_s.gsub(Yoomoney::Internal::Util::RFC_3986_NOT_PCHARS) { ERB::Util.url_encode(_1) }
262
+ end
263
+
250
264
  # @api private
251
265
  #
252
266
  # @param path [String, Array<String>]
@@ -259,7 +273,7 @@ module Yoomoney
259
273
  in []
260
274
  ""
261
275
  in [String => p, *interpolations]
262
- encoded = interpolations.map { ERB::Util.url_encode(_1) }
276
+ encoded = interpolations.map { encode_path(_1) }
263
277
  format(p, *encoded)
264
278
  end
265
279
  end
@@ -571,16 +585,15 @@ module Yoomoney
571
585
  y << "Content-Disposition: form-data"
572
586
 
573
587
  unless key.nil?
574
- name = ERB::Util.url_encode(key.to_s)
575
- y << "; name=\"#{name}\""
588
+ y << "; name=\"#{key}\""
576
589
  end
577
590
 
578
591
  case val
579
592
  in Yoomoney::FilePart unless val.filename.nil?
580
- filename = ERB::Util.url_encode(val.filename)
593
+ filename = encode_path(val.filename)
581
594
  y << "; filename=\"#{filename}\""
582
595
  in Pathname | IO
583
- filename = ERB::Util.url_encode(::File.basename(val.to_path))
596
+ filename = encode_path(::File.basename(val.to_path))
584
597
  y << "; filename=\"#{filename}\""
585
598
  else
586
599
  end
@@ -597,6 +610,7 @@ module Yoomoney
597
610
  #
598
611
  # @return [Array(String, Enumerable<String>)]
599
612
  private def encode_multipart_streaming(body)
613
+ # rubocop:disable Style/CaseEquality
600
614
  # RFC 1521 Section 7.2.1 says we should have 70 char maximum for boundary length
601
615
  boundary = SecureRandom.urlsafe_base64(46)
602
616
 
@@ -606,7 +620,7 @@ module Yoomoney
606
620
  in Hash
607
621
  body.each do |key, val|
608
622
  case val
609
- in Array if val.all? { primitive?(_1) }
623
+ in Array if val.all? { primitive?(_1) || Yoomoney::Internal::Type::FileInput === _1 }
610
624
  val.each do |v|
611
625
  write_multipart_chunk(y, boundary: boundary, key: key, val: v, closing: closing)
612
626
  end
@@ -622,6 +636,7 @@ module Yoomoney
622
636
 
623
637
  fused_io = fused_enum(strio) { closing.each(&:call) }
624
638
  [boundary, fused_io]
639
+ # rubocop:enable Style/CaseEquality
625
640
  end
626
641
 
627
642
  # @api private
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Yoomoney
4
- VERSION = "0.4.1"
4
+ VERSION = "0.5.0"
5
5
  end
@@ -148,12 +148,20 @@ module Yoomoney
148
148
  end
149
149
  end
150
150
 
151
+ # https://www.rfc-editor.org/rfc/rfc3986.html#section-3.3
152
+ RFC_3986_NOT_PCHARS = T.let(/[^A-Za-z0-9\-._~!$&'()*+,;=:@]+/, Regexp)
153
+
151
154
  class << self
152
155
  # @api private
153
156
  sig { params(uri: URI::Generic).returns(String) }
154
157
  def uri_origin(uri)
155
158
  end
156
159
 
160
+ # @api private
161
+ sig { params(path: T.any(String, Integer)).returns(String) }
162
+ def encode_path(path)
163
+ end
164
+
157
165
  # @api private
158
166
  sig { params(path: T.any(String, T::Array[String])).returns(String) }
159
167
  def interpolate_path(path)
@@ -45,8 +45,12 @@ module Yoomoney
45
45
  -> top?
46
46
  } -> top?
47
47
 
48
+ RFC_3986_NOT_PCHARS: Regexp
49
+
48
50
  def self?.uri_origin: (URI::Generic uri) -> String
49
51
 
52
+ def self?.encode_path: (String | Integer path) -> String
53
+
50
54
  def self?.interpolate_path: (String | ::Array[String] path) -> String
51
55
 
52
56
  def self?.decode_query: (String? query) -> ::Hash[String, ::Array[String]]
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: yoomoney
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.1
4
+ version: 0.5.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Yoomoney
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2026-03-16 00:00:00.000000000 Z
11
+ date: 2026-06-19 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: cgi