paypkg 0.1.0 → 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 7a1b1e82c065451cb13a76219b3a7f1cc89f3103
4
- data.tar.gz: 8e3d7e284685f149e6e3184177214483186a77eb
3
+ metadata.gz: b5b0aa6a615a910d02a4c57fa7c2a70fbf95eeb3
4
+ data.tar.gz: 1fd27b3481a219eb03e2c98d11e4fa1e7a24033c
5
5
  SHA512:
6
- metadata.gz: 2a81c0cda26d8a17407a211c53d619c8c4120c033c639f41983d7cdec42afec95c0bb5239cea66b102e9aafa2d5345a535e9f4a5a59f4199c3f0f7cea754fe00
7
- data.tar.gz: 6d204a7697be19548a9f9090a8b7c2d91f969fbc16fc4f8b740df08daa79e8b78c3f008bdcdaa48974a342402b7d15e81d1945841516b467c77abbf6ea370bca
6
+ metadata.gz: 59f31039f45400d9897354dde0e50aaa23226f1ceb623f42a8adc20fbf9d82cf170466097cbbff8a0204ce295fa95e9ea58701d1c48239c2d1fe2e150d7420e3
7
+ data.tar.gz: 115c69d5783457506a674ee76505818c4ce00e648e6af3a5996b7ee94fc2386c00b061a58f13e8d239a48717f15d2bc4f553b830e68f99e457558f97928db947
data/CHANGELOG.md ADDED
@@ -0,0 +1,13 @@
1
+ 0.1.1
2
+ -----
3
+ * Added PaypkgResponse, a class that converts a hash equivilent of the json output to an object.
4
+ This will make it more compatible with existing code based on ActiveRecord.
5
+ * Added more documentation. See the README.md file.
6
+ * Split out all the PayPal functions into individual files so that new functions can be added
7
+ without risking damaging anything. This also makes it easier to add new functions to the gem.
8
+ * Added a PaypkgTestController and a paypkg_test views folder that can be used for testing,
9
+ and seeing how to use the package.
10
+
11
+ 0.1.0
12
+ -----
13
+ * Created initial Pay Package gem and uploaded it to rubygems.org. There is no documentation yet.
data/README.md ADDED
@@ -0,0 +1,222 @@
1
+ Copyright (c) 2014, Michael J. Welch, Ph.D. and Contributors. All Rights Reserved.
2
+ Email: rubygems@czarmail.com
3
+
4
+ This project is licenced under the [MIT License](LICENSE.md).
5
+
6
+
7
+ ###############
8
+ ### Install ###
9
+ ###############
10
+
11
+ To install this gem, use:
12
+ gem install paypkg
13
+
14
+ I also recommend pretty_inspect, which I use in my example below
15
+ and in the test page:
16
+ gem install pretty_inspect
17
+
18
+ Add the following routes to your route file:
19
+ get 'paypkg_test/test1' => 'paypkg_test#test1'
20
+ get 'paypkg_test/test2' => 'paypkg_test#test2'
21
+ get 'paypkg_test/approved' => 'paypkg_test#approved'
22
+ get 'paypkg_test/cancelled' => 'paypkg_test#cancelled'
23
+
24
+ Copy the files in the gem's test folder to the app/controllers and app/views, as appropriate:
25
+
26
+
27
+ ####################################
28
+ ### Setup the Configuration File ###
29
+ ####################################
30
+
31
+ This gem requires a config file in config/paypkg.yml in your
32
+ Rails project that looks like this:
33
+
34
+ --- begin config/paypkg.yml -----------------------------------------------
35
+ development:
36
+ client_id: 'AZPi5hCY-0SoaLmignRs9XV6N4mvRS2TVKFDF2ni53alKL0iJTvtcy9BSR4D'
37
+ secret: 'EDubEBAg_ZztC-_HlsW16IFZcxBIatFt7c0ILuxNTpWAVnvrsO9ywVxnHr7J'
38
+ uri_base: 'https://api.sandbox.paypal.com'
39
+ website: 'http://www.example.com:3000'
40
+
41
+ test:
42
+ client_id: 'AZPi5hCY-0SoaLmignRs9XV6N4mvRS2TVKFDF2ni53alKL0iJTvtcy9BSR4D'
43
+ secret: 'EDubEBAg_ZztC-_HlsW16IFZcxBIatFt7c0ILuxNTpWAVnvrsO9ywVxnHr7J'
44
+ uri_base: 'https://api.sandbox.paypal.com'
45
+ website: 'http://www.example.com:3000'
46
+
47
+ production:
48
+ client_id: 'AVWiuBCE6_ps2zCh0Qaq0MaIbP8v2bjfFnKH5esYR9v6sNvu-MzVeWny3crM'
49
+ secret: 'EKKoNhCgFn_0lmpUAxXir0ySN4cmaLzGugUmnkgZHR90Kg9Y_DFmJbI2H0Ee'
50
+ uri_base: 'https://api.paypal.com'
51
+ website: 'https://www.example.com'
52
+ --- end config/paypkg.yml -------------------------------------------------
53
+
54
+ See the sample in this gem under config/paypkg.yml.
55
+
56
+ You have to place your client_id and secret in the file in place of these,
57
+ and you have to replace the website with yours. Note that the production
58
+ website has https, not http. If your production website is not encrypted
59
+ with SSL, use http instead of https.
60
+
61
+
62
+ ######################
63
+ ### Testing in irb ###
64
+ ######################
65
+
66
+ The Paypkg class can't see the session variable (because it's only visible
67
+ in ApplicationController classes), so to test this interactively, go into
68
+ your project and run "rails c" to start irb with a Rails environment, then
69
+ create a session variable, and create an instance. You can then run the
70
+ functions.
71
+
72
+ Why can't I just use irb? Because you need the Rails environment.
73
+ That's why the tests are supplied as a controller/views.
74
+
75
+
76
+ ######################
77
+ ### Using Bundler? ###
78
+ ######################
79
+
80
+ If you're using bundler, you'll have to add 'paypkg' and 'pretty_inspect'
81
+ to your Gemfile, then do a 'bundler install' to be able to use them.
82
+
83
+
84
+ ###############################
85
+ ### An Example in "rails c" ###
86
+ ###############################
87
+
88
+ To use the example, by the way, you'll have to put in a 'CARD-XXX...'
89
+ number of your own.
90
+
91
+ Here is an example:
92
+
93
+ devel@mail:~/czar$ rails c
94
+ Loading development environment (Rails 4.0.4)
95
+ irb(main):001:0> session = {}
96
+ => {}
97
+ irb(main):002:0> pp = Paypkg.new session
98
+ => #<Paypkg:0x000000049f5138 @session={:paypal_authorization=>{:expires_after=>2014-04-19 04:54:05 +0000,\
99
+ :access_token=>"8PhJDJVg1mxxGUpSHj9RzzUxB0.sS0qiajx2Nxa1.Fg"}}, @mode=:development,
100
+ @credentials={"client_id"=>"AZPi5hCY-0SoaLsvRSni5mignR3a9XlKL2TVKFDFV6N4m20iJTvtcy9BSR4D",
101
+ "secret"=>"EDubEBAg_ZztC-_HlscxNTpWAVtFt7c0ILZW1BIaOnvrsux6IF9ywVxnHr7J",
102
+ "uri_base"=>"https://api.sandbox.paypal.com", "website"=>"http://www.example.com:3000"},
103
+ @website="http://www.example.com:3000", @uri_base="https://api.sandbox.paypal.com",
104
+ @http=#<Net::HTTP api.sandbox.paypal.com:443 open=false>,
105
+ @access_token="8PhJDJVg1mxxGUpSHj9RzzUxB0.sS0qiajx2Nxa1.Fg", @json=[], @hash=[], @status=[]>
106
+ irb(main):003:0> @ok = pp.retrieve_credit_card('CARD-22T35414AU135641UKLX6GPQ')
107
+ => true
108
+ irb(main):004:0> puts pp.json
109
+ {"id":"CARD-22T35414AU135641UKLX6GPQ","state":"ok","payer_id":"admin","type":"visa",
110
+ "number":"xxxxxxxxxxxx0331","expire_month":"11","expire_year":"2018","first_name":"Betsy",
111
+ "last_name":"Buyer","billing_address":{"line1":"111 First Street", "city":"Saratoga",
112
+ "state":"CA","postal_code":"95070","country_code":"US"},
113
+ "valid_until":"2017-02-02T00:00:00Z","create_time":"2014-02-03T18:43:10Z",
114
+ "update_time":"2014-02-03T18:43:10Z",
115
+ "links":[{"href":"https://api.sandbox.paypal.com/v1/vault/credit-card/CARD-22T35414AU135641UKLX6GPQ","rel":"self","method":"GET"},
116
+ {"href":"https://api.sandbox.paypal.com/v1/vault/credit-card/CARD-22T35414AU135641UKLX6GPQ","rel":"delete","method":"DELETE"},
117
+ {"href":"https://api.sandbox.paypal.com/v1/vault/credit-card/CARD-22T35414AU135641UKLX6GPQ","rel":"patch","method":"PATCH"}]}
118
+ => nil
119
+ irb(main):005:0> puts pp.status
120
+ 200
121
+ => nil
122
+ irb(main):006:0> puts pp.mode
123
+ development
124
+ => nil
125
+ irb(main):007:0> puts pp.hash
126
+ {:id=>"CARD-22T35414AU135641UKLX6GPQ", :state=>"ok", :payer_id=>"admin", :type=>"visa",
127
+ :number=>"xxxxxxxxxxxx0331", :expire_month=>"11", :expire_year=>"2018", :first_name=>"Betsy",
128
+ :last_name=>"Buyer", :billing_address=>{:line1=>"111 First Street", :city=>"Saratoga",
129
+ :state=>"CA", :postal_code=>"95070", :country_code=>"US"},
130
+ :valid_until=>"2017-02-02T00:00:00Z", :create_time=>"2014-02-03T18:43:10Z",
131
+ :update_time=>"2014-02-03T18:43:10Z",
132
+ :links=>[{:href=>"https://api.sandbox.paypal.com/v1/vault/credit-card/CARD-22T35414AU135641UKLX6GPQ", :rel=>"self", :method=>"GET"},
133
+ {:href=>"https://api.sandbox.paypal.com/v1/vault/credit-card/CARD-22T35414AU135641UKLX6GPQ", :rel=>"delete", :method=>"DELETE"},
134
+ {:href=>"https://api.sandbox.paypal.com/v1/vault/credit-card/CARD-22T35414AU135641UKLX6GPQ", :rel=>"patch", :method=>"PATCH"}]}
135
+ => nil
136
+ irb(main):008:0> puts pp.hash.pretty_inspect
137
+ [
138
+ {
139
+ :id => "CARD-22T35414AU135641UKLX6GPQ",
140
+ :state => "ok",
141
+ :payer_id => "admin",
142
+ :type => "visa",
143
+ :number => "xxxxxxxxxxxx0331",
144
+ :expire_month => "11",
145
+ :expire_year => "2018",
146
+ :first_name => "Betsy",
147
+ :last_name => "Buyer",
148
+ :billing_address => {
149
+ :line1 => "111 First Street",
150
+ :city => "Saratoga",
151
+ :state => "CA",
152
+ :postal_code => "95070",
153
+ :country_code => "US"
154
+ },
155
+ :valid_until => "2017-02-02T00:00:00Z",
156
+ :create_time => "2014-02-03T18:43:10Z",
157
+ :update_time => "2014-02-03T18:43:10Z",
158
+ :links => [
159
+ {
160
+ :href => "https://api.sandbox.paypal.com/v1/vault/credit-card/CARD-22T35414AU135641UKLX6GPQ",
161
+ :rel => "self",
162
+ :method => "GET"
163
+ },
164
+ {
165
+ :href => "https://api.sandbox.paypal.com/v1/vault/credit-card/CARD-22T35414AU135641UKLX6GPQ",
166
+ :rel => "delete",
167
+ :method => "DELETE"
168
+ },
169
+ {
170
+ :href => "https://api.sandbox.paypal.com/v1/vault/credit-card/CARD-22T35414AU135641UKLX6GPQ",
171
+ :rel => "patch",
172
+ :method => "PATCH"
173
+ }
174
+ ]
175
+ }
176
+ ]
177
+ => nil
178
+ irb(main):009:0> r=pp.response
179
+ => #<PaypkgResponse:0x000000045fe7a0 @id="CARD-22T35414AU135641UKLX6GPQ", @state="ok", @payer_id="admin", @type="visa", @number="xxxxxxxxxxxx0331", @expire_month="11", @expire_year="2018", @first_name="Betsy", @last_name="Buyer", @billing_address=#<PaypkgResponse:0x000000045fd170 @state="CA", @line1="111 First Street", @city="Saratoga", @postal_code="95070", @country_code="US">, @valid_until="2017-02-02T00:00:00Z", @create_time="2014-02-03T18:43:10Z", @update_time="2014-02-03T18:43:10Z", @links=[#<PaypkgResponse:0x00000004603f20 @href="https://api.sandbox.paypal.com/v1/vault/credit-card/CARD-22T35414AU135641UKLX6GPQ", @rel="self", @method="GET">, #<PaypkgResponse:0x00000004603728 @href="https://api.sandbox.paypal.com/v1/vault/credit-card/CARD-22T35414AU135641UKLX6GPQ", @rel="delete", @method="DELETE">, #<PaypkgResponse:0x000000046030c0 @href="https://api.sandbox.paypal.com/v1/vault/credit-card/CARD-22T35414AU135641UKLX6GPQ", @rel="patch", @method="PATCH">]>
180
+ irb(main):010:0> r.billing_address.line1
181
+ => "2945 Hampton Ave"
182
+ irb(main):009:0>
183
+
184
+
185
+ ############################
186
+ ### PaypkgResponse Class ###
187
+ ############################
188
+
189
+ The class PaypkgResponse is used to objectize a response hash (or almost any
190
+ hash object). Free free to use it separately in other projects, if it works for you.
191
+
192
+ To get the PayPal response in an object format, after a successful call, use response = pp.response.
193
+ If you want this, for example:
194
+
195
+ payment_data = pp.hash.last
196
+ @amount = payment_data[:transactions][0][:related_resources][0][:sale][:amount][:total]
197
+
198
+ you would use this:
199
+
200
+ payment_data = pp.response # this will convert pp.hash.last
201
+ @amount = payment_data.transactions[0].related_resources[0].sale.amount.total
202
+
203
+ This is provided to be more compatible with views using ActiveRecord conventions.
204
+
205
+
206
+ ###############
207
+ ### Caveats ###
208
+ ###############
209
+
210
+ Caveats:
211
+ 1. This class is designed to do the most common things most people want
212
+ to do, but without much fuss.
213
+ 2. You can make your own calls to PayPal by creating a json data string
214
+ and calling call_paypal. See the cURL commands in the documentation
215
+ to see how the json should be configured. Look at the existing methods
216
+ in lib/paypkg to see how they are structured. Just add yours to the
217
+ lib/paypkg folder, and it will be available after the gem is
218
+ reloaded. Refer to https://developer.paypal.com/webapps/developer/docs/api/
219
+ for PayPal Restful calls.
220
+ 3. Be sure to look at the PaypkgTestController for information on how
221
+ to use the calls in your appication.
222
+
data/config/paypkg.yml ADDED
@@ -0,0 +1,18 @@
1
+ development:
2
+ client_id: 'AZPi5hCY-0SoaLmignRs9XV6N4mvRS2TVKFDF2ni53alKL0iJTvtcy9BSR4D'
3
+ secret: 'EDubEBAg_ZztC-_HlsW16IFZcxBIatFt7c0ILuxNTpWAVnvrsO9ywVxnHr7J'
4
+ uri_base: 'https://api.sandbox.paypal.com'
5
+ website: 'http://www.example.com:3000'
6
+
7
+ test:
8
+ client_id: 'AZPi5hCY-0SoaLmignRs9XV6N4mvRS2TVKFDF2ni53alKL0iJTvtcy9BSR4D'
9
+ secret: 'EDubEBAg_ZztC-_HlsW16IFZcxBIatFt7c0ILuxNTpWAVnvrsO9ywVxnHr7J'
10
+ uri_base: 'https://api.sandbox.paypal.com'
11
+ website: 'http://www.example.com:3000'
12
+
13
+ production:
14
+ client_id: 'AVWiuBCE6_ps2zCh0Qaq0MaIbP8v2bjfFnKH5esYR9v6sNvu-MzVeWny3crM'
15
+ secret: 'EKKoNhCgFn_0lmpUAxXir0ySN4cmaLzGugUmnkgZHR90Kg9Y_DFmJbI2H0Ee'
16
+ uri_base: 'https://api.paypal.com'
17
+ website: 'https://www.example.com'
18
+
@@ -0,0 +1,77 @@
1
+ ##############################
2
+ ### Payment Through PayPal ###
3
+ ##############################
4
+
5
+ class Paypkg
6
+ # This method is intended for use when you want to charge
7
+ # a user's PayPay account. The user will be required to give
8
+ # an on-line approval.
9
+ #
10
+ # The two urls shown here must be in your controller, and
11
+ # in your config/routes.rb file. See the execute_payment
12
+ # method below. You should store the payment_id you get
13
+ # back from this call (in session[:payment_id] here).
14
+ #
15
+ # @param amount
16
+ # @param desc
17
+ # @param approved_url
18
+ # @param cancelled_url
19
+ # @param payer_id
20
+ def accept_pp_payment(amount, desc, approved_url, cancelled_url, payer_id)
21
+ set_access_token # we need this here to set the @website
22
+ formatted_amount = "%0.2f"%amount
23
+ json, status = call_paypal("/v1/payments/payment", "{
24
+ 'intent':'sale',
25
+ 'redirect_urls':{
26
+ 'return_url':'#{@website}/#{approved_url}/',
27
+ 'cancel_url':'#{@website}/#{cancelled_url}/'
28
+ },
29
+ 'payer':{
30
+ 'payment_method':'paypal'
31
+ },
32
+ 'transactions':[
33
+ {
34
+ 'amount':{
35
+ 'total':'#{formatted_amount}',
36
+ 'currency':'USD'
37
+ },
38
+ 'description':'#{desc}'
39
+ }
40
+ ]
41
+ }")
42
+ if (@status.last=='201') && (@hash.last[:state]=='created')
43
+ @session[:payment_id] = @hash.last[:id]
44
+ @link = @hash.last[:links].select{|link| link[:rel]=='approval_url'}[0][:href]
45
+ return true
46
+ else
47
+ return false
48
+ end
49
+ end
50
+
51
+ # This is executed by the code at the 'accepted' url.
52
+ #
53
+ # Your controller must provide two url's that look like
54
+ # the code below, and are in your config/routes.rb
55
+ #
56
+ # def approved
57
+ # pp = Paypkg.new(session)
58
+ # @ok = pp.execute_payment(params[:PayerID],session[:payment_id])
59
+ # ... more logic ...
60
+ # end
61
+ #
62
+ # def cancelled
63
+ # ... handle the user cancelling out ...
64
+ # end
65
+ #
66
+ # You should save the sale_id returned from this call in your
67
+ # database.
68
+ #
69
+ # @param payer_id
70
+ # @param payment_id
71
+ def execute_payment(payer_id, payment_id)
72
+ call_paypal("/v1/payments/payment/#{payment_id}/execute/", "{
73
+ 'payer_id' : '#{payer_id}'
74
+ }")
75
+ return (@status.last=='200') && (@hash.last[:state]=='approved')
76
+ end
77
+ end
@@ -0,0 +1,43 @@
1
+ ########################################
2
+ ### Payment Using Stored Credit Card ###
3
+ ########################################
4
+
5
+ class Paypkg
6
+ # This method is intended for use when you want to charge
7
+ # a card stored in the vault.
8
+ # @param card_id [String] Required.
9
+ # @param amount [Numeric] Required.
10
+ # @param desc [String] Required.
11
+ # @param email [String] Required.
12
+ # @param payer_id [String] Required.
13
+ def accept_stored_cc_payment(card_id, amount, desc, email, payer_id)
14
+ formatted_amount = "%0.2f"%amount
15
+ call_paypal("/v1/payments/payment", "{
16
+ 'intent':'sale',
17
+ 'payer':{
18
+ 'payment_method':'credit_card',
19
+ 'payer_info':{
20
+ 'email':'#{email}'
21
+ },
22
+ 'funding_instruments':[
23
+ {
24
+ 'credit_card_token':{
25
+ 'credit_card_id':'#{card_id}',
26
+ 'payer_id':'#{payer_id}'
27
+ }
28
+ }
29
+ ]
30
+ },
31
+ 'transactions':[
32
+ {
33
+ 'amount':{
34
+ 'total':'#{formatted_amount}',
35
+ 'currency':'USD'
36
+ },
37
+ 'description':'#{desc}'
38
+ }
39
+ ]
40
+ }")
41
+ return (@status.last=='201') && (@hash.last[:state]=='approved')
42
+ end
43
+ end
@@ -0,0 +1,50 @@
1
+ ##########################################
2
+ ### Payment Using Accepted Credit Card ###
3
+ ##########################################
4
+
5
+ class Paypkg
6
+ # This call is intended for use when the card is presented, but
7
+ # not stored in the vault.
8
+ # @param number [String] Required.
9
+ # @param cvv2 [String] Optional.
10
+ # @param first_name [String] Optional.
11
+ # @param last_name [String] Optional.
12
+ # @param expire_month [String] Required.
13
+ # @param expire_year [String] Required.
14
+ # @param amount [String] Required.
15
+ # @param desc [String] Required.
16
+ def accept_tendered_cc_payment(type, number, expire_month, expire_year, cvv2, first_name,
17
+ last_name, amount, desc)
18
+ formatted_amount = "%0.2f"%amount
19
+ json = "{
20
+ 'intent':'sale',
21
+ 'payer':{
22
+ 'payment_method':'credit_card',
23
+ 'funding_instruments':[
24
+ {
25
+ 'credit_card':{
26
+ 'type':'#{type}',
27
+ 'number':'#{number}',"
28
+ json << " 'cvv2':'#{cvv2}'," if cvv2
29
+ json << " 'first_name':'#{first_name}'," if first_name
30
+ json << " 'last_name':'#{last_name}'," if last_name
31
+ json << " 'expire_month':'#{expire_month}',
32
+ 'expire_year':'#{expire_year}'
33
+ }
34
+ }
35
+ ]
36
+ },
37
+ 'transactions':[
38
+ {
39
+ 'amount':{
40
+ 'total':'#{formatted_amount}',
41
+ 'currency':'USD'
42
+ },
43
+ 'description':'#{desc}'
44
+ }
45
+ ]
46
+ }"
47
+ call_paypal("/v1/payments/payment", json)
48
+ return (@status.last=='201') && (@hash.last[:state]=='approved')
49
+ end
50
+ end
@@ -0,0 +1,13 @@
1
+ ##########################
2
+ ### Delete Credit Card ###
3
+ ##########################
4
+
5
+ class Paypkg
6
+ # Delete a card from the vault. If Paypal already removed the card
7
+ # because it expired, just ignore the error. NO JSON STRING is
8
+ # returned with this call.
9
+ def delete_credit_card(vault_id)
10
+ call_paypal("/v1/vault/credit-card/#{vault_id}", nil, :method => :delete)
11
+ return (@status.last=='204') && (@hash.last==nil)
12
+ end
13
+ end
@@ -0,0 +1,12 @@
1
+ #####################################################
2
+ ### This extends NilClass to add empty? #############
3
+ ### It just makes sense that nil is empty, right? ###
4
+ #####################################################
5
+
6
+ class NilClass
7
+ # This adds the empty? method to nil, so that nil.empty? => true
8
+ def empty?
9
+ true
10
+ end
11
+ end
12
+