paypal_api 0.3.4 → 0.3.5
Sign up to get free protection for your applications and to get access to all the features.
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
|