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
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 56a09d91218ed3f26af740d2452a11f318b20883b3d81232b0d6fc930f4eacdc
4
- data.tar.gz: 55a0ee63c4306a9b5011c9415177173599bf0274910fd32ed7ee8a4e458871c0
3
+ metadata.gz: 159d0b080b0fb36119cdf1c15e0ca07936e938237fd012ed67ddf8f6121dbb53
4
+ data.tar.gz: 7d8812db2e69fc22092bfcca4aa61d30a7578f2d7b5852bbc2f321d47a28f734
5
5
  SHA512:
6
- metadata.gz: d5d7624bd975a7e4e88aa357a99358f35cc45ffdbab1e4331808992b704fbf754c62e7d2ee3280f6fc0424de29f77418d13ebdaeb1ecda2d8cf05562cd45ae0c
7
- data.tar.gz: 9d6668de3ebfd54f9c315c0c3ee69af19dba5448062073c09940969620d0497c074ecb491d22638381eb238d9e2904aa4f74c01f3cd2f090512c1cb48296b8e1
6
+ metadata.gz: 834c524e29ee8e810f6e9ee3dace1ab105e8665c19315a1a3664f14e88118bb1bb0705af5729fbbc11b4ba439bdf7e4f9c8d19dfe9a840938cef9f84255dfc0f
7
+ data.tar.gz: b0ffa2b76120f84ecccf2973cc2dee52e3001a2a5403a5f4c249b82cc222a01f8e391ad420557840737730429ed5ce36a2c867736413ad38a9efefe3277bb65a
data/.eslintrc.json CHANGED
@@ -30,6 +30,7 @@
30
30
  "expect": true,
31
31
  "sinon": true,
32
32
  "fixture": true,
33
- "chai": true
33
+ "chai": true,
34
+ "paypal": true
34
35
  }
35
36
  }
data/.gitignore CHANGED
@@ -1,20 +1,25 @@
1
- .byebug_history
2
1
  .bundle/
3
- Gemfile.lock
4
- .sass-cache/
5
2
  log/*.log
6
3
  pkg/
7
- spec/dummy/public/system/dragonfly
8
- spec/dummy/db/*.sqlite3
9
- spec/dummy/log/*.log
10
- spec/dummy/tmp/
11
- spec/dummy/.sass-cache
12
- test/dummy/public/system/
4
+ test/dummy/db/*.sqlite3
5
+ test/dummy/db/*.sqlite3-journal
13
6
  test/dummy/log/*.log
7
+ test/dummy/node_modules/
8
+ test/dummy/yarn-error.log
9
+ test/dummy/storage/
14
10
  test/dummy/tmp/
15
11
  .DS_Store
12
+ .byebug_history
13
+ .bundle/
14
+ .sass-cache/
15
+ Gemfile.lock
16
+ pkg/
17
+ test/dummy/tmp/
18
+ test/dummy/public/
19
+ log/*.log
20
+ test/dummy/log/*.log
21
+ test/dummy/db/*.sqlite3
22
+ test/dummy/db/*.sqlite3-journal
16
23
  node_modules
17
- test/reports
18
- package.json
19
24
  yarn.lock
20
25
  .rubocop-http*
data/CHANGELOG.md CHANGED
@@ -1,19 +1,43 @@
1
- Workarea Paypal 2.0.11 (2020-07-11)
1
+ Workarea Paypal 3.0.0 (2020-03-03)
2
2
  --------------------------------------------------------------------------------
3
3
 
4
- * Fix Paypal BN code not being sent
4
+ * Improve handling of failed captures
5
5
 
6
+ PAYPAL-5
7
+ Matt Duffy
8
+
9
+ * Clean up NullAddress display, add partner id to all PayPal requests
10
+
11
+ PAYPAL-5
12
+ Matt Duffy
13
+
14
+ * Update README
6
15
 
16
+ PAYPAL-4
7
17
  Matt Duffy
8
18
 
19
+ * Update PayPal integration for PayPal Commerce Platform API
9
20
 
10
- Workarea Paypal 2.0.10 (2020-05-26)
21
+ PAYPAL-3
22
+ Matt Duffy
23
+
24
+
25
+
26
+ Workarea Paypal 2.0.9 (2019-10-30)
11
27
  --------------------------------------------------------------------------------
12
28
 
13
- * Update Paypal BN code
29
+ * Fix Integration Test Failure When PO Box Config Changes
14
30
 
31
+ When `config.allow_shipping_address_po_box` is set to `true`, an
32
+ integration test in the PayPal plugin failed due to the shipping step
33
+ raising an error since no shipping option is available for the address.
34
+ To ensure the test is configured correctly, it's now wrapped in a
35
+ `Workarea.with_config` block, with `config.allow_shipping_address_po_box`
36
+ set to `false`. This allows the test to ensure that the proper redirect
37
+ occurs when a shipping address coming back from PayPal is invalid.
15
38
 
16
- Ben Crouse
39
+ PAYPAL-83
40
+ Tom Scott
17
41
 
18
42
 
19
43
 
data/README.md CHANGED
@@ -3,6 +3,8 @@ Workarea PayPal
3
3
 
4
4
  A Workarea Commerce plugin that adds support for PayPal payments. This plugin adds a new tender type in checkout, which allows users to pay for their items with PayPal.
5
5
 
6
+ As of v3.0, this plugin utilizes the [PayPal Commerce Platform](https://www.paypal.com/us/webapps/mpp/commerce-platform). By default this integrates PayPal's [Smart Payment Buttons](https://developer.paypal.com/docs/commerce-platform/payment/checkout/) into your Workarea Application to allow customer's to use any payment method supported in their area to complete checkout on your storefront.
7
+
6
8
  Getting Started
7
9
  --------------------------------------------------------------------------------
8
10
 
@@ -21,21 +23,113 @@ cd path/to/application
21
23
  bundle
22
24
  ```
23
25
 
24
- Then, configure your secrets.
26
+ Then, add your client ID and secret to Workarea. See "Account Setup" below for more details.
27
+
28
+ For production environments, we recommend you run the webhooks rake task to register critical callbacks from PayPal to help keep the state of your orders on Workarea inline with the state of the PayPal transaction. See the `default_webhook_events` description under "Configuration Options" for more information.
29
+
30
+ ```bash
31
+ bin/rails workarea:paypal:create_webhooks
32
+ ```
33
+
34
+ Account Setup
35
+ --------------------------------------------------------------------------------
36
+
37
+ To begin using PayPal on your site, you will need to have a PayPal merchant account. For development, you can create an account on [developer.paypal.com](htttps://developer.paypal.com). From there you can create a sandbox REST API app, and use those credentials for any non-live environments.
38
+
39
+ Once you have a REST API application in your PayPal sandbox, you must add the client ID and secret to your Workarea application. This can be done through admin configuration, environment variables, Rails credentials, or hard-coded Workarea configuration.
40
+
41
+ ### Admin configuration
42
+
43
+ The PayPal plugin adds admin configuration fields to allow admin user's to set credentials without the need for developer intervention. Log in as an admin user, navigate to the Configuration page, find the PayPal section and add the client ID and secret.
44
+
45
+ ### Environment Variables
46
+
47
+ If the storing and setting of credentials needs to be more dynamic, you can utilize environment variables. Set the environment variables below to connect to PayPal.
48
+
49
+ `WORKAREA_PAYPAL_CLIENT_ID`
50
+ `WORKAREA_PAYPAL_CLIENT_SECRET`
51
+
52
+ ### Rails Credentials
53
+
54
+ This option can be used for any environment, but is most useful in development to store the sandbox credentials within the codebase securely, allowing anyone with the `master.key` of your application to have PayPal configured when they load their application in development.
55
+
56
+ To add your PayPal info to your Rails credentials, open your credentials file for editing:
57
+
58
+ ```bash
59
+ EDITOR=vi bin/rails credentials:edit
60
+ ```
61
+
62
+ Then, add a PayPal section:
25
63
 
26
64
  ```yaml
27
65
  paypal:
28
- login:
29
- password:
30
- signature:
66
+ client_Id: YOUR_CLIENT_ID
67
+ client_secret: YOUR_CLIENT_SECRET
31
68
  ```
32
69
 
33
- These credentials will be sent to you by your client, who should have a PayPal merchant account set up already. If not, or you wish to develop locally, [sign up for a sandbox account](https://developer.paypal.com/developer/accounts/).
70
+ ### Hard-coded configuration
71
+
72
+ This option is not ideal, as it will prevent admin configuration from ever being used, but can be necessary if you need to automate the switching of PayPal accounts in a multi-site environment. It is **strongly** recommended that you store the credentials elsewhere and load them into your configuration dynamically if you need to use this option.
73
+
74
+ In your `config/initializers/workarea.rb`, add:
34
75
 
35
- ## International Addresses
76
+ ```ruby
77
+ Workarea.configure do |config|
78
+ config.paypal_client_id = 'YOUR_CLIENT_ID'
79
+ config.paypal_client_secret = 'YOUR_CLIENT_SECRET'
80
+ end
81
+ ```
82
+
83
+ Configuration Options
84
+ --------------------------------------------------------------------------------
85
+
86
+ `config.paypal_environment`
87
+
88
+ The [PayPal Checkout SDK](https://github.com/paypal/Checkout-Ruby-SDK) gem uses different environment classes depending on whether you are interacting with sandbox or live environments. This config by default will point to the sandbox environment unless you are in production. If you need to customize which environment you wish to connect to you'll have to modify the value of this config. Accepted values are `'Paypal::LiveEnvironment'` or
89
+ `'PayPal::SandboxEnvironment'`.
90
+
91
+ `config.paypal_sdk_params`
92
+
93
+ This config holds a hash of values to be passed as query string arguments to the PayPal when fetching the javascript SDK. See the [PayPal documentation](https://developer.paypal.com/docs/checkout/reference/customize-sdk/) for options. By default, the plugin will pass the client_id, and `'commit' => false`. It will add `'debug' => true` if you are in development for easier troubleshooting.
94
+
95
+ `config.default_webhook_events`
96
+
97
+ PayPal offers a number of [webhook integration options](https://developer.paypal.com/docs/integration/direct/webhooks/rest-webhooks/) that will make calls to your application when something happens within PayPal. You can [create webhooks manually](https://developer.paypal.com/docs/integration/direct/webhooks/rest-webhooks/#to-use-the-dashboard-to-subscribe-to-events) within the PayPal dashboard, but Workarea provides a more automated way to subscribe to events through the `workarea:paypal:create_webhooks` rake task. When run, this rake task will clear any existing webhooks and create a webhook for each event in `config.default_webhook_events`. By default, `PAYMENT.CAPTURE.COMPLETED` and `PAYMENT.CAPTURE.DENIED` are the only events supported by the plugin. If you wish to add more supported events you will also have to provide logic within [`Workarea::Paypal::HandleWebhookEvent`](https://github.com/workarea-commerce/workarea-paypal/blob/master/app/workers/workarea/paypal/handle_webhook_event.rb) to update your application appropriately.
98
+
99
+
100
+ `config.use_paypal_hosted_fields`
101
+
102
+ This configuration toggles on [PayPal Custom Card Fields](https://developer.paypal.com/docs/limited-release/custom-card-fields/) which allows you to use PayPal as your primary credit card payment processor. See "Hosted Fields" below for more information.
103
+
104
+ ### Javascript Configuration
105
+
106
+ Both Smart Payment Buttons and Hosted Fields provide configuration within the javascript `WORKAREA.config` object to customize options passed when initializing those behaviors.
107
+
108
+ `WORKAREA.config.paypalButtons`
109
+
110
+ Customize the Smart Payment Buttons options. See the [PayPal documentation](https://developer.paypal.com/docs/checkout/integration-features/customize-button/) for options.
111
+
112
+ `WORKAREA.config.paypalHostedFields`
113
+
114
+ Customize the Hosted Fields options. See the [PayPal documentation](https://developer.paypal.com/docs/limited-release/custom-card-fields/reference) for options.
115
+
116
+ Hosted Fields
117
+ --------------------------------------------------------------------------------
118
+
119
+ The PayPal Commerce Platform allows you to add unbranded, custom credit card fields to your checkout to accept payments directly on your site. When enabled via `config.use_paypal_hosted_fields`, the Workarea plugin integrates this directly into the existing checkout payment step by replacing the default credit card fields with fields rendered by PayPal. This enables you to accept credit card payments with no other payment processor except PayPal.
120
+
121
+ This does require providing additional information to PayPal through a Workarea-specific partner signup. For sandbox accounts, You can [complete this process](https://www.sandbox.paypal.com/bizsignup/partner/entry?channelId=partner&channel=marketplace&product=ppcp&partnerId=M3XMHZJKTFK88&integrationType=FO) without additional communication using your **sandbox business account login** (found in the PayPal developer dashboard under Sandbox > Accounts). For live environments, contact [Workarea](https://www.workarea.com/pages/contact-us) or reach out to PayPal for more information how you can enable this behavior for your site.
122
+
123
+ Additional Information
124
+ --------------------------------------------------------------------------------
125
+
126
+ See the [PayPal Documentation](https://developer.paypal.com/docs/commerce-platform/) for more information on the PayPal Commerce Platform.
127
+
128
+ ### International Addresses
36
129
 
37
130
  When working with international addresses, the data from PayPal regarding country and region codes is not guaranteed to match the identifiers used in Workarea (derived from our usage of the [countries](https://github.com/hexorx/countries) gem), because the 2-digit codes identifying countries and regions are not the same. Therefore, you may have some issues when accepting international payments through PayPal, and thus some changes will need to be applied to ensure a seamless checkout process for international PayPal users.
38
131
 
132
+
39
133
  Workarea Commerce Documentation
40
134
  --------------------------------------------------------------------------------
41
135
 
data/Rakefile CHANGED
@@ -39,13 +39,12 @@ desc "Release version #{Workarea::Paypal::VERSION} of the gem"
39
39
  task :release do
40
40
  host = "https://#{ENV['BUNDLE_GEMS__WEBLINC__COM']}@gems.weblinc.com"
41
41
 
42
- #Rake::Task['workarea:changelog'].execute
43
- #system 'git add CHANGELOG.md'
44
- #system 'git commit -m "Update CHANGELOG"'
45
- #system 'git push origin HEAD'
42
+ Rake::Task['workarea:changelog'].execute
43
+ system 'git add CHANGELOG.md'
44
+ system 'git commit -m "Update CHANGELOG"'
46
45
 
47
46
  system "git tag -a v#{Workarea::Paypal::VERSION} -m 'Tagging #{Workarea::Paypal::VERSION}'"
48
- system 'git push --tags'
47
+ system 'git push origin HEAD --follow-tags'
49
48
 
50
49
  system 'gem build workarea-paypal.gemspec'
51
50
  system "gem push workarea-paypal-#{Workarea::Paypal::VERSION}.gem"
@@ -0,0 +1,44 @@
1
+ /**
2
+ * @namespace WORKAREA
3
+ */
4
+
5
+ (function () {
6
+ 'use strict';
7
+
8
+ /**
9
+ * @namespace WORKAREA.config
10
+ * @property {object} paypalButtons
11
+ * See https://developer.paypal.com/docs/checkout/integration-features/customize-button/
12
+ * for information on configuration options.
13
+ */
14
+ WORKAREA.config.paypalButtons = {
15
+ style: {
16
+ color: 'blue',
17
+ tagline: false,
18
+ }
19
+ };
20
+
21
+ /**
22
+ * @namespace WORKAREA.config
23
+ * @property {object} paypalHostedFields
24
+ * See https://developer.paypal.com/docs/limited-release/custom-card-fields/reference
25
+ * for information on configuration options.
26
+ */
27
+ WORKAREA.config.paypalHostedFields = {
28
+ fields: {
29
+ number: {
30
+ selector: '#paypal-credit-card-number',
31
+ placeholder: 'Credit Card Number',
32
+ },
33
+ cvv: {
34
+ selector: '#paypal-cvv-field',
35
+ placeholder: 'CVV',
36
+ },
37
+ expirationDate: {
38
+ selector: '#paypal-expiration-field',
39
+ placeholder: 'MM/YYYY',
40
+ }
41
+ }
42
+ };
43
+
44
+ })();
@@ -0,0 +1,71 @@
1
+ /**
2
+ * @namespace WORKAREA.paypalButtons
3
+ */
4
+ WORKAREA.registerModule('paypalButtons', (function () {
5
+ 'use strict';
6
+
7
+ var requestWrapper = function (requestData) {
8
+ var deferred = $.Deferred();
9
+
10
+ $.ajax(requestData)
11
+ .done(function(data) {
12
+ deferred.resolve(data);
13
+ })
14
+ .fail(function(data, status, xhr) {
15
+ deferred.reject(xhr);
16
+ });
17
+
18
+ return deferred.promise();
19
+ },
20
+
21
+ createOrder = function() {
22
+ return requestWrapper({
23
+ url: WORKAREA.routes.storefront.paypalPath(),
24
+ type: 'post',
25
+ dataType: 'json'
26
+ }).then(function (data) {
27
+ return data.id;
28
+ });
29
+ },
30
+
31
+ onApprove = function(data) {
32
+ return requestWrapper({
33
+ url: WORKAREA.routes.storefront.paypalApprovedPath({ id: data.orderID }),
34
+ type: 'put',
35
+ dataType: 'json'
36
+ }).then(function(data) {
37
+ window.location = data.redirect_url; }
38
+ );
39
+ },
40
+
41
+ getConfig = function () {
42
+ return _.assign({}, WORKAREA.config.paypalButtons, {
43
+ createOrder: createOrder,
44
+ onApprove: onApprove
45
+ });
46
+ },
47
+
48
+ setup = function($container) {
49
+ paypal
50
+ .Buttons(getConfig())
51
+ .render($container[0]);
52
+ },
53
+
54
+ /**
55
+ * @method
56
+ * @name init
57
+ * @memberof WORKAREA.paypalButtons
58
+ */
59
+ init = function ($scope) {
60
+ var $buttonContainer = $('#paypal-button-container', $scope);
61
+
62
+ if (window.paypal === undefined) { return; }
63
+ if (_.isEmpty($buttonContainer)) { return; }
64
+
65
+ setup($buttonContainer);
66
+ };
67
+
68
+ return {
69
+ init: init
70
+ };
71
+ }()));
@@ -0,0 +1,96 @@
1
+ /**
2
+ * @namespace WORKAREA.paypalHostedFields
3
+ */
4
+ WORKAREA.registerModule('paypalHostedFields', (function () {
5
+ 'use strict';
6
+
7
+ var requestWrapper = function (requestData) {
8
+ var deferred = $.Deferred();
9
+
10
+ $.ajax(requestData)
11
+ .done(function(data) {
12
+ deferred.resolve(data);
13
+ })
14
+ .fail(function(data, status, xhr) {
15
+ deferred.reject(xhr);
16
+ });
17
+
18
+ return deferred.promise();
19
+ },
20
+
21
+ createOrder = function() {
22
+ return requestWrapper({
23
+ url: WORKAREA.routes.storefront.paypalPath(),
24
+ type: 'post',
25
+ dataType: 'json'
26
+ }).then(function (data) {
27
+ return data.id;
28
+ });
29
+ },
30
+
31
+ onApprove = function($form, data) {
32
+ return requestWrapper({
33
+ url: WORKAREA.routes.storefront.paypalApprovedPath({ id: data.orderId }),
34
+ type: 'put',
35
+ dataType: 'json'
36
+ }).then(
37
+ function() {
38
+ $form
39
+ .off('submit')
40
+ .trigger('submit');
41
+ }
42
+ );
43
+ },
44
+
45
+ addSubmitListener = function($container, hostedFields) {
46
+ var $form = $container.parents('form');
47
+
48
+ $form.on('submit', function(event) {
49
+ if ($form.find('#payment_new_card').is(':checked')) {
50
+ event.preventDefault();
51
+ hostedFields.submit({
52
+ vault: $container.find('input[name="save_card"]').is(':checked')
53
+ }).then(_.partial(onApprove, $form));
54
+ }
55
+ });
56
+ },
57
+
58
+ getConfig = function () {
59
+ return _.assign({}, WORKAREA.config.paypalHostedFields, {
60
+ createOrder: createOrder
61
+ });
62
+ },
63
+
64
+
65
+ setup = function($placeholder, $scope) {
66
+ var template = JST['workarea/storefront/paypal/templates/paypal_fields'],
67
+ options = $placeholder.data('paypalHostedFields'),
68
+ $container = $('.checkout-payment__primary-method--new .checkout-payment__primary-method-edit', $scope);
69
+
70
+ $container.html(template(options));
71
+
72
+ paypal
73
+ .HostedFields
74
+ .render(getConfig())
75
+ .then(_.partial(addSubmitListener, $container));
76
+ },
77
+
78
+ /**
79
+ * @method
80
+ * @name init
81
+ * @memberof WORKAREA.paypalHostedFields
82
+ */
83
+ init = function ($scope) {
84
+ var $placeholder = $('[data-paypal-hosted-fields]', $scope);
85
+
86
+ if (_.isEmpty($placeholder)) { return; }
87
+ if (window.paypal === undefined) { return; }
88
+ if (!paypal.HostedFields.isEligible()) { return; }
89
+
90
+ setup($placeholder, $scope);
91
+ };
92
+
93
+ return {
94
+ init: init
95
+ };
96
+ }()));
@@ -4,9 +4,7 @@
4
4
  WORKAREA.registerModule('updateCheckoutSubmitText', (function () {
5
5
  'use strict';
6
6
 
7
- var submitButtonText = function ($selectedPaymentMethod) {
8
- var data = $selectedPaymentMethod.data('updateCheckoutSubmitText') || {};
9
-
7
+ var submitButtonText = function (data) {
10
8
  if (data.prevent) { return; }
11
9
 
12
10
  if (data.text) {
@@ -17,10 +15,17 @@ WORKAREA.registerModule('updateCheckoutSubmitText', (function () {
17
15
  },
18
16
 
19
17
  updateText = function($selectedPaymentMethod, $checkoutSubmit) {
20
- var text = submitButtonText($selectedPaymentMethod);
18
+ var data = $selectedPaymentMethod.data('updateCheckoutSubmitText') || {},
19
+ text = submitButtonText(data);
21
20
 
22
21
  if (_.isEmpty(text)) { return; }
23
22
 
23
+ if (data.disabled && !data.prevent) {
24
+ $checkoutSubmit.attr('disabled', 'disabled');
25
+ } else {
26
+ $checkoutSubmit.removeAttr('disabled');
27
+ }
28
+
24
29
  $checkoutSubmit.text(text);
25
30
  },
26
31
 
@@ -55,6 +60,7 @@ WORKAREA.registerModule('updateCheckoutSubmitText', (function () {
55
60
  };
56
61
 
57
62
  return {
58
- init: init
63
+ init: init,
64
+ updateText: updateText
59
65
  };
60
66
  }()));
@@ -0,0 +1,43 @@
1
+ <div class="grid grid--auto">
2
+ <div class="grid__cell">
3
+ <div class="property">
4
+ <label class="property__name" for="credit_card_number">
5
+ <span class="property__text">Card Number</span>
6
+ </label>
7
+ <div class="value">
8
+ <div class="text-box" id="paypal-credit-card-number" style="height: 30px;"></div>
9
+ </div>
10
+ </div>
11
+ </div>
12
+ <div class="grid__cell">
13
+ <div class="property">
14
+ <label class="property__name" for="credit_card_expiration">
15
+ <span>Expiration</span>
16
+ </label>
17
+ <div class="value">
18
+ <div class="text-box text-box--small" id="paypal-expiration-field" style="height: 30px;"></div>
19
+ </div>
20
+ </div>
21
+ </div>
22
+ <div class="grid__cell">
23
+ <div class="property">
24
+ <label class="property__name" for="credit_card_cvv">
25
+ <span class="property__text">Security Code</span>
26
+ </label>
27
+ <div class="value">
28
+ <div class="text-box text-box--small" id="paypal-cvv-field" style="height: 30px;"></div>
29
+ </div>
30
+ </div>
31
+ </div>
32
+ </div>
33
+
34
+ <% if (show_save_card) { %>
35
+ <div class="button-property">
36
+ <div class="value">
37
+ <input type="checkbox" name="save_card" id="save_card" value="true" />
38
+ </div>
39
+ <label class="button-property__name" for="save_card">
40
+ <span>Save card for faster checkout</span>
41
+ </label>
42
+ </div>
43
+ <% } %>
@@ -1,10 +1,12 @@
1
1
  module Workarea
2
2
  decorate Storefront::Checkout::PlaceOrderController, with: 'paypal' do
3
3
  def place_order
4
- if params[:payment] == 'paypal' && !current_checkout.payment.paypal? && params[:from_checkout].present?
5
- redirect_to start_paypal_path(from_checkout: 'from_checkout') and return
6
- elsif params[:payment] == 'paypal' && !current_checkout.payment.paypal?
7
- redirect_to start_paypal_path and return
4
+ if params[:payment] == 'paypal' && current_checkout.payment.paypal?
5
+ Paypal::UpdateOrder.new(current_checkout).perform
6
+ super
7
+ elsif params[:payment] == 'paypal'
8
+ flash['info'] = t('workarea.storefront.paypal.errors.place_order')
9
+ redirect_to checkout_payment_path
8
10
  else
9
11
  super
10
12
  end
@@ -2,10 +2,11 @@ module Workarea
2
2
  class Storefront::PaypalController < Storefront::ApplicationController
3
3
  include Storefront::CurrentCheckout
4
4
 
5
- before_action :validate_checkout
5
+ before_action :validate_checkout, except: :event
6
+ skip_before_action :verify_authenticity_token
6
7
 
7
- def start
8
- unless params[:from_checkout].present?
8
+ def create
9
+ unless current_order.checking_out?
9
10
  if logged_in?
10
11
  current_checkout.start_as(current_user)
11
12
  else
@@ -14,38 +15,43 @@ module Workarea
14
15
  end
15
16
 
16
17
  self.current_order = current_checkout.order
17
- Pricing.perform(current_order, current_shipping)
18
18
  check_inventory || (return)
19
19
 
20
- setup = Paypal::Setup.new(
21
- current_order,
22
- current_user,
23
- current_shipping,
24
- self
25
- )
20
+ if current_checkout.payment.paypal?
21
+ current_checkout.payment.paypal.update!(approved: false)
22
+ render json: { id: current_checkout.payment.paypal_id }
23
+ else
24
+ response = Paypal::CreateOrder.new(current_checkout).perform
25
+ render json: { id: response.id }
26
+ end
26
27
 
27
- redirect_to setup.redirect_url
28
+ rescue Paypal::Gateway::RequestError => e
29
+ Rails.logger.error(e)
30
+ flash[:error] = t('workarea.storefront.paypal.errors.request_failed')
31
+ head :internal_server_error
28
32
  end
29
33
 
30
- def complete
31
- self.current_order = Order.find(params[:order_id])
32
- current_order.user_id = current_user.try(:id)
33
- Pricing.perform(current_order, current_shipping)
34
+ def update
34
35
  check_inventory || (return)
35
36
 
36
- Paypal::Update.new(
37
- current_order,
38
- current_checkout.payment,
39
- current_shipping,
40
- params[:token]
41
- ).apply
37
+ Paypal::ApproveOrder.new(current_checkout, params[:id]).perform
42
38
 
43
- unless current_checkout.complete?
44
- flash[:error] = t('workarea.storefront.paypal.address_error')
45
- redirect_to(checkout_addresses_path) && (return)
46
- end
39
+ complete = current_checkout.complete?
40
+ flash[:error] = t('workarea.storefront.paypal.errors.order_incomplete') unless complete
41
+
42
+ render json: {
43
+ success: complete,
44
+ redirect_url: checkout_payment_path
45
+ }
46
+ end
47
+
48
+ def event
49
+ Paypal::HandleWebhookEvent.perform_async(
50
+ params[:event_type],
51
+ params[:resource].to_unsafe_h
52
+ )
47
53
 
48
- redirect_to checkout_payment_path
54
+ head :ok
49
55
  end
50
56
  end
51
57
  end