beanstream 1.0.0.rc1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: abe714a2b18a419e345b2f43e52ce2aacfadc260
4
+ data.tar.gz: 7a42a8d0ee4870b12d79abbec7ee171441885de7
5
+ SHA512:
6
+ metadata.gz: a3d415ae9448fe7717e59085c686b8b3f1a114c5ffdfc58d8a8fc0b4167c6e9b59abe71aaa02305dceabe8313440f60d3253dcce13fd53d353a1f3a801b40e95
7
+ data.tar.gz: fe7f78d9f92f5d06a198338dcc955007c72cc824e29865fffc84e6970745e4808efa2d088fef55996558693d48a02f537c627fd0d5cc1d47f63d3f6eb4bc2f41
@@ -0,0 +1,35 @@
1
+ *.gem
2
+ *.rbc
3
+ /.config
4
+ /coverage/
5
+ /InstalledFiles
6
+ /pkg/
7
+ /spec/reports/
8
+ /test/tmp/
9
+ /test/version_tmp/
10
+ /tmp/
11
+
12
+ ## Specific to RubyMotion:
13
+ .dat*
14
+ .repl_history
15
+ build/
16
+
17
+ ## Documentation cache and generated files:
18
+ /.yardoc/
19
+ /_yardoc/
20
+ /doc/
21
+ /rdoc/
22
+
23
+ ## Environment normalisation:
24
+ /.bundle/
25
+ /vendor/bundle
26
+ /lib/bundler/man/
27
+
28
+ # for a library or gem, you might want to ignore these files since the code is
29
+ # intended to run in multiple environments; otherwise, check them in:
30
+ # Gemfile.lock
31
+ # .ruby-version
32
+ # .ruby-gemset
33
+
34
+ # unless supporting rvm < 1.11.0 or doing something fancy, ignore this:
35
+ .rvmrc
data/Gemfile ADDED
@@ -0,0 +1,6 @@
1
+ source "https://rubygems.org"
2
+ gemspec
3
+
4
+
5
+ gem 'rest-client', '~> 1.8.0'
6
+ gem 'shoulda'
@@ -0,0 +1,66 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ beanstream (1.0.0.rc1)
5
+ json (~> 1.8.1)
6
+ rest-client (~> 1.4)
7
+
8
+ GEM
9
+ remote: https://rubygems.org/
10
+ specs:
11
+ activesupport (4.2.3)
12
+ i18n (~> 0.7)
13
+ json (~> 1.7, >= 1.7.7)
14
+ minitest (~> 5.1)
15
+ thread_safe (~> 0.3, >= 0.3.4)
16
+ tzinfo (~> 1.1)
17
+ domain_name (0.5.24)
18
+ unf (>= 0.0.5, < 1.0.0)
19
+ ffi (1.9.10-x64-mingw32)
20
+ http-cookie (1.0.2)
21
+ domain_name (~> 0.5)
22
+ i18n (0.7.0)
23
+ json (1.8.3)
24
+ mime-types (2.6.1)
25
+ minitest (5.8.0)
26
+ netrc (0.10.3)
27
+ power_assert (0.2.4)
28
+ rake (10.4.2)
29
+ rest-client (1.8.0)
30
+ http-cookie (>= 1.0.2, < 2.0)
31
+ mime-types (>= 1.16, < 3.0)
32
+ netrc (~> 0.7)
33
+ rest-client (1.8.0-x64-mingw32)
34
+ ffi (~> 1.9)
35
+ http-cookie (>= 1.0.2, < 2.0)
36
+ mime-types (>= 1.16, < 3.0)
37
+ netrc (~> 0.7)
38
+ shoulda (3.5.0)
39
+ shoulda-context (~> 1.0, >= 1.0.1)
40
+ shoulda-matchers (>= 1.4.1, < 3.0)
41
+ shoulda-context (1.2.1)
42
+ shoulda-matchers (2.8.0)
43
+ activesupport (>= 3.0.0)
44
+ test-unit (3.1.3)
45
+ power_assert
46
+ thread_safe (0.3.5)
47
+ tzinfo (1.2.2)
48
+ thread_safe (~> 0.1)
49
+ unf (0.1.4)
50
+ unf_ext
51
+ unf_ext (0.0.7.1)
52
+ unf_ext (0.0.7.1-x64-mingw32)
53
+
54
+ PLATFORMS
55
+ ruby
56
+ x64-mingw32
57
+
58
+ DEPENDENCIES
59
+ beanstream!
60
+ rake
61
+ rest-client (~> 1.8.0)
62
+ shoulda
63
+ test-unit
64
+
65
+ BUNDLED WITH
66
+ 1.10.6
data/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2015 Beanstream Digital River World Payments
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
22
+
@@ -0,0 +1,4 @@
1
+ # Beanstream's Ruby SDK
2
+ **NOTE! This SDK is currently under development and is not rated for production use.**
3
+
4
+ If you would like to contribute to it and earn some cash from our code bounty program please contact bowens@beanstream.com
@@ -0,0 +1,7 @@
1
+ require 'rake/testtask'
2
+
3
+ task :default => [:test]
4
+
5
+ Rake::TestTask.new do |t|
6
+ t.pattern = './test/**/*_test.rb'
7
+ end
@@ -0,0 +1,26 @@
1
+ #$:.unshift(File.join(File.dirname(__FILE__), 'lib'))
2
+
3
+
4
+ Gem::Specification.new do |s|
5
+ s.name = 'beanstream'
6
+ s.version = '1.0.0.rc1'
7
+ s.date = '2015-08-14'
8
+ s.summary = "Beanstream Ruby SDK"
9
+ s.description = "Accept payments using Beanstream and Ruby"
10
+ s.authors = ["Brent Owens", "Colin Walker", "Tom Mengda"]
11
+ s.email = 'bowens@beanstream.com'
12
+ s.homepage ='http://developer.beanstream.com'
13
+ s.license = 'MIT'
14
+
15
+ s.files = `git ls-files`.split("\n")
16
+ s.test_files = `git ls-files -- test/*`.split("\n")
17
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
18
+ s.require_paths = ['lib']
19
+
20
+ s.add_dependency('rest-client', '~> 1.4')
21
+ s.add_dependency('json', '~> 1.8.1')
22
+
23
+ s.add_development_dependency('shoulda', '~> 3.4.0')
24
+ s.add_development_dependency('test-unit')
25
+ s.add_development_dependency('rake')
26
+ end
@@ -0,0 +1,52 @@
1
+ require 'beanstream/transaction'
2
+ require 'beanstream/payments_api'
3
+ require 'beanstream/profiles_api'
4
+ require 'beanstream/reporting_api'
5
+ require 'beanstream/util'
6
+ require 'beanstream/exceptions'
7
+
8
+ module Beanstream
9
+
10
+ @url_prefix = "www"
11
+ @url_suffix = "api"
12
+ @url_base = "beanstream.com"
13
+ @url_version = "v1"
14
+ @ssl_ca_cert = File.dirname(__FILE__) + '/resources/cacert.pem'
15
+ @timeout = 80
16
+ @open_timeout = 40
17
+
18
+ class << self
19
+ attr_accessor :merchant_id, :payments_api_key, :profiles_api_key, :reporting_api_key
20
+ attr_accessor :url_prefix, :url_base, :url_suffix, :url_version
21
+ attr_accessor :url_payments, :url_return, :url_void
22
+ attr_accessor :ssl_ca_cert, :timeout, :open_timeout
23
+ end
24
+
25
+ def self.api_host_url()
26
+ "https://#{@url_prefix}.#{url_base}"
27
+ end
28
+
29
+ def self.api_base_url()
30
+ "/#{url_suffix}/#{url_version}"
31
+ end
32
+
33
+ def self.PaymentsAPI()
34
+ Beanstream::PaymentsAPI.new()
35
+ end
36
+
37
+ def self.ProfilesAPI()
38
+ Beanstream::ProfilesAPI.new()
39
+ end
40
+
41
+ def self.ReportingAPI()
42
+ Beanstream::ReportingAPI.new()
43
+ end
44
+ end
45
+
46
+
47
+ def run()
48
+ Beanstream.merchant_id = "300200578"
49
+ Beanstream.payments_api_key = "4BaD82D9197b4cc4b70a221911eE9f70"
50
+ result = Beanstream.PaymentsAPI().make_creditcard_payment(12.5)
51
+ puts "Payment result: #{result}"
52
+ end
@@ -0,0 +1,71 @@
1
+ module Beanstream
2
+
3
+ class BeanstreamException < StandardError
4
+ attr_reader :code, :category, :message, :http_status_code
5
+ def initialize(code=nil, category=nil, message=nil, http_status_code=nil)
6
+ @code = code
7
+ @category = category
8
+ @message = message
9
+ @http_status_code = http_status_code
10
+ end
11
+
12
+ def is_user_error()
13
+ false
14
+ end
15
+
16
+ def user_facing_message()
17
+ "There was an error processing your request. Please try again or use a different card."
18
+ end
19
+ end
20
+
21
+
22
+ class BusinessRuleException < BeanstreamException
23
+ def initialize(code, category, message, http_status_code)
24
+ super(code, category, message, http_status_code)
25
+ end
26
+ end
27
+
28
+ class UnauthorizedException < BeanstreamException
29
+ def initialize(code, category, message, http_status_code)
30
+ super(code, category, message, http_status_code)
31
+ end
32
+ end
33
+
34
+ class ForbiddenException < BeanstreamException
35
+ def initialize(code, category, message, http_status_code)
36
+ super(code, category, message, http_status_code)
37
+ end
38
+ end
39
+
40
+ class InvalidRequestException < BeanstreamException
41
+ def initialize(code, category, message, http_status_code)
42
+ super(code, category, message, http_status_code)
43
+ end
44
+
45
+ def is_user_error()
46
+ if (@category ==1)
47
+ true
48
+ elsif (@category == 3 && code == 52)
49
+ true
50
+ else
51
+ false
52
+ end
53
+ end
54
+
55
+ def user_facing_message()
56
+ if (is_user_error())
57
+ return @message
58
+ else
59
+ super
60
+ end
61
+ end
62
+
63
+ end
64
+
65
+ class InternalServerException < BeanstreamException
66
+ def initialize(code, category, message, http_status_code)
67
+ super(code, category, message, http_status_code)
68
+ end
69
+ end
70
+
71
+ end
@@ -0,0 +1,161 @@
1
+ require 'securerandom'
2
+
3
+ module Beanstream
4
+
5
+ class PaymentMethods
6
+ CARD = "card"
7
+ CASH = "cash"
8
+ CHEQUE = "cheque"
9
+ TOKEN = "token"
10
+ PROFILE = "payment_profile"
11
+ end
12
+
13
+ class PaymentsAPI < Transaction
14
+
15
+ def self.generateRandomOrderId(prefix)
16
+ "#{prefix}_#{SecureRandom.hex(8)}"
17
+ end
18
+
19
+
20
+ # Urls
21
+
22
+ def make_payment_url
23
+ "#{Beanstream.api_base_url()}/payments/"
24
+ end
25
+
26
+ def payment_returns_url(transaction_id)
27
+ "#{Beanstream.api_base_url}/payments/#{transaction_id}/returns"
28
+ end
29
+
30
+ def payment_void_url(transaction_id)
31
+ "#{Beanstream.api_base_url}/payments/#{transaction_id}/void"
32
+ end
33
+
34
+ def get_transaction_url(transaction_id)
35
+ "#{Beanstream.api_base_url}/payments/#{transaction_id}"
36
+ end
37
+
38
+ #Payment Request Hash for making a payment with a Legato token
39
+ def getTokenPaymentRequestTemplate()
40
+ request = getPaymentRequestTemplate()
41
+ request[:payment_method] = PaymentMethods::TOKEN
42
+ request[:token] = {
43
+ :name => "",
44
+ :code => "",
45
+ :complete => true
46
+ }
47
+ end
48
+
49
+ #Payment Request Hash for making a payment with a credit card number
50
+ def getCardPaymentRequestTemplate()
51
+ request = getPaymentRequestTemplate()
52
+ request[:payment_method] = PaymentMethods::CARD
53
+ request[:card] = {
54
+ :name => "",
55
+ :number => "",
56
+ :expiry_month => "",
57
+ :expiry_year => "",
58
+ :cvd => "",
59
+ :complete => true
60
+ }
61
+ end
62
+
63
+ #Payment Request Hash for making a payment with a Payment Profile
64
+ def getProfilePaymentRequestTemplate()
65
+ request = getPaymentRequestTemplate()
66
+ request[:payment_method] = PaymentMethods::PROFILE
67
+ request[:token] = {
68
+ :customer_code => "",
69
+ :card_id => 1,
70
+ :complete => true
71
+ }
72
+ end
73
+
74
+ # Base Payment Request Hash for making a payments
75
+ # Use one of getTokenPaymentRequestTemplate, getCardPaymentRequestTemplate, or getProfilePaymentRequestTemplate
76
+ # +Required parameters+:: :amount, :order_number, :payment_method, and one of [:card, :token, :payment_profile] if not paying for Cash or Cheque.
77
+ # Use PaymentMethods:: for the available payment_method options
78
+ def getPaymentRequestTemplate()
79
+ request = {
80
+ :order_number => "",
81
+ :amount => 0,
82
+ :language=> "",
83
+ :customer_ip=> "",
84
+ :term_url=> "",
85
+ :comments=> "",
86
+ :billing=> {
87
+ :name=> "",
88
+ :address_line1=> "",
89
+ :address_line2=> "",
90
+ :city=> "",
91
+ :province=> "",
92
+ :country=> "",
93
+ :postal_code=> "",
94
+ :phone_number=> "",
95
+ :email_address=> ""
96
+ },
97
+ :shipping=> {
98
+ :name=> "",
99
+ :address_line1=> "",
100
+ :address_line2=> "",
101
+ :city=> "",
102
+ :province=> "",
103
+ :country=> "",
104
+ :postal_code=> "",
105
+ :phone_number=> "",
106
+ :email_address=> ""
107
+ },
108
+ :custom=> {
109
+ :ref1=> "",
110
+ :ref2=> "",
111
+ :ref3=> "",
112
+ :ref4=> "",
113
+ :ref5=> ""
114
+ }
115
+ }
116
+ end
117
+
118
+ #API operations
119
+
120
+ # Make a payment. If the payment is approved the PaymentResponse will be returned. If for any reason
121
+ # the payment is declined or if there is a connection error an exception will be thrown.
122
+ # This will accept a PaymentRequest Hash as defined by getTokenPaymentRequestTemplate(), getCardPaymentRequestTemplate(),
123
+ # or getProfilePaymentRequestTemplate().
124
+ # +PreAuth+:: For a pre-auth you must set the 'complete' parameter of the Card, Token, or Profile to be 'false'.
125
+ def make_payment(payment)
126
+ val = transaction_post("POST", make_payment_url, Beanstream.merchant_id, Beanstream.payments_api_key, payment)
127
+ end
128
+
129
+ def complete_preauth(transaciton_id, amount)
130
+ complete_url = make_payment_url+transaciton_id+"/completions"
131
+ completion = { :amount => amount }
132
+ val = transaction_post("POST", complete_url, Beanstream.merchant_id, Beanstream.payments_api_key, completion)
133
+ end
134
+
135
+ def self.payment_approved(payment_response)
136
+ success = payment_response['approved'] == "1" && payment_response['message'] == "Approved"
137
+ end
138
+
139
+ def get_legato_token(card_info)
140
+ turl = "/scripts/tokenization/tokens"
141
+ result = Transaction.new().transaction_post("POST", turl, "", "", card_info)
142
+ token = result['token']
143
+ end
144
+
145
+ def get_transaction(transaction_id)
146
+ transaction_post("GET", get_transaction_url(transaction_id), Beanstream.merchant_id, Beanstream.payments_api_key)
147
+ end
148
+
149
+ def return_payment(transaction_id, amount)
150
+ data = { amount: amount }
151
+ transaction_post("POST", payment_returns_url(transaction_id), Beanstream.merchant_id, Beanstream.payments_api_key, data)
152
+ end
153
+
154
+ def void_payment(transaction_id, amount)
155
+ data = { amount: amount }
156
+ transaction_post("POST", payment_void_url(transaction_id), Beanstream.merchant_id, Beanstream.payments_api_key, data)
157
+ end
158
+
159
+ end
160
+
161
+ end