vsafe-ruby 0.2.2
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 +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
|