Recently I came across a project which is developed for Campaigning Purpose. The users were given three options for campaigning those are Text Messaging, Voice messaging and Emailing. For Text messaging the services Ericsson is used for United States, while the esendex services used for United Kingdom.Here I will be giving a detailed way to register for service, implementing and using it successfully.Ericsson IPXInternet Payment eXchange (IPX) is a solution and technology for micro payments. IPX acts as a transparent, white-label Content Acquirer and Transaction Router between Operators and Content Providers. Content Providers are provided with an easily implemented interface to connect to IPX, which handles integration to the Operators. The Content Provider’s interface to IPX is independent of the Consumer’s device type (PC, mobile phone, PDA, etc.).The IPX system provides the following basic functionality for short messaging:
- Sending mobile terminated (MT) short messages, such as text or binary.(e.g. EMS) messages, premium and non-premium.
- Receiving delivery reports for submitted MT messages.
- Receiving mobile originated (MO) short messages, premium and nonpremium.
Steps involved in sending message
- The Content Provider makes a request to send an SM to the IPX system.
- IPX handles routing, charging (in case of premium message) and delivers the message to the addressed Consumer.
A message ID is returned to the Content Provider synchronously. This ID can be used for tracing a certain message.Step 4 and 5 are executed if the Content Provider requested a delivery report in step 1.4. A delivery report is triggered, e.g. when the message is delivered to the Consumer’s mobile station.5. The delivery report is sent to the Content Provider (the report contains the same message ID as returned in step 3.Steps involved in receiving message
- The Consumer sends an SM to a short number.
- IPX transmits the SM to the Content Provider.
- The Content Provider acknowledges the SM.
InstallationIPX provides an API exposed as a web service with a SOAP interface. The SOAP protocol and the IPX server are independent of the platform used on the client side, although the installation of the SOAP tools could be different. The web service API is described in WSDL. For those not familiar with web services, IPX also provides a set of Java classes generated from the web service WSDL description. These classes can be used as an SDK and are provided by IPX upon request.System requirementsThe Content Provider needs the following:
- Web server with a fixed domain name or IP address
- SOAP Toolkit/SDK
Tuesday, December 30, 2008
Basic introduction
Reason,Responce codes and variables
Sending SMThe send request element is formatted as follows:
Element
Type
Default Value
Max
length
Description
correlationId
string
100
Correlation ID to keep track of SOAP
requests and responses (WS-I
recommendation). The server echoes
whatever value is provided.
originatingAddress
string
If omitted, this value
is set by IPX (it is
however highly
recommended that
this value always is
set by the Content
Provider)
16
The originating address for the
outgoing SM. Type of originating
address is defined by the
orginatorTON parameter.
Short number max length is 16.
Alpha numeric sender is limited to
GSM default Alphabet with max length
11 characters.
MSISDN sender max length is 16
originatorTON
integer
1
The originating address. type of
number (TON):
0 . Short number
1 . Alpha numeric (max length 11)
2 . MSISDN
Behaviour may vary with Operator
integrations.
destinationAddress
string
40
The MSISDN that the SM should be
sent to, starting with country code.
Example: 46762050312.
For some markets (where the
Consumer MSISDN must be
obfuscated) this value can also be an
alphanumeric alias, prefixed with.#..
Sending SM to multiple recipients is
supported by providing a distribution
list of semi-colon separated MSISDNs
(e.g. 46762050312;46762050313).
Note that no white-spaces are
allowed, the recipients must be unique
within a list and the distribution list is
limited to 1000 entries.
userData
string
Empty message.
280
The message content,
userDataHeader
string
No user data header.
280
User Data Header together with the
User Data can contain up to 140 (i.e.
280 when hex-encoded) octets. This
parameter is always hex-encoded.
DCS
integer
17
3
Data coding scheme. See [5] for more
information.
Behaviour may vary with Operator
integrations.
PID
integer
Use .1 until supported.
relativeValidityTime
integer
172800 (48 hours)
10
Relative validity time in seconds
(relative to the time for the submission
to IPX).
Behaviour may vary with Operator
integrations.
deliveryTime
string
Immediately.
25
The message can be delivered with
delayed delivery time.
Format: yyyy-MM-dd HH:mm:ss Z,
example: 2000-01-01 01:01:01 .0000.
Behaviour may vary with Operator
integrations.
statusReportFlags
integer
0
1
Deliver report request:
0 . No delivery report
1 . Delivery report requested
accountName
string
#NULL#
50
This field allows IPX to route
messages in a flexible manner, which
may or may not be content provider
specific.
For normal usage, #NULL# should be
supplied.
Note: Usage of this field must be
provisioned by IPX.
tariffClass
string
40
Tariff class for the message,
representing the price of a premium
message. Valid market tariff classes
are provided by IPX.
For non-premium messages, the
market.s zero tariff class must be
supplied, e.g. SGD0, EUR0 or
corresponding
VAT
double
-1
5
Set to -1 for normal usage (apply for
most Content Providers).
Specifies the requested (non-default)
VAT.
Note that the VAT finally used is
returned in the submit response.
Behaviour may vary with Operator
integrations.
IPX support should be contacted
before usage.
referenceId
string
150
Referenced order of the premium
message, normally a message ID
from an MO message
contentCategory
string
#NULL#
40
The content category. Set to #NULL#
if not used or not supported by the
market.
Market specific information. Contact
IPX support for further information.
contentMetaData
string
#NULL#
1000
The content meta data. Set to
#NULL# if not used or not supported
by the market.
Market specific information. Contact
IPX support for further information.
Username
string
64
The Content Provider.s username
provided by IPX.
Password
string
64
The Content Provider.s password
provided by IPX.
Receiving SM
Parameter
Type
Max
length
Description
DestinationAddress
string
11
The short number the SM was sent to.
Example: 72160.
OriginatorAddress
string
40
The Consumer.s MSISDN, starting
with the country code (sender of the
SM). Example: 46762050312.
For some markets (where the
Consumer MSISDN must be
obfuscated) this value can also be an
alphanumeric alias, prefixed with .#..
Message
string
280
The message text,
MessageId
string
22
A unique ID for the message. This
message ID should be used as
reference ID when sending premium
MT message.
TimeStamp
string
20
Time of arrival of the SM at the
Operator.s SMSC.
The time zone of the timestamp is
CET or CEST (with summer time as
defined for the EU).
Format: yyyy-MM-dd HH:mm:ss.
Operator
string
100
The name of the Consumer.s Mobile
Operator (a list of available operators
is provided by IPX) or the account
name used when sending the
message.
UserDataHeader
string
280
User Data can contain up to 140 (i.e.
280 when hex-encoded) octets. This
parameter is always hex-encoded.
See [6] for more information.
Behaviour may vary with Operator
integrations. IPX always forwards the
received data unchanged or empty if
not available.
Note: Access to this parameter must
be provisioned by IPX support.
MessageAlphabet
int
2
Indicates the message alphabet used
in the SM:
0 . Default (GSM)
1 . 8 bit (binary)
2 . UCS2
The Message Alphabet is part of the
Data coding scheme as described in
[5].
Note: Access to this parameter must
be provisioned by IPX support.
Related Responce Codes
Code
Text
0
Success
1
Invalid login or un-authorized API
usage
2
Consumer is blocked by IPX
3
Operation is not provisioned by
IPX
4
The consumer is unknown to IPX
5
Consumer has blocked
service in IPX
6
The originating address is not
supported
7
Alpha originating address not
supported by account
8
MSISDN originating address not
supported by account
9
GSM extended not supported by
account
10
Unicode not supported by
account
11
Status report not supported by
account
12
Required capability not
13
Could not route message
14
The content provider max
throttling rate is exceeded
15
The account max throttling rate is
exceeded
50
Partial success: (<1>;<2>;
)
99
Internal server error
100
Invalid destination address
101
Invalid tariff class (price)
102
Invalid referenced (linked) ID
103
Invalid account name
104
Invalid content category
105
Invalid content meta data
106
Invalid originating address
107
Invalid alphanumeric originating
address
108
Invalid validity time
109
Invalid delivery time
110
Invalid message content/user
data
111
Invalid message length
112
Invalid user data header
113
Invalid data coding scheme
114
Invalid protocol ID
115
Invalid status report flags
116
Invalid TON
117
Invalid VAT
200
Operator integration error
201
Communication problems
202
Read timeout
209
Integration error
Reason codes
Reason code
Text
0
Not applicable
1000
The consumer is not
recognized as a subscriber
(from operator)
1001
The subscriber is blocked
(from operator)
1002
The subscriber has insufficient
funds for the requested
transaction (from operator)
1003
The mobile subscribers
message queue is full (from
operator)
1004
Invalid content meta data
1006
Charging error
1007
The subscriber has blocked
this service (from operator)
1008
The subscriber is not
registered (from operator)
working with rails
Sending message:In the Ruby on Rails implementation using Soap4r gem, the SOAP Toolkit has beenused together with ruby Script Version 1.8.6 . The SOAP Toolkit can be downloaded from http://dev.ctor.org/soap4r.
require 'rubygems'gem 'soap4r'require 'soap/rpc/driver'require "soap/wsdlDriver"wsdl_url="http://us.ipx.com/api/services2/SmsApi51?wsdl"soap = SOAP::WSDLDriverFactory.new(wsdl_url).create_rpc_driverh=Hash.newh['originatingAddress']= short_code #provided by ericssonh['originatorTON'] = '0'h['userDataHeader'] =Nh['DCS'] = '17'h['PID'] = '-1'h['relativeValidityTime'] = '-1'h['deliveryTime'] =Nh['statusReportFlags'] = '0'h['accountName'] = Nh['tariffClass'] = 'USD0'h['VAT'] ='-1'h['referenceId'] = Nh['contentCategory'] =Nh['contentMetaData'] =Nh['username']= USERNAME # provided by IPXh['password'] = PASSWORD # provided by IPXh['correlationId'] = sms.correlation_id # set by user sending messageh['destinationAddress'] = sms.destination_address # destination addessh['userData'] = sms.message #actual messageresponce=soap.send(h)puts responceYou can then find the responce codes and reason code as per the table listed in part 2.
Receiving message:
User have to set the callback url from its IPX account. on which the received message will be forwarded by the IPX. The variables those will be received are listed in part 2 of this blog.
Other languages and text messaging
Java code exampleIn the Java implementation the IPX java API (api-smsapi50.jar) and Axis 1.1 have been used together with J2SE 1.4.2.try {// If using proxy// System.setProperty("http.proxyHost", "proxyhost");// System.setProperty("http.proxyPort", "8080");// Change endpoint URL if other than service location specified inWSDLURL aPortUrl = new URL("http://host:port/path");SmsApiServiceLocator aLocator = new SmsApiServiceLocator();SmsApiPort anSmApi = aLocator.getSmsApi51(aPortUrl);((Stub) anSmApi).setTimeout(10*60*1000); // Set read timeout to 10minutesSendRequest aRequest = new SendRequest();aRequest.setCorrelationId("corrID");aRequest.setOriginatingAddress("72160");aRequest.setOriginatorTON(0);aRequest.setDestinationAddress("msisdn");aRequest.setUserData("Test message");aRequest.setUserDataHeader("#NULL#");aRequest.setDCS(-1);aRequest.setPID(-1);aRequest.setRelativeValidityTime(-1);aRequest.setDeliveryTime("#NULL#");aRequest.setStatusReportFlags(0);aRequest.setAccountName("#NULL#");aRequest.setTariffClass("EUR0");aRequest.setVAT(-1);aRequest.setReferenceId("#NULL#");aRequest.setContentCategory("#NULL#");aRequest.setContentMetaData("#NULL#");aRequest.setUsername("username");aRequest.setPassword("password");SendResponse aResult = anSmApi.send(aRequest);// System.out.println("Response: " + aResponse);System.out.println("Result: correlationId: "+ aResult.getCorrelationId());System.out.println("Result: messageId: "+ aResult.getMessageId());System.out.println("Result: responseCode: "+ aResult.getResponseCode());System.out.println("Result: responseMessage: "+ aResult.getResponseMessage());System.out.println("Result: temporaryError: "+ aResult.isTemporaryError());} catch (Exception e) {e.printStackTrace();}PHP code exampleIn the PHP implementation a toolkit called NuSOAP version 0.6.7 (download forfree at http://dietrich.ganx4.com/nusoap/) has been used together with PHP 4.3.5.require_once(’../nusoap.php’);# Load wsdl and reuse the client instance or set all parameters when invokingservice$soapclient = new soapclient(’http://host:port/path?wsdl’,true);# If using proxy# $soapclient = new soapclient(’http://host:port/path?wsdl’,true,# ’proxyhost’, 8080);# print_r($soapclient->getOperationData(’send’));# Change endpoint URL if other than service location specified in WSDL$soapclient->operations[’send’][’endpoint’] = ’http://host:port/path’;# print_r($soapclient->getOperationData(’send’));$soapclient->response_timeout = 600; // Set read timeout to 10 minutes$params = array(’correlationId’ => ’corrID’,’originatingAddress’ => ’72160’,’originatorTON’ => ’0’,’destinationAddress’ => ’msisdn’,’userData’ => ’Test message’,’userDataHeader’ => ’#NULL#’,’DCS’ => ’-1’,’PID’ => ’-1’,’relativeValidityTime’ => ’-1’,’deliveryTime’ => ’#NULL#’,’statusReportFlags’ => ’0’,’accountName’ => ’#NULL#’,’tariffClass’ => ’EUR0’,’VAT’ => ’-1’,’referenceId’ => ’#NULL#’,’contentCategory’ => ’#NULL#’,’contentMetaData’ => ’#NULL#’,’username’ => ’username’,’password’ => ’password’);# print "Request:";# print_r($params);$outparams = $soapclient->call(’send’,array(’request’ => $params));# print "Result:";# print_r($outparams);if ($soapclient->getError() != null) {print "Error: ";print $soapclient->getError()."\n";}else {print "Result: correlationId: ".$outparams[’correlationId’]."\n";print "Result: messageId: ".$outparams[’messageId’]."\n";print "Result: responseCode: ".$outparams[’responseCode’]."\n";print "Result: responseCode: ".$outparams[’reasonCode’]."\n";print "Result: responseMessage: ".$outparams[’responseMessage’]."\n";}?>VBScript code exampleIn the Microsoft implementation using VBScript, the SOAP Toolkit 3.0 has beenused together with Windows Script Host Version 5.6 (cscript.exe). The SOAPToolkit can be downloaded from http://www.microsoft.com/downloads/.Option ExplicitOn Error Resume NextDim SoapClient ’ As SoapClient30Dim SendReturn ’ As IXMLDOMSelectionDim Dom ’ As New DOMDocument3Dim Request ’ As IXMLDOMNodeListSet Soapclient = CreateObject("MSSOAP.SoapClient30")’ In case of Soap Toolkit 2.0’ Set Soapclient = CreateObject("MSSOAP.SoapClient")Call SoapClient.mssoapinit("hhttp://host:port/path?wsdl")’ If using proxy’ SoapClient.ConnectorProperty("ProxyServer") = "proxyhost:8080"’ See SOAP Toolkit API for info about this propertySoapClient.ClientProperty("ServerHTTPRequest") = True’ Change endpoint URL if other than service location specified in WSDLSoapClient.ConnectorProperty("EndPointURL") = "hhttp://host:port/path"’ Set read timeout to 10 minutesSoapClient.ConnectorProperty("Timeout") = 60*10*1000Set Dom = CreateObject("Msxml2.DOMDocument")’ Use this as container when creating the requestSet Dom.documentElement = Dom.createElement("tempDoc")’ Add parametersCall AppendChildElement(Dom, "correlationId", "corrID")Call AppendChildElement(Dom, "originatingAddress", "72160")Call AppendChildElement(Dom, "originatorTON", "0")Call AppendChildElement(Dom, "destinationAddress", "msisdn")Call AppendChildElement(Dom, "userData", "Test message")Call AppendChildElement(Dom, "userDataHeader", "#NULL#")Call AppendChildElement(Dom, "DCS", "-1")Call AppendChildElement(Dom, "PID", "-1")Call AppendChildElement(Dom, "relativeValidityTime", "-1")Call AppendChildElement(Dom, "deliveryTime", "#NULL#")Call AppendChildElement(Dom, "statusReportFlags", "0")Call AppendChildElement(Dom, "accountName", "#NULL#")Call AppendChildElement(Dom, "tariffClass", "EUR0")Call AppendChildElement(Dom, "VAT", "-1")Call AppendChildElement(Dom, "referenceId", "#NULL#")Call AppendChildElement(Dom, "contentCategory", "#NULL#")Call AppendChildElement(Dom, "contentMetaData", "#NULL#")Call AppendChildElement(Dom, "username", "username")Call AppendChildElement(Dom, "password", "password")Set Request = Dom.documentElement.childNodes’ Invoke web serviceSet SendReturn = SoapClient.send(Request)If err <> 0 Thenwscript.echo "Error: "wscript.echo err.descriptionwscript.echo "faultcode=" + Soapclient.faultcodewscript.echo "faultstring=" + Soapclient.faultstringwscript.echo "faultactor=" + Soapclient.faultactorwscript.echo "detail=" + Soapclient.detailElse’ Call PrintResponseParams(SendReturn)wscript.echo "Result: correlationId " & GetResponseParam(SendReturn,"correlationId")wscript.echo "Result: messageId: " & GetResponseParam(SendReturn, "messageId")wscript.echo "Result: responseCode: " & GetResponseParam(SendReturn,"responseCode")wscript.echo "Result: reasonCode: " & GetResponseParam(SendReturn,"reasonCode")wscript.echo "Result: responseMessage: " & GetResponseParam(SendReturn,"responseMessage")End If’ Helper functions’ Parse a DOM for a specific element and return its valueFunction GetResponseParam(oDom, strKey)Dim jFor j = 0 to oDom.lengthIf oDom.item(j).nodeName = strKey ThenGetResponseParam = oDom.item(j).textExit FunctionEnd IfNextEnd Function’ Parse a DOM and print all node names and their valuesSub PrintResponseParams(oDom)Dim jFor j = 0 to oDom.lengthwscript.echo oDom.item(j).nodeName & ": " & oDom.item(j).textNextEnd Sub’ Append a child element to a DOM, with specified name and value.Sub AppendChildElement(byRef oDom, strElementName, strElementValue)Dim ElmSet Elm = oDom.createNode(1, strElementName,"http://www.ipx.com/api/services/smsapi51/types")Elm.text = strElementValueoDom.documentElement.appendChild ElmEnd SubPERL code exampleIn the PERL implementation a toolkit called SOAP::Lite version 0.55 (downloadfor free at http://www.soaplite.com/) has been used together with ActivePerl-5.8.3.809.#!perl -w# If using proxy# $ENV{HTTP_proxy} = "http://proxyhost:8080/";# use SOAP::Lite +trace => ’debug’;use SOAP::Lite;# Target URL. Set read timeout to 10 minutesmy $client = SOAP::Lite ->proxy(’http://host:port/path’, timeout => 600);# Force the SDK not to guess types of the SOAP elements$client->autotype(0);my @parameters =(SOAP::Data->name(correlationId => ’correlationId’)->value(’corrID’),SOAP::Data->name(originatingAddress => ’originatingAddress’)->value(’72160’),SOAP::Data->name(originatorTON => ’originatorTON’)->value(’0’),SOAP::Data->name(destinationAddress => ’destinationAddress’)->value(’msisdn’),# Note: the toolkit does not automatically escape XML unsafe characters,# use encode_dataSOAP::Data->name(userData => ’userData’)->value(SOAP::Utils::encode_data(’Test message’)),SOAP::Data->name(userDataHeader => ’userDataHeader’)->value(’#NULL#’),SOAP::Data->name(DCS => ’DCS’)->value(’-1’),SOAP::Data->name(PID => ’PID’)->value(’-1’),SOAP::Data->name(relativeValidityTime => ’relativeValidityTime’)->value(’-1’),SOAP::Data->name(deliveryTime => ’deliveryTime’)->value(’#NULL#’),SOAP::Data->name(statusReportFlags => ’statusReportFlags’)->value(’0’),SOAP::Data->name(accountName => ’accountName’)->value(’#NULL#’),SOAP::Data->name(tariffClass => ’tariffClass’)->value(’EUR0’),SOAP::Data->name(VAT => ’VAT’)->value(’-1’),SOAP::Data->name(referenceId => ’referenceId’)->value(’#NULL#’),SOAP::Data->name(contentCategory => ’contentCategory’)->value(’#NULL#’),SOAP::Data->name(contentMetaData => ’contentMetaData’)->value(’#NULL#’),SOAP::Data->name(username => ’username’)->value(’username’),SOAP::Data->name(password => ’password’)->value(’password’),);# send request and retrieve information (RPC like document style service)my $body = SOAP::Data->name(’SendRequest’) ->attr({xmlns => ’http://www.ipx.com/api/services/smsapi51/types’});$result = $client->call($body => @parameters);# print all resultsif ($result->fault){print "Error: ", $result->faultstring, "\n";}else{print "Result: correlationId: ", $result->valueof(’//SendResponse/correlationId’), "\n";print "Result: messageId: ", $result->valueof(’//SendResponse/messageId’),"\n";print "Result: responseCode: ", $result->valueof(’//SendResponse/responseCode’), "\n";print "Result: responseCode: ", $result->valueof(’//SendResponse/reasonCode’),"\n";print "Result: responseMessage: ", $result->valueof(’//SendResponse/responseMessage’), "\n";}.NET code exampleThis .NET example is written in C# using Microsoft .NET Framework 1.1. Add thetarget web service WSDL as web reference and .NET will generate the necessarystub code for the client side.try{SmsApiService aService = new SmsApiService();SendRequest aRequest = new SendRequest();aRequest.correlationId = "corrId";aRequest.originatingAddress = "72160";aRequest.originatorTON = 0;aRequest.destinationAddress = "msisdn";aRequest.userData = "Test message";aRequest.userDataHeader = "#NULL#";aRequest.DCS = -1;aRequest.PID = -1;aRequest.relativeValidityTime = -1;aRequest.deliveryTime = "#NULL#";aRequest.statusReportFlags = -1;aRequest.accountName = "#NULL#";aRequest.tariffClass = "EUR0";aRequest.VAT = -1;aRequest.referenceId = "#NULL#";aRequest.contentCategory = "#NULL#";aRequest.contentMetaData = "#NULL#";aRequest.username = "username";aRequest.password = "password";// If using proxy// aService.Proxy = new System.Net.WebProxy("proxyhost", 8080);// Change endpoint URL if other than service location specified inWSDLaService.Url = "http://host:port/path";aService.Timeout = 60*10*1000; // Set read timeout to 10 minutesSendResponse aResult = aService.send(aRequest);Console.Out.WriteLine("Result: correlationId: " +aResult.correlationId);Console.Out.WriteLine("Result: messageId: " + aResult.messageId);Console.Out.WriteLine("Result: responseCode: " +aResult.responseCode);Console.Out.WriteLine("Result: reasonCode: " + aResult.reasonCode);Console.Out.WriteLine("Result: responseMessage: " +aResult.responseMessage);}catch (Exception e){Console.Out.WriteLine("Exception: " + e);}
Monday, December 29, 2008
Send SMS Service with esendex (for United Kingdom)
For messaging in UK, I have used the service by Esendex, which too uses the SOAP protocol. I am hereby listing the code to send the text message with Esendex in UK.Here is the list of the variables to be sent and links for testingVersion:1.0 StartHTML:0000000168 EndHTML:0000005362 StartFragment:0000000520 EndFragment:0000005345Authentication
Username*
Your Esendex username, for example joe.bloggs@test.com
Password*
Your Esendex password, for example joe1234
Account*
Your Esendex account reference, for example 441234567890
Message details
Originator
The alias the message should appear to come from. Can be another phone number or up to 11 alpha numeric characters. For Evaluation accounts, this field must be set to the same value as your Esendex account reference.
Recipient*
The mobile number to send the message to. To send to multiple recipients, separate their numbers with commas.
Body*
The content of the message. 160 max characters for Text, 140 octets max for Binary and SmartMessaging, 70 octet pairs for Unicode messages.
Type
The type of message (Text, Binary, SmartMessage, Unicode). The default is Text.
ValidityPeriod
The validity period of the message in hours. The default is zero, meaning the message never expires.
Other information
SuccessPage
The URL to redirect to if the message is submitted successfully. If you omit this field, an XML response is returned.
FailurePage
The URL to redirect to if an error occurs when submitting the message. If you omit this field, an XML response containing the message ID is returned.
Test
Specify a value for the Test field to have this page redisplayed with the values submitted by your form. This is for test purposes only, and no SMS message will be sent.
PlainText
Specify a value for this field to return plain text results instead of a formatted HTML page.
For a successful request, results are in the format:
Result=OK
MessageIDs=value
where MessageIDs value is the ID that Esendex assigned to the message. You can use this value to query the status of the message using the Query Status service. If a message is sent to multiple recipients, multiple IDs are returned; each seperated by a comma.
For an unsuccessful request, results are in the format:
Result=Error
Message=value
where Message value is a URL encoded description of the error.
