killbill-paypal-express 1.7.0 → 1.7.1
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 +4 -4
- data/.gitignore +1 -4
- data/Gemfile +1 -1
- data/Jarfile +7 -5
- data/LICENSE +201 -0
- data/README.md +1 -1
- data/Rakefile +2 -2
- data/VERSION +1 -1
- data/config.ru +1 -1
- data/db/ddl.sql +35 -7
- data/db/schema.rb +46 -18
- data/killbill-paypal-express.gemspec +13 -8
- data/lib/paypal_express.rb +10 -142
- data/lib/paypal_express/api.rb +177 -180
- data/lib/paypal_express/application.rb +101 -0
- data/lib/paypal_express/models/payment_method.rb +32 -0
- data/lib/paypal_express/models/response.rb +109 -0
- data/lib/paypal_express/models/transaction.rb +11 -0
- data/lib/paypal_express/private_api.rb +30 -43
- data/lib/paypal_express/views/form.erb +8 -0
- data/paypal_express.yml +22 -0
- data/pom.xml +4 -3
- data/release.sh +8 -8
- data/spec/paypal_express/base_plugin_spec.rb +29 -56
- data/spec/paypal_express/remote/integration_spec.rb +117 -136
- data/spec/spec_helper.rb +1 -14
- metadata +92 -29
- data/lib/paypal_express/config/application.rb +0 -55
- data/lib/paypal_express/config/configuration.rb +0 -50
- data/lib/paypal_express/config/properties.rb +0 -27
- data/lib/paypal_express/models/paypal_express_payment_method.rb +0 -140
- data/lib/paypal_express/models/paypal_express_response.rb +0 -235
- data/lib/paypal_express/models/paypal_express_transaction.rb +0 -48
- data/lib/paypal_express/paypal/gateway.rb +0 -26
- data/lib/paypal_express/paypal_express_utils.rb +0 -43
- data/spec/paypal_express/paypal_express_payment_method_spec.rb +0 -130
- data/spec/paypal_express/paypal_express_response_spec.rb +0 -84
- data/spec/paypal_express/streamy_result_set_spec.rb +0 -37
|
@@ -3,7 +3,7 @@ version = File.read(File.expand_path('../VERSION', __FILE__)).strip
|
|
|
3
3
|
Gem::Specification.new do |s|
|
|
4
4
|
s.name = 'killbill-paypal-express'
|
|
5
5
|
s.version = version
|
|
6
|
-
s.summary = 'Plugin to use Express Checkout as a gateway.'
|
|
6
|
+
s.summary = 'Plugin to use Paypal Express Checkout as a gateway.'
|
|
7
7
|
s.description = 'Kill Bill payment plugin for Paypal Express Checkout.'
|
|
8
8
|
|
|
9
9
|
s.required_ruby_version = '>= 1.9.3'
|
|
@@ -18,17 +18,22 @@ Gem::Specification.new do |s|
|
|
|
18
18
|
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
|
19
19
|
s.bindir = 'bin'
|
|
20
20
|
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
|
21
|
-
s.require_paths = [
|
|
21
|
+
s.require_paths = ['lib']
|
|
22
22
|
|
|
23
23
|
s.rdoc_options << '--exclude' << '.'
|
|
24
24
|
|
|
25
|
-
s.add_dependency 'killbill', '~> 3.
|
|
26
|
-
s.add_dependency 'activemerchant', '~> 1.
|
|
27
|
-
s.add_dependency '
|
|
28
|
-
s.add_dependency '
|
|
25
|
+
s.add_dependency 'killbill', '~> 3.1.8'
|
|
26
|
+
s.add_dependency 'activemerchant', '~> 1.44.1'
|
|
27
|
+
s.add_dependency 'offsite_payments', '~> 2.0.1'
|
|
28
|
+
s.add_dependency 'activerecord', '~> 4.1.0'
|
|
29
|
+
s.add_dependency 'actionpack', '~> 4.1.0'
|
|
30
|
+
s.add_dependency 'actionview', '~> 4.1.0'
|
|
31
|
+
s.add_dependency 'activesupport', '~> 4.1.0'
|
|
32
|
+
s.add_dependency 'money', '~> 6.1.1'
|
|
33
|
+
s.add_dependency 'monetize', '~> 0.3.0'
|
|
29
34
|
s.add_dependency 'sinatra', '~> 1.3.4'
|
|
30
35
|
if defined?(JRUBY_VERSION)
|
|
31
|
-
s.add_dependency 'activerecord-jdbcmysql-adapter', '~> 1.
|
|
36
|
+
s.add_dependency 'activerecord-jdbcmysql-adapter', '~> 1.3.7'
|
|
32
37
|
# Required to avoid errors like java.lang.NoClassDefFoundError: org/bouncycastle/asn1/DERBoolean
|
|
33
38
|
s.add_dependency 'jruby-openssl', '~> 0.9.4'
|
|
34
39
|
end
|
|
@@ -37,7 +42,7 @@ Gem::Specification.new do |s|
|
|
|
37
42
|
s.add_development_dependency 'rake', '>= 10.0.0'
|
|
38
43
|
s.add_development_dependency 'rspec', '~> 2.12.0'
|
|
39
44
|
if defined?(JRUBY_VERSION)
|
|
40
|
-
s.add_development_dependency 'activerecord-jdbcsqlite3-adapter', '~> 1.
|
|
45
|
+
s.add_development_dependency 'activerecord-jdbcsqlite3-adapter', '~> 1.3.7'
|
|
41
46
|
else
|
|
42
47
|
s.add_development_dependency 'sqlite3', '~> 1.3.7'
|
|
43
48
|
end
|
data/lib/paypal_express.rb
CHANGED
|
@@ -1,156 +1,24 @@
|
|
|
1
|
+
require 'action_controller'
|
|
1
2
|
require 'active_record'
|
|
2
|
-
require '
|
|
3
|
+
require 'action_view'
|
|
4
|
+
require 'active_merchant'
|
|
5
|
+
require 'active_support'
|
|
3
6
|
require 'bigdecimal'
|
|
4
7
|
require 'money'
|
|
8
|
+
require 'monetize'
|
|
9
|
+
require 'offsite_payments'
|
|
5
10
|
require 'pathname'
|
|
6
11
|
require 'sinatra'
|
|
7
12
|
require 'singleton'
|
|
8
13
|
require 'yaml'
|
|
9
14
|
|
|
10
15
|
require 'killbill'
|
|
11
|
-
|
|
12
|
-
require 'paypal_express/config/configuration'
|
|
13
|
-
require 'paypal_express/config/properties'
|
|
14
|
-
|
|
15
|
-
require 'paypal_express/paypal/gateway'
|
|
16
|
-
|
|
17
|
-
require 'paypal_express/models/paypal_express_payment_method'
|
|
18
|
-
require 'paypal_express/models/paypal_express_response'
|
|
19
|
-
require 'paypal_express/models/paypal_express_transaction'
|
|
20
|
-
|
|
21
|
-
require 'paypal_express/paypal_express_utils'
|
|
16
|
+
require 'killbill/helpers/active_merchant'
|
|
22
17
|
|
|
23
18
|
require 'paypal_express/api'
|
|
24
19
|
require 'paypal_express/private_api'
|
|
25
20
|
|
|
21
|
+
require 'paypal_express/models/payment_method'
|
|
22
|
+
require 'paypal_express/models/response'
|
|
23
|
+
require 'paypal_express/models/transaction'
|
|
26
24
|
|
|
27
|
-
# Thank you Rails for the following!
|
|
28
|
-
|
|
29
|
-
class Object
|
|
30
|
-
def blank?
|
|
31
|
-
respond_to?(:empty?) ? empty? : !self
|
|
32
|
-
end
|
|
33
|
-
end
|
|
34
|
-
|
|
35
|
-
class Hash
|
|
36
|
-
# Return a new hash with all keys converted to symbols, as long as
|
|
37
|
-
# they respond to +to_sym+. This includes the keys from the root hash
|
|
38
|
-
# and from all nested hashes.
|
|
39
|
-
#
|
|
40
|
-
# hash = { 'person' => { 'name' => 'Rob', 'age' => '28' } }
|
|
41
|
-
#
|
|
42
|
-
# hash.deep_symbolize_keys
|
|
43
|
-
# # => { person: { name: "Rob", age: "28" } }
|
|
44
|
-
def deep_symbolize_keys
|
|
45
|
-
deep_transform_keys { |key| key.to_sym rescue key }
|
|
46
|
-
end
|
|
47
|
-
|
|
48
|
-
# Return a new hash with all keys converted by the block operation.
|
|
49
|
-
# This includes the keys from the root hash and from all
|
|
50
|
-
# nested hashes.
|
|
51
|
-
#
|
|
52
|
-
# hash = { person: { name: 'Rob', age: '28' } }
|
|
53
|
-
#
|
|
54
|
-
# hash.deep_transform_keys{ |key| key.to_s.upcase }
|
|
55
|
-
# # => { "PERSON" => { "NAME" => "Rob", "AGE" => "28" } }
|
|
56
|
-
def deep_transform_keys(&block)
|
|
57
|
-
result = {}
|
|
58
|
-
each do |key, value|
|
|
59
|
-
result[yield(key)] = value.is_a?(Hash) ? value.deep_transform_keys(&block) : value
|
|
60
|
-
end
|
|
61
|
-
result
|
|
62
|
-
end
|
|
63
|
-
|
|
64
|
-
# By default, only instances of Hash itself are extractable.
|
|
65
|
-
# Subclasses of Hash may implement this method and return
|
|
66
|
-
# true to declare themselves as extractable. If a Hash
|
|
67
|
-
# is extractable, Array#extract_options! pops it from
|
|
68
|
-
# the Array when it is the last element of the Array.
|
|
69
|
-
def extractable_options?
|
|
70
|
-
instance_of?(Hash)
|
|
71
|
-
end
|
|
72
|
-
end
|
|
73
|
-
|
|
74
|
-
class Array
|
|
75
|
-
# Extracts options from a set of arguments. Removes and returns the last
|
|
76
|
-
# element in the array if it's a hash, otherwise returns a blank hash.
|
|
77
|
-
#
|
|
78
|
-
# def options(*args)
|
|
79
|
-
# args.extract_options!
|
|
80
|
-
# end
|
|
81
|
-
#
|
|
82
|
-
# options(1, 2) # => {}
|
|
83
|
-
# options(1, 2, a: :b) # => {:a=>:b}
|
|
84
|
-
def extract_options!
|
|
85
|
-
if last.is_a?(Hash) && last.extractable_options?
|
|
86
|
-
pop
|
|
87
|
-
else
|
|
88
|
-
{}
|
|
89
|
-
end
|
|
90
|
-
end
|
|
91
|
-
end
|
|
92
|
-
|
|
93
|
-
class Module
|
|
94
|
-
def mattr_reader(*syms)
|
|
95
|
-
options = syms.extract_options!
|
|
96
|
-
syms.each do |sym|
|
|
97
|
-
raise NameError.new('invalid attribute name') unless sym =~ /^[_A-Za-z]\w*$/
|
|
98
|
-
class_eval(<<-EOS, __FILE__, __LINE__ + 1)
|
|
99
|
-
@@#{sym} = nil unless defined? @@#{sym}
|
|
100
|
-
|
|
101
|
-
def self.#{sym}
|
|
102
|
-
@@#{sym}
|
|
103
|
-
end
|
|
104
|
-
EOS
|
|
105
|
-
|
|
106
|
-
unless options[:instance_reader] == false || options[:instance_accessor] == false
|
|
107
|
-
class_eval(<<-EOS, __FILE__, __LINE__ + 1)
|
|
108
|
-
def #{sym}
|
|
109
|
-
@@#{sym}
|
|
110
|
-
end
|
|
111
|
-
EOS
|
|
112
|
-
end
|
|
113
|
-
end
|
|
114
|
-
end
|
|
115
|
-
|
|
116
|
-
def mattr_writer(*syms)
|
|
117
|
-
options = syms.extract_options!
|
|
118
|
-
syms.each do |sym|
|
|
119
|
-
raise NameError.new('invalid attribute name') unless sym =~ /^[_A-Za-z]\w*$/
|
|
120
|
-
class_eval(<<-EOS, __FILE__, __LINE__ + 1)
|
|
121
|
-
def self.#{sym}=(obj)
|
|
122
|
-
@@#{sym} = obj
|
|
123
|
-
end
|
|
124
|
-
EOS
|
|
125
|
-
|
|
126
|
-
unless options[:instance_writer] == false || options[:instance_accessor] == false
|
|
127
|
-
class_eval(<<-EOS, __FILE__, __LINE__ + 1)
|
|
128
|
-
def #{sym}=(obj)
|
|
129
|
-
@@#{sym} = obj
|
|
130
|
-
end
|
|
131
|
-
EOS
|
|
132
|
-
end
|
|
133
|
-
end
|
|
134
|
-
end
|
|
135
|
-
|
|
136
|
-
# Extends the module object with module and instance accessors for class attributes,
|
|
137
|
-
# just like the native attr* accessors for instance attributes.
|
|
138
|
-
#
|
|
139
|
-
# module AppConfiguration
|
|
140
|
-
# mattr_accessor :google_api_key
|
|
141
|
-
#
|
|
142
|
-
# self.google_api_key = "123456789"
|
|
143
|
-
# end
|
|
144
|
-
#
|
|
145
|
-
# AppConfiguration.google_api_key # => "123456789"
|
|
146
|
-
# AppConfiguration.google_api_key = "overriding the api key!"
|
|
147
|
-
# AppConfiguration.google_api_key # => "overriding the api key!"
|
|
148
|
-
#
|
|
149
|
-
# To opt out of the instance writer method, pass <tt>instance_writer: false</tt>.
|
|
150
|
-
# To opt out of the instance reader method, pass <tt>instance_reader: false</tt>.
|
|
151
|
-
# To opt out of both instance methods, pass <tt>instance_accessor: false</tt>.
|
|
152
|
-
def mattr_accessor(*syms)
|
|
153
|
-
mattr_reader(*syms)
|
|
154
|
-
mattr_writer(*syms)
|
|
155
|
-
end
|
|
156
|
-
end
|
data/lib/paypal_express/api.rb
CHANGED
|
@@ -1,235 +1,232 @@
|
|
|
1
|
-
module Killbill
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
1
|
+
module Killbill #:nodoc:
|
|
2
|
+
module PaypalExpress #:nodoc:
|
|
3
|
+
class PaymentPlugin < ::Killbill::Plugin::ActiveMerchant::PaymentPlugin
|
|
4
|
+
|
|
5
|
+
def initialize
|
|
6
|
+
gateway_builder = Proc.new do |config|
|
|
7
|
+
::ActiveMerchant::Billing::PaypalExpressGateway.new :signature => config[:signature],
|
|
8
|
+
:login => config[:login],
|
|
9
|
+
:password => config[:password]
|
|
10
|
+
end
|
|
6
11
|
|
|
7
|
-
|
|
12
|
+
super(gateway_builder,
|
|
13
|
+
:paypal_express,
|
|
14
|
+
::Killbill::PaypalExpress::PaypalExpressPaymentMethod,
|
|
15
|
+
::Killbill::PaypalExpress::PaypalExpressTransaction,
|
|
16
|
+
::Killbill::PaypalExpress::PaypalExpressResponse)
|
|
8
17
|
|
|
9
|
-
|
|
18
|
+
@ip = ::Killbill::Plugin::ActiveMerchant::Utils.ip
|
|
19
|
+
end
|
|
10
20
|
|
|
11
|
-
|
|
12
|
-
|
|
21
|
+
def authorize_payment(kb_account_id, kb_payment_id, kb_payment_transaction_id, kb_payment_method_id, amount, currency, properties, context)
|
|
22
|
+
# Pass extra parameters for the gateway here
|
|
23
|
+
options = {}
|
|
13
24
|
|
|
14
|
-
|
|
15
|
-
def after_request
|
|
16
|
-
ActiveRecord::Base.connection.close
|
|
17
|
-
end
|
|
25
|
+
add_required_options(kb_payment_transaction_id, kb_payment_method_id, context, options)
|
|
18
26
|
|
|
19
|
-
|
|
20
|
-
# Use Money to compute the amount in cents, as it depends on the currency (1 cent of BTC is 1 Satoshi, not 0.01 BTC)
|
|
21
|
-
amount_in_cents = Money.new_with_amount(amount, currency).cents.to_i
|
|
27
|
+
properties = merge_properties(properties, options)
|
|
22
28
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
29
|
+
# Can't use default implementation: the authorize signature is for one-off payments only
|
|
30
|
+
#super(kb_account_id, kb_payment_id, kb_payment_transaction_id, kb_payment_method_id, amount, currency, properties, context)
|
|
31
|
+
gateway_call_proc = Proc.new do |gateway, linked_transaction, payment_source, amount_in_cents, options|
|
|
32
|
+
gateway.authorize_reference_transaction(amount_in_cents, options)
|
|
33
|
+
end
|
|
26
34
|
|
|
27
|
-
|
|
28
|
-
|
|
35
|
+
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)
|
|
36
|
+
end
|
|
29
37
|
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
38
|
+
def capture_payment(kb_account_id, kb_payment_id, kb_payment_transaction_id, kb_payment_method_id, amount, currency, properties, context)
|
|
39
|
+
# Pass extra parameters for the gateway here
|
|
40
|
+
options = {
|
|
41
|
+
# NotComplete to allow for partial captures.
|
|
42
|
+
# If Complete, any remaining amount of the original authorized transaction is automatically voided and all remaining open authorizations are voided.
|
|
43
|
+
:complete_type => 'NotComplete'
|
|
44
|
+
}
|
|
35
45
|
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
options[:reference_id] = payment_method.paypal_express_baid
|
|
46
|
+
properties = merge_properties(properties, options)
|
|
47
|
+
super(kb_account_id, kb_payment_id, kb_payment_transaction_id, kb_payment_method_id, amount, currency, properties, context)
|
|
39
48
|
end
|
|
40
49
|
|
|
50
|
+
def purchase_payment(kb_account_id, kb_payment_id, kb_payment_transaction_id, kb_payment_method_id, amount, currency, properties, context)
|
|
51
|
+
# Pass extra parameters for the gateway here
|
|
52
|
+
options = {}
|
|
41
53
|
|
|
42
|
-
|
|
43
|
-
paypal_response = @gateway.reference_transaction actual_amount, options
|
|
44
|
-
response = save_response_and_transaction paypal_response, :charge, kb_payment_id, actual_amount, actual_currency
|
|
45
|
-
|
|
46
|
-
response.to_payment_response
|
|
47
|
-
end
|
|
54
|
+
add_required_options(kb_payment_transaction_id, kb_payment_method_id, context, options)
|
|
48
55
|
|
|
49
|
-
|
|
50
|
-
paypal_express_transaction = PaypalExpressTransaction.from_kb_payment_id(kb_payment_id)
|
|
56
|
+
properties = merge_properties(properties, options)
|
|
51
57
|
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
58
|
+
# Can't use default implementation: the purchase signature is for one-off payments only
|
|
59
|
+
#super(kb_account_id, kb_payment_id, kb_payment_transaction_id, kb_payment_method_id, amount, currency, properties, context)
|
|
60
|
+
gateway_call_proc = Proc.new do |gateway, linked_transaction, payment_source, amount_in_cents, options|
|
|
61
|
+
gateway.reference_transaction(amount_in_cents, options)
|
|
62
|
+
end
|
|
56
63
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
amount_in_cents = Money.new_with_amount(amount, currency).cents.to_i
|
|
64
|
+
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)
|
|
65
|
+
end
|
|
60
66
|
|
|
61
|
-
|
|
62
|
-
|
|
67
|
+
def void_payment(kb_account_id, kb_payment_id, kb_payment_transaction_id, kb_payment_method_id, properties, context)
|
|
68
|
+
# Pass extra parameters for the gateway here
|
|
69
|
+
options = {
|
|
70
|
+
# Void the original authorization
|
|
71
|
+
:linked_transaction_type => :authorize
|
|
72
|
+
}
|
|
63
73
|
|
|
64
|
-
|
|
74
|
+
properties = merge_properties(properties, options)
|
|
75
|
+
super(kb_account_id, kb_payment_id, kb_payment_transaction_id, kb_payment_method_id, properties, context)
|
|
76
|
+
end
|
|
65
77
|
|
|
66
|
-
|
|
67
|
-
|
|
78
|
+
def credit_payment(kb_account_id, kb_payment_id, kb_payment_transaction_id, kb_payment_method_id, amount, currency, properties, context)
|
|
79
|
+
# Pass extra parameters for the gateway here
|
|
80
|
+
options = {}
|
|
68
81
|
|
|
69
|
-
|
|
82
|
+
properties = merge_properties(properties, options)
|
|
83
|
+
super(kb_account_id, kb_payment_id, kb_payment_transaction_id, kb_payment_method_id, amount, currency, properties, context)
|
|
84
|
+
end
|
|
70
85
|
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
86
|
+
def refund_payment(kb_account_id, kb_payment_id, kb_payment_transaction_id, kb_payment_method_id, amount, currency, properties, context)
|
|
87
|
+
# Cannot refund based on authorizations (default behavior)
|
|
88
|
+
linked_transaction_type = @transaction_model.purchases_from_kb_payment_id(kb_payment_id, context.tenant_id).size > 0 ? :purchase : :capture
|
|
74
89
|
|
|
75
|
-
|
|
76
|
-
|
|
90
|
+
# Pass extra parameters for the gateway here
|
|
91
|
+
options = {
|
|
92
|
+
:linked_transaction_type => linked_transaction_type
|
|
93
|
+
}
|
|
77
94
|
|
|
78
|
-
|
|
79
|
-
|
|
95
|
+
properties = merge_properties(properties, options)
|
|
96
|
+
super(kb_account_id, kb_payment_id, kb_payment_transaction_id, kb_payment_method_id, amount, currency, properties, context)
|
|
97
|
+
end
|
|
80
98
|
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
end
|
|
99
|
+
def get_payment_info(kb_account_id, kb_payment_id, properties, context)
|
|
100
|
+
# Pass extra parameters for the gateway here
|
|
101
|
+
options = {}
|
|
85
102
|
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
# The payment method should have been created during the setup step (see private api)
|
|
91
|
-
payment_method = PaypalExpressPaymentMethod.from_kb_account_id_and_token(kb_account_id, token)
|
|
92
|
-
|
|
93
|
-
# Go to Paypal to get the Payer id (GetExpressCheckoutDetails call)
|
|
94
|
-
paypal_express_details_response = @gateway.details_for token
|
|
95
|
-
response = save_response_and_transaction paypal_express_details_response, :details_for
|
|
96
|
-
return false unless response.success?
|
|
97
|
-
|
|
98
|
-
payer_id = response.payer_id
|
|
99
|
-
unless payer_id.nil?
|
|
100
|
-
# Go to Paypal to create the BAID for recurring payments (CreateBillingAgreement call)
|
|
101
|
-
paypal_express_baid_response = @gateway.store token
|
|
102
|
-
response = save_response_and_transaction paypal_express_baid_response, :create_billing_agreement
|
|
103
|
-
return false unless response.success?
|
|
104
|
-
|
|
105
|
-
if response.billing_agreement_id.blank?
|
|
106
|
-
# If the baid isn't specified (invalid token, maybe expired?), we won't be able to charge that payment method
|
|
107
|
-
# See https://github.com/killbill/killbill-paypal-express-plugin/issues/1
|
|
108
|
-
logger.warn "No BAID returned by the CreateBillingAgreement call for token #{token} (account #{kb_account_id})"
|
|
109
|
-
return false
|
|
110
|
-
end
|
|
103
|
+
properties = merge_properties(properties, options)
|
|
104
|
+
super(kb_account_id, kb_payment_id, properties, context)
|
|
105
|
+
end
|
|
111
106
|
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
payment_method.save!
|
|
107
|
+
def search_payments(search_key, offset, limit, properties, context)
|
|
108
|
+
# Pass extra parameters for the gateway here
|
|
109
|
+
options = {}
|
|
116
110
|
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
else
|
|
120
|
-
logger.warn "Unable to retrieve Payer id details for token #{token} (account #{kb_account_id})"
|
|
121
|
-
false
|
|
111
|
+
properties = merge_properties(properties, options)
|
|
112
|
+
super(search_key, offset, limit, properties, context)
|
|
122
113
|
end
|
|
123
|
-
end
|
|
124
114
|
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
115
|
+
def add_payment_method(kb_account_id, kb_payment_method_id, payment_method_props, set_default, properties, context)
|
|
116
|
+
token = find_value_from_properties(properties, 'token')
|
|
117
|
+
return false if token.nil?
|
|
118
|
+
|
|
119
|
+
# Go to Paypal to get the Payer id (GetExpressCheckoutDetails call)
|
|
120
|
+
options = properties_to_hash(properties)
|
|
121
|
+
payment_processor_account_id = options[:payment_processor_account_id] || :default
|
|
122
|
+
gateway = lookup_gateway(payment_processor_account_id)
|
|
123
|
+
gw_response = gateway.details_for(token)
|
|
124
|
+
response, transaction = save_response_and_transaction(gw_response, :details_for, kb_account_id, context.tenant_id, payment_processor_account_id)
|
|
125
|
+
return false unless response.success? and !response.payer_id.blank?
|
|
126
|
+
|
|
127
|
+
# Pass extra parameters for the gateway here
|
|
128
|
+
options = {
|
|
129
|
+
:paypal_express_token => token,
|
|
130
|
+
:paypal_express_payer_id => response.payer_id
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
properties = merge_properties(properties, options)
|
|
134
|
+
super(kb_account_id, kb_payment_method_id, payment_method_props, set_default, properties, context)
|
|
135
|
+
end
|
|
128
136
|
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
137
|
+
def delete_payment_method(kb_account_id, kb_payment_method_id, properties, context)
|
|
138
|
+
# Pass extra parameters for the gateway here
|
|
139
|
+
options = {}
|
|
132
140
|
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
141
|
+
properties = merge_properties(properties, options)
|
|
142
|
+
super(kb_account_id, kb_payment_method_id, properties, context)
|
|
143
|
+
end
|
|
136
144
|
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
145
|
+
def get_payment_method_detail(kb_account_id, kb_payment_method_id, properties, context)
|
|
146
|
+
# Pass extra parameters for the gateway here
|
|
147
|
+
options = {}
|
|
140
148
|
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
paypal_pms = PaypalExpressPaymentMethod.from_kb_account_id(kb_account_id)
|
|
145
|
-
|
|
146
|
-
payment_methods.delete_if do |payment_method_info_plugin|
|
|
147
|
-
should_be_deleted = false
|
|
148
|
-
paypal_pms.each do |paypal_pm|
|
|
149
|
-
# Do paypal_pm and payment_method_info_plugin represent the same PayPal payment method?
|
|
150
|
-
if paypal_pm.external_payment_method_id == payment_method_info_plugin.external_payment_method_id
|
|
151
|
-
# Do we already have a kb_payment_method_id?
|
|
152
|
-
if paypal_pm.kb_payment_method_id == payment_method_info_plugin.payment_method_id
|
|
153
|
-
should_be_deleted = true
|
|
154
|
-
break
|
|
155
|
-
elsif paypal_pm.kb_payment_method_id.nil?
|
|
156
|
-
# We didn't have the kb_payment_method_id - update it
|
|
157
|
-
paypal_pm.kb_payment_method_id = payment_method_info_plugin.payment_method_id
|
|
158
|
-
should_be_deleted = paypal_pm.save
|
|
159
|
-
break
|
|
160
|
-
# Otherwise the same BAID points to 2 different kb_payment_method_id. This should never happen,
|
|
161
|
-
# but we cowardly will insert a second row below
|
|
162
|
-
end
|
|
163
|
-
end
|
|
164
|
-
end
|
|
149
|
+
properties = merge_properties(properties, options)
|
|
150
|
+
super(kb_account_id, kb_payment_method_id, properties, context)
|
|
151
|
+
end
|
|
165
152
|
|
|
166
|
-
|
|
153
|
+
def set_default_payment_method(kb_account_id, kb_payment_method_id, properties, context)
|
|
154
|
+
# TODO
|
|
167
155
|
end
|
|
168
156
|
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
157
|
+
def get_payment_methods(kb_account_id, refresh_from_gateway, properties, context)
|
|
158
|
+
# Pass extra parameters for the gateway here
|
|
159
|
+
options = {}
|
|
160
|
+
|
|
161
|
+
properties = merge_properties(properties, options)
|
|
162
|
+
super(kb_account_id, refresh_from_gateway, properties, context)
|
|
175
163
|
end
|
|
176
|
-
end
|
|
177
164
|
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
165
|
+
def search_payment_methods(search_key, offset, limit, properties, context)
|
|
166
|
+
# Pass extra parameters for the gateway here
|
|
167
|
+
options = {}
|
|
181
168
|
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
169
|
+
properties = merge_properties(properties, options)
|
|
170
|
+
super(search_key, offset, limit, properties, context)
|
|
171
|
+
end
|
|
185
172
|
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
173
|
+
def reset_payment_methods(kb_account_id, payment_methods, properties, context)
|
|
174
|
+
super
|
|
175
|
+
end
|
|
189
176
|
|
|
190
|
-
|
|
177
|
+
def build_form_descriptor(kb_account_id, descriptor_fields, properties, context)
|
|
178
|
+
# Pass extra parameters for the gateway here
|
|
179
|
+
options = {}
|
|
180
|
+
properties = merge_properties(properties, options)
|
|
191
181
|
|
|
192
|
-
|
|
182
|
+
# Add your custom static hidden tags here
|
|
183
|
+
options = {
|
|
184
|
+
#:token => config[:paypal-express][:token]
|
|
185
|
+
}
|
|
186
|
+
descriptor_fields = merge_properties(descriptor_fields, options)
|
|
193
187
|
|
|
194
|
-
|
|
195
|
-
|
|
188
|
+
super(kb_account_id, descriptor_fields, properties, context)
|
|
189
|
+
end
|
|
196
190
|
|
|
197
|
-
|
|
191
|
+
def process_notification(notification, properties, context)
|
|
192
|
+
# Pass extra parameters for the gateway here
|
|
193
|
+
options = {}
|
|
194
|
+
properties = merge_properties(properties, options)
|
|
195
|
+
|
|
196
|
+
super(notification, properties, context) do |gw_notification, service|
|
|
197
|
+
# Retrieve the payment
|
|
198
|
+
# gw_notification.kb_payment_id =
|
|
199
|
+
#
|
|
200
|
+
# Set the response body
|
|
201
|
+
# gw_notification.entity =
|
|
202
|
+
end
|
|
203
|
+
end
|
|
198
204
|
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
205
|
+
def to_express_checkout_url(response, options = {})
|
|
206
|
+
payment_processor_account_id = options[:payment_processor_account_id] || :default
|
|
207
|
+
gateway = lookup_gateway(payment_processor_account_id)
|
|
208
|
+
gateway.redirect_url_for(response.token)
|
|
203
209
|
end
|
|
204
210
|
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
211
|
+
protected
|
|
212
|
+
|
|
213
|
+
def get_active_merchant_module
|
|
214
|
+
::OffsitePayments.integration(:paypal)
|
|
208
215
|
end
|
|
209
216
|
|
|
210
|
-
|
|
211
|
-
conversion_rate = found[0].value
|
|
212
|
-
output_amount = input_amount * conversion_rate
|
|
213
|
-
return [output_amount.to_i, converted_currency]
|
|
214
|
-
end
|
|
217
|
+
private
|
|
215
218
|
|
|
216
|
-
|
|
217
|
-
|
|
219
|
+
def add_required_options(kb_payment_transaction_id, kb_payment_method_id, context, options)
|
|
220
|
+
payment_method = @payment_method_model.from_kb_payment_method_id(kb_payment_method_id, context.tenant_id)
|
|
218
221
|
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
+
options[:payer_id] ||= payment_method.paypal_express_payer_id
|
|
223
|
+
options[:token] ||= payment_method.paypal_express_token
|
|
224
|
+
options[:reference_id] ||= payment_method.token # baid
|
|
222
225
|
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
:currency => currency,
|
|
227
|
-
:api_call => api_call,
|
|
228
|
-
:kb_payment_id => kb_payment_id,
|
|
229
|
-
:paypal_express_txn_id => response.authorization)
|
|
230
|
-
@logger.debug "Recorded transaction: #{transaction.inspect}"
|
|
226
|
+
options[:payment_type] ||= 'Any'
|
|
227
|
+
options[:invoice_id] ||= kb_payment_transaction_id
|
|
228
|
+
options[:ip] ||= @ip
|
|
231
229
|
end
|
|
232
|
-
response
|
|
233
230
|
end
|
|
234
231
|
end
|
|
235
232
|
end
|