[SalesForce] Not able to post data to Http with content type: application/x-www-form-urlencoded

I have tried with the below code but have received {"error":"invalid_request","error_description":"Missing parameters: password"} in response. I have tried with POSTMAN and getting correct response.

What is missing here:

Http http = new Http();
HttpRequest request = new HttpRequest();
String reqUrl = 'https://api.abc.com/token';
request.setEndpoint(reqUrl);
request.setMethod('POST');
request.setHeader('Content-Type','application/x-www-form-urlencoded');
request.setHeader('Authorization','Basic T2dfT2Q2V1R3OHRkYUhyTkN6WlNwaVk0YldRYTpVW');
String payLoad = 'grant_type=password&username=test@ad.abc.com&password=O$Q3tz%Hdkqq&scope=PRODUCTION';
request.setBody(payLoad);
System.HttpResponse response = new System.Http().send(request);
system.debug(''+response.getBody());

Best Answer

I think you need to URL-encode the parameters in your payload. The password needs it in this instance, and it's worth doing for the username too.

So, you would have:

String payLoad = 'grant_type=password' 
+ '&username=' + EncodingUtil.urlEncode('test@ad.abc.com','UTF-8') 
+ '&password=' + EncodingUtil.urlEncode('O$Q3tz%Hdkqq', 'UTF-8') 
+ '&scope=PRODUCTION';

More generally, I tend to pass the params in as a map, and then write a utility function which url encodes all of the keys and values as it turns them into a query string.

global static String urlEncode(Map<String, String> vals) {
    String result = '';
    for(String thisKey : vals.keySet()) {
        result += EncodingUtil.urlEncode(thisKey, 'UTF-8') + '=' + EncodingUtil.urlEncode(vals.get(thisKey), 'UTF-8') + '&';
    }
    return result.removeEnd('&');    
}