paypal_api 0.3.4 → 0.3.5
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/README.markdown
CHANGED
@@ -7,33 +7,125 @@ the gems that do exist do not cover the entire api.
|
|
7
7
|
|
8
8
|
# Usage
|
9
9
|
|
10
|
-
|
10
|
+
i want interaction with the gem to be flat and straight-forward, with clear mapping between the api docs and the gem. right now
|
11
|
+
the only place where i break this is for "list type" fields, where it makes sense to treat it more like a ruby array.
|
12
|
+
all keys are ruby style (snake_case), and should automatically get converted to the proper formatting for you.
|
13
|
+
|
14
|
+
if you don't add all the required fields to the request, it will raise `Paypal::InvalidRequest` exceptions. if you try to set the wrong
|
15
|
+
type to a field, it will raise `Paypal::InvalidParameter` exceptions.
|
16
|
+
|
17
|
+
### Payments Pro Example
|
18
|
+
|
19
|
+
the most useful methods, imo, are do_direct_payment, do_reference_
|
20
|
+
|
11
21
|
```ruby
|
12
22
|
require "paypal_api"
|
13
23
|
|
14
|
-
|
24
|
+
# create request
|
25
|
+
request = Paypal::PaymentsPro.do_reference_transaction # returns instance of Paypal::DoDirectPaymentRequest
|
15
26
|
|
16
|
-
#
|
17
|
-
request.
|
18
|
-
request.
|
27
|
+
# set required fields
|
28
|
+
request.reference_id = "other_paypal_transaction_id"
|
29
|
+
request.payment_action = :authorization
|
19
30
|
request.amt = 10.00
|
20
31
|
|
21
|
-
#
|
22
|
-
request.
|
23
|
-
|
24
|
-
|
32
|
+
# make request
|
33
|
+
response = request.make
|
34
|
+
|
35
|
+
# usable information
|
36
|
+
response.success? # true if successful
|
37
|
+
response[:correlation_id] # correlation id string returned by paypal
|
38
|
+
transaction_id = response[:transaction_id] # transaction id string, not return on all calls
|
39
|
+
|
40
|
+
# in this example, since the first request was an authorization, you can then capture it
|
41
|
+
request2 = Paypal::PaymentsPro.do_capture # returns instance of Paypal::DoCaptureRequest
|
42
|
+
|
43
|
+
request2.authorization_id = transaction_id
|
44
|
+
request2.amt = 10.00
|
45
|
+
|
46
|
+
response2 = request2.make
|
47
|
+
|
48
|
+
response2.success?
|
49
|
+
```
|
50
|
+
|
51
|
+
### Adaptive Payments Example
|
52
|
+
|
53
|
+
even though the api's are very different, they should be abstracted the same way
|
54
|
+
|
55
|
+
```ruby
|
56
|
+
require "paypal_api"
|
57
|
+
|
58
|
+
request = Paypal::AdaptivePayments.pay # returns instance of Paypal::PayRequest
|
59
|
+
|
60
|
+
# set required fields
|
61
|
+
request.cancel_url = "http://www.test.com/cancel"
|
62
|
+
request.return_url = "http://www.test.com/return"
|
63
|
+
request.ip_address = "192.168.1.1"
|
64
|
+
|
65
|
+
# add a list type field
|
66
|
+
request.receiver.push {
|
67
|
+
:email => "bro@dudeman.com",
|
68
|
+
:amount => 23.0
|
25
69
|
}
|
26
70
|
|
71
|
+
# make request
|
27
72
|
response = request.make
|
28
73
|
|
74
|
+
# usable information
|
29
75
|
response.success? # true if successful
|
76
|
+
response[:pay_key] # usually what you use this api method for
|
30
77
|
|
31
|
-
|
32
|
-
response
|
78
|
+
# in adaptive payments flows, sometimes you need to redirect to paypal
|
79
|
+
response.redirect_url
|
80
|
+
# used if you want the payment flow without the client leaving your site (see below)
|
81
|
+
response.embedded_url
|
82
|
+
|
83
|
+
# errors
|
84
|
+
response.error_message # populated by paypal response error when request fails
|
85
|
+
response.error_code # populated by paypal response error
|
86
|
+
response.error_field # some api calls let you know which field caused the issue
|
87
|
+
```
|
88
|
+
|
89
|
+
for adaptive payments and preapprovals, sometimes you want to use the paypal javascript libraries
|
90
|
+
and their associated "embedded" payment flows. `response.embedded_url` gives you what you need for this.
|
91
|
+
note that you also need to include one of their js libraries.
|
92
|
+
|
93
|
+
```javascript
|
94
|
+
// include one of their libraries asynchronously:
|
95
|
+
// minibrowser library: https://www.paypalobjects.com/js/external/dg.js
|
96
|
+
// embedded library: https://www.paypalobjects.com/js/external/apdg.js
|
97
|
+
window.paypalAsyncInit = function () {
|
98
|
+
window.paypalController = new PAYPAL.apps.DGFlow({expType: "mini"});
|
99
|
+
};
|
100
|
+
|
101
|
+
(function(d){
|
102
|
+
var js, id = 'paypal-sdk'; if (d.getElementById(id)) {return;}
|
103
|
+
js = d.createElement('script'); js.id = id; js.async = true;
|
104
|
+
js.src = "https://www.paypalobjects.com/js/external/dg.js";
|
105
|
+
d.getElementsByTagName('head')[0].appendChild(js);
|
106
|
+
js.onload = window.paypalAsyncInit;
|
107
|
+
}(document));
|
108
|
+
|
109
|
+
|
110
|
+
// later, after receiving embedded_url from the server:
|
111
|
+
window.paypalController.startFlow(embeddUrl);
|
33
112
|
```
|
34
113
|
|
114
|
+
### More
|
115
|
+
|
116
|
+
the actual api method definitions should be more or less readable as is (if not, you can call me a jerk, i sorry). look in
|
117
|
+
`lib/paypal_api/apis/` for reference, until i document each method.
|
118
|
+
|
35
119
|
## Configure
|
36
120
|
|
121
|
+
it's hard to navigate paypals terribly organized everything, here are some links to help you find what you need:
|
122
|
+
|
123
|
+
* paypal api credentials for production: [https://www.paypal.com/us/cgi-bin/webscr?cmd=_profile-api-signature](https://www.paypal.com/us/cgi-bin/webscr?cmd=_profile-api-signature)
|
124
|
+
* sandbox credentials: [https://developer.paypal.com/cgi-bin/devscr?cmd=_certs-session&login_access=0](https://developer.paypal.com/cgi-bin/devscr?cmd=_certs-session&login_access=0)
|
125
|
+
* where to tell paypal what your ipn callback url is: [https://www.paypal.com/cgi-bin/customerprofileweb?cmd=_profile-ipn-notify](https://www.paypal.com/cgi-bin/customerprofileweb?cmd=_profile-ipn-notify)
|
126
|
+
|
127
|
+
### Simple Configuration
|
128
|
+
|
37
129
|
```ruby
|
38
130
|
Paypal::Request.version = "84.0"
|
39
131
|
Paypal::Request.environment = "development" # or "production"
|
@@ -42,11 +134,7 @@ Paypal::Request.pwd = "some_password_they_gave_you"
|
|
42
134
|
Paypal::Request.signature = "some_signature"
|
43
135
|
```
|
44
136
|
|
45
|
-
|
46
|
-
|
47
|
-
sandbox credentials can be found here: [https://developer.paypal.com/cgi-bin/devscr?cmd=_certs-session&login_access=0](https://developer.paypal.com/cgi-bin/devscr?cmd=_certs-session&login_access=0)
|
48
|
-
|
49
|
-
## Rails
|
137
|
+
### Configure For Rails
|
50
138
|
|
51
139
|
if you'd like to have multi environment configuration in rails, place a file at `config/paypal.yml` and the gem will read from it accordingly
|
52
140
|
|
@@ -68,7 +156,7 @@ production:
|
|
68
156
|
|
69
157
|
## Ipn Messages
|
70
158
|
|
71
|
-
there is an ipn message model generator:
|
159
|
+
there is an ipn message model generator: `$ rails generate paypal:ipn_message`, it will create
|
72
160
|
a migration and the IpnMessage model.
|
73
161
|
|
74
162
|
you must edit the route and add a handler like so:
|
@@ -98,8 +186,10 @@ end
|
|
98
186
|
|
99
187
|
## Testing
|
100
188
|
|
101
|
-
|
102
|
-
|
189
|
+
you can run the tests: `$ bundle exec rspec spec`
|
190
|
+
|
191
|
+
i'm an rspec kinda guy, hopefully you are ok with that. note that i have tests for actual requests against the paypal
|
192
|
+
sandbox server, but they are turned off by default. remove the line about `:slow_paypal` in
|
103
193
|
`spec/spec_helper.rb` to turn these back on.
|
104
194
|
|
105
195
|
also note that, for the Adaptive Payments api, an application id is required, for testing,
|
@@ -115,14 +205,40 @@ repository. in order to get to that stage, i will need to add support for adapti
|
|
115
205
|
|
116
206
|
# How To Contribute
|
117
207
|
|
118
|
-
right now the most help i could use is in writing the
|
119
|
-
|
208
|
+
right now the most help i could use is in writing the signatures for the various api calls from the Payments Pro and
|
209
|
+
Adaptive Payments apis (or any others really).
|
120
210
|
|
121
|
-
|
122
|
-
to store ipn messages, and a generated class with callbacks to handle the various cases. this will probably take a lot of effort since there
|
123
|
-
are many intricacies in the meanings of the different ipn's.
|
211
|
+
i've tried to make it easy to contribute, signatures are created pretty easily:
|
124
212
|
|
125
|
-
|
213
|
+
```ruby
|
214
|
+
# lib/paypal_api/apis/payments_pro.rb
|
215
|
+
|
216
|
+
module Paypal
|
217
|
+
class PaymentsPro < Paypal::Api
|
218
|
+
|
219
|
+
set_request_signature :do_capture, {
|
220
|
+
:method => "DoCapture",
|
221
|
+
:authorization_id => String,
|
222
|
+
:amt => Float,
|
223
|
+
:currency_code => Default.new("USD", /^[a-z]{3}$/i),
|
224
|
+
:complete_type => Default.new("Complete", Enum.new("Complete", "NotComplete")),
|
225
|
+
:inv_num => Optional.new(String),
|
226
|
+
:note => Optional.new(String),
|
227
|
+
:soft_descriptor => Optional.new(lambda {|val|
|
228
|
+
if val.match(/^([a-z0-9]|\.|-|\*| )*$/i) && val.length <= 22
|
229
|
+
return true
|
230
|
+
else
|
231
|
+
return false
|
232
|
+
end
|
233
|
+
}),
|
234
|
+
|
235
|
+
:store_id => Optional.new(String),
|
236
|
+
:terminal_id => Optional.new(String)
|
237
|
+
}
|
238
|
+
|
239
|
+
end
|
240
|
+
end
|
241
|
+
```
|
126
242
|
|
127
243
|
this is my first gem, so i'll be excited for any contributions :'(
|
128
244
|
|
@@ -192,8 +308,6 @@ note that you need to request that paypal enable mass pay for your account befor
|
|
192
308
|
|
193
309
|
* mass_pay - ✓
|
194
310
|
|
195
|
-
## Instant Pay Notifications
|
196
|
-
|
197
311
|
## Express Checkout
|
198
312
|
|
199
313
|
## Adaptive Payments
|
@@ -5,6 +5,7 @@
|
|
5
5
|
module Paypal
|
6
6
|
|
7
7
|
class AdaptivePaymentsResponse < Response
|
8
|
+
|
8
9
|
def initialize(stringio)
|
9
10
|
@raw_response = stringio.class == StringIO ? stringio.read : stringio
|
10
11
|
@parsed_response = CGI.parse(@raw_response)
|
@@ -30,6 +31,17 @@ module Paypal
|
|
30
31
|
end
|
31
32
|
end
|
32
33
|
|
34
|
+
def redirect_url
|
35
|
+
"#{self.base_url}/webscr?cmd=_ap-#{command}&#{command_key}=#{command_value}" if webscr?
|
36
|
+
end
|
37
|
+
|
38
|
+
# requires https://www.paypalobjects.com/js/external/dg.js (lightbox)
|
39
|
+
# or https://www.paypalobjects.com/js/external/apdg.js (minibrowser)
|
40
|
+
# to be added to the page
|
41
|
+
def embedded_url
|
42
|
+
"#{self.base_url}/webapps/adaptivepayment/flow/pay?payKey=#{self[:pay_key]}#{"&preapprovalkey=#{self[:preapproval_key]}" if command == :preapproval}" if webscr?
|
43
|
+
end
|
44
|
+
|
33
45
|
protected
|
34
46
|
|
35
47
|
def symbol_to_key(symbol)
|
@@ -40,6 +52,28 @@ module Paypal
|
|
40
52
|
return Paypal::Api.symbol_to_lower_camel(symbol)
|
41
53
|
end
|
42
54
|
end
|
55
|
+
|
56
|
+
def base_url
|
57
|
+
Paypal::Request.environment == "production" ? "https://www.paypal.com" : "https://www.sandbox.paypal.com"
|
58
|
+
end
|
59
|
+
|
60
|
+
private
|
61
|
+
|
62
|
+
def command_key
|
63
|
+
return command == :preapproval ? "preapprovalkey" : "payKey"
|
64
|
+
end
|
65
|
+
|
66
|
+
def command_value
|
67
|
+
return command == :preapproval ? self[:preapproval_key] : self[:pay_key]
|
68
|
+
end
|
69
|
+
|
70
|
+
def command
|
71
|
+
return self[:preapproval_key] ? :preapproval : :payment
|
72
|
+
end
|
73
|
+
|
74
|
+
def webscr?
|
75
|
+
return true if self[:pay_key] || self[:preapproval_key]
|
76
|
+
end
|
43
77
|
end
|
44
78
|
|
45
79
|
class AdaptivePaymentsRequest < Request
|
@@ -134,6 +134,7 @@ module Paypal
|
|
134
134
|
@allowed_values = values[0]
|
135
135
|
else
|
136
136
|
@allowed_values = values
|
137
|
+
@normalized_values = @allowed_values.inject({}){|acc, v| acc[normalize(v)] = v; acc}
|
137
138
|
end
|
138
139
|
end
|
139
140
|
|
@@ -145,8 +146,9 @@ module Paypal
|
|
145
146
|
raise Paypal::InvalidParameter, "'#{val}' must be a key in #{@allowed_values.keys}"
|
146
147
|
end
|
147
148
|
else
|
148
|
-
|
149
|
-
|
149
|
+
normed = normalize(val)
|
150
|
+
if @normalized_values.include?(normed)
|
151
|
+
return @normalized_values[normed]
|
150
152
|
else
|
151
153
|
raise Paypal::InvalidParameter, "'#{val}' must be one of #{@allowed_values}"
|
152
154
|
end
|
@@ -154,9 +156,7 @@ module Paypal
|
|
154
156
|
end
|
155
157
|
|
156
158
|
def normalize(val)
|
157
|
-
return val
|
158
|
-
return Paypal::Api.symbol_to_camel(val) if val.class == Symbol
|
159
|
-
return nil
|
159
|
+
return val.to_s.downcase.gsub(/[^a-z0-9]/,"")
|
160
160
|
end
|
161
161
|
end
|
162
162
|
|
data/lib/paypal_api/version.rb
CHANGED
@@ -19,6 +19,14 @@ describe Paypal::Api::Parameter do
|
|
19
19
|
}.to raise_exception(Paypal::InvalidParameter)
|
20
20
|
end
|
21
21
|
|
22
|
+
it "should allow lookup on normalized matching" do
|
23
|
+
param = @api::Enum.new("This", "FirstTest", "SaweetDude")
|
24
|
+
|
25
|
+
param.parse(:this).should eq("This")
|
26
|
+
param.parse(:first_test).should eq("FirstTest")
|
27
|
+
param.parse(:saweet_dude).should eq("SaweetDude")
|
28
|
+
end
|
29
|
+
|
22
30
|
describe "hash enumerations" do
|
23
31
|
before(:each) do
|
24
32
|
@param = @api::Enum.new({:thing => "OK", :that => "TEO"})
|
@@ -0,0 +1,35 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe Paypal::AdaptivePaymentsResponse do
|
4
|
+
describe "for pay requests" do
|
5
|
+
before(:each) do
|
6
|
+
@response = Paypal::AdaptivePaymentsResponse.new("responseEnvelope.timestamp=2012-02-29T13%3A40%3A17.074-08%3A00&responseEnvelope.ack=Success&responseEnvelope.correlationId=722689b427b7c&responseEnvelope.build=2486531&payKey=AP-1W763567RM6393227&paymentExecStatus=CREATED")
|
7
|
+
end
|
8
|
+
|
9
|
+
describe "embedded url" do
|
10
|
+
it "should create a proper embedded url" do
|
11
|
+
@response.embedded_url.should include("/webapps/adaptivepayment/flow/pay?payKey=")
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
describe "redirect url" do
|
16
|
+
it "should create a proper redirect url" do
|
17
|
+
@response.redirect_url.should include("/webscr?cmd=_ap-")
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
it "should know about production vs sandbox" do
|
22
|
+
Paypal::Request.environment = "production"
|
23
|
+
@response.redirect_url.should_not include("sandbox")
|
24
|
+
Paypal::Request.environment = "something else"
|
25
|
+
@response.redirect_url.should include("sandbox")
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
describe "for payapproval requests" do
|
30
|
+
it "should create a proper redirect url" do
|
31
|
+
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: paypal_api
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.3.
|
4
|
+
version: 0.3.5
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,11 +9,11 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-03-
|
12
|
+
date: 2012-03-02 00:00:00.000000000Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: rails
|
16
|
-
requirement: &
|
16
|
+
requirement: &70244405693760 !ruby/object:Gem::Requirement
|
17
17
|
none: false
|
18
18
|
requirements:
|
19
19
|
- - ~>
|
@@ -21,10 +21,10 @@ dependencies:
|
|
21
21
|
version: '3.1'
|
22
22
|
type: :runtime
|
23
23
|
prerelease: false
|
24
|
-
version_requirements: *
|
24
|
+
version_requirements: *70244405693760
|
25
25
|
- !ruby/object:Gem::Dependency
|
26
26
|
name: ruby-debug19
|
27
|
-
requirement: &
|
27
|
+
requirement: &70244405693180 !ruby/object:Gem::Requirement
|
28
28
|
none: false
|
29
29
|
requirements:
|
30
30
|
- - ! '>='
|
@@ -32,10 +32,10 @@ dependencies:
|
|
32
32
|
version: '0'
|
33
33
|
type: :development
|
34
34
|
prerelease: false
|
35
|
-
version_requirements: *
|
35
|
+
version_requirements: *70244405693180
|
36
36
|
- !ruby/object:Gem::Dependency
|
37
37
|
name: rspec-rails
|
38
|
-
requirement: &
|
38
|
+
requirement: &70244405692480 !ruby/object:Gem::Requirement
|
39
39
|
none: false
|
40
40
|
requirements:
|
41
41
|
- - ~>
|
@@ -43,10 +43,10 @@ dependencies:
|
|
43
43
|
version: '2.6'
|
44
44
|
type: :development
|
45
45
|
prerelease: false
|
46
|
-
version_requirements: *
|
46
|
+
version_requirements: *70244405692480
|
47
47
|
- !ruby/object:Gem::Dependency
|
48
48
|
name: generator_spec
|
49
|
-
requirement: &
|
49
|
+
requirement: &70244405691920 !ruby/object:Gem::Requirement
|
50
50
|
none: false
|
51
51
|
requirements:
|
52
52
|
- - =
|
@@ -54,7 +54,7 @@ dependencies:
|
|
54
54
|
version: 0.8.5
|
55
55
|
type: :development
|
56
56
|
prerelease: false
|
57
|
-
version_requirements: *
|
57
|
+
version_requirements: *70244405691920
|
58
58
|
description: alpha - currently covers part of payments pro and all of mass pay
|
59
59
|
email:
|
60
60
|
- matt.handler@gmail.com
|
@@ -92,6 +92,7 @@ files:
|
|
92
92
|
- spec/support/parameter_spec.rb
|
93
93
|
- spec/support/request_spec.rb
|
94
94
|
- spec/support/response_spec.rb
|
95
|
+
- spec/unit/adaptive_payments_response_spec.rb
|
95
96
|
- spec/unit/adaptive_payments_spec.rb
|
96
97
|
- spec/unit/api_spec.rb
|
97
98
|
- spec/unit/mass_pay_spec.rb
|
@@ -126,6 +127,7 @@ test_files:
|
|
126
127
|
- spec/support/parameter_spec.rb
|
127
128
|
- spec/support/request_spec.rb
|
128
129
|
- spec/support/response_spec.rb
|
130
|
+
- spec/unit/adaptive_payments_response_spec.rb
|
129
131
|
- spec/unit/adaptive_payments_spec.rb
|
130
132
|
- spec/unit/api_spec.rb
|
131
133
|
- spec/unit/mass_pay_spec.rb
|