-
Notifications
You must be signed in to change notification settings - Fork 24
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add frontend view and API controllers for PayPal checkout
Adds routes for orders_controller - which allows the creation of orders on PayPals side. This is called when the paypal button is first clicked, to send the order info to PayPal so they know how to build the order and how much is going to be charged. Also adds a route for payments_controller, which handles the creation of the source/payment for the order. en.yml was updated to display nothing for validation errors for paypal_order_id - the reason is that when you try to proceed without having created a payment on PayPal, the error message "Payments Source #{en.yml entry} Can't Be Blank" appears, with whatever you've set in the paypal_order_id entry appearing in the middle of the string. We may want to adjust the entire error message, but I think it's clearer with nothing in the middle - so just "Payments Source Can't Be Blank", instead of "Payments Source Paypal Order Id Can't Be Blank". Also adds tests for the frontend! 🎉
- Loading branch information
Showing
12 changed files
with
262 additions
and
3 deletions.
There are no files selected for viewing
4 changes: 2 additions & 2 deletions
4
app/assets/javascripts/spree/frontend/solidus_paypal_commerce_platform.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,2 @@ | ||
// Placeholder manifest file. | ||
// the installer will append this file to the app vendored assets here: vendor/assets/javascripts/spree/frontend/all.js' | ||
//= require spree/frontend/solidus_paypal_commerce_platform/namespace | ||
//= require spree/frontend/solidus_paypal_commerce_platform/buttons |
21 changes: 21 additions & 0 deletions
21
app/assets/javascripts/spree/frontend/solidus_paypal_commerce_platform/buttons.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
SolidusPaypalCommercePlatform.renderButton = function(payment_method_id) { | ||
paypal.Buttons({ | ||
createOrder: function (data, actions) { | ||
return Spree.ajax({ | ||
url: '/solidus_paypal_commerce_platform/orders', | ||
method: 'POST', | ||
data: { | ||
payment_method_id: payment_method_id, | ||
order_id: Spree.current_order_id, | ||
order_token: Spree.current_order_token | ||
} | ||
}).then(function(res) { | ||
return res.table.id; | ||
}) | ||
}, | ||
onApprove: function (data, actions) { | ||
$("#payments_source_paypal_order_id").val(data.orderID) | ||
$("#checkout_form_payment").submit() | ||
} | ||
}).render('#paypal-button-container') | ||
} |
1 change: 1 addition & 0 deletions
1
app/assets/javascripts/spree/frontend/solidus_paypal_commerce_platform/namespace.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
window.SolidusPaypalCommercePlatform = {} |
26 changes: 26 additions & 0 deletions
26
app/controllers/solidus_paypal_commerce_platform/orders_controller.rb
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
module SolidusPaypalCommercePlatform | ||
class OrdersController < ::Spree::Api::BaseController | ||
before_action :load_order | ||
before_action :load_payment_method | ||
skip_before_action :authenticate_user | ||
|
||
def create | ||
authorize! :update, @order, order_token | ||
request = SolidusPaypalCommercePlatform::Requests.new( | ||
@payment_method.client_id, @payment_method.client_secret | ||
).create_order(@order, @payment_method.auto_capture) | ||
render json: request, status: :ok | ||
end | ||
|
||
private | ||
|
||
def load_order | ||
@order = Spree::Order.find_by!(number: params[:order_id]) | ||
end | ||
|
||
def load_payment_method | ||
@payment_method = Spree::PaymentMethod.find(params[:payment_method_id]) | ||
end | ||
|
||
end | ||
end |
43 changes: 43 additions & 0 deletions
43
app/controllers/solidus_paypal_commerce_platform/payments_controller.rb
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
module SolidusPaypalCommercePlatform | ||
class PaymentsController < ::Spree::Api::BaseController | ||
before_action :load_order | ||
skip_before_action :authenticate_user | ||
|
||
def create | ||
authorize! :update, @order, order_token | ||
paypal_order_id = paypal_params[:paypal_order_id] | ||
|
||
if !paypal_order_id | ||
return redirect_to checkout_state_path(@order.state), notice: "Invalid order confirmation data passed in" | ||
end | ||
|
||
if @order.complete? | ||
return redirect_to spree.order_path(@order), notice: "Order is already in complete state" | ||
end | ||
|
||
source = SolidusPaypalCommercePlatform::Source.new(paypal_order_id: paypal_order_id) | ||
|
||
source.transaction do | ||
if source.save! | ||
payment = @order.payments.create!({ | ||
payment_method_id: paypal_params[:payment_method_id], | ||
source: source | ||
}) | ||
|
||
render json: {}, status: :ok | ||
end | ||
end | ||
end | ||
|
||
private | ||
|
||
def paypal_params | ||
params.permit(:paypal_order_id, :order_id, :order_token, :payment_method_id) | ||
end | ||
|
||
def load_order | ||
@order = Spree::Order.find_by!(number: params[:order_id]) | ||
end | ||
|
||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
12 changes: 12 additions & 0 deletions
12
lib/views/frontend/spree/checkout/payment/_paypal_commerce_platform.html.erb
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
<script | ||
src="<%= payment_method.sdk_url %>"> | ||
</script> | ||
|
||
<div id="paypal-button-container"></div> | ||
<input type="hidden" name="payment_source[<%= payment_method.id %>][paypal_order_id]" id="payments_source_paypal_order_id"> | ||
|
||
<script> | ||
$( document ).ready(function() { | ||
SolidusPaypalCommercePlatform.renderButton("<%= payment_method.id %>") | ||
}) | ||
</script> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
# frozen_string_literal: true | ||
|
||
FactoryBot.define do | ||
factory :paypal_payment_method, class: 'SolidusPaypalCommercePlatform::Gateway' do | ||
type { "SolidusPaypalCommercePlatform::Gateway" } | ||
name { "PayPal Payment Method" } | ||
preferences { | ||
{ | ||
client_id: SecureRandom.hex(8), | ||
client_secret: SecureRandom.hex(10) | ||
} | ||
} | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
require 'spec_helper' | ||
|
||
RSpec.describe "Checkout" do | ||
|
||
context "paypal payment method" do | ||
let(:order) { Spree::TestingSupport::OrderWalkthrough.up_to(:payment) } | ||
let(:paypal_payment_method) { create(:paypal_payment_method) } | ||
|
||
before do | ||
user = create(:user) | ||
order.user = user | ||
order.recalculate | ||
|
||
paypal_payment_method | ||
allow_any_instance_of(Spree::CheckoutController).to receive_messages(current_order: order, try_spree_current_user: user) | ||
end | ||
|
||
it "should generate a js file with the correct credentials and intent attached" do | ||
visit '/checkout/payment' | ||
expect(page).to have_css( | ||
'script[src*="sdk/js?client-id=' + paypal_payment_method.preferences[:client_id] + '&intent=authorize"]', visible: false | ||
) | ||
end | ||
|
||
context "when auto-capture is set to true" do | ||
it "should generate a js file with intent capture" do | ||
paypal_payment_method.update(auto_capture: true) | ||
visit '/checkout/payment' | ||
expect(page).to have_css( | ||
'script[src*="sdk/js?client-id=' + paypal_payment_method.preferences[:client_id] + '&intent=capture"]', visible: false | ||
) | ||
end | ||
end | ||
|
||
context "if no payment has been made" do | ||
it "should fail to process" do | ||
visit '/checkout/payment' | ||
choose(option: paypal_payment_method.id) | ||
click_button("Save and Continue") | ||
expect(page).to have_content("Payments source can't be blank") | ||
end | ||
end | ||
|
||
context "if payment has been made" do | ||
it "should proceed to the next step" do | ||
visit '/checkout/payment' | ||
choose(option: paypal_payment_method.id) | ||
find(:xpath, "//input[@id='payments_source_paypal_order_id']", visible: false).set SecureRandom.hex(8) | ||
click_button("Save and Continue") | ||
expect(page).to have_css(".current", text: "Confirm") | ||
end | ||
end | ||
|
||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,82 @@ | ||
require 'spec_helper' | ||
require 'paypal-checkout-sdk' | ||
|
||
RSpec.describe "SolidusPaypalCommercePlatform::Gateway", type: :model do | ||
let(:paypal_payment_method) { create(:paypal_payment_method) } | ||
let(:payment) { create(:payment) } | ||
|
||
before do | ||
response = OpenStruct.new( | ||
status_code: 201, | ||
result: OpenStruct.new( | ||
purchase_units: [ | ||
OpenStruct.new( | ||
payments: OpenStruct.new( | ||
authorizations: [ | ||
OpenStruct.new(id: SecureRandom.hex(4)) | ||
] | ||
) | ||
) | ||
] | ||
) | ||
) | ||
|
||
allow_any_instance_of(PayPal::PayPalHttpClient).to receive(:execute) { response } | ||
allow_any_instance_of(PayPal::SandboxEnvironment).to receive(:authorizationString) { "test auth" } | ||
end | ||
|
||
context "#purchase" do | ||
it "should send a purchase request to paypal" do | ||
paypal_order_id = SecureRandom.hex(8) | ||
source = paypal_payment_method.payment_source_class.create(paypal_order_id: paypal_order_id) | ||
request = { | ||
path: "/v2/checkout/orders/#{paypal_order_id}/capture", | ||
headers: { | ||
"Content-Type" => "application/json", | ||
"Authoriation" => "test auth", | ||
"PayPal-Partner-Attribution-Id" => "Solidus_PCP_SP", | ||
}, | ||
verb: "POST" | ||
} | ||
expect(SolidusPaypalCommercePlatform::Requests::Request).to receive(:new).with(request) | ||
paypal_payment_method.purchase(1000,source,{}) | ||
end | ||
end | ||
|
||
context "#authorize" do | ||
it "should send an authorize request to paypal" do | ||
paypal_order_id = SecureRandom.hex(8) | ||
source = paypal_payment_method.payment_source_class.create(paypal_order_id: paypal_order_id) | ||
request = { | ||
path: "/v2/checkout/orders/#{paypal_order_id}/authorize", | ||
headers: { | ||
"Content-Type" => "application/json", | ||
"Authoriation" => "test auth", | ||
"PayPal-Partner-Attribution-Id" => "Solidus_PCP_SP", | ||
}, | ||
verb: "POST" | ||
} | ||
expect(SolidusPaypalCommercePlatform::Requests::Request).to receive(:new).with(request) | ||
paypal_payment_method.authorize(1000,source,{}) | ||
end | ||
end | ||
|
||
context "#capture" do | ||
it "should send a capture request to paypal" do | ||
authorization_id = SecureRandom.hex(8) | ||
source = paypal_payment_method.payment_source_class.create(authorization_id: authorization_id) | ||
payment.source = source | ||
request = { | ||
path: "/v2/payments/authorizations/#{authorization_id}/capture", | ||
headers: { | ||
"Content-Type" => "application/json", | ||
"Authoriation" => "test auth", | ||
"PayPal-Partner-Attribution-Id" => "Solidus_PCP_SP", | ||
}, | ||
verb: "POST" | ||
} | ||
expect(SolidusPaypalCommercePlatform::Requests::Request).to receive(:new).with(request) | ||
paypal_payment_method.capture(1000,{},{originator: payment}) | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters