alpha_card 0.1.6 → 0.1.7
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 +4 -4
- data/Gemfile +0 -1
- data/alpha_card.gemspec +2 -2
- data/lib/alpha_card.rb +59 -19
- data/lib/alpha_card/account.rb +32 -0
- data/lib/alpha_card/alpha_card_error.rb +2 -0
- data/lib/alpha_card/alpha_card_object.rb +13 -7
- data/lib/alpha_card/alpha_card_response.rb +8 -1
- data/lib/alpha_card/billing.rb +3 -0
- data/lib/alpha_card/object.rb +35 -5
- data/lib/alpha_card/order.rb +3 -0
- data/lib/alpha_card/sale.rb +30 -10
- data/lib/alpha_card/shipping.rb +3 -0
- data/lib/alpha_card/utils.rb +90 -0
- metadata +4 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 6af86a7de326ef53708c81f07ed025792c44841c
|
4
|
+
data.tar.gz: 5a670c2177f9b7ac326f34ea1c3e34decd5ea37c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: ca0333c53125849ca415b73a10d9a4c659d54cff80879bc0f2aadd3aa502ffecc3af758ed87709ce83ba7016d57679b7a6f023f672952d7e9f3788fda29f7ad1
|
7
|
+
data.tar.gz: 0bea0ef881a98bd593a99a20883de46f2b94f1d6cf384caa39dbeaed8f95f53a99afa8855a22becba76f0e0f6b5ac90017263dda9d2473a4564e7938c525d7a9
|
data/Gemfile
CHANGED
data/alpha_card.gemspec
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
Gem::Specification.new do |gem|
|
2
2
|
gem.name = 'alpha_card'
|
3
|
-
gem.version = '0.1.
|
4
|
-
gem.date = '2014-06-
|
3
|
+
gem.version = '0.1.7'
|
4
|
+
gem.date = '2014-06-27'
|
5
5
|
gem.summary = 'Alpha Card Services DirectPost API for Ruby'
|
6
6
|
gem.description = 'Gem for creating sales with Alpha Card Services DirectPost API'
|
7
7
|
gem.authors = ['Nikita Bulaj']
|
data/lib/alpha_card.rb
CHANGED
@@ -1,8 +1,9 @@
|
|
1
|
+
# encoding:utf-8
|
1
2
|
require 'yaml'
|
2
3
|
require 'virtus'
|
3
|
-
require 'rack'
|
4
4
|
require 'rest_client'
|
5
5
|
|
6
|
+
require 'alpha_card/utils'
|
6
7
|
require 'alpha_card/object'
|
7
8
|
require 'alpha_card/alpha_card_object'
|
8
9
|
require 'alpha_card/alpha_card_response'
|
@@ -14,25 +15,55 @@ require 'alpha_card/billing'
|
|
14
15
|
require 'alpha_card/order'
|
15
16
|
require 'alpha_card/sale'
|
16
17
|
|
18
|
+
##
|
19
|
+
# AlphaCard is a library for processing payments with Alpha Card Services, Inc.
|
17
20
|
module AlphaCard
|
18
|
-
|
21
|
+
##
|
22
|
+
# Alpha Card Gateway DirectPost API URL
|
19
23
|
@api_base = 'https://secure.alphacardgateway.com/api/transact.php'
|
20
24
|
|
25
|
+
##
|
21
26
|
# Global Payment Systems (NDC) Credit Card Authorization Codes
|
27
|
+
#
|
28
|
+
# @see http://floristwiki.ftdi.com/images/c/ce/Appendix_A_-_Credit_Card_Authorization_Codes.pdf Credit Card Authorization Codes
|
22
29
|
CREDIT_CARD_CODES = YAML.load_file(File.expand_path('../alpha_card/data/codes.yml', __FILE__)) unless defined? CREDIT_CARD_CODES
|
23
30
|
|
24
31
|
class << self
|
32
|
+
# @return [String] Alpha Card Gateway DirectPost API URL.
|
25
33
|
attr_accessor :api_base
|
26
34
|
end
|
27
35
|
|
28
|
-
|
36
|
+
##
|
37
|
+
# Send the POST request to the AlphaCard Gateway from the
|
38
|
+
# specified account. Request must contains params - Alpha Card
|
39
|
+
# transcation variables.
|
40
|
+
#
|
41
|
+
# @param [Hash] params
|
42
|
+
# Alpha Card transaction variables.
|
43
|
+
# @param [AlphaCard::Account] account
|
44
|
+
# An <code>AlphaCard::Account</code> credentials object.
|
45
|
+
#
|
46
|
+
# @return [AlphaCard::AlphaCardResponse]
|
47
|
+
# Response from Alpha Card Gateway.
|
29
48
|
#
|
30
|
-
#
|
31
|
-
#
|
49
|
+
# @raise [AlphaCard::AlphaCardError]
|
50
|
+
# AlphaCardError Exception if request failed.
|
32
51
|
#
|
33
|
-
#
|
34
|
-
#
|
35
|
-
#
|
52
|
+
# @example
|
53
|
+
# account = AlphaCard::Account.new('demo', 'password')
|
54
|
+
# response = AlphaCard.request(
|
55
|
+
# {
|
56
|
+
# cexp: '0720',
|
57
|
+
# ccnumber: '4111111111111111',
|
58
|
+
# amount: '10.00'
|
59
|
+
# },
|
60
|
+
# account
|
61
|
+
# )
|
62
|
+
#
|
63
|
+
# #=> #<AlphaCard::AlphaCardResponse:0x1a0fda8 @data={"response"=>"1",
|
64
|
+
# "responsetext"=>"SUCCESS", "authcode"=>"123", "transactionid"=>"123",
|
65
|
+
# "avsresponse"=>"", "cvvresponse"=>"N", "orderid"=>"", "type"=>"",
|
66
|
+
# "response_code"=>"100"}>
|
36
67
|
def self.request(params = {}, account)
|
37
68
|
unless account.filled?
|
38
69
|
raise AlphaCardError.new('You must set credentials to create the sale!')
|
@@ -52,26 +83,35 @@ module AlphaCard
|
|
52
83
|
|
53
84
|
private
|
54
85
|
|
55
|
-
|
56
|
-
#
|
86
|
+
##
|
87
|
+
# Raises an exception if Alpha Card Gateway return an error or
|
88
|
+
# decline code for the request. Message is taken from the Global
|
89
|
+
# Payment Systems Credit Card Authorization Codes (codes.yml).
|
90
|
+
# If code wasn't found in <code>CREDIT_CARD_CODES</code>, then
|
91
|
+
# message = Alpha Card response text.
|
92
|
+
#
|
93
|
+
# @param [AlphaCard::AlphaCardResponse] response
|
94
|
+
# Alpha Card Response object.
|
57
95
|
#
|
58
|
-
#
|
59
|
-
#
|
96
|
+
# @raise [AlphaCard::AlphaCardError]
|
97
|
+
# AlphaCardError Exception if request failed.
|
60
98
|
#
|
61
|
-
#
|
62
|
-
#
|
99
|
+
# @return [String]
|
100
|
+
# Alpha Card Services response text.
|
63
101
|
def self.handle_alpha_card_errors(response)
|
64
102
|
code = response.text
|
65
103
|
raise AlphaCardError.new(CREDIT_CARD_CODES[code] || code) unless response.success?
|
66
104
|
end
|
67
105
|
|
68
|
-
|
106
|
+
##
|
107
|
+
# Raises an exception if a network error occurs. It
|
108
|
+
# could be request timeout, socket error or anything else.
|
69
109
|
#
|
70
|
-
#
|
71
|
-
#
|
110
|
+
# @param [Exception] e
|
111
|
+
# Exception object.
|
72
112
|
#
|
73
|
-
#
|
74
|
-
#
|
113
|
+
# @raise [AlphaCard::AlphaCardError]
|
114
|
+
# AlphaCardError Exception.
|
75
115
|
def self.handle_connection_errors(e)
|
76
116
|
case e
|
77
117
|
when RestClient::ServerBrokeConnection, RestClient::RequestTimeout
|
data/lib/alpha_card/account.rb
CHANGED
@@ -1,13 +1,45 @@
|
|
1
1
|
module AlphaCard
|
2
|
+
##
|
3
|
+
# Implementation of Alpha Card Services account object.
|
4
|
+
# Contains credentials (username and password) for
|
5
|
+
# the Alpha Card Gateway API access.
|
2
6
|
class Account < AlphaCardObject
|
3
7
|
attribute :username, String
|
4
8
|
attribute :password, String
|
5
9
|
|
10
|
+
##
|
11
|
+
# <code>AlphaCard::Account</code> constructor.
|
12
|
+
#
|
13
|
+
# @param [String] username
|
14
|
+
# @param [String] password
|
15
|
+
#
|
16
|
+
# @example
|
17
|
+
# AlphaCard::Account.new('demo', 'password')
|
18
|
+
#
|
19
|
+
# #=> #<AlphaCard::Account:0x000000039b18a8 @username="demo", @password="password">
|
6
20
|
def initialize(username, password)
|
7
21
|
self.username = username
|
8
22
|
self.password = password
|
9
23
|
end
|
10
24
|
|
25
|
+
##
|
26
|
+
# Say if all the credentials of Account is filled.
|
27
|
+
# Username and password can't be a <code>nil</code>
|
28
|
+
# object or an empty <code>String</code>.
|
29
|
+
#
|
30
|
+
# @return [Boolean]
|
31
|
+
# True if username and password is filled.
|
32
|
+
#
|
33
|
+
# @example
|
34
|
+
# account = AlphaCard::Account.new('demo', 'password')
|
35
|
+
# account.filled?
|
36
|
+
#
|
37
|
+
# #=> true
|
38
|
+
#
|
39
|
+
# account = AlphaCard::Account.new('', nil)
|
40
|
+
# account.filled?
|
41
|
+
#
|
42
|
+
# #=> false
|
11
43
|
def filled?
|
12
44
|
[self.username, self.password].all?(&:present?)
|
13
45
|
end
|
@@ -1,16 +1,22 @@
|
|
1
1
|
module AlphaCard
|
2
|
+
##
|
3
|
+
# Parent class for each Alpha Card Gateway object, such as
|
4
|
+
# Order, Billing, Sale and others.
|
2
5
|
class AlphaCardObject
|
3
6
|
include Virtus.model
|
4
7
|
|
5
|
-
|
8
|
+
##
|
9
|
+
# Returns the <code>Hash</code> with only filled attributes
|
10
|
+
# of the <code>AlphaCard::AlphaCardObject</code>.
|
6
11
|
#
|
7
|
-
#
|
12
|
+
# @return [Hash]
|
13
|
+
# Filled attributes of the <code>AlphaCard::AlphaCardObject</code>.
|
8
14
|
#
|
9
|
-
#
|
10
|
-
#
|
11
|
-
|
12
|
-
#
|
13
|
-
#
|
15
|
+
# @example
|
16
|
+
# order = AlphaCard::Order.new({orderid: '1', tax: nil, ponumber: 'PO123'})
|
17
|
+
# order.filled_attributes
|
18
|
+
#
|
19
|
+
# #=> {orderid: '1', ponumber: 'PO123'}
|
14
20
|
def filled_attributes
|
15
21
|
self.attributes.select { |key, value| value.present? }
|
16
22
|
end
|
@@ -1,13 +1,20 @@
|
|
1
1
|
module AlphaCard
|
2
|
+
##
|
3
|
+
# Implementation of Alpha Card Services response.
|
4
|
+
# Contains all the data, that Alpha Card Gateway
|
5
|
+
# returned for the request.
|
2
6
|
class AlphaCardResponse
|
3
7
|
attr_reader :data
|
4
8
|
|
9
|
+
# Success response code
|
5
10
|
APPROVED = '1'
|
11
|
+
# Decline response code
|
6
12
|
DECLINED = '2'
|
13
|
+
# Error response code
|
7
14
|
ERROR = '3'
|
8
15
|
|
9
16
|
def initialize(request_body)
|
10
|
-
@data =
|
17
|
+
@data = AlphaCard::Utils.parse_query(request_body)
|
11
18
|
end
|
12
19
|
|
13
20
|
def text
|
data/lib/alpha_card/billing.rb
CHANGED
data/lib/alpha_card/object.rb
CHANGED
@@ -1,17 +1,47 @@
|
|
1
|
-
|
2
|
-
#
|
3
|
-
#
|
4
|
-
#
|
5
|
-
# Use-case: standalone Ruby scripts
|
1
|
+
##
|
2
|
+
# Some stolen methods from the active_support gem.
|
3
|
+
# For the clear dependencies.
|
4
|
+
# @todo Remove this class, rewrite library code
|
6
5
|
class Object
|
6
|
+
# An object is blank if it's false, empty, or a whitespace string.
|
7
|
+
# For example, '', ' ', +nil+, [], and {} are all blank.
|
8
|
+
#
|
9
|
+
# This simplifies
|
10
|
+
#
|
11
|
+
# address.nil? || address.empty?
|
12
|
+
#
|
13
|
+
# to
|
14
|
+
#
|
15
|
+
# address.blank?
|
16
|
+
#
|
17
|
+
# @return [true, false]
|
7
18
|
def blank?
|
8
19
|
respond_to?(:empty?) ? !!empty? : !self
|
9
20
|
end
|
10
21
|
|
22
|
+
# An object is present if it's not blank.
|
23
|
+
#
|
24
|
+
# @return [true, false]
|
11
25
|
def present?
|
12
26
|
!blank?
|
13
27
|
end
|
14
28
|
|
29
|
+
# Invokes the public method whose name goes as first argument just like
|
30
|
+
# +public_send+ does, except that if the receiver does not respond to it the
|
31
|
+
# call returns +nil+ rather than raising an exception.
|
32
|
+
#
|
33
|
+
# This method is defined to be able to write
|
34
|
+
#
|
35
|
+
# @person.try(:name)
|
36
|
+
#
|
37
|
+
# instead of
|
38
|
+
#
|
39
|
+
# @person ? @person.name : nil
|
40
|
+
#
|
41
|
+
# +try+ returns +nil+ when called on +nil+ regardless of whether it responds
|
42
|
+
# to the method:
|
43
|
+
#
|
44
|
+
# nil.try(:to_i) # => nil, rather than 0
|
15
45
|
def try(*a, &b)
|
16
46
|
if a.empty? && block_given?
|
17
47
|
yield self
|
data/lib/alpha_card/order.rb
CHANGED
data/lib/alpha_card/sale.rb
CHANGED
@@ -1,24 +1,44 @@
|
|
1
1
|
module AlphaCard
|
2
|
+
##
|
3
|
+
# Implementation of Alpha Card Services Sale object.
|
4
|
+
# Contains all the information about Customer Credit Card,
|
5
|
+
# such as CVV, number, expiration date, etc.
|
6
|
+
# Process the Alpha Card Services payment.
|
2
7
|
class Sale < AlphaCardObject
|
3
8
|
attribute :ccexp, String
|
4
9
|
attribute :ccnumber, String
|
5
10
|
attribute :amount, String
|
6
11
|
attribute :cvv, String
|
7
12
|
|
8
|
-
|
13
|
+
##
|
14
|
+
# Not writable attribute, defines the type of transaction (default is 'sale')
|
15
|
+
#
|
16
|
+
# @attribute [r] type
|
9
17
|
attribute :type, String, default: 'sale', writer: :private
|
10
18
|
|
11
|
-
|
12
|
-
#
|
13
|
-
#
|
19
|
+
##
|
20
|
+
# Creates the sale for the specified <code>AlphaCard::Order</code>
|
21
|
+
# with the <code>AlphaCard::Account</code> credentials.
|
22
|
+
#
|
23
|
+
# @param [AlphaCard::Order] params
|
24
|
+
# An <code>AlphaCard::Order</code> object.
|
25
|
+
# @param [AlphaCard::Account] account
|
26
|
+
# An <code>AlphaCard::Account</code> object.
|
27
|
+
#
|
28
|
+
# @return [Boolean]
|
29
|
+
# True if sale was created successfully.
|
30
|
+
# Raise an AlphaCardError exception if some error occurred.
|
31
|
+
#
|
32
|
+
# @raise [Exception]
|
33
|
+
# Exception if one of required attributes doesn't specified.
|
14
34
|
#
|
15
|
-
#
|
16
|
-
#
|
17
|
-
#
|
35
|
+
# @example
|
36
|
+
# account = AlphaCard::Account.new('demo', 'password')
|
37
|
+
# order = AlphaCard::Order.new({orderid: 1, orderdescription: 'Test order'})
|
38
|
+
# sale = AlphaCard::Sale.new({ccexp: '0117', ccnumber: '4111111111111111', amount: "5.00" })
|
39
|
+
# sale.create(order, account)
|
18
40
|
#
|
19
|
-
#
|
20
|
-
# sale = AlphaCard::Sale.new(attrs)
|
21
|
-
# sale.create(order, account) #=> true or false
|
41
|
+
# #=> true
|
22
42
|
def create(order, account)
|
23
43
|
[:ccexp, :ccnumber, :amount].each do |attr|
|
24
44
|
raise Exception.new("No #{attr} information provided") if self[attr].blank?
|
data/lib/alpha_card/shipping.rb
CHANGED
@@ -0,0 +1,90 @@
|
|
1
|
+
module AlphaCard
|
2
|
+
##
|
3
|
+
# Some stolen methods to clear library dependencies.
|
4
|
+
class Utils
|
5
|
+
##
|
6
|
+
# This one is from the rack gem. It is useful for
|
7
|
+
# parsing of Alpha Card Gateway response body.
|
8
|
+
# @see https://github.com/rack/rack rack gem GitHub
|
9
|
+
class << self
|
10
|
+
##
|
11
|
+
# Default separators for query string.
|
12
|
+
DEFAULT_SEP = /[&;] */n
|
13
|
+
|
14
|
+
# A part of the rack gem.
|
15
|
+
class KeySpaceConstrainedParams
|
16
|
+
def initialize(limit = 65536)
|
17
|
+
@limit = limit
|
18
|
+
@size = 0
|
19
|
+
@params = {}
|
20
|
+
end
|
21
|
+
|
22
|
+
def [](key)
|
23
|
+
@params[key]
|
24
|
+
end
|
25
|
+
|
26
|
+
def []=(key, value)
|
27
|
+
@size += key.size if key && !@params.key?(key)
|
28
|
+
raise RangeError, 'exceeded available parameter key space' if @size > @limit
|
29
|
+
@params[key] = value
|
30
|
+
end
|
31
|
+
|
32
|
+
def key?(key)
|
33
|
+
@params.key?(key)
|
34
|
+
end
|
35
|
+
|
36
|
+
def to_params_hash
|
37
|
+
hash = @params
|
38
|
+
hash.keys.each do |key|
|
39
|
+
value = hash[key]
|
40
|
+
if value.kind_of?(self.class)
|
41
|
+
hash[key] = value.to_params_hash
|
42
|
+
elsif value.kind_of?(Array)
|
43
|
+
value.map! { |x| x.kind_of?(self.class) ? x.to_params_hash : x }
|
44
|
+
end
|
45
|
+
end
|
46
|
+
hash
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
##
|
51
|
+
# Unescapes a URI escaped string with +encoding+. +encoding+ will be the
|
52
|
+
# target encoding of the string returned, and it defaults to UTF-8
|
53
|
+
if defined?(::Encoding)
|
54
|
+
def unescape(s, encoding = Encoding::UTF_8)
|
55
|
+
URI.decode_www_form_component(s, encoding)
|
56
|
+
end
|
57
|
+
else
|
58
|
+
def unescape(s, encoding = nil)
|
59
|
+
URI.decode_www_form_component(s, encoding)
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
##
|
64
|
+
# Parses a query string to a Hash by breaking it up
|
65
|
+
# at the '&' and ';' characters.
|
66
|
+
def parse_query(qs, d = nil, &unescaper)
|
67
|
+
unescaper ||= method(:unescape)
|
68
|
+
|
69
|
+
params = KeySpaceConstrainedParams.new
|
70
|
+
|
71
|
+
(qs || '').split(d ? /[#{d}] */n : DEFAULT_SEP).each do |p|
|
72
|
+
next if p.empty?
|
73
|
+
k, v = p.split('=', 2).map(&unescaper)
|
74
|
+
|
75
|
+
if cur = params[k]
|
76
|
+
if cur.class == Array
|
77
|
+
params[k] << v
|
78
|
+
else
|
79
|
+
params[k] = [cur, v]
|
80
|
+
end
|
81
|
+
else
|
82
|
+
params[k] = v
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
params.to_params_hash
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: alpha_card
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.7
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Nikita Bulaj
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-06-
|
11
|
+
date: 2014-06-27 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rspec
|
@@ -49,6 +49,7 @@ files:
|
|
49
49
|
- lib/alpha_card/order.rb
|
50
50
|
- lib/alpha_card/sale.rb
|
51
51
|
- lib/alpha_card/shipping.rb
|
52
|
+
- lib/alpha_card/utils.rb
|
52
53
|
- spec/alpha_card/alpha_card_response_spec.rb
|
53
54
|
- spec/alpha_card/alpha_card_spec.rb
|
54
55
|
- spec/spec_helper.rb
|
@@ -77,3 +78,4 @@ signing_key:
|
|
77
78
|
specification_version: 4
|
78
79
|
summary: Alpha Card Services DirectPost API for Ruby
|
79
80
|
test_files: []
|
81
|
+
has_rdoc:
|