docdata-order 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +15 -0
- data/.rspec +2 -0
- data/.rubocop.yml +38 -0
- data/.travis.yml +7 -0
- data/CHANGELOG.md +5 -0
- data/Gemfile +8 -0
- data/LICENSE.txt +21 -0
- data/README.md +134 -0
- data/Rakefile +10 -0
- data/bin/console +15 -0
- data/bin/setup +8 -0
- data/docdata-order.gemspec +32 -0
- data/lib/docdata/order.rb +11 -0
- data/lib/docdata/order/client.rb +71 -0
- data/lib/docdata/order/exception.rb +8 -0
- data/lib/docdata/order/gender.rb +11 -0
- data/lib/docdata/order/ideal.rb +20 -0
- data/lib/docdata/order/payment_method.rb +14 -0
- data/lib/docdata/order/request.rb +282 -0
- data/lib/docdata/order/response.rb +328 -0
- data/lib/docdata/order/urls.rb +15 -0
- data/lib/docdata/order/version.rb +7 -0
- metadata +148 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 1504b4d5df07a35ae4e4b403776da567d2bab632
|
4
|
+
data.tar.gz: '079dfe209ce3bc7a99f1040721a5290f2ac29c9b'
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 9d0d115f0d0427605c95c3d1d128e0f8f1e8f2667789b95366fd9a97ea887fbed2a1e6cbcc733b91b7226e7ec4e20a70a6ad186344b19e16f945e0c912d1810a
|
7
|
+
data.tar.gz: 69f6a2e859992879043497eb3d27f76e3e373e1bc965aab1e4ebfd87159d5912b97a1ecce6c388b21ccc5dfe738f4add1d39f2c9ca5ab4f3f5a35c2eeff86f63
|
data/.gitignore
ADDED
data/.rspec
ADDED
data/.rubocop.yml
ADDED
@@ -0,0 +1,38 @@
|
|
1
|
+
# Docdata-order RuboCop configuration
|
2
|
+
|
3
|
+
AllCops:
|
4
|
+
TargetRubyVersion: 2.3
|
5
|
+
DisplayCopNames: true
|
6
|
+
DisplayStyleGuide: true
|
7
|
+
|
8
|
+
Metrics/AbcSize:
|
9
|
+
Max: 53
|
10
|
+
|
11
|
+
Metrics/BlockLength:
|
12
|
+
Exclude:
|
13
|
+
- 'spec/**/*.rb'
|
14
|
+
|
15
|
+
Metrics/ClassLength:
|
16
|
+
Enabled: false
|
17
|
+
|
18
|
+
Metrics/LineLength:
|
19
|
+
Enabled: false
|
20
|
+
|
21
|
+
Metrics/MethodLength:
|
22
|
+
Enabled: false
|
23
|
+
|
24
|
+
Style/BlockDelimiters:
|
25
|
+
Exclude:
|
26
|
+
- 'spec/**/*.rb'
|
27
|
+
|
28
|
+
Style/GuardClause:
|
29
|
+
Enabled: false
|
30
|
+
|
31
|
+
Style/SafeNavigation:
|
32
|
+
Enabled: false
|
33
|
+
|
34
|
+
Style/StringLiterals:
|
35
|
+
Enabled: false
|
36
|
+
|
37
|
+
Style/SymbolArray:
|
38
|
+
Enabled: false
|
data/.travis.yml
ADDED
data/CHANGELOG.md
ADDED
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2017 Peter Postma
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in
|
13
|
+
all copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
21
|
+
THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,134 @@
|
|
1
|
+
# Docdata::Order
|
2
|
+
|
3
|
+
[![Gem Version](https://badge.fury.io/rb/docdata-order.svg)](https://badge.fury.io/rb/docdata-order)
|
4
|
+
[![Build Status](https://travis-ci.org/KentaaNL/docdata-order.svg?branch=master)](https://travis-ci.org/KentaaNL/docdata-order)
|
5
|
+
[![Code Climate](https://codeclimate.com/github/KentaaNL/docdata-order/badges/gpa.svg)](https://codeclimate.com/github/KentaaNL/docdata-order)
|
6
|
+
|
7
|
+
Docdata::Order is a Ruby client for the Docdata Order API version 1.3.
|
8
|
+
|
9
|
+
## Installation
|
10
|
+
|
11
|
+
Add this line to your application's Gemfile:
|
12
|
+
|
13
|
+
```ruby
|
14
|
+
gem 'docdata-order'
|
15
|
+
```
|
16
|
+
|
17
|
+
And then execute:
|
18
|
+
|
19
|
+
$ bundle
|
20
|
+
|
21
|
+
Or install it yourself as:
|
22
|
+
|
23
|
+
$ gem install docdata-order
|
24
|
+
|
25
|
+
## Usage
|
26
|
+
|
27
|
+
### Initialization
|
28
|
+
|
29
|
+
Create a Docdata Order client and configure it with your merchant name and password:
|
30
|
+
|
31
|
+
```ruby
|
32
|
+
order = Docdata::Order::Client.new("name", "password")
|
33
|
+
```
|
34
|
+
|
35
|
+
The client is configured in live mode by default. To put the client in test mode, use `test: true` as third parameter.
|
36
|
+
|
37
|
+
### Create an order
|
38
|
+
|
39
|
+
Create a new order with the `create` method. You need to provide the following parameters to create the order:
|
40
|
+
|
41
|
+
```ruby
|
42
|
+
options = {
|
43
|
+
amount: "12.50",
|
44
|
+
order_reference: "12345",
|
45
|
+
description: "Test order",
|
46
|
+
profile: "profile",
|
47
|
+
shopper: {
|
48
|
+
first_name: "John",
|
49
|
+
last_name: "Doe",
|
50
|
+
email: "john.doe@example.com",
|
51
|
+
language: "en",
|
52
|
+
gender: Docdata::Order::Gender::MALE
|
53
|
+
},
|
54
|
+
address: {
|
55
|
+
street: "Jansbuitensingel",
|
56
|
+
house_number: "29",
|
57
|
+
postal_code: "6811AD",
|
58
|
+
city: "Arnhem",
|
59
|
+
country: "NL"
|
60
|
+
}
|
61
|
+
}
|
62
|
+
|
63
|
+
response = order.create(options)
|
64
|
+
|
65
|
+
if response.success?
|
66
|
+
puts response.order_key
|
67
|
+
puts response.redirect_url
|
68
|
+
else
|
69
|
+
puts response.error_message
|
70
|
+
end
|
71
|
+
```
|
72
|
+
|
73
|
+
The `redirect_url` in the response will redirect the user to the Docdata Payment Menu (One Page Checkout).
|
74
|
+
|
75
|
+
To create an order and automatically redirect to the bank using iDEAL as payment method, use the parameters above including:
|
76
|
+
|
77
|
+
```ruby
|
78
|
+
response = order.create(options.merge(
|
79
|
+
payment_method: Docdata::Order::PaymentMethod::IDEAL,
|
80
|
+
issuer_id: Docdata::Order::Ideal::ISSUERS.first[0],
|
81
|
+
return_url: "http://yourwebshop.nl/payment_return"
|
82
|
+
))
|
83
|
+
```
|
84
|
+
|
85
|
+
### Start a payment order
|
86
|
+
|
87
|
+
When using Webdirect, you can use `start` to start a payment order.
|
88
|
+
|
89
|
+
```ruby
|
90
|
+
options = {
|
91
|
+
order_key: "12345",
|
92
|
+
payment_method: Docdata::Order::PaymentMethod::SEPA_DIRECT_DEBIT,
|
93
|
+
account_name: "Onderheuvel",
|
94
|
+
account_iban: "NL44RABO0123456789"
|
95
|
+
}
|
96
|
+
|
97
|
+
response = order.start(options)
|
98
|
+
|
99
|
+
if response.success?
|
100
|
+
puts response.payment_id
|
101
|
+
else
|
102
|
+
puts response.error_message
|
103
|
+
end
|
104
|
+
```
|
105
|
+
|
106
|
+
### Retrieve status of an order
|
107
|
+
|
108
|
+
To retrieve the status of an order, use `status` with the order key:
|
109
|
+
|
110
|
+
```ruby
|
111
|
+
response = order.status(order_key: "12345")
|
112
|
+
|
113
|
+
if response.success?
|
114
|
+
puts response.paid?
|
115
|
+
else
|
116
|
+
puts response.error_message
|
117
|
+
end
|
118
|
+
```
|
119
|
+
|
120
|
+
## Development
|
121
|
+
|
122
|
+
After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
|
123
|
+
|
124
|
+
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`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
|
125
|
+
|
126
|
+
## Contributing
|
127
|
+
|
128
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/KentaaNL/docdata-order.
|
129
|
+
|
130
|
+
|
131
|
+
## License
|
132
|
+
|
133
|
+
The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
|
134
|
+
|
data/Rakefile
ADDED
data/bin/console
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
require "bundler/setup"
|
5
|
+
require "docdata/order"
|
6
|
+
|
7
|
+
# You can add fixtures and/or initialization code here to make experimenting
|
8
|
+
# with your gem easier. You can also use a different console, if you like.
|
9
|
+
|
10
|
+
# (If you use this, don't forget to add pry to your Gemfile!)
|
11
|
+
# require "pry"
|
12
|
+
# Pry.start
|
13
|
+
|
14
|
+
require "irb"
|
15
|
+
IRB.start(__FILE__)
|
data/bin/setup
ADDED
@@ -0,0 +1,32 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
lib = File.expand_path('../lib', __FILE__)
|
4
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
5
|
+
require 'docdata/order/version'
|
6
|
+
|
7
|
+
Gem::Specification.new do |spec|
|
8
|
+
spec.name = "docdata-order"
|
9
|
+
spec.version = Docdata::Order::VERSION
|
10
|
+
spec.authors = ["Kentaa"]
|
11
|
+
spec.email = ["support@kentaa.nl"]
|
12
|
+
|
13
|
+
spec.summary = "Ruby client for the Docdata Order API"
|
14
|
+
spec.homepage = "https://github.com/KentaaNL/docdata-order"
|
15
|
+
spec.license = "MIT"
|
16
|
+
|
17
|
+
spec.files = `git ls-files -z`.split("\x0").reject do |f|
|
18
|
+
f.match(%r{^(test|spec|features)/})
|
19
|
+
end
|
20
|
+
spec.bindir = "exe"
|
21
|
+
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
22
|
+
spec.require_paths = ["lib"]
|
23
|
+
|
24
|
+
spec.required_ruby_version = ">= 2.0.0"
|
25
|
+
|
26
|
+
spec.add_development_dependency "bundler", "~> 1.14"
|
27
|
+
spec.add_development_dependency "rake", "~> 10.0"
|
28
|
+
spec.add_development_dependency "rspec", "~> 3.0"
|
29
|
+
spec.add_development_dependency "webmock", "~> 2.3", ">= 2.3.2"
|
30
|
+
|
31
|
+
spec.add_dependency "savon", ">= 2.0", "< 3.0"
|
32
|
+
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "docdata/order/client"
|
4
|
+
require "docdata/order/exception"
|
5
|
+
require "docdata/order/gender"
|
6
|
+
require "docdata/order/ideal"
|
7
|
+
require "docdata/order/payment_method"
|
8
|
+
require "docdata/order/request"
|
9
|
+
require "docdata/order/response"
|
10
|
+
require "docdata/order/urls"
|
11
|
+
require "docdata/order/version"
|
@@ -0,0 +1,71 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "savon"
|
4
|
+
|
5
|
+
module Docdata
|
6
|
+
module Order
|
7
|
+
# Client for the Docdata Order API.
|
8
|
+
class Client
|
9
|
+
XMLNS_DDP = "http://www.docdatapayments.com/services/paymentservice/1_3/"
|
10
|
+
DDP_VERSION = "1.3"
|
11
|
+
|
12
|
+
def initialize(name, password, options = {})
|
13
|
+
@options = options.merge(merchant: { name: name, password: password })
|
14
|
+
end
|
15
|
+
|
16
|
+
def create(options = {})
|
17
|
+
params = @options.merge(options)
|
18
|
+
|
19
|
+
response = client.call(:create, message: CreateRequest.new(params), attributes: { xmlns: XMLNS_DDP, version: DDP_VERSION })
|
20
|
+
|
21
|
+
raise Exception, response unless response.success?
|
22
|
+
|
23
|
+
CreateResponse.new(params, response)
|
24
|
+
end
|
25
|
+
|
26
|
+
def start(options = {})
|
27
|
+
params = @options.merge(options)
|
28
|
+
|
29
|
+
response = client.call(:start, message: StartRequest.new(params), attributes: { xmlns: XMLNS_DDP, version: DDP_VERSION })
|
30
|
+
|
31
|
+
raise Exception, response unless response.success?
|
32
|
+
|
33
|
+
StartResponse.new(params, response)
|
34
|
+
end
|
35
|
+
|
36
|
+
def status(options = {})
|
37
|
+
params = @options.merge(options)
|
38
|
+
|
39
|
+
response = client.call(:status_extended, message: ExtendedStatusRequest.new(params), attributes: { xmlns: XMLNS_DDP, version: DDP_VERSION })
|
40
|
+
|
41
|
+
raise Exception, response unless response.success?
|
42
|
+
|
43
|
+
ExtendedStatusResponse.new(params, response)
|
44
|
+
end
|
45
|
+
|
46
|
+
private
|
47
|
+
|
48
|
+
def client
|
49
|
+
@client ||= begin
|
50
|
+
params = { wsdl: wsdl_url, raise_errors: false, namespace_identifier: nil, namespaces: { "xmlns:ddp" => XMLNS_DDP } }
|
51
|
+
|
52
|
+
if @options[:debug]
|
53
|
+
params.merge!(log: true, log_level: :debug, pretty_print_xml: true)
|
54
|
+
end
|
55
|
+
|
56
|
+
params[:logger] = Rails.logger if defined?(Rails)
|
57
|
+
|
58
|
+
Savon.client(params)
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
def wsdl_url
|
63
|
+
if @options[:test]
|
64
|
+
Urls::WSDL_TEST_URL
|
65
|
+
else
|
66
|
+
Urls::WSDL_LIVE_URL
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Docdata
|
4
|
+
module Order
|
5
|
+
module Ideal
|
6
|
+
ISSUERS = {
|
7
|
+
"ABNANL2A" => "ABN AMRO",
|
8
|
+
"ASNBNL21" => "ASN Bank",
|
9
|
+
"BUNQNL2A" => "Bunq",
|
10
|
+
"INGBNL2A" => "ING",
|
11
|
+
"KNABNL2H" => "Knab bank",
|
12
|
+
"RABONL2U" => "Rabobank",
|
13
|
+
"RBRBNL21" => "RegioBank",
|
14
|
+
"SNSBNL2A" => "SNS Bank",
|
15
|
+
"TRIONL2U" => "Triodos Bank",
|
16
|
+
"FVLBNL22" => "Van Lanschot"
|
17
|
+
}.freeze
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Docdata
|
4
|
+
module Order
|
5
|
+
module PaymentMethod
|
6
|
+
IDEAL = "IDEAL"
|
7
|
+
VISA = "VISA"
|
8
|
+
MASTER_CARD = "MASTERCARD"
|
9
|
+
AMERICAN_EXPRESS = "AMEX"
|
10
|
+
PAYPAL = "PAYPAL_EXPRESS_CHECKOUT"
|
11
|
+
SEPA_DIRECT_DEBIT = "SEPA_DIRECT_DEBIT"
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,282 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "builder/xmlmarkup"
|
4
|
+
require "bigdecimal"
|
5
|
+
require "securerandom"
|
6
|
+
|
7
|
+
module Docdata
|
8
|
+
module Order
|
9
|
+
# Base class for XML requests to Docdata.
|
10
|
+
class Request
|
11
|
+
attr_reader :options
|
12
|
+
|
13
|
+
def initialize(options = {})
|
14
|
+
@options = options
|
15
|
+
end
|
16
|
+
|
17
|
+
def to_s
|
18
|
+
builder = Builder::XmlMarkup.new
|
19
|
+
|
20
|
+
# Merchant credentials.
|
21
|
+
builder.merchant(name: merchant_name, password: merchant_password)
|
22
|
+
|
23
|
+
build_request(builder)
|
24
|
+
|
25
|
+
# This element contains information about the application contacting the webservice.
|
26
|
+
# This info is useful when debugging troubleshooting technical integration issues.
|
27
|
+
builder.integrationInfo do |integration|
|
28
|
+
# The name of the plugin used to contact this webservice.
|
29
|
+
integration.webshopPlugin("docdata-order")
|
30
|
+
# The version of the plugin used to contact this webservice.
|
31
|
+
integration.webshopPluginVersion(Docdata::Order::VERSION)
|
32
|
+
# The name of the plugin creator used to contact this webservice.
|
33
|
+
integration.integratorName("Kentaa")
|
34
|
+
# The programming language used to contact this webservice.
|
35
|
+
integration.programmingLanguage("Ruby #{RUBY_VERSION}")
|
36
|
+
# The operating system from which this webservice is contacted.
|
37
|
+
integration.operatingSystem(RUBY_PLATFORM)
|
38
|
+
# The full version number (including minor e.q. 1.3.0)
|
39
|
+
# of the xsd which is used during integration. DDP can make minor
|
40
|
+
# (non-breaking) changes to the xsd. These are reflected in a minor
|
41
|
+
# version number. It can therefore be useful to know if a different
|
42
|
+
# minor version of the xsd was used during merchant development than
|
43
|
+
# the one currently active in production.
|
44
|
+
integration.ddpXsdVersion(Docdata::Order::Client::DDP_VERSION)
|
45
|
+
end
|
46
|
+
|
47
|
+
builder.target!
|
48
|
+
end
|
49
|
+
|
50
|
+
private
|
51
|
+
|
52
|
+
def merchant_name
|
53
|
+
options.fetch(:merchant).fetch(:name)
|
54
|
+
end
|
55
|
+
|
56
|
+
def merchant_password
|
57
|
+
options.fetch(:merchant).fetch(:password)
|
58
|
+
end
|
59
|
+
|
60
|
+
def build_request
|
61
|
+
raise NotImplementedError
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
# Create an Order in the Docdata system.
|
66
|
+
class CreateRequest < Request
|
67
|
+
def build_request(builder)
|
68
|
+
# Unique merchant reference to this order.
|
69
|
+
builder.merchantOrderReference(order_reference)
|
70
|
+
|
71
|
+
# Preferences to use for this payment.
|
72
|
+
builder.paymentPreferences do |preferences|
|
73
|
+
# The profile that is used to select the payment methods that can be used to pay this order.
|
74
|
+
preferences.profile(profile)
|
75
|
+
preferences.numberOfDaysToPay(14)
|
76
|
+
end
|
77
|
+
|
78
|
+
# Information concerning the shopper who placed the order.
|
79
|
+
builder.shopper(id: shopper_id) do |shopper|
|
80
|
+
# Shopper's full name.
|
81
|
+
shopper.name do |name|
|
82
|
+
# The first given name.
|
83
|
+
name.first(shopper_first_name)
|
84
|
+
# Any subsequent given name or names. May also be used as middle initial.
|
85
|
+
name.middle(shopper_infix) if shopper_infix
|
86
|
+
# The family or inherited name(s).
|
87
|
+
name.last(shopper_last_name)
|
88
|
+
end
|
89
|
+
|
90
|
+
# Shopper's e-mail address.
|
91
|
+
shopper.email(shopper_email)
|
92
|
+
# Shopper's preferred language. Language code according to ISO 639.
|
93
|
+
shopper.language(code: shopper_language)
|
94
|
+
# Shopper's gender.
|
95
|
+
shopper.gender(shopper_gender)
|
96
|
+
# Ip address of the shopper. Will be used in the future for riskchecks. Can be ipv4 or ipv6.
|
97
|
+
shopper.ipAddress(shopper_ip_address) if shopper_ip_address
|
98
|
+
end
|
99
|
+
|
100
|
+
# Total order gross amount. The amount in the minor unit for the given currency.
|
101
|
+
# (E.g. for EUR in cents)
|
102
|
+
builder.totalGrossAmount(amount, currency: currency)
|
103
|
+
|
104
|
+
# Name and address to use for billing.
|
105
|
+
builder.billTo do |bill|
|
106
|
+
bill.name do |name|
|
107
|
+
# The first given name.
|
108
|
+
name.first(shopper_first_name)
|
109
|
+
# Any subsequent given name or names. May also be used as middle initial.
|
110
|
+
name.middle(shopper_infix) if shopper_infix
|
111
|
+
# The family or inherited name(s).
|
112
|
+
name.last(shopper_last_name)
|
113
|
+
end
|
114
|
+
# Address of the destination.
|
115
|
+
bill.address do |address|
|
116
|
+
# Address lines must be filled as specific as possible using the house number
|
117
|
+
# and optionally the house number addition field.
|
118
|
+
address.street(address_street)
|
119
|
+
# The house number.
|
120
|
+
address.houseNumber(address_house_number)
|
121
|
+
address.postalCode(address_postal_code)
|
122
|
+
address.city(address_city)
|
123
|
+
# Country code according to ISO 3166.
|
124
|
+
address.country(code: address_country)
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
128
|
+
# The description of the order.
|
129
|
+
builder.description(description)
|
130
|
+
|
131
|
+
# The description that is used by payment providers on shopper statements.
|
132
|
+
builder.receiptText(receipt_text)
|
133
|
+
end
|
134
|
+
|
135
|
+
private
|
136
|
+
|
137
|
+
def amount
|
138
|
+
decimal = BigDecimal.new(options.fetch(:amount).to_s)
|
139
|
+
decimal *= 100 # to cents
|
140
|
+
decimal.to_i
|
141
|
+
end
|
142
|
+
|
143
|
+
def order_reference
|
144
|
+
options.fetch(:order_reference)
|
145
|
+
end
|
146
|
+
|
147
|
+
def profile
|
148
|
+
options.fetch(:profile)
|
149
|
+
end
|
150
|
+
|
151
|
+
def shopper_id
|
152
|
+
options.fetch(:shopper)[:id] || SecureRandom.hex
|
153
|
+
end
|
154
|
+
|
155
|
+
def shopper_first_name
|
156
|
+
options.fetch(:shopper).fetch(:first_name)
|
157
|
+
end
|
158
|
+
|
159
|
+
def shopper_infix
|
160
|
+
options.fetch(:shopper)[:infix]
|
161
|
+
end
|
162
|
+
|
163
|
+
def shopper_last_name
|
164
|
+
options.fetch(:shopper).fetch(:last_name)
|
165
|
+
end
|
166
|
+
|
167
|
+
def shopper_email
|
168
|
+
options.fetch(:shopper).fetch(:email)
|
169
|
+
end
|
170
|
+
|
171
|
+
def shopper_language
|
172
|
+
options.fetch(:shopper).fetch(:language)
|
173
|
+
end
|
174
|
+
|
175
|
+
def shopper_gender
|
176
|
+
options.fetch(:shopper).fetch(:gender)
|
177
|
+
end
|
178
|
+
|
179
|
+
def shopper_ip_address
|
180
|
+
options.fetch(:shopper)[:ip_address]
|
181
|
+
end
|
182
|
+
|
183
|
+
def address_street
|
184
|
+
options.fetch(:address).fetch(:street)
|
185
|
+
end
|
186
|
+
|
187
|
+
def address_house_number
|
188
|
+
options.fetch(:address).fetch(:house_number)
|
189
|
+
end
|
190
|
+
|
191
|
+
def address_postal_code
|
192
|
+
options.fetch(:address).fetch(:postal_code)
|
193
|
+
end
|
194
|
+
|
195
|
+
def address_city
|
196
|
+
options.fetch(:address).fetch(:city)
|
197
|
+
end
|
198
|
+
|
199
|
+
def address_country
|
200
|
+
options.fetch(:address).fetch(:country)
|
201
|
+
end
|
202
|
+
|
203
|
+
def currency
|
204
|
+
options[:currency] || "EUR"
|
205
|
+
end
|
206
|
+
|
207
|
+
def description
|
208
|
+
options.fetch(:description)
|
209
|
+
end
|
210
|
+
|
211
|
+
def receipt_text
|
212
|
+
options.fetch(:description)[0, 49]
|
213
|
+
end
|
214
|
+
end
|
215
|
+
|
216
|
+
# Start a payment order (Webdirect).
|
217
|
+
class StartRequest < Request
|
218
|
+
def build_request(builder)
|
219
|
+
# Payment order key belonging to the order for which a transaction needs to be started.
|
220
|
+
builder.paymentOrderKey(order_key)
|
221
|
+
|
222
|
+
builder.payment do |payment|
|
223
|
+
payment.paymentMethod(payment_method)
|
224
|
+
|
225
|
+
case payment_method
|
226
|
+
when PaymentMethod::IDEAL
|
227
|
+
payment.iDealPaymentInput do |input|
|
228
|
+
input.issuerId(issuer_id)
|
229
|
+
end
|
230
|
+
when PaymentMethod::SEPA_DIRECT_DEBIT
|
231
|
+
payment.directDebitPaymentInput do |input|
|
232
|
+
input.holderName(account_name)
|
233
|
+
input.iban(account_iban)
|
234
|
+
input.bic(account_bic) if account_bic
|
235
|
+
end
|
236
|
+
else
|
237
|
+
raise ArgumentError, "Payment method not supported: #{payment_method}"
|
238
|
+
end
|
239
|
+
end
|
240
|
+
end
|
241
|
+
|
242
|
+
private
|
243
|
+
|
244
|
+
def order_key
|
245
|
+
options.fetch(:order_key)
|
246
|
+
end
|
247
|
+
|
248
|
+
def payment_method
|
249
|
+
options.fetch(:payment_method)
|
250
|
+
end
|
251
|
+
|
252
|
+
def issuer_id
|
253
|
+
options.fetch(:issuer_id)
|
254
|
+
end
|
255
|
+
|
256
|
+
def account_name
|
257
|
+
options.fetch(:account_name)
|
258
|
+
end
|
259
|
+
|
260
|
+
def account_iban
|
261
|
+
options.fetch(:account_iban)
|
262
|
+
end
|
263
|
+
|
264
|
+
def account_bic
|
265
|
+
options[:account_bic]
|
266
|
+
end
|
267
|
+
end
|
268
|
+
|
269
|
+
# Retrieve additional status information of an Order.
|
270
|
+
class ExtendedStatusRequest < Request
|
271
|
+
def build_request(builder)
|
272
|
+
builder.paymentOrderKey(order_key)
|
273
|
+
end
|
274
|
+
|
275
|
+
private
|
276
|
+
|
277
|
+
def order_key
|
278
|
+
options.fetch(:order_key)
|
279
|
+
end
|
280
|
+
end
|
281
|
+
end
|
282
|
+
end
|
@@ -0,0 +1,328 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "uri"
|
4
|
+
|
5
|
+
module Docdata
|
6
|
+
module Order
|
7
|
+
# Base class for responses.
|
8
|
+
class Response
|
9
|
+
attr_reader :options, :response
|
10
|
+
|
11
|
+
def initialize(options, response)
|
12
|
+
@options = options
|
13
|
+
@response = response
|
14
|
+
end
|
15
|
+
|
16
|
+
def body
|
17
|
+
response.body
|
18
|
+
end
|
19
|
+
|
20
|
+
def error_message
|
21
|
+
errors[:error] if errors
|
22
|
+
end
|
23
|
+
|
24
|
+
def error_code
|
25
|
+
errors[:error].attributes["code"] if errors
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
# Response to a create operation.
|
30
|
+
class CreateResponse < Response
|
31
|
+
def data
|
32
|
+
body[:create_response]
|
33
|
+
end
|
34
|
+
|
35
|
+
def success?
|
36
|
+
data.key?(:create_success)
|
37
|
+
end
|
38
|
+
|
39
|
+
def error?
|
40
|
+
data.key?(:create_errors)
|
41
|
+
end
|
42
|
+
|
43
|
+
def errors
|
44
|
+
data[:create_errors]
|
45
|
+
end
|
46
|
+
|
47
|
+
def order_key
|
48
|
+
data[:create_success][:key]
|
49
|
+
end
|
50
|
+
|
51
|
+
def redirect_url
|
52
|
+
params = {
|
53
|
+
command: "show_payment_cluster",
|
54
|
+
merchant_name: merchant_name,
|
55
|
+
client_language: client_language,
|
56
|
+
payment_cluster_key: order_key
|
57
|
+
}
|
58
|
+
|
59
|
+
if payment_method
|
60
|
+
params[:default_pm] = payment_method
|
61
|
+
|
62
|
+
case payment_method
|
63
|
+
when PaymentMethod::IDEAL
|
64
|
+
params[:default_act] = true
|
65
|
+
params[:ideal_issuer_id] = issuer_id if issuer_id
|
66
|
+
when PaymentMethod::PAYPAL
|
67
|
+
params[:default_act] = true
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
if return_url
|
72
|
+
params.merge!(
|
73
|
+
return_url_success: build_return_url("success"),
|
74
|
+
return_url_canceled: build_return_url("cancelled"),
|
75
|
+
return_url_pending: build_return_url("pending"),
|
76
|
+
return_url_error: build_return_url("error")
|
77
|
+
)
|
78
|
+
end
|
79
|
+
|
80
|
+
uri = URI.parse(redirect_base_url)
|
81
|
+
uri.query = URI.encode_www_form(params)
|
82
|
+
uri.to_s
|
83
|
+
end
|
84
|
+
|
85
|
+
private
|
86
|
+
|
87
|
+
def redirect_base_url
|
88
|
+
if options[:test]
|
89
|
+
Urls::MENU_TEST_URL
|
90
|
+
else
|
91
|
+
Urls::MENU_LIVE_URL
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
def merchant_name
|
96
|
+
options.fetch(:merchant).fetch(:name)
|
97
|
+
end
|
98
|
+
|
99
|
+
def client_language
|
100
|
+
options.fetch(:shopper).fetch(:language)
|
101
|
+
end
|
102
|
+
|
103
|
+
def payment_method
|
104
|
+
options[:payment_method]
|
105
|
+
end
|
106
|
+
|
107
|
+
def issuer_id
|
108
|
+
options[:issuer_id]
|
109
|
+
end
|
110
|
+
|
111
|
+
def return_url
|
112
|
+
options[:return_url]
|
113
|
+
end
|
114
|
+
|
115
|
+
def build_return_url(status)
|
116
|
+
uri = URI.parse(return_url)
|
117
|
+
query = URI.decode_www_form(uri.query || "") << ["status", status]
|
118
|
+
uri.query = URI.encode_www_form(query)
|
119
|
+
uri.to_s
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
# Response to a start operation.
|
124
|
+
class StartResponse < Response
|
125
|
+
def data
|
126
|
+
body[:start_response]
|
127
|
+
end
|
128
|
+
|
129
|
+
def success?
|
130
|
+
data.key?(:start_success)
|
131
|
+
end
|
132
|
+
|
133
|
+
def error?
|
134
|
+
data.key?(:start_errors)
|
135
|
+
end
|
136
|
+
|
137
|
+
def errors
|
138
|
+
data[:start_errors]
|
139
|
+
end
|
140
|
+
|
141
|
+
def payment_response
|
142
|
+
data[:start_success][:payment_response]
|
143
|
+
end
|
144
|
+
|
145
|
+
def payment_success
|
146
|
+
payment_response[:payment_success] if payment_response
|
147
|
+
end
|
148
|
+
|
149
|
+
def payment_id
|
150
|
+
payment_success[:id] if payment_success
|
151
|
+
end
|
152
|
+
end
|
153
|
+
|
154
|
+
# Response to a extended status operation.
|
155
|
+
class ExtendedStatusResponse < Response
|
156
|
+
def data
|
157
|
+
body[:extended_status_response]
|
158
|
+
end
|
159
|
+
|
160
|
+
def success?
|
161
|
+
data.key?(:status_success)
|
162
|
+
end
|
163
|
+
|
164
|
+
def error?
|
165
|
+
data.key?(:status_errors)
|
166
|
+
end
|
167
|
+
|
168
|
+
def errors
|
169
|
+
data[:status_errors]
|
170
|
+
end
|
171
|
+
|
172
|
+
def report
|
173
|
+
data[:status_success][:report]
|
174
|
+
end
|
175
|
+
|
176
|
+
def payment
|
177
|
+
payment = report[:payment]
|
178
|
+
|
179
|
+
# When multiple payments are found, return the payment with the newest ID.
|
180
|
+
if payment.is_a?(Array)
|
181
|
+
payment.sort_by { |key, _value| key[:id] }.last
|
182
|
+
else
|
183
|
+
payment
|
184
|
+
end
|
185
|
+
end
|
186
|
+
|
187
|
+
def payment_id
|
188
|
+
payment[:id] if payment
|
189
|
+
end
|
190
|
+
|
191
|
+
def payment_method
|
192
|
+
payment[:payment_method] if payment
|
193
|
+
end
|
194
|
+
|
195
|
+
def authorization
|
196
|
+
payment[:authorization] if payment
|
197
|
+
end
|
198
|
+
|
199
|
+
# The state of the authorization. Current known values:
|
200
|
+
# NEW This is a new payment without any actions performed on it yet.
|
201
|
+
# RISK_CHECK_OK For this payment the risk check was okay.
|
202
|
+
# RISK_CHECK_FAILED The risk check for this payment triggered.
|
203
|
+
# STARTED The user has provided details and is authenticated.
|
204
|
+
# START_ERROR The payment system could not start the payment due to a technical error.
|
205
|
+
# AUTHENTICATED The shopper is authenticated by the acquirer.
|
206
|
+
# REDIRECTED_FOR_AUTHENTICATION The shopper is redirected to the acquirer web-site for authentication.
|
207
|
+
# AUTHENTICATION_FAILED The shopper is not authenticated by the acquirer.
|
208
|
+
# AUTHENTICATION_ERROR Unable to do the authentication of the shopper by the acquirer.
|
209
|
+
# AUTHORIZED This payment is authorized.
|
210
|
+
# REDIRECTED_FOR_AUTHORIZATION The shopper is redirected to the acquirer web-site for authorization.
|
211
|
+
# AUTHORIZATION_REQUESTED Requested authorization for this payment, waiting for a notification from acquirer.
|
212
|
+
# AUTHORIZATION_FAILED The payment was not authorized due to a functional error.
|
213
|
+
# AUTHORIZATION_ERROR Unable to do the payment authorization due to a technical error.
|
214
|
+
# CANCELED The payment is canceled.
|
215
|
+
# CANCEL_FAILED Payment is not canceled, due to functional error.
|
216
|
+
# CANCEL_ERROR Payment is not canceled, due to technical error.
|
217
|
+
# CANCEL_REQUESTED A cancel request sent to acquirer.
|
218
|
+
def authorization_status
|
219
|
+
authorization[:status] if authorization
|
220
|
+
end
|
221
|
+
|
222
|
+
def approximate_totals
|
223
|
+
report[:approximate_totals]
|
224
|
+
end
|
225
|
+
|
226
|
+
def total_registered
|
227
|
+
to_decimal(approximate_totals[:total_registered])
|
228
|
+
end
|
229
|
+
|
230
|
+
def total_shopper_pending
|
231
|
+
to_decimal(approximate_totals[:total_shopper_pending])
|
232
|
+
end
|
233
|
+
|
234
|
+
def total_acquirer_pending
|
235
|
+
to_decimal(approximate_totals[:total_acquirer_pending])
|
236
|
+
end
|
237
|
+
|
238
|
+
def total_acquirer_approved
|
239
|
+
to_decimal(approximate_totals[:total_acquirer_approved])
|
240
|
+
end
|
241
|
+
|
242
|
+
def total_captured
|
243
|
+
to_decimal(approximate_totals[:total_captured])
|
244
|
+
end
|
245
|
+
|
246
|
+
def total_refunded
|
247
|
+
to_decimal(approximate_totals[:total_refunded])
|
248
|
+
end
|
249
|
+
|
250
|
+
def total_reversed
|
251
|
+
to_decimal(approximate_totals[:total_chargedback])
|
252
|
+
end
|
253
|
+
|
254
|
+
def total_charged_back
|
255
|
+
to_decimal(approximate_totals[:total_chargedback])
|
256
|
+
end
|
257
|
+
|
258
|
+
def paid?
|
259
|
+
(total_registered == total_captured) || (total_registered == total_acquirer_approved)
|
260
|
+
end
|
261
|
+
|
262
|
+
def refunded?
|
263
|
+
total_registered == total_refunded
|
264
|
+
end
|
265
|
+
|
266
|
+
def charged_back?
|
267
|
+
total_registered == total_charged_back
|
268
|
+
end
|
269
|
+
|
270
|
+
def reversed?
|
271
|
+
total_registered == total_reversed
|
272
|
+
end
|
273
|
+
|
274
|
+
def started?
|
275
|
+
(authorization_status == "NEW" || authorization_status == "STARTED" ||
|
276
|
+
(total_captured.zero? && total_acquirer_approved.zero?)) && authorization_status != "CANCELED"
|
277
|
+
end
|
278
|
+
|
279
|
+
def cancelled?
|
280
|
+
authorization_status == "CANCELED"
|
281
|
+
end
|
282
|
+
|
283
|
+
def account_iban
|
284
|
+
case payment_method
|
285
|
+
when PaymentMethod::IDEAL
|
286
|
+
payment_info = payment[:extended][:i_deal_payment_info]
|
287
|
+
payment_info[:shopper_bank_account][:iban] if payment_info && payment_info[:shopper_bank_account]
|
288
|
+
when PaymentMethod::SEPA_DIRECT_DEBIT
|
289
|
+
payment_info = payment[:extended][:sepa_direct_debit_payment_info]
|
290
|
+
payment_info[:iban] if payment_info
|
291
|
+
end
|
292
|
+
end
|
293
|
+
|
294
|
+
def account_bic
|
295
|
+
case payment_method
|
296
|
+
when PaymentMethod::IDEAL
|
297
|
+
payment_info = payment[:extended][:i_deal_payment_info]
|
298
|
+
payment_info[:shopper_bank_account][:bic] if payment_info && payment_info[:shopper_bank_account]
|
299
|
+
when PaymentMethod::SEPA_DIRECT_DEBIT
|
300
|
+
payment_info = payment[:extended][:sepa_direct_debit_payment_info]
|
301
|
+
payment_info[:bic] if payment_info
|
302
|
+
end
|
303
|
+
end
|
304
|
+
|
305
|
+
def account_name
|
306
|
+
if payment_method == PaymentMethod::IDEAL
|
307
|
+
payment_info = payment[:extended][:i_deal_payment_info]
|
308
|
+
payment_info[:holder_name] if payment_info
|
309
|
+
end
|
310
|
+
end
|
311
|
+
|
312
|
+
def mandate_number
|
313
|
+
if payment_method == PaymentMethod::SEPA_DIRECT_DEBIT
|
314
|
+
payment_info = payment[:extended][:sepa_direct_debit_payment_info]
|
315
|
+
payment_info[:mandate_number] if payment_info
|
316
|
+
end
|
317
|
+
end
|
318
|
+
|
319
|
+
private
|
320
|
+
|
321
|
+
def to_decimal(cents)
|
322
|
+
total = BigDecimal.new(cents)
|
323
|
+
total /= 100.0
|
324
|
+
total
|
325
|
+
end
|
326
|
+
end
|
327
|
+
end
|
328
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Docdata
|
4
|
+
module Order
|
5
|
+
module Urls
|
6
|
+
# WSDL location, see Order API 1.3.
|
7
|
+
WSDL_LIVE_URL = "https://secure.docdatapayments.com/ps/services/paymentservice/1_3?wsdl"
|
8
|
+
WSDL_TEST_URL = "https://test.docdatapayments.com/ps/services/paymentservice/1_3?wsdl"
|
9
|
+
|
10
|
+
# Payment Menu base URL, see Functional API.
|
11
|
+
MENU_LIVE_URL = "https://secure.docdatapayments.com/ps/menu"
|
12
|
+
MENU_TEST_URL = "https://test.docdatapayments.com/ps/menu"
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
metadata
ADDED
@@ -0,0 +1,148 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: docdata-order
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.0.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Kentaa
|
8
|
+
autorequire:
|
9
|
+
bindir: exe
|
10
|
+
cert_chain: []
|
11
|
+
date: 2018-02-09 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: bundler
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1.14'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1.14'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rake
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '10.0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '10.0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rspec
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '3.0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '3.0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: webmock
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - "~>"
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '2.3'
|
62
|
+
- - ">="
|
63
|
+
- !ruby/object:Gem::Version
|
64
|
+
version: 2.3.2
|
65
|
+
type: :development
|
66
|
+
prerelease: false
|
67
|
+
version_requirements: !ruby/object:Gem::Requirement
|
68
|
+
requirements:
|
69
|
+
- - "~>"
|
70
|
+
- !ruby/object:Gem::Version
|
71
|
+
version: '2.3'
|
72
|
+
- - ">="
|
73
|
+
- !ruby/object:Gem::Version
|
74
|
+
version: 2.3.2
|
75
|
+
- !ruby/object:Gem::Dependency
|
76
|
+
name: savon
|
77
|
+
requirement: !ruby/object:Gem::Requirement
|
78
|
+
requirements:
|
79
|
+
- - ">="
|
80
|
+
- !ruby/object:Gem::Version
|
81
|
+
version: '2.0'
|
82
|
+
- - "<"
|
83
|
+
- !ruby/object:Gem::Version
|
84
|
+
version: '3.0'
|
85
|
+
type: :runtime
|
86
|
+
prerelease: false
|
87
|
+
version_requirements: !ruby/object:Gem::Requirement
|
88
|
+
requirements:
|
89
|
+
- - ">="
|
90
|
+
- !ruby/object:Gem::Version
|
91
|
+
version: '2.0'
|
92
|
+
- - "<"
|
93
|
+
- !ruby/object:Gem::Version
|
94
|
+
version: '3.0'
|
95
|
+
description:
|
96
|
+
email:
|
97
|
+
- support@kentaa.nl
|
98
|
+
executables: []
|
99
|
+
extensions: []
|
100
|
+
extra_rdoc_files: []
|
101
|
+
files:
|
102
|
+
- ".gitignore"
|
103
|
+
- ".rspec"
|
104
|
+
- ".rubocop.yml"
|
105
|
+
- ".travis.yml"
|
106
|
+
- CHANGELOG.md
|
107
|
+
- Gemfile
|
108
|
+
- LICENSE.txt
|
109
|
+
- README.md
|
110
|
+
- Rakefile
|
111
|
+
- bin/console
|
112
|
+
- bin/setup
|
113
|
+
- docdata-order.gemspec
|
114
|
+
- lib/docdata/order.rb
|
115
|
+
- lib/docdata/order/client.rb
|
116
|
+
- lib/docdata/order/exception.rb
|
117
|
+
- lib/docdata/order/gender.rb
|
118
|
+
- lib/docdata/order/ideal.rb
|
119
|
+
- lib/docdata/order/payment_method.rb
|
120
|
+
- lib/docdata/order/request.rb
|
121
|
+
- lib/docdata/order/response.rb
|
122
|
+
- lib/docdata/order/urls.rb
|
123
|
+
- lib/docdata/order/version.rb
|
124
|
+
homepage: https://github.com/KentaaNL/docdata-order
|
125
|
+
licenses:
|
126
|
+
- MIT
|
127
|
+
metadata: {}
|
128
|
+
post_install_message:
|
129
|
+
rdoc_options: []
|
130
|
+
require_paths:
|
131
|
+
- lib
|
132
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
133
|
+
requirements:
|
134
|
+
- - ">="
|
135
|
+
- !ruby/object:Gem::Version
|
136
|
+
version: 2.0.0
|
137
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
138
|
+
requirements:
|
139
|
+
- - ">="
|
140
|
+
- !ruby/object:Gem::Version
|
141
|
+
version: '0'
|
142
|
+
requirements: []
|
143
|
+
rubyforge_project:
|
144
|
+
rubygems_version: 2.6.14
|
145
|
+
signing_key:
|
146
|
+
specification_version: 4
|
147
|
+
summary: Ruby client for the Docdata Order API
|
148
|
+
test_files: []
|