solidus_paypal_commerce_platform 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (101) hide show
  1. checksums.yaml +7 -0
  2. data/.circleci/config.yml +41 -0
  3. data/.gem_release.yml +5 -0
  4. data/.github/stale.yml +17 -0
  5. data/.gitignore +20 -0
  6. data/.rspec +2 -0
  7. data/.rubocop.yml +56 -0
  8. data/Gemfile +33 -0
  9. data/LICENSE +26 -0
  10. data/README.md +173 -0
  11. data/Rakefile +6 -0
  12. data/app/assets/javascripts/spree/backend/solidus_paypal_commerce_platform.js +2 -0
  13. data/app/assets/javascripts/spree/backend/solidus_paypal_commerce_platform/namespace.js +1 -0
  14. data/app/assets/javascripts/spree/backend/solidus_paypal_commerce_platform/wizard.js +28 -0
  15. data/app/assets/javascripts/spree/frontend/solidus_paypal_commerce_platform.js +3 -0
  16. data/app/assets/javascripts/spree/frontend/solidus_paypal_commerce_platform/button_actions.js +191 -0
  17. data/app/assets/javascripts/spree/frontend/solidus_paypal_commerce_platform/buttons.js +26 -0
  18. data/app/assets/javascripts/spree/frontend/solidus_paypal_commerce_platform/namespace.js +1 -0
  19. data/app/assets/stylesheets/spree/backend/solidus_paypal_commerce_platform.css +4 -0
  20. data/app/assets/stylesheets/spree/frontend/solidus_paypal_commerce_platform.css +17 -0
  21. data/app/controllers/solidus_paypal_commerce_platform/orders_controller.rb +83 -0
  22. data/app/controllers/solidus_paypal_commerce_platform/payments_controller.rb +44 -0
  23. data/app/controllers/solidus_paypal_commerce_platform/paypal_orders_controller.rb +19 -0
  24. data/app/controllers/solidus_paypal_commerce_platform/shipping_rates_controller.rb +31 -0
  25. data/app/controllers/solidus_paypal_commerce_platform/wizard_controller.rb +47 -0
  26. data/app/decorators/solidus_paypal_commerce_platform/remove_required_phone_from_address.rb +13 -0
  27. data/app/helpers/solidus_paypal_commerce_platform/button_options_helper.rb +21 -0
  28. data/app/jobs/solidus_paypal_commerce_platform/application_job.rb +6 -0
  29. data/app/jobs/solidus_paypal_commerce_platform/webhook_job.rb +22 -0
  30. data/app/models/solidus_paypal_commerce_platform/gateway.rb +88 -0
  31. data/app/models/solidus_paypal_commerce_platform/payment_method.rb +75 -0
  32. data/app/models/solidus_paypal_commerce_platform/payment_source.rb +27 -0
  33. data/app/models/solidus_paypal_commerce_platform/paypal_address.rb +81 -0
  34. data/app/models/solidus_paypal_commerce_platform/paypal_order.rb +107 -0
  35. data/app/models/solidus_paypal_commerce_platform/pricing_options.rb +9 -0
  36. data/app/models/solidus_paypal_commerce_platform/wizard.rb +40 -0
  37. data/app/overrides/spree/admin/payment_methods/form/insert_email_verification_notification.rb +9 -0
  38. data/app/overrides/spree/admin/payment_methods/index/insert_setup_wizards.rb +17 -0
  39. data/app/overrides/spree/admin/payments/log_entries/add_paypal_debug_id.rb +9 -0
  40. data/app/overrides/spree/orders/edit/insert_cart_buttons.rb +9 -0
  41. data/app/overrides/spree/payments/payment/add_paypal_email_to_payment.rb +9 -0
  42. data/app/overrides/spree/products/cart_form/insert_product_buttons.rb +10 -0
  43. data/app/views/solidus_paypal_commerce_platform/admin/payment_methods/_available_to_users.html.erb +6 -0
  44. data/app/views/solidus_paypal_commerce_platform/admin/payment_methods/_paypal_wizard.html.erb +16 -0
  45. data/app/views/solidus_paypal_commerce_platform/admin/payment_methods/_setup_wizards.html.erb +16 -0
  46. data/app/views/solidus_paypal_commerce_platform/admin/payments/_log_entries.html.erb +32 -0
  47. data/bin/console +17 -0
  48. data/bin/rails +7 -0
  49. data/bin/rails-engine +13 -0
  50. data/bin/rails-sandbox +18 -0
  51. data/bin/rake +7 -0
  52. data/bin/sandbox +86 -0
  53. data/bin/setup +8 -0
  54. data/codecov.yml +14 -0
  55. data/config/locales/en.yml +37 -0
  56. data/config/routes.rb +12 -0
  57. data/db/migrate/20200521190038_add_paypal_commerce_platform_sources.rb +13 -0
  58. data/lib/generators/solidus_paypal_commerce_platform/install/install_generator.rb +38 -0
  59. data/lib/solidus_paypal_commerce_platform.rb +21 -0
  60. data/lib/solidus_paypal_commerce_platform/access_token_authorization_request.rb +21 -0
  61. data/lib/solidus_paypal_commerce_platform/client.rb +84 -0
  62. data/lib/solidus_paypal_commerce_platform/configuration.rb +64 -0
  63. data/lib/solidus_paypal_commerce_platform/engine.rb +45 -0
  64. data/lib/solidus_paypal_commerce_platform/factories.rb +14 -0
  65. data/lib/solidus_paypal_commerce_platform/fetch_merchant_credentials_request.rb +17 -0
  66. data/lib/solidus_paypal_commerce_platform/version.rb +5 -0
  67. data/lib/views/api/spree/api/payments/source_views/_paypal_commerce_platform.json.jbuilder +3 -0
  68. data/lib/views/backend/spree/admin/payments/source_forms/_paypal_commerce_platform.html.erb +1 -0
  69. data/lib/views/backend/spree/admin/payments/source_views/_paypal_commerce_platform.html.erb +18 -0
  70. data/lib/views/backend/spree/admin/shared/preference_fields/_paypal_select.html.erb +13 -0
  71. data/lib/views/frontend/solidus_paypal_commerce_platform/cart/_cart_buttons.html.erb +3 -0
  72. data/lib/views/frontend/solidus_paypal_commerce_platform/payments/_payment.html.erb +4 -0
  73. data/lib/views/frontend/solidus_paypal_commerce_platform/product/_product_buttons.html.erb +3 -0
  74. data/lib/views/frontend/spree/checkout/payment/_paypal_commerce_platform.html.erb +13 -0
  75. data/lib/views/frontend/spree/orders/payment/_paypal_commerce_platform.html.erb +17 -0
  76. data/lib/views/frontend/spree/products/payment/_paypal_commerce_platform.html.erb +15 -0
  77. data/solidus_paypal_commerce_platform.gemspec +39 -0
  78. data/spec/features/backend/new_payment_method_spec.rb +40 -0
  79. data/spec/features/frontend/cart_spec.rb +38 -0
  80. data/spec/features/frontend/checkout_spec.rb +81 -0
  81. data/spec/features/frontend/product_spec.rb +79 -0
  82. data/spec/jobs/solidus_paypal_commerce_platform/fixtures/CHECKOUT.ORDER.COMPLETED.v2.json +121 -0
  83. data/spec/jobs/solidus_paypal_commerce_platform/fixtures/CHECKOUT.ORDER.PROCESSED.v2.json +121 -0
  84. data/spec/jobs/solidus_paypal_commerce_platform/fixtures/PAYMENT.CAPTURE.COMPLETED.v1.json +50 -0
  85. data/spec/jobs/solidus_paypal_commerce_platform/fixtures/PAYMENT.CAPTURE.COMPLETED.v2.json +72 -0
  86. data/spec/jobs/solidus_paypal_commerce_platform/fixtures/PAYMENT.CAPTURE.DENIED.v1.json +50 -0
  87. data/spec/jobs/solidus_paypal_commerce_platform/fixtures/PAYMENT.CAPTURE.DENIED.v2.json +68 -0
  88. data/spec/jobs/solidus_paypal_commerce_platform/fixtures/PAYMENT.CAPTURE.REFUNDED.v1.json +51 -0
  89. data/spec/jobs/solidus_paypal_commerce_platform/fixtures/PAYMENT.CAPTURE.REFUNDED.v2.json +63 -0
  90. data/spec/jobs/solidus_paypal_commerce_platform/webhook_job_spec.rb +44 -0
  91. data/spec/lib/solidus_paypal_commerce_platform/client_spec.rb +21 -0
  92. data/spec/lib/solidus_paypal_commerce_platform/configuration_spec.rb +67 -0
  93. data/spec/models/solidus_paypal_commerce_platform/payment_method_spec.rb +102 -0
  94. data/spec/models/solidus_paypal_commerce_platform/payment_source_spec.rb +62 -0
  95. data/spec/models/solidus_paypal_commerce_platform/paypal_address_spec.rb +55 -0
  96. data/spec/models/solidus_paypal_commerce_platform/wizard_spec.rb +9 -0
  97. data/spec/requests/solidus_paypal_commerce_platform/orders_controller_spec.rb +36 -0
  98. data/spec/requests/solidus_paypal_commerce_platform/shipping_rates_controller_spec.rb +44 -0
  99. data/spec/requests/solidus_paypal_commerce_platform/wizard_controller_spec.rb +44 -0
  100. data/spec/spec_helper.rb +30 -0
  101. metadata +258 -0
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 8d729015bdddd523c8210fb8276c47d11a79b6a3e91ef1107a51c9ced0e9a840
4
+ data.tar.gz: ed5a4f61038c0596b75ae0d6914f3a98a225b3408911bdc64eb287d5131fcde7
5
+ SHA512:
6
+ metadata.gz: 48a8ac2f5d03d0d0e32f0a5d36d53a78ea1baccc6bd4a59e09b24a6d8820d92a4e2a98e0a30fb22c5d969d5bf75a423ed7c8f3bdbbab937ecb7857e270a0778f
7
+ data.tar.gz: e714276710dea1c6538cd46e475a0b689060c905ca0d3a69743e0d8236b16dc8d55b5226012ddc365fc8c0339836cc2b4e3c2662be5e77ccf357c7464c9dc7f7
@@ -0,0 +1,41 @@
1
+ version: 2.1
2
+
3
+ orbs:
4
+ # Always take the latest version of the orb, this allows us to
5
+ # run specs against Solidus supported versions only without the need
6
+ # to change this configuration every time a Solidus version is released
7
+ # or goes EOL.
8
+ solidusio_extensions: solidusio/extensions@volatile
9
+
10
+ jobs:
11
+ run-specs-with-postgres:
12
+ executor: solidusio_extensions/postgres
13
+ steps:
14
+ - solidusio_extensions/run-tests
15
+ run-specs-with-mysql:
16
+ executor: solidusio_extensions/mysql
17
+ steps:
18
+ - solidusio_extensions/run-tests
19
+ lint-code:
20
+ executor: solidusio_extensions/sqlite-memory
21
+ steps:
22
+ - solidusio_extensions/lint-code
23
+
24
+ workflows:
25
+ "Run specs on supported Solidus versions":
26
+ jobs:
27
+ - run-specs-with-postgres
28
+ - run-specs-with-mysql
29
+ - lint-code
30
+
31
+ "Weekly run specs against master":
32
+ triggers:
33
+ - schedule:
34
+ cron: "0 0 * * 4" # every Thursday
35
+ filters:
36
+ branches:
37
+ only:
38
+ - master
39
+ jobs:
40
+ - run-specs-with-postgres
41
+ - run-specs-with-mysql
@@ -0,0 +1,5 @@
1
+ bump:
2
+ recurse: false
3
+ file: 'lib/solidus_paypal_commerce_platform/version.rb'
4
+ message: Bump SolidusPaypalCommercePlatform to %{version}
5
+ tag: true
@@ -0,0 +1,17 @@
1
+ # Number of days of inactivity before an issue becomes stale
2
+ daysUntilStale: 60
3
+ # Number of days of inactivity before a stale issue is closed
4
+ daysUntilClose: 7
5
+ # Issues with these labels will never be considered stale
6
+ exemptLabels:
7
+ - pinned
8
+ - security
9
+ # Label to use when marking an issue as stale
10
+ staleLabel: wontfix
11
+ # Comment to post when marking an issue as stale. Set to `false` to disable
12
+ markComment: >
13
+ This issue has been automatically marked as stale because it has not had
14
+ recent activity. It will be closed if no further activity occurs. Thank you
15
+ for your contributions.
16
+ # Comment to post when closing a stale issue. Set to `false` to disable
17
+ closeComment: false
@@ -0,0 +1,20 @@
1
+ *.gem
2
+ \#*
3
+ *~
4
+ .#*
5
+ .DS_Store
6
+ .idea
7
+ .project
8
+ .sass-cache
9
+ coverage
10
+ Gemfile.lock
11
+ tmp
12
+ nbproject
13
+ pkg
14
+ *.swp
15
+ spec/dummy
16
+ spec/examples.txt
17
+ /sandbox
18
+ .rvmrc
19
+ .ruby-version
20
+ .ruby-gemset
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --color
2
+ --require spec_helper
@@ -0,0 +1,56 @@
1
+ require:
2
+ - solidus_dev_support/rubocop
3
+
4
+ AllCops:
5
+ Exclude:
6
+ - sandbox/**/*
7
+ - spec/dummy/**/*
8
+ - vendor/bundle/**/*
9
+
10
+ Layout/IndentFirstArgument:
11
+ EnforcedStyle: consistent
12
+
13
+ Layout/IndentFirstArrayElement:
14
+ EnforcedStyle: consistent
15
+
16
+ Metrics/LineLength:
17
+ Max: 120
18
+
19
+ # We use this extensively, the alternatives are not viable or desirable.
20
+ RSpec/AnyInstance:
21
+ Enabled: false
22
+
23
+ # Feature specs are not describing any class or module.
24
+ RSpec/DescribeClass:
25
+ Exclude:
26
+ - spec/features/**/*
27
+
28
+ # No need to make the code more complex for no real gain.
29
+ RSpec/MessageSpies:
30
+ Enabled: false
31
+
32
+ # Let's consider legitimate to have multiple expectations within an example.
33
+ RSpec/MultipleExpectations:
34
+ Enabled: false
35
+
36
+ # Allow to use subject as is, no big deal.
37
+ RSpec/NamedSubject:
38
+ Enabled: false
39
+
40
+ # Let's set this to some really exagerate value.
41
+ RSpec/NestedGroups:
42
+ Max: 8
43
+
44
+ RSpec/VerifiedDoubles:
45
+ # Sometimes you really need an "anything" double
46
+ IgnoreSymbolicNames: true
47
+
48
+ Style/FrozenStringLiteralComment:
49
+ Exclude:
50
+ - spec/**/*
51
+ - db/migrate/**/*
52
+ - bin/**/*
53
+
54
+ Security/YAMLLoad:
55
+ Exclude:
56
+ - spec/**/*
data/Gemfile ADDED
@@ -0,0 +1,33 @@
1
+ # frozen_string_literal: true
2
+
3
+ source 'https://rubygems.org'
4
+ git_source(:github) { |repo| "https://github.com/#{repo}.git" }
5
+
6
+ branch = ENV.fetch('SOLIDUS_BRANCH', 'master')
7
+ gem 'solidus', github: 'solidusio/solidus', branch: branch
8
+
9
+ # Needed to help Bundler figure out how to resolve dependencies,
10
+ # otherwise it takes forever to resolve them.
11
+ # See https://github.com/bundler/bundler/issues/6677
12
+ gem 'rails', '>0.a'
13
+
14
+ # Provides basic authentication functionality for testing parts of your engine
15
+ gem 'solidus_auth_devise'
16
+
17
+ case ENV['DB']
18
+ when 'mysql'
19
+ gem 'mysql2'
20
+ when 'postgresql'
21
+ gem 'pg'
22
+ else
23
+ gem 'sqlite3'
24
+ end
25
+
26
+ gemspec
27
+
28
+ # Use a local Gemfile to include development dependencies that might not be
29
+ # relevant for the project or for other contributors, e.g. pry-byebug.
30
+ #
31
+ # We use `send` instead of calling `eval_gemfile` to work around an issue with
32
+ # how Dependabot parses projects: https://github.com/dependabot/dependabot-core/issues/1658.
33
+ send(:eval_gemfile, 'Gemfile-local') if File.exist? 'Gemfile-local'
data/LICENSE ADDED
@@ -0,0 +1,26 @@
1
+ Copyright (c) 2020 Nebulab srls
2
+ All rights reserved.
3
+
4
+ Redistribution and use in source and binary forms, with or without modification,
5
+ are permitted provided that the following conditions are met:
6
+
7
+ * Redistributions of source code must retain the above copyright notice,
8
+ this list of conditions and the following disclaimer.
9
+ * Redistributions in binary form must reproduce the above copyright notice,
10
+ this list of conditions and the following disclaimer in the documentation
11
+ and/or other materials provided with the distribution.
12
+ * Neither the name Solidus nor the names of its contributors may be used to
13
+ endorse or promote products derived from this software without specific
14
+ prior written permission.
15
+
16
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
20
+ CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
21
+ EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
22
+ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
23
+ PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
24
+ LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
25
+ NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
26
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
@@ -0,0 +1,173 @@
1
+ # SolidusPaypalCommercePlatform
2
+
3
+ [![CircleCI](https://circleci.com/gh/nebulab/solidus_paypal_commerce_platform.svg?style=shield)](https://circleci.com/gh/nebulab/solidus_paypal_commerce_platform)
4
+ [![codecov](https://codecov.io/gh/nebulab/solidus_paypal_commerce_platform/branch/master/graph/badge.svg)](https://codecov.io/gh/nebulab/solidus_paypal_commerce_platform)
5
+
6
+ The official PayPal integration of Solidus.
7
+
8
+ ## Installation
9
+
10
+ Add solidus_paypal_commerce_platform to your Gemfile:
11
+
12
+ ```ruby
13
+ gem 'solidus_paypal_commerce_platform'
14
+ ```
15
+
16
+ Bundle your dependencies and run the installation generator:
17
+
18
+ ```shell
19
+ bundle
20
+ bundle exec rails g solidus_paypal_commerce_platform:install
21
+ ```
22
+
23
+ ### PayPal Sandbox/Live Environment
24
+
25
+ This extension will automatically select a PayPal environment based on Rails environment so that "production" will be mapped to the "live" PayPal environment, and everything else will be routed to the "sandbox" PayPal environment.
26
+
27
+ If you want to override these values you can either set `SolidusPaypalCommercePlatform.config.env` to `"live"` or `"sandbox"` inside an initializer. Or, alternatively, you can set the `PAYPAL_ENV` environment variable to one of the same two values.
28
+
29
+ ### Custom PartnerID & PartnerClientID
30
+
31
+ You can declare your PayPal Partner-ID and Partner-Client-ID as environment
32
+ variables or set their values directly on `SolidusPaypalCommercePlatform.config`
33
+ or by using the configuration method detailed in the Customization section.
34
+
35
+ #### Use ENV variables
36
+
37
+ ```shell
38
+ export PAYPAL_PARTNER_ID="xxxxxxxxxxKG2"
39
+ export PAYPAL_PARTNER_CLIENT_ID="xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx-xxxxxxxxxxxxxxxxxxxxxxxxxVSX"
40
+ ```
41
+
42
+ #### Set them directly
43
+
44
+ ```ruby
45
+ SolidusPaypalCommercePlatform.config.partner_id = "xxxxxxxxxxKG2"
46
+ SolidusPaypalCommercePlatform.config.partner_client_id = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx-xxxxxxxxxxxxxxxxxxxxxxxxxVSX"
47
+ ```
48
+
49
+ ## Address Phone Number Validation
50
+
51
+ Since PayPal is being used as the checkout if the user checks out on the product or cart page, and PayPal doesn't collect phone numbers, this extension disables phone number required validation for `Spree::Address`. To turn phone number validation back on, you'll need to either:
52
+
53
+ A) Turn off cart and product page checkout - configurable on the admin payment method page for PayPal Commerce Platform.
54
+ -OR-
55
+ B) Collect the users phone number seperately
56
+
57
+ and then override the `Spree::Address` method `require_phone?` to return `true`.
58
+
59
+ ## Usage
60
+
61
+ ### I already have API credentials
62
+
63
+ If you already have API credentials, then you'll need to store them somewhere. You can do this directly in the
64
+ preferences of the payment method, but we recommend storing your API credentials as an ENV variable and loading
65
+ them in as a preference on initialization.
66
+
67
+ ```ruby
68
+ # config/initializers/spree.rb
69
+ Spree::Config.configure do |config|
70
+ config.static_model_preferences.add(
71
+ SolidusPaypalCommercePlatform::PaymentMethod,
72
+ 'paypal_commerce_platform_credentials', {
73
+ test_mode: !Rails.env.production?,
74
+ client_id: ENV['PAYPAL_CLIENT_ID'],
75
+ client_secret: ENV['PAYPAL_CLIENT_SECRET'],
76
+ paypal_email_confirmed: true,
77
+ display_on_product_page: true,
78
+ display_on_cart: true,
79
+ }
80
+ )
81
+ end
82
+ ```
83
+
84
+ ### I don't have API credentials
85
+
86
+ In this case, we still recommend following the above flow for security, but we have made a payment method setup
87
+ wizard to make it easier to get started. On the payment_methods index page, you'll see a button to set up your
88
+ PayPal Commerce Platform payment method. Click on this button and follow the instructions provided by PayPal.
89
+ When you return to your app, your payment method should be set up and ready to go.
90
+
91
+ ### Email Confirmation
92
+
93
+ A confirmed email is required to get paid by PayPal. You'll need to check `Paypal Email Confirmed` on your new
94
+ payment method before being able to select `Available To Users`.
95
+
96
+ ## Wizards
97
+
98
+ This gem adds support for payment method wizards to be set up. Payment wizards can be used to automatically set up
99
+ payment methods by directing the user to a sign-in page for whatever service they're connecting. In this gem, the
100
+ user is directed to sign up/in for PayPal, and then give their app access to their credentials, which is store in
101
+ preferences.
102
+
103
+ To add a payment wizard, add the class where your wizard is stored on initialization:
104
+
105
+ ```ruby
106
+ initializer "register_solidus_paypal_commerce_platform_wizard", after: "spree.register.payment_methods" do |app|
107
+ app.config.spree.payment_setup_wizards << "SolidusPaypalCommercePlatform::Wizard"
108
+ end
109
+ ```
110
+
111
+ The instances of your wizard class should respond to `#name` and `#partial_name`, where `partial_name` will return the path to the partial you'd like to display on the wizard setup section. In our case, we just display a button to direct the user to PayPal.
112
+
113
+ ## Custom Checkout Steps
114
+
115
+ With product and cart page checkout, the user is directed to the checkout confirmation step when they return from PayPal. If you've removed the confirmation step, you'll need to override the `SolidusPaypalCommercePlatform.finalizeOrder` JavaScript method to instead complete the order.
116
+
117
+ ## Backend Payments
118
+
119
+ PayPals API does not allow for admin-side payments. Instead, backend users taking payments for customers will need to use the PayPal Virtual Terminal to take payments. [More info is available on the PayPal website.](https://www.paypal.com/merchantapps/appcenter/acceptpayments/virtualterminal?locale.x=en_US)
120
+
121
+ ## Development
122
+
123
+ ### Testing the extension
124
+
125
+ First bundle your dependencies, then run `bin/rake`. `bin/rake` will default to building the dummy
126
+ app if it does not exist, then it will run specs. The dummy app can be regenerated by using
127
+ `bin/rake extension:test_app`.
128
+
129
+ ```shell
130
+ bundle
131
+ bin/rake
132
+ ```
133
+
134
+ To run [Rubocop](https://github.com/bbatsov/rubocop) static code analysis run
135
+
136
+ ```shell
137
+ bundle exec rubocop
138
+ ```
139
+
140
+ When testing your application's integration with this extension you may use its factories.
141
+ Simply add this require statement to your spec_helper:
142
+
143
+ ```ruby
144
+ require 'solidus_paypal_commerce_platform/factories'
145
+ ```
146
+
147
+ ### Running the sandbox
148
+
149
+ To run this extension in a sandboxed Solidus application, you can run `bin/sandbox`. The path for
150
+ the sandbox app is `./sandbox` and `bin/rails` will forward any Rails commands to
151
+ `sandbox/bin/rails`.
152
+
153
+ Here's an example:
154
+
155
+ ```shell
156
+ $ bin/rails server
157
+ => Booting Puma
158
+ => Rails 6.0.2.1 application starting in development
159
+ * Listening on tcp://127.0.0.1:3000
160
+ Use Ctrl-C to stop
161
+ ```
162
+
163
+ ### Releasing new versions
164
+
165
+ Your new extension version can be released using `gem-release` like this:
166
+
167
+ ```shell
168
+ bundle exec gem bump -v VERSION --tag --push --remote upstream && gem release
169
+ ```
170
+
171
+ ## License
172
+
173
+ Copyright (c) 2020 Nebulab srls, released under the New BSD License
@@ -0,0 +1,6 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'solidus_dev_support/rake_tasks'
4
+ SolidusDevSupport::RakeTasks.install
5
+
6
+ task default: 'extension:specs'
@@ -0,0 +1,2 @@
1
+ //= require spree/backend/solidus_paypal_commerce_platform/namespace
2
+ //= require spree/backend/solidus_paypal_commerce_platform/wizard
@@ -0,0 +1 @@
1
+ window.SolidusPaypalCommercePlatform = {}
@@ -0,0 +1,28 @@
1
+ /* global Spree, SolidusPaypalCommercePlatform */
2
+
3
+ // This needs to be filled before using the callback
4
+ SolidusPaypalCommercePlatform.nonce = null
5
+
6
+ // Returning from the setup wizard
7
+ SolidusPaypalCommercePlatform.onboardCallback = function(authCode, sharedId) {
8
+ var nonce = SolidusPaypalCommercePlatform.nonce
9
+
10
+ if (!nonce)
11
+ throw new Error("Please set SolidusPaypalCommercePlatform.nonce before calling this function.")
12
+
13
+ Spree.ajax({
14
+ url: '/solidus_paypal_commerce_platform/wizard',
15
+ type: 'POST',
16
+ data: {
17
+ authCode: authCode,
18
+ sharedId: sharedId,
19
+ nonce: nonce
20
+ },
21
+ success: function(response) {
22
+ window.location.href = response.redirectUrl;
23
+ },
24
+ error: function(response) {
25
+ alert("Something went wrong!")
26
+ }
27
+ });
28
+ };
@@ -0,0 +1,3 @@
1
+ //= require spree/frontend/solidus_paypal_commerce_platform/namespace
2
+ //= require spree/frontend/solidus_paypal_commerce_platform/button_actions
3
+ //= require spree/frontend/solidus_paypal_commerce_platform/buttons
@@ -0,0 +1,191 @@
1
+ SolidusPaypalCommercePlatform.showOverlay = function() {
2
+ document.getElementById("paypal_commerce_platform_overlay").style.display = "block";
3
+ }
4
+
5
+ SolidusPaypalCommercePlatform.hideOverlay = function() {
6
+ document.getElementById("paypal_commerce_platform_overlay").style.display = "none";
7
+ }
8
+
9
+ SolidusPaypalCommercePlatform.sendOrder = function(payment_method_id) {
10
+ return Spree.ajax({
11
+ url: '/solidus_paypal_commerce_platform/paypal_orders/' + Spree.current_order_id,
12
+ method: 'GET',
13
+ data: {
14
+ payment_method_id: payment_method_id,
15
+ order_token: Spree.current_order_token
16
+ }
17
+ }).then(function(response) {
18
+ return response.table.id;
19
+ })
20
+ }
21
+
22
+ SolidusPaypalCommercePlatform.createAndSendOrder = function(payment_method_id) {
23
+ return SolidusPaypalCommercePlatform.createOrder().then(function(){
24
+ return SolidusPaypalCommercePlatform.sendOrder(payment_method_id)
25
+ })
26
+ }
27
+
28
+ SolidusPaypalCommercePlatform.createOrder = function() {
29
+ var data = {
30
+ order: {
31
+ line_items_attributes: [{
32
+ variant_id: SolidusPaypalCommercePlatform.getVariantId(),
33
+ quantity: SolidusPaypalCommercePlatform.getQuantity()
34
+ }]
35
+ }
36
+ }
37
+
38
+ return Spree.ajax({
39
+ url: "/solidus_paypal_commerce_platform/orders",
40
+ method: 'POST',
41
+ data: data,
42
+ error: function(response) {
43
+ message = response.responseJSON
44
+ alert('A problem has occurred while creating your order - ' + message);
45
+ }
46
+ }).then(function(response) {
47
+ Spree.current_order_id = response.number
48
+ Spree.current_order_token = response.guest_token
49
+ });
50
+ }
51
+
52
+ SolidusPaypalCommercePlatform.getVariantId = function() {
53
+ var variants = document.getElementsByName("variant_id")
54
+ var variant_id;
55
+ if(variants.length == 1){
56
+ variant_id = variants[0].value
57
+ }else{
58
+ var i;
59
+ for (i = 0; i < variants.length; i++) {
60
+ if (variants[i].checked) {
61
+ variant_id = variants[i].value
62
+ }
63
+ }
64
+ }
65
+ return variant_id
66
+ }
67
+
68
+ SolidusPaypalCommercePlatform.getQuantity = function() {
69
+ return document.getElementById("quantity").value
70
+ }
71
+
72
+ SolidusPaypalCommercePlatform.approveOrder = function(data, actions) {
73
+ SolidusPaypalCommercePlatform.showOverlay()
74
+ actions.order.get().then(function(response){
75
+ SolidusPaypalCommercePlatform.updateAddress(response).then(function() {
76
+ SolidusPaypalCommercePlatform.verifyTotal(response.purchase_units[0].amount.value).then(function(){
77
+ $("#payments_source_paypal_order_id").val(data.orderID)
78
+ $("#payments_source_paypal_email").val(response.payer.email_address)
79
+ $("#checkout_form_payment").submit()
80
+ })
81
+ })
82
+ })
83
+ }
84
+
85
+ SolidusPaypalCommercePlatform.shippingChange = function(data, actions) {
86
+ Spree.ajax({
87
+ url: '/solidus_paypal_commerce_platform/shipping_rates',
88
+ method: 'GET',
89
+ data: {
90
+ order_id: Spree.current_order_id,
91
+ order_token: Spree.current_order_token,
92
+ address: data.shipping_address
93
+ },
94
+ error: function(response) {
95
+ message = response.responseJSON;
96
+ console.log('There were some problems with your payment address - ' + message);
97
+ actions.reject()
98
+ }
99
+ }).then(function(response) {
100
+ actions.order.patch([response]);
101
+ });
102
+ }
103
+
104
+ SolidusPaypalCommercePlatform.verifyTotal = function(paypal_total) {
105
+ return Spree.ajax({
106
+ url: '/solidus_paypal_commerce_platform/verify_total',
107
+ method: 'GET',
108
+ data: {
109
+ order_id: Spree.current_order_id,
110
+ order_token: Spree.current_order_token,
111
+ paypal_total: paypal_total
112
+ },
113
+ error: function(response) {
114
+ SolidusPaypalCommercePlatform.hideOverlay()
115
+ alert('There were some problems with your payment - ' + response.responseJSON.errors.expected_total);
116
+ }
117
+ })
118
+ }
119
+
120
+ SolidusPaypalCommercePlatform.finalizeOrder = function(payment_method_id, data, actions) {
121
+ SolidusPaypalCommercePlatform.showOverlay()
122
+ actions.order.get().then(function(response){
123
+ SolidusPaypalCommercePlatform.updateAddress(response).then(function() {
124
+ var paypal_amount = response.purchase_units[0].amount.value
125
+ SolidusPaypalCommercePlatform.advanceOrder().then(function() {
126
+ SolidusPaypalCommercePlatform.verifyTotal(paypal_amount).then(function(){
127
+ SolidusPaypalCommercePlatform.addPayment(paypal_amount, payment_method_id, data, response.payer.email_address).then(function() {
128
+ window.location.href = SolidusPaypalCommercePlatform.checkout_url
129
+ })
130
+ })
131
+ })
132
+ })
133
+ })
134
+ }
135
+
136
+ SolidusPaypalCommercePlatform.advanceOrder = function() {
137
+ return Spree.ajax({
138
+ url: '/api/checkouts/' + Spree.current_order_id + '/advance',
139
+ method: 'PUT',
140
+ data: {
141
+ order_token: Spree.current_order_token
142
+ },
143
+ error: function(response) {
144
+ SolidusPaypalCommercePlatform.hideOverlay()
145
+ alert('There were some problems with your order');
146
+ }
147
+ })
148
+ }
149
+
150
+ SolidusPaypalCommercePlatform.addPayment = function(paypal_amount, payment_method_id, data, email) {
151
+ return Spree.ajax({
152
+ url: '/api/checkouts/' + Spree.current_order_id + '/payments',
153
+ method: 'POST',
154
+ data: {
155
+ order_token: Spree.current_order_token,
156
+ payment: {
157
+ amount: paypal_amount,
158
+ payment_method_id: payment_method_id,
159
+ source_attributes: {
160
+ paypal_order_id: data.orderID,
161
+ paypal_email: email
162
+ }
163
+ }
164
+ },
165
+ error: function(response) {
166
+ SolidusPaypalCommercePlatform.hideOverlay()
167
+ alert('There were some problems with your payment');
168
+ }
169
+ })
170
+ }
171
+
172
+ SolidusPaypalCommercePlatform.updateAddress = function(response) {
173
+ var updated_address = response.purchase_units[0].shipping.address
174
+ return Spree.ajax({
175
+ url: '/solidus_paypal_commerce_platform/update_address',
176
+ method: 'POST',
177
+ data: {
178
+ address: {
179
+ updated_address: updated_address,
180
+ recipient: response.payer
181
+ },
182
+ order_id: Spree.current_order_id,
183
+ order_token: Spree.current_order_token
184
+ },
185
+ error: function(response) {
186
+ SolidusPaypalCommercePlatform.hideOverlay()
187
+ message = response.responseJSON;
188
+ alert('There were some problems with your payment address - ' + message);
189
+ }
190
+ })
191
+ }