active_merchant-epsilon 0.13.0 → 0.14.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: c43c4d71a9719ec55be94aa1f66222eac8bead4b16db6a31611269aee844afcf
4
- data.tar.gz: 6bb0b39a5598d3cb8718037df3fd00ff42a53cded61bc98529a4ad00aa9f4259
3
+ metadata.gz: 8fe0b19a8605e29e5c3a2a310e3b9684767a21fb2f93957342ffd41b9135657e
4
+ data.tar.gz: b8eb1a2b4d150c0696d26a52e58f5069a60542739bc6461d61f864ad20a470db
5
5
  SHA512:
6
- metadata.gz: 164e39f8d0e343f0172e5371fc99d1c46d8d04346c8e0c135ac7478cbe507be36d6182913df016e510eb75073559ad9d59b042718f3c26fa5fb6a37c20e940f6
7
- data.tar.gz: 1b5e435a9342d69b78e032d466fb3f930805912bb2c4ac24eb7e7d9ce2bcf652a5b15f050ab38ad3526929cda5cc00ac32d0f540828226d97a0ca69ab986f845
6
+ metadata.gz: 87d7533d96fd6591a2b4ffeb78c7cfe2de4ad987e41c58be72083672f346178be6fa593e3aad6a5f3b66b0dde708e883d6d82a8c864a05006589d33a2978b41c
7
+ data.tar.gz: '0782a6f4c48fcc0e905a7b72205d5511bea0ffa95ca285dceee5058d97ae0d63e25fc2e2b009910b800c398b2cb07451cb525f8d0ee1f58696228c487f2f4106'
@@ -1,6 +1,9 @@
1
1
  name: test
2
- on: push
3
-
2
+ on:
3
+ push:
4
+ branches:
5
+ - master
6
+ pull_request:
4
7
  jobs:
5
8
  test-all:
6
9
  runs-on: ubuntu-latest
data/CHANGELOG.md CHANGED
@@ -1,5 +1,9 @@
1
1
  # CHANGELOG
2
2
 
3
+ ### 0.14.0
4
+
5
+ - [Support 3D Secure 2.0 for credit card payments](https://github.com/pepabo/active_merchant-epsilon/pull/121)
6
+
3
7
  ### 0.13.0
4
8
 
5
9
  - [Add `last-update` to OrderResponse](https://github.com/pepabo/active_merchant-epsilon/pull/118)
data/README.md CHANGED
@@ -159,6 +159,57 @@ purchase_detail = {
159
159
  # (snip)
160
160
  ```
161
161
 
162
+ ### CreditCard Payment with 3D secure 2.0(with token)
163
+
164
+ ```ruby
165
+ # 3D secure 2.0 does not have a test environment for epsilon
166
+ ActiveMerchant::Billing::Base.mode = :production
167
+
168
+ amount = 1000
169
+ purchase_detail = {
170
+ user_id: 'YOUR_APP_USER_IDENTIFIER',
171
+ user_name: '山田 太郎',
172
+ user_email: 'yamada-taro@example.com',
173
+ item_code: 'ITEM001',
174
+ item_name: 'Greate Product',
175
+ order_number: 'UNIQUE ORDER NUMBER',
176
+ three_d_secure_check_code: 1,
177
+ token: 'CREDIT CARD TOKEN'
178
+ tds_flag: 21 # 21 or 22
179
+ # optional:
180
+ # add params for risk-based certification(billAddrCity etc...)
181
+ }
182
+
183
+ response = gateway.purchase(amount, ActiveMerchant::Billing::CreditCard.new, purchase_detail)
184
+
185
+ if response.success?
186
+ if response.params['three_d_secure']
187
+ puts response.params['tds2_url']
188
+ puts response.params['pa_req']
189
+ else
190
+ # NOT 3D SECURE
191
+ puts "Successfully charged #{amount} yen as credit card payment(not 3D secure)"
192
+ end
193
+ else
194
+ raise StandardError, response.message
195
+ end
196
+
197
+ # (The card holder identifies himself on credit card's page and comes back here)
198
+
199
+ # AND SECOND REQUEST
200
+
201
+ response = gateway.authenticate(
202
+ order_number: 'ORDER NUMBER',
203
+ three_d_secure_pares: 'PAYMENT AUTHENTICATION RESPONSE',
204
+ )
205
+
206
+ if response.success?
207
+ puts 'Successfully charged as credit card payment(3D secure 2.0)'
208
+ else
209
+ raise StandardError, response.message
210
+ end
211
+ ```
212
+
162
213
  ### CreditCard Revolving Payment
163
214
 
164
215
  ```ruby
@@ -48,6 +48,7 @@ module ActiveMerchant #:nodoc:
48
48
  :three_d_secure,
49
49
  :acs_url,
50
50
  :pa_req,
51
+ :tds2_url,
51
52
  :receipt_number,
52
53
  :receipt_date,
53
54
  :captured,
@@ -22,6 +22,20 @@ module ActiveMerchant #:nodoc:
22
22
  capture: 'sales_payment.cgi',
23
23
  }.freeze
24
24
 
25
+ RISK_BASE_AUTH_PARAMS_KEYS = %i[
26
+ tds_flag billAddrCity billAddrCountry billAddrLine1 billAddrLine2 billAddrLine3
27
+ billAddrPostCode billAddrState shipAddrCity shipAddrCountry shipAddrLine1 shipAddrLine2
28
+ shipAddrLine3 shipAddrPostCode shipAddrState chAccAgeInd chAccChange
29
+ chAccChangeIndchAccDate chAccPwdChange chAccPwChangeInd nbPurchaseAccount paymentAccAge
30
+ paymentAccInd provisionAttemptsDay shipAddressUsage shipAddressUsageInd shipNameIndicator
31
+ suspiciousAccActivity txnActivityDay txnActivityYear threeDSReqAuthData threeDSReqAuthMethod
32
+ threeDSReqAuthTimestamp addrMatch cardholderName homePhone mobilePhone
33
+ workPhone challengeInd deliveryEmailAddress deliveryTimeframe giftCardAmount
34
+ giftCardCount preOrderDate preOrderPurchaseInd reorderItemsInd shipIndicator
35
+ ].freeze
36
+
37
+ THREE_D_SECURE_2_INDICATORS = [21, 22].freeze
38
+
25
39
  self.supported_cardtypes = [:visa, :master, :american_express, :discover]
26
40
 
27
41
  def purchase(amount, credit_card, detail = {})
@@ -29,6 +43,10 @@ module ActiveMerchant #:nodoc:
29
43
 
30
44
  params = billing_params(amount, credit_card, detail)
31
45
 
46
+ if three_d_secure_2?(detail)
47
+ params.merge!(detail.slice(*RISK_BASE_AUTH_PARAMS_KEYS).compact)
48
+ end
49
+
32
50
  commit(PATHS[:purchase], params)
33
51
  end
34
52
 
@@ -54,6 +72,10 @@ module ActiveMerchant #:nodoc:
54
72
  params[:memo2] = detail[:memo2] if detail.has_key?(:memo2)
55
73
  params[:kari_flag] = detail[:capture] ? 2 : 1 if detail.has_key?(:capture)
56
74
 
75
+ if three_d_secure_2?(detail)
76
+ params.merge!(detail.slice(*RISK_BASE_AUTH_PARAMS_KEYS).compact)
77
+ end
78
+
57
79
  commit(PATHS[:registered_purchase], params)
58
80
  end
59
81
 
@@ -239,6 +261,10 @@ module ActiveMerchant #:nodoc:
239
261
 
240
262
  params
241
263
  end
264
+
265
+ def three_d_secure_2?(detail)
266
+ THREE_D_SECURE_2_INDICATORS.include?(detail[:tds_flag])
267
+ end
242
268
  end
243
269
  end
244
270
  end
@@ -10,7 +10,7 @@ module ActiveMerchant #:nodoc:
10
10
  @result = @xml.xpath(ResponseXpath::RESULT).to_s
11
11
 
12
12
  response = {
13
- success: [ResultCode::SUCCESS, ResultCode::THREE_D_SECURE].include?(@result) || !state.empty?,
13
+ success: [ResultCode::SUCCESS, ResultCode::THREE_D_SECURE_1, ResultCode::THREE_D_SECURE_2].include?(@result) || !state.empty?,
14
14
  message: "#{error_code}: #{error_detail}"
15
15
  }
16
16
 
@@ -48,7 +48,7 @@ module ActiveMerchant #:nodoc:
48
48
  end
49
49
 
50
50
  def three_d_secure
51
- @result == ResultCode::THREE_D_SECURE
51
+ [ResultCode::THREE_D_SECURE_1, ResultCode::THREE_D_SECURE_2].include?(@result)
52
52
  end
53
53
 
54
54
  def acs_url
@@ -59,6 +59,10 @@ module ActiveMerchant #:nodoc:
59
59
  uri_decode(@xml.xpath(ResponseXpath::PA_REQ).to_s)
60
60
  end
61
61
 
62
+ def tds2_url
63
+ uri_decode(@xml.xpath(ResponseXpath::TDS2_URL).to_s)
64
+ end
65
+
62
66
  def receipt_number
63
67
  @xml.xpath(ResponseXpath::RECEIPT_NUMBER).to_s
64
68
  end
@@ -145,6 +149,7 @@ module ActiveMerchant #:nodoc:
145
149
  CARD_EXPIRE = '//Epsilon_result/result[@card_expire]/@card_expire'
146
150
  ACS_URL = '//Epsilon_result/result[@acsurl]/@acsurl' # ACS (Access Control Server)
147
151
  PA_REQ = '//Epsilon_result/result[@pareq]/@pareq' # PAReq (payer authentication request)
152
+ TDS2_URL = '//Epsilon_result/result[@tds2_url]/@tds2_url'
148
153
  RECEIPT_NUMBER = '//Epsilon_result/result[@receipt_no][1]/@receipt_no'
149
154
  RECEIPT_DATE = '//Epsilon_result/result[@receipt_date][1]/@receipt_date'
150
155
  CONVENIENCE_STORE_LIMIT_DATE = '//Epsilon_result/result[@conveni_limit][1]/@conveni_limit'
@@ -166,10 +171,11 @@ module ActiveMerchant #:nodoc:
166
171
  end
167
172
 
168
173
  module ResultCode
169
- FAILURE = '0'
170
- SUCCESS = '1'
171
- THREE_D_SECURE = '5'
172
- SYSTEM_ERROR = '9'
174
+ FAILURE = '0'
175
+ SUCCESS = '1'
176
+ THREE_D_SECURE_1 = '5'
177
+ THREE_D_SECURE_2 = '6'
178
+ SYSTEM_ERROR = '9'
173
179
  end
174
180
  end
175
181
  end
@@ -1,5 +1,5 @@
1
1
  module ActiveMerchant
2
2
  module Epsilon
3
- VERSION = "0.13.0"
3
+ VERSION = "0.14.0"
4
4
  end
5
5
  end
@@ -0,0 +1,51 @@
1
+ ---
2
+ http_interactions:
3
+ - request:
4
+ method: post
5
+ uri: https://secure.epsilon.jp/cgi-bin/order/direct_card_payment.cgi
6
+ body:
7
+ encoding: UTF-8
8
+ string: contract_code=[CONTRACT_CODE]&order_number=O30189731&tds_check_code=2&tds_pares=dummy+pa_res
9
+ headers:
10
+ Content-Type:
11
+ - application/x-www-form-urlencoded
12
+ Connection:
13
+ - close
14
+ Accept-Encoding:
15
+ - gzip;q=1.0,deflate;q=0.6,identity;q=0.3
16
+ Accept:
17
+ - "*/*"
18
+ User-Agent:
19
+ - Ruby
20
+ response:
21
+ status:
22
+ code: 200
23
+ message: OK
24
+ headers:
25
+ Date:
26
+ - Thu, 15 Sep 2022 08:09:38 GMT
27
+ Server:
28
+ - Apache
29
+ Vary:
30
+ - Accept-Encoding
31
+ Content-Length:
32
+ - '161'
33
+ Connection:
34
+ - close
35
+ Content-Type:
36
+ - text/xml; charset=CP932
37
+ body:
38
+ encoding: ASCII-8BIT
39
+ string: |-
40
+ <?xml version="1.0" encoding="x-sjis-cp932"?>
41
+ <Epsilon_result>
42
+ <result acsurl="" />
43
+ <result err_code="" />
44
+ <result err_detail="" />
45
+ <result kari_flag="0" />
46
+ <result pareq="" />
47
+ <result result="1" />
48
+ <result trans_code="257072796" />
49
+ </Epsilon_result>
50
+ recorded_at: Thu, 15 Sep 2022 08:09:38 GMT
51
+ recorded_with: VCR 6.1.0
@@ -0,0 +1,51 @@
1
+ ---
2
+ http_interactions:
3
+ - request:
4
+ method: post
5
+ uri: https://secure.epsilon.jp/cgi-bin/order/direct_card_payment.cgi
6
+ body:
7
+ encoding: UTF-8
8
+ string: contract_code=[CONTRACT_CODE]&user_id=124014051&user_name=YAMADA+TARO&user_mail_add=yamada-taro%40example.com&item_code=ITEM001&item_name=Greate+Product&order_number=O1663728963&st_code=10000-0000-0000&mission_code=1&item_price=1000&process_code=2&card_st_code=&pay_time=&xml=1&tds_flag=21
9
+ headers:
10
+ Content-Type:
11
+ - application/x-www-form-urlencoded
12
+ Connection:
13
+ - close
14
+ Accept-Encoding:
15
+ - gzip;q=1.0,deflate;q=0.6,identity;q=0.3
16
+ Accept:
17
+ - "*/*"
18
+ User-Agent:
19
+ - Ruby
20
+ response:
21
+ status:
22
+ code: 200
23
+ message: OK
24
+ headers:
25
+ Date:
26
+ - Wed, 21 Sep 2022 02:56:03 GMT
27
+ Server:
28
+ - Apache
29
+ Vary:
30
+ - Accept-Encoding
31
+ Content-Length:
32
+ - '234'
33
+ Connection:
34
+ - close
35
+ Content-Type:
36
+ - text/xml; charset=CP932
37
+ body:
38
+ encoding: ASCII-8BIT
39
+ string: |-
40
+ <?xml version="1.0" encoding="x-sjis-cp932"?>
41
+ <Epsilon_result>
42
+ <result acsurl="" />
43
+ <result err_code="" />
44
+ <result err_detail="" />
45
+ <result pareq="sOuxTX%252BZHCDBJKRdKkN2Iw53" />
46
+ <result result="6" />
47
+ <result tds2_url="https%3A%2F%2Fsecure.epsilon.jp%2Fcgi-bin%2Forder%2Ftds2.cgi" />
48
+ <result trans_code="257810878" />
49
+ </Epsilon_result>
50
+ recorded_at: Wed, 21 Sep 2022 02:56:04 GMT
51
+ recorded_with: VCR 6.1.0
@@ -75,6 +75,34 @@ class RemoteEpsilonGatewayTest < MiniTest::Test
75
75
  end
76
76
  end
77
77
 
78
+ def test_purchase_with_three_d_secure_2_successful
79
+ # 3DS2.0はテスト環境がないので mode を :production にする
80
+ ActiveMerchant::Billing::Base.stub(:mode, :production) do
81
+ VCR.use_cassette(:purchase_with_three_d_secure_2_successful) do
82
+ response = gateway.purchase(
83
+ 1000,
84
+ ActiveMerchant::Billing::CreditCard.new,
85
+ purchase_detail_for_three_d_secure_2
86
+ )
87
+
88
+ assert_equal true, response.success?
89
+ assert_equal true, response.params['three_d_secure']
90
+ assert_equal true, response.params['tds2_url'].present?
91
+ assert_equal true, response.params['pa_req'].present?
92
+ assert_empty response.params['acs_url']
93
+ end
94
+
95
+ VCR.use_cassette(:authenticate_with_three_d_secure_2_successful) do
96
+ response = gateway.authenticate(
97
+ order_number: purchase_detail_for_three_d_secure_2[:order_number],
98
+ three_d_secure_pa_res: 'dummy pa_res'
99
+ )
100
+
101
+ assert_equal true, response.success?
102
+ end
103
+ end
104
+ end
105
+
78
106
  def test_purchase_with_capture_true_successful
79
107
  VCR.use_cassette(:purchase_with_capture_true_successful) do
80
108
  response = gateway.purchase(1000, valid_credit_card, purchase_detail.merge(capture: true))
@@ -256,6 +284,30 @@ class RemoteEpsilonGatewayTest < MiniTest::Test
256
284
  end
257
285
  end
258
286
 
287
+ def test_registered_purchase_with_three_d_secure_2_successful
288
+ # 3DS2.0はテスト環境がないので mode を :production にする
289
+ ActiveMerchant::Billing::Base.stub(:mode, :production) do
290
+ VCR.use_cassette(:purchase_with_three_d_secure_2_successful) do
291
+ response = gateway.registered_purchase(1000, purchase_detail_for_registered_and_three_d_secure_2)
292
+
293
+ assert_equal true, response.success?
294
+ assert_equal true, response.params['three_d_secure']
295
+ assert_equal true, response.params['tds2_url'].present?
296
+ assert_equal true, response.params['pa_req'].present?
297
+ assert_empty response.params['acs_url']
298
+ end
299
+
300
+ VCR.use_cassette(:authenticate_with_three_d_secure_2_successful) do
301
+ response = gateway.authenticate(
302
+ order_number: purchase_detail_for_three_d_secure_2[:order_number],
303
+ three_d_secure_pa_res: 'dummy pa_res'
304
+ )
305
+
306
+ assert_equal true, response.success?
307
+ end
308
+ end
309
+ end
310
+
259
311
  def test_registered_purchase_fail
260
312
  VCR.use_cassette(:registered_purchase_fail) do
261
313
  invalid_purchase_detail = purchase_detail_for_registered
data/test/test_helper.rb CHANGED
@@ -156,6 +156,33 @@ module SamplePaymentMethods
156
156
  }
157
157
  end
158
158
 
159
+ def purchase_detail_for_three_d_secure_2
160
+ now = Time.now
161
+ {
162
+ user_id: "U#{now.to_i}",
163
+ user_name: 'YAMADA Taro',
164
+ user_email: 'yamada-taro@example.com',
165
+ item_code: 'ITEM001',
166
+ item_name: 'Greate Product',
167
+ order_number: "O#{now.sec}#{now.usec}",
168
+ token: '03d4a2ce2f747c9223a4ead24888d0293ad26c06273e296f9faa0675f99a1ff7',
169
+ three_d_secure_check_code: 1,
170
+ tds_flag: 21,
171
+ }
172
+ end
173
+
174
+ def purchase_detail_for_registered_and_three_d_secure_2
175
+ {
176
+ user_id: '124014051',
177
+ user_email: 'yamada-taro@example.com',
178
+ user_name: 'YAMADA TARO',
179
+ item_code: 'ITEM001',
180
+ item_name: 'Greate Product',
181
+ order_number: "O#{Time.now.to_i}",
182
+ tds_flag: 21,
183
+ }
184
+ end
185
+
159
186
  def valid_three_d_secure_pa_res
160
187
  now = Time.now
161
188
  {
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: active_merchant-epsilon
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.13.0
4
+ version: 0.14.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Kenichi TAKAHASHI
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-01-25 00:00:00.000000000 Z
11
+ date: 2022-09-21 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activemerchant
@@ -178,6 +178,7 @@ files:
178
178
  - lib/active_merchant/billing/gateways/response_parser.rb
179
179
  - lib/active_merchant/epsilon.rb
180
180
  - lib/active_merchant/epsilon/version.rb
181
+ - test/fixtures/vcr_cassettes/authenticate_with_three_d_secure_2_successful.yml
181
182
  - test/fixtures/vcr_cassettes/autheticate_three_d_secure_card_successful.yml
182
183
  - test/fixtures/vcr_cassettes/cancel_recurring_fail.yml
183
184
  - test/fixtures/vcr_cassettes/cancel_recurring_successful.yml
@@ -208,6 +209,7 @@ files:
208
209
  - test/fixtures/vcr_cassettes/purchase_successful.yml
209
210
  - test/fixtures/vcr_cassettes/purchase_with_capture_false_successful.yml
210
211
  - test/fixtures/vcr_cassettes/purchase_with_capture_true_successful.yml
212
+ - test/fixtures/vcr_cassettes/purchase_with_three_d_secure_2_successful.yml
211
213
  - test/fixtures/vcr_cassettes/purchase_with_three_d_secure_card_successful.yml
212
214
  - test/fixtures/vcr_cassettes/purchase_with_verification_value.yml
213
215
  - test/fixtures/vcr_cassettes/recurring_fail.yml
@@ -239,7 +241,7 @@ homepage: http://github.com/pepabo/active_merchant-epsilon
239
241
  licenses:
240
242
  - MIT
241
243
  metadata: {}
242
- post_install_message:
244
+ post_install_message:
243
245
  rdoc_options: []
244
246
  require_paths:
245
247
  - lib
@@ -254,11 +256,12 @@ required_rubygems_version: !ruby/object:Gem::Requirement
254
256
  - !ruby/object:Gem::Version
255
257
  version: '0'
256
258
  requirements: []
257
- rubygems_version: 3.2.3
258
- signing_key:
259
+ rubygems_version: 3.0.3
260
+ signing_key:
259
261
  specification_version: 4
260
262
  summary: Epsilon integration for ActiveMerchant.
261
263
  test_files:
264
+ - test/fixtures/vcr_cassettes/authenticate_with_three_d_secure_2_successful.yml
262
265
  - test/fixtures/vcr_cassettes/autheticate_three_d_secure_card_successful.yml
263
266
  - test/fixtures/vcr_cassettes/cancel_recurring_fail.yml
264
267
  - test/fixtures/vcr_cassettes/cancel_recurring_successful.yml
@@ -289,6 +292,7 @@ test_files:
289
292
  - test/fixtures/vcr_cassettes/purchase_successful.yml
290
293
  - test/fixtures/vcr_cassettes/purchase_with_capture_false_successful.yml
291
294
  - test/fixtures/vcr_cassettes/purchase_with_capture_true_successful.yml
295
+ - test/fixtures/vcr_cassettes/purchase_with_three_d_secure_2_successful.yml
292
296
  - test/fixtures/vcr_cassettes/purchase_with_three_d_secure_card_successful.yml
293
297
  - test/fixtures/vcr_cassettes/purchase_with_verification_value.yml
294
298
  - test/fixtures/vcr_cassettes/recurring_fail.yml