beanstreamy 0.2.1 → 0.2.2
Sign up to get free protection for your applications and to get access to all the features.
- data/VERSION +1 -1
- data/beanstreamy.gemspec +2 -2
- data/lib/beanstreamy/gateway.rb +12 -0
- data/lib/beanstreamy/hosted_payment_helper.rb +73 -7
- data/lib/beanstreamy/util.rb +54 -0
- metadata +3 -3
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.2.
|
1
|
+
0.2.2
|
data/beanstreamy.gemspec
CHANGED
@@ -5,11 +5,11 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = %q{beanstreamy}
|
8
|
-
s.version = "0.2.
|
8
|
+
s.version = "0.2.2"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = ["Jeff Siegel"]
|
12
|
-
s.date = %q{2010-07-
|
12
|
+
s.date = %q{2010-07-12}
|
13
13
|
s.description = %q{Adds activemerchant gateway support for hash validation, querying transactions, and submitting payment via hosted forms}
|
14
14
|
s.email = %q{jeff@stage2.ca}
|
15
15
|
s.extra_rdoc_files = [
|
data/lib/beanstreamy/gateway.rb
CHANGED
@@ -29,6 +29,18 @@ module Beanstreamy
|
|
29
29
|
|
30
30
|
private
|
31
31
|
|
32
|
+
def parse(body)
|
33
|
+
results = super
|
34
|
+
|
35
|
+
if results[:errorMessage]
|
36
|
+
results[:errorMessage].gsub!(/<LI>/, "")
|
37
|
+
results[:errorMessage].gsub!(/(\.)?<br>/, ". ")
|
38
|
+
results[:errorMessage].strip!
|
39
|
+
end
|
40
|
+
|
41
|
+
results
|
42
|
+
end
|
43
|
+
|
32
44
|
def add_transaction_type(post, action)
|
33
45
|
post[:trnType] = EXTRA_TRANSACTIONS[action] || super
|
34
46
|
end
|
@@ -4,21 +4,86 @@ module Beanstreamy
|
|
4
4
|
mattr_accessor :config
|
5
5
|
@@config = Beanstreamy.config
|
6
6
|
|
7
|
-
|
7
|
+
# Generate a form that will submit payment information to Beanstream's payment gateway
|
8
|
+
# using the http POST method.
|
9
|
+
#
|
10
|
+
# === Hash Validation
|
11
|
+
#
|
12
|
+
# It's highly recommended you enable hash validation. Otherwise end-users will be able
|
13
|
+
# to modify any information submitted to Beanstream, including the amount to be charged.
|
14
|
+
# You can specify the hash key with the +:hash_key+ option.
|
15
|
+
#
|
16
|
+
# (*Note*: Currently only SHA1 hashing is supported.)
|
17
|
+
#
|
18
|
+
# The +amount+ argument is expected to be an +Integer+ in cents, just like in ActiveMerchant.
|
19
|
+
#
|
20
|
+
# === Options
|
21
|
+
#
|
22
|
+
# [:merchant_id]
|
23
|
+
# The merchant id of your Beanstream account. This is required. You can specify this in
|
24
|
+
# the beanstreamy initializer file
|
25
|
+
# [:hash_key]
|
26
|
+
# The key used for SHA1 hash validation. You can specify this in the beanstreamy initializer file
|
27
|
+
# [:skip_hash]
|
28
|
+
# If +true+, turn off hash validation. Default is +false+.
|
29
|
+
# [:approved_url]
|
30
|
+
# The url that beanstream will redirect to for approved transactions
|
31
|
+
# [:declined_url]
|
32
|
+
# The url that beanstream will redirect to for declined transactions
|
33
|
+
# [:error_url]
|
34
|
+
# The url that beanstream will redirect to when there's validation errors with any of the submitted fields
|
35
|
+
# [:options]
|
36
|
+
# A hash of extra gateway parameters such as billing address and subtotals. Uses the same
|
37
|
+
# format as gateway options in ActiveMerchant. You'll most likely want to specify the +:order_id+ option
|
38
|
+
# at a minimum.
|
39
|
+
#
|
40
|
+
# === Example
|
41
|
+
#
|
42
|
+
# <%= beanstream_hosted_payment_form 3456, :merchant_id => 454353534, :hash_key => "FK49Clk34Jd",
|
43
|
+
# :options => {
|
44
|
+
# :order_id => "R5564396848",
|
45
|
+
# :email => "customer@example.com",
|
46
|
+
# :billing_address => {
|
47
|
+
# :name => "Reginald DeBillings",
|
48
|
+
# :address1 => "15 Over There Rd",
|
49
|
+
# :city => "Somecity",
|
50
|
+
# :province => "AB",
|
51
|
+
# :country => "CA",
|
52
|
+
# :postal_code => "T6G1K7"
|
53
|
+
# }
|
54
|
+
# } %>
|
55
|
+
# # Render fields needed for CC info
|
56
|
+
# <% end -%>
|
57
|
+
#
|
58
|
+
# In this example, it is assumed the billing information has been captured in a previous step. If you wanted to
|
59
|
+
# capture both billing information along with the CC info in one step, you would exclude it from the +:options+
|
60
|
+
# and render the appropriate fields.
|
61
|
+
#
|
62
|
+
# === TODO
|
63
|
+
#
|
64
|
+
# For rendered inputs, you need to specify the exact parameter names that Beanstream
|
65
|
+
# expects (e.g. +trnCardNumber+). There should be some extra helper methods that abstracts these to be
|
66
|
+
# similar to the +options+ hash.
|
67
|
+
def beanstream_hosted_payment_form(amount, options = {}, &block)
|
68
|
+
amount = Util.amount(amount) # convert from cents to dollars
|
8
69
|
|
9
|
-
order_id = options.delete(:order_id) or raise("Missing order id")
|
10
|
-
amount = options.delete(:amount) or raise("Missing amount")
|
11
70
|
merchant_id = options.delete(:merchant_id) || config.merchant_id
|
12
71
|
hash_key = options.delete(:hash_key) || config.hash_key
|
72
|
+
skip_hash = options.delete(:skip_hash)
|
73
|
+
|
13
74
|
approved_url = options.delete(:approved_url) || config.approved_url
|
14
75
|
declined_url = options.delete(:declined_url) || config.declined_url
|
15
76
|
error_url = options.delete(:error_url)
|
16
77
|
|
17
|
-
|
78
|
+
gateway_options = options.delete(:options) || {}
|
79
|
+
gateway_params = {}
|
80
|
+
Util.add_address(gateway_params, gateway_options)
|
81
|
+
Util.add_invoice(gateway_params, gateway_options)
|
82
|
+
|
18
83
|
extra_params = options.delete(:params)
|
19
84
|
|
85
|
+
# construct the parameter list
|
20
86
|
hashed_params = [["merchant_id", merchant_id],
|
21
|
-
["trnOrderNumber", order_id],
|
22
87
|
["trnAmount", amount]]
|
23
88
|
hashed_params << ["approvedPage", approved_url] if approved_url.present?
|
24
89
|
hashed_params << ["declinedPage", declined_url] if declined_url.present?
|
@@ -28,18 +93,19 @@ module Beanstreamy
|
|
28
93
|
hashed_params << ["hashExpiry", Util.hash_expiry(expire_at)]
|
29
94
|
end
|
30
95
|
|
96
|
+
hashed_params += Array(gateway_params)
|
31
97
|
hashed_params += Array(extra_params)
|
32
98
|
|
33
99
|
form = content_tag(:form, options.merge(:action => config.payment_url, :method => "post")) do
|
34
100
|
hashed_params.each do |key, value|
|
35
|
-
concat hidden_field_tag(key, value)
|
101
|
+
concat hidden_field_tag(key, value) if value
|
36
102
|
end
|
37
103
|
|
38
104
|
hash_value = nil
|
39
105
|
if hash_key.present? && !skip_hash
|
40
106
|
# Beansream's hosted page uses hash validation to prevent price modification. This hash is computed from
|
41
107
|
# the url encoded string of the above inputs
|
42
|
-
query_string = hashed_params.reject { |k,v| v
|
108
|
+
query_string = hashed_params.reject { |k,v| !v }.map { |k,v| v.to_query(k) }.join('&')
|
43
109
|
hash_value = Util.hash_value(hash_key, query_string)
|
44
110
|
|
45
111
|
concat hidden_field_tag("hashValue", hash_value)
|
data/lib/beanstreamy/util.rb
CHANGED
@@ -1,13 +1,67 @@
|
|
1
1
|
module Beanstreamy
|
2
2
|
module Util
|
3
|
+
|
3
4
|
def self.hash_value(key, message)
|
4
5
|
Digest::SHA1.hexdigest(message + key)
|
5
6
|
end
|
6
7
|
|
8
|
+
def self.amount(cents)
|
9
|
+
sprintf("%.2f", cents.to_f / 100)
|
10
|
+
end
|
11
|
+
|
7
12
|
def self.hash_expiry(expire_at)
|
8
13
|
# Beanstream uses PST/PDT for all their timestamps. Time stamps only have minute resolution,
|
9
14
|
# so the seconds need chopping off.
|
10
15
|
expire_at.in_time_zone("Pacific Time (US & Canada)").to_s(:number)[0..-3]
|
11
16
|
end
|
17
|
+
|
18
|
+
def self.add_address(params, options)
|
19
|
+
prepare_address_for_non_american_countries(options)
|
20
|
+
|
21
|
+
if billing_address = options[:billing_address] || options[:address]
|
22
|
+
params[:ordName] = billing_address[:name]
|
23
|
+
params[:ordEmailAddress] = options[:email]
|
24
|
+
params[:ordPhoneNumber] = billing_address[:phone]
|
25
|
+
params[:ordAddress1] = billing_address[:address1]
|
26
|
+
params[:ordAddress2] = billing_address[:address2]
|
27
|
+
params[:ordCity] = billing_address[:city]
|
28
|
+
params[:ordProvince] = billing_address[:province] || billing_address[:state]
|
29
|
+
params[:ordPostalCode] = billing_address[:postal_code] || billing_address[:zip]
|
30
|
+
params[:ordCountry] = billing_address[:country]
|
31
|
+
end
|
32
|
+
|
33
|
+
if shipping_address = options[:shipping_address]
|
34
|
+
params[:shipName] = shipping_address[:name]
|
35
|
+
params[:shipEmailAddress] = options[:email]
|
36
|
+
params[:shipPhoneNumber] = shipping_address[:phone]
|
37
|
+
params[:shipAddress1] = shipping_address[:address1]
|
38
|
+
params[:shipAddress2] = shipping_address[:address2]
|
39
|
+
params[:shipCity] = shipping_address[:city]
|
40
|
+
params[:shipProvince] = shipping_address[:province] || shipping_address[:state]
|
41
|
+
params[:shipPostalCode] = shipping_address[:postal_code] || shipping_address[:zip]
|
42
|
+
params[:shipCountry] = shipping_address[:country]
|
43
|
+
params[:shippingMethod] = shipping_address[:shipping_method]
|
44
|
+
params[:deliveryEstimate] = shipping_address[:delivery_estimate]
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
def self.prepare_address_for_non_american_countries(options)
|
49
|
+
[ options[:billing_address], options[:shipping_address] ].compact.each do |address|
|
50
|
+
unless ['US', 'CA'].include?(address[:country])
|
51
|
+
address[:province] = '--'
|
52
|
+
address[:postal_code] = '000000' unless address[:postal_code] || address[:zip]
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
def self.add_invoice(params, options)
|
58
|
+
params[:trnOrderNumber] = options[:order_id]
|
59
|
+
params[:trnComments] = options[:description]
|
60
|
+
params[:ordItemPrice] = amount(options[:subtotal])
|
61
|
+
params[:ordShippingPrice] = amount(options[:shipping])
|
62
|
+
params[:ordTax1Price] = amount(options[:tax1] || options[:tax])
|
63
|
+
params[:ordTax2Price] = amount(options[:tax2])
|
64
|
+
params[:ref1] = options[:custom]
|
65
|
+
end
|
12
66
|
end
|
13
67
|
end
|
metadata
CHANGED
@@ -5,8 +5,8 @@ version: !ruby/object:Gem::Version
|
|
5
5
|
segments:
|
6
6
|
- 0
|
7
7
|
- 2
|
8
|
-
-
|
9
|
-
version: 0.2.
|
8
|
+
- 2
|
9
|
+
version: 0.2.2
|
10
10
|
platform: ruby
|
11
11
|
authors:
|
12
12
|
- Jeff Siegel
|
@@ -14,7 +14,7 @@ autorequire:
|
|
14
14
|
bindir: bin
|
15
15
|
cert_chain: []
|
16
16
|
|
17
|
-
date: 2010-07-
|
17
|
+
date: 2010-07-12 00:00:00 -06:00
|
18
18
|
default_executable:
|
19
19
|
dependencies:
|
20
20
|
- !ruby/object:Gem::Dependency
|