pin-payments 0.0.3 → 1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/README.md CHANGED
@@ -1,12 +1,6 @@
1
1
  ## pin-payments
2
2
 
3
- A wrapper for the [pin.net.au](https://pin.net.au/) [API](https://pin.net.au/docs/api). Available via [RubyGems](http://rubygems.org/gems/pin-payments):
4
-
5
- gem install pin-payments
6
-
7
- Extracted from [PayAus](http://www.payaus.com/). Still a bit rough around the edges.
8
-
9
- MIT licensed, contributions are very welcome!
3
+ A wrapper for the [pin.net.au](https://pin.net.au/) [API](https://pin.net.au/docs/api). MIT licensed.
10
4
 
11
5
  ## Usage
12
6
 
@@ -16,47 +10,104 @@ You'll need to create an account at [pin.net.au](https://pin.net.au/) first.
16
10
 
17
11
  ### Setup
18
12
 
19
- Create an initializer, eg. `pin.rb`:
13
+ Create an initializer, eg. `pin.rb`, using keys from Pin's [Your Account](https://dashboard.pin.net.au/account) page.
20
14
 
21
15
  ```ruby
22
- Pin::Base.setup ENV['PIN_SECRET_KEY'], ENV['PIN_ENV']
16
+ Pin.setup secret_key: 'PIN_SECRET_KEY', publishable_key: 'PIN_PUBLISHABLE_KEY', mode: :test
23
17
  ```
24
18
 
25
- You can get your secret key from Pin's [Your Account](https://dashboard.pin.net.au/account) page. The second argument should be "live" or "test" depending on which API you want to access.
19
+ The `mode` should be `:live` or `:test` depending on which API you want to access. The `publishable_key` is optional.
20
+
21
+ Alternatively, you could fetch keys from a YAML file, e.g. like this initializer:
22
+
23
+ ```ruby
24
+ pin_config_path = Rails.root.join 'config', 'pin.yml'
25
+ if File.exists?(pin_config_path)
26
+ configuration = YAML.load_file(pin_config_path)
27
+ raise "No environment configured for Pin for RAILS_ENV=#{Rails.env}" unless configuration[Rails.env]
28
+ Pin.setup configuration[Rails.env].symbolize_keys
29
+ end
30
+ ```
31
+
32
+ and then in `config/pin.yml`:
33
+
34
+ ```yaml
35
+ test:
36
+ secret_key: "TEST_API_SECRET"
37
+ publishable_key: "TEST_PUBLISHABLE_KEY"
38
+ mode: "test"
39
+
40
+ development:
41
+ secret_key: "TEST_API_SECRET"
42
+ publishable_key: "TEST_PUBLISHABLE_KEY"
43
+ mode: "test"
44
+
45
+ production:
46
+ secret_key: "LIVE_API_SECRET"
47
+ publishable_key: "LIVE_PUBLISHABLE_KEY"
48
+ mode: "live"
49
+ ```
50
+
51
+ This allows you to inject `pin.yml` at deployment time, so that the secret key can be kept separate from your codebase.
26
52
 
27
53
  ### Usage
28
54
 
29
- You'll probably want to create a form through which users can enter their details. [Pin's guide](https://pin.net.au/docs/guides/payment-forms) will step you through this.
55
+ You'll probably want to create a form through which users can enter their details. [Pin's guide](https://pin.net.au/docs/guides/payment-forms) will step you through this. The publishable key will be necessary and, if set, can be obtained by calling `Pin.publishable_key`. You can also ask the module for the path to the javascript for the configured mode:
56
+
57
+ ```erb
58
+ <%= javascript_include_tag Pin.js_url %>
59
+ ```
30
60
 
31
- Then, in your controller:
61
+ Creating a charge is simple. In your controller:
32
62
 
33
63
  ```ruby
34
64
  def create
35
- Pin::Charge.create email: 'alex@payaus.com', description: '1 month of service', amount: 19900,
65
+ Pin::Charge.create email: 'user@example.com', description: '1 year of service', amount: 10000,
36
66
  currency: 'AUD', ip_address: params[:ip_address], card_token: params[:card_token]
67
+
37
68
  redirect_to new_payment_path, notice: "Your credit card has been charged"
38
69
  end
39
70
  ```
40
71
 
41
- This will issue a once-off charge ([API](https://pin.net.au/docs/api/charges)). Alternatively, you may wish to create a customer. To do this, create a `Card` object first, then a corresponding `Customer` via the [API](https://pin.net.au/docs/api/customers).
72
+ This will issue a once-off charge ([API](https://pin.net.au/docs/api/charges)).
73
+
74
+ For a recurring charge, you may wish to create a customer record at Pin. To do this, either create a `Card` object first, then a corresponding `Customer` via the [API](https://pin.net.au/docs/api/customers); or use a `card_token` returned from `Pin.js` to create a customer. Note that in either case you may activate additional compliance provisions in Pin's [Terms & Conditions](https://pin.net.au/terms).
42
75
 
43
76
  ```ruby
44
- card = Pin::Card.new number: '5520000000000000', expiry_month: '12', expiry_year: '2014', cvc: '123',
45
- name: 'Roland Robot', address_line1: '42 Sevenoaks St', address_city: 'Lathlain', address_postcode: '6454', address_state: 'WA', address_country: 'Australia'
46
- customer = Pin::Customer.create 'alex@payaus.com', card # this contacts the API
47
- Pin::Charge.create email: 'alex@payaus.com', description: '1 month of service', amount: 19900,
48
- currency: 'AUD', ip_address: '203.192.1.172', customer: customer # shorthand for customer_token: customer.token
77
+ # this doesn't contact the API
78
+ card = Pin::Card.new number: '5520000000000000', expiry_month: '12', expiry_year: '2018', cvc: '123',
79
+ name: 'User Name', address_line1: 'GPO Box 1234', address_city: 'Melbourne', address_postcode: '3001', address_state: 'VIC', address_country: 'Australia'
80
+
81
+ # this contacts the API and returns a customer
82
+ customer = Pin::Customer.create 'user@example.com', card
83
+
84
+ # this contacts the API and returns a charge
85
+ Pin::Charge.create email: 'user@example.com', description: '1 year of service', amount: 10000,
86
+ currency: 'AUD', ip_address: '127.0.0.1', customer: customer # shorthand for customer_token: customer.token
49
87
  ```
50
88
 
51
89
  You can view your customers in the [Pin dashboard](https://dashboard.pin.net.au/test/customers). This lets you charge customers regularly without asking for their credit card details each time.
52
90
 
53
91
  ```ruby
92
+ # get all customers from the API
54
93
  customers = Pin::Customer.all
55
- customer = customers.find {|c| c.email == user.email} # assume user is the user you are trying to charge
56
- Pin::Charge.create email: user.email, description: '1 month of service', amount: 19900, currency: 'AUD',
57
- ip_address: user.ip_address, customer: customer
94
+
95
+ # find the customer you are trying to charge, assuming `current_user` is defined elsewhere
96
+ customer = customers.find {|c| c.email == current_user.email}
97
+
98
+ # create a charge for the customer
99
+ # note that using this method you will need to store the `ip_address` of the user
100
+ # generally you can store this from when you initially created the customer (via Pin.js)
101
+ Pin::Charge.create email: user.email, description: '1 month of service', amount: 19900,
102
+ currency: 'AUD', ip_address: user.ip_address, customer: customer
58
103
  ```
59
104
 
60
- ## Credits
105
+ Errors from the API will result in a`Pin::APIError` exception being thrown:
61
106
 
62
- https://github.com/ghiculescu/pin-payments/graphs/contributors
107
+ ```ruby
108
+ begin
109
+ response = Pin::Charge.create( ... )
110
+ rescue Pin::APIError => e
111
+ redirect_to new_payment_path, flash: { error: "Charge failed: #{e.message}" }
112
+ end
113
+ ```
@@ -2,6 +2,51 @@ require 'httparty'
2
2
  require 'json'
3
3
 
4
4
  require 'pin-payments/base'
5
+ require 'pin-payments/response'
5
6
  require 'pin-payments/card'
6
7
  require 'pin-payments/charge'
7
- require 'pin-payments/customer'
8
+ require 'pin-payments/customer'
9
+ require 'pin-payments/refund'
10
+
11
+ module Pin
12
+ class Error < StandardError; end
13
+ class APIError < Error
14
+ attr_reader :code, :error, :description, :response
15
+
16
+ def initialize(response)
17
+ @code = response.code
18
+ @error = response['error']
19
+ @description = response['description']
20
+ @response = response
21
+ end
22
+
23
+ def to_s
24
+ "#@code #@error #@description"
25
+ end
26
+ end
27
+
28
+ class << self
29
+ attr_reader :publishable_key, :js_url, :auth
30
+
31
+ def setup(options)
32
+ raise ArgumentError, "Pin.setup wants an options hash" unless Hash === options
33
+ raise ArgumentError, "no secret key configured" unless options[:secret_key]
34
+ raise ArgumentError, "no mode configured" unless options[:mode]
35
+
36
+ @auth = {username: options[:secret_key], password: ''}
37
+ @publishable_key = options[:publishable_key]
38
+
39
+ mode = options[:mode].to_sym
40
+ uri = if mode == :live
41
+ "https://api.pin.net.au"
42
+ elsif mode == :test
43
+ "https://test-api.pin.net.au"
44
+ else
45
+ raise ArgumentError, "Incorrect API mode! Must be :live or :test"
46
+ end
47
+
48
+ @js_url = "#{uri}/pin.js"
49
+ Pin::Base.base_uri "#{uri}/1"
50
+ end
51
+ end
52
+ end
@@ -12,39 +12,75 @@ module Pin
12
12
  end
13
13
  end
14
14
 
15
- def self.setup(key, mode = :live)
16
- @@auth = {username: key, password: ''}
17
- mode = mode.to_sym
18
- uri = if mode == :test
19
- "https://test-api.pin.net.au/1"
20
- elsif mode == :live
21
- "https://api.pin.net.au/1"
22
- else
23
- raise "Incorrect API mode! Must be :live or :test (leave blank for :live)."
24
- end
25
- base_uri uri
26
- end
15
+ class << self
16
+
17
+ def create(options, path = api_path)
18
+ response = authenticated_post(path, options)
19
+ if response.code == 201 # object created
20
+ build_instance_from_response(response)
21
+ else
22
+ raise Pin::APIError.new(response)
23
+ end
24
+ end
25
+
26
+ def all(options = {})
27
+ options = {path: api_path, page: 1}.merge(options)
28
+ paging = "page=#{options[:page]}" unless options[:page] == 1
29
+ build_collection_from_response(authenticated_get(options[:path], paging))
30
+ end
31
+
32
+ def all_pages(options = {})
33
+ options = options.merge(path: api_path)
34
+ end
35
+
36
+ def first(options = {})
37
+ all(options).first
38
+ end
39
+ def last(options = {})
40
+ all(options).last
41
+ end
27
42
 
43
+ def find(token, options = {})
44
+ options = options.merge(path: api_path)
45
+ build_instance_from_response(authenticated_get("#{options[:path]}/#{token}"))
46
+ end
47
+
28
48
  protected
29
- def self.authenticated_post(url, body)
30
- post(url, body: body, basic_auth: @@auth)
31
- end
32
- def self.authenticated_get(url, query = nil)
33
- get(url, query: query, basic_auth: @@auth)
34
- end
49
+
50
+ def auth
51
+ Pin.auth
52
+ end
53
+
54
+ def api_path
55
+ short = if i = name.rindex('::')
56
+ name[(i+2)..-1]
57
+ else
58
+ name
59
+ end
60
+ "/#{short}s".downcase
61
+ end
62
+
63
+ def authenticated_post(url, body)
64
+ post(url, body: body, basic_auth: auth)
65
+ end
66
+ def authenticated_get(url, query = nil)
67
+ get(url, query: query, basic_auth: auth)
68
+ end
35
69
 
36
- def self.build_instance_from_response(response)
37
- new(response.parsed_response['response'])
38
- end
70
+ def build_instance_from_response(response)
71
+ new(response.parsed_response['response'])
72
+ end
39
73
 
40
- def self.build_collection_from_response(response)
41
- models = []
42
- if response.code == 200
43
- response.parsed_response['response'].each do |model|
44
- models << new(model)
74
+ def build_collection_from_response(response)
75
+ models = []
76
+ if response.code == 200
77
+ response.parsed_response['response'].each do |model|
78
+ models << new(model)
79
+ end
45
80
  end
81
+ pg = response.parsed_response['pagination']
82
+ CollectionResponse.new(models, pg['per_page'], pg['pages'], pg['current'])
46
83
  end
47
- models
48
84
  end
49
85
  end
50
86
  end
@@ -15,19 +15,15 @@ module Pin
15
15
  hash
16
16
  end
17
17
 
18
- # options should be a hash with the following keys:
19
- # :number, :expiry_month, :expiry_year, :cvc, :name, :address_line1,
20
- # :address_city, :address_postcode, :address_state, :address_country
21
- #
22
- # it can also have the following optional keys:
23
- # :address_line2
24
- def self.create(options = {})
25
- response = authenticated_post '/cards', options
26
- if response.code == 201 # card created
27
- build_instance_from_response(response)
28
- else
29
- # handle the error
30
- false
18
+ class << self
19
+ # options should be a hash with the following keys:
20
+ # :number, :expiry_month, :expiry_year, :cvc, :name, :address_line1,
21
+ # :address_city, :address_postcode, :address_state, :address_country
22
+ #
23
+ # it can also have the following optional keys:
24
+ # :address_line2
25
+ def create(options = {})
26
+ super(options)
31
27
  end
32
28
  end
33
29
  end
@@ -6,25 +6,33 @@ module Pin
6
6
  :amount_refunded, :total_fees, :merchant_entitlement, :refund_pending,
7
7
  :success, :status_message, :error_message, :transfer, :created_at
8
8
 
9
- # options should be a hash with the following params
10
- # email, description, amount, currency, ip_address are mandatory
11
- # identifier must be a hash, can take the forms
12
- # {card: <Pin::Card>}
13
- # {card_token: String<"...">}
14
- # {customer_token: String<"...">}
15
- # {customer: <Pin::Customer>}
16
- # eg. {email: 'alex@payaus.com', description: '1 month of PayAus', amount: 19900, currency: 'AUD', ip_address: '203.192.1.172', customer_token: 'asdf'}
17
- def self.create(options = {})
18
- options[:customer_token] = options.delete(:customer).token unless options[:customer].nil?
19
- build_instance_from_response(authenticated_post('/charges', options))
9
+ attr_accessor :refunds
10
+
11
+ class << self
12
+ # options should be a hash with the following params
13
+ # email, description, amount, currency, ip_address are mandatory
14
+ # identifier must be a hash, can take the forms
15
+ # {card: <Pin::Card>}
16
+ # {card_token: String<"...">}
17
+ # {customer_token: String<"...">}
18
+ # {customer: <Pin::Customer>}
19
+ # eg. {email: 'user@example.com', description: 'One month subscription', amount: 19900, currency: 'USD', ip_address: '192.0.0.1', customer_token: 'asdf'}
20
+ def create(options = {})
21
+ options[:customer_token] = options.delete(:customer).token unless options[:customer].nil?
22
+ super(options)
23
+ end
20
24
  end
21
25
 
22
- def self.all # TODO: pagination
23
- build_collection_from_response(authenticated_get('/charges'))
26
+ # find all refunds for the current Charge object
27
+ # returns a list of Refunds
28
+ def refunds
29
+ Refund.all(token)
24
30
  end
25
31
 
26
- def self.find(token)
27
- build_instance_from_response(authenticated_get("/charges/#{token}"))
32
+ # creates a refund for this Charge
33
+ # refunds the full amount of the charge by default, provide an amount in cents to override
34
+ def refund!(amnt = nil)
35
+ Refund.create(token, amnt)
28
36
  end
29
37
  end
30
38
  end
@@ -2,25 +2,19 @@ module Pin
2
2
  class Customer < Base
3
3
  attr_accessor :email, :created_at, :token, :card
4
4
 
5
- # email should be a string
6
- # card_or_token can be a Pin::Card object
7
- # or a card_token (as a string)
8
- def self.create(email, card_or_token)
9
- options = if card_or_token.respond_to?(:to_hash) # card
10
- {card: card_or_token.to_hash}
11
- else # token
12
- {card_token: card_or_token}
13
- end.merge(email: email)
5
+ class << self
6
+ # email should be a string
7
+ # card_or_token can be a Pin::Card object
8
+ # or a card_token (as a string)
9
+ def create(email, card_or_token)
10
+ options = if card_or_token.respond_to?(:to_hash) # card
11
+ {card: card_or_token.to_hash}
12
+ else # token
13
+ {card_token: card_or_token}
14
+ end.merge(email: email)
14
15
 
15
- build_instance_from_response(authenticated_post('/customers', options))
16
- end
17
-
18
- def self.all # TODO: pagination
19
- build_collection_from_response(authenticated_get('/customers'))
20
- end
21
-
22
- def self.find(token)
23
- build_instance_from_response(authenticated_get("/customers/#{token}"))
16
+ super(options)
17
+ end
24
18
  end
25
19
  end
26
20
  end
@@ -0,0 +1,40 @@
1
+ module Pin
2
+ class Refund < Base
3
+ attr_accessor :token,
4
+ :amount, :currency, :charge,
5
+ :success, :error_message, :created_at
6
+
7
+ class << self
8
+ # provide a charge object, or charge ID, and it will be refunded
9
+ # optionally provide an amount in cents, greater than equal to 100, to refund
10
+ # defaults to the full amount of the charge
11
+ def create(charge_or_charge_id, amount = nil)
12
+ raise "`amount` must be greater than or equal to 100" if !amount.nil? && amount < 100
13
+
14
+ super({amount: amount}, path_for(charge_or_charge_id))
15
+ end
16
+
17
+ def all(charge_or_charge_id)
18
+ super(path: path_for(charge_or_charge_id))
19
+ end
20
+
21
+ protected
22
+ def api_path
23
+ "charges/%s/refunds"
24
+ end
25
+
26
+ private
27
+ def path_for(charge_or_charge_id)
28
+ api_path % parse_charge_id(charge_or_charge_id)
29
+ end
30
+
31
+ def parse_charge_id(charge_or_charge_id)
32
+ if charge_or_charge_id.respond_to?(:token) # charge
33
+ charge_or_charge_id.token
34
+ else # already an ID
35
+ charge_or_charge_id
36
+ end
37
+ end
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,36 @@
1
+ module Pin
2
+ class CollectionResponse
3
+ attr_reader :collection, :page_count, :per_page, :page
4
+
5
+ def initialize(collection, per_page, page_count, current_page)
6
+ @collection = collection
7
+ @page_count = page_count
8
+ @per_page = per_page
9
+ @page = current_page
10
+ end
11
+
12
+ def first_page?
13
+ @page == 1
14
+ end
15
+
16
+ def last_page?
17
+ @page == @page_count
18
+ end
19
+
20
+ def next_page?
21
+ @page_count > 1 && !last_page?
22
+ end
23
+
24
+ def previous_page?
25
+ @page_count > 1 && !first_page?
26
+ end
27
+
28
+ def method_missing(meth, *args, &block)
29
+ if collection.respond_to?(meth)
30
+ collection.send(meth, *args, &block)
31
+ else
32
+ super
33
+ end
34
+ end
35
+ end
36
+ end
@@ -4,8 +4,8 @@ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
4
 
5
5
  Gem::Specification.new do |s|
6
6
  s.name = 'pin-payments'
7
- s.version = '0.0.3'
8
- s.date = '2013-07-26'
7
+ s.version = '1.0'
8
+ s.date = '2013-08-06'
9
9
  s.summary = "Pin Payments API wrapper"
10
10
  s.description = "A wrapper for the Pin Payments (https://pin.net.au/) API"
11
11
  s.authors = ["Alex Ghiculescu"]
@@ -20,6 +20,7 @@
20
20
  "pagination": {
21
21
  "current": 1,
22
22
  "per_page": 25,
23
+ "pages": 1,
23
24
  "count": 1
24
25
  }
25
26
  }
@@ -0,0 +1,26 @@
1
+ {
2
+ "response": {
3
+ "token": "ch_lfUYEBK14zotCTykezJkfg",
4
+ "success": true,
5
+ "amount": 400,
6
+ "currency": null,
7
+ "description": "test charge",
8
+ "email": "roland@pin.net.au",
9
+ "ip_address": "203.192.1.172",
10
+ "created_at": "2012-06-20T03:10:49Z",
11
+ "status_message": "Success!",
12
+ "error_message": null,
13
+ "card": {
14
+ "token": "card_nytGw7koRg23EEp9NTmz9w",
15
+ "display_number": "XXXX-XXXX-XXXX-0000",
16
+ "scheme": "master",
17
+ "address_line1": "42 Sevenoaks St",
18
+ "address_line2": null,
19
+ "address_city": "Lathlain",
20
+ "address_postcode": "6454",
21
+ "address_state": "WA",
22
+ "address_country": "Australia"
23
+ },
24
+ "transfer": null
25
+ }
26
+ }
@@ -0,0 +1,18 @@
1
+ {
2
+ "response": {
3
+ "token": "cus_XZg1ULpWaROQCOT5PdwLkQ",
4
+ "email": "roland@pin.net.au",
5
+ "created_at": "2012-06-22T06:27:33Z",
6
+ "card": {
7
+ "token": "card_nytGw7koRg23EEp9NTmz9w",
8
+ "display_number": "XXXX-XXXX-XXXX-0000",
9
+ "scheme": "master",
10
+ "address_line1": "42 Sevenoaks St",
11
+ "address_line2": null,
12
+ "address_city": "Lathlain",
13
+ "address_postcode": "6454",
14
+ "address_state": "WA",
15
+ "address_country": "Australia"
16
+ }
17
+ }
18
+ }
@@ -0,0 +1,12 @@
1
+ {
2
+ "response": {
3
+ "token": "rf_ERCQy--Ay6o-NKGiUVcKKA",
4
+ "success": null,
5
+ "amount": 400,
6
+ "currency": "AUD",
7
+ "charge": "ch_bZ3RhJnIUZ8HhfvH8CCvfA",
8
+ "created_at": "2012-10-27T13:00:00Z",
9
+ "error_message": null,
10
+ "status_message": "Pending"
11
+ }
12
+ }
@@ -0,0 +1,19 @@
1
+ {
2
+ "response": [
3
+ {
4
+ "token": "rf_ERCQy--Ay6o-NKGiUVcKKA",
5
+ "success": null,
6
+ "amount": 400,
7
+ "currency": "AUD",
8
+ "charge": "ch_bZ3RhJnIUZ8HhfvH8CCvfA",
9
+ "created_at": "2012-10-27T13:00:00Z",
10
+ "error_message": null,
11
+ "status_message": "Pending"
12
+ }
13
+ ],
14
+ "pagination": {
15
+ "current": 1,
16
+ "per_page": 25,
17
+ "count": 1
18
+ }
19
+ }
@@ -11,13 +11,14 @@ module TestHelper
11
11
  SECRET_KEY = ENV["PIN_SECRET_KEY"] || "fake_key"
12
12
  PIN_ENV = ENV["PIN_ENV"] || :test
13
13
 
14
- Pin::Base.setup SECRET_KEY, PIN_ENV
14
+ Pin.setup(secret_key: SECRET_KEY, mode: PIN_ENV)
15
15
 
16
16
  def get_file(filename)
17
17
  File.new(File.dirname(__FILE__) + "/stub_responses/" + filename)
18
18
  end
19
19
 
20
- def get_record_json(type, token = nil)
20
+ def get_record_json(type, new_record = false, token = nil)
21
+ type = "new_#{type.singularize}" if new_record
21
22
  if token.nil?
22
23
  get_file("#{type}.json")
23
24
  else
@@ -27,24 +28,20 @@ module TestHelper
27
28
 
28
29
  def mock_get(model_name, do_each = true)
29
30
  stub_request(:get, /#{model_name.downcase}$/).to_return(body: get_record_json(model_name.downcase.pluralize), status: 200, headers: {'Content-Type' => 'application/json; charset=utf-8'})
31
+ stub_request(:get, /#{model_name.downcase}\?page=[0-9]$/).to_return(body: get_record_json(model_name.downcase.pluralize), status: 200, headers: {'Content-Type' => 'application/json; charset=utf-8'})
30
32
  if do_each
31
33
  Pin.const_get(model_name.singularize).all.each do |record|
32
- stub_request(:get, /#{model_name.downcase}\/#{record.token}$/).to_return(body: get_record_json(model_name.downcase.singularize, record.token), status: 200, headers: {'Content-Type' => 'application/json; charset=utf-8'})
34
+ stub_request(:get, /#{model_name.downcase}\/#{record.token}$/).to_return(body: get_record_json(model_name.downcase.singularize, false, record.token), status: 200, headers: {'Content-Type' => 'application/json; charset=utf-8'})
33
35
  end
34
36
  end
35
37
  end
36
38
 
37
- def mock_post(model_name, do_each = true)
38
- stub_request(:post, /#{model_name.downcase}$/).to_return(body: get_record_json(model_name.downcase.pluralize), status: 201, headers: {'Content-Type' => 'application/json; charset=utf-8'})
39
- if do_each
40
- Pin.const_get(model_name.singularize).all.each do |record|
41
- stub_request(:post, /#{model_name.downcase}\/#{record.token}$/).to_return(body: get_record_json(model_name.downcase.singularize, record.token), status: 201, headers: {'Content-Type' => 'application/json; charset=utf-8'})
42
- end
43
- end
39
+ def mock_post(model_name)
40
+ stub_request(:post, /#{model_name.downcase}$/).to_return(body: get_record_json(model_name.downcase.pluralize, true), status: 201, headers: {'Content-Type' => 'application/json; charset=utf-8'})
44
41
  end
45
42
 
46
- def mock_api(model_name)
47
- mock_get(model_name)
43
+ def mock_api(model_name, do_each = true)
44
+ mock_get(model_name, do_each)
48
45
  mock_post(model_name)
49
46
  end
50
47
  end
@@ -4,7 +4,7 @@ class CardsTest < Test::Unit::TestCase
4
4
  include TestHelper
5
5
 
6
6
  def setup
7
- mock_post('Cards', false)
7
+ mock_post('Cards')
8
8
  end
9
9
 
10
10
  def test_create
@@ -4,7 +4,7 @@ class ChargesTest < Test::Unit::TestCase
4
4
  include TestHelper
5
5
 
6
6
  def setup
7
- mock_post('Cards', false)
7
+ mock_post('Cards')
8
8
  mock_api('Charges')
9
9
  mock_api('Customers')
10
10
  end
@@ -5,7 +5,7 @@ class CustomersTest < Test::Unit::TestCase
5
5
 
6
6
  def setup
7
7
  mock_api('Customers')
8
- mock_post('Cards', false)
8
+ mock_post('Cards')
9
9
  end
10
10
 
11
11
  def test_get_all # for some reason `test "get all" do` wasn't working...
@@ -17,6 +17,15 @@ class CustomersTest < Test::Unit::TestCase
17
17
  assert_not_nil customer
18
18
  end
19
19
 
20
+ def test_get_pages_of_customers
21
+ customers = Pin::Customer.all(page: 1)
22
+ assert_equal 1, customers.page
23
+
24
+ # TODO: mock this
25
+ #customers = Pin::Customer.all(page: 2)
26
+ #assert_equal 2, customers.page
27
+ end
28
+
20
29
  def test_create_customer_with_card
21
30
  card = Pin::Card.new number: '5520000000000000', expiry_month: '12', expiry_year: '2014', cvc: '123', name: 'Roland Robot', address_line1: '42 Sevenoaks St', address_city: 'Lathlain', address_postcode: '6454', address_state: 'WA', address_country: 'Australia'
22
31
 
@@ -0,0 +1,38 @@
1
+ require 'test_helper'
2
+
3
+ class RefundsTest < Test::Unit::TestCase
4
+ include TestHelper
5
+
6
+ def setup
7
+ mock_api('Charges')
8
+ mock_api('Refunds', false)
9
+ end
10
+
11
+ def test_get_all_with_charge
12
+ charge = Pin::Charge.first
13
+
14
+ refunds = Pin::Refund.all(charge)
15
+ assert_equal 1, refunds.length
16
+ end
17
+
18
+ def test_get_all_with_charge_token
19
+ charge = Pin::Charge.first
20
+
21
+ refunds = Pin::Refund.all(charge.token)
22
+ assert_equal 1, refunds.length
23
+ end
24
+
25
+ def test_get_refunds_as_charge_method
26
+ charge = Pin::Charge.first
27
+
28
+ refunds = charge.refunds
29
+ assert_equal 1, refunds.length
30
+ end
31
+
32
+ def test_create_refund
33
+ charge = Pin::Charge.first
34
+
35
+ refund = charge.refund!
36
+ assert_not_nil refund
37
+ end
38
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: pin-payments
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.3
4
+ version: '1.0'
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-07-26 00:00:00.000000000 Z
12
+ date: 2013-08-06 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: httparty
@@ -75,16 +75,23 @@ files:
75
75
  - lib/pin-payments/card.rb
76
76
  - lib/pin-payments/charge.rb
77
77
  - lib/pin-payments/customer.rb
78
+ - lib/pin-payments/refund.rb
79
+ - lib/pin-payments/response.rb
78
80
  - pin-payments.gemspec
79
- - test/stub_responses/cards.json
80
81
  - test/stub_responses/charges.json
81
82
  - test/stub_responses/customers.json
83
+ - test/stub_responses/new_card.json
84
+ - test/stub_responses/new_charge.json
85
+ - test/stub_responses/new_customer.json
86
+ - test/stub_responses/new_refund.json
82
87
  - test/stub_responses/records/charge-ch_lfUYEBK14zotCTykezJkfg.json
83
88
  - test/stub_responses/records/customer-cus_XZg1ULpWaROQCOT5PdwLkQ.json
89
+ - test/stub_responses/refunds.json
84
90
  - test/test_helper.rb
85
91
  - test/unit/cards_test.rb
86
92
  - test/unit/charges_test.rb
87
93
  - test/unit/customers_test.rb
94
+ - test/unit/refunds_test.rb
88
95
  homepage: https://github.com/ghiculescu/pin-payments
89
96
  licenses:
90
97
  - MIT
@@ -111,12 +118,17 @@ signing_key:
111
118
  specification_version: 3
112
119
  summary: Pin Payments API wrapper
113
120
  test_files:
114
- - test/stub_responses/cards.json
115
121
  - test/stub_responses/charges.json
116
122
  - test/stub_responses/customers.json
123
+ - test/stub_responses/new_card.json
124
+ - test/stub_responses/new_charge.json
125
+ - test/stub_responses/new_customer.json
126
+ - test/stub_responses/new_refund.json
117
127
  - test/stub_responses/records/charge-ch_lfUYEBK14zotCTykezJkfg.json
118
128
  - test/stub_responses/records/customer-cus_XZg1ULpWaROQCOT5PdwLkQ.json
129
+ - test/stub_responses/refunds.json
119
130
  - test/test_helper.rb
120
131
  - test/unit/cards_test.rb
121
132
  - test/unit/charges_test.rb
122
133
  - test/unit/customers_test.rb
134
+ - test/unit/refunds_test.rb