paypoint-blue 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +9 -0
- data/.travis.yml +3 -0
- data/.yardopts +1 -0
- data/Gemfile +4 -0
- data/LICENSE +22 -0
- data/README.md +71 -0
- data/Rakefile +8 -0
- data/bin/console +167 -0
- data/bin/setup +7 -0
- data/lib/paypoint/blue/api.rb +134 -0
- data/lib/paypoint/blue/base.rb +122 -0
- data/lib/paypoint/blue/body_extractor.rb +18 -0
- data/lib/paypoint/blue/error.rb +57 -0
- data/lib/paypoint/blue/faraday_runscope.rb +74 -0
- data/lib/paypoint/blue/hash_key_converter.rb +26 -0
- data/lib/paypoint/blue/hosted.rb +92 -0
- data/lib/paypoint/blue/payload_builder.rb +77 -0
- data/lib/paypoint/blue/raise_errors.rb +53 -0
- data/lib/paypoint/blue/utils.rb +51 -0
- data/lib/paypoint/blue/version.rb +5 -0
- data/lib/paypoint/blue.rb +24 -0
- data/paypoint-blue.gemspec +29 -0
- data/support/yard_ext.rb +13 -0
- metadata +152 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 9097aafc20b17695e989cce94618d414cb72d404
|
4
|
+
data.tar.gz: 7dfc8e09ba1b8268dfc7e357eb62b87ca8964d86
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: fa0c78e2028e56f6b876ba359a0090360975fee9432d6e87af6420d022069af5f01ce607d5d7f3bc4b46afad7a72bba970d5047b1224f7acd0cb5ac5de4c30f6
|
7
|
+
data.tar.gz: 9ae0701c9674f7b3b048f42d23ab68de6417bf14c11c8ebef486d220a46991115bebc961a90d449be04ece80f4ddd5ea1213b6fee58c469c1873072e53f538c0
|
data/.gitignore
ADDED
data/.travis.yml
ADDED
data/.yardopts
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
-e support/yard_ext.rb --tag "applies_defaults:Payload defaults this method will apply" --tag "api_url:API reference"
|
data/Gemfile
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2015 Laszlo Bacsi
|
4
|
+
Copyright (c) 2015 Drop and Collect Ltd
|
5
|
+
|
6
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
7
|
+
of this software and associated documentation files (the "Software"), to deal
|
8
|
+
in the Software without restriction, including without limitation the rights
|
9
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
10
|
+
copies of the Software, and to permit persons to whom the Software is
|
11
|
+
furnished to do so, subject to the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be included in
|
14
|
+
all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
17
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
18
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
19
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
20
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
21
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
22
|
+
THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,71 @@
|
|
1
|
+
# PayPoint::Blue
|
2
|
+
|
3
|
+
API client for PayPoint's 3rd generation PSP product a.k.a PayPoint Blue.
|
4
|
+
|
5
|
+
## Installation
|
6
|
+
|
7
|
+
Add this line to your application's Gemfile:
|
8
|
+
|
9
|
+
gem 'paypoint-blue'
|
10
|
+
|
11
|
+
And then execute:
|
12
|
+
|
13
|
+
$ bundle
|
14
|
+
|
15
|
+
Or install it yourself as:
|
16
|
+
|
17
|
+
$ gem install paypoint-blue
|
18
|
+
|
19
|
+
## Usage
|
20
|
+
|
21
|
+
Read the [documentation](http://www.rubydoc.info/gems/paypoint-blue).
|
22
|
+
|
23
|
+
Run `bin/console` to start an interactive prompt for a playgound where
|
24
|
+
you can experiment with the API. You will have a bunch of meaningful
|
25
|
+
defaults set and some helpers to use. Just call the `help` or `h` method
|
26
|
+
in the console to learn more about the different helpers.
|
27
|
+
|
28
|
+
### Example
|
29
|
+
|
30
|
+
# Endpoint can be the actual URL or one of :test or :live.
|
31
|
+
# Installation id and credentials default to these ENV vars if omitted.
|
32
|
+
blue = PayPoint::Blue.hosted_client(
|
33
|
+
endpoint: :test,
|
34
|
+
inst_id: ENV['BLUE_API_INSTALLATION'],
|
35
|
+
api_id: ENV['BLUE_API_ID'],
|
36
|
+
api_password: ENV['BLUE_API_PASSWORD'],
|
37
|
+
defaults: {
|
38
|
+
currency: "GBP",
|
39
|
+
return_url: "http://example.com/callback/return",
|
40
|
+
skin: "9001"
|
41
|
+
}
|
42
|
+
)
|
43
|
+
|
44
|
+
blue.ping # => true
|
45
|
+
|
46
|
+
result = blue.make_payment(
|
47
|
+
merchant_ref: "abcd-1234",
|
48
|
+
amount: "4.89",
|
49
|
+
customer_ref: "42",
|
50
|
+
customer_name: "Alice"
|
51
|
+
)
|
52
|
+
result.session_id # => "39ac..."
|
53
|
+
result.redirect_url # => "https://hosted.paypoint.net/..."
|
54
|
+
|
55
|
+
# The hosted product doesn't have this endpoint, but the client will delegate
|
56
|
+
# this request to an API client for the regular API product behind the scenes.
|
57
|
+
blue.transaction(transaction_id) # => { processing: { ... }, payment_method: { ... }, ... }
|
58
|
+
|
59
|
+
## Development
|
60
|
+
|
61
|
+
After checking out the repo, run `bin/setup` to install dependencies. Then, run `bin/console` for an interactive prompt that will allow you to experiment.
|
62
|
+
|
63
|
+
To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release` to create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
|
64
|
+
|
65
|
+
## Contributing
|
66
|
+
|
67
|
+
1. Fork it ( https://github.com/CPlus/paypoint-blue/fork )
|
68
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
69
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
70
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
71
|
+
5. Create a new Pull Request
|
data/Rakefile
ADDED
data/bin/console
ADDED
@@ -0,0 +1,167 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require "bundler/setup"
|
4
|
+
require "paypoint/blue"
|
5
|
+
|
6
|
+
def bold(text)
|
7
|
+
"\e[1m#{text}\e[0m"
|
8
|
+
end
|
9
|
+
|
10
|
+
def help
|
11
|
+
puts <<-EOS
|
12
|
+
#{bold "API client helpers"}
|
13
|
+
|
14
|
+
#{bold "blue"}(**api_options)
|
15
|
+
#{bold "blue_hosted"}(**api_options)
|
16
|
+
|
17
|
+
Create and memoize API clients with these two. Options are the same as for
|
18
|
+
PayPoint::Blue::Base#initialize, but default endpoint to :test.
|
19
|
+
|
20
|
+
Export BLUE_API_INSTALLATION, BLUE_API_ID, and BLUE_API_PASSWORD as environment
|
21
|
+
variables, and you won't have to pass them to the helpers. See direnv.net for
|
22
|
+
an easy way to do that.
|
23
|
+
|
24
|
+
It's recommended to use either logging or the Runscope integration to keep track
|
25
|
+
and inspect all the traffic. You may set the RUNSCOPE_BUCKET environment
|
26
|
+
variable to have the integration be turned on by default. Otherwise you only
|
27
|
+
have to provide the runscope option the first time you call one of the API
|
28
|
+
client helpers:
|
29
|
+
|
30
|
+
blue(runscope: 'bucket-key')
|
31
|
+
|
32
|
+
#{bold "Callback endpoints"}
|
33
|
+
|
34
|
+
#{bold "cb"}(id)
|
35
|
+
|
36
|
+
This is most useful when using the Runscope integration. The available ids are:
|
37
|
+
|
38
|
+
:preauth_proceed, :preauth_cancel, :preauth_suspend, :preauth_suspend_replay,
|
39
|
+
:postauth_proceed, :postauth_cancel, :empty
|
40
|
+
|
41
|
+
These will return mocky.io urls which return the proper response. Using the
|
42
|
+
Runscope integration you will see the requests PayPoint makes to these endpoints
|
43
|
+
in your bucket.
|
44
|
+
|
45
|
+
#{bold "callbacks"}()
|
46
|
+
|
47
|
+
Returns the callbacks section of the payload with all callbacks set to proceed.
|
48
|
+
|
49
|
+
#{bold "Credit/Debit cards helpers"}
|
50
|
+
|
51
|
+
#{bold "card"}(type: :mc, valid: true, threeDS: true)
|
52
|
+
|
53
|
+
Returns a credit/debit card number for testing. Possible options:
|
54
|
+
|
55
|
+
type: :mc_debit, :mc_credit, :visa_debit, :visa_credit
|
56
|
+
valid: true, false
|
57
|
+
threeDS: true, false, :unknown
|
58
|
+
EOS
|
59
|
+
end
|
60
|
+
alias :h :help
|
61
|
+
|
62
|
+
def blue_default_options
|
63
|
+
return_base = ENV['RUNSCOPE_BUCKET'] ? "https://#{RUNSCOPE_BUCKET}.runscope.net" : "http://bluedemo.dev"
|
64
|
+
{
|
65
|
+
runscope: ENV['RUNSCOPE_BUCKET'],
|
66
|
+
defaults: {
|
67
|
+
currency: 'GBP',
|
68
|
+
commerce_type: 'ECOM',
|
69
|
+
skin: ENV['BLUE_SKIN'],
|
70
|
+
return_url: "#{return_base}/callback/return",
|
71
|
+
restore_url: "#{return_base}/callback/restore",
|
72
|
+
pre_auth_callback: cb(:preauth_proceed),
|
73
|
+
post_auth_callback: cb(:postauth_proceed),
|
74
|
+
transaction_notification: cb(:empty),
|
75
|
+
expiry_notification: cb(:empty)
|
76
|
+
}
|
77
|
+
}
|
78
|
+
end
|
79
|
+
|
80
|
+
def blue(endpoint: :test, **options)
|
81
|
+
options = blue_default_options.merge(options)
|
82
|
+
$blue_api ||= PayPoint::Blue.api_client(endpoint: endpoint, **options)
|
83
|
+
end
|
84
|
+
|
85
|
+
def blue_hosted(endpoint: :test, **options)
|
86
|
+
options = blue_default_options.merge(options)
|
87
|
+
$blue_hosted ||= PayPoint::Blue.hosted_client(endpoint: endpoint, **options)
|
88
|
+
end
|
89
|
+
|
90
|
+
def cb(id)
|
91
|
+
{
|
92
|
+
preauth_proceed: "http://www.mocky.io/v2/550f10df3645066a0a2a420e",
|
93
|
+
preauth_cancel: "http://www.mocky.io/v2/550f10ec364506660a2a420f",
|
94
|
+
preauth_suspend: "http://www.mocky.io/v2/550f10ff364506670a2a4210",
|
95
|
+
preauth_suspend_replay: "http://www.mocky.io/v2/550f110a364506690a2a4211",
|
96
|
+
postauth_proceed: "http://www.mocky.io/v2/550f1159364506650a2a4212",
|
97
|
+
postauth_cancel: "http://www.mocky.io/v2/550f11633645066c0a2a4213",
|
98
|
+
empty: "http://www.mocky.io/v2/550f11723645066c0a2a4214"
|
99
|
+
}[id]
|
100
|
+
end
|
101
|
+
|
102
|
+
def callbacks
|
103
|
+
{
|
104
|
+
callbacks: {
|
105
|
+
preAuthCallback: { url: cb(:preauth_proceed), format: "REST_JSON" },
|
106
|
+
postAuthCallback: { url: cb(:postauth_proceed), format: "REST_JSON" },
|
107
|
+
transactionNotification: { url: cb(:empty), format: "REST_JSON" },
|
108
|
+
expiryNotification: { url: cb(:empty), format: "REST_JSON" }
|
109
|
+
}
|
110
|
+
}
|
111
|
+
end
|
112
|
+
|
113
|
+
def card(type: :mc_debit, valid: true, threeDS: true)
|
114
|
+
{
|
115
|
+
mc_debit: {
|
116
|
+
true => {
|
117
|
+
true => "9900000000005159",
|
118
|
+
false => "9900000000000010",
|
119
|
+
:unknown => "9900000000010258"
|
120
|
+
},
|
121
|
+
false => {
|
122
|
+
true => "9900000000005282",
|
123
|
+
false => "9900000000000168",
|
124
|
+
:unknown => "9900000000010407"
|
125
|
+
}
|
126
|
+
},
|
127
|
+
mc_credit: {
|
128
|
+
true => {
|
129
|
+
true => "9901000000005133",
|
130
|
+
false => "9901000000000019",
|
131
|
+
:unknown => "9901000000010257"
|
132
|
+
},
|
133
|
+
false => {
|
134
|
+
true => "9901000000005281",
|
135
|
+
false => "9901000000000167",
|
136
|
+
:unknown => "9901000000010406"
|
137
|
+
}
|
138
|
+
},
|
139
|
+
visa_debit: {
|
140
|
+
true => {
|
141
|
+
true => "9902000000005132",
|
142
|
+
false => "9902000000000018",
|
143
|
+
:unknown => "9902000000010256"
|
144
|
+
},
|
145
|
+
false => {
|
146
|
+
true => "9902000000005280",
|
147
|
+
false => "9902000000000166",
|
148
|
+
:unknown => "9902000000010405"
|
149
|
+
}
|
150
|
+
},
|
151
|
+
visa_credit: {
|
152
|
+
true => {
|
153
|
+
true => "9903000000005131",
|
154
|
+
false => "9903000000000017",
|
155
|
+
:unknown => "9903000000010255"
|
156
|
+
},
|
157
|
+
false => {
|
158
|
+
true => "9903000000005289",
|
159
|
+
false => "9903000000000165",
|
160
|
+
:unknown => "9903000000010404"
|
161
|
+
}
|
162
|
+
}
|
163
|
+
}[type][valid][threeDS]
|
164
|
+
end
|
165
|
+
|
166
|
+
require "irb"
|
167
|
+
IRB.start
|
data/bin/setup
ADDED
@@ -0,0 +1,134 @@
|
|
1
|
+
require "paypoint/blue/base"
|
2
|
+
|
3
|
+
# Client class for the API product.
|
4
|
+
class PayPoint::Blue::API < PayPoint::Blue::Base
|
5
|
+
|
6
|
+
ENDPOINTS = {
|
7
|
+
test: "https://api.mite.paypoint.net:2443/acceptor/rest",
|
8
|
+
live: "https://api.paypoint.net/acceptor/rest",
|
9
|
+
}.freeze
|
10
|
+
|
11
|
+
shortcut :merchant_ref, 'transaction.merchant_ref'
|
12
|
+
shortcut :amount, 'transaction.amount'
|
13
|
+
shortcut :currency, 'transaction.currency'
|
14
|
+
shortcut :commerce_type, 'transaction.commerce_type'
|
15
|
+
shortcut :customer_ref, 'customer.merchant_ref'
|
16
|
+
shortcut :customer_name, 'customer.display_name'
|
17
|
+
|
18
|
+
shortcut :pre_auth_callback, 'callbacks.pre_auth_callback.url'
|
19
|
+
shortcut :post_auth_callback, 'callbacks.post_auth_callback.url'
|
20
|
+
shortcut :transaction_notification, 'callbacks.transaction_notification.url'
|
21
|
+
shortcut :expiry_notification, 'callbacks.expiry_notification.url'
|
22
|
+
|
23
|
+
# Test connectivity
|
24
|
+
#
|
25
|
+
# @return [true,false]
|
26
|
+
def ping
|
27
|
+
client.get "transactions/ping"
|
28
|
+
true
|
29
|
+
rescue Faraday::ClientError
|
30
|
+
false
|
31
|
+
end
|
32
|
+
|
33
|
+
# Make a payment
|
34
|
+
#
|
35
|
+
# @api_url https://developer.paypoint.com/payments/docs/#payments/make_a_payment
|
36
|
+
#
|
37
|
+
# @applies_defaults
|
38
|
+
# +:currency+, +:commerce_type+, +:pre_auth_callback+,
|
39
|
+
# +:post_auth_callback+, +:transaction_notification+,
|
40
|
+
# +:expiry_notification+
|
41
|
+
#
|
42
|
+
# @param [Hash] payload the payload is made up of the keyword
|
43
|
+
# arguments passed to the method
|
44
|
+
#
|
45
|
+
# @return the API response
|
46
|
+
def make_payment(**payload)
|
47
|
+
payload = build_payload(payload,
|
48
|
+
defaults: %i[
|
49
|
+
currency commerce_type pre_auth_callback post_auth_callback
|
50
|
+
transaction_notification expiry_notification
|
51
|
+
]
|
52
|
+
)
|
53
|
+
client.post "transactions/#{inst_id}/payment", payload
|
54
|
+
end
|
55
|
+
|
56
|
+
# Submit an authorisation
|
57
|
+
#
|
58
|
+
# @api_url https://developer.paypoint.com/payments/docs/#payments/submit_an_authorisation
|
59
|
+
# @see #make_payment
|
60
|
+
#
|
61
|
+
# This is a convenience method which makes a payment with the
|
62
|
+
# transaction's +deferred+ value set to +true+.
|
63
|
+
#
|
64
|
+
# @param (see #make_payment)
|
65
|
+
#
|
66
|
+
# @return the API response
|
67
|
+
def submit_authorisation(**payload)
|
68
|
+
payload[:transaction] ||= {}
|
69
|
+
payload[:transaction][:deferred] = true
|
70
|
+
make_payment(**payload)
|
71
|
+
end
|
72
|
+
|
73
|
+
# Capture an authorisation
|
74
|
+
#
|
75
|
+
# @api_url https://developer.paypoint.com/payments/docs/#payments/capture_an_authorisation
|
76
|
+
#
|
77
|
+
# @applies_defaults +:commerce_type+
|
78
|
+
#
|
79
|
+
# @param [String] transaction_id the id of the previous transaction
|
80
|
+
# @param [Hash] payload the payload is made up of the keyword
|
81
|
+
# arguments passed to the method
|
82
|
+
#
|
83
|
+
# @return the API response
|
84
|
+
def capture_authorisation(transaction_id, **payload)
|
85
|
+
payload = build_payload(payload, defaults: %i[commerce_type])
|
86
|
+
client.post "transactions/#{inst_id}/#{transaction_id}/capture", payload
|
87
|
+
end
|
88
|
+
|
89
|
+
# Cancel an authorisation
|
90
|
+
#
|
91
|
+
# @api_url https://developer.paypoint.com/payments/docs/#payments/cancel_an_authorisation
|
92
|
+
#
|
93
|
+
# @applies_defaults +:commerce_type+
|
94
|
+
#
|
95
|
+
# @param (see #capture_authorisation)
|
96
|
+
#
|
97
|
+
# @return the API response
|
98
|
+
def cancel_authorisation(transaction_id, **payload)
|
99
|
+
payload = build_payload(payload, defaults: %i[commerce_type])
|
100
|
+
client.post "transactions/#{inst_id}/#{transaction_id}/cancel", payload
|
101
|
+
end
|
102
|
+
|
103
|
+
# Get transaction details
|
104
|
+
#
|
105
|
+
# @api_url https://developer.paypoint.com/payments/docs/#payments/request_a_previous_transaction
|
106
|
+
#
|
107
|
+
# @param [String] transaction_id the id of the transaction
|
108
|
+
#
|
109
|
+
# @return the API response
|
110
|
+
def transaction(transaction_id)
|
111
|
+
client.get "transactions/#{inst_id}/#{transaction_id}"
|
112
|
+
end
|
113
|
+
|
114
|
+
# Refund a payment
|
115
|
+
#
|
116
|
+
# @api_url https://developer.paypoint.com/payments/docs/#payments/refund_a_payment
|
117
|
+
#
|
118
|
+
# Without a payload this will refund the full amount. If you only want
|
119
|
+
# to refund a smaller amount, you will need to pass either the
|
120
|
+
# +amount+ or a +transaction+ hash as a keyword argument.
|
121
|
+
#
|
122
|
+
# @example Partial refund
|
123
|
+
# blue.refund_payment(txn_id, amount: '3.49') # assumes currency set as default
|
124
|
+
#
|
125
|
+
# @param (see #capture_authorisation)
|
126
|
+
#
|
127
|
+
# @return the API response
|
128
|
+
def refund_payment(transaction_id, **payload)
|
129
|
+
defaults = payload[:amount] || payload[:transaction] && payload[:transaction][:amount] ? %i[currency commerce_type] : []
|
130
|
+
payload = build_payload(payload, defaults: defaults)
|
131
|
+
client.post "transactions/#{inst_id}/#{transaction_id}/refund", payload
|
132
|
+
end
|
133
|
+
|
134
|
+
end
|
@@ -0,0 +1,122 @@
|
|
1
|
+
require "faraday"
|
2
|
+
require "faraday_middleware"
|
3
|
+
|
4
|
+
require "paypoint/blue/payload_builder"
|
5
|
+
require "paypoint/blue/body_extractor"
|
6
|
+
require "paypoint/blue/hash_key_converter"
|
7
|
+
require "paypoint/blue/raise_errors"
|
8
|
+
require "paypoint/blue/faraday_runscope"
|
9
|
+
|
10
|
+
module PayPoint
|
11
|
+
module Blue
|
12
|
+
|
13
|
+
# Abstract base class for the API clients. Takes care of
|
14
|
+
# initializing the Faraday client by setting up middlewares in the
|
15
|
+
# right order.
|
16
|
+
#
|
17
|
+
# The base class doesn't implement any of the API interface methods,
|
18
|
+
# but leaves that to the subclasses.
|
19
|
+
#
|
20
|
+
# @note All payloads expected by the API interface methods in the
|
21
|
+
# subclasses will be processed by {PayloadBuilder} and the
|
22
|
+
# {HashKeyConverter} middleware. Shortcuts will be moved to their
|
23
|
+
# proper paths, default values will be applied, and snakecase keys
|
24
|
+
# will be converted to camelcase.
|
25
|
+
#
|
26
|
+
# @abstract
|
27
|
+
class Base
|
28
|
+
|
29
|
+
include PayloadBuilder
|
30
|
+
|
31
|
+
# The Faraday client
|
32
|
+
attr_reader :client
|
33
|
+
|
34
|
+
# Creates a PayPoint Blue API client
|
35
|
+
#
|
36
|
+
# Options not listed here will be passed on to the Faraday client.
|
37
|
+
#
|
38
|
+
# @param endpoint +:test+, +:live+, or a string with the API
|
39
|
+
# endpoint URL
|
40
|
+
# @param inst_id the ID for your installation as provided by
|
41
|
+
# PayPoint
|
42
|
+
# @param api_id your API user ID
|
43
|
+
# @param api_password your API user password
|
44
|
+
#
|
45
|
+
# @option options [Hash] :defaults default payload values; see the
|
46
|
+
# documentation of the methods of {API} and {Hosted} for the
|
47
|
+
# payload keys that can have defaults
|
48
|
+
# @option options [true,false] :log whether to log requests and
|
49
|
+
# responses
|
50
|
+
# @option options [Logger] :logger a custom logger instance,
|
51
|
+
# implies +log: true+
|
52
|
+
# @option options [true,false] :raw whether to return the raw
|
53
|
+
# +Faraday::Response+ object instead of a parsed value
|
54
|
+
# @option options [String] :runscope when used, all traffic will
|
55
|
+
# pass through the provided {https://www.runscope.com/ Runscope}
|
56
|
+
# bucket, including notification callbacks
|
57
|
+
def initialize(endpoint:,
|
58
|
+
inst_id: ENV['BLUE_API_INSTALLATION'],
|
59
|
+
api_id: ENV['BLUE_API_ID'],
|
60
|
+
api_password: ENV['BLUE_API_PASSWORD'],
|
61
|
+
**options)
|
62
|
+
|
63
|
+
@endpoint = self.class.const_get('ENDPOINTS').fetch(endpoint, endpoint.to_s)
|
64
|
+
|
65
|
+
@inst_id = inst_id or raise ArgumentError, "missing inst_id"
|
66
|
+
@api_id = api_id or raise ArgumentError, "missing api_id"
|
67
|
+
@api_password = api_password or raise ArgumentError, "missing api_password"
|
68
|
+
|
69
|
+
options[:url] = @endpoint
|
70
|
+
@options = options
|
71
|
+
|
72
|
+
self.defaults = options.delete(:defaults)
|
73
|
+
|
74
|
+
@client = build_client
|
75
|
+
end
|
76
|
+
|
77
|
+
private
|
78
|
+
|
79
|
+
attr_reader :inst_id, :options
|
80
|
+
|
81
|
+
def client_options
|
82
|
+
options.select { |k,v| Faraday::ConnectionOptions.members.include?(k) }
|
83
|
+
end
|
84
|
+
|
85
|
+
def build_client
|
86
|
+
Faraday.new(client_options) do |f|
|
87
|
+
unless options[:raw]
|
88
|
+
# This extracts the body and discards all other data from the
|
89
|
+
# Faraday::Response object. It should be placed here before
|
90
|
+
# all response middlewares, so that it runs as the last one.
|
91
|
+
f.use PayPoint::Blue::BodyExtractor
|
92
|
+
end
|
93
|
+
|
94
|
+
f.use PayPoint::Blue::RaiseErrors
|
95
|
+
unless options[:raw]
|
96
|
+
f.response :mashify
|
97
|
+
f.use PayPoint::Blue::HashKeyConverter
|
98
|
+
end
|
99
|
+
f.response :dates
|
100
|
+
f.response :json, content_type: /\bjson$/
|
101
|
+
f.response :logger, options[:logger] if options[:logger] || options[:log]
|
102
|
+
|
103
|
+
# This sends all API traffic through Runscope, including
|
104
|
+
# notifications. It needs to be inserted here before the JSON
|
105
|
+
# request middleware so that it is able to transform
|
106
|
+
# notification URLs too.
|
107
|
+
if options[:runscope]
|
108
|
+
f.use FaradayRunscope, options[:runscope],
|
109
|
+
transform_paths: /\A(callbacks|session)\.\w+(Callback|Notification)\.url\Z/
|
110
|
+
end
|
111
|
+
|
112
|
+
f.request :basic_auth, @api_id, @api_password
|
113
|
+
f.request :json
|
114
|
+
|
115
|
+
f.adapter Faraday.default_adapter
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
end
|
120
|
+
|
121
|
+
end
|
122
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module PayPoint
|
2
|
+
module Blue
|
3
|
+
|
4
|
+
# Faraday middleware which extracts the body from the response
|
5
|
+
# object and returns with just that discarding all other meta
|
6
|
+
# information.
|
7
|
+
class BodyExtractor < Faraday::Middleware
|
8
|
+
|
9
|
+
# Extract and return just the body discarding everything else
|
10
|
+
def call(env)
|
11
|
+
response = @app.call(env)
|
12
|
+
response.env[:body]
|
13
|
+
end
|
14
|
+
|
15
|
+
end
|
16
|
+
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
module PayPoint
|
2
|
+
module Blue
|
3
|
+
|
4
|
+
# Abstract error base class
|
5
|
+
# @abstract
|
6
|
+
class Error < StandardError
|
7
|
+
|
8
|
+
# the response that caused the error
|
9
|
+
attr_reader :response
|
10
|
+
|
11
|
+
# the outcome code (e.g. +'V402'+)
|
12
|
+
attr_reader :code
|
13
|
+
|
14
|
+
# Initializes the error from the response object. It uses the
|
15
|
+
# outcome message from the response if set.
|
16
|
+
def initialize(response)
|
17
|
+
@response = response
|
18
|
+
|
19
|
+
if outcome
|
20
|
+
@code = outcome[:reason_code]
|
21
|
+
message = outcome[:reason_message]
|
22
|
+
else
|
23
|
+
message = "the server responded with status #{response[:status]}"
|
24
|
+
end
|
25
|
+
|
26
|
+
super(message)
|
27
|
+
end
|
28
|
+
|
29
|
+
private
|
30
|
+
|
31
|
+
def outcome
|
32
|
+
@outcome ||= response[:body].is_a?(Hash) && response[:body][:outcome]
|
33
|
+
end
|
34
|
+
|
35
|
+
# Generic client error class, also a base class for more specific
|
36
|
+
# types of errors
|
37
|
+
class Client < Error; end
|
38
|
+
|
39
|
+
# Specific error class for errors with a +'V'+ outcome code
|
40
|
+
class Validation < Error; end
|
41
|
+
|
42
|
+
# Specific error class for errors with an +'A'+ outcome code
|
43
|
+
class Auth < Error; end
|
44
|
+
|
45
|
+
# Specific error class for errors with a +'C'+ outcome code
|
46
|
+
class Cancelled < Error; end
|
47
|
+
|
48
|
+
# Specific error class for errors with a +'X'+ outcome code
|
49
|
+
class External < Error; end
|
50
|
+
|
51
|
+
# Specific error class for errors with an +'U'+ outcome code
|
52
|
+
class Suspended < Error; end
|
53
|
+
|
54
|
+
end
|
55
|
+
|
56
|
+
end
|
57
|
+
end
|
@@ -0,0 +1,74 @@
|
|
1
|
+
class FaradayRunscope < Faraday::Middleware
|
2
|
+
|
3
|
+
CUSTOM_PORT = "Runscope-Request-Port".freeze
|
4
|
+
|
5
|
+
def initialize(app, bucket, transform_paths: false)
|
6
|
+
super(app)
|
7
|
+
self.bucket = bucket
|
8
|
+
self.transform_paths = Array(transform_paths)
|
9
|
+
end
|
10
|
+
|
11
|
+
def call(env)
|
12
|
+
if env.url.port != env.url.default_port
|
13
|
+
env.request_headers[CUSTOM_PORT] = env.url.port.to_s
|
14
|
+
env.url.port = env.url.default_port
|
15
|
+
end
|
16
|
+
|
17
|
+
transform_url env.url
|
18
|
+
|
19
|
+
if transform_paths && env.body.respond_to?(:each_with_index)
|
20
|
+
transform_paths!(env.body)
|
21
|
+
end
|
22
|
+
|
23
|
+
@app.call env
|
24
|
+
end
|
25
|
+
|
26
|
+
protected
|
27
|
+
|
28
|
+
attr_accessor :bucket, :transform_paths
|
29
|
+
|
30
|
+
def transform_url(url)
|
31
|
+
if url.respond_to?(:host=)
|
32
|
+
url.host = runscope_host(url.host)
|
33
|
+
elsif url.is_a?(String)
|
34
|
+
uri = URI.parse(url)
|
35
|
+
uri.host = runscope_host(uri.host)
|
36
|
+
return uri.to_s
|
37
|
+
end
|
38
|
+
url
|
39
|
+
end
|
40
|
+
|
41
|
+
def runscope_host(host)
|
42
|
+
"#{host.tr('.', '-')}-#{bucket}.runscope.net"
|
43
|
+
end
|
44
|
+
|
45
|
+
def transform_paths!(enum, path=nil)
|
46
|
+
each_pair(enum) do |key, value|
|
47
|
+
key_path = path ? "#{path}.#{key}" : key.to_s
|
48
|
+
if value.respond_to?(:each_with_index)
|
49
|
+
transform_paths!(value, key_path)
|
50
|
+
elsif transform_path?(key_path)
|
51
|
+
enum[key] = transform_url(value)
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
def each_pair(enum)
|
57
|
+
if enum.respond_to?(:each_pair)
|
58
|
+
enum.each_pair do |key, value|
|
59
|
+
yield key, value
|
60
|
+
end
|
61
|
+
else
|
62
|
+
enum.each_with_index do |value, index|
|
63
|
+
yield index, value
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
def transform_path?(path)
|
69
|
+
transform_paths.any? do |path_to_transform|
|
70
|
+
path_to_transform === path
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
module PayPoint
|
2
|
+
module Blue
|
3
|
+
|
4
|
+
# Faraday middleware for converting hash keys in the request payload
|
5
|
+
# from snake_case to camelCase and the other way around in the
|
6
|
+
# response.
|
7
|
+
class HashKeyConverter < Faraday::Middleware
|
8
|
+
|
9
|
+
# Convert hash keys to camelCase in the request and to snake_case
|
10
|
+
# in the response
|
11
|
+
def call(env)
|
12
|
+
if env.body.is_a?(Enumerable)
|
13
|
+
env.body = Utils.camelcase_and_symbolize_keys(env.body)
|
14
|
+
end
|
15
|
+
|
16
|
+
@app.call(env).on_complete do |response_env|
|
17
|
+
if response_env.body.is_a?(Enumerable)
|
18
|
+
response_env.body = Utils.snakecase_and_symbolize_keys(response_env.body)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
end
|
24
|
+
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,92 @@
|
|
1
|
+
require "forwardable"
|
2
|
+
|
3
|
+
require "paypoint/blue/base"
|
4
|
+
|
5
|
+
# Client class for the Hosted product.
|
6
|
+
class PayPoint::Blue::Hosted < PayPoint::Blue::Base
|
7
|
+
|
8
|
+
ENDPOINTS = {
|
9
|
+
test: "https://hosted.mite.paypoint.net/hosted/rest",
|
10
|
+
live: "https://hosted.paypoint.net/hosted/rest"
|
11
|
+
}.freeze
|
12
|
+
|
13
|
+
shortcut :merchant_ref, 'transaction.merchant_reference'
|
14
|
+
shortcut :amount, 'transaction.money.amount.fixed'
|
15
|
+
shortcut :currency, 'transaction.money.currency'
|
16
|
+
shortcut :customer_ref, 'customer.identity.merchant_customer_id'
|
17
|
+
shortcut :customer_name, 'customer.details.name'
|
18
|
+
shortcut :return_url, 'session.return_url.url'
|
19
|
+
shortcut :restore_url, 'session.restore_url.url'
|
20
|
+
shortcut :skin, 'session.skin'
|
21
|
+
|
22
|
+
shortcut :pre_auth_callback, 'session.pre_auth_callback.url'
|
23
|
+
shortcut :post_auth_callback, 'session.post_auth_callback.url'
|
24
|
+
shortcut :transaction_notification, 'session.transaction_notification.url'
|
25
|
+
|
26
|
+
extend Forwardable
|
27
|
+
|
28
|
+
def_delegators :@api_client,
|
29
|
+
:capture_authorisation,
|
30
|
+
:cancel_authorisation,
|
31
|
+
:transaction,
|
32
|
+
:refund_payment
|
33
|
+
|
34
|
+
# The Hosted product has only a few endpoints. However, users most
|
35
|
+
# likey will want to access the endpoints of the API product as well.
|
36
|
+
# Therefore, this class also delegates to an API client which is
|
37
|
+
# initialized using the same options that this object receives.
|
38
|
+
def initialize(**options)
|
39
|
+
@api_client = PayPoint::Blue::API.new(**options)
|
40
|
+
super
|
41
|
+
end
|
42
|
+
|
43
|
+
# Test connectivity
|
44
|
+
#
|
45
|
+
# @return [true,false]
|
46
|
+
def ping
|
47
|
+
client.get "sessions/ping"
|
48
|
+
true
|
49
|
+
rescue Faraday::ClientError
|
50
|
+
false
|
51
|
+
end
|
52
|
+
|
53
|
+
# Make a payment
|
54
|
+
#
|
55
|
+
# @api_url https://developer.paypoint.com/payments/docs/#payments/make_a_payment
|
56
|
+
#
|
57
|
+
# @applies_defaults
|
58
|
+
# +:currency+, +:return_url+, +:restore_url+, +:skin+,
|
59
|
+
# +:pre_auth_callback+, +:post_auth_callback+, +:transaction_notification+
|
60
|
+
#
|
61
|
+
# @param [Hash] payload the payload is made up of the keyword
|
62
|
+
# arguments passed to the method
|
63
|
+
#
|
64
|
+
# @return the API response
|
65
|
+
def make_payment(**payload)
|
66
|
+
payload = build_payload(payload,
|
67
|
+
defaults: %i[
|
68
|
+
currency return_url restore_url skin
|
69
|
+
pre_auth_callback post_auth_callback transaction_notification
|
70
|
+
]
|
71
|
+
)
|
72
|
+
client.post "sessions/#{inst_id}/payments", build_payload(payload)
|
73
|
+
end
|
74
|
+
|
75
|
+
# Submit an authorisation
|
76
|
+
#
|
77
|
+
# @api_url https://developer.paypoint.com/payments/docs/#payments/submit_an_authorisation
|
78
|
+
# @see #make_payment
|
79
|
+
#
|
80
|
+
# This is a convenience method which makes a payment with the
|
81
|
+
# transaction's +deferred+ value set to +true+.
|
82
|
+
#
|
83
|
+
# @param (see #make_payment)
|
84
|
+
#
|
85
|
+
# @return the API response
|
86
|
+
def submit_authorisation(**payload)
|
87
|
+
payload[:transaction] ||= {}
|
88
|
+
payload[:transaction][:deferred] = true
|
89
|
+
make_payment(**payload)
|
90
|
+
end
|
91
|
+
|
92
|
+
end
|
@@ -0,0 +1,77 @@
|
|
1
|
+
module PayPoint
|
2
|
+
module Blue
|
3
|
+
|
4
|
+
# Provides helper methods for payload construction used throughout
|
5
|
+
# the API. It allows definition of payload shortcuts and default
|
6
|
+
# values.
|
7
|
+
module PayloadBuilder
|
8
|
+
|
9
|
+
def self.included(base)
|
10
|
+
base.extend ClassMethods
|
11
|
+
end
|
12
|
+
|
13
|
+
module ClassMethods
|
14
|
+
attr_accessor :shortcuts
|
15
|
+
|
16
|
+
# Define a payload shortcut
|
17
|
+
#
|
18
|
+
# Shortcuts help payload construction by defining short aliases
|
19
|
+
# to commonly used paths.
|
20
|
+
#
|
21
|
+
# @example Define and use a shortcut
|
22
|
+
# PayPoint::Blue::Hosted.shortcut :amount, 'transaction.money.amount.fixed'
|
23
|
+
# blue.make_payment(amount: '3.49', ...)
|
24
|
+
# # this will be turned into
|
25
|
+
# # { transaction: { money: { amount: { fixed: '3.49' } } } }
|
26
|
+
#
|
27
|
+
# @param [Symbol] key the shortcut key
|
28
|
+
# @param [String] path a path into the payload with segments
|
29
|
+
# separated by dots (e.g. +'transaction.money.amount.fixed'+)
|
30
|
+
def shortcut(key, path=nil)
|
31
|
+
if path.nil?
|
32
|
+
shortcuts && shortcuts[key]
|
33
|
+
else
|
34
|
+
self.shortcuts ||= {}
|
35
|
+
shortcuts[key] = path
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
attr_accessor :defaults
|
41
|
+
|
42
|
+
# Builds the payload by applying default values and replacing
|
43
|
+
# shortcuts
|
44
|
+
#
|
45
|
+
# @param [Hash] payload the original payload using shortcuts
|
46
|
+
# @param [Array<Symbol>] defaults an array of symbols for defaults
|
47
|
+
# that should be applied to this payload
|
48
|
+
def build_payload(payload, defaults: [])
|
49
|
+
apply_defaults(payload, defaults)
|
50
|
+
payload.keys.each do |key|
|
51
|
+
if path = self.class.shortcut(key)
|
52
|
+
value = payload.delete(key)
|
53
|
+
segments = path.split('.').map(&:to_sym)
|
54
|
+
leaf = segments.pop
|
55
|
+
leaf_parent = segments.reduce(payload) {|h,k| h[k] ||= {}}
|
56
|
+
leaf_parent[leaf] ||= value
|
57
|
+
end
|
58
|
+
end
|
59
|
+
payload
|
60
|
+
end
|
61
|
+
|
62
|
+
private
|
63
|
+
|
64
|
+
def apply_defaults(payload, applicable_defaults)
|
65
|
+
return unless defaults
|
66
|
+
|
67
|
+
defaults.each do |key, value|
|
68
|
+
if applicable_defaults.include?(key) && !payload.has_key?(key)
|
69
|
+
payload[key] = value
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
end
|
75
|
+
|
76
|
+
end
|
77
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
require "paypoint/blue/error"
|
2
|
+
|
3
|
+
module PayPoint
|
4
|
+
module Blue
|
5
|
+
|
6
|
+
# Faraday response middleware for handling various error scenarios
|
7
|
+
class RaiseErrors < Faraday::Response::Middleware
|
8
|
+
|
9
|
+
# Raise an error if the response outcome signifies a failure or
|
10
|
+
# the HTTP status code is 400 or greater.
|
11
|
+
#
|
12
|
+
# @raise [Error::Validation] for an outcome code starting with +V+
|
13
|
+
# @raise [Error::Auth] for an outcome code starting with +A+
|
14
|
+
# @raise [Error::Cancelled] for an outcome code starting with +C+
|
15
|
+
# @raise [Error::External] for an outcome code starting with +X+
|
16
|
+
# @raise [Error::Suspended] for an outcome code starting with +U+
|
17
|
+
# @raise [Error::Client] for all other error scenarios
|
18
|
+
def on_complete(env)
|
19
|
+
outcome = fetch_outcome(env)
|
20
|
+
if outcome
|
21
|
+
case outcome[:reason_code]
|
22
|
+
when /^S/ then return
|
23
|
+
when /^V/ then raise Error::Validation, response_values(env)
|
24
|
+
when /^A/ then raise Error::Auth, response_values(env)
|
25
|
+
when /^C/ then raise Error::Cancelled, response_values(env)
|
26
|
+
when /^X/ then raise Error::External, response_values(env)
|
27
|
+
when /^U/ then raise Error::Suspended, response_values(env)
|
28
|
+
else
|
29
|
+
raise Error::Client, response_values(env)
|
30
|
+
end
|
31
|
+
elsif env.status >= 400
|
32
|
+
raise Error::Client, response_values(env)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
private
|
37
|
+
|
38
|
+
def fetch_outcome(env)
|
39
|
+
env.body.is_a?(Hash) && env.body[:outcome]
|
40
|
+
end
|
41
|
+
|
42
|
+
def response_values(env)
|
43
|
+
{
|
44
|
+
status: env.status,
|
45
|
+
headers: env.response_headers,
|
46
|
+
body: env.body
|
47
|
+
}
|
48
|
+
end
|
49
|
+
|
50
|
+
end
|
51
|
+
|
52
|
+
end
|
53
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
module PayPoint
|
2
|
+
module Blue
|
3
|
+
module Utils
|
4
|
+
|
5
|
+
extend self
|
6
|
+
|
7
|
+
def snakecase_and_symbolize_keys(hash)
|
8
|
+
case hash
|
9
|
+
when Hash
|
10
|
+
hash.each_with_object({}) do |(key, value), snakified|
|
11
|
+
snakified[snakecase(key)] = snakecase_and_symbolize_keys(value)
|
12
|
+
end
|
13
|
+
when Enumerable
|
14
|
+
hash.map {|v| snakecase_and_symbolize_keys(v)}
|
15
|
+
else
|
16
|
+
hash
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def camelcase_and_symbolize_keys(hash)
|
21
|
+
case hash
|
22
|
+
when Hash
|
23
|
+
hash.each_with_object({}) do |(key, value), camelized|
|
24
|
+
camelized[camelcase(key)] = camelcase_and_symbolize_keys(value)
|
25
|
+
end
|
26
|
+
when Enumerable
|
27
|
+
hash.map {|v| camelcase_and_symbolize_keys(v)}
|
28
|
+
else
|
29
|
+
hash
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
private
|
34
|
+
|
35
|
+
def snakecase(original)
|
36
|
+
string = original.is_a?(Symbol) ? original.to_s : original.dup
|
37
|
+
string.gsub!(/([A-Z\d]+)([A-Z][a-z])/, '\1_\2')
|
38
|
+
string.gsub!(/([a-z\d])([A-Z])/, '\1_\2')
|
39
|
+
string.downcase!
|
40
|
+
string.to_sym
|
41
|
+
end
|
42
|
+
|
43
|
+
def camelcase(original)
|
44
|
+
string = original.is_a?(Symbol) ? original.to_s : original.dup
|
45
|
+
string.gsub!(/_([a-z\d]*)/) { $1.capitalize }
|
46
|
+
string.to_sym
|
47
|
+
end
|
48
|
+
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
require "paypoint/blue/version"
|
2
|
+
require "paypoint/blue/api"
|
3
|
+
require "paypoint/blue/hosted"
|
4
|
+
require "paypoint/blue/utils"
|
5
|
+
|
6
|
+
module PayPoint
|
7
|
+
module Blue
|
8
|
+
|
9
|
+
# Creates a client for the PayPoint Blue API product
|
10
|
+
#
|
11
|
+
# @see PayPoint::Blue::Base#initialize
|
12
|
+
def self.api_client(**options)
|
13
|
+
PayPoint::Blue::API.new(**options)
|
14
|
+
end
|
15
|
+
|
16
|
+
# Creates a client for the PayPoint Blue Hosted product
|
17
|
+
#
|
18
|
+
# @see PayPoint::Blue::Base#initialize
|
19
|
+
def self.hosted_client(**options)
|
20
|
+
PayPoint::Blue::Hosted.new(**options)
|
21
|
+
end
|
22
|
+
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'paypoint/blue/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "paypoint-blue"
|
8
|
+
spec.version = PayPoint::Blue::VERSION
|
9
|
+
spec.authors = ["Laszlo Bacsi"]
|
10
|
+
spec.email = ["lackac@lackac.hu"]
|
11
|
+
|
12
|
+
spec.summary = %q{API client for PayPoint Blue}
|
13
|
+
spec.description = %q{API client for PayPoint's 3rd generation PSP product a.k.a PayPoint Blue}
|
14
|
+
spec.homepage = "https://github.com/CPlus/paypoint-blue"
|
15
|
+
spec.license = "MIT"
|
16
|
+
|
17
|
+
spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
18
|
+
spec.bindir = "exe"
|
19
|
+
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
20
|
+
spec.require_paths = ["lib"]
|
21
|
+
|
22
|
+
spec.add_dependency "faraday"
|
23
|
+
spec.add_dependency "faraday_middleware"
|
24
|
+
spec.add_dependency "hashie"
|
25
|
+
|
26
|
+
spec.add_development_dependency "bundler", "~> 1.8"
|
27
|
+
spec.add_development_dependency "rake", "~> 10.0"
|
28
|
+
spec.add_development_dependency "webmock"
|
29
|
+
end
|
data/support/yard_ext.rb
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
class ShortcutHandler < YARD::Handlers::Ruby::Base
|
2
|
+
handles method_call(:shortcut)
|
3
|
+
namespace_only
|
4
|
+
|
5
|
+
def process
|
6
|
+
unless namespace.docstring.index('== Payload Shortcuts')
|
7
|
+
namespace.docstring += "\n\n== Payload Shortcuts\n"
|
8
|
+
end
|
9
|
+
shortcut = statement.parameters.first.jump(:ident).source
|
10
|
+
path = statement.parameters[1].jump(:string_content).source
|
11
|
+
namespace.docstring += "\n[+:#{shortcut}+] +#{path}+"
|
12
|
+
end
|
13
|
+
end
|
metadata
ADDED
@@ -0,0 +1,152 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: paypoint-blue
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Laszlo Bacsi
|
8
|
+
autorequire:
|
9
|
+
bindir: exe
|
10
|
+
cert_chain: []
|
11
|
+
date: 2015-03-24 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: faraday
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: faraday_middleware
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: hashie
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ">="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :runtime
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: bundler
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - "~>"
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '1.8'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - "~>"
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '1.8'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: rake
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - "~>"
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '10.0'
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - "~>"
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '10.0'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: webmock
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - ">="
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '0'
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - ">="
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '0'
|
97
|
+
description: API client for PayPoint's 3rd generation PSP product a.k.a PayPoint Blue
|
98
|
+
email:
|
99
|
+
- lackac@lackac.hu
|
100
|
+
executables: []
|
101
|
+
extensions: []
|
102
|
+
extra_rdoc_files: []
|
103
|
+
files:
|
104
|
+
- ".gitignore"
|
105
|
+
- ".travis.yml"
|
106
|
+
- ".yardopts"
|
107
|
+
- Gemfile
|
108
|
+
- LICENSE
|
109
|
+
- README.md
|
110
|
+
- Rakefile
|
111
|
+
- bin/console
|
112
|
+
- bin/setup
|
113
|
+
- lib/paypoint/blue.rb
|
114
|
+
- lib/paypoint/blue/api.rb
|
115
|
+
- lib/paypoint/blue/base.rb
|
116
|
+
- lib/paypoint/blue/body_extractor.rb
|
117
|
+
- lib/paypoint/blue/error.rb
|
118
|
+
- lib/paypoint/blue/faraday_runscope.rb
|
119
|
+
- lib/paypoint/blue/hash_key_converter.rb
|
120
|
+
- lib/paypoint/blue/hosted.rb
|
121
|
+
- lib/paypoint/blue/payload_builder.rb
|
122
|
+
- lib/paypoint/blue/raise_errors.rb
|
123
|
+
- lib/paypoint/blue/utils.rb
|
124
|
+
- lib/paypoint/blue/version.rb
|
125
|
+
- paypoint-blue.gemspec
|
126
|
+
- support/yard_ext.rb
|
127
|
+
homepage: https://github.com/CPlus/paypoint-blue
|
128
|
+
licenses:
|
129
|
+
- MIT
|
130
|
+
metadata: {}
|
131
|
+
post_install_message:
|
132
|
+
rdoc_options: []
|
133
|
+
require_paths:
|
134
|
+
- lib
|
135
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
136
|
+
requirements:
|
137
|
+
- - ">="
|
138
|
+
- !ruby/object:Gem::Version
|
139
|
+
version: '0'
|
140
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
141
|
+
requirements:
|
142
|
+
- - ">="
|
143
|
+
- !ruby/object:Gem::Version
|
144
|
+
version: '0'
|
145
|
+
requirements: []
|
146
|
+
rubyforge_project:
|
147
|
+
rubygems_version: 2.4.5
|
148
|
+
signing_key:
|
149
|
+
specification_version: 4
|
150
|
+
summary: API client for PayPoint Blue
|
151
|
+
test_files: []
|
152
|
+
has_rdoc:
|