docdata 0.0.1 → 0.0.2
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 +4 -4
- data/.coveralls.yml +2 -0
- data/.gitignore +4 -1
- data/.travis.yml +10 -0
- data/LICENSE +1 -1
- data/README.md +173 -7
- data/Rakefile +8 -0
- data/docdata.gemspec +18 -11
- data/lib/docdata.rb +74 -1
- data/lib/docdata/bank.rb +27 -0
- data/lib/docdata/config.rb +41 -0
- data/lib/docdata/docdata_error.rb +8 -0
- data/lib/docdata/engine.rb +13 -0
- data/lib/docdata/ideal.rb +40 -0
- data/lib/docdata/line_item.rb +99 -0
- data/lib/docdata/payment.rb +196 -0
- data/lib/docdata/response.rb +173 -0
- data/lib/docdata/shopper.rb +112 -0
- data/lib/docdata/version.rb +1 -1
- data/lib/docdata/xml/bank-list.xml +39 -0
- data/lib/docdata/xml/cancel.xml.erb +9 -0
- data/lib/docdata/xml/create.xml.erb +98 -0
- data/lib/docdata/xml/start.xml.erb +67 -0
- data/lib/docdata/xml/status.xml.erb +9 -0
- data/php-example/create.xml.erb +140 -0
- data/php-example/index.html +78 -0
- data/php-example/process.php +182 -0
- data/php-example/return.php +36 -0
- data/php-example/soap.rb +21 -0
- data/spec/config_spec.rb +53 -0
- data/spec/ideal_spec.rb +19 -0
- data/spec/line_item_spec.rb +55 -0
- data/spec/payment_spec.rb +162 -0
- data/spec/response_spec.rb +206 -0
- data/spec/shopper_spec.rb +50 -0
- data/spec/spec_helper.rb +36 -0
- data/spec/xml/status-canceled-creditcard.xml +34 -0
- data/spec/xml/status-canceled-ideal.xml +29 -0
- data/spec/xml/status-new.xml +20 -0
- data/spec/xml/status-paid-creditcard.xml +33 -0
- data/spec/xml/status-paid-ideal.xml +33 -0
- data/spec/xml/status-paid-sofort.xml +33 -0
- metadata +145 -13
- data/LICENSE.txt +0 -22
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c5ff4754891764a2fadf457caa3103234ab0ff66
|
4
|
+
data.tar.gz: 4a88eccbd3b38ca964800661cbff4f8caa01d856
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 14bb38e8034b1b17ce035e0e2a49637491622a699556b1886aa803bedd78e52685de32fa2cb4110c975cea5c8bb52d29d7e46af219b200f0ad1f4e0911042ab3
|
7
|
+
data.tar.gz: bf6a93bb98864ffb8a576bf6c9e4ef07e6832fc3221d1cd5805302dcd21bc0fd0da042f11ef17dcdff66b25d9ee3017775ec4dfcfd7328cbe24c04e9be7cbff7
|
data/.coveralls.yml
ADDED
data/.gitignore
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
*.gem
|
2
2
|
*.rbc
|
3
|
+
.DS_Store
|
3
4
|
.bundle
|
4
5
|
.config
|
5
6
|
.yardoc
|
@@ -7,11 +8,13 @@ Gemfile.lock
|
|
7
8
|
InstalledFiles
|
8
9
|
_yardoc
|
9
10
|
coverage
|
10
|
-
doc/
|
11
11
|
lib/bundler/man
|
12
12
|
pkg
|
13
|
+
doc
|
13
14
|
rdoc
|
14
15
|
spec/reports
|
15
16
|
test/tmp
|
16
17
|
test/version_tmp
|
17
18
|
tmp
|
19
|
+
spec/vcr_cassettes
|
20
|
+
test-credentials.yaml
|
data/.travis.yml
ADDED
@@ -0,0 +1,10 @@
|
|
1
|
+
language: ruby
|
2
|
+
script: bundle exec rake --trace
|
3
|
+
rvm:
|
4
|
+
- '2.0'
|
5
|
+
env:
|
6
|
+
global:
|
7
|
+
- secure: TIDimYgwlRDIMSeNUDsc3Bwb1dCSdfyF89clBbGssrolmxDSOMCWEkKg+XVeiR8ZTaprule80X35rw8xqoNqpYuZedH0Z6owu1JQ6C3XkUW9TXVhcIQ3WF7KF8YVXwSLYTf9W4F9j8KNW8azb2PmmuLbDqmqAhBxMsG+i1hgPaw=
|
8
|
+
- secure: ZrkG1/8uInY6xiP8xD7HhjDxgxmvbxRHdmzveN/qh9CIsOjCAESfgjd9WjiP8IiW2/G5tYRkVeqYijDLnTkWuyn2lsiWRjE+CflwqTo8XHQCKLCKGbLJzR13i+ulos5ByjUV7OVPTZ241Lxaaw7JBgUgFP3BUqA0127pX8mxpm0=
|
9
|
+
- secure: MQLynyivQIoClPKv3mA62S3E3SVR1ho/8rQ3xs43fsT4PNClwftOO+fRiH0djkmZ4dzJSAD5H70ikcAJoOQ3dAul2+xA5uPAt4AUBk0sindcT2PeEnjPIH9rt/AxLYG67MWZihTr2xcQ38xh6nNJZslyFSglntCTFPmyBy3D0KM=
|
10
|
+
- secure: FrWAE8ZvvBnI6+VwxdBZIHQwQPQKOqFMP9g3XVMyJOPCF4HWlzBor1e5MZ9UquVYaL+/2OL0aDxhgN33y0YsX3/2c5Z25cPGglzE3VsPzRdzDqarwPEz/tEzTYG/bKKPIEI9q+cKQNnSBuMtk4EELBmOJ9iA8jPD0OCNgRedlRw=
|
data/LICENSE
CHANGED
data/README.md
CHANGED
@@ -1,6 +1,12 @@
|
|
1
|
-
#
|
1
|
+
# Docdata
|
2
|
+
[](http://travis-ci.org/henkm/docdata)
|
3
|
+
[](http://badge.fury.io/rb/docdata)
|
4
|
+
[](https://codeclimate.com/github/henkm/docdata)
|
5
|
+
[](https://coveralls.io/r/henkm/docdata)
|
2
6
|
|
3
|
-
|
7
|
+
Docdata is a Ruby binder for Docdata Payments. Current status: **in progress, not stable**.
|
8
|
+
|
9
|
+
This gem relies on the awesom Savon gem to communicate with Docdata Payments' SOAP API.
|
4
10
|
|
5
11
|
## Installation
|
6
12
|
|
@@ -16,14 +22,174 @@ Or install it yourself as:
|
|
16
22
|
|
17
23
|
$ gem install docdata
|
18
24
|
|
19
|
-
##
|
25
|
+
## Workflow
|
26
|
+
Each transaction consists of 2 - optionally 3 - parts:
|
27
|
+
|
28
|
+
- `Docdata::Shopper` (details about the shopper: name, email, etc.)
|
29
|
+
- `Docdata::Payment` (details about the payment: currency, gross amount, etc.)
|
30
|
+
- `Docdata::LineItem` (optionally list the products of this payment) **currently not working!**
|
31
|
+
|
32
|
+
|
33
|
+
The general workflow is as follows:
|
34
|
+
|
35
|
+
1. Set up a `Docdata::Shopper` object with the details of your shopper: `@shopper = Docdata::Shopper.new`
|
36
|
+
2. Set up a `Docdata::Payment` object with the details of your order: `@payment = Docdata::Payment.new(shopper: @shopper)`
|
37
|
+
3. Call the `create` method (`@payment.create`)
|
38
|
+
4. On success, store the payment key and use `@payment.redirect_url` to redirect the consumer to the transaction page.
|
39
|
+
5. When the consumer gets back to your application, use the `Docdata::Payment.find("PA1M3NTK3Y").status.paid` to check if the order was paid for.
|
40
|
+
|
41
|
+
## Parameters
|
42
|
+
All the payment details that Docdata Payments requires, are - obviously - also required to make payments via this gem.
|
43
|
+
|
44
|
+
#### Docdata::Shopper:
|
45
|
+
| Name | Type | Required | Defaults to |
|
46
|
+
|-----------|------------|---------|----|
|
47
|
+
| id | String (ID for own reference) | Yes | |
|
48
|
+
| first_name | String | Yes | First Name |
|
49
|
+
| last_name | String | Yes | Last Name |
|
50
|
+
| street | String | Yes | Main Street |
|
51
|
+
| house_number | String | Yes | 123 |
|
52
|
+
| postal_code | String | Yes | 2244 |
|
53
|
+
| city | String | Yes | City |
|
54
|
+
| country_code | String (ISO country code) | Yes | NL |
|
55
|
+
| language_code | String (ISO language code) | Yes | nl |
|
56
|
+
| email | String | Yes | random@example.com |
|
57
|
+
|
58
|
+
#### Docdata::Payment:
|
59
|
+
| Name | Type | Required |
|
60
|
+
|-----------|------------|---------|
|
61
|
+
| amount | Integer (amount in cents) | Yes |
|
62
|
+
| currency | String (ISO currency code) | Yes |
|
63
|
+
| order_reference | String (your own unique reference) | Yes |
|
64
|
+
| profile | String (name of your Docdata Payment profile)| Yes |
|
65
|
+
| shopper | Docdata::Shopper | Yes |
|
66
|
+
| line_items | Array (of Docdata::LineItem objects) | No |
|
67
|
+
| bank_id | String | No |
|
68
|
+
| prefered_payment_method | String | No |
|
69
|
+
| key | String (is availabel after successful 'create' action) | No (readonly)
|
70
|
+
|
71
|
+
|
72
|
+
## Default values
|
73
|
+
A quick warning about the default values for the Shopper object: **For some payment methods, Docdata Payments needs the actual information in order for the payment to take place.**
|
74
|
+
|
75
|
+
If you use `GIROPAY`, `SEPA` and `AFTERPAY` this is the case. (Maybe also in other payment methods, please let me know!)
|
76
|
+
|
77
|
+
## Example usage in Rails application
|
78
|
+
The example below assumes you have your application set up with a Order model, which contains the information needed for this transaction (amount, name, etc.).
|
79
|
+
```ruby
|
80
|
+
# orders_controller.rb
|
81
|
+
def start_transaction
|
82
|
+
# find the order from your database
|
83
|
+
@order = Order.find(params[:id])
|
84
|
+
|
85
|
+
# initialize a shopper, use details from your order
|
86
|
+
shopper = Docdata::Shopper.new(first_name: @order.first_name, last_name: @order.last_name)
|
87
|
+
|
88
|
+
# set up a payment
|
89
|
+
@payment = Docdata::Payment.new(
|
90
|
+
amount: @order.total,
|
91
|
+
currency: @order.currency,
|
92
|
+
shopper: shopper,
|
93
|
+
profile: "My Default Profile",
|
94
|
+
order_reference: "order ##{@order.id}"
|
95
|
+
)
|
96
|
+
|
97
|
+
# create the payment via the docdata api and collect the result
|
98
|
+
result = @payment.create
|
99
|
+
|
100
|
+
if result.success?
|
101
|
+
# Set the transaction key for future reference
|
102
|
+
@order.update_column :docdata_key, result.key
|
103
|
+
# redirect the user to the docdata payment page
|
104
|
+
redirect_to @payment.redirect_url
|
105
|
+
else
|
106
|
+
# TODO: Display the error and warn the user that something went wrong.
|
107
|
+
end
|
108
|
+
end
|
109
|
+
```
|
110
|
+
|
111
|
+
## Ideal
|
112
|
+
|
113
|
+
For transactions in the Netherlands, iDeal is the most common option. To redirect a user directly to the bank page (skipping the Docdata web menu page), you can ask your user to choose a bank from any of the banks listed in the `Docdata::Ideal.banks` method.
|
114
|
+
|
115
|
+
In `Docdata::Payment` you can set `bank_id` to any value. If you do, the redirect URI will redirect your user directly to the bank page.
|
116
|
+
|
117
|
+
Example code:
|
118
|
+
```ruby
|
119
|
+
# orders_controller.rb
|
120
|
+
def ideal_checkout
|
121
|
+
@order = Order.find(params[:order_id])
|
122
|
+
@banks = Docdata::Ideal.banks
|
123
|
+
end
|
124
|
+
|
125
|
+
def start_ideal_transaction
|
126
|
+
@order = Order.find(params[:order_id])
|
127
|
+
|
128
|
+
# initialize a shopper, use details from your order
|
129
|
+
shopper = Docdata::Shopper.new(first_name: @order.first_name, last_name: @order.last_name)
|
130
|
+
|
131
|
+
# set up a payment
|
132
|
+
@payment = Docdata::Payment.new(
|
133
|
+
amount: @order.total,
|
134
|
+
currency: @order.currency,
|
135
|
+
shopper: shopper,
|
136
|
+
profile: "My Default Profile",
|
137
|
+
order_reference: "order ##{@order.id}",
|
138
|
+
bank_id: params[:bank_id],
|
139
|
+
default_act: true # redirect directly to the bank, skipping the Docdata web menu
|
140
|
+
)
|
141
|
+
|
142
|
+
# create the payment via the docdata api and collect the result
|
143
|
+
result = @payment.create
|
144
|
+
|
145
|
+
if result.success?
|
146
|
+
# Set the transaction key for future reference
|
147
|
+
@order.update_column :docdata_key, result.key
|
148
|
+
# redirect the user to the bank page
|
149
|
+
redirect_to @payment.redirect_url
|
150
|
+
else
|
151
|
+
# TODO: Display the error and warn the user that something went wrong.
|
152
|
+
end
|
153
|
+
end
|
154
|
+
```
|
155
|
+
|
156
|
+
View template (ideal_checkout.html.erb):
|
157
|
+
|
158
|
+
```erb
|
159
|
+
<h2>Choose your bank</h2>
|
160
|
+
<%= form_tag start_ideal_transaction_path, method: :post, target: "_blank" do %>
|
161
|
+
<%= select_tag "bank_id", options_from_collection_for_select(@banks, "id", "name") %>
|
162
|
+
<%= hidden_field_tag :order_id, @order.id %>
|
163
|
+
<%= submit_tag "Proceed to checkout" %>
|
164
|
+
<% end %>
|
165
|
+
```
|
166
|
+
|
167
|
+
## Tips and samples
|
168
|
+
|
169
|
+
#### Redirect directly to bank page (skip Docdata web menu)
|
170
|
+
When making a new `Docdata::Payment`, use the `default_act` parameter to redirect consumers directly to the acquirers website. Example:
|
171
|
+
|
172
|
+
```ruby
|
173
|
+
@payment = Docdata::Payment.new(
|
174
|
+
amount: @order.total,
|
175
|
+
currency: @order.currency,
|
176
|
+
shopper: shopper,
|
177
|
+
profile: "My Default Profile",
|
178
|
+
order_reference: "order ##{@order.id}",
|
179
|
+
bank_id: params[:bank_id],
|
180
|
+
default_act: true # redirect directly to the bank, skipping the Docdata web menu
|
181
|
+
)
|
182
|
+
```
|
20
183
|
|
21
|
-
|
184
|
+
#### Retrieve a list of iDeal banks to show
|
185
|
+
`Docata::Ideal.banks` returns an Array.
|
22
186
|
|
23
187
|
## Contributing
|
24
188
|
|
25
189
|
1. Fork it
|
26
190
|
2. Create your feature branch (`git checkout -b my-new-feature`)
|
27
|
-
3.
|
28
|
-
4.
|
29
|
-
5.
|
191
|
+
3. Make changes, document them and add tests (rspec)
|
192
|
+
4. Run the entire test suite and make sure all tests pass
|
193
|
+
5. Commit your changes (`git commit -am 'Add some feature'`)
|
194
|
+
6. Push to the branch (`git push origin my-new-feature`)
|
195
|
+
7. Create new Pull Request
|
data/Rakefile
CHANGED
data/docdata.gemspec
CHANGED
@@ -8,23 +8,30 @@ Gem::Specification.new do |spec|
|
|
8
8
|
spec.version = Docdata::VERSION
|
9
9
|
spec.authors = ["Henk Meijer", "Eskes Media"]
|
10
10
|
spec.email = ["meijerhenk@gmail.com"]
|
11
|
-
spec.description = %q{A ruby binder for the
|
12
|
-
spec.summary = %q{This gem provides a ruby
|
13
|
-
spec.homepage = ""
|
11
|
+
spec.description = %q{A ruby binder for the Docdata Payment API.}
|
12
|
+
spec.summary = %q{This gem provides a ruby interface for the Docdata Payment API. You basically create a Payment object and receive a reirect_url back to take your users to the checkout page.}
|
13
|
+
spec.homepage = "http://rdoc.info/github/henkm/docdata/"
|
14
14
|
spec.license = "MIT"
|
15
15
|
|
16
|
+
spec.files = `git ls-files`.split($/)
|
17
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
18
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
|
+
spec.require_paths = ["lib"]
|
20
|
+
|
21
|
+
spec.add_development_dependency "bundler" #, "~> 1.3"
|
22
|
+
spec.add_development_dependency "rake"
|
16
23
|
spec.add_development_dependency "rspec"
|
17
24
|
spec.add_development_dependency "vcr"
|
18
25
|
spec.add_development_dependency "fakeweb"
|
19
26
|
spec.add_development_dependency "coveralls"
|
20
27
|
spec.add_development_dependency "simplecov"
|
21
28
|
spec.add_development_dependency "yard"
|
29
|
+
spec.add_development_dependency "rubyntlm"
|
22
30
|
|
23
|
-
spec.
|
24
|
-
spec.
|
25
|
-
spec.
|
26
|
-
spec.
|
27
|
-
|
28
|
-
spec.
|
29
|
-
|
30
|
-
end
|
31
|
+
# spec.add_runtime_dependency 'savon', git: 'savonrb/savon'
|
32
|
+
spec.add_dependency 'savon', '~> 2.0'
|
33
|
+
spec.add_dependency 'nori'
|
34
|
+
spec.add_dependency 'veto'
|
35
|
+
spec.add_dependency 'nokogiri'
|
36
|
+
spec.add_dependency("railties")
|
37
|
+
end
|
data/lib/docdata.rb
CHANGED
@@ -1,5 +1,78 @@
|
|
1
|
+
# Libraries
|
2
|
+
require 'ostruct'
|
3
|
+
require 'rails'
|
4
|
+
require 'savon'
|
5
|
+
require 'active_support/dependencies'
|
6
|
+
require 'active_support'
|
7
|
+
require 'open-uri'
|
8
|
+
require 'nokogiri'
|
9
|
+
require 'veto'
|
10
|
+
|
11
|
+
|
12
|
+
# Files
|
1
13
|
require "docdata/version"
|
14
|
+
require "docdata/docdata_error"
|
15
|
+
require "docdata/shopper"
|
16
|
+
require "docdata/payment"
|
17
|
+
require "docdata/line_item"
|
18
|
+
require "docdata/response"
|
19
|
+
require "docdata/ideal"
|
20
|
+
require "docdata/bank"
|
2
21
|
|
22
|
+
include Savon
|
23
|
+
|
24
|
+
#
|
25
|
+
# Docdata Module
|
26
|
+
#
|
3
27
|
module Docdata
|
4
|
-
|
28
|
+
API_VERSION = 1
|
29
|
+
|
30
|
+
# @return [String] Your DocData username
|
31
|
+
# @note The is a required parameter.
|
32
|
+
mattr_accessor :username
|
33
|
+
@@username = nil
|
34
|
+
|
35
|
+
# @return [String] Your DocData password
|
36
|
+
mattr_accessor :password
|
37
|
+
@@password = nil
|
38
|
+
|
39
|
+
# @return [Boolean] Test mode switch
|
40
|
+
mattr_accessor :test_mode
|
41
|
+
@@test_mode = true
|
42
|
+
|
43
|
+
# @param [String] Set the url of your website where docdata can send messages to
|
44
|
+
mattr_accessor :return_url
|
45
|
+
@@return_url = nil
|
46
|
+
|
47
|
+
# returns the version number
|
48
|
+
def self.version
|
49
|
+
VERSION
|
50
|
+
end
|
51
|
+
|
52
|
+
# sets up configuration
|
53
|
+
def self.setup
|
54
|
+
yield self
|
55
|
+
end
|
56
|
+
|
57
|
+
def self.url
|
58
|
+
if test_mode
|
59
|
+
"https://test.docdatapayments.com/ps/services/paymentservice/1_1?wsdl"
|
60
|
+
else
|
61
|
+
"https://www.docdatapayments.com/ps/services/paymentservice/1_1?wsdl"
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
# For testing purpose only: set the username and password
|
66
|
+
# in environment variables to make the tests pass with your test
|
67
|
+
# credentials.
|
68
|
+
def self.set_credentials_from_environment
|
69
|
+
self.password = ENV["DOCDATA_PASSWORD"]
|
70
|
+
self.username = ENV["DOCDATA_USERNAME"]
|
71
|
+
self.return_url = ENV["DOCDATA_RETURN_URL"]
|
72
|
+
end
|
73
|
+
|
74
|
+
def self.client
|
75
|
+
Savon.client(wsdl: url)
|
76
|
+
end
|
77
|
+
|
5
78
|
end
|
data/lib/docdata/bank.rb
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
module Docdata
|
2
|
+
#
|
3
|
+
# Object representing a "Bank" object with attributes provided by Mollie
|
4
|
+
#
|
5
|
+
# @example
|
6
|
+
# Bank.new({
|
7
|
+
# :id => "0031",
|
8
|
+
# :name => "ABN AMRO"
|
9
|
+
# })
|
10
|
+
class Bank
|
11
|
+
# @return [String] The id of the bank provided by Mollie.
|
12
|
+
attr_accessor :id
|
13
|
+
# @return [String] The name of the bank.
|
14
|
+
attr_accessor :name
|
15
|
+
|
16
|
+
#
|
17
|
+
# Initializer to transform a +Hash+ into an Bank object
|
18
|
+
#
|
19
|
+
# @param [Hash] values
|
20
|
+
def initialize(values=nil)
|
21
|
+
return if values.nil?
|
22
|
+
|
23
|
+
@id = values[:id].to_s
|
24
|
+
@name = values[:name].to_s
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
#
|
2
|
+
# Configuration object for storing some parameters required for making transactions
|
3
|
+
#
|
4
|
+
module Docdata::Config
|
5
|
+
class << self
|
6
|
+
# @return [String] Your DocData username
|
7
|
+
# @note The is a required parameter.
|
8
|
+
attr_accessor :username
|
9
|
+
# @return [String] Your DocData password
|
10
|
+
attr_accessor :password
|
11
|
+
# @return [Boolean] Test mode switch
|
12
|
+
attr_accessor :test_mode
|
13
|
+
|
14
|
+
|
15
|
+
# Set's the default value's to nil and false
|
16
|
+
# @return [Hash] configuration options
|
17
|
+
def init!
|
18
|
+
@defaults = {
|
19
|
+
:@username => nil,
|
20
|
+
:@password => nil,
|
21
|
+
:@test_mode => true
|
22
|
+
}
|
23
|
+
end
|
24
|
+
|
25
|
+
# Resets the value's to there previous value (instance_variable)
|
26
|
+
# @return [Hash] configuration options
|
27
|
+
def reset!
|
28
|
+
@defaults.each { |key, value| instance_variable_set(key, value) }
|
29
|
+
end
|
30
|
+
|
31
|
+
# Set's the new value's as instance variables
|
32
|
+
# @return [Hash] configuration options
|
33
|
+
def update!
|
34
|
+
@defaults.each do |key, value|
|
35
|
+
instance_variable_set(key, value) unless instance_variable_defined?(key)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
init!
|
40
|
+
reset!
|
41
|
+
end
|