workarea-paypal 2.0.9 → 3.0.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (90) hide show
  1. checksums.yaml +4 -4
  2. data/.eslintrc.json +2 -1
  3. data/.gitignore +16 -11
  4. data/CHANGELOG.md +79 -0
  5. data/README.md +105 -6
  6. data/Rakefile +4 -5
  7. data/UPGRADE.md +46 -0
  8. data/app/assets/javascripts/workarea/storefront/paypal/config.js.erb +44 -0
  9. data/app/assets/javascripts/workarea/storefront/paypal/modules/paypal_buttons.js +71 -0
  10. data/app/assets/javascripts/workarea/storefront/paypal/modules/paypal_hosted_fields.js +96 -0
  11. data/app/assets/javascripts/workarea/storefront/paypal/modules/update_checkout_submit_text.js +11 -5
  12. data/app/assets/javascripts/workarea/storefront/paypal/templates/paypal_fields.jst.ejs +43 -0
  13. data/app/controllers/workarea/storefront/checkout/place_order_controller.decorator +6 -4
  14. data/app/controllers/workarea/storefront/paypal_controller.rb +32 -26
  15. data/app/helpers/workarea/storefront/paypal_helper.rb +38 -0
  16. data/app/models/workarea/payment.decorator +17 -3
  17. data/app/models/workarea/payment/authorize/paypal.rb +13 -13
  18. data/app/models/workarea/payment/capture/paypal.rb +10 -20
  19. data/app/models/workarea/payment/null_address.rb +37 -0
  20. data/app/models/workarea/payment/purchase/paypal.rb +1 -25
  21. data/app/models/workarea/payment/refund/paypal.rb +3 -6
  22. data/app/models/workarea/payment/tender/paypal.rb +14 -2
  23. data/app/services/workarea/paypal/approve_order.rb +104 -0
  24. data/app/services/workarea/paypal/create_order.rb +177 -0
  25. data/app/services/workarea/paypal/update_order.rb +44 -0
  26. data/app/views/workarea/admin/orders/tenders/_paypal.html.haml +5 -2
  27. data/app/views/workarea/api/orders/tenders/_paypal.json.jbuilder +7 -1
  28. data/app/views/workarea/storefront/carts/_paypal_checkout.html.haml +6 -1
  29. data/app/views/workarea/storefront/checkouts/_paypal_payment.html.haml +16 -5
  30. data/app/views/workarea/storefront/order_mailer/tenders/_paypal.html.haml +5 -3
  31. data/app/views/workarea/storefront/orders/tenders/_paypal.html.haml +9 -2
  32. data/app/views/workarea/storefront/paypal/_paypal_sdk.html.haml +1 -0
  33. data/app/workers/workarea/paypal/handle_webhook_event.rb +64 -0
  34. data/config/initializers/append_points.rb +17 -5
  35. data/config/initializers/fields.rb +27 -0
  36. data/config/initializers/workarea.rb +41 -5
  37. data/config/locales/en.yml +14 -4
  38. data/config/routes.rb +3 -2
  39. data/lib/tasks/workarea/create_webhooks.rake +29 -0
  40. data/lib/workarea/paypal.rb +22 -18
  41. data/lib/workarea/paypal/engine.rb +4 -0
  42. data/lib/workarea/paypal/gateway.rb +200 -0
  43. data/lib/workarea/paypal/requests/create_webhook.rb +21 -0
  44. data/lib/workarea/paypal/requests/delete_webhook.rb +17 -0
  45. data/lib/workarea/paypal/requests/generate_token.rb +21 -0
  46. data/lib/workarea/paypal/requests/list_webhooks.rb +17 -0
  47. data/lib/workarea/paypal/version.rb +1 -1
  48. data/package.json +9 -0
  49. data/test/dummy/config/initializers/workarea.rb +1 -1
  50. data/test/factories/workarea/capture_completed_webhook.json +70 -0
  51. data/test/factories/workarea/capture_denied_webhook.json +68 -0
  52. data/test/factories/workarea/paypal.rb +34 -0
  53. data/test/helpers/workarea/storefront/paypal_helper_test.rb +35 -0
  54. data/test/integration/workarea/storefront/paypal_integration_test.rb +104 -294
  55. data/test/integration/workarea/storefront/paypal_place_order_integration_test.rb +42 -0
  56. data/test/lib/workarea/paypal/gateway_test.rb +236 -0
  57. data/test/models/workarea/payment/authorize/paypal_test.rb +57 -46
  58. data/test/models/workarea/payment/capture/paypal_test.rb +9 -51
  59. data/test/models/workarea/payment/null_address_test.rb +53 -0
  60. data/test/models/workarea/payment/refund/paypal_test.rb +39 -38
  61. data/test/models/workarea/paypal_payment_test.rb +65 -0
  62. data/test/models/workarea/search/paypal_order_text_test.rb +14 -0
  63. data/test/services/workarea/paypal/approve_order_test.rb +35 -0
  64. data/test/services/workarea/paypal/create_order_test.rb +127 -0
  65. data/test/services/workarea/paypal/update_order_test.rb +73 -0
  66. data/test/support/workarea/paypal_setup.rb +49 -0
  67. data/test/system/workarea/storefront/cart_system_test.decorator +1 -1
  68. data/test/system/workarea/storefront/logged_in_checkout_system_test.decorator +1 -1
  69. data/test/vcr_cassettes/paypal_approve_order.yml +106 -0
  70. data/test/vcr_cassettes/paypal_create_order.yml +110 -0
  71. data/test/vcr_cassettes/paypal_gateway_create_order.yml +105 -0
  72. data/test/vcr_cassettes/paypal_gateway_generate_token.yml +103 -0
  73. data/test/vcr_cassettes/paypal_gateway_get_order.yml +103 -0
  74. data/test/vcr_cassettes/paypal_gateway_update_order.yml +199 -0
  75. data/test/vcr_cassettes/paypal_gateway_webhooks.yml +403 -0
  76. data/test/vcr_cassettes/paypal_update_order.yml +204 -0
  77. data/test/workers/workarea/paypal/handle_webhook_event_test.rb +60 -0
  78. data/workarea-paypal.gemspec +2 -1
  79. metadata +65 -14
  80. data/app/services/workarea/paypal/setup.rb +0 -114
  81. data/app/services/workarea/paypal/update.rb +0 -69
  82. data/app/views/workarea/storefront/checkouts/_paypal_error.html.haml +0 -6
  83. data/app/views/workarea/storefront/order_mailer/tenders/_paypal.text.haml +0 -2
  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
@@ -1,3 +1,5 @@
1
- %p{ style: "margin: 0 0 6px; font: 13px/1.5 arial; color: #{@config.text_color};" }
2
- = t('workarea.storefront.paypal.paid_with_paypal')
3
- = number_to_currency tender.amount
1
+ - if tender.direct_payment?
2
+ = render 'workarea/storefront/order_mailer/tenders/credit_card', tender: tender
3
+ - else
4
+ %p
5
+ = "#{t('workarea.storefront.paypal.paid_with_paypal')}: #{number_to_currency tender.amount}"
@@ -1,2 +1,9 @@
1
- %p= t('workarea.storefront.paypal.paid_with_paypal')
2
- %p= number_to_currency(tender.amount)
1
+ - if tender.direct_payment?
2
+ = render 'workarea/storefront/orders/tenders/credit_card', tender: tender
3
+ - else
4
+ .data-card
5
+ .data-card__cell
6
+ %p.data-card__line
7
+ = t('workarea.storefront.paypal.paid_with_paypal')
8
+ %p.data-card__line
9
+ = number_to_currency(tender.amount)
@@ -0,0 +1 @@
1
+ = include_paypal_javascript_tag
@@ -0,0 +1,64 @@
1
+ module Workarea
2
+ module Paypal
3
+ class HandleWebhookEvent
4
+ include Sidekiq::Worker
5
+
6
+ def perform(event, resource)
7
+ event_method = event.optionize
8
+ return send(event_method, resource) if respond_to?(event_method)
9
+
10
+ logger.error("FAILED: #{event} webhook is not supported.")
11
+ end
12
+
13
+ def payment_capture_completed(resource)
14
+ transaction = Payment::Transaction.where(
15
+ 'response.params.id' => resource['id']
16
+ ).first
17
+
18
+ if transaction.nil?
19
+ logger.error("FAILED: Transaction with capture ID of #{resource['id']} does not exist.")
20
+ return
21
+ end
22
+
23
+ tender = transaction.payment.tenders.detect do |t|
24
+ t.id.to_s == transaction.tender_id
25
+ end
26
+ return unless tender.present?
27
+
28
+ amount = resource['amount']
29
+ txn = tender.build_transaction(
30
+ action: 'capture',
31
+ success: true,
32
+ reference: transaction,
33
+ amount: amount['value'].to_m(amount['currency_code']),
34
+ response: ActiveMerchant::Billing::Response.new(
35
+ true,
36
+ 'Paypal capture was confirmed.',
37
+ resource
38
+ )
39
+ )
40
+
41
+ txn.save!
42
+ end
43
+
44
+ def payment_capture_denied(resource)
45
+ transaction = Payment::Transaction.where(
46
+ 'response.params.id' => resource['id']
47
+ ).first
48
+
49
+ if transaction.nil?
50
+ logger.error("FAILED: Transaction with capture ID of #{resource['id']} does not exist.")
51
+ return
52
+ end
53
+
54
+ transaction.cancellation = ActiveMerchant::Billing::Response.new(
55
+ true,
56
+ "PayPal capture was denied",
57
+ resource
58
+ )
59
+ transaction.canceled_at = Time.current
60
+ transaction.save!
61
+ end
62
+ end
63
+ end
64
+ end
@@ -1,11 +1,11 @@
1
1
  Workarea::Plugin.append_partials(
2
- 'storefront.cart_checkout_actions',
3
- 'workarea/storefront/carts/paypal_checkout'
2
+ 'storefront.document_head',
3
+ 'workarea/storefront/paypal/paypal_sdk'
4
4
  )
5
5
 
6
6
  Workarea::Plugin.append_partials(
7
- 'storefront.payment_error',
8
- 'workarea/storefront/checkouts/paypal_error'
7
+ 'storefront.cart_show',
8
+ 'workarea/storefront/carts/paypal_checkout'
9
9
  )
10
10
 
11
11
  Workarea::Plugin.append_partials(
@@ -13,7 +13,19 @@ Workarea::Plugin.append_partials(
13
13
  'workarea/storefront/checkouts/paypal_payment'
14
14
  )
15
15
 
16
+ Workarea::Plugin.append_javascripts(
17
+ 'storefront.config',
18
+ 'workarea/storefront/paypal/config'
19
+ )
20
+
21
+ Workarea::Plugin.append_javascripts(
22
+ 'storefront.templates',
23
+ 'workarea/storefront/paypal/templates/paypal_fields'
24
+ )
25
+
16
26
  Workarea::Plugin.append_javascripts(
17
27
  'storefront.modules',
18
- 'workarea/storefront/paypal/modules/update_checkout_submit_text'
28
+ 'workarea/storefront/paypal/modules/update_checkout_submit_text',
29
+ 'workarea/storefront/paypal/modules/paypal_buttons',
30
+ 'workarea/storefront/paypal/modules/paypal_hosted_fields'
19
31
  )
@@ -0,0 +1,27 @@
1
+ Workarea::Configuration.define_fields do
2
+ fieldset 'PayPal', namespaced: false do
3
+ # PayPal credentials can be configured via environment variables:
4
+ # WORKAREA_PAYPAL_CLIENT_ID
5
+ # WORKAREA_PAYPAL_CLIENT_SECRET
6
+ #
7
+ # via rails credentials:
8
+ # paypal:
9
+ # client_id: YOUR_CLIENT_ID
10
+ # client_secret: YOUR_CLIENT_SECRET
11
+ #
12
+ # Or through the workarea admin configuration. Setting credentials through
13
+ # the configuration allows for dyanmically changing credentials if, for
14
+ # example, you are using the multi-site plugin and wish to use different
15
+ # PayPal accounts for some or all sites.
16
+ #
17
+ field 'Client ID',
18
+ type: :string,
19
+ id: 'paypal_client_id',
20
+ description: 'Your Paypal Merchant Account Application Client ID'
21
+ field 'Client Secret',
22
+ type: :string,
23
+ id: 'paypal_client_secret',
24
+ encrypted: true,
25
+ description: 'Your Paypal Merchant Account Application Client Secret'
26
+ end
27
+ end
@@ -1,7 +1,43 @@
1
- Workarea.config.tender_types << :paypal
2
1
 
3
- # Gateway application_id is sent as PayPal BN code for revenue sharing
4
- # 'WebLinc_SP' should be used for all WebLinc installations
5
- ActiveMerchant::Billing::PaypalGateway.application_id = 'WebLinc_SP'
2
+ Workarea.configure do |config|
3
+ config.tender_types << :paypal
6
4
 
7
- Workarea::Paypal.auto_configure_gateway
5
+ # Determines which environment class to use. The PayPal SDK requires the
6
+ # use of different classes depending on the type of environment you are
7
+ # interacting with. By default, sandbox will be used unless in production.
8
+ # This behavior can be changed within your application by redefining this
9
+ # configuration.
10
+ #
11
+ config.paypal_environment =
12
+ if Rails.env.production?
13
+ 'Paypal::LiveEnvironment'
14
+ else
15
+ 'PayPal::SandboxEnvironment'
16
+ end
17
+
18
+ # Parameters passed as a query string to the paypal javascript sdk script
19
+ # when loaded on the storefront. This can be used to customize settings and
20
+ # display options.
21
+ # See https://developer.paypal.com/docs/checkout/reference/customize-sdk/
22
+ # for more information.
23
+ #
24
+ config.paypal_sdk_params = {
25
+ commit: false,
26
+ debug: Rails.env.development?
27
+ }
28
+
29
+ # Enable/Disable paypal as your credit card processor. This will enable
30
+ # code that takes over the credit card fields during checkout and submits
31
+ # payment info directly to paypal. You will need to enable unbranded credit
32
+ # cards through PayPal. Contact PayPal directly for more information.
33
+ #
34
+ config.use_paypal_hosted_fields = false
35
+
36
+ # Events to register a webhook for when running the rake tasks to setup
37
+ # webhooks, workarea:payal:create_webhooks.
38
+ #
39
+ config.default_webhook_events = %w(
40
+ PAYMENT.CAPTURE.COMPLETED
41
+ PAYMENT.CAPTURE.DENIED
42
+ )
43
+ end
@@ -1,4 +1,3 @@
1
- ---
2
1
  en:
3
2
  workarea:
4
3
  admin:
@@ -6,13 +5,24 @@ en:
6
5
  tenders:
7
6
  paypal:
8
7
  title: PayPal
8
+ payment:
9
+ paypal_capture: Paypal funding is pending capture and cannot be completed manually. Capture will be recorded after an update from PayPal.
10
+ paypal:
11
+ gateway:
12
+ http_error: "%{status} : PayPal request error, debug ID %{debug_id}"
13
+ capture_error: Select a new payment option and try again.
9
14
  storefront:
10
15
  paypal:
11
- address_error: We can not ship to this address. Please enter a new address.
12
16
  check_out: Check Out with PayPal
13
- checkout_submit_text: Continue to PayPal
14
- on_continue: When you continue, you will be taken to the PayPal website.
17
+ checkout_submit_text: Select a PayPal payment option to continue
18
+ checkout_review_text: Submit Payment and Review
19
+ errors:
20
+ order_incomplete: Your checkout is incomplete. Please review your shipping and billing information and try again.
21
+ place_order: You must complete your paypal transaction before submitting your order.
22
+ request_failed: There was a problem contacting PayPal. Please try again. If the problem persists, try a different payment method or contact customer support.
23
+ on_continue: Select a PayPal payment option.
15
24
  paid_with_paypal: Paid with PayPal
25
+ payment_failed: Your submitted PayPal payment could not be completed. Select a new method and try again.
16
26
  payment_recieved: Thank You! We have received your information back from PayPal.
17
27
  Please confirm that the shipping address and shipping method are correct,
18
28
  then click on 'Place Order'.
@@ -1,4 +1,5 @@
1
1
  Workarea::Storefront::Engine.routes.draw do
2
- get 'paypal/start' => 'paypal#start', as: :start_paypal
3
- get 'paypal/complete/:order_id' => 'paypal#complete', as: :complete_paypal
2
+ post 'paypal' => 'paypal#create'
3
+ put 'paypal/:id/approved' => 'paypal#update', as: :paypal_approved
4
+ post 'paypal/event' => 'paypal#event', as: :paypal_event
4
5
  end
@@ -0,0 +1,29 @@
1
+ namespace :workarea do
2
+ namespace :paypal do
3
+ desc 'Register webhook listeners for PayPal'
4
+ task create_webhooks: :environment do
5
+ puts 'Unsubscribing existing webhooks...'
6
+ webhooks = Workarea::Paypal.gateway.list_webhooks.result.webhooks
7
+
8
+
9
+ webhooks.each do |webhook|
10
+ begin
11
+ Workarea::Paypal.gateway.delete_webhook(webhook.id)
12
+ rescue Workarea::Paypal::Gateway::RequestError => e
13
+ puts "Webhook deletion #{id} failed. #{e.message}"
14
+ end
15
+ end
16
+
17
+ puts 'Subscribing to PayPal webhook events...'
18
+ Workarea::Paypal.gateway.create_webhook(
19
+ url: Workarea::Storefront::Engine.routes.url_helpers.paypal_event_url(
20
+ host: Workarea.config.host,
21
+ protocol: Rails.application.config.force_ssl ? 'https' : 'http'
22
+ ),
23
+ event_types: Workarea.config.default_webhook_events
24
+ )
25
+
26
+ puts 'completed successfully!'
27
+ end
28
+ end
29
+ end
@@ -2,29 +2,33 @@ require 'workarea'
2
2
  require 'workarea/storefront'
3
3
  require 'workarea/admin'
4
4
 
5
+ require 'paypal-checkout-sdk'
6
+ require 'workarea/paypal/requests/generate_token'
7
+ require 'workarea/paypal/requests/list_webhooks'
8
+ require 'workarea/paypal/requests/create_webhook'
9
+ require 'workarea/paypal/requests/delete_webhook'
10
+ require 'workarea/paypal/gateway'
11
+
5
12
  module Workarea
6
13
  module Paypal
7
- def self.gateway
8
- Workarea.config.gateways.paypal
9
- end
10
-
11
- def self.gateway=(gateway)
12
- Workarea.config.gateways.paypal = gateway
13
- end
14
+ class << self
15
+ delegate :client, to: :gateway
14
16
 
15
- def self.auto_configure_gateway
16
- if Rails.application.secrets.paypal.present?
17
- self.gateway = ActiveMerchant::Billing::PaypalExpressGateway.new(
18
- Rails.application.secrets.paypal.deep_symbolize_keys
19
- )
20
- elsif gateway.blank?
21
- self.gateway = ActiveMerchant::Billing::BogusGateway.new
17
+ def gateway
18
+ Workarea::Paypal::Gateway.new
22
19
  end
23
20
 
24
- if ENV['HTTP_PROXY'].present? && gateway.present?
25
- parsed = URI.parse(ENV['HTTP_PROXY'])
26
- gateway.proxy_address = parsed.host
27
- gateway.proxy_port = parsed.port
21
+ def transform_values(value)
22
+ case value
23
+ when OpenStruct
24
+ transform_values(value.to_h)
25
+ when Hash
26
+ value.transform_values(&method(:transform_values))
27
+ when Array
28
+ value.map(&method(:transform_values))
29
+ else
30
+ value
31
+ end
28
32
  end
29
33
  end
30
34
  end
@@ -3,6 +3,10 @@ module Workarea
3
3
  class Engine < ::Rails::Engine
4
4
  include Workarea::Plugin
5
5
  isolate_namespace Workarea::Paypal
6
+
7
+ config.to_prepare do
8
+ Storefront::ApplicationController.helper(Storefront::PaypalHelper)
9
+ end
6
10
  end
7
11
  end
8
12
  end
@@ -0,0 +1,200 @@
1
+ module Workarea
2
+ module Paypal
3
+ class Gateway
4
+ class RequestError < StandardError; end
5
+
6
+ def environment
7
+ @environment =
8
+ Workarea.config.paypal_environment.constantize.new(
9
+ client_id,
10
+ client_secret
11
+ )
12
+ end
13
+
14
+ def client
15
+ PayPal::PayPalHttpClient.new(environment)
16
+ end
17
+
18
+ def send_request(request)
19
+ # Do not change this
20
+ request.headers["PayPal-Partner-Attribution-Id"] = 'Workarea_SP'
21
+
22
+ client.execute(request)
23
+ end
24
+
25
+ # This gets a token required to render hosted fields. Not used for
26
+ # smart payment buttons.
27
+ def generate_token(user: nil)
28
+ request = Workarea::Paypal::Requests::GenerateToken.new
29
+ id = user&.id.to_s.last(22) # length limit
30
+ request.request_body(customer_id: id) if user.present?
31
+
32
+ handle_connection_errors { send_request(request) }
33
+ end
34
+
35
+ def get_order(order_id)
36
+ request = PayPalCheckoutSdk::Orders::OrdersGetRequest.new(order_id)
37
+ handle_connection_errors { send_request(request) }
38
+ end
39
+
40
+ def create_order(body:)
41
+ request = PayPalCheckoutSdk::Orders::OrdersCreateRequest.new
42
+ request.request_body(body)
43
+
44
+ handle_connection_errors do
45
+ response = send_request(request)
46
+ response.result
47
+ end
48
+ end
49
+
50
+ def update_order(order_id, body: {})
51
+ request = PayPalCheckoutSdk::Orders::OrdersPatchRequest.new(order_id)
52
+ request.request_body(body)
53
+
54
+ handle_connection_errors do
55
+ response = send_request(request)
56
+ response.result
57
+ end
58
+ end
59
+
60
+ def capture(order_id)
61
+ request = PayPalCheckoutSdk::Orders::OrdersCaptureRequest.new(order_id)
62
+ request.prefer("return=representation")
63
+
64
+ if ENV['PAYPAL_MOCK_RESPONSE'].present? && Rails.env.in?(%w(test development))
65
+ request.headers['PayPal-Mock-Response'] = ENV['PAYPAL_MOCK_RESPONSE']
66
+ end
67
+
68
+ handle_transaction_errors do
69
+ response = send_request(request)
70
+ result = response.result
71
+ capture = result&.purchase_units&.first&.payments&.captures&.last
72
+ success = response.status_code == 201 && capture&.status != 'DECLINED'
73
+
74
+ ActiveMerchant::Billing::Response.new(
75
+ success,
76
+ "PayPal capture #{success ? 'succeeded' : 'failed'}",
77
+ Paypal.transform_values(success ? capture : result)
78
+ )
79
+ end
80
+ end
81
+
82
+ # No body means refunding the entire captured amount, otherwise an amount
83
+ # object needs to be supplied.
84
+ #
85
+ def refund(capture_id, amount: nil)
86
+ request = PayPalCheckoutSdk::Payments::CapturesRefundRequest.new(capture_id)
87
+ request.prefer("return=representation")
88
+
89
+ if amount.present?
90
+ request.request_body(
91
+ amount: {
92
+ value: amount.to_s,
93
+ currency_code: amount.currency.iso_code
94
+ }
95
+ )
96
+ end
97
+
98
+ handle_transaction_errors do
99
+ response = send_request(request)
100
+ refund = response.result
101
+ success = response.status_code == 201 && refund.status != 'CANCELLED'
102
+
103
+ ActiveMerchant::Billing::Response.new(
104
+ success,
105
+ "PayPal refund #{success ? 'succeeded' : 'failed'}",
106
+ {
107
+ id: refund.id,
108
+ status: refund.status,
109
+ status_details: refund.status_details.to_h,
110
+ capture_id: capture_id,
111
+ amount: amount.to_s
112
+ }
113
+ )
114
+ end
115
+ end
116
+
117
+ def create_webhook(url:, event_types:)
118
+ request = Workarea::Paypal::Requests::CreateWebhook.new
119
+ request.request_body(
120
+ url: url,
121
+ event_types: Array.wrap(event_types).map { |type| { name: type } }
122
+ )
123
+
124
+ response = handle_connection_errors { send_request(request) }
125
+
126
+ throw_request_error(response) unless response.status_code == 201
127
+ response
128
+ end
129
+
130
+ def delete_webhook(webhook_id)
131
+ request = Workarea::Paypal::Requests::DeleteWebhook.new(webhook_id)
132
+ response = handle_connection_errors { send_request(request) }
133
+
134
+ throw_request_error(response) unless response.status_code == 204
135
+ response
136
+ end
137
+
138
+ def list_webhooks
139
+ request = Workarea::Paypal::Requests::ListWebhooks.new
140
+ response = handle_connection_errors { send_request(request) }
141
+
142
+ throw_request_error(response) unless response.status_code == 200
143
+ response
144
+ end
145
+
146
+ def configured?
147
+ client_id.present? && client_secret.present?
148
+ end
149
+
150
+ def client_id
151
+ ENV['WORKAREA_PAYPAL_CLIENT_ID'].presence ||
152
+ Rails.application.credentials.paypal.try(:[], :client_id) ||
153
+ Workarea.config.paypal_client_id
154
+ end
155
+
156
+ private
157
+
158
+ def client_secret
159
+ ENV['WORKAREA_PAYPAL_CLIENT_SECRET'].presence ||
160
+ Rails.application.credentials.paypal.try(:[], :client_secret) ||
161
+ Workarea.config.paypal_client_secret
162
+ end
163
+
164
+ def throw_request_error(error)
165
+ raise RequestError.new(
166
+ I18n.t(
167
+ 'workarea.paypal.gateway.http_error',
168
+ status: error.status_code,
169
+ debug_id: error.headers['paypal-debug-id']
170
+ )
171
+ )
172
+ end
173
+
174
+ def handle_connection_errors
175
+ begin
176
+ yield
177
+ rescue PayPalHttp::HttpError => error
178
+ Rails.logger.error(error.message)
179
+ Rails.logger.error(error.result)
180
+ throw_request_error(error)
181
+ end
182
+ end
183
+
184
+ def handle_transaction_errors
185
+ begin
186
+ yield
187
+ rescue PayPalHttp::HttpError => error
188
+ ActiveMerchant::Billing::Response.new(
189
+ false,
190
+ I18n.t('workarea.paypal.gateway.capture_error'),
191
+ status_code: error.status_code,
192
+ debug_id: error.headers['paypal-debug-id']
193
+ )
194
+ rescue StandardError => error
195
+ ActiveMerchant::Billing::Response.new(false, error.message, {})
196
+ end
197
+ end
198
+ end
199
+ end
200
+ end