cashstar-ruby 0.1.7
Sign up to get free protection for your applications and to get access to all the features.
- data/.rspec +2 -0
- data/.ruby-gemset +1 -0
- data/.ruby-version +1 -0
- data/Gemfile +5 -0
- data/Gemfile.lock +48 -0
- data/README.md +47 -0
- data/Rakefile +2 -0
- data/cashstar.gemspec +31 -0
- data/lib/.DS_Store +0 -0
- data/lib/cashstar.rb +28 -0
- data/lib/cashstar/.DS_Store +0 -0
- data/lib/cashstar/api.rb +24 -0
- data/lib/cashstar/authentication.rb +23 -0
- data/lib/cashstar/client.rb +24 -0
- data/lib/cashstar/client/catalog.rb +12 -0
- data/lib/cashstar/client/faceplates.rb +14 -0
- data/lib/cashstar/client/gift_card.rb +41 -0
- data/lib/cashstar/client/merchants.rb +13 -0
- data/lib/cashstar/client/order.rb +30 -0
- data/lib/cashstar/configuration.rb +83 -0
- data/lib/cashstar/connection.rb +46 -0
- data/lib/cashstar/error.rb +36 -0
- data/lib/cashstar/request.rb +43 -0
- data/lib/cashstar/version.rb +3 -0
- data/lib/faraday/request/basic_auth.rb +17 -0
- data/lib/faraday/request/gateway.rb +18 -0
- data/lib/faraday/response/raise_http_4xx.rb +45 -0
- data/lib/faraday/response/raise_http_5xx.rb +24 -0
- data/lib/faraday/response/strip_card_numbers.rb +20 -0
- data/spec/fixtures/merchants.json +17 -0
- data/spec/integration/client/merchants_spec.rb +5 -0
- data/spec/integration/get_merchants_spec.rb +20 -0
- data/spec/spec_helper.rb +19 -0
- metadata +211 -0
data/.rspec
ADDED
data/.ruby-gemset
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
cashstar-ruby
|
data/.ruby-version
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
1.9.3
|
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,48 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
cashstar-ruby (0.1.7)
|
5
|
+
faraday (~> 0.8.0)
|
6
|
+
faraday_middleware (~> 0.8.0)
|
7
|
+
hashie (~> 1.2.0)
|
8
|
+
multi_json (~> 1.8.0)
|
9
|
+
multi_xml (~> 0.5.0)
|
10
|
+
|
11
|
+
GEM
|
12
|
+
remote: http://rubygems.org/
|
13
|
+
specs:
|
14
|
+
addressable (2.3.2)
|
15
|
+
crack (0.3.2)
|
16
|
+
diff-lcs (1.1.3)
|
17
|
+
faraday (0.8.9)
|
18
|
+
multipart-post (~> 1.2.0)
|
19
|
+
faraday_middleware (0.8.8)
|
20
|
+
faraday (>= 0.7.4, < 0.9)
|
21
|
+
hashie (1.2.0)
|
22
|
+
metaclass (0.0.1)
|
23
|
+
mocha (0.13.1)
|
24
|
+
metaclass (~> 0.0.1)
|
25
|
+
multi_json (1.8.4)
|
26
|
+
multi_xml (0.5.5)
|
27
|
+
multipart-post (1.2.0)
|
28
|
+
rspec (2.12.0)
|
29
|
+
rspec-core (~> 2.12.0)
|
30
|
+
rspec-expectations (~> 2.12.0)
|
31
|
+
rspec-mocks (~> 2.12.0)
|
32
|
+
rspec-core (2.12.2)
|
33
|
+
rspec-expectations (2.12.1)
|
34
|
+
diff-lcs (~> 1.1.3)
|
35
|
+
rspec-mocks (2.12.1)
|
36
|
+
webmock (1.9.0)
|
37
|
+
addressable (>= 2.2.7)
|
38
|
+
crack (>= 0.1.7)
|
39
|
+
|
40
|
+
PLATFORMS
|
41
|
+
java
|
42
|
+
ruby
|
43
|
+
|
44
|
+
DEPENDENCIES
|
45
|
+
cashstar-ruby!
|
46
|
+
mocha (~> 0.13)
|
47
|
+
rspec (~> 2.12)
|
48
|
+
webmock (~> 1.9)
|
data/README.md
ADDED
@@ -0,0 +1,47 @@
|
|
1
|
+
# A CashStar Ruby Gem
|
2
|
+
A Ruby wrapper for the CashStar REST API
|
3
|
+
|
4
|
+
## <a name="installation">Installation</a>
|
5
|
+
gem install cashstar
|
6
|
+
|
7
|
+
## <a name="Full API Docs">Full Documentation</a>
|
8
|
+
please consult your CashStar API documentation for full use cases and support
|
9
|
+
|
10
|
+
## <a name="Notes">Current Limitations</a>
|
11
|
+
as of v0.1.2, this gems supports json only and only one gift card is supported per order.
|
12
|
+
|
13
|
+
## <a name="examples">Usage Examples</a>
|
14
|
+
require "cashstar"
|
15
|
+
|
16
|
+
# Configure your CashStar settings - for Rails, typically in /config/initializers/cashstar.rb
|
17
|
+
# Optionally, store your credentials for each environment in a cashstar.yml file and load from there.
|
18
|
+
|
19
|
+
Cashstar.configure do |config|
|
20
|
+
config.username = 'username'
|
21
|
+
config.password = 'password'
|
22
|
+
config.endpoint = 'production or semi-production url'
|
23
|
+
config.format = 'json' #or 'xml'
|
24
|
+
end
|
25
|
+
|
26
|
+
# Gift Card numbers are not returned by default - only urls to the hosted Gift Card and the associated challenge phrase
|
27
|
+
# If you need the gift card number and pin, include the following in your config block:
|
28
|
+
|
29
|
+
config.return_card_numbers = true
|
30
|
+
|
31
|
+
# Get all merchants enabled for this account
|
32
|
+
puts Cashstar.merchants
|
33
|
+
|
34
|
+
# Get all faceplates for a merchant
|
35
|
+
puts Cashstar.faceplates(:merchant_code)
|
36
|
+
|
37
|
+
# Build an Order Entity
|
38
|
+
# An order is composed of one or many gift card entities, which are in turn composed of delivery and message entities
|
39
|
+
delivery = Cashstar::Client::Delivery.new(:delivered_by => :CLIENT)
|
40
|
+
message = Cashstar::Client::Message.new(:body => 'Thanks for all the hard work!', :from => 'Santa Claus', :to => 'Rudolph')
|
41
|
+
gift_card = Cashstar::Client::GiftCard.new(:merchant_code => 'GAP', :initial_balance => '100.00', :delivery => delivery, :message => message)
|
42
|
+
order = Cashstar::Client::Order.new(:audit_number => '123456', :gift_card => gift_card) #Audit Number is required
|
43
|
+
|
44
|
+
|
45
|
+
# Issue the built order
|
46
|
+
puts Cashstar.issue(order)
|
47
|
+
|
data/Rakefile
ADDED
data/cashstar.gemspec
ADDED
@@ -0,0 +1,31 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
$:.push File.expand_path("../lib", __FILE__)
|
3
|
+
require "cashstar/version"
|
4
|
+
|
5
|
+
Gem::Specification.new do |s|
|
6
|
+
s.name = "cashstar-ruby"
|
7
|
+
s.version = Cashstar::VERSION
|
8
|
+
s.platform = Gem::Platform::RUBY
|
9
|
+
s.authors = ["Charlie White"]
|
10
|
+
s.email = ["cwhite@cashstar.com"]
|
11
|
+
s.homepage = "http://www.cashstar.com"
|
12
|
+
s.summary = %q{Ruby Bindings for the CashStar API}
|
13
|
+
s.description = %q{CashStar's API provides a simple interface for purchasing and issuing electronic gift cards from a variety of brands}
|
14
|
+
s.rubyforge_project = "cashstar-ruby"
|
15
|
+
|
16
|
+
s.files = `git ls-files`.split("\n")
|
17
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
18
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
19
|
+
s.require_paths = ["lib"]
|
20
|
+
#s.files = Dir['lib/**/*.rb']
|
21
|
+
|
22
|
+
s.add_dependency 'hashie', '~> 1.2.0'
|
23
|
+
s.add_dependency 'faraday', '~> 0.8.0'
|
24
|
+
s.add_dependency 'faraday_middleware', '~> 0.8.0'
|
25
|
+
s.add_dependency 'multi_json', '~> 1.8.0'
|
26
|
+
s.add_dependency 'multi_xml', '~> 0.5.0'
|
27
|
+
|
28
|
+
s.add_development_dependency 'rspec', '~> 2.12'
|
29
|
+
s.add_development_dependency 'mocha', '~> 0.13'
|
30
|
+
s.add_development_dependency 'webmock', '~> 1.9'
|
31
|
+
end
|
data/lib/.DS_Store
ADDED
Binary file
|
data/lib/cashstar.rb
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
require 'cashstar/api'
|
2
|
+
require 'cashstar/client'
|
3
|
+
require 'cashstar/configuration'
|
4
|
+
require 'cashstar/error'
|
5
|
+
|
6
|
+
|
7
|
+
module Cashstar
|
8
|
+
extend Configuration
|
9
|
+
class << self
|
10
|
+
# Alias for Cashstar::Client.new
|
11
|
+
#
|
12
|
+
# @return [Cashstar::Client]
|
13
|
+
def new(options={})
|
14
|
+
Cashstar::Client.new(options)
|
15
|
+
end
|
16
|
+
|
17
|
+
private
|
18
|
+
# Delegate to Cashstar::Client
|
19
|
+
def method_missing(method, *args, &block)
|
20
|
+
return super unless new.respond_to?(method)
|
21
|
+
new.send(method, *args, &block)
|
22
|
+
end
|
23
|
+
|
24
|
+
def respond_to?(method, include_private = false)
|
25
|
+
new.respond_to?(method, include_private) || super(method, include_private)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
Binary file
|
data/lib/cashstar/api.rb
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
require 'cashstar/authentication'
|
2
|
+
require 'cashstar/configuration'
|
3
|
+
require 'cashstar/connection'
|
4
|
+
require 'cashstar/request'
|
5
|
+
|
6
|
+
module Cashstar
|
7
|
+
# @private
|
8
|
+
class API
|
9
|
+
include Connection
|
10
|
+
include Request
|
11
|
+
include Authentication
|
12
|
+
|
13
|
+
# @private
|
14
|
+
attr_accessor *Configuration::VALID_OPTIONS_KEYS
|
15
|
+
|
16
|
+
# Creates a new API
|
17
|
+
def initialize(options={})
|
18
|
+
options = Cashstar.options.merge(options)
|
19
|
+
Configuration::VALID_OPTIONS_KEYS.each do |key|
|
20
|
+
send("#{key}=", options[key])
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module Cashstar
|
2
|
+
# @private
|
3
|
+
module Authentication
|
4
|
+
private
|
5
|
+
|
6
|
+
# Authentication hash
|
7
|
+
#
|
8
|
+
# @return [Hash]
|
9
|
+
def authentication
|
10
|
+
{
|
11
|
+
:username => username,
|
12
|
+
:password => password,
|
13
|
+
}
|
14
|
+
end
|
15
|
+
|
16
|
+
# Check whether user is authenticated
|
17
|
+
#
|
18
|
+
# @return [Boolean]
|
19
|
+
def authenticated?
|
20
|
+
authentication.values.all?
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module Cashstar
|
2
|
+
# Wrapper for the CashStar REST API
|
3
|
+
#
|
4
|
+
# @note All methods have been separated into modules
|
5
|
+
class Client < API
|
6
|
+
# Require client method modules after initializing the Client class in
|
7
|
+
# order to avoid a superclass mismatch error, allowing those modules to be
|
8
|
+
# Client-namespaced.
|
9
|
+
require 'cashstar/client/merchants'
|
10
|
+
require 'cashstar/client/catalog'
|
11
|
+
require 'cashstar/client/faceplates'
|
12
|
+
require 'cashstar/client/order'
|
13
|
+
require 'cashstar/client/gift_card'
|
14
|
+
|
15
|
+
|
16
|
+
alias :api_endpoint :endpoint
|
17
|
+
|
18
|
+
include Cashstar::Client::Merchants
|
19
|
+
include Cashstar::Client::Faceplates
|
20
|
+
include Cashstar::Client::Catalog
|
21
|
+
include Cashstar::Client::OrderMethods
|
22
|
+
include Cashstar::Client::GiftCardMethods
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
module Cashstar
|
2
|
+
class Client
|
3
|
+
# Defines methods related to a Cashstar Order
|
4
|
+
module Catalog
|
5
|
+
|
6
|
+
def catalog(merchant_code)
|
7
|
+
response = get("/v2/merchant/#{merchant_code}/catalog/")
|
8
|
+
format.to_s.downcase == 'xml' ? response['catalog'] : response['catalog']
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
module Cashstar
|
2
|
+
class Client
|
3
|
+
# Defines methods related to a Cashstar Order
|
4
|
+
module Faceplates
|
5
|
+
|
6
|
+
def faceplates(merchant_code)
|
7
|
+
response = get("/v2/merchant/#{merchant_code}/faceplate/")
|
8
|
+
format.to_s.downcase == 'xml' ? response['merchant'] : response['faceplates']['faceplate']
|
9
|
+
end
|
10
|
+
|
11
|
+
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
require 'hashie'
|
2
|
+
|
3
|
+
module Cashstar
|
4
|
+
class Client
|
5
|
+
module GiftCardMethods
|
6
|
+
def balance_inquiry(merchant, egc_code)
|
7
|
+
response = get("/v2/merchant/#{merchant}/egc/#{egc_code}/balance/")
|
8
|
+
format.to_s.downcase == 'xml' ? response['egc'] : response['egc']
|
9
|
+
end
|
10
|
+
|
11
|
+
def cancel(merchant, egc_code)
|
12
|
+
response = delete("/v2/merchant/#{merchant}/egc/#{egc_code}/")
|
13
|
+
format.to_s.downcase == 'xml' ? response['egc'] : response['egc']
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
# Defines methods related to a Cashstar Order
|
18
|
+
class GiftCard < Hashie::Dash
|
19
|
+
property :merchant_code, :required => true
|
20
|
+
property :initial_balance, :required => true
|
21
|
+
property :currency, :default => 'USD'
|
22
|
+
property :challenge
|
23
|
+
property :challenge_description
|
24
|
+
property :delivery
|
25
|
+
property :message
|
26
|
+
end
|
27
|
+
|
28
|
+
class Delivery < Hashie::Dash
|
29
|
+
property :delivered_by, :default => 'CASHSTAR'
|
30
|
+
property :method
|
31
|
+
property :target
|
32
|
+
property :scheduled
|
33
|
+
end
|
34
|
+
|
35
|
+
class Message < Hashie::Dash
|
36
|
+
property :from
|
37
|
+
property :to
|
38
|
+
property :body
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
module Cashstar
|
2
|
+
class Client
|
3
|
+
# Defines methods related to Cashstar merchants
|
4
|
+
module Merchants
|
5
|
+
|
6
|
+
def merchants
|
7
|
+
response = get("/v2/merchant/")
|
8
|
+
format.to_s.downcase == 'xml' ? response['merchant'] : response['merchants']['merchant']
|
9
|
+
end
|
10
|
+
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
require 'hashie'
|
2
|
+
|
3
|
+
|
4
|
+
module Cashstar
|
5
|
+
class Client
|
6
|
+
module OrderMethods
|
7
|
+
def issue(order)
|
8
|
+
response = post("/v2/order/", order.to_json)
|
9
|
+
format.to_s.downcase == 'xml' ? response['order'] : response['order']
|
10
|
+
end
|
11
|
+
|
12
|
+
def return(order)
|
13
|
+
true
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
# Defines methods related to a Cashstar Order
|
18
|
+
class Order < Hashie::Dash
|
19
|
+
property :audit_number, :required => true
|
20
|
+
property :gift_card, :required => true
|
21
|
+
property :payment, :default => nil
|
22
|
+
|
23
|
+
def to_json()
|
24
|
+
"{ \"order\" : { \"audit_number\" : \"#{self.audit_number}\", \"egc\" : #{self.gift_card.to_json}}}"
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,83 @@
|
|
1
|
+
require 'cashstar/version'
|
2
|
+
|
3
|
+
module Cashstar
|
4
|
+
# Defines constants and methods related to configuration
|
5
|
+
module Configuration
|
6
|
+
# An array of valid keys in the options hash when configuring a {Cashstar::API}
|
7
|
+
VALID_OPTIONS_KEYS = [
|
8
|
+
:username,
|
9
|
+
:password,
|
10
|
+
:endpoint,
|
11
|
+
:return_card_numbers,
|
12
|
+
:format,
|
13
|
+
:user_agent,
|
14
|
+
:adapter,
|
15
|
+
:faraday_options].freeze
|
16
|
+
|
17
|
+
# The adapter that will be used to connect if none is set
|
18
|
+
DEFAULT_ADAPTER = :net_http
|
19
|
+
|
20
|
+
# By default, don't set a username
|
21
|
+
DEFAULT_USERNAME = nil
|
22
|
+
|
23
|
+
# By default, don't set a password
|
24
|
+
DEFAULT_PASSWORD = nil
|
25
|
+
|
26
|
+
# The endpoint that will be used to connect if none is set
|
27
|
+
#
|
28
|
+
# @note This is configurable in case you want to connect to CashStar's test environment at https://api-semiprod.cashstar.com
|
29
|
+
DEFAULT_ENDPOINT = 'https://api-semiprod.cashstar.com'.freeze
|
30
|
+
|
31
|
+
# By default, we do not pass card numbers and pins back, only url's and challenge codes. This helps default to the most
|
32
|
+
# secure mode of usage.
|
33
|
+
DEFAULT_RETURN_CARD_NUMBERS = false
|
34
|
+
|
35
|
+
# The response format appended to the path and sent in the 'Accept' header if none is set
|
36
|
+
#
|
37
|
+
# @note JSON is preferred over XML because it is more concise and faster to parse.
|
38
|
+
DEFAULT_FORMAT = :json
|
39
|
+
|
40
|
+
# The value sent in the 'User-Agent' header if none is set
|
41
|
+
DEFAULT_USER_AGENT = "CashStar Ruby Gem #{Cashstar::VERSION}".freeze
|
42
|
+
|
43
|
+
DEFAULT_FARADAY_OPTIONS = {}.freeze
|
44
|
+
|
45
|
+
# @private
|
46
|
+
attr_accessor *VALID_OPTIONS_KEYS
|
47
|
+
|
48
|
+
# When this module is extended, set all configuration options to their default values
|
49
|
+
def self.extended(base)
|
50
|
+
base.reset
|
51
|
+
end
|
52
|
+
|
53
|
+
# Convenience method to allow configuration options to be set in a block
|
54
|
+
def configure
|
55
|
+
yield self
|
56
|
+
end
|
57
|
+
|
58
|
+
# Convienince method determining if pointed to the test env.
|
59
|
+
def test?
|
60
|
+
self.endpoint == DEFAULT_ENDPOINT
|
61
|
+
end
|
62
|
+
|
63
|
+
# Create a hash of options and their values
|
64
|
+
def options
|
65
|
+
options = {}
|
66
|
+
VALID_OPTIONS_KEYS.each{|k| options[k] = send(k)}
|
67
|
+
options
|
68
|
+
end
|
69
|
+
|
70
|
+
# Reset all configuration options to defaults
|
71
|
+
def reset
|
72
|
+
self.adapter = DEFAULT_ADAPTER
|
73
|
+
self.username = DEFAULT_USERNAME
|
74
|
+
self.password = DEFAULT_PASSWORD
|
75
|
+
self.endpoint = DEFAULT_ENDPOINT
|
76
|
+
self.format = DEFAULT_FORMAT
|
77
|
+
self.user_agent = DEFAULT_USER_AGENT
|
78
|
+
self.faraday_options = DEFAULT_FARADAY_OPTIONS
|
79
|
+
self.return_card_numbers = DEFAULT_RETURN_CARD_NUMBERS
|
80
|
+
self
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
require 'faraday_middleware'
|
2
|
+
require 'faraday/request/gateway'
|
3
|
+
require 'faraday/request/basic_auth'
|
4
|
+
require 'faraday/response/raise_http_4xx'
|
5
|
+
require 'faraday/response/raise_http_5xx'
|
6
|
+
require 'faraday/response/strip_card_numbers'
|
7
|
+
|
8
|
+
module Cashstar
|
9
|
+
# @private
|
10
|
+
module Connection
|
11
|
+
private
|
12
|
+
|
13
|
+
def connection(options={})
|
14
|
+
merged_options = faraday_options.merge({
|
15
|
+
:headers => {
|
16
|
+
'Accept' => "application/json",
|
17
|
+
'User-Agent' => user_agent,
|
18
|
+
'Content-Type' => "application/json"
|
19
|
+
},
|
20
|
+
:ssl => {:verify => false},
|
21
|
+
:url => options.fetch(:endpoint, api_endpoint)
|
22
|
+
})
|
23
|
+
|
24
|
+
Faraday.new(merged_options) do |builder|
|
25
|
+
builder.use Faraday::Request::BasicAuth, authentication if authenticated?
|
26
|
+
builder.use Faraday::Request::UrlEncoded
|
27
|
+
builder.use Faraday::Response::RaiseHttp4xx
|
28
|
+
unless return_card_numbers
|
29
|
+
builder.use Faraday::Response::StripCardNumbers
|
30
|
+
end
|
31
|
+
unless options[:raw]
|
32
|
+
case options.fetch(:format, format).to_s.downcase
|
33
|
+
when 'json'
|
34
|
+
builder.use Faraday::Response::Mashify
|
35
|
+
builder.use Faraday::Response::ParseJson
|
36
|
+
when 'xml'
|
37
|
+
builder.use Faraday::Response::Mashify
|
38
|
+
builder.use Faraday::Response::ParseXml
|
39
|
+
end
|
40
|
+
end
|
41
|
+
builder.use Faraday::Response::RaiseHttp5xx
|
42
|
+
builder.adapter(adapter)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
module Cashstar
|
2
|
+
# Custom error class for rescuing from all Cashstar errors
|
3
|
+
class Error < StandardError
|
4
|
+
attr_reader :http_headers
|
5
|
+
|
6
|
+
def initialize(message, http_headers)
|
7
|
+
@http_headers = Hash[http_headers]
|
8
|
+
super message
|
9
|
+
end
|
10
|
+
|
11
|
+
end
|
12
|
+
|
13
|
+
# Raised when Cashstar returns the HTTP status code 400
|
14
|
+
class BadRequest < Error; end
|
15
|
+
|
16
|
+
# Raised when Cashstar returns the HTTP status code 401
|
17
|
+
class Unauthorized < Error; end
|
18
|
+
|
19
|
+
# Raised when Cashstar returns the HTTP status code 403
|
20
|
+
class Forbidden < Error; end
|
21
|
+
|
22
|
+
# Raised when Cashstar returns the HTTP status code 404
|
23
|
+
class NotFound < Error; end
|
24
|
+
|
25
|
+
# Raised when Cashstar returns the HTTP status code 406
|
26
|
+
class NotAcceptable < Error; end
|
27
|
+
|
28
|
+
# Raised when Cashstar returns the HTTP status code 500
|
29
|
+
class InternalServerError < Error; end
|
30
|
+
|
31
|
+
# Raised when Cashstar returns the HTTP status code 502
|
32
|
+
class BadGateway < Error; end
|
33
|
+
|
34
|
+
# Raised when Cashstar returns the HTTP status code 503
|
35
|
+
class ServiceUnavailable < Error; end
|
36
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
module Cashstar
|
2
|
+
# Defines HTTP request methods
|
3
|
+
module Request
|
4
|
+
# Perform an HTTP GET request
|
5
|
+
def get(path, params={}, options={})
|
6
|
+
request(:get, path, params, options)
|
7
|
+
end
|
8
|
+
|
9
|
+
def post(path, params={}, options={})
|
10
|
+
request(:post, path, params, options)
|
11
|
+
end
|
12
|
+
|
13
|
+
# Perform an HTTP PUT request
|
14
|
+
def put(path, params={}, options={})
|
15
|
+
request(:put, path, params, options)
|
16
|
+
end
|
17
|
+
|
18
|
+
# Perform an HTTP DELETE request
|
19
|
+
def delete(path, params={}, options={})
|
20
|
+
request(:delete, path, params, options)
|
21
|
+
end
|
22
|
+
|
23
|
+
private
|
24
|
+
|
25
|
+
# Perform an HTTP request
|
26
|
+
def request(method, path, params, options)
|
27
|
+
response = connection(options).send(method) do |request|
|
28
|
+
case method.to_sym
|
29
|
+
when :get, :delete
|
30
|
+
request.url(path, params)
|
31
|
+
when :post, :put
|
32
|
+
request.path = path
|
33
|
+
request.body = params unless params.empty?
|
34
|
+
end
|
35
|
+
end
|
36
|
+
options[:raw] ? response : response.body
|
37
|
+
end
|
38
|
+
|
39
|
+
def formatted_path(path, options={})
|
40
|
+
#[path, options.fetch(:format, format)].compact.join('.')
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
require 'faraday'
|
2
|
+
|
3
|
+
module Faraday
|
4
|
+
class Request::BasicAuth < Faraday::Middleware
|
5
|
+
require 'base64'
|
6
|
+
|
7
|
+
def call(env)
|
8
|
+
header = Base64.encode64("#{@options[:username]}:#{@options[:password]}")
|
9
|
+
env[:request_headers]['Authorization'] = "Basic #{header.to_s}"
|
10
|
+
@app.call(env)
|
11
|
+
end
|
12
|
+
|
13
|
+
def initialize(app, options)
|
14
|
+
@app, @options = app, options
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
require 'faraday'
|
2
|
+
|
3
|
+
# @private
|
4
|
+
module Faraday
|
5
|
+
# @private
|
6
|
+
class Request::Gateway < Faraday::Middleware
|
7
|
+
def call(env)
|
8
|
+
url = env[:url].dup
|
9
|
+
url.host = @gateway
|
10
|
+
env[:url] = url
|
11
|
+
@app.call(env)
|
12
|
+
end
|
13
|
+
|
14
|
+
def initialize(app, gateway)
|
15
|
+
@app, @gateway = app, gateway
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
require 'faraday'
|
2
|
+
|
3
|
+
# @private
|
4
|
+
module Faraday
|
5
|
+
# @private
|
6
|
+
class Response::RaiseHttp4xx < Response::Middleware
|
7
|
+
def on_complete(env)
|
8
|
+
case env[:status].to_i
|
9
|
+
when 400
|
10
|
+
raise Cashstar::BadRequest.new(error_message(env), env[:response_headers])
|
11
|
+
when 401
|
12
|
+
raise Cashstar::Unauthorized.new(error_message(env), env[:response_headers])
|
13
|
+
when 403
|
14
|
+
raise Cashstar::Forbidden.new(error_message(env), env[:response_headers])
|
15
|
+
when 404
|
16
|
+
raise Cashstar::NotFound.new(error_message(env), env[:response_headers])
|
17
|
+
when 406
|
18
|
+
raise Cashstar::NotAcceptable.new(error_message(env), env[:response_headers])
|
19
|
+
when 420
|
20
|
+
raise Cashstar::EnhanceYourCalm.new(error_message(env), env[:response_headers])
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
private
|
25
|
+
|
26
|
+
def error_message(env)
|
27
|
+
"#{env[:method].to_s.upcase} #{env[:url].to_s}: #{env[:status]}#{error_body(env[:body])}"
|
28
|
+
end
|
29
|
+
|
30
|
+
def error_body(body)
|
31
|
+
if body.nil?
|
32
|
+
nil
|
33
|
+
elsif body['error']
|
34
|
+
": #{body['error']}"
|
35
|
+
elsif body['errors']
|
36
|
+
first = Array(body['errors']).first
|
37
|
+
if first.kind_of? Hash
|
38
|
+
": #{first['message'].chomp}"
|
39
|
+
else
|
40
|
+
": #{first.chomp}"
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
require 'faraday'
|
2
|
+
|
3
|
+
# @private
|
4
|
+
module Faraday
|
5
|
+
# @private
|
6
|
+
class Response::RaiseHttp5xx < Response::Middleware
|
7
|
+
def on_complete(env)
|
8
|
+
case env[:status].to_i
|
9
|
+
when 500
|
10
|
+
raise Cashstar::InternalServerError.new(error_message(env, "Something is technically wrong."), env[:response_headers])
|
11
|
+
when 502
|
12
|
+
raise Cashstar::BadGateway.new(error_message(env, "Cashstar is down or being upgraded."), env[:response_headers])
|
13
|
+
when 503
|
14
|
+
raise Cashstar::ServiceUnavailable.new(error_message(env, "(__-){ Cashstar is over capacity or a service error occured."), env[:response_headers])
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
private
|
19
|
+
|
20
|
+
def error_message(env, body=nil)
|
21
|
+
"#{env[:method].to_s.upcase} #{env[:url].to_s}: #{[env[:status].to_s + ':', body].compact.join(' ')}"
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
require 'faraday'
|
2
|
+
|
3
|
+
module Faraday
|
4
|
+
class Response::StripCardNumbers < Response::Middleware
|
5
|
+
|
6
|
+
def parse(body)
|
7
|
+
if body
|
8
|
+
if body["egc"]
|
9
|
+
body["egc"].delete("egc_number")
|
10
|
+
body["egc"].delete("access_code")
|
11
|
+
end
|
12
|
+
if body["order"] and body["order"]["egc"]
|
13
|
+
body["order"]["egc"].delete("egc_number")
|
14
|
+
body["order"]["egc"].delete("access_code")
|
15
|
+
end
|
16
|
+
end
|
17
|
+
body
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
{
|
2
|
+
"merchants": {
|
3
|
+
"transaction_id": "12421413",
|
4
|
+
"merchant": [
|
5
|
+
{
|
6
|
+
"name": "Widget Store",
|
7
|
+
"legal_name": "The Widget Store, Inc.",
|
8
|
+
"merchant_code": "TWS"
|
9
|
+
},
|
10
|
+
{
|
11
|
+
"name": "Yummy Food",
|
12
|
+
"legal_name": "Yummy Food",
|
13
|
+
"merchant_code": "YUM"
|
14
|
+
}
|
15
|
+
]
|
16
|
+
}
|
17
|
+
}
|
@@ -0,0 +1,20 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe 'get merchants' do
|
4
|
+
subject do
|
5
|
+
Cashstar::Client.new(DEFAULT_OPTIONS)
|
6
|
+
end
|
7
|
+
|
8
|
+
before do
|
9
|
+
stub_get('v2/merchant', 'merchants')
|
10
|
+
end
|
11
|
+
|
12
|
+
it 'returns merchants' do
|
13
|
+
subject.merchants.should == [ { 'name' => 'Widget Store',
|
14
|
+
'legal_name' => 'The Widget Store, Inc.',
|
15
|
+
'merchant_code' => 'TWS' },
|
16
|
+
{ 'name' => 'Yummy Food',
|
17
|
+
'legal_name' => 'Yummy Food',
|
18
|
+
'merchant_code' => 'YUM' } ]
|
19
|
+
end
|
20
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'bundler/setup'
|
3
|
+
require 'webmock/rspec'
|
4
|
+
require 'cashstar'
|
5
|
+
|
6
|
+
DEFAULT_OPTIONS = { :username => 'cashstars', :password => 'sekret', :endpoint => 'https://cashstar.example.com' }
|
7
|
+
|
8
|
+
def stub_get(endpoint, json_stub)
|
9
|
+
body = load_fixture(json_stub)
|
10
|
+
stub_request(:get, "https://cashstars:sekret@cashstar.example.com/#{endpoint}/").
|
11
|
+
to_return(:status => 200, :body => body, :headers => {})
|
12
|
+
end
|
13
|
+
|
14
|
+
def load_fixture(file_name)
|
15
|
+
file = File.open(File.join(Dir.pwd, 'spec', 'fixtures', "#{file_name}.json"))
|
16
|
+
contents = file.read
|
17
|
+
file.close
|
18
|
+
contents
|
19
|
+
end
|
metadata
ADDED
@@ -0,0 +1,211 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: cashstar-ruby
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.7
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Charlie White
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2014-02-04 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: hashie
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ~>
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: 1.2.0
|
22
|
+
type: :runtime
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ~>
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: 1.2.0
|
30
|
+
- !ruby/object:Gem::Dependency
|
31
|
+
name: faraday
|
32
|
+
requirement: !ruby/object:Gem::Requirement
|
33
|
+
none: false
|
34
|
+
requirements:
|
35
|
+
- - ~>
|
36
|
+
- !ruby/object:Gem::Version
|
37
|
+
version: 0.8.0
|
38
|
+
type: :runtime
|
39
|
+
prerelease: false
|
40
|
+
version_requirements: !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ~>
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: 0.8.0
|
46
|
+
- !ruby/object:Gem::Dependency
|
47
|
+
name: faraday_middleware
|
48
|
+
requirement: !ruby/object:Gem::Requirement
|
49
|
+
none: false
|
50
|
+
requirements:
|
51
|
+
- - ~>
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: 0.8.0
|
54
|
+
type: :runtime
|
55
|
+
prerelease: false
|
56
|
+
version_requirements: !ruby/object:Gem::Requirement
|
57
|
+
none: false
|
58
|
+
requirements:
|
59
|
+
- - ~>
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: 0.8.0
|
62
|
+
- !ruby/object:Gem::Dependency
|
63
|
+
name: multi_json
|
64
|
+
requirement: !ruby/object:Gem::Requirement
|
65
|
+
none: false
|
66
|
+
requirements:
|
67
|
+
- - ~>
|
68
|
+
- !ruby/object:Gem::Version
|
69
|
+
version: 1.8.0
|
70
|
+
type: :runtime
|
71
|
+
prerelease: false
|
72
|
+
version_requirements: !ruby/object:Gem::Requirement
|
73
|
+
none: false
|
74
|
+
requirements:
|
75
|
+
- - ~>
|
76
|
+
- !ruby/object:Gem::Version
|
77
|
+
version: 1.8.0
|
78
|
+
- !ruby/object:Gem::Dependency
|
79
|
+
name: multi_xml
|
80
|
+
requirement: !ruby/object:Gem::Requirement
|
81
|
+
none: false
|
82
|
+
requirements:
|
83
|
+
- - ~>
|
84
|
+
- !ruby/object:Gem::Version
|
85
|
+
version: 0.5.0
|
86
|
+
type: :runtime
|
87
|
+
prerelease: false
|
88
|
+
version_requirements: !ruby/object:Gem::Requirement
|
89
|
+
none: false
|
90
|
+
requirements:
|
91
|
+
- - ~>
|
92
|
+
- !ruby/object:Gem::Version
|
93
|
+
version: 0.5.0
|
94
|
+
- !ruby/object:Gem::Dependency
|
95
|
+
name: rspec
|
96
|
+
requirement: !ruby/object:Gem::Requirement
|
97
|
+
none: false
|
98
|
+
requirements:
|
99
|
+
- - ~>
|
100
|
+
- !ruby/object:Gem::Version
|
101
|
+
version: '2.12'
|
102
|
+
type: :development
|
103
|
+
prerelease: false
|
104
|
+
version_requirements: !ruby/object:Gem::Requirement
|
105
|
+
none: false
|
106
|
+
requirements:
|
107
|
+
- - ~>
|
108
|
+
- !ruby/object:Gem::Version
|
109
|
+
version: '2.12'
|
110
|
+
- !ruby/object:Gem::Dependency
|
111
|
+
name: mocha
|
112
|
+
requirement: !ruby/object:Gem::Requirement
|
113
|
+
none: false
|
114
|
+
requirements:
|
115
|
+
- - ~>
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: '0.13'
|
118
|
+
type: :development
|
119
|
+
prerelease: false
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
121
|
+
none: false
|
122
|
+
requirements:
|
123
|
+
- - ~>
|
124
|
+
- !ruby/object:Gem::Version
|
125
|
+
version: '0.13'
|
126
|
+
- !ruby/object:Gem::Dependency
|
127
|
+
name: webmock
|
128
|
+
requirement: !ruby/object:Gem::Requirement
|
129
|
+
none: false
|
130
|
+
requirements:
|
131
|
+
- - ~>
|
132
|
+
- !ruby/object:Gem::Version
|
133
|
+
version: '1.9'
|
134
|
+
type: :development
|
135
|
+
prerelease: false
|
136
|
+
version_requirements: !ruby/object:Gem::Requirement
|
137
|
+
none: false
|
138
|
+
requirements:
|
139
|
+
- - ~>
|
140
|
+
- !ruby/object:Gem::Version
|
141
|
+
version: '1.9'
|
142
|
+
description: CashStar's API provides a simple interface for purchasing and issuing
|
143
|
+
electronic gift cards from a variety of brands
|
144
|
+
email:
|
145
|
+
- cwhite@cashstar.com
|
146
|
+
executables: []
|
147
|
+
extensions: []
|
148
|
+
extra_rdoc_files: []
|
149
|
+
files:
|
150
|
+
- .rspec
|
151
|
+
- .ruby-gemset
|
152
|
+
- .ruby-version
|
153
|
+
- Gemfile
|
154
|
+
- Gemfile.lock
|
155
|
+
- README.md
|
156
|
+
- Rakefile
|
157
|
+
- cashstar.gemspec
|
158
|
+
- lib/.DS_Store
|
159
|
+
- lib/cashstar.rb
|
160
|
+
- lib/cashstar/.DS_Store
|
161
|
+
- lib/cashstar/api.rb
|
162
|
+
- lib/cashstar/authentication.rb
|
163
|
+
- lib/cashstar/client.rb
|
164
|
+
- lib/cashstar/client/catalog.rb
|
165
|
+
- lib/cashstar/client/faceplates.rb
|
166
|
+
- lib/cashstar/client/gift_card.rb
|
167
|
+
- lib/cashstar/client/merchants.rb
|
168
|
+
- lib/cashstar/client/order.rb
|
169
|
+
- lib/cashstar/configuration.rb
|
170
|
+
- lib/cashstar/connection.rb
|
171
|
+
- lib/cashstar/error.rb
|
172
|
+
- lib/cashstar/request.rb
|
173
|
+
- lib/cashstar/version.rb
|
174
|
+
- lib/faraday/request/basic_auth.rb
|
175
|
+
- lib/faraday/request/gateway.rb
|
176
|
+
- lib/faraday/response/raise_http_4xx.rb
|
177
|
+
- lib/faraday/response/raise_http_5xx.rb
|
178
|
+
- lib/faraday/response/strip_card_numbers.rb
|
179
|
+
- spec/fixtures/merchants.json
|
180
|
+
- spec/integration/client/merchants_spec.rb
|
181
|
+
- spec/integration/get_merchants_spec.rb
|
182
|
+
- spec/spec_helper.rb
|
183
|
+
homepage: http://www.cashstar.com
|
184
|
+
licenses: []
|
185
|
+
post_install_message:
|
186
|
+
rdoc_options: []
|
187
|
+
require_paths:
|
188
|
+
- lib
|
189
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
190
|
+
none: false
|
191
|
+
requirements:
|
192
|
+
- - ! '>='
|
193
|
+
- !ruby/object:Gem::Version
|
194
|
+
version: '0'
|
195
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
196
|
+
none: false
|
197
|
+
requirements:
|
198
|
+
- - ! '>='
|
199
|
+
- !ruby/object:Gem::Version
|
200
|
+
version: '0'
|
201
|
+
requirements: []
|
202
|
+
rubyforge_project: cashstar-ruby
|
203
|
+
rubygems_version: 1.8.25
|
204
|
+
signing_key:
|
205
|
+
specification_version: 3
|
206
|
+
summary: Ruby Bindings for the CashStar API
|
207
|
+
test_files:
|
208
|
+
- spec/fixtures/merchants.json
|
209
|
+
- spec/integration/client/merchants_spec.rb
|
210
|
+
- spec/integration/get_merchants_spec.rb
|
211
|
+
- spec/spec_helper.rb
|