-
-
-
-
diff --git a/lib/poundpay.rb b/lib/poundpay.rb
index 837f98d..b4cf4ec 100644
--- a/lib/poundpay.rb
+++ b/lib/poundpay.rb
@@ -1,6 +1,7 @@
require 'poundpay/resource'
require 'poundpay/elements'
require 'poundpay/callback'
+require 'poundpay/exceptions'
require 'poundpay/rails'
@@ -24,7 +25,7 @@ def configure(developer_sid, auth_token)
end
yield self if block_given?
-
+
api_url.sub! /(\/)$/, "" # Remove trailing backslash
www_url.sub /(\/)$/, ""
Resource.site = "#{api_url}/#{api_version}/"
@@ -34,9 +35,8 @@ def configure(developer_sid, auth_token)
# Set callback_url if defined in configuration
if callback_url
- @me = Developer.me
+ @me = Developer.new
@me.callback_url = callback_url
- @me.save!
end
end
@@ -84,4 +84,4 @@ def api_version
@api_version || API_VERSION
end
end
-end
\ No newline at end of file
+end
diff --git a/lib/poundpay/elements.rb b/lib/poundpay/elements.rb
index 18f019d..4666a7d 100644
--- a/lib/poundpay/elements.rb
+++ b/lib/poundpay/elements.rb
@@ -5,6 +5,9 @@
class PaymentException < Exception
end
+class PaymentAuthorizeException < PaymentException
+end
+
class PaymentEscrowException < PaymentException
end
@@ -14,6 +17,12 @@ class PaymentReleaseException < PaymentException
class PaymentCancelException < PaymentException
end
+class ChargePermissionException < Exception
+end
+
+class ChargePermissionDeactivateException < ChargePermissionException
+end
+
module Poundpay
class Developer < Resource
def self.me
@@ -22,6 +31,7 @@ def self.me
def save
validate_url callback_url
+ validate_url charge_permission_callback_url
super
end
@@ -29,6 +39,11 @@ def callback_url=(url)
validate_url url
attributes['callback_url'] = url
end
+
+ def charge_permission_callback_url=(url)
+ validate_url url
+ attributes['charge_permission_callback_url'] = url
+ end
protected
def validate_url(url)
@@ -40,32 +55,64 @@ def validate_url(url)
end
end
+ class User < Resource
+ end
+
+ class ChargePermission < Resource
+ def deactivate
+ states = ['CREATED', 'ACTIVE']
+ unless states.include?(state)
+ raise ChargePermissionDeactivateException.new "Charge permission state is #{state}. Only CREATED or ACTIVE charge permissions may be deactivated."
+ end
+ attributes['state'] = 'INACTIVE'
+ save
+ end
+ end
+
class Payment < Resource
+
+ def self.batch_update(params)
+ body = self.put('', {}, self.urlencode(params)).body
+ collection = self.format.decode(body)
+ return self.instantiate_collection(collection)
+ end
+
+ def authorize
+ unless state == 'CREATED'
+ raise PaymentAuthorizeException.new "Payment state is #{state}. Only CREATED payments may be AUTHORIZED."
+ end
+ attributes['state'] = 'AUTHORIZED'
+ save
+ end
+
def escrow
- unless status == 'AUTHORIZED'
- raise PaymentEscrowException.new "Payment status is #{status}. Only AUTHORIZED payments may be released"
+ unless state == 'AUTHORIZED'
+ raise PaymentEscrowException.new "Payment state is #{state}. Only AUTHORIZED payments may be ESCROWED."
end
- attributes['status'] = 'ESCROWED'
+ attributes['state'] = 'ESCROWED'
save
end
def release
- unless status == 'ESCROWED'
- raise PaymentReleaseException.new "Payment status is #{status}. Only ESCROWED payments may be released"
+ states = ['ESCROWED']
+ unless states.include?(state)
+ raise PaymentReleaseException.new "Payment state is #{state}. Only ESCROWED payments may be RELEASED."
end
- # Tried setting status with status=, but save still had status == 'ESCROWED'.
- # Setting the status through the attributes, however, does work.
- attributes['status'] = 'RELEASED'
+ # Tried setting state with state=, but save still had state == 'ESCROWED'.
+ # Setting the state through the attributes, however, does work.
+ attributes['state'] = 'RELEASED'
save
end
def cancel
- unless status == 'ESCROWED'
- raise PaymentCancelException.new "Payment status is #{status}. Only ESCROWED payments may be canceled"
+ states = ['CREATED', 'AUTHORIZED', 'ESCROWED']
+ unless states.include?(state)
+ raise PaymentCancelException.new "Payment state is #{state}. Only payments with states " \
+ "#{states.join(', ')} may be canceled"
end
- attributes['status'] = 'CANCELED'
+ attributes['state'] = 'CANCELED'
save
end
end
-end
\ No newline at end of file
+end
diff --git a/lib/poundpay/exceptions.rb b/lib/poundpay/exceptions.rb
new file mode 100644
index 0000000..d767bdd
--- /dev/null
+++ b/lib/poundpay/exceptions.rb
@@ -0,0 +1,10 @@
+require 'active_resource/exceptions'
+
+# monkey patch the base AR exception class to provide access to the response body in a structured format.
+module ActiveResource
+ class ConnectionError
+ def data
+ @data ||= ActiveSupport::JSON.decode(self.response.body).symbolize_keys rescue {}
+ end
+ end
+end
diff --git a/lib/poundpay/rails.rb b/lib/poundpay/rails.rb
index ae43a90..b31a9ad 100644
--- a/lib/poundpay/rails.rb
+++ b/lib/poundpay/rails.rb
@@ -3,8 +3,8 @@ module Poundpay
def self.configure_from_yaml(path)
pathname = Pathname.new Rails.root.join(path)
raise ArgumentError.new "File does not exist: #{pathname.to_s}" unless pathname.exist?
- config = YAML::load_file(pathname)[Rails.env]
+ config = YAML::load(ERB.new(File.read(pathname)).result)[Rails.env]
Poundpay.configure_from_hash(config)
end
end
-end
\ No newline at end of file
+end
diff --git a/lib/poundpay/resource.rb b/lib/poundpay/resource.rb
index 3849dea..557e219 100644
--- a/lib/poundpay/resource.rb
+++ b/lib/poundpay/resource.rb
@@ -7,7 +7,11 @@ class Resource < ActiveResource::Base
self.format = Formats::UrlencodedJsonFormat
class << self
- attr_accessor_with_default(:primary_key, 'sid')
+ attr_accessor :primary_key
+
+ def primary_key
+ @primary_key ||= 'sid'
+ end
# Modified default to not use an extension
def element_path(id, prefix_options = {}, query_options = nil)
@@ -27,6 +31,12 @@ def collection_path(prefix_options = {}, query_options = nil)
remove_extension(path)
end
+ # Modified default to not use an extension
+ def custom_method_collection_url(method_name, options = {})
+ path = super(method_name, options)
+ remove_extension(path)
+ end
+
# Handle paginated collections
def instantiate_collection(collection, prefix_options = {})
# TODO: Consume pages
@@ -36,14 +46,14 @@ def instantiate_collection(collection, prefix_options = {})
protected
def remove_extension(path)
- path.sub /(\.#{format.extension})$/, ""
+ path.sub /(\.#{format.extension})/, ""
end
end
# Poundpay accepts urlencoded form parameters
# Ideally we should override this functionality in the format, but it's not very straightforward to do so
def encode
- urlencode(@attributes)
+ Resource.urlencode(@attributes)
end
def collection_name
@@ -51,8 +61,14 @@ def collection_name
end
protected
- def urlencode(params)
- params.to_a.collect! { |k, v| "#{k}=#{CGI.escape(v.to_s)}" }.join("&")
- end
+ def self.urlencode(params)
+ params.to_a.collect! { |k, v|
+ if v.kind_of?(Array)
+ v.collect! { |x| "#{k}=#{CGI.escape(x.to_s)}"}.join("&")
+ else
+ "#{k}=#{CGI.escape(v.to_s)}"
+ end
+ }.join("&")
+ end
end
end
\ No newline at end of file
diff --git a/lib/poundpay/version.rb b/lib/poundpay/version.rb
index 634b36c..da123cc 100644
--- a/lib/poundpay/version.rb
+++ b/lib/poundpay/version.rb
@@ -1,3 +1,3 @@
module Poundpay
- VERSION = "0.2.8"
+ VERSION = "0.4.0"
end
diff --git a/poundpay.gemspec b/poundpay.gemspec
index 1eed260..a48680c 100644
--- a/poundpay.gemspec
+++ b/poundpay.gemspec
@@ -14,7 +14,7 @@ Gem::Specification.new do |s|
s.rubyforge_project = "poundpay"
- s.add_dependency("activeresource", ">= 3.0")
+ s.add_dependency("activeresource", "~> 3.1.0")
s.add_development_dependency("rspec", ">= 2.0")
s.add_development_dependency("wirble")
diff --git a/spec/fixtures/charge_permissions.rb b/spec/fixtures/charge_permissions.rb
new file mode 100644
index 0000000..76794af
--- /dev/null
+++ b/spec/fixtures/charge_permissions.rb
@@ -0,0 +1,24 @@
+module Poundpay
+ module ChargePermissionFixture
+ def created_attributes
+ {
+ "email_address" => "john@example.com",
+ "state" => "CREATED",
+ "updated_at" => "2011-02-11T19:07:05.332356Z",
+ "created_at" => "2011-02-11T19:07:05.332356Z",
+ }
+ end
+
+ def active_attributes
+ @attributes = created_attributes
+ @attributes["state"] = "ACTIVE"
+ @attributes
+ end
+
+ def inactive_attributes
+ @attributes = created_attributes
+ @attributes["state"] = "INACTIVE"
+ @attributes
+ end
+ end
+end
diff --git a/spec/fixtures/payments.rb b/spec/fixtures/payments.rb
index ca1d6ad..f6b8661 100644
--- a/spec/fixtures/payments.rb
+++ b/spec/fixtures/payments.rb
@@ -1,6 +1,6 @@
module Poundpay
module PaymentFixture
- def staged_payment_attributes
+ def created_payment_attributes
{
"amount" => 20000,
"payer_fee_amount" => 0,
@@ -9,7 +9,7 @@ def staged_payment_attributes
"recipient_email_address" => "david@example.com",
"description" => "Beats by Dr. Dre",
"sid" => "PY1d82752a361211e0bce31231400042c7",
- "status" => "STAGED",
+ "state" => "CREATED",
"amount_to_credit_developer" => 550,
"updated_at" => "2011-02-11T19:07:05.332356Z",
"recipient_sid" => nil,
@@ -23,27 +23,27 @@ def staged_payment_attributes
end
def authorized_payment_attributes
- @attributes = staged_payment_attributes
- @attributes["status"] = "AUTHORIZED"
+ @attributes = created_payment_attributes
+ @attributes["state"] = "AUTHORIZED"
@attributes
end
def escrowed_payment_attributes
- @attributes = staged_payment_attributes
- @attributes["status"] = "ESCROWED"
+ @attributes = created_payment_attributes
+ @attributes["state"] = "ESCROWED"
@attributes
end
def released_payment_attributes
- @attributes = staged_payment_attributes
- @attributes["status"] = "RELEASED"
+ @attributes = created_payment_attributes
+ @attributes["state"] = "RELEASED"
@attributes
end
def canceled_payment_attributes
- @attributes = staged_payment_attributes
- @attributes["status"] = "CANCELED"
+ @attributes = created_payment_attributes
+ @attributes["state"] = "CANCELED"
@attributes
end
end
-end
\ No newline at end of file
+end
diff --git a/spec/fixtures/poundpay.yml b/spec/fixtures/poundpay.yml
index dbe8e43..705374f 100644
--- a/spec/fixtures/poundpay.yml
+++ b/spec/fixtures/poundpay.yml
@@ -1,6 +1,6 @@
development:
developer_sid: DV0383d447360511e0bbac00264a09ff3c
- auth_token: development_auth_token
+ auth_token: <%= "development_auth_token" %>
www_url: https://www-sandbox.poundpay.com
api_url: https://api-sandbox.poundpay.com
diff --git a/spec/poundpay/elements_spec.rb b/spec/poundpay/elements_spec.rb
index 4c1623e..d5cacf1 100644
--- a/spec/poundpay/elements_spec.rb
+++ b/spec/poundpay/elements_spec.rb
@@ -2,6 +2,7 @@
require 'poundpay/elements'
require 'fixtures/payments'
require 'fixtures/developers'
+require 'fixtures/charge_permissions'
include Poundpay
@@ -66,10 +67,25 @@
Poundpay.clear_config!
end
+ describe "#authorize" do
+ it "should not be able to authorize a non CREATED payment" do
+ @non_created_payment = Payment.new authorized_payment_attributes
+ expect {@non_created_payment.authorize}.to raise_error(PaymentAuthorizeException)
+ end
+
+ it "should authorize a CREATED payment" do
+ @created_payment = Payment.new created_payment_attributes
+ @created_payment.should_receive(:save).and_return(Payment.new authorized_payment_attributes)
+
+ @created_payment.authorize
+ @created_payment.state.should == 'AUTHORIZED'
+ end
+ end
+
describe "#escrow" do
- it "should not be able to escrow a STAGED payment" do
- @staged_payment = Payment.new staged_payment_attributes
- expect {@staged_payment.escrow}.to raise_error(PaymentEscrowException)
+ it "should not be able to escrow a CREATED payment" do
+ @created_payment = Payment.new created_payment_attributes
+ expect {@created_payment.escrow}.to raise_error(PaymentEscrowException)
end
it "should escrow an AUTHORIZED payment" do
@@ -77,14 +93,14 @@
@authorized_payment.should_receive(:save).and_return(Payment.new escrowed_payment_attributes)
@authorized_payment.escrow
- @authorized_payment.status.should == 'ESCROWED'
+ @authorized_payment.state.should == 'ESCROWED'
end
end
describe "#release" do
- it "should not be able to release a STAGED payment" do
- @staged_payment = Payment.new staged_payment_attributes
- expect {@staged_payment.release}.to raise_error(PaymentReleaseException)
+ it "should not be able to release a CREATED payment" do
+ @created_payment = Payment.new created_payment_attributes
+ expect {@created_payment.release}.to raise_error(PaymentReleaseException)
end
it "should release an ESCROWED payment" do
@@ -92,22 +108,65 @@
@escrowed_payment.should_receive(:save).and_return(Payment.new released_payment_attributes)
@escrowed_payment.release
- @escrowed_payment.status.should == 'RELEASED'
+ @escrowed_payment.state.should == 'RELEASED'
end
- end
+ end
describe "#cancel" do
- it "should not be able to cancel a STAGED payment" do
- @staged_payment = Payment.new staged_payment_attributes
- expect {@staged_payment.cancel}.to raise_error(PaymentCancelException)
+ it "should not be able to cancel a RELEASED payment" do
+ @released_payment = Payment.new released_payment_attributes
+ expect {@released_payment.cancel}.to raise_error(PaymentCancelException)
end
- it "should release an ESCROWED payment" do
+ it "should cancel an ESCROWED payment" do
@escrowed_payment = Payment.new escrowed_payment_attributes
@escrowed_payment.should_receive(:save).and_return(Payment.new canceled_payment_attributes)
@escrowed_payment.cancel
- @escrowed_payment.status.should == 'CANCELED'
+ @escrowed_payment.state.should == 'CANCELED'
+ end
+
+ it "should cancel a CREATED payment" do
+ @created_payment = Payment.new created_payment_attributes
+ @created_payment.should_receive(:save).and_return(Payment.new canceled_payment_attributes)
+
+ @created_payment.cancel
+ @created_payment.state.should == 'CANCELED'
+ end
+ end
+end
+
+describe ChargePermission do
+ include ChargePermissionFixture
+
+ before (:all) do
+ Poundpay.configure(
+ "DV0383d447360511e0bbac00264a09ff3c",
+ "c31155b9f944d7aed204bdb2a253fef13b4fdcc6ae1540200449cc4526b2381a")
+ end
+
+ after (:all) do
+ Poundpay.clear_config!
+ end
+
+ describe "#deactivate" do
+ it "should not be able to deactivate an INACTIVE charge permission" do
+ @inactive_charge_permission = ChargePermission.new inactive_attributes
+ expect {@inactive_charge_permission.deactivate}.to raise_error(ChargePermissionDeactivateException)
+ end
+
+ it "should deactivate a CREATED charge permission" do
+ @created_charge_permission = ChargePermission.new created_attributes
+ @created_charge_permission.should_receive(:save).and_return(ChargePermission.new created_attributes)
+ @created_charge_permission.deactivate
+ @created_charge_permission.state.should == 'INACTIVE'
+ end
+
+ it "should deactivate an ACTIVE charge permission" do
+ @active_charge_permission = ChargePermission.new active_attributes
+ @active_charge_permission.should_receive(:save).and_return(ChargePermission.new active_attributes)
+ @active_charge_permission.deactivate
+ @active_charge_permission.state.should == 'INACTIVE'
end
end
-end
\ No newline at end of file
+end
diff --git a/spec/poundpay/exceptions_spec.rb b/spec/poundpay/exceptions_spec.rb
new file mode 100644
index 0000000..6a54fdc
--- /dev/null
+++ b/spec/poundpay/exceptions_spec.rb
@@ -0,0 +1,11 @@
+require 'poundpay'
+
+describe ActiveResource::ConnectionError do
+ describe ".data" do
+ it "should return the parsed response body" do
+ response = double('response')
+ response.stub(:body).and_return('{"error_message":"You screwed up!"}')
+ ActiveResource::ConnectionError.new(response).data.should == {error_message: "You screwed up!"}
+ end
+ end
+end
diff --git a/spec/poundpay/resource_spec.rb b/spec/poundpay/resource_spec.rb
index 3309387..ba08e31 100644
--- a/spec/poundpay/resource_spec.rb
+++ b/spec/poundpay/resource_spec.rb
@@ -29,6 +29,12 @@ class FakeElement < Resource
FakeElement.collection_path.should == "/version/fake_elements"
end
end
+
+ describe "#self.custom_method_collection_url" do
+ it "should not add a extension to the custom_method_collection_url" do
+ FakeElement.custom_method_collection_url("").should == "/version/fake_elements/"
+ end
+ end
describe "#self.instantiate_collection" do
it "should handle paginated responses" do
@@ -43,6 +49,10 @@ class FakeElement < Resource
fake_element = FakeElement.new(:foo => "bar baz")
fake_element.encode.should == "foo=bar+baz"
end
+ it "should urlencode the attributes wuihtout brackets" do
+ fake_element = FakeElement.new(:foo => ["bar", "baz"])
+ fake_element.encode.should == "foo=bar&foo=baz"
+ end
end
describe "#collection_name" do
diff --git a/spec/poundpay_spec.rb b/spec/poundpay_spec.rb
index b141d80..d7a7f91 100644
--- a/spec/poundpay_spec.rb
+++ b/spec/poundpay_spec.rb
@@ -60,8 +60,7 @@
it "should configure callback_url" do
callback_url = "http://awesomemarketplace.com/payments/callback"
@developer = Poundpay::Developer.new
- @developer.should_receive(:save!)
- Poundpay::Developer.should_receive(:me).and_return(@developer)
+ Poundpay::Developer.should_receive(:new).and_return(@developer)
Poundpay.configure("DV0383d447360511e0bbac00264a09ff3c", "c31155b9f944d7aed204bdb2a253fef13b4fdcc6ae1540200449cc4526b2381a") do |c|
c.callback_url = callback_url
end
@@ -120,8 +119,7 @@
config = @config["production"]
config["callback_url"] = "http://awesomemarketplace.com/payments/callback"
@developer = Poundpay::Developer.new
- @developer.should_receive(:save!)
- Poundpay::Developer.should_receive(:me).and_return(@developer)
+ Poundpay::Developer.should_receive(:new).and_return(@developer)
Poundpay.configure_from_hash config
@developer.callback_url.should == config["callback_url"]
end
@@ -143,4 +141,4 @@
Poundpay::Resource.password.should == nil
end
end
-end
\ No newline at end of file
+end