paypkg 0.1.0 → 0.1.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 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
+