on 06-18-2019 2:50 AM
Hi guys,
Can you please help me to call an instance of the Proof of State service from my application?
I've been following this guide to build the service. It's up and running and I don't have any problems calling it from the SAP API Hub. Here is the 201 response after I saved a primitive example payload with id "3" below:
{"test": "value"}
Now if I try to generate a JavaScript code snippet and use it in my own application to call the service directly, I receive a 500 error. Here is the code I use:
writeData: function () {
var data = JSON.stringify({
"test": "value"
});
var xhr = new XMLHttpRequest();
xhr.withCredentials = false;
xhr.open("POST", "https://blockchain-service.cfapps.us10.hana.ondemand.com/blockchain/proofOfState/api/v1/states/4");
xhr.setRequestHeader("Content-Type", "application/json");
xhr.setRequestHeader("Accept", "application/json");
xhr.setRequestHeader("Access-Control-Allow-Credentials", "true");
xhr.setRequestHeader("Access-Control-Allow-Origin", "https://<myRouter>-approuter.cfapps.us10.hana.ondemand.com");
xhr.setRequestHeader("Access-Control-Allow-Headers", "access-control-allow-origin,authorization,content-type");
xhr.setRequestHeader("Access-Control-Allow-Methods", "GET,HEAD,PUT,PATCH,POST,DELETE");
xhr.setRequestHeader("Authorization", "Bearer <myToken>");
xhr.onload = function () {
if (xhr.status === 200) {
alert("Sucessfully called the API!");
} else {
alert("Calling the API failed");
}
};
xhr.send(data);
}
Here is the 500 response from the service:
{"error":{"code":500,"message":"{\"statusCode\":500} - Please see our documentation at https://help.sap.com/viewer/p/BLOCKCHAIN_APPLICATION_ENABLEMENT/"}}
Mind you, it's not a 403 or a CORS error. I already resolved those. The call does reach the service and I can see it in the dashboard as below:
I don't understand why is it 500? The worst thing that the service doesn't provide explanation and the error is not traceable anywhere. I suspect my payload is not correct, but the documentation doesn't give any examples of a proper payload for a post operation.
So I'd be really grateful if you could suggest anything or give an example of how the service should be called.
Thank you!
------------------------------------------------------
I already looked at the following examples, but couldn't find an answer:
https://developers.sap.com/tutorials/blockchain-application-enablement-proofstate.html
https://help.sap.com/viewer/71a0bb282b2144c6b27fefc772394bff/BLOCKCHAIN/en-US/58cfd045142c4696baced2...
https://github.wdf.sap.corp/blockchain/timestamp/blob/master/index.js
Hi Anton,
I’m from the SAP Blockchain Team and inspected your issue. It seems like the problem is caused by the token exchange that is somehow not working correctly.
I saw in your code that you pass the user token to retrieve the refresh_token and then retrieve the technical token for the service via the refresh token (So the technical token is extended with user data). The problem is that the required uaa.user scope seems to get lost. If you call thh blockchain service with that token, it also wants to do a token exchange for the fabric service but fails because the scope is missing. (this caused the 500 error - we will improve the message and status code there).
For now the easiest option for you is to call the service by just using the technical token without doing a token exchange.
Here is a code example:
// get access token
request.post({
url: baas_options.authentication.url + '/oauth/token?grant_type=client_credentials',
json: true,
headers: {
Authorization: "Basic " + Buffer.from(baas_options.authentication.clientId + ':' + baas_options.authentication.clientSecret, 'utf8')
.toString('base64')
}
}, function (err, r, body) {
// call BAE service
request.get({
url: bcService.serviceUrl + '/states/<ID>',
json: true,
headers: {
Authorization: "Bearer " + body.access_token,
}
}, function (err, r, body2) {
// …
});
});
Best,
Christopher
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Hi Rudramani,
I appreciate you're not giving up on this.
Yes, your picture is exactly my sequence of calls in the application. With a little addition that there is an app router between UI5 and Node.js apps. I've created a Blockchain Application Enablement Service instance under the 'blockchain-proof-of-state' service plan and connected it to Hyperledger.
After I failed calling the service from my Node.js app, I've tried to use the JavaScript code snippet generated by the SAP API Hub to call it directly from UI5 (my first post as part of this question). I failed there too. Tried to call it directly from Postman - that failed as well. Not sure what to do. All of my calls do reach the Blockchain Application Enablement Service instance, but it returns status 500.
I think I'll just try to create a different type of BC AE Service instance and try to play with it. Not sure where my mistake is.
Thanks,
Anton
Have you tried calling your API via postman?
I will suggest to get your token and with that, call your API via the postman.
Well, I prefer AJAX calls, so I will just provide you my snippet of AJAX.
In the code below, we are calling the API and receiving the token; and then again calling the API with that token and a body. The code mentioned below was written in node.js under MTA UI5.
// update proof history
app.get('/UPDATE_OBJECT_HISTORY', function (req, res, next) {
var uname = req.query.USERNAME;
var pass = req.query.PASSWORD;
var dats = req.query.TIMESTAMP;
// Get Token
var tokenoptions = {
method: 'GET',
url: configData.tokenUrl,
qs: {
grant_type: 'client_credentials'
},
headers: {
'cache-control': 'no-cache',
Authorization: configData.authorization
}
};
request(tokenoptions, function (error, response, body) {
if (error) throw new Error(error);
data = JSON.parse(body);
token = data.access_token;
var dataoptions = {
method: 'PATCH',
url: configData.blockServUrl + '/logon',
headers: {
'cache-control': 'no-cache',
'Content-Type': 'application/json',
Accept: 'application/json',
Authorization: 'Bearer ' + token
},
// Important in your case
body: {
USERNAME: uname,
PASSWORD: pass,
TIMESTAMP: dats
},
json: true
};
request(dataoptions, function (error, response, body) {
if (error) throw new Error(error);
res.json(globalBody);
});
});
});
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Hi Rudramani,
No, unfortunately your code snippet didn't help me. I used it in my middleware node.js layer of the MTA app and still received the same generic 500 error without any further explanations. Here is how my code looks like:
var express = require('express');
var bodyParser = require('body-parser');
var request = require('request');
var cfenv = require('cfenv');
const appEnv = cfenv.getAppEnv();
// below is my hardcoded instance name of the PoS service. It's described as a resource dependency
// to the current node.js module in the mta.yaml
var baas_options = appEnv.getServiceCreds("dm2_pos");
var app = express();
app.use(bodyParser.json());
app.use(getUserToken);
//app.get("/api/v1/pos/:key", handleRead);
app.post("/api/v1/pos/:key", handleWrite);
function handleWrite(req, res) {
var dataoptions = {
method: 'POST',
url: baas_options.serviceUrl + "states/" + req.params.key,
headers: {
'cache-control': 'no-cache',
'Content-Type': 'application/json',
'Accept': 'application/json',
'Authorization': 'Bearer ' + req.user_access_token
},
// Important in your case
body: {
Title: "Title 11",
Author: "Author 11"
},
json: true
};
request(dataoptions, function (err, posRes, body) {
//console.log("In the handleWrite callback function. posRes = " + JSON.stringify(posRes));
var status = posRes ? posRes.statusCode : "500";
if (err) {
body = err;
}
res.status(status).send(body);
});
}
function getUserToken(req, res, next) {
request.post({
url: baas_options.authentication.url + '/oauth/token?client_id=' + baas_options.authentication.clientId +
'&response_type=token&grant_type=user_token',
headers: {
Authorization: req.headers.authorization
}
}, function (err, res, body) {
request.post({
url: baas_options.authentication.url + '/oauth/token?refresh_token=' + JSON.parse(body).refresh_token + '&grant_type=refresh_token',
json: true,
headers: {
Authorization: "Basic " + Buffer.from(baas_options.authentication.clientId + ':' + baas_options.authentication.clientSecret, 'utf8')
.toString('base64')
}
}, function (err, res, body2) {
req.user_access_token = body2.access_token;
next();
});
});
}
The request successfully reaches the blockchain-proof-of-state service instance. I can see it in the service's 'API Calls' cockpit with status 500, but no further logs available...
Thank you for your help,
Anton
Tried to call directly via Postman. Same result 500 without explanation.
POST to https://blockchain-service.cfapps.us10.hana.ondemand.com/blockchain/proofOfState/api/v1/states/15
{
"error": {
"code": 500,
"message": "{\"statusCode\":500} - Please see our documentation at https://help.sap.com/viewer/p/BLOCKCHAIN_APPLICATION_ENABLEMENT/";
}
}
Hey I also have a problem with the Proof of State API. I tried to call it from the SAP API Business hub and just got the message: "Unauthorized". I provided all OAuth2.0 informations... Do I need to make some additional configuration to call the api?
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
User | Count |
---|---|
86 | |
10 | |
10 | |
9 | |
7 | |
7 | |
6 | |
5 | |
4 | |
4 |
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.