spree_gmo_pg 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (35) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +5 -0
  3. data/Gemfile +5 -0
  4. data/LICENSE +673 -0
  5. data/README.md +58 -0
  6. data/app/controllers/spree/gmo_pg_callback_controller.rb +37 -0
  7. data/app/controllers/spree/payment_sources_controller.rb +47 -0
  8. data/app/controllers/spree_gmo_pg/checkout_controller_decorator.rb +40 -0
  9. data/app/javascript/spree_gmo_pg/controllers/gmo_pg_payment_controller.js +295 -0
  10. data/app/javascript/spree_gmo_pg/index.js +11 -0
  11. data/app/models/spree/payment_method/gmo_pg.rb +418 -0
  12. data/app/models/spree_gmo_pg/order_updater_decorator.rb +78 -0
  13. data/app/overrides/hide_preference_fields_for_payment_method_gmo_pg.rb +12 -0
  14. data/app/overrides/spree/gmo_pg_javascript_import.rb +28 -0
  15. data/app/views/spree/admin/payment_methods/custom_form_fields/_gmo_pg_form_fields.html.erb +63 -0
  16. data/app/views/spree/checkout/payment/_gmo_pg.html.erb +154 -0
  17. data/app/views/spree/checkout/payment/_saved_cards.html.erb +36 -0
  18. data/app/views/spree/gmo_pg_callback/callback.html.erb +51 -0
  19. data/app/views/spree/shared/_error.html.erb +3 -0
  20. data/config/importmap.rb +9 -0
  21. data/config/locales/en.yml +29 -0
  22. data/config/locales/ja.yml +29 -0
  23. data/config/routes.rb +10 -0
  24. data/lib/spree/payment_redirect_required.rb +23 -0
  25. data/lib/spree_gmo_pg/engine.rb +44 -0
  26. data/lib/spree_gmo_pg/version.rb +5 -0
  27. data/lib/spree_gmo_pg.rb +16 -0
  28. data/spec/controllers/spree/gmo_pg_callback_controller_spec.rb +46 -0
  29. data/spec/controllers/spree/payment_sources_controller_spec.rb +75 -0
  30. data/spec/factories/payment_method_factory.rb +19 -0
  31. data/spec/models/spree/order_updater_decorator_spec.rb +221 -0
  32. data/spec/models/spree/payment_method/gmo_pg_spec.rb +860 -0
  33. data/spec/spec_helper.rb +25 -0
  34. data/spree_gmo_pg.gemspec +32 -0
  35. metadata +152 -0
@@ -0,0 +1,221 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ RSpec.describe Spree::OrderUpdater, type: :model do
6
+ let(:store) { create(:store) }
7
+ let(:user) { create(:user) }
8
+ let(:order) { create(:order_with_line_items, user: user, store: store, state: 'complete', completed_at: Time.current) }
9
+ let(:payment_method) do
10
+ pm = create(:payment_method_gmo_pg)
11
+ pm.stores << store unless pm.stores.include?(store)
12
+ pm
13
+ end
14
+ let(:updater) { described_class.new(order) }
15
+
16
+ describe '#persist_totals' do
17
+ context 'GMO-PG決済で金額が変更された場合' do
18
+ context 'pending状態(オーソリ済み)の場合' do
19
+ let(:credit_card) { create(:credit_card, user: user, payment_method: payment_method) }
20
+ let!(:payment) do
21
+ create(:payment,
22
+ order: order,
23
+ payment_method: payment_method,
24
+ source: credit_card,
25
+ amount: order.total,
26
+ state: 'pending',
27
+ response_code: 'access_id_123|access_pass_456|order_789')
28
+ end
29
+
30
+ it 'GMO-PG APIを呼び出して金額を更新する' do
31
+ stub_request(:post, "https://pt01.mul-pay.jp/payment/ChangeTran.idPass")
32
+ .with(
33
+ body: hash_including(
34
+ "ShopID" => payment_method.preferred_shop_id,
35
+ "AccessID" => "access_id_123",
36
+ "AccessPass" => "access_pass_456",
37
+ "JobCd" => "AUTH"
38
+ )
39
+ )
40
+ .to_return(status: 200, body: "AccessID=access_id_123&Forward=2a99662&Approve=0123456&TranID=789&TranDate=20251203015959")
41
+
42
+ # 注文の金額を変更(数量を減らす)
43
+ order.line_items.first.update!(quantity: 1)
44
+ updater.update
45
+
46
+ payment.reload
47
+ expect(payment.amount).to eq(order.total)
48
+ end
49
+ end
50
+
51
+ context 'completed状態(売上計上済み)の場合' do
52
+ let(:credit_card) { create(:credit_card, user: user, payment_method: payment_method) }
53
+ let!(:payment) do
54
+ create(:payment,
55
+ order: order,
56
+ payment_method: payment_method,
57
+ source: credit_card,
58
+ amount: order.total,
59
+ state: 'completed',
60
+ response_code: 'access_id_123|access_pass_456|order_789')
61
+ end
62
+
63
+ it 'GMO-PG APIを呼び出して金額を更新する' do
64
+ stub_request(:post, "https://pt01.mul-pay.jp/payment/ChangeTran.idPass")
65
+ .with(
66
+ body: hash_including(
67
+ "ShopID" => payment_method.preferred_shop_id,
68
+ "AccessID" => "access_id_123",
69
+ "AccessPass" => "access_pass_456",
70
+ "JobCd" => "CAPTURE"
71
+ )
72
+ )
73
+ .to_return(status: 200, body: "AccessID=access_id_123&Forward=2a99662&Approve=0123456&TranID=789&TranDate=20251203015959")
74
+
75
+ # 注文の金額を変更(数量を減らす)
76
+ order.line_items.first.update!(quantity: 1)
77
+ updater.update
78
+
79
+ payment.reload
80
+ expect(payment.amount).to eq(order.total)
81
+ end
82
+
83
+ context 'PaymentCaptureEventの作成' do
84
+ before do
85
+ # 初期のPaymentCaptureEventを作成(purchase時に作成されるもの)
86
+ payment.capture_events.create!(amount: payment.amount)
87
+ end
88
+
89
+ it '金額変更時に差分をPaymentCaptureEventとして記録する' do
90
+ # paymentを直接操作して金額差分を作る
91
+ original_amount = payment.amount
92
+ original_captured_amount = payment.captured_amount
93
+ new_amount = original_amount * 2
94
+
95
+ # 注文の合計を変更
96
+ order.update_column(:total, new_amount)
97
+
98
+ # Gateway APIをモック
99
+ gateway = payment.payment_method.provider
100
+ allow(gateway).to receive(:update_amount).and_return(
101
+ ActiveMerchant::Billing::Response.new(true, 'Success')
102
+ )
103
+
104
+ # adjust_gmo_pg_paymentを直接呼び出す
105
+ updater.send(:adjust_gmo_pg_payment, payment)
106
+
107
+ # payment.amountが更新されていること
108
+ expect(payment.reload.amount).to eq(new_amount)
109
+
110
+ # PaymentCaptureEventが2つになっていること(初期 + 差分)
111
+ expect(payment.capture_events.count).to eq(2)
112
+
113
+ # 差分のPaymentCaptureEventが作成されていること
114
+ amount_diff = new_amount - original_amount
115
+ diff_event = payment.capture_events.order(:created_at).last
116
+ expect(diff_event.amount).to eq(amount_diff)
117
+
118
+ # payment.captured_amountが正しく更新されていること
119
+ expect(payment.captured_amount).to eq(original_captured_amount + amount_diff)
120
+ expect(payment.captured_amount).to eq(new_amount)
121
+ end
122
+ end
123
+ end
124
+
125
+ context '金額が既に一致している場合' do
126
+ let(:credit_card) { create(:credit_card, user: user, payment_method: payment_method) }
127
+ let!(:payment) do
128
+ create(:payment,
129
+ order: order,
130
+ payment_method: payment_method,
131
+ source: credit_card,
132
+ amount: order.total,
133
+ state: 'pending',
134
+ response_code: 'access_id_123|access_pass_456|order_789')
135
+ end
136
+
137
+ it 'GMO-PG APIを呼び出さない' do
138
+ # 金額を変更しない更新
139
+ expect { updater.update }.not_to raise_error
140
+ end
141
+ end
142
+
143
+ context 'GMO-PG APIエラーが発生した場合' do
144
+ let(:credit_card) { create(:credit_card, user: user, payment_method: payment_method) }
145
+ let!(:payment) do
146
+ create(:payment,
147
+ order: order,
148
+ payment_method: payment_method,
149
+ source: credit_card,
150
+ amount: order.total,
151
+ state: 'pending',
152
+ response_code: 'access_id_123|access_pass_456|order_789')
153
+ end
154
+
155
+ it '注文の更新は継続され、payment.amountは変更されない' do
156
+ stub_request(:post, "https://pt01.mul-pay.jp/payment/ChangeTran.idPass")
157
+ .to_return(status: 200, body: "ErrCode=E01&ErrInfo=エラーが発生しました")
158
+
159
+ original_amount = payment.amount
160
+
161
+ # 注文の金額を変更(数量を減らす)
162
+ order.line_items.first.update!(quantity: 1)
163
+
164
+ # エラーが発生しても例外は投げられない
165
+ expect { updater.update }.not_to raise_error
166
+
167
+ payment.reload
168
+ expect(payment.amount).to eq(original_amount) # 変更されない
169
+ end
170
+ end
171
+ end
172
+
173
+ context 'GMO-PG以外の決済方法の場合' do
174
+ let(:bank_transfer_method) do
175
+ pm = create(:check_payment_method)
176
+ pm.stores << store unless pm.stores.include?(store)
177
+ pm
178
+ end
179
+ let!(:payment) do
180
+ create(:payment,
181
+ order: order,
182
+ payment_method: bank_transfer_method,
183
+ amount: order.total,
184
+ state: 'pending')
185
+ end
186
+
187
+ it '金額を自動更新しない' do
188
+ original_amount = payment.amount
189
+
190
+ # 注文の金額を変更(数量を減らす)
191
+ order.line_items.first.update!(quantity: 1)
192
+ updater.update
193
+
194
+ payment.reload
195
+ expect(payment.amount).to eq(original_amount)
196
+ end
197
+ end
198
+
199
+ context '未完了の注文の場合' do
200
+ let(:incomplete_order) { create(:order_with_line_items, user: user, store: store, state: 'payment') }
201
+ let(:incomplete_updater) { described_class.new(incomplete_order) }
202
+ let(:credit_card) { create(:credit_card, user: user, payment_method: payment_method) }
203
+ let!(:payment) do
204
+ create(:payment,
205
+ order: incomplete_order,
206
+ payment_method: payment_method,
207
+ source: credit_card,
208
+ amount: incomplete_order.total,
209
+ state: 'pending',
210
+ response_code: 'access_id_123|access_pass_456|order_789')
211
+ end
212
+
213
+ it 'GMO-PG APIを呼び出さない' do
214
+ # 注文の金額を変更(数量を減らす)
215
+ incomplete_order.line_items.first.update!(quantity: 1)
216
+
217
+ expect { incomplete_updater.update }.not_to raise_error
218
+ end
219
+ end
220
+ end
221
+ end