yp-ruby 0.1.3 → 0.1.4a
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/README.md +81 -2
- data/data/gateway_responses.yml +69 -0
- data/lib/base.rb +18 -47
- data/lib/response.rb +36 -0
- data/lib/response/error.rb +16 -0
- data/lib/response/error_logger.rb +53 -0
- data/lib/response/gateway_error.rb +68 -0
- data/lib/response/parser.rb +27 -0
- data/lib/response/validator.rb +21 -0
- data/lib/response/validator/acquirer.rb +27 -0
- data/lib/response/validator/gateway.rb +41 -0
- data/lib/response/validator/signing_key.rb +38 -0
- data/lib/signing_hash_creator.rb +32 -0
- data/lib/transaction_logger.rb +15 -3
- data/lib/version.rb +1 -1
- metadata +15 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 9f28691645bfdb90373e2524028d93a1e711bb46
|
4
|
+
data.tar.gz: cd6b81278539fbea582bf11dca079e7131f45357
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 4f933e44afc37aa9a3a244e89c78f6a7ef4f75e6ca20cb8e95dbf57df2557b6fa73afe5ea6b37aa5d0cfefd84ab625bdec24f105c09d16e8e7d712873d766a97
|
7
|
+
data.tar.gz: 299c5520a8dd0234828004f7e5d16e1b4ad404f977deddf700010606b02fb4423e475c933c201964e9c9d36852bfe57b631e433565032dc27a80a4250468f4da
|
data/README.md
CHANGED
@@ -20,7 +20,86 @@ Or install it yourself as:
|
|
20
20
|
|
21
21
|
## Usage
|
22
22
|
|
23
|
-
|
23
|
+
Different classes are available for the Gateway actions:
|
24
|
+
|
25
|
+
- Yp::Sale
|
26
|
+
- Yp::Preauth
|
27
|
+
- Yp::Verify
|
28
|
+
|
29
|
+
If you need support for more actions, please [open an issue](https://github.com/andytango/yp-ruby/issues)!
|
30
|
+
|
31
|
+
### Authentication and params
|
32
|
+
|
33
|
+
You will need to pass in the correct parameters according to the Yorkshire Payments integration guide:
|
34
|
+
|
35
|
+
```ruby
|
36
|
+
|
37
|
+
signature_key = 'Engine0Milk12Next'
|
38
|
+
|
39
|
+
params = {
|
40
|
+
merchantID: '101381',
|
41
|
+
countryCode: 826,
|
42
|
+
currencyCode: 826,
|
43
|
+
cardNumber: '4012001037141112',
|
44
|
+
cardExpiryMonth: 12,
|
45
|
+
cardExpiryYear: 15,
|
46
|
+
cardCVV: '083',
|
47
|
+
customerName: 'Yorkshire Payments',
|
48
|
+
customerEmail: 'support@yorkshirepayments.com',
|
49
|
+
customerAddress: '16 Test Street',
|
50
|
+
customerPostCode: 'TE15 5ST',
|
51
|
+
orderRef: 'Test purchase'
|
52
|
+
}
|
53
|
+
|
54
|
+
transaction = Yp::Sale.new(signature, params)
|
55
|
+
|
56
|
+
```
|
57
|
+
|
58
|
+
The library will *not* validate your parameters before sending. This feature is coming soon.
|
59
|
+
|
60
|
+
You pass in a callback method as a block, or access the response after the transaction is sent:
|
61
|
+
|
62
|
+
```ruby
|
63
|
+
|
64
|
+
transaction.send! do |response|
|
65
|
+
puts response.state # --> 'captured'
|
66
|
+
end
|
67
|
+
|
68
|
+
# OR:
|
69
|
+
|
70
|
+
response = transaction.send!
|
71
|
+
puts response.state # --> 'captured'
|
72
|
+
|
73
|
+
```
|
74
|
+
|
75
|
+
### Error Handling
|
76
|
+
|
77
|
+
The client will raise a number of different types of errors:
|
78
|
+
|
79
|
+
#### Validation Errors
|
80
|
+
|
81
|
+
These occur if we could not perform any validation. This means the response is
|
82
|
+
malformed and can arise if you did not correctly sign your request:
|
83
|
+
|
84
|
+
- Yp::Response::InvalidSignatureError (potentially malicious)
|
85
|
+
- Yp::Response::MissingSignatureError
|
86
|
+
- Yp::Response::MissingResponseCodeError
|
87
|
+
|
88
|
+
#### Gateway Errors
|
89
|
+
|
90
|
+
These occur if, during validation, we found a Gateway error code. These come in
|
91
|
+
three different flavours:
|
92
|
+
|
93
|
+
- Yp::Response::MissingFieldError: _a field was missing in your request_
|
94
|
+
- Yp::Response::InvalidFieldError: _a field value was invalid in your request_
|
95
|
+
- Yp::Response::GatewayError: _the error could not be classified. The gateway's
|
96
|
+
error message will be supplied_
|
97
|
+
|
98
|
+
#### Transaction Declined Error
|
99
|
+
|
100
|
+
This occurs if the transaction has entered the **Declined** state:
|
101
|
+
|
102
|
+
- Yp::Response::DeclinedError
|
24
103
|
|
25
104
|
## Development
|
26
105
|
|
@@ -30,7 +109,7 @@ To install this gem onto your local machine, run `bundle exec rake install`. To
|
|
30
109
|
|
31
110
|
## Contributing
|
32
111
|
|
33
|
-
Bug reports and pull requests are welcome on GitHub at https://github.com/
|
112
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/andytango/yp-ruby. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [Contributor Covenant](http://contributor-covenant.org) code of conduct.
|
34
113
|
|
35
114
|
|
36
115
|
## License
|
@@ -0,0 +1,69 @@
|
|
1
|
+
missing_field:
|
2
|
+
66048: 'request'
|
3
|
+
66049: 'merchantID'
|
4
|
+
66055: 'action'
|
5
|
+
66056: 'amount'
|
6
|
+
66057: 'currencyCode'
|
7
|
+
66058: 'cardNumber'
|
8
|
+
66059: 'cardExpiryMonth'
|
9
|
+
66060: 'cardExpiryYear'
|
10
|
+
66064: 'cardCVV'
|
11
|
+
66065: 'customerName'
|
12
|
+
66066: 'customerAddress'
|
13
|
+
66067: 'customerPostCode'
|
14
|
+
66068: 'customerEmail'
|
15
|
+
66070: 'countyCode'
|
16
|
+
66087: 'signature'
|
17
|
+
66092: 'threeDSPaRes'
|
18
|
+
66093: 'threeDSECI'
|
19
|
+
66094: 'threeDSCAVV'
|
20
|
+
66095: 'threeDSXID'
|
21
|
+
66096: 'threeDSEnrolled'
|
22
|
+
66097: 'threeDSAuthenticated'
|
23
|
+
66098: 'threeDSCheckPref'
|
24
|
+
66099: 'cv2CheckPref'
|
25
|
+
66100: 'addressCheckPref'
|
26
|
+
66101: 'postcodeCheckPref'
|
27
|
+
66102: 'captureDelay'
|
28
|
+
66103: 'orderDate'
|
29
|
+
66104: 'grossAmount'
|
30
|
+
66105: 'netAmount'
|
31
|
+
66016: 'taxRate'
|
32
|
+
66016: 'taxReason'
|
33
|
+
66160: 'cardExpiryDate'
|
34
|
+
66161: 'cardStartDate'
|
35
|
+
|
36
|
+
invalid_field:
|
37
|
+
66304: 'request'
|
38
|
+
66305: 'merchantID'
|
39
|
+
66311: 'action'
|
40
|
+
66312: 'amount'
|
41
|
+
66313: 'currencyCode'
|
42
|
+
66314: 'cardNumber'
|
43
|
+
66315: 'cardExpiryMonth'
|
44
|
+
66316: 'cardExpiryYear'
|
45
|
+
66317: 'cardCVV'
|
46
|
+
66332: 'customerName'
|
47
|
+
66322: 'customerAddress'
|
48
|
+
66323: 'customerPostCode'
|
49
|
+
66324: 'customerEmail'
|
50
|
+
66326: 'countyCode'
|
51
|
+
66343: 'signature'
|
52
|
+
66348: 'threeDSPaRes'
|
53
|
+
66349: 'threeDSECI'
|
54
|
+
66350: 'threeDSCAVV'
|
55
|
+
66351: 'threeDSXID'
|
56
|
+
66352: 'threeDSEnrolled'
|
57
|
+
66353: 'threeDSAuthenticated'
|
58
|
+
66354: 'threeDSCheckPref'
|
59
|
+
66355: 'cv2CheckPref'
|
60
|
+
66356: 'addressCheckPref'
|
61
|
+
66357: 'postcodeCheckPref'
|
62
|
+
66358: 'captureDelay'
|
63
|
+
66359: 'orderDate'
|
64
|
+
66360: 'grossAmount'
|
65
|
+
66361: 'netAmount'
|
66
|
+
66362: 'taxRate'
|
67
|
+
66363: 'taxReason'
|
68
|
+
66416: 'cardExpiryDate'
|
69
|
+
66417: 'cardStartDate'
|
data/lib/base.rb
CHANGED
@@ -1,4 +1,6 @@
|
|
1
1
|
require 'transaction_logger'
|
2
|
+
require 'signing_hash_creator'
|
3
|
+
require 'response'
|
2
4
|
|
3
5
|
module Yp
|
4
6
|
class Base
|
@@ -15,24 +17,13 @@ module Yp
|
|
15
17
|
@signature_key = signature_key
|
16
18
|
end
|
17
19
|
|
18
|
-
def
|
19
|
-
@params.clone.tap do |params|
|
20
|
-
params[:signature] = create_signing_hash
|
21
|
-
TransactionLogger.log_request(params)
|
22
|
-
end
|
23
|
-
end
|
24
|
-
|
25
|
-
def create_signing_hash
|
26
|
-
self.class.digest(self.class.serialize_params(@params) + @signature_key)
|
27
|
-
end
|
28
|
-
|
29
|
-
def send
|
20
|
+
def send!
|
30
21
|
if block_given?
|
31
22
|
RestClient.post(URL, body) do |response|
|
32
|
-
yield(
|
23
|
+
yield(parse_and_validate response)
|
33
24
|
end
|
34
25
|
else
|
35
|
-
|
26
|
+
parse_and_validate(RestClient.post(URL, body))
|
36
27
|
end
|
37
28
|
end
|
38
29
|
|
@@ -59,42 +50,22 @@ module Yp
|
|
59
50
|
{ type: TYPE[type] }
|
60
51
|
end
|
61
52
|
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
end
|
67
|
-
|
68
|
-
def serialize_params(params)
|
69
|
-
uri_string_from_hash(params)
|
70
|
-
end
|
71
|
-
|
72
|
-
def parse(response)
|
73
|
-
ruby_hash_from_response(CGI::parse(response)).tap do |parsed|
|
74
|
-
TransactionLogger.log_response(parsed)
|
75
|
-
end
|
76
|
-
end
|
77
|
-
|
78
|
-
private
|
79
|
-
|
80
|
-
def uri_string_from_hash(hash)
|
81
|
-
hash.map { |key, value| uri_query_param(key, value) }.sort.join '&'
|
82
|
-
end
|
83
|
-
|
84
|
-
def uri_query_param(key, value)
|
85
|
-
encode_url_component(key) + '=' + encode_url_component(value)
|
86
|
-
end
|
87
|
-
|
88
|
-
def encode_url_component(key)
|
89
|
-
ERB::Util::url_encode(key).gsub(/%20/, '+')
|
53
|
+
def body
|
54
|
+
@params.clone.tap do |params|
|
55
|
+
params[:signature] = create_signing_hash
|
56
|
+
TransactionLogger.log_request(params)
|
90
57
|
end
|
58
|
+
end
|
91
59
|
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
end
|
96
|
-
end
|
60
|
+
def create_signing_hash
|
61
|
+
SigningHashCreator.new(@params, @signature_key).create
|
62
|
+
end
|
97
63
|
|
64
|
+
def parse_and_validate(response)
|
65
|
+
Response
|
66
|
+
.new(@signature_key, response, TransactionLogger)
|
67
|
+
.parse_and_validate
|
98
68
|
end
|
69
|
+
|
99
70
|
end
|
100
71
|
end
|
data/lib/response.rb
ADDED
@@ -0,0 +1,36 @@
|
|
1
|
+
require 'response/parser'
|
2
|
+
require 'response/error'
|
3
|
+
require 'response/validator'
|
4
|
+
require 'response/error_logger'
|
5
|
+
|
6
|
+
module Yp
|
7
|
+
class Response
|
8
|
+
def initialize(signature, params, logger)
|
9
|
+
@signature = signature
|
10
|
+
@params = params
|
11
|
+
@logger = logger
|
12
|
+
end
|
13
|
+
|
14
|
+
def parse_and_validate
|
15
|
+
validate!
|
16
|
+
parsed
|
17
|
+
end
|
18
|
+
|
19
|
+
private
|
20
|
+
|
21
|
+
def validate!
|
22
|
+
ErrorLogger.new(@logger).log do
|
23
|
+
Validator.new(parsed, @signature).validate!
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def parsed
|
28
|
+
@parsed ||= parse_params
|
29
|
+
end
|
30
|
+
|
31
|
+
def parse_params
|
32
|
+
Parser.new(@params).parse.tap { |parsed| @logger.log_response(parsed) }
|
33
|
+
end
|
34
|
+
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
module Yp
|
2
|
+
class Response
|
3
|
+
class ValidationError < StandardError
|
4
|
+
def initialize
|
5
|
+
super('Gateway response could not be validated.')
|
6
|
+
end
|
7
|
+
end
|
8
|
+
|
9
|
+
class InvalidSignatureError < ValidationError; end
|
10
|
+
class MissingSignatureError < ValidationError; end
|
11
|
+
class MissingResponseCodeError < ValidationError; end
|
12
|
+
class MissingResponseMessageError < ValidationError; end
|
13
|
+
|
14
|
+
class DeclinedError < StandardError; end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
module Yp
|
2
|
+
class Response
|
3
|
+
class ErrorLogger
|
4
|
+
extend Forwardable
|
5
|
+
|
6
|
+
def_delegators :@logger, :fatal, :error
|
7
|
+
|
8
|
+
def initialize(logger)
|
9
|
+
@logger = logger
|
10
|
+
end
|
11
|
+
|
12
|
+
def log
|
13
|
+
begin
|
14
|
+
yield
|
15
|
+
rescue InvalidSignatureError => e
|
16
|
+
log_fatal 'An invalid signature was received', e
|
17
|
+
rescue MissingSignatureError => e
|
18
|
+
log_not_found 'Signature', e
|
19
|
+
rescue MissingResponseCodeError => e
|
20
|
+
log_not_found 'Response Code', e
|
21
|
+
rescue MissingResponseMessageError => e
|
22
|
+
log_not_found 'Response Message', e
|
23
|
+
rescue DeclinedError => e
|
24
|
+
log_error 'Transaction was declined by the acquirer', e
|
25
|
+
rescue MissingFieldError => e
|
26
|
+
log_error 'Gateway responded with missing field', e
|
27
|
+
rescue InvalidFieldError => e
|
28
|
+
log_error 'Gateway responded with invalid field', e
|
29
|
+
rescue GatewayError => e
|
30
|
+
log_error 'Gateway responded with error', e
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
private
|
35
|
+
|
36
|
+
def log_not_found(thing, e)
|
37
|
+
log_fatal("#{thing} was not found in the response", e)
|
38
|
+
end
|
39
|
+
|
40
|
+
def log_fatal(str, e)
|
41
|
+
fatal(str)
|
42
|
+
raise e
|
43
|
+
end
|
44
|
+
|
45
|
+
def log_error(str, e)
|
46
|
+
error("#{str} (#{e})")
|
47
|
+
raise e
|
48
|
+
end
|
49
|
+
|
50
|
+
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
@@ -0,0 +1,68 @@
|
|
1
|
+
require 'yaml'
|
2
|
+
|
3
|
+
module Yp
|
4
|
+
class Response
|
5
|
+
class GatewayError < StandardError
|
6
|
+
|
7
|
+
def self.from_response_code(code, message)
|
8
|
+
Factory.new(code, message).error
|
9
|
+
end
|
10
|
+
|
11
|
+
class Factory
|
12
|
+
|
13
|
+
class << self
|
14
|
+
def error_map
|
15
|
+
@error_map ||= load_error_map
|
16
|
+
end
|
17
|
+
|
18
|
+
private
|
19
|
+
|
20
|
+
def load_error_map
|
21
|
+
YAML.load(File.read('data/gateway_responses.yml'))
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def initialize(code, message)
|
26
|
+
@code = code
|
27
|
+
@message = message
|
28
|
+
end
|
29
|
+
|
30
|
+
def error
|
31
|
+
if is_missing_field?
|
32
|
+
MissingFieldError.new(missing_field)
|
33
|
+
elsif is_invalid_field?
|
34
|
+
InvalidFieldError.new(invalid_field)
|
35
|
+
else
|
36
|
+
GatewayError.new(@message)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
private
|
41
|
+
|
42
|
+
def is_missing_field?
|
43
|
+
!missing_field.nil?
|
44
|
+
end
|
45
|
+
|
46
|
+
def missing_field
|
47
|
+
@missing_field ||= mapped_error(:missing_field)
|
48
|
+
end
|
49
|
+
|
50
|
+
def is_invalid_field?
|
51
|
+
!invalid_field.nil?
|
52
|
+
end
|
53
|
+
|
54
|
+
def invalid_field
|
55
|
+
@invalid_field ||= mapped_error(:invalid_field)
|
56
|
+
end
|
57
|
+
|
58
|
+
def mapped_error(sym)
|
59
|
+
Factory.error_map[sym.to_s][@code.to_i]
|
60
|
+
end
|
61
|
+
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
class MissingFieldError < GatewayError; end
|
66
|
+
class InvalidFieldError < GatewayError; end
|
67
|
+
end
|
68
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
module Yp
|
2
|
+
class Response
|
3
|
+
class Parser
|
4
|
+
|
5
|
+
def initialize(params)
|
6
|
+
@params = params
|
7
|
+
end
|
8
|
+
|
9
|
+
def parse
|
10
|
+
ruby_hash_from_response(parse_string)
|
11
|
+
end
|
12
|
+
|
13
|
+
private
|
14
|
+
|
15
|
+
def parse_string
|
16
|
+
CGI::parse(@params)
|
17
|
+
end
|
18
|
+
|
19
|
+
def ruby_hash_from_response(hash)
|
20
|
+
hash.reduce({}) do |memo, (key, value)|
|
21
|
+
memo.merge({key.to_sym => value.first})
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
require_relative 'validator/signing_key'
|
2
|
+
require_relative 'validator/gateway'
|
3
|
+
require_relative 'validator/acquirer'
|
4
|
+
|
5
|
+
module Yp
|
6
|
+
class Response
|
7
|
+
class Validator
|
8
|
+
def initialize(params, signature)
|
9
|
+
@params = params
|
10
|
+
@signature = signature
|
11
|
+
end
|
12
|
+
|
13
|
+
def validate!
|
14
|
+
SigningKey.new(@params, @signature).validate!
|
15
|
+
Gateway.new(@params).validate!
|
16
|
+
Acquirer.new(@params).validate!
|
17
|
+
end
|
18
|
+
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
module Yp
|
2
|
+
class Response
|
3
|
+
class Validator
|
4
|
+
class Acquirer
|
5
|
+
|
6
|
+
def initialize(params)
|
7
|
+
@params = params
|
8
|
+
end
|
9
|
+
|
10
|
+
def validate!
|
11
|
+
!declined? || (raise DeclinedError)
|
12
|
+
end
|
13
|
+
|
14
|
+
private
|
15
|
+
|
16
|
+
def declined?
|
17
|
+
response_code == 4 || response_code == 5
|
18
|
+
end
|
19
|
+
|
20
|
+
def response_code
|
21
|
+
@response_code ||= @params[:responseCode].to_i
|
22
|
+
end
|
23
|
+
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
require_relative '../gateway_error'
|
2
|
+
|
3
|
+
module Yp
|
4
|
+
class Response
|
5
|
+
class Validator
|
6
|
+
class Gateway
|
7
|
+
|
8
|
+
def initialize(params)
|
9
|
+
@params = params
|
10
|
+
end
|
11
|
+
|
12
|
+
def validate!
|
13
|
+
is_valid_response_code? || (raise error_from_response)
|
14
|
+
end
|
15
|
+
|
16
|
+
private
|
17
|
+
|
18
|
+
def is_valid_response_code?
|
19
|
+
response_code.to_i <= 5
|
20
|
+
end
|
21
|
+
|
22
|
+
def error_from_response
|
23
|
+
GatewayError.from_response_code(response_code, response_message)
|
24
|
+
end
|
25
|
+
|
26
|
+
def response_code
|
27
|
+
@response_code ||= find_response_code
|
28
|
+
end
|
29
|
+
|
30
|
+
def find_response_code
|
31
|
+
@params[:responseCode] || (raise MissingResponseCodeError)
|
32
|
+
end
|
33
|
+
|
34
|
+
def response_message
|
35
|
+
@params[:responseMessage] || (raise MissingResponseMessageError)
|
36
|
+
end
|
37
|
+
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
require 'signing_hash_creator'
|
2
|
+
|
3
|
+
module Yp
|
4
|
+
class Response
|
5
|
+
class Validator
|
6
|
+
class SigningKey
|
7
|
+
|
8
|
+
def initialize(params, signature)
|
9
|
+
@params = params
|
10
|
+
@signature = signature
|
11
|
+
end
|
12
|
+
|
13
|
+
def validate!
|
14
|
+
has_valid_signing_key? || (raise InvalidSignatureError)
|
15
|
+
end
|
16
|
+
|
17
|
+
private
|
18
|
+
|
19
|
+
def has_valid_signing_key?
|
20
|
+
their_signing_key == our_signing_key
|
21
|
+
end
|
22
|
+
|
23
|
+
def their_signing_key
|
24
|
+
@params[:signature] || (raise MissingSignatureError)
|
25
|
+
end
|
26
|
+
|
27
|
+
def our_signing_key
|
28
|
+
SigningHashCreator.new(signing_key_params, @signature).create
|
29
|
+
end
|
30
|
+
|
31
|
+
def signing_key_params
|
32
|
+
@params.reject { |k, _| k == :signature }
|
33
|
+
end
|
34
|
+
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
module Yp
|
2
|
+
class SigningHashCreator
|
3
|
+
def initialize(params, signature_key)
|
4
|
+
@params = params
|
5
|
+
@signature_key = signature_key
|
6
|
+
end
|
7
|
+
|
8
|
+
def create
|
9
|
+
self.class.digest(self.class.serialize_params(@params) + @signature_key)
|
10
|
+
end
|
11
|
+
|
12
|
+
class << self
|
13
|
+
|
14
|
+
def digest(str_params)
|
15
|
+
Digest::SHA512.hexdigest str_params
|
16
|
+
end
|
17
|
+
|
18
|
+
def serialize_params(params)
|
19
|
+
params.map { |key, value| uri_query_param(key, value) }.sort.join('&')
|
20
|
+
end
|
21
|
+
|
22
|
+
def uri_query_param(key, value)
|
23
|
+
encode_url_component(key) + '=' + encode_url_component(value)
|
24
|
+
end
|
25
|
+
|
26
|
+
def encode_url_component(key)
|
27
|
+
ERB::Util::url_encode(key).gsub(/%20/, '+')
|
28
|
+
end
|
29
|
+
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
data/lib/transaction_logger.rb
CHANGED
@@ -12,10 +12,22 @@ module Yp
|
|
12
12
|
info 'Response received', params
|
13
13
|
end
|
14
14
|
|
15
|
+
def info(str, params=nil)
|
16
|
+
Yp.logger.info(format(str, params))
|
17
|
+
end
|
18
|
+
|
19
|
+
def error(str)
|
20
|
+
Yp.logger.error(format_message(str))
|
21
|
+
end
|
22
|
+
|
23
|
+
def fatal(str)
|
24
|
+
Yp.logger.fatal(format_message(str))
|
25
|
+
end
|
26
|
+
|
15
27
|
private
|
16
28
|
|
17
|
-
def
|
18
|
-
|
29
|
+
def format(str, params)
|
30
|
+
"#{format_message(str)} #{format_params(params)}"
|
19
31
|
end
|
20
32
|
|
21
33
|
def format_message(str)
|
@@ -23,7 +35,7 @@ module Yp
|
|
23
35
|
end
|
24
36
|
|
25
37
|
def format_params(params)
|
26
|
-
" with params #{filter_card_params(params).to_s}"
|
38
|
+
" with params #{filter_card_params(params).to_s}" unless params.nil?
|
27
39
|
end
|
28
40
|
|
29
41
|
def filter_card_params(hash)
|
data/lib/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: yp-ruby
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.4a
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Andrew Hall
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2017-
|
11
|
+
date: 2017-03-04 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rest-client
|
@@ -133,12 +133,23 @@ files:
|
|
133
133
|
- Rakefile
|
134
134
|
- bin/console
|
135
135
|
- bin/setup
|
136
|
+
- data/gateway_responses.yml
|
136
137
|
- exe/yp-ruby
|
137
138
|
- lib/base.rb
|
138
139
|
- lib/factory.rb
|
139
140
|
- lib/nil_logger.rb
|
140
141
|
- lib/preauth.rb
|
142
|
+
- lib/response.rb
|
143
|
+
- lib/response/error.rb
|
144
|
+
- lib/response/error_logger.rb
|
145
|
+
- lib/response/gateway_error.rb
|
146
|
+
- lib/response/parser.rb
|
147
|
+
- lib/response/validator.rb
|
148
|
+
- lib/response/validator/acquirer.rb
|
149
|
+
- lib/response/validator/gateway.rb
|
150
|
+
- lib/response/validator/signing_key.rb
|
141
151
|
- lib/sale.rb
|
152
|
+
- lib/signing_hash_creator.rb
|
142
153
|
- lib/transaction_logger.rb
|
143
154
|
- lib/verify.rb
|
144
155
|
- lib/version.rb
|
@@ -160,9 +171,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
160
171
|
version: '0'
|
161
172
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
162
173
|
requirements:
|
163
|
-
- - "
|
174
|
+
- - ">"
|
164
175
|
- !ruby/object:Gem::Version
|
165
|
-
version:
|
176
|
+
version: 1.3.1
|
166
177
|
requirements: []
|
167
178
|
rubyforge_project:
|
168
179
|
rubygems_version: 2.5.2
|