Skip to content

Commit

Permalink
Update API
Browse files Browse the repository at this point in the history
* Searching for products
* Creating new line items syntax changes
* Complete Payments API

Anything else that wasn't cherry-picked across during the frantic work
on 1-1-stable.
  • Loading branch information
radar committed Apr 17, 2012
1 parent bcc1e89 commit fc4c1c5
Show file tree
Hide file tree
Showing 12 changed files with 135 additions and 20 deletions.
37 changes: 27 additions & 10 deletions api/app/controllers/spree/api/v1/payments_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ module Api
module V1
class PaymentsController < Spree::Api::V1::BaseController
before_filter :find_order
before_filter :find_payment, :only => [:show, :authorize, :capture]
before_filter :find_payment, :only => [:show, :authorize, :purchase, :capture, :void, :credit]

def index
@payments = @order.payments
Expand All @@ -26,17 +26,22 @@ def show
end

def authorize
authorize! :authorize, Payment
begin
@payment.authorize!
rescue Spree::Core::GatewayError
#noop, will deal with it in the response
end
perform_payment_action(:authorize)
end

def purchase
perform_payment_action(:purchase)
end

def void
perform_payment_action(:void_transaction)
end

if @payment.failed?
render :gateway_error, :status => 422
def credit
if params[:amount].to_f > @payment.credit_allowed
render "spree/api/v1/payments/credit_over_limit", :status => 422
else
render :show, :status => 200
perform_payment_action(:credit, params[:amount])
end
end

Expand All @@ -50,6 +55,18 @@ def find_order
def find_payment
@payment = @order.payments.find(params[:id])
end

def perform_payment_action(action, *args)
authorize! action, Payment

begin
@payment.send("#{action}!", *args)
render :show
rescue Spree::Core::GatewayError => e
@error = e.message
render "spree/api/v1/errors/gateway_error", :status => 422
end
end
end
end
end
Expand Down
5 changes: 5 additions & 0 deletions api/app/controllers/spree/api/v1/products_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,11 @@ def index
@products = product_scope.page(params[:page])
end

def search
@products = product_scope.search(params[:q]).result.page(params[:page])
render :index
end

def show
@product = find_product(params[:id])
end
Expand Down
6 changes: 3 additions & 3 deletions api/app/models/spree/order_decorator.rb
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
Spree::Order.class_eval do
def self.build_from_api(user, params)
order = create
params[:line_items].each do |variant_id, quantity|
line_item_params = { :variant_id => variant_id, :quantity => quantity }
line_item = order.add_variant(Spree::Variant.find(variant_id), quantity)
params[:line_items].each do |line_item|
order.add_variant(Spree::Variant.find(line_item[:variant_id]), line_item[:quantity])
end

order.user = user
order.email = user.email
order
Expand Down
5 changes: 0 additions & 5 deletions api/app/models/spree/payment_decorator.rb
Original file line number Diff line number Diff line change
@@ -1,5 +0,0 @@
Spree::Payment.class_eval do
def authorize!
self.payment_source.authorize(self)
end
end
2 changes: 2 additions & 0 deletions api/app/views/spree/api/v1/errors/gateway_error.rabl
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
object false
node(:error) { I18n.t(:gateway_error, :scope => "spree.api", :text => @error) }
2 changes: 2 additions & 0 deletions api/app/views/spree/api/v1/payments/credit_over_limit.rabl
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
object false
node(:error) { I18n.t(:credit_over_limit, :limit => @payment.credit_allowed, :scope => 'spree.api') }
2 changes: 2 additions & 0 deletions api/config/locales/en.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ en:
unauthorized: "You are not authorized to perform that action."
invalid_resource: "Invalid resource. Please fix errors and try again."
resource_not_found: "The resource you were looking for could not be found."
gateway_error: "There was a problem with the payment gateway: %{text}"
credit_over_limit: "This payment can only be credited up to %{limit}. Please specify an amount less than or equal to this number."

order:
could_not_transition: "The order could not be transitioned. Please fix the errors and try again."
Expand Down
13 changes: 13 additions & 0 deletions api/config/routes.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@
namespace :api do
scope :module => :v1 do
resources :products do
collection do
get :search
end

resources :variants
resources :images
end
Expand All @@ -13,9 +17,18 @@
resources :orders do
member do
put :address
put :delivery
end

resources :line_items
resources :payments do
member do
put :authorize
put :purchase
put :void
put :credit
end
end
end

resources :countries, :only => [:index, :show]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ module Spree

it "can create an order" do
variant = Factory(:variant)
api_post :create, :order => { :line_items => { variant.to_param => 5 } }
api_post :create, :order => { :line_items => [{ :variant_id => variant.to_param, :quantity => 5 }] }
response.status.should == 200
order = Order.last
order.line_items.count.should == 1
Expand Down
72 changes: 72 additions & 0 deletions api/spec/controllers/spree/api/v1/payments_controller_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -74,13 +74,85 @@ module Spree
it "can authorize" do
api_put :authorize, :id => payment.to_param
response.status.should == 200
payment.reload
payment.state.should == "pending"
end

it "returns a 422 status when authorization fails" do
fake_response = stub(:success? => false, :to_s => "Could not authorize card")
Spree::Gateway::Bogus.any_instance.should_receive(:authorize).and_return(fake_response)
api_put :authorize, :id => payment.to_param
response.status.should == 422
json_response["error"].should == "There was a problem with the payment gateway: Could not authorize card"
payment.reload
payment.state.should == "failed"
end

it "can purchase" do
api_put :purchase, :id => payment.to_param
response.status.should == 200
payment.reload
payment.state.should == "completed"
end

it "returns a 422 status when purchasing fails" do
fake_response = stub(:success? => false, :to_s => "Insufficient funds")
Spree::Gateway::Bogus.any_instance.should_receive(:purchase).and_return(fake_response)
api_put :purchase, :id => payment.to_param
response.status.should == 422
json_response["error"].should == "There was a problem with the payment gateway: Insufficient funds"

payment.reload
payment.state.should == "failed"
end

it "can void" do
api_put :void, :id => payment.to_param
response.status.should == 200
payment.reload
payment.state.should == "void"
end

it "returns a 422 status when voiding fails" do
fake_response = stub(:success? => false, :to_s => "NO REFUNDS")
Spree::Gateway::Bogus.any_instance.should_receive(:void).and_return(fake_response)
api_put :void, :id => payment.to_param
response.status.should == 422
json_response["error"].should == "There was a problem with the payment gateway: NO REFUNDS"

payment.reload
payment.state.should == "pending"
end

context "crediting" do
before do
payment.purchase!
end

it "can credit" do
api_put :credit, :id => payment.to_param
response.status.should == 200
payment.reload
payment.state.should == "completed"

# Ensur that a credit payment was created, and it has correct credit amount
credit_payment = Payment.where(:source_type => 'Spree::Payment', :source_id => payment.id).last
credit_payment.amount.to_f.should == -45.75
end

it "returns a 422 status when crediting fails" do
fake_response = stub(:success? => false, :to_s => "NO CREDIT FOR YOU")
Spree::Gateway::Bogus.any_instance.should_receive(:credit).and_return(fake_response)
api_put :credit, :id => payment.to_param
response.status.should == 422
json_response["error"].should == "There was a problem with the payment gateway: NO CREDIT FOR YOU"
end

it "cannot credit over credit_allowed limit" do
api_put :credit, :id => payment.to_param, :amount => 1000000
response.status.should == 422
json_response["error"].should == "This payment can only be credited up to 45.75. Please specify an amount less than or equal to this number."
end
end
end

Expand Down
7 changes: 7 additions & 0 deletions api/spec/controllers/spree/api/v1/products_controller_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,13 @@ module Spree
end
end

it "can search for products" do
Factory(:product, :name => "The best product in the world")
api_get :search, :q => { :name_cont => "best" }
json_response["products"].first.should have_attributes(attributes)
json_response["count"].should == 1
end

it "gets a single product" do
product.master.images.create!(:attachment => image("thinking-cat.jpg"))
api_get :show, :id => product.to_param
Expand Down
2 changes: 1 addition & 1 deletion api/spec/models/spree/order_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ module Spree
it 'can build an order from API parameters' do

Spree::Variant.should_receive(:find).and_return(stub_model(Variant, :id => 1))
order = Order.build_from_api(user, { :line_items => { 1 => 5 }})
order = Order.build_from_api(user, { :line_items => [{ :variant_id => 1, :quantity => 5 }]})

order.user.should == user
line_item = order.line_items.first
Expand Down

0 comments on commit fc4c1c5

Please sign in to comment.