paysimple 1.0.0
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/History.txt +5 -0
- data/MIT-LICENSE +20 -0
- data/Manifest.txt +10 -0
- data/README.txt +152 -0
- data/Rakefile +37 -0
- data/init.rb +1 -0
- data/lib/paysimple.rb +256 -0
- data/lib/usaepay.wsdl +1173 -0
- data/test/paysimple_test.rb +8 -0
- data/uninstall.rb +1 -0
- metadata +76 -0
data/History.txt
ADDED
data/MIT-LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2007 [Jonathan Younger]
|
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/Manifest.txt
ADDED
data/README.txt
ADDED
@@ -0,0 +1,152 @@
|
|
1
|
+
[PaySimple](http://www.paysimple.com) is a payment gateway providing credit card
|
2
|
+
processing, check processing and recurring / subscription billing services.
|
3
|
+
|
4
|
+
== DESCRIPTION:
|
5
|
+
|
6
|
+
This library provides a simple interface to find, create, edit, delete, and query subscriptions
|
7
|
+
using the PaySimple SOAP API. [PaySimple API](https://www.usaepay.com/developer/docs/beta5)
|
8
|
+
|
9
|
+
|
10
|
+
== Installation:
|
11
|
+
|
12
|
+
The simple way:
|
13
|
+
$ sudo gem install paysimple
|
14
|
+
|
15
|
+
Directly from repository:
|
16
|
+
$ svn co svn://svn.roundhaus.com/daikini/plugins/paysimple
|
17
|
+
|
18
|
+
== Requirements:
|
19
|
+
|
20
|
+
* soap4r 1.5.6 or higher
|
21
|
+
|
22
|
+
== Configuration:
|
23
|
+
|
24
|
+
When you signup for a PaySimple account you can setup a source key and optionally a pin and client ip address.
|
25
|
+
These are your credentials when using the PaySimple API.
|
26
|
+
|
27
|
+
PaySimple.key = "123456"
|
28
|
+
PaySimple.pin = "topsecret"
|
29
|
+
PaySimple.client_ip = "192.168.0.1"
|
30
|
+
|
31
|
+
|
32
|
+
== Usage:
|
33
|
+
|
34
|
+
require 'paysimple'
|
35
|
+
|
36
|
+
# Bill Jennifer $12.00 monthly
|
37
|
+
begin
|
38
|
+
customer_number = PaySimple::Subscription.create(
|
39
|
+
:CustomerID => 12345,
|
40
|
+
:BillingAddress => {
|
41
|
+
:FirstName => "Jennifer",
|
42
|
+
:LastName => "Smith"
|
43
|
+
},
|
44
|
+
:CreditCardData => {
|
45
|
+
:CardNumber => '4444555566667779',
|
46
|
+
:CardExpiration => '0908'
|
47
|
+
},
|
48
|
+
:Schedule => :monthly,
|
49
|
+
:Next => "2008-09-05",
|
50
|
+
:Amount => 12.00
|
51
|
+
)
|
52
|
+
|
53
|
+
puts "Subscription created with Customer Number: #{customer_number}"
|
54
|
+
rescue Exception => e
|
55
|
+
puts "An error occurred: #{e.message}"
|
56
|
+
end
|
57
|
+
|
58
|
+
|
59
|
+
# Update subscription to use new credit card
|
60
|
+
begin
|
61
|
+
customer_number = 12345
|
62
|
+
response = PaySimple::Subscription.update(
|
63
|
+
customer_number,
|
64
|
+
:CreditCardData => {
|
65
|
+
:CardNumber => '4444555566667779',
|
66
|
+
:CardExpiration => '0908'
|
67
|
+
}
|
68
|
+
)
|
69
|
+
|
70
|
+
puts "Subscription updated"
|
71
|
+
rescue Exception => e
|
72
|
+
puts "An error occurred: #{e.message}"
|
73
|
+
end
|
74
|
+
|
75
|
+
|
76
|
+
# Delete subscription
|
77
|
+
begin
|
78
|
+
customer_number = 12345
|
79
|
+
response = PaySimple::Subscription.delete(customer_number)
|
80
|
+
|
81
|
+
puts "Subscription removed from active use."
|
82
|
+
rescue Exception => e
|
83
|
+
puts "An error occurred: #{e.message}"
|
84
|
+
end
|
85
|
+
|
86
|
+
|
87
|
+
# Find an existing subscription
|
88
|
+
begin
|
89
|
+
customer_number = 12345
|
90
|
+
customer = PaySimple::Subscription.find(customer_number)
|
91
|
+
|
92
|
+
puts "Found subscription for #{ [customer["BillingAddress"]["FirstName"], customer["BillingAddress"]["LastName"]].join(" ")}"
|
93
|
+
rescue Exception => e
|
94
|
+
puts "An error occurred: #{e.message}"
|
95
|
+
end
|
96
|
+
|
97
|
+
|
98
|
+
# Process one-time sale against existing subscription
|
99
|
+
begin
|
100
|
+
customer_number = 12345
|
101
|
+
response = PaySimple::Subscription.charge(customer_number, :Amount => 34.56)
|
102
|
+
|
103
|
+
if response['Response'] == "Approved"
|
104
|
+
puts "One-time charge successful."
|
105
|
+
else
|
106
|
+
puts "An error occurred: #{response['Error']}"
|
107
|
+
end
|
108
|
+
rescue Exception => e
|
109
|
+
puts "An error occurred: #{e.message}"
|
110
|
+
end
|
111
|
+
|
112
|
+
|
113
|
+
# Search for transactions
|
114
|
+
begin
|
115
|
+
response = PaySimple::Subscription.query(
|
116
|
+
[
|
117
|
+
{ :Field => 'amount', :Type => 'gt', :Value => '5.0' }
|
118
|
+
]
|
119
|
+
)
|
120
|
+
|
121
|
+
response.transactions.each do |transaction|
|
122
|
+
puts "CustomerID = #{transaction['CustomerID']}, Amount = #{transaction['Details']['Amount']}"
|
123
|
+
end
|
124
|
+
rescue Exception => e
|
125
|
+
puts "An error occurred: #{e.message}"
|
126
|
+
end
|
127
|
+
|
128
|
+
|
129
|
+
== LICENSE:
|
130
|
+
|
131
|
+
paysimple is licensed under the MIT License.
|
132
|
+
|
133
|
+
Copyright (c) 2007 [Jonathan Younger], released under the MIT license
|
134
|
+
|
135
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
136
|
+
of this software and associated documentation files (the "Software"), to deal
|
137
|
+
in the Software without restriction, including without limitation the rights
|
138
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
139
|
+
copies of the Software, and to permit persons to whom the Software is
|
140
|
+
furnished to do so, subject to the following conditions:
|
141
|
+
|
142
|
+
The above copyright notice and this permission notice shall be included in
|
143
|
+
all copies or substantial portions of the Software.
|
144
|
+
|
145
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
146
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
147
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
148
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
149
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
150
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
151
|
+
THE SOFTWARE.
|
152
|
+
|
data/Rakefile
ADDED
@@ -0,0 +1,37 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'hoe'
|
3
|
+
require 'rake'
|
4
|
+
require 'rake/testtask'
|
5
|
+
require 'rake/rdoctask'
|
6
|
+
require './lib/paysimple.rb'
|
7
|
+
|
8
|
+
Hoe.new('paysimple', PaySimple::VERSION) do |p|
|
9
|
+
p.rubyforge_name = 'paysimple'
|
10
|
+
p.author = ["Jonathan Younger"]
|
11
|
+
p.email = ["jonathan@daikini.com"]
|
12
|
+
p.summary = "Ruby library for the PaySimple payment gateway."
|
13
|
+
p.description = p.paragraphs_of('README.txt', 2..5).join("\n\n")
|
14
|
+
p.url = "http://paysimple.rubyforge.org/"
|
15
|
+
p.changes = p.paragraphs_of('History.txt', 0..1).join("\n\n")
|
16
|
+
p.remote_rdoc_dir = "" # Release to root
|
17
|
+
p.extra_deps << ["soap4r", ">= 1.5.6"]
|
18
|
+
end
|
19
|
+
|
20
|
+
desc 'Default: run unit tests.'
|
21
|
+
task :default => :test
|
22
|
+
|
23
|
+
desc 'Test the paysimple plugin.'
|
24
|
+
Rake::TestTask.new(:test) do |t|
|
25
|
+
t.libs << 'lib'
|
26
|
+
t.pattern = 'test/**/*_test.rb'
|
27
|
+
t.verbose = true
|
28
|
+
end
|
29
|
+
|
30
|
+
desc 'Generate documentation for the paysimple plugin.'
|
31
|
+
Rake::RDocTask.new(:rdoc) do |rdoc|
|
32
|
+
rdoc.rdoc_dir = 'rdoc'
|
33
|
+
rdoc.title = 'PaySimple'
|
34
|
+
rdoc.options << '--line-numbers' << '--inline-source'
|
35
|
+
rdoc.rdoc_files.include('README')
|
36
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
37
|
+
end
|
data/init.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require 'paysimple'
|
data/lib/paysimple.rb
ADDED
@@ -0,0 +1,256 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
gem 'soap4r', '>= 1.5.6' # 1.5.6 or higher
|
3
|
+
require 'soap/wsdlDriver'
|
4
|
+
require 'digest/sha1'
|
5
|
+
|
6
|
+
# [PaySimple](http://www.paysimple.com) is a payment gateway providing credit card
|
7
|
+
# processing, check processing and recurring / subscription billing services.
|
8
|
+
#
|
9
|
+
# This library provides a simple interface to find, create, edit, delete, and query subscriptions
|
10
|
+
# using the PaySimple SOAP API. [PaySimple API](https://www.usaepay.com/developer/docs/beta5)
|
11
|
+
#
|
12
|
+
# == Installation
|
13
|
+
#
|
14
|
+
# The simple way:
|
15
|
+
# $ sudo gem install paysimple
|
16
|
+
#
|
17
|
+
# Directly from repository:
|
18
|
+
# $ ./script/plugin install svn://svn.roundhaus.com/daikini/plugins/paysimple
|
19
|
+
#
|
20
|
+
# Directly from repository using piston:
|
21
|
+
# $ piston import svn://svn.roundhaus.com/daikini/plugins/paysimple vendor/plugins/paysimple
|
22
|
+
#
|
23
|
+
# == Configuration
|
24
|
+
#
|
25
|
+
# When you signup for a PaySimple account you can setup a source key and optionally a pin and client ip address.
|
26
|
+
# These are your credentials when using the PaySimple API.
|
27
|
+
#
|
28
|
+
# PaySimple.key = "123456"
|
29
|
+
# PaySimple.pin = "topsecret"
|
30
|
+
# PaySimple.client_ip = "192.168.0.1"
|
31
|
+
#
|
32
|
+
class PaySimple
|
33
|
+
VERSION = "1.0.0"
|
34
|
+
WSDL_URL = File.dirname(__FILE__) + '/usaepay.wsdl'
|
35
|
+
|
36
|
+
class << self
|
37
|
+
attr_accessor :key, :pin, :client_ip
|
38
|
+
end
|
39
|
+
self.key = "TestMerchant"
|
40
|
+
|
41
|
+
class Subscription
|
42
|
+
class << self
|
43
|
+
# # Bill Jennifer $12.00 monthly
|
44
|
+
# begin
|
45
|
+
# customer_number = PaySimple::Subscription.create(
|
46
|
+
# :CustomerID => 12345,
|
47
|
+
# :BillingAddress => {
|
48
|
+
# :FirstName => "Jennifer",
|
49
|
+
# :LastName => "Smith"
|
50
|
+
# },
|
51
|
+
# :CreditCardData => {
|
52
|
+
# :CardNumber => '4444555566667779',
|
53
|
+
# :CardExpiration => '0908'
|
54
|
+
# },
|
55
|
+
# :Schedule => :monthly,
|
56
|
+
# :Next => "2008-09-05",
|
57
|
+
# :Amount => 12.00
|
58
|
+
# )
|
59
|
+
#
|
60
|
+
# puts "Subscription created with Customer Number: #{customer_number}"
|
61
|
+
# rescue Exception => e
|
62
|
+
# puts "An error occurred: #{e.message}"
|
63
|
+
# end
|
64
|
+
def create(options)
|
65
|
+
PaySimple.send_request(:addCustomer, { :NumLeft => 0, :Enabled => true }.merge(options))
|
66
|
+
end
|
67
|
+
|
68
|
+
# # Update subscription to use new credit card
|
69
|
+
# begin
|
70
|
+
# customer_number = 12345
|
71
|
+
# response = PaySimple::Subscription.update(
|
72
|
+
# customer_number,
|
73
|
+
# :CreditCardData => {
|
74
|
+
# :CardNumber => '4444555566667779',
|
75
|
+
# :CardExpiration => '0908'
|
76
|
+
# }
|
77
|
+
# )
|
78
|
+
#
|
79
|
+
# puts "Subscription updated"
|
80
|
+
# rescue Exception => e
|
81
|
+
# puts "An error occurred: #{e.message}"
|
82
|
+
# end
|
83
|
+
def update(customer_number, options)
|
84
|
+
customer = find(customer_number)
|
85
|
+
options = PaySimple.symbolize_hash(options)
|
86
|
+
|
87
|
+
# Add the existing customer properties to the options hash unless they already exist
|
88
|
+
[
|
89
|
+
:CustomerID,
|
90
|
+
:SendReceipt,
|
91
|
+
:ReceiptNote,
|
92
|
+
:Notes,
|
93
|
+
:User,
|
94
|
+
:Source,
|
95
|
+
:Schedule,
|
96
|
+
:Next,
|
97
|
+
:NumLeft,
|
98
|
+
:Amount,
|
99
|
+
:Enabled,
|
100
|
+
:CustomData,
|
101
|
+
:Description,
|
102
|
+
:OrderID
|
103
|
+
].each do |property|
|
104
|
+
options[property] = customer[property.to_s] unless options.has_key?(property)
|
105
|
+
end
|
106
|
+
|
107
|
+
# Add the existing customer address properties to the options hash unless they already exist
|
108
|
+
options[:BillingAddress] ||= {}
|
109
|
+
[
|
110
|
+
:FirstName,
|
111
|
+
:LastName,
|
112
|
+
:Company,
|
113
|
+
:Street,
|
114
|
+
:Street2,
|
115
|
+
:City,
|
116
|
+
:State,
|
117
|
+
:Zip,
|
118
|
+
:Country,
|
119
|
+
:Phone,
|
120
|
+
:Fax,
|
121
|
+
:Email
|
122
|
+
].each do |property|
|
123
|
+
options[:BillingAddress][property] = customer["BillingAddress"][property.to_s] unless options[:BillingAddress].has_key?(property)
|
124
|
+
end
|
125
|
+
|
126
|
+
# Add the existing customer credit card properties to the options hash unless they already exist
|
127
|
+
options[:CreditCardData] ||= {}
|
128
|
+
[
|
129
|
+
:CardNumber,
|
130
|
+
:CardExpiration,
|
131
|
+
:CardCode,
|
132
|
+
:AvsStreet,
|
133
|
+
:AvsZip,
|
134
|
+
:CardPresent,
|
135
|
+
:MagStripe,
|
136
|
+
:TermType,
|
137
|
+
:MagSupport,
|
138
|
+
:XID,
|
139
|
+
:CAVV,
|
140
|
+
:ECI,
|
141
|
+
:InternalCardAuth,
|
142
|
+
:Pares
|
143
|
+
].each do |property|
|
144
|
+
options[:CreditCardData][property] = customer["CreditCardData"][property.to_s] unless options[:CreditCardData].has_key?(property)
|
145
|
+
end
|
146
|
+
|
147
|
+
# Add the existing customer check properties to the options hash unless they already exist
|
148
|
+
options[:CheckData] ||= {}
|
149
|
+
[
|
150
|
+
:CheckNumber,
|
151
|
+
:Routing,
|
152
|
+
:Account,
|
153
|
+
:SSN,
|
154
|
+
:DriversLicense,
|
155
|
+
:DriversLicenseState
|
156
|
+
].each do |property|
|
157
|
+
options[:CheckData][property] = customer["CheckData"][property.to_s] unless options[:CheckData].has_key?(property)
|
158
|
+
end
|
159
|
+
|
160
|
+
PaySimple.send_request(:updateCustomer, customer_number, options)
|
161
|
+
end
|
162
|
+
|
163
|
+
# # Delete subscription
|
164
|
+
# begin
|
165
|
+
# customer_number = 12345
|
166
|
+
# response = PaySimple::Subscription.delete(customer_number)
|
167
|
+
#
|
168
|
+
# puts "Subscription removed from active use."
|
169
|
+
# rescue Exception => e
|
170
|
+
# puts "An error occurred: #{e.message}"
|
171
|
+
# end
|
172
|
+
def delete(customer_number)
|
173
|
+
PaySimple.send_request(:deleteCustomer, customer_number)
|
174
|
+
end
|
175
|
+
|
176
|
+
# # Find an existing subscription
|
177
|
+
# begin
|
178
|
+
# customer_number = 12345
|
179
|
+
# customer = PaySimple::Subscription.find(customer_number)
|
180
|
+
#
|
181
|
+
# puts "Found subscription for #{ [customer["BillingAddress"]["FirstName"], customer["BillingAddress"]["LastName"]].join(" ")}"
|
182
|
+
# rescue Exception => e
|
183
|
+
# puts "An error occurred: #{e.message}"
|
184
|
+
# end
|
185
|
+
def find(customer_number)
|
186
|
+
PaySimple.send_request(:getCustomer, customer_number)
|
187
|
+
end
|
188
|
+
|
189
|
+
# # Process one-time sale against existing subscription
|
190
|
+
# begin
|
191
|
+
# customer_number = 12345
|
192
|
+
# response = PaySimple::Subscription.charge(customer_number, :Amount => 34.56)
|
193
|
+
#
|
194
|
+
# if response['Response'] == "Approved"
|
195
|
+
# puts "One-time charge successful."
|
196
|
+
# else
|
197
|
+
# puts "An error occurred: #{response['Error']}"
|
198
|
+
# end
|
199
|
+
# rescue Exception => e
|
200
|
+
# puts "An error occurred: #{e.message}"
|
201
|
+
# end
|
202
|
+
def charge(customer_number, options, auth_only = false)
|
203
|
+
PaySimple.send_request(:runCustomerSale, customer_number, options, auth_only)
|
204
|
+
end
|
205
|
+
|
206
|
+
# # Search for transactions
|
207
|
+
# begin
|
208
|
+
# response = PaySimple::Subscription.query(
|
209
|
+
# [
|
210
|
+
# { :Field => 'amount', :Type => 'gt', :Value => '5.0' }
|
211
|
+
# ]
|
212
|
+
# )
|
213
|
+
#
|
214
|
+
# response.transactions.each do |transaction|
|
215
|
+
# puts "CustomerID = #{transaction['CustomerID']}, Amount = #{transaction['Details']['Amount']}"
|
216
|
+
# end
|
217
|
+
# rescue Exception => e
|
218
|
+
# puts "An error occurred: #{e.message}"
|
219
|
+
# end
|
220
|
+
def query(options)
|
221
|
+
match_all = options.delete(:match_all)
|
222
|
+
start = options.delete(:start) || 0
|
223
|
+
limit = options.delete(:limit) || 100
|
224
|
+
PaySimple.send_request(:searchTransactions, options, match_all, start, limit)
|
225
|
+
end
|
226
|
+
end
|
227
|
+
end
|
228
|
+
|
229
|
+
private
|
230
|
+
class << self
|
231
|
+
def symbolize_hash(hash)
|
232
|
+
hash.inject({}) { |h,(k,v)| h[k.to_sym] = v; h }
|
233
|
+
end
|
234
|
+
|
235
|
+
def token
|
236
|
+
seed = "#{Time.now.to_i}#{rand(999999)}"
|
237
|
+
hash = Digest::SHA1.hexdigest([key, seed, pin].join)
|
238
|
+
{
|
239
|
+
'SourceKey' => key,
|
240
|
+
'PinHash' => {
|
241
|
+
'Type' => "sha1",
|
242
|
+
'Seed' => seed,
|
243
|
+
'HashValue' => hash
|
244
|
+
},
|
245
|
+
'ClientIP' => client_ip
|
246
|
+
}
|
247
|
+
end
|
248
|
+
|
249
|
+
def send_request(request, *args)
|
250
|
+
@driver ||= SOAP::WSDLDriverFactory.new(WSDL_URL).create_rpc_driver
|
251
|
+
@driver.options["protocol.http.ssl_config.verify_mode"] = nil
|
252
|
+
@driver.send(request, token, *args)
|
253
|
+
end
|
254
|
+
end
|
255
|
+
|
256
|
+
end
|