Integrations and APIs for Service

Get Involved. Join the Conversation.

Comments

  • Scott Harwell

    You're probably hitting some rate limits.  Does the process work if you add a 500 millisecond or so delay between each post the the API?

  • Rajan Davis

    Alright, I did some quick hacking and got file attachments to work with May 2015.

    I was trying to set the "uRL" attribute for the fileAttachment, but it kept spitting back an error saying that the uRL attribute was "read-only" despite the fact that the REST API documentation says otherwise. What I realized is that you can use the data attribute instead and pass in the tmp_name from the callback from using the fattach controller from the customer portal. 

    Here's a Ruby script (with one dependency that will need to be downloaded) that will let you create an incident with a file upload; my hypothesis was correct and you can use the normal file attachment controller from the customer portal as a work around:

    # dependencies for script
    # the "rest_client" gem is not a native Ruby library
    # you will need to install from the command line
    # using 'gem install "rest_client"'
    # the rest are native Ruby libraries
    require "json"
    require "net/http"
    require "uri"
    require "openssl"
    require "rest_client"
    
    # input your Oracle Service Cloud credentials here
    @username = ENV['OSC_ADMIN'] # => 'username'
    @password = ENV['OSC_PASSWORD'] # =>  'password'
    
    # sets the interface to where you wish to create the incident
    @interface = ENV['OSC_SITE']
    
    # sets the base URL for the site where the incident is going to be created
    @site_url = "https://#{@interface}.custhelp.com"
    
    # put the path to the file you wish to upload
    @file_path = "path/to/file"
    
    # this initializes the file as a Ruby File class
    @file_to_attach = File.new(@file_path,'r')
    
    # Upload the file using the rest_client gem
    @file_attachment_response = RestClient.post("#{@site_url}/ci/fattach/upload", :file => @file_to_attach)
    
    # this is the JSON response from the server with the file attachment info
    @fa_info = JSON.parse(@file_attachment_response.body)
    
    #echos the JSON response from the file system server
    puts @fa_info
    
    # create an empty hash
    @json_content = {}
    
    # assign a hash to the 'primaryContact' key
    @json_content['primaryContact'] = {}
    
    # set the value of the primary contact ID for the incident
    @json_content['primaryContact']['id'] = 236948
    
    # set the value for the subject line of the incident
    @json_content['subject'] = 'Test please delete'
    
    # create an empty array for the file attachment data
    @json_content['fileAttachments'] = []
    
    # input the file attachment data as a hash into the empty array
    @json_content['fileAttachments'][0] = {'fileName' => @fa_info['name'],'name' => @fa_info['name'],'data' => "#{@fa_info['tmp_name']}",'contentType'=>@fa_info['type']}
    
    # parse the URL for the REST API endpoint
    @uri = URI.parse("#{@site_url}/services/rest/connect/v1.3/incidents")
    
    # sets a variable for the Net::HTTP response for post the incident and fileAttachment information above
    response = Net::HTTP.start(@uri.host, @uri.port,
            :use_ssl => true, 
            :verify_mode => OpenSSL::SSL::VERIFY_PEER) do |http|
    
            request = Net::HTTP::Post.new @uri.request_uri
            request.basic_auth @username, @password
            request.content_type = "application/json"
            request.body = JSON.dump(@json_content)
    
            http.request request # Net::HTTPResponse object
    
    end
    
    # will tell you the HTTP response code
    puts response.code
    
    # will tell you the JSON output from the REST API
    puts response.body
    
    

    Hope this helps.

    Rajan

  • Dietrik

    Have a look at the release notes. Attachments are not supported in your version.

    Upgrade to a newer release,

  • Rajan Davis

    Walid,

    In order to upload and attach a file attachment to an incident, you need to have a way to upload the file to the server. You do not need the content-type per se.

    Once you have uploaded the file to the server, you will be given a callback with information as to where the file lives in the temporary file system. From there, you can take that information and save it to the incident.

    There are default widgets that handle this behavior for you; however, the gist of what you need to do is that you need to POST your file upload to the '/ci/fattach/upload' endpoint.

    From there, you should get a callback that looks like the following:

    {
        error:0, 
        name:"filename.PNG", 
        size:32859, 
        tmp_name:"NYfmoqyour-interface.custhelp.com", 
        type:"image/png"
    }
    

    And then when you are submitting the incident, you need to pass the name and the tmp_name from the callback above with your form. I think the default widgets handle this for you.

    Below is an example of workflow that I use for a few custom incident forms where the entire process is custom, asynchronous, and handles files uploads.


    Below is (simplified) code for a custom incident controller that

    1. Makes sure that the session has a valid token for submitting form
    2. Takes the values of the form (including the file upload) and puts them into an object
    3. Passes this object to a custom incident model

    From there, I will get a result with the incident information as far as if the incident creation is successful.

    This allows me to make sure that the information that is passed up from the form is what I am expecting when I create the incident and I can also use this same controller for various incident forms.

    function createIncident(){
    
            // retrieves token saved in session
            $formToken = $this->get_ftok();
    
            // checks to see if f_tok is valid
            if (!AbuseDetection::isAbuse($formToken)) {
    
                // loads the custom model
                $this->load->model('custom/custom_incident_model');
                    
                // parse the form information so that I can get
                // an associative array for values to check against in the model
                $data = array(
                    'contact_id'=>$this->getContactID()->value,
                    'file_upload_tmp_name'=> $this->input->post('file_upload_tmp_name'),
                    'file_upload_name'=> $this->input->post('file_upload_name')
                );
                
                // pass in the info into the custom model create method which
                // will return an associative array of whether or not the 
                // incident was created
                $result = $this->custom_incident_model->create($data);
                
                // make sure the associative array
                // returns as JSON 
                echo json_encode($result);    
    
            }else{
                // if abuse is detected
                // essentially NO-OP
                echo json_encode('stop abusing me');
            }
        }
    
    

    Then it passes the information into a custom model that checks for these values like the following in regards to the file upload information:

    // check if the callback values for a file upload are present
    if($data['file_upload_tmp_name'] && $data['file_upload_name']){
    
        // instantiate an instance of a FileAttachmentIncidentArray class
        $incident->FileAttachments = new RNCPHP\FileAttachmentIncidentArray();
    
        // instantiate an instance of a FileAttachmentIncident class
        $fattach = new RNCPHP\FileAttachmentIncident();
    
        // this method will set the file to be what was saved in the 
        // temporary file system
        $fattach->setFile('/tmp/'.$data['file_upload_tmp_name']);
    
        // Sets the file name from what was called back from the file upload
        $fattach->FileName = $data['file_upload_name'];
    
        // adds the FileAttachmentIncident instance to the FileAttachmentIncidentArray instance
        $incident->FileAttachments[] = $fattach;
    }
    
    

    The only additional information that is required when you create an incident is that you set a primary contact; make sure in addition to a file upload that you are passing in a valid contact ID. In the custom controller code above, I am pulling the ID from the current session. I also have the forms set up such that they are only visible if the customer is logged in.

            $contact_id = $data['contact_id'];
            $incident->PrimaryContact = RNCPHP\Contact::fetch($contact_id);
    
    

    Then you can call

    $incident->save()
    

    which will associate the file attachment to the incident. 

     

    Hopefully this helps clarify a few things.

    Kind Regards,

    Rajan

  • Suresh Thirukoti

    Steve - I have checked now.....it looks like File attachments name is FileAttachments not fileAttachments

    so using below URL I am able to download attachments in .tgz format

    https://UserName:Password@xxxxx.rightnowdemo.com/services/rest/connect/v1.3/{Package}.{ObjectName}/1/FileAttachments?download

    ~Suresh

  • Robert Surujbhan

    Hi Pramod - take a look at the Json.NET library for .NET (aka Newtonsoft.Json - available via the NuGet Package Manager in VS).  Using this, you can create C# classes representing your object and data structure(s), and then functions like JsonConvert.SerializeObject(your_obj) can help serialize them to JSON strings. You can then pass these to a StringContent object for encoding before sending them to a REST service.  It's much easier compared to manual string handling.

  • Rajan Davis

    Hope this helps, but I had the same issue and found my answer from this post.



    I got around this by using a POST request and then adding the following header:



    X-HTTP-Method-Override: PATCH



    It's actually documented in the REST API, but it would be nice if in the documentation for creating objects if they had mentioned this.



    Edit: updated the link because it was broken.

  • Suresh Thirukoti

    You need to iterate and put the values in an array..and use that array for further processing

    $arrayresult = array();

    while ($val = $maxbookingtime->next())

    {

    $arrayresult[] = $val['id'];

    }

    ~Suresh

  • Gursimran Singh Saini

    Hi Nishi

    We have faced this issue as well. That's just the way Rest API is designed.

    You have to execute queryResults or AnalyticsReportResults to check if any Contact with this email address exists or not. If not, you can create a new Contact.

     

    Gursimran

  • Suresh Thirukoti

    Can you check this?

    select * from Incident where createdtime between '2017-02-22T00:00:00Z' and '2017-02-22T23:59:00'

    ~Suresh

  • Pramod Vasudeva Murthy

    I had done a migration project 2 years ago which included migration of 10 lac records of Contact, Incident, Org..

    Here is the method how I achieved:

    • First create data model for all objects - Custom fields, Custom objects, Mailboxes and System attributes
    • Once done - extract all info from source site using standard data extract. If there are 5 lac records extract 1 lac records at a time
    • Start importing from highest level of hierarchy - Org - Contacts- Incident
    • Using OOTB data import you can import 1 lac records(Not sure how it is 10K records)
    • After each import cross verify using report
    • Another big hurdle is matching ID's of Custom menu fields and Standard menu fields. Extarc data and use vlookup in excel it is quite easy
    • Create an additional custom field(called as source_ID) for each object to keep track of associativity of objects in Source site. For eg; In destination site Contact ID might be 345 where as in Source site it will be 123. So store this 123 as custom field value in destination field.
    • Use this source_ID to associate various object. You have to extract data from destination and do vlookup again using source_ID(of destination) and actual source ID
    • Do another update for association accordingly after extracting the data and finding right associativity.

    This needs a little time, patience and alertness to carry out to closure.

    If these steps are tedious use a JAVA program to develop a batch (because of easier logs and batching concepts) and use mutli-threading to quicken the process. Schedule  a batch program using OOTB OS offered schedulers.

    Note: It took me 6 weeks to import data using batch program for all object(running 24 X 7) wink. But later I found out easy ways to achieve this using threads. Hence recommending the same.

    - VIP

  • Scott Harwell

    You could use ROQL and get the incident and thread data in a single call:

    SELECT *, Threads.* FROM Incident WHERE ReferenceNumber = '170206-000000'
    

    Or, threads only:

    SELECT Threads.* FROM Incident WHERE ReferenceNumber = '170206-000000'
    
  • Scott Harwell

    Looks like a memory error from the output that you've provided.  What version of OSvC are you using?  Which version of CPHP are you using?  Are you using external PHP libraries in your PHP code?

    Importing large amount of records (this would fall into that category) through CPHP can be susceptible to memory leaks depending on how you've implemented your script.

    If you move your script from an OSvC server side process to a web-services based process, does the script hit memory issues locally too?  For both recurring and one-time imports, your better option is to use web services than trying to run a custom script through your browser to process data.

  • Scott Harwell

    It appears that you might be confused about how a server side script operates.  The script that you have written attempts to pickup JRRTEST.txt from the same directory that PHP is running on the server.  This, of course, will not have your file since you mentioned that it's on your desktop.  In order for PHP to read the file, it would already have to exist in an accessible folder on the server.

    You shouldn't be running imports from text files through a custom process model in any case.  If you want to import a file from your "desktop" or local PC, write the script so that it runs locally and uses the SOAP or REST API to post the data to the OSVC.

    Also, you're writing logs to the assets folder, which is exposed on the public internet and likely means that you're opening up a security hole for intruders to see what your script does and how to compromise it.  You should not do that.

    What is the purpose of the script and when should it be triggered?  Likely, there is a much better approach to do what you are attempting.

  • Scott Harwell

    Setting the mime type of the image is usually placed in content type, if you are attaching the file (i.e. "image/jpeg").

    If you want to embed it in the HTML, you can base64 encode the image and put it inline in the HTML directly, but that should be done with smaller files.