payload-api 0.0.0 → 0.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: a3fb1c5560cf78f19c57bd89cdb1e13baf1ed62724aeaf79f8540063aef38ec1
4
- data.tar.gz: 118974f17c2e63757df0720945ef7c2bce8a8a306f4ae22dc88caf1745883d2e
3
+ metadata.gz: 0711e29f8e4a39b865cda04ddc414b3b34c38d8b9f9314f785410fb4f1346c7e
4
+ data.tar.gz: 04cfdc8927d2c47e16db1ceaf8aff90c54b8e87bb1cb57b6e4edc907755f44b6
5
5
  SHA512:
6
- metadata.gz: b3ff208b9b111d64cbb18807da8600bc4bb7dcb92b68746f21079eab95a3caf51fa089352530023a1ff4d7dc53352d3a9db68d77efba25d6b842d079fb6a73d0
7
- data.tar.gz: eebbf9fa92b613fe279f3d322a8694f322e73954c7743483a222fd82dc8c0baa9b97010ccfc6c9e7ba4d5db33ab2c23ec866c82ae23c875d377ef64337d63d1e
6
+ metadata.gz: e2f51ded017699686030ca7c8c4ab38ebcdbf3efd11f416a467c2aac5435b68b7935b9802429f2665338e2bc5e886aa0b3399d06a881ac3d89a382200e0a2ce4
7
+ data.tar.gz: 82c40295cc2a47068ad93cf7dcce41c1bdaef381fde723aefb07da4826d6d52a0284b45f343b9eb6cf07d1762481e0b8bfea380d760eec33bf3a2002a27019cc
data/README.md CHANGED
@@ -1,13 +1,13 @@
1
1
  # Payload RubyGem
2
2
 
3
- A RubyGem for interfacing with the Payload API
3
+ A RubyGem for integrating [Payload](https://payload.co).
4
4
 
5
5
  ## Installation
6
6
 
7
7
  To install using [Bundler](https://bundler.io):
8
8
 
9
9
  ```ruby
10
- gem 'place-api', '~> 0.5.5'
10
+ gem 'payload-api', '~> 0.1.0'
11
11
  ```
12
12
 
13
13
  To install using gem:
@@ -16,9 +16,81 @@ To install using gem:
16
16
  gem install payload
17
17
  ```
18
18
 
19
+ ## Get Started
19
20
 
20
- ## Basic usage
21
- Coming Soon
21
+ Once you've installed the Payload Python library to your environment,
22
+ import the `payload` module to get started. **Note:** We recommend
23
+ using the shorthand name of `pl` when importing.
24
+
25
+ ```python
26
+ import payload as pl
27
+ ```
28
+
29
+ ### API Authentication
30
+
31
+ To authenticate with the Payload API, you'll need a live or test API key. API
32
+ keys are accessible from within the Payload dashboard.
33
+
34
+ ```python
35
+ import payload as pl
36
+ pl.api_key = 'secret_key_3bW9JMZtPVDOfFNzwRdfE'
37
+ ```
38
+
39
+ ### Creating an Object
40
+
41
+ Interfacing with the Payload API is done primarily through Payload Objects. Below is an example of
42
+ creating a customer using the `Payload::Customer` object.
43
+
44
+
45
+ ```ruby
46
+ # Create a Customer
47
+ customer = Payload::Customer.create(
48
+ email: 'matt.perez@example.com',
49
+ full_name: 'Matt Perez'
50
+ )
51
+ ```
52
+
53
+
54
+ ```ruby
55
+ # Create a Payment
56
+ payment = Payload::Payment.create(
57
+ amount: 100.0,
58
+ payment_method: Payload::Card(
59
+ card_number: '4242 4242 4242 4242'
60
+ )
61
+ )
62
+ ```
63
+
64
+ ### Accessing Object Attributes
65
+
66
+ Object attributes are accessible through both dot and bracket notation.
67
+
68
+ ```ruby
69
+ customer.name
70
+ customer['name']
71
+ ```
72
+
73
+ ### Updating an Object
74
+
75
+ Updating an object is a simple call to the `update` object method.
76
+
77
+ ```ruby
78
+ # Updating a customer's email
79
+ customer.update( email: 'matt.perez@newwork.com' )
80
+ ```
81
+
82
+ ### Selecting Objects
83
+
84
+ Objects can be selected using any of their attributes.
85
+
86
+ ```ruby
87
+ # Select a customer by email
88
+ customers = Payload::Customer.filter_by(
89
+ email: 'matt.perez@example.com'
90
+ )
91
+ ```
22
92
 
23
93
  ## Documentation
24
- Read the [docs](https://docs.payload.co/?ruby)
94
+
95
+ To get further information on Payload's RubyGem and API capabilities,
96
+ visit the unabridged [Payload Documentation](https://docs.payload.co/?ruby).
@@ -1,6 +1,16 @@
1
- require "place/version"
1
+ require "payload/version"
2
+ require "payload/objects"
2
3
 
3
4
  module Payload
5
+ @URL = "https://api.payload.co"
6
+ @api_url = @URL
7
+ @api_key = nil
8
+
4
9
  class << self
10
+ attr_accessor :api_key, :api_url
11
+ end
12
+
13
+ def self.create(objects)
14
+ return Payload::ARMRequest.new().create(objects)
5
15
  end
6
16
  end
@@ -0,0 +1,85 @@
1
+ require "payload/arm/request"
2
+
3
+ module Payload
4
+ class ARMObject
5
+ @poly = nil
6
+ @data = nil
7
+ @@cache = {}
8
+
9
+ class << self
10
+ attr_reader :spec, :poly, :data
11
+ end
12
+
13
+ def initialize(data)
14
+ self.set_data(data)
15
+ end
16
+
17
+ def self.new(data)
18
+ if data.key?('id') and @@cache.key?(data['id'])
19
+ @@cache[data['id']].set_data(data)
20
+ return @@cache[data['id']]
21
+ else
22
+ inst = super
23
+ if data.key?('id') and not data['id'].nil? and not data['id'].empty?
24
+ @@cache[data['id']] = inst
25
+ end
26
+
27
+ return inst
28
+ end
29
+ end
30
+
31
+ def data
32
+ @data
33
+ end
34
+
35
+ def set_data(data)
36
+ @data = data
37
+ end
38
+
39
+ def method_missing(name, *args)
40
+ attr = name.to_s
41
+ if @data.key?(attr)
42
+ return @data[attr]
43
+ else
44
+ super
45
+ end
46
+ end
47
+
48
+ def [](key)
49
+ return @data[key]
50
+ end
51
+
52
+ def self.select(*args, **data)
53
+ return Payload::ARMRequest.new(self).select(*args, **data)
54
+ end
55
+
56
+ def self.filter_by(*args, **data)
57
+ return Payload::ARMRequest.new(self).filter_by(*args, **data)
58
+ end
59
+
60
+ def self.create(*args, **data)
61
+ if args.length != 0
62
+ return Payload::ARMRequest.new(self).create(args[0])
63
+ else
64
+ return Payload::ARMRequest.new(self).create(data)
65
+ end
66
+ end
67
+
68
+ def self.get(id)
69
+ return Payload::ARMRequest.new(self).get(id)
70
+ end
71
+
72
+ def self.delete(objects)
73
+ return Payload::ARMRequest.new(self).delete(objects)
74
+ end
75
+
76
+ def update(**update)
77
+ return Payload::ARMRequest.new(self.class)._request('Put', id: self.id, json: update)
78
+ end
79
+
80
+ def delete()
81
+ return Payload::ARMRequest.new(self.class)._request('Delete', id: self.id)
82
+ end
83
+ end
84
+ end
85
+
@@ -0,0 +1,145 @@
1
+ require "payload/exceptions"
2
+ require "payload/utils"
3
+ require "net/http"
4
+ require "uri"
5
+ require "json"
6
+
7
+ module Payload
8
+ class ARMRequest
9
+ @cls = nil
10
+
11
+ def initialize(cls=nil)
12
+ @cls = cls
13
+ @filters = {}
14
+ end
15
+
16
+ def select(*args, **data)
17
+ if @cls.poly
18
+ data = data.merge(@cls.poly)
19
+ end
20
+
21
+ return self
22
+ end
23
+
24
+ def filter_by(*args, **data)
25
+ if @cls.poly
26
+ data = data.merge(@cls.poly)
27
+ end
28
+
29
+ @filters = @filters.merge(data)
30
+
31
+ return self
32
+ end
33
+
34
+ def all()
35
+ return self._request('Get')
36
+ end
37
+
38
+ def get(id)
39
+ if id.nil? || id.empty?
40
+ throw 'id cannot be empty'
41
+ end
42
+
43
+ return self._request('Get', id: id)
44
+ end
45
+
46
+ def update(**updates)
47
+ return self.filter_by(mode: 'query')
48
+ ._request('Put', json: updates)
49
+ end
50
+
51
+ def delete(objects)
52
+ deletes = objects.map {|o| o.id }.join('|')
53
+ return self.filter_by(mode: 'query', id: deletes)
54
+ ._request('Delete')
55
+ end
56
+
57
+ def create(data)
58
+ if data.is_a? Array
59
+ data = data.map do |obj|
60
+ if obj.kind_of?(ARMObject)
61
+ if @cls and not obj.instance_of?(@cls)
62
+ throw "All objects must be of the same type"
63
+ end
64
+
65
+ @cls = obj.class
66
+ obj = obj.data
67
+ end
68
+
69
+ if @cls.poly
70
+ obj = obj.merge(@cls.poly)
71
+ end
72
+
73
+ obj
74
+ end
75
+
76
+ data = { object: 'list', values: data }
77
+ else
78
+ if @cls.poly
79
+ data = data.merge(@cls.poly)
80
+ end
81
+ end
82
+
83
+ return self._request('Post', json: data)
84
+ end
85
+
86
+ def _request(method, id: nil, json: nil)
87
+ if @cls.spec.key?("endpoint")
88
+ endpoint = @cls.spec["endpoint"]
89
+ else
90
+ endpoint = "/"+@cls.spec["object"]+"s"
91
+ end
92
+
93
+ if id
94
+ endpoint = File.join(endpoint, id)
95
+ end
96
+
97
+ url = URI.join(Payload::api_url, endpoint)
98
+ url.query = URI.encode_www_form(@filters)
99
+
100
+ http = Net::HTTP.new(url.host, url.port)
101
+
102
+ if url.port == 443
103
+ http.use_ssl = true
104
+ end
105
+
106
+ request = Net::HTTP.const_get(method).new(url.request_uri)
107
+ request.basic_auth(Payload::api_key, '')
108
+
109
+ if json
110
+ request.body = json.to_json
111
+ request.add_field('Content-Type', 'application/json')
112
+ end
113
+
114
+ response = http.request(request)
115
+
116
+ begin
117
+ data = JSON.parse(response.body)
118
+ rescue JSON::ParserError
119
+ if response.code == '500'
120
+ raise Payload::InternalError.new
121
+ else
122
+ raise Place::UnknownResponse.new
123
+ end
124
+ end
125
+
126
+ if response.code == '200'
127
+ if data['object'] == 'list'
128
+ return data['values'].map {|obj| Payload::get_cls(obj).new(obj) }
129
+ else
130
+ return Payload::get_cls(data).new(data)
131
+ end
132
+ else
133
+ for error in Payload::subclasses(Payload::PayloadError)
134
+ if error.code != response.code or error.name.split('::')[-1] != data['error_type']
135
+ next
136
+ end
137
+
138
+ raise error.new(data['description'], data)
139
+ end
140
+
141
+ raise Payload::BadRequest.new(data['description'], data)
142
+ end
143
+ end
144
+ end
145
+ end
@@ -0,0 +1,48 @@
1
+ module Payload
2
+ class PayloadError < StandardError
3
+ @code = nil
4
+ class << self
5
+ attr_reader :code
6
+ end
7
+
8
+ def initialize(msg, details = nil)
9
+ super(msg)
10
+ @details = details
11
+ end
12
+ end
13
+
14
+ class UnknownResponse < PayloadError
15
+ end
16
+
17
+ class BadRequest < PayloadError
18
+ @code='400'
19
+ end
20
+
21
+ class InvalidAttributes < PayloadError
22
+ @code='400'
23
+ end
24
+
25
+ class Unauthorized < PayloadError
26
+ @code='401'
27
+ end
28
+
29
+ class Forbidden < PayloadError
30
+ @code='403'
31
+ end
32
+
33
+ class NotFound < PayloadError
34
+ @code='404'
35
+ end
36
+
37
+ class TooManyRequests < PayloadError
38
+ @code='429'
39
+ end
40
+
41
+ class InternalServerError < PayloadError
42
+ @code='500'
43
+ end
44
+
45
+ class ServiceUnavailable < PayloadError
46
+ @code='503'
47
+ end
48
+ end
@@ -0,0 +1,79 @@
1
+ require "payload/arm/object"
2
+
3
+ module Payload
4
+ class Account < ARMObject
5
+ @spec = { 'object' => 'account' }
6
+ end
7
+
8
+ class Customer < ARMObject
9
+ @spec = { 'object' => 'account' }
10
+ @poly = { 'type' => 'customer' }
11
+ end
12
+
13
+ class ProcessingAccount < ARMObject
14
+ @spec = { 'object' => 'account' }
15
+ @poly = { 'type' => 'processing' }
16
+ end
17
+
18
+ class Org < ARMObject
19
+ @spec = { 'object' => 'org', 'endoint' => '/account/orgs' }
20
+ end
21
+
22
+ class Transaction < ARMObject
23
+ @spec = { 'object' => 'transaction' }
24
+ end
25
+
26
+ class Payment < ARMObject
27
+ @spec = { 'object' => 'transaction' }
28
+ @poly = { 'type' => 'payment' }
29
+ end
30
+
31
+ class Refund < ARMObject
32
+ @spec = { 'object' => 'transaction' }
33
+ @poly = { 'type' => 'refund' }
34
+ end
35
+
36
+ class Ledger < ARMObject
37
+ @spec = { 'object' => 'transaction_ledger' }
38
+ end
39
+
40
+ class PaymentMethod < ARMObject
41
+ @spec = { 'object' => 'payment_method' }
42
+ end
43
+
44
+ class Card < ARMObject
45
+ @spec = { 'object' => 'payment_method' }
46
+ @poly = { 'type' => 'card' }
47
+ end
48
+
49
+ class BankAccount < ARMObject
50
+ @spec = { 'object' => 'payment_method' }
51
+ @poly = { 'type' => 'bank_account' }
52
+ end
53
+
54
+ class BillingSchedule < ARMObject
55
+ @spec = { 'object' => 'billing_schedule' }
56
+ end
57
+
58
+ class BillingCharge < ARMObject
59
+ @spec = { 'object' => 'billing_charge' }
60
+ end
61
+
62
+ class Invoice < ARMObject
63
+ @spec = { 'object' => 'invoice' }
64
+ end
65
+
66
+ class LineItem < ARMObject
67
+ @spec = { 'object' => 'line_item' }
68
+ end
69
+
70
+ class ChargeItem < ARMObject
71
+ @spec = { 'object' => 'line_item' }
72
+ @poly = { 'type' => 'charge' }
73
+ end
74
+
75
+ class PaymentItem < ARMObject
76
+ @spec = { 'object' => 'line_item' }
77
+ @poly = { 'type' => 'payment' }
78
+ end
79
+ end
@@ -0,0 +1,38 @@
1
+ module Payload
2
+
3
+ def self.subclasses(super_cls)
4
+ ObjectSpace.each_object(Class).select { |cls| cls < super_cls }
5
+ end
6
+
7
+ def self.get_cls(data)
8
+ match = nil
9
+ for cls in subclasses(Payload::ARMObject)
10
+ if cls.spec['object'] != data['object']
11
+ next
12
+ end
13
+
14
+ if not cls.poly and not match
15
+ match = cls
16
+
17
+ elsif cls.poly
18
+
19
+ invalid = false
20
+ cls.poly.each do |key, value|
21
+ if data[key] != value
22
+ invalid = true
23
+ end
24
+ end
25
+
26
+ if invalid
27
+ next
28
+ end
29
+
30
+ match = cls
31
+ break
32
+ end
33
+ end
34
+
35
+ match
36
+ end
37
+
38
+ end
@@ -1,3 +1,3 @@
1
1
  module Payload
2
- VERSION = '0.0.0'
2
+ VERSION = '0.1.0'
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: payload-api
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.0
4
+ version: 0.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Payload
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-10-28 00:00:00.000000000 Z
11
+ date: 2019-05-05 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: A simple library to interface with the Payload API. See https://docs.payload.co
14
14
  for details.
@@ -20,6 +20,11 @@ files:
20
20
  - LICENSE
21
21
  - README.md
22
22
  - lib/payload.rb
23
+ - lib/payload/arm/object.rb
24
+ - lib/payload/arm/request.rb
25
+ - lib/payload/exceptions.rb
26
+ - lib/payload/objects.rb
27
+ - lib/payload/utils.rb
23
28
  - lib/payload/version.rb
24
29
  - payload.gemspec
25
30
  homepage: https://docs.payload.co
@@ -41,8 +46,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
41
46
  - !ruby/object:Gem::Version
42
47
  version: '0'
43
48
  requirements: []
44
- rubyforge_project:
45
- rubygems_version: 2.7.7
49
+ rubygems_version: 3.0.1
46
50
  signing_key:
47
51
  specification_version: 4
48
52
  summary: Payload ruby library