killbill-paypal-express 4.1.2 → 4.1.3

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 0272226dd57a3807c6e6b92fa8ce4343170e5990
4
- data.tar.gz: b270eedffc900003c247412f6ec23eb8270b833c
3
+ metadata.gz: 6d005c1bdd9b05742e9898d5fef94c1f72c0eb81
4
+ data.tar.gz: 683c9b2837efe00ff16d65f62c964b9e46020540
5
5
  SHA512:
6
- metadata.gz: 7d914623be7ecbe94d1e47b128d75720610cd24d2b74224c9f7fa4c4e06d931678326d6f44bce61b7aa71320cc508c395d36ce105fc9d14548096c58a6ab8dfc
7
- data.tar.gz: 1149ded1259435470009aec193e42b90d12b437211bd73e7511900ae875dbb088f7e224d67293b209ee72fa0d8cc4d5c4fb334c797ca40d174a824d95b67aa96
6
+ metadata.gz: b8c9c42cb7e253e38338107f86efdd8dbc27d762c2590dd7bc5f9718de8e9b1acf3b82c186930d1dd8f85fe1698aec7d7ede4ced070a3a0ea2d37730399f35fb
7
+ data.tar.gz: 03da6bfa63eaaa3631f48a40c07c99fff32ce0e58ff97a28b67a2bf2166bee83ca0546ab599e1cc91a0e6b8c0ef706631e5c35c5ae2e877b15dce200f8baf447
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- killbill-paypal-express (4.1.2)
4
+ killbill-paypal-express (4.1.3)
5
5
  actionpack (~> 4.1.0)
6
6
  actionview (~> 4.1.0)
7
7
  activemerchant (~> 1.53.0)
@@ -58,6 +58,8 @@ GEM
58
58
  ice_nine (~> 0.11.0)
59
59
  thread_safe (~> 0.3, >= 0.3.1)
60
60
  builder (3.2.2)
61
+ childprocess (0.5.9)
62
+ ffi (~> 1.0, >= 1.0.11)
61
63
  coercible (1.0.0)
62
64
  descendants_tracker (~> 0.0.1)
63
65
  descendants_tracker (0.0.4)
@@ -65,7 +67,7 @@ GEM
65
67
  diff-lcs (1.1.3)
66
68
  equalizer (0.0.11)
67
69
  erubis (2.7.0)
68
- ethon (0.8.1)
70
+ ethon (0.9.0)
69
71
  ffi (>= 1.3.0)
70
72
  ffi (1.9.10-java)
71
73
  i18n (0.7.0)
@@ -119,6 +121,11 @@ GEM
119
121
  ruby-maven (3.3.8)
120
122
  ruby-maven-libs (~> 3.3.1)
121
123
  ruby-maven-libs (3.3.3)
124
+ rubyzip (1.2.0)
125
+ selenium-webdriver (2.53.0)
126
+ childprocess (~> 0.5)
127
+ rubyzip (~> 1.0)
128
+ websocket (~> 1.0)
122
129
  sinatra (1.3.6)
123
130
  rack (~> 1.4)
124
131
  rack-protection (~> 1.3)
@@ -134,6 +141,7 @@ GEM
134
141
  coercible (~> 1.0)
135
142
  descendants_tracker (~> 0.0, >= 0.0.3)
136
143
  equalizer (~> 0.0, >= 0.0.9)
144
+ websocket (1.2.3)
137
145
 
138
146
  PLATFORMS
139
147
  java
@@ -146,6 +154,7 @@ DEPENDENCIES
146
154
  killbill-paypal-express!
147
155
  rake (>= 10.0.0)
148
156
  rspec (~> 2.12.0)
157
+ selenium-webdriver (~> 2.53.0)
149
158
 
150
159
  BUNDLED WITH
151
160
  1.11.2
data/NEWS CHANGED
@@ -1,3 +1,7 @@
1
+ 4.1.3
2
+ Add support for auth-only HPP flow
3
+ Add support for multiple merchant accounts
4
+
1
5
  4.1.2
2
6
  Configure ButtonSource parameter
3
7
 
data/README.md CHANGED
@@ -217,4 +217,5 @@ Plugin properties
217
217
  | zip | Billing address zip code |
218
218
  | state | Billing address state |
219
219
  | country | Billing address country |
220
- | max_amount | Maximum amount parameter (optional) for SetExpressCheckout call |
220
+ | max_amount | Maximum amount parameter (optional) for SetExpressCheckout call |
221
+ | auth_mode | If true, [Authorization Payment Action](https://developer.paypal.com/docs/classic/express-checkout/integration-guide/ECRelatedAPIOps/) is adopted. Otherwise, Sale Payment Action is used.|
data/VERSION CHANGED
@@ -1 +1 @@
1
- 4.1.2
1
+ 4.1.3
@@ -42,6 +42,7 @@ Gem::Specification.new do |s|
42
42
  s.add_development_dependency 'jbundler', '~> 0.9.2'
43
43
  s.add_development_dependency 'rake', '>= 10.0.0'
44
44
  s.add_development_dependency 'rspec', '~> 2.12.0'
45
+ s.add_development_dependency 'selenium-webdriver', '~>2.53.0'
45
46
  if defined?(JRUBY_VERSION)
46
47
  s.add_development_dependency 'jdbc-sqlite3', '~> 3.7'
47
48
  s.add_development_dependency 'jdbc-mariadb', '~> 1.1'
@@ -29,20 +29,7 @@ module Killbill #:nodoc:
29
29
  end
30
30
 
31
31
  def authorize_payment(kb_account_id, kb_payment_id, kb_payment_transaction_id, kb_payment_method_id, amount, currency, properties, context)
32
- # Pass extra parameters for the gateway here
33
- options = {}
34
-
35
- add_required_options(kb_payment_transaction_id, kb_payment_method_id, context, options)
36
-
37
- properties = merge_properties(properties, options)
38
-
39
- # Can't use default implementation: the authorize signature is for one-off payments only
40
- #super(kb_account_id, kb_payment_id, kb_payment_transaction_id, kb_payment_method_id, amount, currency, properties, context)
41
- gateway_call_proc = Proc.new do |gateway, linked_transaction, payment_source, amount_in_cents, options|
42
- gateway.authorize_reference_transaction(amount_in_cents, options)
43
- end
44
-
45
- dispatch_to_gateways(:authorize, kb_account_id, kb_payment_id, kb_payment_transaction_id, kb_payment_method_id, amount, currency, properties, context, gateway_call_proc)
32
+ authorize_or_purchase_payment kb_account_id, kb_payment_id, kb_payment_transaction_id, kb_payment_method_id, amount, currency, properties, context, true
46
33
  end
47
34
 
48
35
  def capture_payment(kb_account_id, kb_payment_id, kb_payment_transaction_id, kb_payment_method_id, amount, currency, properties, context)
@@ -58,73 +45,8 @@ module Killbill #:nodoc:
58
45
  end
59
46
 
60
47
  def purchase_payment(kb_account_id, kb_payment_id, kb_payment_transaction_id, kb_payment_method_id, amount, currency, properties, context)
61
- payment_processor_account_id = find_value_from_properties(properties, 'payment_processor_account_id')
62
-
63
- # Callback from the plugin itself (HPP flow)
64
- if find_value_from_properties(properties, 'from_hpp') == 'true'
65
- token = find_value_from_properties(properties, 'token')
66
-
67
- response = @response_model.create(:api_call => :build_form_descriptor,
68
- :kb_account_id => kb_account_id,
69
- :kb_payment_id => kb_payment_id,
70
- :kb_payment_transaction_id => kb_payment_transaction_id,
71
- :transaction_type => :PURCHASE,
72
- :authorization => token,
73
- :payment_processor_account_id => payment_processor_account_id,
74
- :kb_tenant_id => context.tenant_id,
75
- :success => true,
76
- :created_at => Time.now.utc,
77
- :updated_at => Time.now.utc,
78
- :message => { :payment_plugin_status => :PENDING }.to_json)
79
- transaction = response.to_transaction_info_plugin(nil)
80
- transaction.amount = amount
81
- transaction.currency = currency
82
- transaction
83
- else
84
- options = {}
85
- add_required_options(kb_payment_transaction_id, kb_payment_method_id, context, options)
86
-
87
- # We have a baid on file
88
- if options[:token]
89
- gateway_call_proc = Proc.new do |gateway, linked_transaction, payment_source, amount_in_cents, options|
90
- # Can't use default implementation: the purchase signature is for one-off payments only
91
- gateway.reference_transaction(amount_in_cents, options)
92
- end
93
- else
94
- # One-off payment
95
- options[:token] = find_value_from_properties(properties, 'token') || find_last_token(kb_account_id, context.tenant_id)
96
- gateway_call_proc = Proc.new do |gateway, linked_transaction, payment_source, amount_in_cents, options|
97
- gateway.purchase(amount_in_cents, options)
98
- end
99
- end
100
-
101
- # Populate the Payer id if missing
102
- options[:payer_id] = find_value_from_properties(properties, 'payer_id')
103
- begin
104
- options[:payer_id] ||= find_payer_id(options[:token],
105
- kb_account_id,
106
- context.tenant_id,
107
- properties_to_hash(properties))
108
- rescue => e
109
- # Maybe invalid token?
110
- response = @response_model.create(:api_call => :purchase,
111
- :kb_account_id => kb_account_id,
112
- :kb_payment_id => kb_payment_id,
113
- :kb_payment_transaction_id => kb_payment_transaction_id,
114
- :transaction_type => :PURCHASE,
115
- :authorization => nil,
116
- :payment_processor_account_id => payment_processor_account_id,
117
- :kb_tenant_id => context.tenant_id,
118
- :success => false,
119
- :created_at => Time.now.utc,
120
- :updated_at => Time.now.utc,
121
- :message => { :payment_plugin_status => :CANCELED, :exception_class => e.class.to_s, :exception_message => e.message }.to_json)
122
- return response.to_transaction_info_plugin(nil)
123
- end
124
-
125
- properties = merge_properties(properties, options)
126
- dispatch_to_gateways(:purchase, kb_account_id, kb_payment_id, kb_payment_transaction_id, kb_payment_method_id, amount, currency, properties, context, gateway_call_proc)
127
- end
48
+ # by default, this call will purchase a payment
49
+ authorize_or_purchase_payment kb_account_id, kb_payment_id, kb_payment_transaction_id, kb_payment_method_id, amount, currency, properties, context
128
50
  end
129
51
 
130
52
  def void_payment(kb_account_id, kb_payment_id, kb_payment_transaction_id, kb_payment_method_id, properties, context)
@@ -151,7 +73,7 @@ module Killbill #:nodoc:
151
73
  linked_transaction_type = @transaction_model.purchases_from_kb_payment_id(kb_payment_id, context.tenant_id).size > 0 ? :PURCHASE : :CAPTURE
152
74
 
153
75
  # Pass extra parameters for the gateway here
154
- options = {
76
+ options = {
155
77
  :linked_transaction_type => linked_transaction_type
156
78
  }
157
79
 
@@ -162,12 +84,14 @@ module Killbill #:nodoc:
162
84
  def get_payment_info(kb_account_id, kb_payment_id, properties, context)
163
85
  t_info_plugins = super(kb_account_id, kb_payment_id, properties, context)
164
86
 
165
- # Completed purchases will have two rows in the responses table (one for api_call 'build_form_descriptor', one for api_call 'purchase')
87
+ # Completed purchases/authorizations will have two rows in the responses table (one for api_call 'build_form_descriptor', one for api_call 'purchase/authorize')
166
88
  # Other transaction types don't support the :PENDING state
167
- is_purchase_pending = t_info_plugins.find { |t_info_plugin| t_info_plugin.transaction_type == :PURCHASE && t_info_plugin.status != :PENDING }.nil?
168
- t_info_plugins_without_purchase_pending = t_info_plugins.reject { |t_info_plugin| t_info_plugin.transaction_type == :PURCHASE && t_info_plugin.status == :PENDING }
89
+ target_transaction_types = [:PURCHASE, :AUTHORIZE]
90
+ is_transaction_pending = t_info_plugins.find { |t_info_plugin| target_transaction_types.include?(t_info_plugin.transaction_type) && t_info_plugin.status != :PENDING }.nil?
91
+ t_info_plugins_without_pending = t_info_plugins.reject { |t_info_plugin| target_transaction_types.include?(t_info_plugin.transaction_type) && t_info_plugin.status == :PENDING }
169
92
 
170
- is_purchase_pending ? t_info_plugins: t_info_plugins_without_purchase_pending
93
+ # If only pending transactions exist, return the pending one. Otherwise, only return those non-pending transaction.
94
+ is_transaction_pending ? t_info_plugins: t_info_plugins_without_pending
171
95
  end
172
96
 
173
97
  def search_payments(search_key, offset, limit, properties, context)
@@ -189,10 +113,13 @@ module Killbill #:nodoc:
189
113
  }
190
114
  else
191
115
  # Go to Paypal to get the Payer id (GetExpressCheckoutDetails call)
192
- payer_id = find_payer_id(token, kb_account_id, context.tenant_id, properties_to_hash(properties))
116
+ payment_processor_account_id = find_value_from_properties(properties, :payment_processor_account_id)
117
+ payment_processor_account_id ||= find_payment_processor_id_from_initial_call(kb_account_id, context.tenant_id, token)
118
+ payer_id = find_payer_id(token, kb_account_id, context.tenant_id, payment_processor_account_id)
193
119
  options = {
194
- :paypal_express_token => token,
195
- :paypal_express_payer_id => payer_id
120
+ :paypal_express_token => token,
121
+ :paypal_express_payer_id => payer_id,
122
+ :payment_processor_account_id => payment_processor_account_id
196
123
  }
197
124
  end
198
125
 
@@ -260,22 +187,40 @@ module Killbill #:nodoc:
260
187
  # By default, pending payments are not created for HPP
261
188
  create_pending_payment = ::Killbill::Plugin::ActiveMerchant::Utils.normalized(options, :create_pending_payment)
262
189
  if create_pending_payment
263
- custom_props = hash_to_properties(:from_hpp => true,
264
- :token => response.token)
190
+ payment_processor_account_id = ::Killbill::Plugin::ActiveMerchant::Utils.normalized(options, :payment_processor_account_id)
191
+ custom_props = hash_to_properties(:from_hpp => true,
192
+ :token => response.token,
193
+ :payment_processor_account_id => payment_processor_account_id)
265
194
  payment_external_key = ::Killbill::Plugin::ActiveMerchant::Utils.normalized(options, :payment_external_key)
266
195
  transaction_external_key = ::Killbill::Plugin::ActiveMerchant::Utils.normalized(options, :transaction_external_key)
267
196
 
268
197
  kb_payment_method = (@kb_apis.payment_api.get_account_payment_methods(kb_account_id, false, [], jcontext).find { |pm| pm.plugin_name == 'killbill-paypal-express' })
269
- payment = @kb_apis.payment_api
270
- .create_purchase(kb_account.send(:__instance_object__),
271
- kb_payment_method.id,
272
- nil,
273
- amount,
274
- currency,
275
- payment_external_key,
276
- transaction_external_key,
277
- custom_props,
278
- jcontext)
198
+
199
+ auth_mode = ::Killbill::Plugin::ActiveMerchant::Utils.normalized(options, :auth_mode)
200
+ # By default, the SALE mode is used.
201
+ if auth_mode
202
+ payment = @kb_apis.payment_api
203
+ .create_authorization(kb_account.send(:__instance_object__),
204
+ kb_payment_method.id,
205
+ nil,
206
+ amount,
207
+ currency,
208
+ payment_external_key,
209
+ transaction_external_key,
210
+ custom_props,
211
+ jcontext)
212
+ else
213
+ payment = @kb_apis.payment_api
214
+ .create_purchase(kb_account.send(:__instance_object__),
215
+ kb_payment_method.id,
216
+ nil,
217
+ amount,
218
+ currency,
219
+ payment_external_key,
220
+ transaction_external_key,
221
+ custom_props,
222
+ jcontext)
223
+ end
279
224
 
280
225
  descriptor.properties << build_property('kb_payment_id', payment.id)
281
226
  descriptor.properties << build_property('kb_payment_external_key', payment.external_key)
@@ -318,11 +263,11 @@ module Killbill #:nodoc:
318
263
  @response_model.last_token(kb_account_id, kb_tenant_id)
319
264
  end
320
265
 
321
- def find_payer_id(token, kb_account_id, kb_tenant_id, options = {})
266
+ def find_payer_id(token, kb_account_id, kb_tenant_id, payment_processor_account_id)
322
267
  raise 'Could not find the payer_id: the token is missing' if token.blank?
323
268
 
324
269
  # Go to Paypal to get the Payer id (GetExpressCheckoutDetails call)
325
- payment_processor_account_id = options[:payment_processor_account_id] || :default
270
+ payment_processor_account_id = payment_processor_account_id || :default
326
271
  gateway = lookup_gateway(payment_processor_account_id, kb_tenant_id)
327
272
  gw_response = gateway.details_for(token)
328
273
  response, transaction = save_response_and_transaction(gw_response, :details_for, kb_account_id, kb_tenant_id, payment_processor_account_id)
@@ -353,6 +298,7 @@ module Killbill #:nodoc:
353
298
  options = {}
354
299
  options[:return_url] = ::Killbill::Plugin::ActiveMerchant::Utils.normalized(properties_hash, :return_url)
355
300
  options[:cancel_return_url] = ::Killbill::Plugin::ActiveMerchant::Utils.normalized(properties_hash, :cancel_return_url)
301
+ options[:payment_processor_account_id] = ::Killbill::Plugin::ActiveMerchant::Utils.normalized(properties_hash, :payment_processor_account_id)
356
302
 
357
303
  max_amount_value = ::Killbill::Plugin::ActiveMerchant::Utils.normalized(properties_hash, :max_amount)
358
304
  if max_amount_value
@@ -373,6 +319,99 @@ module Killbill #:nodoc:
373
319
 
374
320
  response
375
321
  end
322
+
323
+ def authorize_or_purchase_payment(kb_account_id, kb_payment_id, kb_payment_transaction_id, kb_payment_method_id, amount, currency, properties, context, is_authorize = false)
324
+ payment_processor_account_id = find_value_from_properties(properties, 'payment_processor_account_id')
325
+ transaction_type = is_authorize ? :AUTHORIZE : :PURCHASE
326
+ api_call_type = is_authorize ? :authorize : :purchase
327
+
328
+ # Callback from the plugin itself (HPP flow)
329
+ if find_value_from_properties(properties, 'from_hpp') == 'true'
330
+ token = find_value_from_properties(properties, 'token')
331
+
332
+ response = @response_model.create(:api_call => :build_form_descriptor,
333
+ :kb_account_id => kb_account_id,
334
+ :kb_payment_id => kb_payment_id,
335
+ :kb_payment_transaction_id => kb_payment_transaction_id,
336
+ :transaction_type => transaction_type,
337
+ :authorization => token,
338
+ :payment_processor_account_id => payment_processor_account_id,
339
+ :kb_tenant_id => context.tenant_id,
340
+ :success => true,
341
+ :created_at => Time.now.utc,
342
+ :updated_at => Time.now.utc,
343
+ :message => { :payment_plugin_status => :PENDING }.to_json)
344
+ transaction = response.to_transaction_info_plugin(nil)
345
+ transaction.amount = amount
346
+ transaction.currency = currency
347
+ transaction
348
+ else
349
+ options = {}
350
+ add_required_options(kb_payment_transaction_id, kb_payment_method_id, context, options)
351
+
352
+ # We have a baid on file
353
+ if options[:token]
354
+ if is_authorize
355
+ gateway_call_proc = Proc.new do |gateway, linked_transaction, payment_source, amount_in_cents, options|
356
+ # Can't use default implementation: the purchase signature is for one-off payments only
357
+ gateway.authorize_reference_transaction(amount_in_cents, options)
358
+ end
359
+ else
360
+ gateway_call_proc = Proc.new do |gateway, linked_transaction, payment_source, amount_in_cents, options|
361
+ # Can't use default implementation: the purchase signature is for one-off payments only
362
+ gateway.reference_transaction(amount_in_cents, options)
363
+ end
364
+ end
365
+ else
366
+ # One-off payment
367
+ options[:token] = find_value_from_properties(properties, 'token') || find_last_token(kb_account_id, context.tenant_id)
368
+ if is_authorize
369
+ gateway_call_proc = Proc.new do |gateway, linked_transaction, payment_source, amount_in_cents, options|
370
+ gateway.authorize(amount_in_cents, options)
371
+ end
372
+ else
373
+ gateway_call_proc = Proc.new do |gateway, linked_transaction, payment_source, amount_in_cents, options|
374
+ gateway.purchase(amount_in_cents, options)
375
+ end
376
+ end
377
+ end
378
+
379
+ # Find the payment_processor_id if not provided
380
+ payment_processor_account_id ||= find_payment_processor_id_from_initial_call(kb_account_id, context.tenant_id, options[:token])
381
+ options[:payment_processor_account_id] = payment_processor_account_id
382
+
383
+ # Populate the Payer id if missing
384
+ options[:payer_id] = find_value_from_properties(properties, 'payer_id')
385
+ begin
386
+ options[:payer_id] ||= find_payer_id(options[:token],
387
+ kb_account_id,
388
+ context.tenant_id,
389
+ payment_processor_account_id)
390
+ rescue => e
391
+ # Maybe invalid token?
392
+ response = @response_model.create(:api_call => api_call_type,
393
+ :kb_account_id => kb_account_id,
394
+ :kb_payment_id => kb_payment_id,
395
+ :kb_payment_transaction_id => kb_payment_transaction_id,
396
+ :transaction_type => transaction_type,
397
+ :authorization => nil,
398
+ :payment_processor_account_id => payment_processor_account_id,
399
+ :kb_tenant_id => context.tenant_id,
400
+ :success => false,
401
+ :created_at => Time.now.utc,
402
+ :updated_at => Time.now.utc,
403
+ :message => { :payment_plugin_status => :CANCELED, :exception_class => e.class.to_s, :exception_message => e.message }.to_json)
404
+ return response.to_transaction_info_plugin(nil)
405
+ end
406
+
407
+ properties = merge_properties(properties, options)
408
+ dispatch_to_gateways(api_call_type, kb_account_id, kb_payment_id, kb_payment_transaction_id, kb_payment_method_id, amount, currency, properties, context, gateway_call_proc)
409
+ end
410
+ end
411
+
412
+ def find_payment_processor_id_from_initial_call(kb_account_id, kb_tenant_id, token)
413
+ @response_model.initial_payment_account_processor_id kb_account_id, kb_tenant_id, token
414
+ end
376
415
  end
377
416
  end
378
417
  end
@@ -67,6 +67,16 @@ module Killbill #:nodoc:
67
67
  response.nil? ? nil : response.token
68
68
  end
69
69
 
70
+ def self.initial_payment_account_processor_id(kb_account_id, kb_tenant_id, token)
71
+ return nil if token.blank?
72
+ response = where(:api_call => 'initiate_express_checkout',
73
+ :success => true,
74
+ :kb_account_id => kb_account_id,
75
+ :kb_tenant_id => kb_tenant_id,
76
+ :token => token).last
77
+ response.nil? ? nil : response.payment_processor_account_id
78
+ end
79
+
70
80
  def to_transaction_info_plugin(transaction=nil)
71
81
  t_info_plugin = super(transaction)
72
82
 
data/pom.xml CHANGED
@@ -26,7 +26,7 @@
26
26
  <groupId>org.kill-bill.billing.plugin.ruby</groupId>
27
27
  <artifactId>paypal-express-plugin</artifactId>
28
28
  <packaging>pom</packaging>
29
- <version>4.1.2</version>
29
+ <version>4.1.3</version>
30
30
  <name>paypal-express-plugin</name>
31
31
  <url>http://github.com/killbill/killbill-paypal-express-plugin</url>
32
32
  <description>Plugin for accessing Paypal Express Checkout as a payment gateway</description>
@@ -1,53 +1,12 @@
1
1
  require 'spec_helper'
2
+ require_relative 'build_plugin_helpers'
3
+ require_relative 'baid_spec_helpers'
2
4
 
3
5
  ActiveMerchant::Billing::Base.mode = :test
4
6
 
5
- describe Killbill::PaypalExpress::PaymentPlugin do
6
-
7
- include ::Killbill::Plugin::ActiveMerchant::RSpec
8
-
9
- # Share the BAID
10
- before(:all) do
11
- @plugin = build_plugin(::Killbill::PaypalExpress::PaymentPlugin, 'paypal_express')
12
- svcs = @plugin.kb_apis.proxied_services
13
- svcs[:payment_api] = PaypalExpressJavaPaymentApi.new(@plugin)
14
- @plugin.kb_apis = ::Killbill::Plugin::KillbillApi.new('paypal_express', svcs)
15
- @plugin.start_plugin
16
-
17
- @call_context = build_call_context
18
-
19
- @properties = []
20
- @amount = BigDecimal.new('100')
21
- @currency = 'USD'
22
-
23
- kb_account_id = SecureRandom.uuid
24
- external_key, kb_account_id = create_kb_account(kb_account_id, @plugin.kb_apis.proxied_services[:account_user_api])
25
-
26
- # Initiate the setup process
27
- response = create_token(kb_account_id, @call_context.tenant_id)
28
- token = response.token
29
- print "\nPlease go to #{@plugin.to_express_checkout_url(response, @call_context.tenant_id)} to proceed and press any key to continue...
30
- Note: you need to log-in with a paypal sandbox account (create one here: https://developer.paypal.com/webapps/developer/applications/accounts)\n"
31
- $stdin.gets
32
-
33
- # Complete the setup process
34
- @properties << build_property('token', token)
35
- @pm = create_payment_method(::Killbill::PaypalExpress::PaypalExpressPaymentMethod, kb_account_id, @call_context.tenant_id, @properties)
36
-
37
- # Verify our table directly. Note that @pm.token is the baid
38
- payment_methods = ::Killbill::PaypalExpress::PaypalExpressPaymentMethod.from_kb_account_id_and_token(@pm.token, kb_account_id, @call_context.tenant_id)
39
- payment_methods.size.should == 1
40
- payment_method = payment_methods.first
41
- payment_method.should_not be_nil
42
- payment_method.paypal_express_payer_id.should_not be_nil
43
- payment_method.token.should == @pm.token
44
- payment_method.kb_payment_method_id.should == @pm.kb_payment_method_id
45
- end
46
-
7
+ shared_examples 'baid_spec_common' do
47
8
  before(:each) do
48
9
  ::Killbill::PaypalExpress::PaypalExpressTransaction.delete_all
49
- ::Killbill::PaypalExpress::PaypalExpressResponse.delete_all
50
-
51
10
  kb_payment_id = SecureRandom.uuid
52
11
  1.upto(6) do
53
12
  @kb_payment = @plugin.kb_apis.proxied_services[:payment_api].add_payment(kb_payment_id)
@@ -70,6 +29,7 @@ Note: you need to log-in with a paypal sandbox account (create one here: https:/
70
29
  payment_infos[0].status.should == :PROCESSED
71
30
  payment_infos[0].gateway_error.should == 'Success'
72
31
  payment_infos[0].gateway_error_code.should be_nil
32
+ find_value_from_properties(payment_infos[0].properties, 'payment_processor_account_id').should == @payment_processor_account_id
73
33
 
74
34
  # Try a full refund
75
35
  refund_response = @plugin.refund_payment(@pm.kb_account_id, @kb_payment.id, @kb_payment.transactions[1].id, @pm.kb_payment_method_id, @amount, @currency, @properties, @call_context)
@@ -87,6 +47,7 @@ Note: you need to log-in with a paypal sandbox account (create one here: https:/
87
47
  payment_infos[0].status.should == :PROCESSED
88
48
  payment_infos[0].gateway_error.should == 'Success'
89
49
  payment_infos[0].gateway_error_code.should be_nil
50
+ find_value_from_properties(payment_infos[0].properties, 'payment_processor_account_id').should == @payment_processor_account_id
90
51
  payment_infos[1].kb_payment_id.should == @kb_payment.id
91
52
  payment_infos[1].transaction_type.should == :REFUND
92
53
  payment_infos[1].amount.should == @amount
@@ -94,6 +55,7 @@ Note: you need to log-in with a paypal sandbox account (create one here: https:/
94
55
  payment_infos[1].status.should == :PROCESSED
95
56
  payment_infos[1].gateway_error.should == 'Success'
96
57
  payment_infos[1].gateway_error_code.should be_nil
58
+ find_value_from_properties(payment_infos[1].properties, 'payment_processor_account_id').should == @payment_processor_account_id
97
59
  end
98
60
 
99
61
  it 'should be able to auth, capture and refund' do
@@ -112,6 +74,7 @@ Note: you need to log-in with a paypal sandbox account (create one here: https:/
112
74
  payment_infos[0].status.should == :PROCESSED
113
75
  payment_infos[0].gateway_error.should == 'Success'
114
76
  payment_infos[0].gateway_error_code.should be_nil
77
+ find_value_from_properties(payment_infos[0].properties, 'payment_processor_account_id').should == @payment_processor_account_id
115
78
 
116
79
  # Try multiple partial captures
117
80
  partial_capture_amount = BigDecimal.new('10')
@@ -131,6 +94,7 @@ Note: you need to log-in with a paypal sandbox account (create one here: https:/
131
94
  payment_infos[i].status.should == :PROCESSED
132
95
  payment_infos[i].gateway_error.should == 'Success'
133
96
  payment_infos[i].gateway_error_code.should be_nil
97
+ find_value_from_properties(payment_infos[i].properties, 'payment_processor_account_id').should == @payment_processor_account_id
134
98
  end
135
99
 
136
100
  # Try a partial refund
@@ -149,6 +113,7 @@ Note: you need to log-in with a paypal sandbox account (create one here: https:/
149
113
  payment_infos[4].status.should == :PROCESSED
150
114
  payment_infos[4].gateway_error.should == 'Success'
151
115
  payment_infos[4].gateway_error_code.should be_nil
116
+ find_value_from_properties(payment_infos[4].properties, 'payment_processor_account_id').should == @payment_processor_account_id
152
117
 
153
118
  # Try to capture again
154
119
  payment_response = @plugin.capture_payment(@pm.kb_account_id, @kb_payment.id, @kb_payment.transactions[5].id, @pm.kb_payment_method_id, partial_capture_amount, @currency, @properties, @call_context)
@@ -166,6 +131,7 @@ Note: you need to log-in with a paypal sandbox account (create one here: https:/
166
131
  payment_infos[5].status.should == :PROCESSED
167
132
  payment_infos[5].gateway_error.should == 'Success'
168
133
  payment_infos[5].gateway_error_code.should be_nil
134
+ find_value_from_properties(payment_infos[5].properties, 'payment_processor_account_id').should == @payment_processor_account_id
169
135
  end
170
136
 
171
137
  it 'should be able to auth and void' do
@@ -184,6 +150,7 @@ Note: you need to log-in with a paypal sandbox account (create one here: https:/
184
150
  payment_infos[0].status.should == :PROCESSED
185
151
  payment_infos[0].gateway_error.should == 'Success'
186
152
  payment_infos[0].gateway_error_code.should be_nil
153
+ find_value_from_properties(payment_infos[0].properties, 'payment_processor_account_id').should == @payment_processor_account_id
187
154
 
188
155
  payment_response = @plugin.void_payment(@pm.kb_account_id, @kb_payment.id, @kb_payment.transactions[1].id, @pm.kb_payment_method_id, @properties, @call_context)
189
156
  payment_response.status.should eq(:PROCESSED), payment_response.gateway_error
@@ -199,6 +166,7 @@ Note: you need to log-in with a paypal sandbox account (create one here: https:/
199
166
  payment_infos[0].status.should == :PROCESSED
200
167
  payment_infos[0].gateway_error.should == 'Success'
201
168
  payment_infos[0].gateway_error_code.should be_nil
169
+ find_value_from_properties(payment_infos[0].properties, 'payment_processor_account_id').should == @payment_processor_account_id
202
170
  payment_infos[1].kb_payment_id.should == @kb_payment.id
203
171
  payment_infos[1].transaction_type.should == :VOID
204
172
  payment_infos[1].amount.should be_nil
@@ -206,6 +174,7 @@ Note: you need to log-in with a paypal sandbox account (create one here: https:/
206
174
  payment_infos[1].status.should == :PROCESSED
207
175
  payment_infos[1].gateway_error.should == 'Success'
208
176
  payment_infos[1].gateway_error_code.should be_nil
177
+ find_value_from_properties(payment_infos[1].properties, 'payment_processor_account_id').should == @payment_processor_account_id
209
178
  end
210
179
 
211
180
  it 'should be able to auth, partial capture and void' do
@@ -224,6 +193,7 @@ Note: you need to log-in with a paypal sandbox account (create one here: https:/
224
193
  payment_infos[0].status.should == :PROCESSED
225
194
  payment_infos[0].gateway_error.should == 'Success'
226
195
  payment_infos[0].gateway_error_code.should be_nil
196
+ find_value_from_properties(payment_infos[0].properties, 'payment_processor_account_id').should == @payment_processor_account_id
227
197
 
228
198
  partial_capture_amount = BigDecimal.new('10')
229
199
  payment_response = @plugin.capture_payment(@pm.kb_account_id, @kb_payment.id, @kb_payment.transactions[1].id, @pm.kb_payment_method_id, partial_capture_amount, @currency, @properties, @call_context)
@@ -241,6 +211,7 @@ Note: you need to log-in with a paypal sandbox account (create one here: https:/
241
211
  payment_infos[1].status.should == :PROCESSED
242
212
  payment_infos[1].gateway_error.should == 'Success'
243
213
  payment_infos[1].gateway_error_code.should be_nil
214
+ find_value_from_properties(payment_infos[1].properties, 'payment_processor_account_id').should == @payment_processor_account_id
244
215
 
245
216
  payment_response = @plugin.void_payment(@pm.kb_account_id, @kb_payment.id, @kb_payment.transactions[2].id, @pm.kb_payment_method_id, @properties, @call_context)
246
217
  payment_response.status.should eq(:PROCESSED), payment_response.gateway_error
@@ -256,32 +227,57 @@ Note: you need to log-in with a paypal sandbox account (create one here: https:/
256
227
  payment_infos[2].status.should == :PROCESSED
257
228
  payment_infos[2].gateway_error.should == 'Success'
258
229
  payment_infos[2].gateway_error_code.should be_nil
230
+ find_value_from_properties(payment_infos[2].properties, 'payment_processor_account_id').should == @payment_processor_account_id
259
231
  end
260
232
 
261
233
  it 'should generate forms correctly' do
262
234
  context = @plugin.kb_apis.create_context(@call_context.tenant_id)
263
- fields = @plugin.hash_to_properties(
264
- :order_id => '1234',
265
- :amount => 12,
266
- )
235
+ fields = @plugin.hash_to_properties(
236
+ :order_id => '1234',
237
+ :amount => 12
238
+ )
267
239
 
268
240
  properties = @plugin.hash_to_properties(
269
- :create_pending_payment => false
241
+ :create_pending_payment => false
270
242
  )
271
243
 
272
244
  form = @plugin.build_form_descriptor(@pm.kb_account_id, fields, properties, context)
273
245
 
274
246
  form.kb_account_id.should == @pm.kb_account_id
275
- form.form_method.should == 'GET'
247
+ form.form_method.should == 'GET'
276
248
  form.form_url.should start_with('https://www.sandbox.paypal.com/cgi-bin/webscr')
277
249
  end
278
250
 
279
- private
251
+ end
252
+
253
+ describe Killbill::PaypalExpress::PaymentPlugin do
254
+ include ::Killbill::Plugin::ActiveMerchant::RSpec
255
+ include ::Killbill::PaypalExpress::BuildPluginHelpers
256
+ include ::Killbill::PaypalExpress::BaidSpecHelpers
257
+
258
+ context 'baid test with a single account' do
259
+ # Share the BAID
260
+ before(:all) do
261
+ # delete once here because we need to keep the initial response for later tests to find the payment processor account id
262
+ ::Killbill::PaypalExpress::PaypalExpressResponse.delete_all
263
+ @payment_processor_account_id = 'default'
264
+ @plugin = build_start_paypal_plugin
265
+ baid_setup
266
+ end
267
+
268
+ include_examples 'baid_spec_common'
269
+ end
270
+
271
+ context 'baid tests with multiple accounts' do
272
+ # Share the BAID
273
+ before(:all) do
274
+ # delete once here because we need to keep the initial response for later tests to find the payment processor account id
275
+ ::Killbill::PaypalExpress::PaypalExpressResponse.delete_all
276
+ @payment_processor_account_id = 'paypal_test_account'
277
+ @plugin = build_start_paypal_plugin @payment_processor_account_id
278
+ baid_setup @payment_processor_account_id
279
+ end
280
280
 
281
- def create_token(kb_account_id, kb_tenant_id)
282
- private_plugin = ::Killbill::PaypalExpress::PrivatePaymentPlugin.new
283
- response = private_plugin.initiate_express_checkout(kb_account_id, kb_tenant_id)
284
- response.success.should be_true
285
- response
281
+ include_examples 'baid_spec_common'
286
282
  end
287
283
  end