0

I'm working on a project to

  1. retrieve/GET a csv file using an HTTPRequest
  2. update the associated Salesforce records, and
  3. POST a csv back

I found this 'send a report as a CSV/TEXT' thread, which looks as though it will be just what I need for #3, but I'm still working on getting my first objective completed. The services that I'm connecting to generate the file and provide a URL for the download. I can access the URL, but when I use .getBody() on the HTTPResponse I'm not seeing anything.

Here's the request that I'm using to retrieve the file:

    HttpRequest req = new HttpRequest();

    req.setMethod('GET');            
    req.setHeader('Authorization', authHeader);
    req.setHeader('content-type', 'application/json');
    req.setEndpoint(tmpURL);                

    Http http = new Http();

    try{
        HTTPResponse res = http.send(req);
        String sBody = res.getBody();
        result = sBody;

        Utils.debug('STATUS_CODE:'+ sBody + ' from URL ' + tmpURL...);

    } catch(System.CalloutException e){
        Utils.debug('An error occurred accessing the download URL...' + e.getMessage() + ',\n' + e.getCause() + ',\nLine: ' + e.getLineNumber()...);

    }

I think that it is probably related to the content-type(?) or another attribute that's not set up correctly to actually retrieve the file. Or should I be using .getBodyAsBlob() to retrieve it?

0

I would use postman/curl to inspect requests to that endpoint more closely.

Anyways, first try using getBodyAsBlob() from the HttpResponse Class to retrieve binary data and then use Blob.toString() to get a String value of the retrieved data.

Basically content-type you set in the request header should tell the server in what format you expect the response data be. You might want to inspect the response header using getHeaderKeys() and getHeader(key) to get more insights on the response and see if there are some issues.

  • I did try getBodyAsBlob(), but it appears that I'm getting an empty response; thanks for the suggestions re getHeader() & getHeaderKeys() - I'll see what I can find there. – Duncan Stewart Jul 11 '18 at 15:41
  • Also play with postman/curl and see what response and its details you get. It seems that request you are making indeed returns an empty body (no data). – Eduard Jul 11 '18 at 16:00
  • Of the header keys being returned (X-Cache,inin-ratelimit-count,Connection,Pragma,ININ-Correlation-Id,Date,Via,Cache-Control,inin-ratelimit-reset,X-Amz-Cf-Id,Expires,Content-Length,inin-ratelimit-allowed,Location), the only two of value appear to be Content-Length, which = 0, and Location, which indicates the AWS location of the file -- i.e. both the endpoint URL and Location are pointing to the file I'm looking for, but it doesn't appear to be part of the response. I did change the Content-Type to 'text/csv', to no avail. – Duncan Stewart Jul 11 '18 at 16:05
  • Could you post the full request/response from debug here? – Eduard Jul 11 '18 at 16:32
0

This has been an interesting exercise, and there are several additional parts to follow, but I have been successful in this at least - initiating a file export, retrieving the download URL(s - I'll get into that), and accessing the results.

I'm integrating with PureCloud/Genesys in this example, and these are the steps involved:

  1. Request the Authorization token
  2. Initiate the file creation/export
  3. Request the 'friendly URL' (which works for a manual download, but not an HTTPRequest.)
  4. Request the file/download URL
  5. Request the 'file'.
  6. Parse it (not covered here)

    HttpRequest req = new HttpRequest();
    
    req.setMethod('POST');        
    req.setHeader('Authorization', 'Basic ' +
      EncodingUtil.base64Encode(Blob.valueOf(clientId + ':' + clientSecret)));
    req.setHeader('Host','https://login.mypurecloud.com/oauth');
    req.setHeader('content-type', 'application/x-www-form-urlencoded');
    req.setEndpoint('https://login.mypurecloud.com/oauth/token');
    req.setBody('grant_type=client_credentials');
    
    Http http = new Http();
    String JSONString = '';
    
    try{
        HTTPResponse res = http.send(req);
        JSONString = JSON.serialize(res.getBody());
        updateSuccessful = true;
    
        // JSON.serialize() formats the data in comma-separated label:value pairs
        // "{\"access_token\":\"bigIndeciphera_bleStr1ng23etc\",\"token_type\":\"bearer\",\"expires_in\":86399}\n"
    
    } catch(System.CalloutException e){
        Utils.debug(e.getMessage() + ',\n' + e.getCause() + ',\nLine: ' + e.getLineNumber(), 'REST Callout', 'PureCloudUpdateCampaign[63]');
    }
    
    if(updateSuccessful){
    
        String accessToken = '';
        String issuedAt = '';
    
        //Parse JSON for Bearer Token
        JSONParser parser = JSON.createParser(JSONString);
        while (parser.nextToken() != null) 
        {               
            if (parser.getCurrentToken() == JSONToken.VALUE_STRING && //JSONToken.FIELD_NAME && 
                parser.getText().contains('access_token')) // == 'access_token')
            {
               accessToken = parser.getText();
            }
        }
    
        // The access token is returned as a VALUE_STRING, not a FIELD_NAME:
        // JSONParser.getText() cleans it up some: 
        //{"access_token":"bigIndeciphera_bleStr1ng23etc","token_type":"bearer","expires_in":86399}
    
        String[] stringParts = accessToken.split('"');
        accessToken = stringParts[3];
        String authHeader = 'Bearer ' + accessToken;
    
        HttpRequest req2 = new HttpRequest();
    
        req2.setMethod('POST');            
        req2.setHeader('Authorization', authHeader);
        req2.setEndpoint('https://api.mypurecloud.com/api/v2/outbound/contactlists/' + pureCloudCListId + '/export');                
    
        Http http2 = new Http();
    
        try{
            HTTPResponse res2 = http2.send(req2);
            updateSuccessful = true;
        } catch(System.CalloutException e){
            Utils.debug('An error occurred initializing Contact list export...' + e.getMessage() + ',\n' + e.getCause() + ',\nLine: ' + e.getLineNumber(), 'REST Callout', 'PureCloudUpdateCampaign[102]');
            updateSuccessful = false;
        }
    
        String sURL = '';
        if(updateSuccessful){
            sURL = getContactListURL(authHeader, pureCloudCListId);
        }
        String sNext = '';
        if(updateSuccessful){
            sNext = getContactList(authHeader, sURL);
        }
    
        parseContactList(sNext);
    }
    

    }

    public String getContactListURL(String authHeader, String cListId){

    String result = '';
    HttpRequest req = new HttpRequest();
    
    req.setMethod('GET');            
    req.setHeader('Authorization', authHeader);
    req.setHeader('content-type', 'application/json');
    req.setEndpoint('https://api.mypurecloud.com/api/v2/outbound/contactlists/' + cListId + '/export');                
    
    Http http = new Http();
    
    try{
        HTTPResponse res = http.send(req);
        String sBody = res.getBody();
        result = sBody;
        updateSuccessful = true;
    
        // which returns {"uri":"https://api.mypurecloud.com/api/v2/downloads/<fileName>","exportTimestamp":"2018-07-13T15:40:26.684Z"}
    
    } catch(System.CalloutException e){
        Utils.debug('An error occurred retrieving the Contact list download URL...' + e.getMessage() + ',\n' + e.getCause() + ',\nLine: ' + e.getLineNumber(), 'REST Callout', 'PureCloudUpdateCampaign[137]');
        updateSuccessful = false;
    }
    
    return result;        
    

    }

    public String getContactList(String authHeader, String URL){

    String result = '';
    String tmpURL = '';
    String JSONString = JSON.serialize(URL);
    
    JSONParser parser = JSON.createParser(JSONString);
    while (parser.nextToken() != null) 
    {               
        if (parser.getCurrentToken() == JSONToken.VALUE_STRING && //JSONToken.FIELD_NAME && 
            parser.getText().contains('uri'))
        {
            tmpURL = parser.getText();
        }
    }
    
    String[] stringParts = tmpURL.split('"');
    tmpURL = stringParts[3];
    
    // https://api.mypurecloud.com/api/v2/downloads/<fileName/>
    
    HttpRequest req = new HttpRequest();
    
    req.setMethod('GET');            
    req.setHeader('Authorization', authHeader);
    req.setHeader('Content-Type', 'text/csv');
    req.setEndpoint(tmpURL);                
    
    Http http = new Http();
    Boolean locationSuccess = false;
    try{
        HTTPResponse res = http.send(req);
    
        // 07.11: There is no response body, nor is there any content per se; 
        //  HeaderKey 'Location' returns the actual AWS location of the file, 
        //  but not the file itself.
    
        String[] headerkeys = res.getHeaderKeys();
        String[] keyDetails = new String[]{};
    
        for(String s : headerKeys){
            keyDetails.add(res.getHeader(s));
        }
        for(integer i=0;i<keyDetails.size();i++){
            if(headerKeys[i] == 'Location'){
                tmpURL = keyDetails[i];
                locationSuccess = true;
            }
        }
    
        // Now we have the AWS location
        // https://prod-dialer.s3.amazonaws.com/contact-lists/exports/something_proprietary-PureCloud%20Inventory%20IVR%20Report%207.12b.csv?additionalParams
    
    } catch(System.CalloutException e){
        Utils.debug('An error occurred accessing the download URL...' + e.getMessage() + ',\n' + e.getCause() + ',\nLine: ' + e.getLineNumber(), 'REST Callout', 'PureCloudUpdateCampaign[196]');
        locationSuccess = false;
    }
    
    if(locationSuccess == true){
    
        req = new HttpRequest();
    
        req.setMethod('GET');            
        req.setHeader('Content-Type', 'text/csv');
        req.setEndpoint(tmpURL);                
    
        http = new Http();
        try{
            HTTPResponse res = http.send(req);
            result = res.getBody();
    
        } catch(System.CalloutException e){
            Utils.debug('An error occurred accessing the download URL...' + e.getMessage() + ',\n' + e.getCause() + ',\nLine: ' + e.getLineNumber(), 'REST Callout', 'PureCloudUpdateCampaign[214]');
        }
    }
    
    // And here we see the actual data: 
    // "inin-outbound-id",,"Phone","First Name","Last Name","18 Digit Contact ID","18 Digit SFDC ID","etc"
    // "e60a7ff7cc2de18e23a0ceb37dfdb819","ivr-07/12/18-682719","(781) ..."
    // "938ddcefe9de99e5c2e54d95123368c1","ivr-07/12/18-683108","(978) ..."
    
    return result;        
    

    }

  • BTW, while I didn't use Postman for much, it was very useful for taking the URL responses from PureCloud and inspecting what was being returned, which did not include the Contact List as data / request.Body, but did reveal where the AWS S3 URL was hiding in the header key. – Duncan Stewart Jul 13 '18 at 19:01

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.