wheretocard 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 +10 -0
- data/.rspec +2 -0
- data/.travis.yml +4 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +21 -0
- data/README.md +102 -0
- data/Rakefile +6 -0
- data/bin/console +14 -0
- data/bin/setup +7 -0
- data/documentation/Ticketing order interface specification v1.60.pdf +0 -0
- data/documentation/test_wtc_api.php +243 -0
- data/lib/wheretocard.rb +39 -0
- data/lib/wheretocard/client.rb +66 -0
- data/lib/wheretocard/config.rb +8 -0
- data/lib/wheretocard/line_item.rb +47 -0
- data/lib/wheretocard/order.rb +113 -0
- data/lib/wheretocard/response.rb +114 -0
- data/lib/wheretocard/version.rb +3 -0
- data/lib/wheretocard/wheretocard_error.rb +7 -0
- data/lib/wheretocard/xml/order_request.xml.erb +44 -0
- data/wheretocard.gemspec +45 -0
- metadata +192 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 9525b0d8a16b19b0ca6a24e94c14c0695fbad479
|
4
|
+
data.tar.gz: e023fb76f40ed4ed084f710b0f8845e4364904c1
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 74b996595133f49ea3a67b3fcd64f7d0039676995d16ff6670d86554143250568a3ea586dcb561cd48feb45ceff6e585d1776ce8a0072623040ccf888cbd0b8e
|
7
|
+
data.tar.gz: b65fb0053e6d10167f7ac99832f79e10d0a9ea31d40015a32b15883de515943b7a7a7998ac8ec9a38534b8772fdbc051e8819cdf4cfac36eb44625d836154472
|
data/.gitignore
ADDED
data/.rspec
ADDED
data/.travis.yml
ADDED
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2016 Henk Meijer
|
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,102 @@
|
|
1
|
+
|
2
|
+
# Wheretocard
|
3
|
+
|
4
|
+
The Wheretocard gem is a straight forward ruby binder for the Wheretocard API.
|
5
|
+
|
6
|
+
|
7
|
+
## Installation
|
8
|
+
|
9
|
+
Add this line to your application's Gemfile:
|
10
|
+
|
11
|
+
```ruby
|
12
|
+
gem 'wheretocard'
|
13
|
+
```
|
14
|
+
|
15
|
+
And then execute:
|
16
|
+
|
17
|
+
$ bundle
|
18
|
+
|
19
|
+
Or install it yourself as:
|
20
|
+
|
21
|
+
$ gem install wheretocard
|
22
|
+
|
23
|
+
## Usage
|
24
|
+
|
25
|
+
To request two barcodes from two different ticket kinds (4 barcodes in total), you can do the following:
|
26
|
+
|
27
|
+
|
28
|
+
```ruby
|
29
|
+
# Setup the WtC client with credentials
|
30
|
+
@wtc_client = Wheretocard::Client.new(
|
31
|
+
username: yourusername,
|
32
|
+
password: yourpassword,
|
33
|
+
client_code: yourclientcode,
|
34
|
+
case_code: yourcasecode
|
35
|
+
)
|
36
|
+
|
37
|
+
# Check the credentials first, without making test orders
|
38
|
+
@order.check_credentials("TICKET_KIND_1_CODE") #returns true or false
|
39
|
+
|
40
|
+
# Initialize a new OrderRequest
|
41
|
+
@order_request = @wtc_client.order_request
|
42
|
+
@order_request.first_name = "Foo"
|
43
|
+
@order_request.last_name = "Bar"
|
44
|
+
@order_request.email = "foobar@example.org"
|
45
|
+
@order_request.delivery_type = "BARCODE" # ["TEXTCODE","BARCODE"]
|
46
|
+
|
47
|
+
# Add line itmes to the request
|
48
|
+
# Please note: the price is in cents (currency is EUR)
|
49
|
+
@order_request.add_line_item(
|
50
|
+
product_code: TICKET_KIND_1_CODE,
|
51
|
+
quantity: 2,
|
52
|
+
price: 1250,
|
53
|
+
description: Action Description,
|
54
|
+
valid_from: Time.now,
|
55
|
+
valid_until: Time.now + 3.months
|
56
|
+
)
|
57
|
+
|
58
|
+
# It is also possible to not let WtC pick a barcode,
|
59
|
+
# but to submit your own barcode by adding the 'barcode' param
|
60
|
+
@order_request.add_line_item(
|
61
|
+
product_code: TICKET_KIND_3_CODE,
|
62
|
+
quantity: 2,
|
63
|
+
price: 1750,
|
64
|
+
description: Action Description,
|
65
|
+
barcode: "ABC12345"
|
66
|
+
valid_from: Time.now,
|
67
|
+
valid_until: Time.now + 3.months
|
68
|
+
)
|
69
|
+
|
70
|
+
|
71
|
+
# Submit the request and receive a response object
|
72
|
+
@response = @order_request.submit
|
73
|
+
|
74
|
+
# redirect the consumer to the PDF download page:
|
75
|
+
if @response.success?
|
76
|
+
redirect_to @response.url
|
77
|
+
# => https://ticketing.wheretocard.nl/ticketService/print/printTicket?refId=xxx&ui=yyy
|
78
|
+
else
|
79
|
+
# TODO: handle exception
|
80
|
+
end
|
81
|
+
|
82
|
+
```
|
83
|
+
|
84
|
+
## Development
|
85
|
+
|
86
|
+
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.
|
87
|
+
|
88
|
+
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).
|
89
|
+
|
90
|
+
## Contributing
|
91
|
+
|
92
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/henkm/wheretocard.
|
93
|
+
|
94
|
+
|
95
|
+
## License
|
96
|
+
|
97
|
+
The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
|
98
|
+
|
99
|
+
## Credits and disclaimer
|
100
|
+
|
101
|
+
This gem is made with love by the smart people at [Eskes Media B.V.](http://www.eskesmedia.nl) and [dagjewegtickets.nl](https://www.dagjewegtickets.nl)
|
102
|
+
Wheretocard is not involved with this project and has no affiliation with Eskes Media B.V.
|
data/Rakefile
ADDED
data/bin/console
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require "bundler/setup"
|
4
|
+
require "wheretocard"
|
5
|
+
|
6
|
+
# You can add fixtures and/or initialization code here to make experimenting
|
7
|
+
# with your gem easier. You can also use a different console, if you like.
|
8
|
+
|
9
|
+
# (If you use this, don't forget to add pry to your Gemfile!)
|
10
|
+
# require "pry"
|
11
|
+
# Pry.start
|
12
|
+
|
13
|
+
require "irb"
|
14
|
+
IRB.start
|
data/bin/setup
ADDED
Binary file
|
@@ -0,0 +1,243 @@
|
|
1
|
+
<?php
|
2
|
+
|
3
|
+
// test_wtc_api.php
|
4
|
+
// 20160410/PPM Created
|
5
|
+
|
6
|
+
// Warning: This scripts doesn't work without valid credentials in wtc_parameters
|
7
|
+
|
8
|
+
|
9
|
+
test_wtc_api();
|
10
|
+
|
11
|
+
|
12
|
+
// test_wtc_api()
|
13
|
+
// Description: Send request, show result
|
14
|
+
|
15
|
+
|
16
|
+
|
17
|
+
function xml_entities($string) {
|
18
|
+
return strtr(
|
19
|
+
$string,
|
20
|
+
array(
|
21
|
+
"<" => "<",
|
22
|
+
">" => ">",
|
23
|
+
'"' => """,
|
24
|
+
"'" => "'",
|
25
|
+
"&" => "&",
|
26
|
+
)
|
27
|
+
);
|
28
|
+
}
|
29
|
+
|
30
|
+
function convertdate_last2to($date_last){
|
31
|
+
$date_to = date('Y-m-d', strtotime($date_last.' + 1 day'));
|
32
|
+
|
33
|
+
return $date_to;
|
34
|
+
}
|
35
|
+
|
36
|
+
|
37
|
+
function test_wtc_api(){
|
38
|
+
|
39
|
+
// Initialize
|
40
|
+
$fname = __FUNCTION__;
|
41
|
+
$dbg = 1;
|
42
|
+
|
43
|
+
if($dbg>0){ echo "$fname()<br>\n"; }
|
44
|
+
|
45
|
+
// WtC parameters
|
46
|
+
$wtc_client_code = 'CLIENT_TICKETCOUNTER_API';
|
47
|
+
$wtc_case_code = 'TCAPI_CLIENT_NAME';
|
48
|
+
$wtc_client_username = 'username_api';
|
49
|
+
$wtc_client_password = 'rand0mpa55w0rd';
|
50
|
+
$wtc_request_url = 'https://ticketing.wheretocard.nl/ticketService/submitOrder';
|
51
|
+
|
52
|
+
/*
|
53
|
+
CLIENT_TICKETCOUNTER_API
|
54
|
+
Case:
|
55
|
+
TCAPI_CLIENT_NAME
|
56
|
+
Apicodes:
|
57
|
+
TICKET_KIND_1_API_CODE
|
58
|
+
TICKET_KIND_2_API_CODE
|
59
|
+
*/
|
60
|
+
|
61
|
+
// Construct name
|
62
|
+
$order_code = '1234';
|
63
|
+
$name = 'My Name';
|
64
|
+
$email = 'myemail@myemail.com';
|
65
|
+
$street = 'My Street';
|
66
|
+
$house_number = 123;
|
67
|
+
$postal_code = '1234AB';
|
68
|
+
$city = 'My City';
|
69
|
+
|
70
|
+
// To xml
|
71
|
+
$xml_order_code = xml_entities($order_code);
|
72
|
+
$xml_name = xml_entities($name);
|
73
|
+
$xml_email = xml_entities($email);
|
74
|
+
$xml_street = xml_entities($street);
|
75
|
+
$xml_house_number = xml_entities($house_number);
|
76
|
+
$xml_postal_code = xml_entities($postal_code);
|
77
|
+
$xml_city = xml_entities($city);
|
78
|
+
|
79
|
+
$properties_first_name = '';
|
80
|
+
$properties_infix = '';
|
81
|
+
$properties_last_name = $xml_name;
|
82
|
+
$properties_email = $xml_email;
|
83
|
+
$properties_street = $xml_street;
|
84
|
+
$properties_house_number = $xml_house_number;
|
85
|
+
$properties_postal_code = $xml_postal_code;
|
86
|
+
$properties_city = $xml_city;
|
87
|
+
|
88
|
+
if($dbg>0){ echo "$fname: prepare xml request ...<br>\n"; }
|
89
|
+
|
90
|
+
// Construct orderlines by constructing orderline items
|
91
|
+
// <orderline code="{{ reservation.producttypeperiodtime.producttypeperiod.producttype.code }}" ticket-ref="{{ reservation.number }}"><quantity>1</quantity><price>{{ reservation.price|makeCents }}</price><action>{{ reservation.producttypeperiodtime.producttypeperiod.producttype.name }}</action><validPeriod from="{{ reservation.reservationdate|date:"Y-m-d" }}T00:00:00" to="{{ reservation.reservationdate|addDays:1|date:"Y-m-d" }}T00:00:00"/></orderline>
|
92
|
+
|
93
|
+
$orderitems = array();
|
94
|
+
// Product#1
|
95
|
+
$orderitems[] = array(
|
96
|
+
'product_code' => 'TICKET_KIND_1_API_CODE',
|
97
|
+
'product_name' => 'My Ticket',
|
98
|
+
'quantity' => 1,
|
99
|
+
'unitprice' => 1150,
|
100
|
+
'dated_from' => '2016-04-10',
|
101
|
+
'dated_last' => '2016-06-30',
|
102
|
+
);
|
103
|
+
// Product#2
|
104
|
+
$orderitems[] = array(
|
105
|
+
'product_code' => 'TICKET_KIND_2_API_CODE',
|
106
|
+
'product_name' => 'My Ticket 2',
|
107
|
+
'quantity' => 2,
|
108
|
+
'unitprice' => 2250,
|
109
|
+
'dated_from' => '2016-04-10',
|
110
|
+
'dated_last' => '2016-06-30',
|
111
|
+
|
112
|
+
);
|
113
|
+
|
114
|
+
$orderlines = array();
|
115
|
+
foreach($orderitems as $orderitem){
|
116
|
+
|
117
|
+
$xml_orderline_ticketref = 23;
|
118
|
+
|
119
|
+
$xml_orderline_code = $orderitem['product_code'];
|
120
|
+
|
121
|
+
$xml_quantity = $orderitem['quantity'];
|
122
|
+
$orderline_quantity =<<<EOT
|
123
|
+
<quantity>$xml_quantity</quantity>
|
124
|
+
EOT;
|
125
|
+
|
126
|
+
$xml_price = $orderitem['unitprice'];
|
127
|
+
$orderline_price =<<<EOT
|
128
|
+
<price>$xml_price</price>
|
129
|
+
EOT;
|
130
|
+
|
131
|
+
$validPeriod_from = $orderitem['dated_from'].'T00:00:00';
|
132
|
+
$validPeriod_to = convertdate_last2to($orderitem['dated_from']).'T00:00:00';
|
133
|
+
$orderline_validPeriod =<<<EOT
|
134
|
+
<validPeriod from="$validPeriod_from" to="$validPeriod_to"/>
|
135
|
+
EOT;
|
136
|
+
|
137
|
+
$xml_product_name = xml_entities($orderitem['product_name']);
|
138
|
+
$orderline_action =<<<EOT
|
139
|
+
<action>$xml_product_name</action>
|
140
|
+
EOT;
|
141
|
+
|
142
|
+
// Construct orderline
|
143
|
+
$orderline = '<orderline code="'.$xml_orderline_code.'" ticket-ref="'.$xml_orderline_ticketref.'">'.$orderline_quantity.$orderline_price.$orderline_action.$orderline_validPeriod.'</orderline>';
|
144
|
+
|
145
|
+
// Add to list
|
146
|
+
$orderlines[] = $orderline;
|
147
|
+
}
|
148
|
+
|
149
|
+
// Join orderlines
|
150
|
+
$orderlines_list = join("\n", $orderlines);
|
151
|
+
|
152
|
+
$xml_request_data = <<<EOT
|
153
|
+
<orderRequest version="1.0">
|
154
|
+
<client code="$wtc_client_code">
|
155
|
+
<username>$wtc_client_username</username>
|
156
|
+
<password>$wtc_client_password</password>
|
157
|
+
</client>
|
158
|
+
<order referenceId="$xml_order_code">
|
159
|
+
<properties>
|
160
|
+
<property name="FIRST_NAME" value="$properties_first_name"/>
|
161
|
+
<property name="INFIX" value="$properties_infix"/>
|
162
|
+
<property name="LAST_NAME" value="$properties_last_name"/>
|
163
|
+
<property name="EMAIL" value="$properties_email"/>
|
164
|
+
<property name="STREET" value="$properties_street"/>
|
165
|
+
<property name="HOUSE_NUMBER" value="$properties_house_number"/>
|
166
|
+
<property name="POSTAL_CODE" value="$properties_postal_code"/>
|
167
|
+
<property name="CITY" value="$properties_city"/>
|
168
|
+
</properties>
|
169
|
+
<cases>
|
170
|
+
<case code="$wtc_case_code">
|
171
|
+
<orderlines>
|
172
|
+
$orderlines_list
|
173
|
+
</orderlines>
|
174
|
+
</case>
|
175
|
+
</cases>
|
176
|
+
</order>
|
177
|
+
<tickets>
|
178
|
+
<ticket ref="23" delivery-channel="WEB" delivery-format="BARCODE">
|
179
|
+
</ticket>
|
180
|
+
</tickets>
|
181
|
+
</orderRequest>
|
182
|
+
EOT;
|
183
|
+
|
184
|
+
if($dbg>0){ echo "$fname: wtc_request_url = ".$wtc_request_url."<br>\n"; }
|
185
|
+
if($dbg>0){ echo "$fname: xml_request_data = ".$xml_request_data; }
|
186
|
+
|
187
|
+
|
188
|
+
$ch = curl_init();
|
189
|
+
curl_setopt($ch, CURLOPT_HTTPHEADER, array('Expect:', 'Content-Type: text/xml'));
|
190
|
+
curl_setopt($ch, CURLOPT_URL, $wtc_request_url);
|
191
|
+
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
|
192
|
+
curl_setopt($ch, CURLOPT_POST, 1);
|
193
|
+
curl_setopt($ch, CURLOPT_TIMEOUT, 30);
|
194
|
+
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
|
195
|
+
curl_setopt($ch, CURLOPT_POSTFIELDS, $xml_request_data);
|
196
|
+
|
197
|
+
$time_start = time();
|
198
|
+
$result = curl_exec($ch);
|
199
|
+
$time_end = time();
|
200
|
+
|
201
|
+
if($dbg>0){ echo "$fname: result = ".$result; }
|
202
|
+
|
203
|
+
$time_diff = $time_end - $time_start;
|
204
|
+
if($dbg>0){ echo "$fname: curl request executed in $time_diff second(s)<br>\n"; }
|
205
|
+
|
206
|
+
$curl_errors = 0;
|
207
|
+
$curl_errors_msg = '';
|
208
|
+
if(curl_errno($ch)){
|
209
|
+
// print curl_error($ch);
|
210
|
+
$curl_errors++;
|
211
|
+
$curl_errors_msg = curl_error($ch);
|
212
|
+
if($dbg>0){ echo "$fname: curl_error = ".$curl_errors_msg."<br>\n"; }
|
213
|
+
$result = '';
|
214
|
+
}else{
|
215
|
+
if($dbg>0){ echo "$fname: NO curl error(s)<br>\n"; }
|
216
|
+
}
|
217
|
+
curl_close($ch);
|
218
|
+
|
219
|
+
$got_ok = 0;
|
220
|
+
$got_url = 0;
|
221
|
+
$url = '';
|
222
|
+
if($curl_errors == 0){
|
223
|
+
// Try to locate OK (= <orderResponse status="OK"> ) in result
|
224
|
+
if(preg_match("/\<\s*orderResponse\s+status\s*\=\s*\"OK\"\\s*[\/]*\s*>/", $result)){
|
225
|
+
$got_ok = 1;
|
226
|
+
|
227
|
+
// Now try to get the URL
|
228
|
+
if(preg_match("/\<\s*comment\s+type\s*\=\s*\"url\"\\s*[\/]*\s*>/", $result)){
|
229
|
+
if(preg_match("/\[CDATA\[http(.*?)\]\]/", $result, $matches)){
|
230
|
+
$got_url = 1;
|
231
|
+
$url = 'http'.$matches[1];
|
232
|
+
}
|
233
|
+
}
|
234
|
+
}
|
235
|
+
}
|
236
|
+
|
237
|
+
if($dbg>0){ echo "$fname: curl_errors = $curl_errors, got_ok = $got_ok, got_url = $got_url, url = ".$url."<br>\n"; }
|
238
|
+
|
239
|
+
}
|
240
|
+
|
241
|
+
|
242
|
+
|
243
|
+
?>
|
data/lib/wheretocard.rb
ADDED
@@ -0,0 +1,39 @@
|
|
1
|
+
# Libraries
|
2
|
+
require 'ostruct'
|
3
|
+
require 'httparty'
|
4
|
+
# require 'uri'
|
5
|
+
# require 'rails'
|
6
|
+
# require 'active_support/dependencies'
|
7
|
+
# require 'active_support'
|
8
|
+
require 'open-uri'
|
9
|
+
require 'nokogiri'
|
10
|
+
# require 'veto'
|
11
|
+
|
12
|
+
|
13
|
+
# Files
|
14
|
+
require "wheretocard/version"
|
15
|
+
require "wheretocard/config"
|
16
|
+
require "wheretocard/engine" if defined?(Rails) && Rails::VERSION::MAJOR.to_i >= 3
|
17
|
+
require "wheretocard/wheretocard_error"
|
18
|
+
require "wheretocard/client"
|
19
|
+
require "wheretocard/order"
|
20
|
+
require "wheretocard/line_item"
|
21
|
+
require "wheretocard/response"
|
22
|
+
|
23
|
+
|
24
|
+
#
|
25
|
+
# Wheretocard Module
|
26
|
+
#
|
27
|
+
module Wheretocard
|
28
|
+
API_VERSION = 1
|
29
|
+
|
30
|
+
# returns the version number
|
31
|
+
def self.version
|
32
|
+
VERSION
|
33
|
+
end
|
34
|
+
|
35
|
+
def self.url
|
36
|
+
"https://ticketing.wheretocard.nl/ticketService/submitOrder"
|
37
|
+
end
|
38
|
+
|
39
|
+
end
|
@@ -0,0 +1,66 @@
|
|
1
|
+
module Wheretocard
|
2
|
+
|
3
|
+
class Client
|
4
|
+
# @note The is a required parameter.
|
5
|
+
attr_accessor :username
|
6
|
+
# @return [String] Your Wheretocard password
|
7
|
+
attr_accessor :password
|
8
|
+
# @return [String] Your Wheretocard client code
|
9
|
+
attr_accessor :client_code
|
10
|
+
# @return [String] Your Wheretocard case code
|
11
|
+
attr_accessor :case_code
|
12
|
+
|
13
|
+
|
14
|
+
#
|
15
|
+
# Initializer to transform a +Hash+ into an Client object
|
16
|
+
#
|
17
|
+
# @param [Hash] args
|
18
|
+
def initialize(args=nil)
|
19
|
+
required_args = [:username, :password, :client_code, :case_code]
|
20
|
+
for arg in required_args
|
21
|
+
if args.nil? || args[arg].nil?
|
22
|
+
raise WheretocardError.new(self), "Insufficient login credentials. Please provide @username, @password, @client_code and @case_code"
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
return if args.nil?
|
27
|
+
args.each do |k,v|
|
28
|
+
instance_variable_set("@#{k}", v) unless v.nil?
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def check_credentials(product_code="")
|
33
|
+
o = order
|
34
|
+
o.add_line_item(
|
35
|
+
price: 0,
|
36
|
+
description: 'Checking credentials [TEST]',
|
37
|
+
ticket_ref: 1234,
|
38
|
+
valid_from: Time.now,
|
39
|
+
valid_until: Time.now + 24*31*3600,
|
40
|
+
product_code: product_code,
|
41
|
+
quantity: 0
|
42
|
+
)
|
43
|
+
begin
|
44
|
+
o.submit
|
45
|
+
rescue WheretocardError => e
|
46
|
+
# return true if the error raised is only about the
|
47
|
+
# number of tickets (cannot be zero)
|
48
|
+
e.to_s.include?("OI_0210")
|
49
|
+
end
|
50
|
+
|
51
|
+
end
|
52
|
+
|
53
|
+
# def order_requests
|
54
|
+
# Wheretocard::Order
|
55
|
+
# end
|
56
|
+
# alias :order_request :order_requests
|
57
|
+
|
58
|
+
def order(args={})
|
59
|
+
Wheretocard::Order.new({client: self}.merge(args))
|
60
|
+
end
|
61
|
+
alias :orders :order
|
62
|
+
alias :new_order :order
|
63
|
+
alias :add_order :order
|
64
|
+
|
65
|
+
end
|
66
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
module Wheretocard
|
2
|
+
#
|
3
|
+
# Object representing a line item with attributes provided by WTC
|
4
|
+
# required args:
|
5
|
+
# - product_code (string)
|
6
|
+
# - price (integer - cents)
|
7
|
+
# - valid_from (DateTime / Date)
|
8
|
+
# - valid_until (DateTime / Date)
|
9
|
+
# - barcode (string) OR quantity (integer)
|
10
|
+
#
|
11
|
+
# @return [Array] Errors
|
12
|
+
class LineItem
|
13
|
+
attr_accessor :errors
|
14
|
+
attr_accessor :product_code
|
15
|
+
# If a barcode is given, it'll be used. There is no check for
|
16
|
+
# uniqueness. If no barcode is given, WtC will generate a unique one.
|
17
|
+
attr_accessor :barcode
|
18
|
+
attr_accessor :quantity
|
19
|
+
attr_accessor :ticket_ref
|
20
|
+
attr_accessor :price
|
21
|
+
attr_accessor :description
|
22
|
+
attr_accessor :valid_from
|
23
|
+
attr_accessor :valid_until
|
24
|
+
|
25
|
+
#
|
26
|
+
# Initializer to transform a +Hash+ into an Payment object
|
27
|
+
#
|
28
|
+
# @param [Hash] args
|
29
|
+
def initialize(args=nil)
|
30
|
+
@quantity = 1
|
31
|
+
return if args.nil?
|
32
|
+
args.each do |k,v|
|
33
|
+
instance_variable_set("@#{k}", v) unless v.nil?
|
34
|
+
end
|
35
|
+
|
36
|
+
validate
|
37
|
+
end
|
38
|
+
|
39
|
+
def validate
|
40
|
+
if barcode && quantity && quantity > 1
|
41
|
+
raise WheretocardError.new(self), "Quantity cannot be greater than 1 if a barcode is specified."
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
|
46
|
+
end
|
47
|
+
end
|
@@ -0,0 +1,113 @@
|
|
1
|
+
module Wheretocard
|
2
|
+
|
3
|
+
# Creates a validator
|
4
|
+
class OrderValidator
|
5
|
+
# include Veto.validator
|
6
|
+
# validates :value, presence: true, integer: true
|
7
|
+
# validates :profile, presence: true
|
8
|
+
# validates :currency, presence: true, format: /[A-Z]{3}/
|
9
|
+
# validates :email, presence: true
|
10
|
+
end
|
11
|
+
|
12
|
+
|
13
|
+
|
14
|
+
#
|
15
|
+
# Object representing a response object with attributes provided by WTC
|
16
|
+
#
|
17
|
+
# @return [Array] Errors
|
18
|
+
# @param :amount [Integer] The total price in cents
|
19
|
+
class Order
|
20
|
+
attr_accessor :errors
|
21
|
+
attr_accessor :reference_id
|
22
|
+
attr_accessor :first_name
|
23
|
+
attr_accessor :infix
|
24
|
+
attr_accessor :last_name
|
25
|
+
attr_accessor :street
|
26
|
+
attr_accessor :house_number
|
27
|
+
attr_accessor :city
|
28
|
+
attr_accessor :postal_code
|
29
|
+
attr_accessor :country
|
30
|
+
attr_accessor :email
|
31
|
+
attr_accessor :phone_number
|
32
|
+
attr_accessor :value
|
33
|
+
attr_accessor :client
|
34
|
+
attr_accessor :line_items
|
35
|
+
attr_accessor :delivery_format
|
36
|
+
attr_accessor :delivery_channel
|
37
|
+
|
38
|
+
|
39
|
+
#
|
40
|
+
# Initializer to transform a +Hash+ into an Payment object
|
41
|
+
#
|
42
|
+
# @param [Hash] args
|
43
|
+
def initialize(args=nil)
|
44
|
+
@line_items = []
|
45
|
+
@delivery_format = "BARCODE"
|
46
|
+
@delivery_channel = "WEB"
|
47
|
+
return if args.nil?
|
48
|
+
args.each do |k,v|
|
49
|
+
instance_variable_set("@#{k}", v) unless v.nil?
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
# @return [Boolean] true/false, depending if this instanciated object is valid
|
54
|
+
def valid?
|
55
|
+
validator = OrderValidator.new
|
56
|
+
validator.valid?(self)
|
57
|
+
end
|
58
|
+
|
59
|
+
#
|
60
|
+
# This is the most importent method. It uses all the attributes
|
61
|
+
# and performs a `order` action on Wheretocard API.
|
62
|
+
# @return [Wheretocard::Response] response object with `key`, `message` and `success?` methods
|
63
|
+
#
|
64
|
+
def create
|
65
|
+
# if there are any line items, they should all be valid.
|
66
|
+
validate_line_items
|
67
|
+
|
68
|
+
# make the API call
|
69
|
+
# response = Docdata.client.call(:create, xml: create_xml)
|
70
|
+
# response_object = Docdata::Response.parse(:create, response)
|
71
|
+
if response_object.success?
|
72
|
+
self.key = response_object.key
|
73
|
+
end
|
74
|
+
|
75
|
+
# set `self` as the value of the `payment` attribute in the response object
|
76
|
+
response_object.payment = self
|
77
|
+
response_object.url = redirect_url
|
78
|
+
|
79
|
+
return response_object
|
80
|
+
end
|
81
|
+
|
82
|
+
# adds a line item of type LineItem to the line_items atribute (array)
|
83
|
+
def add_line_item(args=nil)
|
84
|
+
line_item = Wheretocard::LineItem.new(args)
|
85
|
+
line_items << line_item
|
86
|
+
return line_item
|
87
|
+
end
|
88
|
+
|
89
|
+
# @return [String] the xml to send in the SOAP API
|
90
|
+
def to_xml
|
91
|
+
xml_file = "#{File.dirname(__FILE__)}/xml/order_request.xml.erb"
|
92
|
+
template = File.read(xml_file)
|
93
|
+
namespace = OpenStruct.new(order: self, client: client)
|
94
|
+
xml = ERB.new(template).result(namespace.instance_eval { binding })
|
95
|
+
end
|
96
|
+
alias :xml :to_xml
|
97
|
+
|
98
|
+
# submit the xml to the WtC API url
|
99
|
+
# return object is a Wheretocard::Response
|
100
|
+
def submit
|
101
|
+
# validate_line_items
|
102
|
+
Wheretocard::Response.from_order_request(self)
|
103
|
+
end
|
104
|
+
|
105
|
+
end
|
106
|
+
|
107
|
+
private
|
108
|
+
|
109
|
+
# make sure all the line items are valid
|
110
|
+
def validate_line_items
|
111
|
+
|
112
|
+
end
|
113
|
+
end
|
@@ -0,0 +1,114 @@
|
|
1
|
+
module Wheretocard
|
2
|
+
|
3
|
+
|
4
|
+
#
|
5
|
+
# Object representing a response object with attributes provided by WTC
|
6
|
+
#
|
7
|
+
# @return [Array] Errors
|
8
|
+
# @param :amount [Integer] The total price in cents
|
9
|
+
class Response
|
10
|
+
attr_accessor :errors
|
11
|
+
attr_accessor :body
|
12
|
+
attr_accessor :comment
|
13
|
+
attr_accessor :status
|
14
|
+
attr_accessor :url
|
15
|
+
|
16
|
+
#
|
17
|
+
# Initializer to transform a +Hash+ into an Payment object
|
18
|
+
#
|
19
|
+
# @param [Hash] args
|
20
|
+
def initialize(args=nil)
|
21
|
+
@line_items = []
|
22
|
+
return if args.nil?
|
23
|
+
args.each do |k,v|
|
24
|
+
instance_variable_set("@#{k}", v) unless v.nil?
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
# raise errors if the API returns errors
|
29
|
+
def validate
|
30
|
+
if nokogiri_document.xpath('//error').any?
|
31
|
+
code = nokogiri_document.xpath('//code').text
|
32
|
+
desc = nokogiri_document.xpath('//description').text
|
33
|
+
raise WheretocardError.new(self), "#{desc}\nError code: #{code} (#{error_codes[code]})"
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
# return true if status is "OK"
|
38
|
+
def success
|
39
|
+
status == "OK"
|
40
|
+
end
|
41
|
+
alias :success? :success
|
42
|
+
|
43
|
+
# return the parsed xml document
|
44
|
+
def nokogiri_document
|
45
|
+
@nokogiri_document ||= Nokogiri::XML(body)
|
46
|
+
end
|
47
|
+
|
48
|
+
def error_codes
|
49
|
+
{
|
50
|
+
"OI_0001" => "Internal server error",
|
51
|
+
"OI_0099" => "Unknown error",
|
52
|
+
|
53
|
+
"OI_0101" => "Supplied client not found",
|
54
|
+
"OI_0102" => "Interface not enabled for client",
|
55
|
+
|
56
|
+
"OI_0201" => "Submitted client not found",
|
57
|
+
"OI_0202" => "Interface not enabled for client",
|
58
|
+
"OI_0203" => "Missing (or empty) order reference id attribute.",
|
59
|
+
"OI_0204" => "Request contains invalid orderline.ticket-ref <-> ticket.ref link reference(s)",
|
60
|
+
"OI_0205" => "Unknown delivery channel",
|
61
|
+
"OI_0206" => "Unknown delivery format",
|
62
|
+
"OI_0207" => "Device manufacturerer/type is not known",
|
63
|
+
"OI_0208" => "The delivery address is not specified",
|
64
|
+
"OI_0209" => "The submitted data for order reference id (max 32 chars), or one of the
|
65
|
+
properties (max 100 chars) is too long.",
|
66
|
+
"OI_0210" => "Submitted number of persons is negative or 0",
|
67
|
+
"OI_0211" => "Submitted times valid is negative or 0",
|
68
|
+
"OI_0212" => "Supplied email address is missing or the format is not correct",
|
69
|
+
"OI_0213" => "The submitted orderline type does not belong to the client",
|
70
|
+
"OI_0214" => "Missing required orderlinetype",
|
71
|
+
"OI_0215" => "Orderline type is not owned by the submitted case",
|
72
|
+
"OI_0216" => "Could not generate ticket code for request, all ticket codes are in use (batch
|
73
|
+
full).",
|
74
|
+
}
|
75
|
+
end
|
76
|
+
|
77
|
+
def self.parse_respose_code(order, code)
|
78
|
+
if code == 200
|
79
|
+
return
|
80
|
+
elsif code == 500
|
81
|
+
raise WheretocardError.new(order), "A server error occured (500)"
|
82
|
+
else
|
83
|
+
raise WheretocardError.new(order), "The request failed (http status code #{code})"
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
def self.from_order_request(order)
|
88
|
+
response = HTTParty.post(Wheretocard.url, body: order.to_xml)
|
89
|
+
# puts response.body, response.code, response.message, response.headers.inspect
|
90
|
+
|
91
|
+
|
92
|
+
# raise error if code is not 200
|
93
|
+
parse_respose_code(order, response.code)
|
94
|
+
|
95
|
+
# parse the response
|
96
|
+
# <orderResponse status="NOT_OK">
|
97
|
+
# <error>
|
98
|
+
# <code>OI_0202</code>
|
99
|
+
# <description><![CDATA[Posted XML not valid, or not conform Schema definition. ]]></description>
|
100
|
+
# </error>
|
101
|
+
# </orderResponse>
|
102
|
+
|
103
|
+
r = Response.new()
|
104
|
+
r.body = response.body
|
105
|
+
r.status = r.nokogiri_document.xpath('//orderResponse/@status').text
|
106
|
+
if r.nokogiri_document.search('comment[type="url"]').any?
|
107
|
+
r.url = r.nokogiri_document.search('comment[type="url"]').first.text
|
108
|
+
end
|
109
|
+
r.validate
|
110
|
+
return r
|
111
|
+
end
|
112
|
+
|
113
|
+
end
|
114
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
2
|
+
<orderRequest version="1.0">
|
3
|
+
<client code="<%= client.client_code %>">
|
4
|
+
<username><%= client.username%></username>
|
5
|
+
<password><%= client.password%></password>
|
6
|
+
</client>
|
7
|
+
<order referenceId="<%= order.reference_id %>">
|
8
|
+
<properties>
|
9
|
+
<property name="FIRST_NAME" value="<%= order.first_name %>"/>
|
10
|
+
<property name="INFIX" value="<%= order.infix %>"/>
|
11
|
+
<property name="LAST_NAME" value="<%= order.last_name %>"/>
|
12
|
+
<property name="EMAIL" value="<%= order.email %>"/>
|
13
|
+
<property name="STREET" value="<%= order.street %>"/>
|
14
|
+
<property name="HOUSE_NUMBER" value="<%= order.house_number %>"/>
|
15
|
+
<property name="POSTAL_CODE" value="<%= order.postal_code %>"/>
|
16
|
+
<property name="CITY" value="<%= order.city %>"/>
|
17
|
+
</properties>
|
18
|
+
<cases>
|
19
|
+
<case code="<%= client.case_code %>">
|
20
|
+
<orderlines>
|
21
|
+
<% for line_item in order.line_items %>
|
22
|
+
<orderline code="<%= line_item.product_code %>" ticket-ref="<%= line_item.ticket_ref %>">
|
23
|
+
<quantity><%= line_item.quantity %></quantity>
|
24
|
+
<price><%= line_item.price %></price>
|
25
|
+
<action><%= line_item.description %></action>
|
26
|
+
<% if line_item.valid_from && line_item.valid_until %>
|
27
|
+
<validPeriod from="<%= line_item.valid_from.strftime("%Y-%m-%dT%H:%M:%S") %>" to="<%= line_item.valid_until.strftime("%Y-%m-%dT%H:%M:%S") %>"/>
|
28
|
+
<% end %>
|
29
|
+
</orderline>
|
30
|
+
<% end %>
|
31
|
+
</orderlines>
|
32
|
+
</case>
|
33
|
+
</cases>
|
34
|
+
</order>
|
35
|
+
<tickets>
|
36
|
+
<% for line_item in order.line_items %>
|
37
|
+
<ticket ref="<%= line_item.ticket_ref %>" delivery-channel="<%= order.delivery_channel %>" delivery-format="<%= order.delivery_format %>">
|
38
|
+
<% if line_item.barcode %>
|
39
|
+
<contentCode><%= line_item.barcode %></contentCode>
|
40
|
+
<% end %>
|
41
|
+
</ticket>
|
42
|
+
<% end %>
|
43
|
+
</tickets>
|
44
|
+
</orderRequest>
|
data/wheretocard.gemspec
ADDED
@@ -0,0 +1,45 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'wheretocard/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "wheretocard"
|
8
|
+
spec.version = Wheretocard::VERSION
|
9
|
+
spec.authors = ["Henk Meijer"]
|
10
|
+
spec.email = ["henk.meijer@eskesmedia.nl"]
|
11
|
+
|
12
|
+
spec.summary = %q{Ruby binder to the Wherto CARD API}
|
13
|
+
spec.description = %q{Ruby binder to the Wherto CARD API}
|
14
|
+
spec.homepage = "http://www.eskesmedia.nl/"
|
15
|
+
spec.license = "MIT"
|
16
|
+
|
17
|
+
# Prevent pushing this gem to RubyGems.org by setting 'allowed_push_host', or
|
18
|
+
# delete this section to allow pushing this gem to any host.
|
19
|
+
# if spec.respond_to?(:metadata)
|
20
|
+
# spec.metadata['allowed_push_host'] = "TODO: Set to 'http://mygemserver.com'"
|
21
|
+
# else
|
22
|
+
# raise "RubyGems 2.0 or newer is required to protect against public gem pushes."
|
23
|
+
# end
|
24
|
+
|
25
|
+
spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
26
|
+
spec.bindir = "exe"
|
27
|
+
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
28
|
+
spec.require_paths = ["lib"]
|
29
|
+
|
30
|
+
spec.add_development_dependency "bundler", "~> 1.10"
|
31
|
+
spec.add_development_dependency "rake", "~> 10.0"
|
32
|
+
spec.add_development_dependency "rspec"
|
33
|
+
spec.add_development_dependency "vcr"
|
34
|
+
spec.add_development_dependency "fakeweb"
|
35
|
+
spec.add_development_dependency "coveralls"
|
36
|
+
spec.add_development_dependency "simplecov"
|
37
|
+
|
38
|
+
|
39
|
+
# spec.add_dependency 'veto'
|
40
|
+
# spec.add_dependency 'rubyntlm' #, '0.4.0'
|
41
|
+
spec.add_dependency 'httparty'
|
42
|
+
spec.add_dependency 'nokogiri'
|
43
|
+
# spec.add_dependency 'railties'
|
44
|
+
|
45
|
+
end
|
metadata
ADDED
@@ -0,0 +1,192 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: wheretocard
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Henk Meijer
|
8
|
+
autorequire:
|
9
|
+
bindir: exe
|
10
|
+
cert_chain: []
|
11
|
+
date: 2016-04-18 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.10'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ~>
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1.10'
|
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: '0'
|
48
|
+
type: :development
|
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: vcr
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - '>='
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - '>='
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: fakeweb
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - '>='
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '0'
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - '>='
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '0'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: coveralls
|
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
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: simplecov
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - '>='
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: '0'
|
104
|
+
type: :development
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - '>='
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: '0'
|
111
|
+
- !ruby/object:Gem::Dependency
|
112
|
+
name: httparty
|
113
|
+
requirement: !ruby/object:Gem::Requirement
|
114
|
+
requirements:
|
115
|
+
- - '>='
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: '0'
|
118
|
+
type: :runtime
|
119
|
+
prerelease: false
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
121
|
+
requirements:
|
122
|
+
- - '>='
|
123
|
+
- !ruby/object:Gem::Version
|
124
|
+
version: '0'
|
125
|
+
- !ruby/object:Gem::Dependency
|
126
|
+
name: nokogiri
|
127
|
+
requirement: !ruby/object:Gem::Requirement
|
128
|
+
requirements:
|
129
|
+
- - '>='
|
130
|
+
- !ruby/object:Gem::Version
|
131
|
+
version: '0'
|
132
|
+
type: :runtime
|
133
|
+
prerelease: false
|
134
|
+
version_requirements: !ruby/object:Gem::Requirement
|
135
|
+
requirements:
|
136
|
+
- - '>='
|
137
|
+
- !ruby/object:Gem::Version
|
138
|
+
version: '0'
|
139
|
+
description: Ruby binder to the Wherto CARD API
|
140
|
+
email:
|
141
|
+
- henk.meijer@eskesmedia.nl
|
142
|
+
executables: []
|
143
|
+
extensions: []
|
144
|
+
extra_rdoc_files: []
|
145
|
+
files:
|
146
|
+
- .gitignore
|
147
|
+
- .rspec
|
148
|
+
- .travis.yml
|
149
|
+
- Gemfile
|
150
|
+
- LICENSE.txt
|
151
|
+
- README.md
|
152
|
+
- Rakefile
|
153
|
+
- bin/console
|
154
|
+
- bin/setup
|
155
|
+
- documentation/Ticketing order interface specification v1.60.pdf
|
156
|
+
- documentation/test_wtc_api.php
|
157
|
+
- lib/wheretocard.rb
|
158
|
+
- lib/wheretocard/client.rb
|
159
|
+
- lib/wheretocard/config.rb
|
160
|
+
- lib/wheretocard/line_item.rb
|
161
|
+
- lib/wheretocard/order.rb
|
162
|
+
- lib/wheretocard/response.rb
|
163
|
+
- lib/wheretocard/version.rb
|
164
|
+
- lib/wheretocard/wheretocard_error.rb
|
165
|
+
- lib/wheretocard/xml/order_request.xml.erb
|
166
|
+
- wheretocard.gemspec
|
167
|
+
homepage: http://www.eskesmedia.nl/
|
168
|
+
licenses:
|
169
|
+
- MIT
|
170
|
+
metadata: {}
|
171
|
+
post_install_message:
|
172
|
+
rdoc_options: []
|
173
|
+
require_paths:
|
174
|
+
- lib
|
175
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
176
|
+
requirements:
|
177
|
+
- - '>='
|
178
|
+
- !ruby/object:Gem::Version
|
179
|
+
version: '0'
|
180
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
181
|
+
requirements:
|
182
|
+
- - '>='
|
183
|
+
- !ruby/object:Gem::Version
|
184
|
+
version: '0'
|
185
|
+
requirements: []
|
186
|
+
rubyforge_project:
|
187
|
+
rubygems_version: 2.3.0
|
188
|
+
signing_key:
|
189
|
+
specification_version: 4
|
190
|
+
summary: Ruby binder to the Wherto CARD API
|
191
|
+
test_files: []
|
192
|
+
has_rdoc:
|