killbill-paypal-express 5.0.3 → 5.0.4
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile.lock +7 -7
- data/VERSION +1 -1
- data/lib/paypal_express/api.rb +95 -27
- data/lib/paypal_express/models/response.rb +66 -0
- data/lib/paypal_express/private_api.rb +30 -0
- data/pom.xml +1 -1
- data/spec/paypal_express/remote/hpp_spec.rb +104 -0
- data/spec/paypal_express/remote/hpp_spec_helpers.rb +35 -0
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 5d00219df8659d8d04add7832192638b8cc94388
|
4
|
+
data.tar.gz: ae0902eee81f58d4bc5fe7c3353f9d1bfcb7c628
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f3e647b46904500a810148b4a631a065efe737f3653a84106cb6330883b794c46ed7398d241fadde9c2ec18a7565371cde185e0fdb236c278fb8e9fafb75f8a1
|
7
|
+
data.tar.gz: 1a4a5610a2fca9f7b1b6fd23daf5a1cc9e96342c3d54c2945aae3f840d2ad0dbcfb6454f43ee6752a7e9aab76c7174c3ccb3473e72d884c4e74f1af05a1c18d3
|
data/Gemfile.lock
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
killbill-paypal-express (5.0.
|
4
|
+
killbill-paypal-express (5.0.4)
|
5
5
|
actionpack (~> 4.1.0)
|
6
6
|
actionview (~> 4.1.0)
|
7
7
|
activemerchant (~> 1.53.0)
|
@@ -57,7 +57,7 @@ GEM
|
|
57
57
|
descendants_tracker (~> 0.0.4)
|
58
58
|
ice_nine (~> 0.11.0)
|
59
59
|
thread_safe (~> 0.3, >= 0.3.1)
|
60
|
-
builder (3.2.
|
60
|
+
builder (3.2.3)
|
61
61
|
childprocess (0.5.9)
|
62
62
|
ffi (~> 1.0, >= 1.0.11)
|
63
63
|
coercible (1.0.0)
|
@@ -82,20 +82,20 @@ GEM
|
|
82
82
|
jdbc-postgres (9.4.1206)
|
83
83
|
jdbc-sqlite3 (3.8.11.2)
|
84
84
|
jruby-openssl (0.9.18-java)
|
85
|
-
json (1.8.
|
86
|
-
killbill (8.3.
|
85
|
+
json (1.8.6-java)
|
86
|
+
killbill (8.3.1)
|
87
87
|
rack (>= 1.5.2)
|
88
88
|
sinatra (~> 1.3.4)
|
89
89
|
typhoeus (~> 0.6.9)
|
90
90
|
tzinfo (~> 1.2.0)
|
91
91
|
maven-tools (1.1.6)
|
92
92
|
virtus (~> 1.0)
|
93
|
-
minitest (5.
|
93
|
+
minitest (5.10.1)
|
94
94
|
monetize (1.1.0)
|
95
95
|
money (~> 6.5.0)
|
96
96
|
money (6.5.1)
|
97
97
|
i18n (>= 0.6.4, <= 0.7.0)
|
98
|
-
nokogiri (1.
|
98
|
+
nokogiri (1.7.0.1-java)
|
99
99
|
offsite_payments (2.1.0)
|
100
100
|
actionpack (>= 3.2.20, < 5.0.0)
|
101
101
|
active_utils (~> 3.0.0)
|
@@ -157,4 +157,4 @@ DEPENDENCIES
|
|
157
157
|
selenium-webdriver (~> 2.53.0)
|
158
158
|
|
159
159
|
BUNDLED WITH
|
160
|
-
1.
|
160
|
+
1.14.3
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
5.0.
|
1
|
+
5.0.4
|
data/lib/paypal_express/api.rb
CHANGED
@@ -3,6 +3,7 @@ module Killbill #:nodoc:
|
|
3
3
|
class PaymentPlugin < ::Killbill::Plugin::ActiveMerchant::PaymentPlugin
|
4
4
|
|
5
5
|
THREE_HOURS_AGO = (3*3600)
|
6
|
+
FIVE_MINUTES_AGO = 300
|
6
7
|
|
7
8
|
def initialize
|
8
9
|
gateway_builder = Proc.new do |config|
|
@@ -84,37 +85,32 @@ module Killbill #:nodoc:
|
|
84
85
|
end
|
85
86
|
|
86
87
|
def get_payment_info(kb_account_id, kb_payment_id, properties, context)
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
88
|
+
filtered_plugin_info, plugin_info, with_only_pending_trx = get_raw_payment_info(kb_payment_id, context)
|
89
|
+
|
90
|
+
return filtered_plugin_info if filtered_plugin_info.empty?
|
91
|
+
|
92
|
+
options = properties_to_hash(properties)
|
93
|
+
# We won't be in a state where we have both a pending and unknown plugin infos; so we just return here.
|
94
|
+
if fix_unknown_transactions(kb_payment_id, plugin_info, options, kb_account_id, context) ||
|
95
|
+
cancel_pending_transactions(filtered_plugin_info, with_only_pending_trx)
|
96
|
+
return get_raw_payment_info(kb_payment_id, context)[0]
|
94
97
|
end
|
95
|
-
# Should never happen...
|
96
|
-
return [] if t_info_plugins.nil?
|
97
98
|
|
98
|
-
|
99
|
-
|
100
|
-
target_transaction_types = [:PURCHASE, :AUTHORIZE]
|
101
|
-
only_pending_transaction = t_info_plugins.find { |t_info_plugin| target_transaction_types.include?(t_info_plugin.transaction_type) && t_info_plugin.status != :PENDING }.nil?
|
102
|
-
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 }
|
99
|
+
filtered_plugin_info
|
100
|
+
end
|
103
101
|
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
t_info_plugins
|
114
|
-
end
|
115
|
-
else
|
116
|
-
t_info_plugins_without_pending
|
102
|
+
def cancel_pending_transactions(t_info_plugins, only_pending_trx)
|
103
|
+
return false unless only_pending_trx && token_expired(t_info_plugins.last)
|
104
|
+
|
105
|
+
begin
|
106
|
+
cancel_pending_transaction(t_info_plugins.last).nil?
|
107
|
+
logger.info("Cancel pending kb_payment_id='#{t_info_plugins.last.kb_payment_id}', kb_payment_transaction_id='#{t_info_plugins.last.kb_transaction_payment_id}'")
|
108
|
+
return true
|
109
|
+
rescue => e
|
110
|
+
logger.warn("Unexpected exception while canceling pending kb_payment_id='#{t_info_plugins.last.kb_payment_id}', kb_payment_transaction_id='#{t_info_plugins.last.kb_transaction_payment_id}': #{e.message}\n#{e.backtrace.join("\n")}")
|
117
111
|
end
|
112
|
+
|
113
|
+
false
|
118
114
|
end
|
119
115
|
|
120
116
|
def search_payments(search_key, offset, limit, properties, context)
|
@@ -558,6 +554,78 @@ module Killbill #:nodoc:
|
|
558
554
|
end
|
559
555
|
sub_hash.empty? ? nil : sub_hash
|
560
556
|
end
|
557
|
+
|
558
|
+
def fix_unknown_transactions(payment_id, trx_plugin_info, options, kb_account_id, context)
|
559
|
+
unknown_transactions_info = trx_plugin_info.find_all { |t_info_plugin| t_info_plugin.status == :UNDEFINED }
|
560
|
+
now = Time.parse(@clock.get_clock.get_utc_now.to_s)
|
561
|
+
|
562
|
+
token = trx_plugin_info.map {|plugin_info| find_value_from_properties(plugin_info.properties, 'authorization')}.find {|token| !token.blank?}
|
563
|
+
if token.nil?
|
564
|
+
logger.warn("Unable to fix UNDEFINED kb_payment_id='#{payment_id}'. Unable to find its token.")
|
565
|
+
return false
|
566
|
+
end
|
567
|
+
|
568
|
+
need_refresh = false
|
569
|
+
payment_processor_account_id = find_payment_processor_id_from_initial_call(kb_account_id, context.tenant_id, token) || :default
|
570
|
+
unknown_transactions_info.each do |unknown_trx_info|
|
571
|
+
delay_since_transaction = now - unknown_trx_info.created_date
|
572
|
+
delay_since_transaction = 0 if delay_since_transaction < 0
|
573
|
+
|
574
|
+
# Do nothing before the delayed checking time
|
575
|
+
janitor_delay_threshold = (Killbill::Plugin::ActiveMerchant::Utils.normalized(options, :janitor_delay_threshold) || FIVE_MINUTES_AGO).to_i
|
576
|
+
next unless delay_since_transaction >= janitor_delay_threshold
|
577
|
+
|
578
|
+
paypal_response_id = find_value_from_properties(unknown_trx_info.properties, 'paypalExpressResponseId')
|
579
|
+
if paypal_response_id.nil?
|
580
|
+
logger.warn("Unable to fix UNDEFINED kb_transaction_id='#{unknown_trx_info.kb_transaction_payment_id}' (paypal_response_id not specified)")
|
581
|
+
next
|
582
|
+
end
|
583
|
+
response = PaypalExpressResponse.find_by(:id => paypal_response_id)
|
584
|
+
|
585
|
+
fixed = false
|
586
|
+
begin
|
587
|
+
gateway = lookup_gateway(payment_processor_account_id, context.tenant_id)
|
588
|
+
fixed = @private_api.fix_unknown_transaction(response, unknown_trx_info, gateway, kb_account_id, context.tenant_id)
|
589
|
+
logger.info("Unable to fix UNDEFINED kb_transaction_id='#{unknown_trx_info.kb_transaction_payment_id}' (not found in PayPal)") unless fixed
|
590
|
+
rescue => e
|
591
|
+
logger.warn("Unable to fix UNDEFINED kb_transaction_id='#{unknown_trx_info.kb_transaction_payment_id}': #{e.message}\n#{e.backtrace.join("\n")}")
|
592
|
+
end
|
593
|
+
|
594
|
+
if !fixed
|
595
|
+
# hard expiration limit
|
596
|
+
janitor_cancellation_threshold = (Killbill::Plugin::ActiveMerchant::Utils.normalized(options, :cancel_threshold) || THREE_HOURS_AGO).to_i
|
597
|
+
if delay_since_transaction >= janitor_cancellation_threshold
|
598
|
+
response.transition_to_plugin_failure
|
599
|
+
logger.info("Expire UNDEFINED kb_transaction_id='#{unknown_trx_info.kb_transaction_payment_id}' to CANCELED")
|
600
|
+
need_refresh = true
|
601
|
+
end
|
602
|
+
else
|
603
|
+
need_refresh = true
|
604
|
+
end
|
605
|
+
end
|
606
|
+
|
607
|
+
need_refresh
|
608
|
+
end
|
609
|
+
|
610
|
+
def get_raw_payment_info(kb_payment_id, context)
|
611
|
+
ignored_api_calls = [:details_for]
|
612
|
+
responses = @response_model.from_kb_payment_id(@transaction_model, kb_payment_id, context.tenant_id)
|
613
|
+
responses = responses.reject do |response|
|
614
|
+
ignored_api_calls.include?(response.api_call.to_sym)
|
615
|
+
end
|
616
|
+
t_info_plugins = responses.collect do |response|
|
617
|
+
response.to_transaction_info_plugin(response.send("#{@identifier}_transaction"))
|
618
|
+
end
|
619
|
+
|
620
|
+
# Completed purchases/authorizations will have two rows in the responses table (one for api_call 'build_form_descriptor', one for api_call 'purchase/authorize')
|
621
|
+
# Other transaction types don't support the :PENDING state
|
622
|
+
target_transaction_types = [:PURCHASE, :AUTHORIZE]
|
623
|
+
with_only_pending_trx = t_info_plugins.find { |t_info_plugin| target_transaction_types.include?(t_info_plugin.transaction_type) && t_info_plugin.status != :PENDING }.nil?
|
624
|
+
|
625
|
+
# Filter out the pending transaction if there is already a response tied with the same transaction but indicating a final state
|
626
|
+
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 }
|
627
|
+
[with_only_pending_trx ? t_info_plugins : t_info_plugins_without_pending, t_info_plugins, with_only_pending_trx]
|
628
|
+
end
|
561
629
|
end
|
562
630
|
end
|
563
631
|
end
|
@@ -146,6 +146,72 @@ module Killbill #:nodoc:
|
|
146
146
|
|
147
147
|
t_info_plugin
|
148
148
|
end
|
149
|
+
|
150
|
+
def transition_to_plugin_failure
|
151
|
+
transition_to_failure
|
152
|
+
end
|
153
|
+
|
154
|
+
def transition_to_payment_failure(transaction_id)
|
155
|
+
transition_to_failure false, {:authorization => transaction_id}
|
156
|
+
end
|
157
|
+
|
158
|
+
def transition_to_failure(is_plugin_failure = true, params = {})
|
159
|
+
begin
|
160
|
+
error_details = JSON.parse(message)
|
161
|
+
original_message = nil
|
162
|
+
rescue
|
163
|
+
error_details = {}
|
164
|
+
original_message = message
|
165
|
+
end
|
166
|
+
error_details['original_message'] = original_message unless original_message.blank?
|
167
|
+
error_details['payment_plugin_status'] = is_plugin_failure ? 'CANCELED' : 'ERROR'
|
168
|
+
|
169
|
+
updated_attributes = {
|
170
|
+
:message => error_details.to_json,
|
171
|
+
:success => false,
|
172
|
+
:updated_at => Time.now.utc
|
173
|
+
}.merge!(params)
|
174
|
+
|
175
|
+
# Update the response row
|
176
|
+
update!(updated_attributes)
|
177
|
+
end
|
178
|
+
|
179
|
+
def transition_to_success(transaction_id, trx_plugin_info)
|
180
|
+
begin
|
181
|
+
new_message = JSON.parse(message)
|
182
|
+
original_message = nil
|
183
|
+
rescue
|
184
|
+
new_message = {}
|
185
|
+
original_message = message
|
186
|
+
end
|
187
|
+
new_message['original_message'] = original_message unless original_message.blank?
|
188
|
+
new_message['payment_plugin_status'] = 'PROCESSED'
|
189
|
+
new_message['janitor'] = 'Janitor transitioned the response to success'
|
190
|
+
|
191
|
+
updated_attributes = {
|
192
|
+
:message => new_message.to_json,
|
193
|
+
:authorization => transaction_id,
|
194
|
+
:success => true,
|
195
|
+
:updated_at => Time.now.utc
|
196
|
+
}
|
197
|
+
|
198
|
+
# Update the response row
|
199
|
+
update!(updated_attributes)
|
200
|
+
|
201
|
+
# Create the transaction row if needed (cannot have been created before or the state wouldn't have been UNDEFINED)
|
202
|
+
build_paypal_express_transaction(:kb_account_id => kb_account_id,
|
203
|
+
:kb_tenant_id => kb_tenant_id,
|
204
|
+
:amount_in_cents => trx_plugin_info.amount,
|
205
|
+
:currency => trx_plugin_info.currency,
|
206
|
+
:api_call => api_call,
|
207
|
+
:kb_payment_id => kb_payment_id,
|
208
|
+
:kb_payment_transaction_id => kb_payment_transaction_id,
|
209
|
+
:transaction_type => transaction_type,
|
210
|
+
:payment_processor_account_id => payment_processor_account_id,
|
211
|
+
:txn_id => txn_id,
|
212
|
+
:created_at => updated_at,
|
213
|
+
:updated_at => updated_at).save!
|
214
|
+
end
|
149
215
|
end
|
150
216
|
end
|
151
217
|
end
|
@@ -1,6 +1,12 @@
|
|
1
1
|
module Killbill #:nodoc:
|
2
2
|
module PaypalExpress #:nodoc:
|
3
3
|
class PrivatePaymentPlugin < ::Killbill::Plugin::ActiveMerchant::PrivatePaymentPlugin
|
4
|
+
|
5
|
+
ONE_HOUR_AGO = 3600
|
6
|
+
STATUS = {:CAPTURE => {:success_status => 'Completed', :type => 'Payment'},
|
7
|
+
:AUTHORIZE => {:success_status => 'Pending', :type => 'Authorization'},
|
8
|
+
:REFUND => {:success_status => 'Completed', :type => 'Refund'}}
|
9
|
+
|
4
10
|
def initialize(session = {})
|
5
11
|
super(:paypal_express,
|
6
12
|
::Killbill::PaypalExpress::PaypalExpressPaymentMethod,
|
@@ -42,6 +48,30 @@ module Killbill #:nodoc:
|
|
42
48
|
context = kb_apis.create_context(kb_tenant_id)
|
43
49
|
kb_account_ids.map {|id| kb_apis.account_user_api.get_account_by_id(id, context).external_key }
|
44
50
|
end
|
51
|
+
|
52
|
+
def fix_unknown_transaction(plugin_response, trx_plugin_info, gateway, kb_account_id, kb_tenant_id)
|
53
|
+
status, transaction_id, type = search_transaction(trx_plugin_info.created_date - ONE_HOUR_AGO,
|
54
|
+
trx_plugin_info.amount,
|
55
|
+
trx_plugin_info.currency,
|
56
|
+
gateway,
|
57
|
+
trx_plugin_info.kb_transaction_payment_id)
|
58
|
+
return false if status.blank? || transaction_id.blank? || type.blank?
|
59
|
+
|
60
|
+
if type == STATUS[trx_plugin_info.transaction_type][:type] &&
|
61
|
+
status == STATUS[trx_plugin_info.transaction_type][:success_status]
|
62
|
+
plugin_response.transition_to_success transaction_id, trx_plugin_info
|
63
|
+
logger.info("Fixed UNDEFINED kb_transaction_id='#{trx_plugin_info.kb_transaction_payment_id}' to PROCESSED")
|
64
|
+
return true
|
65
|
+
end
|
66
|
+
|
67
|
+
false
|
68
|
+
end
|
69
|
+
|
70
|
+
def search_transaction(start_time, amount, currency, gateway, kb_payment_transaction_id)
|
71
|
+
options = {:start_date => start_time, :invoice_id => kb_payment_transaction_id, :amount => amount, :currency => currency}
|
72
|
+
response = gateway.transaction_search options
|
73
|
+
[response.params['status'], response.authorization, response.params['type']]
|
74
|
+
end
|
45
75
|
end
|
46
76
|
end
|
47
77
|
end
|
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>5.0.
|
29
|
+
<version>5.0.4</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>
|
@@ -13,6 +13,11 @@ shared_examples 'hpp_spec_common' do
|
|
13
13
|
@plugin.kb_apis.proxied_services[:payment_api].delete_all_payments
|
14
14
|
end
|
15
15
|
|
16
|
+
it 'should return an empty list of plugin info if payment does not exist' do
|
17
|
+
payment_plugin_info = @plugin.get_payment_info(@pm.kb_account_id, SecureRandom.uuid, [], @call_context)
|
18
|
+
payment_plugin_info.size.should == 0
|
19
|
+
end
|
20
|
+
|
16
21
|
it 'should generate forms correctly' do
|
17
22
|
::Killbill::PaypalExpress::PaypalExpressTransaction.count.should == 0
|
18
23
|
::Killbill::PaypalExpress::PaypalExpressResponse.count.should == 0
|
@@ -369,6 +374,105 @@ shared_examples 'hpp_spec_common' do
|
|
369
374
|
payment_infos[0].gateway_error.should == 'Token expired. Payment Canceled by Janitor.'
|
370
375
|
payment_infos[0].gateway_error_code.should be_nil
|
371
376
|
end
|
377
|
+
|
378
|
+
it 'should fix the unknown transactions to success' do
|
379
|
+
[:AUTHORIZE, :CAPTURE, :REFUND].each do |type|
|
380
|
+
payment_external_key = SecureRandom.uuid
|
381
|
+
properties = @plugin.hash_to_properties(
|
382
|
+
:transaction_external_key => payment_external_key,
|
383
|
+
:create_pending_payment => true,
|
384
|
+
:payment_processor_account_id => @payment_processor_account_id,
|
385
|
+
:auth_mode => true
|
386
|
+
)
|
387
|
+
form = @plugin.build_form_descriptor(@pm.kb_account_id, @form_fields, properties, @call_context)
|
388
|
+
kb_payment_id = validate_form_property(form, 'kb_payment_id')
|
389
|
+
kb_trx_id = validate_form_property(form, 'kb_transaction_id')
|
390
|
+
validate_token(form)
|
391
|
+
|
392
|
+
@plugin.authorize_payment(@pm.kb_account_id, kb_payment_id, kb_trx_id, @pm.kb_payment_method_id, @amount, @currency, properties, @call_context)
|
393
|
+
nb_plugin_info = 1
|
394
|
+
if type == :AUTHORIZE
|
395
|
+
verify_janitor_transition nb_plugin_info, type, :PROCESSED, kb_payment_id
|
396
|
+
# Be able to capture
|
397
|
+
payment_response = @plugin.capture_payment(@pm.kb_account_id, kb_payment_id, SecureRandom.uuid, @pm.kb_payment_method_id, @amount, @currency, properties, @call_context)
|
398
|
+
payment_response.status.should eq(:PROCESSED), payment_response.gateway_error
|
399
|
+
payment_response.amount.should == @amount
|
400
|
+
payment_response.transaction_type.should == :CAPTURE
|
401
|
+
elsif type == :CAPTURE
|
402
|
+
nb_plugin_info = 2
|
403
|
+
@plugin.capture_payment(@pm.kb_account_id, kb_payment_id, SecureRandom.uuid, @pm.kb_payment_method_id, @amount, @currency, properties, @call_context)
|
404
|
+
verify_janitor_transition nb_plugin_info, type, :PROCESSED, kb_payment_id
|
405
|
+
# Be able to refund
|
406
|
+
payment_response = @plugin.refund_payment(@pm.kb_account_id, kb_payment_id, SecureRandom.uuid, @pm.kb_payment_method_id, @amount, @currency, properties, @call_context)
|
407
|
+
payment_response.status.should eq(:PROCESSED), payment_response.gateway_error
|
408
|
+
payment_response.amount.should == @amount
|
409
|
+
payment_response.transaction_type.should == :REFUND
|
410
|
+
elsif type == :REFUND
|
411
|
+
nb_plugin_info = 3
|
412
|
+
@plugin.capture_payment(@pm.kb_account_id, kb_payment_id, SecureRandom.uuid, @pm.kb_payment_method_id, @amount, @currency, properties, @call_context)
|
413
|
+
@plugin.refund_payment(@pm.kb_account_id, kb_payment_id, SecureRandom.uuid, @pm.kb_payment_method_id, @amount, @currency, properties, @call_context)
|
414
|
+
verify_janitor_transition nb_plugin_info, type, :PROCESSED, kb_payment_id
|
415
|
+
end
|
416
|
+
end
|
417
|
+
end
|
418
|
+
|
419
|
+
it 'should fix the unknown transactions to plugin failure' do
|
420
|
+
[:AUTHORIZE, :CAPTURE, :REFUND].each do |type|
|
421
|
+
payment_external_key = SecureRandom.uuid
|
422
|
+
properties = @plugin.hash_to_properties(
|
423
|
+
:transaction_external_key => payment_external_key,
|
424
|
+
:create_pending_payment => true,
|
425
|
+
:payment_processor_account_id => @payment_processor_account_id,
|
426
|
+
:auth_mode => true
|
427
|
+
)
|
428
|
+
form = @plugin.build_form_descriptor(@pm.kb_account_id, @form_fields, properties, @call_context)
|
429
|
+
kb_payment_id = validate_form_property(form, 'kb_payment_id')
|
430
|
+
kb_trx_id = validate_form_property(form, 'kb_transaction_id')
|
431
|
+
validate_token(form)
|
432
|
+
|
433
|
+
properties = @plugin.hash_to_properties({:skip_gw => true})
|
434
|
+
@plugin.authorize_payment(@pm.kb_account_id, kb_payment_id, kb_trx_id, @pm.kb_payment_method_id, @amount, @currency, properties, @call_context)
|
435
|
+
nb_plugin_info = 1
|
436
|
+
if type == :CAPTURE
|
437
|
+
nb_plugin_info = 2
|
438
|
+
@plugin.capture_payment(@pm.kb_account_id, kb_payment_id, SecureRandom.uuid, @pm.kb_payment_method_id, @amount, @currency, properties, @call_context)
|
439
|
+
elsif type == :REFUND
|
440
|
+
nb_plugin_info = 3
|
441
|
+
@plugin.capture_payment(@pm.kb_account_id, kb_payment_id, SecureRandom.uuid, @pm.kb_payment_method_id, @amount, @currency, properties, @call_context)
|
442
|
+
@plugin.refund_payment(@pm.kb_account_id, kb_payment_id, SecureRandom.uuid, @pm.kb_payment_method_id, @amount, @currency, properties, @call_context)
|
443
|
+
end
|
444
|
+
verify_janitor_transition nb_plugin_info, type, :CANCELED, kb_payment_id
|
445
|
+
end
|
446
|
+
end
|
447
|
+
|
448
|
+
it 'should remain in unknown if cancellation period is not reached' do
|
449
|
+
[:AUTHORIZE, :CAPTURE, :REFUND].each do |type|
|
450
|
+
payment_external_key = SecureRandom.uuid
|
451
|
+
properties = @plugin.hash_to_properties(
|
452
|
+
:transaction_external_key => payment_external_key,
|
453
|
+
:create_pending_payment => true,
|
454
|
+
:payment_processor_account_id => @payment_processor_account_id,
|
455
|
+
:auth_mode => true
|
456
|
+
)
|
457
|
+
form = @plugin.build_form_descriptor(@pm.kb_account_id, @form_fields, properties, @call_context)
|
458
|
+
kb_payment_id = validate_form_property(form, 'kb_payment_id')
|
459
|
+
kb_trx_id = validate_form_property(form, 'kb_transaction_id')
|
460
|
+
validate_token(form)
|
461
|
+
|
462
|
+
properties = @plugin.hash_to_properties({:skip_gw => true})
|
463
|
+
@plugin.authorize_payment(@pm.kb_account_id, kb_payment_id, kb_trx_id, @pm.kb_payment_method_id, @amount, @currency, properties, @call_context)
|
464
|
+
nb_plugin_info = 1
|
465
|
+
if type == :CAPTURE
|
466
|
+
nb_plugin_info = 2
|
467
|
+
@plugin.capture_payment(@pm.kb_account_id, kb_payment_id, SecureRandom.uuid, @pm.kb_payment_method_id, @amount, @currency, properties, @call_context)
|
468
|
+
elsif type == :REFUND
|
469
|
+
nb_plugin_info = 3
|
470
|
+
@plugin.capture_payment(@pm.kb_account_id, kb_payment_id, SecureRandom.uuid, @pm.kb_payment_method_id, @amount, @currency, properties, @call_context)
|
471
|
+
@plugin.refund_payment(@pm.kb_account_id, kb_payment_id, SecureRandom.uuid, @pm.kb_payment_method_id, @amount, @currency, properties, @call_context)
|
472
|
+
end
|
473
|
+
verify_janitor_transition nb_plugin_info, type, :UNDEFINED, kb_payment_id, true, 3600*3
|
474
|
+
end
|
475
|
+
end
|
372
476
|
end
|
373
477
|
|
374
478
|
describe Killbill::PaypalExpress::PaymentPlugin do
|
@@ -312,6 +312,41 @@ module Killbill
|
|
312
312
|
payment_infos[0].gateway_error_code.should == gateway_error_code
|
313
313
|
end
|
314
314
|
|
315
|
+
def transition_last_response_to_UNDEFINED(expected_nb_transactions, kb_payment_id, delete_last_trx = true)
|
316
|
+
Killbill::PaypalExpress::PaypalExpressTransaction.last.delete if delete_last_trx
|
317
|
+
response = Killbill::PaypalExpress::PaypalExpressResponse.last
|
318
|
+
initial_auth = response.authorization
|
319
|
+
response.update(:authorization => nil, :message => {:payment_plugin_status => 'UNDEFINED'}.to_json)
|
320
|
+
|
321
|
+
skip_gw = Killbill::Plugin::Model::PluginProperty.new
|
322
|
+
skip_gw.key = 'skip_gw'
|
323
|
+
skip_gw.value = 'true'
|
324
|
+
properties_with_skip_gw = [skip_gw]
|
325
|
+
|
326
|
+
# Set skip_gw=true, to avoid calling the report API
|
327
|
+
transaction_info_plugins = @plugin.get_payment_info(@pm.kb_account_id, kb_payment_id, properties_with_skip_gw, @call_context)
|
328
|
+
transaction_info_plugins.size.should == expected_nb_transactions
|
329
|
+
transaction_info_plugins.last.status.should eq(:UNDEFINED)
|
330
|
+
|
331
|
+
[response, initial_auth]
|
332
|
+
end
|
333
|
+
|
334
|
+
def verify_janitor_transition(nb_trx_plugin_info, trx_type, trx_status, kb_payment_id, delete_last_trx = true, hard_expiration_date = 0, janitor_delay = 0)
|
335
|
+
transition_last_response_to_UNDEFINED(nb_trx_plugin_info, kb_payment_id, delete_last_trx)
|
336
|
+
# wait 5 sec for PayPal to populate the record in search endpoint
|
337
|
+
sleep 5
|
338
|
+
janitor_delay_threshold = Killbill::Plugin::Model::PluginProperty.new
|
339
|
+
janitor_delay_threshold.key = 'janitor_delay_threshold'
|
340
|
+
janitor_delay_threshold.value = janitor_delay
|
341
|
+
cancel_threshold = Killbill::Plugin::Model::PluginProperty.new
|
342
|
+
cancel_threshold.key = 'cancel_threshold'
|
343
|
+
cancel_threshold.value = hard_expiration_date
|
344
|
+
transaction_info_plugins = @plugin.get_payment_info(@pm.kb_account_id, kb_payment_id, [janitor_delay_threshold, cancel_threshold], @call_context)
|
345
|
+
transaction_info_plugins.size.should == nb_trx_plugin_info
|
346
|
+
transaction_info_plugins.last.status.should eq(trx_status)
|
347
|
+
transaction_info_plugins.last.transaction_type.should eq(trx_type)
|
348
|
+
end
|
349
|
+
|
315
350
|
private
|
316
351
|
|
317
352
|
def verify_payment_method(kb_account_id = nil)
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: killbill-paypal-express
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 5.0.
|
4
|
+
version: 5.0.4
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Kill Bill core team
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2017-
|
11
|
+
date: 2017-04-18 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
requirement: !ruby/object:Gem::Requirement
|