remit 0.0.5 → 0.0.6
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.
- data/lib/amazon/fps/ca-bundle.crt +7989 -0
- data/lib/amazon/fps/signatureutils.rb +143 -0
- data/lib/amazon/fps/signatureutilsforoutbound.rb +180 -0
- data/lib/remit.rb +9 -8
- data/lib/remit/common.rb +14 -2
- data/lib/remit/get_pipeline.rb +41 -23
- data/lib/remit/ipn_request.rb +7 -13
- data/lib/remit/pipeline_response.rb +12 -11
- data/spec/integrations/get_account_activity_spec.rb +2 -2
- data/spec/integrations/get_tokens_spec.rb +0 -1
- data/spec/integrations/ipn_request_spec.rb +32 -0
- metadata +40 -10
- data/spec/units/ipn_request_spec.rb +0 -32
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
###############################################################################
|
|
2
|
+
# Copyright 2008-2010 Amazon Technologies, Inc
|
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
+
#
|
|
5
|
+
# You may not use this file except in compliance with the License.
|
|
6
|
+
# You may obtain a copy of the License at: http://aws.amazon.com/apache2.0
|
|
7
|
+
# This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
|
8
|
+
# CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
|
9
|
+
# specific language governing permissions and limitations under the License.
|
|
10
|
+
##############################################################################
|
|
11
|
+
require 'base64'
|
|
12
|
+
require 'cgi'
|
|
13
|
+
require 'openssl'
|
|
14
|
+
|
|
15
|
+
module Amazon
|
|
16
|
+
module FPS
|
|
17
|
+
|
|
18
|
+
#
|
|
19
|
+
# Copyright:: Copyright (c) 2009 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
|
20
|
+
#
|
|
21
|
+
# RFC 2104-compliant HMAC signature for request parameters
|
|
22
|
+
# Implements AWS Signature, as per following spec:
|
|
23
|
+
#
|
|
24
|
+
# If Signature Version is 1, it performs the following:
|
|
25
|
+
#
|
|
26
|
+
# Sorts all parameters (including SignatureVersion and excluding Signature,
|
|
27
|
+
# the value of which is being created), ignoring case.
|
|
28
|
+
#
|
|
29
|
+
# Iterate over the sorted list and append the parameter name (in original case)
|
|
30
|
+
# and then its value. It will not URL-encode the parameter values before
|
|
31
|
+
# constructing this string. There are no separators.
|
|
32
|
+
#
|
|
33
|
+
# If Signature Version is 2, string to sign is based on following:
|
|
34
|
+
#
|
|
35
|
+
# 1. The HTTP Request Method followed by an ASCII newline (%0A)
|
|
36
|
+
# 2. The HTTP Host header in the form of lowercase host, followed by an ASCII newline.
|
|
37
|
+
# 3. The URL encoded HTTP absolute path component of the URI
|
|
38
|
+
# (up to but not including the query string parameters);
|
|
39
|
+
# if this is empty use a forward '/'. This parameter is followed by an ASCII newline.
|
|
40
|
+
# 4. The concatenation of all query string components (names and values)
|
|
41
|
+
# as UTF-8 characters which are URL encoded as per RFC 3986
|
|
42
|
+
# (hex characters MUST be uppercase), sorted using lexicographic byte ordering.
|
|
43
|
+
# Parameter names are separated from their values by the '=' character
|
|
44
|
+
# (ASCII character 61), even if the value is empty.
|
|
45
|
+
# Pairs of parameter and values are separated by the '&' character (ASCII code 38).
|
|
46
|
+
#
|
|
47
|
+
class SignatureUtils
|
|
48
|
+
|
|
49
|
+
SIGNATURE_KEYNAME = "Signature"
|
|
50
|
+
SIGNATURE_METHOD_KEYNAME = "SignatureMethod"
|
|
51
|
+
SIGNATURE_VERSION_KEYNAME = "SignatureVersion"
|
|
52
|
+
|
|
53
|
+
HMAC_SHA256_ALGORITHM = "HmacSHA256"
|
|
54
|
+
HMAC_SHA1_ALGORITHM = "HmacSHA1"
|
|
55
|
+
|
|
56
|
+
def self.sign_parameters(args)
|
|
57
|
+
signature_version = args[:parameters][SIGNATURE_VERSION_KEYNAME]
|
|
58
|
+
string_to_sign = "";
|
|
59
|
+
algorithm = 'sha1';
|
|
60
|
+
if (signature_version == '1') then
|
|
61
|
+
string_to_sign = calculate_string_to_sign_v1(args)
|
|
62
|
+
elsif (signature_version == '2') then
|
|
63
|
+
algorithm = get_algorithm(args[:parameters][SIGNATURE_METHOD_KEYNAME])
|
|
64
|
+
string_to_sign = calculate_string_to_sign_v2(args)
|
|
65
|
+
else
|
|
66
|
+
raise "Invalid Signature Version specified"
|
|
67
|
+
end
|
|
68
|
+
return compute_signature(string_to_sign, args[:aws_secret_key], algorithm)
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
# Convert a string into URL encoded form.
|
|
72
|
+
def self.urlencode(plaintext)
|
|
73
|
+
CGI.escape(plaintext.to_s).gsub("+", "%20").gsub("%7E", "~")
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
private # All the methods below are private
|
|
77
|
+
|
|
78
|
+
def self.calculate_string_to_sign_v1(args)
|
|
79
|
+
parameters = args[:parameters]
|
|
80
|
+
|
|
81
|
+
# exclude any existing Signature parameter from the canonical string
|
|
82
|
+
sorted = (parameters.reject { |k, v| k == SIGNATURE_KEYNAME }).sort { |a,b| a[0].downcase <=> b[0].downcase }
|
|
83
|
+
|
|
84
|
+
canonical = ''
|
|
85
|
+
sorted.each do |v|
|
|
86
|
+
canonical << v[0]
|
|
87
|
+
canonical << v[1] unless(v[1].nil?)
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
return canonical
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
def self.calculate_string_to_sign_v2(args)
|
|
94
|
+
parameters = args[:parameters]
|
|
95
|
+
|
|
96
|
+
uri = args[:uri]
|
|
97
|
+
uri = "/" if uri.nil? or uri.empty?
|
|
98
|
+
uri = urlencode(uri).gsub("%2F", "/")
|
|
99
|
+
|
|
100
|
+
verb = args[:verb]
|
|
101
|
+
host = args[:host].downcase
|
|
102
|
+
|
|
103
|
+
# exclude any existing Signature parameter from the canonical string
|
|
104
|
+
sorted = (parameters.reject { |k, v| k == SIGNATURE_KEYNAME })
|
|
105
|
+
|
|
106
|
+
# sort the parameters
|
|
107
|
+
sorted = sorted.sort{ |a, b| a.to_s <=> b.to_s }
|
|
108
|
+
|
|
109
|
+
canonical = "#{verb}\n#{host}\n#{uri}\n"
|
|
110
|
+
isFirst = true
|
|
111
|
+
|
|
112
|
+
sorted.each { |v|
|
|
113
|
+
if(isFirst) then
|
|
114
|
+
isFirst = false
|
|
115
|
+
else
|
|
116
|
+
canonical << '&'
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
canonical << urlencode(v[0])
|
|
120
|
+
unless(v[1].nil?) then
|
|
121
|
+
canonical << '='
|
|
122
|
+
canonical << urlencode(v[1])
|
|
123
|
+
end
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
return canonical
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
def self.get_algorithm(signature_method)
|
|
130
|
+
return 'sha256' if (signature_method == HMAC_SHA256_ALGORITHM);
|
|
131
|
+
return 'sha1'
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
def self.compute_signature(canonical, aws_secret_key, algorithm = 'sha1')
|
|
135
|
+
digest = OpenSSL::Digest::Digest.new(algorithm)
|
|
136
|
+
return Base64.encode64(OpenSSL::HMAC.digest(digest, aws_secret_key, canonical)).chomp
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
end
|
|
140
|
+
|
|
141
|
+
end
|
|
142
|
+
end
|
|
143
|
+
|
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
###############################################################################
|
|
2
|
+
# Copyright 2008-2010 Amazon Technologies, Inc
|
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
+
#
|
|
5
|
+
# You may not use this file except in compliance with the License.
|
|
6
|
+
# You may obtain a copy of the License at: http://aws.amazon.com/apache2.0
|
|
7
|
+
# This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
|
8
|
+
# CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
|
9
|
+
# specific language governing permissions and limitations under the License.
|
|
10
|
+
##############################################################################
|
|
11
|
+
|
|
12
|
+
require 'base64'
|
|
13
|
+
require 'cgi'
|
|
14
|
+
require 'openssl'
|
|
15
|
+
require 'net/http'
|
|
16
|
+
require 'net/https'
|
|
17
|
+
require 'rexml/document'
|
|
18
|
+
|
|
19
|
+
module Amazon
|
|
20
|
+
module FPS
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
class SignatureUtilsForOutbound
|
|
24
|
+
|
|
25
|
+
SIGNATURE_KEYNAME = "signature"
|
|
26
|
+
SIGNATURE_METHOD_KEYNAME = "signatureMethod"
|
|
27
|
+
SIGNATURE_VERSION_KEYNAME = "signatureVersion"
|
|
28
|
+
CERTIFICATE_URL_KEYNAME = "certificateUrl"
|
|
29
|
+
CERTIFICATE_URL_ROOT = "https://fps.amazonaws.com/"
|
|
30
|
+
CERTIFICATE_URL_ROOT_SANDBOX = "https://fps.sandbox.amazonaws.com/"
|
|
31
|
+
|
|
32
|
+
FPS_PROD_ENDPOINT = CERTIFICATE_URL_ROOT
|
|
33
|
+
FPS_SANDBOX_ENDPOINT = CERTIFICATE_URL_ROOT_SANDBOX
|
|
34
|
+
ACTION_PARAM = "?Action=VerifySignature"
|
|
35
|
+
END_POINT_PARAM = "&UrlEndPoint="
|
|
36
|
+
HTTP_PARAMS_PARAM = "&HttpParameters="
|
|
37
|
+
VERSION_PARAM_VALUE = "&Version=2008-09-17"
|
|
38
|
+
|
|
39
|
+
USER_AGENT_STRING = "SigV2_MigrationSampleCode_Ruby-2010-09-13"
|
|
40
|
+
|
|
41
|
+
SIGNATURE_VERSION_1 = "1"
|
|
42
|
+
SIGNATURE_VERSION_2 = "2"
|
|
43
|
+
RSA_SHA1_ALGORITHM = "RSA-SHA1"
|
|
44
|
+
|
|
45
|
+
def initialize(aws_access_key, aws_secret_key)
|
|
46
|
+
@aws_secret_key = aws_secret_key
|
|
47
|
+
@aws_access_key = aws_access_key
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def validate_request(args)
|
|
51
|
+
parameters = args[:parameters]
|
|
52
|
+
return validate_signature_v2(args) if (parameters[SIGNATURE_VERSION_KEYNAME] == SIGNATURE_VERSION_2)
|
|
53
|
+
return validate_signature_v1(args)
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
def validate_signature_v1(args)
|
|
57
|
+
parameters = args[:parameters]
|
|
58
|
+
signature = "";
|
|
59
|
+
if(parameters[SIGNATURE_KEYNAME] != nil) then
|
|
60
|
+
signature = parameters[SIGNATURE_KEYNAME];
|
|
61
|
+
else
|
|
62
|
+
raise "Signature is missing from parameters"
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
canonical = SignatureUtilsForOutbound::calculate_string_to_sign_v1(args)
|
|
66
|
+
digest = OpenSSL::Digest::Digest.new('sha1')
|
|
67
|
+
return signature == Base64.encode64(OpenSSL::HMAC.digest(digest, @aws_secret_key, canonical)).chomp
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
def validate_signature_v2(args)
|
|
71
|
+
[:parameters,
|
|
72
|
+
:http_method,
|
|
73
|
+
:url_end_point].each do |arg|
|
|
74
|
+
raise "#{arg.inspect} is missing from the arguments." unless args[arg]
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
url_end_point = args[:url_end_point]
|
|
78
|
+
|
|
79
|
+
parameters = args[:parameters]
|
|
80
|
+
raise ":parameters must be enumerable" unless args[:parameters].kind_of? Enumerable
|
|
81
|
+
|
|
82
|
+
signature = parameters[SIGNATURE_KEYNAME];
|
|
83
|
+
raise "'signature' is missing from the parameters." if (signature.nil? or signature.empty?)
|
|
84
|
+
|
|
85
|
+
signature_version = parameters[SIGNATURE_VERSION_KEYNAME];
|
|
86
|
+
raise "'signatureVersion' is missing from the parameters." if (signature_version.nil? or signature_version.empty?)
|
|
87
|
+
raise "'signatureVersion' present in parameters is invalid. Valid values are: 2" if (signature_version != SIGNATURE_VERSION_2)
|
|
88
|
+
|
|
89
|
+
signature_method = parameters[SIGNATURE_METHOD_KEYNAME]
|
|
90
|
+
raise "'signatureMethod' is missing from the parameters." if (signature_method.nil? or signature_method.empty?)
|
|
91
|
+
signature_algorithm = SignatureUtilsForOutbound::get_algorithm(signature_method)
|
|
92
|
+
raise "'signatureMethod' present in parameters is invalid. Valid values are: RSA-SHA1" if (signature_algorithm.nil?)
|
|
93
|
+
|
|
94
|
+
certificate_url = parameters[CERTIFICATE_URL_KEYNAME]
|
|
95
|
+
raise "'certificate_url' is missing from the parameters." if (certificate_url.nil? or certificate_url.empty?)
|
|
96
|
+
|
|
97
|
+
# Construct VerifySignatureAPI request
|
|
98
|
+
if(SignatureUtilsForOutbound::starts_with(certificate_url, FPS_SANDBOX_ENDPOINT) == true) then
|
|
99
|
+
verify_signature_request = FPS_SANDBOX_ENDPOINT
|
|
100
|
+
elsif(SignatureUtilsForOutbound::starts_with(certificate_url, FPS_PROD_ENDPOINT) == true) then
|
|
101
|
+
verify_signature_request = FPS_PROD_ENDPOINT
|
|
102
|
+
else
|
|
103
|
+
raise "'certificateUrl' received is not valid. Valid certificate urls start with " <<
|
|
104
|
+
CERTIFICATE_URL_ROOT << " or " << CERTIFICATE_URL_ROOT_SANDBOX << "."
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
verify_signature_request = verify_signature_request + ACTION_PARAM +
|
|
108
|
+
END_POINT_PARAM +
|
|
109
|
+
SignatureUtilsForOutbound::urlencode(url_end_point) +
|
|
110
|
+
VERSION_PARAM_VALUE +
|
|
111
|
+
HTTP_PARAMS_PARAM +
|
|
112
|
+
SignatureUtilsForOutbound::urlencode(SignatureUtilsForOutbound::get_http_params(parameters))
|
|
113
|
+
|
|
114
|
+
verify_signature_response = SignatureUtilsForOutbound::get_http_data(verify_signature_request)
|
|
115
|
+
|
|
116
|
+
# parse the response
|
|
117
|
+
document = REXML::Document.new(verify_signature_response)
|
|
118
|
+
|
|
119
|
+
status_el = document.elements['VerifySignatureResponse/VerifySignatureResult/VerificationStatus']
|
|
120
|
+
return (!status_el.nil? && status_el.text == "Success")
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
def self.calculate_string_to_sign_v1(args)
|
|
124
|
+
parameters = args[:parameters]
|
|
125
|
+
|
|
126
|
+
# exclude any existing Signature parameter from the canonical string
|
|
127
|
+
sorted = (parameters.reject { |k, v| ((k == SIGNATURE_KEYNAME)) }).sort { |a,b| a[0].downcase <=> b[0].downcase }
|
|
128
|
+
|
|
129
|
+
canonical = ''
|
|
130
|
+
sorted.each do |v|
|
|
131
|
+
canonical << v[0]
|
|
132
|
+
canonical << v[1] unless(v[1].nil?)
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
return canonical
|
|
136
|
+
end
|
|
137
|
+
|
|
138
|
+
def self.get_algorithm(signature_method)
|
|
139
|
+
return OpenSSL::Digest::SHA1.new if (signature_method == RSA_SHA1_ALGORITHM)
|
|
140
|
+
return nil
|
|
141
|
+
end
|
|
142
|
+
|
|
143
|
+
# Convert a string into URL encoded form.
|
|
144
|
+
def self.urlencode(plaintext)
|
|
145
|
+
CGI.escape(plaintext.to_s).gsub("+", "%20").gsub("%7E", "~")
|
|
146
|
+
end
|
|
147
|
+
|
|
148
|
+
def self.get_http_data(url)
|
|
149
|
+
#2. fetch certificate if not found in cache
|
|
150
|
+
uri = URI.parse(url)
|
|
151
|
+
http_session = Net::HTTP.new(uri.host, uri.port)
|
|
152
|
+
http_session.use_ssl = true
|
|
153
|
+
http_session.ca_file = File.dirname(__FILE__) + '/ca-bundle.crt'
|
|
154
|
+
http_session.verify_mode = OpenSSL::SSL::VERIFY_PEER
|
|
155
|
+
http_session.verify_depth = 5
|
|
156
|
+
|
|
157
|
+
res = http_session.start {|http_session|
|
|
158
|
+
req = Net::HTTP::Get.new(url, {"User-Agent" => USER_AGENT_STRING})
|
|
159
|
+
http_session.request(req)
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
return res.body
|
|
163
|
+
end
|
|
164
|
+
|
|
165
|
+
def self.starts_with(string, prefix)
|
|
166
|
+
prefix = prefix.to_s
|
|
167
|
+
string[0, prefix.length] == prefix
|
|
168
|
+
end
|
|
169
|
+
|
|
170
|
+
def self.get_http_params(params)
|
|
171
|
+
params.map do |(k, v)|
|
|
172
|
+
urlencode(k) + "=" + urlencode(v)
|
|
173
|
+
end.join("&")
|
|
174
|
+
end
|
|
175
|
+
|
|
176
|
+
end
|
|
177
|
+
|
|
178
|
+
end
|
|
179
|
+
end
|
|
180
|
+
|
data/lib/remit.rb
CHANGED
|
@@ -85,7 +85,7 @@ module Remit
|
|
|
85
85
|
PIPELINE_URL = 'https://authorize.payments.amazon.com/cobranded-ui/actions/start'.freeze
|
|
86
86
|
PIPELINE_SANDBOX_URL = 'https://authorize.payments-sandbox.amazon.com/cobranded-ui/actions/start'.freeze
|
|
87
87
|
API_VERSION = Date.new(2007, 1, 8).to_s.freeze
|
|
88
|
-
SIGNATURE_VERSION =
|
|
88
|
+
SIGNATURE_VERSION = 2.freeze
|
|
89
89
|
|
|
90
90
|
attr_reader :access_key
|
|
91
91
|
attr_reader :secret_key
|
|
@@ -108,6 +108,7 @@ module Remit
|
|
|
108
108
|
new_query({
|
|
109
109
|
:AWSAccessKeyId => @access_key,
|
|
110
110
|
:SignatureVersion => SIGNATURE_VERSION,
|
|
111
|
+
Amazon::FPS::SignatureUtils::SIGNATURE_METHOD_KEYNAME => Amazon::FPS::SignatureUtils::HMAC_SHA256_ALGORITHM,
|
|
111
112
|
:Version => API_VERSION,
|
|
112
113
|
:Timestamp => Time.now.utc.strftime('%Y-%m-%dT%H:%M:%SZ')
|
|
113
114
|
})
|
|
@@ -122,13 +123,13 @@ module Remit
|
|
|
122
123
|
private :query
|
|
123
124
|
|
|
124
125
|
def sign(values)
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
126
|
+
signature = Amazon::FPS::SignatureUtils.sign_parameters({
|
|
127
|
+
:parameters => values,
|
|
128
|
+
:aws_secret_key => @secret_key,
|
|
129
|
+
:host => @endpoint.host,
|
|
130
|
+
:verb => "GET",
|
|
131
|
+
:uri => @endpoint.path })
|
|
132
|
+
return signature
|
|
132
133
|
end
|
|
133
134
|
private :sign
|
|
134
135
|
end
|
data/lib/remit/common.rb
CHANGED
|
@@ -5,6 +5,9 @@ require 'uri'
|
|
|
5
5
|
require 'rubygems'
|
|
6
6
|
require 'relax'
|
|
7
7
|
|
|
8
|
+
require File.dirname(__FILE__) + '/../amazon/fps/signatureutils'
|
|
9
|
+
require File.dirname(__FILE__) + '/../amazon/fps/signatureutilsforoutbound'
|
|
10
|
+
|
|
8
11
|
module Remit
|
|
9
12
|
class Request < Relax::Request
|
|
10
13
|
def self.action(name)
|
|
@@ -63,8 +66,17 @@ module Remit
|
|
|
63
66
|
end
|
|
64
67
|
|
|
65
68
|
def sign
|
|
66
|
-
|
|
67
|
-
|
|
69
|
+
self[Amazon::FPS::SignatureUtils::SIGNATURE_VERSION_KEYNAME] = Remit::API::SIGNATURE_VERSION
|
|
70
|
+
self[Amazon::FPS::SignatureUtils::SIGNATURE_METHOD_KEYNAME] = Amazon::FPS::SignatureUtils::HMAC_SHA256_ALGORITHM
|
|
71
|
+
|
|
72
|
+
signature = Amazon::FPS::SignatureUtils.sign_parameters({
|
|
73
|
+
:parameters => self,
|
|
74
|
+
:aws_secret_key => @secret_key,
|
|
75
|
+
:host => @uri.host,
|
|
76
|
+
:verb => "GET",
|
|
77
|
+
:uri => @uri.path })
|
|
78
|
+
|
|
79
|
+
store(Amazon::FPS::SignatureUtilsForOutbound::SIGNATURE_KEYNAME.to_sym, signature)
|
|
68
80
|
end
|
|
69
81
|
|
|
70
82
|
def to_s(signed=true)
|
data/lib/remit/get_pipeline.rb
CHANGED
|
@@ -7,35 +7,36 @@ module Remit
|
|
|
7
7
|
class Pipeline
|
|
8
8
|
@parameters = []
|
|
9
9
|
attr_reader :parameters
|
|
10
|
-
|
|
10
|
+
|
|
11
11
|
class << self
|
|
12
12
|
# Create the parameters hash for the subclass.
|
|
13
13
|
def inherited(subclass) #:nodoc:
|
|
14
14
|
subclass.instance_variable_set('@parameters', [])
|
|
15
15
|
end
|
|
16
|
-
|
|
16
|
+
|
|
17
17
|
def parameter(name)
|
|
18
18
|
attr_accessor name
|
|
19
19
|
@parameters << name
|
|
20
20
|
end
|
|
21
|
-
|
|
21
|
+
|
|
22
22
|
def convert_key(key)
|
|
23
23
|
key.to_s.gsub(/_(.)/) { $1.upcase }.to_sym
|
|
24
24
|
end
|
|
25
|
-
|
|
25
|
+
|
|
26
26
|
# Returns a hash of all of the parameters for this request, including
|
|
27
27
|
# those that are inherited.
|
|
28
28
|
def parameters #:nodoc:
|
|
29
29
|
(superclass.respond_to?(:parameters) ? superclass.parameters : []) + @parameters
|
|
30
30
|
end
|
|
31
31
|
end
|
|
32
|
-
|
|
32
|
+
|
|
33
33
|
attr_reader :api
|
|
34
|
-
|
|
34
|
+
|
|
35
35
|
parameter :pipeline_name
|
|
36
36
|
parameter :return_url
|
|
37
37
|
parameter :caller_key
|
|
38
38
|
parameter :version
|
|
39
|
+
parameter :signature_version
|
|
39
40
|
parameter :address_name
|
|
40
41
|
parameter :address_line_1
|
|
41
42
|
parameter :address_line_2
|
|
@@ -47,7 +48,7 @@ module Remit
|
|
|
47
48
|
|
|
48
49
|
def initialize(api, options)
|
|
49
50
|
@api = api
|
|
50
|
-
|
|
51
|
+
|
|
51
52
|
options.each do |k,v|
|
|
52
53
|
self.send("#{k}=", v)
|
|
53
54
|
end
|
|
@@ -55,14 +56,14 @@ module Remit
|
|
|
55
56
|
|
|
56
57
|
def url
|
|
57
58
|
uri = URI.parse(@api.pipeline_url)
|
|
58
|
-
|
|
59
|
+
|
|
59
60
|
query = {}
|
|
60
61
|
self.class.parameters.each do |p|
|
|
61
62
|
val = self.send(p)
|
|
62
|
-
|
|
63
|
+
|
|
63
64
|
# Convert Time values to seconds from Epoch
|
|
64
65
|
val = val.to_i if val.is_a?(Time)
|
|
65
|
-
|
|
66
|
+
|
|
66
67
|
query[self.class.convert_key(p.to_s)] = val
|
|
67
68
|
end
|
|
68
69
|
|
|
@@ -73,19 +74,19 @@ module Remit
|
|
|
73
74
|
uri.to_s
|
|
74
75
|
end
|
|
75
76
|
end
|
|
76
|
-
|
|
77
|
+
|
|
77
78
|
class SingleUsePipeline < Pipeline
|
|
78
79
|
parameter :caller_reference
|
|
79
80
|
parameter :payment_reason
|
|
80
81
|
parameter :payment_method
|
|
81
82
|
parameter :transaction_amount
|
|
82
83
|
parameter :recipient_token
|
|
83
|
-
|
|
84
|
+
|
|
84
85
|
def pipeline_name
|
|
85
86
|
Remit::PipelineName::SINGLE_USE
|
|
86
87
|
end
|
|
87
88
|
end
|
|
88
|
-
|
|
89
|
+
|
|
89
90
|
class MultiUsePipeline < Pipeline
|
|
90
91
|
parameter :caller_reference
|
|
91
92
|
parameter :payment_reason
|
|
@@ -103,12 +104,12 @@ module Remit
|
|
|
103
104
|
parameter :usage_limit_period_2
|
|
104
105
|
parameter :usage_limit_value_2
|
|
105
106
|
parameter :is_recipient_cobranding
|
|
106
|
-
|
|
107
|
+
|
|
107
108
|
def pipeline_name
|
|
108
109
|
Remit::PipelineName::MULTI_USE
|
|
109
110
|
end
|
|
110
111
|
end
|
|
111
|
-
|
|
112
|
+
|
|
112
113
|
class RecipientPipeline < Pipeline
|
|
113
114
|
parameter :caller_reference
|
|
114
115
|
parameter :validity_start # Time or seconds from Epoch
|
|
@@ -118,7 +119,7 @@ module Remit
|
|
|
118
119
|
parameter :caller_reference_refund
|
|
119
120
|
parameter :max_variable_fee
|
|
120
121
|
parameter :max_fixed_fee
|
|
121
|
-
|
|
122
|
+
|
|
122
123
|
def pipeline_name
|
|
123
124
|
Remit::PipelineName::RECIPIENT
|
|
124
125
|
end
|
|
@@ -132,13 +133,13 @@ module Remit
|
|
|
132
133
|
parameter :validity_start # Time or seconds from Epoch
|
|
133
134
|
parameter :validity_expiry # Time or seconds from Epoch
|
|
134
135
|
parameter :payment_method
|
|
135
|
-
parameter :recurring_period
|
|
136
|
-
|
|
136
|
+
parameter :recurring_period
|
|
137
|
+
|
|
137
138
|
def pipeline_name
|
|
138
139
|
Remit::PipelineName::RECURRING
|
|
139
|
-
end
|
|
140
|
+
end
|
|
140
141
|
end
|
|
141
|
-
|
|
142
|
+
|
|
142
143
|
class PostpaidPipeline < Pipeline
|
|
143
144
|
parameter :caller_reference_sender
|
|
144
145
|
parameter :caller_reference_settlement
|
|
@@ -154,12 +155,25 @@ module Remit
|
|
|
154
155
|
parameter :usage_limit_type2
|
|
155
156
|
parameter :usage_limit_period2
|
|
156
157
|
parameter :usage_limit_value2
|
|
157
|
-
|
|
158
|
+
|
|
158
159
|
def pipeline_name
|
|
159
160
|
Remit::PipelineName::SETUP_POSTPAID
|
|
160
161
|
end
|
|
161
162
|
end
|
|
162
163
|
|
|
164
|
+
class PrepaidPipeline < Pipeline
|
|
165
|
+
parameter :caller_reference_sender
|
|
166
|
+
parameter :caller_reference_funding
|
|
167
|
+
parameter :payment_reason
|
|
168
|
+
parameter :payment_method
|
|
169
|
+
parameter :validity_start # Time or seconds from Epoch
|
|
170
|
+
parameter :validity_expiry # Time or seconds from Epoch
|
|
171
|
+
parameter :funding_amount
|
|
172
|
+
def pipeline_name
|
|
173
|
+
Remit::PipelineName::SETUP_PREPAID
|
|
174
|
+
end
|
|
175
|
+
end
|
|
176
|
+
|
|
163
177
|
def get_single_use_pipeline(options)
|
|
164
178
|
self.get_pipeline(SingleUsePipeline, options)
|
|
165
179
|
end
|
|
@@ -171,14 +185,18 @@ module Remit
|
|
|
171
185
|
def get_recipient_pipeline(options)
|
|
172
186
|
self.get_pipeline(RecipientPipeline, options)
|
|
173
187
|
end
|
|
174
|
-
|
|
188
|
+
|
|
175
189
|
def get_recurring_use_pipeline(options)
|
|
176
190
|
self.get_pipeline(RecurringUsePipeline, options)
|
|
177
191
|
end
|
|
178
|
-
|
|
192
|
+
|
|
179
193
|
def get_postpaid_pipeline(options)
|
|
180
194
|
self.get_pipeline(PostpaidPipeline, options)
|
|
181
195
|
end
|
|
196
|
+
|
|
197
|
+
def get_prepaid_pipeline(options)
|
|
198
|
+
self.get_pipeline(PrepaidPipeline, options)
|
|
199
|
+
end
|
|
182
200
|
|
|
183
201
|
def get_pipeline(pipeline_subclass, options)
|
|
184
202
|
pipeline = pipeline_subclass.new(self, {
|