wheretocard 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +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:
|