active_paypal_adaptive_payment 0.1.2 → 0.2.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.
- data/CHANGELOG.md +12 -0
- data/lib/active_merchant/billing/gateways/paypal_adaptive_payment.rb +249 -258
- data/lib/active_merchant/billing/gateways/paypal_adaptive_payments/adaptive_payment_response.rb +37 -119
- data/lib/active_merchant/billing/gateways/paypal_adaptive_payments/ext.rb +9 -7
- data/lib/active_paypal_adaptive_payment.rb +1 -10
- data/{README.markdown → readme.md} +24 -15
- metadata +26 -18
- data/CHANGELOG +0 -0
- data/lib/active_merchant/billing/gateways/paypal_adaptive_payments/utils.rb +0 -8
data/CHANGELOG.md
ADDED
@@ -1,308 +1,299 @@
|
|
1
1
|
# -*- coding: utf-8 -*-
|
2
2
|
dir = File.dirname(__FILE__)
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
require dir
|
7
|
-
require 'json/add/rails'
|
3
|
+
[ '/paypal_adaptive_payments/exceptions.rb',
|
4
|
+
'/paypal_adaptive_payments/adaptive_payment_response.rb',
|
5
|
+
'/paypal_adaptive_payments/ext.rb'
|
6
|
+
].each { |f| require File.join(dir, f) }
|
8
7
|
|
9
|
-
|
8
|
+
require 'money'
|
10
9
|
|
11
|
-
|
12
|
-
|
10
|
+
module ActiveMerchant #:nodoc:
|
11
|
+
module Billing #:nodoc:
|
12
|
+
class PaypalAdaptivePayment < Gateway # :nodoc:
|
13
13
|
|
14
|
-
|
15
|
-
|
14
|
+
TEST_URL = 'https://svcs.sandbox.paypal.com/AdaptivePayments/'
|
15
|
+
LIVE_URL = 'https://svcs.paypal.com/AdaptivePayments/'
|
16
16
|
|
17
|
-
|
18
|
-
|
17
|
+
EMBEDDED_FLOW_TEST_URL = 'https://www.sandbox.paypal.com/webapps/adaptivepayment/flow/pay'
|
18
|
+
EMBEDDED_FLOW_LIVE_URL = 'https://www.paypal.com/webapps/adaptivepayment/flow/pay'
|
19
19
|
|
20
|
-
|
21
|
-
|
20
|
+
module FeesPayer
|
21
|
+
OPTIONS = %w(SENDER PRIMARYRECEIVER EACHRECEIVER SECONDARYONLY)
|
22
|
+
OPTIONS.each { |opt| const_set(opt, opt) }
|
23
|
+
end
|
22
24
|
|
23
|
-
|
24
|
-
|
25
|
+
module PaymentType
|
26
|
+
TYPES = %w(DIGITALGOODS)
|
27
|
+
TYPES.each { |pt| const_set(pt, pt) }
|
28
|
+
end
|
25
29
|
|
26
|
-
|
27
|
-
|
30
|
+
# The countries the gateway supports merchants from as 2 digit ISO country codes
|
31
|
+
self.supported_countries = ['US']
|
28
32
|
|
29
|
-
|
30
|
-
|
31
|
-
if options.empty?
|
32
|
-
load_config
|
33
|
-
else
|
34
|
-
@config.merge! options
|
35
|
-
end
|
36
|
-
end
|
33
|
+
# The homepage URL of the gateway
|
34
|
+
self.homepage_url = 'http://x.com/'
|
37
35
|
|
38
|
-
|
39
|
-
|
40
|
-
end
|
36
|
+
# The name of the gateway
|
37
|
+
self.display_name = 'Paypal Adaptive Payments'
|
41
38
|
|
42
|
-
|
43
|
-
|
44
|
-
|
39
|
+
def initialize(config = {})
|
40
|
+
requires!(config, :login, :password, :signature, :appid)
|
41
|
+
@config = config.dup
|
42
|
+
super
|
43
|
+
end
|
45
44
|
|
46
|
-
|
47
|
-
|
48
|
-
|
45
|
+
def pay(options)
|
46
|
+
commit('Pay', build_adaptive_payment_pay_request(options))
|
47
|
+
end
|
49
48
|
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
#
|
54
|
-
# * +:end_date+ - _xs:datetime_ The ending date
|
55
|
-
# * +:start_date+ - _xs:datetime_ The start date (defaults: current)
|
56
|
-
# * +:max_amount+ - _xs:decimal_ The preapproved maximum total amount of all payments.
|
57
|
-
# * +:currency_code+ - The currency code (defaults: USD)
|
58
|
-
# * +:cancel_url+ - URL to redirect the sender’s browser to after canceling the preapproval
|
59
|
-
# * +:return_url+ - URL to redirect the sender’s browser to after the sender has logged into PayPal and confirmed the preapproval
|
60
|
-
# * +:notify_url+ - The URL to which you want all IPN messages for this preapproval to be sent. (Optional)
|
61
|
-
#
|
62
|
-
# To get more details on fields see +Paypal PreApproval API+ at https://www.x.com/docs/DOC-1419
|
63
|
-
def preapprove_payment options
|
64
|
-
commit 'Preapproval', build_preapproval_payment(options)
|
65
|
-
end
|
49
|
+
def details_for_payment(options)
|
50
|
+
commit('PaymentDetails', build_adaptive_payment_details_request(options))
|
51
|
+
end
|
66
52
|
|
67
|
-
|
68
|
-
|
69
|
-
|
53
|
+
def refund(options)
|
54
|
+
commit('Refund', build_adaptive_refund_details(options))
|
55
|
+
end
|
70
56
|
|
71
|
-
|
72
|
-
|
73
|
-
|
57
|
+
# Send a preapproval request to pay pal
|
58
|
+
#
|
59
|
+
# ==== Options
|
60
|
+
#
|
61
|
+
# * +:end_date+ - _xs:datetime_ The ending date
|
62
|
+
# * +:start_date+ - _xs:datetime_ The start date (defaults: current)
|
63
|
+
# * +:max_amount+ - _xs:decimal_ The preapproved maximum total amount of all payments.
|
64
|
+
# * +:currency_code+ - The currency code (defaults: USD)
|
65
|
+
# * +:cancel_url+ - URL to redirect the sender’s browser to after canceling the preapproval
|
66
|
+
# * +:return_url+ - URL to redirect the sender’s browser to after the sender has logged into PayPal and confirmed the preapproval
|
67
|
+
# * +:notify_url+ - The URL to which you want all IPN messages for this preapproval to be sent. (Optional)
|
68
|
+
#
|
69
|
+
# To get more details on fields see +Paypal PreApproval API+ at https://www.x.com/docs/DOC-1419
|
70
|
+
def preapprove_payment(options)
|
71
|
+
commit('Preapproval', build_preapproval_payment(options))
|
72
|
+
end
|
74
73
|
|
75
|
-
|
76
|
-
|
77
|
-
|
74
|
+
def cancel_preapproval(options)
|
75
|
+
commit('CancelPreapproval', build_cancel_preapproval(options))
|
76
|
+
end
|
78
77
|
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
end
|
78
|
+
def preapproval_details_for(options)
|
79
|
+
commit('PreapprovalDetails', build_preapproval_details(options))
|
80
|
+
end
|
83
81
|
|
84
|
-
|
82
|
+
def convert_currency(options)
|
83
|
+
commit('ConvertCurrency', build_currency_conversion(options))
|
84
|
+
end
|
85
85
|
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
@config.merge! Yaml.load_file(@config_path)[RAILS_ENV].symbolize_keys!
|
90
|
-
end
|
86
|
+
def embedded_flow_url
|
87
|
+
test? ? EMBEDDED_FLOW_TEST_URL : EMBEDDED_FLOW_LIVE_URL
|
88
|
+
end
|
91
89
|
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
xml.instruct!
|
96
|
-
xml.PayRequest do |x|
|
97
|
-
x.requestEnvelope do |x|
|
98
|
-
x.detailLevel 'ReturnAll'
|
99
|
-
x.errorLanguage opts[:error_language] ||= 'en_US'
|
90
|
+
#debug method, provides an easy to use debug method for the class
|
91
|
+
def debug
|
92
|
+
"Url: #{@url}\n\n Request: #{@xml} \n\n Response: #{@response.json}"
|
100
93
|
end
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
94
|
+
|
95
|
+
private
|
96
|
+
def build_adaptive_payment_pay_request(opts)
|
97
|
+
@xml = ''
|
98
|
+
xml = Builder::XmlMarkup.new :target => @xml, :indent => 2
|
99
|
+
xml.instruct!
|
100
|
+
xml.PayRequest do |x|
|
101
|
+
x.requestEnvelope do |x|
|
102
|
+
x.detailLevel 'ReturnAll'
|
103
|
+
x.errorLanguage opts[:error_language] ||= 'en_US'
|
104
|
+
end
|
105
|
+
x.actionType 'PAY'
|
106
|
+
x.senderEmail opts[:sender_email] if opts.key?(:sender_email)
|
107
|
+
x.cancelUrl opts[:cancel_url]
|
108
|
+
x.returnUrl opts[:return_url]
|
109
|
+
x.ipnNotificationUrl opts[:ipn_notification_url] if opts[:ipn_notification_url]
|
110
|
+
x.memo opts[:memo] if opts.key?(:memo)
|
111
|
+
x.feesPayer opts[:fees_payer] if opts[:fees_payer]
|
112
|
+
x.pin opts[:pin] if opts[:pin]
|
113
|
+
x.currencyCode opts[:currency_code] ||= 'USD'
|
114
|
+
x.receiverList do |x|
|
115
|
+
opts[:receiver_list].each do |receiver|
|
116
|
+
x.receiver do |x|
|
117
|
+
x.email receiver[:email]
|
118
|
+
x.amount receiver[:amount].to_s
|
119
|
+
x.primary receiver[:primary] if receiver.key?(:primary)
|
120
|
+
x.paymentType receiver[:payment_type] if receiver.key?(:payment_type)
|
121
|
+
x.invoiceId receiver[:invoice_id] if receiver.key?(:invoice_id)
|
122
|
+
end
|
123
|
+
end
|
124
|
+
end
|
125
|
+
x.reverseAllParallelPaymentsOnError opts[:reverse_all_parallel_payments_on_error] || 'false'
|
126
|
+
x.trackingId opts[:tracking_id] if opts[:tracking_id]
|
127
|
+
end
|
107
128
|
end
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
x.
|
115
|
-
x.
|
116
|
-
x.
|
117
|
-
x.primary receiver[:primary] if receiver[:primary]
|
118
|
-
x.paymentType receiver[:payment_type] ||= 'GOODS'
|
119
|
-
x.invoiceId receiver[:invoice_id] if receiver[:invoice_id]
|
129
|
+
|
130
|
+
def build_adaptive_payment_details_request(opts)
|
131
|
+
@xml = ''
|
132
|
+
xml = Builder::XmlMarkup.new :target => @xml, :indent => 2
|
133
|
+
xml.instruct!
|
134
|
+
xml.PayRequest do |x|
|
135
|
+
x.requestEnvelope do |x|
|
136
|
+
x.detailLevel 'ReturnAll'
|
137
|
+
x.errorLanguage opts[:error_language] ||= 'en_US'
|
120
138
|
end
|
139
|
+
x.payKey opts[:paykey]
|
121
140
|
end
|
122
141
|
end
|
123
|
-
x.reverseAllParallelPaymentsOnError opts[:reverse_all_parallel_payments_on_error] || 'false'
|
124
|
-
end
|
125
|
-
end
|
126
142
|
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
143
|
+
def build_adaptive_refund_details(options)
|
144
|
+
@xml = ''
|
145
|
+
xml = Builder::XmlMarkup.new :target => @xml, :indent => 2
|
146
|
+
xml.instruct!
|
147
|
+
xml.RefundRequest do |x|
|
148
|
+
x.requestEnvelope do |x|
|
149
|
+
x.detailLevel 'ReturnAll'
|
150
|
+
x.errorLanguage options[:error_language] ||= 'en_US'
|
151
|
+
end
|
152
|
+
x.actionType 'REFUND'
|
153
|
+
if options[:pay_key]
|
154
|
+
x.payKey options[:pay_key]
|
155
|
+
end
|
156
|
+
if options[:transaction_id]
|
157
|
+
x.payKey options[:transaction_id]
|
158
|
+
end
|
159
|
+
if options[:tracking_id]
|
160
|
+
x.trackingId options[:tracking_id]
|
161
|
+
end
|
162
|
+
x.cancelUrl options[:cancel_url]
|
163
|
+
x.returnUrl options[:return_url]
|
164
|
+
x.currencyCode options[:currency_code] ||= 'USD'
|
165
|
+
x.receiverList do |x|
|
166
|
+
options[:receiver_list].each do |receiver|
|
167
|
+
x.receiver do |x|
|
168
|
+
x.amount receiver[:amount]
|
169
|
+
x.paymentType receiver[:payment_type] ||= 'GOODS'
|
170
|
+
x.invoiceId receiver[:invoice_id] if receiver[:invoice_id]
|
171
|
+
x.email receiver[:email]
|
172
|
+
end
|
173
|
+
end
|
174
|
+
end
|
175
|
+
x.feesPayer options[:fees_payer] ||= 'EACHRECEIVER'
|
176
|
+
end
|
135
177
|
end
|
136
|
-
x.payKey opts[:paykey]
|
137
|
-
end
|
138
|
-
end
|
139
178
|
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
179
|
+
def build_preapproval_payment(options)
|
180
|
+
opts = {
|
181
|
+
:currency_code => "USD",
|
182
|
+
:start_date => DateTime.current
|
183
|
+
}.update(options)
|
184
|
+
|
185
|
+
@xml = ''
|
186
|
+
xml = Builder::XmlMarkup.new :target => @xml, :indent => 2
|
187
|
+
xml.instruct!
|
188
|
+
xml.PreapprovalRequest do |x|
|
189
|
+
# request envelope
|
190
|
+
x.requestEnvelope do |x|
|
191
|
+
x.detailLevel 'ReturnAll'
|
192
|
+
x.errorLanguage opts[:error_language] ||= 'en_US'
|
193
|
+
x.senderEmail opts[:senderEmail]
|
194
|
+
end
|
195
|
+
|
196
|
+
# required preapproval fields
|
197
|
+
x.endingDate opts[:end_date].strftime("%Y-%m-%dT%H:%M:%S")
|
198
|
+
x.startingDate opts[:start_date].strftime("%Y-%m-%dT%H:%M:%S")
|
199
|
+
x.maxTotalAmountOfAllPayments opts[:max_amount]
|
200
|
+
x.maxNumberOfPayments opts[:maxNumberOfPayments] if opts.has_key?(:maxNumberOfPayments)
|
201
|
+
x.currencyCode options[:currency_code]
|
202
|
+
x.cancelUrl opts[:cancel_url]
|
203
|
+
x.returnUrl opts[:return_url]
|
204
|
+
|
205
|
+
# notify url
|
206
|
+
x.ipnNotificationUrl opts[:notify_url] if opts.has_key?(:notify_url)
|
207
|
+
end
|
158
208
|
end
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
x.
|
167
|
-
x.
|
168
|
-
x.email receiver[:email]
|
209
|
+
|
210
|
+
def build_preapproval_details(options)
|
211
|
+
@xml = ''
|
212
|
+
xml = Builder::XmlMarkup.new :target => @xml, :indent => 2
|
213
|
+
xml.instruct!
|
214
|
+
xml.PreapprovalDetailsRequest do |x|
|
215
|
+
x.requestEnvelope do |x|
|
216
|
+
x.detailLevel 'ReturnAll'
|
217
|
+
x.errorLanguage options[:error_language] ||= 'en_US'
|
169
218
|
end
|
219
|
+
x.preapprovalKey options[:preapproval_key]
|
220
|
+
x.getBillingAddress options[:get_billing_address] if options[:get_billing_address]
|
170
221
|
end
|
171
222
|
end
|
172
|
-
x.feesPayer options[:fees_payer] ||= 'EACHRECEIVER'
|
173
|
-
end
|
174
|
-
end
|
175
223
|
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
x.requestEnvelope do |x|
|
188
|
-
x.detailLevel 'ReturnAll'
|
189
|
-
x.errorLanguage opts[:error_language] ||= 'en_US'
|
190
|
-
x.senderEmail opts[:senderEmail]
|
224
|
+
def build_cancel_preapproval(options)
|
225
|
+
@xml = ''
|
226
|
+
xml = Builder::XmlMarkup.new :target => @xml, :indent => 2
|
227
|
+
xml.instruct!
|
228
|
+
xml.PreapprovalDetailsRequest do |x|
|
229
|
+
x.requestEnvelope do |x|
|
230
|
+
x.detailLevel 'ReturnAll'
|
231
|
+
x.errorLanguage options[:error_language] ||= 'en_US'
|
232
|
+
end
|
233
|
+
x.preapprovalKey options[:preapproval_key]
|
234
|
+
end
|
191
235
|
end
|
192
236
|
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
237
|
+
def build_currency_conversion(options)
|
238
|
+
@xml = ''
|
239
|
+
xml = Builder::XmlMarkup.new :target => @xml, :indent => 2
|
240
|
+
xml.instruct!
|
241
|
+
xml.ConvertCurrencyRequest do |x|
|
242
|
+
x.requestEnvelope do |x|
|
243
|
+
x.detailLevel 'ReturnAll'
|
244
|
+
x.errorLanguage options[:error_language] ||= 'en_US'
|
245
|
+
end
|
246
|
+
x.baseAmountList do |x|
|
247
|
+
options[:currency_list].each do |currency|
|
248
|
+
x.currency do |x|
|
249
|
+
x.amount currency[:amount]
|
250
|
+
x.code currency[:code ]
|
251
|
+
end
|
252
|
+
end
|
253
|
+
end
|
254
|
+
x.convertToCurrencyList do |x|
|
255
|
+
options[:to_currencies].each do |k,v|
|
256
|
+
x.currencyCode "#{v}"
|
257
|
+
end
|
258
|
+
end
|
259
|
+
end
|
205
260
|
end
|
206
|
-
end
|
207
|
-
end
|
208
261
|
|
209
|
-
|
210
|
-
|
211
|
-
xml = Builder::XmlMarkup.new :target => @xml, :indent => 2
|
212
|
-
xml.instruct!
|
213
|
-
xml.PreapprovalDetailsRequest do |x|
|
214
|
-
x.requestEnvelope do |x|
|
215
|
-
x.detailLevel 'ReturnAll'
|
216
|
-
x.errorLanguage options[:error_language] ||= 'en_US'
|
262
|
+
def commit(action, data)
|
263
|
+
@response = AdaptivePaymentResponse.new(post_through_ssl(action, data))
|
217
264
|
end
|
218
|
-
x.preapprovalKey options[:preapproval_key]
|
219
|
-
x.getBillingAddress options[:get_billing_address] if options[:get_billing_address]
|
220
|
-
end
|
221
|
-
end
|
222
265
|
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
266
|
+
def post_through_ssl(action, parameters = {})
|
267
|
+
headers = {
|
268
|
+
"X-PAYPAL-REQUEST-DATA-FORMAT" => "XML",
|
269
|
+
"X-PAYPAL-RESPONSE-DATA-FORMAT" => "JSON",
|
270
|
+
"X-PAYPAL-SECURITY-USERID" => @config[:login],
|
271
|
+
"X-PAYPAL-SECURITY-PASSWORD" => @config[:password],
|
272
|
+
"X-PAYPAL-SECURITY-SIGNATURE" => @config[:signature],
|
273
|
+
"X-PAYPAL-APPLICATION-ID" => @config[:appid]
|
274
|
+
}
|
275
|
+
action_url(action)
|
276
|
+
request = Net::HTTP::Post.new(@url.path)
|
277
|
+
request.body = @xml
|
278
|
+
headers.each_pair { |k,v| request[k] = v }
|
279
|
+
request.content_type = 'text/xml'
|
280
|
+
server = Net::HTTP.new(@url.host, 443)
|
281
|
+
server.use_ssl = true
|
282
|
+
server.start { |http| http.request(request) }.body
|
231
283
|
end
|
232
|
-
x.preapprovalKey options[:preapproval_key]
|
233
|
-
end
|
234
|
-
end
|
235
284
|
|
236
|
-
|
237
|
-
|
238
|
-
xml = Builder::XmlMarkup.new :target => @xml, :indent => 2
|
239
|
-
xml.instruct!
|
240
|
-
xml.ConvertCurrencyRequest do |x|
|
241
|
-
x.requestEnvelope do |x|
|
242
|
-
x.detailLevel 'ReturnAll'
|
243
|
-
x.errorLanguage options[:error_language] ||= 'en_US'
|
285
|
+
def endpoint_url
|
286
|
+
test? ? TEST_URL : LIVE_URL
|
244
287
|
end
|
245
288
|
|
246
|
-
|
247
|
-
|
248
|
-
x.currency do |x|
|
249
|
-
x.amount currency[:amount]
|
250
|
-
x.code currency[:code ]
|
251
|
-
end
|
252
|
-
end
|
289
|
+
def test?
|
290
|
+
Base.gateway_mode == :test
|
253
291
|
end
|
254
292
|
|
255
|
-
|
256
|
-
|
257
|
-
x.currencyCode "#{v}"
|
258
|
-
end
|
293
|
+
def action_url(action)
|
294
|
+
@url = URI.parse(endpoint_url + action)
|
259
295
|
end
|
260
|
-
end
|
261
|
-
end
|
262
296
|
|
263
|
-
def parse json
|
264
|
-
@raw = json
|
265
|
-
resp = JSON.parse json
|
266
|
-
if resp['responseEnvelope']['ack'] == 'Failure'
|
267
|
-
error = AdaptivePaypalErrorResponse.new(json)
|
268
|
-
else
|
269
|
-
AdaptivePaypalSuccessResponse.new(resp)
|
270
297
|
end
|
271
298
|
end
|
272
|
-
|
273
|
-
def commit(action, data)
|
274
|
-
@response = parse(post_through_ssl(action, data))
|
275
|
-
end
|
276
|
-
|
277
|
-
def post_through_ssl(action, parameters = {})
|
278
|
-
headers = {
|
279
|
-
"X-PAYPAL-REQUEST-DATA-FORMAT" => "XML",
|
280
|
-
"X-PAYPAL-RESPONSE-DATA-FORMAT" => "JSON",
|
281
|
-
"X-PAYPAL-SECURITY-USERID" => @config[:login],
|
282
|
-
"X-PAYPAL-SECURITY-PASSWORD" => @config[:password],
|
283
|
-
"X-PAYPAL-SECURITY-SIGNATURE" => @config[:signature],
|
284
|
-
"X-PAYPAL-APPLICATION-ID" => @config[:appid]
|
285
|
-
}
|
286
|
-
url action
|
287
|
-
request = Net::HTTP::Post.new(@url.path)
|
288
|
-
request.body = @xml
|
289
|
-
headers.each_pair { |k,v| request[k] = v }
|
290
|
-
request.content_type = 'text/xml'
|
291
|
-
server = Net::HTTP.new(@url.host, 443)
|
292
|
-
server.use_ssl = true
|
293
|
-
server.start { |http| http.request(request) }.body
|
294
|
-
end
|
295
|
-
|
296
|
-
def endpoint_url
|
297
|
-
test? ? TEST_URL : LIVE_URL
|
298
|
-
end
|
299
|
-
|
300
|
-
def test?
|
301
|
-
Base.gateway_mode == :test
|
302
|
-
end
|
303
|
-
|
304
|
-
def url action
|
305
|
-
@url = URI.parse(endpoint_url + action)
|
306
|
-
end
|
307
|
-
|
308
|
-
end; end; end
|
299
|
+
end
|
data/lib/active_merchant/billing/gateways/paypal_adaptive_payments/adaptive_payment_response.rb
CHANGED
@@ -1,134 +1,52 @@
|
|
1
|
-
|
1
|
+
require 'multi_json'
|
2
|
+
require 'hashie'
|
3
|
+
require 'rash'
|
2
4
|
|
3
|
-
|
5
|
+
module ActiveMerchant
|
6
|
+
module Billing
|
7
|
+
class AdaptivePaymentResponse
|
4
8
|
|
5
|
-
|
6
|
-
|
9
|
+
REDIRECT_URL = 'https://www.paypal.com/webscr?cmd=_ap-payment&paykey='
|
10
|
+
TEST_REDIRECT_URL = 'https://www.sandbox.paypal.com/cgi-bin/webscr?cmd=_ap-payment&paykey='
|
7
11
|
|
8
|
-
|
12
|
+
SUCCESS = 'Success'.freeze
|
9
13
|
|
10
|
-
|
11
|
-
|
12
|
-
@params = json
|
13
|
-
end
|
14
|
+
attr_reader :json
|
15
|
+
alias :raw :json
|
14
16
|
|
15
|
-
|
16
|
-
|
17
|
-
|
17
|
+
def initialize(json)
|
18
|
+
@json = json
|
19
|
+
@response_rash = Hashie::Rash.new(MultiJson.decode(json))
|
20
|
+
end
|
18
21
|
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
+
def method_missing(method, *args, &block)
|
23
|
+
@response_rash.send(method, *args, &block)
|
24
|
+
end
|
22
25
|
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
+
def redirect_url_for
|
27
|
+
Base.gateway_mode == :test ? (TEST_REDIRECT_URL + pay_key) : (REDIRECT_URL + pay_key)
|
28
|
+
end
|
26
29
|
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
def senderEmail
|
32
|
-
@params['senderEmail']
|
33
|
-
end
|
34
|
-
|
35
|
-
def actionType
|
36
|
-
@params['actionType']
|
37
|
-
end
|
38
|
-
|
39
|
-
def feesPayer
|
40
|
-
@params['feesPayer']
|
41
|
-
end
|
42
|
-
|
43
|
-
def currencyCode
|
44
|
-
@params['currencyCode']
|
45
|
-
end
|
46
|
-
|
47
|
-
def payKey
|
48
|
-
@params['payKey']
|
49
|
-
end
|
50
|
-
|
51
|
-
def correlationId
|
52
|
-
@params['responseEnvelope']['correlationId']
|
53
|
-
end
|
54
|
-
|
55
|
-
def build
|
56
|
-
@params['responseEnvelope']['build']
|
57
|
-
end
|
58
|
-
|
59
|
-
def refundInfoList
|
60
|
-
@params['refundInfoList']
|
61
|
-
end
|
62
|
-
|
63
|
-
def preapprovalKey
|
64
|
-
@params['preapprovalKey']
|
65
|
-
end
|
66
|
-
|
67
|
-
def curPaymentsAmount
|
68
|
-
@params['curPaymentsAmount']
|
69
|
-
end
|
30
|
+
def ack
|
31
|
+
response_envelope.ack
|
32
|
+
end
|
70
33
|
|
71
|
-
|
72
|
-
|
73
|
-
|
34
|
+
def timestamp
|
35
|
+
response_envelope.timestamp
|
36
|
+
end
|
74
37
|
|
75
|
-
|
76
|
-
|
77
|
-
|
38
|
+
def build
|
39
|
+
response_envelope.build
|
40
|
+
end
|
78
41
|
|
79
|
-
|
80
|
-
|
81
|
-
|
42
|
+
def correlation_id
|
43
|
+
response_envelope.correlation_id
|
44
|
+
end
|
45
|
+
alias :correlationId :correlation_id
|
82
46
|
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
rescue
|
87
|
-
raise AttributenotFound
|
47
|
+
def success?
|
48
|
+
ack == SUCCESS
|
49
|
+
end
|
88
50
|
end
|
89
51
|
end
|
90
|
-
|
91
|
-
def [](key)
|
92
|
-
return @params[key] if @params.include? key
|
93
|
-
raise AttributenotFound
|
94
|
-
end
|
95
|
-
|
96
|
-
def status
|
97
|
-
@params['status']
|
98
|
-
end
|
99
|
-
|
100
52
|
end
|
101
|
-
|
102
|
-
class AdaptivePaypalErrorResponse
|
103
|
-
|
104
|
-
def initialize error
|
105
|
-
@raw = error
|
106
|
-
@errlist = ActiveSupport::JSON.decode(error)
|
107
|
-
end
|
108
|
-
|
109
|
-
def debug
|
110
|
-
@raw.inspect
|
111
|
-
end
|
112
|
-
|
113
|
-
def ack
|
114
|
-
@raw['responseEnvelope']['ack']
|
115
|
-
end
|
116
|
-
|
117
|
-
def timestamp
|
118
|
-
@raw['responseEnvelope']['timestamp']
|
119
|
-
end
|
120
|
-
|
121
|
-
def build
|
122
|
-
@raw['responseEnvelope']['build']
|
123
|
-
end
|
124
|
-
|
125
|
-
def correlationId
|
126
|
-
@raw['responseEnvelope']['correlationId']
|
127
|
-
end
|
128
|
-
|
129
|
-
def errormessage
|
130
|
-
@errlist['error']
|
131
|
-
end
|
132
|
-
end
|
133
|
-
|
134
|
-
end; end; end
|
@@ -1,10 +1,12 @@
|
|
1
1
|
# fix for case sensitive headers in paypal (issue #1)
|
2
|
-
module Net
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
2
|
+
module Net
|
3
|
+
module HTTPHeader
|
4
|
+
def []= key, val
|
5
|
+
unless val
|
6
|
+
@header.delete key
|
7
|
+
return val
|
8
|
+
end
|
9
|
+
@header[key] = [val]
|
7
10
|
end
|
8
|
-
@header[key] = [val]
|
9
11
|
end
|
10
|
-
end
|
12
|
+
end
|
@@ -1,13 +1,4 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
begin
|
4
|
-
require 'active_support'
|
5
|
-
require 'active_merchant/common'
|
6
|
-
rescue LoadError
|
7
|
-
require 'rubygems'
|
8
|
-
require 'active_support'
|
9
|
-
require 'active_merchant/common'
|
10
|
-
end
|
1
|
+
require 'active_merchant'
|
11
2
|
|
12
3
|
dir = File.dirname(__FILE__) + '/active_merchant/billing/gateways'
|
13
4
|
require dir + '/paypal_adaptive_payment'
|
@@ -4,8 +4,7 @@ This library is meant to interface with PayPal web services Adaptive Payment Gat
|
|
4
4
|
|
5
5
|
[Active Merchant]:http://www.activemerchant.org
|
6
6
|
|
7
|
-
|
8
|
-
|
7
|
+
[iAuction: An Adaptive Payments Tutorial Featuring Parallel Payments](https://www.x.com/docs/DOC-2505)
|
9
8
|
## Supported
|
10
9
|
|
11
10
|
* payments
|
@@ -18,23 +17,28 @@ This library is meant to interface with PayPal web services Adaptive Payment Gat
|
|
18
17
|
|
19
18
|
Add the following line to your app Gemfile:
|
20
19
|
|
21
|
-
gem "active_paypal_adaptive_payment"
|
20
|
+
gem "active_paypal_adaptive_payment"
|
22
21
|
|
23
22
|
## Implementation
|
24
23
|
|
25
|
-
|
24
|
+
See  tutorial for more info.
|
26
25
|
|
27
|
-
|
28
|
-
@gateway ||= PaypalAdaptivePaymentGateway.new(
|
29
|
-
:login => 'your_email',
|
30
|
-
:password => 'your_password',
|
31
|
-
:signature => ' your_signature',
|
32
|
-
:appid => 'your_app_id'
|
33
|
-
)
|
34
|
-
end
|
26
|
+
### Pre-approved paymen
|
35
27
|
|
36
|
-
|
28
|
+
gateway.preapprove_payment (
|
29
|
+
:return_url => "returnURL",
|
30
|
+
:cancel_url => "cancelURL",
|
31
|
+
:senderEmail =>"email address of sender",
|
32
|
+
:start_date => Time.now,
|
33
|
+
:end_date => Time.now + (60*60*24) * 30,
|
34
|
+
:currency_code =>"currency code",
|
35
|
+
:max_amount => "maxTotalAmountOfAllPayments",
|
36
|
+
:maxNumberOfPayments => "maxNumberOfPayments" )
|
37
37
|
|
38
|
+
### Cancel pre-approved payment
|
39
|
+
|
40
|
+
gateway.cancel_preapproval(:preapproval_key => "preapprovalkey"
|
41
|
+
)
|
38
42
|
### Chained payments
|
39
43
|
|
40
44
|
def checkout
|
@@ -63,16 +67,21 @@ response, the xml sent and the url it was posted to.
|
|
63
67
|
|
64
68
|
From the Rails console it can be accessed like such:
|
65
69
|
|
66
|
-
ActiveMerchant::Billing::
|
70
|
+
ActiveMerchant::Billing::PaypalAdaptivePayment
|
71
|
+
|
72
|
+
`PaypalAdaptivePayment#debug` or `AdaptivePaymentResponse#debug` return the raw
|
73
|
+
xml request, raw json response and the URL of the endpoint.
|
67
74
|
|
68
75
|
## TODO
|
69
76
|
|
70
|
-
*
|
77
|
+
* Documentation
|
78
|
+
* More tests
|
71
79
|
|
72
80
|
## Contributors
|
73
81
|
|
74
82
|
* Jose Pablo Barrantes (<http://jpablobr.com/>)
|
75
83
|
* Zarne Dravitzki (<http://github.com/zarno>)
|
84
|
+
* LeviRosol (<https://github.com/LeviRosol>)
|
76
85
|
|
77
86
|
## Other previous contributors where some code was taken from.
|
78
87
|
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: active_paypal_adaptive_payment
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1
|
4
|
+
version: 0.2.1
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,12 +9,11 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2011-
|
13
|
-
default_executable:
|
12
|
+
date: 2011-08-12 00:00:00.000000000Z
|
14
13
|
dependencies:
|
15
14
|
- !ruby/object:Gem::Dependency
|
16
15
|
name: activemerchant
|
17
|
-
requirement: &
|
16
|
+
requirement: &11874900 !ruby/object:Gem::Requirement
|
18
17
|
none: false
|
19
18
|
requirements:
|
20
19
|
- - ! '>='
|
@@ -22,29 +21,40 @@ dependencies:
|
|
22
21
|
version: 1.5.1
|
23
22
|
type: :runtime
|
24
23
|
prerelease: false
|
25
|
-
version_requirements: *
|
24
|
+
version_requirements: *11874900
|
26
25
|
- !ruby/object:Gem::Dependency
|
27
|
-
name:
|
28
|
-
requirement: &
|
26
|
+
name: multi_json
|
27
|
+
requirement: &11874420 !ruby/object:Gem::Requirement
|
29
28
|
none: false
|
30
29
|
requirements:
|
31
30
|
- - ! '>='
|
32
31
|
- !ruby/object:Gem::Version
|
33
|
-
version:
|
32
|
+
version: 1.0.0
|
34
33
|
type: :runtime
|
35
34
|
prerelease: false
|
36
|
-
version_requirements: *
|
35
|
+
version_requirements: *11874420
|
37
36
|
- !ruby/object:Gem::Dependency
|
38
|
-
name:
|
39
|
-
requirement: &
|
37
|
+
name: rash
|
38
|
+
requirement: &11873820 !ruby/object:Gem::Requirement
|
40
39
|
none: false
|
41
40
|
requirements:
|
42
41
|
- - ! '>='
|
43
42
|
- !ruby/object:Gem::Version
|
44
|
-
version:
|
43
|
+
version: 0.3.0
|
45
44
|
type: :runtime
|
46
45
|
prerelease: false
|
47
|
-
version_requirements: *
|
46
|
+
version_requirements: *11873820
|
47
|
+
- !ruby/object:Gem::Dependency
|
48
|
+
name: money
|
49
|
+
requirement: &11873220 !ruby/object:Gem::Requirement
|
50
|
+
none: false
|
51
|
+
requirements:
|
52
|
+
- - ! '>='
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: 3.6.0
|
55
|
+
type: :runtime
|
56
|
+
prerelease: false
|
57
|
+
version_requirements: *11873220
|
48
58
|
description: This library is meant to interface with PayPal web services Adaptive
|
49
59
|
Payment Gateway Library.
|
50
60
|
email:
|
@@ -55,14 +65,12 @@ extra_rdoc_files: []
|
|
55
65
|
files:
|
56
66
|
- lib/active_paypal_adaptive_payment.rb
|
57
67
|
- lib/active_merchant/billing/gateways/paypal_adaptive_payments/exceptions.rb
|
58
|
-
- lib/active_merchant/billing/gateways/paypal_adaptive_payments/utils.rb
|
59
68
|
- lib/active_merchant/billing/gateways/paypal_adaptive_payments/adaptive_payment_response.rb
|
60
69
|
- lib/active_merchant/billing/gateways/paypal_adaptive_payments/ext.rb
|
61
70
|
- lib/active_merchant/billing/gateways/paypal_adaptive_payment.rb
|
62
71
|
- MIT-LICENSE
|
63
|
-
-
|
64
|
-
- CHANGELOG
|
65
|
-
has_rdoc: true
|
72
|
+
- readme.md
|
73
|
+
- CHANGELOG.md
|
66
74
|
homepage: http://github.com/jpablobr/active_paypal_adaptive_payment
|
67
75
|
licenses: []
|
68
76
|
post_install_message:
|
@@ -83,7 +91,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
83
91
|
version: 1.3.6
|
84
92
|
requirements: []
|
85
93
|
rubyforge_project:
|
86
|
-
rubygems_version: 1.
|
94
|
+
rubygems_version: 1.8.7
|
87
95
|
signing_key:
|
88
96
|
specification_version: 3
|
89
97
|
summary: ActiveMercant PayPal Adaptive Payment Library
|
data/CHANGELOG
DELETED
File without changes
|