paypoint-blue 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 +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:
|