gmo 0.5.7 → 0.5.9
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 +4 -4
- data/.github/workflows/ruby.yml +1 -1
- data/CHANGELOG.md +11 -0
- data/fixtures/vcr_cassettes/GMO_Payment_ShopAPI/_exec_tran_with_3DS2_0_returns_3DS2_0_challenge_flow_response.yml +33 -0
- data/fixtures/vcr_cassettes/GMO_Payment_ShopAPI/_secure_tran_2_completes_payment_after_3DS2_0_challenge_verification.yml +33 -0
- data/fixtures/vcr_cassettes/GMO_Payment_ShopAPI/_tds2_auth_executes_3DS2_0_authentication.yml +33 -0
- data/fixtures/vcr_cassettes/GMO_Payment_ShopAPI/_tds2_result_gets_3DS2_0_authentication_result.yml +33 -0
- data/gmo.gemspec +1 -0
- data/lib/gmo/const.rb +66 -1
- data/lib/gmo/http_services.rb +2 -1
- data/lib/gmo/shop_api.rb +33 -0
- data/lib/gmo/version.rb +1 -1
- data/lib/gmo.rb +11 -3
- data/spec/gmo/api_spec.rb +28 -0
- data/spec/gmo/net_http_service_spec.rb +88 -0
- data/spec/gmo/remittance_api_spec.rb +1 -0
- data/spec/gmo/shop_api_spec.rb +112 -0
- metadata +22 -3
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: af1dd3f7ad4b9e6ac9d6ca3031f4667297e6f031aba145d50665d01fc32025e5
|
|
4
|
+
data.tar.gz: 616883c20b27bb5d94a0c4b11abfb3396247abe6da1e592d30282cba9dccb0ac
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: d570dc713d1281eebb404d022f2fdb07eca419f770bdd685d217b2ac7798474e5f03c292b606c59d3beb30f24996152e6b812e05849a636b694edf4658c1bfb4
|
|
7
|
+
data.tar.gz: 121ec172132e99240b194da859e997140758d0a822e49bd55ad36ea114efb38442b462ac8126cc99a99826627bc72d582819d35e4d202f7877031e75f1582522
|
data/.github/workflows/ruby.yml
CHANGED
data/CHANGELOG.md
CHANGED
|
@@ -1,4 +1,15 @@
|
|
|
1
1
|
# CHANGELOG
|
|
2
|
+
## 0.5.9
|
|
3
|
+
- net-http 0.7.0+でcontent typeを明示的に設定する必要がある問題を修正 [#79](https://github.com/t-k/gmo-payment-ruby/pull/79) (Thanks [@johnnyshields](https://github.com/johnnyshields))
|
|
4
|
+
|
|
5
|
+
## 0.5.8
|
|
6
|
+
- クレジットカード決済の3Dセキュア2.0に対応 [#76](https://github.com/t-k/gmo-payment-ruby/pull/76)
|
|
7
|
+
- 3DS2.0認証実行 (`tds2_auth`)
|
|
8
|
+
- 3DS2.0認証結果取得 (`tds2_result`)
|
|
9
|
+
- 認証後決済実行 (`secure_tran_2`)
|
|
10
|
+
- Ruby 3.4のサポートを追加 [#74](https://github.com/t-k/gmo-payment-ruby/pull/74) (Thanks [@y-yagi](https://github.com/y-yagi))
|
|
11
|
+
- `ostruct`を明示的な依存関係として追加 [#74](https://github.com/t-k/gmo-payment-ruby/pull/74) (Thanks [@y-yagi](https://github.com/y-yagi))
|
|
12
|
+
|
|
2
13
|
## 0.5.7
|
|
3
14
|
- Added `nkf` as a dependency. This fixes the warning that appears with Ruby 3.3.0 and later versions. [#67](https://github.com/t-k/gmo-payment-ruby/pull/69)
|
|
4
15
|
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
---
|
|
2
|
+
http_interactions:
|
|
3
|
+
- request:
|
|
4
|
+
method: post
|
|
5
|
+
uri: https://<HOST>/payment/ExecTran.idPass
|
|
6
|
+
body:
|
|
7
|
+
encoding: UTF-8
|
|
8
|
+
string: AccessID=<ACCESS_ID>&AccessPass=<ACCESS_PASS>&OrderID=<ORDER_ID>&Method=1&PayTimes=&MemberID=<MEMBER_ID>&CardSeq=0&TdsType=2&Tds2Type=2&CallBackUrl=https%3A%2F%2Fexample.com%2Fcallback&Tds2RetUrl=https%3A%2F%2Fexample.com%2F3ds%2Freturn
|
|
9
|
+
headers:
|
|
10
|
+
Accept:
|
|
11
|
+
- "*/*"
|
|
12
|
+
Accept-Encoding:
|
|
13
|
+
- gzip;q=1.0,deflate;q=0.6,identity;q=0.3
|
|
14
|
+
Content-Type:
|
|
15
|
+
- application/x-www-form-urlencoded
|
|
16
|
+
User-Agent:
|
|
17
|
+
- Ruby
|
|
18
|
+
response:
|
|
19
|
+
status:
|
|
20
|
+
code: 200
|
|
21
|
+
message: OK
|
|
22
|
+
headers:
|
|
23
|
+
Content-Type:
|
|
24
|
+
- text/plain; charset=shift_jis
|
|
25
|
+
Date:
|
|
26
|
+
- Thu, 24 Jul 2025 23:15:18 GMT
|
|
27
|
+
Server:
|
|
28
|
+
- Apache
|
|
29
|
+
body:
|
|
30
|
+
encoding: UTF-8
|
|
31
|
+
string: OrderID=<ORDER_ID>&Forward=<FORWARD>&Method=1&PayTimes=&Approve=&TranID=<TRAN_ID>&TranDate=<TRAN_DATE>&CheckString=<CHECK_STRING>&Tds2TransResult=C&Tds2TransResultReason=01&Tds2ChallengeUrl=https://<HOST>/payment/Tds2Challenge?tds2TransID=<TDS2_TRANS_ID>&Tds2TransID=<TDS2_TRANS_ID>
|
|
32
|
+
recorded_at: Thu, 24 Jul 2025 23:15:18 GMT
|
|
33
|
+
recorded_with: VCR 6.3.1
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
---
|
|
2
|
+
http_interactions:
|
|
3
|
+
- request:
|
|
4
|
+
method: post
|
|
5
|
+
uri: https://<HOST>/payment/SecureTran2.idPass
|
|
6
|
+
body:
|
|
7
|
+
encoding: UTF-8
|
|
8
|
+
string: AccessID=<ACCESS_ID>&AccessPass=<ACCESS_PASS>
|
|
9
|
+
headers:
|
|
10
|
+
Accept:
|
|
11
|
+
- "*/*"
|
|
12
|
+
Accept-Encoding:
|
|
13
|
+
- gzip;q=1.0,deflate;q=0.6,identity;q=0.3
|
|
14
|
+
Content-Type:
|
|
15
|
+
- application/x-www-form-urlencoded
|
|
16
|
+
User-Agent:
|
|
17
|
+
- Ruby
|
|
18
|
+
response:
|
|
19
|
+
status:
|
|
20
|
+
code: 200
|
|
21
|
+
message: OK
|
|
22
|
+
headers:
|
|
23
|
+
Content-Type:
|
|
24
|
+
- text/plain; charset=shift_jis
|
|
25
|
+
Date:
|
|
26
|
+
- Thu, 24 Jul 2025 23:15:18 GMT
|
|
27
|
+
Server:
|
|
28
|
+
- Apache
|
|
29
|
+
body:
|
|
30
|
+
encoding: UTF-8
|
|
31
|
+
string: OrderID=<ORDER_ID>&Forward=<FORWARD>&Method=1&PayTimes=&Approve=<APPROVE>&TranID=<TRAN_ID>&TranDate=<TRAN_DATE>&CheckString=<CHECK_STRING>
|
|
32
|
+
recorded_at: Thu, 24 Jul 2025 23:15:18 GMT
|
|
33
|
+
recorded_with: VCR 6.3.1
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
---
|
|
2
|
+
http_interactions:
|
|
3
|
+
- request:
|
|
4
|
+
method: post
|
|
5
|
+
uri: https://<HOST>/payment/Tds2Auth.idPass
|
|
6
|
+
body:
|
|
7
|
+
encoding: UTF-8
|
|
8
|
+
string: AccessID=<ACCESS_ID>&AccessPass=<ACCESS_PASS>&Tds2Param=<TDS2_PARAM>&ShopID=<SHOP_ID>&ShopPass=<SHOP_PASS>
|
|
9
|
+
headers:
|
|
10
|
+
Accept:
|
|
11
|
+
- "*/*"
|
|
12
|
+
Accept-Encoding:
|
|
13
|
+
- gzip;q=1.0,deflate;q=0.6,identity;q=0.3
|
|
14
|
+
Content-Type:
|
|
15
|
+
- application/x-www-form-urlencoded
|
|
16
|
+
User-Agent:
|
|
17
|
+
- Ruby
|
|
18
|
+
response:
|
|
19
|
+
status:
|
|
20
|
+
code: 200
|
|
21
|
+
message: OK
|
|
22
|
+
headers:
|
|
23
|
+
Content-Type:
|
|
24
|
+
- text/plain; charset=shift_jis
|
|
25
|
+
Date:
|
|
26
|
+
- Thu, 24 Jul 2025 23:15:18 GMT
|
|
27
|
+
Server:
|
|
28
|
+
- Apache
|
|
29
|
+
body:
|
|
30
|
+
encoding: UTF-8
|
|
31
|
+
string: OrderID=<ORDER_ID>&Forward=<FORWARD>&Method=1&PayTimes=&Approve=&TranID=<TRAN_ID>&TranDate=<TRAN_DATE>&CheckString=<CHECK_STRING>&Tds2TransResult=Y&Tds2TransResultReason=&Tds2ChallengeUrl=https://<HOST>/payment/Tds2Challenge?tds2TransID=<TDS2_TRANS_ID>
|
|
32
|
+
recorded_at: Thu, 24 Jul 2025 23:15:18 GMT
|
|
33
|
+
recorded_with: VCR 6.3.1
|
data/fixtures/vcr_cassettes/GMO_Payment_ShopAPI/_tds2_result_gets_3DS2_0_authentication_result.yml
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
---
|
|
2
|
+
http_interactions:
|
|
3
|
+
- request:
|
|
4
|
+
method: post
|
|
5
|
+
uri: https://<HOST>/payment/Tds2Result.idPass
|
|
6
|
+
body:
|
|
7
|
+
encoding: UTF-8
|
|
8
|
+
string: AccessID=<ACCESS_ID>&AccessPass=<ACCESS_PASS>&ShopID=<SHOP_ID>&ShopPass=<SHOP_PASS>
|
|
9
|
+
headers:
|
|
10
|
+
Accept:
|
|
11
|
+
- "*/*"
|
|
12
|
+
Accept-Encoding:
|
|
13
|
+
- gzip;q=1.0,deflate;q=0.6,identity;q=0.3
|
|
14
|
+
Content-Type:
|
|
15
|
+
- application/x-www-form-urlencoded
|
|
16
|
+
User-Agent:
|
|
17
|
+
- Ruby
|
|
18
|
+
response:
|
|
19
|
+
status:
|
|
20
|
+
code: 200
|
|
21
|
+
message: OK
|
|
22
|
+
headers:
|
|
23
|
+
Content-Type:
|
|
24
|
+
- text/plain; charset=shift_jis
|
|
25
|
+
Date:
|
|
26
|
+
- Thu, 24 Jul 2025 23:15:18 GMT
|
|
27
|
+
Server:
|
|
28
|
+
- Apache
|
|
29
|
+
body:
|
|
30
|
+
encoding: UTF-8
|
|
31
|
+
string: OrderID=<ORDER_ID>&Forward=<FORWARD>&Method=1&PayTimes=&Approve=&TranID=<TRAN_ID>&TranDate=<TRAN_DATE>&CheckString=<CHECK_STRING>&Tds2TransResult=Y&Tds2TransResultReason=
|
|
32
|
+
recorded_at: Thu, 24 Jul 2025 23:15:18 GMT
|
|
33
|
+
recorded_with: VCR 6.3.1
|
data/gmo.gemspec
CHANGED
data/lib/gmo/const.rb
CHANGED
|
@@ -20,7 +20,7 @@ module GMO
|
|
|
20
20
|
order_id: '3'
|
|
21
21
|
}
|
|
22
22
|
|
|
23
|
-
|
|
23
|
+
BASE_INPUT_PARAMS = {
|
|
24
24
|
:access_id => "AccessID",
|
|
25
25
|
:access_pass => "AccessPass",
|
|
26
26
|
:account_name => "Account_Name",
|
|
@@ -37,11 +37,13 @@ module GMO
|
|
|
37
37
|
:auth_code_2 => "Auth_Code2",
|
|
38
38
|
:auth_code_3 => "Auth_Code3",
|
|
39
39
|
:amount => "Amount",
|
|
40
|
+
:app_mode => "AppMode",
|
|
40
41
|
:bank_code => "Bank_Code",
|
|
41
42
|
:bank_id => "Bank_ID",
|
|
42
43
|
:branch_code => "Branch_Code",
|
|
43
44
|
:branch_code_jp => "Branch_Code_Jpbank",
|
|
44
45
|
:call_back_url => "Call_Back_Url",
|
|
46
|
+
:callback_type => "CallbackType",
|
|
45
47
|
:cancel_amount => "CancelAmount",
|
|
46
48
|
:cancel_tax => "CancelTax",
|
|
47
49
|
:card_name => "CardName",
|
|
@@ -156,7 +158,55 @@ module GMO
|
|
|
156
158
|
:suica_add_info_4 => "SuicaAddInfo4",
|
|
157
159
|
:tax => "Tax",
|
|
158
160
|
:td_flag => "TdFlag",
|
|
161
|
+
:tds2_type => "Tds2Type",
|
|
162
|
+
:td_required => "TdRequired",
|
|
159
163
|
:td_tenant_name => "TdTenantName",
|
|
164
|
+
:tds2_ch_acc_change => "Tds2ChAccChange",
|
|
165
|
+
:tds2_ch_acc_date => "Tds2ChAccDate",
|
|
166
|
+
:tds2_ch_acc_pw_change => "Tds2ChAccPwChange",
|
|
167
|
+
:tds2_nb_purchase_account => "Tds2NbPurchaseAccount",
|
|
168
|
+
:tds2_param => "Tds2Param",
|
|
169
|
+
:tds2_payment_acc_age => "Tds2PaymentAccAge",
|
|
170
|
+
:tds2_provision_attempts_day => "Tds2ProvisionAttemptsDay",
|
|
171
|
+
:tds2_ship_address_usage => "Tds2ShipAddressUsage",
|
|
172
|
+
:tds2_ship_name_ind => "Tds2ShipNameInd",
|
|
173
|
+
:tds2_suspicious_acc_activity => "Tds2SuspiciousAccActivity",
|
|
174
|
+
:tds2_txn_activity_day => "Tds2TxnActivityDay",
|
|
175
|
+
:tds2_txn_activity_year => "Tds2TxnActivityYear",
|
|
176
|
+
:tds2_3ds_req_auth_data => "Tds2ThreeDSReqAuthData",
|
|
177
|
+
:tds2_3ds_req_auth_method => "Tds2ThreeDSReqAuthMethod",
|
|
178
|
+
:tds2_3ds_req_auth_timestamp => "Tds2ThreeDSReqAuthTimestamp",
|
|
179
|
+
:tds2_addr_match => "Tds2AddrMatch",
|
|
180
|
+
:tds2_bill_addr_city => "Tds2BillAddrCity",
|
|
181
|
+
:tds2_bill_addr_country => "Tds2BillAddrCountry",
|
|
182
|
+
:tds2_bill_addr_line1 => "Tds2BillAddrLine1",
|
|
183
|
+
:tds2_bill_addr_line2 => "Tds2BillAddrLine2",
|
|
184
|
+
:tds2_bill_addr_line3 => "Tds2BillAddrLine3",
|
|
185
|
+
:tds2_bill_addr_post_code => "Tds2BillAddrPostCode",
|
|
186
|
+
:tds2_bill_addr_state => "Tds2BillAddrState",
|
|
187
|
+
:tds2_email => "Tds2Email",
|
|
188
|
+
:tds2_home_phone_cc => "Tds2HomePhoneCC",
|
|
189
|
+
:tds2_home_phone_subscriber => "Tds2HomePhoneSubscriber",
|
|
190
|
+
:tds2_mobile_phone_cc => "Tds2MobilePhoneCC",
|
|
191
|
+
:tds2_mobile_phone_subscriber => "Tds2MobilePhoneSubscriber",
|
|
192
|
+
:tds2_work_phone_cc => "Tds2WorkPhoneCC",
|
|
193
|
+
:tds2_work_phone_subscriber => "Tds2WorkPhoneSubscriber",
|
|
194
|
+
:tds2_ship_addr_city => "Tds2ShipAddrCity",
|
|
195
|
+
:tds2_ship_addr_country => "Tds2ShipAddrCountry",
|
|
196
|
+
:tds2_ship_addr_line1 => "Tds2ShipAddrLine1",
|
|
197
|
+
:tds2_ship_addr_line2 => "Tds2ShipAddrLine2",
|
|
198
|
+
:tds2_ship_addr_line3 => "Tds2ShipAddrLine3",
|
|
199
|
+
:tds2_ship_addr_post_code => "Tds2ShipAddrPostCode",
|
|
200
|
+
:tds2_ship_addr_state => "Tds2ShipAddrState",
|
|
201
|
+
:tds2_delivery_email_address => "Tds2DeliveryEmailAddress",
|
|
202
|
+
:tds2_delivery_time_frame => "Tds2DeliveryTimeframe",
|
|
203
|
+
:tds2_gift_card_amount => "Tds2GiftCardAmount",
|
|
204
|
+
:tds2_gift_card_count => "Tds2GiftCardCount",
|
|
205
|
+
:tds2_gift_card_curr => "Tds2GiftCardCurr",
|
|
206
|
+
:tds2_pre_order_date => "Tds2PreOrderDate",
|
|
207
|
+
:tds2_pre_order_purchase_ind => "Tds2PreOrderPurchaseInd",
|
|
208
|
+
:tds2_reorder_items_ind => "Tds2ReorderItemsInd",
|
|
209
|
+
:tds2_ship_ind => "Tds2ShipInd",
|
|
160
210
|
:tel_no => "TelNo",
|
|
161
211
|
:token => "Token",
|
|
162
212
|
:token_seq => "TokenSeq",
|
|
@@ -176,6 +226,21 @@ module GMO
|
|
|
176
226
|
:trade_client_mail_address => "TradeClientMailAddress"
|
|
177
227
|
}.freeze
|
|
178
228
|
|
|
229
|
+
# NOTE: 決済方法によってはcaseに揺らぎがあるのでここで上書きする
|
|
230
|
+
PAYMENT_SPECIFIC_PARAMS = {
|
|
231
|
+
"ExecTran.idPass" => {
|
|
232
|
+
ret_url: "RetUrl" # NOTE: 3Dセキュア認証後にお戻しする加盟店様側のURLになります。
|
|
233
|
+
},
|
|
234
|
+
}.freeze
|
|
235
|
+
|
|
236
|
+
def self.input_params(api_method_name)
|
|
237
|
+
if PAYMENT_SPECIFIC_PARAMS.key?(api_method_name)
|
|
238
|
+
BASE_INPUT_PARAMS.dup.merge!(PAYMENT_SPECIFIC_PARAMS[api_method_name])
|
|
239
|
+
else
|
|
240
|
+
BASE_INPUT_PARAMS
|
|
241
|
+
end
|
|
242
|
+
end
|
|
243
|
+
|
|
179
244
|
API_ERROR_MESSAGES_EN = {
|
|
180
245
|
'000' => 'Token acquisition completed normally',
|
|
181
246
|
'100' => 'Card number Required check error',
|
data/lib/gmo/http_services.rb
CHANGED
|
@@ -44,7 +44,8 @@ module GMO
|
|
|
44
44
|
headers = { "Content-Type" => "application/json" }
|
|
45
45
|
h.post(path, args.to_json, headers)
|
|
46
46
|
else
|
|
47
|
-
|
|
47
|
+
headers = { "Content-Type" => "application/x-www-form-urlencoded" }
|
|
48
|
+
h.post(path, encode_params(args), headers)
|
|
48
49
|
end
|
|
49
50
|
else
|
|
50
51
|
h.get("#{path}?#{encode_params(args)}")
|
data/lib/gmo/shop_api.rb
CHANGED
|
@@ -691,6 +691,39 @@ module GMO
|
|
|
691
691
|
post_request name, options
|
|
692
692
|
end
|
|
693
693
|
|
|
694
|
+
###################################################
|
|
695
|
+
# 3DS2.0 対応
|
|
696
|
+
###################################################
|
|
697
|
+
|
|
698
|
+
# 4.3.1.7 3DS2.0認証実行(Tds2Auth)
|
|
699
|
+
# DS2.0認証を実行します。
|
|
700
|
+
# 3DS2.0認証初期化URL(RedirectUrl)のコールバックを受けたタイミングで本処理を実行してください。
|
|
701
|
+
def tds2_auth(options = {})
|
|
702
|
+
name = "Tds2Auth.idPass"
|
|
703
|
+
required = [:access_id, :access_pass, :tds2_param]
|
|
704
|
+
assert_required_options(required, options)
|
|
705
|
+
post_request name, options
|
|
706
|
+
end
|
|
707
|
+
|
|
708
|
+
# 4.3.1.8 3DS2.0認証結果取得(Tds2Result)
|
|
709
|
+
# 3DS2.0認証の最終的な認証結果を取得します。
|
|
710
|
+
# 3DS2.0認証チャレンジURL(ChallengeUrl)のコールバックを受けたタイミングで本処理を実行してください。
|
|
711
|
+
def tds2_result(options = {})
|
|
712
|
+
name = "Tds2Result.idPass"
|
|
713
|
+
required = [:access_id, :access_pass]
|
|
714
|
+
assert_required_options(required, options)
|
|
715
|
+
post_request name, options
|
|
716
|
+
end
|
|
717
|
+
|
|
718
|
+
# 4.3.1.12 3DS2.0認証後決済実行(SecureTran2)
|
|
719
|
+
# 3DS2.0サービスの結果を解析し、その情報を使用してカード会社と通信を行い決済を実施して結果を返します。
|
|
720
|
+
def secure_tran_2(options = {})
|
|
721
|
+
name = "SecureTran2.idPass"
|
|
722
|
+
required = [:access_id, :access_pass]
|
|
723
|
+
assert_required_options(required, options)
|
|
724
|
+
post_request name, options
|
|
725
|
+
end
|
|
726
|
+
|
|
694
727
|
private
|
|
695
728
|
|
|
696
729
|
def api_call(name, args = {}, verb = "post", options = {})
|
data/lib/gmo/version.rb
CHANGED
data/lib/gmo.rb
CHANGED
|
@@ -48,6 +48,13 @@ module GMO
|
|
|
48
48
|
key_values = result.body.to_s.split('&').map { |str| str.split('=', 2) }.flatten
|
|
49
49
|
response = Hash[*key_values]
|
|
50
50
|
end
|
|
51
|
+
# Transform the redirect_url
|
|
52
|
+
# "ACS=2&RedirectUrl=https://manage.tds2gw.gmopg.jp/api/v2/brw/callback?transId=6e48e31f-2940-48e1-a702-ebba2f3373ee&t=dccc8a7ed85372c9accff576bff59b3a"
|
|
53
|
+
# => { "ACS" => "2", RedirectUrl => "https://manage.tds2gw.gmopg.jp/api/v2/brw/callback?transId=6e48e31f-2940-48e1-a702- ebba2f3373ee&t=dccc8a7ed85372c9accff576bff59b3a" }
|
|
54
|
+
if response['RedirectUrl'] && response['RedirectUrl'] != '' && response['t'] && response['t'] != '' && response.keys.index('RedirectUrl') + 1 == response.keys.index('t')
|
|
55
|
+
response['RedirectUrl'] = response['RedirectUrl'] + '&t=' + response['t']
|
|
56
|
+
response.delete('t')
|
|
57
|
+
end
|
|
51
58
|
# converting to UTF-8
|
|
52
59
|
body = response = Hash[response.map { |k,v| [k, NKF.nkf('-S -w',v)] }]
|
|
53
60
|
# Check for errors if provided a error_checking_block
|
|
@@ -70,7 +77,7 @@ module GMO
|
|
|
70
77
|
# gmo.post_request("EntryTran.idPass", {:foo => "bar"})
|
|
71
78
|
# POST /EntryTran.idPass with params foo=bar
|
|
72
79
|
def post_request(name, args = {}, options = {})
|
|
73
|
-
args = associate_options_to_gmo_params args
|
|
80
|
+
args = associate_options_to_gmo_params(name, args)
|
|
74
81
|
api_call(name, args, "post", options)
|
|
75
82
|
end
|
|
76
83
|
alias :post! :post_request
|
|
@@ -82,8 +89,9 @@ module GMO
|
|
|
82
89
|
raise ArgumentError, "Required #{missing.join(', ')} were not provided." unless missing.empty?
|
|
83
90
|
end
|
|
84
91
|
|
|
85
|
-
def associate_options_to_gmo_params(options)
|
|
86
|
-
|
|
92
|
+
def associate_options_to_gmo_params(api_method_name, options)
|
|
93
|
+
params = GMO::Const.input_params(api_method_name)
|
|
94
|
+
Hash[options.map { |k, v| [params[k], v] }]
|
|
87
95
|
end
|
|
88
96
|
|
|
89
97
|
def api_call(*args)
|
data/spec/gmo/api_spec.rb
CHANGED
|
@@ -29,4 +29,32 @@ describe "GMO::Payment::API" do
|
|
|
29
29
|
end
|
|
30
30
|
end
|
|
31
31
|
|
|
32
|
+
describe "#associate_options_to_gmo_params" do
|
|
33
|
+
let(:service) { GMO::Payment::API.new() }
|
|
34
|
+
|
|
35
|
+
context "with ExecTran.idPass" do
|
|
36
|
+
it "converts access_id and access_pass normally" do
|
|
37
|
+
options = {
|
|
38
|
+
access_id: "test_access_id",
|
|
39
|
+
access_pass: "test_access_pass",
|
|
40
|
+
ret_url: "https://example.com/callback"
|
|
41
|
+
}
|
|
42
|
+
result = service.send(:associate_options_to_gmo_params, "ExecTran.idPass", options)
|
|
43
|
+
expect(result).to eq({
|
|
44
|
+
"AccessID" => "test_access_id",
|
|
45
|
+
"AccessPass" => "test_access_pass",
|
|
46
|
+
"RetUrl" => "https://example.com/callback"
|
|
47
|
+
})
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
context "with other API methods" do
|
|
52
|
+
it "converts ret_url to RetURL for standard cases" do
|
|
53
|
+
options = { ret_url: "https://example.com/callback" }
|
|
54
|
+
result = service.send(:associate_options_to_gmo_params, "AnotherAPI", options)
|
|
55
|
+
expect(result).to eq({ "RetURL" => "https://example.com/callback" })
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
|
|
32
60
|
end
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
class FakeNetHTTPService
|
|
4
|
+
include GMO::NetHTTPService
|
|
5
|
+
end
|
|
6
|
+
|
|
7
|
+
describe "GMO::NetHTTPService" do
|
|
8
|
+
|
|
9
|
+
describe "#make_request" do
|
|
10
|
+
let(:mock_http) { double("Net::HTTP") }
|
|
11
|
+
let(:mock_http_session) { double("Net::HTTP session") }
|
|
12
|
+
let(:mock_response) { double("Net::HTTPResponse", code: "200", body: "AccessID=test123") }
|
|
13
|
+
|
|
14
|
+
before do
|
|
15
|
+
allow(Net::HTTP).to receive(:new).and_return(mock_http)
|
|
16
|
+
allow(mock_http).to receive(:use_ssl=)
|
|
17
|
+
allow(mock_http).to receive(:start).and_yield(mock_http_session)
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
describe "Content-Type header for form-encoded POST requests" do
|
|
21
|
+
it "sets Content-Type to application/x-www-form-urlencoded" do
|
|
22
|
+
expect(mock_http_session).to receive(:post) do |path, body, headers|
|
|
23
|
+
expect(path).to eq("/payment/EntryTran.idPass")
|
|
24
|
+
expect(headers["Content-Type"]).to eq("application/x-www-form-urlencoded")
|
|
25
|
+
mock_response
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
FakeNetHTTPService.make_request(
|
|
29
|
+
"/payment/EntryTran.idPass",
|
|
30
|
+
{ "ShopID" => "shop123", "OrderID" => "order456" },
|
|
31
|
+
"post",
|
|
32
|
+
{ :host => "example.com" }
|
|
33
|
+
)
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
it "properly encodes form parameters" do
|
|
37
|
+
expect(mock_http_session).to receive(:post) do |path, body, headers|
|
|
38
|
+
expect(path).to eq("/payment/EntryTran.idPass")
|
|
39
|
+
expect(body).to include("ShopID=")
|
|
40
|
+
expect(body).to include("OrderID=")
|
|
41
|
+
expect(headers["Content-Type"]).to eq("application/x-www-form-urlencoded")
|
|
42
|
+
mock_response
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
FakeNetHTTPService.make_request(
|
|
46
|
+
"/payment/EntryTran.idPass",
|
|
47
|
+
{ "ShopID" => "shop123", "OrderID" => "order456" },
|
|
48
|
+
"post",
|
|
49
|
+
{ :host => "example.com" }
|
|
50
|
+
)
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
describe "Content-Type header for JSON POST requests" do
|
|
55
|
+
it "sets Content-Type to application/json for .json paths" do
|
|
56
|
+
expect(mock_http_session).to receive(:post) do |path, body, headers|
|
|
57
|
+
expect(path).to eq("/payment/EntryTran.json")
|
|
58
|
+
expect(headers["Content-Type"]).to eq("application/json")
|
|
59
|
+
mock_response
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
FakeNetHTTPService.make_request(
|
|
63
|
+
"/payment/EntryTran.json",
|
|
64
|
+
{ "ShopID" => "shop123" },
|
|
65
|
+
"post",
|
|
66
|
+
{ :host => "example.com" }
|
|
67
|
+
)
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
describe "GET requests" do
|
|
72
|
+
it "appends parameters to query string without Content-Type header" do
|
|
73
|
+
expect(mock_http_session).to receive(:get) do |path_with_query|
|
|
74
|
+
expect(path_with_query).to include("/payment/SearchTrade.idPass?")
|
|
75
|
+
expect(path_with_query).to include("ShopID=")
|
|
76
|
+
mock_response
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
FakeNetHTTPService.make_request(
|
|
80
|
+
"/payment/SearchTrade.idPass",
|
|
81
|
+
{ "ShopID" => "shop123" },
|
|
82
|
+
"get",
|
|
83
|
+
{ :host => "example.com" }
|
|
84
|
+
)
|
|
85
|
+
end
|
|
86
|
+
end
|
|
87
|
+
end
|
|
88
|
+
end
|
data/spec/gmo/shop_api_spec.rb
CHANGED
|
@@ -328,6 +328,28 @@ describe "GMO::Payment::ShopAPI" do
|
|
|
328
328
|
}.should_not raise_error("Required card_no, expire were not provided.")
|
|
329
329
|
end
|
|
330
330
|
|
|
331
|
+
it "converts ret_url to RetUrl for ExecTran.idPass" do
|
|
332
|
+
# Test that ret_url is converted to RetUrl by associate_options_to_gmo_params
|
|
333
|
+
actual_params = nil
|
|
334
|
+
allow(@service).to receive(:api_call) do |name, args, method, options|
|
|
335
|
+
actual_params = args
|
|
336
|
+
{}
|
|
337
|
+
end
|
|
338
|
+
|
|
339
|
+
@service.exec_tran({
|
|
340
|
+
:order_id => "test_order",
|
|
341
|
+
:access_id => "test_access",
|
|
342
|
+
:access_pass => "test_pass",
|
|
343
|
+
:method => 1,
|
|
344
|
+
:pay_times => 1,
|
|
345
|
+
:card_no => "4111111111111111",
|
|
346
|
+
:expire => "1405",
|
|
347
|
+
:ret_url => "https://example.com/3d-secure-callback"
|
|
348
|
+
})
|
|
349
|
+
|
|
350
|
+
expect(actual_params).to include("RetUrl" => "https://example.com/3d-secure-callback")
|
|
351
|
+
end
|
|
352
|
+
|
|
331
353
|
context "parameter contains Japanese characters" do
|
|
332
354
|
before { require "kconv" unless defined?(Kconv) }
|
|
333
355
|
|
|
@@ -1170,4 +1192,94 @@ describe "GMO::Payment::ShopAPI" do
|
|
|
1170
1192
|
end
|
|
1171
1193
|
end
|
|
1172
1194
|
|
|
1195
|
+
describe "#exec_tran with 3DS2.0" do
|
|
1196
|
+
it "returns 3DS2.0 challenge flow response", :vcr do
|
|
1197
|
+
result = @service.exec_tran({
|
|
1198
|
+
:access_id => "test_access_7ed782e0e10604b31258e0d69ee3e887",
|
|
1199
|
+
:access_pass => "test_pass_7be5e8786e2e959d7b48ad708634dc7e",
|
|
1200
|
+
:order_id => "TEST_3DS_20250724231518",
|
|
1201
|
+
:method => 1,
|
|
1202
|
+
:pay_times => "",
|
|
1203
|
+
:card_no => "4111111111111111",
|
|
1204
|
+
:expire => "2512",
|
|
1205
|
+
:member_id => "TEST_MEMBER_5df458bc",
|
|
1206
|
+
:card_seq => 0,
|
|
1207
|
+
:tds_type => 2,
|
|
1208
|
+
:tds2_type => 2,
|
|
1209
|
+
:call_back_url => "https://example.com/callback",
|
|
1210
|
+
:tds2_ret_url => "https://example.com/3ds/return"
|
|
1211
|
+
})
|
|
1212
|
+
|
|
1213
|
+
result["OrderID"].should == "<ORDER_ID>"
|
|
1214
|
+
result["Forward"].should == "<FORWARD>"
|
|
1215
|
+
result["Method"].should == "1"
|
|
1216
|
+
result["TranID"].should == "<TRAN_ID>"
|
|
1217
|
+
result["TranDate"].should == "<TRAN_DATE>"
|
|
1218
|
+
result["Tds2TransResult"].should == "C"
|
|
1219
|
+
result["Tds2TransResultReason"].should == "01"
|
|
1220
|
+
result["Tds2ChallengeUrl"].should include("/payment/Tds2Challenge")
|
|
1221
|
+
result["Tds2TransID"].should == "<TDS2_TRANS_ID>"
|
|
1222
|
+
end
|
|
1223
|
+
end
|
|
1224
|
+
|
|
1225
|
+
describe "#tds2_auth" do
|
|
1226
|
+
it "executes 3DS2.0 authentication", :vcr do
|
|
1227
|
+
result = @service.tds2_auth({
|
|
1228
|
+
:access_id => "test_access_7ed782e0e10604b31258e0d69ee3e887",
|
|
1229
|
+
:access_pass => "test_pass_7be5e8786e2e959d7b48ad708634dc7e",
|
|
1230
|
+
:tds2_param => "dummy_tds2_param"
|
|
1231
|
+
})
|
|
1232
|
+
|
|
1233
|
+
result["OrderID"].should == "<ORDER_ID>"
|
|
1234
|
+
result["Forward"].should == "<FORWARD>"
|
|
1235
|
+
result["Method"].should == "1"
|
|
1236
|
+
result["PayTimes"].should == ""
|
|
1237
|
+
result["Approve"].should == ""
|
|
1238
|
+
result["TranID"].should == "<TRAN_ID>"
|
|
1239
|
+
result["TranDate"].should == "<TRAN_DATE>"
|
|
1240
|
+
result["CheckString"].should == "<CHECK_STRING>"
|
|
1241
|
+
result["Tds2TransResult"].should == "Y" # Authentication successful
|
|
1242
|
+
result["Tds2TransResultReason"].should == ""
|
|
1243
|
+
result["Tds2ChallengeUrl"].should_not be_nil
|
|
1244
|
+
result["Tds2ChallengeUrl"].should include("/payment/Tds2Challenge")
|
|
1245
|
+
end
|
|
1246
|
+
end
|
|
1247
|
+
|
|
1248
|
+
describe "#tds2_result" do
|
|
1249
|
+
it "gets 3DS2.0 authentication result", :vcr do
|
|
1250
|
+
result = @service.tds2_result({
|
|
1251
|
+
:access_id => "test_access_7ed782e0e10604b31258e0d69ee3e887",
|
|
1252
|
+
:access_pass => "test_pass_7be5e8786e2e959d7b48ad708634dc7e"
|
|
1253
|
+
})
|
|
1254
|
+
|
|
1255
|
+
result["OrderID"].should == "<ORDER_ID>"
|
|
1256
|
+
result["Forward"].should == "<FORWARD>"
|
|
1257
|
+
result["Method"].should == "1"
|
|
1258
|
+
result["PayTimes"].should == ""
|
|
1259
|
+
result["Approve"].should == ""
|
|
1260
|
+
result["TranID"].should == "<TRAN_ID>"
|
|
1261
|
+
result["TranDate"].should == "<TRAN_DATE>"
|
|
1262
|
+
result["CheckString"].should == "<CHECK_STRING>"
|
|
1263
|
+
result["Tds2TransResult"].should == "Y" # Authentication successful
|
|
1264
|
+
result["Tds2TransResultReason"].should == ""
|
|
1265
|
+
end
|
|
1266
|
+
end
|
|
1267
|
+
|
|
1268
|
+
describe "#secure_tran_2" do
|
|
1269
|
+
it "completes payment after 3DS2.0 challenge verification", :vcr do
|
|
1270
|
+
result = @service.secure_tran_2({
|
|
1271
|
+
:access_id => "test_access_7ed782e0e10604b31258e0d69ee3e887",
|
|
1272
|
+
:access_pass => "test_pass_7be5e8786e2e959d7b48ad708634dc7e"
|
|
1273
|
+
})
|
|
1274
|
+
|
|
1275
|
+
result["OrderID"].should == "<ORDER_ID>"
|
|
1276
|
+
result["Forward"].should == "<FORWARD>"
|
|
1277
|
+
result["Method"].should == "1"
|
|
1278
|
+
result["PayTimes"].should == ""
|
|
1279
|
+
result["Approve"].should == "<APPROVE>"
|
|
1280
|
+
result["TranID"].should == "<TRAN_ID>"
|
|
1281
|
+
result["TranDate"].should == "<TRAN_DATE>"
|
|
1282
|
+
result["CheckString"].should == "<CHECK_STRING>"
|
|
1283
|
+
end
|
|
1284
|
+
end
|
|
1173
1285
|
end
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: gmo
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.5.
|
|
4
|
+
version: 0.5.9
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Tatsuo Kaniwa
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date:
|
|
11
|
+
date: 2026-02-09 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: rack
|
|
@@ -108,6 +108,20 @@ dependencies:
|
|
|
108
108
|
- - ">="
|
|
109
109
|
- !ruby/object:Gem::Version
|
|
110
110
|
version: '0'
|
|
111
|
+
- !ruby/object:Gem::Dependency
|
|
112
|
+
name: ostruct
|
|
113
|
+
requirement: !ruby/object:Gem::Requirement
|
|
114
|
+
requirements:
|
|
115
|
+
- - ">="
|
|
116
|
+
- !ruby/object:Gem::Version
|
|
117
|
+
version: '0'
|
|
118
|
+
type: :development
|
|
119
|
+
prerelease: false
|
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
121
|
+
requirements:
|
|
122
|
+
- - ">="
|
|
123
|
+
- !ruby/object:Gem::Version
|
|
124
|
+
version: '0'
|
|
111
125
|
description: Ruby client library for the GMO Payment Platform.
|
|
112
126
|
email:
|
|
113
127
|
- tatsuo@kaniwa.biz
|
|
@@ -177,13 +191,17 @@ files:
|
|
|
177
191
|
- fixtures/vcr_cassettes/GMO_Payment_ShopAPI/_exec_tran_rakuten_id_gets_data_about_a_transaction.yml
|
|
178
192
|
- fixtures/vcr_cassettes/GMO_Payment_ShopAPI/_exec_tran_suica_gets_data_about_a_transaction.yml
|
|
179
193
|
- fixtures/vcr_cassettes/GMO_Payment_ShopAPI/_exec_tran_virtualaccount_gets_data_about_a_transaction.yml
|
|
194
|
+
- fixtures/vcr_cassettes/GMO_Payment_ShopAPI/_exec_tran_with_3DS2_0_returns_3DS2_0_challenge_flow_response.yml
|
|
180
195
|
- fixtures/vcr_cassettes/GMO_Payment_ShopAPI/_refund_tran_brandtoken_gets_data_about_a_transaction.yml
|
|
181
196
|
- fixtures/vcr_cassettes/GMO_Payment_ShopAPI/_sales_tran_brandtoken_gets_data_about_a_transaction.yml
|
|
182
197
|
- fixtures/vcr_cassettes/GMO_Payment_ShopAPI/_search_trade_gets_data_about_order.yml
|
|
183
198
|
- fixtures/vcr_cassettes/GMO_Payment_ShopAPI/_search_trade_got_error_if_missing_options.yml
|
|
184
199
|
- fixtures/vcr_cassettes/GMO_Payment_ShopAPI/_search_trade_multi_gets_data_about_order.yml
|
|
185
200
|
- fixtures/vcr_cassettes/GMO_Payment_ShopAPI/_search_trade_multi_got_error_if_missing_options.yml
|
|
201
|
+
- fixtures/vcr_cassettes/GMO_Payment_ShopAPI/_secure_tran_2_completes_payment_after_3DS2_0_challenge_verification.yml
|
|
186
202
|
- fixtures/vcr_cassettes/GMO_Payment_ShopAPI/_secure_tran_gets_data_about_a_transaction.yml
|
|
203
|
+
- fixtures/vcr_cassettes/GMO_Payment_ShopAPI/_tds2_auth_executes_3DS2_0_authentication.yml
|
|
204
|
+
- fixtures/vcr_cassettes/GMO_Payment_ShopAPI/_tds2_result_gets_3DS2_0_authentication_result.yml
|
|
187
205
|
- fixtures/vcr_cassettes/GMO_Payment_ShopAPI/_void_tran_brandtoken_gets_data_about_order.yml
|
|
188
206
|
- fixtures/vcr_cassettes/GMO_Payment_ShopAPI/secure_tran_request_params.yml
|
|
189
207
|
- fixtures/vcr_cassettes/GMO_Payment_ShopAndSiteAPI/_exec_tran_brandtoken_got_data.yml
|
|
@@ -218,6 +236,7 @@ files:
|
|
|
218
236
|
- spec/gmo/errors_spec.rb
|
|
219
237
|
- spec/gmo/http_service_spec.rb
|
|
220
238
|
- spec/gmo/json_spec.rb
|
|
239
|
+
- spec/gmo/net_http_service_spec.rb
|
|
221
240
|
- spec/gmo/remittance_api_spec.rb
|
|
222
241
|
- spec/gmo/shop_and_site_api_spec.rb
|
|
223
242
|
- spec/gmo/shop_api_spec.rb
|
|
@@ -251,7 +270,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
251
270
|
- !ruby/object:Gem::Version
|
|
252
271
|
version: '0'
|
|
253
272
|
requirements: []
|
|
254
|
-
rubygems_version: 3.4.
|
|
273
|
+
rubygems_version: 3.4.10
|
|
255
274
|
signing_key:
|
|
256
275
|
specification_version: 4
|
|
257
276
|
summary: 'GMO Payment API client: Ruby client library for the GMO Payment Platform.'
|