Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

Loading…

Don't call out to the poundpay api when a callback_url is specified #4

Open
wants to merge 25 commits into from

6 participants

Alex Sharp Justin Smestad Brian Racer Jareau Wade Brian Moseley Mahmoud Abdelkader
Alex Sharp

There are a number of problems with doing this, forcing an external API call in the test environment being one of them. Another issue I ran into was not being able to load the console without an active network/internet connection because ActiveSupport raises an unrescued error.

If all this is doing is registering the callback_url with the poundpay servers, this certainly isn't something that needs to be done every time an application is loaded.

Justin Smestad

any update on pulling this in?

jsmestad and others added some commits
Justin Smestad jsmestad Resolve deprecation warning for `attr_accessor_with_default` by using…
… Ruby only.
23dbfbd
Brian Racer anveo allow erb in poundpay.yml fe46dbd
Alex Sharp ajsharp Merge pull request #1 from anveo/master
erb in poundpay.yml
0db9d30
Andrew partial release 3234f01
Andrew changes for consistency 1bd49de
Andrew doc update e873040
Andrew User resource is 2 lines! e2b3192
Jareau Wade jkwade updatd the ruby client readme doc to show kitchit how to create a user de95e33
Jareau Wade jkwade updated gemfile version number 8cd0f84
Andrew - revert partial release
- add charge permissions
- add developer charge permission callback url
f30f936
Brian Moseley bcm make response data available from Active Resource exceptions
this monkey patches Active Resource to make the exception's response body
available as a hash parsed from the original JSON. eventually a more general
version of this patch should be applied to Active Resource directly.
50692bf
Mahmoud Abdelkader mahmoudimus added `authorize` method to the ruby client and fleshed a full fledge…
…d simple marketplace app
dbd7628
Mahmoud Abdelkader mahmoudimus migrate config back to sandbox ee2d463
Mahmoud Abdelkader mahmoudimus bump version to 0.3 9fc085b
Mahmoud Abdelkader mahmoudimus update documentation 6effc8c
Mahmoud Abdelkader mahmoudimus fix issue with Poundpay::Payment.authorize method, add two tests, bum…
…p version
bd3ceb6
Andrew submod fe 80b8764
Andrew batching d4cd6f8
Andrew . 5f8453f
Andrew update doc 1e29b27
Andrew remove old fe 8d21618
Andrew add new fe 56f98db
Andrew - change payment field status to state
- change payment state STAGED to CREATED
022d881
Justin Smestad jsmestad update gemspec to allow 3.1 d8d453f
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Commits on May 11, 2011
  1. Alex Sharp
Commits on Nov 15, 2011
  1. Justin Smestad
Commits on Jan 18, 2012
  1. Brian Racer

    allow erb in poundpay.yml

    anveo authored
  2. Alex Sharp

    Merge pull request #1 from anveo/master

    ajsharp authored
    erb in poundpay.yml
Commits on Feb 1, 2012
  1. Alex Sharp

    partial release

    Andrew authored ajsharp committed
  2. Alex Sharp

    changes for consistency

    Andrew authored ajsharp committed
  3. Alex Sharp

    doc update

    Andrew authored ajsharp committed
  4. Alex Sharp

    User resource is 2 lines!

    Andrew authored ajsharp committed
  5. Jareau Wade Alex Sharp
  6. Jareau Wade Alex Sharp

    updated gemfile version number

    jkwade authored ajsharp committed
  7. Alex Sharp

    - revert partial release

    Andrew authored ajsharp committed
    - add charge permissions
    - add developer charge permission callback url
  8. Brian Moseley Alex Sharp

    make response data available from Active Resource exceptions

    bcm authored ajsharp committed
    this monkey patches Active Resource to make the exception's response body
    available as a hash parsed from the original JSON. eventually a more general
    version of this patch should be applied to Active Resource directly.
  9. Mahmoud Abdelkader Alex Sharp

    added `authorize` method to the ruby client and fleshed a full fledge…

    mahmoudimus authored ajsharp committed
    …d simple marketplace app
  10. Mahmoud Abdelkader Alex Sharp

    migrate config back to sandbox

    mahmoudimus authored ajsharp committed
  11. Mahmoud Abdelkader Alex Sharp

    bump version to 0.3

    mahmoudimus authored ajsharp committed
  12. Mahmoud Abdelkader Alex Sharp

    update documentation

    mahmoudimus authored ajsharp committed
  13. Mahmoud Abdelkader Alex Sharp

    fix issue with Poundpay::Payment.authorize method, add two tests, bum…

    mahmoudimus authored ajsharp committed
    …p version
  14. Alex Sharp

    submod fe

    Andrew authored ajsharp committed
  15. Alex Sharp

    batching

    Andrew authored ajsharp committed
  16. Alex Sharp

    .

    Andrew authored ajsharp committed
  17. Alex Sharp

    update doc

    Andrew authored ajsharp committed
  18. Alex Sharp

    remove old fe

    Andrew authored ajsharp committed
  19. Alex Sharp

    add new fe

    Andrew authored ajsharp committed
  20. Alex Sharp

    - change payment field status to state

    Andrew authored ajsharp committed
    - change payment state STAGED to CREATED
Commits on Feb 20, 2012
  1. Justin Smestad

    update gemspec to allow 3.1

    jsmestad authored
This page is out of date. Refresh to see the latest.
Showing with 719 additions and 164 deletions.
  1. +3 −0  .gitignore
  2. +3 −0  .gitmodules
  3. +128 −5 README.rdoc
  4. 0  examples/{simple_application → marketplace}/.gems
  5. +1 −1  examples/{simple_application → marketplace}/.rvmrc
  6. 0  examples/{simple_application → marketplace}/README
  7. +181 −0 examples/marketplace/application.rb
  8. +20 −0 examples/marketplace/config.rb
  9. +20 −0 examples/marketplace/config.ru
  10. +1 −0  examples/marketplace/fe
  11. +129 −0 examples/marketplace/index.html.erb
  12. +0 −65 examples/simple_application/application.rb
  13. +0 −11 examples/simple_application/config.rb
  14. +0 −6 examples/simple_application/config.ru
  15. +0 −18 examples/simple_application/index.html.erb
  16. +4 −4 lib/poundpay.rb
  17. +59 −12 lib/poundpay/elements.rb
  18. +10 −0 lib/poundpay/exceptions.rb
  19. +2 −2 lib/poundpay/rails.rb
  20. +22 −6 lib/poundpay/resource.rb
  21. +1 −1  lib/poundpay/version.rb
  22. +1 −1  poundpay.gemspec
  23. +24 −0 spec/fixtures/charge_permissions.rb
  24. +11 −11 spec/fixtures/payments.rb
  25. +1 −1  spec/fixtures/poundpay.yml
  26. +74 −15 spec/poundpay/elements_spec.rb
  27. +11 −0 spec/poundpay/exceptions_spec.rb
  28. +10 −0 spec/poundpay/resource_spec.rb
  29. +3 −5 spec/poundpay_spec.rb
3  .gitignore
View
@@ -1,3 +1,6 @@
pkg/
Gemfile.lock
*.gem
+.project
+.idea
+.bundle
3  .gitmodules
View
@@ -0,0 +1,3 @@
+[submodule "examples/marketplace/fe"]
+ path = examples/marketplace/fe
+ url = git@github.com:PoundPay/simplefe.git
133 README.rdoc
View
@@ -7,7 +7,7 @@ Poundpay is a payments platform for marketplaces
1. Add the following to your Gemfile
- gem 'poundpay', '~> 0.2.0'
+ gem 'poundpay', '~> 0.3.1'
2. At the command prompt, install the gem with bundler
@@ -35,6 +35,13 @@ Poundpay is a payments platform for marketplaces
before_filter :verify_poundpay_callback
+== Creating a user
+
+ @user = Poundpay::User.create(
+ :first_name => "Dart",
+ :last_name => "Master",
+ :email_address => "dart-master@example.com")
+
== Creating a payment
@@ -47,7 +54,7 @@ Poundpay is a payments platform for marketplaces
:description => "Beats by Dr. Dre")
-== Serving IFRAME
+== Serving the payment IFRAME
<script src="https://www.poundpay.com/js/poundpay.js"></script>
@@ -79,6 +86,122 @@ Poundpay is a payments platform for marketplaces
== Payment methods
payment = Poundpay::Payment.find(payment_sid)
- payment.escrow # AUTHORIZED -> ESCROWED. Credit card is charged
- payment.release # ESCROWED -> RELEASED. Recipient receives money
- payment.cancel # ESCROWED -> CANCELED. Payer receives refund
+ payment.escrow # AUTHORIZED -> ESCROWED. Credit card is charged
+ payment.release # ESCROWED or PARTIALLY_RELEASED -> RELEASED. Recipient receives money
+ payment.cancel # ESCROWED or PARTIALLY_RELEASED -> CANCELED. Payer receives refund
+ Poundpay::Payment.batch_update # Batch update a list of payments.
+
+
+== Creating a charge permission
+
+ @charge_permission = Poundpay::ChargePermission.create(
+ :email_address => "fred@example.com")
+
+
+== Serving the charge permission IFRAME
+
+ <script src="https://www.poundpay.com/js/poundpay.js"></script>
+
+ <div id="pound-root"></div>
+
+ <script>
+ function handleChargePermissionSuccess() {
+ // do something
+ }
+
+ function handleChargePermissionError() {
+ // handle error
+ }
+
+ PoundPay.init({
+ charge_permission_sid: "<%= @charge_permission.sid %>",
+ success: handleChargePermissionSuccess,
+ error: handleChargePermissionError,
+ name: "Fred Nietzsche", // Optional
+ address_street: "330 Townsend St", // Optional
+ address_city: "San Francisco", // Optional
+ address_state: "California", // Optional
+ address_zip: "94107", // Optional
+ server: "<%= Poundpay.www_url %>"
+ });
+ </script>
+
+
+== Charge permission methods
+
+ charge_permission = Poundpay::ChargePermission.find(charge_permission_sid)
+ charge_permission.deactivate # CREATED or ACTIVE -> INACTIVE. Charge permission is deactivated and can no longer be used to authorize payments for the associated payer.
+
+
+== Batching
+
+In some cases you may wish to batch authorize and escrow a collection of
+payments. By doing so there will be only *one* payer charge for that collection
+of payments. Note that if you do batch authorize a collection of payments that
+it must *also* be batch escrowed.
+
+Batching is designed for shopping carts where you want a collection of payments
+to appear to appear as a single charge.
+
+In order to use batching you simply need to pass `sids` for *all* payments in
+the collection you want to batch to the IFrame
+
+ <script src="https://www.poundpay.com/js/poundpay.js"></script>
+
+ <div id="pound-root"></div>
+
+ <script>
+ function handlePaymentSuccess() {
+ // do something
+ }
+
+ function handlePaymentError() {
+ // handle error
+ }
+
+ PoundPay.init({
+ payment_sid: [
+ "<%= @payment1.sid %>"
+ "<%= @payment2.sid %>",
+ "<%= @payment3.sid %>"
+ ],
+ success: handlePaymentSuccess,
+ error: handlePaymentError,
+ first_name: "Fred", // Optional
+ last_name: "Nietzsche", // Optional
+ address_street: "990 Guerrero St", // Optional
+ address_city: "San Francisco", // Optional
+ address_state: "California", // Optional
+ address_zip: "94110", // Optional
+ server: "https://www-sandbox.poundpay.com" // Exclude for production
+ });
+ </script>
+
+Alternatively if you are directly authorizing the payments using a charge
+permission
+
+ Poundpay::Payment.batch_update(
+ :sid => [payment1.sid, payment2.sid, payment3.sid],
+ :status => 'AUTHORIZED')
+
+Finally you'll need to batch escrow the payments
+
+ Poundpay::Payment.batch_update(
+ :sid => [payment1.sid, payment2.sid, payment3.sid],
+ :status => 'ESCROWED')
+
+Notice that if you did the following instead an error would be triggered since
+batched payments *must* be authorized and escrowed collectively
+
+ payment = Poundpay::Payment.find(payment1_sid)
+ payment.escrow # fails
+
+However if you cancel some of the payments prior to batch escrow you should
+exclude them from the batch call
+
+ payment1 = Poundpay::Payment.find(payment1_sid)
+ payment1.cancel # ok
+
+ Poundpay::Payment.batch_update(
+ :sid => [payment2.sid, payment3.sid],
+ :status => 'ESCROWED')
0  examples/simple_application/.gems → examples/marketplace/.gems
View
File renamed without changes
2  examples/simple_application/.rvmrc → examples/marketplace/.rvmrc
View
@@ -1,3 +1,3 @@
# echo 'Switching rvm gemset ...'
-rvm use --create --install 1.9.1@poundpay-simple_application >& /dev/null
+rvm use --create --install 1.9.2@poundpay-simple_application >& /dev/null
# rvm gemset import >& /dev/null
0  examples/simple_application/README → examples/marketplace/README
View
File renamed without changes
181 examples/marketplace/application.rb
View
@@ -0,0 +1,181 @@
+require 'pp'
+require 'poundpay'
+
+require './config'
+
+
+class SimpleController
+ attr_reader :poundpay_client
+
+ def initialize
+ if Poundpay.configured?
+ return
+ end
+ config = SimpleApplication::CONFIG[:poundpay]
+ puts config
+ Poundpay.configure_from_hash(config)
+ end
+
+ def return_404
+ response = Rack::Response.new(["Page Not Found"], 404, {"Content-Type" => "text/plain"})
+ response.finish
+ end
+
+end
+
+class Index < SimpleController
+
+ def call env
+ request = Rack::Request.new(env)
+ unless request.path == '/' and request.get?
+ return return_404
+ end
+ # Create payment request
+ payment = SimpleApplication::CONFIG[:default_payment]
+ # Render and return page
+ www_poundpay_url = Poundpay.www_url
+ template = ERB.new(open("index.html.erb").read)
+ page = template.result(binding)
+ response = Rack::Response.new([page], 200, {"Content-Type" => "text/html"})
+ response.finish
+ end
+
+end
+
+class Payment < SimpleController
+
+ def call env
+ request = Rack::Request.new(env)
+ return_value, mime_type = case request.path.gsub(/\/$/, '') # trim trailing /
+ when '/payment' then request.post? ? create(request) : [nil, nil]
+ when '/payment/release' then request.post? ? release(request) : [nil, nil]
+ when '/payment/authorize' then request.post? ? authorize(request) : [nil, nil]
+ when '/payment/cancel' then request.post? ? cancel(request) : [nil, nil]
+ when '/payment/escrow' then request.post? ? escrow(request) : [nil, nil]
+ else nil
+ end
+
+ if return_value
+ response = Rack::Response.new([return_value], 201, {"Content-Type" => mime_type})
+ response.finish
+ else
+ return_404
+ end
+ end
+
+ def create request
+ payment = Poundpay::Payment.create(request.POST)
+ payment.include_root_in_json = false
+ return payment.to_json(), "application/json"
+ end
+
+ def authorize request
+ if request.POST['sid'].kind_of?(Array)
+ payments = Poundpay::Payment.batch_update(:sid => request.POST['sid'], :state => 'authorized')
+ payments = payments.collect! {|p| p.schema }
+ return PP.pp(payments, ''), "text/html"
+ else
+ payment = Poundpay::Payment.find(request.POST['sid'])
+ payment.authorize
+ payment.save
+ return PP.pp(payment.schema, ''), "text/html"
+ end
+ end
+
+ def release request
+ payment = Poundpay::Payment.find(request.POST['sid'])
+ payment.release
+ return PP.pp(payment.schema, ''), "text/html"
+ end
+
+ def cancel request
+ payment = Poundpay::Payment.find(request.POST['sid'])
+ payment.cancel
+ return PP.pp(payment.schema, ''), "text/html"
+ end
+
+ def escrow request
+ if request.POST['sid'].kind_of?(Array)
+ payments = Poundpay::Payment.batch_update(:sid => request.POST['sid'], :state => 'escrowed')
+ payments = payments.collect! {|p| p.schema }
+ return PP.pp(payments, ''), "text/html"
+ else
+ payment = Poundpay::Payment.find(request.POST['sid'])
+ payment.escrow
+ return PP.pp(payment.schema, ''), "text/html"
+ end
+ end
+
+end
+
+
+class User < SimpleController
+
+ def call env
+ request = Rack::Request.new(env)
+ return_value, mime_type = case request.path.gsub(/\/$/, '') # trim trailing /
+ when '/user' then request.post? ? create(request) : [nil, nil]
+ else [nil, nil]
+ end
+
+ if return_value
+ response = Rack::Response.new([return_value], 201, {"Content-Type" => mime_type})
+ response.finish
+ else
+ return_404
+ end
+ end
+
+ def create request
+ user = Poundpay::User.create({
+ :first_name => request.POST['user_first_name'],
+ :last_name => request.POST['user_last_name'],
+ :email_address => request.POST['user_email_address']
+ })
+ return PP.pp(user.schema, ''), "text/html"
+ end
+
+end
+
+
+class ChargePermission < SimpleController
+
+ def call env
+ request = Rack::Request.new(env)
+ return_value, mime_type = case request.path.gsub(/\/$/, '') # trim trailing /
+ when '/charge_permission' then request.post? ? create(request) : [nil, nil]
+ when '/charge_permission/find' then request.post? ? show(request) : [nil, nil]
+ when '/charge_permission/deactivate' then request.post? ? deactivate(request) : [nil, nil]
+ else [nil, nil]
+ end
+
+ if return_value
+ response = Rack::Response.new([return_value], 201, {"Content-Type" => mime_type})
+ response.finish
+ else
+ return_404
+ end
+ end
+
+ def create request
+ charge_permission = Poundpay::ChargePermission.create(request.POST)
+ charge_permission.include_root_in_json = false
+ return charge_permission.to_json(), "application/json"
+ end
+
+ def show request
+ charge_permissions = Poundpay::ChargePermission.find(:all, :params => { :email_address => request.POST['email_address'] })
+ if charge_permissions
+ return PP.pp(charge_permissions.map {|cp| cp.schema}, ''), 'text/plain'
+ else
+ return [nil, nil]
+ end
+ end
+
+ def deactivate request
+ charge_permission = Poundpay::ChargePermission.find(request.POST['sid'])
+ charge_permission.deactivate
+ return PP.pp(charge_permission.schema, ''), 'text/plain'
+ end
+
+end
20 examples/marketplace/config.rb
View
@@ -0,0 +1,20 @@
+class SimpleApplication
+ CONFIG = {
+ poundpay: {
+ "api_url" => "https://api-sandbox.poundpay.com",
+ "www_url" => "https://www-sandbox.poundpay.com",
+ "version" => "silver",
+ "developer_sid" => "DVxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
+ "auth_token" => "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
+ "callback_url" => '',
+ },
+ default_payment: {
+ "amount" => "67890",
+ "payer_fee_amount" => "100",
+ "recipient_fee_amount" => "200",
+ "payer_email_address" => "sam@example.com",
+ "recipient_email_address" => "jacob@example.net",
+ "description" => "this is a simple description that just loves developers, developers",
+ }
+ }
+end
20 examples/marketplace/config.ru
View
@@ -0,0 +1,20 @@
+# http://stackoverflow.com/questions/2900370/
+# why-does-ruby-1-9-2-remove-from-load-path-and-whats-the-alternative
+
+require 'rack'
+require 'rack/urlmap'
+
+use Rack::ShowExceptions
+use Rack::Lint
+use Rack::Static, :urls => ["/static"], :root => "fe"
+
+require './application'
+
+app = Rack::URLMap.new(
+ '/' => Index.new,
+ '/payment' => Payment.new,
+ '/charge_permission'=> ChargePermission.new,
+ '/user' => User.new,
+)
+
+run app
1  examples/marketplace/fe
@@ -0,0 +1 @@
+Subproject commit 6637c1c181355a53821cdac621090199ab756b8e
129 examples/marketplace/index.html.erb
View
@@ -0,0 +1,129 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf-8">
+ <meta name="description" content="Simple Marketplace">
+ <title>Simple MarketPlace</title>
+ <link rel="icon" href="static/favicon.ico" type="image/x-icon">
+ <link rel="stylesheet" href="static/css/simplemp.css">
+ <script src="static/js/jquery-1.6.1.js"></script>
+ <script src="static/js/jquery-ui-1.8.13.custom.min.js"></script>
+ <script src="<%= www_poundpay_url %>/js/poundpay.js"></script>
+ <script src="static/js/simplemp.js"></script>
+ </head>
+ <body>
+ <h1>Create charge permission</h1>
+ <table id="chargePermissionTable">
+ <tr>
+ <td>Email
+ <td><input type="text" class="text" id="email_address" value="<%= payment['payer_email_address'] %>">
+ </tr>
+ </table>
+ <a href="javascript:;" onclick="createChargePermission();">Create Charge Permission</a><br>
+ <a href="javascript:;" onclick="findChargePermission();">Find Charge Permission</a><br>
+ <pre id="find_charge_permission_results"></pre>
+
+ <h1>Display charge permission iframe</h1>
+ <table>
+ <tr>
+ <td>Charge permission id
+ <td><input type="text" class="text" id="charge_permission_id">
+ </tr>
+ <tr>
+ <td>Card holder name</td>
+ <td><input type="text" class="text" id="charge_permission_cardholder_name">
+ </tr>
+ <tr>
+ <td>server
+ <td><input type="text" class="text" id="charge_permission_server" value="<%= www_poundpay_url %>">
+ </tr>
+ </table>
+ <a href="javascript:;" onclick="deactivateChargePermission();">Deactivate Charge Permission</a><br>
+ <a href="javascript:;" onclick="startChargePermissionIFrame();">Start Charge Permission IFrame</a><br>
+ <div id="pound-pcp"></div>
+
+ <h1>Create payment</h1>
+ <table id="paymentsTable">
+ <tr>
+ <td>Payment Amount
+ <td><input type="text" class="text" id="amount" value="<%= payment['amount'] %>">
+ </tr>
+ <tr>
+ <td>Payer Fee</td>
+ <td><input type="text" class="text" id="payer_fee_amount" value="<%= payment['payer_fee_amount'] %>">
+ </tr>
+ <tr>
+ <td>Recipient Fee</td>
+ <td><input type="text" class="text" id="recipient_fee_amount" value="<%= payment['recipient_fee_amount'] %>">
+ </tr>
+ <tr>
+ <td>Payer Email</td>
+ <td><input type="text" class="text" id="payer_email_address" value="<%= payment['payer_email_address'] %>">
+ </tr>
+ <tr>
+ <td>Recipient Email</td>
+ <td><input type="text" class="text" id="recipient_email_address" value="<%= payment['recipient_email_address'] %>">
+ </tr>
+ <tr>
+ <td>Description</td>
+ <td><input type="text" class="text" id="description" value="<%= payment['description'] %>">
+ </tr>
+ </table>
+
+ <a href="javascript:;" onclick="createPayment();">Create Payment</a>
+
+ <h1>Display payment iframe</h1>
+ <table>
+ <tr>
+ <td>Payment request id</td>
+ <td><input type="text" class="text" id="payment_id">
+ </tr>
+ <tr>
+ <td>Card holder name</td>
+ <td><input type="text" class="text" id="cardholder_name">
+ </tr>
+ <tr>
+ <td>server</td>
+ <td><input type="text" class="text" id="server" value="<%= www_poundpay_url %>">
+ </tr>
+ </table>
+ <a href="javascript:;" onclick="startIFrame();">Start Payment IFrame</a>
+ <div id="pound-root"></div>
+ <h1 id="paymentComplete" style="display:none;color:green;">
+ Payment Complete
+ </h1>
+ <h1>Create User</h1>
+ <table id="create_user_table">
+ <tr>
+ <td>First Name</td>
+ <td><input type="text" class="text" id="user_first_name">
+ </tr>
+ <tr>
+ <td>Last Name</td>
+ <td><input type="text" class="text" id="user_last_name">
+ </tr>
+ <tr>
+ <td>Email Address</td>
+ <td><input type="text" class="text" id="user_email_address">
+ </tr>
+ </table>
+ <a href="javascript:;" onclick="createUser();">Create User</a>
+
+ <pre id="created_user_results"></pre>
+
+
+ <h1>Payment Operations</h1>
+ <table>
+ <tr>
+ <td>Payment SID
+ <td><input type="text" class="text" id="operating_payment_sid">
+ </tr>
+ </table>
+ <a href="javascript:;" onclick="authorizePayment();">Authorize Payment</a><br>
+ <a href="javascript:;" onclick="escrowPayment();">Escrow Payment</a><br>
+ <a href="javascript:;" onclick="releasePayment();">Release Payment</a><br>
+ <a href="javascript:;" onclick="cancelPayment();">Cancel Payment</a><br>
+
+ <pre id="operation_results"></pre>
+ </body>
+</html>
65 examples/simple_application/application.rb
View
@@ -1,65 +0,0 @@
-require 'uri'
-require 'net/http'
-require 'net/https'
-require 'json'
-require 'erb'
-
-require 'config'
-
-
-class PoundPay
- attr_reader :api_url, :version, :sid, :token
-
- def initialize(api_url, version, sid, token)
- @api_url = api_url
- @version = version
- @sid = sid
- @token = token
- end
-
- def post(endpoint, params)
- request_url = "#{@api_url}/#{@version}/#{endpoint}"
- puts request_url, params
- uri = URI.parse request_url
- http = Net::HTTP.new uri.host, uri.port
- http.use_ssl = true
- req = Net::HTTP::Post.new uri.request_uri
- req.set_form_data params
- req.basic_auth @sid, @token
- response = http.request req
- JSON.load response.body
- end
-end
-
-
-class SimpleApplication
- attr_reader :poundpay_client
-
- def initialize
- config = SimpleApplication::CONFIG[:poundpay]
- @poundpay_client = PoundPay.new(config[:api_url], config[:version], config[:sid], config[:token])
- end
-
- def call(env)
- unless env['REQUEST_PATH'] == '/' and env['REQUEST_METHOD'] == 'GET'
- return [404, {"Content-Type" => "text/plain"}, ["Page Not Found"]]
- end
- # Create payment request
- params = {
- 'amount' => 20000, # In USD cents
- 'payer_fee_amount' => 0,
- 'payer_email_address' => 'goliath@example.com',
- 'recipient_fee_amount' => 500,
- 'recipient_email_address' => 'david@example.com',
- 'description' => 'Beats by Dr. Dre',
- }
- payment = @poundpay_client.post 'payments', params
- puts payment
-
- # Render and return page
- www_poundpay_url = SimpleApplication::CONFIG[:poundpay][:www_url]
- template = ERB.new(open("index.html.erb").read)
- page = template.result(binding)
- [200, {"Content-Type" => "text/html"}, [page]]
- end
-end
11 examples/simple_application/config.rb
View
@@ -1,11 +0,0 @@
-class SimpleApplication
- CONFIG = {
- poundpay: {
- api_url: "https://api-sandbox.poundpay.com",
- www_url: "https://www-sandbox.poundpay.com",
- version: "silver",
- sid: "DVxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
- token: "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
- }
- }
-end
6 examples/simple_application/config.ru
View
@@ -1,6 +0,0 @@
-require 'application'
-
-use Rack::ShowExceptions
-use Rack::Lint
-
-run SimpleApplication.new
18 examples/simple_application/index.html.erb
View
@@ -1,18 +0,0 @@
-<html>
- <title>Simple Marketplace</title>
- <script src="<%= www_poundpay_url %>/js/poundpay.js"></script>
- <body>
- <h1>Simple Marketplace</h1>
- <h2><%= payment['description'] %></h2>
- <div id="pound-root"></div>
- <script type="text/javascript">
- PoundPay.init({
- // success: successCallback, // Optional js callback
- payment_sid: "<%= payment['sid'] %>",
- server: "<%= www_poundpay_url %>",
- cardholder_name: "David Stonethrower", // Optional
- phone_number: "6505551234" // Optional
- });
- </script>
- </body>
-</html>
8 lib/poundpay.rb
View
@@ -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
+end
71 lib/poundpay/elements.rb
View
@@ -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
+end
10 lib/poundpay/exceptions.rb
View
@@ -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
4 lib/poundpay/rails.rb
View
@@ -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
+end
28 lib/poundpay/resource.rb
View
@@ -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
2  lib/poundpay/version.rb
View
@@ -1,3 +1,3 @@
module Poundpay
- VERSION = "0.2.8"
+ VERSION = "0.4.0"
end
2  poundpay.gemspec
View
@@ -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")
24 spec/fixtures/charge_permissions.rb
View
@@ -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
22 spec/fixtures/payments.rb
View
@@ -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
+end
2  spec/fixtures/poundpay.yml
View
@@ -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
89 spec/poundpay/elements_spec.rb
View
@@ -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
+end
11 spec/poundpay/exceptions_spec.rb
View
@@ -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
10 spec/poundpay/resource_spec.rb
View
@@ -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
8 spec/poundpay_spec.rb
View
@@ -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
+end
Something went wrong with that request. Please try again.