payex 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.
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source :rubygems
2
+ ruby '1.9.3'
3
+ gemspec
data/Gemfile.lock ADDED
@@ -0,0 +1,76 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ payex (0.0.1)
5
+ nori (~> 1.1)
6
+ savon (~> 1.1)
7
+
8
+ GEM
9
+ remote: http://rubygems.org/
10
+ specs:
11
+ akami (1.2.0)
12
+ gyoku (>= 0.4.0)
13
+ nokogiri (>= 1.4.0)
14
+ builder (3.0.0)
15
+ diff-lcs (1.1.3)
16
+ ffi (1.1.5)
17
+ guard (1.3.2)
18
+ listen (>= 0.4.2)
19
+ thor (>= 0.14.6)
20
+ guard-bundler (1.0.0)
21
+ bundler (~> 1.0)
22
+ guard (~> 1.1)
23
+ guard-rspec (1.2.1)
24
+ guard (>= 1.1)
25
+ gyoku (0.4.6)
26
+ builder (>= 2.1.2)
27
+ httpi (1.1.1)
28
+ rack
29
+ listen (0.4.7)
30
+ rb-fchange (~> 0.0.5)
31
+ rb-fsevent (~> 0.9.1)
32
+ rb-inotify (~> 0.8.8)
33
+ nokogiri (1.5.5)
34
+ nori (1.1.3)
35
+ rack (1.4.1)
36
+ rb-fchange (0.0.5)
37
+ ffi
38
+ rb-fsevent (0.9.1)
39
+ rb-inotify (0.8.8)
40
+ ffi (>= 0.5.0)
41
+ rspec (2.11.0)
42
+ rspec-core (~> 2.11.0)
43
+ rspec-expectations (~> 2.11.0)
44
+ rspec-mocks (~> 2.11.0)
45
+ rspec-core (2.11.1)
46
+ rspec-expectations (2.11.2)
47
+ diff-lcs (~> 1.1.3)
48
+ rspec-mocks (2.11.2)
49
+ savon (1.1.0)
50
+ akami (~> 1.2.0)
51
+ builder (>= 2.1.2)
52
+ gyoku (~> 0.4.5)
53
+ httpi (~> 1.1.0)
54
+ nokogiri (>= 1.4.0)
55
+ nori (~> 1.1.0)
56
+ wasabi (~> 2.5.0)
57
+ savon_spec (1.3.0)
58
+ rspec (>= 2.0.0)
59
+ savon (~> 1.0)
60
+ terminal-notifier-guard (1.5.3)
61
+ thor (0.16.0)
62
+ wasabi (2.5.1)
63
+ httpi (~> 1.0)
64
+ nokogiri (>= 1.4.0)
65
+
66
+ PLATFORMS
67
+ ruby
68
+
69
+ DEPENDENCIES
70
+ guard (~> 1.3)
71
+ guard-bundler (~> 1.0)
72
+ guard-rspec (~> 1.2)
73
+ payex!
74
+ rspec (~> 2.11)
75
+ savon_spec (~> 1.3)
76
+ terminal-notifier-guard (~> 1.5)
data/Guardfile ADDED
@@ -0,0 +1,10 @@
1
+ # -*- ruby -*-
2
+
3
+ guard :bundler do
4
+ watch 'Gemfile'
5
+ watch 'payex.gemspec'
6
+ end
7
+
8
+ guard :rspec, cli: '--color', bundler: false do
9
+ watch(%r'^(lib|spec)/') { 'spec' }
10
+ end
data/README ADDED
@@ -0,0 +1,34 @@
1
+ # -*- ruby -*-
2
+ require 'payex'
3
+
4
+ # This is how a basic PayEx transaction works:
5
+
6
+ PayEx.account_number = 123456789
7
+ PayEx.encryption_key = 'e4939be3910ebu194'
8
+
9
+ PayEx.return_url = 'http://example.com/payex-return'
10
+ PayEx.cancel_url = 'http://example.com/payex-cancel'
11
+
12
+ local_order_id = 'c704acc45a4bec4c8cd50b73fb01a7c7'
13
+
14
+ payment_url = PayEx.authorize_transaction! local_order_id,
15
+ product_number: '123456',
16
+ product_description: 'Brief product description',
17
+ price: 14900, # Price in cents
18
+ customer_ip: '12.34.56.78'
19
+
20
+ # After sending the customer to `payment_url`, they will enter their
21
+ # payment details before being redirected back to `PayEx.return_url`
22
+ # with an `orderRef` parameter appended to the query string:
23
+ #
24
+ # <http://example.com/payex-return?orderRef=9b4031c19960da92d>
25
+ #
26
+ # By giving the `orderRef` value to `PayEx.complete_transaction!` you
27
+ # retreive your local order ID and your app can proceed from there.
28
+
29
+ begin
30
+ local_order_id = PayEx.complete_transaction! '9b4031c19960da92d'
31
+ # [transaction successful]
32
+ rescue PayEx::Error => error
33
+ # [transaction unsucessful]
34
+ end
data/Rakefile ADDED
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env rake
2
+
3
+ require 'bundler/gem_tasks'
data/lib/payex/api.rb ADDED
@@ -0,0 +1,101 @@
1
+ require 'nori'
2
+ require 'savon'
3
+
4
+ module PayEx::API
5
+ extend self
6
+
7
+ class ParamError < StandardError; end
8
+
9
+ def invoke! wsdl, name, params, specs
10
+ body = get_request_body(params, specs)
11
+ response = invoke_raw! wsdl, name, body
12
+
13
+ # Unwrap e.g. <Initialize8Response>
14
+ response = response[response.keys.first]
15
+ # Unwrap e.g. <Initialize8Result>
16
+ response = response[response.keys.first]
17
+ # Parse embedded XML document
18
+ response = Nori.parse(response)
19
+ # Unwrap <payex>
20
+ response = response[response.keys.first]
21
+
22
+ if ok = response[:status][:code] == 'OK' rescue false
23
+ response
24
+ elsif defined? response[:status][:description]
25
+ raise PayEx::Error, response[:status][:description]
26
+ else
27
+ raise PayEx::Error, %{invalid response: #{response.inspect}}
28
+ end
29
+ end
30
+
31
+ def invoke_raw! wsdl, name, body
32
+ Savon.client(wsdl).request(name, body: body) {
33
+ http.headers.delete('SOAPAction')
34
+ }.body
35
+ end
36
+
37
+ def signed_hash(string)
38
+ Digest::MD5.hexdigest(string + PayEx.encryption_key!)
39
+ end
40
+
41
+ def get_request_body(params, specs)
42
+ parse_params(params, specs).tap do |params|
43
+ params['hash'] = sign_params(params, specs)
44
+ end
45
+ end
46
+
47
+ def sign_params(params, specs)
48
+ signed_hash(hashed_params(params, specs).join)
49
+ end
50
+
51
+ def hashed_params(params, specs)
52
+ specs.select { |key, options| options[:signed] }.
53
+ keys.map { |key| params[key] }
54
+ end
55
+
56
+ def parse_params(params, specs)
57
+ stringify_keys(params).tap do |result|
58
+ _parse_params! result, specs
59
+ result.select! { |k, v| v != nil }
60
+ end
61
+ end
62
+
63
+ def stringify_keys(hash)
64
+ Hash[*hash.map { |k, v| [k.to_s, v] }.flatten]
65
+ end
66
+
67
+ def _parse_params!(params, specs)
68
+ for name, options in specs
69
+ begin
70
+ params[name] = parse_param(params[name], options)
71
+ rescue PayEx::API::ParamError => error
72
+ param_error! %{#{name.inspect}: #{error.message}}
73
+ end
74
+ end
75
+ end
76
+
77
+ def parse_param(param, options)
78
+ unless options.is_a? Hash
79
+ raise ArgumentError, %{expected Hash, got #{options.inspect}}
80
+ end
81
+
82
+ if param != nil
83
+ result = param
84
+ elsif options.include? :default
85
+ result = options[:default]
86
+ result = result.call if result.is_a? Proc
87
+ else
88
+ param_error! 'parameter required'
89
+ end
90
+
91
+ if options.include?(:format) and not options[:format] === result
92
+ param_error! %{must match #{options[:format].inspect}}
93
+ else
94
+ result
95
+ end
96
+ end
97
+
98
+ def param_error! message
99
+ raise ParamError, message
100
+ end
101
+ end
@@ -0,0 +1,94 @@
1
+ module PayEx::PxOrder
2
+ extend self
3
+
4
+ def wsdl
5
+ '%s/pxorder/pxorder.asmx?WSDL' % PayEx.base_url
6
+ end
7
+
8
+ def Initialize7(params)
9
+ PayEx::API.invoke! wsdl, 'Initialize7', params, {
10
+ 'accountNumber' => {
11
+ signed: true,
12
+ default: proc { PayEx.account_number! }
13
+ },
14
+ 'purchaseOperation' => {
15
+ signed: true
16
+ },
17
+ 'price' => {
18
+ signed: true,
19
+ format: Integer
20
+ },
21
+ 'priceArgList' => {
22
+ signed: true,
23
+ default: ''
24
+ },
25
+ 'currency' => {
26
+ signed: true,
27
+ default: proc { PayEx.default_currency }
28
+ },
29
+ 'vat' => {
30
+ signed: true,
31
+ format: Integer,
32
+ default: 0
33
+ },
34
+ 'orderID' => {
35
+ signed: true,
36
+ format: /^[a-z0-9]{,50}$/i
37
+ },
38
+ 'productNumber' => {
39
+ signed: true,
40
+ format: /^[A-Z0-9]{,50}$/
41
+ },
42
+ 'description' => {
43
+ signed: true,
44
+ format: /^.{,160}$/
45
+ },
46
+ 'clientIPAddress' => {
47
+ signed: true
48
+ },
49
+ 'clientIdentifier' => {
50
+ signed: true,
51
+ default: ''
52
+ },
53
+ 'additionalValues' => {
54
+ signed: true,
55
+ default: ''
56
+ },
57
+ 'externalID' => {
58
+ signed: true,
59
+ default: ''
60
+ },
61
+ 'returnUrl' => {
62
+ signed: true
63
+ },
64
+ 'view' => {
65
+ signed: true,
66
+ default: 'CREDITCARD'
67
+ },
68
+ 'agreementRef' => {
69
+ signed: true,
70
+ default: ''
71
+ },
72
+ 'cancelUrl' => {
73
+ signed: true,
74
+ default: ''
75
+ },
76
+ 'clientLanguage' => {
77
+ signed: true,
78
+ default: ''
79
+ }
80
+ }
81
+ end
82
+
83
+ def Complete(params)
84
+ PayEx::API.invoke! wsdl, 'Complete', params, {
85
+ 'accountNumber' => {
86
+ signed: true,
87
+ default: proc { PayEx.account_number! }
88
+ },
89
+ 'orderRef' => {
90
+ signed: true
91
+ }
92
+ }
93
+ end
94
+ end
data/lib/payex.rb ADDED
@@ -0,0 +1,78 @@
1
+ module PayEx
2
+ extend self
3
+
4
+ TEST_URL = 'https://test-external.payex.com'
5
+ LIVE_URL = 'https://external.payex.com'
6
+
7
+ class Error < StandardError; end
8
+
9
+ attr_accessor :default_currency
10
+ attr_accessor :base_url
11
+
12
+ attr_accessor :account_number
13
+ attr_accessor :encryption_key
14
+
15
+ attr_accessor :return_url
16
+ attr_accessor :cancel_url
17
+ end
18
+
19
+ PayEx.default_currency = 'SEK'
20
+ PayEx.base_url = PayEx::TEST_URL
21
+
22
+ require 'payex/api'
23
+ require 'payex/pxorder'
24
+
25
+ def PayEx.account_number!
26
+ PayEx.account_number or fail 'Please set PayEx.account_number'
27
+ end
28
+
29
+ def PayEx.encryption_key!
30
+ PayEx.encryption_key or fail 'Please set PayEx.encryption_key'
31
+ end
32
+
33
+ def PayEx.authorize_transaction! order_id, params
34
+ response = PayEx::PxOrder.Initialize7 \
35
+ orderID: order_id,
36
+ purchaseOperation: 'AUTHORIZATION',
37
+ productNumber: params[:product_number],
38
+ description: params[:product_description],
39
+ price: params[:price],
40
+ clientIPAddress: params[:customer_ip],
41
+ returnUrl: PayEx.return_url,
42
+ cancelUrl: PayEx.cancel_url
43
+
44
+ response[:redirect_url]
45
+ end
46
+
47
+ def PayEx.complete_transaction! id
48
+ response = PayEx::PxOrder.Complete(orderRef: id)
49
+
50
+ status = response[:transaction_status]
51
+ status = PayEx.parse_transaction_status(status)
52
+
53
+ case status
54
+ when :sale, :authorize
55
+ response[:order_id]
56
+ when :initialize
57
+ raise PayEx::Error, 'Transaction not completed'
58
+ when :failure
59
+ message = response[:error_details][:third_party_error] rescue nil
60
+ raise PayEx::Error, message
61
+ else
62
+ raise PayEx::Error, 'Unexpected transaction status: ' +
63
+ status.to_s.upcase
64
+ end
65
+ end
66
+
67
+ def PayEx.parse_transaction_status(status)
68
+ case status.to_s
69
+ when '0' then :sale
70
+ when '1' then :initialize
71
+ when '2' then :credit
72
+ when '3' then :authorize
73
+ when '4' then :cancel
74
+ when '5' then :failure
75
+ when '6' then :capture
76
+ else status.to_s
77
+ end
78
+ end
data/payex.gemspec ADDED
@@ -0,0 +1,19 @@
1
+ # -*- ruby; coding: utf-8 -*-
2
+
3
+ Gem::Specification.new do |gem|
4
+ gem.name = 'payex'
5
+ gem.version = '0.0.1'
6
+ gem.summary = 'PayEx SOAP API glue'
7
+ gem.author = 'Daniel Brockman'
8
+ gem.files = `git ls-files 2>/dev/null`.split($\)
9
+
10
+ gem.add_dependency 'nori', '~> 1.1'
11
+ gem.add_dependency 'savon', '~> 1.1'
12
+
13
+ gem.add_development_dependency 'guard', '~> 1.3'
14
+ gem.add_development_dependency 'guard-bundler', '~> 1.0'
15
+ gem.add_development_dependency 'guard-rspec', '~> 1.2'
16
+ gem.add_development_dependency 'rspec', '~> 2.11'
17
+ gem.add_development_dependency 'savon_spec', '~> 1.3'
18
+ gem.add_development_dependency 'terminal-notifier-guard', '~> 1.5'
19
+ end
@@ -0,0 +1,60 @@
1
+ # -*- coding: utf-8 -*-
2
+ require 'payex'
3
+ require 'spec_helper'
4
+
5
+ describe PayEx::API do
6
+ before {
7
+ PayEx.encryption_key = 'foo'
8
+ }
9
+
10
+ it 'should know how to stringify keys' do
11
+ PayEx::API.stringify_keys(a: 1, b: 2).
12
+ should == { 'a' => 1, 'b' => 2 }
13
+ end
14
+
15
+ it 'should know how to sign params' do
16
+ param_hash, specs, param_array = {}, {}, []
17
+
18
+ for name in 'a'..'z'
19
+ if rand < 0.5
20
+ param_hash[name] = rand
21
+ param_array << param_hash[name]
22
+ specs[name] = { signed: true }
23
+ else
24
+ param_hash[name] = rand
25
+ end
26
+ end
27
+
28
+ actual = PayEx::API.sign_params(param_hash, specs)
29
+
30
+ to_sign = param_array.join + PayEx.encryption_key
31
+ expected = Digest::MD5.hexdigest(to_sign)
32
+
33
+ actual.should == expected
34
+ end
35
+
36
+ it 'should know how to add defaults' do
37
+ PayEx::API.parse_param(nil, { default: 2 }).should == 2
38
+ end
39
+
40
+ it 'should know how to call default procs' do
41
+ PayEx::API.parse_param(nil, { default: proc { 2 } }).should == 2
42
+ end
43
+
44
+ it 'should reject wrong type of value' do
45
+ proc {
46
+ PayEx::API.parse_param('foobar', { format: Integer })
47
+ }.should raise_error PayEx::API::ParamError
48
+ end
49
+
50
+ it 'should reject strings based on regular expressions' do
51
+ proc {
52
+ PayEx::API.parse_param('foobar', { format: /^.{,3}$/ })
53
+ }.should raise_error PayEx::API::ParamError
54
+ end
55
+
56
+ it 'should stringify keys when parsing params' do
57
+ PayEx::API.parse_params({ a: 1 }, { 'b' => { default: 2 } }).
58
+ should == { 'a' => 1, 'b' => 2 }
59
+ end
60
+ end
@@ -0,0 +1,30 @@
1
+ <?xml version="1.0" encoding="utf-8"?>
2
+ <env:Envelope xmlns:env="http://schemas.xmlsoap.org/soap/envelope/"
3
+ xmlns:xsd="http://www.w3.org/2001/XMLSchema"
4
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
5
+ <env:Body>
6
+ <Initialize7Response xmlns="http://external.payex.com/PxOrder/">
7
+ <Initialize7Result>
8
+ <![CDATA[
9
+ <?xml version="1.0" encoding="utf-8"?>
10
+ <payex>
11
+ <header name="Payex Header v1.0">
12
+ <id>4e0fbe36b146452b8ce7b87e6186a3e3</id>
13
+ <date>2010-11-10 06:13:48</date>
14
+ </header>
15
+ <status>
16
+ <code>OK</code>
17
+ <description>OK</description>
18
+ <errorCode>OK</errorCode>
19
+ <paramName/>
20
+ <thirdPartyError/>
21
+ </status>
22
+ <orderRef>b93d29bf7df3424cac23407a987c0be9</orderRef>
23
+ <sessionRef>7807accc0e7e4d069e1d92ec5680d0cc</sessionRef>
24
+ <redirectUrl>https://test-confined.payex.com/PxOrderCC.aspx?orderRef=b93d29bf7df3424cac23407a987c0be9</redirectUrl>
25
+ </payex>
26
+ ]]>
27
+ </Initialize7Result>
28
+ </Initialize7Response>
29
+ </env:Body>
30
+ </env:Envelope>
@@ -0,0 +1,45 @@
1
+ # -*- coding: utf-8 -*-
2
+ require 'payex'
3
+ require 'spec_helper'
4
+
5
+ describe PayEx do
6
+ before {
7
+ PayEx.account_number = 'foo-account'
8
+ PayEx.encryption_key = 'foo-secret'
9
+ PayEx.return_url = 'http://example.com/payex-callback'
10
+ }
11
+
12
+ it 'should send request and parse response' do
13
+ expected = {
14
+ 'accountNumber' => 'foo-account',
15
+ 'purchaseOperation' => 'AUTHORIZATION',
16
+ 'price' => 12300,
17
+ 'priceArgList' => '',
18
+ 'currency' => 'SEK',
19
+ 'vat' => 0,
20
+ 'orderID' => 'order123',
21
+ 'productNumber' => 'PRODUCT123',
22
+ 'description' => 'Product description',
23
+ 'clientIPAddress' => '12.34.56.78',
24
+ 'clientIdentifier' => '',
25
+ 'additionalValues' => '',
26
+ 'externalID' => '',
27
+ 'returnUrl' => 'http://example.com/payex-callback',
28
+ 'view' => 'CREDITCARD',
29
+ 'agreementRef' => '',
30
+ 'cancelUrl' => '',
31
+ 'clientLanguage' => ''
32
+ }
33
+
34
+ expected['hash'] = PayEx::API.signed_hash(expected.values.join)
35
+ savon.expects('Initialize7').with(expected).returns(:initialize_ok)
36
+
37
+ href = PayEx.authorize_transaction! 'order123',
38
+ product_number: 'PRODUCT123',
39
+ product_description: 'Product description',
40
+ price: 12300,
41
+ customer_ip: '12.34.56.78'
42
+
43
+ href.should include 'http'
44
+ end
45
+ end
@@ -0,0 +1,8 @@
1
+ require 'savon_spec'
2
+
3
+ Savon::Spec::Fixture.path =
4
+ File.expand_path('../fixtures', __FILE__)
5
+
6
+ RSpec.configure do |config|
7
+ config.include Savon::Spec::Macros
8
+ end
metadata ADDED
@@ -0,0 +1,185 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: payex
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Daniel Brockman
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-09-04 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: nori
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ~>
20
+ - !ruby/object:Gem::Version
21
+ version: '1.1'
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ~>
28
+ - !ruby/object:Gem::Version
29
+ version: '1.1'
30
+ - !ruby/object:Gem::Dependency
31
+ name: savon
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ~>
36
+ - !ruby/object:Gem::Version
37
+ version: '1.1'
38
+ type: :runtime
39
+ prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ~>
44
+ - !ruby/object:Gem::Version
45
+ version: '1.1'
46
+ - !ruby/object:Gem::Dependency
47
+ name: guard
48
+ requirement: !ruby/object:Gem::Requirement
49
+ none: false
50
+ requirements:
51
+ - - ~>
52
+ - !ruby/object:Gem::Version
53
+ version: '1.3'
54
+ type: :development
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ~>
60
+ - !ruby/object:Gem::Version
61
+ version: '1.3'
62
+ - !ruby/object:Gem::Dependency
63
+ name: guard-bundler
64
+ requirement: !ruby/object:Gem::Requirement
65
+ none: false
66
+ requirements:
67
+ - - ~>
68
+ - !ruby/object:Gem::Version
69
+ version: '1.0'
70
+ type: :development
71
+ prerelease: false
72
+ version_requirements: !ruby/object:Gem::Requirement
73
+ none: false
74
+ requirements:
75
+ - - ~>
76
+ - !ruby/object:Gem::Version
77
+ version: '1.0'
78
+ - !ruby/object:Gem::Dependency
79
+ name: guard-rspec
80
+ requirement: !ruby/object:Gem::Requirement
81
+ none: false
82
+ requirements:
83
+ - - ~>
84
+ - !ruby/object:Gem::Version
85
+ version: '1.2'
86
+ type: :development
87
+ prerelease: false
88
+ version_requirements: !ruby/object:Gem::Requirement
89
+ none: false
90
+ requirements:
91
+ - - ~>
92
+ - !ruby/object:Gem::Version
93
+ version: '1.2'
94
+ - !ruby/object:Gem::Dependency
95
+ name: rspec
96
+ requirement: !ruby/object:Gem::Requirement
97
+ none: false
98
+ requirements:
99
+ - - ~>
100
+ - !ruby/object:Gem::Version
101
+ version: '2.11'
102
+ type: :development
103
+ prerelease: false
104
+ version_requirements: !ruby/object:Gem::Requirement
105
+ none: false
106
+ requirements:
107
+ - - ~>
108
+ - !ruby/object:Gem::Version
109
+ version: '2.11'
110
+ - !ruby/object:Gem::Dependency
111
+ name: savon_spec
112
+ requirement: !ruby/object:Gem::Requirement
113
+ none: false
114
+ requirements:
115
+ - - ~>
116
+ - !ruby/object:Gem::Version
117
+ version: '1.3'
118
+ type: :development
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ none: false
122
+ requirements:
123
+ - - ~>
124
+ - !ruby/object:Gem::Version
125
+ version: '1.3'
126
+ - !ruby/object:Gem::Dependency
127
+ name: terminal-notifier-guard
128
+ requirement: !ruby/object:Gem::Requirement
129
+ none: false
130
+ requirements:
131
+ - - ~>
132
+ - !ruby/object:Gem::Version
133
+ version: '1.5'
134
+ type: :development
135
+ prerelease: false
136
+ version_requirements: !ruby/object:Gem::Requirement
137
+ none: false
138
+ requirements:
139
+ - - ~>
140
+ - !ruby/object:Gem::Version
141
+ version: '1.5'
142
+ description:
143
+ email:
144
+ executables: []
145
+ extensions: []
146
+ extra_rdoc_files: []
147
+ files:
148
+ - Gemfile
149
+ - Gemfile.lock
150
+ - Guardfile
151
+ - README
152
+ - Rakefile
153
+ - lib/payex.rb
154
+ - lib/payex/api.rb
155
+ - lib/payex/pxorder.rb
156
+ - payex.gemspec
157
+ - spec/api_unit_spec.rb
158
+ - spec/fixtures/Initialize7/initialize_ok.xml
159
+ - spec/integration_spec.rb
160
+ - spec/spec_helper.rb
161
+ homepage:
162
+ licenses: []
163
+ post_install_message:
164
+ rdoc_options: []
165
+ require_paths:
166
+ - lib
167
+ required_ruby_version: !ruby/object:Gem::Requirement
168
+ none: false
169
+ requirements:
170
+ - - ! '>='
171
+ - !ruby/object:Gem::Version
172
+ version: '0'
173
+ required_rubygems_version: !ruby/object:Gem::Requirement
174
+ none: false
175
+ requirements:
176
+ - - ! '>='
177
+ - !ruby/object:Gem::Version
178
+ version: '0'
179
+ requirements: []
180
+ rubyforge_project:
181
+ rubygems_version: 1.8.24
182
+ signing_key:
183
+ specification_version: 3
184
+ summary: PayEx SOAP API glue
185
+ test_files: []