s.shashank.v.v… | Posts: 29

How to add Signed Document to the Salesforce Record while working with APEX SDK

0 votes

Hi Team,

I am new to OneSpan and start working on the Apex SDK. I have gone through the SDK documentation but I am not able to find out how we can attach the signed document to the record or package can be assigned to the Parent record.

It will be really great if you can provide some documentation to achieve this functionality.

Regards,

Shashank Verma


Duo_Liang | Posts: 3776

Reply to: How to add Signed Document to the Salesforce Record while working with APEX SDK

0 votes

Hi Shashank Verma,

 

If you are looking for download capability, please refer to the Checking Transaction Status & Downloading Documents guide.

If you are looking for the callback mechanism to inform your application when the transaction has been completed, please refer to my blog series OAuth Event Notification for Salesforce Part 1 Part 2 and Part 3.

 

Duo


s.shashank.v.v… | Posts: 29

Reply to:

0 votes

Hi Liang,

I am going through your OAuth Event Notification for Salesforce blogs and for the Part 2, I am getting error while doing Update OneSpan Sign Callback Service

I am doing the exact steps which you have mentioned but while doing HTTP request for Post I am getting error i.e. Service not found at: /api/callback/connectors/salesforceOauth2.

Can you please let me know what is the reason I am getting this error.

Regards,

Shashank Verma


Duo_Liang | Posts: 3776

Reply to:

0 votes

Hi Shashank Verma,

 

I am not able to reproduce the "Service not found at" error.

- Can you provide a screenshot of it? Is the error message returned in JSON or HTML format?

- Can you make a GET call and will the error consistent?

- Can you try invoking the API through Swagger?

 

Duo


s.shashank.v.v… | Posts: 29

Reply to: How to add Signed Document to the Salesforce Record while working with APEX SDK

0 votes

Hi Liang,

We tried the exact steps that mentioned inside the blog Part 2. Below are the POST request details
 1. We are using POST Url : sandbox.esignlive.com/api/callback/connectors/salesforceOauth2 
 2. POST Header : 
    Content-Type: application/json
    Accept: application/json
    Authorization: Basic {My OneSpan API Key}
 3. POST Body : 
 {
  "url": "https://test123.my.salesforce.com/services/apexrest/oss/callback",
  "events": ["DOCUMENT_SIGNED","EMAIL_BOUNCE","KBA_FAILURE","PACKAGE_ACTIVATE","PACKAGE_ARCHIVE","PACKAGE_ATTACHMENT","PACKAGE_COMPLETE","PACKAGE_CREATE","PACKAGE_DEACTIVATE","PACKAGE_DECLINE","PACKAGE_DELETE","PACKAGE_EXPIRE","PACKAGE_OPT_OUT","PACKAGE_READY_FOR_COMPLETE","PACKAGE_RESTORE","PACKAGE_TRASH","ROLE_REASSIGN","SIGNER_COMPLETE","SIGNER_LOCKED","TEMPLATE_CREATE"],
  "key": "{Key Encrypted in Base64}"
}

While testing from PostMan we are getting following error 

"Error: connect ETIMEDOUT 54.85.59.26:80"

Can you please let us know if the we are using the correct endpoint and let us know if the above steps are right.

Regards,

Shashank Verma


s.shashank.v.v… | Posts: 29

Reply to: How to add Signed Document to the Salesforce Record while working with APEX SDK

0 votes

Hi Liang,

We have added the HTTPS schema but now I am getting the below error in response body:

<html> 
    <head>
        <title>400 Bad Request</title>
    </head> 
    <body> 
        <center><h1>400 Bad Request</h1></center> 
        <hr><center>nginx</center> 
    </body> 
</html>

Can you please let me know if we are doing something wrong.

Regards,

Shashank Verma


Duo_Liang | Posts: 3776

Reply to:

0 votes

Hi Shashank Verma,

 

The easiest way to work around this is to use the Swagger instead of Postman.

In order to further investigate your issue, are you connecting through a proxy server? Can you open the Postman console (view > open postman console) and make a screenshot of request body in raw format (don't forget to hide the API key)?

 

Duo


s.shashank.v.v… | Posts: 29

Reply to: How to add Signed Document to the Salesforce Record while working with APEX SDK

0 votes

Hi Liang,

Below is the PostMan console log

POST https://sandbox.esignlive.com/api/callback/connectors/salesforceOauth2
400
1094 ms
POST /api/callback/connectors/salesforceOauth2 HTTP/1.1
Content-Type: application/json
Accept: application/json
Authorization: Basic { }
Postman-Token: { }
 
{
"url": "https://test123.lightning.force.com/services/apexrest/oss/callback",
"events": ["DOCUMENT_SIGNED","PACKAGE_READY_FOR_COMPLETE","PACKAGE_RESTORE","PACKAGE_TRASH","ROLE_REASSIGN","SIGNER_COMPLETE","SIGNER_LOCKED","TEMPLATE_CREATE"],
"key": " "
}
 
HTTP/1.1 400 Bad Request
Server: nginx
Date: Wed, 19 May 2021 06:50:36 GMT
Content-Type: text/html
Content-Length: 150
Connection: close
Allow: GET, POST, HEAD, PUT, PATCH, DELETE
 
<html>
<head><title>400 Bad Request</title></head>
<body>
<center><h1>400 Bad Request</h1></center>
<hr><center>nginx</center>
</body>
</html>

and also in the Swagger we are getting below error

{ "messageKey": "error.unauthorised.noSession", "message": "Failed to retrieve Session", "code": 401, "name": "Unauthorized" }

 

Regards,

Shashank Verma


Duo_Liang | Posts: 3776

Reply to:

0 votes

I see. 

For Swagger, click the "Authorize" button on top, then insert "Basic your_api_key" as ApiKeyAuth.

For your Postman settings, it seems your outbound request lacks two headers "Content-Length" and "Host". These two values should be auto-calculated by Postman (as per their documentation), make sure you didn't disable them.

 

Duo


s.shashank.v.v… | Posts: 29

Reply to:

0 votes

Hi Liang,

Thank you for your quick response !!!

I have tried the above step and got the below response for POST

POST https://sandbox.esignlive.com/api/callback/connectors/salesforceOauth2

POST /api/callback/connectors/salesforceOauth2 HTTP/1.1
Content-Type: application/json
Accept: application/json
Authorization: Basic { }
Postman-Token: { }
Host: sandbox.esignlive.com
Content-Length: 799
 
{
"url": "https://test123.lightning.force.com/services/apexrest/oss/callback",
"events": ["DOCUMENT_SIGNED","EMAIL_BOUNCE","KBA_FAILURE","PACKAGE_ACTIVATE","PACKAGE_ARCHIVE","PACKAGE_ATTACHMENT","PACKAGE_COMPLETE","PACKAGE_CREATE","PACKAGE_DEACTIVATE","PACKAGE_DECLINE","PACKAGE_DELETE","PACKAGE_EXPIRE","PACKAGE_OPT_OUT","PACKAGE_READY_FOR_COMPLETE","PACKAGE_RESTORE","PACKAGE_TRASH","ROLE_REASSIGN","SIGNER_COMPLETE","SIGNER_LOCKED","TEMPLATE_CREATE"],
"key":"{ }"
}
 
HTTP/1.1 200 OK
Server: nginx
Date: Wed, 19 May 2021 14:11:41 GMT
Content-Type: application/json
Content-Length: 783
Connection: keep-alive
Expires: Wed, 19 May 2021 14:11:41 GMT
Cache-Control: no-cache, no-transform, max-age=0
Strict-Transport-Security: max-age=31536000; includeSubdomains;
Allow: GET, POST, HEAD, PUT, PATCH, DELETE
P3P: CP="IDC DSP COR ADM DEVi TAIi PSA PSD IVAi IVDi CONi HIS OUR IND CNT"
 
{"url":"https://test123.lightning.force.com/services/apexrest/oss/callback","events":["DOCUMENT_SIGNED","EMAIL_BOUNCE","KBA_FAILURE","PACKAGE_ACTIVATE","PACKAGE_ARCHIVE","PACKAGE_ATTACHMENT","PACKAGE_COMPLETE","PACKAGE_CREATE","PACKAGE_DEACTIVATE","PACKAGE_DECLINE","PACKAGE_DELETE","PACKAGE_EXPIRE","PACKAGE_OPT_OUT","PACKAGE_READY_FOR_COMPLETE","PACKAGE_RESTORE","PACKAGE_TRASH","ROLE_REASSIGN","SIGNER_COMPLETE","SIGNER_LOCKED","TEMPLATE_CREATE"],"key":"{ }"}

Also below is the GET response

GET https://sandbox.esignlive.com/api/callback/connectors/salesforceOauth2
GET /api/callback/connectors/salesforceOauth2 HTTP/1.1
Content-Type: application/json
Accept: application/json
Authorization: Basic { }
Postman-Token: { }
Host: sandbox.esignlive.com
 
HTTP/1.1 200 OK
Server: nginx
Date: Wed, 19 May 2021 14:14:01 GMT
Content-Type: application/json
Content-Length: 783
Connection: keep-alive
Expires: Wed, 19 May 2021 14:14:01 GMT
Cache-Control: no-cache, no-transform, max-age=0
Strict-Transport-Security: max-age=31536000; includeSubdomains;
Allow: GET, POST, HEAD, PUT, PATCH, DELETE
P3P: CP="IDC DSP COR ADM DEVi TAIi PSA PSD IVAi IVDi CONi HIS OUR IND CNT"
 
{"url":"https://test123.lightning.force.com/services/apexrest/oss/callback","key":"{ }","events":["DOCUMENT_SIGNED","EMAIL_BOUNCE","KBA_FAILURE","PACKAGE_ACTIVATE","PACKAGE_ARCHIVE","PACKAGE_ATTACHMENT","PACKAGE_COMPLETE","PACKAGE_CREATE","PACKAGE_DEACTIVATE","PACKAGE_DECLINE","PACKAGE_DELETE","PACKAGE_EXPIRE","PACKAGE_OPT_OUT","PACKAGE_READY_FOR_COMPLETE","PACKAGE_RESTORE","PACKAGE_TRASH","ROLE_REASSIGN","SIGNER_COMPLETE","SIGNER_LOCKED","TEMPLATE_CREATE"]}

For the next step we have implemented the Part 3 blog mentioned steps. But as mentioned in the blog we didn't get any debug logs and as well files not created inside the folder.

Can you please let me know if we are doing something wrong.

 

 Regards,

Shashank Verma


Duo_Liang | Posts: 3776

Reply to:

0 votes

Hi Shashank Verma,

 

Try to test your exposed service separately:

(1)manually generate an access token for your connected app

(2)in Postman, make below call and stimulate the callback notification:

POST https://test123.lightning.force.com/services/apexrest/oss/callback

with header: Authorization: Bearer generated_access_token

with payload: {"@class":"com.silanis.esl.packages.event.ESLProcessEvent","name":"PACKAGE_COMPLETE","sessionUser":"18EZDL44xgsX","packageId":"jYLxykyNOHoZ6c7YY2p7BfANpeg=","message":null,"documentId":null,"createdDate":"2018-07-18T18:19:19.356Z"}

You can replace the packageId with a real one.

(3)check if above call succeeds, and if there's any income request in SFDC console.

If it turns out that the connected app is configured correctly and the code works, can you share your actual payload to [email protected] and let me have a further investigate?

 

Duo

 

 


s.shashank.v.v… | Posts: 29

Reply to:

0 votes

Hi Liang,

 

We have tried the above step and getting the below error:

 

GET https://test123.my.salesforce.com/services/apexrest/oss/callback

GET /services/apexrest/oss/callback HTTP/1.1

Accept: application/json

Postman-Token: { }

Cookie: BrowserId= {Browser Id}

Referer: https://test123.lightning.force.com/services/apexrest/oss/callback

Host: test123.my.salesforce.com

 

{"@class":"com.silanis.esl.packages.event.ESLProcessEvent","name":"PACKAGE_COMPLETE","sessionUser":"18EZDL44xgsX","packageId":"{ }","message":null,"documentId":null,"createdDate":"2018-07-18T18:19:19.356Z"}

 

HTTP/1.1 401 Unauthorized

Date: Thu, 20 May 2021 06:35:38 GMT

Strict-Transport-Security: max-age=31536002; includeSubDomains

X-Content-Type-Options: nosniff

X-XSS-Protection: 1; mode=block

X-Robots-Tag: none

Cache-Control: no-cache,must-revalidate,max-age=0,no-store,private

WWW-Authenticate: Token

Content-Type: application/json;charset=UTF-8

Transfer-Encoding: chunked

 

[{"message":"Session expired or invalid","errorCode":"INVALID_SESSION_ID"}]

 

Can you please let us know what will be the issue and also we are not sure about the sessionUser you have mentioned in the payload.

 

Regards,

Shashank Verma


Duo_Liang | Posts: 3776

Reply to:

0 votes

Hi Shashank Verma,

 

Few things I've noticed:
(1)When an event of interest get triggered, OneSpan Sign sends a POST call to your callback endpoint. Therefore you also need to expose a POST function. (It seems that you were testing with a GET function)

(2)Have you manually generated a SFDC access token via below call? - It seems there's no Bearer header in your testing call.

5-20-1

 

Duo


s.shashank.v.v… | Posts: 29

Reply to:

0 votes

Hi Liang,

 

I have did the same steps you have mentioned and sends the POST call but with the POST request I also got the GET response. Below, are the POST call details

POST / HTTP/1.1

Content-Type: application/json

Accept: application/json

Authorization: Bearer { }

Postman-Token: { }

Host: test123.lightning.force.com

Content-Length: 231

Cookie: BrowserId={ }

 

HTTP/1.1 302

Date: Thu, 20 May 2021 15:37:10 GMT

Strict-Transport-Security: max-age=31536001; includeSubDomains

X-Content-Type-Options: nosniff

X-XSS-Protection: 1; mode=block

Content-Security-Policy: upgrade-insecure-requests

X-Robots-Tag: none

Cache-Control: no-cache,must-revalidate,max-age=0,no-store,private

Location: https://test123.my.salesforce.com/services/apexrest/oss/callback

Content-Length: 0

 

GET response 

GET /services/apexrest/oss/callback HTTP/1.1

Accept: application/json

Postman-Token: { }

Cookie: BrowserId={ }

Referer: https://test123.force.com/services/apexrest/oss/callback

Host: test123.my.salesforce.com

 

{"@class":"com.silanis.esl.packages.event.ESLProcessEvent","name":"PACKAGE_COMPLETE","sessionUser":"18EZDL44xgsX","packageId":"{ }=","message":null,"documentId":null,"createdDate":"2018-07-18T18:19:19.356Z"}

 

HTTP/1.1 401 Unauthorized

Date: Thu, 20 May 2021 15:37:11 GMT

Strict-Transport-Security: max-age=31536002; includeSubDomains

X-Content-Type-Options: nosniff

X-XSS-Protection: 1; mode=block

X-Robots-Tag: none

Cache-Control: no-cache,must-revalidate,max-age=0,no-store,private

WWW-Authenticate: Token

Content-Type: application/json;charset=UTF-8

Transfer-Encoding: chunked

 

[{"message":"Session expired or invalid","errorCode":"INVALID_SESSION_ID"}]

 

Can you please check what will be the issue.

 

Regards,

Shashank Verma


Duo_Liang | Posts: 3776

Reply to:

0 votes

Hi Shashank Verma,

 

The response code is 302 which means to redirect to "Location" header, that's why you saw a second GET call. Because it's a GET call (not POST) and doesn't carry the Bearer header, hence yield the 401 error.

The first line appears like "POST / HTTP/1.1", are you aware why it's not something like "POST /services/apexrest/oss/callback HTTP/1.1"?

For your reference, this is an example from my postman console:

POST /services/apexrest/oss/callback HTTP/1.1

Authorization: Bearer 00D0b000000CxxxxxxxxyD82g.vuyHOsxNO

Content-Type: application/json

User-Agent: PostmanRuntime/7.26.10

Accept: */*

Cache-Control: no-cache

Postman-Token: c135a07a-2f07-40ab-894d-9ecc66941878

Host: mydomain-dev-ed.my.salesforce.com

Accept-Encoding: gzip, deflate, br

Connection: keep-alive

Content-Length: 239

Cookie: BrowserId=3wr9yblvEeuwTxl2UA4Wog

{

"@class": "com.silanis.esl.packages.event.ESLProcessEvent",

"name": "PACKAGE_COMPLETE",

"sessionUser": "0787be84-f095-44c7-ba00-787093df86fc",

"packageId": "WKZ0PV6yjLegSUjmt3kxQBDx5wU=",

"message": null,

"documentId": null

}

 

 

Duo


s.shashank.v.v… | Posts: 29

Reply to: How to add Signed Document to the Salesforce Record while working with APEX SDK

0 votes

Hi Duo,

 

We have exactly did the same steps what you have mentioned but we are not sure why we are getting GET response.

Also, can you please confirm about the sessionUser which you have used in pay load.

Let me know if you have any solution. So, we can move forward.

 

Regards,

Shashank Verma


jwesly | Posts: 2

Reply to: How to add Signed Document to the Salesforce Record while working with APEX SDK

0 votes

Hi Duo,

We tried the steps which you have mentioned in the post on "Wednesday, May 19, 2021 at 10:13am". We are able to see the callback request coming to Salesforce. So I believe this means our Connected App configuration is proper. 

However, the OneSpan is not notifying the callback listener (in Salesforce) whenever the events we have registered is triggered. 

We have followed all the steps in your 3-part blog to register our callback with our OneSpan sandbox account ([email protected]).

Thanks,

John Wesly


jwesly | Posts: 2

Reply to: How to add Signed Document to the Salesforce Record while working with APEX SDK

0 votes

Hi Duo,

Finally figured out the issue! :)

As per your blog post (part-2), the POST URL which we need to use to register the callback is "/api/callback/connectors/salesforceOauth2". When we used this, we were NOT getting any event notifications. 

We did the following changes:

  • Used "/api/callback" endpoint to register the callback
  • Updated the Apex SDK class OneSpanAPIObjects.apxc to have "origin" as "OSS" (originally it was "Salesforce" in the Data inner class)

Can you tell us why the "/api/callback/connectors/salesforceOauth2" endpoint didn't work in our case?

Thanks,

John Wesly


Duo_Liang | Posts: 3776

Reply to:

0 votes

Hi John,

 

I believe specifying "origin" as "OSS" does the trick.

For the callback service endpoint, it's defined in the swagger, hence I won't think it's a problem here.

For the origin attribute, it was also highlighted in my blog:
Take current version (11.40) for example, if a transaction is created from sender portal or equivalently carries “data” > “origin” : “OSS” in transaction JSON, once an event of interest triggers, the callback framework will deliver the notification to the Salesforce listener, which is registered as “salesforceOauth2”.

 

Duo


s.shashank.v.v… | Posts: 29

Reply to:

0 votes

Hey Duo,

 

We are able to get the callback in Salesforce but now we are trying to get the callback from the different OneSpan account. While doing that we are getting the below error on the registered user account email:

Failed to communicate with the callback server.

URL: https://test123.my.salesforce.com/services/apexrest/oss/callback
Payload: {"@class":"com.silanis.esl.packages.event.ESLProcessEvent","name":"SIGNER_COMPLETE","sessionUser":"{ }","packageId":"{ }" ,"message":null,"documentId":null,"createdDate":"2021-05-27T13:30:12.920Z"}
Reason(s): status code: 401, reason phrase: 401: Unauthorized

 

Can you please let us know what will be the issue.

 

Regards,

Shashank Verma


Duo_Liang | Posts: 3776

Reply to:

0 votes

Hi Shashank,

 

Glad to hear it partially works for you. Have you updated the OneSpan Sign Callback Service API (POST /api/callback/connectors/salesforceOauth2)? Did you send the package with the package data "origin" : "OSS"?

 

Duo


s.shashank.v.v… | Posts: 29

Reply to:

0 votes

Hey Duo,

 

As we mentioned before OneSpan Sign Callback Service API (POST /api/callback/connectors/salesforceOauth2) is not working. 

We did the following changes:

  • Used "/api/callback" endpoint to register the callback
  • Updated the Apex SDK class OneSpanAPIObjects.apxc to have "origin" as "OSS" (originally it was "Salesforce" in the Data inner class)

then we are able to get the callback. But when we have changed the Salesforce org and used the same setting then again we are not getting callback in the system.

Also, we are getting below error

Failed to communicate with the callback server.

URL: http://localhost:11567/connectors/callback/salesforceOauth2
Payload: {"type":"PACKAGE_CREATE","origin":"salesforceOauth2","packageId":"{ }","packageOwnerUid":"{ }","sessionUser":"{ }","documentId":null,"accountOwnerUid":"{ }","connectorInfo":"{ }"}
Reason(s): HttpResponseException: 503: IOException: Authenticate request was not successful (http code: 400, response body: {"error":"invalid_grant","error_description":"expired access/refresh token"})

We have created new refresh token as well but again we are getting above error.

Can you please let us know if we doing something wrong.

 

Shashank Verma


Duo_Liang | Posts: 3776

Reply to:

0 votes

Hi Shashank,

 

As the error message suggested "http code: 400, response body: {"error":"invalid_grant","error_description":"expired access/refresh token"}", can you double check if the refresh token you supplied is still valid?

 

Duo


s.shashank.v.v… | Posts: 29

Reply to:

0 votes

Hi Duo,

 

We are now getting following errors in callback via mail:

Failed to communicate with the callback server.

URL: https://testDomain.my.salesforce.com/services/apexrest/oss/callback
Payload: {"@class":"com.silanis.esl.packages.event.ESLProcessEvent","name":"PACKAGE_CREATE","sessionUser":"{ }","packageId":"{ }","message":null,"documentId":null,"createdDate":"2021-06-03T14:40:11.518Z"}
Reason(s): status code: 401, reason phrase: 401: Unauthorized

 

Failed to communicate with the callback server.

URL: http://localhost:11567/connectors/callback/salesforceOauth2
Payload: {"type":"PACKAGE_CREATE","origin":"salesforceOauth2","packageId":"{ }","packageOwnerUid":"{ }","sessionUser":"{ }","documentId":null,"accountOwnerUid":"{ }","connectorInfo":"BASE64"}
Reason(s): HttpResponseException: status code: 503, reason phrase: 503: IOException: Unexpected response code for CONNECT: 503

 

In BASE64 Callback URL we are getting older salesforce org URL which we had registered earlier. But, OneSpan sanbox showing the updated Event Notification.

Please let us know how to reset all the Callback URL's.

 

Regards,

Shashank Verma


Duo_Liang | Posts: 3776

Reply to:

0 votes

These two callbacks are sent by different callback services, you can tell the difference from the payload - 

The top one comes from the normal callback service with Basic authentication. When you are engaging Salesforce (OAuth2) callback service, you don't need to register the normal callback service, and it won't work. You can cancel the registration from sender portal (e.g. https://sandbox.esignlive.com/a/login) > Admin > Event Notification > scroll down to the bottom and select "Clear".

 

The bottom one is the callback service you registered via "POST /api/callback/connectors/salesforceOauth2" endpoint. You won't be able to view the configuration through UI portal and the only way to check is through a GET call "GET /api/callback/connectors/salesforceOauth2".

I understood that you were experiencing problem pinging the endpoint using Postman. But you can always utilize the Swagger page.

 

Duo


Hello! Looks like you're enjoying the discussion, but haven't signed up for an account.

When you create an account, we remember exactly what you've read, so you always come right back where you left off