garbanzo 0.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.
data/bin/setup ADDED
@@ -0,0 +1,7 @@
1
+ #!/bin/bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+
5
+ bundle install
6
+
7
+ # Do any other automated setup that you need to do here
data/garbanzo.gemspec ADDED
@@ -0,0 +1,31 @@
1
+ lib = File.expand_path('../lib', __FILE__)
2
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
3
+ require 'garbanzo/version'
4
+
5
+ Gem::Specification.new do |spec|
6
+ spec.name = 'garbanzo'
7
+ spec.version = Garbanzo::VERSION
8
+ spec.authors = ['Corin Schedler']
9
+ spec.email = ['corin@dubdromic.com']
10
+
11
+ spec.summary = 'A small library for interacting with Authorize ARB'
12
+ spec.description = 'A small library for interacting with Authorize ARB'
13
+ spec.homepage = 'https://github.com/dubdromic/garbanzo'
14
+ spec.license = 'GPLv2'
15
+
16
+ spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
17
+ spec.require_paths = ['lib']
18
+
19
+ spec.add_dependency 'active_attr'
20
+ spec.add_dependency 'nokogiri'
21
+ spec.add_dependency 'gyoku', '~> 1.0'
22
+ spec.add_dependency 'faraday'
23
+
24
+ spec.add_development_dependency 'bundler', '~> 1.9'
25
+ spec.add_development_dependency 'rake', '~> 10.0'
26
+ spec.add_development_dependency 'pry'
27
+ spec.add_development_dependency 'minitest', '~> 5.0'
28
+ spec.add_development_dependency 'minitest-color'
29
+ spec.add_development_dependency 'credit_card_validator'
30
+ spec.add_development_dependency 'webmock'
31
+ end
data/lib/garbanzo.rb ADDED
@@ -0,0 +1,43 @@
1
+ require 'garbanzo/version'
2
+ require 'pry'
3
+ require 'active_attr'
4
+
5
+ # Garbanzo - A small Ruby library for interacting with Authorize.Net ARB
6
+ # Copyright (c) 2015 Corin Schedler
7
+ #
8
+ # This program is free software; you can redistribute it and/or modify
9
+ # it under the terms of the GNU General Public License as published by
10
+ # the Free Software Foundation; either version 2 of the License, or
11
+ # (at your option) any later version.
12
+ #
13
+ # This program is distributed in the hope that it will be useful,
14
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
15
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16
+ # GNU General Public License for more details.
17
+ #
18
+ # You should have received a copy of the GNU General Public License along
19
+ # with this program; if not, write to the Free Software Foundation, Inc.,
20
+ # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
21
+
22
+ module Garbanzo
23
+ require 'garbanzo/connection'
24
+ require 'garbanzo/parser'
25
+ require 'garbanzo/request'
26
+ require 'garbanzo/response'
27
+ require 'garbanzo/ast'
28
+ require 'garbanzo/parameters'
29
+ require 'garbanzo/subscription'
30
+
31
+ TEST_HOST = 'https://apitest.authorize.net'
32
+ LIVE_HOST = 'https://api2.authorize.net'
33
+ API_URI = '/xml/v1/request.api'
34
+
35
+ class << self
36
+ attr_accessor :connection
37
+ end
38
+
39
+ def self.configure
40
+ self.connection ||= Connection.new
41
+ yield connection
42
+ end
43
+ end
@@ -0,0 +1,35 @@
1
+ module Garbanzo
2
+ class Address
3
+ ATTRIBUTES = [
4
+ :first_name,
5
+ :last_name,
6
+ :company,
7
+ :address1,
8
+ :address2,
9
+ :city,
10
+ :state,
11
+ :zip,
12
+ :country
13
+ ]
14
+
15
+ attr_accessor *ATTRIBUTES
16
+
17
+ def initialize(options = {})
18
+ options.each do |attribute, value|
19
+ public_send("#{attribute}=", value)
20
+ end
21
+ end
22
+
23
+ def valid?
24
+ first_name.to_s != '' && last_name.to_s != ''
25
+ end
26
+
27
+ def to_h
28
+ ATTRIBUTES.reduce({}) do |hash, attribute|
29
+ value = public_send(attribute)
30
+ hash.merge!(attribute => value) if value
31
+ hash
32
+ end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,9 @@
1
+ module Garbanzo
2
+ module AST
3
+ require 'garbanzo/ast/base'
4
+ require 'garbanzo/ast/create'
5
+ require 'garbanzo/ast/cancel'
6
+ require 'garbanzo/ast/status'
7
+ require 'garbanzo/ast/update'
8
+ end
9
+ end
@@ -0,0 +1,33 @@
1
+ module Garbanzo
2
+ module AST
3
+ class Base
4
+ attr_accessor :nodes
5
+
6
+ def initialize(credentials)
7
+ @credentials = credentials
8
+ @nodes = {}
9
+ end
10
+
11
+ private
12
+
13
+ attr_reader :credentials
14
+
15
+ def set_nodes(hash)
16
+ @nodes = {
17
+ type => credentials_hash.merge(hash),
18
+ :attributes! => { type => { xmlns: 'AnetApi/xml/v1/schema/AnetApiSchema.xsd' }}
19
+ }
20
+ self
21
+ end
22
+
23
+ def credentials_hash
24
+ {
25
+ merchant_authentication: {
26
+ name: credentials.login,
27
+ transaction_key: credentials.password
28
+ }
29
+ }
30
+ end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,19 @@
1
+ module Garbanzo
2
+ module AST
3
+ class Cancel < Base
4
+ def build(subscription_id)
5
+ hash = {
6
+ subscription_id: subscription_id
7
+ }
8
+
9
+ set_nodes hash
10
+ end
11
+
12
+ private
13
+
14
+ def type
15
+ 'ARBCancelSubscriptionRequest'
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,30 @@
1
+ module Garbanzo
2
+ module AST
3
+ class Create < Base
4
+ def build(amount, card, address, duration, interval)
5
+ hash = {
6
+ subscription: {
7
+ payment_schedule: {
8
+ interval: interval.to_h,
9
+ start_date: duration.start_date,
10
+ total_occurrences: duration.occurrences
11
+ },
12
+ amount: amount.to_i,
13
+ payment: {
14
+ credit_card: card.to_h
15
+ },
16
+ bill_to: address.to_h,
17
+ }
18
+ }
19
+
20
+ set_nodes hash
21
+ end
22
+
23
+ private
24
+
25
+ def type
26
+ 'ARBCreateSubscriptionRequest'
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,19 @@
1
+ module Garbanzo
2
+ module AST
3
+ class Status < Base
4
+ def build(subscription_id)
5
+ hash = {
6
+ subscription_id: subscription_id
7
+ }
8
+
9
+ set_nodes hash
10
+ end
11
+
12
+ private
13
+
14
+ def type
15
+ 'ARBGetSubscriptionStatusRequest'
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,30 @@
1
+ module Garbanzo
2
+ module AST
3
+ class Update < Base
4
+ def build(subscription_id, amount, card, address, duration, interval)
5
+ hash = {
6
+ subscription_id: subscription_id,
7
+ subscription: {
8
+ payment_schedule: {
9
+ start_date: duration.start_date,
10
+ total_occurrences: duration.occurrences
11
+ },
12
+ amount: amount.to_i,
13
+ payment: {
14
+ credit_card: card.to_h
15
+ },
16
+ bill_to: address.to_h,
17
+ }
18
+ }
19
+
20
+ set_nodes hash
21
+ end
22
+
23
+ private
24
+
25
+ def type
26
+ 'ARBUpdateSubscriptionRequest'
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,11 @@
1
+ module Garbanzo
2
+ class Connection
3
+ attr_accessor :login, :password, :test_mode
4
+
5
+ def initialize(login = nil, password = nil, test_mode = false)
6
+ @login = login
7
+ @password = password
8
+ @test_mode = test_mode
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,23 @@
1
+ module Garbanzo
2
+ class Credentials
3
+ attr_reader :login, :password, :test_mode
4
+
5
+ def initialize(login, password, test_mode = true)
6
+ @login = login
7
+ @password = password
8
+ @test_mode = test_mode
9
+ end
10
+
11
+ def to_h
12
+ {
13
+ login: login,
14
+ password: password,
15
+ test_mode: test_mode
16
+ }
17
+ end
18
+
19
+ def valid?
20
+ true
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,36 @@
1
+ require 'credit_card_validator'
2
+
3
+ module Garbanzo
4
+ class CreditCard
5
+ attr_accessor :number, :exp_month, :exp_year
6
+
7
+ def initialize(number, exp_month, exp_year, card_validator = ::CreditCardValidator::Validator)
8
+ @number = number.gsub(/[^\d]/, '')
9
+ @exp_month = exp_month.to_i
10
+ @exp_year = exp_year.to_i
11
+ @card_validator = card_validator
12
+ end
13
+
14
+ # TODO: fix this
15
+ def valid?
16
+ exp_month.between?(1, 12) &&
17
+ exp_year >= Date.today.year &&
18
+ card_validator.valid?(number)
19
+ end
20
+
21
+ def to_h
22
+ {
23
+ card_number: number,
24
+ expiration_date: expiration_date
25
+ }
26
+ end
27
+
28
+ def expiration_date
29
+ format('%04d-%02d', exp_year, exp_month)
30
+ end
31
+
32
+ private
33
+
34
+ attr_reader :card_validator
35
+ end
36
+ end
@@ -0,0 +1,21 @@
1
+ module Garbanzo
2
+ class Duration
3
+ attr_reader :start_date, :occurrences
4
+
5
+ def initialize(start_date = Date.today, occurrences = 9999)
6
+ @start_date = start_date
7
+ @occurrences = occurrences.to_i
8
+ end
9
+
10
+ def to_h
11
+ {
12
+ start_date: start_date,
13
+ occurrences: occurrences
14
+ }
15
+ end
16
+
17
+ def valid?
18
+ start_date.respond_to?(:strftime) && occurrences.between?(1, 9999)
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,45 @@
1
+ module Garbanzo
2
+ class Interval
3
+ attr_reader :length, :unit
4
+
5
+ def initialize(length = 1, unit = :month)
6
+ @length = length.to_i
7
+ @unit = normalize_unit unit.to_sym
8
+ end
9
+
10
+ def to_h
11
+ {
12
+ length: length,
13
+ unit: unit
14
+ }
15
+ end
16
+
17
+ def valid?
18
+ unit_valid? && length_valid?
19
+ end
20
+
21
+ private
22
+
23
+ def normalize_unit(unit)
24
+ unit == :month ? :months : unit
25
+ end
26
+
27
+ def unit_valid?
28
+ months? || days?
29
+ end
30
+
31
+ def length_valid?
32
+ fail NotImplementedError unless unit_valid?
33
+ return length.between?(1, 12) if months?
34
+ return length.between?(7, 365) if days?
35
+ end
36
+
37
+ def months?
38
+ unit == :months
39
+ end
40
+
41
+ def days?
42
+ unit == :days
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,10 @@
1
+ require 'garbanzo/credentials'
2
+ require 'garbanzo/interval'
3
+ require 'garbanzo/duration'
4
+ require 'garbanzo/address'
5
+ require 'garbanzo/credit_card'
6
+
7
+ module Garbanzo
8
+ module Parameters
9
+ end
10
+ end
@@ -0,0 +1,21 @@
1
+ require 'nokogiri'
2
+
3
+ module Garbanzo
4
+ class Parser
5
+ def initialize(raw_document)
6
+ @raw_document = raw_document
7
+ end
8
+
9
+ private
10
+
11
+ attr_reader :raw_document
12
+
13
+ def node(name)
14
+ document.search(name.to_s).text
15
+ end
16
+
17
+ def document
18
+ @document ||= Nokogiri::XML.parse raw_document
19
+ end
20
+ end
21
+ end