vantiv 0.1.0 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (43) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +64 -0
  3. data/README.md +20 -4
  4. data/cert_fixtures/L_EP_1.json +3 -1
  5. data/cert_fixtures/L_EP_2.json +3 -1
  6. data/cert_fixtures/L_EP_3.json +3 -1
  7. data/cert_fixtures/L_EP_4.json +4 -0
  8. data/cert_fixtures/L_EP_5.json +4 -0
  9. data/cert_fixtures/L_EP_6.json +3 -1
  10. data/cert_fixtures/L_EP_7.json +3 -1
  11. data/exe/vantiv-certify-app +1 -0
  12. data/lib/vantiv.rb +13 -7
  13. data/lib/vantiv/api/live_transaction_response.rb +3 -1
  14. data/lib/vantiv/api/request_body.rb +28 -8
  15. data/lib/vantiv/api/response.rb +16 -5
  16. data/lib/vantiv/api/tokenization_response.rb +4 -0
  17. data/lib/vantiv/mocked_sandbox/api_request.rb +31 -3
  18. data/lib/vantiv/mocked_sandbox/dynamic_response_body.rb +40 -0
  19. data/lib/vantiv/mocked_sandbox/fixture_generator.rb +171 -19
  20. data/lib/vantiv/mocked_sandbox/fixtures/auth--4457002100000005.json.erb +26 -0
  21. data/lib/vantiv/mocked_sandbox/fixtures/auth--4457010000000009.json.erb +27 -0
  22. data/lib/vantiv/mocked_sandbox/fixtures/auth--5112001600000006.json.erb +26 -0
  23. data/lib/vantiv/mocked_sandbox/fixtures/auth--5112001900000003.json.erb +26 -0
  24. data/lib/vantiv/mocked_sandbox/fixtures/auth_capture--4457002100000005.json.erb +26 -0
  25. data/lib/vantiv/mocked_sandbox/fixtures/auth_capture--4457010000000009.json.erb +27 -0
  26. data/lib/vantiv/mocked_sandbox/fixtures/auth_capture--5112001600000006.json.erb +26 -0
  27. data/lib/vantiv/mocked_sandbox/fixtures/auth_capture--5112001900000003.json.erb +26 -0
  28. data/lib/vantiv/mocked_sandbox/fixtures/auth_reversal.json.erb +21 -0
  29. data/lib/vantiv/mocked_sandbox/fixtures/capture.json.erb +21 -0
  30. data/lib/vantiv/mocked_sandbox/fixtures/credit.json.erb +21 -0
  31. data/lib/vantiv/mocked_sandbox/fixtures/refund--4457002100000005.json.erb +22 -0
  32. data/lib/vantiv/mocked_sandbox/fixtures/refund--4457010000000009.json.erb +22 -0
  33. data/lib/vantiv/mocked_sandbox/fixtures/refund--5112001600000006.json.erb +22 -0
  34. data/lib/vantiv/mocked_sandbox/fixtures/refund--5112001900000003.json.erb +22 -0
  35. data/lib/vantiv/mocked_sandbox/fixtures/tokenize_by_direct_post--4457002100000005.json.erb +4 -4
  36. data/lib/vantiv/mocked_sandbox/fixtures/tokenize_by_direct_post--4457010000000009.json.erb +2 -2
  37. data/lib/vantiv/mocked_sandbox/fixtures/tokenize_by_direct_post--4457010010900010.json.erb +3 -4
  38. data/lib/vantiv/mocked_sandbox/fixtures/tokenize_by_direct_post--5112001600000006.json.erb +4 -4
  39. data/lib/vantiv/mocked_sandbox/fixtures/tokenize_by_direct_post--5112001900000003.json.erb +2 -2
  40. data/lib/vantiv/mocked_sandbox/fixtures/void.json.erb +21 -0
  41. data/lib/vantiv/test_card.rb +25 -1
  42. data/lib/vantiv/version.rb +1 -1
  43. metadata +20 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 923cb51d4a0626d8b63cb9139ff3961ea5bbbd96
4
- data.tar.gz: 5ce0a976b96f07c76e1251d5c4de9b453b26b56f
3
+ metadata.gz: 4eafce70c91d564dbbab06586a1fc13f0a7f1458
4
+ data.tar.gz: b5abe4e788d601c489d882db8ac0b9f32dbacf59
5
5
  SHA512:
6
- metadata.gz: 4209143635bf22f01654e50a1dbddd61b331a1329b0a9d5a4fb26b74da986260a2e3c7c6cfee33667cfec3ef6b200fc862ae2724cf4fe85b903a255d3e7dd2f3
7
- data.tar.gz: 3b61c32775ed45e78a0cd3f1454acd7729b56abbf9e7bb6743ff7e8f20a60bdfc524c15c49bb15fb843a487517f1c061bd3216ef447723e4dd63c8ffd67239e1
6
+ metadata.gz: b85dc5bc03b74980e17ab655bd63b0999931a3e512ac4a28ef8a1bd3ee635b26d04e5a5f386930ac7fe722f573c7dac037c86415da70baf3bd484f1014969ae4
7
+ data.tar.gz: 97b171c491f1503d1e5eb259d1140ce1e64487297eb8173588450a69eeed428c6a302c3e2a1c6760282143b7c6f70611e247c00fe4f16d80fa2e3cf800ce45e4
@@ -0,0 +1,64 @@
1
+ Vantiv Ruby Changes
2
+
3
+ 0.2.0
4
+ -----------
5
+
6
+ NOTE: API change occurs in this version bump on:
7
+
8
+ 1. `Vantiv.auth` and `Vantiv.auth_capture` now require `expiry_month`
9
+ and `expiry_year` to be passed. Merchants are responsible for persisting
10
+ this data.
11
+ 2. `Vantiv.credit`'s `amount` argument is now optional.
12
+
13
+ - Send expiration data on live transactions
14
+ - Major miscommunication from Vantiv during development that sending
15
+ expiration data on authorizations and auth_captures (Sale) was
16
+ not necessary.
17
+ - Expiration data is required for card-not-present transactions
18
+ - In actuality, majority of transactions will work without expiry
19
+ data but a significant number of them will fail with "Invalid Transaction"
20
+ and "Do No Honor" response codes.
21
+ - Make amount in credit endpoint optional; with no amount passed, Vantiv
22
+ credits full amount of original transaction
23
+ - Strip non-numeric characters from credit card numbers:
24
+ - Numbers input with spaces or delimeters are acceptable for direct
25
+ tokenization as a result
26
+ - Cast arguments accepted to strings in Request Bodies
27
+ - Retry requests when Vantiv doesn't respond with JSON
28
+ - Sometimes, Vantiv's API doesn't respond with JSON (typically, when
29
+ a service is down or something)
30
+ - It seems safe to retry requests in that case, up to 3 times.
31
+ - Add mocked sandbox responses for all other endpoints:
32
+ - Auth
33
+ - Capture
34
+ - Auth Reversal
35
+ - Credit
36
+ - Refund
37
+ - Void
38
+
39
+ 0.1.0
40
+ -----------
41
+
42
+ - Add a mocked sandbox structure for gem to operate in test:
43
+ - Allows gem to operate in a test environment without making real
44
+ network requests, while still behaving identically to certification
45
+ Environment
46
+ - Only difference is that mocked sandbox has consistent payment account
47
+ IDs per card number, available on TestCard object
48
+ #mocked_sandbox_payment_account_id
49
+ - Intially only for direct tokenization endpoint
50
+ - Implement direct tokenization, allowing merchants to both use eProtect or
51
+ tokenize with Vantiv directly.
52
+ - Implement auth reversal
53
+ - Implement refunds
54
+ - Implement credits
55
+ - Implement voids
56
+ - Add TravisCI for CI
57
+ - Add paypage server and paypage driver, objects to run a basic version of
58
+ an eProtect page. Enables retrieving paypageRegistrationIDs in order to test
59
+ usage to tokenize via eProtect.
60
+ - Add script to run all Devhub certification environment validation tests
61
+ via script:
62
+ - Allows merchants to install gem and certify quickly, rather than manually
63
+
64
+
data/README.md CHANGED
@@ -6,7 +6,7 @@
6
6
  Add this line to your application's Gemfile:
7
7
 
8
8
  ```ruby
9
- gem 'vantiv-ruby'
9
+ gem 'vantiv'
10
10
  ```
11
11
 
12
12
  And then execute:
@@ -15,7 +15,7 @@ And then execute:
15
15
 
16
16
  Or install it yourself as:
17
17
 
18
- $ gem install vantiv-ruby
18
+ $ gem install vantiv
19
19
 
20
20
  ## Configuration
21
21
 
@@ -53,7 +53,7 @@ Navigate to your application's page in DevHub's developer portal (apideveloper.v
53
53
 
54
54
  ## Usage
55
55
 
56
- The vantiv-ruby gem provides a simple ruby client for interacting with Vantiv's DevHub API. This API wraps their Litle/XML API and provides an API that uses json. This gem provides a way for a merchant to:
56
+ The vantiv gem provides a simple ruby client for interacting with Vantiv's DevHub API. This API wraps their Litle/XML API and provides an API that uses json. This gem provides a way for a merchant to:
57
57
 
58
58
  1. Use Vantiv's eProtect feature to tokenize sensitive card information directly to Vantiv's servers.
59
59
  2. Run the following transactions on customers' accounts:
@@ -181,7 +181,23 @@ In the server, once a temporary token has been received, a permanent token can b
181
181
  Vantiv.tokenize(temporary_token: 'temporary-token-here')
182
182
  ```
183
183
 
184
- This will return a TokenizationResponse object, which responds to `success?` and `failure?`, and which returns the `payment_account_id` retrieved from Vantiv. The merchant should save this token for use on future transactions.
184
+ This will return a TokenizationResponse object, which responds to `success?` and `failure?`, and which returns a `card_type` and the `payment_account_id` retrieved from Vantiv. The merchant should save this token for use on future transactions.
185
+
186
+ The `card_type` corresponds with the type of account that was used in the transaction and has the following enumerations:
187
+
188
+ | Enumeration | Description |
189
+ | ------------- | ------------- |
190
+ | MC | MasterCard |
191
+ | VI | Visa |
192
+ | AX | American Express |
193
+ | DC | Diner’s Club |
194
+ | DI | Discover |
195
+ | PP | PayPal |
196
+ | JC | JCB (Japanese Credit Bureau) |
197
+ | BL | PayPal Credit |
198
+ | EC | eCheck |
199
+ | GC | Gift Card |
200
+ | “” | (empty) Card type unknown or undefined |
185
201
 
186
202
  NOTES: There are a few gotchas with tokenization, namely:
187
203
 
@@ -9,7 +9,9 @@
9
9
  "PartialApprovedFlag": "false"
10
10
  },
11
11
  "Card": {
12
- "PaypageRegistrationID": "${eProtect.4457010000000009}"
12
+ "PaypageRegistrationID": "${eProtect.4457010000000009}",
13
+ "ExpirationMonth": "01",
14
+ "ExpirationYear": "16"
13
15
  }
14
16
  }
15
17
  }
@@ -9,7 +9,9 @@
9
9
  "PartialApprovedFlag": "false"
10
10
  },
11
11
  "Card": {
12
- "PaypageRegistrationID": "${eProtect.5435101234510196}"
12
+ "PaypageRegistrationID": "${eProtect.5435101234510196}",
13
+ "ExpirationMonth": "01",
14
+ "ExpirationYear": "16"
13
15
  }
14
16
  }
15
17
  }
@@ -2,7 +2,9 @@
2
2
  "endpoint": "TOKENIZATION",
3
3
  "body": {
4
4
  "Card": {
5
- "PaypageRegistrationID": "${eProtect.6011010140000004}"
5
+ "PaypageRegistrationID": "${eProtect.6011010140000004}",
6
+ "ExpirationMonth": "01",
7
+ "ExpirationYear": "16"
6
8
  },
7
9
  "Transaction": {
8
10
  "CustomerID": "123"
@@ -10,6 +10,10 @@
10
10
  },
11
11
  "PaymentAccount": {
12
12
  "PaymentAccountID": "#{L_EP_1.litleOnlineResponse.authorizationResponse.tokenResponse.PaymentAccountID}"
13
+ },
14
+ "Card": {
15
+ "ExpirationMonth": "01",
16
+ "ExpirationYear": "16"
13
17
  }
14
18
  }
15
19
  }
@@ -10,6 +10,10 @@
10
10
  },
11
11
  "PaymentAccount": {
12
12
  "PaymentAccountID": "#{L_EP_2.litleOnlineResponse.saleResponse.tokenResponse.PaymentAccountID}"
13
+ },
14
+ "Card": {
15
+ "ExpirationMonth": "01",
16
+ "ExpirationYear": "16"
13
17
  }
14
18
  }
15
19
  }
@@ -9,7 +9,9 @@
9
9
  "PartialApprovedFlag": "false"
10
10
  },
11
11
  "Card": {
12
- "PaypageRegistrationID": "cDZJcmd1VjNlYXNaSlRMTGpocVZQY1NWVXE4ZW5UTko4NU9KK3p1L1p1Vzg4YzVPQVlSUHNITG1JN2I0NzlyTg=="
12
+ "PaypageRegistrationID": "cDZJcmd1VjNlYXNaSlRMTGpocVZQY1NWVXE4ZW5UTko4NU9KK3p1L1p1Vzg4YzVPQVlSUHNITG1JN2I0NzlyTg==",
13
+ "ExpirationMonth": "01",
14
+ "ExpirationYear": "16"
13
15
  }
14
16
  }
15
17
  }
@@ -9,7 +9,9 @@
9
9
  "PartialApprovedFlag": "false"
10
10
  },
11
11
  "Card": {
12
- "PaypageRegistrationID": "RGFQNCt6U1d1M21SeVByVTM4dHlHb1FsVkUrSmpnWXhNY0o5UkMzRlZFanZiUHVnYjN1enJXbG1WSDF4aXlNcA=="
12
+ "PaypageRegistrationID": "RGFQNCt6U1d1M21SeVByVTM4dHlHb1FsVkUrSmpnWXhNY0o5UkMzRlZFanZiUHVnYjN1enJXbG1WSDF4aXlNcA==",
13
+ "ExpirationMonth": "01",
14
+ "ExpirationYear": "16"
13
15
  }
14
16
  }
15
17
  }
@@ -11,6 +11,7 @@ Vantiv.configure do |config|
11
11
  config.license_id = ENV["LICENSE_ID"]
12
12
  config.acceptor_id = ENV["ACCEPTOR_ID"]
13
13
  config.paypage_id = ENV["PAYPAGE_ID"]
14
+ config.environment = Vantiv::Environment::CERTIFICATION
14
15
 
15
16
  config.default_report_group = '1'
16
17
  end
@@ -37,12 +37,14 @@ module Vantiv
37
37
  ).run
38
38
  end
39
39
 
40
- def self.auth(amount:, payment_account_id:, customer_id:, order_id:)
40
+ def self.auth(amount:, payment_account_id:, customer_id:, order_id:, expiry_month:, expiry_year:)
41
41
  body = Api::RequestBody.for_auth_or_sale(
42
42
  amount: amount,
43
43
  order_id: order_id,
44
44
  customer_id: customer_id,
45
- payment_account_id: payment_account_id
45
+ payment_account_id: payment_account_id,
46
+ expiry_month: expiry_month,
47
+ expiry_year: expiry_year
46
48
  )
47
49
  Api::Request.new(
48
50
  endpoint: Api::Endpoints::AUTHORIZATION,
@@ -77,12 +79,14 @@ module Vantiv
77
79
  ).run
78
80
  end
79
81
 
80
- def self.auth_capture(amount:, payment_account_id:, customer_id:, order_id:)
82
+ def self.auth_capture(amount:, payment_account_id:, customer_id:, order_id:, expiry_month:, expiry_year:)
81
83
  body = Api::RequestBody.for_auth_or_sale(
82
84
  amount: amount,
83
85
  order_id: order_id,
84
86
  customer_id: customer_id,
85
- payment_account_id: payment_account_id
87
+ payment_account_id: payment_account_id,
88
+ expiry_month: expiry_month,
89
+ expiry_year: expiry_year
86
90
  )
87
91
  Api::Request.new(
88
92
  endpoint: Api::Endpoints::SALE,
@@ -93,7 +97,7 @@ module Vantiv
93
97
 
94
98
  # NOTE: ActiveMerchant's #refund... only for use on a capture or sale it seems
95
99
  # -> 'returns' are refunds too, credits are tied to a sale/capture, returns can be willy nilly
96
- def self.credit(transaction_id:, amount:)
100
+ def self.credit(transaction_id:, amount: nil)
97
101
  body = Api::RequestBody.for_credit(
98
102
  amount: amount,
99
103
  transaction_id: transaction_id
@@ -105,12 +109,14 @@ module Vantiv
105
109
  ).run
106
110
  end
107
111
 
108
- def self.refund(amount:, payment_account_id:, customer_id:, order_id:)
112
+ def self.refund(amount:, payment_account_id:, customer_id:, order_id:, expiry_month:, expiry_year:)
109
113
  body = Api::RequestBody.for_return(
110
114
  amount: amount,
111
115
  customer_id: customer_id,
112
116
  order_id: order_id,
113
- payment_account_id: payment_account_id
117
+ payment_account_id: payment_account_id,
118
+ expiry_month: expiry_month,
119
+ expiry_year: expiry_year
114
120
  )
115
121
  Api::Request.new(
116
122
  endpoint: Api::Endpoints::RETURN,
@@ -5,8 +5,10 @@ module Vantiv
5
5
  approved: '000',
6
6
  insufficient_funds: '110',
7
7
  invalid_account_number: '301',
8
+ pick_up_card: '303',
8
9
  expired_card: '305',
9
- token_not_found: '822'
10
+ token_not_found: '822',
11
+ token_invalid: '823'
10
12
  }
11
13
 
12
14
  LIVE_TRANSACTION_RESPONSE_NAMES = {
@@ -1,13 +1,17 @@
1
1
  module Vantiv
2
2
  module Api
3
3
  module RequestBody
4
- def self.for_auth_or_sale(amount:, customer_id:, order_id:, payment_account_id:)
4
+ def self.for_auth_or_sale(amount:, customer_id:, order_id:, payment_account_id:, expiry_month:, expiry_year:)
5
5
  RequestBodyGenerator.run(
6
6
  transaction_element(
7
7
  amount: amount,
8
8
  order_id: order_id,
9
9
  customer_id: customer_id
10
10
  ),
11
+ card_element_for_live_transactions(
12
+ expiry_month: expiry_month,
13
+ expiry_year: expiry_year
14
+ ),
11
15
  payment_account_element(payment_account_id: payment_account_id)
12
16
  )
13
17
  end
@@ -30,7 +34,7 @@ module Vantiv
30
34
  )
31
35
  end
32
36
 
33
- def self.for_return(amount:, customer_id:, order_id:, payment_account_id:)
37
+ def self.for_return(amount:, customer_id:, order_id:, payment_account_id:, expiry_month:, expiry_year:)
34
38
  transaction = transaction_element(
35
39
  amount: amount,
36
40
  order_id: order_id,
@@ -39,6 +43,10 @@ module Vantiv
39
43
  transaction["Transaction"].delete("PartialApprovedFlag")
40
44
  RequestBodyGenerator.run(
41
45
  transaction,
46
+ card_element_for_live_transactions(
47
+ expiry_month: expiry_month,
48
+ expiry_year: expiry_year
49
+ ),
42
50
  payment_account_element(payment_account_id: payment_account_id)
43
51
  )
44
52
  end
@@ -53,10 +61,10 @@ module Vantiv
53
61
  RequestBodyGenerator.run(
54
62
  {
55
63
  "Card" => {
56
- "AccountNumber" => card_number,
57
- "ExpirationMonth" => expiry_month,
58
- "ExpirationYear" => expiry_year,
59
- "CVV" => cvv
64
+ "AccountNumber" => card_number.to_s.gsub(/\D*/, ""),
65
+ "ExpirationMonth" => format_expiry(expiry_month),
66
+ "ExpirationYear" => format_expiry(expiry_year),
67
+ "CVV" => cvv.to_s
60
68
  }
61
69
  }
62
70
  )
@@ -74,6 +82,15 @@ module Vantiv
74
82
  }
75
83
  end
76
84
 
85
+ def self.card_element_for_live_transactions(expiry_month:, expiry_year:)
86
+ {
87
+ "Card" => {
88
+ "ExpirationMonth" => format_expiry(expiry_month),
89
+ "ExpirationYear" => format_expiry(expiry_year)
90
+ }
91
+ }
92
+ end
93
+
77
94
  def self.tied_transaction_element(transaction_id:, amount: nil)
78
95
  res = {
79
96
  "Transaction" => {
@@ -89,7 +106,7 @@ module Vantiv
89
106
  def self.transaction_element(amount:, customer_id:, order_id:)
90
107
  {
91
108
  "Transaction" => {
92
- "ReferenceNumber" => order_id,
109
+ "ReferenceNumber" => order_id.to_s,
93
110
  "TransactionAmount" => '%.2f' % (amount / 100.0),
94
111
  "OrderSource" => Vantiv.order_source,
95
112
  "CustomerID" => customer_id,
@@ -105,7 +122,10 @@ module Vantiv
105
122
  }
106
123
  }
107
124
  end
108
- end
109
125
 
126
+ def self.format_expiry(raw_value)
127
+ raw_value.to_s.reverse[0..1].reverse.rjust(2, "0")
128
+ end
129
+ end
110
130
  end
111
131
  end
@@ -15,17 +15,17 @@ module Vantiv
15
15
  end
16
16
 
17
17
  def api_level_failure?
18
- !httpok ||
19
- # NOTE: this kind of sucks, but at the commit point, the DevHub
20
- # Api sometimes gives 200OK when litle had a parse issue and returns
21
- # 'Error validating xml data...' instead of an actual error
22
- @body["litleOnlineResponse"]["@message"].match(/error/i)
18
+ !httpok || litle_response_has_error?
23
19
  end
24
20
 
25
21
  def message
26
22
  litle_transaction_response["message"]
27
23
  end
28
24
 
25
+ def error_message
26
+ api_level_failure? ? api_level_error_message : message
27
+ end
28
+
29
29
  def response_code
30
30
  litle_transaction_response["response"]
31
31
  end
@@ -36,6 +36,17 @@ module Vantiv
36
36
 
37
37
  private
38
38
 
39
+ def litle_response_has_error?
40
+ # NOTE: this kind of sucks, but at the commit point, the DevHub
41
+ # Api sometimes gives 200OK when litle had a parse issue and returns
42
+ # 'Error validating xml data...' instead of an actual error
43
+ !!@body["litleOnlineResponse"]["@message"].match(/error/i)
44
+ end
45
+
46
+ def api_level_error_message
47
+ body["errormsg"]
48
+ end
49
+
39
50
  attr_reader :transaction_response_name
40
51
 
41
52
  def litle_response
@@ -26,6 +26,10 @@ module Vantiv
26
26
  success? ? litle_transaction_response["PaymentAccountID"] : nil
27
27
  end
28
28
 
29
+ def card_type
30
+ success? ? litle_transaction_response["Type"] : nil
31
+ end
32
+
29
33
  def invalid_card_number?
30
34
  response_code == RESPONSE_CODES[:credit_card_number_invalid]
31
35
  end
@@ -1,6 +1,7 @@
1
1
  module Vantiv
2
2
  module MockedSandbox
3
3
  class ApiRequest
4
+ class EndpointNotMocked < StandardError; end
4
5
  class FixtureNotFound < StandardError; end
5
6
 
6
7
  def self.run(endpoint:, body:)
@@ -17,6 +18,22 @@ module Vantiv
17
18
  if direct_post?
18
19
  load_fixture("tokenize_by_direct_post", card_number)
19
20
  end
21
+ elsif endpoint == Api::Endpoints::SALE
22
+ load_fixture("auth_capture", card_number_from_payment_account_id)
23
+ elsif endpoint == Api::Endpoints::AUTHORIZATION
24
+ load_fixture("auth", card_number_from_payment_account_id)
25
+ elsif endpoint == Api::Endpoints::CAPTURE
26
+ load_fixture("capture")
27
+ elsif endpoint == Api::Endpoints::AUTH_REVERSAL
28
+ load_fixture("auth_reversal")
29
+ elsif endpoint == Api::Endpoints::CREDIT
30
+ load_fixture("credit")
31
+ elsif endpoint == Api::Endpoints::RETURN
32
+ load_fixture("refund", card_number_from_payment_account_id)
33
+ elsif endpoint == Api::Endpoints::VOID
34
+ load_fixture("void")
35
+ else
36
+ raise EndpointNotMocked.new("#{endpoint} is not mocked!")
20
37
  end
21
38
  {
22
39
  httpok: fixture["httpok"],
@@ -37,11 +54,22 @@ module Vantiv
37
54
  request_body["Card"]["AccountNumber"]
38
55
  end
39
56
 
40
- def load_fixture(api_method, card_number)
57
+ def card_number_from_payment_account_id
58
+ TestCard.find_by_payment_account_id(
59
+ request_body["PaymentAccount"]["PaymentAccountID"]
60
+ ).card_number
61
+ end
62
+
63
+ def load_fixture(api_method, card_number = nil)
64
+ fixture_file_name = card_number ? "#{api_method}--#{card_number}" : api_method
41
65
  begin
42
- self.fixture = File.open("#{MockedSandbox.fixtures_directory}#{api_method}--#{card_number}.json.erb", 'r') do |f|
66
+ self.fixture = File.open("#{MockedSandbox.fixtures_directory}#{fixture_file_name}.json.erb", 'r') do |f|
43
67
  raw_fixture = JSON.parse(f.read)
44
- raw_fixture["response_body"] = raw_fixture["response_body"].to_json
68
+ # Prevent rails overridden version of to_json from encoding erb sepcial characters
69
+ raw_fixture["response_body"] = JSON::Ext::Generator::GeneratorMethods::Hash
70
+ .instance_method(:to_json)
71
+ .bind(raw_fixture["response_body"])
72
+ .call
45
73
  raw_fixture
46
74
  end
47
75
  rescue Errno::ENOENT