payjpv2 1.0.9 → 1.0.11

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: 0ca8c575db78b77fb06a21cdb1ffc6e284f77ee7ab3467cac2561ae8a785e1b4
4
- data.tar.gz: 82b57ee3897a2fc4eb630bce32953b0eb0f90b91814ea5d788ec23351f368ac3
3
+ metadata.gz: b5c7c9af553704a217bd596adb3053420567631ce8cc4f70e645359d4d4bd39e
4
+ data.tar.gz: c6f326ca919ac51333a6088d36dccca76d3a7748006709b52af31b0beaf1a9b1
5
5
  SHA512:
6
- metadata.gz: e27d9de313657404a90718cf6557fe580330f4d92bf7ebf9a1ba4bf2c2dc256115417511d403d0b1a0ba29f369daa8a21c798ff6b759f4e8a8f3fe643e116c25
7
- data.tar.gz: 5ec8dde17ad88188980108f983b961f6f8a636c10fcd7f4e4d94ec12daea76dde422ddeea87037c83e57a42e22c800b9522b04ed4c0dd4dae8af138bd6c08976
6
+ metadata.gz: 347a4b4656ec911fc1cdb57edff26d85111fa396c62e7d620d31ff529b4eb28c5f9cf0104131316e95583cab03177d4e6261dc794fe4a438fa22486dbcd665bd
7
+ data.tar.gz: aa7a00e763734f551ee06ec9eaba83608c798d9979ae473c28cc36edfc7530a67aa3abf44117e949c841dc2c1ba4a502c9372f1ba48feea428ea646cbb6d268d
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- payjpv2 (1.0.9)
4
+ payjpv2 (1.0.11)
5
5
  typhoeus (~> 1.0, >= 1.0.1)
6
6
 
7
7
  GEM
data/README.md CHANGED
@@ -5,7 +5,7 @@ A Ruby client library for the PAY.JP v2 API. This SDK provides a convenient way
5
5
  This Ruby gem is automatically generated by the [OpenAPI Generator](https://openapi-generator.tech) project:
6
6
 
7
7
  - API version: 2.0.0
8
- - Package version: 1.0.9
8
+ - Package version: 1.0.11
9
9
  - Generator version: 7.14.0
10
10
  - Build package: org.openapitools.codegen.languages.RubyClientCodegen
11
11
 
@@ -26,7 +26,7 @@ gem install payjpv2
26
26
  Add this line to your application's Gemfile:
27
27
 
28
28
  ```ruby
29
- gem 'payjpv2', '~> 1.0.9'
29
+ gem 'payjpv2', '~> 1.0.11'
30
30
  ```
31
31
 
32
32
  Then execute:
@@ -4,7 +4,7 @@
4
4
 
5
5
  | Name | Type | Description | Notes |
6
6
  | ---- | ---- | ----------- | ----- |
7
- | **request_extended_authorization** | **String** | オーソリ期間の延長要求 | 指定できる値 | |:---| | **if_available**: オーソリ期間の延長が可能な場合に延長要求を行います。 | | **never**: オーソリ期間の延長要求を行いません。 | | [optional] |
7
+ | **request_extended_authorization** | **String** | オーソリ期間の延長要求 | 指定できる値 | |:---| | **if_available**: オーソリ期間の延長が可能な場合に延長要求を行います。 | | **must_extend**: オーソリ期間の延長を必須とします。延長できない場合はエラーを返します。 | | **never**: オーソリ期間の延長要求を行いません。 | | [optional] |
8
8
  | **request_three_d_secure** | **String** | 3D セキュア認証の要求方法 | 指定できる値 | |:---| | **any**: 3D セキュア認証を要求します。 | | **automatic**: 必要な場合にのみ 3D セキュア認証を要求します。 | | [optional] |
9
9
 
10
10
  ## Example
@@ -4,7 +4,7 @@
4
4
 
5
5
  | Name | Type | Description | Notes |
6
6
  | ---- | ---- | ----------- | ----- |
7
- | **request_extended_authorization** | **String** | オーソリ期間の延長要求 | 値 | |:---| | **if_available**: オーソリ期間の延長が可能な場合に延長要求を行います。 | | **never**: オーソリ期間の延長要求を行いません。 | | [optional] |
7
+ | **request_extended_authorization** | **String** | オーソリ期間の延長要求 | 値 | |:---| | **if_available**: オーソリ期間の延長が可能な場合に延長要求を行います。 | | **must_extend**: オーソリ期間の延長を必須とします。延長できない場合はエラーを返します。 | | **never**: オーソリ期間の延長要求を行いません。 | | [optional] |
8
8
  | **request_three_d_secure** | **String** | 3D セキュア認証の要求方法。 | 値 | |:---| | **any**: 3D セキュア認証を要求します。 | | **automatic**: 必要な場合にのみ 3D セキュア認証を要求します。 | | [optional] |
9
9
 
10
10
  ## Example
@@ -24,6 +24,7 @@
24
24
  | **last_payment_error** | **Hash<String, Object>** | | |
25
25
  | **cancellation_reason** | [**PaymentFlowCancellationReason**](PaymentFlowCancellationReason.md) | | |
26
26
  | **canceled_at** | **Time** | | |
27
+ | **expired_at** | **Time** | | [optional] |
27
28
  | **metadata** | [**Hash<String, MetadataValue>**](MetadataValue.md) | メタデータ | |
28
29
  | **created_at** | **Time** | 作成日時 (UTC, ISO 8601 形式) | |
29
30
  | **updated_at** | **Time** | 更新日時 (UTC, ISO 8601 形式) | |
@@ -54,6 +55,7 @@ instance = PAYJPv2::PaymentFlowResponse.new(
54
55
  last_payment_error: null,
55
56
  cancellation_reason: null,
56
57
  canceled_at: null,
58
+ expired_at: null,
57
59
  metadata: null,
58
60
  created_at: null,
59
61
  updated_at: null
data/example.rb CHANGED
@@ -21,6 +21,7 @@ api_instance = PAYJPv2::CustomersApi.new
21
21
  checkout_sessions_api = PAYJPv2::CheckoutSessionsApi.new
22
22
  products_api = PAYJPv2::ProductsApi.new
23
23
  prices_api = PAYJPv2::PricesApi.new
24
+ payment_methods_api = PAYJPv2::PaymentMethodsApi.new
24
25
 
25
26
  customer_create_request = PAYJPv2::CustomerCreateRequest.new(
26
27
  email: 'jennyrosen@example.com',
@@ -73,16 +74,65 @@ begin
73
74
  end
74
75
  puts "\n"
75
76
 
76
- # 5. Delete Customer
77
- puts "=== 5. Delete Customer ==="
77
+ # 5. PaymentMethod operations
78
+ # Note: create_payment_method is available only in test mode. In production,
79
+ # a PaymentMethod is created by tokenizing card details on the client side
80
+ # (e.g. payment.js) and then attaching the resulting token to a Customer.
81
+ puts "=== 5. PaymentMethod operations ==="
82
+
83
+ # 5a. Create PaymentMethod (test mode)
84
+ puts "\n--- 5a. Create PaymentMethod (test mode) ---"
85
+ payment_method_request = PAYJPv2::PaymentMethodCardCreateRequest.new(
86
+ type: 'card',
87
+ card: PAYJPv2::PaymentMethodCreateCardDetailsRequest.new(
88
+ number: '4242424242424242',
89
+ exp_month: 12,
90
+ exp_year: 2030,
91
+ cvc: '123'
92
+ ),
93
+ billing_details: PAYJPv2::PaymentMethodCardBillingDetailsRequest.new(
94
+ email: 'billing@example.com'
95
+ )
96
+ )
97
+ payment_method = payment_methods_api.create_payment_method(payment_method_request)
98
+ payment_method_id = payment_method.id
99
+ puts "Created PaymentMethod: #{payment_method_id}"
100
+ puts "Type: #{payment_method.type}"
101
+
102
+ # 5b. Attach PaymentMethod to Customer
103
+ puts "\n--- 5b. Attach PaymentMethod ---"
104
+ attached = payment_methods_api.attach_payment_method(
105
+ payment_method_id,
106
+ PAYJPv2::PaymentMethodAttachRequest.new(customer_id: customer_id)
107
+ )
108
+ puts "Attached PaymentMethod: #{attached.id}"
109
+ puts "Customer: #{attached.customer_id}"
110
+
111
+ # 5c. Retrieve PaymentMethod (active)
112
+ puts "\n--- 5c. Retrieve PaymentMethod ---"
113
+ retrieved_pm = payment_methods_api.get_payment_method(payment_method_id)
114
+ puts "PaymentMethod ID: #{retrieved_pm.id}"
115
+ puts "Customer: #{retrieved_pm.customer_id}"
116
+ puts "Detached at: #{retrieved_pm.detached_at || '(active)'}"
117
+
118
+ # 5d. Detach PaymentMethod
119
+ # The API marks the PaymentMethod with `detached_at` while keeping
120
+ # `customer_id` for historical reference.
121
+ puts "\n--- 5d. Detach PaymentMethod ---"
122
+ detached = payment_methods_api.detach_payment_method(payment_method_id)
123
+ puts "Detached PaymentMethod: #{detached.id}"
124
+ puts "Detached at: #{detached.detached_at}\n\n"
125
+
126
+ # 6. Delete Customer
127
+ puts "=== 6. Delete Customer ==="
78
128
  api_instance.delete_customer(customer_id)
79
129
  puts "Deleted customer: #{customer_id}\n\n"
80
130
 
81
- # 6. Create Product, Price, and Checkout Session
82
- puts "=== 6. Create Product, Price, and Checkout Session ==="
131
+ # 7. Create Product, Price, and Checkout Session
132
+ puts "=== 7. Create Product, Price, and Checkout Session ==="
83
133
 
84
- # 6a. Create Product
85
- puts "\n--- 6a. Create Product ---"
134
+ # 7a. Create Product
135
+ puts "\n--- 7a. Create Product ---"
86
136
  product_request = PAYJPv2::ProductCreateRequest.new(
87
137
  name: 'Sample Product',
88
138
  description: 'A sample product for checkout session demo',
@@ -100,8 +150,8 @@ begin
100
150
  puts "Created product: #{product_id}"
101
151
  puts "Product name: #{product.name}"
102
152
 
103
- # 6b. Create Price
104
- puts "\n--- 6b. Create Price ---"
153
+ # 7b. Create Price
154
+ puts "\n--- 7b. Create Price ---"
105
155
  price_request = PAYJPv2::PriceCreateRequest.new(
106
156
  currency: 'jpy',
107
157
  product_id: product_id,
@@ -121,8 +171,8 @@ begin
121
171
  puts "Created price: #{price_id}"
122
172
  puts "Unit amount: #{price.unit_amount} JPY"
123
173
 
124
- # 6c. Create Checkout Session
125
- puts "\n--- 6c. Create Checkout Session ---"
174
+ # 7c. Create Checkout Session
175
+ puts "\n--- 7c. Create Checkout Session ---"
126
176
  line_items = [
127
177
  PAYJPv2::LineItemRequest.new(
128
178
  price_id: price_id, # Use the actual price ID we just created
@@ -158,5 +208,5 @@ begin
158
208
  puts "=== All tests passed! ==="
159
209
 
160
210
  rescue PAYJPv2::ApiError => e
161
- puts "Exception when calling CustomersApi->create_customer: #{e}"
211
+ puts "Exception when calling PAYJPv2 API: #{e}"
162
212
  end
@@ -280,9 +280,9 @@ module PAYJPv2
280
280
  data.each { |k, v| hash[k] = convert_to_type(v, sub_type) }
281
281
  end
282
282
  else
283
- # models (e.g. Pet) or oneOf
283
+ # models (e.g. Pet) or oneOf / anyOf
284
284
  klass = PAYJPv2.const_get(return_type)
285
- klass.respond_to?(:openapi_one_of) ? klass.build(data) : klass.build_from_hash(data)
285
+ klass.respond_to?(:openapi_any_of) || klass.respond_to?(:openapi_one_of) ? klass.build(data) : klass.build_from_hash(data)
286
286
  end
287
287
  end
288
288
 
@@ -15,7 +15,7 @@ require 'time'
15
15
 
16
16
  module PAYJPv2
17
17
  class CheckoutSessionPaymentMethodOptionsCardRequest
18
- # オーソリ期間の延長要求 | 指定できる値 | |:---| | **if_available**: オーソリ期間の延長が可能な場合に延長要求を行います。 | | **never**: オーソリ期間の延長要求を行いません。 |
18
+ # オーソリ期間の延長要求 | 指定できる値 | |:---| | **if_available**: オーソリ期間の延長が可能な場合に延長要求を行います。 | | **must_extend**: オーソリ期間の延長を必須とします。延長できない場合はエラーを返します。 | | **never**: オーソリ期間の延長要求を行いません。 |
19
19
  attr_accessor :request_extended_authorization
20
20
 
21
21
  # 3D セキュア認証の要求方法 | 指定できる値 | |:---| | **any**: 3D セキュア認証を要求します。 | | **automatic**: 必要な場合にのみ 3D セキュア認証を要求します。 |
@@ -103,7 +103,7 @@ module PAYJPv2
103
103
  # Custom attribute writer method checking allowed values (enum).
104
104
  # @param [Object] request_extended_authorization Object to be assigned
105
105
  def request_extended_authorization=(request_extended_authorization)
106
- validator = EnumAttributeValidator.new('String', ["if_available", "never"])
106
+ validator = EnumAttributeValidator.new('String', ["if_available", "must_extend", "never"])
107
107
  unless validator.valid?(request_extended_authorization)
108
108
  raise ArgumentError, "invalid value for \"request_extended_authorization\", must be one of #{validator.allowable_values}."
109
109
  end
@@ -88,7 +88,8 @@ module PAYJPv2
88
88
  return model if model
89
89
  else
90
90
  # raise if data contains keys that are not known to the model
91
- raise if const.respond_to?(:acceptable_attributes) && !(data.keys - const.acceptable_attributes).empty?
91
+ # NOTE: acceptable_attributes returns symbols while data keys are strings (from JSON.parse), so symbolize before diff
92
+ raise if const.respond_to?(:acceptable_attributes) && !(data.keys.map(&:to_sym) - const.acceptable_attributes).empty?
92
93
  model = const.build_from_hash(data)
93
94
  return model if model
94
95
  end
@@ -15,7 +15,7 @@ require 'time'
15
15
 
16
16
  module PAYJPv2
17
17
  class PaymentFlowPaymentMethodOptionsCardRequest
18
- # オーソリ期間の延長要求 | 値 | |:---| | **if_available**: オーソリ期間の延長が可能な場合に延長要求を行います。 | | **never**: オーソリ期間の延長要求を行いません。 |
18
+ # オーソリ期間の延長要求 | 値 | |:---| | **if_available**: オーソリ期間の延長が可能な場合に延長要求を行います。 | | **must_extend**: オーソリ期間の延長を必須とします。延長できない場合はエラーを返します。 | | **never**: オーソリ期間の延長要求を行いません。 |
19
19
  attr_accessor :request_extended_authorization
20
20
 
21
21
  # 3D セキュア認証の要求方法。 | 値 | |:---| | **any**: 3D セキュア認証を要求します。 | | **automatic**: 必要な場合にのみ 3D セキュア認証を要求します。 |
@@ -103,7 +103,7 @@ module PAYJPv2
103
103
  # Custom attribute writer method checking allowed values (enum).
104
104
  # @param [Object] request_extended_authorization Object to be assigned
105
105
  def request_extended_authorization=(request_extended_authorization)
106
- validator = EnumAttributeValidator.new('String', ["if_available", "never"])
106
+ validator = EnumAttributeValidator.new('String', ["if_available", "must_extend", "never"])
107
107
  unless validator.valid?(request_extended_authorization)
108
108
  raise ArgumentError, "invalid value for \"request_extended_authorization\", must be one of #{validator.allowable_values}."
109
109
  end
@@ -63,6 +63,8 @@ module PAYJPv2
63
63
 
64
64
  attr_accessor :canceled_at
65
65
 
66
+ attr_accessor :expired_at
67
+
66
68
  # メタデータ
67
69
  attr_accessor :metadata
68
70
 
@@ -117,6 +119,7 @@ module PAYJPv2
117
119
  :last_payment_error => :last_payment_error,
118
120
  :cancellation_reason => :cancellation_reason,
119
121
  :canceled_at => :canceled_at,
122
+ :expired_at => :expired_at,
120
123
  :metadata => :metadata,
121
124
  :created_at => :created_at,
122
125
  :updated_at => :updated_at
@@ -156,6 +159,7 @@ module PAYJPv2
156
159
  :last_payment_error => :'Hash<String, Object>',
157
160
  :cancellation_reason => :'PaymentFlowCancellationReason',
158
161
  :canceled_at => :'Time',
162
+ :expired_at => :'Time',
159
163
  :metadata => :'Hash<String, MetadataValue>',
160
164
  :created_at => :'Time',
161
165
  :updated_at => :'Time'
@@ -176,6 +180,7 @@ module PAYJPv2
176
180
  :last_payment_error,
177
181
  :cancellation_reason,
178
182
  :canceled_at,
183
+ :expired_at,
179
184
  ])
180
185
  end
181
186
 
@@ -323,6 +328,10 @@ module PAYJPv2
323
328
  self.canceled_at = nil
324
329
  end
325
330
 
331
+ if attributes.key?(:expired_at)
332
+ self.expired_at = attributes[:expired_at]
333
+ end
334
+
326
335
  if attributes.key?(:metadata)
327
336
  if (value = attributes[:metadata]).is_a?(Hash)
328
337
  self.metadata = value
@@ -489,6 +498,7 @@ module PAYJPv2
489
498
  last_payment_error == o.last_payment_error &&
490
499
  cancellation_reason == o.cancellation_reason &&
491
500
  canceled_at == o.canceled_at &&
501
+ expired_at == o.expired_at &&
492
502
  metadata == o.metadata &&
493
503
  created_at == o.created_at &&
494
504
  updated_at == o.updated_at
@@ -503,7 +513,7 @@ module PAYJPv2
503
513
  # Calculates hash code according to all attributes.
504
514
  # @return [Integer] Hash code
505
515
  def hash
506
- [object, id, livemode, amount, currency, amount_capturable, amount_received, client_secret, customer_id, description, payment_method_id, payment_method_options, payment_method_types, status, next_action, return_url, capture_method, last_payment_error, cancellation_reason, canceled_at, metadata, created_at, updated_at].hash
516
+ [object, id, livemode, amount, currency, amount_capturable, amount_received, client_secret, customer_id, description, payment_method_id, payment_method_options, payment_method_types, status, next_action, return_url, capture_method, last_payment_error, cancellation_reason, canceled_at, expired_at, metadata, created_at, updated_at].hash
507
517
  end
508
518
 
509
519
  # Builds the object from hash
@@ -87,7 +87,8 @@ module PAYJPv2
87
87
  return model if model
88
88
  else
89
89
  # raise if data contains keys that are not known to the model
90
- raise if const.respond_to?(:acceptable_attributes) && !(data.keys - const.acceptable_attributes).empty?
90
+ # NOTE: acceptable_attributes returns symbols while data keys are strings (from JSON.parse), so symbolize before diff
91
+ raise if const.respond_to?(:acceptable_attributes) && !(data.keys.map(&:to_sym) - const.acceptable_attributes).empty?
91
92
  model = const.build_from_hash(data)
92
93
  return model if model
93
94
  end
@@ -11,5 +11,5 @@ Generator version: 7.14.0
11
11
  =end
12
12
 
13
13
  module PAYJPv2
14
- VERSION = '1.0.9'
14
+ VERSION = '1.0.11'
15
15
  end
@@ -0,0 +1,107 @@
1
+ =begin
2
+ PaymentMethodResponse のような anyOf module が API client の convert_to_type 経由で
3
+ 正しくデシリアライズされることを確認するスペック。
4
+
5
+ 過去、 templates/ruby/api_client.mustache の convert_to_type は openapi_one_of だけを
6
+ チェックして openapi_any_of を見ていなかったため、 Pydantic の RootModel + Union から
7
+ 生成された anyOf module に対して build_from_hash を呼んでしまい
8
+ ``NoMethodError: undefined method 'build_from_hash' for module PAYJPv2::PaymentMethodResponse``
9
+ が発生していた。
10
+
11
+ 加えて partial_anyof_module.mustache (および partial_oneof_module.mustache) の
12
+ find_and_cast_into_type は data.keys (string, from JSON.parse) を
13
+ acceptable_attributes (symbol) と直接比較していたため、常に raise → rescue → nil で
14
+ build 自体も機能していなかった。
15
+
16
+ 両者を修正した後の挙動を回帰テストとして固定する。
17
+ =end
18
+
19
+ require 'spec_helper'
20
+
21
+ describe 'anyOf module deserialization via ApiClient#convert_to_type' do
22
+ let(:api_client) { PAYJPv2::ApiClient.new }
23
+
24
+ let(:card_payload) do
25
+ {
26
+ 'object' => 'payment_method',
27
+ 'id' => 'pm_test_card',
28
+ 'livemode' => false,
29
+ 'type' => 'card',
30
+ 'customer_id' => 'cus_test',
31
+ 'detached_at' => nil,
32
+ 'metadata' => {},
33
+ 'created_at' => '2026-01-01T00:00:00Z',
34
+ 'updated_at' => '2026-01-01T00:00:00Z',
35
+ 'billing_details' => {
36
+ 'name' => 'PAY TARO',
37
+ 'phone' => '09012345678',
38
+ 'email' => 'test@example.com',
39
+ 'address' => {
40
+ 'country' => 'JP',
41
+ 'zip' => '1000001',
42
+ 'state' => 'Tokyo',
43
+ 'city' => 'Chiyoda',
44
+ 'line1' => '1-1-1',
45
+ 'line2' => nil
46
+ }
47
+ },
48
+ 'card' => {
49
+ 'last4' => '4242',
50
+ 'brand' => 'visa',
51
+ 'exp_month' => 12,
52
+ 'exp_year' => 2030,
53
+ 'fingerprint' => 'fp_test',
54
+ 'country' => 'JP'
55
+ }
56
+ }
57
+ end
58
+
59
+ let(:paypay_payload) do
60
+ {
61
+ 'object' => 'payment_method',
62
+ 'id' => 'pm_test_paypay',
63
+ 'livemode' => false,
64
+ 'type' => 'paypay',
65
+ 'customer_id' => 'cus_test',
66
+ 'detached_at' => nil,
67
+ 'metadata' => {},
68
+ 'created_at' => '2026-01-01T00:00:00Z',
69
+ 'updated_at' => '2026-01-01T00:00:00Z',
70
+ 'billing_details' => {
71
+ 'name' => 'PAY TARO',
72
+ 'phone' => '09012345678',
73
+ 'email' => 'test@example.com',
74
+ 'address' => {
75
+ 'country' => 'JP',
76
+ 'zip' => '1000001',
77
+ 'state' => 'Tokyo',
78
+ 'city' => 'Chiyoda',
79
+ 'line1' => '1-1-1',
80
+ 'line2' => nil
81
+ }
82
+ }
83
+ }
84
+ end
85
+
86
+ it 'PaymentMethodResponse が anyOf module として生成されていること' do
87
+ expect(PAYJPv2::PaymentMethodResponse).to be_a(Module)
88
+ expect(PAYJPv2::PaymentMethodResponse).to respond_to(:openapi_any_of)
89
+ expect(PAYJPv2::PaymentMethodResponse).to respond_to(:build)
90
+ expect(PAYJPv2::PaymentMethodResponse).not_to respond_to(:build_from_hash)
91
+ end
92
+
93
+ it 'card 型のレスポンスを convert_to_type で PaymentMethodCardResponse に解決できること' do
94
+ result = api_client.send(:convert_to_type, card_payload, 'PaymentMethodResponse')
95
+ expect(result).to be_a(PAYJPv2::PaymentMethodCardResponse)
96
+ expect(result.id).to eq('pm_test_card')
97
+ expect(result.type).to eq('card')
98
+ expect(result.card.last4).to eq('4242')
99
+ end
100
+
101
+ it 'paypay 型のレスポンスを convert_to_type で PaymentMethodPayPayResponse に解決できること' do
102
+ result = api_client.send(:convert_to_type, paypay_payload, 'PaymentMethodResponse')
103
+ expect(result).to be_a(PAYJPv2::PaymentMethodPayPayResponse)
104
+ expect(result.id).to eq('pm_test_paypay')
105
+ expect(result.type).to eq('paypay')
106
+ end
107
+ end
@@ -0,0 +1,137 @@
1
+ =begin
2
+ 加盟店から報告された事象の回帰テスト。
3
+
4
+ pm_api = PAYJPv2::PaymentMethodsApi.new
5
+ pm_api.detach_payment_method(payment_method_id)
6
+ # => NoMethodError: undefined method 'build_from_hash' for module PAYJPv2::PaymentMethodResponse
7
+
8
+ がテンプレート修正後は起きないこと、および返り値が想定どおりの
9
+ 具体クラス (PaymentMethodCardResponse / PaymentMethodPayPayResponse) で
10
+ 返ってくることを呼び出し経路全体で保証する。
11
+
12
+ anyof_deserialization_spec.rb は ApiClient#convert_to_type を直接叩いており
13
+ バグの根因の単体検証だが、本 spec は加盟店が書いたコード経路そのものを
14
+ Typhoeus stub 経由で再現する。
15
+ =end
16
+
17
+ require 'spec_helper'
18
+
19
+ describe 'PAYJPv2::PaymentMethodsApi#detach_payment_method (regression for anyOf build_from_hash)' do
20
+ let(:payment_method_id) { 'pm_test_card' }
21
+
22
+ let(:detached_card_response_body) do
23
+ {
24
+ 'object' => 'payment_method',
25
+ 'id' => payment_method_id,
26
+ 'livemode' => false,
27
+ 'type' => 'card',
28
+ 'customer_id' => 'cus_test',
29
+ 'detached_at' => '2026-05-13T15:00:00Z',
30
+ 'metadata' => {},
31
+ 'created_at' => '2026-01-01T00:00:00Z',
32
+ 'updated_at' => '2026-05-13T15:00:00Z',
33
+ 'billing_details' => {
34
+ 'name' => 'PAY TARO',
35
+ 'phone' => '09012345678',
36
+ 'email' => 'test@example.com',
37
+ 'address' => {
38
+ 'country' => 'JP',
39
+ 'zip' => '1000001',
40
+ 'state' => 'Tokyo',
41
+ 'city' => 'Chiyoda',
42
+ 'line1' => '1-1-1',
43
+ 'line2' => nil
44
+ }
45
+ },
46
+ 'card' => {
47
+ 'last4' => '4242',
48
+ 'brand' => 'visa',
49
+ 'exp_month' => 12,
50
+ 'exp_year' => 2030,
51
+ 'fingerprint' => 'fp_test',
52
+ 'country' => 'JP'
53
+ }
54
+ }
55
+ end
56
+
57
+ let(:detached_paypay_response_body) do
58
+ {
59
+ 'object' => 'payment_method',
60
+ 'id' => 'pm_test_paypay',
61
+ 'livemode' => false,
62
+ 'type' => 'paypay',
63
+ 'customer_id' => 'cus_test',
64
+ 'detached_at' => '2026-05-13T15:00:00Z',
65
+ 'metadata' => {},
66
+ 'created_at' => '2026-01-01T00:00:00Z',
67
+ 'updated_at' => '2026-05-13T15:00:00Z',
68
+ 'billing_details' => {
69
+ 'name' => 'PAY TARO',
70
+ 'phone' => '09012345678',
71
+ 'email' => 'test@example.com',
72
+ 'address' => {
73
+ 'country' => 'JP',
74
+ 'zip' => '1000001',
75
+ 'state' => 'Tokyo',
76
+ 'city' => 'Chiyoda',
77
+ 'line1' => '1-1-1',
78
+ 'line2' => nil
79
+ }
80
+ }
81
+ }
82
+ end
83
+
84
+ before do
85
+ PAYJPv2.configure do |c|
86
+ c.host = 'api.pay.jp'
87
+ c.access_token = 'sk_test_dummy'
88
+ end
89
+ Typhoeus::Expectation.clear
90
+ end
91
+
92
+ after do
93
+ Typhoeus::Expectation.clear
94
+ end
95
+
96
+ it 'card 型の detach レスポンスを PaymentMethodCardResponse で受け取れる' do
97
+ Typhoeus.stub(/payment_methods\/#{payment_method_id}\/detach/).and_return(
98
+ Typhoeus::Response.new(
99
+ code: 200,
100
+ headers: { 'Content-Type' => 'application/json' },
101
+ body: detached_card_response_body.to_json
102
+ )
103
+ )
104
+
105
+ pm_api = PAYJPv2::PaymentMethodsApi.new
106
+
107
+ expect { pm_api.detach_payment_method(payment_method_id) }.not_to raise_error
108
+
109
+ result = pm_api.detach_payment_method(payment_method_id)
110
+ expect(result).to be_a(PAYJPv2::PaymentMethodCardResponse)
111
+ expect(result.id).to eq(payment_method_id)
112
+ expect(result.type).to eq('card')
113
+ expect(result.detached_at).not_to be_nil
114
+ expect(result.card.last4).to eq('4242')
115
+ end
116
+
117
+ it 'paypay 型の detach レスポンスを PaymentMethodPayPayResponse で受け取れる' do
118
+ paypay_id = 'pm_test_paypay'
119
+ Typhoeus.stub(/payment_methods\/#{paypay_id}\/detach/).and_return(
120
+ Typhoeus::Response.new(
121
+ code: 200,
122
+ headers: { 'Content-Type' => 'application/json' },
123
+ body: detached_paypay_response_body.to_json
124
+ )
125
+ )
126
+
127
+ pm_api = PAYJPv2::PaymentMethodsApi.new
128
+
129
+ expect { pm_api.detach_payment_method(paypay_id) }.not_to raise_error
130
+
131
+ result = pm_api.detach_payment_method(paypay_id)
132
+ expect(result).to be_a(PAYJPv2::PaymentMethodPayPayResponse)
133
+ expect(result.id).to eq(paypay_id)
134
+ expect(result.type).to eq('paypay')
135
+ expect(result.detached_at).not_to be_nil
136
+ end
137
+ end
@@ -30,7 +30,7 @@ describe PAYJPv2::CheckoutSessionPaymentMethodOptionsCardRequest do
30
30
  describe 'test attribute "request_extended_authorization"' do
31
31
  it 'should work' do
32
32
  # assertion here. ref: https://rspec.info/features/3-12/rspec-expectations/built-in-matchers/
33
- # validator = Petstore::EnumTest::EnumAttributeValidator.new('String', ["if_available", "never"])
33
+ # validator = Petstore::EnumTest::EnumAttributeValidator.new('String', ["if_available", "must_extend", "never"])
34
34
  # validator.allowable_values.each do |value|
35
35
  # expect { instance.request_extended_authorization = value }.not_to raise_error
36
36
  # end
@@ -30,7 +30,7 @@ describe PAYJPv2::PaymentFlowPaymentMethodOptionsCardRequest do
30
30
  describe 'test attribute "request_extended_authorization"' do
31
31
  it 'should work' do
32
32
  # assertion here. ref: https://rspec.info/features/3-12/rspec-expectations/built-in-matchers/
33
- # validator = Petstore::EnumTest::EnumAttributeValidator.new('String', ["if_available", "never"])
33
+ # validator = Petstore::EnumTest::EnumAttributeValidator.new('String', ["if_available", "must_extend", "never"])
34
34
  # validator.allowable_values.each do |value|
35
35
  # expect { instance.request_extended_authorization = value }.not_to raise_error
36
36
  # end
@@ -151,6 +151,12 @@ describe PAYJPv2::PaymentFlowResponse do
151
151
  end
152
152
  end
153
153
 
154
+ describe 'test attribute "expired_at"' do
155
+ it 'should work' do
156
+ # assertion here. ref: https://rspec.info/features/3-12/rspec-expectations/built-in-matchers/
157
+ end
158
+ end
159
+
154
160
  describe 'test attribute "metadata"' do
155
161
  it 'should work' do
156
162
  # assertion here. ref: https://rspec.info/features/3-12/rspec-expectations/built-in-matchers/
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: payjpv2
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.9
4
+ version: 1.0.11
5
5
  platform: ruby
6
6
  authors:
7
7
  - PAY.JP
@@ -362,6 +362,8 @@ files:
362
362
  - spec/api/statements_api_spec.rb
363
363
  - spec/api/tax_rates_api_spec.rb
364
364
  - spec/api/terms_api_spec.rb
365
+ - spec/integration/anyof_deserialization_spec.rb
366
+ - spec/integration/payment_methods_api_detach_spec.rb
365
367
  - spec/models/apple_pay_config_request_spec.rb
366
368
  - spec/models/balance_list_response_spec.rb
367
369
  - spec/models/balance_response_spec.rb
@@ -527,6 +529,8 @@ test_files:
527
529
  - spec/api/statements_api_spec.rb
528
530
  - spec/api/tax_rates_api_spec.rb
529
531
  - spec/api/terms_api_spec.rb
532
+ - spec/integration/anyof_deserialization_spec.rb
533
+ - spec/integration/payment_methods_api_detach_spec.rb
530
534
  - spec/models/apple_pay_config_request_spec.rb
531
535
  - spec/models/balance_list_response_spec.rb
532
536
  - spec/models/balance_response_spec.rb