a) Tyr Webservice
The Tyr webservice or tyrservice is a XML-RPC based service, providing webSignatureOffice functionality for integration in third party applications (http://en.wikipedia.org/wiki/XML-RPC).
The Tyr webservice can be used by a variety of XML-RPC libraries which are available for all major programming languages (https://www.tutorialspoint.com/xml-rpc/xml_rpc_examples).
A help documentation of the webSignatureOffice services / methods can be displayed by a HTTP GET request on our tyrservice URL https://websignatureoffice.stepover.de:8450/tyrservice (stage server, can be down at times).
Preview + Testing
The Tyr webservice can be tested with a test account on webSignatureOffice.com, a development server can be provided on request.
Authentication and request signing
In order to use this service two keys have to be requested from StepOver:
- an application key (tyrservice ID)
- a request signing key (shared secret)
All service calls (other than login) must contain a sessionId string as follows:
session_id:timestamp:unique_id:application_key
- session_id: the string returned after successful login
- timestamp: unix timestamp
- unique_id: a nonce, best is to use a UUID generator
- application_key: the application key supplied by StepOver
Example: 7bd273e259b20052666ce9194468c439:1563264207:b9554fc6-43a2-467d-b4e9-7c694306f639:af5539de0753868ef1872410b2eb7366
How to implement the Tyr webservice in third party applications
Each request is signed as follows:
The request signature hash is built by concatenating the request xml and the shared secret, then SHA256 hashing the result.
The request signature hash (hex representation) is sent as a HTTP header "X-SOSIGNATURE".
*Please note*: The request signature key should be securely stored, in an app it should be obfuscated.
Example Client in Java (Apache XMLRpc)
public class TyrServiceClient { XmlRpcClient client = new XmlRpcClient(); XmlRpcClientConfigImpl config = new XmlRpcClientConfigImpl(); String sharedSecret; String customerKey; public TyrServiceClient(String host, String sharedSecret, String customerKey) throws MalformedURLException, NoSuchAlgorithmException, KeyManagementException { this.customerKey = customerKey; this.sharedSecret = sharedSecret; config.setServerURL(new URL(host + "/tyrservice")); client.setConfig(config); client.setTransportFactory(new LoggingTransportFactory(client)); config.setEnabledForExtensions(true); TrustManager[] trustAllCerts = new TrustManager[]{new X509TrustManager() { public X509Certificate[] getAcceptedIssuers() { return null; } public void checkClientTrusted(X509Certificate[] certs, String authType) { // Trust always } public void checkServerTrusted(X509Certificate[] certs, String authType) { // Trust always } }}; // Install the all-trusting trust manager SSLContext sc = SSLContext.getInstance("SSL"); // Create empty HostnameVerifier HostnameVerifier hv = new HostnameVerifier() { public boolean verify(String arg0, SSLSession arg1) { return true; } }; sc.init(null, trustAllCerts, new java.security.SecureRandom()); HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory()); HttpsURLConnection.setDefaultHostnameVerifier(hv); } class LoggingTransportFactory extends XmlRpcSun15HttpTransportFactory { XmlRpcClient client; @Override public XmlRpcTransport getTransport() { return new LoggingTransport(client); } public LoggingTransportFactory(XmlRpcClient pClient) { super(pClient); client = pClient; } } class LoggingTransport extends XmlRpcSun15HttpTransport { @Override protected InputStream getInputStream() throws XmlRpcException { BufferedReader reader = null; StringBuilder respBuf = new StringBuilder(); try { InputStream inputStream = super.getInputStream(); reader = new BufferedReader(new InputStreamReader(inputStream)); String line = null; while ((line = reader.readLine()) != null) { respBuf.append(line); } } catch (IOException e) { e.printStackTrace(); } return new ByteArrayInputStream(respBuf.toString().getBytes()); } @Override protected void writeRequest(ReqWriter reqWriter) throws XmlRpcException { try { ByteArrayOutputStream os = new ByteArrayOutputStream(); reqWriter.write(os); String requestHeader = ""; requestHeader = new String(Hex.encodeHex(DigestUtils.sha256(os.toString() + sharedSecret))); this.setRequestHeader("X-SOSIGNATURE", requestHeader); super.writeRequest(reqWriter); } catch (Exception e) { e.printStackTrace(); } } public LoggingTransport(XmlRpcClient pFactory) { super(pFactory); } } public Object execute(String method, Object[] param) throws XmlRpcException { Object execute = client.execute("tyrservice." + method, param); return execute; }
Example client with imports:
Requests
1.) First you have to create a session ID for the sessionIdString.
Method: tyrservice.login | Return: sessionId
XmlRpcClient client = new XmlRpcClient(); Object[] loginParams = new Object[]{ "mylogin", "mypassword" }; //parameters are username/login and password sessionId = (String) client.execute( "login", loginParams ); String sessionIdString = sessionId + ":" + System.currentTimeMillis() / 1000 + ":" + UUID.randomUUID() + ":" + customerKey; //the sessionIdString has to be added for each method call, e.g. for method processXml( string sessionIdString, base64 xml )
2.) Now you have the option for uploading XML-Files which contains the PDF.
For this step, you need to encode your PDF-file into base64. The base64 code will be placed then inside the tag <PDF> at the end of the XML-File.
The structure of the XML will be shown later at topic "Input-XML Extensions" or here: XML Sample
Please continue with the implementation steps.
Method: tyrservice.processXML | Return: documentID
Object[] params = new Object[]{ sessionIdString, xmlBytes }; //parameters are sessionIdString and XML bytes Integer documentId = (Integer)client.execute( "processXml", params );
-> The file is uploaded on the webSignatureOffice server as a PDF now.
3.) To view the uploaded PDF, you need to create a document link. For this you have to encode the document relevant data for a URL-safe link.
The method getUrlSignature generates a signature string which is part of the document URL.
Method: tyrservice.getUrlSignature | Return: URL signature for a action handled by the process servlet
/*Collecting the document link relevant data*/ String userId = 123; //you will get your userId with the method tyrservice.getUserMetaByLogin; see below String time = Long.toString( System.currentTimeMillis() + ( 1000 * 60 * 2880 ) ); //the validity of the URL, for example 48 hours String documentId = 2222; //the response from the processXML call Map<String, String> values = new HashMap<>(); values.put( "u", userId ); values.put( "t", time ); values.put( "d", documentId ); Object[] params = new Object[]{ sessionIdString, "tldv", values }; //action is TimeLimitedDocumentViewer String signature = (String) client.execute( "tyrservice.getUrlSignature", params ); String url = host + "/process?x=tldv&u=" + userId + "&t=" + time + "&d=" + documentId + "&xx=" + signature;
Method: tyrservice.getUserMetaByLogin | Return: user metadata (necessary for document links)
Object[] params = new Object[]{ sessionIdString, "mylogin" }; // parameters are sessionIdString and username/login HashMap<String,Object> userMetadata = (HashMap<String, Object>) client.execute( "tyrservice.getUserMetaByLogin", params ); String userId = userMetadata.get("user_id").toString();
Input-XML Extensions
For customers which used or still use our eSignatureOffice in the past: webSignatureOffice uses the same standard input-XML as eSignatureOffice does, but with a few extensions.
You can find the definition of the input XML here: /wiki/spaces/PESO/pages/79200348
The following extended tags can be used to optimize the use of the /wiki/spaces/PESO/pages/79200348 with webSignatureOffice:
In the signature field definition a user name can be set, if no user name is defined, the logged in user is taken as signer
<Signatures> <Signature> <Placeholder>Signature 1</Placeholder> <Width>4</Width> <Height>3</Height> <UserName>myLogin</UserName> ...
<Signatures> <Signature> <Placeholder>Signature 1</Placeholder> <Width>4</Width> <Height>3</Height> <UserName>username</UserName> <SignatureType>2</SignatureType> ...
You can also rename the uploaded PDF with the PDFName tag.
With this tag you can change the standard upload name into something more suitable.
<Signatures> <Signature> <Placeholder>Signature 1</Placeholder> <Width>4</Width> <Height>3</Height> <UserName>username</UserName> <SignatureType>2</SignatureType> ... </Signature> </Signatures> <PDFName>AlternativePDFName</PDFName>
Tyr webservice help documentation
This service implements a simple XML-RPC interface to the FRIGG Server (web frontend), that can be used by a variety of clients.
XML-RPC spec: http://xmlrpc.scripting.com/spec.html
HTML server implementation: http://ws.apache.org/xmlrpc
To activate gzip compression the http header Content-Encoding has to be set to gzip, this reduces the required bandwidth.
*********************
Error codes:
********************* 100 = service signature not valid, session expired 101 = braga server exception, severe 102 = login data incorrect 103 = max login tries reached, account locked, try again in 5 minutes 104 = document locked, try again later 105 = document upload failed 106 = permission denied 107 = user unknown 108 = no signature request 109 = duplicate pdf field name 110 = unexpected error 111 = document not found
112 = DB error
113 = invalid adhoc code
114 = operation time out
115 = audit trail server exception *********************
TyrService Methods:
a list of all tyrservice methods is available under:
https://websignatureoffice.stepover.de:8450/tyrservice (Stage server, can be down at times)
request examples:
tyrservice.login
<?xml version="1.0" encoding="UTF-8"?>
<methodCall xmlns:ex="http://ws.apache.org/xmlrpc/namespaces/extensions">
<methodName>tyrservice.login</methodName>
<params>
<param>
<value>foo</value>
</param>
<param>
<value>bar</value>
</param>
</params>
</methodCall>
tyrservice.getUrlSignature
<?xml version="1.0" encoding="UTF-8"?>
<methodCall xmlns:ex="http://ws.apache.org/xmlrpc/namespaces/extensions">
<methodName>tyrservice.getUrlSignature</methodName>
<params>
<param>
<value>eb9cd247e5850e785093aee86b9b35b9:1581602515:4942e688-d29f-49ed-aafc-8a6d49ec1eb5:abc439de0723860ee8871234b2eb73a8</value>
</param>
<param>
<value>tldv</value>
</param>
<param>
<value>
<struct>
<member>
<name>t</name>
<value>1581775315944</value>
</member>
<member>
<name>d</name>
<value>22186</value>
</member>
<member>
<name>u</name>
<value>2451</value>
</member>
</struct>
</value>
</param>
</params>
</methodCall>
response examples:
tyrservice.login
<?xml version="1.0" encoding="UTF-8"?>
<methodResponse xmlns:ex="http://ws.apache.org/xmlrpc/namespaces/extensions">
<params>
<param>
<value>eb9cd247e5850e785093aee86b9b35b9</value>
</param>
</params>
</methodResponse>
tyrservice.getUrlSignature
<?xml version="1.0" encoding="UTF-8"?>
<methodResponse xmlns:ex="http://ws.apache.org/xmlrpc/namespaces/extensions">
<params>
<param>
<value>DJ5S_aMp2NQPy6Dgwxg8bGeKPRfDEPKJajJOcQ</value>
</param>
</params>
</methodResponse>