18

I have a google script running as a webapp to handle the backend of a slack app.

The app has been Authenticated and I have the OAUTH token from this.

I can currently post to a channel with button actions using the chat.postMessage using the for-mentioned token.

Actions url points back at my webapp and hook in via doGet, from this response i construct a JSON object.

var response_payload = {
    "token" : access_token,
    "ts" : message_ts,
    "channel" : channel_id,
    "text" : "Approved! you are a winner!"
  })

response_url = "https://slack.com/api/chat.update";

sendToSlack_(response_url, response_payload)

posted via the following function:

function sendToSlack_(url,payload) {
   var options =  {
    "method" : "post",
    "contentType" : "application/json;charset=iso-8859-1",
    "payload" : JSON.stringify(payload)
  };
  return UrlFetchApp.fetch(url, options)
}

however returned is the following:

{"ok":false,"error":"not_authed"}

I can't find any documentation about this error other than the following

Sending JSON to Slack in a HTTP POST request

However this is in regard to a chat.postMessage request of which in my implementation is working correctly.

Community
  • 1
  • 1
Jamie
  • 271
  • 1
  • 2
  • 11
  • Could you provide your html source code? – Apoorv Kansal Dec 06 '16 at 02:41
  • this is all done in google script (javaScript) there is no html.. – Jamie Dec 06 '16 at 02:54
  • Is this project a webhook for something like a slash command? There are a few problems with this code such as you are using POST instead of GET. Paramaters are sent in the url not the post body. BUT if this is a webhook called from a doGet you are going to verify the webhook requests token, then in response respond with a json object VIA content service. I've got an example if that IS what you are trying to do. – Spencer Easton Dec 06 '16 at 13:16
  • No I have a app integration that has `chat:write:bot` [scope](https://api.slack.com/docs/oauth-scopes#scopes) and while it does have a hook I'm not using and instead direction your `chat.postMessage` and `chat.update`. Funnily enough the whole thing seems to be working now.. I'm about to post an update about this.. – Jamie Dec 07 '16 at 21:05
  • With any type of token, currently only `application/x-www-form-urlencoded` works fine. – Ivan Didur Jun 30 '18 at 15:22

3 Answers3

24

You need to put token to header instead of json payload if using application/json. Here is doc for this.

So you request should look like this:

POST /api/chat.update HTTP/1.1
Authorization: Bearer xoxp-xxx-xxx-xxx-xxx
Content-Type: application/json;charset=UTF-8

{
    "channel": "xxx",
    "text": "Hello ~World~ Welt",
    "ts": "xxx"
}

Note: there is no token field in payload.

Walery Strauch
  • 6,792
  • 8
  • 50
  • 57
  • 1
    This helped, ended up finding this https://api.slack.com/web#slack-web-api__basics__post-bodies for further verification – Leo Fisher Feb 11 '21 at 02:03
2

Well according to the link your provided, Slack does not accept JSON data (weird).

Also, after playing around with their tester, Slack seems to be doing a GET request on https://slack.com/api/chat.update with query parameters attached like this:

https://slack.com/api/chat.update?token=YOUR_TOKEN&ts=YOUR_TIME&channel=YOUR_CHANNEL&text=YOUR_TEXT_URL_ENCODED&pretty=1

So use this code:

var response_payload = {
    "token" : access_token,
    "ts" : message_ts,
    "channel" : channel_id,
    "text" : "Approved! you are a winner!"
  }


function httpGet(theUrl)
{
    var xmlHttp = new XMLHttpRequest();
    xmlHttp.open( "GET", theUrl, false ); // false for synchronous request
    xmlHttp.send( null );
    return xmlHttp.responseText;
}

response_url = encodeURI("https://slack.com/api/chat.update?token=" + response_payload['token'] + 
"&ts=" + response_payload['ts'] + "&channel=" + response_payload['channel'] + "&text=" + response_payload['text'] +"&pretty=1");

httpGet(response_url);
Apoorv Kansal
  • 3,210
  • 6
  • 27
  • 37
  • 1
    Thanks for this.. I tried this out and modifications of it and got no where.. mysteriously after tweeting at slack about it.. my original script started working.. – Jamie Dec 07 '16 at 21:06
  • Ah right very very odd. I believe the Slack team are in the middle of supporting json data and probably heard you! – Apoorv Kansal Dec 07 '16 at 21:14
  • Yeah bro.. I don't know.. they said that they don't.. but all of a sudden it kinda works.. I don't find their API documentation to be very good at all – Jamie Dec 07 '16 at 21:16
1

Ok! thankyou all for your input.. certainly I have learned a little more. After tweeting at slack_api my original code more or less worked as is.. I had to JSON.parse(payload); the payload in order to then access the object parameters within.. the full example is as below.

function post_update(url, payload) {
  var options =
  {
    'method': 'post',
    "payload" : payload,
  };

  var result = UrlFetchApp.fetch(url, options);
  return result.getContentText();
}

function doPost(e) {
  var payload = e.parameter.payload;
  var json = JSON.parse(payload);

  response_url = "https://slack.com/api/chat.update";

  // get object elements
  var action = json.actions[0].value;
  var user = json["user"].name;
  var message_ts = json["message_ts"];
  var channel_id = json["channel"].id;

  if (action == 'approved') // payload if action is 'approved'
  {
    var response_payload = {
      "token" : access_token,
      "ts" : message_ts,
      "channel" : channel_id,
      "text" : "Approved! *" + invitation_name + "* has been sent an invite!",
      "attachments" : JSON.stringify([{
          "text": ":white_check_mark: Approved by @" + user,
           }])
      }
  }

  if (action == 'denied') // payload if action is 'denied'
  {
    var response_payload = {
      "token" : access_token,
      "ts" : message_ts,
      "channel" : channel_id,
      "text" : "Denied. *" + invitation_name + "* has been declined an invite",
      "attachments" :JSON.stringify([{
          "text": ":exclamation: Declined by @" + user,
          }])
    }
  }

  post_update(response_url, response_payload);
  return ContentService.createTextOutput().setMimeType(ContentService.MimeType.JSON);

}
Jamie
  • 271
  • 1
  • 2
  • 11