paypal-sdk-rest-pmrb 1.8.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (72) hide show
  1. checksums.yaml +7 -0
  2. data/Gemfile +15 -0
  3. data/README.md +265 -0
  4. data/Rakefile +15 -0
  5. data/data/DigiCertHighAssuranceEVRootCA.pem +23 -0
  6. data/data/DigiCertSHA2ExtendedValidationServerCA.pem +28 -0
  7. data/data/paypal.crt +193 -0
  8. data/lib/generators/paypal/sdk/USAGE +3 -0
  9. data/lib/generators/paypal/sdk/install_generator.rb +17 -0
  10. data/lib/generators/paypal/sdk/templates/paypal.rb +2 -0
  11. data/lib/generators/paypal/sdk/templates/paypal.yml +29 -0
  12. data/lib/paypal-sdk-core.rb +38 -0
  13. data/lib/paypal-sdk-rest.rb +2 -0
  14. data/lib/paypal-sdk/core/api.rb +20 -0
  15. data/lib/paypal-sdk/core/api/base.rb +169 -0
  16. data/lib/paypal-sdk/core/api/data_types/array_with_block.rb +44 -0
  17. data/lib/paypal-sdk/core/api/data_types/base.rb +225 -0
  18. data/lib/paypal-sdk/core/api/data_types/enum.rb +26 -0
  19. data/lib/paypal-sdk/core/api/data_types/simple_types.rb +52 -0
  20. data/lib/paypal-sdk/core/api/ipn.rb +66 -0
  21. data/lib/paypal-sdk/core/api/rest.rb +177 -0
  22. data/lib/paypal-sdk/core/authentication.rb +66 -0
  23. data/lib/paypal-sdk/core/config.rb +253 -0
  24. data/lib/paypal-sdk/core/credential.rb +16 -0
  25. data/lib/paypal-sdk/core/credential/base.rb +27 -0
  26. data/lib/paypal-sdk/core/credential/certificate.rb +32 -0
  27. data/lib/paypal-sdk/core/credential/signature.rb +22 -0
  28. data/lib/paypal-sdk/core/credential/third_party/subject.rb +25 -0
  29. data/lib/paypal-sdk/core/credential/third_party/token.rb +39 -0
  30. data/lib/paypal-sdk/core/exceptions.rb +112 -0
  31. data/lib/paypal-sdk/core/logging.rb +50 -0
  32. data/lib/paypal-sdk/core/openid_connect.rb +140 -0
  33. data/lib/paypal-sdk/core/openid_connect/api.rb +50 -0
  34. data/lib/paypal-sdk/core/openid_connect/data_types.rb +73 -0
  35. data/lib/paypal-sdk/core/openid_connect/get_api.rb +28 -0
  36. data/lib/paypal-sdk/core/openid_connect/request_data_type.rb +52 -0
  37. data/lib/paypal-sdk/core/openid_connect/set_api.rb +36 -0
  38. data/lib/paypal-sdk/core/util.rb +11 -0
  39. data/lib/paypal-sdk/core/util/http_helper.rb +171 -0
  40. data/lib/paypal-sdk/core/util/oauth_signature.rb +64 -0
  41. data/lib/paypal-sdk/core/util/ordered_hash.rb +165 -0
  42. data/lib/paypal-sdk/rest.rb +39 -0
  43. data/lib/paypal-sdk/rest/api.rb +23 -0
  44. data/lib/paypal-sdk/rest/data_types.rb +2597 -0
  45. data/lib/paypal-sdk/rest/error_hash.rb +39 -0
  46. data/lib/paypal-sdk/rest/get_api.rb +20 -0
  47. data/lib/paypal-sdk/rest/request_data_type.rb +53 -0
  48. data/lib/paypal-sdk/rest/set_api.rb +42 -0
  49. data/lib/paypal-sdk/rest/version.rb +7 -0
  50. data/spec/README.md +22 -0
  51. data/spec/config/cacert.pem +171 -0
  52. data/spec/config/cert_key.pem +33 -0
  53. data/spec/config/paypal.yml +35 -0
  54. data/spec/config/sample_data.yml +3 -0
  55. data/spec/core/api/data_type_spec.rb +289 -0
  56. data/spec/core/api/rest_spec.rb +211 -0
  57. data/spec/core/config_spec.rb +192 -0
  58. data/spec/core/logging_spec.rb +28 -0
  59. data/spec/core/openid_connect_spec.rb +153 -0
  60. data/spec/invoice_examples_spec.rb +38 -0
  61. data/spec/log/http.log +175 -0
  62. data/spec/log/rest_http.log +0 -0
  63. data/spec/payments_examples_spec.rb +437 -0
  64. data/spec/payouts_examples_spec.rb +74 -0
  65. data/spec/rest/data_types_spec.rb +62 -0
  66. data/spec/rest/error_hash_spec.rb +83 -0
  67. data/spec/spec_helper.rb +37 -0
  68. data/spec/subscription_examples_spec.rb +227 -0
  69. data/spec/support/sample_data.rb +5 -0
  70. data/spec/web_profile_examples_spec.rb +106 -0
  71. data/spec/webhooks_examples_spec.rb +93 -0
  72. metadata +177 -0
@@ -0,0 +1,165 @@
1
+ module PayPal::SDK::Core
2
+ module Util
3
+ class OrderedHash < ::Hash #:nodoc:
4
+
5
+ def to_yaml_type
6
+ "!tag:yaml.org,2002:map"
7
+ end
8
+
9
+ # Hash is ordered in Ruby 1.9!
10
+ if RUBY_VERSION < '1.9'
11
+
12
+ # In MRI the Hash class is core and written in C. In particular, methods are
13
+ # programmed with explicit C function calls and polymorphism is not honored.
14
+ #
15
+ # For example, []= is crucial in this implementation to maintain the @keys
16
+ # array but hash.c invokes rb_hash_aset() originally. This prevents method
17
+ # reuse through inheritance and forces us to reimplement stuff.
18
+ #
19
+ # For instance, we cannot use the inherited #merge! because albeit the algorithm
20
+ # itself would work, our []= is not being called at all by the C code.
21
+
22
+ def initialize(*args, &block)
23
+ super
24
+ @keys = []
25
+ end
26
+
27
+ def self.[](*args)
28
+ ordered_hash = new
29
+
30
+ if (args.length == 1 && args.first.is_a?(Array))
31
+ args.first.each do |key_value_pair|
32
+ next unless (key_value_pair.is_a?(Array))
33
+ ordered_hash[key_value_pair[0]] = key_value_pair[1]
34
+ end
35
+
36
+ return ordered_hash
37
+ end
38
+
39
+ unless (args.size % 2 == 0)
40
+ raise ArgumentError.new("odd number of arguments for Hash")
41
+ end
42
+
43
+ args.each_with_index do |val, ind|
44
+ next if (ind % 2 != 0)
45
+ ordered_hash[val] = args[ind + 1]
46
+ end
47
+
48
+ ordered_hash
49
+ end
50
+
51
+ def initialize_copy(other)
52
+ super
53
+ # make a deep copy of keys
54
+ @keys = other.keys
55
+ end
56
+
57
+ def []=(key, value)
58
+ @keys << key if !has_key?(key)
59
+ super
60
+ end
61
+
62
+ def delete(key)
63
+ if has_key? key
64
+ index = @keys.index(key)
65
+ @keys.delete_at index
66
+ end
67
+ super
68
+ end
69
+
70
+ def delete_if
71
+ super
72
+ sync_keys!
73
+ self
74
+ end
75
+
76
+ def reject!
77
+ super
78
+ sync_keys!
79
+ self
80
+ end
81
+
82
+ def reject(&block)
83
+ dup.reject!(&block)
84
+ end
85
+
86
+ def keys
87
+ @keys.dup
88
+ end
89
+
90
+ def values
91
+ @keys.collect { |key| self[key] }
92
+ end
93
+
94
+ def to_hash
95
+ self
96
+ end
97
+
98
+ def to_a
99
+ @keys.map { |key| [ key, self[key] ] }
100
+ end
101
+
102
+ def each_key
103
+ @keys.each { |key| yield key }
104
+ end
105
+
106
+ def each_value
107
+ @keys.each { |key| yield self[key]}
108
+ end
109
+
110
+ def each
111
+ @keys.each {|key| yield [key, self[key]]}
112
+ end
113
+
114
+ alias_method :each_pair, :each
115
+
116
+ def clear
117
+ super
118
+ @keys.clear
119
+ self
120
+ end
121
+
122
+ def shift
123
+ k = @keys.first
124
+ v = delete(k)
125
+ [k, v]
126
+ end
127
+
128
+ def merge!(other_hash)
129
+ if block_given?
130
+ other_hash.each { |k, v| self[k] = key?(k) ? yield(k, self[k], v) : v }
131
+ else
132
+ other_hash.each { |k, v| self[k] = v }
133
+ end
134
+ self
135
+ end
136
+
137
+ alias_method :update, :merge!
138
+
139
+ def merge(other_hash, &block)
140
+ dup.merge!(other_hash, &block)
141
+ end
142
+
143
+ # When replacing with another hash, the initial order of our keys must come from the other hash -ordered or not.
144
+ def replace(other)
145
+ super
146
+ @keys = other.keys
147
+ self
148
+ end
149
+
150
+ def invert
151
+ OrderedHash[self.to_a.map!{|key_value_pair| key_value_pair.reverse}]
152
+ end
153
+
154
+ def inspect
155
+ "#<OrderedHash #{super}>"
156
+ end
157
+
158
+ private
159
+ def sync_keys!
160
+ @keys.delete_if {|k| !has_key?(k)}
161
+ end
162
+ end
163
+ end
164
+ end
165
+ end
@@ -0,0 +1,39 @@
1
+ require 'paypal-sdk-core'
2
+
3
+ module PayPal
4
+ module SDK
5
+ module REST
6
+ autoload :VERSION, "paypal-sdk/rest/version"
7
+ autoload :DataTypes, "paypal-sdk/rest/data_types"
8
+ autoload :API, "paypal-sdk/rest/api"
9
+ autoload :RequestDataType, "paypal-sdk/rest/request_data_type"
10
+ autoload :SetAPI, "paypal-sdk/rest/set_api"
11
+ autoload :GetAPI, "paypal-sdk/rest/get_api"
12
+ autoload :ErrorHash, "paypal-sdk/rest/error_hash"
13
+
14
+ include DataTypes
15
+ include Core::Exceptions
16
+
17
+ module ClassMethods
18
+ def method_missing(name, *args)
19
+ RequestDataType.send(name, *args)
20
+ end
21
+ end
22
+
23
+ class << self
24
+ def new(*args)
25
+ API.new(*args)
26
+ end
27
+
28
+ include ClassMethods
29
+
30
+ def included(klass)
31
+ if klass.is_a? Module
32
+ klass.extend(ClassMethods)
33
+ end
34
+ end
35
+ end
36
+
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,23 @@
1
+ require 'paypal-sdk-core'
2
+ require 'paypal-sdk/rest/version'
3
+
4
+ module PayPal
5
+ module SDK
6
+ module REST
7
+ class API < Core::API::REST
8
+ # include Services
9
+
10
+ def initialize(environment = nil, options = {})
11
+ super("", environment, options)
12
+ end
13
+
14
+ class << self
15
+ def user_agent
16
+ @user_agent ||= "PayPalSDK/PayPal-Ruby-SDK #{PayPal::SDK::REST::VERSION} (#{sdk_library_details})"
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
22
+ end
23
+
@@ -0,0 +1,2597 @@
1
+ require 'paypal-sdk-core'
2
+ require 'securerandom'
3
+ require 'multi_json'
4
+ require 'zlib'
5
+ require "base64"
6
+ require 'net/http'
7
+
8
+ module PayPal::SDK
9
+ module REST
10
+ module DataTypes
11
+ class Base < Core::API::DataTypes::Base
12
+ attr_accessor :error
13
+ attr_writer :header, :request_id
14
+
15
+ def header
16
+ @header ||= {}
17
+ end
18
+
19
+ def request_id
20
+ @request_id ||= SecureRandom.uuid
21
+ end
22
+
23
+ def http_header
24
+ { "PayPal-Request-Id" => request_id.to_s }.merge(header)
25
+ end
26
+
27
+ def success?
28
+ @error.nil?
29
+ end
30
+
31
+ def merge!(values)
32
+ @error = nil
33
+ super
34
+ end
35
+
36
+ def raise_error!
37
+ raise Core::Exceptions::UnsuccessfulApiCall, error if error
38
+ end
39
+
40
+ def self.load_members
41
+ end
42
+
43
+ def self.raise_on_api_error(*methods)
44
+ methods.each do |symbol|
45
+ define_method("#{symbol}!") {|*arg|
46
+ raise_error! unless send(symbol, *arg)
47
+ }
48
+ end
49
+ end
50
+
51
+ class Number < Float
52
+ end
53
+ end
54
+
55
+ class Payment < Base
56
+ def self.load_members
57
+ object_of :id, String
58
+ object_of :intent, String
59
+ object_of :payer, Payer
60
+ object_of :payee, Payee
61
+ object_of :cart, String
62
+ array_of :transactions, Transaction
63
+ array_of :failed_transactions, Error
64
+ object_of :payment_instruction, PaymentInstruction
65
+ object_of :state, String
66
+ object_of :experience_profile_id, String
67
+ object_of :note_to_payer, String
68
+ object_of :redirect_urls, RedirectUrls
69
+ object_of :failure_reason, String
70
+ object_of :create_time, String
71
+ object_of :update_time, String
72
+ array_of :links, Links
73
+ object_of :note_to_payer, String
74
+ array_of :billing_agreement_tokens, String
75
+ object_of :potential_payer_info, PotentialPayerInfo
76
+ object_of :credit_financing_offered, CreditFinancingOffered
77
+ object_of :failure_reason, String
78
+ end
79
+
80
+ include RequestDataType
81
+
82
+ def create()
83
+ path = "v1/payments/payment"
84
+ response = api.post(path, self.to_hash, http_header)
85
+ self.merge!(response)
86
+ success?
87
+ end
88
+
89
+ def update(patch_requests)
90
+ patch_request_array = []
91
+ patch_requests.each do |patch_request|
92
+ patch_request = Patch.new(patch_request) unless patch_request.is_a? Patch
93
+ patch_request_array << patch_request.to_hash
94
+ end
95
+ path = "v1/payments/payment/#{self.id}"
96
+ response = api.patch(path, patch_request_array, http_header)
97
+ self.merge!(response)
98
+ success?
99
+ end
100
+
101
+ def execute(payment_execution)
102
+ payment_execution = PaymentExecution.new(payment_execution) unless payment_execution.is_a? PaymentExecution
103
+ path = "v1/payments/payment/#{self.id}/execute"
104
+ response = api.post(path, payment_execution.to_hash, http_header)
105
+ self.merge!(response)
106
+ success?
107
+ end
108
+
109
+ raise_on_api_error :create, :update, :execute
110
+
111
+ def approval_url(immediate = false)
112
+ link = links.detect { |l| l.rel == 'approval_url' }
113
+ return nil unless link
114
+ link.href + (immediate ? '&useraction=commit' : '')
115
+ end
116
+
117
+ def token
118
+ url = approval_url
119
+ return nil unless url
120
+ CGI.parse(URI.parse(url).query)['token'].first
121
+ end
122
+
123
+ class << self
124
+ def find(resource_id)
125
+ raise ArgumentError.new("id required") if resource_id.to_s.strip.empty?
126
+ path = "v1/payments/payment/#{resource_id}"
127
+ self.new(api.get(path))
128
+ end
129
+
130
+ def all(options = {})
131
+ path = "v1/payments/payment"
132
+ PaymentHistory.new(api.get(path, options))
133
+ end
134
+ end
135
+ end
136
+
137
+ class PotentialPayerInfo < Base
138
+ def self.load_members
139
+ object_of :email, String
140
+ object_of :external_remember_me_id, String
141
+ object_of :billing_address, Address
142
+ end
143
+
144
+ include RequestDataType
145
+ end
146
+
147
+ class ProcessorResponse < Base
148
+ def self.load_members
149
+ object_of :response_code, String
150
+ object_of :avs_code, String
151
+ object_of :cvv_code, Address
152
+ object_of :advice_code, String
153
+ object_of :eci_submitted, String
154
+ object_of :vpas, String
155
+ end
156
+
157
+ include RequestDataType
158
+ end
159
+
160
+ class AlternatePayment < Base
161
+ def self.load_members
162
+ object_of :alternate_payment_account_id, String
163
+ object_of :external_customer_id, String
164
+ object_of :alternate_payment_provider_id, String
165
+ end
166
+
167
+ include RequestDataType
168
+ end
169
+
170
+ class Billing < Base
171
+ def self.load_members
172
+ object_of :billing_agreement_id, String
173
+ object_of :selected_installment_option, InstallmentOption
174
+ end
175
+
176
+ include RequestDataType
177
+ end
178
+
179
+ class BillingAgreementToken < Base
180
+ def self.load_members
181
+ end
182
+
183
+ include RequestDataType
184
+ end
185
+
186
+ class CountryCode < Base
187
+ def self.load_members
188
+ object_of :country_code, String
189
+ end
190
+
191
+ include RequestDataType
192
+ end
193
+
194
+ class CreditFinancingOffered < Base
195
+ def self.load_members
196
+ object_of :total_cost, Currency
197
+ object_of :term, Number
198
+ object_of :monthly_payment, Currency
199
+ object_of :total_interest, Currency
200
+ object_of :payer_acceptance, Boolean
201
+ object_of :cart_amount_immutable, Boolean
202
+ end
203
+
204
+ include RequestDataType
205
+ end
206
+
207
+ class ExternalFunding < Base
208
+ def self.load_members
209
+ object_of :reference_id, String
210
+ object_of :code, String
211
+ object_of :funding_account_id, String
212
+ object_of :display_text, String
213
+ object_of :amount, Currency
214
+ object_of :funding_instruction, String
215
+ end
216
+
217
+ include RequestDataType
218
+ end
219
+
220
+ class PotentialPayerInfo < Base
221
+ def self.load_members
222
+ object_of :email, String
223
+ object_of :external_remember_me_id, String
224
+ object_of :billing_address, Address
225
+ end
226
+
227
+ include RequestDataType
228
+ end
229
+
230
+ class PrivateLabelCard < Base
231
+ def self.load_members
232
+ object_of :id, String
233
+ object_of :card_number, String
234
+ object_of :issuer_id, Address
235
+ object_of :issuer_name, Address
236
+ object_of :image_key, Address
237
+ end
238
+
239
+ include RequestDataType
240
+ end
241
+
242
+ class ProcessorResponse < Base
243
+ def self.load_members
244
+ object_of :response_code, String
245
+ object_of :avs_code, String
246
+ object_of :cvv_code, String
247
+ object_of :advice_code, String
248
+ object_of :eci_submitted, String
249
+ object_of :vpas, String
250
+ end
251
+
252
+ include RequestDataType
253
+ end
254
+
255
+
256
+
257
+
258
+ class FuturePayment < Payment
259
+
260
+ def create(correlation_id=nil)
261
+ path = "v1/payments/payment"
262
+ if correlation_id != nil
263
+ header = http_header
264
+ header = header.merge({
265
+ "PAYPAL-CLIENT-METADATA-ID" => correlation_id})
266
+ end
267
+ response = api.post(path, self.to_hash, http_header)
268
+ self.merge!(response)
269
+ success?
270
+ end
271
+
272
+ raise_on_api_error :create
273
+
274
+ class << self
275
+
276
+ def exch_token(auth_code)
277
+ if auth_code
278
+ PayPal::SDK::OpenIDConnect::DataTypes::Tokeninfo.token_hash(auth_code)
279
+ else
280
+ raise ArgumentError.new("authorization code required") if auth_code.to_s.strip.empty?
281
+ end
282
+ end
283
+
284
+ end
285
+ end
286
+
287
+ class Payer < Base
288
+ def self.load_members
289
+ object_of :payment_method, String
290
+ object_of :status, String
291
+ object_of :account_type, String
292
+ object_of :account_age, String
293
+ array_of :funding_instruments, FundingInstrument
294
+ object_of :funding_option_id, String
295
+ object_of :funding_option, FundingOption
296
+ object_of :external_selected_funding_instrument_type, String
297
+ object_of :related_funding_option, FundingOption
298
+ object_of :payer_info, PayerInfo
299
+ object_of :billing, Billing
300
+ end
301
+ end
302
+
303
+ class FundingInstrument < Base
304
+ def self.load_members
305
+ object_of :credit_card, CreditCard
306
+ object_of :credit_card_token, CreditCardToken
307
+ end
308
+ end
309
+
310
+ class CreditCard < Base
311
+ def self.load_members
312
+ object_of :id, String
313
+ object_of :number, String
314
+ object_of :type, String
315
+ object_of :expire_month, Integer
316
+ object_of :expire_year, Integer
317
+ object_of :cvv2, String
318
+ object_of :first_name, String
319
+ object_of :last_name, String
320
+ object_of :billing_address, Address
321
+ object_of :external_customer_id, String
322
+ object_of :state, String
323
+ object_of :valid_until, String
324
+ object_of :create_time, String
325
+ object_of :update_time, String
326
+ array_of :links, Links
327
+ end
328
+
329
+ include RequestDataType
330
+
331
+ def create()
332
+ path = "v1/vault/credit-cards"
333
+ response = api.post(path, self.to_hash, http_header)
334
+ self.merge!(response)
335
+ success?
336
+ end
337
+
338
+ class << self
339
+ def find(resource_id)
340
+ raise ArgumentError.new("id required") if resource_id.to_s.strip.empty?
341
+ path = "v1/vault/credit-cards/#{resource_id}"
342
+ self.new(api.get(path))
343
+ end
344
+ end
345
+
346
+ def delete()
347
+ path = "v1/vault/credit-cards/#{self.id}"
348
+ response = api.delete(path, {})
349
+ self.merge!(response)
350
+ success?
351
+ end
352
+
353
+ def update(patch_requests)
354
+ patch_request_array = []
355
+ patch_requests.each do |patch_request|
356
+ patch_request = Patch.new(patch_request) unless patch_request.is_a? Patch
357
+ patch_request_array << patch_request.to_hash
358
+ end
359
+ path = "v1/vault/credit-cards/#{self.id}"
360
+ response = api.patch(path, patch_request_array, http_header)
361
+ self.merge!(response)
362
+ success?
363
+ end
364
+
365
+ raise_on_api_error :create, :update, :delete
366
+ end
367
+
368
+ class BaseAddress < Base
369
+ def self.load_members
370
+ object_of :line1, String
371
+ object_of :line2, String
372
+ object_of :city, String
373
+ object_of :country_code, String
374
+ object_of :postal_code, String
375
+ object_of :state, String
376
+ object_of :normalization_status, String
377
+ object_of :status, String
378
+ object_of :type, String
379
+ end
380
+ end
381
+
382
+ class Address < BaseAddress
383
+ def self.load_members
384
+ object_of :phone, String
385
+ end
386
+ end
387
+
388
+ class InvoiceAddress < BaseAddress
389
+ def self.load_members
390
+ object_of :phone, Phone
391
+ end
392
+ end
393
+
394
+ class OneOf < Base
395
+ def self.load_members
396
+ object_of :phone, Phone
397
+ end
398
+ end
399
+
400
+ class CreditCardToken < Base
401
+ def self.load_members
402
+ object_of :credit_card_id, String
403
+ object_of :payer_id, String
404
+ object_of :last4, String
405
+ object_of :type, String
406
+ object_of :expire_month, Integer
407
+ object_of :expire_year, Integer
408
+ end
409
+ end
410
+
411
+ class PaymentCard < Base
412
+ def self.load_members
413
+ object_of :id, String
414
+ object_of :number, String
415
+ object_of :type, String
416
+ object_of :expire_month, Integer
417
+ object_of :expire_year, Integer
418
+ object_of :start_month, String
419
+ object_of :start_year, String
420
+ object_of :cvv2, String
421
+ object_of :first_name, String
422
+ object_of :last_name, String
423
+ object_of :billing_country, String
424
+ object_of :billing_address, Address
425
+ object_of :external_customer_id, String
426
+ object_of :status, String
427
+ object_of :card_product_class, String
428
+ object_of :valid_until, String
429
+ object_of :issue_number, String
430
+ end
431
+ end
432
+
433
+ class BankAccount < Base
434
+ def self.load_members
435
+ object_of :id, String
436
+ object_of :account_number, String
437
+ object_of :account_number_type, String
438
+ object_of :routing_number, String
439
+ object_of :account_type, String
440
+ object_of :account_name, String
441
+ object_of :check_type, String
442
+ object_of :auth_type, String
443
+ object_of :auth_capture_timestamp, String
444
+ object_of :bank_name, String
445
+ object_of :country_code, String
446
+ object_of :first_name, String
447
+ object_of :last_name, String
448
+ object_of :birth_date, String
449
+ object_of :billing_address, Address
450
+ object_of :state, String
451
+ object_of :confirmation_status, String
452
+ object_of :payer_id, String
453
+ object_of :external_customer_id, String
454
+ object_of :merchant_id, String
455
+ object_of :create_time, String
456
+ object_of :update_time, String
457
+ object_of :valid_until, String
458
+ end
459
+
460
+ include RequestDataType
461
+
462
+ def create()
463
+ path = "v1/vault/bank-accounts"
464
+ response = api.post(path, self.to_hash, http_header)
465
+ self.merge!(response)
466
+ success?
467
+ end
468
+
469
+ class << self
470
+ def find(resource_id)
471
+ raise ArgumentError.new("id required") if resource_id.to_s.strip.empty?
472
+ path = "v1/vault/bank-accounts/#{resource_id}"
473
+ self.new(api.get(path))
474
+ end
475
+ end
476
+
477
+ def delete()
478
+ path = "v1/vault/bank-accounts/#{self.id}"
479
+ response = api.delete(path, {})
480
+ self.merge!(response)
481
+ success?
482
+ end
483
+
484
+ def update(patch_request)
485
+ patch_request = PatchRequest.new(patch_request) unless patch_request.is_a? PatchRequest
486
+ path = "v1/vault/bank-accounts/#{self.id}"
487
+ response = api.patch(path, patch_request.to_hash, http_header)
488
+ self.merge!(response)
489
+ success?
490
+ end
491
+
492
+ raise_on_api_error :create, :update, :delete
493
+ end
494
+
495
+ class ExtendedBankAccount < BankAccount
496
+ def self.load_members
497
+ object_of :mandate_reference_number, String
498
+ end
499
+ end
500
+
501
+ class BankToken < Base
502
+ def self.load_members
503
+ object_of :bank_id, String
504
+ object_of :external_customer_id, String
505
+ object_of :mandate_reference_number, String
506
+ end
507
+ end
508
+
509
+ class Credit < Base
510
+ def self.load_members
511
+ object_of :id, String
512
+ object_of :type, String
513
+ end
514
+ end
515
+
516
+ class Incentive < Base
517
+ def self.load_members
518
+ object_of :id, String
519
+ object_of :code, String
520
+ object_of :name, String
521
+ object_of :description, String
522
+ object_of :minimum_purchase_amount, Currency
523
+ object_of :logo_image_url, String
524
+ object_of :expiry_date, String
525
+ object_of :type, String
526
+ object_of :terms, String
527
+ end
528
+ end
529
+
530
+ class Currency < Base
531
+ def self.load_members
532
+ object_of :currency, String
533
+ object_of :value, String
534
+ end
535
+ end
536
+
537
+ class CarrierAccountToken < Base
538
+ def self.load_members
539
+ object_of :carrier_account_id, String
540
+ object_of :external_customer_id, String
541
+ end
542
+ end
543
+
544
+ class FundingOption < Base
545
+ def self.load_members
546
+ object_of :id, String
547
+ array_of :funding_sources, FundingSource
548
+ object_of :backup_funding_instrument, FundingInstrument
549
+ object_of :currency_conversion, CurrencyConversion
550
+ object_of :installment_info, InstallmentInfo
551
+ end
552
+ end
553
+
554
+ class FundingSource < Base
555
+ def self.load_members
556
+ object_of :funding_mode, String
557
+ object_of :funding_instrument_type, String
558
+ object_of :soft_descriptor, String
559
+ object_of :amount, Currency
560
+ object_of :negative_balance_amount, Currency
561
+ object_of :legal_text, String
562
+ object_of :terms, String
563
+ object_of :funding_detail, FundingDetail
564
+ object_of :additional_text, String
565
+ object_of :extends, FundingInstrument
566
+ object_of :negative_balance_amount, Currency
567
+ object_of :links, Links
568
+ end
569
+ end
570
+
571
+ class FundingDetail < Base
572
+ def self.load_members
573
+ object_of :clearing_time, String
574
+ object_of :payment_hold_date, String
575
+ object_of :payment_debit_date, String
576
+ object_of :processing_type, String
577
+ end
578
+ end
579
+
580
+ class CurrencyConversion < Base
581
+ def self.load_members
582
+ object_of :conversion_date, String
583
+ object_of :from_currency, String
584
+ object_of :from_amount, Number
585
+ object_of :to_currency, String
586
+ object_of :to_amount, Number
587
+ object_of :conversion_type, String
588
+ object_of :conversion_type_changeable, Boolean
589
+ object_of :web_url, String
590
+ end
591
+ end
592
+
593
+ class InstallmentInfo < Base
594
+ def self.load_members
595
+ object_of :installment_id, String
596
+ object_of :network, String
597
+ object_of :issuer, String
598
+ array_of :installment_options, InstallmentOption
599
+ end
600
+ end
601
+
602
+ class InstallmentOption < Base
603
+ def self.load_members
604
+ object_of :term, Integer
605
+ object_of :monthly_payment, Currency
606
+ object_of :discount_amount, Currency
607
+ object_of :discount_percentage, Percentage
608
+ end
609
+ end
610
+
611
+ class Percentage < Base
612
+ def self.load_members
613
+ end
614
+ end
615
+
616
+ class PayerInfo < Base
617
+ def self.load_members
618
+ object_of :email, String
619
+ object_of :external_remember_me_id, String
620
+ object_of :buyer_account_number, String
621
+ object_of :salutation, String
622
+ object_of :first_name, String
623
+ object_of :middle_name, String
624
+ object_of :last_name, String
625
+ object_of :suffix, String
626
+ object_of :payer_id, String
627
+ object_of :phone, String
628
+ object_of :phone_type, String
629
+ object_of :birth_date, String
630
+ object_of :tax_id, String
631
+ object_of :tax_id_type, String
632
+ object_of :country_code, String
633
+ object_of :billing_address, Address
634
+ object_of :shipping_address, ShippingAddress
635
+ end
636
+ end
637
+
638
+ class ShippingAddress < Base
639
+ def self.load_members
640
+ object_of :line1, String
641
+ object_of :line2, String
642
+ object_of :city, String
643
+ object_of :state, String
644
+ object_of :postal_code, String
645
+ object_of :country_code, String
646
+ object_of :phone, String
647
+ object_of :normalization_status, String
648
+ object_of :id, String
649
+ object_of :recipient_name, String
650
+ end
651
+ end
652
+
653
+ class AllOf < Base
654
+ def self.load_members
655
+ array_of :related_resources, RelatedResources
656
+ end
657
+ end
658
+
659
+ class Transaction < Base
660
+ def self.load_members
661
+ object_of :amount, Amount
662
+ object_of :payee, Payee
663
+ object_of :description, String
664
+ object_of :invoice_number, String
665
+ object_of :custom, String
666
+ object_of :soft_descriptor, String
667
+ object_of :item_list, ItemList
668
+ object_of :notify_url, String
669
+ object_of :purchase_unit_reference_id, String
670
+ array_of :related_resources, RelatedResources
671
+ array_of :transactions, Transaction
672
+ object_of :payment_options, PaymentOptions
673
+ end
674
+ end
675
+
676
+ class CartBase < Base
677
+ def self.load_members
678
+ object_of :amount, Amount
679
+ object_of :payee, Payee
680
+ object_of :description, String
681
+ object_of :note_to_payee, String
682
+ object_of :custom, String
683
+ object_of :invoice_number, String
684
+ object_of :soft_descriptor, String
685
+ object_of :payment_options, PaymentOptions
686
+ object_of :item_list, ItemList
687
+ object_of :notify_url, String
688
+ object_of :order_url, String
689
+ object_of :reference_id, String
690
+ end
691
+ end
692
+
693
+ class Amount < Base
694
+ def self.load_members
695
+ object_of :currency, String
696
+ object_of :total, String
697
+ object_of :details, Details
698
+ end
699
+ end
700
+
701
+ class Details < Base
702
+ def self.load_members
703
+ object_of :subtotal, String
704
+ object_of :shipping, String
705
+ object_of :tax, String
706
+ object_of :fee, String
707
+ object_of :handling_fee, String
708
+ object_of :shipping_discount, String
709
+ object_of :insurance, String
710
+ object_of :gift_wrap, String
711
+ end
712
+ end
713
+
714
+ class Payee < Base
715
+ def self.load_members
716
+ object_of :email, String
717
+ object_of :merchant_id, String
718
+ object_of :phone, Phone
719
+ end
720
+ end
721
+
722
+ class Phone < Base
723
+ def self.load_members
724
+ object_of :country_code, String
725
+ object_of :national_number, String
726
+ object_of :extension, String
727
+ end
728
+ end
729
+
730
+ class PaymentOptions < Base
731
+ def self.load_members
732
+ object_of :allowed_payment_method, String
733
+ end
734
+ end
735
+
736
+ class Item < Base
737
+ def self.load_members
738
+ object_of :sku, String
739
+ object_of :name, String
740
+ object_of :description, String
741
+ object_of :quantity, String
742
+ object_of :price, String
743
+ object_of :currency, String
744
+ object_of :tax, String
745
+ object_of :url, String
746
+ object_of :category, String
747
+ object_of :weight, Measurement
748
+ object_of :length, Measurement
749
+ object_of :height, Measurement
750
+ object_of :width, Measurement
751
+ array_of :supplementary_data, NameValuePair
752
+ array_of :postback_data, NameValuePair
753
+ end
754
+ end
755
+
756
+ class Measurement < Base
757
+ def self.load_members
758
+ object_of :value, String
759
+ object_of :unit, String
760
+ end
761
+ end
762
+
763
+ class NameValuePair < Base
764
+ def self.load_members
765
+ object_of :name, String
766
+ object_of :value, String
767
+ end
768
+ end
769
+
770
+ class ItemList < Base
771
+ def self.load_members
772
+ array_of :items, Item
773
+ object_of :shipping_address, ShippingAddress
774
+ object_of :shipping_method, String
775
+ object_of :shipping_phone_number, String
776
+ end
777
+ end
778
+
779
+ class RelatedResources < Base
780
+ def self.load_members
781
+ object_of :sale, Sale
782
+ object_of :authorization, Authorization
783
+ object_of :order, Order
784
+ object_of :capture, Capture
785
+ object_of :refund, Refund
786
+ end
787
+ end
788
+
789
+ class Sale < Base
790
+ def self.load_members
791
+ object_of :id, String
792
+ object_of :purchase_unit_reference_id, String
793
+ object_of :amount, Amount
794
+ object_of :payment_mode, String
795
+ object_of :state, String
796
+ object_of :reason_code, String
797
+ object_of :protection_eligibility, String
798
+ object_of :protection_eligibility_type, String
799
+ object_of :clearing_time, String
800
+ object_of :recipient_fund_status, String
801
+ object_of :payment_hold_status, String
802
+ object_of :hold_reason, String
803
+ object_of :transaction_fee, Currency
804
+ object_of :receivable_amount, Currency
805
+ object_of :exchange_rate, String
806
+ object_of :fmf_details, FmfDetails
807
+ object_of :receipt_id, String
808
+ object_of :parent_payment, String
809
+ object_of :create_time, String
810
+ object_of :update_time, String
811
+ array_of :links, Links
812
+ object_of :billing_agreement_id, String
813
+ object_of :payment_hold_reasons, String
814
+ object_of :processor_response, ProcessorResponse
815
+ end
816
+
817
+ include RequestDataType
818
+
819
+ class << self
820
+ def find(resource_id)
821
+ raise ArgumentError.new("id required") if resource_id.to_s.strip.empty?
822
+ path = "v1/payments/sale/#{resource_id}"
823
+ self.new(api.get(path))
824
+ end
825
+ end
826
+
827
+ def refund(refund)
828
+ refund = Refund.new(refund) unless refund.is_a? Refund
829
+ path = "v1/payments/sale/#{self.id}/refund"
830
+ response = api.post(path, refund.to_hash, http_header)
831
+ Refund.new(response)
832
+ end
833
+
834
+ def refund_request(refund_request)
835
+ refund_request = RefundRequest.new(refund_request) unless refund_request.is_a? RefundRequest
836
+ path = "v1/payments/sale/#{self.id}/refund"
837
+ response = api.post(path, refund_request.to_hash, http_header)
838
+ DetailedRefund.new(response)
839
+ end
840
+
841
+ end
842
+
843
+ class AnyOf < Base
844
+ def self.load_members
845
+ object_of :refund, Refund
846
+ end
847
+ end
848
+
849
+ class Authorization < Base
850
+ def self.load_members
851
+ object_of :id, String
852
+ object_of :amount, Amount
853
+ object_of :payment_mode, String
854
+ object_of :state, String
855
+ object_of :reason_code, String
856
+ object_of :protection_eligibility, String
857
+ object_of :protection_eligibility_type, String
858
+ object_of :fmf_details, FmfDetails
859
+ object_of :parent_payment, String
860
+ object_of :valid_until, String
861
+ object_of :create_time, String
862
+ object_of :update_time, String
863
+ object_of :reference_id, String
864
+ object_of :receipt_id, String
865
+ array_of :links, Links
866
+ end
867
+
868
+ include RequestDataType
869
+
870
+ class << self
871
+ def find(resource_id)
872
+ raise ArgumentError.new("id required") if resource_id.to_s.strip.empty?
873
+ path = "v1/payments/authorization/#{resource_id}"
874
+ self.new(api.get(path))
875
+ end
876
+ end
877
+
878
+ def capture(capture)
879
+ capture = Capture.new(capture) unless capture.is_a? Capture
880
+ path = "v1/payments/authorization/#{self.id}/capture"
881
+ response = api.post(path, capture.to_hash, http_header)
882
+ Capture.new(response)
883
+ end
884
+
885
+ def void()
886
+ path = "v1/payments/authorization/#{self.id}/void"
887
+ response = api.post(path, {}, http_header)
888
+ self.merge!(response)
889
+ success?
890
+ end
891
+
892
+ def reauthorize()
893
+ path = "v1/payments/authorization/#{self.id}/reauthorize"
894
+ response = api.post(path, self.to_hash, http_header)
895
+ self.merge!(response)
896
+ success?
897
+ end
898
+
899
+ raise_on_api_error :capture, :void, :reauthorize
900
+ end
901
+
902
+ class Order < Base
903
+ def self.load_members
904
+ object_of :id, String
905
+ object_of :purchase_unit_reference_id, String # Deprecated - use :reference_id instead
906
+ object_of :reference_id, String
907
+ object_of :amount, Amount
908
+ object_of :payment_mode, String
909
+ object_of :state, String
910
+ object_of :reason_code, String
911
+ object_of :pending_reason, String
912
+ object_of :protection_eligibility, String
913
+ object_of :protection_eligibility_type, String
914
+ object_of :parent_payment, String
915
+ object_of :fmf_details, FmfDetails
916
+ object_of :create_time, String
917
+ object_of :update_time, String
918
+ array_of :links, Links
919
+ end
920
+
921
+ include RequestDataType
922
+
923
+ class << self
924
+ def find(resource_id)
925
+ raise ArgumentError.new("id required") if resource_id.to_s.strip.empty?
926
+ path = "v1/payments/orders/#{resource_id}"
927
+ self.new(api.get(path))
928
+ end
929
+ end
930
+
931
+ def capture(capture)
932
+ capture = Capture.new(capture) unless capture.is_a? Capture
933
+ path = "v1/payments/orders/#{self.id}/capture"
934
+ response = api.post(path, capture.to_hash, http_header)
935
+ Capture.new(response)
936
+ end
937
+
938
+ def void()
939
+ path = "v1/payments/orders/#{self.id}/do-void"
940
+ response = api.post(path, {}, http_header)
941
+ self.merge!(response)
942
+ success?
943
+ end
944
+
945
+ def authorize()
946
+ path = "v1/payments/orders/#{self.id}/authorize"
947
+ response = api.post(path, self.to_hash, http_header)
948
+ Authorization.new(response)
949
+ end
950
+
951
+ raise_on_api_error :capture, :void, :authorize
952
+ end
953
+
954
+ class Capture < Base
955
+ def self.load_members
956
+ object_of :id, String
957
+ object_of :amount, Amount
958
+ object_of :is_final_capture, Boolean
959
+ object_of :state, String
960
+ object_of :reason_code, String
961
+ object_of :parent_payment, String
962
+ object_of :invoice_number, String
963
+ object_of :transaction_fee, Currency
964
+ object_of :create_time, String
965
+ object_of :update_time, String
966
+ array_of :links, Links
967
+ end
968
+
969
+ include RequestDataType
970
+
971
+ class << self
972
+ def find(resource_id)
973
+ raise ArgumentError.new("id required") if resource_id.to_s.strip.empty?
974
+ path = "v1/payments/capture/#{resource_id}"
975
+ self.new(api.get(path))
976
+ end
977
+ end
978
+
979
+ # Deprecated - please use refund_request
980
+ def refund(refund)
981
+ refund = Refund.new(refund) unless refund.is_a? Refund
982
+ path = "v1/payments/capture/#{self.id}/refund"
983
+ response = api.post(path, refund.to_hash, http_header)
984
+ Refund.new(response)
985
+ end
986
+
987
+ def refund_request(refund_request)
988
+ refund_request = RefundRequest.new(refund_request) unless refund_request.is_a? RefundRequest
989
+ path = "v1/payments/capture/#{self.id}/refund"
990
+ response = api.post(path, refund_request.to_hash, http_header)
991
+ DetailedRefund.new(response)
992
+ end
993
+ end
994
+
995
+ class Refund < Base
996
+ def self.load_members
997
+ object_of :id, String
998
+ object_of :amount, Amount
999
+ object_of :state, String
1000
+ object_of :reason, String
1001
+ object_of :invoice_number, String
1002
+ object_of :sale_id, String
1003
+ object_of :capture_id, String
1004
+ object_of :parent_payment, String
1005
+ object_of :description, String
1006
+ object_of :create_time, String
1007
+ object_of :update_time, String
1008
+ object_of :reason_code, String
1009
+ array_of :links, Links
1010
+ end
1011
+
1012
+ include RequestDataType
1013
+
1014
+ class << self
1015
+ def find(resource_id)
1016
+ raise ArgumentError.new("id required") if resource_id.to_s.strip.empty?
1017
+ path = "v1/payments/refund/#{resource_id}"
1018
+ self.new(api.get(path))
1019
+ end
1020
+ end
1021
+ end
1022
+
1023
+ class RefundRequest < Base
1024
+ def self.load_members
1025
+ object_of :amount, Amount
1026
+ object_of :description, String
1027
+ object_of :refund_type, String
1028
+ object_of :refund_source, String
1029
+ object_of :reason, String
1030
+ object_of :invoice_number, String
1031
+ object_of :refund_advice, Boolean
1032
+ object_of :is_non_platform_transaction, String
1033
+ end
1034
+ end
1035
+
1036
+ class DetailedRefund < Refund
1037
+ def self.load_members
1038
+ object_of :custom, String
1039
+ object_of :invoice_number, String
1040
+ object_of :refund_to_payer, Currency
1041
+ array_of :refund_to_external_funding, ExternalFunding
1042
+ object_of :refund_from_transaction_fee, Currency
1043
+ object_of :refund_from_received_amount, Currency
1044
+ object_of :total_refunded_amount, Currency
1045
+ end
1046
+ end
1047
+
1048
+ class Error < Base
1049
+ def self.load_members
1050
+ object_of :name, String
1051
+ object_of :debug_id, String
1052
+ object_of :message, String
1053
+ object_of :code, String
1054
+ object_of :information_link, String
1055
+ array_of :details, ErrorDetails
1056
+ array_of :links, Links
1057
+ end
1058
+ end
1059
+
1060
+ class ErrorDetails < Base
1061
+ def self.load_members
1062
+ object_of :field, String
1063
+ object_of :issue, String
1064
+ object_of :code, String
1065
+ end
1066
+ end
1067
+
1068
+ class FmfDetails < Base
1069
+ def self.load_members
1070
+ object_of :filter_type, String
1071
+ object_of :filter_id, String
1072
+ object_of :name, String
1073
+ object_of :description, String
1074
+ end
1075
+ end
1076
+
1077
+ class PaymentInstruction < Base
1078
+ def self.load_members
1079
+ object_of :reference_number, String
1080
+ object_of :instruction_type, String
1081
+ object_of :recipient_banking_instruction, RecipientBankingInstruction
1082
+ object_of :amount, Currency
1083
+ object_of :payment_due_date, String
1084
+ object_of :note, String
1085
+ array_of :links, Links
1086
+ end
1087
+
1088
+ include RequestDataType
1089
+
1090
+ class << self
1091
+ def find(resource_id)
1092
+ raise ArgumentError.new("id required") if resource_id.to_s.strip.empty?
1093
+ path = "v1/payments/payments/payment/#{resource_id}/payment-instruction"
1094
+ self.new(api.get(path))
1095
+ end
1096
+ end
1097
+ end
1098
+
1099
+ class RecipientBankingInstruction < Base
1100
+ def self.load_members
1101
+ object_of :bank_name, String
1102
+ object_of :account_holder_name, String
1103
+ object_of :account_number, String
1104
+ object_of :routing_number, String
1105
+ object_of :international_bank_account_number, String
1106
+ object_of :bank_identifier_code, String
1107
+ end
1108
+ end
1109
+
1110
+ class RedirectUrls < Base
1111
+ def self.load_members
1112
+ object_of :return_url, String
1113
+ object_of :cancel_url, String
1114
+ end
1115
+ end
1116
+
1117
+ class Patch < Base
1118
+ def self.load_members
1119
+ object_of :op, String
1120
+ object_of :path, String
1121
+ object_of :value, Object
1122
+ object_of :from, String
1123
+ end
1124
+ end
1125
+
1126
+ class PatchRequest < Base
1127
+ def self.load_members
1128
+ object_of :op, String
1129
+ object_of :path, String
1130
+ object_of :value, Object
1131
+ object_of :from, String
1132
+ end
1133
+
1134
+ end
1135
+ class PaymentExecution < Base
1136
+ def self.load_members
1137
+ object_of :payer_id, String
1138
+ object_of :carrier_account_id, String
1139
+ array_of :transactions, CartBase
1140
+ end
1141
+ end
1142
+
1143
+ class PaymentHistory < Base
1144
+ def self.load_members
1145
+ array_of :payments, Payment
1146
+ object_of :count, Integer
1147
+ object_of :next_id, String
1148
+ end
1149
+ end
1150
+
1151
+ class CreditCardList < Base
1152
+ def self.load_members
1153
+ array_of :items, CreditCard
1154
+ object_of :total_items, Integer
1155
+ object_of :total_pages, Integer
1156
+ array_of :links, Links
1157
+ end
1158
+
1159
+ class << self
1160
+ def list(options={})
1161
+ # for entire list of filter options, see https://developer.paypal.com/webapps/developer/docs/api/#list-credit-card-resources
1162
+ path = "v1/vault/credit-cards"
1163
+ response = api.get(path, options)
1164
+ self.new(response)
1165
+ end
1166
+ end
1167
+ end
1168
+
1169
+ class BankAccountsList < Base
1170
+ def self.load_members
1171
+ array_of :bank_accounts, BankAccount
1172
+ object_of :count, Integer
1173
+ object_of :next_id, String
1174
+ end
1175
+ end
1176
+
1177
+ class InvoiceAmountWrapper < Base
1178
+ def self.load_members
1179
+ object_of :paypal, Currency
1180
+ end
1181
+ end
1182
+
1183
+ class Invoice < Base
1184
+ def self.load_members
1185
+ object_of :id, String
1186
+ object_of :number, String
1187
+ object_of :template_id, String
1188
+ object_of :uri, String
1189
+ object_of :status, String
1190
+ object_of :merchant_info, MerchantInfo
1191
+ array_of :billing_info, BillingInfo
1192
+ array_of :cc_info, Participant
1193
+ object_of :shipping_info, ShippingInfo
1194
+ array_of :items, InvoiceItem
1195
+ object_of :invoice_date, String
1196
+ object_of :payment_term, PaymentTerm
1197
+ object_of :reference, String
1198
+ object_of :discount, Cost
1199
+ object_of :shipping_cost, ShippingCost
1200
+ object_of :custom, CustomAmount
1201
+ object_of :allow_partial_payment, Boolean
1202
+ object_of :minimum_amount_due, Currency
1203
+ object_of :tax_calculated_after_discount, Boolean
1204
+ object_of :tax_inclusive, Boolean
1205
+ object_of :terms, String
1206
+ object_of :note, String
1207
+ object_of :merchant_memo, String
1208
+ object_of :logo_url, String
1209
+ object_of :total_amount, Currency
1210
+ array_of :payments, PaymentDetail
1211
+ array_of :refunds, RefundDetail
1212
+ object_of :metadata, Metadata
1213
+ object_of :additional_data, String
1214
+ object_of :gratuity, Currency
1215
+ object_of :paid_amount, PaymentSummary
1216
+ object_of :refunded_amount, PaymentSummary
1217
+ array_of :attachments, FileAttachment
1218
+ array_of :links, Links
1219
+ end
1220
+
1221
+ include RequestDataType
1222
+
1223
+ def create()
1224
+ path = "v1/invoicing/invoices"
1225
+ response = api.post(path, self.to_hash, http_header)
1226
+ self.merge!(response)
1227
+ success?
1228
+ end
1229
+
1230
+ def send_invoice()
1231
+ path = "v1/invoicing/invoices/#{self.id}/send"
1232
+ response = api.post(path, {}, http_header)
1233
+ self.merge!(response)
1234
+ success?
1235
+ end
1236
+
1237
+ def remind(notification)
1238
+ notification = Notification.new(notification) unless notification.is_a? Notification
1239
+ path = "v1/invoicing/invoices/#{self.id}/remind"
1240
+ response = api.post(path, notification.to_hash, http_header)
1241
+ self.merge!(response)
1242
+ success?
1243
+ end
1244
+
1245
+ def cancel(cancel_notification)
1246
+ cancel_notification = CancelNotification.new(cancel_notification) unless cancel_notification.is_a? CancelNotification
1247
+ path = "v1/invoicing/invoices/#{self.id}/cancel"
1248
+ response = api.post(path, cancel_notification.to_hash, http_header)
1249
+ self.merge!(response)
1250
+ success?
1251
+ end
1252
+
1253
+ def record_payment(payment_detail)
1254
+ payment_detail = PaymentDetail.new(payment_detail) unless payment_detail.is_a? PaymentDetail
1255
+ path = "v1/invoicing/invoices/#{self.id}/record-payment"
1256
+ response = api.post(path, payment_detail.to_hash, http_header)
1257
+ self.merge!(response)
1258
+ success?
1259
+ end
1260
+
1261
+ def record_refund(refund_detail)
1262
+ refund_detail = RefundDetail.new(refund_detail) unless refund_detail.is_a? RefundDetail
1263
+ path = "v1/invoicing/invoices/#{self.id}/record-refund"
1264
+ response = api.post(path, refund_detail.to_hash, http_header)
1265
+ self.merge!(response)
1266
+ success?
1267
+ end
1268
+
1269
+ def update()
1270
+ path = "v1/invoicing/invoices/#{self.id}"
1271
+ response = api.put(path, self.to_hash, http_header)
1272
+ self.merge!(response)
1273
+ success?
1274
+ end
1275
+
1276
+ def delete()
1277
+ path = "v1/invoicing/invoices/#{self.id}"
1278
+ response = api.delete(path, {})
1279
+ self.merge!(response)
1280
+ success?
1281
+ end
1282
+
1283
+ raise_on_api_error :create, :send_invoice, :remind, :cancel,
1284
+ :record_payment, :record_refund, :update, :delete
1285
+
1286
+ #
1287
+ class << self
1288
+ def search(options, access_token = nil)
1289
+ path = "v1/invoicing/search"
1290
+ api.token = access_token unless access_token.nil?
1291
+ response = api.post(path, options)
1292
+ Invoices.new(response)
1293
+ end
1294
+
1295
+ def find(resource_id, access_token = nil)
1296
+ raise ArgumentError.new("id required") if resource_id.to_s.strip.empty?
1297
+ path = "v1/invoicing/invoices/#{resource_id}"
1298
+ api.token = access_token unless access_token.nil?
1299
+ self.new(api.get(path))
1300
+ end
1301
+
1302
+ def get_all(options = {}, access_token = nil)
1303
+ path = "v1/invoicing/invoices/"
1304
+ api.token = access_token unless access_token.nil?
1305
+ Invoices.new(api.get(path, options))
1306
+ end
1307
+
1308
+ def qr_code(options = {})
1309
+ path = "v1/invoicing/invoices/{invoice_id}/qr-code"
1310
+ object.new(api.get(path, options))
1311
+ end
1312
+
1313
+ def self.generate_number(options)
1314
+ path = "v1/invoicing/invoices/next-invoice-number"
1315
+ response = api.post(path, options)
1316
+ object.new(response)
1317
+ end
1318
+ end
1319
+ end
1320
+
1321
+ class Participant < Base
1322
+ def self.load_members
1323
+ object_of :email, String
1324
+ object_of :first_name, String
1325
+ object_of :last_name, String
1326
+ object_of :business_name, String
1327
+ object_of :phone, Phone
1328
+ object_of :fax, Phone
1329
+ object_of :website, String
1330
+ object_of :additional_info, String
1331
+ object_of :address, Address
1332
+ end
1333
+ end
1334
+
1335
+ class Template < Base
1336
+
1337
+ def self.load_members
1338
+ object_of :template_id, String
1339
+ object_of :name, String
1340
+ object_of :default, Boolean
1341
+ object_of :template_data, TemplateData
1342
+ array_of :settings, TemplateSettings
1343
+ object_of :unit_of_measure, String
1344
+ object_of :custom, Boolean
1345
+ array_of :links, Links
1346
+ end
1347
+
1348
+ include RequestDataType
1349
+
1350
+ def delete()
1351
+ path = "v1/invoicing/templates/#{self.template_id}"
1352
+ response = api.delete(path, {})
1353
+ self.merge!(response)
1354
+ success?
1355
+ end
1356
+
1357
+ def update()
1358
+ path = "v1/invoicing/templates/#{self.template_id}"
1359
+ response = api.put(path, self.to_hash, http_header)
1360
+ self.merge!(response)
1361
+ Template.new(response)
1362
+ end
1363
+
1364
+ def create()
1365
+ path = "v1/invoicing/templates"
1366
+ response = api.post(path, self.to_hash, http_header)
1367
+ self.merge!(response)
1368
+ Template.new(response)
1369
+ end
1370
+
1371
+ class << self
1372
+ def get(template_id, options = {})
1373
+ raise ArgumentError.new("template_id required") if template_id.to_s.strip.empty?
1374
+ path = "v1/invoicing/templates/#{template_id}"
1375
+ self.new(api.get(path, options))
1376
+ end
1377
+ end
1378
+ end
1379
+
1380
+ class TemplateData < Base
1381
+
1382
+ def self.load_members
1383
+ object_of :merchant_info, MerchantInfo
1384
+ array_of :billing_info, BillingInfo
1385
+ array_of :cc_info, String
1386
+ object_of :shipping_info, ShippingInfo
1387
+ array_of :items, InvoiceItem
1388
+ object_of :payment_term, PaymentTerm
1389
+ object_of :reference, String
1390
+ object_of :discount, Cost
1391
+ object_of :shipping_cost, ShippingCost
1392
+ object_of :custom, CustomAmount
1393
+ object_of :allow_partial_payment, Boolean
1394
+ object_of :minimum_amount_due, Currency
1395
+ object_of :tax_calculated_after_discount, Boolean
1396
+ object_of :tax_inclusive, Boolean
1397
+ object_of :terms, String
1398
+ object_of :note, String
1399
+ object_of :merchant_memo, String
1400
+ object_of :logo_url, String
1401
+ object_of :total_amount, Currency
1402
+ array_of :attachments, FileAttachment
1403
+ end
1404
+
1405
+ end
1406
+
1407
+ class TemplateSettings < Base
1408
+
1409
+ def self.load_members
1410
+ object_of :field_name, String
1411
+ object_of :display_preference, TemplateSettingsMetadata
1412
+ end
1413
+ end
1414
+
1415
+ class TemplateSettingsMetadata < Base
1416
+
1417
+ def self.load_members
1418
+ object_of :hidden, Boolean
1419
+ end
1420
+
1421
+ end
1422
+
1423
+ class PaymentSummary < Base
1424
+ def self.load_members
1425
+ object_of :paypal, Currency
1426
+ object_of :other, Currency
1427
+ end
1428
+ end
1429
+ class FileAttachment < Base
1430
+
1431
+ def self.load_members
1432
+ object_of :name, String
1433
+ object_of :url, String
1434
+ end
1435
+
1436
+ end
1437
+ class Templates < Base
1438
+
1439
+ def self.load_members
1440
+ array_of :addresses, Address
1441
+ array_of :emails, String
1442
+ array_of :phones, Phone
1443
+ array_of :templates, Template
1444
+ array_of :links, Links
1445
+ end
1446
+
1447
+ include RequestDataType
1448
+
1449
+ class << self
1450
+ def get_all(options = {})
1451
+ path = "v1/invoicing/templates/"
1452
+ Templates.new(api.get(path, options))
1453
+ end
1454
+ end
1455
+ end
1456
+
1457
+ class WebhooksEventType < Base
1458
+ def self.load_members
1459
+ array_of :event_types, EventType
1460
+ end
1461
+
1462
+ include RequestDataType
1463
+
1464
+ class << self
1465
+ def all(options = {})
1466
+ path = "v1/notifications/webhooks-event-types"
1467
+ EventTypeList.new(api.get(path, options))
1468
+ end
1469
+ end
1470
+ end
1471
+
1472
+ class EventTypeList < Base
1473
+ def self.load_members
1474
+ array_of :event_types, EventType
1475
+ end
1476
+ end
1477
+
1478
+ class WebhookList < Base
1479
+ def self.load_members
1480
+ array_of :webhooks, Webhook
1481
+ end
1482
+ end
1483
+
1484
+ class EventType < Base
1485
+ def self.load_members
1486
+ object_of :name, String
1487
+ object_of :description, String
1488
+ object_of :status, String
1489
+ end
1490
+ end
1491
+
1492
+ class WebhookEventList < Base
1493
+ def self.load_members
1494
+ object_of :count, Integer
1495
+ array_of :events, WebhookEvent
1496
+ array_of :links, Links
1497
+ end
1498
+ end
1499
+
1500
+ class WebhookEvent < Base
1501
+ def self.load_members
1502
+ object_of :id, String
1503
+ object_of :create_time, String
1504
+ object_of :resource_type, String
1505
+ object_of :event_version, String
1506
+ object_of :event_type, String
1507
+ object_of :summary, String
1508
+ object_of :status, String
1509
+ object_of :resource, Hash
1510
+ array_of :links, Links
1511
+ end
1512
+
1513
+ def resend()
1514
+ path = "v1/notifications/webhooks-events/#{self.id}/resend"
1515
+ WebhookEvent.new(api.post(path))
1516
+ end
1517
+
1518
+ def get_resource()
1519
+ webhook_resource_type = self.resource_type
1520
+ resource_class = self.class.get_resource_class(webhook_resource_type)
1521
+ if resource_class
1522
+ return Object::const_get(resource_class).new(self.resource)
1523
+ else
1524
+ return self.resource
1525
+ end
1526
+ end
1527
+
1528
+ include RequestDataType
1529
+
1530
+ class << self
1531
+
1532
+ def get_cert(cert_url)
1533
+ data = Net::HTTP.get_response(URI.parse(cert_url))
1534
+ cert = OpenSSL::X509::Certificate.new data.body
1535
+ end
1536
+
1537
+ def get_cert_chain()
1538
+ root_cert = File.expand_path(File.join(File.dirname(__FILE__), '../../../data/DigiCertHighAssuranceEVRootCA.pem'))
1539
+ intermediate_cert = File.expand_path(File.join(File.dirname(__FILE__), '../../../data/DigiCertSHA2ExtendedValidationServerCA.pem'))
1540
+
1541
+ cert_store = OpenSSL::X509::Store.new
1542
+ cert_store.add_file(root_cert)
1543
+ cert_store.add_file(intermediate_cert)
1544
+
1545
+ cert_store
1546
+ end
1547
+
1548
+ def get_expected_sig(transmission_id, timestamp, webhook_id, event_body)
1549
+ utf8_encoded_event_body = event_body.force_encoding("UTF-8")
1550
+ crc = Zlib::crc32(utf8_encoded_event_body).to_s
1551
+ transmission_id + "|" + timestamp + "|" + webhook_id + "|" + crc
1552
+ end
1553
+
1554
+ def verify_common_name(cert)
1555
+ common_name = cert.subject.to_a.select{|name, _, _| name == 'CN' }.first[1]
1556
+
1557
+ common_name.start_with?("messageverificationcerts.") && common_name.end_with?(".paypal.com")
1558
+ end
1559
+
1560
+ def verify_signature(transmission_id, timestamp, webhook_id, event_body, cert, actual_sig_encoded, algo)
1561
+ expected_sig = get_expected_sig(transmission_id, timestamp, webhook_id, event_body)
1562
+
1563
+ digest = OpenSSL::Digest.new(algo)
1564
+ digest.update(expected_sig)
1565
+ actual_sig = Base64.decode64(actual_sig_encoded).force_encoding('UTF-8')
1566
+
1567
+ cert.public_key.verify(digest, actual_sig, expected_sig)
1568
+ end
1569
+
1570
+ def verify_expiration(cert)
1571
+ cert.not_after >= Time.now
1572
+ end
1573
+
1574
+ def verify_cert_chain(cert_store, cert)
1575
+ cert_store.verify(cert)
1576
+ end
1577
+
1578
+ def verify_cert(cert)
1579
+ cert_store = get_cert_chain()
1580
+
1581
+ verify_cert_chain(cert_store, cert) && verify_common_name(cert) && verify_expiration(cert)
1582
+ end
1583
+
1584
+ def verify(transmission_id, timestamp, webhook_id, event_body, cert_url, sig, algo='sha256')
1585
+ cert = get_cert(cert_url)
1586
+ verify_signature(transmission_id, timestamp, webhook_id, event_body, cert, sig, algo) && verify_cert(cert)
1587
+ end
1588
+
1589
+ def get_resource_class(name)
1590
+ class_array = PayPal::SDK::REST.constants.select {|c| Class === PayPal::SDK::REST.const_get(c)}
1591
+ class_array.each do |classname|
1592
+ if (classname.to_s.downcase == name.downcase)
1593
+ return classname
1594
+ end
1595
+ end
1596
+ end
1597
+
1598
+ def search(page_size, start_time, end_time)
1599
+ path = "v1/notifications/webhooks-events"
1600
+ options = { :page_size => page_size, :start_time => start_time, :end_time => end_time }
1601
+ WebhookEventList.new(api.get(path, options))
1602
+ end
1603
+
1604
+ def get(webhook_event_id)
1605
+ WebhookEvent.find(webhook_event_id)
1606
+ end
1607
+
1608
+ def find(resource_id)
1609
+ raise ArgumentError.new("webhook_event_id required") if resource_id.to_s.strip.empty?
1610
+ path = "v1/notifications/webhooks-events/#{resource_id}"
1611
+ self.new(api.get(path))
1612
+ end
1613
+
1614
+ def all(options = {})
1615
+ path = "v1/notifications/webhooks-events"
1616
+ WebhookEventList.new(api.get(path, options))
1617
+ end
1618
+ end
1619
+ end
1620
+
1621
+ class Webhook < Base
1622
+
1623
+ def self.load_members
1624
+ object_of :id, String
1625
+ object_of :url, String
1626
+ array_of :event_types, EventType
1627
+ array_of :links, Links
1628
+ end
1629
+
1630
+ include RequestDataType
1631
+
1632
+ def create()
1633
+ path = "v1/notifications/webhooks"
1634
+ response = api.post(path, self.to_hash, http_header)
1635
+ self.merge!(response)
1636
+ Webhook.new(response)
1637
+ end
1638
+
1639
+ def update(patch)
1640
+ patch = Patch.new(patch) unless patch.is_a? Patch
1641
+ patch_request = Array.new(1, patch.to_hash)
1642
+ path = "v1/notifications/webhooks/#{self.id}"
1643
+ response = api.patch(path, patch_request, http_header)
1644
+ self.merge!(response)
1645
+ success?
1646
+ end
1647
+
1648
+ def delete()
1649
+ path = "v1/notifications/webhooks/#{self.id}"
1650
+ response = api.delete(path, {})
1651
+ self.merge!(response)
1652
+ success?
1653
+ end
1654
+
1655
+ raise_on_api_error :update, :delete
1656
+
1657
+ class << self
1658
+ def get(webhook_id)
1659
+ raise ArgumentError.new("webhook_id required") if webhook_id.to_s.strip.empty?
1660
+ path = "v1/notifications/webhooks/#{webhook_id}"
1661
+ Webhook.new(api.get(path))
1662
+ end
1663
+
1664
+ def get_event_types(webhook_id)
1665
+ raise ArgumentError.new("webhook_id required") if webhook_id.to_s.strip.empty?
1666
+ path = "v1/notifications/webhooks/#{webhook_id}/event-types"
1667
+ EventTypeList.new(api.get(path))
1668
+ end
1669
+
1670
+ def all(options={})
1671
+ path = "v1/notifications/webhooks"
1672
+ WebhookList.new(api.get(path))
1673
+ end
1674
+
1675
+ def simulate_event(webhook_id, url, event_type)
1676
+ path = "v1/notifications/simulate-event"
1677
+ options = { :webhook_id => webhook_id, :url => url, :event_type => event_type }
1678
+ response = api.post(path, options)
1679
+ WebhookEvent.new(response)
1680
+ end
1681
+ end
1682
+ end
1683
+
1684
+ class Payout < Base
1685
+
1686
+ def self.load_members
1687
+ object_of :sender_batch_header, PayoutSenderBatchHeader
1688
+ array_of :items, PayoutItem
1689
+ end
1690
+
1691
+ include RequestDataType
1692
+
1693
+ def create(sync_mode = false)
1694
+ path = "v1/payments/payouts"
1695
+ options = { :sync_mode => sync_mode }
1696
+ response = api.post(path, self.to_hash, http_header, options)
1697
+ PayoutBatch.new(response)
1698
+ end
1699
+
1700
+ class << self
1701
+ def get(payout_batch_id, options = {})
1702
+ raise ArgumentError.new("id required") if payout_batch_id.to_s.strip.empty?
1703
+ path = "v1/payments/payouts/#{payout_batch_id}"
1704
+ PayoutBatch.new(api.get(path, options))
1705
+ end
1706
+ end
1707
+ end
1708
+ class PayoutItem < Base
1709
+
1710
+ def self.load_members
1711
+ object_of :recipient_type, String
1712
+ object_of :amount, Currency
1713
+ object_of :note, String
1714
+ object_of :receiver, String
1715
+ object_of :sender_item_id, String
1716
+ object_of :recipient_wallet, String
1717
+ end
1718
+
1719
+ include RequestDataType
1720
+
1721
+ class << self
1722
+ def get(payout_item_id)
1723
+ raise ArgumentError.new("payout_item_id required") if payout_item_id.to_s.strip.empty?
1724
+ path = "v1/payments/payouts-item/#{payout_item_id}"
1725
+ PayoutItemDetails.new(api.get(path))
1726
+ end
1727
+ def cancel(payout_item_id)
1728
+ raise ArgumentError.new("payout_item_id required") if payout_item_id.to_s.strip.empty?
1729
+ path = "v1/payments/payouts-item/#{payout_item_id}/cancel"
1730
+ PayoutItemDetails.new(api.post(path))
1731
+ end
1732
+ end
1733
+
1734
+ end
1735
+ class PayoutItemDetails < Base
1736
+
1737
+ def self.load_members
1738
+ object_of :payout_item_id, String
1739
+ object_of :transaction_id, String
1740
+ object_of :transaction_status, String
1741
+ object_of :payout_item_fee, Currency
1742
+ object_of :payout_batch_id, String
1743
+ object_of :sender_batch_id, String
1744
+ object_of :payout_item, PayoutItem
1745
+ object_of :time_processed, String
1746
+ object_of :errors, Error
1747
+ array_of :links, Links
1748
+ end
1749
+
1750
+ end
1751
+ class PayoutBatch < Base
1752
+
1753
+ def self.load_members
1754
+ object_of :batch_header, PayoutBatchHeader
1755
+ array_of :items, PayoutItemDetails
1756
+ array_of :links, Links
1757
+ end
1758
+
1759
+ end
1760
+ class PayoutBatchHeader < Base
1761
+
1762
+ def self.load_members
1763
+ object_of :payout_batch_id, String
1764
+ object_of :batch_status, String
1765
+ object_of :time_created, String
1766
+ object_of :time_completed, String
1767
+ object_of :sender_batch_header, PayoutSenderBatchHeader
1768
+ object_of :amount, Currency
1769
+ object_of :fees, Currency
1770
+ object_of :errors, Error
1771
+ end
1772
+
1773
+ end
1774
+ class PayoutSenderBatchHeader < Base
1775
+
1776
+ def self.load_members
1777
+ object_of :sender_batch_id, String
1778
+ object_of :email_subject, String
1779
+ object_of :recipient_type, String
1780
+ end
1781
+
1782
+ end
1783
+ class Invoices < Base
1784
+ def self.load_members
1785
+ object_of :total_count, Integer
1786
+ array_of :invoices, Invoice
1787
+ end
1788
+ end
1789
+
1790
+ class InvoiceItem < Base
1791
+ def self.load_members
1792
+ object_of :name, String
1793
+ object_of :description, String
1794
+ object_of :quantity, Number
1795
+ object_of :unit_price, Currency
1796
+ object_of :tax, Tax
1797
+ object_of :date, String
1798
+ object_of :discount, Cost
1799
+ object_of :image_url, String
1800
+ object_of :unit_of_measure, String
1801
+ end
1802
+ end
1803
+
1804
+ class MerchantInfo < Base
1805
+ def self.load_members
1806
+ object_of :email, String
1807
+ object_of :first_name, String
1808
+ object_of :last_name, String
1809
+ object_of :address, Address
1810
+ object_of :business_name, String
1811
+ object_of :phone, Phone
1812
+ object_of :fax, Phone
1813
+ object_of :website, String
1814
+ object_of :tax_id, String
1815
+ object_of :additional_info_label, String
1816
+ object_of :additional_info, String
1817
+ end
1818
+ end
1819
+
1820
+ class BillingInfo < Base
1821
+ def self.load_members
1822
+ object_of :email, String
1823
+ object_of :first_name, String
1824
+ object_of :last_name, String
1825
+ object_of :business_name, String
1826
+ object_of :address, InvoiceAddress
1827
+ object_of :language, String
1828
+ object_of :additional_info, String
1829
+ object_of :notification_channel, String
1830
+ object_of :phone, Phone
1831
+
1832
+ define_method "address=" do |value|
1833
+ if value.is_a?(Address)
1834
+ value = value.to_hash
1835
+ end
1836
+ object = convert_object(value, InvoiceAddress)
1837
+ instance_variable_set("@address", object)
1838
+ end
1839
+
1840
+ define_method "address" do |&block|
1841
+ default_value = PayPal::SDK::Core::Util::OrderedHash.new
1842
+ value = instance_variable_get("@address") || ( default_value && (send("address=", default_value)))
1843
+ value = convert_object(value.to_hash, Address)
1844
+ value
1845
+ end
1846
+
1847
+ define_method "invoice_address=" do |value|
1848
+ object = convert_object(value, InvoiceAddress)
1849
+ instance_variable_set("@address", object)
1850
+ end
1851
+
1852
+ define_method "invoice_address" do |&block|
1853
+ default_value = PayPal::SDK::Core::Util::OrderedHash.new
1854
+ value = instance_variable_get("@address") || ( default_value && (send("address=", default_value)))
1855
+ value
1856
+ end
1857
+ end
1858
+ end
1859
+
1860
+ class ShippingInfo < Base
1861
+ def self.load_members
1862
+ object_of :first_name, String
1863
+ object_of :last_name, String
1864
+ object_of :business_name, String
1865
+ object_of :address, InvoiceAddress
1866
+ object_of :email, String
1867
+
1868
+ define_method "address=" do |value|
1869
+ if value.is_a?(Address)
1870
+ value = value.to_hash
1871
+ end
1872
+ object = convert_object(value, InvoiceAddress)
1873
+ instance_variable_set("@address", object)
1874
+ end
1875
+
1876
+ define_method "address" do |&block|
1877
+ default_value = PayPal::SDK::Core::Util::OrderedHash.new
1878
+ value = instance_variable_get("@address") || ( default_value && (send("address=", default_value)))
1879
+ value = convert_object(value.to_hash, Address)
1880
+ value
1881
+ end
1882
+
1883
+ define_method "invoice_address=" do |value|
1884
+ object = convert_object(value, InvoiceAddress)
1885
+ instance_variable_set("@address", object)
1886
+ end
1887
+
1888
+ define_method "invoice_address" do |&block|
1889
+ default_value = PayPal::SDK::Core::Util::OrderedHash.new
1890
+ value = instance_variable_get("@address") || ( default_value && (send("address=", default_value)))
1891
+ value
1892
+ end
1893
+ end
1894
+ end
1895
+
1896
+ class InvoicingNotification < Base
1897
+ def self.load_members
1898
+ object_of :subject, String
1899
+ object_of :note, String
1900
+ object_of :send_to_merchant, Boolean
1901
+ array_of :cc_emails, String
1902
+ end
1903
+ end
1904
+
1905
+ class InvoicingMetaData < Base
1906
+ def self.load_members
1907
+ object_of :created_date, String
1908
+ object_of :created_by, String
1909
+ object_of :cancelled_date, String
1910
+ object_of :cancelled_by, String
1911
+ object_of :last_updated_date, String
1912
+ object_of :last_updated_by, String
1913
+ object_of :first_sent_date, String
1914
+ object_of :last_sent_date, String
1915
+ object_of :last_sent_by, String
1916
+ end
1917
+ end
1918
+
1919
+ class InvoicingPaymentDetail < Base
1920
+ def self.load_members
1921
+ object_of :type, String
1922
+ object_of :transaction_id, String
1923
+ object_of :transaction_type, String
1924
+ object_of :date, String
1925
+ object_of :method, String
1926
+ object_of :note, String
1927
+ end
1928
+ end
1929
+
1930
+ class InvoicingRefundDetail < Base
1931
+ def self.load_members
1932
+ object_of :type, String
1933
+ object_of :date, String
1934
+ object_of :note, String
1935
+ end
1936
+ end
1937
+
1938
+ class InvoicingSearch < Base
1939
+ def self.load_members
1940
+ object_of :email, String
1941
+ object_of :recipient_first_name, String
1942
+ object_of :recipient_last_name, String
1943
+ object_of :recipient_business_name, String
1944
+ object_of :number, String
1945
+ object_of :status, String
1946
+ object_of :lower_total_amount, Currency
1947
+ object_of :upper_total_amount, Currency
1948
+ object_of :start_invoice_date, String
1949
+ object_of :end_invoice_date, String
1950
+ object_of :start_due_date, String
1951
+ object_of :end_due_date, String
1952
+ object_of :start_payment_date, String
1953
+ object_of :end_payment_date, String
1954
+ object_of :start_creation_date, String
1955
+ object_of :end_creation_date, String
1956
+ object_of :page, Number
1957
+ object_of :page_size, Number
1958
+ object_of :total_count_required, Boolean
1959
+ object_of :archived, Boolean
1960
+ end
1961
+ end
1962
+
1963
+ class PaymentTerm < Base
1964
+ def self.load_members
1965
+ object_of :term_type, String
1966
+ object_of :due_date, String
1967
+ end
1968
+ end
1969
+
1970
+ class Cost < Base
1971
+ def self.load_members
1972
+ object_of :percent, Number
1973
+ object_of :amount, Currency
1974
+ end
1975
+ end
1976
+
1977
+ class ShippingCost < Base
1978
+ def self.load_members
1979
+ object_of :amount, Currency
1980
+ object_of :tax, Tax
1981
+ end
1982
+ end
1983
+
1984
+ class Tax < Base
1985
+ def self.load_members
1986
+ object_of :id, String
1987
+ object_of :name, String
1988
+ object_of :percent, Number
1989
+ object_of :amount, Currency
1990
+ end
1991
+ end
1992
+
1993
+ class CustomAmount < Base
1994
+ def self.load_members
1995
+ object_of :label, String
1996
+ object_of :amount, Currency
1997
+ end
1998
+ end
1999
+
2000
+ class PaymentDetail < Base
2001
+ def self.load_members
2002
+ object_of :type, String
2003
+ object_of :transaction_id, String
2004
+ object_of :transaction_type, String
2005
+ object_of :date, String
2006
+ object_of :method, String
2007
+ object_of :note, String
2008
+ end
2009
+ end
2010
+
2011
+ class RefundDetail < Base
2012
+ def self.load_members
2013
+ object_of :type, String
2014
+ object_of :date, String
2015
+ object_of :note, String
2016
+ end
2017
+ end
2018
+
2019
+ class Metadata < Base
2020
+ def self.load_members
2021
+ object_of :created_date, String
2022
+ object_of :created_by, String
2023
+ object_of :cancelled_date, String
2024
+ object_of :cancelled_by, String
2025
+ object_of :last_updated_date, String
2026
+ object_of :last_updated_by, String
2027
+ object_of :first_sent_date, String
2028
+ object_of :last_sent_date, String
2029
+ object_of :last_sent_by, String
2030
+ object_of :payer_view_url, String
2031
+ end
2032
+ end
2033
+
2034
+ class Notification < Base
2035
+ def self.load_members
2036
+ object_of :subject, String
2037
+ object_of :note, String
2038
+ object_of :send_to_merchant, Boolean
2039
+ end
2040
+ end
2041
+
2042
+ class Search < Base
2043
+ def self.load_members
2044
+ object_of :email, String
2045
+ object_of :recipient_first_name, String
2046
+ object_of :recipient_last_name, String
2047
+ object_of :recipient_business_name, String
2048
+ object_of :number, String
2049
+ object_of :status, String
2050
+ object_of :lower_total_amount, Currency
2051
+ object_of :upper_total_amount, Currency
2052
+ object_of :start_invoice_date, String
2053
+ object_of :end_invoice_date, String
2054
+ object_of :start_due_date, String
2055
+ object_of :end_due_date, String
2056
+ object_of :start_payment_date, String
2057
+ object_of :end_payment_date, String
2058
+ object_of :start_creation_date, String
2059
+ object_of :end_creation_date, String
2060
+ object_of :page, Number
2061
+ object_of :page_size, Number
2062
+ object_of :total_count_required, Boolean
2063
+ end
2064
+ end
2065
+
2066
+ class CancelNotification < Base
2067
+ def self.load_members
2068
+ object_of :subject, String
2069
+ object_of :note, String
2070
+ object_of :send_to_merchant, Boolean
2071
+ object_of :send_to_payer, Boolean
2072
+ end
2073
+ end
2074
+
2075
+ class Plan < Base
2076
+ def self.load_members
2077
+ object_of :id, String
2078
+ object_of :name, String
2079
+ object_of :description, String
2080
+ object_of :type, String
2081
+ object_of :state, String
2082
+ object_of :create_time, String
2083
+ object_of :update_time, String
2084
+ array_of :payment_definitions, PaymentDefinition
2085
+ array_of :terms, Terms
2086
+ object_of :merchant_preferences, MerchantPreferences
2087
+ array_of :links, Links
2088
+ end
2089
+
2090
+ include RequestDataType
2091
+
2092
+ def create()
2093
+ path = "v1/payments/billing-plans/"
2094
+ response = api.post(path, self.to_hash, http_header)
2095
+ self.merge!(response)
2096
+ success?
2097
+ end
2098
+
2099
+ def update(patch)
2100
+ patch = Patch.new(patch) unless patch.is_a? Patch
2101
+ patch_request = Array.new(1, patch.to_hash)
2102
+ path = "v1/payments/billing-plans/#{self.id}"
2103
+ response = api.patch(path, patch_request, http_header)
2104
+ self.merge!(response)
2105
+ success?
2106
+ end
2107
+
2108
+ raise_on_api_error :create, :update
2109
+
2110
+ class << self
2111
+ def find(resource_id)
2112
+ raise ArgumentError.new("id required") if resource_id.to_s.strip.empty?
2113
+ path = "v1/payments/billing-plans/#{resource_id}"
2114
+ self.new(api.get(path))
2115
+ end
2116
+
2117
+ def all(options = {})
2118
+ path = "v1/payments/billing-plans/"
2119
+ PlanList.new(api.get(path, options))
2120
+ end
2121
+ end
2122
+ end
2123
+
2124
+ class PaymentDefinition < Base
2125
+ def self.load_members
2126
+ object_of :id, String
2127
+ object_of :name, String
2128
+ object_of :type, String
2129
+ object_of :frequency_interval, String
2130
+ object_of :frequency, String
2131
+ object_of :cycles, String
2132
+ object_of :amount, Currency
2133
+ array_of :charge_models, ChargeModels
2134
+ end
2135
+ end
2136
+
2137
+ class ChargeModels < Base
2138
+ def self.load_members
2139
+ object_of :id, String
2140
+ object_of :type, String
2141
+ object_of :amount, Currency
2142
+ end
2143
+ end
2144
+
2145
+ class Terms < Base
2146
+ def self.load_members
2147
+ object_of :id, String
2148
+ object_of :type, String
2149
+ object_of :max_billing_amount, Currency
2150
+ object_of :occurrences, String
2151
+ object_of :amount_range, Currency
2152
+ object_of :buyer_editable, String
2153
+ end
2154
+ end
2155
+
2156
+ class MerchantPreferences < Base
2157
+ def self.load_members
2158
+ object_of :id, String
2159
+ object_of :setup_fee, Currency
2160
+ object_of :cancel_url, String
2161
+ object_of :return_url, String
2162
+ object_of :notify_url, String
2163
+ object_of :max_fail_attempts, String
2164
+ object_of :auto_bill_amount, String
2165
+ object_of :initial_fail_amount_action, String
2166
+ object_of :accepted_payment_type, String
2167
+ object_of :char_set, String
2168
+ end
2169
+ end
2170
+
2171
+ class Links < Base
2172
+ def self.load_members
2173
+ object_of :href, String
2174
+ object_of :rel, String
2175
+ object_of :targetSchema, HyperSchema
2176
+ object_of :method, String
2177
+ object_of :encType, String
2178
+ object_of :schema, HyperSchema
2179
+ end
2180
+ end
2181
+
2182
+ class Schema < Base
2183
+ def self.load_members
2184
+ object_of :type, Object
2185
+ object_of :properties, Schema
2186
+ object_of :patternProperties, Schema
2187
+ object_of :additionalProperties, Object
2188
+ object_of :items, Object
2189
+ object_of :additionalItems, Object
2190
+ object_of :required, Boolean
2191
+ object_of :dependencies, Object
2192
+ object_of :minimum, Number
2193
+ object_of :maximum, Number
2194
+ object_of :exclusiveMinimum, Boolean
2195
+ object_of :exclusiveMaximum, Boolean
2196
+ object_of :minItems, Integer
2197
+ object_of :maxItems, Integer
2198
+ object_of :uniqueItems, Boolean
2199
+ object_of :pattern, String
2200
+ object_of :minLength, Integer
2201
+ object_of :maxLength, Integer
2202
+ array_of :enum, Array
2203
+ object_of :title, String
2204
+ object_of :description, String
2205
+ object_of :format, String
2206
+ object_of :divisibleBy, Number
2207
+ object_of :disallow, Object
2208
+ object_of :extends, Object
2209
+ object_of :id, String
2210
+ object_of :$ref, String
2211
+ object_of :$schema, String
2212
+ end
2213
+ end
2214
+
2215
+ class HyperSchema < Schema
2216
+ def self.load_members
2217
+ array_of :links, Links
2218
+ object_of :fragmentResolution, String
2219
+ object_of :readonly, Boolean
2220
+ object_of :contentEncoding, String
2221
+ object_of :pathStart, String
2222
+ object_of :mediaType, String
2223
+ end
2224
+ end
2225
+
2226
+ class PlanList < Base
2227
+ def self.load_members
2228
+ array_of :plans, Plan
2229
+ object_of :total_items, String
2230
+ object_of :total_pages, String
2231
+ array_of :links, Links
2232
+ end
2233
+ end
2234
+
2235
+ class Agreement < Base
2236
+ def self.load_members
2237
+ object_of :id, String
2238
+ object_of :state, String
2239
+ object_of :name, String
2240
+ object_of :description, String
2241
+ object_of :start_date, String
2242
+ object_of :agreement_details, AgreementDetails
2243
+ object_of :payer, Payer
2244
+ object_of :shipping_address, Address
2245
+ object_of :override_merchant_preferences, MerchantPreferences
2246
+ array_of :override_charge_models, OverrideChargeModel
2247
+ object_of :plan, Plan
2248
+ object_of :create_time, String
2249
+ object_of :update_time, String
2250
+ array_of :links, Links
2251
+ object_of :token, String
2252
+ end
2253
+
2254
+ include RequestDataType
2255
+
2256
+ def create()
2257
+ path = "v1/payments/billing-agreements/"
2258
+ response = api.post(path, self.to_hash, http_header)
2259
+ self.merge!(response)
2260
+ self.get_token(self.links)
2261
+ success?
2262
+ end
2263
+
2264
+ def execute()
2265
+ path = "v1/payments/billing-agreements/#{self.token}/agreement-execute"
2266
+ response = api.post(path, {}, http_header)
2267
+ self.merge!(response)
2268
+ success?
2269
+ end
2270
+
2271
+ class << self
2272
+ def find(resource_id)
2273
+ raise ArgumentError.new("id required") if resource_id.to_s.strip.empty?
2274
+ path = "v1/payments/billing-agreements/#{resource_id}"
2275
+ self.new(api.get(path))
2276
+ end
2277
+ end
2278
+
2279
+ def update(patch)
2280
+ patch = Patch.new(patch) unless patch.is_a? Patch
2281
+ path = "v1/payments/billing-agreements/#{self.id}"
2282
+ response = api.patch(path, [patch.to_hash], http_header)
2283
+ self.merge!(response)
2284
+ success?
2285
+ end
2286
+
2287
+ def suspend(agreement_state_descriptor)
2288
+ agreement_state_descriptor = AgreementStateDescriptor.new(agreement_state_descriptor) unless agreement_state_descriptor.is_a? AgreementStateDescriptor
2289
+ path = "v1/payments/billing-agreements/#{self.id}/suspend"
2290
+ response = api.post(path, agreement_state_descriptor.to_hash, http_header)
2291
+ self.merge!(response)
2292
+ success?
2293
+ end
2294
+
2295
+ def re_activate(agreement_state_descriptor)
2296
+ agreement_state_descriptor = AgreementStateDescriptor.new(agreement_state_descriptor) unless agreement_state_descriptor.is_a? AgreementStateDescriptor
2297
+ path = "v1/payments/billing-agreements/#{self.id}/re-activate"
2298
+ response = api.post(path, agreement_state_descriptor.to_hash, http_header)
2299
+ self.merge!(response)
2300
+ success?
2301
+ end
2302
+
2303
+ def cancel(agreement_state_descriptor)
2304
+ agreement_state_descriptor = AgreementStateDescriptor.new(agreement_state_descriptor) unless agreement_state_descriptor.is_a? AgreementStateDescriptor
2305
+ path = "v1/payments/billing-agreements/#{self.id}/cancel"
2306
+ response = api.post(path, agreement_state_descriptor.to_hash, http_header)
2307
+ self.merge!(response)
2308
+ success?
2309
+ end
2310
+
2311
+ def bill_balance(agreement_state_descriptor)
2312
+ agreement_state_descriptor = AgreementStateDescriptor.new(agreement_state_descriptor) unless agreement_state_descriptor.is_a? AgreementStateDescriptor
2313
+ path = "v1/payments/billing-agreements/#{self.id}/bill-balance"
2314
+ response = api.post(path, agreement_state_descriptor.to_hash, http_header)
2315
+ self.merge!(response)
2316
+ success?
2317
+ end
2318
+
2319
+ def set_balance(currency)
2320
+ currency = Currency.new(currency) unless currency.is_a? Currency
2321
+ path = "v1/payments/billing-agreements/#{self.id}/set-balance"
2322
+ response = api.post(path, currency.to_hash, http_header)
2323
+ self.merge!(response)
2324
+ success?
2325
+ end
2326
+
2327
+ raise_on_api_error :create, :execute, :update, :suspend, :re_activate,
2328
+ :cancel, :bill_balance, :set_balance
2329
+
2330
+ class << self
2331
+ def transactions(agreement_id, start_date, end_date, options = {})
2332
+ path = "v1/payments/billing-agreements/#{agreement_id}/transactions" #?start-date=#{start_date}&end-date=#{end_date}"
2333
+ options = { :start_date => start_date, :end_date => end_date }
2334
+ AgreementTransactions.new(api.get(path, options))
2335
+ end
2336
+ end
2337
+
2338
+ def get_token(links)
2339
+ links.each do |link|
2340
+ if link.rel.eql? "approval_url"
2341
+ uri = URI.parse(link.href)
2342
+ params = CGI.parse(uri.query)
2343
+ self.token = params['token'][0]
2344
+ return
2345
+ end
2346
+ end
2347
+ end
2348
+ end
2349
+ class AgreementDetails < Base
2350
+ def self.load_members
2351
+ object_of :outstanding_balance, Currency
2352
+ object_of :cycles_remaining, String
2353
+ object_of :cycles_completed, String
2354
+ object_of :next_billing_date, String
2355
+ object_of :last_payment_date, String
2356
+ object_of :last_payment_amount, Currency
2357
+ object_of :final_payment_date, String
2358
+ object_of :failed_payment_count, String
2359
+ end
2360
+ end
2361
+
2362
+ class OverrideChargeModel < Base
2363
+ def self.load_members
2364
+ object_of :charge_id, String
2365
+ object_of :amount, Currency
2366
+ end
2367
+ end
2368
+
2369
+ class AgreementStateDescriptor < Base
2370
+ def self.load_members
2371
+ object_of :note, String
2372
+ object_of :amount, Currency
2373
+ end
2374
+ end
2375
+
2376
+ class AgreementTransactions < Base
2377
+ def self.load_members
2378
+ array_of :agreement_transaction_list, AgreementTransaction
2379
+ end
2380
+ end
2381
+
2382
+ class AgreementTransaction < Base
2383
+ def self.load_members
2384
+ object_of :transaction_id, String
2385
+ object_of :status, String
2386
+ object_of :transaction_type, String
2387
+ object_of :amount, Currency
2388
+ object_of :fee_amount, Currency
2389
+ object_of :net_amount, Currency
2390
+ object_of :payer_email, String
2391
+ object_of :payer_name, String
2392
+ object_of :time_zone, String
2393
+ object_of :time_stamp, DateTime
2394
+ end
2395
+ end
2396
+
2397
+ class WebProfile < Base
2398
+ def self.load_members
2399
+ object_of :id, String
2400
+ object_of :name, String
2401
+ object_of :temporary, Boolean
2402
+ object_of :flow_config, FlowConfig
2403
+ object_of :input_fields, InputFields
2404
+ object_of :presentation, Presentation
2405
+ end
2406
+
2407
+ include RequestDataType
2408
+
2409
+ def create()
2410
+ path = "v1/payment-experience/web-profiles/"
2411
+ response = api.post(path, self.to_hash, http_header)
2412
+ self.merge!(response)
2413
+ WebProfile.new(response)
2414
+ end
2415
+
2416
+ def update()
2417
+ path = "v1/payment-experience/web-profiles/#{self.id}"
2418
+ response = api.put(path, self.to_hash, http_header)
2419
+ self.merge!(response)
2420
+ success?
2421
+ end
2422
+
2423
+ def partial_update(patch_request)
2424
+ patch_request = PatchRequest.new(patch_request) unless patch_request.is_a? PatchRequest
2425
+ path = "v1/payment-experience/web-profiles/#{self.id}"
2426
+ response = api.patch(path, patch_request.to_hash, http_header)
2427
+ self.merge!(response)
2428
+ success?
2429
+ end
2430
+
2431
+ def delete()
2432
+ path = "v1/payment-experience/web-profiles/#{self.id}"
2433
+ response = api.delete(path, {})
2434
+ self.merge!(response)
2435
+ success?
2436
+ end
2437
+
2438
+ raise_on_api_error :update, :partial_update, :delete
2439
+
2440
+ class << self
2441
+ def find(resource_id)
2442
+ raise ArgumentError.new("id required") if resource_id.to_s.strip.empty?
2443
+ path = "v1/payment-experience/web-profiles/#{resource_id}"
2444
+ self.new(api.get(path))
2445
+ end
2446
+
2447
+ def get_list(options = {})
2448
+ path = "v1/payment-experience/web-profiles/"
2449
+ l = api.get(path, options)
2450
+ # The API is inconsistent in that it returns an array of WebProfiles
2451
+ # instead of a JSON object with a property which should be a list
2452
+ # of WebProfiles.
2453
+ #
2454
+ # Note that the WebProfileList is technically incorrect. It should
2455
+ # be a WebProfile.new() here, but due to backwards-compatibility,
2456
+ # may need to leave it as WebProfileList.
2457
+ l.map { |x| WebProfileList.new(x) }
2458
+ end
2459
+ end
2460
+ end
2461
+
2462
+ class FlowConfig < Base
2463
+ def self.load_members
2464
+ object_of :landing_page_type, String
2465
+ object_of :bank_txn_pending_url, String
2466
+ object_of :user_action, String
2467
+ object_of :return_uri_http_method, String
2468
+ end
2469
+ end
2470
+
2471
+ class InputFields < Base
2472
+ def self.load_members
2473
+ object_of :allow_note, Boolean
2474
+ object_of :no_shipping, Integer
2475
+ object_of :address_override, Integer
2476
+ end
2477
+ end
2478
+
2479
+ class Presentation < Base
2480
+ def self.load_members
2481
+ object_of :brand_name, String
2482
+ object_of :logo_image, String
2483
+ object_of :locale_code, String
2484
+ object_of :return_url_label, String
2485
+ object_of :note_to_seller_label, String
2486
+ end
2487
+ end
2488
+
2489
+ class WebProfileList < Base
2490
+ def self.load_members
2491
+ object_of :id, String
2492
+ object_of :name, String
2493
+ object_of :flow_config, FlowConfig
2494
+ object_of :input_fields, InputFields
2495
+ object_of :presentation, Presentation
2496
+ object_of :temporary, Boolean
2497
+ end
2498
+ end
2499
+
2500
+ class Dispute < Base
2501
+ def self.load_members
2502
+ object_of :dispute_id, String
2503
+ object_of :create_time, String
2504
+ object_of :update_time, String
2505
+ array_of :disputed_transactions, TransactionInfo
2506
+ object_of :reason, String
2507
+ object_of :status, String
2508
+ object_of :dispute_amount, Money
2509
+ object_of :external_reason_code, String
2510
+ object_of :dispute_outcome, DisputeOutcome
2511
+ object_of :dispute_life_cycle_stage, String
2512
+ object_of :dispute_channel, String
2513
+ array_of :messages, Messages
2514
+ object_of :buyer_response_due_date, String
2515
+ object_of :seller_response_due_date, String
2516
+ object_of :offer, Offer
2517
+ array_of :links, Links
2518
+ end
2519
+ end
2520
+
2521
+ class TransactionInfo < Base
2522
+ def self.load_members
2523
+ object_of :buyer_transaction_id, String
2524
+ object_of :seller_transaction_id, String
2525
+ object_of :create_time, String
2526
+ object_of :transaction_status, String
2527
+ object_of :gross_amount, Money
2528
+ object_of :invoice_number, String
2529
+ object_of :custom, String
2530
+ object_of :buyer, Buyer
2531
+ object_of :seller, Seller
2532
+ array_of :items, ItemInfo
2533
+ end
2534
+ end
2535
+
2536
+ class Buyer < Base
2537
+ def self.load_members
2538
+ object_of :email, String
2539
+ object_of :name, String
2540
+ end
2541
+ end
2542
+
2543
+ class Seller < Base
2544
+ def self.load_members
2545
+ object_of :email, String
2546
+ object_of :merchant_id, String
2547
+ object_of :name, String
2548
+ end
2549
+ end
2550
+
2551
+ class ItemInfo < Base
2552
+ def self.load_members
2553
+ object_of :item_id, String
2554
+ object_of :partner_transaction_id, String
2555
+ object_of :reason, String
2556
+ object_of :dispute_amount, Money
2557
+ object_of :notes, String
2558
+ end
2559
+ end
2560
+
2561
+ class Money < Base
2562
+ def self.load_members
2563
+ object_of :currency_code, String
2564
+ object_of :value, String
2565
+ end
2566
+ end
2567
+
2568
+ class DisputeOutcome < Base
2569
+ def self.load_members
2570
+ object_of :outcome_code, String
2571
+ object_of :amount_refunded, Money
2572
+ end
2573
+ end
2574
+
2575
+ class Messages < Base
2576
+ def self.load_members
2577
+ object_of :posted_by, String
2578
+ object_of :time_posted, String
2579
+ object_of :content, String
2580
+ end
2581
+ end
2582
+
2583
+ class Offer < Base
2584
+ def self.load_members
2585
+ object_of :buyer_requested_amount, Money
2586
+ object_of :seller_offered_amount, Money
2587
+ object_of :offer_type, String
2588
+ end
2589
+ end
2590
+
2591
+ constants.each do |data_type_klass|
2592
+ data_type_klass = const_get(data_type_klass)
2593
+ data_type_klass.load_members if defined? data_type_klass.load_members
2594
+ end
2595
+ end
2596
+ end
2597
+ end