amazon_pay_sdk_ruby 2.0.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.
@@ -0,0 +1,6 @@
1
+ require 'bundler/gem_tasks'
2
+ require 'rspec/core/rake_task'
3
+
4
+ RSpec::Core::RakeTask.new(:spec)
5
+
6
+ task default: :spec
@@ -0,0 +1,41 @@
1
+ lib = File.expand_path('lib', __dir__)
2
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
3
+ require 'amazon_pay/version'
4
+
5
+ Gem::Specification.new do |spec|
6
+ spec.name = 'amazon_pay_sdk_ruby'
7
+ spec.version = AmazonPay::VERSION
8
+ spec.authors = ['Everistus Olumese']
9
+ spec.email = ['everistusolumese@gmail.com']
10
+
11
+ spec.summary = 'AmazonPay Ruby SDK'
12
+ spec.description = 'AmazonPay Ruby SDK'
13
+ spec.homepage = 'https://github.com/bytenaija/amazon-pay-sdk-ruby'
14
+ spec.license = 'MIT'
15
+
16
+ # Prevent pushing this gem to RubyGems.org. To allow pushes either set the 'allowed_push_host'
17
+ # to allow pushing to a single host or delete this section to allow pushing to any host.
18
+ # if spec.respond_to?(:metadata)
19
+ # spec.metadata["allowed_push_host"] = "TODO: Set to 'http://mygemserver.com'"
20
+
21
+ # spec.metadata["homepage_uri"] = spec.homepage
22
+ # spec.metadata["source_code_uri"] = "TODO: Put your gem's public repo URL here."
23
+ # spec.metadata["changelog_uri"] = "TODO: Put your gem's CHANGELOG.md URL here."
24
+ # else
25
+ # raise "RubyGems 2.0 or newer is required to protect against " \
26
+ # "public gem pushes."
27
+ # end
28
+
29
+ # Specify which files should be added to the gem when it is released.
30
+ # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
31
+ spec.files = Dir.chdir(File.expand_path(__dir__)) do
32
+ `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
33
+ end
34
+ spec.bindir = 'exe'
35
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
36
+ spec.require_paths = ['lib']
37
+
38
+ spec.add_development_dependency 'bundler', '~> 1.17'
39
+ spec.add_development_dependency 'rake', '~> 10.0'
40
+ spec.add_development_dependency 'rspec', '~> 3.0'
41
+ end
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'bundler/setup'
4
+ require 'amazon_pay_sdk_ruby'
5
+
6
+ # You can add fixtures and/or initialization code here to make experimenting
7
+ # with your gem easier. You can also use a different console, if you like.
8
+
9
+ # (If you use this, don't forget to add pry to your Gemfile!)
10
+ # require "pry"
11
+ # Pry.start
12
+
13
+ require 'irb'
14
+ IRB.start(__FILE__)
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
7
+
8
+ # Do any other automated setup that you need to do here
@@ -0,0 +1,53 @@
1
+ module AmazonPay
2
+ # Class for Amazon Web Store
3
+ class AmazonInStoreClient < AmazonPayClient
4
+ def initialize(config_args)
5
+ super(config_args)
6
+ end
7
+
8
+ # API to initiate a purchase with a merchant
9
+ # - Initiates a purchase with a merchant.
10
+ # @see //TODO Update Live URL
11
+ # @param {Hash} payload - The payload for the request
12
+ # @param {Hash} [headers=nil] - The headers for the request
13
+ #
14
+ def merchant_scan(payload: nil, headers: nil)
15
+ api_call(options: {
16
+ method: 'POST',
17
+ url_fragment: 'in-store/merchantScan',
18
+ payload: payload,
19
+ headers: headers
20
+ })
21
+ end
22
+
23
+ # API to create Charge to the buyer
24
+ # - Creates a charge to the buyer with the requested amount.
25
+ # @see //TODO Update Live URL
26
+ # @param {Hash} payload - The payload for the request
27
+ # @param {Hash} [headers=nil] - The headers for the request
28
+ #
29
+ def charge(payload: nil, headers: nil)
30
+ api_call(options: {
31
+ method: 'POST',
32
+ url_fragment: 'in-store/charge',
33
+ payload: payload,
34
+ headers: headers
35
+ })
36
+ end
37
+
38
+ # API to create a Refund to the buyer
39
+ # - Refunds an amount that was previously charged to the buyer.
40
+ # @see //TODO Update Live URL
41
+ # @param {Hash} payload - The payload for the request
42
+ # @param {Hash} [headers=nil] - The headers for the request
43
+ #
44
+ def refund(payload: nil, headers: nil)
45
+ api_call(options: {
46
+ method: 'POST',
47
+ url_fragment: 'in-store/refund',
48
+ payload: payload,
49
+ headers: headers
50
+ })
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,85 @@
1
+ require 'amazon_pay/client_helper'
2
+
3
+ module AmazonPay
4
+ class AmazonPayClient
5
+ def initialize(config_args)
6
+ @config_args = config_args.freeze
7
+ end
8
+
9
+ # API to process a request
10
+ # - Makes an API Call using the specified options.
11
+ # @param {Hash} options - The options to make the API Call
12
+ # @param {String} options.method - The HTTP request method
13
+ # @param {String} options.url_fragment - The URI for the API Call
14
+ # @param {String} [options.payload=nil] - The payload for the API Call
15
+ # @param {Hash} [options.headers=nil] - The headers for the API Call
16
+ # @param {Hash} [options.queryParams=nil] - The headers for the API Call
17
+
18
+ def api_call(options: {})
19
+ prepared_options = AmazonPay::ClientHelper.prepare_options(config_args: @config_args, options: options)
20
+ prepared_options[:headers] = AmazonPay::ClientHelper.sign_headers(config_args: @config_args, options: prepared_options)
21
+ AmazonPay::ClientHelper.invoke_api(config_args: @config_args, api_options: prepared_options)
22
+ end
23
+
24
+ # Signs the request headers
25
+ # - Signs the request provided and returns the signed headers Hash.
26
+ # @param {Hash} options - The options to make the API Call
27
+ # @param {String} options.method - The HTTP request method
28
+ # @param {String} options.url_fragment - The URI for the API Call
29
+ # @param {String} [options.payload=nil] - The payload for the API Call
30
+ # @param {Hash} [options.headers=nil] - The headers for the API Call
31
+
32
+ def get_signed_headers(options: {})
33
+ prepared_options = AmazonPay::ClientHelper.prepare_options(@config_args, options)
34
+ AmazonPay::ClientHelper.sign_headers(config_args: @config_args, options: prepared_options)
35
+ end
36
+
37
+ # Lets the solution provider get Authorization Token for their merchants if they are granted the delegation.
38
+ # - Please note that your solution provider account must have a pre-existing relationship (valid and active MWS authorization token) with the merchant account in order to use this function.
39
+ # @param {String} mws_auth_token - The mws_auth_token
40
+ # @param {String} merchant_id - The merchant_id
41
+ # @param {Hash} [headers=nil] - The headers for the request
42
+
43
+ def get_authorization_token(mws_auth_token: nil, merchant_id: nil, headers: nil)
44
+ api_call(options: {
45
+ method: 'GET',
46
+ url_fragment: "authorizationTokens/#{mws_auth_token}",
47
+ headers: headers,
48
+ query_params: {
49
+ merchantId: merchant_id
50
+ }
51
+ })
52
+ end
53
+
54
+ # Generates static signature for amazon.Pay.renderButton used by checkout.js.
55
+ # - Returns signature as string.
56
+ # @param {Hash} payload - The payload for the request
57
+ # @returns {String} signature
58
+
59
+ def generate_button_signature(payload: nil)
60
+ AmazonPay::ClientHelper.sign_payload(config_args: @config_args, payload: payload)
61
+ end
62
+
63
+ # Lets the solution provider make the DeliveryTrackers request with their auth token.
64
+ # - Lets you provide shipment tracking information to Amazon Pay so that Amazon Pay will
65
+ # be able to notify buyers on Alexa when shipments are delivered.
66
+ # @see https://developer.amazon.com/docs/amazon-pay-onetime/delivery-notifications.html#api-reference
67
+ # @param {Hash} payload - The payload for the request
68
+ # @param {String} payload.amazonOrderReferenceId - The Amazon Order Reference ID or Charge
69
+ # Permission Id associated with the order for which the shipments need
70
+ # to be tracked
71
+ # @param {String} payload.trackingNumber - The tracking number for the shipment provided by
72
+ # the shipping company
73
+ # @param {Hash} payload.carrierCode - The shipping company code used for delivering goods to the customer
74
+ # @param {Hash} [headers=nil] - The headers for the request
75
+
76
+ def delivery_trackers(payload: nil, headers: nil)
77
+ api_call(options: {
78
+ method: 'POST',
79
+ url_fragment: 'deliveryTrackers',
80
+ payload: payload,
81
+ headers: headers
82
+ })
83
+ end
84
+ end
85
+ end
@@ -0,0 +1,215 @@
1
+ # rubocop:disable Metrics/ClassLength
2
+
3
+ module AmazonPay
4
+ # Class for Amazon Web Store
5
+ class AmazonWebStoreClient < AmazonPayClient
6
+ def initialize(config_args)
7
+ super(config_args)
8
+ end
9
+
10
+ # API to get the Buyer Hash
11
+ # - Get Buyer details can include buyer ID, name, email address, postal code,
12
+ # and country code
13
+ # - when used with the Amazon.Pay.renderButton 'SignIn' productType and corresponding
14
+ # signInScopes
15
+ # @param {String} buyer_token - The checkout session Id
16
+ # @param {Hash} [headers=nil] - The headers for the request
17
+
18
+ def get_buyer(buyer_token: nil, headers: nil)
19
+ api_call(options:
20
+ {
21
+ method: 'GET',
22
+ url_fragment: "buyers/#{buyer_token}",
23
+ headers: headers
24
+ })
25
+ end
26
+
27
+ # API to create a CheckoutSession Hash
28
+ # - Creates a new CheckoutSession Hash.
29
+ # @see https://amazonpaycheckoutintegrationguide.s3.amazonaws.com/amazon-pay-api-v2/checkout-session.html#create-checkout-session
30
+ # @param {Hash} payload - The payload for the request
31
+ # @param {Hash} headers - The headers for the request
32
+ def create_checkout_session(payload: nil, headers: nil)
33
+ api_call(options: {
34
+ method: 'POST',
35
+ url_fragment: 'checkoutSessions',
36
+ payload: payload,
37
+ headers: headers
38
+ })
39
+ end
40
+
41
+ # API to get the CheckoutSession Hash
42
+ # - Retrives details of a previously created CheckoutSession Hash.
43
+ # @see https://amazonpaycheckoutintegrationguide.s3.amazonaws.com/amazon-pay-api-v2/checkout-session.html#get-checkout-session
44
+ # @param {String} checkout_session_id - The checkout session Id
45
+ # @param {Hash} [headers=nil] - The headers for the request
46
+ def get_checkout_session(checkout_session_id: nil, headers: nil)
47
+ api_call(options: {
48
+ method: 'GET',
49
+ url_fragment: "checkoutSessions/#{checkout_session_id}",
50
+ headers: headers
51
+ })
52
+ end
53
+
54
+ # API to update the CheckoutSession Hash
55
+ # - Updates a previously created CheckoutSession Hash.
56
+ # @see https://amazonpaycheckoutintegrationguide.s3.amazonaws.com/amazon-pay-api-v2/checkout-session.html#update-checkout-session
57
+ # @param {String} checkout_session_id - The checkout session Id
58
+ # @param {Hash} payload - The payload for the request
59
+ # @param {Hash} [headers=nil] - The headers for the request
60
+ def update_checkout_session(checkout_session_id: nil, payload: nil, headers: nil)
61
+ api_call(options: {
62
+ method: 'PATCH',
63
+ url_fragment: "checkoutSessions/#{checkout_session_id}",
64
+ payload: payload,
65
+ headers: headers
66
+ })
67
+ end
68
+
69
+ # API to complete a Checkout Session
70
+ # - Confirms the completion of buyer checkout.
71
+ # @see //TODO Update Live URL
72
+ # @param {String} checkout_session_id - The checkout session Id
73
+ # @param {Hash} payload - The payload for the request
74
+ # @param {Hash} [headers=nil] - The headers for the request
75
+ def complete_checkout_session(checkout_session_id: nil, payload: nil, headers: nil)
76
+ api_call(options: {
77
+ method: 'POST',
78
+ url_fragment: "checkoutSessions/#{checkout_session_id}/complete",
79
+ payload: payload,
80
+ headers: headers
81
+ })
82
+ end
83
+
84
+ # API to get a ChargePermission Hash
85
+ # - Retrives details of a previously created ChargePermission Hash.
86
+ # @see https://amazonpaycheckoutintegrationguide.s3.amazonaws.com/amazon-pay-api-v2/charge-permission.html#get-charge-permission
87
+ # @param {String} charge_permission_id - The charge permission Id
88
+ # @param {Hash} [headers=nil] - The headers for the request
89
+ def get_charge_permission(charge_permission_id: nil, headers: nil)
90
+ api_call(options: {
91
+ method: 'GET',
92
+ url_fragment: "chargePermissions/#{charge_permission_id}",
93
+ headers: headers
94
+ })
95
+ end
96
+
97
+ # API to update a ChargePermission Hash
98
+ # - Updates a previously created ChargePermission Hash.
99
+ # @see https://amazonpaycheckoutintegrationguide.s3.amazonaws.com/amazon-pay-api-v2/charge-permission.html#update-charge-permission
100
+ # @param {String} charge_permission_id - The charge permission Id
101
+ # @param {Hash} payload - The payload for the request
102
+ # @param {Hash} [headers=nil] - The headers for the request
103
+ def update_charge_permission(charge_permission_id: nil, payload: nil, headers: nil)
104
+ api_call(options: {
105
+ method: 'PATCH',
106
+ url_fragment: "chargePermissions/#{charge_permission_id}",
107
+ payload: payload,
108
+ headers: headers
109
+ })
110
+ end
111
+
112
+ # API to close a ChargePermission Hash
113
+ # - Closes a perviously created ChargePermission Hash.
114
+ # @see https://amazonpaycheckoutintegrationguide.s3.amazonaws.com/amazon-pay-api-v2/charge-permission.html#close-charge-permission
115
+ # @param {String} charge_permission_id - The charge permission Id
116
+ # @param {Hash} payload - The payload for the request
117
+ # @param {Hash} [headers=nil] - The headers for the request
118
+ def close_charge_permission(charge_permission_id: nil, payload: nil, headers: nil)
119
+ api_call(options: {
120
+ method: 'DELETE',
121
+ url_fragment: "chargePermissions/#{charge_permission_id}/close",
122
+ payload: payload,
123
+ headers: headers
124
+ })
125
+ end
126
+
127
+ # API to create a Charge Hash
128
+ # - Creates a new Charge Hash.
129
+ # @see https://amazonpaycheckoutintegrationguide.s3.amazonaws.com/amazon-pay-api-v2/charge.html#create-charge
130
+ # @param {Hash} payload - The payload for the request
131
+ # @param {Hash} headers - The headers for the request
132
+ def create_charge(payload: nil, headers: nil)
133
+ api_call(options: {
134
+ method: 'POST',
135
+ url_fragment: 'charges',
136
+ payload: payload,
137
+ headers: headers
138
+ })
139
+ end
140
+
141
+ # API to get the Charge Hash
142
+ # - Retrieves a perviously created Charge Hash.
143
+ # @see https://amazonpaycheckoutintegrationguide.s3.amazonaws.com/amazon-pay-api-v2/charge.html#get-charge
144
+ # @param {String} charge_id - The charge Id
145
+ # @param {Hash} [headers=nil] - The headers for the request
146
+ def get_charge(charge_id: nil, headers: nil)
147
+ api_call(options: {
148
+ method: 'GET',
149
+ url_fragment: "charges/#{charge_id}",
150
+ headers: headers
151
+ })
152
+ end
153
+
154
+ # API to create a captureCharge request
155
+ # - Captures an existing charge
156
+ # @see https://amazonpaycheckoutintegrationguide.s3.amazonaws.com/amazon-pay-api-v2/charge.html#capture-charge
157
+ # @param {String} charge_id - The charge Id
158
+ # @param {Hash} payload - The payload for the request
159
+ # @param {Hash} [headers=nil] - The headers for the request
160
+
161
+ def capture_charge(charge_id: nil, payload: nil, headers: nil)
162
+ api_call(options: {
163
+ method: 'POST',
164
+ url_fragment: "charges/#{charge_id}/capture",
165
+ payload: payload,
166
+ headers: headers
167
+ })
168
+ end
169
+
170
+ # API to create a cancelCharge request
171
+ # - Cancels an existing charge.
172
+ # @see https://amazonpaycheckoutintegrationguide.s3.amazonaws.com/amazon-pay-api-v2/charge.html#cancel-charge
173
+ # @param {String} charge_id - The charge Id
174
+ # @param {Hash} payload - The payload for the request
175
+ # @param {Hash} [headers=nil] - The headers for the request
176
+
177
+ def cancel_charge(charge_id: nil, payload: nil, headers: nil)
178
+ api_call(options: {
179
+ method: 'DELETE',
180
+ url_fragment: "charges/#{charge_id}/cancel",
181
+ payload: payload,
182
+ headers: headers
183
+ })
184
+ end
185
+
186
+ # API to create a Refund Hash
187
+ # - Generates a refund.
188
+ # @see https://amazonpaycheckoutintegrationguide.s3.amazonaws.com/amazon-pay-api-v2/refund.html#create-refund
189
+ # @param {Hash} payload - The payload for the request
190
+ # @param {Hash} headers - The headers for the request
191
+
192
+ def create_refund(payload: nil, headers: nil)
193
+ api_call(options: {
194
+ method: 'POST',
195
+ url_fragment: 'refunds',
196
+ payload: payload,
197
+ headers: headers
198
+ })
199
+ end
200
+
201
+ # API to get a Refund Hash
202
+ # - Retreives details of an existing refund.
203
+ # @see https://amazonpaycheckoutintegrationguide.s3.amazonaws.com/amazon-pay-api-v2/refund.html#get-refund
204
+ # @param {String} refundId - The refund Id
205
+ # @param {Hash} [headers=nil] - The headers for the request
206
+
207
+ def get_refund(refund_id: nil, headers: nil)
208
+ api_call(options: {
209
+ method: 'GET',
210
+ url_fragment: "refunds/#{refund_id}",
211
+ headers: headers
212
+ })
213
+ end
214
+ end
215
+ end
@@ -0,0 +1,185 @@
1
+ # rubocop:disable Metrics/MethodLength, Metrics/ClassLength, Metrics/AbcSize
2
+
3
+ require 'openssl'
4
+ require 'base64'
5
+ require 'json'
6
+ require 'time'
7
+ require 'date'
8
+ require 'net/http'
9
+ require 'amazon_pay/constants'
10
+
11
+ module AmazonPay
12
+ # All the helper files
13
+ class ClientHelper
14
+ def self.fetch_timestamp
15
+ Time.now.utc.iso8601
16
+ end
17
+
18
+ def self.fetch_api_endpoint_base_url(config_args: {})
19
+ if config_args[:overrideServiceUrl]&.length&.positive?
20
+ config_args[:overrideServiceUrl]
21
+ else
22
+ region = config_args[:region].downcase.to_sym
23
+ region_map = AmazonPay::CONSTANTS[:REGION_MAP][region].to_sym
24
+
25
+ AmazonPay::CONSTANTS[:API_ENDPOINTS][region_map]
26
+ end
27
+ end
28
+
29
+ def self.invoke_api(config_args: {}, api_options: {})
30
+ options = {
31
+ method: api_options[:method],
32
+ json: false,
33
+ headers: api_options[:headers],
34
+ url: "https://#{fetch_api_endpoint_base_url(config_args: config_args)}/#{api_options[:url_fragment]}"\
35
+ "#{fetch_query_string(request_params: api_options[:query_params])}",
36
+ body: api_options[:payload]
37
+ }
38
+
39
+ retry_logic(options: options, count: 1)
40
+ end
41
+
42
+ def self.fetch_query_string(request_params: nil)
43
+ return "?#{fetch_parameters_as_string(request_params: request_params)}" if request_params
44
+
45
+ ''
46
+ end
47
+
48
+ def self.fetch_parameters_as_string(request_params: nil)
49
+ return '' if request_params.nil?
50
+
51
+ query_params = []
52
+ request_params.map do |key, value|
53
+ query_params << "#{key}=#{CGI.escape(value)}"
54
+ end
55
+ query_params.join('&')
56
+ end
57
+
58
+ def self.prepare_options(config_args: {}, options: {})
59
+ options[:headers] ||= {}
60
+
61
+ # if user doesn't pass in a string, assume it's a JS Hash and convert it to a JSON string
62
+ unless options[:payload].is_a?(String) || options[:payload].nil?
63
+ options[:payload] = JSON.generate(options[:payload])
64
+ end
65
+
66
+ options[:url_fragment] = if config_args[:sandbox] == true || config_args[:sandbox] == 'true'
67
+ "sandbox/#{AmazonPay::CONSTANTS[:API_VERSION]}/#{options[:url_fragment]}"
68
+ else
69
+ "live/#{AmazonPay::CONSTANTS[:API_VERSION]}/#{options[:url_fragment]}"
70
+ end
71
+
72
+ options
73
+ end
74
+
75
+ def self.sign(private_key: nil, data: nil)
76
+ sign_hash = OpenSSL::Digest.new('SHA256')
77
+ priv = OpenSSL::PKey::RSA.new(private_key)
78
+ signature = priv.sign_pss(sign_hash, data, salt_length: 20, mgf1_hash: 'SHA256')
79
+ Base64.strict_encode64(signature)
80
+ end
81
+
82
+ def self.retry_logic(options: {}, count: 0)
83
+ response = send_request(options: options, count: count)
84
+ return response if count > AmazonPay::CONSTANTS[:RETRIES]
85
+
86
+ return response unless response.nil?
87
+
88
+ count += 1
89
+ retry_logic(options: options, count: count)
90
+ end
91
+
92
+ def self.send_request(options: {}, count: 0)
93
+ delay_time = count == 1 ? 0 : (2**(count - 1)).seconds
94
+ sleep(delay_time)
95
+ begin
96
+ uri = URI(options[:url])
97
+
98
+ http = Net::HTTP.new(uri.host, uri.port)
99
+ http.use_ssl = true
100
+ http.verify_mode = OpenSSL::SSL::VERIFY_PEER
101
+
102
+ case options[:method].to_sym
103
+ when :GET
104
+ response = http.get(uri, options[:headers])
105
+ when :DELETE
106
+ response = http.delete(uri.request_uri, options[:headers])
107
+ when :POST
108
+ request = Net::HTTP::Post.new(uri.path, options[:headers])
109
+ request.body = options[:body]
110
+ response = http.request(request)
111
+ when :PATCH
112
+ request = Net::HTTP::Patch.new(uri.path, options[:headers])
113
+ request.body = options[:body]
114
+ response = http.request(request)
115
+ end
116
+ JSON.parse(response.body)
117
+ rescue StandardError
118
+ nil
119
+ end
120
+ end
121
+
122
+ # Expected options:
123
+ # options[:method]
124
+ # options[:url_fragment]
125
+ # options[:payload]
126
+ # options[:headers]
127
+
128
+ def self.sign_headers(config_args: {}, options: {})
129
+ headers = options[:headers] || {}
130
+ headers['x-amz-pay-region'] = 'us'
131
+ headers['x-amz-pay-host'] = fetch_api_endpoint_base_url(config_args: config_args)
132
+ headers['x-amz-pay-date'] = fetch_timestamp
133
+ headers['content-type'] = 'application/json'
134
+ headers['accept'] = 'application/json'
135
+ headers[
136
+ 'user-agent'
137
+ ] = "amazon-pay-api-sdk-ruby/#{AmazonPay::CONSTANTS[:SDK_VERSION]} (Ruby/#{RUBY_VERSION}; #{RUBY_PLATFORM})"
138
+
139
+ lower_case_sorted_header_keys = headers.keys.sort.map(&:downcase)
140
+ signed_headers = lower_case_sorted_header_keys.join(';')
141
+
142
+ payload = options[:payload]
143
+
144
+ if payload.nil? || options[:url_fragment].include?('/account-management/'\
145
+ "#{AmazonPay::CONSTANTS[:API_VERSION]}/accounts")
146
+ payload = '' # do not sign payload for payment critical data APIs
147
+ end
148
+
149
+ canonical_request =
150
+ options[:method] + "\n/" +
151
+ options[:url_fragment] + "\n" +
152
+ fetch_parameters_as_string(request_params: options[:query_params]) +
153
+ "\n"
154
+
155
+ lower_case_sorted_header_keys.each do |item|
156
+ str = item.downcase + ':' + headers[item] + "\n"
157
+
158
+ canonical_request += str
159
+ end
160
+
161
+ canonical_request += "\n" + signed_headers + "\n" +
162
+ OpenSSL::Digest::SHA256.hexdigest(payload)
163
+
164
+ string_to_sign =
165
+ AmazonPay::CONSTANTS[:AMAZON_SIGNATURE_ALGORITHM] +
166
+ "\n" +
167
+ OpenSSL::Digest::SHA256.hexdigest(canonical_request)
168
+
169
+ signature = sign(private_key: config_args[:private_key], data: string_to_sign)
170
+
171
+ headers['authorization'] = "#{AmazonPay::CONSTANTS[:AMAZON_SIGNATURE_ALGORITHM]} "\
172
+ "PublicKeyId=#{config_args[:public_key_id]}, SignedHeaders=#{signed_headers}, Signature=#{signature}"
173
+
174
+ headers
175
+ end
176
+
177
+ def self.sign_payload(config_args: nil, payload: nil)
178
+ # if user doesn't pass in a string, assume it's a JS Hash and convert it to a JSON string
179
+ payload = JSON.generate(payload) unless payload.is_a?(String)
180
+ string_to_sign = AmazonPay::CONSTANTS[:AMAZON_SIGNATURE_ALGORITHM] + "\n" +
181
+ OpenSSL::Digest::SHA256.hexdigest(payload)
182
+ sign(private_key: config_args[:private_key], data: string_to_sign)
183
+ end
184
+ end
185
+ end