paypkg 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
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: []