omnipay 0.0.1

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: c3c13dede2e2ea788ee716eb834b225b1cae1ca9
4
+ data.tar.gz: 949abeb3bde942deb0c11d8c011814b692f538f1
5
+ SHA512:
6
+ metadata.gz: afbd5ccc734ef955631e111ded2dbf447dc63ae3658069d7b72c1c8210dbee2eb707a989f5057dc0ec112f0a7dcfa43660b6f8d0aaa6b76a80155b6883331d09
7
+ data.tar.gz: d419fd51650c301b5c2a379fea3a11192921b1b585f146726af5ed2d933d0c1054afd28ac1c6d41cafb443e835e2075554048a85aa59faeddb8cb23af40934c3
@@ -0,0 +1,32 @@
1
+ require 'singleton'
2
+
3
+ module Omnipay
4
+
5
+ autoload :Gateway, 'omnipay/gateway'
6
+ autoload :Adapter, 'omnipay/adapter'
7
+ autoload :RequestPhase, 'omnipay/request_phase'
8
+ autoload :CallbackPhase, 'omnipay/callback_phase'
9
+ autoload :AutosubmitForm, 'omnipay/autosubmit_form'
10
+ autoload :Signer, 'omnipay/signer'
11
+
12
+ # Error codes
13
+ INVALID_RESPONSE = :invalid_response
14
+ CANCELATION = :cancelation
15
+ PAYMENT_REFUSED = :payment_refused
16
+ WRONG_SIGNATURE = :wrong_signature
17
+
18
+ # Configuration
19
+ class Configuration
20
+ include Singleton
21
+ attr_accessor :secret_token
22
+ end
23
+
24
+ def self.configuration
25
+ Configuration.instance
26
+ end
27
+
28
+ def self.configure
29
+ yield configuration
30
+ end
31
+
32
+ end
@@ -0,0 +1,62 @@
1
+ # Glue between the rack middleware and the adapter implementation
2
+ # Responsible for initializing, configuring the adapter, and formatting
3
+ # the responses for use in the middleware
4
+
5
+ module Omnipay
6
+
7
+ class Adapter
8
+
9
+ attr_reader :uid
10
+
11
+ def initialize(uid, callback_url, config, dynamic_config)
12
+ @uid = uid
13
+ @callback_url = callback_url
14
+ @config = config
15
+ @dynamic_config = dynamic_config
16
+
17
+ @strategy = build_strategy
18
+ end
19
+
20
+ def valid?
21
+ @strategy != nil
22
+ end
23
+
24
+ def request_phase(amount, opts)
25
+ @strategy.request_phase(amount, opts)
26
+ end
27
+
28
+ def callback_hash(params)
29
+ @strategy.callback_hash(params)
30
+ end
31
+
32
+
33
+ private
34
+
35
+ def build_strategy
36
+ return nil unless strategy_class
37
+
38
+ strategy_class.new(@callback_url, strategy_config)
39
+ end
40
+
41
+ def strategy_class
42
+ params[:adapter]
43
+ end
44
+
45
+ def strategy_config
46
+ params[:config] || {}
47
+ end
48
+
49
+ def params
50
+ return @params if @params
51
+
52
+ if @dynamic_config
53
+ @params = @dynamic_config.call(@uid) || {}
54
+ else
55
+ @params = @config || {}
56
+ end
57
+
58
+ @params ||= {}
59
+ end
60
+
61
+ end
62
+ end
@@ -0,0 +1,140 @@
1
+ # Omnipay adapter for mangopay
2
+ # documentation : http://docs.mangopay.com/api-references/
3
+ #
4
+ # Configuration :
5
+ # - client_id:string (mandatory) : client id of your mangopay account
6
+ # - client_passphrase:string (mandatory) : the passphrase for your account
7
+ # - wallet_id:string (mandatory) : the wallet to be credited with the payments
8
+
9
+ require_relative 'mangopay/client'
10
+
11
+
12
+ module Omnipay
13
+ module Adapters
14
+
15
+ class Mangopay
16
+
17
+ attr_reader :client
18
+
19
+ def initialize(callback_url, config = {})
20
+
21
+ raise ArgumentError.new("Missing client_id, client_passphrase, or wallet_id parameter") unless [config[:client_id], config[:client_passphrase], config[:wallet_id]].all?
22
+
23
+ @client = Client.new(config[:client_id], config[:client_passphrase], :sandbox => !!config[:sandbox])
24
+ @callback_url = callback_url
25
+ @wallet_id = config[:wallet_id]
26
+
27
+ end
28
+
29
+
30
+ def request_phase(amount, params = {})
31
+
32
+ transaction_id, redirect_url = create_web_payin(amount, params)
33
+
34
+ # Generate the path and query parameters from the returned redirect_url string
35
+ uri = URI(redirect_url)
36
+
37
+ return [
38
+ 'GET',
39
+ "#{uri.scheme}://#{uri.host}#{uri.path}",
40
+ Rack::Utils.parse_nested_query(uri.query),
41
+ transaction_id
42
+ ]
43
+
44
+ end
45
+
46
+
47
+ def callback_hash(params)
48
+
49
+ transaction_id = params[:transactionId]
50
+
51
+ begin
52
+ response = @client.get "/payins/#{transaction_id}"
53
+ rescue Mangopay::Client::Error => e
54
+ return {
55
+ :success => false,
56
+ :error => Omnipay::INVALID_RESPONSE,
57
+ :error_message => "Could not fetch details of transaction #{transaction_id}"
58
+ }
59
+ end
60
+
61
+ # Check if the response is valid
62
+ if response['code'] != 200
63
+ return {
64
+ :success => false,
65
+ :error => Omnipay::INVALID_RESPONSE
66
+ }
67
+ end
68
+
69
+
70
+ # Successful transaction
71
+ if response['Status'] == 'SUCCEEDED'
72
+ {
73
+ :success => true,
74
+ :amount => response['DebitedFunds']['Amount'],
75
+ :transaction_id => transaction_id
76
+ }
77
+ else
78
+
79
+ # Cancelation
80
+ if ['101001', '101002'].include? response['ResultCode']
81
+ {
82
+ :success => false,
83
+ :error => Omnipay::CANCELATION
84
+ }
85
+ else
86
+ {
87
+ :success => false,
88
+ :error => Omnipay::PAYMENT_REFUSED,
89
+ :error_message => "Refused payment for transaction #{transaction_id}.\nCode : #{response['ResultCode']}\nMessage : #{response['ResultMessage']}"
90
+ }
91
+ end
92
+ end
93
+ end
94
+
95
+
96
+ private
97
+
98
+ def create_web_payin(amount, params)
99
+
100
+ # Create a user
101
+ random_key = "#{Time.now.to_i}-#{(0...3).map { ('a'..'z').to_a[rand(26)] }.join}"
102
+ user_params = {
103
+ :Email => "user-#{random_key}@host.tld",
104
+ :FirstName => "User #{random_key}",
105
+ :LastName => "User #{random_key}",
106
+ :Birthday => Time.now.to_i,
107
+ :Nationality => "FR",
108
+ :CountryOfResidence => "FR"
109
+ }
110
+
111
+ user_id = (@client.post('/users/natural', user_params))["Id"]
112
+
113
+ # Create the web payin
114
+ payin_params = {
115
+ :AuthorId => user_id,
116
+ :DebitedFunds => {
117
+ :Currency => 'EUR',
118
+ :Amount => amount
119
+ },
120
+ :Fees => {
121
+ :Currency => 'EUR',
122
+ :Amount => 0
123
+ },
124
+ :CreditedWalletId => @wallet_id,
125
+ :ReturnURL => @callback_url,
126
+ :Culture => (params[:locale] || 'fr').upcase,
127
+ :CardType => 'CB_VISA_MASTERCARD',
128
+ :SecureMode => 'FORCE'
129
+ }
130
+
131
+ payin = @client.post '/payins/card/web', payin_params
132
+
133
+ # Return the transaction reference, and the full redirection url
134
+ return [payin["Id"], payin["RedirectURL"]]
135
+ end
136
+
137
+ end
138
+
139
+ end
140
+ end
@@ -0,0 +1,70 @@
1
+ # Client for the mangopay API
2
+
3
+ require 'httparty'
4
+
5
+ module Omnipay
6
+ module Adapters
7
+ class Mangopay
8
+
9
+ class Client
10
+
11
+ class Error < ::StandardError ; end
12
+
13
+ include HTTParty
14
+
15
+ format :json
16
+
17
+ headers 'Accept' => 'application/json'
18
+ headers 'Content-Type' => 'application/json'
19
+
20
+ def initialize(key, secret, opts = {})
21
+ @key = key
22
+ @secret = secret
23
+
24
+ if opts[:sandbox]
25
+ @base_uri = 'https://api.sandbox.mangopay.com/v2'
26
+ else
27
+ @base_uri = 'https://api.mangopay.com/v2'
28
+ end
29
+ end
30
+
31
+ def get(path)
32
+ response = self.class.get "/#{@key}#{path}",
33
+ :basic_auth => {:username => @key, :password => @secret},
34
+ :base_uri => @base_uri
35
+
36
+ check_errors(response)
37
+
38
+ response.parsed_response.merge("code" => response.code)
39
+ end
40
+
41
+ def post(path, params = {})
42
+ response = self.class.post "/#{@key}#{path}",
43
+ :body => params.to_json,
44
+ :basic_auth => {:username => @key, :password => @secret},
45
+ :base_uri => @base_uri
46
+
47
+ check_errors(response)
48
+
49
+ response.parsed_response.merge("code" => response.code)
50
+ end
51
+
52
+
53
+ private
54
+
55
+ def check_errors(response)
56
+ # nocommit, log the request :/
57
+ if response.code != 200
58
+ error_message = response.parsed_response.merge(
59
+ "code" => response.code
60
+ )
61
+
62
+ raise Error, error_message.inspect
63
+ end
64
+ end
65
+
66
+ end
67
+
68
+ end
69
+ end
70
+ end
@@ -0,0 +1,130 @@
1
+ # Omnipay adapter for oneclicpay
2
+ # documentation : docs.oneclicpay.com
3
+ #
4
+ # Configuration :
5
+ # - tpe_id:string (mandatory) : serial number of your virutal payment terminal
6
+ # - secret_key:string (mandatory) : security key for your account
7
+ # - sandbox:boolean (default: false) : use the sandbox or the production environment
8
+
9
+ require 'base64'
10
+ require 'digest'
11
+ require 'httparty'
12
+
13
+ module Omnipay
14
+ module Adapters
15
+
16
+ class Oneclicpay
17
+
18
+ HTTP_METHOD = 'POST'
19
+
20
+ REDIRECT_URLS = {
21
+ :sandbox => 'https://secure.homologation.oneclicpay.com',
22
+ :production => 'https://secure.oneclicpay.com'
23
+ }
24
+
25
+ VALIDATION_URLS = {
26
+ :sandbox => 'https://secure.homologation.oneclicpay.com:60000',
27
+ :production => 'https://secure.oneclicpay.com:60000'
28
+ }
29
+
30
+ def initialize(callback_url, config)
31
+ @callback_url = callback_url
32
+
33
+ @tpe_id = config[:tpe_id]
34
+ @secret_key = config[:secret_key]
35
+ @is_sandbox = config[:sandbox]
36
+
37
+ raise ArgumentError.new("Missing tpe_id or secret_key parameter") unless [@tpe_id, @secret_key].all?
38
+ end
39
+
40
+
41
+ def request_phase(amount, params={})
42
+ product_name = params[:title] || ''
43
+ transaction_id = params[:transaction_id] || random_transaction_id
44
+ locale = params[:locale] || 'fr'
45
+
46
+ [
47
+ HTTP_METHOD,
48
+ redirect_url,
49
+ redirect_params_for(amount, product_name, transaction_id, locale),
50
+ transaction_id
51
+ ]
52
+ end
53
+
54
+
55
+ def callback_hash(params)
56
+
57
+ if params[:result] == "NOK" && params[:reason] == "Abandon de la transaction."
58
+ return { :success => false, :error => Omnipay::CANCELATION }
59
+ end
60
+
61
+
62
+ if params[:result] == "OK"
63
+
64
+ # Validate the response via the API
65
+ transaction_id = params[:transactionId]
66
+ amount = get_transaction_amount(transaction_id)
67
+
68
+ if amount
69
+ { :success => true, :amount => amount, :transaction_id => transaction_id }
70
+ else
71
+ { :success => false, :error => Omnipay::INVALID_RESPONSE, :error_message => "Could not fetch the amount of the transaction #{transaction_id}" }
72
+ end
73
+
74
+
75
+ elsif params[:result] == "NOK"
76
+ { :success => false, :error => Omnipay::PAYMENT_REFUSED, :error_message => params[:reason] }
77
+
78
+ else
79
+ { :success => false, :error => Omnipay::INVALID_RESPONSE, :error_message => "No :result key in the params #{params.inspect}" }
80
+ end
81
+ end
82
+
83
+
84
+ private
85
+
86
+ def redirect_params_for(amount, product_name, transaction_id, locale)
87
+ {
88
+ :montant => (amount.to_f/100).to_s,
89
+ :idTPE => @tpe_id,
90
+ :idTransaction => transaction_id,
91
+ :devise => 'EUR',
92
+ :lang => locale,
93
+ :nom_produit => product_name,
94
+ :urlRetourOK => @callback_url,
95
+ :urlRetourNOK => @callback_url
96
+ }.tap{|params|
97
+ params[:sec] = signature(params)
98
+ }
99
+ end
100
+
101
+ def random_transaction_id
102
+ "#{Time.now.to_i}-#{@tpe_id}-#{random_token}"
103
+ end
104
+
105
+ def random_token
106
+ (0...3).map { ('a'..'z').to_a[rand(26)] }.join
107
+ end
108
+
109
+ def signature(params)
110
+ to_sign = (params.values + [@secret_key]).join('|')
111
+ Digest::SHA512.hexdigest(Base64.encode64(to_sign).gsub(/\n/, ''))
112
+ end
113
+
114
+ def get_transaction_amount(transaction_id)
115
+ response = HTTParty.post("#{validation_url}/rest/payment/find?serialNumber=#{@tpe_id}&key=#{@secret_key}&transactionRef=#{transaction_id}")
116
+ (response.parsed_response["transaction"][0]["ok"] != 0) && response.parsed_response["transaction"][0]["amount"]
117
+ end
118
+
119
+ def redirect_url
120
+ @is_sandbox ? REDIRECT_URLS[:sandbox] : REDIRECT_URLS[:production]
121
+ end
122
+
123
+ def validation_url
124
+ @is_sandbox ? VALIDATION_URLS[:sandbox] : VALIDATION_URLS[:production]
125
+ end
126
+
127
+ end
128
+
129
+ end
130
+ end
@@ -0,0 +1,43 @@
1
+ # Builds an html page with an autosubmitted form, to handle POST redirections
2
+ module Omnipay
3
+ class AutosubmitForm
4
+
5
+ HEADER = <<-HEADER
6
+ <!DOCTYPE html>
7
+ <html>
8
+ <head>
9
+ <script type="text/javascript">
10
+ window.onload=function(){
11
+ document.getElementById('autosubmit-form').submit();
12
+ }
13
+ </script>
14
+ </head>
15
+
16
+ <body>
17
+ <h1>Redirecting...</h1>
18
+ HEADER
19
+
20
+ FOOTER = <<-FOOTER
21
+ </body>
22
+ </html>
23
+ FOOTER
24
+
25
+ def initialize(action, fields)
26
+ @action = action
27
+ @fields = fields.map{|name, value| {:name => name, :value => value}}
28
+ end
29
+
30
+ def html
31
+ HEADER + form_html + FOOTER
32
+ end
33
+
34
+ def form_html
35
+ " <form method=\"POST\" id=\"autosubmit-form\" action=\"#{@action}\">\n" +
36
+ @fields.map{|field|
37
+ " <input type=\"hidden\" name=\"#{field[:name]}\" value=\"#{field[:value]}\"/>\n"
38
+ }.join +
39
+ " </form>\n"
40
+ end
41
+
42
+ end
43
+ end
@@ -0,0 +1,68 @@
1
+ # Class responsible for updating the request env in the callback phase
2
+
3
+ module Omnipay
4
+ class CallbackPhase
5
+
6
+ def initialize(request, adapter)
7
+ @request = request
8
+ @adapter = adapter
9
+ end
10
+
11
+
12
+ def update_env!
13
+
14
+ # The request params, keys symbolized
15
+ params = Hash[@request.params.map{|k,v|[k.to_sym,v]}]
16
+
17
+ # Get the callback hash
18
+ callback_hash = @adapter.callback_hash(params)
19
+
20
+ # Check the signature
21
+ if callback_hash[:success] && !valid_signature?(callback_hash)
22
+ callback_hash = {
23
+ :success => false,
24
+ :error => Omnipay::WRONG_SIGNATURE,
25
+ :error_message => "Signatures do not match."
26
+ }
27
+ end
28
+
29
+ # If not successful response, add informations to the error message
30
+ if !callback_hash[:success]
31
+ callback_hash[:error_message] = (callback_hash[:error_message] || callback_hash[:error].to_s) +
32
+ "\nAdapter : #{@adapter.uid}" +
33
+ "\nContext : #{context.inspect}" +
34
+ "\nStored signature : #{stored_signature}" +
35
+ "\nRequest : #{@request.inspect}"
36
+ end
37
+
38
+ # Store the response in the environment
39
+ @request.env['omnipay.response'] = callback_hash.merge(:raw => params, :context => context)
40
+
41
+ # Force GET request
42
+ @request.env['REQUEST_METHOD'] = 'GET'
43
+ end
44
+
45
+
46
+ private
47
+
48
+ def valid_signature?(callback_hash)
49
+ callback_signature = Signer.new(callback_hash[:transaction_id], callback_hash[:amount], context).signature
50
+
51
+ callback_signature == stored_signature
52
+ end
53
+
54
+ def stored_signature
55
+ @stored_signature ||= @request.session['omnipay.signature'] && @request.session['omnipay.signature'].delete(@adapter.uid)
56
+ end
57
+
58
+ def callback_signature
59
+ @callback_signatureSigner.new(callback_hash[:transaction_id], callback_hash[:amount], context).signature
60
+ end
61
+
62
+ def context
63
+ @context ||= @request.session['omnipay.context'] && @request.session['omnipay.context'].delete(@adapter.uid)
64
+ @context ||= {}
65
+ end
66
+
67
+ end
68
+ end
@@ -0,0 +1,85 @@
1
+ require 'rack'
2
+
3
+ module Omnipay
4
+
5
+ # Gateway middleware
6
+ class Gateway
7
+
8
+ BASE_PATH = '/pay'
9
+
10
+ def initialize(app, options={}, &block)
11
+ @app = app
12
+
13
+ @adapter_options = options
14
+ @adapter_config_block = block
15
+
16
+ # Refreshed at each request
17
+ @uid = nil
18
+ @request = nil
19
+ end
20
+
21
+
22
+ def call(env)
23
+
24
+ # Get the current request
25
+ @request = Rack::Request.new(env)
26
+
27
+ # Check if the path is good, and extract the uid
28
+ @uid = extract_uid_from_path(@request.path)
29
+ return @app.call(env) unless @uid
30
+
31
+ # Get the adapter config for this uid (to handle dynamic configuration)
32
+ adapter = Adapter.new(@uid, callback_url, @adapter_options, @adapter_config_block)
33
+ return @app.call(env) unless adapter.valid?
34
+
35
+ # Handle the request phase
36
+ if request_phase?
37
+ return RequestPhase.new(@request, adapter).response
38
+ end
39
+
40
+ # Handle the callback phase
41
+ if callback_phase?
42
+ CallbackPhase.new(@request, adapter).update_env!
43
+ end
44
+
45
+ # Forward to the app
46
+ @app.call(env)
47
+
48
+ end
49
+
50
+
51
+ private
52
+
53
+ # Check if the current request matches the request or callback phase
54
+ def request_phase?
55
+ @request.path == "#{BASE_PATH}/#{@uid}" && @request.request_method == 'GET'
56
+ end
57
+
58
+ def callback_phase?
59
+ @request.path == "#{BASE_PATH}/#{@uid}/callback"
60
+ end
61
+
62
+
63
+ # Extract the uid from the path
64
+ # If uid already defined, check if it matches
65
+ # "/pay/foobar/callback" => "foobar"
66
+ def extract_uid_from_path(path)
67
+ if path.start_with? BASE_PATH
68
+ uid = path.gsub(/^#{BASE_PATH}/, '').split('/')[1]
69
+ end
70
+
71
+ if !@adapter_options.empty?
72
+ uid = nil unless uid == @adapter_options[:uid]
73
+ end
74
+
75
+ uid
76
+ end
77
+
78
+
79
+ # The callback url for a uid in the current host
80
+ def callback_url
81
+ "#{@request.base_url}#{BASE_PATH}/#{@uid}/callback"
82
+ end
83
+
84
+ end
85
+ end
@@ -0,0 +1,76 @@
1
+ # Class responsible for formatting the redirection in the request phase
2
+
3
+ module Omnipay
4
+ class RequestPhase
5
+
6
+ def initialize(request, adapter)
7
+ @request = request
8
+ @adapter = adapter
9
+ end
10
+
11
+ def response
12
+ method, url, params, transaction_id = @adapter.request_phase(amount, adapter_params)
13
+
14
+ context = store_context!
15
+
16
+ signature = Signer.new(transaction_id, amount, context).signature
17
+ store_signature!(signature)
18
+
19
+ if method == 'GET'
20
+ get_redirect_response(url, params)
21
+ elsif method == 'POST'
22
+ post_redirect_response(url, params)
23
+ else
24
+ raise TypeError.new('request_phase returned http method must be \'GET\' or \'POST\'')
25
+ end
26
+ end
27
+
28
+
29
+ private
30
+
31
+ def amount
32
+ @request.params['amount'].tap{ |amount|
33
+ raise ArgumentError.new('No amount specified') unless amount
34
+ }.to_i
35
+ end
36
+
37
+ def adapter_params
38
+ params = @request.params.dup
39
+
40
+ params.delete 'amount'
41
+ params.delete 'context'
42
+
43
+ # Symbolize the keys
44
+ Hash[params.map{|k,v|[k.to_sym,v]}]
45
+ end
46
+
47
+ def get_redirect_response(url, params)
48
+ redirect_url = url + '?' + Rack::Utils.build_query(params)
49
+ Rack::Response.new.tap{|response| response.redirect(redirect_url)}
50
+ end
51
+
52
+ def post_redirect_response(url, params)
53
+ form = AutosubmitForm.new(url, params)
54
+ Rack::Response.new([form.html], 200, {'Content-Type' => 'text/html;charset=utf-8'})
55
+ end
56
+
57
+ # Store the request's context in session
58
+ def store_context!
59
+ context = @request.params.delete('context')
60
+
61
+ if context
62
+ @request.session['omnipay.context'] ||= {}
63
+ @request.session['omnipay.context'][@adapter.uid] = context
64
+ end
65
+
66
+ return context
67
+ end
68
+
69
+ # Store the requests signature in the session
70
+ def store_signature!(signature)
71
+ @request.session['omnipay.signature'] ||= {}
72
+ @request.session['omnipay.signature'][@adapter.uid] = signature
73
+ end
74
+
75
+ end
76
+ end
@@ -0,0 +1,34 @@
1
+ # Class responsible for signing the outgoing payments in the request phase,
2
+ # and validating them in the callback phase
3
+
4
+ require 'openssl'
5
+
6
+ module Omnipay
7
+ class Signer
8
+
9
+ def initialize(transaction_id, amount, context)
10
+ @transaction_id = transaction_id
11
+ @amount = amount
12
+ @context = context || {}
13
+ end
14
+
15
+ def signature
16
+ to_sign = "#{secret_token}:#{@transaction_id}:#{@amount}:#{self.class.hash_to_string @context}"
17
+ CGI.escape(Base64.encode64(OpenSSL::HMAC.digest('sha1', secret_token, to_sign)))
18
+ end
19
+
20
+
21
+ # Unique key : to configure globally
22
+ def secret_token
23
+ Omnipay.configuration.secret_token
24
+ end
25
+
26
+ private
27
+
28
+ def self.hash_to_string(hash)
29
+ # key/values appended by alphabetical key order
30
+ hash.sort_by{|k,_|k}.flatten.join('')
31
+ end
32
+
33
+ end
34
+ end
@@ -0,0 +1,3 @@
1
+ module Omnipay
2
+ VERSION = "0.0.1"
3
+ end
metadata ADDED
@@ -0,0 +1,83 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: omnipay
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - ClicRDV
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2014-01-10 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rack
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - '>='
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - '>='
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: httparty
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - <
32
+ - !ruby/object:Gem::Version
33
+ version: '1.0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - <
39
+ - !ruby/object:Gem::Version
40
+ version: '1.0'
41
+ description: Payment gateway abstraction for rack applications. Think omniauth for
42
+ off-site payment.
43
+ email:
44
+ - contact@clicrdv.com
45
+ executables: []
46
+ extensions: []
47
+ extra_rdoc_files: []
48
+ files:
49
+ - lib/omnipay.rb
50
+ - lib/omnipay/adapter.rb
51
+ - lib/omnipay/adapters/mangopay.rb
52
+ - lib/omnipay/adapters/mangopay/client.rb
53
+ - lib/omnipay/adapters/oneclicpay.rb
54
+ - lib/omnipay/autosubmit_form.rb
55
+ - lib/omnipay/callback_phase.rb
56
+ - lib/omnipay/gateway.rb
57
+ - lib/omnipay/request_phase.rb
58
+ - lib/omnipay/signer.rb
59
+ - lib/omnipay/version.rb
60
+ homepage: https://github.com/clicrdv/omnipay
61
+ licenses: []
62
+ metadata: {}
63
+ post_install_message:
64
+ rdoc_options: []
65
+ require_paths:
66
+ - lib
67
+ required_ruby_version: !ruby/object:Gem::Requirement
68
+ requirements:
69
+ - - '>='
70
+ - !ruby/object:Gem::Version
71
+ version: '0'
72
+ required_rubygems_version: !ruby/object:Gem::Requirement
73
+ requirements:
74
+ - - '>='
75
+ - !ruby/object:Gem::Version
76
+ version: '0'
77
+ requirements: []
78
+ rubyforge_project: '[none]'
79
+ rubygems_version: 2.0.6
80
+ signing_key:
81
+ specification_version: 4
82
+ summary: Payment gateway abstraction for rack applications.
83
+ test_files: []