stamps 0.2.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.
- data/.gitignore +5 -0
- data/.rvmrc +1 -0
- data/Gemfile +4 -0
- data/Gemfile.lock +49 -0
- data/README.md +186 -0
- data/Rakefile +13 -0
- data/lib/stamps.rb +33 -0
- data/lib/stamps/api.rb +18 -0
- data/lib/stamps/client.rb +12 -0
- data/lib/stamps/client/account.rb +36 -0
- data/lib/stamps/client/address.rb +16 -0
- data/lib/stamps/client/rate.rb +39 -0
- data/lib/stamps/client/stamp.rb +62 -0
- data/lib/stamps/configuration.rb +69 -0
- data/lib/stamps/errors.rb +34 -0
- data/lib/stamps/mapping.rb +247 -0
- data/lib/stamps/request.rb +55 -0
- data/lib/stamps/response.rb +71 -0
- data/lib/stamps/trash.rb +29 -0
- data/lib/stamps/types.rb +68 -0
- data/lib/stamps/version.rb +3 -0
- data/stamps.gemspec +33 -0
- data/test/client/account_test.rb +64 -0
- data/test/client/address_test.rb +36 -0
- data/test/client/rate_test.rb +44 -0
- data/test/client/stamp_test.rb +89 -0
- data/test/fixtures/AuthenticateUser.xml +9 -0
- data/test/fixtures/CancelIndicium.xml +8 -0
- data/test/fixtures/CarrierPickup.xml +11 -0
- data/test/fixtures/CleanseAddress.xml +24 -0
- data/test/fixtures/CreateIndicium.xml +32 -0
- data/test/fixtures/GetAccountInfo.xml +87 -0
- data/test/fixtures/GetRate.xml +163 -0
- data/test/fixtures/GetRates.xml +645 -0
- data/test/fixtures/InsufficientPostage.xml +14 -0
- data/test/fixtures/InvalidSoap.xml +13 -0
- data/test/fixtures/PurchasePostage.xml +16 -0
- data/test/fixtures/TrackShipment.xml +43 -0
- data/test/helper.rb +58 -0
- data/test/mapping_test.rb +33 -0
- data/test/response_test.rb +66 -0
- data/test/stamps_test.rb +26 -0
- data/test/types_test.rb +25 -0
- metadata +228 -0
@@ -0,0 +1,69 @@
|
|
1
|
+
module Stamps
|
2
|
+
# Defines constants and methods related to configuration
|
3
|
+
module Configuration
|
4
|
+
|
5
|
+
# An array of valid keys in the options hash when configuring a {Twitter::API}
|
6
|
+
VALID_OPTIONS_KEYS = [
|
7
|
+
:integration_id,
|
8
|
+
:username,
|
9
|
+
:password,
|
10
|
+
:namespace,
|
11
|
+
:format,
|
12
|
+
:return_address,
|
13
|
+
:test_mode,
|
14
|
+
:raise_errors,
|
15
|
+
:log_messages,
|
16
|
+
:endpoint].freeze
|
17
|
+
|
18
|
+
# The endpoint that will be used to connect if none is set
|
19
|
+
DEFAULT_ENDPOINT = 'https://swsim.testing.stamps.com/swsim/swsimv12.asmx'.freeze
|
20
|
+
|
21
|
+
# The default namespace used on Stamps.com wsdl
|
22
|
+
DEFAULT_NAMESPACE = 'http://stamps.com/xml/namespace/2010/11/swsim/swsimv12'
|
23
|
+
|
24
|
+
# @note JSON is preferred over XML because it is more concise and faster to parse.
|
25
|
+
DEFAULT_FORMAT = :hash
|
26
|
+
|
27
|
+
# The user agent that will be sent to the API endpoint if none is set
|
28
|
+
DEFAULT_USER_AGENT = "Stamps Ruby Gem".freeze
|
29
|
+
|
30
|
+
# Do not raise errors by default
|
31
|
+
DEFAULT_RAISE_ERRORS = false
|
32
|
+
|
33
|
+
# Do not log requests and response by default
|
34
|
+
DEFAULT_LOG_MESSAGES = false
|
35
|
+
|
36
|
+
# @private
|
37
|
+
attr_accessor *VALID_OPTIONS_KEYS
|
38
|
+
|
39
|
+
# When this module is extended, set all configuration options to their default values
|
40
|
+
def self.extended(base)
|
41
|
+
base.reset
|
42
|
+
end
|
43
|
+
|
44
|
+
# Convenience method to allow configuration options to be set in a block
|
45
|
+
def configure
|
46
|
+
yield self
|
47
|
+
|
48
|
+
HTTPI.log = false
|
49
|
+
Savon.configure do |config|
|
50
|
+
config.log = self.log_messages
|
51
|
+
config.raise_errors = self.raise_errors
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
# Create a hash of options and their values
|
56
|
+
def options
|
57
|
+
Hash[VALID_OPTIONS_KEYS.map {|key| [key, send(key)] }]
|
58
|
+
end
|
59
|
+
|
60
|
+
# Reset all configuration options to defaults
|
61
|
+
def reset
|
62
|
+
self.endpoint = DEFAULT_ENDPOINT
|
63
|
+
self.namespace = DEFAULT_NAMESPACE
|
64
|
+
self.format = DEFAULT_FORMAT
|
65
|
+
self.log_messages = DEFAULT_LOG_MESSAGES
|
66
|
+
self.raise_errors = DEFAULT_RAISE_ERRORS
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
module Stamps
|
2
|
+
|
3
|
+
# Custom error class for rescuing from all Stamps.com errors
|
4
|
+
class Error < StandardError
|
5
|
+
attr_reader :data
|
6
|
+
|
7
|
+
def initialize(data)
|
8
|
+
@data = data
|
9
|
+
super
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
# Raised when Stamps.com returns the HTTP status code 400
|
14
|
+
class BadRequest < Error; end
|
15
|
+
|
16
|
+
# Raised when Stamps.com returns the HTTP status code 401
|
17
|
+
class Unauthorized < Error; end
|
18
|
+
|
19
|
+
# Raised when Stamps.com returns the HTTP status code 403
|
20
|
+
class Forbidden < Error; end
|
21
|
+
|
22
|
+
# Raised when Stamps.com returns the HTTP status code 404
|
23
|
+
class NotFound < Error; end
|
24
|
+
|
25
|
+
# Raised when Stamps.com returns the HTTP status code 406
|
26
|
+
class NotAcceptable < Error; end
|
27
|
+
|
28
|
+
# Raised when Stamps.com returns the HTTP status code 500
|
29
|
+
class InternalServerError < Error; end
|
30
|
+
|
31
|
+
# Raised when Stamps.com returns the HTTP status code 503
|
32
|
+
class ServiceUnavailable < Error; end
|
33
|
+
|
34
|
+
end
|
@@ -0,0 +1,247 @@
|
|
1
|
+
module Stamps
|
2
|
+
|
3
|
+
# == Mapping Module
|
4
|
+
#
|
5
|
+
# Provides an interface to convert hash keys and values into a
|
6
|
+
# hash that can be easily coverted to an xml document that the
|
7
|
+
# web service can understand.
|
8
|
+
#
|
9
|
+
#
|
10
|
+
module Mapping
|
11
|
+
|
12
|
+
class Account < Hashie::Trash
|
13
|
+
property :Authenticator, :from => :authenticator
|
14
|
+
end
|
15
|
+
|
16
|
+
class AuthenticateUser < Hashie::Trash
|
17
|
+
property :Credentials, :from => :credentials
|
18
|
+
|
19
|
+
def credentials=(val)
|
20
|
+
self[:Credentials] = Credentials.new(val)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
class Credentials < Hashie::Trash
|
25
|
+
property :IntegrationID, :from => :integration_id
|
26
|
+
property :Username, :from => :username
|
27
|
+
property :Password, :from => :password
|
28
|
+
end
|
29
|
+
|
30
|
+
class Rates < Hashie::Trash
|
31
|
+
property :Authenticator, :from => :authenticator
|
32
|
+
property :Rate, :from => :rate
|
33
|
+
end
|
34
|
+
|
35
|
+
class Rate < Hashie::Trash
|
36
|
+
property :FromZIPCode, :from => :from_zip_code
|
37
|
+
property :ToZIPCode, :from => :to_zip_code
|
38
|
+
property :ToCountry, :from => :to_country
|
39
|
+
property :Amount, :from => :amount
|
40
|
+
property :MaxAmount, :from => :max_amount
|
41
|
+
property :ServiceType, :from => :service_type
|
42
|
+
property :PrintLayout, :from => :print_layout
|
43
|
+
property :DeliverDays, :from => :deliver_days
|
44
|
+
property :Error, :from => :error
|
45
|
+
property :WeightLb, :from => :weight_lb
|
46
|
+
property :WeightOz, :from => :weight_oz
|
47
|
+
property :PackageType, :from => :package_type
|
48
|
+
property :RequiresAllOf, :from => :requires_all
|
49
|
+
property :Length, :from => :length
|
50
|
+
property :Width, :from => :width
|
51
|
+
property :Height, :from => :height
|
52
|
+
property :ShipDate, :from => :ship_date
|
53
|
+
property :InsuredValue, :from => :insured_value
|
54
|
+
property :RegisteredValue, :from => :registration_value
|
55
|
+
property :CODValue, :from => :cod_value
|
56
|
+
property :DeclaredValue, :from => :declared_value
|
57
|
+
property :NonMachinable, :from => :non_machinable
|
58
|
+
property :RectangularShaped, :from => :rectangular
|
59
|
+
property :Prohibitions, :from => :prohibitions
|
60
|
+
property :Restrictions, :from => :restrictions
|
61
|
+
property :Observations, :from => :observations
|
62
|
+
property :Regulations, :from => :regulations
|
63
|
+
property :GEMNotes, :from => :gem_notes
|
64
|
+
property :MaxDimensions, :from => :max_dimensions
|
65
|
+
property :DimWeighting, :from => :dim_weighting
|
66
|
+
property :AddOns, :from => :add_ons
|
67
|
+
property :EffectiveWeightInOunces, :from => :effective_weight_in_ounces
|
68
|
+
property :IsIntraBMC, :from => :is_intra_bmc
|
69
|
+
property :Zone, :from => :zone
|
70
|
+
property :RateCategory, :from => :rate_category
|
71
|
+
property :ToState, :from => :to_state
|
72
|
+
property :CubicPricing, :from => :cubic_pricing
|
73
|
+
|
74
|
+
# Maps :rate to AddOns map
|
75
|
+
def add_ons=(addons)
|
76
|
+
self[:AddOns] = AddOnsArray.new(:add_on => addons[:add_on])
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
class AddOnsArray < Hashie::Trash
|
81
|
+
property :AddOnV2, :from => :add_on
|
82
|
+
def add_on=(vals)
|
83
|
+
return unless vals
|
84
|
+
self[:AddOnV2] = vals.map{ |value| AddOnV2.new(value).to_hash }
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
class AddOnV2 < Hashie::Trash
|
89
|
+
property :Amount, :from => :amount
|
90
|
+
property :AddOnType, :from => :type
|
91
|
+
end
|
92
|
+
|
93
|
+
class Stamp < Hashie::Trash
|
94
|
+
property :Authenticator, :from => :authenticator
|
95
|
+
property :IntegratorTxID, :from => :transaction_id
|
96
|
+
property :TrackingNumber, :from => :tracking_number
|
97
|
+
property :Rate, :from => :rate
|
98
|
+
property :From, :from => :from
|
99
|
+
property :To, :from => :to
|
100
|
+
property :CustomerID, :from => :customer_id
|
101
|
+
property :Customs, :from => :customs
|
102
|
+
property :SampleOnly, :from => :sample
|
103
|
+
property :ImageType, :from => :image_type
|
104
|
+
property :EltronPrinterDPIType, :from => :label_resolution
|
105
|
+
property :memo
|
106
|
+
property :recipient_email, :from => :recipient_email
|
107
|
+
property :deliveryNotification, :from => :notify
|
108
|
+
property :shipmentNotificationCC, :from => :notify_crates
|
109
|
+
property :shipmentNotificationFromCompany, :from => :notify_from_company
|
110
|
+
property :shipmentNotificationCompanyInSubject, :from => :notify_in_subject
|
111
|
+
property :rotationDegrees, :from => :rotation
|
112
|
+
property :printMemo, :from => :print_memo
|
113
|
+
|
114
|
+
# Maps :from to Address map
|
115
|
+
def from=(val)
|
116
|
+
# Set the defult :from address from address
|
117
|
+
self[:From] = Address.new(Stamps.return_address.merge!(val))
|
118
|
+
end
|
119
|
+
|
120
|
+
# Maps :to to Address map
|
121
|
+
def to=(val)
|
122
|
+
self[:To] = Address.new(val)
|
123
|
+
end
|
124
|
+
|
125
|
+
# Maps :rate to Rate map
|
126
|
+
def rate=(val)
|
127
|
+
self[:Rate] = Rate.new(val)
|
128
|
+
end
|
129
|
+
|
130
|
+
# Maps :customs to Customs map
|
131
|
+
def customs=(val)
|
132
|
+
self[:Customs] = Customs.new(val)
|
133
|
+
end
|
134
|
+
end
|
135
|
+
|
136
|
+
class Address < Hashie::Trash
|
137
|
+
property :FullName, :from => :full_name
|
138
|
+
property :NamePrefix, :from => :name_prefix
|
139
|
+
property :FirstName, :from => :first_name
|
140
|
+
property :MiddleName, :from => :middle_name
|
141
|
+
property :LastName, :from => :last_name
|
142
|
+
property :NameSuffix, :from => :name_suffex
|
143
|
+
property :Title, :from => :title
|
144
|
+
property :Department, :from => :deparartment
|
145
|
+
property :Company, :from => :company
|
146
|
+
property :Address1, :from => :address1
|
147
|
+
property :Address2, :from => :address2
|
148
|
+
property :City, :from => :city
|
149
|
+
property :State, :from => :state
|
150
|
+
property :ZIPCode, :from => :zip_code
|
151
|
+
property :ZIPCodeAddOn, :from => :zip_code_add_on
|
152
|
+
property :DPB, :from => :dpb
|
153
|
+
property :CheckDigit, :from => :check_digit
|
154
|
+
property :Province, :from => :province
|
155
|
+
property :PostalCode, :from => :postal_code
|
156
|
+
property :Country, :from => :country
|
157
|
+
property :Urbanization, :from => :urbanization
|
158
|
+
property :PhoneNumber, :from => :phone_number
|
159
|
+
property :Extension, :from => :extentsion
|
160
|
+
property :CleanseHash, :from => :cleanse_hash
|
161
|
+
property :OverrideHash, :from => :override_hash
|
162
|
+
end
|
163
|
+
|
164
|
+
class CleanseAddress < Hashie::Trash
|
165
|
+
property :Authenticator, :from => :authenticator
|
166
|
+
property :Address, :from => :address
|
167
|
+
|
168
|
+
# Maps :address to Address map
|
169
|
+
def address=(val)
|
170
|
+
self[:Address] = Address.new(val)
|
171
|
+
end
|
172
|
+
end
|
173
|
+
|
174
|
+
class PurchasePostage < Hashie::Trash
|
175
|
+
property :Authenticator, :from => :authenticator
|
176
|
+
property :PurchaseAmount, :from => :amount
|
177
|
+
property :ControlTotal, :from => :control_total
|
178
|
+
end
|
179
|
+
|
180
|
+
class CancelStamp< Hashie::Trash
|
181
|
+
property :Authenticator, :from => :authenticator
|
182
|
+
property :StampsTxID, :from => :transaction_id
|
183
|
+
property :TrackingNumber, :from => :tracking_number
|
184
|
+
end
|
185
|
+
|
186
|
+
class CarrierPickup < Hashie::Trash
|
187
|
+
property :Authenticator, :from => :authenticator
|
188
|
+
property :FirstName, :from => :first_name
|
189
|
+
property :LastName, :from => :last_name
|
190
|
+
property :Company, :from => :company
|
191
|
+
property :Address, :from => :address
|
192
|
+
property :SuiteOrApt, :from => :suite, :default => ''
|
193
|
+
property :City, :from => :city
|
194
|
+
property :State, :from => :state
|
195
|
+
property :ZIP, :from => :zip
|
196
|
+
property :ZIP4, :from => :zip_four
|
197
|
+
property :PhoneNumber, :from => :phone
|
198
|
+
property :PhoneExt, :from => :phone_ext
|
199
|
+
property :NumberOfExpressMailPieces, :from => :express_mail_count
|
200
|
+
property :NumberOfPriorityMailPieces, :from => :priority_mail_count
|
201
|
+
property :NumberOfInternationalPieces, :from => :international_mail_count
|
202
|
+
property :NumberOfOtherPieces, :from => :other_mail_count
|
203
|
+
property :TotalWeightOfPackagesLbs, :from => :total_weight
|
204
|
+
property :PackageLocation, :from => :location
|
205
|
+
property :SpecialInstruction, :from => :special_instruction
|
206
|
+
end
|
207
|
+
|
208
|
+
class Customs < Hashie::Trash
|
209
|
+
property :ContentType, :from => :content_type
|
210
|
+
property :Comments, :from => :comments
|
211
|
+
property :LicenseNumber, :from => :license_number
|
212
|
+
property :CertificateNumber, :from => :certificate_number
|
213
|
+
property :InvoiceNumber, :from => :invoice_number
|
214
|
+
property :OtherDescribe, :from => :other_describe
|
215
|
+
property :CustomsLines, :from => :customs_lines
|
216
|
+
|
217
|
+
# Maps :customs CustomsLine map
|
218
|
+
def customs_lines=(customs)
|
219
|
+
# Important: Must call to_hash to force re-ordering!
|
220
|
+
self[:CustomsLines] = customs.collect{ |val| CustomsLinesArray.new(val).to_hash }
|
221
|
+
end
|
222
|
+
end
|
223
|
+
|
224
|
+
class CustomsLinesArray < Hashie::Trash
|
225
|
+
property :CustomsLine, :from => :custom
|
226
|
+
def custom=(val)
|
227
|
+
self[:CustomsLine] = CustomsLine.new(val).to_hash
|
228
|
+
end
|
229
|
+
end
|
230
|
+
|
231
|
+
class CustomsLine < Hashie::Trash
|
232
|
+
property :Description, :from => :description
|
233
|
+
property :Quantity, :from => :quantity
|
234
|
+
property :Value, :from => :value
|
235
|
+
property :WeightLb, :from => :weight_lb
|
236
|
+
property :WeightOz, :from => :weight_oz
|
237
|
+
property :HSTariffNumber, :from => :hs_tariff_number
|
238
|
+
property :CountryOfOrigin, :from => :country_of_origin
|
239
|
+
end
|
240
|
+
|
241
|
+
class TrackShipment < Hashie::Trash
|
242
|
+
property :Authenticator, :from => :authenticator
|
243
|
+
property :StampsTxID, :from => :stamps_transaction_id
|
244
|
+
end
|
245
|
+
|
246
|
+
end
|
247
|
+
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
require 'hashie'
|
2
|
+
require 'savon'
|
3
|
+
require File.expand_path('../response', __FILE__)
|
4
|
+
|
5
|
+
module Stamps
|
6
|
+
|
7
|
+
# Defines HTTP request methods
|
8
|
+
module Request
|
9
|
+
|
10
|
+
# Perform an HTTP request
|
11
|
+
def request(web_method, params, raw=false)
|
12
|
+
client = Savon::Client.new do |wsdl, http|
|
13
|
+
wsdl.endpoint = self.endpoint
|
14
|
+
wsdl.namespace = self.namespace
|
15
|
+
end
|
16
|
+
|
17
|
+
response = client.request :tns, web_method do
|
18
|
+
http.headers = { "SoapAction" => formatted_soap_action(web_method) }
|
19
|
+
soap.namespace = 'tns'
|
20
|
+
soap.element_form_default = :qualified
|
21
|
+
soap.env_namespace = 'soap'
|
22
|
+
soap.namespaces["xmlns:tns"] = self.namespace
|
23
|
+
soap.body = params.to_hash
|
24
|
+
end
|
25
|
+
Stamps::Response.new(response).to_hash
|
26
|
+
end
|
27
|
+
|
28
|
+
# Get the Authenticator token. By using an Authenticator, the integration
|
29
|
+
# can be sure that the conversation between the integration and the SWS
|
30
|
+
# server is kept in sync and no messages have been lost.
|
31
|
+
#
|
32
|
+
def authenticator_token
|
33
|
+
@authenticator ||= self.get_authenticator_token
|
34
|
+
end
|
35
|
+
|
36
|
+
# Make Authentication request for the user
|
37
|
+
#
|
38
|
+
def get_authenticator_token
|
39
|
+
self.request('AuthenticateUser',
|
40
|
+
Stamps::Mapping::AuthenticateUser.new(
|
41
|
+
:credentials => {
|
42
|
+
:integration_id => self.integration_id,
|
43
|
+
:username => self.username,
|
44
|
+
:password => self.password
|
45
|
+
})
|
46
|
+
)[:authenticate_user_response][:authenticator]
|
47
|
+
end
|
48
|
+
|
49
|
+
# Concatenates namespace and web method in a way the API can understand
|
50
|
+
def formatted_soap_action(web_method)
|
51
|
+
[self.namespace, web_method.to_s].compact.join('/')
|
52
|
+
end
|
53
|
+
|
54
|
+
end
|
55
|
+
end
|
@@ -0,0 +1,71 @@
|
|
1
|
+
module Stamps
|
2
|
+
|
3
|
+
# = Stamps::Response
|
4
|
+
#
|
5
|
+
# Represents the response and contains the HTTP response.
|
6
|
+
#
|
7
|
+
class Response
|
8
|
+
|
9
|
+
# Expects an <tt>Savon::SOAP::Response</tt> and handles errors.
|
10
|
+
def initialize(response)
|
11
|
+
self.errors = []
|
12
|
+
self.valid = true
|
13
|
+
self.savon = response
|
14
|
+
self.http = response.http
|
15
|
+
self.hash = self.savon.to_hash
|
16
|
+
raise_errors
|
17
|
+
end
|
18
|
+
|
19
|
+
attr_accessor :savon, :http, :errors, :valid, :hash, :code
|
20
|
+
|
21
|
+
# Returns the SOAP response body as a Hash.
|
22
|
+
def to_hash
|
23
|
+
self.hash.merge!(:errors => self.errors)
|
24
|
+
self.hash.merge!(:valid? => self.valid)
|
25
|
+
self.hash
|
26
|
+
Stamps.format.to_s.downcase == 'hashie' ? Hashie::Mash.new(@hash) : self.hash
|
27
|
+
end
|
28
|
+
|
29
|
+
# Um, there's gotta be a better way
|
30
|
+
def valid?
|
31
|
+
self.valid
|
32
|
+
end
|
33
|
+
|
34
|
+
# Process any errors we get back from the service.
|
35
|
+
# Wrap any internal errors (from Soap Faults) into an array
|
36
|
+
# so that clients can process the error messages as they wish
|
37
|
+
#
|
38
|
+
def raise_errors
|
39
|
+
message = 'FIXME: Need to parse http for response message'
|
40
|
+
return self.format_soap_faults if savon.soap_fault.present?
|
41
|
+
|
42
|
+
case http.code.to_i
|
43
|
+
when 200
|
44
|
+
return
|
45
|
+
when 400
|
46
|
+
raise BadRequest, "(#{http.code}): #{message}"
|
47
|
+
when 401
|
48
|
+
raise Unauthorized, "(#{http.code}): #{message}"
|
49
|
+
when 403
|
50
|
+
raise Forbidden, "(#{http.code}): #{message}"
|
51
|
+
when 404
|
52
|
+
raise NotFound, "(#{http.code}): #{message}"
|
53
|
+
when 406
|
54
|
+
raise NotAcceptable, "(#{http.code}): #{message}"
|
55
|
+
when 500
|
56
|
+
raise InternalServerError, "Stamps.com had an internal error. (#{http.code}): #{message}"
|
57
|
+
when 502..503
|
58
|
+
raise ServiceUnavailable, "(#{http.code}): #{message}"
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
# Include any errors in the response
|
63
|
+
#
|
64
|
+
def format_soap_faults
|
65
|
+
fault = self.hash.delete(:fault)
|
66
|
+
self.errors << fault[:faultstring]
|
67
|
+
self.valid = false
|
68
|
+
end
|
69
|
+
|
70
|
+
end
|
71
|
+
end
|