paypal-sdk-rest-pmrb 1.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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