payjp 0.0.2

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.
Files changed (59) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +7 -0
  3. data/.rubocop.yml +82 -0
  4. data/.rubocop_todo.yml +35 -0
  5. data/.travis.yml +22 -0
  6. data/CONTRIBUTORS +0 -0
  7. data/Gemfile +8 -0
  8. data/History.txt +0 -0
  9. data/LICENSE +21 -0
  10. data/README.rdoc +43 -0
  11. data/Rakefile +8 -0
  12. data/VERSION +1 -0
  13. data/gemfiles/default-with-activesupport.gemfile +10 -0
  14. data/gemfiles/json.gemfile +12 -0
  15. data/gemfiles/yajl.gemfile +12 -0
  16. data/lib/payjp.rb +279 -0
  17. data/lib/payjp/account.rb +11 -0
  18. data/lib/payjp/api_operations/create.rb +16 -0
  19. data/lib/payjp/api_operations/delete.rb +11 -0
  20. data/lib/payjp/api_operations/list.rb +17 -0
  21. data/lib/payjp/api_operations/request.rb +39 -0
  22. data/lib/payjp/api_operations/update.rb +17 -0
  23. data/lib/payjp/api_resource.rb +35 -0
  24. data/lib/payjp/card.rb +18 -0
  25. data/lib/payjp/charge.rb +27 -0
  26. data/lib/payjp/customer.rb +8 -0
  27. data/lib/payjp/errors/api_connection_error.rb +4 -0
  28. data/lib/payjp/errors/api_error.rb +4 -0
  29. data/lib/payjp/errors/authentication_error.rb +4 -0
  30. data/lib/payjp/errors/card_error.rb +11 -0
  31. data/lib/payjp/errors/invalid_request_error.rb +10 -0
  32. data/lib/payjp/errors/payjp_error.rb +20 -0
  33. data/lib/payjp/event.rb +5 -0
  34. data/lib/payjp/list_object.rb +33 -0
  35. data/lib/payjp/payjp_object.rb +259 -0
  36. data/lib/payjp/plan.rb +8 -0
  37. data/lib/payjp/subscription.rb +37 -0
  38. data/lib/payjp/token.rb +5 -0
  39. data/lib/payjp/transfer.rb +5 -0
  40. data/lib/payjp/util.rb +121 -0
  41. data/lib/payjp/version.rb +3 -0
  42. data/payjp.gemspec +27 -0
  43. data/test/payjp/account_test.rb +17 -0
  44. data/test/payjp/api_resource_test.rb +445 -0
  45. data/test/payjp/charge_test.rb +83 -0
  46. data/test/payjp/customer_card_test.rb +61 -0
  47. data/test/payjp/customer_test.rb +35 -0
  48. data/test/payjp/event_test.rb +26 -0
  49. data/test/payjp/list_object_test.rb +16 -0
  50. data/test/payjp/metadata_test.rb +103 -0
  51. data/test/payjp/payjp_object_test.rb +28 -0
  52. data/test/payjp/plan_test.rb +48 -0
  53. data/test/payjp/subscription_test.rb +58 -0
  54. data/test/payjp/token_test.rb +34 -0
  55. data/test/payjp/transfer_test.rb +34 -0
  56. data/test/payjp/util_test.rb +34 -0
  57. data/test/test_data.rb +291 -0
  58. data/test/test_helper.rb +45 -0
  59. metadata +201 -0
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: a3ebefc29e62141f365e3ca15bb11d052229d6fc
4
+ data.tar.gz: 198a11ab68493049c173f512f05d6ac9122bad64
5
+ SHA512:
6
+ metadata.gz: 18b6e0e221ad9d6da678bd12cc5b091b6a824f95e3e0de34841a500ceed0fa25b6ab9724abc834180f39a609f379a181fa347a9a9d930fb5ff26ad8a47dc0002
7
+ data.tar.gz: 58037b77c13b1aa5d2536c0ddced86fc72fc99f6e5e0b6fe2f872efdfab5a60a4e19f67f9dd6e1a04d966cdc872b07fbb50cac3535d2c1d673fa4b5a41308350
@@ -0,0 +1,7 @@
1
+ /payjp-*.gem
2
+ /Gemfile.lock
3
+ .rvmrc
4
+ Gemfile.lock
5
+ .idea/*
6
+ .ruby-version
7
+ pkg/*
@@ -0,0 +1,82 @@
1
+ inherit_from: .rubocop_todo.yml
2
+
3
+ Style/PerlBackrefs:
4
+ Enabled: false
5
+
6
+ Style/IndentHash:
7
+ Enabled: false
8
+
9
+ Style/StringLiterals:
10
+ Enabled: false
11
+
12
+ Style/DeprecatedHashMethods:
13
+ Enabled: false
14
+
15
+ Style/RaiseArgs:
16
+ Enabled: false
17
+
18
+ Style/SignalException:
19
+ Enabled: false
20
+
21
+ Style/NumericLiterals:
22
+ MinDigits: 11
23
+
24
+ Style/ClassAndModuleChildren:
25
+ Enabled: false
26
+
27
+ Style/Documentation:
28
+ Enabled: false
29
+
30
+ Metrics/AbcSize:
31
+ Max: 45
32
+
33
+ Metrics/ClassLength:
34
+ Max: 376
35
+
36
+ Metrics/CyclomaticComplexity:
37
+ Max: 16
38
+
39
+ Metrics/LineLength:
40
+ Max: 315
41
+
42
+ Metrics/MethodLength:
43
+ Max: 63
44
+
45
+ Metrics/ModuleLength:
46
+ Max: 265
47
+
48
+ Metrics/ParameterLists:
49
+ Max: 6
50
+
51
+ Metrics/PerceivedComplexity:
52
+ Max: 20
53
+
54
+ Style/GuardClause:
55
+ MinBodyLength: 4
56
+
57
+ Style/FileName:
58
+ Exclude:
59
+ - '**/payjp-console'
60
+
61
+ Style/RescueModifier:
62
+ Enabled: false
63
+
64
+ #######################
65
+ # for ruby 1.8.7
66
+ #######################
67
+ # Configuration parameters: WordRegex.
68
+ Style/WordArray:
69
+ MinSize: 2
70
+
71
+ # Configuration parameters: SupportedStyles, UseHashRocketsWithSymbolValues.
72
+ Style/HashSyntax:
73
+ EnforcedStyle: hash_rockets
74
+
75
+ Style/Lambda:
76
+ Enabled: false
77
+
78
+ Style/EachWithObject:
79
+ Enabled: false
80
+
81
+ Style/DotPosition:
82
+ Enabled: false
@@ -0,0 +1,35 @@
1
+ # This configuration was generated by `rubocop --auto-gen-config`
2
+ # on 2015-06-28 13:48:45 +0900 using RuboCop version 0.32.1.
3
+ # The point is for the user to remove these configuration records
4
+ # one by one as the offenses are removed from the code base.
5
+ # Note that changes in the inspected code, or installation of new
6
+ # versions of RuboCop, may require this file to be generated again.
7
+
8
+ # Offense count: 3
9
+ # Configuration parameters: AllowSafeAssignment.
10
+ Lint/AssignmentInCondition:
11
+ Enabled: false
12
+
13
+ # Offense count: 1
14
+ Lint/ShadowingOuterLocalVariable:
15
+ Enabled: false
16
+
17
+ # Offense count: 3
18
+ # Cop supports --auto-correct.
19
+ # Configuration parameters: EnforcedStyle, SupportedStyles.
20
+ Style/AndOr:
21
+ Enabled: false
22
+
23
+ # Offense count: 32
24
+ # Configuration parameters: EnforcedStyle, SupportedStyles.
25
+ Style/BracesAroundHashParameters:
26
+ Enabled: false
27
+
28
+ # Offense count: 1
29
+ Style/ClassVars:
30
+ Enabled: false
31
+
32
+ # Offense count: 6
33
+ Style/DoubleNegation:
34
+ Enabled: false
35
+
@@ -0,0 +1,22 @@
1
+ language: ruby
2
+
3
+ rvm:
4
+ - 1.8.7
5
+ - 1.9.2
6
+ - 1.9.3
7
+ - 2.0.0
8
+ - 2.1
9
+ - 2.2
10
+ - jruby-19mode
11
+
12
+ gemfile:
13
+ - gemfiles/default-with-activesupport.gemfile
14
+ - gemfiles/json.gemfile
15
+ - gemfiles/yajl.gemfile
16
+
17
+ matrix:
18
+ exclude:
19
+ - rvm: jruby-19mode
20
+ gemfile: gemfiles/yajl.gemfile
21
+
22
+ sudo: false
File without changes
data/Gemfile ADDED
@@ -0,0 +1,8 @@
1
+ source "https://rubygems.org"
2
+ gemspec
3
+
4
+ if Gem::Version.new(RUBY_VERSION.dup) < Gem::Version.new('1.9.3')
5
+ gem 'i18n', '< 0.7'
6
+ gem 'rest-client', '~> 1.6.8'
7
+ gem 'activesupport', '~> 3.2'
8
+ end
File without changes
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License
2
+
3
+ Copyright (c) 2011- Stripe, Inc. (https://stripe.com)
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
@@ -0,0 +1,43 @@
1
+ = PAY.JP for Ruby
2
+
3
+ == Documentation
4
+
5
+ {PAY.JP API Docs}[http://pay.readme.io/v1.0/docs]
6
+
7
+ == Installation
8
+
9
+ You don't need this source code unless you want to modify the gem. If
10
+ you just want to use the Payjp Ruby bindings, you should run:
11
+
12
+ gem install payjp
13
+
14
+ If you want to build the gem from source:
15
+
16
+ gem build payjp.gemspec
17
+
18
+ == Requirements
19
+
20
+ * Ruby 1.8.7 or above. (Ruby 1.8.6 may work if you load
21
+ ActiveSupport.) For Ruby versions before 1.9.2, you'll need to add this to your Gemfile:
22
+
23
+ if Gem::Version.new(RUBY_VERSION) < Gem::Version.new('1.9.2')
24
+ gem 'rest-client', '~> 1.6.8'
25
+ end
26
+
27
+
28
+ * rest-client, json
29
+
30
+ == Bundler
31
+
32
+ If you are installing via bundler, you should be sure to use the https
33
+ rubygems source in your Gemfile, as any gems fetched over http could potentially be
34
+ compromised in transit and alter the code of gems fetched securely over https:
35
+
36
+ source 'https://rubygems.org'
37
+
38
+ gem 'rails'
39
+ gem 'payjp'
40
+
41
+ == Development
42
+
43
+ Test cases can be run with: `bundle exec rake test`
@@ -0,0 +1,8 @@
1
+ require 'bundler/gem_tasks'
2
+ require 'rake/testtask'
3
+
4
+ task :default => [:test]
5
+
6
+ Rake::TestTask.new do |t|
7
+ t.pattern = './test/**/*_test.rb'
8
+ end
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.0.2
@@ -0,0 +1,10 @@
1
+ source "https://rubygems.org"
2
+ gemspec :path => File.join(File.dirname(__FILE__), "..")
3
+
4
+ if Gem::Version.new(RUBY_VERSION) < Gem::Version.new('1.9.3')
5
+ gem 'i18n', '< 0.7'
6
+ gem 'rest-client', '~> 1.6.8'
7
+ gem 'activesupport', '~> 3.2'
8
+ else
9
+ gem 'activesupport'
10
+ end
@@ -0,0 +1,12 @@
1
+ source "https://rubygems.org"
2
+ gemspec :path => File.join(File.dirname(__FILE__), "..")
3
+
4
+ if Gem::Version.new(RUBY_VERSION) < Gem::Version.new('1.9.3')
5
+ gem 'i18n', '< 0.7'
6
+ gem 'rest-client', '~> 1.6.8'
7
+ gem 'activesupport', '~> 3.2'
8
+ else
9
+ gem 'activesupport'
10
+ end
11
+
12
+ gem 'json'
@@ -0,0 +1,12 @@
1
+ source "https://rubygems.org"
2
+ gemspec :path => File.join(File.dirname(__FILE__), "..")
3
+
4
+ if Gem::Version.new(RUBY_VERSION) < Gem::Version.new('1.9.3')
5
+ gem 'i18n', '< 0.7'
6
+ gem 'rest-client', '~> 1.6.8'
7
+ gem 'activesupport', '~> 3.2'
8
+ else
9
+ gem 'activesupport'
10
+ end
11
+
12
+ gem 'yajl-ruby'
@@ -0,0 +1,279 @@
1
+ # Payjp Ruby bindings
2
+ # API spec at https://pay.jp/docs/api
3
+ require 'cgi'
4
+ require 'openssl'
5
+ require 'rbconfig'
6
+ require 'set'
7
+ require 'socket'
8
+
9
+ require 'rest-client'
10
+ require 'json'
11
+ require 'base64'
12
+
13
+ # Version
14
+ require 'payjp/version'
15
+
16
+ # API operations
17
+ require 'payjp/api_operations/create'
18
+ require 'payjp/api_operations/update'
19
+ require 'payjp/api_operations/delete'
20
+ require 'payjp/api_operations/list'
21
+ require 'payjp/api_operations/request'
22
+
23
+ # Resources
24
+ require 'payjp/util'
25
+ require 'payjp/payjp_object'
26
+ require 'payjp/api_resource'
27
+ require 'payjp/list_object'
28
+ require 'payjp/account'
29
+ require 'payjp/customer'
30
+ require 'payjp/charge'
31
+ require 'payjp/plan'
32
+ require 'payjp/token'
33
+ require 'payjp/event'
34
+ require 'payjp/transfer'
35
+ require 'payjp/card'
36
+ require 'payjp/subscription'
37
+
38
+ # Errors
39
+ require 'payjp/errors/payjp_error'
40
+ require 'payjp/errors/api_error'
41
+ require 'payjp/errors/api_connection_error'
42
+ require 'payjp/errors/card_error'
43
+ require 'payjp/errors/invalid_request_error'
44
+ require 'payjp/errors/authentication_error'
45
+
46
+ module Payjp
47
+ @api_base = 'https://api.pay.jp'
48
+
49
+ class << self
50
+ attr_accessor :api_key, :api_base, :api_version, :connect_base, :uploads_base
51
+ end
52
+
53
+ def self.api_url(url = '', api_base_url = nil)
54
+ (api_base_url || @api_base) + url
55
+ end
56
+
57
+ def self.request(method, url, api_key, params = {}, headers = {}, api_base_url = nil)
58
+ api_base_url ||= @api_base
59
+
60
+ unless api_key ||= @api_key
61
+ raise AuthenticationError.new('No API key provided. ' \
62
+ 'Set your API key using "Payjp.api_key = <API-KEY>". ' \
63
+ 'You can generate API keys from the Payjp web interface. ' \
64
+ 'See https://pay.jp/api for details, or email support@pay.jp ' \
65
+ 'if you have any questions.')
66
+ end
67
+
68
+ if api_key =~ /\s/
69
+ raise AuthenticationError.new('Your API key is invalid, as it contains ' \
70
+ 'whitespace. (HINT: You can double-check your API key from the ' \
71
+ 'Payjp web interface. See https://pay.jp/api for details, or ' \
72
+ 'email support@pay.jp if you have any questions.)')
73
+ end
74
+
75
+ request_opts = {}
76
+
77
+ params = Util.objects_to_ids(params)
78
+ url = api_url(url, api_base_url)
79
+
80
+ case method.to_s.downcase.to_sym
81
+ when :get, :head, :delete
82
+ # Make params into GET parameters
83
+ url += "#{URI.parse(url).query ? '&' : '?'}#{uri_encode(params)}" if params && params.any?
84
+ payload = nil
85
+ else
86
+ if headers[:content_type] && headers[:content_type] == "multipart/form-data"
87
+ payload = params
88
+ else
89
+ payload = uri_encode(params)
90
+ end
91
+ end
92
+
93
+ request_opts.update(:headers => request_headers(api_key).update(headers),
94
+ :method => method, :open_timeout => 30,
95
+ :payload => payload, :url => url, :timeout => 80)
96
+
97
+ begin
98
+ # $stderr.puts request_opts
99
+
100
+ response = execute_request(request_opts)
101
+ rescue SocketError => e
102
+ handle_restclient_error(e, api_base_url)
103
+ rescue NoMethodError => e
104
+ # Work around RestClient bug
105
+ if e.message =~ /\WRequestFailed\W/
106
+ e = APIConnectionError.new('Unexpected HTTP response code')
107
+ handle_restclient_error(e, api_base_url)
108
+ else
109
+ raise
110
+ end
111
+ rescue RestClient::ExceptionWithResponse => e
112
+ if rcode = e.http_code and rbody = e.http_body
113
+ handle_api_error(rcode, rbody)
114
+ else
115
+ handle_restclient_error(e, api_base_url)
116
+ end
117
+ rescue RestClient::Exception, Errno::ECONNREFUSED => e
118
+ handle_restclient_error(e, api_base_url)
119
+ end
120
+
121
+ [parse(response), api_key]
122
+ end
123
+
124
+ private
125
+
126
+ def self.user_agent
127
+ @uname ||= uname
128
+ lang_version = "#{RUBY_VERSION} p#{RUBY_PATCHLEVEL} (#{RUBY_RELEASE_DATE})"
129
+
130
+ {
131
+ :bindings_version => Payjp::VERSION,
132
+ :lang => 'ruby',
133
+ :lang_version => lang_version,
134
+ :platform => RUBY_PLATFORM,
135
+ :engine => defined?(RUBY_ENGINE) ? RUBY_ENGINE : '',
136
+ :publisher => 'payjp',
137
+ :uname => @uname,
138
+ :hostname => Socket.gethostname
139
+ }
140
+ end
141
+
142
+ def self.uname
143
+ if File.exist?('/proc/version')
144
+ File.read('/proc/version').strip
145
+ else
146
+ case RbConfig::CONFIG['host_os']
147
+ when /linux|darwin|bsd|sunos|solaris|cygwin/i
148
+ _uname_uname
149
+ when /mswin|mingw/i
150
+ _uname_ver
151
+ else
152
+ "unknown platform"
153
+ end
154
+ end
155
+ end
156
+
157
+ def self._uname_uname
158
+ (`uname -a 2>/dev/null` || '').strip
159
+ rescue Errno::ENOMEM # couldn't create subprocess
160
+ "uname lookup failed"
161
+ end
162
+
163
+ def self._uname_ver
164
+ (`ver` || '').strip
165
+ rescue Errno::ENOMEM # couldn't create subprocess
166
+ "uname lookup failed"
167
+ end
168
+
169
+ def self.uri_encode(params)
170
+ Util.flatten_params(params).
171
+ map { |k, v| "#{k}=#{Util.url_encode(v)}" }.join('&')
172
+ end
173
+
174
+ def self.request_headers(api_key)
175
+ headers = {
176
+ :user_agent => "Payjp/v1 RubyBindings/#{Payjp::VERSION}",
177
+ :authorization => "Basic #{Base64.encode64("#{api_key}:")}",
178
+ :content_type => 'application/x-www-form-urlencoded'
179
+ }
180
+
181
+ headers[:payjp_version] = api_version if api_version
182
+
183
+ begin
184
+ headers.update(:x_payjp_client_user_agent => JSON.generate(user_agent))
185
+ rescue => e
186
+ headers.update(:x_payjp_client_raw_user_agent => user_agent.inspect,
187
+ :error => "#{e} (#{e.class})")
188
+ end
189
+ end
190
+
191
+ def self.execute_request(opts)
192
+ RestClient::Request.execute(opts)
193
+ end
194
+
195
+ def self.parse(response)
196
+ begin
197
+ # Would use :symbolize_names => true, but apparently there is
198
+ # some library out there that makes symbolize_names not work.
199
+ response = JSON.parse(response.body)
200
+ rescue JSON::ParserError
201
+ raise general_api_error(response.code, response.body)
202
+ end
203
+
204
+ Util.symbolize_names(response)
205
+ end
206
+
207
+ def self.general_api_error(rcode, rbody)
208
+ APIError.new("Invalid response object from API: #{rbody.inspect} " \
209
+ "(HTTP response code was #{rcode})", rcode, rbody)
210
+ end
211
+
212
+ def self.handle_api_error(rcode, rbody)
213
+ begin
214
+ error_obj = JSON.parse(rbody)
215
+ error_obj = Util.symbolize_names(error_obj)
216
+ error = error_obj[:error] or raise PayjpError.new # escape from parsing
217
+
218
+ rescue JSON::ParserError, PayjpError
219
+ raise general_api_error(rcode, rbody)
220
+ end
221
+
222
+ case rcode
223
+ when 400, 404
224
+ raise invalid_request_error error, rcode, rbody, error_obj
225
+ when 401
226
+ raise authentication_error error, rcode, rbody, error_obj
227
+ when 402
228
+ raise card_error error, rcode, rbody, error_obj
229
+ else
230
+ raise api_error error, rcode, rbody, error_obj
231
+ end
232
+ end
233
+
234
+ def self.invalid_request_error(error, rcode, rbody, error_obj)
235
+ InvalidRequestError.new(error[:message], error[:param], rcode,
236
+ rbody, error_obj)
237
+ end
238
+
239
+ def self.authentication_error(error, rcode, rbody, error_obj)
240
+ AuthenticationError.new(error[:message], rcode, rbody, error_obj)
241
+ end
242
+
243
+ def self.card_error(error, rcode, rbody, error_obj)
244
+ CardError.new(error[:message], error[:param], error[:code],
245
+ rcode, rbody, error_obj)
246
+ end
247
+
248
+ def self.api_error(error, rcode, rbody, error_obj)
249
+ APIError.new(error[:message], rcode, rbody, error_obj)
250
+ end
251
+
252
+ def self.handle_restclient_error(e, api_base_url = nil)
253
+ api_base_url = @api_base unless api_base_url
254
+ connection_message = "Please check your internet connection and try again. " \
255
+ "If this problem persists, you should check Payjp's service status at " \
256
+ "https://twitter.com/payjpstatus, or let us know at support@pay.jp."
257
+
258
+ case e
259
+ when RestClient::RequestTimeout
260
+ message = "Could not connect to Payjp (#{api_base_url}). #{connection_message}"
261
+
262
+ when RestClient::ServerBrokeConnection
263
+ message = "The connection to the server (#{api_base_url}) broke before the " \
264
+ "request completed. #{connection_message}"
265
+
266
+ when SocketError
267
+ message = "Unexpected error communicating when trying to connect to Payjp. " \
268
+ "You may be seeing this message because your DNS is not working. " \
269
+ "To check, try running 'host pay.jp' from the command line."
270
+
271
+ else
272
+ message = "Unexpected error communicating with Payjp. " \
273
+ "If this problem persists, let us know at support@pay.jp."
274
+
275
+ end
276
+
277
+ raise APIConnectionError.new(message + "\n\n(Network error: #{e.message})")
278
+ end
279
+ end