workarea-paypal 2.0.12 → 3.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (91) hide show
  1. checksums.yaml +4 -4
  2. data/.eslintrc.json +2 -1
  3. data/.gitignore +16 -11
  4. data/CHANGELOG.md +29 -5
  5. data/README.md +100 -6
  6. data/Rakefile +4 -5
  7. data/app/assets/javascripts/workarea/storefront/paypal/config.js.erb +44 -0
  8. data/app/assets/javascripts/workarea/storefront/paypal/modules/paypal_buttons.js +71 -0
  9. data/app/assets/javascripts/workarea/storefront/paypal/modules/paypal_hosted_fields.js +96 -0
  10. data/app/assets/javascripts/workarea/storefront/paypal/modules/update_checkout_submit_text.js +11 -5
  11. data/app/assets/javascripts/workarea/storefront/paypal/templates/paypal_fields.jst.ejs +43 -0
  12. data/app/controllers/workarea/storefront/checkout/place_order_controller.decorator +6 -4
  13. data/app/controllers/workarea/storefront/paypal_controller.rb +32 -26
  14. data/app/helpers/workarea/storefront/paypal_helper.rb +38 -0
  15. data/app/models/workarea/payment/authorize/paypal.rb +13 -13
  16. data/app/models/workarea/payment/capture/paypal.rb +10 -20
  17. data/app/models/workarea/payment/null_address.rb +37 -0
  18. data/app/models/workarea/payment/purchase/paypal.rb +1 -25
  19. data/app/models/workarea/payment/refund/paypal.rb +3 -6
  20. data/app/models/workarea/payment/tender/paypal.rb +14 -2
  21. data/app/models/workarea/payment.decorator +17 -3
  22. data/app/services/workarea/paypal/approve_order.rb +104 -0
  23. data/app/services/workarea/paypal/create_order.rb +177 -0
  24. data/app/services/workarea/paypal/update_order.rb +44 -0
  25. data/app/views/workarea/admin/orders/tenders/_paypal.html.haml +5 -2
  26. data/app/views/workarea/api/orders/tenders/_paypal.json.jbuilder +7 -1
  27. data/app/views/workarea/storefront/carts/_paypal_checkout.html.haml +6 -1
  28. data/app/views/workarea/storefront/checkouts/_paypal_payment.html.haml +16 -5
  29. data/app/views/workarea/storefront/order_mailer/tenders/_paypal.html.haml +5 -3
  30. data/app/views/workarea/storefront/orders/tenders/_paypal.html.haml +9 -2
  31. data/app/views/workarea/storefront/paypal/_paypal_sdk.html.haml +1 -0
  32. data/app/workers/workarea/paypal/handle_webhook_event.rb +64 -0
  33. data/config/initializers/append_points.rb +17 -5
  34. data/config/initializers/fields.rb +27 -0
  35. data/config/initializers/workarea.rb +41 -5
  36. data/config/locales/en.yml +14 -4
  37. data/config/routes.rb +3 -2
  38. data/lib/tasks/workarea/create_webhooks.rake +28 -0
  39. data/lib/workarea/paypal/engine.rb +4 -0
  40. data/lib/workarea/paypal/gateway.rb +200 -0
  41. data/lib/workarea/paypal/requests/create_webhook.rb +21 -0
  42. data/lib/workarea/paypal/requests/delete_webhook.rb +17 -0
  43. data/lib/workarea/paypal/requests/generate_token.rb +21 -0
  44. data/lib/workarea/paypal/requests/list_webhooks.rb +17 -0
  45. data/lib/workarea/paypal/version.rb +1 -1
  46. data/lib/workarea/paypal.rb +22 -19
  47. data/package.json +9 -0
  48. data/test/dummy/config/initializers/workarea.rb +1 -1
  49. data/test/factories/workarea/capture_completed_webhook.json +70 -0
  50. data/test/factories/workarea/capture_denied_webhook.json +68 -0
  51. data/test/factories/workarea/paypal.rb +34 -0
  52. data/test/helpers/workarea/storefront/paypal_helper_test.rb +35 -0
  53. data/test/integration/workarea/storefront/papyal_place_order_integration_test.rb +42 -0
  54. data/test/integration/workarea/storefront/paypal_integration_test.rb +104 -294
  55. data/test/lib/workarea/paypal/gateway_test.rb +236 -0
  56. data/test/models/workarea/payment/authorize/paypal_test.rb +57 -46
  57. data/test/models/workarea/payment/capture/paypal_test.rb +9 -51
  58. data/test/models/workarea/payment/null_address_test.rb +53 -0
  59. data/test/models/workarea/payment/refund/paypal_test.rb +39 -38
  60. data/test/models/workarea/paypal_payment_test.rb +65 -0
  61. data/test/models/workarea/search/paypal_order_text_test.rb +14 -0
  62. data/test/services/workarea/paypal/approve_order_test.rb +35 -0
  63. data/test/services/workarea/paypal/create_order_test.rb +127 -0
  64. data/test/services/workarea/paypal/update_order_test.rb +73 -0
  65. data/test/support/workarea/paypal_setup.rb +49 -0
  66. data/test/system/workarea/storefront/cart_system_test.decorator +1 -1
  67. data/test/system/workarea/storefront/logged_in_checkout_system_test.decorator +1 -1
  68. data/test/vcr_cassettes/paypal_approve_order.yml +106 -0
  69. data/test/vcr_cassettes/paypal_create_order.yml +110 -0
  70. data/test/vcr_cassettes/paypal_gateway_create_order.yml +105 -0
  71. data/test/vcr_cassettes/paypal_gateway_generate_token.yml +103 -0
  72. data/test/vcr_cassettes/paypal_gateway_get_order.yml +103 -0
  73. data/test/vcr_cassettes/paypal_gateway_update_order.yml +199 -0
  74. data/test/vcr_cassettes/paypal_gateway_webhooks.yml +403 -0
  75. data/test/vcr_cassettes/paypal_update_order.yml +204 -0
  76. data/test/workers/workarea/paypal/handle_webhook_event_test.rb +60 -0
  77. data/workarea-paypal.gemspec +2 -1
  78. metadata +64 -16
  79. data/app/services/workarea/paypal/setup.rb +0 -114
  80. data/app/services/workarea/paypal/update.rb +0 -69
  81. data/app/views/workarea/storefront/checkouts/_paypal_error.html.haml +0 -6
  82. data/app/views/workarea/storefront/order_mailer/tenders/_paypal.text.haml +0 -2
  83. data/lib/workarea/paypal/ext/active_merchant/paypal_express_gateway.rb +0 -9
  84. data/test/dummy/config/initializers/session_store.rb +0 -3
  85. data/test/integration/workarea/storefront/place_order_integration_test.decorator +0 -11
  86. data/test/models/workarea/payment/purchase/paypal_test.rb +0 -94
  87. data/test/models/workarea/payment_test.decorator +0 -34
  88. data/test/models/workarea/search/admin/order_test.decorator +0 -32
  89. data/test/services/workarea/paypal/setup_test.rb +0 -120
  90. data/test/services/workarea/paypal/update_test.rb +0 -221
  91. data/test/workarea/paypal/ext/active_merchant/paypal_express_gateway_test.rb +0 -17
@@ -3,346 +3,156 @@ require 'test_helper'
3
3
  module Workarea
4
4
  module Storefront
5
5
  class PaypalIntengrationTest < Workarea::IntegrationTest
6
- delegate :gateway, to: Workarea::Paypal
6
+ def assert_paypal_create_order
7
+ Paypal::CreateOrder.any_instance.expects(:perform)
8
+ .returns(OpenStruct.new(id: 'test123'))
9
+ end
10
+
11
+ def assert_paypal_approve_order
12
+ Paypal::ApproveOrder.any_instance.expects(:perform).returns(true)
13
+ end
14
+
15
+ def product
16
+ @product ||= create_product(
17
+ variants: [{ sku: 'SKU1', regular: 6.to_m, tax_code: '001' }]
18
+ )
19
+ end
7
20
 
8
- setup :stub_paypal_setup_redirect_url
21
+ def add_item_to_cart
22
+ post storefront.cart_items_path, params: {
23
+ product_id: product.id,
24
+ sku: product.skus.first,
25
+ quantity: 2
26
+ }
27
+ end
9
28
 
10
- def test_start_starts_checkout_when_guest
29
+ def test_create_starts_checkout_when_guest
11
30
  add_item_to_cart
12
31
  Workarea::Checkout.any_instance.expects(:start_as).with(:guest)
13
- get storefront.start_paypal_path
32
+ assert_paypal_create_order
33
+
34
+ post storefront.paypal_path, xhr: true
14
35
  end
15
36
 
16
- def test_start_starts_checkout_when_logged_in
37
+ def test_create_starts_checkout_when_logged_in
17
38
  add_item_to_cart
18
- user = User.new
19
39
 
20
- Workarea::Storefront::PaypalController
21
- .any_instance
22
- .stubs(:current_user)
23
- .returns(user)
40
+ user = create_user(email: 'test@workarea.com')
41
+ set_current_user(user)
24
42
 
25
43
  Workarea::Checkout.any_instance.expects(:start_as).with(user)
26
- get storefront.start_paypal_path
44
+ assert_paypal_create_order
45
+
46
+ post storefront.paypal_path, xhr: true
27
47
  end
28
48
 
29
- def test_start_does_not_start_checkout_from_checkout
49
+ def test_create_does_not_start_checkout_from_checkout
30
50
  add_item_to_cart
51
+ Workarea::Order.last.touch_checkout!
52
+
31
53
  Workarea::Checkout.any_instance.expects(:start_as).never
54
+ assert_paypal_create_order
32
55
 
33
- get storefront.start_paypal_path, params: { from_checkout: 'from_checkout' }
56
+ post storefront.paypal_path, xhr: true
34
57
  end
35
58
 
36
- def test_start_prices_the_order
59
+ def test_create_success
37
60
  add_item_to_cart
38
- Workarea::Pricing.expects(:perform)
39
61
 
40
- get storefront.start_paypal_path
41
- end
62
+ assert_paypal_create_order
42
63
 
43
- def test_start_uses_setup_to_redirect
44
- add_item_to_cart
45
- get storefront.start_paypal_path
46
- assert_redirected_to('http://paypal.com')
47
- end
64
+ post storefront.paypal_path, xhr: true
48
65
 
49
- def test_start_redirects_to_cart_if_empty
50
- get storefront.start_paypal_path
51
- assert_redirected_to(storefront.cart_path)
66
+ json = JSON.parse(response.body)
67
+ assert(json['id'].present?)
52
68
  end
53
69
 
54
- def test_start_rdirects_to_cart_if_inventory_is_not_available
55
- product = create_product(variants: [{ sku: 'SKU', regular: 5 }])
70
+ def test_create_on_existing_paypal_order
71
+ add_item_to_cart
56
72
 
57
- post storefront.cart_items_path, params: {
58
- product_id: product.id,
59
- sku: product.skus.first,
60
- quantity: 1
61
- }
73
+ order = Order.carts.last
74
+ order.touch_checkout!
62
75
 
63
- create_inventory(
64
- id: product.skus.first,
65
- policy: 'standard',
66
- available: 0
67
- )
76
+ payment = Payment.find_or_initialize_by(id: order.id)
77
+ payment.build_paypal(paypal_id: '0987', approved: true)
78
+ payment.save!
68
79
 
69
- get storefront.start_paypal_path
70
- assert_redirected_to(storefront.cart_path)
71
- end
80
+ Paypal::CreateOrder.any_instance.expects(:perform).never
72
81
 
73
- def test_complete_sets_the_current_order
74
- add_item_to_cart
75
- stub_paypal_update_apply
76
- Workarea::Storefront::PaypalController
77
- .any_instance
78
- .expects(:current_order=)
79
- get storefront.complete_paypal_path(order_id: order.id)
80
- end
82
+ post storefront.paypal_path, xhr: true
81
83
 
82
- def test_complete_applies_a_paupal_update
83
- add_item_to_cart
84
- Workarea::Paypal::Update
85
- .any_instance
86
- .expects(:apply)
87
-
88
- get storefront.complete_paypal_path(order_id: order.id)
84
+ json = JSON.parse(response.body)
85
+ assert_equal('0987', json['id'])
86
+ refute(payment.reload.paypal.approved?)
89
87
  end
90
88
 
91
- def test_complete_redirects_to_checkout_path
89
+ def test_create_failure
92
90
  add_item_to_cart
93
- stub_paypal_update_apply
94
- Workarea::Checkout
95
- .any_instance
96
- .stubs(:complete?)
97
- .returns(true)
98
- get storefront.complete_paypal_path(order_id: order.id)
99
- assert_redirected_to(storefront.checkout_payment_path)
100
- end
101
91
 
102
- def test_complete_redirects_to_payment_as_purchasable
103
- shipping_method = create_shipping_service
104
- product = create_product(variants: [{ sku: 'SKU', regular: 49.to_m }])
92
+ Paypal::CreateOrder.any_instance.expects(:perform).raises(
93
+ Paypal::Gateway::RequestError.new('failed')
94
+ )
105
95
 
106
- post storefront.cart_items_path, params: {
107
- product_id: product.id,
108
- sku: product.skus.first,
109
- quantity: 2
110
- }
96
+ post storefront.paypal_path, xhr: true
111
97
 
112
- order = Workarea::Order.last
113
-
114
- Workarea::Shipping.find_or_create_by(id: order.id)
115
- Workarea::Payment.find_or_create_by(id: order.id)
116
-
117
- checkout = Workarea::Checkout.new(order)
118
- checkout.update(
119
- shipping_address: {
120
- first_name: 'Test',
121
- last_name: 'User',
122
- street: '1 Main St',
123
- street_2: nil,
124
- city: 'San Jose',
125
- region: 'CA',
126
- postal_code: '95131',
127
- country: 'US'
128
- },
129
- billing_address: {
130
- first_name: 'Test',
131
- last_name: 'User',
132
- street: '1 Main St',
133
- street_2: nil,
134
- city: 'San Jose',
135
- region: 'CA',
136
- postal_code: '95131',
137
- country: 'US'
138
- },
139
- shipping_method_id: shipping_method.id,
140
- payment: 'paypal'
141
- )
98
+ assert_equal(500, response.status)
99
+ assert(flash[:error].present?)
100
+ end
142
101
 
143
- gateway.expects(:details_for).returns(details)
102
+ def test_update_success
103
+ add_item_to_cart
144
104
 
145
- get storefront.complete_paypal_path(order_id: order.id)
105
+ PaypalController.any_instance.expects(:check_inventory).returns(true)
106
+ Paypal::ApproveOrder.any_instance.expects(:perform).returns(true)
107
+ Workarea::Checkout.any_instance.expects(:complete?).returns(true)
146
108
 
147
- assert_redirected_to(storefront.checkout_payment_path)
148
- end
109
+ put storefront.paypal_approved_path('1234'), xhr: true
149
110
 
150
- def test_complete_redirects_to_address_if_paypal_address_invalid
151
- Workarea.with_config do |config|
152
- config.allow_shipping_address_po_box = false
153
-
154
- details.params['PaymentDetails']['ShipToAddress'] = {
155
- 'Name' => 'Test User',
156
- 'Street1' => 'PO Box 123',
157
- 'Street2' => nil,
158
- 'CityName' => 'San Jose',
159
- 'StateOrProvince' => 'CA',
160
- 'Country' => 'US',
161
- 'CountryName' => 'United States',
162
- 'Phone' => '610-867-5309',
163
- 'PostalCode' => '95131',
164
- 'AddressID' => nil,
165
- 'AddressOwner' => 'PayPal',
166
- 'ExternalAddressID' => nil,
167
- 'AddressStatus' => 'Confirmed'
168
- }
169
-
170
- gateway.expects(:details_for).returns(details)
171
-
172
- product = create_product(variants: [{ sku: 'SKU', regular: 5 }])
173
-
174
- post storefront.cart_items_path, params: {
175
- product_id: product.id,
176
- sku: product.skus.first,
177
- quantity: 1
178
- }
179
-
180
- order = Order.first
181
-
182
- get storefront.complete_paypal_path(order_id: order.id)
183
- assert_redirected_to(storefront.checkout_addresses_path)
184
- end
111
+ json = JSON.parse(response.body)
112
+ assert(json['success'])
113
+ assert_equal(storefront.checkout_payment_path, json['redirect_url'])
185
114
  end
186
115
 
187
- private
116
+ def test_update_failure
117
+ add_item_to_cart
188
118
 
189
- def order
190
- @order ||= create_order
191
- end
119
+ PaypalController.any_instance.expects(:check_inventory).returns(true)
120
+ Paypal::ApproveOrder.any_instance.expects(:perform).returns(true)
121
+ Workarea::Checkout.any_instance.expects(:complete?).returns(false)
122
+
123
+ put storefront.paypal_approved_path('1234'), xhr: true
124
+
125
+ json = JSON.parse(response.body)
126
+ refute(json['success'])
127
+ assert(flash[:error].present?)
128
+ end
129
+
130
+ def test_events
131
+ payment = create_payment(paypal: { paypal_id: '123', approved: true }).tap do |p|
132
+ p.paypal.build_transaction(
133
+ action: 'authorize',
134
+ amount: 5.to_m,
135
+ response: ActiveMerchant::Billing::Response.new(
136
+ true,
137
+ 'PayPal capture succeeded',
138
+ id: 'CAPTURE001',
139
+ status: 'PENDING'
140
+ )
141
+ ).save!
142
+ end
192
143
 
193
- def product
194
- @product ||= create_product(
195
- variants: [{ sku: 'SKU1', regular: 6.to_m, tax_code: '001' }]
196
- )
197
- end
144
+ post storefront.paypal_event_path,
145
+ params: webhook_capture_completed_payload
198
146
 
199
- def details
200
- @details ||= stub(
201
- email: 'bcrouse@workarea.com',
202
- token: 'EC-3LX76108SH791964A',
203
- payer_id: 'MDJZZYJ9SZJ52',
204
- params: {
205
- 'timestamp' => '2012-02-16T15:22:17Z',
206
- 'ack' => 'Success',
207
- 'correlation_id' => 'e5e29daee048a',
208
- 'version' => '62.0',
209
- 'build' => '2571254',
210
- 'token' => 'EC-3LX76108SH791964A',
211
- 'payer' => 'bcrouse@workarea.com',
212
- 'payer_id' => 'MDJZZYJ9SZJ52',
213
- 'payer_status' => 'verified',
214
- 'salutation' => nil,
215
- 'first_name' => 'Test',
216
- 'middle_name' => nil,
217
- 'last_name' => 'User',
218
- 'suffix' => nil,
219
- 'payer_country' => 'US',
220
- 'payer_business' => nil,
221
- 'name' => 'Test Product 866',
222
- 'street1' => '1 Main St',
223
- 'street2' => nil,
224
- 'city_name' => 'San Jose',
225
- 'state_or_province' => 'CA',
226
- 'country' => 'US',
227
- 'country_name' => 'United States',
228
- 'postal_code' => '95131',
229
- 'address_owner' => 'PayPal',
230
- 'address_status' => 'Confirmed',
231
- 'order_total' => '98.00',
232
- 'order_total_currency_id' => 'USD',
233
- 'item_total' => '98.00',
234
- 'item_total_currency_id' => 'USD',
235
- 'shipping_total' => '0.00',
236
- 'shipping_total_currency_id' => 'USD',
237
- 'handling_total' => '0.00',
238
- 'handling_total_currency_id' => 'USD',
239
- 'tax_total' => '0.00',
240
- 'tax_total_currency_id' => 'USD',
241
- 'phone' => nil,
242
- 'address_id' => nil,
243
- 'external_address_id' => nil,
244
- 'quantity' => '2',
245
- 'tax' => '0.00',
246
- 'tax_currency_id' => 'USD',
247
- 'amount' => '49.00',
248
- 'amount_currency_id' => 'USD',
249
- 'ebay_item_payment_details_item' => nil,
250
- 'insurance_total' => '0.00',
251
- 'insurance_total_currency_id' => 'USD',
252
- 'shipping_discount' => '0.00',
253
- 'shipping_discount_currency_id' => 'USD',
254
- 'insurance_option_offered' => 'false',
255
- 'seller_details' => nil,
256
- 'payment_request_id' => nil,
257
- 'order_url' => nil,
258
- 'soft_descriptor' => nil,
259
- 'checkout_status' => 'PaymentActionNotInitiated',
260
- 'Token' => 'EC-3LX76108SH791964A',
261
- 'PayerInfo' => {
262
- 'Payer' => 'bcrouse@workarea.com',
263
- 'PayerID' => 'MDJZZYJ9SZJ52',
264
- 'PayerStatus' => 'verified',
265
- 'PayerName' => {
266
- 'Salutation' => nil,
267
- 'FirstName' => 'Test',
268
- 'MiddleName' => nil,
269
- 'LastName' => 'User',
270
- 'Suffix' => nil
271
- },
272
- 'PayerCountry' => 'US',
273
- 'PayerBusiness' => nil,
274
- 'Address' => {
275
- 'Name' => 'Test User',
276
- 'Street1' => '1 Main St',
277
- 'Street2' => nil,
278
- 'CityName' => 'San Jose',
279
- 'StateOrProvince' => 'CA',
280
- 'Country' => 'US',
281
- 'CountryName' => 'United States',
282
- 'PostalCode' => '95131',
283
- 'AddressOwner' => 'PayPal',
284
- 'AddressStatus' => 'Confirmed'
285
- }
286
- },
287
- 'PaymentDetails' => {
288
- 'OrderTotal' => '98.00',
289
- 'ItemTotal' => '98.00',
290
- 'ShippingTotal' => '0.00',
291
- 'HandlingTotal' => '0.00',
292
- 'TaxTotal' => '0.00',
293
- 'ShipToAddress' => {
294
- 'Name' => 'Test User',
295
- 'Street1' => '1 Main St',
296
- 'Street2' => nil,
297
- 'CityName' => 'San Jose',
298
- 'StateOrProvince' => 'CA',
299
- 'Country' => 'US',
300
- 'CountryName' => 'United States',
301
- 'PostalCode' => '95131',
302
- 'AddressID' => nil,
303
- 'AddressOwner' => 'PayPal',
304
- 'ExternalAddressID' => nil,
305
- 'AddressStatus' => 'Confirmed'
306
- },
307
- 'PaymentDetailsItem' => {
308
- 'Name' => 'Test Product 866',
309
- 'Quantity' => '2',
310
- 'Tax' => '0.00',
311
- 'Amount' => '49.00',
312
- 'EbayItemPaymentDetailsItem' => nil
313
- },
314
- 'InsuranceTotal' => '0.00',
315
- 'ShippingDiscount' => '0.00',
316
- 'InsuranceOptionOffered' => 'false',
317
- 'SellerDetails' => nil,
318
- 'PaymentRequestID' => nil,
319
- 'OrderURL' => nil,
320
- 'SoftDescriptor' => nil
321
- },
322
- 'CheckoutStatus' => 'PaymentActionNotInitiated'
323
- }
324
- )
325
- end
147
+ assert(response.ok?)
326
148
 
327
- def add_item_to_cart
328
- post storefront.cart_items_path, params: {
329
- product_id: product.id,
330
- sku: product.skus.first,
331
- quantity: 2
332
- }
333
- end
149
+ payment.reload
334
150
 
335
- def stub_paypal_setup_redirect_url
336
- Workarea::Paypal::Setup
337
- .any_instance
338
- .stubs(:redirect_url)
339
- .returns('http://paypal.com')
340
- end
151
+ assert_equal(2, payment.paypal.transactions.count)
341
152
 
342
- def stub_paypal_update_apply
343
- Workarea::Paypal::Update
344
- .any_instance
345
- .stubs(:apply)
153
+ txn = payment.paypal.transactions.captures.first
154
+ assert(txn.success?)
155
+ assert_equal(5.to_m, txn.amount)
346
156
  end
347
157
  end
348
158
  end
@@ -0,0 +1,236 @@
1
+ require 'test_helper'
2
+
3
+ module Workarea
4
+ module Paypal
5
+ class GatewayTest < TestCase
6
+ include PaypalSetup
7
+
8
+ def gateway
9
+ Paypal::Gateway.new
10
+ end
11
+
12
+ def body
13
+ {
14
+ intent: 'CAPTURE',
15
+ purchase_units: [{
16
+ amount: {
17
+ currency_code: 'USD',
18
+ value: '100.00'
19
+ }
20
+ }]
21
+ }
22
+ end
23
+
24
+ def order_id
25
+ VCR.use_cassette('paypal_gateway_create_order') do
26
+ gateway.create_order(body: body).id
27
+ end
28
+ end
29
+
30
+ def test_generate_token
31
+ response = VCR.use_cassette('paypal_gateway_generate_token') do
32
+ gateway.generate_token
33
+ end
34
+
35
+ assert(response.result.client_token.present?)
36
+ end
37
+
38
+ def test_get_order
39
+ response = VCR.use_cassette('paypal_gateway_get_order') do
40
+ gateway.get_order(order_id)
41
+ end
42
+
43
+ assert_equal(200, response.status_code)
44
+ assert_equal(order_id, response.result.id)
45
+ assert(response.result.purchase_units.first.present?)
46
+ end
47
+
48
+ def test_create_order
49
+ response = VCR.use_cassette('paypal_gateway_create_order') do
50
+ gateway.create_order(body: body)
51
+ end
52
+
53
+ assert_equal('CREATED', response.status)
54
+ assert(response.id.present?)
55
+ end
56
+
57
+ def test_update_order
58
+ body = [
59
+ {
60
+ op: 'replace',
61
+ path: "/purchase_units/@reference_id=='default'/amount",
62
+ value: {
63
+ currency_code: 'USD',
64
+ value: '125.00'
65
+ }
66
+ }
67
+ ]
68
+
69
+ VCR.use_cassette('paypal_gateway_update_order') do
70
+ response = gateway.update_order(order_id, body: body)
71
+
72
+ response = gateway.get_order(order_id)
73
+ assert_equal(200, response.status_code)
74
+ assert_equal('125.00', response.result.purchase_units.first.amount.value)
75
+ end
76
+ end
77
+
78
+
79
+ def test_capture
80
+ stubbed_response = OpenStruct.new(
81
+ status_code: 201,
82
+ result: PayPalHttp::HttpClient.new(nil)._parse_values(
83
+ purchase_units: [
84
+ {
85
+ payments: {
86
+ captures: [{ id: 'CAPTURE_0001', status: 'COMPLETED' }]
87
+ }
88
+ }
89
+ ]
90
+ )
91
+ )
92
+
93
+ PayPal::PayPalHttpClient.any_instance.expects(:execute).returns(stubbed_response)
94
+
95
+ result = gateway.capture('1234')
96
+ assert(result.success?)
97
+ assert_equal('PayPal capture succeeded', result.message)
98
+ assert_equal({ 'id' => 'CAPTURE_0001', 'status' => 'COMPLETED' }, result.params)
99
+
100
+ stubbed_response.result.purchase_units.first.payments.captures.first.status = 'DECLINED'
101
+ PayPal::PayPalHttpClient.any_instance.unstub
102
+ PayPal::PayPalHttpClient.any_instance.expects(:execute).returns(stubbed_response)
103
+
104
+ result = gateway.capture('1234')
105
+ refute(result.success?)
106
+ assert_equal('PayPal capture failed', result.message)
107
+
108
+ stubbed_response.status_code = 422
109
+ stubbed_response.result.purchase_units.first.payments.captures.first.status = 'COMPLETED'
110
+ PayPal::PayPalHttpClient.any_instance.unstub
111
+ PayPal::PayPalHttpClient.any_instance.expects(:execute).returns(stubbed_response)
112
+
113
+ result = gateway.capture('1234')
114
+ refute(result.success?)
115
+ assert_equal('PayPal capture failed', result.message)
116
+ assert_equal(
117
+ { 'purchase_units' => [
118
+ { payments: { captures: [{ id: "CAPTURE_0001", status: 'COMPLETED' }] } }
119
+ ]
120
+ },
121
+ result.params
122
+ )
123
+
124
+ PayPal::PayPalHttpClient.any_instance.unstub
125
+ PayPal::PayPalHttpClient.any_instance.expects(:execute).raises(
126
+ PayPalHttp::HttpError.new(422, {}, { 'paypal-debug-id' => '123' })
127
+ )
128
+
129
+ result = gateway.capture('1234')
130
+ refute(result.success?)
131
+ assert_equal({ 'status_code' => 422, 'debug_id' => '123' }, result.params)
132
+
133
+ PayPal::PayPalHttpClient.any_instance.unstub
134
+ PayPal::PayPalHttpClient.any_instance.expects(:execute).raises(
135
+ StandardError.new('failed')
136
+ )
137
+
138
+ result = gateway.capture('1234')
139
+ refute(result.success?)
140
+ assert_equal('failed', result.message)
141
+ assert(result.params.blank?)
142
+ end
143
+
144
+
145
+ def test_refund
146
+ stubbed_response = OpenStruct.new(
147
+ status_code: 201,
148
+ result: OpenStruct.new(
149
+ id: 'REFUND_0001',
150
+ status: 'COMPLETED',
151
+ status_details: { reason: 'test test' }
152
+ )
153
+ )
154
+
155
+ PayPal::PayPalHttpClient
156
+ .any_instance
157
+ .expects(:execute)
158
+ .returns(stubbed_response)
159
+
160
+ result = gateway.refund('1234')
161
+ assert(result.success?)
162
+ assert_equal('PayPal refund succeeded', result.message)
163
+ assert_equal(
164
+ {
165
+ 'id' => 'REFUND_0001',
166
+ 'status' => 'COMPLETED',
167
+ 'status_details' => { reason: 'test test' },
168
+ 'capture_id' => '1234',
169
+ 'amount' => ''
170
+ },
171
+ result.params
172
+ )
173
+
174
+ PayPal::PayPalHttpClient.any_instance.unstub
175
+ PayPal::PayPalHttpClient
176
+ .any_instance
177
+ .expects(:execute)
178
+ .with { |req| assert_equal('50.00', req.body[:amount][:value]) }
179
+ .returns(stubbed_response)
180
+
181
+ result = gateway.refund('1234', amount: 50.to_m)
182
+ assert(result.success?)
183
+ assert_equal('PayPal refund succeeded', result.message)
184
+ assert_equal(
185
+ {
186
+ 'id' => 'REFUND_0001',
187
+ 'status' => 'COMPLETED',
188
+ 'status_details' => { reason: 'test test' },
189
+ 'capture_id' => '1234',
190
+ 'amount' => '50.00'
191
+ },
192
+ result.params
193
+ )
194
+ end
195
+
196
+ def test_webhooks
197
+ VCR.use_cassette('paypal_gateway_webhooks') do
198
+ webhook = gateway.create_webhook(
199
+ url: 'https://example.com/my-webhooks',
200
+ event_types: %w(
201
+ PAYMENT.CAPTURE.COMPLETED
202
+ PAYMENT.CAPTURE.DENIED
203
+ )
204
+ ).result
205
+
206
+ assert(webhook.id.present?)
207
+ assert_equal('https://example.com/my-webhooks', webhook.url)
208
+
209
+ list = gateway.list_webhooks.result.webhooks
210
+
211
+ assert_equal(1, list.length)
212
+ assert_equal(webhook.id, list.first.id)
213
+
214
+ gateway.delete_webhook(webhook.id)
215
+
216
+ list = gateway.list_webhooks.result.webhooks
217
+ assert_equal(0, list.length)
218
+ end
219
+ end
220
+
221
+ def test_client_id
222
+ ENV['WORKAREA_PAYPAL_CLIENT_ID'] = nil
223
+
224
+ if Rails.application.credentials.paypal.present?
225
+ assert(Rails.application.credentials.paypal[:client_id], gateway.client_id)
226
+ elsif Workarea.config.paypal.try(:[], :client_id).present?
227
+ assert(Workarea.config.paypal[:client_id], gateway.client_id)
228
+ end
229
+
230
+ ENV['WORKAREA_PAYPAL_CLIENT_ID'] = 'abc123'
231
+
232
+ assert('abc123', gateway.client_id)
233
+ end
234
+ end
235
+ end
236
+ end