I want to integrate SalesForce with Facebook Messenger. For this I've retrieved access token, app id , app secret. When I hit a HTTP request in developer console to send a message then there is an error.
In the given code it is not accepting messages as parameter throwing error but working without messages.
ref: https://developers.facebook.com/docs/messenger-platform/send-messages/?translation#sending_text
Httprequest req = new httpRequest();
req.setEndPoint('https://graph.facebook.com/v5.0/1798927698340/messages?access_token={PUT-ACCESS-TOKEN-HERE}');
String body = '{'+
'"recipient": {'+
'"id": "100042977199143"'+
'},'+
'"message": {'+
'"text": "hello, world!"' +
'}' +
'}';
req.setMethod('POST');
req.setHeader('Content-Type','application/json');
Http h = new Http();
HttpResponse res = h.send(req);
system.debug(res.getBody());
error message :
16:55:58:127 USER_DEBUG [16]|DEBUG|{"error":{"message":"Unsupported
post request. Object with ID 'me' does not exist, cannot be loaded due
to missing permissions, or does not support this operation. Please
read the Graph API documentation at
https://developers.facebook.com/docs/graph-api","type":"GraphMethodException","code":100,"error_subcode":33,"fbtrace_id":"AcqDT5M6mGXSOCr4mOd3kDf"}}
actual response : success = true
This problem arises sometimes when we use invalid access token or user access token instead of page access token.
Related
When users signup for our application, we ask them to go through the oAuth process. We ask them for their organisation first, so we can use the access token we receive during oauth to make requests.
Here is a sample of the code we use to do that:
var client = new RestClient();
var createItemRequest = new RestRequest("https://app.vssps.visualstudio.com/oauth2/token", Method.POST);
string body = $"client_assertion_type=urn:ietf:params:oauth:client-assertion-type:jwt-bearer&" +
$"client_assertion={HttpUtility.UrlEncode(clientSecret)}&grant_type=urn:ietf:params:oauth:grant-type:jwt-bearer" +
$"&assertion={HttpUtility.UrlEncode(code)}&redirect_uri={redirectUrl}";
var formData = Encoding.UTF8.GetBytes(body);
createItemRequest.AddParameter("application/x-www-form-urlencoded", formData, ParameterType.RequestBody);
var accessTokenResponse = client.Execute(createItemRequest).Content;
_logger.LogInformation($"accessToken response: {accessTokenResponse}");
var accessTokenObject = JsonConvert.DeserializeObject<AccessTokenResponse>(accessTokenResponse);
if (accessTokenObject != null
&& !string.IsNullOrEmpty(accessTokenObject.AccessToken)
&& !string.IsNullOrEmpty(accessTokenObject.RefreshToken))
{
_logger.LogInformation($"We have access token and refresh");
}
We always manage to get the refresh + access tokens for every user. Directly after this call we make a "get all projects call" to test the connection and tokens. For some users signing up when we make this call to check we can see them, some users receive a 203 response when we use the access token to make the first call (to get a list of projects). The request looks like:
The HTML returns:
My question is, why do some users receive a 203 and some not? We have NO idea of what to tell the user when this happens - what do they check? Why does this happen? And how can they fix it?
Pre-req:Rest-assured api tests with Java
Step
1. Launch URL and get login ticket - code snippet below to get login ticket
RestAssured.baseURI = "https://ve4al10p:453";
RestAssured.useRelaxedHTTPSValidation();
Response res =
given().
header("Content-Type","application/json").
when().
post("/i/login?action=lt").
then().
assertThat().statusCode(200).
extract().response();
res.prettyPrint();
Output: Notice login ticket
lt":"LT-12370-j4znjFQkGMXMjlT3uKJ"
Step 2. Use login ticket and perform login with username and password.
I extracted login ticket and passed to next request (continued snippet).
CookieFilter cookieFilter = new CookieFilter();
Response res1 = given().
filter(cookieFilter).
header("Content-Type","application/json").
queryParam("lt",loginticket).
queryParam("username","user1").
queryParam("password","pass1").
when().
post("/i/login?service=https://ve4al10p:443/spa").
then().
assertThat().statusCode(200).
extract().response();
res1.prettyPrint();
Output: Notice it again creates a new login ticket, that means a new session and fails give expected output.
**"lt":"LT-12369-u6osMkesdg6RQu9JPoDARL4D"**
Note: I also noticed the sessions for above requests and both are different.
Expected Output: I want to use same login ticket and maintain same sessions.
you can get the SessionID/cookie from login and pass this as SessionID to next request as header to maintain single session.
for eg :
String JsessionID = given().header(h1).body(payload).when().post(basepath).thenReturn().cookie("JSESSIONID");
given().headers(JsessionID).body(body).when().post();
How about send request with cookie?
Let's say you got access_token in cookie after login success, you can send request within the access_token in cookie:
String token = given()
.contentType(ContentType.JSON)
.body(payload)
.log()
.all()
.when()
.post(loginUrl)
.thenReturn()
.cookie("access_token");
Cookie tokenCookie = new Cookie.Builder("access_token", token)
.setSecured(true)
.setComment("some comment")
.build();
assertEquals(given()
.cookie(tokenCookie)
.when()
.get(nextRequest)
.statusCode(), 200);
I want to generate a simple post call from Apex for the access token. I am new to Apex and Rest so is there someone explain me how to do that?
I have endpointurl, client _secret, client_id, scope, and grant_type is Client_credentials'.
I tried to run this in Postman and it works fine but not in salesforce.
Http http = new Http();
HttpRequest request = new HttpRequest();
request.setEndpoint('https://xxx.xxx.eu/o/oauth2/token');
string mybody='{"client_id":"xxxx","client_secret":"xxxx","grant_type":"client_credentials","scope": "xxx.Rest.everything"}';
request.setMethod('POST');
request.setHeader('Content-Type', 'application/json;charset=UTF-8');
// Set the body as a JSON object
request.setBody(mybody);
HttpResponse response = http.send(request);
// Parse the JSON response
if (response.getStatusCode() != 201) {
System.debug('The status code returned was not expected: ' +
response.getStatusCode() + ' ' + response.getStatus());
} else {
System.debug(response.getBody());
}
´´´´
Have you added the remote site? It is the probable reason I believe.
If not, try
From Setup, enter Remote Site Settings in the Quick Find box, then
select Remote Site Settings.
Click New Remote Site.
Enter a descriptive term for the Remote Site Name.
Enter the URL for
the remote site. Optionally, enter a description of the site.
Click Save
I use the Private Replies API call to send a message in Messenger to someone commenting on a Facebook post. If the doc says I should get back the message id and the user_id, I only get the message id in response:
body:
'{"id":"m_ZpLkUdJGAoJ9WCpeROAvWJaHycesSPGVPmoNH0SXTUB8WYqRqHl0ru0y3mniMP3q7YL9rl1lfuQr0x9fyNP
Here is my API call code in ruby:
url = "https://graph.facebook.com/v3.1/" + #comment_id + "/private_replies?message=" + #trigger_message + "&access_token=" + #page_access_token
uri = URI.parse(url)
https = Net::HTTP.new(uri.host,uri.port)
https.use_ssl = true
request = Net::HTTP::Post.new(uri, initheader = {'Content-Type' =>'application/json'})
resp = https.request(request)
Why don't I get the user_id?
Facebook private replies API was supposed to return App scoped ID or ASID, though post the new app verification or around that time, they have stopped giving ASID into private reply API - most probably because they are heading towards returning Page scoped ID or PSID (PSID Migration)
Though you can still get ASID from either :
a. The webhook that could be providing comment ID, it should be providing ASID as sender_id
b. from field with parsing comment ID. This is used to parse single comment node, you can find more info here
Do keep in mind ASID to PSID migration...
It is said, that it is not possible to initiate new conversation through the API alone, except using Facebook's own Form integrated in the app. Is this correct, or is there some new API, which enables me to initiate a new conversation?
To reply to an existing conversation, I retrieved the conversations id using the following FQL Query "SELECT thread_id, . WHERE viewer_id={0} AND folder_id=0". Afterwards I retrieved the PageAccessToken for my app page using my user Access token, and tried to use this call:
*You can reply to a user's message by issuing an HTTP POST to /CONVERSATION_ID/messages with the following parameters [conversation id, message]. A conversation ID look like t_id.216477638451347.*
My POST Call looked like this (this is not a valid thread id): /t_id.2319203912/messages with message parameter filled. But it always said "Unknown method". Can you help me out with this one? Is there a parameter missing? I passed in the page's Access Token to call this one.
Is there some API out (except Facebook's Chat API), that I am missing, which can send private messages to users?
Edit:
What I wonder about is, that the code below only returns a single page, the application's page. Is this correct, or is there another page token required? This is what bugged me the most about the returned page.
The FacebookClient uses my UserToken to perform the next following task.
This is the code to retrieve my Page Access Token:
dynamic pageService = FacebookContext.FacebookClient.GetTaskAsync("/"+UserId+"/accounts").Result;
dynamic pageResult = pageService.data[0];
_pageId = pageResult["id"].ToString();
return pageResult["access_token"].ToString();
Now the code to retrieve my ConversationÍd:
dynamic parameters = new ExpandoObject();
parameters.q = string.Format("SELECT thread_id, folder_id, subject, recipients, updated_time, parent_message_id, parent_thread_id, message_count, snippet, snippet_author, object_id, unread, viewer_id FROM thread WHERE viewer_id={0} AND folder_id=0", FacebookContext.UserId);
dynamic conversations = FacebookContext.FacebookClient.GetTaskAsync("/fql",parameters).Result;
The following code is executed using the access token retrieved from the code above (page access token request).
Now the Code used to send the reply:
dynamic parameters = new ExpandoObject();
parameters.message = CurrentAnswer;
string taskString = "/t_id." + _conversationId + "/messages";
dynamic result = FacebookContext.FacebookClient.PostTaskAsync(taskString,parameters).Result;
return true;
I also tried it with facebook's graph API Debugger using the token, which is returned by my first part of code. But with the same error message.