vsafe-ruby 0.2.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/README.md +241 -0
- data/Rakefile +6 -0
- data/lib/vsafe.rb +14 -0
- data/lib/vsafe/auth_result.rb +11 -0
- data/lib/vsafe/avs_result.rb +24 -0
- data/lib/vsafe/card_type.rb +29 -0
- data/lib/vsafe/charge_source.rb +12 -0
- data/lib/vsafe/client.rb +101 -0
- data/lib/vsafe/client_error.rb +4 -0
- data/lib/vsafe/config.rb +22 -0
- data/lib/vsafe/cvn_result.rb +17 -0
- data/lib/vsafe/payment_status.rb +15 -0
- data/lib/vsafe/request_error.rb +11 -0
- data/lib/vsafe/response.rb +47 -0
- data/lib/vsafe/response_error.rb +36 -0
- data/lib/vsafe/responses/charge_account_to_temporary_token.rb +12 -0
- data/lib/vsafe/responses/charge_authorize.rb +19 -0
- data/lib/vsafe/responses/charge_confirm.rb +10 -0
- data/lib/vsafe/responses/charge_sale.rb +20 -0
- data/lib/vsafe/responses/get_session_tags.rb +10 -0
- data/lib/vsafe/responses/reverse_payment.rb +12 -0
- data/lib/vsafe/responses/validate_charge_account.rb +19 -0
- data/lib/vsafe/version.rb +3 -0
- data/spec/spec_helper.rb +17 -0
- data/spec/vsafe/auth_result_spec.rb +12 -0
- data/spec/vsafe/avs_result_spec.rb +12 -0
- data/spec/vsafe/card_type_spec.rb +44 -0
- data/spec/vsafe/charge_source_spec.rb +12 -0
- data/spec/vsafe/client_spec.rb +186 -0
- data/spec/vsafe/config_spec.rb +14 -0
- data/spec/vsafe/cvn_result_spec.rb +12 -0
- data/spec/vsafe/payment_status_spec.rb +12 -0
- data/spec/vsafe/request_error_spec.rb +12 -0
- data/spec/vsafe/response_error_spec.rb +37 -0
- data/spec/vsafe/response_spec.rb +161 -0
- data/spec/vsafe/responses/charge_account_to_temporary_token_spec.rb +27 -0
- data/spec/vsafe/responses/charge_authorize_spec.rb +61 -0
- data/spec/vsafe/responses/charge_confirm_spec.rb +18 -0
- data/spec/vsafe/responses/charge_sale_spec.rb +68 -0
- data/spec/vsafe/responses/get_session_tags_spec.rb +27 -0
- data/spec/vsafe/responses/reverse_payment_spec.rb +37 -0
- data/spec/vsafe/responses/validate_charge_account.rb +19 -0
- data/spec/vsafe/vsafe_spec.rb +12 -0
- metadata +174 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 9554215e285634ed75d2a15ee084aee48fd4dc21
|
4
|
+
data.tar.gz: fc340a8c12c446ec0e6c168b9fcb777e3a7dd819
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 15a2f77685b3c972eba40a1c1db35112f0ca56706048c6632889b0be2685bdbf3635307948177c407247b4b95712188cc62b169ae23513d3e78add18c1661c1e
|
7
|
+
data.tar.gz: 6668a08b8e4c50006814118e5ce1f8de165f7fc9eec840e84bbe3cb251255a3f6b0d41c29016564a43a67e0fd43c6bd3e5f26bfc9f6bfc3b29ac0f9bc65e9abf
|
data/README.md
ADDED
@@ -0,0 +1,241 @@
|
|
1
|
+
# VSafe
|
2
|
+
|
3
|
+
|
4
|
+
## Installation
|
5
|
+
|
6
|
+
Add this line to your application's Gemfile:
|
7
|
+
|
8
|
+
```ruby
|
9
|
+
gem 'vsafe-ruby'
|
10
|
+
```
|
11
|
+
|
12
|
+
And then execute:
|
13
|
+
|
14
|
+
$ bundle
|
15
|
+
|
16
|
+
Or install it yourself as:
|
17
|
+
|
18
|
+
$ gem install vsafe-ruby
|
19
|
+
|
20
|
+
## Configuration
|
21
|
+
|
22
|
+
```ruby
|
23
|
+
VSafe.configure do |config|
|
24
|
+
config.account_name = "YOUR VESTA ACCOUNT"
|
25
|
+
config.password = "YOUR VESTA PASSWORD"
|
26
|
+
config.sandbox = true # Sandbox mode, Default to true
|
27
|
+
config.request_timeout = 20 # Request timeout, default to 20
|
28
|
+
end
|
29
|
+
```
|
30
|
+
|
31
|
+
Config can also be overridden when initializing a request client:
|
32
|
+
|
33
|
+
```ruby
|
34
|
+
client = VSafe::Client.new do |config|
|
35
|
+
config.sandbox = !Rails.env.production?
|
36
|
+
config.request_timeout = 3
|
37
|
+
end
|
38
|
+
```
|
39
|
+
|
40
|
+
## Request & Response
|
41
|
+
|
42
|
+
First, Setup a client for making request:
|
43
|
+
|
44
|
+
```ruby
|
45
|
+
client = VSafe::Client.new
|
46
|
+
```
|
47
|
+
|
48
|
+
##### Heartbeat request
|
49
|
+
```ruby
|
50
|
+
# Check if VSafe API is up or not
|
51
|
+
client.heartbeat.success?
|
52
|
+
|
53
|
+
```
|
54
|
+
|
55
|
+
##### Get vesta session tags
|
56
|
+
```ruby
|
57
|
+
response = client.get_session_tags # => #<VSafe::Responses::GetSessionTags ...>
|
58
|
+
|
59
|
+
# Response attributes
|
60
|
+
response.org_id
|
61
|
+
response.web_session_id
|
62
|
+
```
|
63
|
+
|
64
|
+
##### Authorize charge
|
65
|
+
```ruby
|
66
|
+
auth_params = {
|
67
|
+
TransactionID: "...",
|
68
|
+
ChargeAccountNumberToken: "...",
|
69
|
+
ChargeAmount: 10,
|
70
|
+
WebSessionID: "100_000000000", # Fingerprint generated by get_session_tags as part of ChargeSource::WEB transaction
|
71
|
+
PaymentDescriptor: "...",
|
72
|
+
ChargeSource: VSafe::ChargeSource::WEB, # Or VSafe::ChargeSource::PPD/VSafe::ChargeSource::TEL
|
73
|
+
RiskInformation: "...", # XML string for the transaction
|
74
|
+
IsTempToken: false,
|
75
|
+
CardHolderFirstName: "Foo",
|
76
|
+
CardHolderLastName: "Bar",
|
77
|
+
CardHolderAddressLine1: "...",
|
78
|
+
CardHolderAddressLine2: "...",
|
79
|
+
CardHolderCity: "...",
|
80
|
+
CardHolderRegion: "...",
|
81
|
+
CardHolderPostalCode: "...",
|
82
|
+
CardHolderCountryCode: "...",
|
83
|
+
ChargeCVN: 123, # Card's CVV
|
84
|
+
ChargeExpirationMMYY: "1221", # Card's expiration date in MMYY format
|
85
|
+
StoreCard: true # Get a permanent token or not
|
86
|
+
}
|
87
|
+
|
88
|
+
client.charge_authorize(params) # => #<VSafe::Responses::ChargeAuthorize ...>
|
89
|
+
|
90
|
+
# Response attributes
|
91
|
+
response.avs_result
|
92
|
+
response.auth_result
|
93
|
+
response.cvn_result
|
94
|
+
response.charge_permanent_token
|
95
|
+
response.payment_acquirer_name
|
96
|
+
response.payment_id
|
97
|
+
response.payment_status
|
98
|
+
```
|
99
|
+
|
100
|
+
##### Authorize charge
|
101
|
+
|
102
|
+
Authorize a credit card charge attempt for later confirm usage.
|
103
|
+
|
104
|
+
```ruby
|
105
|
+
auth_params = {
|
106
|
+
TransactionID: "...",
|
107
|
+
ChargeAccountNumberToken: "...",
|
108
|
+
ChargeAmount: 10,
|
109
|
+
WebSessionID: "100_000000000", # Fingerprint generated by get_session_tags as part of ChargeSource::WEB transaction
|
110
|
+
PaymentDescriptor: "...",
|
111
|
+
ChargeSource: VSafe::ChargeSource::WEB, # Or VSafe::ChargeSource::PPD/VSafe::ChargeSource::TEL
|
112
|
+
RiskInformation: "...", # XML string for the transaction
|
113
|
+
IsTempToken: false,
|
114
|
+
CardHolderFirstName: "Foo",
|
115
|
+
CardHolderLastName: "Bar",
|
116
|
+
CardHolderAddressLine1: "...",
|
117
|
+
CardHolderAddressLine2: "...",
|
118
|
+
CardHolderCity: "...",
|
119
|
+
CardHolderRegion: "...",
|
120
|
+
CardHolderPostalCode: "...",
|
121
|
+
CardHolderCountryCode: "...",
|
122
|
+
ChargeCVN: 123, # Card's CVV
|
123
|
+
ChargeExpirationMMYY: "1221", # Card's expiration date in MMYY format
|
124
|
+
StoreCard: true # Get a permanent token or not
|
125
|
+
}
|
126
|
+
|
127
|
+
response = client.charge_authorize(params) # => #<VSafe::Responses::ChargeAuthorize ...>
|
128
|
+
|
129
|
+
# Response attributes
|
130
|
+
response.avs_result
|
131
|
+
response.auth_result
|
132
|
+
response.cvn_result
|
133
|
+
response.charge_permanent_token
|
134
|
+
response.payment_acquirer_name
|
135
|
+
response.payment_id
|
136
|
+
response.payment_status
|
137
|
+
```
|
138
|
+
|
139
|
+
##### Confirm charge
|
140
|
+
|
141
|
+
This should coupled with `charge_authorize`, confirms the previous authorized charge attempt.
|
142
|
+
|
143
|
+
```ruby
|
144
|
+
auth_response = client.charge_authorize(auth_params)
|
145
|
+
|
146
|
+
confirm_params = {
|
147
|
+
PaymentID: auth_response.payment_id,
|
148
|
+
ChargeAmount: auth_params[:ChargeAmount],
|
149
|
+
TransactionID: auth_params[:TransactionID]
|
150
|
+
}
|
151
|
+
|
152
|
+
response = client.charge_confirm(confirm_params) # => #<VSafe::Responses::ChargeConfirm ...>
|
153
|
+
|
154
|
+
response.payment_status
|
155
|
+
```
|
156
|
+
|
157
|
+
##### Charge sale
|
158
|
+
|
159
|
+
Directly charge credit card.
|
160
|
+
|
161
|
+
```ruby
|
162
|
+
charge_params = {
|
163
|
+
#... Same as authorize charge params
|
164
|
+
}
|
165
|
+
|
166
|
+
response = client.charge_sale(charge_params) # => #<VSafe::Responses::ChargeSale ...>
|
167
|
+
|
168
|
+
# Response attributes
|
169
|
+
response.avs_result
|
170
|
+
response.auth_result
|
171
|
+
response.cvn_result
|
172
|
+
response.charge_permanent_token
|
173
|
+
response.payment_acquirer_name
|
174
|
+
response.payment_id
|
175
|
+
response.payment_id_pk
|
176
|
+
response.payment_status
|
177
|
+
```
|
178
|
+
|
179
|
+
##### Reverse payment
|
180
|
+
|
181
|
+
Reverse a previously charged payment.
|
182
|
+
|
183
|
+
```ruby
|
184
|
+
params = {
|
185
|
+
RefundAmount: 10.0,
|
186
|
+
PaymentID: "...", # payment id from charge_confirm or charge_sale
|
187
|
+
TransactionID: "..." # transaction id passed-in in charge/auth params
|
188
|
+
}
|
189
|
+
|
190
|
+
response = client.reverse_payment(params) # => #<VSafe::Responses::ReversePayment ...>
|
191
|
+
|
192
|
+
# Response attributes
|
193
|
+
response.available_refund_amount
|
194
|
+
response.payment_acquirer_name
|
195
|
+
response.payment_id
|
196
|
+
```
|
197
|
+
|
198
|
+
##### Validate Credit card
|
199
|
+
|
200
|
+
Check to see if a credit card is valid.
|
201
|
+
|
202
|
+
```ruby
|
203
|
+
params = {
|
204
|
+
TransactionID: "...",
|
205
|
+
ChargeAccountNumberToken: "...",
|
206
|
+
WebSessionID: "100_000000000", # Fingerprint generated by get_session_tags as part of ChargeSource::WEB transaction
|
207
|
+
IsTempToken: true,
|
208
|
+
StoreCard: true,
|
209
|
+
PaymentDescriptor: "...",
|
210
|
+
ChargeSource: VSafe::ChargeSource::WEB,
|
211
|
+
CardHolderFirstName: "Foo",
|
212
|
+
CardHolderLastName: "Bar",
|
213
|
+
CardHolderAddressLine1: "...",
|
214
|
+
CardHolderAddressLine2: "...",
|
215
|
+
CardHolderCity: "...",
|
216
|
+
CardHolderRegion: "...",
|
217
|
+
CardHolderPostalCode: "...",
|
218
|
+
CardHolderCountryCode: "...",
|
219
|
+
ChargeCVN: 123, # Card's CVV
|
220
|
+
ChargeExpirationMMYY: "1221", # Card's expiration date in MMYY format
|
221
|
+
}
|
222
|
+
|
223
|
+
response = client.validate_charge_account(params)
|
224
|
+
|
225
|
+
response.avs_result
|
226
|
+
response.auth_result
|
227
|
+
response.cvn_result
|
228
|
+
response.charge_permanent_token
|
229
|
+
response.payment_acquirer_name
|
230
|
+
response.payment_id
|
231
|
+
response.payment_status
|
232
|
+
```
|
233
|
+
|
234
|
+
|
235
|
+
## Contributing
|
236
|
+
|
237
|
+
1. Fork it ( https://github.com/[my-github-username]/vsafe-ruby/fork )
|
238
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
239
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
240
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
241
|
+
5. Create a new Pull Request
|
data/Rakefile
ADDED
data/lib/vsafe.rb
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
module VSafe
|
2
|
+
class AvsResult
|
3
|
+
AVS_NOT_PERFORMED = 5
|
4
|
+
NO_ADDRESS_SUPPLIED = 6
|
5
|
+
AVS_DATA_INVALID = 7
|
6
|
+
FOREIGN_ADDRESS_MATCH = 8
|
7
|
+
FOREIGN_ADDRESS_MISMATCH = 9
|
8
|
+
AVS_NOT_AVAILABLE = 10
|
9
|
+
AVS_POSTAL_CODE_AND_LOCALE_MATCH = 11
|
10
|
+
AVS_LOCALE_MATCH = 12
|
11
|
+
AVS_POSTAL_CODE_MATCH = 13
|
12
|
+
AVS_NOT_MATCHED = 14
|
13
|
+
FORIEGN_ISSUER_AVS_NOT_AVAILABLE = 16
|
14
|
+
AVS_SYSTEM_UNAVAILABLE = 24
|
15
|
+
AVS_PARTIAL_MATCH = 39
|
16
|
+
AMEX_AUTOMATED_ADDRESS_VERIFICATION = 2000
|
17
|
+
|
18
|
+
attr_reader :code
|
19
|
+
|
20
|
+
def initialize(code)
|
21
|
+
@code = code.to_i
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
module VSafe
|
2
|
+
class CardType
|
3
|
+
AMERICAN_EXPRESS = 3
|
4
|
+
VISA = 4
|
5
|
+
MASTERCARD = 5
|
6
|
+
DISCOVER = 6
|
7
|
+
DINERS_CLUB = 7
|
8
|
+
OPTIMA = 10
|
9
|
+
|
10
|
+
HUMANIZED_NAMES = {
|
11
|
+
AMERICAN_EXPRESS => "American Express".freeze,
|
12
|
+
VISA => "Visa".freeze,
|
13
|
+
MASTERCARD => "MasterCard".freeze,
|
14
|
+
DISCOVER => "Discover".freeze,
|
15
|
+
DINERS_CLUB => "Diners Club".freeze,
|
16
|
+
OPTIMA => "Optima".freeze
|
17
|
+
}
|
18
|
+
|
19
|
+
attr_reader :code
|
20
|
+
|
21
|
+
def initialize(code)
|
22
|
+
@code = code.to_i
|
23
|
+
end
|
24
|
+
|
25
|
+
def description
|
26
|
+
HUMANIZED_NAMES[code]
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
module VSafe
|
2
|
+
class ChargeSource
|
3
|
+
# Use this to specify that the payment has been prearranged. This is used
|
4
|
+
# when the payment device has been validated or already had a successful
|
5
|
+
# charge against it. When this option is used, the ChargeCVN is not required.
|
6
|
+
PPD = "PPD"
|
7
|
+
# Use this to specify that the payment has been taken over the telephone.
|
8
|
+
TEL = "TEL"
|
9
|
+
# Use this to specify that the payment has been taken over the Web.
|
10
|
+
WEB = "WEB"
|
11
|
+
end
|
12
|
+
end
|
data/lib/vsafe/client.rb
ADDED
@@ -0,0 +1,101 @@
|
|
1
|
+
require "vsafe/config"
|
2
|
+
require "vsafe/charge_source"
|
3
|
+
require "vsafe/response"
|
4
|
+
require "vsafe/responses/get_session_tags"
|
5
|
+
require "vsafe/responses/charge_authorize"
|
6
|
+
require "vsafe/responses/charge_confirm"
|
7
|
+
require "vsafe/responses/reverse_payment"
|
8
|
+
require "vsafe/responses/charge_account_to_temporary_token"
|
9
|
+
require "vsafe/responses/charge_sale"
|
10
|
+
require "vsafe/responses/validate_charge_account"
|
11
|
+
require "securerandom"
|
12
|
+
require "uri"
|
13
|
+
|
14
|
+
module VSafe
|
15
|
+
class Client
|
16
|
+
SANDBOX_FINGERPRINT_PATH = "ThreatMetrixUIRedirector".freeze
|
17
|
+
FINGERPRINT_PATH = "PaySafeUIRedirector".freeze
|
18
|
+
# We should only use JSONP_SERVICE_PATH for charge_acct_to_tempory_token call in web js.
|
19
|
+
JSONP_SERVICE_PATH = "GatewayProxyJSON/Service".freeze
|
20
|
+
SERVICE_PATH = "GatewayProxy/Service".freeze
|
21
|
+
REQUEST_CONTENT_TYPE = "application/json; charset=utf-8".freeze
|
22
|
+
|
23
|
+
attr_reader :config
|
24
|
+
|
25
|
+
def initialize
|
26
|
+
# dup config in case we need to override default settings
|
27
|
+
@config = VSafe.config.dup
|
28
|
+
|
29
|
+
yield config if block_given?
|
30
|
+
end
|
31
|
+
|
32
|
+
def get_session_tags
|
33
|
+
params = {
|
34
|
+
TransactionID: SecureRandom.uuid
|
35
|
+
}
|
36
|
+
|
37
|
+
VSafe::Responses::GetSessionTags.new(request(service_url("GetSessionTags"), params))
|
38
|
+
end
|
39
|
+
|
40
|
+
def charge_authorize(params)
|
41
|
+
VSafe::Responses::ChargeAuthorize.new(request(service_url("ChargeAuthorize"), params))
|
42
|
+
end
|
43
|
+
|
44
|
+
def charge_confirm(params)
|
45
|
+
VSafe::Responses::ChargeConfirm.new(request(service_url("ChargeConfirm"), params))
|
46
|
+
end
|
47
|
+
|
48
|
+
def reverse_payment(params)
|
49
|
+
VSafe::Responses::ReversePayment.new(request(service_url("ReversePayment"), params))
|
50
|
+
end
|
51
|
+
|
52
|
+
def heartbeat
|
53
|
+
VSafe::Response.new(request(service_url("HeartBeat")))
|
54
|
+
end
|
55
|
+
|
56
|
+
def charge_sale(params)
|
57
|
+
VSafe::Responses::ChargeSale.new(request(service_url("ChargeSale"), params))
|
58
|
+
end
|
59
|
+
|
60
|
+
def validate_charge_account(params)
|
61
|
+
VSafe::Responses::ValidateChargeAccount.new(request(service_url("ValidateChargeAccount"), params))
|
62
|
+
end
|
63
|
+
|
64
|
+
def service_url(endpoint = nil, jsonp = false)
|
65
|
+
parts = [
|
66
|
+
config.url,
|
67
|
+
jsonp ? JSONP_SERVICE_PATH : SERVICE_PATH
|
68
|
+
]
|
69
|
+
parts << endpoint if endpoint
|
70
|
+
|
71
|
+
File.join(parts)
|
72
|
+
end
|
73
|
+
|
74
|
+
def fingerprint_url
|
75
|
+
@_fingerprint_url ||= URI.join(config.url, config.sandbox ? SANDBOX_FINGERPRINT_PATH : FINGERPRINT_PATH).to_s
|
76
|
+
end
|
77
|
+
|
78
|
+
private
|
79
|
+
|
80
|
+
def request(url, params = {})
|
81
|
+
options = {
|
82
|
+
timeout: config.request_timeout,
|
83
|
+
body: params.merge(
|
84
|
+
AccountName: config.account_name,
|
85
|
+
Password: config.password
|
86
|
+
).to_json,
|
87
|
+
headers: {
|
88
|
+
"Content-Type" => REQUEST_CONTENT_TYPE
|
89
|
+
}
|
90
|
+
}
|
91
|
+
|
92
|
+
# The HTTPS endpoint for VSafe Sandbox has an outdated SSL version.
|
93
|
+
# We need to do this so that we can actually connect.
|
94
|
+
if config.sandbox
|
95
|
+
options[:ssl_version] = :TLSv1
|
96
|
+
end
|
97
|
+
|
98
|
+
response = HTTParty.post(url, options)
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|