inpay 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
data/.document ADDED
@@ -0,0 +1,5 @@
1
+ lib/**/*.rb
2
+ bin/*
3
+ -
4
+ features/**/*.feature
5
+ LICENSE.txt
data/Gemfile ADDED
@@ -0,0 +1,13 @@
1
+ source "http://rubygems.org"
2
+ # Add dependencies required to use your gem here.
3
+ # Example:
4
+ # gem "activesupport", ">= 2.3.5"
5
+
6
+ # Add dependencies to develop your gem here.
7
+ # Include everything needed to run rake, tests, features, etc.
8
+ group :development do
9
+ gem "shoulda", ">= 0"
10
+ gem "bundler", "~> 1.0.0"
11
+ gem "jeweler", "~> 1.5.2"
12
+ gem "rcov", ">= 0"
13
+ end
data/Gemfile.lock ADDED
@@ -0,0 +1,20 @@
1
+ GEM
2
+ remote: http://rubygems.org/
3
+ specs:
4
+ git (1.2.5)
5
+ jeweler (1.5.2)
6
+ bundler (~> 1.0.0)
7
+ git (>= 1.2.5)
8
+ rake
9
+ rake (0.8.7)
10
+ rcov (0.9.9)
11
+ shoulda (2.11.3)
12
+
13
+ PLATFORMS
14
+ ruby
15
+
16
+ DEPENDENCIES
17
+ bundler (~> 1.0.0)
18
+ jeweler (~> 1.5.2)
19
+ rcov
20
+ shoulda
data/LICENSE.txt ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2011 Wout Fierens
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.markdown ADDED
@@ -0,0 +1,140 @@
1
+ # inpay gem
2
+
3
+ ## What is it?
4
+ A Ruby gem wrapping the inpay.com API for online bank payments.
5
+
6
+ ## Who should use it?
7
+ Any Ruby on Rails developer who wants/needs to work with inpay.
8
+
9
+ ## Usage
10
+
11
+ ### Installation
12
+
13
+ gem install inpay
14
+
15
+ ### Configuration
16
+
17
+ By default the environment is set to test. Add the following line to the environments/production.rb:
18
+
19
+ Inpay::Config.mode = :production
20
+
21
+ You will also need to define the IP (or IPs) you will accept postbacks form. Add a private method in your application controller, something like this:
22
+
23
+ private
24
+
25
+ def set_inpay_ips
26
+ Inpay::Config.server_ips = 'xxx.xxx.xxx.xxx'
27
+ end
28
+
29
+ You can also use an array:
30
+
31
+ private
32
+
33
+ def set_inpay_ips
34
+ Inpay::Config.server_ips = ['xxx.xxx.xxx.xxx', 'xxx.xxx.xxx.xxx', 'xxx.xxx.xxx.xxx']
35
+ end
36
+
37
+ In the controller that will process the postback add a before filter:
38
+
39
+ before_filter :set_inpay_ips
40
+
41
+ ### The form in your view
42
+
43
+ Create a form tag and use the inpay_setup method to generate the necessary hidden fields:
44
+
45
+ <%= form_tag inpay_flow_url do %>
46
+ <%= raw inpay_setup(amount, options) %>
47
+ <% end %>
48
+
49
+ The amount can be either a float or a Money object. Options should be passed as a hash with symbolized keys.
50
+
51
+ These are all required options:
52
+
53
+ - :order_id
54
+ - :merchant_id _(your merchant id at inpay)_
55
+ - :currency _(defaults to :EUR)_
56
+ - :order_text _(a brief description)_
57
+ - :buyer_email
58
+ - :secret_key _(your sectret key from inpay)_
59
+ - :flow_layout _(defaults to :multi_page)_
60
+
61
+ These are nonmandatory:
62
+
63
+ - :return_url _(defaults to the return url set in the inpay admin)_
64
+ - :pending_url _(defaults to the return url set in the inpay admin)_
65
+ - :cancel_url _(defaults to the return url set in the inpay admin)_
66
+ - :country
67
+ - :invoice_comment
68
+ - :buyer_name
69
+ - :buyer_address
70
+
71
+ ### Handling a postback in your controller
72
+
73
+ An Inpay postback controller might look something like this:
74
+
75
+ class InpaysController < ApplicationController
76
+ skip_before_filter :verify_authenticity_token
77
+
78
+ def postback
79
+ begin
80
+ @postback = Inpay::Postback.new(request, _your_inpay_secret_key_ )
81
+
82
+ if @postback.genuine?
83
+ if @postback.approved?
84
+ ... yay ...
85
+ else
86
+ ... meh ...
87
+ end
88
+ end
89
+ rescue Exception => e
90
+ ... handle the error ...
91
+ end
92
+
93
+ render :nothing => true
94
+ end
95
+ end
96
+
97
+ Important: make sure no errors are thrown when something goes wrong. Logically Inpay will see this as a failure and keep on sending postbacks. Hence the begin/rescue block.
98
+
99
+ The Inpay::Postback instance has a lot of methods for the result of the transactions:
100
+
101
+ - genuine? _(verifies the checksum and IP of the server that performed the postback)_
102
+ - pending?
103
+ - sum_too_low?
104
+ - approved?
105
+ - cancelled?
106
+ - refunded?
107
+ - refund_pending?
108
+ - error? _(when something went wrong with connection)_
109
+
110
+ The inpay server will post back the following params:
111
+
112
+ - :invoice_currency
113
+ - :invoice_reference
114
+ - :checksum
115
+ - :order_id
116
+ - :invoice_amount
117
+ - :invoice_created_at _(e.g. 2011-02-19 10:41:55)_
118
+ - :invoice_status
119
+
120
+ You might need some of those params to fetch the invoice, status and so on.
121
+
122
+ ## Important
123
+
124
+ This gem is written for Rails 3. Rails 2 might work but it's not tested.
125
+
126
+ ## Contributing to inpay
127
+
128
+ * Check out the latest master to make sure the feature hasn't been implemented or the bug hasn't been fixed yet
129
+ * Check out the issue tracker to make sure someone already hasn't requested it and/or contributed it
130
+ * Fork the project
131
+ * Start a feature/bugfix branch
132
+ * Commit and push until you are happy with your contribution
133
+ * Make sure to add tests for it. This is important so I don't break it in a future version unintentionally.
134
+ * Please try not to mess with the Rakefile, version, or history. If you want to have your own version, or is otherwise necessary, that is fine, but please isolate to its own commit so I can cherry-pick around it.
135
+
136
+ ## Copyright
137
+
138
+ Copyright (c) 2011 Wout Fierens. See LICENSE.txt for
139
+ further details.
140
+
data/Rakefile ADDED
@@ -0,0 +1,55 @@
1
+ require 'rubygems'
2
+ require 'bundler'
3
+ begin
4
+ Bundler.setup(:default, :development)
5
+ rescue Bundler::BundlerError => e
6
+ $stderr.puts e.message
7
+ $stderr.puts "Run `bundle install` to install missing gems"
8
+ exit e.status_code
9
+ end
10
+ require 'rake'
11
+
12
+ require 'jeweler'
13
+ Jeweler::Tasks.new do |gem|
14
+ # gem is a Gem::Specification... see http://docs.rubygems.org/read/chapter/20 for more options
15
+ gem.name = "inpay"
16
+ gem.homepage = "http://github.com/wout/inpay"
17
+ gem.license = "MIT"
18
+ gem.summary = %Q{An API wrapper for the inpay.com payment system}
19
+ gem.description = %Q{An API wrapper for the inpay.com payment system}
20
+ gem.email = "wout@boysabroad.com"
21
+ gem.authors = ["Wout Fierens"]
22
+
23
+ # add main dependencies
24
+ #gem.add_dependency 'activesupport', '>= 3.0.0'
25
+
26
+ # add development dependencies
27
+ gem.add_development_dependency 'rspec', '>= 2.0.0'
28
+ end
29
+ Jeweler::RubygemsDotOrgTasks.new
30
+
31
+ require 'rake/testtask'
32
+ Rake::TestTask.new(:test) do |test|
33
+ test.libs << 'lib' << 'test'
34
+ test.pattern = 'test/**/test_*.rb'
35
+ test.verbose = true
36
+ end
37
+
38
+ require 'rcov/rcovtask'
39
+ Rcov::RcovTask.new do |test|
40
+ test.libs << 'test'
41
+ test.pattern = 'test/**/test_*.rb'
42
+ test.verbose = true
43
+ end
44
+
45
+ task :default => :test
46
+
47
+ require 'rake/rdoctask'
48
+ Rake::RDocTask.new do |rdoc|
49
+ version = File.exist?('VERSION') ? File.read('VERSION') : ""
50
+
51
+ rdoc.rdoc_dir = 'rdoc'
52
+ rdoc.title = "inpay #{version}"
53
+ rdoc.rdoc_files.include('README*')
54
+ rdoc.rdoc_files.include('lib/**/*.rb')
55
+ end
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.0.1
data/inpay.gemspec ADDED
@@ -0,0 +1,80 @@
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE DIRECTLY
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
4
+ # -*- encoding: utf-8 -*-
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = %q{inpay}
8
+ s.version = "0.0.1"
9
+
10
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
+ s.authors = ["Wout Fierens"]
12
+ s.date = %q{2011-02-19}
13
+ s.description = %q{An API wrapper for the inpay.com payment system}
14
+ s.email = %q{wout@boysabroad.com}
15
+ s.extra_rdoc_files = [
16
+ "LICENSE.txt",
17
+ "README.markdown"
18
+ ]
19
+ s.files = [
20
+ ".document",
21
+ "Gemfile",
22
+ "Gemfile.lock",
23
+ "LICENSE.txt",
24
+ "README.markdown",
25
+ "Rakefile",
26
+ "VERSION",
27
+ "inpay.gemspec",
28
+ "lib/inpay.rb",
29
+ "lib/inpay/checksum.rb",
30
+ "lib/inpay/checksum/create_invoice.rb",
31
+ "lib/inpay/checksum/postback.rb",
32
+ "lib/inpay/config.rb",
33
+ "lib/inpay/core_extensions.rb",
34
+ "lib/inpay/helpers/common.rb",
35
+ "lib/inpay/postback.rb",
36
+ "lib/inpay/rails.rb",
37
+ "lib/inpay/transaction.rb",
38
+ "spec/checksum_spec.rb",
39
+ "spec/inpay_spec.rb",
40
+ "spec/spec_helper.rb",
41
+ "test/helper.rb"
42
+ ]
43
+ s.homepage = %q{http://github.com/wout/inpay}
44
+ s.licenses = ["MIT"]
45
+ s.require_paths = ["lib"]
46
+ s.rubygems_version = %q{1.3.7}
47
+ s.summary = %q{An API wrapper for the inpay.com payment system}
48
+ s.test_files = [
49
+ "spec/checksum_spec.rb",
50
+ "spec/inpay_spec.rb",
51
+ "spec/spec_helper.rb",
52
+ "test/helper.rb"
53
+ ]
54
+
55
+ if s.respond_to? :specification_version then
56
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
57
+ s.specification_version = 3
58
+
59
+ if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
60
+ s.add_development_dependency(%q<shoulda>, [">= 0"])
61
+ s.add_development_dependency(%q<bundler>, ["~> 1.0.0"])
62
+ s.add_development_dependency(%q<jeweler>, ["~> 1.5.2"])
63
+ s.add_development_dependency(%q<rcov>, [">= 0"])
64
+ s.add_development_dependency(%q<rspec>, [">= 2.0.0"])
65
+ else
66
+ s.add_dependency(%q<shoulda>, [">= 0"])
67
+ s.add_dependency(%q<bundler>, ["~> 1.0.0"])
68
+ s.add_dependency(%q<jeweler>, ["~> 1.5.2"])
69
+ s.add_dependency(%q<rcov>, [">= 0"])
70
+ s.add_dependency(%q<rspec>, [">= 2.0.0"])
71
+ end
72
+ else
73
+ s.add_dependency(%q<shoulda>, [">= 0"])
74
+ s.add_dependency(%q<bundler>, ["~> 1.0.0"])
75
+ s.add_dependency(%q<jeweler>, ["~> 1.5.2"])
76
+ s.add_dependency(%q<rcov>, [">= 0"])
77
+ s.add_dependency(%q<rspec>, [">= 2.0.0"])
78
+ end
79
+ end
80
+
@@ -0,0 +1,13 @@
1
+ module Inpay
2
+ module Checksum
3
+ class CreateInvoice < Inpay::Checksum::Base
4
+
5
+ private
6
+
7
+ def keys
8
+ Inpay::Config.keys_for(:create_invoice)
9
+ end
10
+
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,13 @@
1
+ module Inpay
2
+ module Checksum
3
+ class Postback < Inpay::Checksum::Base
4
+
5
+ private
6
+
7
+ def keys
8
+ Inpay::Config.keys_for(:postback)
9
+ end
10
+
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,29 @@
1
+ # -*- encoding : utf-8 -*-
2
+ require 'cgi'
3
+ require 'digest/md5'
4
+
5
+ module Inpay
6
+ module Checksum
7
+
8
+ # checksum base class should only be used as a subclass
9
+ class Base
10
+
11
+ def initialize params
12
+ @params = params
13
+ end
14
+
15
+ # build a checksum from given parameters
16
+ def result
17
+ @_result ||= Digest::MD5.hexdigest(param_string)
18
+ end
19
+
20
+ # build a param_string from given parameters
21
+ def param_string
22
+ keys.collect do |p|
23
+ "#{ p }=#{ CGI.escape(@params[:"#{ p }"].to_s) }"
24
+ end.join('&')
25
+ end
26
+
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,48 @@
1
+ module Inpay
2
+ module Config
3
+
4
+ # flow urls
5
+ def self.flow_urls
6
+ Thread.current[:flow_urls] ||= {
7
+ :test => "https://test-secure.inpay.com/",
8
+ :production => "https://secure.inpay.com/"
9
+ }
10
+ end
11
+ def self.flow_url
12
+ flow_urls[mode]
13
+ end
14
+
15
+ # current operation mode
16
+ def self.mode= new_mode
17
+ new_mode = new_mode.to_sym
18
+
19
+ unless [:test, :production].include?(new_mode)
20
+ raise ArgumentError.new("Inpay::Config.mode should be either :test or :production (you tried to set it as :#{ new_mode })")
21
+ end
22
+
23
+ Thread.current[:mode] = new_mode
24
+ end
25
+ def self.mode
26
+ Thread.current[:mode] ||= :test
27
+ end
28
+
29
+ # inpay server ips
30
+ def self.server_ips= ips
31
+ Thread.current[:server_ips] = [ips].flatten
32
+ end
33
+ def self.server_ips
34
+ Thread.current[:server_ips] ||= []
35
+ end
36
+
37
+ # fields
38
+ def self.keys_for action
39
+ case action.to_sym
40
+ when :create_invoice
41
+ %w(merchant_id order_id amount currency order_text flow_layout secret_key)
42
+ when :postback
43
+ %w(order_id invoice_reference invoice_amount invoice_currency invoice_created_at invoice_status secret_key)
44
+ end
45
+ end
46
+
47
+ end
48
+ end
@@ -0,0 +1,11 @@
1
+ # -*- encoding : utf-8 -*-
2
+ class Hash
3
+ def recursive_symbolize_keys!
4
+ symbolize_keys!
5
+ # symbolize each hash in .values
6
+ values.each{|h| h.recursive_symbolize_keys! if h.is_a?(Hash) }
7
+ # symbolize each hash inside an array in .values
8
+ values.select{|v| v.is_a?(Array) }.flatten.each{|h| h.recursive_symbolize_keys! if h.is_a?(Hash) }
9
+ self
10
+ end
11
+ end
@@ -0,0 +1,70 @@
1
+ module Inpay
2
+ module Helpers
3
+ module Common
4
+
5
+ # nice option for form url
6
+ def inpay_flow_url
7
+ Inpay::Config.flow_url
8
+ end
9
+
10
+ def inpay_setup amount, options
11
+ misses = (options.keys - valid_invoice_options)
12
+ raise ArgumentError, "Unknown options #{ misses.inspect }" unless misses.empty?
13
+
14
+ params = {
15
+ :currency => :EUR,
16
+ :flow_layout => :multi_page
17
+ }.merge(options)
18
+
19
+ # fetch currency from amount if a Money object is passed
20
+ params[:currency] = amount.currency if amount.respond_to?(:currency)
21
+
22
+ # accept both strings and Money objects as amount
23
+ amount = amount.cents.to_f / 100.0 if amount.respond_to?(:cents)
24
+ params[:amount] = sprintf('%.2f', amount)
25
+
26
+ # add checksum
27
+ params[:checksum] = Inpay.checksum(:create_invoice, params)
28
+
29
+ params.delete(:secret_key)
30
+
31
+ # build form
32
+ inpay_fields(params)
33
+ end
34
+
35
+ def inpay_fields fields = {}
36
+ fields.collect do |key, value|
37
+ %Q{<input type="hidden" name="#{ key }" value="#{ value }" />}
38
+ end.join("\n")
39
+ end
40
+
41
+ private
42
+
43
+ # all possible invoice options
44
+ def valid_invoice_options
45
+ [
46
+ # required
47
+ :order_id,
48
+ :merchant_id,
49
+ :amount,
50
+ :currency,
51
+ :order_text,
52
+ :flow_layout,
53
+ :buyer_email,
54
+ :secret_key,
55
+ :checksum,
56
+
57
+ # nonmandatory
58
+ :return_url,
59
+ :pending_url,
60
+ :cancel_url,
61
+ :country,
62
+ :invoice_comment,
63
+ :buyer_name,
64
+ :buyer_address
65
+ ]
66
+ end
67
+
68
+ end
69
+ end
70
+ end
@@ -0,0 +1,83 @@
1
+ # -*- encoding : utf-8 -*-
2
+ module Inpay
3
+ class NoDataError < StandardError; end
4
+ class InvalidIPError < StandardError; end
5
+ class ForgedRequestError < StandardError; end
6
+
7
+ class Postback
8
+ attr_accessor :raw, :params, :error
9
+
10
+ def initialize request, secret_key
11
+ raise NoDataError if request.nil? || request.raw_post.to_s.blank?
12
+
13
+ @secret_key = secret_key
14
+ @remote_ip = request.remote_ip
15
+ @params = {}
16
+ @raw = ''
17
+
18
+ parse(request.raw_post)
19
+ end
20
+
21
+ # Transaction statuses
22
+ def pending?
23
+ status == :pending
24
+ end
25
+
26
+ def sum_too_low?
27
+ status == :sum_too_low
28
+ end
29
+
30
+ def approved?
31
+ status == :approved
32
+ end
33
+
34
+ def cancelled?
35
+ status == :cancelled
36
+ end
37
+
38
+ def refunded?
39
+ status == :refunded?
40
+ end
41
+
42
+ def refund_pending?
43
+ status == :refund_pending
44
+ end
45
+
46
+ def error?
47
+ status == :error
48
+ end
49
+
50
+ def method_missing(method, *args)
51
+ params[method.to_s] || super
52
+ end
53
+
54
+ # acknowledge postback data
55
+ def genuine?
56
+ self.error = InvalidIPError unless Inpay::Config.server_ips.include?(@remote_ip)
57
+ self.error = ForgedRequestError unless Inpay.checksum(:postback, params) == params[:checksum]
58
+
59
+ error.nil?
60
+ end
61
+
62
+ private
63
+
64
+ def status
65
+ @status ||= (params[:invoice_status] ? params[:invoice_status].to_sym : nil)
66
+ end
67
+
68
+ # Take the posted data and move the relevant data into a hash
69
+ def parse post
70
+ @raw = post
71
+ self.params = Rack::Utils.parse_query(post).symbolize_keys
72
+
73
+ # Rack allows duplicate keys in queries, we need to use only the last value here
74
+ params.each do |k, v|
75
+ self.params[k] = v.last if v.is_a?(Array)
76
+ end
77
+
78
+ # add secret key
79
+ params[:secret_key] = @secret_key
80
+ end
81
+ end
82
+
83
+ end
@@ -0,0 +1,3 @@
1
+ require File.join(File.dirname(__FILE__), 'helpers', 'common')
2
+
3
+ ActionView::Base.send(:include, Inpay::Helpers::Common)
@@ -0,0 +1,4 @@
1
+ # -*- encoding : utf-8 -*-
2
+ class Inpay::Transaction
3
+
4
+ end
data/lib/inpay.rb ADDED
@@ -0,0 +1,31 @@
1
+ # -*- encoding : utf-8 -*-
2
+ require 'rubygems'
3
+ require 'net/http'
4
+
5
+ require 'active_support/core_ext/hash/conversions'
6
+ require 'active_support/core_ext/string/inflections'
7
+
8
+ require 'inpay/config'
9
+ require 'inpay/rails'
10
+ require 'inpay/core_extensions'
11
+ require 'inpay/postback'
12
+ require 'inpay/checksum'
13
+ require 'inpay/checksum/create_invoice'
14
+ require 'inpay/checksum/postback'
15
+
16
+ $:.unshift(File.dirname(__FILE__)) unless
17
+ $:.include?(File.dirname(__FILE__)) || $:.include?(File.expand_path(File.dirname(__FILE__)))
18
+
19
+ module Inpay
20
+
21
+ # shortcut for checksum calculation
22
+ def self.checksum action, params
23
+ unless %w(create_invoice postback).include?(action.to_s)
24
+ raise ArgumentError.new("'#{ action }' is not a valid action")
25
+ end
26
+
27
+ checksum = "Inpay::Checksum::#{ action.to_s.classify }".constantize.new(params)
28
+ checksum.result
29
+ end
30
+
31
+ end
@@ -0,0 +1,69 @@
1
+ # -*- encoding : utf-8 -*-
2
+ require 'spec_helper'
3
+ require 'inpay/checksum'
4
+
5
+ describe Inpay::Checksum::CreateInvoice do
6
+
7
+ describe "calculate checksum according to values in API manual" do
8
+ before(:each) do
9
+ init_checksum(
10
+ :merchant_id => 1,
11
+ :order_id => 123,
12
+ :amount => 100.07,
13
+ :currency => :USD,
14
+ :order_text => "on på x.y-z",
15
+ :secret_key => 'sec'
16
+ )
17
+ end
18
+
19
+ it "builds an url encoded string of params" do
20
+ @checksum.param_string.should == 'merchant_id=1&order_id=123&amount=100.07&currency=USD&order_text=on+p%C3%A5+x.y-z&flow_layout=multi_page&secret_key=sec'
21
+ end
22
+
23
+ it "generates a md5 key" do
24
+ @checksum.result.should == 'd861859457208e4b40777b85502b0fcd'
25
+ end
26
+ end
27
+
28
+ describe "calculate checksum with Canadian dollars" do
29
+ before(:each) do
30
+ init_checksum
31
+ end
32
+
33
+ it "builds an url encoded string of params" do
34
+ @checksum.param_string.should == 'merchant_id=100&order_id=987654&amount=20&currency=CAD&order_text=Order+%23987654+ad+mysite.com&flow_layout=multi_page&secret_key=foo'
35
+ end
36
+
37
+ it "generates a md5 key" do
38
+ @checksum.result.should == '012d5ffd5bac11fa051bcd42f648a4d7'
39
+ end
40
+ end
41
+
42
+ describe "calculate checksum with tailing zero in float" do
43
+ before(:each) do
44
+ init_checksum(:amount => 10.0, :currency => :EUR)
45
+ end
46
+
47
+ it "builds an url encoded string of params" do
48
+ @checksum.param_string.should == 'merchant_id=100&order_id=987654&amount=10.0&currency=EUR&order_text=Order+%23987654+ad+mysite.com&flow_layout=multi_page&secret_key=foo'
49
+ end
50
+
51
+ it "generates a md5 key" do
52
+ @checksum.result.should == 'fd41e34f3e9691de18b6fde0c36dfc6a'
53
+ end
54
+ end
55
+
56
+ private
57
+
58
+ def init_checksum options = {}
59
+ @checksum = Inpay::Checksum::CreateInvoice.new({
60
+ :merchant_id => '100',
61
+ :order_id => '987654',
62
+ :amount => 20,
63
+ :currency => :CAD,
64
+ :order_text => 'Order #987654 ad mysite.com',
65
+ :flow_layout => :multi_page,
66
+ :secret_key => 'foo'
67
+ }.update(options))
68
+ end
69
+ end
@@ -0,0 +1,27 @@
1
+ # -*- encoding : utf-8 -*-
2
+ require 'spec_helper'
3
+ require 'inpay'
4
+
5
+ describe Inpay do
6
+
7
+ describe "#checksum" do
8
+ it "should generate a valid checksum for 'create_invoice'" do
9
+ Inpay.checksum(:create_invoice, create_invoice_params).should == '012d5ffd5bac11fa051bcd42f648a4d7'
10
+ end
11
+ end
12
+
13
+ private
14
+
15
+ def create_invoice_params
16
+ {
17
+ :merchant_id => '100',
18
+ :order_id => '987654',
19
+ :amount => 20,
20
+ :currency => :CAD,
21
+ :order_text => 'Order #987654 ad mysite.com',
22
+ :flow_layout => :multi_page,
23
+ :secret_key => 'foo'
24
+ }
25
+ end
26
+
27
+ end
@@ -0,0 +1,21 @@
1
+ # -*- encoding : utf-8 -*-
2
+ require 'inpay'
3
+ require 'inpay/checksum'
4
+ require 'inpay/notification'
5
+ require 'inpay/transaction'
6
+
7
+ class Hash
8
+
9
+ def except(*keys)
10
+ self.reject { |k,v| keys.include?(k || k.to_sym) }
11
+ end
12
+
13
+ def with(overrides = {})
14
+ self.merge overrides
15
+ end
16
+
17
+ def only(*keys)
18
+ self.reject { |k,v| !keys.include?(k || k.to_sym) }
19
+ end
20
+
21
+ end
data/test/helper.rb ADDED
@@ -0,0 +1,19 @@
1
+ # -*- encoding : utf-8 -*-
2
+ require 'rubygems'
3
+ require 'bundler'
4
+ begin
5
+ Bundler.setup(:default, :development)
6
+ rescue Bundler::BundlerError => e
7
+ $stderr.puts e.message
8
+ $stderr.puts "Run `bundle install` to install missing gems"
9
+ exit e.status_code
10
+ end
11
+ require 'test/unit'
12
+ require 'shoulda'
13
+
14
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
15
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
16
+ require 'inpay'
17
+
18
+ class Test::Unit::TestCase
19
+ end
metadata ADDED
@@ -0,0 +1,160 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: inpay
3
+ version: !ruby/object:Gem::Version
4
+ prerelease: false
5
+ segments:
6
+ - 0
7
+ - 0
8
+ - 1
9
+ version: 0.0.1
10
+ platform: ruby
11
+ authors:
12
+ - Wout Fierens
13
+ autorequire:
14
+ bindir: bin
15
+ cert_chain: []
16
+
17
+ date: 2011-02-19 00:00:00 +01:00
18
+ default_executable:
19
+ dependencies:
20
+ - !ruby/object:Gem::Dependency
21
+ name: shoulda
22
+ requirement: &id001 !ruby/object:Gem::Requirement
23
+ none: false
24
+ requirements:
25
+ - - ">="
26
+ - !ruby/object:Gem::Version
27
+ segments:
28
+ - 0
29
+ version: "0"
30
+ type: :development
31
+ prerelease: false
32
+ version_requirements: *id001
33
+ - !ruby/object:Gem::Dependency
34
+ name: bundler
35
+ requirement: &id002 !ruby/object:Gem::Requirement
36
+ none: false
37
+ requirements:
38
+ - - ~>
39
+ - !ruby/object:Gem::Version
40
+ segments:
41
+ - 1
42
+ - 0
43
+ - 0
44
+ version: 1.0.0
45
+ type: :development
46
+ prerelease: false
47
+ version_requirements: *id002
48
+ - !ruby/object:Gem::Dependency
49
+ name: jeweler
50
+ requirement: &id003 !ruby/object:Gem::Requirement
51
+ none: false
52
+ requirements:
53
+ - - ~>
54
+ - !ruby/object:Gem::Version
55
+ segments:
56
+ - 1
57
+ - 5
58
+ - 2
59
+ version: 1.5.2
60
+ type: :development
61
+ prerelease: false
62
+ version_requirements: *id003
63
+ - !ruby/object:Gem::Dependency
64
+ name: rcov
65
+ requirement: &id004 !ruby/object:Gem::Requirement
66
+ none: false
67
+ requirements:
68
+ - - ">="
69
+ - !ruby/object:Gem::Version
70
+ segments:
71
+ - 0
72
+ version: "0"
73
+ type: :development
74
+ prerelease: false
75
+ version_requirements: *id004
76
+ - !ruby/object:Gem::Dependency
77
+ name: rspec
78
+ requirement: &id005 !ruby/object:Gem::Requirement
79
+ none: false
80
+ requirements:
81
+ - - ">="
82
+ - !ruby/object:Gem::Version
83
+ segments:
84
+ - 2
85
+ - 0
86
+ - 0
87
+ version: 2.0.0
88
+ type: :development
89
+ prerelease: false
90
+ version_requirements: *id005
91
+ description: An API wrapper for the inpay.com payment system
92
+ email: wout@boysabroad.com
93
+ executables: []
94
+
95
+ extensions: []
96
+
97
+ extra_rdoc_files:
98
+ - LICENSE.txt
99
+ - README.markdown
100
+ files:
101
+ - .document
102
+ - Gemfile
103
+ - Gemfile.lock
104
+ - LICENSE.txt
105
+ - README.markdown
106
+ - Rakefile
107
+ - VERSION
108
+ - inpay.gemspec
109
+ - lib/inpay.rb
110
+ - lib/inpay/checksum.rb
111
+ - lib/inpay/checksum/create_invoice.rb
112
+ - lib/inpay/checksum/postback.rb
113
+ - lib/inpay/config.rb
114
+ - lib/inpay/core_extensions.rb
115
+ - lib/inpay/helpers/common.rb
116
+ - lib/inpay/postback.rb
117
+ - lib/inpay/rails.rb
118
+ - lib/inpay/transaction.rb
119
+ - spec/checksum_spec.rb
120
+ - spec/inpay_spec.rb
121
+ - spec/spec_helper.rb
122
+ - test/helper.rb
123
+ has_rdoc: true
124
+ homepage: http://github.com/wout/inpay
125
+ licenses:
126
+ - MIT
127
+ post_install_message:
128
+ rdoc_options: []
129
+
130
+ require_paths:
131
+ - lib
132
+ required_ruby_version: !ruby/object:Gem::Requirement
133
+ none: false
134
+ requirements:
135
+ - - ">="
136
+ - !ruby/object:Gem::Version
137
+ hash: -701876357935352884
138
+ segments:
139
+ - 0
140
+ version: "0"
141
+ required_rubygems_version: !ruby/object:Gem::Requirement
142
+ none: false
143
+ requirements:
144
+ - - ">="
145
+ - !ruby/object:Gem::Version
146
+ segments:
147
+ - 0
148
+ version: "0"
149
+ requirements: []
150
+
151
+ rubyforge_project:
152
+ rubygems_version: 1.3.7
153
+ signing_key:
154
+ specification_version: 3
155
+ summary: An API wrapper for the inpay.com payment system
156
+ test_files:
157
+ - spec/checksum_spec.rb
158
+ - spec/inpay_spec.rb
159
+ - spec/spec_helper.rb
160
+ - test/helper.rb