aws_agcod_2 1.1.0
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/LICENSE.txt +22 -0
- data/README.md +115 -0
- data/Rakefile +7 -0
- data/lib/aws_agcod.rb +19 -0
- data/lib/aws_agcod/available_funds.rb +13 -0
- data/lib/aws_agcod/cancel_gift_card.rb +16 -0
- data/lib/aws_agcod/config.rb +27 -0
- data/lib/aws_agcod/create_gift_card.rb +43 -0
- data/lib/aws_agcod/get_available_funds.rb +30 -0
- data/lib/aws_agcod/gift_card_activity_list.rb +54 -0
- data/lib/aws_agcod/request.rb +61 -0
- data/lib/aws_agcod/response.rb +31 -0
- data/lib/aws_agcod/signature.rb +95 -0
- data/lib/aws_agcod/version.rb +3 -0
- data/spec/aws_agcod/cancel_gift_card_spec.rb +49 -0
- data/spec/aws_agcod/config_spec.rb +44 -0
- data/spec/aws_agcod/create_gift_card_spec.rb +104 -0
- data/spec/aws_agcod/get_available_funds_spec.rb +62 -0
- data/spec/aws_agcod/gift_card_activity_list_spec.rb +75 -0
- data/spec/aws_agcod/request_spec.rb +79 -0
- data/spec/aws_agcod/response_spec.rb +66 -0
- data/spec/aws_agcod_spec.rb +12 -0
- data/spec/spec_helper.rb +18 -0
- metadata +135 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 57228cfced3a4ce27d86778e5458cb28c6dd00490880ae22db9ef8c2b1ca456e
|
4
|
+
data.tar.gz: f06da4395c979dba879ef0aaced9bbdd6ad79958b3514340d6ccbed0bfec74f0
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 7384eddccb0d643c91eb8e6c00ea515333b7a9a602b46200f2bda20d1d5464e49c02dbc36b3d650de43ffc27aa9a5fc6bc35349a6ae6b1007f92400545e3b12a
|
7
|
+
data.tar.gz: 7971db886d28511ba4818d283b8c3245ac0cf14f850d14ea58539e8b574293ae4d7b75454d0661574556bd6b7348a83dfe8d11bec623071e7efa0c187aef5a79
|
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2015 Xenor Chang
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,115 @@
|
|
1
|
+
# AGCOD
|
2
|
+
|
3
|
+
[](https://travis-ci.org/compwron/aws_agcod)
|
4
|
+
[](http://badge.fury.io/rb/aws_agcod)
|
5
|
+
|
6
|
+
Amazon Gift Code On Demand (AGCOD) API v2 implementation for distributing Amazon gift cards (gift codes) instantly in any denomination.
|
7
|
+
|
8
|
+
## Installation
|
9
|
+
|
10
|
+
Add this line to your application's Gemfile:
|
11
|
+
|
12
|
+
```ruby
|
13
|
+
gem 'aws_agcod'
|
14
|
+
```
|
15
|
+
|
16
|
+
And then execute:
|
17
|
+
|
18
|
+
$ bundle
|
19
|
+
|
20
|
+
Or install it yourself as:
|
21
|
+
|
22
|
+
$ gem install aws_agcod
|
23
|
+
|
24
|
+
## Usage
|
25
|
+
|
26
|
+
#### Configure
|
27
|
+
|
28
|
+
```ruby
|
29
|
+
require "aws_agcod"
|
30
|
+
|
31
|
+
AGCOD.configure do |config|
|
32
|
+
config.access_key = "YOUR ACCESS KEY"
|
33
|
+
config.secret_key = "YOUR SECRET KEY"
|
34
|
+
config.partner_id = "PARTNER ID"
|
35
|
+
|
36
|
+
# The `production` config is important as it determines which endpoint
|
37
|
+
# you're hitting.
|
38
|
+
config.production = true # This defaults to false.
|
39
|
+
|
40
|
+
# Optionally, you can customize the URI completely.
|
41
|
+
config.uri = "https://my-custom-agcod-endpoint.com"
|
42
|
+
|
43
|
+
config.region = "us-east-1" # default
|
44
|
+
end
|
45
|
+
```
|
46
|
+
|
47
|
+
#### Create Gift Code/Card
|
48
|
+
|
49
|
+
```ruby
|
50
|
+
request_id = "test"
|
51
|
+
amount = 10
|
52
|
+
currency = "USD" # default to USD, available types are: USD, EUR, JPY, CNY, CAD
|
53
|
+
httpable = HTTP # or HTTParty- whatever library you're using that has .post
|
54
|
+
request = AGCOD::CreateGiftCard.new(httpable, request_id, amount, currency)
|
55
|
+
|
56
|
+
# When succeed
|
57
|
+
if request.success?
|
58
|
+
request.claim_code # => code for the gift card
|
59
|
+
request.gc_id # => gift card id
|
60
|
+
request.request_id # => your request id
|
61
|
+
else
|
62
|
+
# When failed
|
63
|
+
request.error_message # => Error response from AGCOD service
|
64
|
+
end
|
65
|
+
```
|
66
|
+
|
67
|
+
#### Cancel Gift Code/Card
|
68
|
+
|
69
|
+
```ruby
|
70
|
+
request_id = "test"
|
71
|
+
gc_id = "test_gc_id"
|
72
|
+
httpable = HTTP # or HTTParty- whatever library you're using that has .post
|
73
|
+
request = AGCOD::CancelGiftCard.new(httpable, request_id, gc_id)
|
74
|
+
|
75
|
+
# When failed
|
76
|
+
unless request.success?
|
77
|
+
request.error_message # => Error response from AGCOD service
|
78
|
+
end
|
79
|
+
```
|
80
|
+
|
81
|
+
#### Get Gift Code/Card activities
|
82
|
+
|
83
|
+
```ruby
|
84
|
+
request_id = "test"
|
85
|
+
start_time = Time.now - 86400
|
86
|
+
end_time = Time.now
|
87
|
+
page = 1
|
88
|
+
per_page = 100
|
89
|
+
show_no_ops = false # Whether or not to show activities with no operation
|
90
|
+
httpable = HTTP # or HTTParty- whatever library you're using that has .post
|
91
|
+
request = AGCOD::GiftCardActivityList.new(httpable, request_id, start_time, end_time, page, per_page, show_no_ops)
|
92
|
+
|
93
|
+
if request.success?
|
94
|
+
request.results.each do |activity|
|
95
|
+
activity.status # => SUCCESS, FAILURE, RESEND
|
96
|
+
activity.created_at
|
97
|
+
activity.type
|
98
|
+
activity.card_number
|
99
|
+
activity.amount
|
100
|
+
activity.error_code
|
101
|
+
activity.gc_id
|
102
|
+
activity.partner_id
|
103
|
+
activity.request_id
|
104
|
+
end
|
105
|
+
else
|
106
|
+
request.error_message # => Error response from AGCOD service
|
107
|
+
end
|
108
|
+
```
|
109
|
+
## Contributing
|
110
|
+
|
111
|
+
1. Fork it ( https://github.com/[my-github-username]/aws_agcod/fork )
|
112
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
113
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
114
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
115
|
+
5. Create a new Pull Request
|
data/Rakefile
ADDED
data/lib/aws_agcod.rb
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
require "aws_agcod/version"
|
2
|
+
require "aws_agcod/config"
|
3
|
+
require "aws_agcod/create_gift_card"
|
4
|
+
require "aws_agcod/cancel_gift_card"
|
5
|
+
require "aws_agcod/gift_card_activity_list"
|
6
|
+
|
7
|
+
module AGCOD
|
8
|
+
def self.configure(&block)
|
9
|
+
@config = Config.new
|
10
|
+
|
11
|
+
yield @config
|
12
|
+
|
13
|
+
nil
|
14
|
+
end
|
15
|
+
|
16
|
+
def self.config
|
17
|
+
@config
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
require "aws_agcod/request"
|
2
|
+
|
3
|
+
module AGCOD
|
4
|
+
class CancelGiftCard
|
5
|
+
extend Forwardable
|
6
|
+
|
7
|
+
def_delegators :@response, :status, :success?, :error_message
|
8
|
+
|
9
|
+
def initialize(httpable, request_id, gc_id)
|
10
|
+
@response = Request.new(httpable,"CancelGiftCard",
|
11
|
+
"creationRequestId" => request_id,
|
12
|
+
"gcId" => gc_id
|
13
|
+
).response
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
module AGCOD
|
2
|
+
class Config
|
3
|
+
attr_writer :uri
|
4
|
+
attr_accessor :access_key,
|
5
|
+
:secret_key,
|
6
|
+
:partner_id,
|
7
|
+
:region,
|
8
|
+
:production
|
9
|
+
|
10
|
+
URI = {
|
11
|
+
sandbox: "https://agcod-v2-gamma.amazon.com",
|
12
|
+
production: "https://agcod-v2.amazon.com"
|
13
|
+
}
|
14
|
+
|
15
|
+
def initialize
|
16
|
+
# API defaults
|
17
|
+
@production = false
|
18
|
+
@region = "us-east-1"
|
19
|
+
end
|
20
|
+
|
21
|
+
def uri
|
22
|
+
return @uri if @uri
|
23
|
+
|
24
|
+
production ? URI[:production] : URI[:sandbox]
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
require "aws_agcod/request"
|
2
|
+
|
3
|
+
module AGCOD
|
4
|
+
class CreateGiftCardError < StandardError; end
|
5
|
+
|
6
|
+
class CreateGiftCard
|
7
|
+
extend Forwardable
|
8
|
+
|
9
|
+
CURRENCIES = %w(USD EUR JPY CNY CAD)
|
10
|
+
|
11
|
+
def_delegators :@response, :status, :success?, :error_message
|
12
|
+
|
13
|
+
def initialize(httpable, request_id, amount, currency = "USD")
|
14
|
+
unless CURRENCIES.include?(currency.to_s)
|
15
|
+
raise CreateGiftCardError, "Currency #{currency} not supported, available types are #{CURRENCIES.join(", ")}"
|
16
|
+
end
|
17
|
+
|
18
|
+
@response = Request.new(httpable, "CreateGiftCard",
|
19
|
+
"creationRequestId" => request_id,
|
20
|
+
"value" => {
|
21
|
+
"currencyCode" => currency,
|
22
|
+
"amount" => amount
|
23
|
+
}
|
24
|
+
).response
|
25
|
+
end
|
26
|
+
|
27
|
+
def claim_code
|
28
|
+
@response.payload["gcClaimCode"]
|
29
|
+
end
|
30
|
+
|
31
|
+
def expiration_date
|
32
|
+
@expiration_date ||= Time.parse @response.payload["gcExpirationDate"]
|
33
|
+
end
|
34
|
+
|
35
|
+
def gc_id
|
36
|
+
@response.payload["gcId"]
|
37
|
+
end
|
38
|
+
|
39
|
+
def request_id
|
40
|
+
@response.payload["creationRequestId"]
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
require 'aws_agcod/request'
|
2
|
+
require 'aws_agcod/available_funds'
|
3
|
+
|
4
|
+
module AGCOD
|
5
|
+
class GetAvailableFunds
|
6
|
+
extend Forwardable
|
7
|
+
|
8
|
+
def initialize(httpable, partner_id)
|
9
|
+
@response = Request.new(httpable, 'GetAvailableFunds',
|
10
|
+
'partnerId' => partner_id,
|
11
|
+
).response
|
12
|
+
end
|
13
|
+
|
14
|
+
def available_funds
|
15
|
+
@response.payload['availableFunds'].map { |payload| AGCOD::AvailableFunds.new(payload) }
|
16
|
+
end
|
17
|
+
|
18
|
+
def timestamp
|
19
|
+
Time.parse(@response.payload['timestamp'])
|
20
|
+
end
|
21
|
+
|
22
|
+
def status
|
23
|
+
@response.payload['status']
|
24
|
+
end
|
25
|
+
|
26
|
+
def success?
|
27
|
+
@response.payload['status'] == 'SUCCESS'
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
require "aws_agcod/request"
|
2
|
+
|
3
|
+
module AGCOD
|
4
|
+
class GiftCardActivityListError < StandardError; end
|
5
|
+
|
6
|
+
class GiftCardActivity
|
7
|
+
attr_reader :status, :created_at, :type, :card_number, :amount, :error_code,
|
8
|
+
:gc_id, :partner_id, :request_id
|
9
|
+
|
10
|
+
def initialize(payload)
|
11
|
+
@payload = payload
|
12
|
+
@status = payload["activityStatus"]
|
13
|
+
@created_at = payload["activityTime"]
|
14
|
+
@type = payload["activityType"]
|
15
|
+
@card_number = payload["cardNumber"]
|
16
|
+
@amount = payload["cardValue"]["amount"] if payload["cardValue"]
|
17
|
+
@error_code = payload["failureCode"]
|
18
|
+
@gc_id = payload["gcId"]
|
19
|
+
@partner_id = payload["partnerId"]
|
20
|
+
@request_id = payload["requestId"]
|
21
|
+
end
|
22
|
+
|
23
|
+
def is_real?
|
24
|
+
@payload["isRealOp"] == "true"
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
class GiftCardActivityList
|
29
|
+
extend Forwardable
|
30
|
+
|
31
|
+
LIMIT = 1000 # limit per request
|
32
|
+
TIME_FORMAT = "%Y-%m-%dT%H:%M:%SZ"
|
33
|
+
|
34
|
+
def_delegators :@response, :success?, :error_message
|
35
|
+
|
36
|
+
def initialize(httpable, request_id, start_time, end_time, page = 1, per_page = 100, show_no_ops = false)
|
37
|
+
raise GiftCardActivityListError, "Only #{LIMIT} records allowed per request." if per_page > LIMIT
|
38
|
+
|
39
|
+
@response = Request.new(httpable,"GetGiftCardActivityPage",
|
40
|
+
"requestId" => request_id,
|
41
|
+
"utcStartDate" => start_time.strftime(TIME_FORMAT),
|
42
|
+
"utcEndDate" => end_time.strftime(TIME_FORMAT),
|
43
|
+
"pageIndex" => (page - 1) * per_page,
|
44
|
+
"pageSize" => per_page,
|
45
|
+
"showNoOps" => show_no_ops
|
46
|
+
).response
|
47
|
+
end
|
48
|
+
|
49
|
+
def results
|
50
|
+
@response.payload["cardActivityList"].map { |payload| GiftCardActivity.new(payload) }
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
@@ -0,0 +1,61 @@
|
|
1
|
+
require "aws_agcod/signature"
|
2
|
+
require "aws_agcod/response"
|
3
|
+
require "http"
|
4
|
+
require "yaml"
|
5
|
+
|
6
|
+
module AGCOD
|
7
|
+
class Request
|
8
|
+
TIME_FORMAT = "%Y%m%dT%H%M%SZ"
|
9
|
+
MOCK_REQUEST_IDS = %w(F0000 F2005)
|
10
|
+
|
11
|
+
attr_reader :response
|
12
|
+
|
13
|
+
def initialize(httpable, action, params) # httpable is anything that can have post called upon it; this allows passing in a proxy
|
14
|
+
@action = action
|
15
|
+
@params = sanitized_params(params)
|
16
|
+
|
17
|
+
@response = Response.new(httpable.post(uri, body: body, headers: signed_headers).body)
|
18
|
+
end
|
19
|
+
|
20
|
+
private
|
21
|
+
|
22
|
+
def signed_headers
|
23
|
+
time = Time.now.utc
|
24
|
+
|
25
|
+
headers = {
|
26
|
+
"content-type" => "application/json",
|
27
|
+
"x-amz-date" => time.strftime(TIME_FORMAT),
|
28
|
+
"accept" => "application/json",
|
29
|
+
"host" => uri.host,
|
30
|
+
"x-amz-target" => "com.amazonaws.agcod.AGCODService.#{@action}",
|
31
|
+
"date" => time.to_s
|
32
|
+
}
|
33
|
+
|
34
|
+
Signature.new(AGCOD.config).sign(uri, headers, body)
|
35
|
+
end
|
36
|
+
|
37
|
+
def uri
|
38
|
+
@uri ||= URI("#{AGCOD.config.uri}/#{@action}")
|
39
|
+
end
|
40
|
+
|
41
|
+
def body
|
42
|
+
@body ||= @params.merge(
|
43
|
+
"partnerId" => AGCOD.config.partner_id
|
44
|
+
).to_json
|
45
|
+
end
|
46
|
+
|
47
|
+
def sanitized_params(params)
|
48
|
+
# Prefix partner_id when it's not given as part of request_id for creationRequestId and it's not a mock request_id
|
49
|
+
if params["creationRequestId"] && !(params["creationRequestId"] =~ /#{AGCOD.config.partner_id}/) && !(MOCK_REQUEST_IDS.member?(params["creationRequestId"]))
|
50
|
+
params["creationRequestId"] = "#{AGCOD.config.partner_id}#{params["creationRequestId"]}"
|
51
|
+
end
|
52
|
+
|
53
|
+
# Remove partner_id when it's prefixed in requestId
|
54
|
+
if params["requestId"] && !!(params["requestId"] =~ /^#{AGCOD.config.partner_id}/)
|
55
|
+
params["requestId"].sub!(/^#{AGCOD.config.partner_id}/, "")
|
56
|
+
end
|
57
|
+
|
58
|
+
params
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
require "json"
|
2
|
+
|
3
|
+
module AGCOD
|
4
|
+
class Response
|
5
|
+
attr_reader :status, :payload
|
6
|
+
|
7
|
+
def initialize(raw_json)
|
8
|
+
@payload = JSON.parse(raw_json)
|
9
|
+
|
10
|
+
# All status:
|
11
|
+
# SUCCESS -- Operation succeeded
|
12
|
+
# FAILURE -- Operation failed
|
13
|
+
# RESEND -- A temporary/recoverable system failure that can be resolved by the partner retrying the request
|
14
|
+
@status = if payload["status"]
|
15
|
+
payload["status"]
|
16
|
+
elsif payload["agcodResponse"]
|
17
|
+
payload["agcodResponse"]["status"]
|
18
|
+
else
|
19
|
+
"FAILURE"
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def success?
|
24
|
+
status == "SUCCESS"
|
25
|
+
end
|
26
|
+
|
27
|
+
def error_message
|
28
|
+
"#{payload["errorCode"]} #{payload["errorType"]} - #{payload["message"]}"
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,95 @@
|
|
1
|
+
# Currently AGCOD v2 uses v4 Signature for it's authentication,
|
2
|
+
# this class generates signed headers for making proper request to AGCOD service.
|
3
|
+
#
|
4
|
+
# Based on https://github.com/ifeelgoods/aws4/blob/master/lib/aws4/signer.rb
|
5
|
+
require "openssl"
|
6
|
+
require "uri"
|
7
|
+
require "pathname"
|
8
|
+
|
9
|
+
module AGCOD
|
10
|
+
class Signature
|
11
|
+
SERVICE = "AGCODService"
|
12
|
+
|
13
|
+
def initialize(credentials)
|
14
|
+
@access_key = credentials.access_key
|
15
|
+
@secret_key = credentials.secret_key
|
16
|
+
@region = credentials.region || DEFAULT_REGION
|
17
|
+
end
|
18
|
+
|
19
|
+
def sign(uri, headers, body = "")
|
20
|
+
@uri = uri
|
21
|
+
@headers = headers
|
22
|
+
@body = body
|
23
|
+
@date = headers["x-amz-date"]
|
24
|
+
|
25
|
+
signed_headers = headers.dup
|
26
|
+
signed_headers["Authorization"] = authorization
|
27
|
+
|
28
|
+
signed_headers
|
29
|
+
end
|
30
|
+
|
31
|
+
private
|
32
|
+
|
33
|
+
def authorization
|
34
|
+
[
|
35
|
+
"AWS4-HMAC-SHA256 Credential=#{@access_key}/#{credential_string}",
|
36
|
+
"SignedHeaders=#{@headers.keys.map(&:downcase).sort.join(";")}",
|
37
|
+
"Signature=#{signature}"
|
38
|
+
].join(", ")
|
39
|
+
end
|
40
|
+
|
41
|
+
# Reference http://docs.aws.amazon.com/general/latest/gr/sigv4-calculate-signature.html
|
42
|
+
def signature
|
43
|
+
k_date = hmac("AWS4" + @secret_key, @date[0, 8])
|
44
|
+
k_region = hmac(k_date, @region)
|
45
|
+
k_service = hmac(k_region, SERVICE)
|
46
|
+
k_credentials = hmac(k_service, "aws4_request")
|
47
|
+
hexhmac(k_credentials, string_to_sign)
|
48
|
+
end
|
49
|
+
|
50
|
+
# Reference http://docs.aws.amazon.com/general/latest/gr/sigv4-create-string-to-sign.html
|
51
|
+
def string_to_sign
|
52
|
+
@string_to_sign ||= [
|
53
|
+
"AWS4-HMAC-SHA256", # Algorithm
|
54
|
+
@date, # RequestDate
|
55
|
+
credential_string, # CredentialScope
|
56
|
+
hexdigest(canonical_request) # HashedCanonicalRequest
|
57
|
+
].join("\n")
|
58
|
+
end
|
59
|
+
|
60
|
+
def credential_string
|
61
|
+
@credential_string ||= [@date[0, 8], @region, SERVICE, "aws4_request"].join("/")
|
62
|
+
end
|
63
|
+
|
64
|
+
# Reference http://docs.aws.amazon.com/general/latest/gr/sigv4-create-canonical-request.html
|
65
|
+
def canonical_request
|
66
|
+
@canonical_request ||= [
|
67
|
+
"POST", # HTTPRequestMethod
|
68
|
+
Pathname.new(@uri.path).cleanpath.to_s, # CanonicalURI
|
69
|
+
@uri.query, # CanonicalQueryString
|
70
|
+
@headers.sort.map { |k, v| [k.downcase, v.strip].join(":") }.join("\n") + "\n", # CanonicalHeaders
|
71
|
+
@headers.sort.map { |k, v| k.downcase }.join(";"), # SignedHeaders
|
72
|
+
hexdigest(@body) # HexEncode(Hash(RequestPayload))
|
73
|
+
].join("\n")
|
74
|
+
end
|
75
|
+
|
76
|
+
# Hexdigest simply produces an ascii safe way
|
77
|
+
# to view the bytes produced from the hash algorithm.
|
78
|
+
# It takes the hex representation of each byte
|
79
|
+
# and concatenates them together to produce a string
|
80
|
+
def hexdigest(value)
|
81
|
+
Digest::SHA256.new.update(value).hexdigest
|
82
|
+
end
|
83
|
+
|
84
|
+
# Hash-based message authentication code (HMAC)
|
85
|
+
# is a mechanism for calculating a message authentication code
|
86
|
+
# involving a hash function in combination with a secret key
|
87
|
+
def hmac(key, value)
|
88
|
+
OpenSSL::HMAC.digest(OpenSSL::Digest.new("sha256"), key, value)
|
89
|
+
end
|
90
|
+
|
91
|
+
def hexhmac(key, value)
|
92
|
+
OpenSSL::HMAC.hexdigest(OpenSSL::Digest.new("sha256"), key, value)
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
require "aws_agcod/cancel_gift_card"
|
3
|
+
|
4
|
+
describe AGCOD::CancelGiftCard do
|
5
|
+
let(:partner_id) { "Testa" }
|
6
|
+
let(:response) { spy }
|
7
|
+
let(:httpable) { HTTP }
|
8
|
+
|
9
|
+
before do
|
10
|
+
AGCOD.configure do |config|
|
11
|
+
config.partner_id = partner_id
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
context ".new" do
|
16
|
+
let(:request_id) { "test1" }
|
17
|
+
let(:gc_id) { "FOO" }
|
18
|
+
|
19
|
+
it "makes cancel request" do
|
20
|
+
expect(AGCOD::Request).to receive(:new) do |_, action, params|
|
21
|
+
expect(action).to eq("CancelGiftCard")
|
22
|
+
expect(params["creationRequestId"]).to eq(request_id)
|
23
|
+
expect(params["gcId"]).to eq(gc_id)
|
24
|
+
end.and_return(response)
|
25
|
+
|
26
|
+
AGCOD::CancelGiftCard.new(httpable, request_id, gc_id)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
shared_context "request with response" do
|
31
|
+
let(:gc_id) { "BAR" }
|
32
|
+
let(:creation_request_id) { "BAZ" }
|
33
|
+
let(:status) { "SUCCESS" }
|
34
|
+
let(:request) { AGCOD::CancelGiftCard.new(httpable, creation_request_id, gc_id) }
|
35
|
+
|
36
|
+
before do
|
37
|
+
allow(AGCOD::Request).to receive(:new) { double(response: response) }
|
38
|
+
allow(response).to receive(:status) { status }
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
context "#status" do
|
43
|
+
include_context "request with response"
|
44
|
+
|
45
|
+
it "returns the response status" do
|
46
|
+
expect(request.status).to eq(status)
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
require "aws_agcod/config"
|
3
|
+
|
4
|
+
describe AGCOD::Config do
|
5
|
+
let(:config) { AGCOD::Config.new }
|
6
|
+
|
7
|
+
context ".new" do
|
8
|
+
it "sets default uri and region" do
|
9
|
+
expect(config.uri).not_to be_nil
|
10
|
+
expect(config.region).not_to be_nil
|
11
|
+
expect(config.production).to eq(false)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
context "#uri" do
|
16
|
+
context "when uri is set" do
|
17
|
+
before do
|
18
|
+
config.uri = "https://custom-uri.example.com"
|
19
|
+
end
|
20
|
+
|
21
|
+
it "returns the custom uri" do
|
22
|
+
expect(config.uri).to eq("https://custom-uri.example.com")
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
context "when uri is not set" do
|
27
|
+
context "when production is enabled" do
|
28
|
+
before do
|
29
|
+
config.production = true
|
30
|
+
end
|
31
|
+
|
32
|
+
it "returns the production uri" do
|
33
|
+
expect(config.uri).to eq(AGCOD::Config::URI[:production])
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
context "when production is disabled" do
|
38
|
+
it "returns the sandbox uri" do
|
39
|
+
expect(config.uri).to eq(AGCOD::Config::URI[:sandbox])
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,104 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
require "aws_agcod/create_gift_card"
|
3
|
+
|
4
|
+
describe AGCOD::CreateGiftCard do
|
5
|
+
let(:partner_id) { "Testa" }
|
6
|
+
let(:request_id) { "test1" }
|
7
|
+
let(:amount) { 10 }
|
8
|
+
let(:currency) { AGCOD::CreateGiftCard::CURRENCIES.first }
|
9
|
+
let(:response) { spy }
|
10
|
+
let(:httpable) { HTTP }
|
11
|
+
|
12
|
+
before do
|
13
|
+
AGCOD.configure do |config|
|
14
|
+
config.partner_id = partner_id
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
context ".new" do
|
19
|
+
context "when currency available" do
|
20
|
+
it "makes create request" do
|
21
|
+
expect(AGCOD::Request).to receive(:new) do |httpable, action, params|
|
22
|
+
expect(httpable).to eq(HTTP)
|
23
|
+
expect(action).to eq("CreateGiftCard")
|
24
|
+
expect(params["creationRequestId"]).to eq(request_id)
|
25
|
+
expect(params["value"]).to eq(
|
26
|
+
"currencyCode" => currency,
|
27
|
+
"amount" => amount
|
28
|
+
)
|
29
|
+
end.and_return(response)
|
30
|
+
|
31
|
+
AGCOD::CreateGiftCard.new(httpable, request_id, amount, currency)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
context "when currency not available" do
|
36
|
+
let(:currency) { "NOTEXIST" }
|
37
|
+
|
38
|
+
it "raises error" do
|
39
|
+
expect {
|
40
|
+
AGCOD::CreateGiftCard.new(httpable, request_id, amount, currency)
|
41
|
+
}.to raise_error(
|
42
|
+
AGCOD::CreateGiftCardError,
|
43
|
+
"Currency #{currency} not supported, available types are #{AGCOD::CreateGiftCard::CURRENCIES.join(", ")}"
|
44
|
+
)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
shared_context "request with response" do
|
50
|
+
let(:claim_code) { "FOO" }
|
51
|
+
let(:expiration_date) { "Wed Mar 12 22:59:59 UTC 2025" }
|
52
|
+
let(:gc_id) { "BAR" }
|
53
|
+
let(:creation_request_id) { "BAZ" }
|
54
|
+
let(:status) { "SUCCESS" }
|
55
|
+
let(:payload) { {"gcClaimCode" => claim_code, "gcId" => gc_id, "creationRequestId" => creation_request_id, "gcExpirationDate" => expiration_date} }
|
56
|
+
let(:request) { AGCOD::CreateGiftCard.new(httpable, request_id, amount, currency) }
|
57
|
+
|
58
|
+
before do
|
59
|
+
allow(AGCOD::Request).to receive(:new) { double(response: response) }
|
60
|
+
allow(response).to receive(:payload) { payload }
|
61
|
+
allow(response).to receive(:status) { status }
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
context "#claim_code" do
|
66
|
+
include_context "request with response"
|
67
|
+
|
68
|
+
it "returns claim_code" do
|
69
|
+
expect(request.claim_code).to eq(claim_code)
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
context "#expiration_date" do
|
74
|
+
include_context "request with response"
|
75
|
+
|
76
|
+
it "returns expiration_date" do
|
77
|
+
expect(request.expiration_date).to eq(Time.parse expiration_date)
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
context "#gc_id" do
|
82
|
+
include_context "request with response"
|
83
|
+
|
84
|
+
it "returns gc_id" do
|
85
|
+
expect(request.gc_id).to eq(gc_id)
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
context "#request_id" do
|
90
|
+
include_context "request with response"
|
91
|
+
|
92
|
+
it "returns creation request_id" do
|
93
|
+
expect(request.request_id).to eq(creation_request_id)
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
context "#status" do
|
98
|
+
include_context "request with response"
|
99
|
+
|
100
|
+
it "returns the response status" do
|
101
|
+
expect(request.status).to eq(status)
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
@@ -0,0 +1,62 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'aws_agcod/get_available_funds'
|
3
|
+
require 'ostruct'
|
4
|
+
|
5
|
+
describe AGCOD::GetAvailableFunds do
|
6
|
+
let(:partner_id) { 'Testa' }
|
7
|
+
let(:currency) { AGCOD::CreateGiftCard::CURRENCIES.first }
|
8
|
+
let(:httpable) { HTTP }
|
9
|
+
let(:timestamp) { '20180323T233815Z' }
|
10
|
+
let(:status) { 'SUCCESS' }
|
11
|
+
let(:currency_code) { 'USD' }
|
12
|
+
let(:amount) { 0.0 }
|
13
|
+
OpenStruct.new(
|
14
|
+
first_name: OpenStruct.new({
|
15
|
+
primary: OpenStruct.new({
|
16
|
+
first_name: 'Albus',
|
17
|
+
}),
|
18
|
+
}),
|
19
|
+
)
|
20
|
+
let(:payload) { { "availableFunds" => { "amount" => amount, "currencyCode" => currency_code }, "status" => status, "timestamp" => timestamp } }
|
21
|
+
|
22
|
+
let(:request_response) {
|
23
|
+
OpenStruct.new(response:
|
24
|
+
OpenStruct.new(payload:
|
25
|
+
{
|
26
|
+
"availableFunds" => [
|
27
|
+
{
|
28
|
+
"amount" => amount,
|
29
|
+
"currencyCode" => currency_code
|
30
|
+
}
|
31
|
+
],
|
32
|
+
"status" => status,
|
33
|
+
"timestamp" => timestamp
|
34
|
+
}
|
35
|
+
)
|
36
|
+
)
|
37
|
+
}
|
38
|
+
|
39
|
+
subject { described_class.new(httpable, partner_id) }
|
40
|
+
|
41
|
+
before do
|
42
|
+
AGCOD.configure do |config|
|
43
|
+
config.partner_id = partner_id
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
context '.new' do
|
48
|
+
it 'makes request' do
|
49
|
+
expect(AGCOD::Request).to receive(:new) do |httpable, action, params|
|
50
|
+
expect(httpable).to eq(HTTP)
|
51
|
+
expect(action).to eq('GetAvailableFunds')
|
52
|
+
expect(params['partnerId']).to eq(partner_id)
|
53
|
+
end.and_return(request_response)
|
54
|
+
|
55
|
+
expect(subject.available_funds.first.currency_code).to eq currency
|
56
|
+
expect(subject.available_funds.first.amount).to eq amount
|
57
|
+
expect(subject.timestamp).to eq Time.parse(timestamp)
|
58
|
+
expect(subject.status).to eq status
|
59
|
+
expect(subject.success?).to eq true
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
@@ -0,0 +1,75 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
require "aws_agcod/gift_card_activity_list"
|
3
|
+
|
4
|
+
describe AGCOD::GiftCardActivityList do
|
5
|
+
let(:partner_id) { "Testa" }
|
6
|
+
let(:request_id) { "test1" }
|
7
|
+
let(:start_time) { double("start_time") }
|
8
|
+
let(:end_time) { double("end_time") }
|
9
|
+
let(:page) { 1 }
|
10
|
+
let(:per_page) { AGCOD::GiftCardActivityList::LIMIT }
|
11
|
+
let(:show_no_ops) { true }
|
12
|
+
let(:response) { spy }
|
13
|
+
let(:httpable) { HTTP }
|
14
|
+
|
15
|
+
before do
|
16
|
+
AGCOD.configure do |config|
|
17
|
+
config.partner_id = partner_id
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
context ".new" do
|
22
|
+
it "makes request" do
|
23
|
+
expect(start_time).to receive(:strftime).with(
|
24
|
+
AGCOD::GiftCardActivityList::TIME_FORMAT
|
25
|
+
).and_return(start_time)
|
26
|
+
|
27
|
+
expect(end_time).to receive(:strftime).with(
|
28
|
+
AGCOD::GiftCardActivityList::TIME_FORMAT
|
29
|
+
).and_return(end_time)
|
30
|
+
|
31
|
+
expect(AGCOD::Request).to receive(:new) do |_, action, params|
|
32
|
+
expect(action).to eq("GetGiftCardActivityPage")
|
33
|
+
expect(params["requestId"]).to eq(request_id)
|
34
|
+
expect(params["utcStartDate"]).to eq(start_time)
|
35
|
+
expect(params["utcEndDate"]).to eq(end_time)
|
36
|
+
expect(params["pageIndex"]).to eq((page - 1) * per_page)
|
37
|
+
expect(params["pageSize"]).to eq(per_page)
|
38
|
+
expect(params["showNoOps"]).to eq(show_no_ops)
|
39
|
+
end.and_return(response)
|
40
|
+
|
41
|
+
AGCOD::GiftCardActivityList.new(httpable, request_id, start_time, end_time, page, per_page, show_no_ops)
|
42
|
+
end
|
43
|
+
|
44
|
+
context "when request per_page reaches limit" do
|
45
|
+
let(:per_page) { AGCOD::GiftCardActivityList::LIMIT + 1 }
|
46
|
+
|
47
|
+
it "raises error" do
|
48
|
+
expect {
|
49
|
+
AGCOD::GiftCardActivityList.new(httpable, request_id, start_time, end_time, page, per_page, show_no_ops)
|
50
|
+
}.to raise_error(
|
51
|
+
AGCOD::GiftCardActivityListError,
|
52
|
+
"Only #{AGCOD::GiftCardActivityList::LIMIT} records allowed per request."
|
53
|
+
)
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
context "#results" do
|
59
|
+
let(:payload) { { "cardActivityList" => [spy] } }
|
60
|
+
let(:request) { AGCOD::GiftCardActivityList.new(httpable, request_id, start_time, end_time, page, per_page, show_no_ops) }
|
61
|
+
|
62
|
+
before do
|
63
|
+
allow(start_time).to receive(:strftime)
|
64
|
+
allow(end_time).to receive(:strftime)
|
65
|
+
allow(AGCOD::Request).to receive(:new) { double(response: response) }
|
66
|
+
allow(response).to receive(:payload) { payload }
|
67
|
+
end
|
68
|
+
|
69
|
+
it "returns GiftCardActivity instances" do
|
70
|
+
request.results.each do |item|
|
71
|
+
expect(item).to be_a(AGCOD::GiftCardActivity)
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
@@ -0,0 +1,79 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
require "aws_agcod/request"
|
3
|
+
|
4
|
+
describe AGCOD::Request do
|
5
|
+
let(:action) { "Foo" }
|
6
|
+
let(:params) { {} }
|
7
|
+
let(:signature) { double("Signature") }
|
8
|
+
let(:signed_headers) { double("signed_headers") }
|
9
|
+
let(:base_uri) { "https://example.com" }
|
10
|
+
let(:partner_id) { "BAR" }
|
11
|
+
let(:config) { double(uri: base_uri, partner_id: partner_id) }
|
12
|
+
let(:httpable) { HTTP }
|
13
|
+
|
14
|
+
context "#new" do
|
15
|
+
before do
|
16
|
+
allow(AGCOD).to receive(:config) { config }
|
17
|
+
allow(AGCOD::Signature).to receive(:new).with(config) { signature }
|
18
|
+
end
|
19
|
+
|
20
|
+
context "with creationRequestId as special testing value" do
|
21
|
+
let(:params) { { creationRequestId: creationRequestId } }
|
22
|
+
|
23
|
+
subject { AGCOD::Request.new(httpable, action, params) }
|
24
|
+
|
25
|
+
before do
|
26
|
+
allow(signature).to receive(:sign).and_return(signed_headers)
|
27
|
+
end
|
28
|
+
|
29
|
+
context "with special creationRequestId F0000" do
|
30
|
+
let(:creationRequestId) { "F0000" }
|
31
|
+
|
32
|
+
it "does not add partnerId to creationRequestId" do
|
33
|
+
expect(HTTP).to receive(:post) do |_, options|
|
34
|
+
expect(JSON.parse(options[:body])["creationRequestId"]).to eq("F0000")
|
35
|
+
end.and_return(double(body: params.to_json))
|
36
|
+
subject
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
context "with special creationRequestId F2005" do
|
41
|
+
let(:creationRequestId) { "F2005" }
|
42
|
+
|
43
|
+
it "does not add partnerId to creationRequestId" do
|
44
|
+
expect(HTTP).to receive(:post) do |_, options|
|
45
|
+
expect(JSON.parse(options[:body])["creationRequestId"]).to eq("F2005")
|
46
|
+
end.and_return(double(body: params.to_json))
|
47
|
+
subject
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
it "sends post request to endpoint uri" do
|
53
|
+
expect(signature).to receive(:sign) do |uri, headers, body|
|
54
|
+
expect(uri).to eq(URI("#{base_uri}/#{action}"))
|
55
|
+
expect(headers.keys).to match_array(%w(content-type x-amz-date accept host x-amz-target date))
|
56
|
+
expect(headers["content-type"]).to eq("application/json")
|
57
|
+
expect(headers["x-amz-target"]).to eq("com.amazonaws.agcod.AGCODService.#{action}")
|
58
|
+
expect(JSON.parse(body)["partnerId"]).to eq(partner_id)
|
59
|
+
end.and_return(signed_headers)
|
60
|
+
|
61
|
+
expect(HTTP).to receive(:post) do |uri, options|
|
62
|
+
expect(uri).to eq(URI("#{base_uri}/#{action}"))
|
63
|
+
expect(JSON.parse(options[:body])["partnerId"]).to eq(partner_id)
|
64
|
+
expect(options[:headers]).to eq(signed_headers)
|
65
|
+
end.and_return(double(body: params.to_json))
|
66
|
+
|
67
|
+
AGCOD::Request.new(httpable, action, params)
|
68
|
+
end
|
69
|
+
|
70
|
+
it "sets response" do
|
71
|
+
expect(signature).to receive(:sign) { signed_headers }
|
72
|
+
expect(HTTP).to receive(:post) { (double(body: params.to_json)) }
|
73
|
+
|
74
|
+
response = AGCOD::Request.new(httpable, action, params).response
|
75
|
+
|
76
|
+
expect(response).to be_a(AGCOD::Response)
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
@@ -0,0 +1,66 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
require "aws_agcod/response"
|
3
|
+
|
4
|
+
describe AGCOD::Response do
|
5
|
+
let(:payload) { { foo: "bar" }.to_json }
|
6
|
+
|
7
|
+
context "#new" do
|
8
|
+
it "sets payload and status" do
|
9
|
+
response = AGCOD::Response.new(payload)
|
10
|
+
|
11
|
+
expect(response.payload).not_to be_nil
|
12
|
+
expect(response.status).not_to be_nil
|
13
|
+
end
|
14
|
+
|
15
|
+
context "when no status in payload" do
|
16
|
+
it "sets status to failure" do
|
17
|
+
expect(AGCOD::Response.new(payload).status).to eq("FAILURE")
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
context "when has status in payload" do
|
22
|
+
let(:status) { "foo" }
|
23
|
+
let(:payload) { { status: status }.to_json }
|
24
|
+
|
25
|
+
it "sets status as payload's status" do
|
26
|
+
expect(AGCOD::Response.new(payload).status).to eq(status)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
context "when has agcodResponse in payload" do
|
31
|
+
let(:status) { "foo" }
|
32
|
+
let(:payload) { { agcodResponse: { status: status } }.to_json }
|
33
|
+
|
34
|
+
it "sets status as agcodResponse's status" do
|
35
|
+
expect(AGCOD::Response.new(payload).status).to eq(status)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
context "success?" do
|
41
|
+
context "when status is SUCCESS" do
|
42
|
+
let(:payload) { { status: "SUCCESS" }.to_json }
|
43
|
+
|
44
|
+
it "returns true" do
|
45
|
+
expect(AGCOD::Response.new(payload).success?).to be_truthy
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
context "when status is not SUCCESS" do
|
50
|
+
it "returns false" do
|
51
|
+
expect(AGCOD::Response.new(payload).success?).to be_falsey
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
context "error_message" do
|
57
|
+
let(:error_code) { "foo" }
|
58
|
+
let(:error_type) { "bar" }
|
59
|
+
let(:error_message) { "baz" }
|
60
|
+
let(:payload) { { errorCode: error_code, errorType: error_type, message: error_message }.to_json }
|
61
|
+
|
62
|
+
it "composes error message by error code, type, and message from payload" do
|
63
|
+
expect(AGCOD::Response.new(payload).error_message).to eq("#{error_code} #{error_type} - #{error_message}")
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
require "pathname"
|
2
|
+
require "http"
|
3
|
+
|
4
|
+
ROOT_PATH = Pathname.new(__FILE__).join("../..").expand_path
|
5
|
+
$LOAD_PATH.unshift(ROOT_PATH.join("lib"))
|
6
|
+
|
7
|
+
RSpec.configure do |config|
|
8
|
+
# Run specs in random order to surface order dependencies. If you find an
|
9
|
+
# order dependency and want to debug it, you can fix the order by providing
|
10
|
+
# the seed, which is printed after each run.
|
11
|
+
# --seed 1234
|
12
|
+
config.order = "random"
|
13
|
+
|
14
|
+
# Disable the should syntax compeletely; we use the expect syntax only.
|
15
|
+
config.expect_with :rspec do |c|
|
16
|
+
c.syntax = :expect
|
17
|
+
end
|
18
|
+
end
|
metadata
ADDED
@@ -0,0 +1,135 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: aws_agcod_2
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Xenor Chang
|
8
|
+
- compwron
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2018-03-24 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: http
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
requirements:
|
18
|
+
- - ">="
|
19
|
+
- !ruby/object:Gem::Version
|
20
|
+
version: '0'
|
21
|
+
type: :runtime
|
22
|
+
prerelease: false
|
23
|
+
version_requirements: !ruby/object:Gem::Requirement
|
24
|
+
requirements:
|
25
|
+
- - ">="
|
26
|
+
- !ruby/object:Gem::Version
|
27
|
+
version: '0'
|
28
|
+
- !ruby/object:Gem::Dependency
|
29
|
+
name: bundler
|
30
|
+
requirement: !ruby/object:Gem::Requirement
|
31
|
+
requirements:
|
32
|
+
- - ">="
|
33
|
+
- !ruby/object:Gem::Version
|
34
|
+
version: '0'
|
35
|
+
type: :development
|
36
|
+
prerelease: false
|
37
|
+
version_requirements: !ruby/object:Gem::Requirement
|
38
|
+
requirements:
|
39
|
+
- - ">="
|
40
|
+
- !ruby/object:Gem::Version
|
41
|
+
version: '0'
|
42
|
+
- !ruby/object:Gem::Dependency
|
43
|
+
name: rake
|
44
|
+
requirement: !ruby/object:Gem::Requirement
|
45
|
+
requirements:
|
46
|
+
- - "~>"
|
47
|
+
- !ruby/object:Gem::Version
|
48
|
+
version: '12'
|
49
|
+
type: :development
|
50
|
+
prerelease: false
|
51
|
+
version_requirements: !ruby/object:Gem::Requirement
|
52
|
+
requirements:
|
53
|
+
- - "~>"
|
54
|
+
- !ruby/object:Gem::Version
|
55
|
+
version: '12'
|
56
|
+
- !ruby/object:Gem::Dependency
|
57
|
+
name: rspec
|
58
|
+
requirement: !ruby/object:Gem::Requirement
|
59
|
+
requirements:
|
60
|
+
- - "~>"
|
61
|
+
- !ruby/object:Gem::Version
|
62
|
+
version: '3'
|
63
|
+
type: :development
|
64
|
+
prerelease: false
|
65
|
+
version_requirements: !ruby/object:Gem::Requirement
|
66
|
+
requirements:
|
67
|
+
- - "~>"
|
68
|
+
- !ruby/object:Gem::Version
|
69
|
+
version: '3'
|
70
|
+
description: |-
|
71
|
+
Amazon Gift Code On Demand (AGCOD) API v2 implementation for
|
72
|
+
distribute Amazon gift cards (gift codes) instantly in any denomination
|
73
|
+
email:
|
74
|
+
- xenor@listia.com
|
75
|
+
executables: []
|
76
|
+
extensions: []
|
77
|
+
extra_rdoc_files: []
|
78
|
+
files:
|
79
|
+
- LICENSE.txt
|
80
|
+
- README.md
|
81
|
+
- Rakefile
|
82
|
+
- lib/aws_agcod.rb
|
83
|
+
- lib/aws_agcod/available_funds.rb
|
84
|
+
- lib/aws_agcod/cancel_gift_card.rb
|
85
|
+
- lib/aws_agcod/config.rb
|
86
|
+
- lib/aws_agcod/create_gift_card.rb
|
87
|
+
- lib/aws_agcod/get_available_funds.rb
|
88
|
+
- lib/aws_agcod/gift_card_activity_list.rb
|
89
|
+
- lib/aws_agcod/request.rb
|
90
|
+
- lib/aws_agcod/response.rb
|
91
|
+
- lib/aws_agcod/signature.rb
|
92
|
+
- lib/aws_agcod/version.rb
|
93
|
+
- spec/aws_agcod/cancel_gift_card_spec.rb
|
94
|
+
- spec/aws_agcod/config_spec.rb
|
95
|
+
- spec/aws_agcod/create_gift_card_spec.rb
|
96
|
+
- spec/aws_agcod/get_available_funds_spec.rb
|
97
|
+
- spec/aws_agcod/gift_card_activity_list_spec.rb
|
98
|
+
- spec/aws_agcod/request_spec.rb
|
99
|
+
- spec/aws_agcod/response_spec.rb
|
100
|
+
- spec/aws_agcod_spec.rb
|
101
|
+
- spec/spec_helper.rb
|
102
|
+
homepage: https://github.com/compwron/aws_agcod
|
103
|
+
licenses:
|
104
|
+
- MIT
|
105
|
+
metadata: {}
|
106
|
+
post_install_message:
|
107
|
+
rdoc_options: []
|
108
|
+
require_paths:
|
109
|
+
- lib
|
110
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
111
|
+
requirements:
|
112
|
+
- - ">="
|
113
|
+
- !ruby/object:Gem::Version
|
114
|
+
version: '0'
|
115
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
116
|
+
requirements:
|
117
|
+
- - ">="
|
118
|
+
- !ruby/object:Gem::Version
|
119
|
+
version: '0'
|
120
|
+
requirements: []
|
121
|
+
rubyforge_project:
|
122
|
+
rubygems_version: 2.7.6
|
123
|
+
signing_key:
|
124
|
+
specification_version: 4
|
125
|
+
summary: AWS AGCOD API v2 endpoints implementation
|
126
|
+
test_files:
|
127
|
+
- spec/aws_agcod/cancel_gift_card_spec.rb
|
128
|
+
- spec/aws_agcod/config_spec.rb
|
129
|
+
- spec/aws_agcod/create_gift_card_spec.rb
|
130
|
+
- spec/aws_agcod/get_available_funds_spec.rb
|
131
|
+
- spec/aws_agcod/gift_card_activity_list_spec.rb
|
132
|
+
- spec/aws_agcod/request_spec.rb
|
133
|
+
- spec/aws_agcod/response_spec.rb
|
134
|
+
- spec/aws_agcod_spec.rb
|
135
|
+
- spec/spec_helper.rb
|