nfg-client 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +15 -0
- data/.gitignore +7 -0
- data/.rspec +1 -0
- data/Gemfile +4 -0
- data/LICENSE.md +21 -0
- data/README.md +360 -0
- data/Rakefile +8 -0
- data/lib/nfg-client.rb +3 -0
- data/lib/nfg-client/client.rb +321 -0
- data/lib/nfg-client/utils.rb +91 -0
- data/lib/nfg-client/version.rb +3 -0
- data/nfg-client.gemspec +25 -0
- data/spec/nfg_client_spec.rb +0 -0
- data/spec/spec_helper.rb +20 -0
- metadata +102 -0
checksums.yaml
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
---
|
2
|
+
!binary "U0hBMQ==":
|
3
|
+
metadata.gz: !binary |-
|
4
|
+
ZDhhZGYxODA1OTNjMTcwNWJiMDVjMzUwOTE5NTgzNzEwOGQ3NDY5Mg==
|
5
|
+
data.tar.gz: !binary |-
|
6
|
+
ZmVjOTFiMWM5ZTA2NGQwMzc5NjNmYWZjNTBlYjllYjlkNDllNmNlMw==
|
7
|
+
SHA512:
|
8
|
+
metadata.gz: !binary |-
|
9
|
+
OTU5ZjhlZTQ1NGNlNDNiNDY0MDI1OTI2ODA1N2JhZDk5NGJlNzgxYWQ0Njgy
|
10
|
+
YzRlZGRlOWY0MjA0MmMyYTY4MGE1NDg4ZTk3NmJmNjQ5ODA5MTg3M2U4OThl
|
11
|
+
ODYyODRlNGNjNjQ1ZGI3MjJkZTc0ZGEwNmExZjhiMzBhMzA4YmE=
|
12
|
+
data.tar.gz: !binary |-
|
13
|
+
ODc3MTViZmU1YzBmNzI2NjMwMGVhNWQ5OGRkNzg0MTliNzcyYjc2N2M1NzM2
|
14
|
+
ZTczOTMzYWE1YzQyNTgyNzA0MGE4ODMyMGFiNzc1ZjMxNGNhYmJmZTE1OGVm
|
15
|
+
NTM3NWY3MzAxMTFmZjNjOTA2ZDY2NGJjMDQ0Yjg4ZTk4ZWU2Mzc=
|
data/.gitignore
ADDED
data/.rspec
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
--colour
|
data/Gemfile
ADDED
data/LICENSE.md
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2014 Antonio Ruano Cuesta
|
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,360 @@
|
|
1
|
+
# NFG Client
|
2
|
+
|
3
|
+
A client to interact with the NFG (Network for Good) API via SOAP requests.
|
4
|
+
|
5
|
+
## Installation
|
6
|
+
|
7
|
+
Install the gem:
|
8
|
+
|
9
|
+
gem install nfg-client
|
10
|
+
|
11
|
+
Or add it to your Gemfile:
|
12
|
+
|
13
|
+
gem "nfg-client"
|
14
|
+
|
15
|
+
## Usage
|
16
|
+
|
17
|
+
Create a NFG Client instance using your NFG credentials:
|
18
|
+
|
19
|
+
nfg_client = NFGClient.new(partner_id, partner_password, partner_source, partner_campaign, use_sandbox)
|
20
|
+
|
21
|
+
The fifth parameter is optional (defaults to false), and indicates the Client which API URLs to use (sandbox or production).
|
22
|
+
|
23
|
+
Use the Client to make calls to the NFG API, each call will take a hash with the parameters you want to send along with it (apart from the NFG credentials).
|
24
|
+
|
25
|
+
Example:
|
26
|
+
|
27
|
+
nfg_client.get_donor_cofs({"DonorToken" => donor_token})
|
28
|
+
|
29
|
+
All required parameters for the different calls should have the name specified by the NFG documentation.
|
30
|
+
|
31
|
+
For more information, refer to the official NFG documentation:
|
32
|
+
|
33
|
+
http://www.thenetworkforgood.org/t5/Developer-Resource-Center/ct-p/Developer
|
34
|
+
|
35
|
+
## Supported Calls
|
36
|
+
|
37
|
+
Below, the list of supported calls and examples of usage. All functions return a hash with the response from NFG.
|
38
|
+
|
39
|
+
### CreateCOF
|
40
|
+
|
41
|
+
Creates a Card on File without a transaction.
|
42
|
+
|
43
|
+
**_Call_**
|
44
|
+
|
45
|
+
response = nfg_client.create_cof({
|
46
|
+
"DonorToken" => "",
|
47
|
+
"DonorFirstName" => "",
|
48
|
+
"DonorLastName" => "",
|
49
|
+
"DonorEmail" => "",
|
50
|
+
"DonorAddress1" => "",
|
51
|
+
"DonorAddress2" => "",
|
52
|
+
"DonorCity" => "",
|
53
|
+
"DonorState" => "",
|
54
|
+
"DonorZip" => "",
|
55
|
+
"DonorCountry" => "",
|
56
|
+
"DonorPhone" => "",
|
57
|
+
"CardType" => "", # Unk, Visa, Mastercard, Amex or Discover
|
58
|
+
"NameOnCard" => "",
|
59
|
+
"CardNumber" => "",
|
60
|
+
"ExpMonth" => "",
|
61
|
+
"ExpYear" => "",
|
62
|
+
"CSC" => ""
|
63
|
+
})
|
64
|
+
|
65
|
+
**_Response on Success_**
|
66
|
+
|
67
|
+
{
|
68
|
+
"StatusCode" => "Success",
|
69
|
+
"Message" => "", # Empty
|
70
|
+
"ErrorDetails" => "", # Empty
|
71
|
+
"CallDuration" => "x.x",
|
72
|
+
"DonorToken" => "x",
|
73
|
+
"COFId" => "x" # Integer
|
74
|
+
}
|
75
|
+
|
76
|
+
### GetDonorCOFs
|
77
|
+
|
78
|
+
Gets a list of donor Cards on File.
|
79
|
+
|
80
|
+
**_Call_**
|
81
|
+
|
82
|
+
response = nfg_client.get_donor_cofs({
|
83
|
+
"DonorToken" => ""
|
84
|
+
})
|
85
|
+
|
86
|
+
**_Response on Success_**
|
87
|
+
|
88
|
+
{
|
89
|
+
"StatusCode" => "Success",
|
90
|
+
"Message" => "", # Empty
|
91
|
+
"ErrorDetails" => "", # Empty
|
92
|
+
"CallDuration" => "x.x",
|
93
|
+
"DonorToken" => "x",
|
94
|
+
"Cards" => [
|
95
|
+
{
|
96
|
+
"COFId" => "x", # Integer
|
97
|
+
"CardType" => "x", # e.g. Mastercard
|
98
|
+
"CCSuffix" => "xxxx", # Last four digits
|
99
|
+
"CCExpMonth" => "", # 1 or 2 digits
|
100
|
+
"CCExpYear" => "", # 4 digits
|
101
|
+
"bInUseByLiveRD" => "", # true or false
|
102
|
+
"COFEmailAddress" => ""
|
103
|
+
},
|
104
|
+
...
|
105
|
+
]
|
106
|
+
}
|
107
|
+
|
108
|
+
### DeleteDonorCOF
|
109
|
+
|
110
|
+
Removes an existing Card on File.
|
111
|
+
|
112
|
+
**_Call_**
|
113
|
+
|
114
|
+
response = nfg_client.delete_donor_cof({
|
115
|
+
"DonorToken" => "",
|
116
|
+
"COFId" => ""
|
117
|
+
})
|
118
|
+
|
119
|
+
**_Response on Success_**
|
120
|
+
|
121
|
+
{
|
122
|
+
"StatusCode" => "Success",
|
123
|
+
"Message" => "", # Empty
|
124
|
+
"ErrorDetails" => "", # Empty
|
125
|
+
"CallDuration" => "x.xx"
|
126
|
+
}
|
127
|
+
|
128
|
+
### MakeCOFDonation
|
129
|
+
|
130
|
+
Triggers a one-time or recurring donation to one or more charities with an existing Card on File.
|
131
|
+
|
132
|
+
**_Call_**
|
133
|
+
|
134
|
+
response = nfg_client.make_cof_donation({
|
135
|
+
"DonationLineItems" => {
|
136
|
+
"DonationItem1" => {
|
137
|
+
"NpoEin" => "",
|
138
|
+
"donorVis" => "", # ProvideAll, ProvideNameAndEmailOnly or Anonymous
|
139
|
+
"ItemAmount" => "",
|
140
|
+
"RecurType" => "", # NotRecurring, Monthly, Quarterly or Annually
|
141
|
+
"Designation" => ""
|
142
|
+
"Dedication" => ""
|
143
|
+
},
|
144
|
+
"DonationItem2" => {
|
145
|
+
...
|
146
|
+
},
|
147
|
+
...
|
148
|
+
},
|
149
|
+
"TotalAmount" => "",
|
150
|
+
"TipAmount" => "",
|
151
|
+
"DonorIpAddress" => "",
|
152
|
+
"DonorToken" => "",
|
153
|
+
"COFId" => ""
|
154
|
+
})
|
155
|
+
|
156
|
+
**_Response on Success_**
|
157
|
+
|
158
|
+
{
|
159
|
+
"StatusCode" => "Success",
|
160
|
+
"Message" => "", # Empty
|
161
|
+
"ErrorDetails" => "", # Empty
|
162
|
+
"CallDuration" => "x.x",
|
163
|
+
"ChargeId" => "x", # Integer
|
164
|
+
"COFId" => "0"
|
165
|
+
}
|
166
|
+
|
167
|
+
### MakeDonationAddCOF
|
168
|
+
|
169
|
+
Triggers a one-time or recurring donation to one or more charities with a new Card on File.
|
170
|
+
|
171
|
+
**_Call_**
|
172
|
+
|
173
|
+
response = nfg_client.make_donation_add_cof({
|
174
|
+
"DonationLineItems" => {
|
175
|
+
"DonationItem1" => {
|
176
|
+
"NpoEin" => "",
|
177
|
+
"donorVis" => "", # ProvideAll, ProvideNameAndEmailOnly or Anonymous
|
178
|
+
"ItemAmount" => "",
|
179
|
+
"RecurType" => "", # NotRecurring, Monthly, Quarterly or Annually
|
180
|
+
"Designation" => ""
|
181
|
+
"Dedication" => ""
|
182
|
+
},
|
183
|
+
"DonationItem2" => {
|
184
|
+
...
|
185
|
+
},
|
186
|
+
...
|
187
|
+
},
|
188
|
+
"TotalAmount" => "",
|
189
|
+
"TipAmount" => "",
|
190
|
+
"DonorIpAddress" => "",
|
191
|
+
"DonorToken" => "",
|
192
|
+
"COFId" => "",
|
193
|
+
"DonorFirstName" => "",
|
194
|
+
"DonorLastName" => "",
|
195
|
+
"DonorEmail" => "",
|
196
|
+
"DonorAddress1" => "",
|
197
|
+
"DonorAddress2" => "",
|
198
|
+
"DonorCity" => "",
|
199
|
+
"DonorState" => "",
|
200
|
+
"DonorZip" => "",
|
201
|
+
"DonorCountry" => "",
|
202
|
+
"DonorPhone" => "",
|
203
|
+
"CardType" => "", # Unk, Visa, Mastercard, Amex or Discover
|
204
|
+
"NameOnCard" => "",
|
205
|
+
"CardNumber" => "",
|
206
|
+
"ExpMonth" => "",
|
207
|
+
"ExpYear" => "",
|
208
|
+
"CSC" => ""
|
209
|
+
})
|
210
|
+
|
211
|
+
**_Response on Success_**
|
212
|
+
|
213
|
+
{
|
214
|
+
"StatusCode" => "Success",
|
215
|
+
"Message" => "", # Empty
|
216
|
+
"ErrorDetails" => "", # Empty
|
217
|
+
"CallDuration" => "x.x",
|
218
|
+
"ChargeId" => "x", # Integer
|
219
|
+
"COFId" => "0"
|
220
|
+
}
|
221
|
+
|
222
|
+
### GetFee
|
223
|
+
|
224
|
+
Calculates the fee for a transaction that would ultimately be used with payment functions.
|
225
|
+
|
226
|
+
**_Call_**
|
227
|
+
|
228
|
+
response = nfg_client.get_fee({
|
229
|
+
"DonationLineItems" => {
|
230
|
+
"DonationItem1" => {
|
231
|
+
"NpoEin" => "",
|
232
|
+
"donorVis" => "", # ProvideAll, ProvideNameAndEmailOnly or Anonymous
|
233
|
+
"ItemAmount" => "",
|
234
|
+
"RecurType" => "", # NotRecurring, Monthly, Quarterly or Annually
|
235
|
+
"Designation" => ""
|
236
|
+
"Dedication" => ""
|
237
|
+
},
|
238
|
+
"DonationItem2" => {
|
239
|
+
...
|
240
|
+
},
|
241
|
+
...
|
242
|
+
},
|
243
|
+
"TipAmount" => "",
|
244
|
+
"CardType" => ""
|
245
|
+
})
|
246
|
+
|
247
|
+
**_Response on Success_**
|
248
|
+
|
249
|
+
{
|
250
|
+
"Message" => "", # Empty
|
251
|
+
"ErrorDetails" => "", # Empty
|
252
|
+
"CallDuration" => "x.x",
|
253
|
+
"TotalChargeAmount" => "x.x",
|
254
|
+
"TotalAddFee" => "x.x",
|
255
|
+
"TotalDeductFee" => "x.x",
|
256
|
+
"TipAmount" => "x.x"
|
257
|
+
}
|
258
|
+
|
259
|
+
### GetDonorDonationHistory
|
260
|
+
|
261
|
+
Gets donor transactions.
|
262
|
+
|
263
|
+
**_Call_**
|
264
|
+
|
265
|
+
response = nfg_client.get_donor_donation_history({
|
266
|
+
"DonorToken" => ""
|
267
|
+
})
|
268
|
+
|
269
|
+
**_Response on Success_**
|
270
|
+
|
271
|
+
{
|
272
|
+
"StatusCode" => "Success",
|
273
|
+
"Message" => "", # Empty
|
274
|
+
"ErrorDetails" => "", # Empty
|
275
|
+
"CallDuration" => "x.x",
|
276
|
+
"DonorToken" => "x",
|
277
|
+
"Donations"=>[
|
278
|
+
{
|
279
|
+
"DonationDate" => "xxxx-xx-xxTxx:xx:xx.xx",
|
280
|
+
"RecurType" => "x", # e.g. NotRecurring
|
281
|
+
"IsTpcAddOnFee" => "", # true or false
|
282
|
+
"NpoName" => "", # e.g. Smithsonian Institution
|
283
|
+
"Designation" => "",
|
284
|
+
"Dedication" => "",
|
285
|
+
"Amount" => "x.x",
|
286
|
+
"ChargeId" => "x" # Integer
|
287
|
+
},
|
288
|
+
...
|
289
|
+
]
|
290
|
+
}
|
291
|
+
|
292
|
+
### GetDonationReport
|
293
|
+
|
294
|
+
Returns a report of partner transactions during a specific period of time.
|
295
|
+
|
296
|
+
**_Call_**
|
297
|
+
|
298
|
+
response = nfg_client.get_donation_report({
|
299
|
+
"StartDate" => "",
|
300
|
+
"EndDate" => "",
|
301
|
+
"DonationReportType" => "" # All, OneTime or Recurring
|
302
|
+
})
|
303
|
+
|
304
|
+
**_Response on Success_**
|
305
|
+
|
306
|
+
{
|
307
|
+
"StatusCode" => "Success",
|
308
|
+
"Message" => "", # Empty
|
309
|
+
"ErrorDetails" => "", # Empty
|
310
|
+
"CallDuration" => "x.x",
|
311
|
+
"ReturnCount" => "x",
|
312
|
+
"ReportResults"=>[
|
313
|
+
{
|
314
|
+
"Source" => "x",
|
315
|
+
"Campaign" => "x",
|
316
|
+
"ChargeId" => "x", # Integer
|
317
|
+
"ShareWithCharity" => "x", # e.g. No Donor Info - Anonymous
|
318
|
+
"DonorEmail" => "x",
|
319
|
+
"DonorFirstName" => "x",
|
320
|
+
"DonorLastName" => "x",
|
321
|
+
"DonorAddress1" => "x",
|
322
|
+
"DonorAddress2" => "x",
|
323
|
+
"DonorCity" => "x",
|
324
|
+
"DonorState" => "x",
|
325
|
+
"DonorZip" => "x",
|
326
|
+
"DonorCountry" => "x",
|
327
|
+
"DonorPhone" => "x",
|
328
|
+
"Designation" => "",
|
329
|
+
"DonateInName" => "",
|
330
|
+
"RecurringPeriod" => "",
|
331
|
+
"EventDate" => "xxxx-xx-xxTxx:xx:xx.xxxZ",
|
332
|
+
"NpoEIN" => "x",
|
333
|
+
"NpoName" => "x",
|
334
|
+
"ChargeStatus" => "", # e.g. CS_SUCCESS
|
335
|
+
"ChargeAmount" => "x.x",
|
336
|
+
"NpoTPC" => "x.x",
|
337
|
+
"DonationItemAmount" => "x.x",
|
338
|
+
"TotalDonationAmount" => "x.x",
|
339
|
+
"HistoryRecordId" => "x"
|
340
|
+
},
|
341
|
+
...
|
342
|
+
]
|
343
|
+
}
|
344
|
+
|
345
|
+
## Failed calls
|
346
|
+
|
347
|
+
When a call fails (i.e. the "StatusCode" is different than "Success"), it's usually possible to find out more about the error looking at the "Message" and "ErrorDetails" fields. "Message" is a string, while "ErrorDetails" is a hash with the following format:
|
348
|
+
|
349
|
+
{
|
350
|
+
"StatusCode" => "Other",
|
351
|
+
"Message" => "x",
|
352
|
+
"ErrorDetails" => {
|
353
|
+
"ErrorInfo"=>{
|
354
|
+
"ErrCode" => "x",
|
355
|
+
"ErrData" => "x"
|
356
|
+
}
|
357
|
+
}
|
358
|
+
"CallDuration" => "x.x",
|
359
|
+
...
|
360
|
+
}
|
data/Rakefile
ADDED
data/lib/nfg-client.rb
ADDED
@@ -0,0 +1,321 @@
|
|
1
|
+
module NFGClient
|
2
|
+
|
3
|
+
def self.new(partner_id, partner_password, partner_source, partner_campaign, use_sandbox = false)
|
4
|
+
NFGClient::Client.new(partner_id, partner_password, partner_source, partner_campaign, use_sandbox)
|
5
|
+
end
|
6
|
+
|
7
|
+
class Client
|
8
|
+
include NFGClient::Utils
|
9
|
+
|
10
|
+
def initialize(partner_id, partner_password, partner_source, partner_campaign, use_sandbox)
|
11
|
+
@partner_id = partner_id
|
12
|
+
@partner_password = partner_password
|
13
|
+
@partner_source = partner_source
|
14
|
+
@partner_campaign = partner_campaign
|
15
|
+
@use_sandbox = use_sandbox
|
16
|
+
end
|
17
|
+
|
18
|
+
# Creates a card on file for the given donor token
|
19
|
+
#
|
20
|
+
# Arguments:
|
21
|
+
# params: (Hash)
|
22
|
+
def create_cof(params)
|
23
|
+
call_params = add_credentials_to_params(params)
|
24
|
+
response = nfg_soap_request('CreateCOF', call_params, @use_sandbox)
|
25
|
+
if response.is_a? REXML::Element
|
26
|
+
{
|
27
|
+
'StatusCode' => response.elements['StatusCode'].get_text.to_s,
|
28
|
+
'Message' => response.elements['Message'].get_text.to_s,
|
29
|
+
'ErrorDetails' => response.elements['ErrorDetails'].get_text.to_s,
|
30
|
+
'CallDuration' => response.elements['CallDuration'].get_text.to_s,
|
31
|
+
'DonorToken' => response.elements['DonorToken'].get_text.to_s,
|
32
|
+
'COFId' => response.elements['CofId'].get_text.to_s
|
33
|
+
}
|
34
|
+
else
|
35
|
+
response
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
# Deletes a card on file for the given donor token
|
40
|
+
#
|
41
|
+
# Arguments:
|
42
|
+
# params: (Hash)
|
43
|
+
def delete_donor_cof(params)
|
44
|
+
call_params = add_credentials_to_params(params)
|
45
|
+
response = nfg_soap_request('DeleteDonorCOF', call_params, @use_sandbox)
|
46
|
+
if response.is_a? REXML::Element
|
47
|
+
if response.elements['StatusCode'].get_text.to_s == 'Success'
|
48
|
+
{
|
49
|
+
'StatusCode' => response.elements['StatusCode'].get_text.to_s,
|
50
|
+
'Message' => response.elements['Message'].get_text.to_s,
|
51
|
+
'ErrorDetails' => response.elements['ErrorDetails'].get_text.to_s,
|
52
|
+
'CallDuration' => response.elements['CallDuration'].get_text.to_s
|
53
|
+
}
|
54
|
+
else
|
55
|
+
{
|
56
|
+
'StatusCode' => response.elements['StatusCode'].get_text.to_s,
|
57
|
+
'Message' => response.elements['Message'].get_text.to_s,
|
58
|
+
'ErrorDetails' => {
|
59
|
+
'ErrorInfo' => {
|
60
|
+
'ErrCode' => response.elements['ErrorDetails'].andand.elements.andand['ErrorInfo'].andand.elements.andand['ErrCode'].andand.get_text.andand.to_s,
|
61
|
+
'ErrData' => response.elements['ErrorDetails'].andand.elements.andand['ErrorInfo'].andand.elements.andand['ErrData'].andand.get_text.andand.to_s
|
62
|
+
}
|
63
|
+
},
|
64
|
+
'CallDuration' => response.elements['CallDuration'].get_text.to_s
|
65
|
+
}
|
66
|
+
end
|
67
|
+
else
|
68
|
+
response
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
# Gets a list of the given donor token's cards on file
|
73
|
+
#
|
74
|
+
# Arguments:
|
75
|
+
# params: (Hash)
|
76
|
+
def get_donor_cofs(params)
|
77
|
+
call_params = add_credentials_to_params(params)
|
78
|
+
response = nfg_soap_request('GetDonorCOFs', call_params, @use_sandbox)
|
79
|
+
if response.is_a? REXML::Element
|
80
|
+
response_hash = {
|
81
|
+
'StatusCode' => response.elements['StatusCode'].get_text.to_s,
|
82
|
+
'Message' => response.elements['Message'].get_text.to_s,
|
83
|
+
'ErrorDetails' => response.elements['ErrorDetails'].get_text.to_s,
|
84
|
+
'CallDuration' => response.elements['CallDuration'].get_text.to_s,
|
85
|
+
'DonorToken' => response.elements['DonorToken'].get_text.to_s
|
86
|
+
}
|
87
|
+
response_hash['Cards'] = Array.new
|
88
|
+
response.elements.each('Cards/COFRecord') do |card|
|
89
|
+
response_hash['Cards'] << {
|
90
|
+
'COFId' => card.elements['COFId'].get_text.to_s,
|
91
|
+
'CardType' => card.elements['CardType'].get_text.to_s,
|
92
|
+
'CCSuffix' => card.elements['CCSuffix'].get_text.to_s,
|
93
|
+
'CCExpMonth' => card.elements['CCExpMonth'].get_text.to_s,
|
94
|
+
'CCExpYear' => card.elements['CCExpYear'].get_text.to_s,
|
95
|
+
'bInUseByLiveRD' => card.elements['bInUseByLiveRD'].get_text.to_s,
|
96
|
+
'COFEmailAddress' => card.elements['COFEmailAddress'].get_text.to_s
|
97
|
+
}
|
98
|
+
end
|
99
|
+
response_hash
|
100
|
+
else
|
101
|
+
response
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
# Calculates fee tied to transaction
|
106
|
+
#
|
107
|
+
# Arguments:
|
108
|
+
# params: (Hash)
|
109
|
+
def get_fee(params)
|
110
|
+
call_params = add_credentials_to_params(params)
|
111
|
+
response = nfg_soap_request('GetFee', call_params, @use_sandbox)
|
112
|
+
if response.is_a? REXML::Element
|
113
|
+
if response.elements['ErrorDetails'].elements['ErrorInfo'].nil?
|
114
|
+
{
|
115
|
+
'Message' => response.elements['Message'].get_text.to_s,
|
116
|
+
'ErrorDetails' => response.elements['ErrorDetails'].get_text.to_s,
|
117
|
+
'CallDuration' => response.elements['CallDuration'].get_text.to_s,
|
118
|
+
'TotalChargeAmount' => response.elements['TotalChargeAmount'].get_text.to_s,
|
119
|
+
'TotalAddFee' => response.elements['TotalAddFee'].get_text.to_s,
|
120
|
+
'TotalDeductFee' => response.elements['TotalChargeAmount'].get_text.to_s,
|
121
|
+
'TipAmount' => response.elements['TotalAddFee'].get_text.to_s
|
122
|
+
}
|
123
|
+
else
|
124
|
+
{
|
125
|
+
'Message' => response.elements['Message'].get_text.to_s,
|
126
|
+
'ErrorDetails' => {
|
127
|
+
'ErrorInfo' => {
|
128
|
+
'ErrCode' => response.elements['ErrorDetails'].andand.elements.andand['ErrorInfo'].andand.elements.andand['ErrCode'].andand.get_text.andand.to_s,
|
129
|
+
'ErrData' => response.elements['ErrorDetails'].andand.elements.andand['ErrorInfo'].andand.elements.andand['ErrData'].andand.get_text.andand.to_s
|
130
|
+
}
|
131
|
+
},
|
132
|
+
'CallDuration' => response.elements['CallDuration'].get_text.to_s,
|
133
|
+
'TotalChargeAmount' => response.elements['TotalChargeAmount'].get_text.to_s,
|
134
|
+
'TotalAddFee' => response.elements['TotalAddFee'].get_text.to_s,
|
135
|
+
'TotalDeductFee' => response.elements['TotalChargeAmount'].get_text.to_s,
|
136
|
+
'TipAmount' => response.elements['TotalAddFee'].get_text.to_s
|
137
|
+
}
|
138
|
+
end
|
139
|
+
else
|
140
|
+
response
|
141
|
+
end
|
142
|
+
end
|
143
|
+
|
144
|
+
# Makes a donation using the given COF
|
145
|
+
#
|
146
|
+
# Arguments:
|
147
|
+
# params: (Hash)
|
148
|
+
def make_cof_donation(params)
|
149
|
+
call_params = add_credentials_to_params(params)
|
150
|
+
response = nfg_soap_request('MakeCOFDonation', call_params, @use_sandbox)
|
151
|
+
if response.is_a? REXML::Element
|
152
|
+
if response.elements['StatusCode'].get_text.to_s == 'Success'
|
153
|
+
{
|
154
|
+
'StatusCode' => response.elements['StatusCode'].get_text.to_s,
|
155
|
+
'Message' => response.elements['Message'].get_text.to_s,
|
156
|
+
'ErrorDetails' => response.elements['ErrorDetails'].get_text.to_s,
|
157
|
+
'CallDuration' => response.elements['CallDuration'].get_text.to_s,
|
158
|
+
'ChargeId' => response.elements['ChargeId'].get_text.to_s,
|
159
|
+
'COFId' => response.elements['CofId'].get_text.to_s
|
160
|
+
}
|
161
|
+
else
|
162
|
+
{
|
163
|
+
'StatusCode' => response.elements['StatusCode'].get_text.to_s,
|
164
|
+
'Message' => response.elements['Message'].get_text.to_s,
|
165
|
+
'ErrorDetails' => {
|
166
|
+
'ErrorInfo' => {
|
167
|
+
'ErrCode' => response.elements['ErrorDetails'].andand.elements.andand['ErrorInfo'].andand.elements.andand['ErrCode'].andand.get_text.andand.to_s,
|
168
|
+
'ErrData' => response.elements['ErrorDetails'].andand.elements.andand['ErrorInfo'].andand.elements.andand['ErrData'].andand.get_text.andand.to_s
|
169
|
+
}
|
170
|
+
},
|
171
|
+
'CallDuration' => response.elements['CallDuration'].get_text.to_s,
|
172
|
+
'ChargeId' => response.elements['ChargeId'].get_text.to_s,
|
173
|
+
'COFId' => response.elements['CofId'].get_text.to_s
|
174
|
+
}
|
175
|
+
end
|
176
|
+
else
|
177
|
+
response
|
178
|
+
end
|
179
|
+
end
|
180
|
+
|
181
|
+
# Makes a donation and stores a COF for the given donor token
|
182
|
+
#
|
183
|
+
# Arguments:
|
184
|
+
# params: (Hash)
|
185
|
+
def make_donation_add_cof(params)
|
186
|
+
call_params = add_credentials_to_params(params)
|
187
|
+
response = nfg_soap_request('MakeDonationAddCOF', call_params, @use_sandbox)
|
188
|
+
if response.is_a? REXML::Element
|
189
|
+
if (response.elements['StatusCode'].get_text.to_s == 'Success') || ((response.elements['StatusCode'].get_text.to_s != 'Success') && response.elements['ErrorDetails'].elements['ErrorInfo'].nil?)
|
190
|
+
{
|
191
|
+
'StatusCode' => response.elements['StatusCode'].get_text.to_s,
|
192
|
+
'Message' => response.elements['Message'].get_text.to_s,
|
193
|
+
'ErrorDetails' => response.elements['ErrorDetails'].get_text.to_s,
|
194
|
+
'CallDuration' => response.elements['CallDuration'].get_text.to_s,
|
195
|
+
'ChargeId' => response.elements['ChargeId'].get_text.to_s,
|
196
|
+
'COFId' => response.elements['CofId'].get_text.to_s
|
197
|
+
}
|
198
|
+
else
|
199
|
+
{
|
200
|
+
'StatusCode' => response.elements['StatusCode'].get_text.to_s,
|
201
|
+
'Message' => response.elements['Message'].get_text.to_s,
|
202
|
+
'ErrorDetails' => {
|
203
|
+
'ErrorInfo' => {
|
204
|
+
'ErrCode' => response.elements['ErrorDetails'].andand.elements.andand['ErrorInfo'].andand.elements.andand['ErrCode'].andand.get_text.andand.to_s,
|
205
|
+
'ErrData' => response.elements['ErrorDetails'].andand.elements.andand['ErrorInfo'].andand.elements.andand['ErrData'].andand.get_text.andand.to_s
|
206
|
+
}
|
207
|
+
},
|
208
|
+
'CallDuration' => response.elements['CallDuration'].get_text.to_s,
|
209
|
+
'ChargeId' => response.elements['ChargeId'].get_text.to_s,
|
210
|
+
'COFId' => response.elements['CofId'].get_text.to_s
|
211
|
+
}
|
212
|
+
end
|
213
|
+
else
|
214
|
+
response
|
215
|
+
end
|
216
|
+
end
|
217
|
+
|
218
|
+
# Retrieves the donation history for a specified donor token
|
219
|
+
#
|
220
|
+
# Arguments:
|
221
|
+
# params: (Hash)
|
222
|
+
def get_donor_donation_history(params)
|
223
|
+
call_params = add_credentials_to_params(params)
|
224
|
+
response = nfg_soap_request('GetDonorDonationHistory', call_params, @use_sandbox)
|
225
|
+
if response.is_a? REXML::Element
|
226
|
+
response_hash = {
|
227
|
+
'StatusCode' => response.elements['StatusCode'].get_text.to_s,
|
228
|
+
'Message' => response.elements['Message'].get_text.to_s,
|
229
|
+
'ErrorDetails' => response.elements['ErrorDetails'].get_text.to_s,
|
230
|
+
'CallDuration' => response.elements['CallDuration'].get_text.to_s,
|
231
|
+
'DonorToken' => response.elements['DonorToken'].get_text.to_s
|
232
|
+
}
|
233
|
+
response_hash['Donations'] = Array.new
|
234
|
+
response.elements.each('Donations/DonationItemData') do |donation|
|
235
|
+
response_hash['Donations'] << {
|
236
|
+
'DonationDate' => donation.elements['DonationDate'].get_text.to_s,
|
237
|
+
'RecurType' => donation.elements['RecurType'].get_text.to_s,
|
238
|
+
'IsTpcAddOnFee' => donation.elements['IsTpcAddOnFee'].get_text.to_s,
|
239
|
+
'NpoName' => donation.elements['NpoName'].get_text.to_s,
|
240
|
+
'Designation' => donation.elements['Designation'].get_text.to_s,
|
241
|
+
'Dedication' => donation.elements['Dedication'].get_text.to_s,
|
242
|
+
'Amount' => donation.elements['Amount'].get_text.to_s,
|
243
|
+
'ChargeId' => donation.elements['ChargeId'].get_text.to_s,
|
244
|
+
}
|
245
|
+
end
|
246
|
+
response_hash
|
247
|
+
else
|
248
|
+
response
|
249
|
+
end
|
250
|
+
end
|
251
|
+
|
252
|
+
# Retrieves the donation history by date
|
253
|
+
#
|
254
|
+
# Arguments:
|
255
|
+
# params: (Hash)
|
256
|
+
def get_donation_report(params)
|
257
|
+
call_params = add_credentials_to_params(params)
|
258
|
+
response = nfg_soap_request('GetDonationReport', call_params, @use_sandbox)
|
259
|
+
if response.is_a? REXML::Element
|
260
|
+
response_hash = {
|
261
|
+
'StatusCode' => response.elements['StatusCode'].get_text.to_s,
|
262
|
+
'Message' => response.elements['Message'].get_text.to_s,
|
263
|
+
'ErrorDetails' => response.elements['ErrorDetails'].get_text.to_s,
|
264
|
+
'CallDuration' => response.elements['CallDuration'].get_text.to_s,
|
265
|
+
'ReturnCount' => response.elements['ReturnCount'].get_text.to_s
|
266
|
+
}
|
267
|
+
response_hash['ReportResults'] = Array.new
|
268
|
+
response.elements.each('ReportResults/DonationReportResult') do |donation|
|
269
|
+
response_hash['ReportResults'] << {
|
270
|
+
'Source' => donation.elements['Source'].get_text.to_s,
|
271
|
+
'Campaign' => donation.elements['Campaign'].get_text.to_s,
|
272
|
+
'ChargeId' => donation.elements['ChargeId'].get_text.to_s,
|
273
|
+
'ShareWithCharity' => donation.elements['ShareWithCharity'].get_text.to_s,
|
274
|
+
'DonorEmail' => donation.elements['DonorEmail'].get_text.to_s,
|
275
|
+
'DonorFirstName' => donation.elements['DonorFirstName'].get_text.to_s,
|
276
|
+
'DonorLastName' => donation.elements['DonorLastName'].get_text.to_s,
|
277
|
+
'DonorAddress1' => donation.elements['DonorAddress1'].get_text.to_s,
|
278
|
+
'DonorAddress2' => donation.elements['DonorAddress2'].get_text.to_s,
|
279
|
+
'DonorCity' => donation.elements['DonorCity'].get_text.to_s,
|
280
|
+
'DonorState' => donation.elements['DonorState'].get_text.to_s,
|
281
|
+
'DonorZip' => donation.elements['DonorZip'].get_text.to_s,
|
282
|
+
'DonorCountry' => donation.elements['DonorCountry'].get_text.to_s,
|
283
|
+
'DonorPhone' => donation.elements['DonorPhone'].get_text.to_s,
|
284
|
+
'Designation' => donation.elements['Designation'].get_text.to_s,
|
285
|
+
'DonateInName' => donation.elements['DonateInName'].get_text.to_s,
|
286
|
+
'RecurringPeriod' => donation.elements['RecurringPeriod'].get_text.to_s,
|
287
|
+
'EventDate' => donation.elements['EventDate'].get_text.to_s,
|
288
|
+
'NpoEIN' => donation.elements['NpoEIN'].get_text.to_s,
|
289
|
+
'NpoName' => donation.elements['NpoName'].get_text.to_s,
|
290
|
+
'ChargeStatus' => donation.elements['ChargeStatus'].get_text.to_s,
|
291
|
+
'ChargeAmount' => donation.elements['ChargeAmount'].get_text.to_s,
|
292
|
+
'NpoTPC' => donation.elements['NpoTPC'].get_text.to_s,
|
293
|
+
'DonationItemAmount' => donation.elements['DonationItemAmount'].get_text.to_s,
|
294
|
+
'TotalDonationAmount' => donation.elements['TotalDonationAmount'].get_text.to_s,
|
295
|
+
'HistoryRecordId' => donation.elements['HistoryRecordId'].get_text.to_s
|
296
|
+
}
|
297
|
+
end
|
298
|
+
response_hash
|
299
|
+
else
|
300
|
+
response
|
301
|
+
end
|
302
|
+
end
|
303
|
+
|
304
|
+
private
|
305
|
+
|
306
|
+
# Adds client credentials to hash of parameters
|
307
|
+
#
|
308
|
+
# Arguments:
|
309
|
+
# params: (Hash)
|
310
|
+
def add_credentials_to_params(params)
|
311
|
+
return params unless params.is_a? Hash
|
312
|
+
credentials = {
|
313
|
+
'PartnerID' => @partner_id,
|
314
|
+
'PartnerPW' => @partner_password,
|
315
|
+
'PartnerSource' => @partner_source,
|
316
|
+
'PartnerCampaign' => @partner_campaign
|
317
|
+
}
|
318
|
+
credentials.merge(params)
|
319
|
+
end
|
320
|
+
end
|
321
|
+
end
|
@@ -0,0 +1,91 @@
|
|
1
|
+
require 'net/http'
|
2
|
+
require 'rexml/document'
|
3
|
+
|
4
|
+
module NFGClient
|
5
|
+
module Utils
|
6
|
+
@@nfg_urls = {
|
7
|
+
'sandbox' => {
|
8
|
+
'host' => 'api-sandbox.networkforgood.org',
|
9
|
+
'url' => 'https://api-sandbox.networkforgood.org/PartnerDonationService/DonationServices.asmx',
|
10
|
+
'wsdl' => 'https://api-sandbox.networkforgood.org/PartnerDonationService/DonationServices.asmx?wsdl'
|
11
|
+
},
|
12
|
+
'production' => {
|
13
|
+
'host' => 'api.networkforgood.org',
|
14
|
+
'url' => 'https://api.networkforgood.org/PartnerDonationService/DonationServices.asmx',
|
15
|
+
'wsdl' => 'https://api.networkforgood.org/PartnerDonationService/DonationServices.asmx?wsdl'
|
16
|
+
}
|
17
|
+
}
|
18
|
+
|
19
|
+
# Makes HTTP POST request to NFG server (sandbox or production) and returns parsed XML response.
|
20
|
+
#
|
21
|
+
# Arguments:
|
22
|
+
# nfg_method: (String)
|
23
|
+
# params: (Hash)
|
24
|
+
def nfg_soap_request(nfg_method, params, use_sandbox = false)
|
25
|
+
if (nfg_method.is_a? String) && (params.is_a? Hash)
|
26
|
+
# Build SOAP 1.2 request
|
27
|
+
soap_request = build_nfg_soap_request(nfg_method,params)
|
28
|
+
|
29
|
+
# Build request URL & header
|
30
|
+
host = use_sandbox ? @@nfg_urls['sandbox']['host'] : @@nfg_urls['production']['host']
|
31
|
+
url = use_sandbox ? @@nfg_urls['sandbox']['url'] : @@nfg_urls['production']['url']
|
32
|
+
headers = {
|
33
|
+
'Host' => host,
|
34
|
+
'Content-Type' => 'application/soap+xml; charset=utf-8',
|
35
|
+
'Content-Length' => soap_request.length.to_s,
|
36
|
+
'SOAPAction' => "#{url}/#{nfg_method}".gsub('.asmx','')
|
37
|
+
}
|
38
|
+
|
39
|
+
return_value = Hash.new
|
40
|
+
|
41
|
+
# Being HTTP Post
|
42
|
+
begin
|
43
|
+
uri = URI.parse(url)
|
44
|
+
https_conn = Net::HTTP.new(uri.host, uri.port)
|
45
|
+
https_conn.use_ssl = true
|
46
|
+
response = https_conn.post(uri.path, soap_request, headers)
|
47
|
+
if response.code == '200'
|
48
|
+
parsed = REXML::Document.new(response.body)
|
49
|
+
#return response.body
|
50
|
+
# Build return hash parsing XML response
|
51
|
+
if parsed.root.nil?
|
52
|
+
return_value['StatusCode'] = 'MissingParameter'
|
53
|
+
return_value['Message'] = response.body
|
54
|
+
return_value['ErrorDetails'] = nil
|
55
|
+
else
|
56
|
+
return_value = parsed.root.elements['soap:Body'].elements["#{nfg_method}Response"].elements["#{nfg_method}Result"]
|
57
|
+
end
|
58
|
+
else
|
59
|
+
return_value['StatusCode'] = 'UnexpectedError'
|
60
|
+
return_value['Message'] = response.message
|
61
|
+
return_value['ErrorDetails'] = response.body
|
62
|
+
end
|
63
|
+
rescue StandardError => e
|
64
|
+
return_value['StatusCode'] = 'UnexpectedError'
|
65
|
+
return_value['Message'] = e
|
66
|
+
return_value['ErrorDetails'] = e.backtrace.join(' ')
|
67
|
+
end
|
68
|
+
|
69
|
+
return_value
|
70
|
+
else
|
71
|
+
raise ArgumentError.new('http_post requires a nfg_method and a hash of params')
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
def build_nfg_soap_request(nfg_method, params)
|
76
|
+
get_nfg_soap_request_template.gsub('|body|',"<#{nfg_method} xmlns=\"http://api.networkforgood.org/partnerdonationservice\">#{hash_to_xml(params)}</#{nfg_method}>")
|
77
|
+
end
|
78
|
+
|
79
|
+
def get_nfg_soap_request_template
|
80
|
+
"<?xml version=\"1.0\" encoding=\"utf-8\"?><soap12:Envelope xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:soap12=\"http://www.w3.org/2003/05/soap-envelope\"><soap12:Body>|body|</soap12:Body></soap12:Envelope>"
|
81
|
+
end
|
82
|
+
|
83
|
+
def hash_to_xml(hash)
|
84
|
+
hash.map do |k, v|
|
85
|
+
text = (v.is_a? Hash) ? hash_to_xml(v) : v
|
86
|
+
xml_elem = (v.is_a? Hash) ? k.gsub(/(\d)/, "") : k
|
87
|
+
"<%s>%s</%s>" % [xml_elem, text, xml_elem]
|
88
|
+
end.join
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
data/nfg-client.gemspec
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'nfg-client/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |gem|
|
7
|
+
gem.name = "nfg-client"
|
8
|
+
gem.version = NFGClient::VERSION
|
9
|
+
gem.authors = ["Antonio Ruano Cuesta"]
|
10
|
+
gem.email = ["ruanest@gmail.com"]
|
11
|
+
gem.description = %q{Client for the Network for Good SOAP API.}
|
12
|
+
gem.summary = gem.description
|
13
|
+
gem.licenses = %w(MIT)
|
14
|
+
gem.homepage = "https://github.com/aruanoc/nfg-client"
|
15
|
+
|
16
|
+
gem.files = `git ls-files`.split($/)
|
17
|
+
gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
|
18
|
+
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
19
|
+
gem.require_paths = ["lib"]
|
20
|
+
|
21
|
+
gem.add_runtime_dependency 'andand', "~> 1.3.3"
|
22
|
+
|
23
|
+
gem.add_development_dependency 'rspec', '~> 2.13.0'
|
24
|
+
gem.add_development_dependency 'simplecov'
|
25
|
+
end
|
File without changes
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
require 'simplecov'
|
2
|
+
SimpleCov.start
|
3
|
+
|
4
|
+
# This file was generated by the `rspec --init` command. Conventionally, all
|
5
|
+
# specs live under a `spec` directory, which RSpec adds to the `$LOAD_PATH`.
|
6
|
+
# Require this file using `require "spec_helper"` to ensure that it is only
|
7
|
+
# loaded once.
|
8
|
+
#
|
9
|
+
# See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
|
10
|
+
RSpec.configure do |config|
|
11
|
+
config.treat_symbols_as_metadata_keys_with_true_values = true
|
12
|
+
config.run_all_when_everything_filtered = true
|
13
|
+
config.filter_run :focus
|
14
|
+
|
15
|
+
# Run specs in random order to surface order dependencies. If you find an
|
16
|
+
# order dependency and want to debug it, you can fix the order by providing
|
17
|
+
# the seed, which is printed after each run.
|
18
|
+
# --seed 1234
|
19
|
+
config.order = 'random'
|
20
|
+
end
|
metadata
ADDED
@@ -0,0 +1,102 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: nfg-client
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.0.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Antonio Ruano Cuesta
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2014-03-18 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: andand
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ~>
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: 1.3.3
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ~>
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: 1.3.3
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rspec
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ~>
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: 2.13.0
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ~>
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: 2.13.0
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: simplecov
|
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
|
+
description: Client for the Network for Good SOAP API.
|
56
|
+
email:
|
57
|
+
- ruanest@gmail.com
|
58
|
+
executables: []
|
59
|
+
extensions: []
|
60
|
+
extra_rdoc_files: []
|
61
|
+
files:
|
62
|
+
- .gitignore
|
63
|
+
- .rspec
|
64
|
+
- Gemfile
|
65
|
+
- LICENSE.md
|
66
|
+
- README.md
|
67
|
+
- Rakefile
|
68
|
+
- lib/nfg-client.rb
|
69
|
+
- lib/nfg-client/client.rb
|
70
|
+
- lib/nfg-client/utils.rb
|
71
|
+
- lib/nfg-client/version.rb
|
72
|
+
- nfg-client.gemspec
|
73
|
+
- spec/nfg_client_spec.rb
|
74
|
+
- spec/spec_helper.rb
|
75
|
+
homepage: https://github.com/aruanoc/nfg-client
|
76
|
+
licenses:
|
77
|
+
- MIT
|
78
|
+
metadata: {}
|
79
|
+
post_install_message:
|
80
|
+
rdoc_options: []
|
81
|
+
require_paths:
|
82
|
+
- lib
|
83
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
84
|
+
requirements:
|
85
|
+
- - ! '>='
|
86
|
+
- !ruby/object:Gem::Version
|
87
|
+
version: '0'
|
88
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
89
|
+
requirements:
|
90
|
+
- - ! '>='
|
91
|
+
- !ruby/object:Gem::Version
|
92
|
+
version: '0'
|
93
|
+
requirements: []
|
94
|
+
rubyforge_project:
|
95
|
+
rubygems_version: 2.2.2
|
96
|
+
signing_key:
|
97
|
+
specification_version: 4
|
98
|
+
summary: Client for the Network for Good SOAP API.
|
99
|
+
test_files:
|
100
|
+
- spec/nfg_client_spec.rb
|
101
|
+
- spec/spec_helper.rb
|
102
|
+
has_rdoc:
|