killbill-paypal-express 4.1.2 → 4.1.3

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.
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