payza_payments 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (68) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +19 -0
  3. data/.travis.yml +5 -0
  4. data/Gemfile +4 -0
  5. data/LICENSE.txt +22 -0
  6. data/README.md +135 -0
  7. data/Rakefile +1 -0
  8. data/lib/payza_payments.rb +23 -0
  9. data/lib/payza_payments/base.rb +17 -0
  10. data/lib/payza_payments/button_generator.rb +41 -0
  11. data/lib/payza_payments/ipn_handler.rb +44 -0
  12. data/lib/payza_payments/version.rb +3 -0
  13. data/payza_payments.gemspec +29 -0
  14. data/spec/payza_payments/button_generator_spec.rb +24 -0
  15. data/spec/spec_helper.rb +6 -0
  16. data/test/dummy/.gitignore +16 -0
  17. data/test/dummy/Gemfile +54 -0
  18. data/test/dummy/README.rdoc +28 -0
  19. data/test/dummy/Rakefile +6 -0
  20. data/test/dummy/app/assets/images/.keep +0 -0
  21. data/test/dummy/app/assets/javascripts/application.js +16 -0
  22. data/test/dummy/app/assets/stylesheets/application.css +13 -0
  23. data/test/dummy/app/controllers/application_controller.rb +5 -0
  24. data/test/dummy/app/controllers/concerns/.keep +0 -0
  25. data/test/dummy/app/controllers/dummy_controller.rb +5 -0
  26. data/test/dummy/app/helpers/application_helper.rb +2 -0
  27. data/test/dummy/app/mailers/.keep +0 -0
  28. data/test/dummy/app/models/.keep +0 -0
  29. data/test/dummy/app/models/concerns/.keep +0 -0
  30. data/test/dummy/app/views/dummy/index.html.haml +1 -0
  31. data/test/dummy/app/views/layouts/application.html.erb +14 -0
  32. data/test/dummy/bin/bundle +3 -0
  33. data/test/dummy/bin/rails +4 -0
  34. data/test/dummy/bin/rake +4 -0
  35. data/test/dummy/config.ru +4 -0
  36. data/test/dummy/config/application.rb +23 -0
  37. data/test/dummy/config/boot.rb +4 -0
  38. data/test/dummy/config/database.yml +25 -0
  39. data/test/dummy/config/environment.rb +5 -0
  40. data/test/dummy/config/environments/development.rb +29 -0
  41. data/test/dummy/config/environments/production.rb +80 -0
  42. data/test/dummy/config/environments/test.rb +36 -0
  43. data/test/dummy/config/initializers/backtrace_silencers.rb +7 -0
  44. data/test/dummy/config/initializers/filter_parameter_logging.rb +4 -0
  45. data/test/dummy/config/initializers/inflections.rb +16 -0
  46. data/test/dummy/config/initializers/mime_types.rb +5 -0
  47. data/test/dummy/config/initializers/payza.rb +4 -0
  48. data/test/dummy/config/initializers/secret_token.rb +12 -0
  49. data/test/dummy/config/initializers/session_store.rb +3 -0
  50. data/test/dummy/config/initializers/wrap_parameters.rb +14 -0
  51. data/test/dummy/config/locales/en.yml +23 -0
  52. data/test/dummy/config/payza.yml +14 -0
  53. data/test/dummy/config/routes.rb +58 -0
  54. data/test/dummy/db/schema.rb +16 -0
  55. data/test/dummy/db/seeds.rb +7 -0
  56. data/test/dummy/dump.rdb +0 -0
  57. data/test/dummy/lib/assets/.keep +0 -0
  58. data/test/dummy/lib/tasks/.keep +0 -0
  59. data/test/dummy/public/404.html +58 -0
  60. data/test/dummy/public/422.html +58 -0
  61. data/test/dummy/public/500.html +57 -0
  62. data/test/dummy/public/favicon.ico +0 -0
  63. data/test/dummy/public/robots.txt +5 -0
  64. data/test/dummy/spec/controllers/dummy_controller_spec.rb +43 -0
  65. data/test/dummy/spec/spec_helper.rb +43 -0
  66. data/test/dummy/vendor/assets/javascripts/.keep +0 -0
  67. data/test/dummy/vendor/assets/stylesheets/.keep +0 -0
  68. metadata +263 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 3a2eb8ce7c8f9c67f7d01d9b96a3dd840d3c636f
4
+ data.tar.gz: 4f8d0ed3b043c50c59a7541ce54c04f7dd0036d3
5
+ SHA512:
6
+ metadata.gz: 05756a59ad447e1330d0abfc977407fce2e6f53cd08b8565ad3eeb2c75dcc11856dd4a8bf67f0f4de77cbdd3ac733775648579f688c7df243acf438c376e5407
7
+ data.tar.gz: f39a10e68a5684923f687260a2d9b2a94e787bae39ed212827f300a072dcc63d4112804e300b9f96166312066742311a12f547fd160b5fe18f2ea6425557b7a1
data/.gitignore ADDED
@@ -0,0 +1,19 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
18
+ .idea/
19
+ .DS_Store
data/.travis.yml ADDED
@@ -0,0 +1,5 @@
1
+ language: ruby
2
+ rvm:
3
+ - 2.0.0
4
+ before_script: cd ./test/dummy/ && bundle install
5
+ script: cd ./test/dummy/ && bundle exec rake spec
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in payza_payments.gemspec
4
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2013 Patricio Cano
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,135 @@
1
+ # PayzaPayments
2
+ [![Build Status](https://travis-ci.org/FreedomVPN/liberty_reserve_payments.png?branch=master)](https://travis-ci.org/FreedomVPN/liberty_reserve_payments)
3
+
4
+ Configure buttons for Payza based on your requirements and validate IPN requests sent by Payza.
5
+ With this gem the user of your shop can pay for a digital item (or any type of item) and you can validate the transaction
6
+ after it was made.
7
+
8
+ ## Installation
9
+
10
+ Add this line to your application's Gemfile:
11
+
12
+ gem 'payza_payments'
13
+
14
+ And then execute:
15
+
16
+ $ bundle
17
+
18
+ Or install it yourself as:
19
+
20
+ $ gem install payza_payments
21
+
22
+ ## Usage
23
+
24
+ After the installation, you still need two files for the gem to work. A Yaml config file and an initializer.
25
+
26
+ ### config/payza.yml
27
+ ```yaml
28
+ development:
29
+ ipn_security_code: xhs123457
30
+ merchant_email: sample@example.com
31
+ sandbox: true
32
+
33
+ production:
34
+ ipn_security_code: xhs123457
35
+ merchant_email: sample@example.com
36
+ sandbox: false
37
+
38
+ test:
39
+ ipn_security_code: xhs123457
40
+ merchant_email: sample@example.com
41
+ sandbox: true
42
+ ```
43
+
44
+ ### config/initializers/payza.rb
45
+ ```ruby
46
+ require 'payza_payments'
47
+
48
+ PAYZA_CONFIG = YAML.load_file("#{Rails.root}/config/payza.yml")[Rails.env].symbolize_keys
49
+ ```
50
+
51
+ After creating these files you still need to add the methods provided by this gem to your PaymentsController.
52
+ To do this you can add the following template methods to you file:
53
+
54
+ ```ruby
55
+ def pay_item_with_payza
56
+ # With this you will pass the ButtonGenerator instance to the view
57
+ # in order to be able to get the button in your view with the correct
58
+ # parameters.
59
+ @payza = PayzaPayments::ButtonGenerator.new PAYZA_CONFIG
60
+ @invoice = Invoice.new(params[:invoice])
61
+ end
62
+ ```
63
+
64
+ There are two methods for generating buttons. `.generate_simple_button` and
65
+ `.generate_subscription_button`. Both take similar parameters:
66
+ ```ruby
67
+ # action points to the current view
68
+ # order_id can be any identifier you want. It should allow you to match
69
+ # the IPN request to something in your application.
70
+ .generate_simple_button(action, purchase_type, item_name, amount, currency,
71
+ return_url, cancel_url, item_description, order_id)
72
+
73
+ # time_unit: can be 'Day', 'Week', 'Month', 'Year'
74
+ # period_length: gives how long the subscription will be, depending on time_unit
75
+ # it can go from 1 to 90.
76
+ .generate_subscription_button(action, purchase_type, item_name, amount, currency,
77
+ return_url, cancel_url, item_description, order_id,
78
+ time_unit, period_length)
79
+ ```
80
+ The code in the view may look like this (Haml example)
81
+ ```haml
82
+ = @payza.generate_simple_button(self, :item, 'Sample item', 5, 'EUR', 'http://exa.co/success',
83
+ 'http://exa.co/cancel', 'Sample Desc', @invoice.id)
84
+
85
+ ```
86
+ You should also add a route for Payza to send the IPN notifications. This gem supports both v1 and v2
87
+ of Payza. PayzaPayments will only validate the basic verification parameters. After a successful validation
88
+ you should still manually go through the parameters in order to match the payment to a corresponding order.
89
+
90
+ It can point to a method looking like this:
91
+
92
+ ```ruby
93
+ def validate_ipn_v2
94
+ handler = PayzaPayments::IpnHandler.new PAYZA_CONFIG
95
+ response = handler.handle_ipn_v2(params[:token])
96
+ if response == 'INVALID REQUEST'
97
+ # Response is not valid, log it and review it later
98
+ else
99
+ # The transaction has been successfully verified
100
+ # use the response hash to validate it has the
101
+ # correct data. You should use response['apc_1'] to
102
+ # fetch the order id, or any other parameter you passed
103
+ # on the view to validate against your DB.
104
+ invoice = Invoice.find(response['apc_1'])
105
+ if (response['ap_merchant'] == handler.merchant_email and
106
+ response['ap_status'] == 'Success' and response['ap_amount'] == invoice.amount)
107
+ # Now we know that the transaction was successful, the amount matches and
108
+ # the payment was sent to us. For a list of all the IPN variables go to
109
+ # https://dev.payza.com/resources/references/ipn-variables
110
+ else
111
+ # Something devious has happened!
112
+ end
113
+ end
114
+ end
115
+
116
+ def validate_ipn
117
+ handler = ...
118
+ response = handler.handle_ipn(params)
119
+ if response == true
120
+ # params[:ap_securitycode] and params[:ap_merchant] have already been
121
+ # validated. You should still validate the rest.
122
+ else
123
+ # INVALID
124
+ end
125
+ end
126
+
127
+ ```
128
+
129
+ ## Contributing
130
+
131
+ 1. Fork it
132
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
133
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
134
+ 4. Push to the branch (`git push origin my-new-feature`)
135
+ 5. Create new Pull Request
data/Rakefile ADDED
@@ -0,0 +1 @@
1
+ require "bundler/gem_tasks"
@@ -0,0 +1,23 @@
1
+ require 'attr_required'
2
+ require 'attr_optional'
3
+ require 'payza_payments/version'
4
+ require 'payza_payments/base'
5
+ require 'payza_payments/ipn_handler'
6
+ require 'payza_payments/button_generator'
7
+
8
+ module PayzaPayments
9
+
10
+ def self.sandbox!
11
+ self.sandbox = true
12
+ end
13
+
14
+ def self.sandbox=(boolean)
15
+ @@sandbox = boolean
16
+ end
17
+
18
+ def self.sandbox?
19
+ @@sandbox
20
+ end
21
+ self.sandbox = false
22
+
23
+ end
@@ -0,0 +1,17 @@
1
+ module PayzaPayments
2
+ class Base
3
+ include AttrRequired, AttrOptional
4
+
5
+ attr_required :ipn_security_code, :merchant_email, :sandbox
6
+
7
+ def initialize(attributes = {})
8
+ if attributes.is_a?(Hash)
9
+ (required_attributes + optional_attributes).each do |key|
10
+ value = attributes[key]
11
+ self.send "#{key}=", value
12
+ end
13
+ end
14
+ attr_missing!
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,41 @@
1
+ #require 'action_view'
2
+ module PayzaPayments
3
+ class ButtonGenerator < Base
4
+ include ActionView::Helpers
5
+
6
+ def initialize(attributes = {})
7
+ super
8
+ end
9
+
10
+ def generate_simple_button(action, purchase_type, item_name, amount, currency, return_url, cancel_url, item_description, order_id)
11
+ action.content_tag(:form, method: :post, action: 'https://secure.payza.com/checkout') do
12
+ common_tags(purchase_type, item_name, amount, currency, return_url, cancel_url, item_description, order_id)
13
+ end
14
+ end
15
+
16
+ def generate_subscription_button(action, purchase_type, item_name, amount, currency, return_url, cancel_url,
17
+ item_description, order_id, time_unit, period_length)
18
+ action.content_tag :form, method: :post, action: 'https://secure.payza.com/checkout' do
19
+ common_tags(purchase_type, item_name, amount, currency, return_url, cancel_url, item_description, order_id) +
20
+ tag(:input, type: :hidden, name: 'ap_timeunit', value: time_unit) +
21
+ tag(:input, type: :hidden, name: 'ap_periodlength', value: period_length)
22
+ end
23
+ end
24
+
25
+ private
26
+
27
+ def common_tags(purchase_type, item_name, amount, currency, return_url, cancel_url, item_description, order_id)
28
+ tag(:input, type: :hidden, name: 'ap_purchasetype', value: purchase_type) +
29
+ tag(:input, type: :hidden, name: 'ap_merchant', value: self.merchant_email) +
30
+ tag(:input, type: :hidden, name: 'ap_itemname', value: item_name) +
31
+ tag(:input, type: :hidden, name: 'ap_currency', value: currency) +
32
+ tag(:input, type: :hidden, name: 'ap_amount', value: amount) +
33
+ tag(:input, type: :hidden, name: 'ap_description', value: item_description) +
34
+ tag(:input, type: :hidden, name: 'ap_returnurl', value: return_url) +
35
+ tag(:input, type: :hidden, name: 'ap_cancelurl', value: cancel_url) +
36
+ tag(:input, type: :hidden, name: 'apc_1', value: order_id) +
37
+ tag(:input, type: :image, name: 'ap_image', src: 'https://www.payza.com/images/payza-buy-now.png')
38
+ end
39
+
40
+ end
41
+ end
@@ -0,0 +1,44 @@
1
+ require 'httparty'
2
+ module PayzaPayments
3
+ class IpnHandler < Base
4
+
5
+ SANDBOX_IPN = 'https://sandbox.payza.com/sandbox/ipn2.ashx'
6
+ PRODUCTION_IPN = 'https://secure.payza.com/ipn2.ashx'
7
+
8
+ def initialize(attributes = {})
9
+ super
10
+ end
11
+
12
+ def handle_ipn(params)
13
+ if params[:ap_securitycode] == self.ipn_security_code and params[:ap_merchant] == self.merchant_email
14
+ true
15
+ else
16
+ false
17
+ end
18
+ end
19
+
20
+ def handle_ipn_v2(token)
21
+ validate_ipn(token) ? @response.parsed_response : 'INVALID REQUEST'
22
+ end
23
+
24
+ private
25
+
26
+ def validate_ipn(token)
27
+ if self.sandbox?
28
+ send_ipn_validation(token, SANDBOX_IPN)
29
+ else
30
+ send_ipn_validation(token, PRODUCTION_IPN)
31
+ end
32
+ end
33
+
34
+ def send_ipn_validation(token_value, url)
35
+ token = { token: token_value }
36
+ @response = HTTParty.post(url, token)
37
+ if @response.parsed_response == 'INVALID TOKEN'
38
+ false
39
+ else
40
+ true
41
+ end
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,3 @@
1
+ module PayzaPayments
2
+ VERSION = '0.1.0'
3
+ end
@@ -0,0 +1,29 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'payza_payments/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = 'payza_payments'
8
+ spec.version = PayzaPayments::VERSION
9
+ spec.authors = ['Patricio Cano']
10
+ spec.email = %w(admin@insomniware.com)
11
+ spec.description = %q{Validate Payza IPN payments and create payment buttons}
12
+ spec.summary = %q{You can generate buy now and subscription buttons for your application, and then
13
+ validate the IPN request sent.}
14
+ spec.homepage = 'https://github.com/supernova32/payza_payments'
15
+ spec.license = 'MIT'
16
+
17
+ spec.files = `git ls-files`.split($/)
18
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
19
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
20
+ spec.require_paths = %w(lib)
21
+
22
+ spec.add_development_dependency 'bundler', '~> 1.3'
23
+ spec.add_development_dependency 'rake'
24
+ spec.add_development_dependency 'rspec'
25
+ spec.add_development_dependency 'rspec-rails'
26
+ spec.add_dependency 'attr_required', '>= 0.0.5'
27
+ spec.add_dependency 'httparty', '>=0.10.0'
28
+ spec.add_dependency 'rails', '>=3.2.14'
29
+ end
@@ -0,0 +1,24 @@
1
+ require 'spec_helper'
2
+ require 'action_view'
3
+
4
+ class ButtonTest < ActionView::TestCase
5
+
6
+ end
7
+
8
+ describe PayzaPayments::ButtonGenerator do
9
+ let :attributes do
10
+ {ipn_security_code: 'U123456', merchant_email: 'support@freedomvpn.info', sandbox: true}
11
+ end
12
+
13
+ let :instance do
14
+ PayzaPayments::ButtonGenerator.new attributes
15
+ end
16
+
17
+ describe '.generate_simple_button' do
18
+
19
+ it 'should render a valid button' do
20
+ instance.generate_simple_button(ButtonTest.new, :item, 'test', 5, 'EUR', 'https://freedomvpn.info',
21
+ 'https://freedomvpn.info', 'test', 1).should == '<form action="https://secure.payza.com/checkout" method="post"><input name="ap_purchasetype" type="hidden" value="item" /><input name="ap_merchant" type="hidden" value="support@freedomvpn.info" /><input name="ap_itemname" type="hidden" value="test" /><input name="ap_currency" type="hidden" value="EUR" /><input name="ap_amount" type="hidden" value="5" /><input name="ap_description" type="hidden" value="test" /><input name="ap_returnurl" type="hidden" value="https://freedomvpn.info" /><input name="ap_cancelurl" type="hidden" value="https://freedomvpn.info" /><input name="apc_1" type="hidden" value="1" /><input name="ap_image" src="https://www.payza.com/images/payza-buy-now.png" type="image" /><input name="ap_timeunit" type="hidden" value="Month" /><input name="ap_periodlength" type="hidden" value="12" /></form>'
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,6 @@
1
+ require 'rspec'
2
+ require 'payza_payments'
3
+ #require 'action_view/test_helper'
4
+ #RSpec.configure do |config|
5
+ # config.include ActionView::TestCase::Behavior
6
+ #end
@@ -0,0 +1,16 @@
1
+ # See http://help.github.com/ignore-files/ for more about ignoring files.
2
+ #
3
+ # If you find yourself ignoring temporary files generated by your text editor
4
+ # or operating system, you probably want to add a global ignore instead:
5
+ # git config --global core.excludesfile '~/.gitignore_global'
6
+
7
+ # Ignore bundler config.
8
+ /.bundle
9
+
10
+ # Ignore the default SQLite database.
11
+ /db/*.sqlite3
12
+ /db/*.sqlite3-journal
13
+
14
+ # Ignore all logfiles and tempfiles.
15
+ /log/*.log
16
+ /tmp
@@ -0,0 +1,54 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Bundle edge Rails instead: gem 'rails', github: 'rails/rails'
4
+ gem 'rails', '4.0.0'
5
+
6
+ # Use sqlite3 as the database for Active Record
7
+ gem 'sqlite3'
8
+
9
+ # Use SCSS for stylesheets
10
+ gem 'sass-rails', '~> 4.0.0'
11
+
12
+ # Use Uglifier as compressor for JavaScript assets
13
+ gem 'uglifier', '>= 1.3.0'
14
+
15
+ # Use CoffeeScript for .js.coffee assets and views
16
+ gem 'coffee-rails', '~> 4.0.0'
17
+
18
+ # See https://github.com/sstephenson/execjs#readme for more supported runtimes
19
+ # gem 'therubyracer', platforms: :ruby
20
+
21
+ # Use jquery as the JavaScript library
22
+ gem 'jquery-rails'
23
+ gem 'better_errors'
24
+ gem 'binding_of_caller'
25
+ gem 'rspec-rails'
26
+ gem 'simplecov'
27
+ gem 'capybara'
28
+ gem 'shoulda-matchers'
29
+
30
+ # Turbolinks makes following links in your web application faster. Read more: https://github.com/rails/turbolinks
31
+ gem 'turbolinks'
32
+
33
+ gem 'payza_payments', git: 'git@github.com:supernova32/payza_payments.git'
34
+ gem 'haml-rails'
35
+
36
+ # Build JSON APIs with ease. Read more: https://github.com/rails/jbuilder
37
+ gem 'jbuilder', '~> 1.2'
38
+
39
+ group :doc do
40
+ # bundle exec rake doc:rails generates the API under doc/api.
41
+ gem 'sdoc', require: false
42
+ end
43
+
44
+ # Use ActiveModel has_secure_password
45
+ # gem 'bcrypt-ruby', '~> 3.0.0'
46
+
47
+ # Use unicorn as the app server
48
+ # gem 'unicorn'
49
+
50
+ # Use Capistrano for deployment
51
+ # gem 'capistrano', group: :development
52
+
53
+ # Use debugger
54
+ # gem 'debugger', group: [:development, :test]