Skip to Content
Technical Articles

SAP Concur – Blog 1 – Interfacing is interesting

This could be an interesting blog explaining the interface from SAP purchase orders to Concur.  We are on-premise.  Keep that in mind because it does make a difference.

I plan to write more blogs as I accomplish something in Concur.  Why?  Because I’ve been struggling a bit to find answers.  I can share as I go.  That way I don’t forget my struggles.

Before I start here are some great links:

SAP Concur Development Center – really it gives basic information and the API format.

SAP API Business Hub for Concur Invoice – it has a lot of the API information for everything Invoicing.  So yes, the purchase order API was here as well.

Postman

If you don’t have it downloaded you should.   This just makes everything go easier.  It is the ultimate testing tool.  You can start with the required fields and gradually add to it until all your fields are loading to Concur – or some fields are not available.   I’ll get back to that shortly as that was a challenge for me.

It does depend on how you are going to set up your integration to Concur.  So you’ll get all the information you need from Concur.   We decided to connect using an API and not the add-on.  This one will come up shortly too.

Version of Concur

It does matter which version of Concur you have purchased.   You lose some functionality when you purchase the standard version.  One of the huge differences is no development client.  Yes, you read right.  At the time my company purchased Concur there was no development client/box for us – we have the standard version.  It will make supporting it hard.  But hey, we are just in the implementation phase.

Interesting Issues

If you purchase the standard version, and you look at the APIs.  All of the fields are not available.  So you gradually find out which ones are available by starting (for me) in Postman.  Only send the required fields and then add them one at a time.  There will be errors when you can’t use a field.

At the time of writing this – if you are on standard, these fields can’t be passed via the API.  Thee are probably more.  These are just some of the fields we wanted to use.

Header:
AmountWithoutVat,
DiscountPercentage,
DiscountTerms,
IsTest,
Requestedby

Line:
AmountWithoutVat,
RequestedDeliveryDate

 

API vs. SAP Add-on for Concur

Again at the time of writing this document, Concur did not support the Invoice add-ons.  That includes the purchase order available in the add-on.   No it might be different if you are only doing travel and expense.  That app has been around a lot longer than the invoice one.

So you can save yourself some time.  Ask your Concur person what you can use before thinking you hit a really good solution.

Good vs. Bad

So now you’ve seen some of my issues.  This does not me “don’t buy Concur”.  This means things to look at when you buy Concur.

The longer we move forward with the project, it looks pretty cool.

Tech Stuff:

I’m on 1709 on-premise.  I had a lot of different ways I could have called the APIs.  I decided to simply use the class.  I know, I know, I could have done this a lot differently.  However, I needed to get started quickly.

So here are some code snippets. And yes, I did a lot of clean up of our data to get this to work.  These will run during BADIs so the API process starts fairly quickly.   It may / may not be a good way to do it for you.   We do not have a ton of purchase order creations daily.

I sent over the data in JSON format.  This was an awesome class to use

    loop at lt_abap_in-line_item into ls_line.
      condense: ls_line-account_code, ls_line-create_date, ls_line-external_id,
                ls_line-line_number, ls_line-quantity, ls_line-supplier_part_id,
                ls_line-unit_price.
      modify lt_abap_in-line_item from ls_line.
      endloop.
    lv_json = /ui2/cl_json=>serialize( data = lt_abap_in
                                       compress = /ui2/cl_json=>C_BOOL-true
                                       pretty_name = /ui2/cl_json=>pretty_mode-camel_case
                                       assoc_arrays = abap_false ).

I did find out that if I didn’t condense my fields, they were going into the json class and a space was at the end.  That caused issues on the Concur side.

Next I started to send my data:

* Verify a valid token only used for an hour
    check_token( ).

    CALL METHOD cl_http_client=>create_by_url
      EXPORTING
        url                = iv_url
      IMPORTING
        client             = DATA(lo_http_client)
      EXCEPTIONS
        argument_not_found = 1
        plugin_not_active  = 2
        internal_error     = 3
        OTHERS             = 4.

Check_token verified if there was a token already being used.   If there wasn’t one was retrieved.

    cl_http_client=>create_by_url(
         EXPORTING
           url                = lv_url
         IMPORTING
           client             = DATA(http_client)
         EXCEPTIONS
           argument_not_found = 1
           plugin_not_active  = 2
           internal_error     = 3
           OTHERS             = 4 ).
    IF sy-subrc <> 0.
      RAISE url_not_created.
    ENDIF.


    http_client->propertytype_accept_cookie = if_http_client=>co_enabled.
    CALL METHOD http_client->request->set_header_field
      EXPORTING
        name  = '~request_method'
        value = 'POST'.

The token is good for one hour.  Next you send all your credentials.

Here is where I sent the token in the header of the request.

    DATA: value TYPE string.
    CONCATENATE 'Bearer' gv_token INTO value SEPARATED BY ' '.
    lo_http_client->request->set_header_field(
          EXPORTING
            name  = 'Authorization'
            value = value ).

To end it out – I sent the data and retrieved the response – Yes, I’m not done putting error checking into my code.

    lo_http_client->receive(
     EXCEPTIONS
       http_communication_failure = 1
       http_invalid_state         = 2
       http_processing_failed     = 3 ).
    IF sy-subrc <> 0.
*      RAISE receive.
    ENDIF.

    ex_result = lo_http_client->response->get_cdata( ).
    lo_http_client->response->get_status( IMPORTING code = gv_code
                                                    reason = gv_reason ).

 

And that’s it!   Well I did a lot of changes to our data before I sent it.   We use conditions for things other than shipping and the invoice can come in at different times for different vendors. There were other things as well.  Things we had to change on the SAP side so that it would integrate with the Concur side.

So it’s a very long blog.   AND if you are on-cloud version of SAP.   I believe they have the interfaces done for you.  And it becomes more of a configuration mapping.

I can’t wait to have everything set up.  Then I can really see how it works out!

Now go!!!  If you have a better way to do this, please comment and I’ll learn.  If any of the information in here is incorrect, please comment.   And well…  Comment for anything you want to comment about.

Be the first to leave a comment
You must be Logged on to comment or reply to a post.