paypkg 0.1.0

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.
Files changed (3) hide show
  1. checksums.yaml +7 -0
  2. data/lib/paypkg.rb +634 -0
  3. metadata +47 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 7a1b1e82c065451cb13a76219b3a7f1cc89f3103
4
+ data.tar.gz: 8e3d7e284685f149e6e3184177214483186a77eb
5
+ SHA512:
6
+ metadata.gz: 2a81c0cda26d8a17407a211c53d619c8c4120c033c639f41983d7cdec42afec95c0bb5239cea66b102e9aafa2d5345a535e9f4a5a59f4199c3f0f7cea754fe00
7
+ data.tar.gz: 6d204a7697be19548a9f9090a8b7c2d91f969fbc16fc4f8b740df08daa79e8b78c3f008bdcdaa48974a342402b7d15e81d1945841516b467c77abbf6ea370bca
data/lib/paypkg.rb ADDED
@@ -0,0 +1,634 @@
1
+ require "net/http"
2
+ require "yaml"
3
+
4
+ class NilClass
5
+ def empty?
6
+ true
7
+ end
8
+ end
9
+
10
+ class Paypkg
11
+
12
+ # when changing this, also change the gemspec
13
+ VERSION = "0.1.0"
14
+
15
+ attr_reader :json, :hash, :status, :mode, :link
16
+
17
+ private
18
+
19
+ def initialize(session=nil)
20
+ @session = if session then session else {} end
21
+ @session[:paypal_authorization] ||= {}
22
+ @session[:paypal_authorization][:expires_after] ||= Time.now-6
23
+ @session[:paypal_authorization][:access_token] ||= ""
24
+ env = Rails.env
25
+ @mode = env.to_sym
26
+ @credentials = YAML.load_file("#{Rails.root.to_path}/config/paypkg.yml")[env]
27
+ @website = @credentials['website']
28
+ @uri_base = @credentials['uri_base']
29
+ uri = URI.parse(@uri_base)
30
+ @http = Net::HTTP.new(uri.host, uri.port)
31
+ @http.use_ssl = true
32
+ #@http.set_debug_output $stderr # <-- ONLY FOR DEBUG!
33
+ @http.verify_mode = OpenSSL::SSL::VERIFY_NONE
34
+ set_access_token
35
+ @json = []
36
+ @hash = []
37
+ @status = []
38
+ end
39
+
40
+ def set_access_token
41
+ if (Time.now-5)>@session[:paypal_authorization][:expires_after]
42
+ request = Net::HTTP::Post.new("/v1/oauth2/token")
43
+ request.add_field("Accept","application/json")
44
+ request.add_field("Accept-Language","en_US")
45
+ request.basic_auth(@credentials['client_id'], @credentials['secret'])
46
+ request.body = "grant_type=client_credentials"
47
+ response = @http.request(request)
48
+ if response.code!='200'
49
+ @session[:paypal_authorization][:expires_after] = Time.now-1
50
+ @session[:paypal_authorization][:access_token] = ""
51
+ @access_token = nil
52
+ raise Net::HTTPServerException.new("Unable to obtain access token from PayPal", response)
53
+ else
54
+ hash = JSON.parse(response.body, :symbolize_names=>true)
55
+ @session[:paypal_authorization][:expires_after] = Time.now+hash[:expires_in]
56
+ @session[:paypal_authorization][:access_token] = hash[:access_token]
57
+ @access_token = @session[:paypal_authorization][:access_token]
58
+ end
59
+ else
60
+ @access_token = @session[:paypal_authorization][:access_token]
61
+ end
62
+ end
63
+
64
+ public
65
+
66
+ def call_paypal(endpoint, data=nil, options={reset: :yes, method: :get})
67
+ set_access_token
68
+ options = {:reset => :yes, :method => :get}.merge(options)
69
+ if options[:reset]==:yes
70
+ @json = []
71
+ @hash = []
72
+ @status = []
73
+ end
74
+ case
75
+ when options[:method]==:delete
76
+ request = Net::HTTP::Delete.new(endpoint)
77
+ when options[:method]==:post || data # a json string
78
+ request = Net::HTTP::Post.new(endpoint)
79
+ when options[:method]==:get
80
+ request = Net::HTTP::Get.new(endpoint)
81
+ end
82
+ request.add_field("Content-Type","application/json")
83
+ request.add_field("Authorization", "Bearer #{@access_token}")
84
+ request.body = data.gsub("'",'"') if data
85
+ response = @http.request(request)
86
+ response.body = nil if response.body.empty?
87
+ @json << response.body
88
+ @hash << if response.body then JSON.parse(response.body, :symbolize_names=>true) else nil end
89
+ @status << response.code
90
+ end
91
+
92
+ ######################
93
+ ### CURRENCY CODES ###
94
+ ######################
95
+
96
+ PAYPAL_CURRENCIES = {
97
+ "Australian dollar" => "AUD",
98
+ "Brazilian real" => "BRL",
99
+ "Canadian dollar" => "CAD",
100
+ "Czech koruna" => "CZK",
101
+ "Danish krone" => "DKK",
102
+ "Euro" => "EUR",
103
+ "Hong Kong dollar" => "HKD",
104
+ "Hungarian forint" => "HUF",
105
+ "Israeli new shekel" => "ILS",
106
+ "Japanese yen" => "JPY",
107
+ "Malaysian ringgit" => "MYR",
108
+ "Mexican peso" => "MXN",
109
+ "New Taiwan dollar" => "TWD",
110
+ "New Zealand dollar" => "NZD",
111
+ "Norwegian krone" => "NOK",
112
+ "Philippine peso" => "PHP",
113
+ "Polish złoty" => "PLN",
114
+ "Pound sterling" => "GBP",
115
+ "Singapore dollar" => "SGD",
116
+ "Swedish krona" => "SEK",
117
+ "Swiss franc" => "CHF",
118
+ "Thai baht" => "THB",
119
+ "Turkish lira" => "TRY",
120
+ "United States dollar" => "USD"
121
+ }
122
+
123
+ ######################
124
+ ### LANGUAGE CODES ###
125
+ ######################
126
+
127
+ PAYPAL_LANGUAGES = [
128
+ "da_DK",
129
+ "de_DE",
130
+ "en_AU",
131
+ "en_GB",
132
+ "en_US",
133
+ "es_ES",
134
+ "es_XC",
135
+ "fr_CA",
136
+ "fr_FR",
137
+ "fr_XC",
138
+ "he_IL",
139
+ "id_ID",
140
+ "it_IT",
141
+ "ja_JP",
142
+ "nl_NL",
143
+ "no_NO",
144
+ "pl_PL",
145
+ "pt_BR",
146
+ "pt_PT",
147
+ "ru_RU",
148
+ "sv_SE",
149
+ "th_TH",
150
+ "tr_TR",
151
+ "zh_CN",
152
+ "zh_HK",
153
+ "zh_TW",
154
+ "zh_XC"
155
+ ]
156
+
157
+ #####################
158
+ ### COUNTRY CODES ###
159
+ #####################
160
+
161
+ PAYPAL_COUNTRIES = {
162
+ "ALAND ISLANDS" => "AX",
163
+ "ALBANIA" => "AL",
164
+ "ALGERIA" => "DZ",
165
+ "AMERICAN SAMOA" => "AS",
166
+ "ANDORRA" => "AD",
167
+ "ANGOLA" => "AO",
168
+ "ANGUILLA" => "AI",
169
+ "ANTARCTICA" => "AQ",
170
+ "ANTIGUA AND BARBUDA" => "AG",
171
+ "ARGENTINA" => "AR",
172
+ "ARMENIA" => "AM",
173
+ "ARUBA" => "AW",
174
+ "AUSTRALIA" => "AU",
175
+ "AUSTRIA" => "AT",
176
+ "AZERBAIJAN" => "AZ",
177
+ "BAHAMAS" => "BS",
178
+ "BAHRAIN" => "BH",
179
+ "BANGLADESH" => "BD",
180
+ "BARBADOS" => "BB",
181
+ "BELGIUM" => "BE",
182
+ "BELIZE" => "BZ",
183
+ "BENIN" => "BJ",
184
+ "BERMUDA" => "BM",
185
+ "BHUTAN" => "BT",
186
+ "BOLIVIA" => "BO",
187
+ "BOSNIA-HERZEGOVINA" => "BA",
188
+ "BOTSWANA" => "BW",
189
+ "BOUVET ISLAND" => "BV",
190
+ "BRAZIL" => "BR",
191
+ "BRITISH INDIAN OCEAN TERRITORY" => "IO",
192
+ "BRUNEI DARUSSALAM" => "BN",
193
+ "BULGARIA" => "BG",
194
+ "BURKINA FASO" => "BF",
195
+ "BURUNDI" => "BI",
196
+ "CAMBODIA" => "KH",
197
+ "CANADA" => "CA",
198
+ "CAPE VERDE" => "CV",
199
+ "CAYMAN ISLANDS" => "KY",
200
+ "CENTRAL AFRICAN REPUBLIC" => "CF",
201
+ "CHAD" => "TD",
202
+ "CHILE" => "CL",
203
+ "CHINA" => "CN (For domestic Chinese bank transactions only)",
204
+ "CHRISTMAS ISLAND" => "CX",
205
+ "COCOS (KEELING) ISLANDS" => "CC",
206
+ "COLOMBIA" => "CO",
207
+ "COMOROS" => "KM",
208
+ "DEMOCRATIC REPUBLIC OF CONGO" => "CD",
209
+ "CONGO" => "CG",
210
+ "COOK ISLANDS" => "CK",
211
+ "COSTA RICA" => "CR",
212
+ "CROATIA" => "HR",
213
+ "CYPRUS" => "CY",
214
+ "CZECH REPUBLIC" => "CZ",
215
+ "DENMARK" => "DK",
216
+ "DJIBOUTI" => "DJ",
217
+ "DOMINICA" => "DM",
218
+ "DOMINICAN REPUBLIC" => "DO",
219
+ "ECUADOR" => "EC",
220
+ "EGYPT" => "EG",
221
+ "EL SALVADOR" => "SV",
222
+ "ERITERIA" => "ER",
223
+ "ESTONIA" => "EE",
224
+ "ETHIOPIA" => "ET",
225
+ "FALKLAND ISLANDS (MALVINAS)" => "FK",
226
+ "FAROE ISLANDS" => "FO",
227
+ "FIJI" => "FJ",
228
+ "FINLAND" => "FI",
229
+ "FRANCE" => "FR",
230
+ "FRENCH GUIANA" => "GF",
231
+ "FRENCH POLYNESIA" => "PF",
232
+ "FRENCH SOUTHERN TERRITORIES" => "TF",
233
+ "GABON" => "GA",
234
+ "GAMBIA" => "GM",
235
+ "GEORGIA" => "GE",
236
+ "GERMANY" => "DE",
237
+ "GHANA" => "GH",
238
+ "GIBRALTAR" => "GI",
239
+ "GREECE" => "GR",
240
+ "GREENLAND" => "GL",
241
+ "GRENADA" => "GD",
242
+ "GUADELOUPE" => "GP",
243
+ "GUAM" => "GU",
244
+ "GUATEMALA" => "GT",
245
+ "GUERNSEY" => "GG",
246
+ "GUINEA" => "GN",
247
+ "GUINEA BISSAU" => "GW",
248
+ "GUYANA" => "GY",
249
+ "HEARD ISLAND AND MCDONALD ISLANDS" => "HM",
250
+ "HOLY SEE (VATICAN CITY STATE)" => "VA",
251
+ "HONDURAS" => "HN",
252
+ "HONG KONG" => "HK",
253
+ "HUNGARY" => "HU",
254
+ "ICELAND" => "IS",
255
+ "INDIA" => "IN",
256
+ "INDONESIA" => "ID",
257
+ "IRELAND" => "IE",
258
+ "ISLE OF MAN" => "IM",
259
+ "ISRAEL" => "IL",
260
+ "ITALY" => "IT",
261
+ "JAMAICA" => "JM",
262
+ "JAPAN" => "JP",
263
+ "JERSEY" => "JE",
264
+ "JORDAN" => "JO",
265
+ "KAZAKHSTAN" => "KZ",
266
+ "KENYA" => "KE",
267
+ "KIRIBATI" => "KI",
268
+ "KOREA, REPUBLIC OF" => "KR",
269
+ "KUWAIT" => "KW",
270
+ "KYRGYZSTAN" => "KG",
271
+ "LAOS" => "LA",
272
+ "LATVIA" => "LV",
273
+ "LESOTHO" => "LS",
274
+ "LIECHTENSTEIN" => "LI",
275
+ "LITHUANIA" => "LT",
276
+ "LUXEMBOURG" => "LU",
277
+ "MACAO" => "MO",
278
+ "MACEDONIA" => "MK",
279
+ "MADAGASCAR" => "MG",
280
+ "MALAWI" => "MW",
281
+ "MALAYSIA" => "MY",
282
+ "MALDIVES" => "MV",
283
+ "MALI" => "ML",
284
+ "MALTA" => "MT",
285
+ "MARSHALL ISLANDS" => "MH",
286
+ "MARTINIQUE" => "MQ",
287
+ "MAURITANIA" => "MR",
288
+ "MAURITIUS" => "MU",
289
+ "MAYOTTE" => "YT",
290
+ "MEXICO" => "MX",
291
+ "MICRONESIA, FEDERATED STATES OF" => "FM",
292
+ "MOLDOVA, REPUBLIC OF" => "MD",
293
+ "MONACO" => "MC",
294
+ "MONGOLIA" => "MN",
295
+ "MONTENEGRO" => "ME",
296
+ "MONTSERRAT" => "MS",
297
+ "MOROCCO" => "MA",
298
+ "MOZAMBIQUE" => "MZ",
299
+ "NAMIBIA" => "NA",
300
+ "NAURU" => "NR",
301
+ "NEPAL" => "NP",
302
+ "NETHERLANDS" => "NL",
303
+ "NETHERLANDS ANTILLES" => "AN",
304
+ "NEW CALEDONIA" => "NC",
305
+ "NEW ZEALAND" => "NZ",
306
+ "NICARAGUA" => "NI",
307
+ "NIGER" => "NE",
308
+ "NIUE" => "NU",
309
+ "NORFOLK ISLAND" => "NF",
310
+ "NORTHERN MARIANA ISLANDS" => "MP",
311
+ "NORWAY" => "NO",
312
+ "OMAN" => "OM",
313
+ "PALAU" => "PW",
314
+ "PALESTINE" => "PS",
315
+ "PANAMA" => "PA",
316
+ "PARAGUAY" => "PY",
317
+ "PAPUA NEW GUINEA" => "PG",
318
+ "PERU" => "PE",
319
+ "PHILIPPINES" => "PH",
320
+ "PITCAIRN" => "PN",
321
+ "POLAND" => "PL",
322
+ "PORTUGAL" => "PT",
323
+ "PUERTO RICO" => "PR",
324
+ "QATAR" => "QA",
325
+ "REUNION" => "RE",
326
+ "ROMANIA" => "RO",
327
+ "REPUBLIC OF SERBIA" => "RS",
328
+ "RUSSIAN FEDERATION" => "RU",
329
+ "RWANDA" => "RW",
330
+ "SAINT HELENA" => "SH",
331
+ "SAINT KITTS AND NEVIS" => "KN",
332
+ "SAINT LUCIA" => "LC",
333
+ "SAINT PIERRE AND MIQUELON" => "PM",
334
+ "SAINT VINCENT AND THE GRENADINES" => "VC",
335
+ "SAMOA" => "WS",
336
+ "SAN MARINO" => "SM",
337
+ "SAO TOME AND PRINCIPE" => "ST",
338
+ "SAUDI ARABIA" => "SA",
339
+ "SENEGAL" => "SN",
340
+ "SEYCHELLES" => "SC",
341
+ "SIERRA LEONE" => "SL",
342
+ "SINGAPORE" => "SG",
343
+ "SLOVAKIA" => "SK",
344
+ "SLOVENIA" => "SI",
345
+ "SOLOMON ISLANDS" => "SB",
346
+ "SOMALIA" => "SO",
347
+ "SOUTH AFRICA" => "ZA",
348
+ "SOUTH GEORGIA AND THE SOUTH SANDWICH ISLANDS" => "GS",
349
+ "SPAIN" => "ES",
350
+ "SRI LANKA" => "LK",
351
+ "SURINAME" => "SR",
352
+ "SVALBARD AND JAN MAYEN" => "SJ",
353
+ "SWAZILAND" => "SZ",
354
+ "SWEDEN" => "SE",
355
+ "SWITZERLAND" => "CH",
356
+ "TAIWAN, PROVINCE OF CHINA" => "TW",
357
+ "TAJIKISTAN" => "TJ",
358
+ "TANZANIA, UNITED REPUBLIC OF" => "TZ",
359
+ "THAILAND" => "TH",
360
+ "TIMOR-LESTE" => "TL",
361
+ "TOGO" => "TG",
362
+ "TOKELAU" => "TK",
363
+ "TONGA" => "TO",
364
+ "TRINIDAD AND TOBAGO" => "TT",
365
+ "TUNISIA" => "TN",
366
+ "TURKEY" => "TR",
367
+ "TURKMENISTAN" => "TM",
368
+ "TURKS AND CAICOS ISLANDS" => "TC",
369
+ "TUVALU" => "TV",
370
+ "UGANDA" => "UG",
371
+ "UKRAINE" => "UA",
372
+ "UNITED ARAB EMIRATES" => "AE",
373
+ "UNITED KINGDOM" => "GB",
374
+ "UNITED STATES" => "US",
375
+ "UNITED STATES MINOR OUTLYING ISLANDS" => "UM",
376
+ "URUGUAY" => "UY",
377
+ "UZBEKISTAN" => "UZ",
378
+ "VANUATU" => "VU",
379
+ "VENEZUELA" => "VE",
380
+ "VIETNAM" => "VN",
381
+ "VIRGIN ISLANDS, BRITISH" => "VG",
382
+ "VIRGIN ISLANDS, U.S." => "VI",
383
+ "WALLIS AND FUTUNA" => "WF",
384
+ "WESTERN SAHARA" => "EH",
385
+ "YEMEN" => "YE",
386
+ "ZAMBIA" => "ZM"
387
+ }
388
+
389
+ ############################
390
+ ### Validate Credit Card ###
391
+ ############################
392
+
393
+ def validate_credit_card(type, number, expire_month, expire_year, cvv2, \
394
+ first_name, last_name, line1, city, state, postal_code, country_code)
395
+ call_paypal("/v1/payments/payment", "{
396
+ 'intent':'authorize',
397
+ 'payer':{
398
+ 'payment_method':'credit_card',
399
+ 'funding_instruments':[
400
+ {
401
+ 'credit_card':{
402
+ 'number':'#{number}',
403
+ 'type':'#{type}',
404
+ 'expire_month':#{expire_month},
405
+ 'expire_year':#{expire_year},
406
+ 'cvv2':'#{cvv2}',
407
+ 'first_name':'#{first_name}',
408
+ 'last_name':'#{last_name}',
409
+ 'billing_address':{
410
+ 'line1':'#{line1}',
411
+ 'city':'#{city}',
412
+ 'state':'#{state}',
413
+ 'postal_code':'#{postal_code}',
414
+ 'country_code':'#{country_code}'
415
+ }
416
+ }
417
+ }
418
+ ]
419
+ },
420
+ 'transactions':[
421
+ {
422
+ 'amount':{
423
+ 'total':0.01,
424
+ 'currency':'USD'
425
+ },
426
+ 'description':'This is a validation transaction.'
427
+ }
428
+ ]
429
+ }")
430
+ if (@status.last=='201') && (@hash.last[:state]=='approved')
431
+ link = @hash.last[:transactions][0][:related_resources][0][:authorization][:links].select{|link| link[:rel]=='void'}
432
+ call_paypal(link[0][:href], nil, :method => :post, :reset => :no)
433
+ return true if (@status.last=='200') && (@hash.last[:state]=='voided')
434
+ end
435
+ return false
436
+ end
437
+
438
+ #########################
439
+ ### Store Credit Card ###
440
+ #########################
441
+
442
+ def store_credit_card(type, number, expire_month, expire_year, cvv2, first_name,
443
+ last_name, line1, line2, city, state, postal_code, country_code, payer_id)
444
+ json = "{
445
+ 'payer_id':'#{payer_id}',
446
+ 'type':'#{type}',
447
+ 'number':'#{number}',
448
+ 'expire_month':'#{expire_month}',
449
+ 'expire_year':'#{expire_year}',
450
+ 'cvv2':'#{cvv2}',
451
+ 'first_name':'#{first_name}',
452
+ 'last_name':'#{last_name}',
453
+ 'billing_address':{
454
+ 'line1':'#{line1}',\n"
455
+ json << " 'line2':'#{line2}',\n" if line2
456
+ json << " 'city':'#{city}',
457
+ 'state':'#{state}',
458
+ 'postal_code':'#{postal_code}',
459
+ 'country_code':'#{country_code}'
460
+ }
461
+ }"
462
+ call_paypal("/v1/vault/credit-card", json)
463
+ return (@status.last=='201') && (@hash.last[:state]=='ok')
464
+ end
465
+
466
+ ############################
467
+ ### Retrieve Credit Card ###
468
+ ############################
469
+
470
+ def retrieve_credit_card(vault_id)
471
+ call_paypal("/v1/vault/credit-card/#{vault_id}")
472
+ return (@status.last=='200') && (@hash.last[:state]=='ok')
473
+ end
474
+
475
+ ##########################
476
+ ### Delete Credit Card ###
477
+ ##########################
478
+
479
+ def delete_credit_card(vault_id)
480
+ call_paypal("/v1/vault/credit-card/#{vault_id}", nil, :method => :delete)
481
+ return (@status.last=='204') && (@hash.last==nil)
482
+ end
483
+
484
+ ##########################################
485
+ ### Payment Using Accepted Credit Card ###
486
+ ##########################################
487
+
488
+ def accept_tendered_cc_payment(type, number, expire_month, expire_year, cvv2, first_name,
489
+ last_name, amount, desc)
490
+ formatted_amount = "%0.2f"%amount
491
+ json = "{
492
+ 'intent':'sale',
493
+ 'payer':{
494
+ 'payment_method':'credit_card',
495
+ 'funding_instruments':[
496
+ {
497
+ 'credit_card':{
498
+ 'type':'#{type}',
499
+ 'number':'#{number}',"
500
+ json << " 'cvv2':'#{cvv2}'," if cvv2
501
+ json << " 'first_name':'#{first_name}'," if first_name
502
+ json << " 'last_name':'#{last_name}'," if last_name
503
+ json << " 'expire_month':'#{expire_month}',
504
+ 'expire_year':'#{expire_year}'
505
+ }
506
+ }
507
+ ]
508
+ },
509
+ 'transactions':[
510
+ {
511
+ 'amount':{
512
+ 'total':'#{formatted_amount}',
513
+ 'currency':'USD'
514
+ },
515
+ 'description':'#{desc}'
516
+ }
517
+ ]
518
+ }"
519
+ call_paypal("/v1/payments/payment", json)
520
+ return (@status.last=='201') && (@hash.last[:state]=='approved')
521
+ end
522
+
523
+ ########################################
524
+ ### Payment Using Stored Credit Card ###
525
+ ########################################
526
+
527
+ def accept_stored_cc_payment(card_id, amount, desc, email, payer_id)
528
+ formatted_amount = "%0.2f"%amount
529
+ call_paypal("/v1/payments/payment", "{
530
+ 'intent':'sale',
531
+ 'payer':{
532
+ 'payment_method':'credit_card',
533
+ 'payer_info':{
534
+ 'email':'#{email}'
535
+ },
536
+ 'funding_instruments':[
537
+ {
538
+ 'credit_card_token':{
539
+ 'credit_card_id':'#{card_id}',
540
+ 'payer_id':'#{payer_id}'
541
+ }
542
+ }
543
+ ]
544
+ },
545
+ 'transactions':[
546
+ {
547
+ 'amount':{
548
+ 'total':'#{formatted_amount}',
549
+ 'currency':'USD'
550
+ },
551
+ 'description':'#{desc}'
552
+ }
553
+ ]
554
+ }")
555
+ return (@status.last=='201') && (@hash.last[:state]=='approved')
556
+ end
557
+
558
+ ##############################
559
+ ### Payment Through PayPal ###
560
+ ##############################
561
+
562
+ def accept_pp_payment(amount, desc, approved_url, cancelled_url, payer_id)
563
+ set_access_token # we need this here to set the @website
564
+ formatted_amount = "%0.2f"%amount
565
+ json, status = call_paypal("/v1/payments/payment", "{
566
+ 'intent':'sale',
567
+ 'redirect_urls':{
568
+ 'return_url':'#{@website}/#{approved_url}/',
569
+ 'cancel_url':'#{@website}/#{cancelled_url}/'
570
+ },
571
+ 'payer':{
572
+ 'payment_method':'paypal'
573
+ },
574
+ 'transactions':[
575
+ {
576
+ 'amount':{
577
+ 'total':'#{formatted_amount}',
578
+ 'currency':'USD'
579
+ },
580
+ 'description':'#{desc}'
581
+ }
582
+ ]
583
+ }")
584
+ if (@status.last=='201') && (@hash.last[:state]=='created')
585
+ @session[:payment_id] = @hash.last[:id]
586
+ @link = @hash.last[:links].select{|link| link[:rel]=='approval_url'}[0][:href]
587
+ return true
588
+ else
589
+ return false
590
+ end
591
+ end
592
+
593
+ # this is executed by the code at the 'accepted' url
594
+ def execute_payment(payer_id, payment_id)
595
+ call_paypal("/v1/payments/payment/#{payment_id}/execute/", "{
596
+ 'payer_id' : '#{payer_id}'
597
+ }")
598
+ return (@status.last=='200') && (@hash.last[:state]=='approved')
599
+ end
600
+
601
+ #################################
602
+ ### Retrieve Sale Transaction ###
603
+ #################################
604
+
605
+ def retrieve_sale_transaction(sale_id)
606
+ call_paypal("/v1/payments/sale/#{sale_id}")
607
+ return (@status.last=='200') && (['pending', 'completed', 'refunded', 'partially_refunded'].index(@hash.last[:state])>0)
608
+ end
609
+
610
+ ###############################################
611
+ ### Full or Partial Refund Previous Payment ###
612
+ ###############################################
613
+
614
+ def refund_sale(sale_id,amount)
615
+ formatted_amount = "%0.2f"%amount
616
+ call_paypal("/v1/payments/sale/#{sale_id}/refund", "{
617
+ 'amount': {
618
+ 'total': #{formatted_amount},
619
+ 'currency': 'USD'
620
+ }
621
+ }")
622
+ return (@status.last=='201') && (@hash.last[:state]=='completed')
623
+ end
624
+
625
+ ###################################
626
+ ### Retrieve Refund Transaction ###
627
+ ###################################
628
+
629
+ def retrieve_refund_transaction(refund_id)
630
+ call_paypal("/v1/payments/refund/#{refund_id}")
631
+ return (@status.last=='200') && (['pending', 'completed', 'refunded', 'partially_refunded'].index(@hash.last[:state])>0)
632
+ end
633
+
634
+ end
metadata ADDED
@@ -0,0 +1,47 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: paypkg
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Michael J. Welch, Ph.D.
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2014-04-16 00:00:00.000000000 Z
12
+ dependencies: []
13
+ description: An interface to PayPal that's simple and transparent. This gem uses Net::HTTP
14
+ to communicate with the PayPal servers, and json files that conform to the specs
15
+ on developer.paypal.com. Look at lib/paypkg.rb in the gem. This gem has absolutely
16
+ no documentation yet, but I'll get around to it later.
17
+ email: paypkg@czarmail.com
18
+ executables: []
19
+ extensions: []
20
+ extra_rdoc_files: []
21
+ files:
22
+ - lib/paypkg.rb
23
+ homepage: http://rubygems.org/gems/paypkg
24
+ licenses:
25
+ - MIT
26
+ metadata: {}
27
+ post_install_message:
28
+ rdoc_options: []
29
+ require_paths:
30
+ - lib
31
+ required_ruby_version: !ruby/object:Gem::Requirement
32
+ requirements:
33
+ - - '>='
34
+ - !ruby/object:Gem::Version
35
+ version: '0'
36
+ required_rubygems_version: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - '>='
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ requirements: []
42
+ rubyforge_project:
43
+ rubygems_version: 2.0.7
44
+ signing_key:
45
+ specification_version: 4
46
+ summary: Pay Package (paypkg) is a simple, transparent interface to PayPal.
47
+ test_files: []