ldc-crm-client/docs/usages/custom.md
Alexis Gousseau 1f42c1a4d8 client v4
2023-09-11 16:19:10 +02:00

8.3 KiB

Custom implementation

Back

PLEASE NOTE: This should not be ever implemented on client side js lib or any. Doing this you will allow access all you clients data and make a security breach. You api secret shall remain secret. At your request it can be regenerated.

The service provided is a restful api. The access is pretty simple but remains secured as possible. Make sure you read all of the sections as you handle api errors correctly. The two steps you may achieve are

  • Authenticate to the api correctly
  • Implement a correct usage of each available calls you need.

Prerequisite

From here you will learn how to consume data from LDC CRM. The prerequisite are still the same. You will need a service token and password. The endpoint remains the same https://ldc-crm.ldc.fr.


There are multiple calls you can make but you will need to get some informations from this repo.

  • From file apiConfig.readonly.json

    • version: Use this as a landmark, if version evolves you may hear from us warning changes. As a matter effect from here only security updates may be applied. Any major changes may be discussed with partners.
    • timestampTimeout: This value is in seconds and means that if your call cannot reach us until this delay it will not be accepted.
    • apiRequestRatePerMinute: This is the threshold per minutes that will trigger throttling, thus your request may be refused.
    • servicesDBCache: This value you can just ignore it.
  • From file src/routes.json

Authentication

The system used is completely restful. It prevents timing attacks, replay attacks (in a time lap), man in the middle attacks. We choose to adopt a system like Amazon web service uses https://docs.aws.amazon.com/AmazonSimpleDB/latest/DeveloperGuide/HMACAuth.html

We consider this to be enough as the point the actual CRM is, also with regard to the financial resources available to LDC.

How to create a signature ?

You will need to assemble information on your request.

  • The URL including scheme, host and path (eg: https://ldc-crm.fr/customer/1)

  • Http method in lowercase (eg: get)

  • Parameters

    All request must be sent as www/url-encoded. Also parameters you have to collect here must be flattened joined with dots. example:

      'code_on_pack',
      'code_unique',
      'label_type_support',
      'operation',
      'order_date',
      'support_code',
      'type',
      'deliver.firstname',
      'deliver.lastname',
      'deliver.email',
      'deliver.address',
      'deliver.address2',
      'deliver.city',
      'deliver.postcode',
      'deliver.phone' 
    

    Then have to be sorted by natural order eg:

      'code_on_pack',
      'code_unique',
      'deliver.address',
      'deliver.address2',
      'deliver.city',
      'deliver.email',
      'deliver.firstname',
      'deliver.lastname',
      'deliver.phone',
      'deliver.postcode',
      'label_type_support',
      'operation',
      'order_date',
      'support_code',
      'type'
    

    Notes: To these parameters you must add two things your service token and a timestamp.

    eg:

    • bearer_token=cc82d97eb7235812f5cc1561ddcd64969
    • timestamp=2021-12-29 21:10:31

    Time stamp must have this format Y-m-d H:i:s as a classic DateTime. This will serve as nonce making harder to guess data obfuscated with ssl.

    After this you will have to concatenate all parameters names with their values using = then all parameters between them using char &. Note that each parameter key and value must be url encoded according rfc3986.

    Finally you will have to concatenate those 3 items, uri, method and parameters with \n. eg:

      http://127.0.0.1/api/v4/arcadia/outgoing-mail/default\n
      post\n
      bearer_token=cc82d97eb7235812f5cc1561ddcd64969
      4810e56&deliver.address=94%2C%20chemin%20de%20
      Hamon%0A79344%20Bonnin&deliver.address2=&
      deliver.city=Blanchet&deliver.email=danielle
      42%40gmail.com&deliver.firstname=Marianne&
      deliver.lastname=Morvan&deliver.phone=01%2043%20
      53%2013%2073&deliver.postcode=92%20197&label_
      type_support=Fond%20carte%20Aimant%C3%A9&
      operation=16&order_date=2021%2F12%2F29%2022
      %3A10%3A31&order_num=23&package_unit_weight=0&
      state_order=0&support_code=1&timestamp=2021-
      12-29%2021%3A10%3A31
    

    This string will be used to calculate our signature using hmac, rfc2104 method with algo sha256, the result will be binary encode as base64.

    PHP

      base64_encode(hash_hmac(
          'sha256',
          $concatRequestString,
          $servicePassword,
          true
      ));
    

    ASP.NET

      var secretKeyByteArray = Convert.FromBase64String(APIKey);
    
      byte[] signature = Encoding.UTF8.GetBytes(signatureRawData);
    
      using (HMACSHA256 hmac = new HMACSHA256(secretKeyByteArray))
      {
          byte[] signatureBytes = hmac.ComputeHash(signature);
          string requestSignatureBase64String = Convert.ToBase64String(signatureBytes);
      }
    

    JAVA

      byte[] secretKey = "bearer_pwd".getBytes("UTF-8");
      byte[] message = "https://ldc-crm.fr\nget\n....".getBytes("UTF-8")
      byte[] hmacSha256 = null;
      String base64HmacSha256 = '';
      try {
          Mac mac = Mac.getInstance("HmacSHA256");
          SecretKeySpec secretKeySpec = new SecretKeySpec(secretKey, "HmacSHA256");
          mac.init(secretKeySpec);
          hmacSha256 = mac.doFinal(message);
          base64HmacSha256 = Base64.getEncoder().encodeToString(hmacSha256);
      } catch (Exception e) {
          throw new RuntimeException("Failed to calculate hmac-sha256", e);
      }
    

This way your request will be able to pass checks, also to be authenticated since you give your api token we now which data you may be served with. Details about how to implement this is up to you after that. If your request is not accepted you will always have details about what is wrong.

Mandatory parameters for all requests

Every request except apiV4.ping needs a signature parameter. Some you have to provide foreach each request bearer_token, timestamp, signature. Also only request.

HTTP CONTENT-TYPE

Every request have to be json_encoded. The crm will only handle json requests and also respond only in json. No other ways are handled at this time. This means your requests will need to have two HTTP headers

  • Accept: application/json
  • Content-Type: application/json Of course body will have to be encoded as json to be a valid request. Minimal body content shall be {}, [] following RFC-4627 instead of RFC-8259 witch is the actual "Internet Standard" as marked from 2017.

Handling Errors

All responses will be constants, this means you will always find a json array which contains :

[
    'status': 'OK' or 'KO',
    'data': [],
    'version': '3.0.0' // status version
]

So having to handle error you will find

[
    'status': 'KO'
    'data': [
        'code': xxx, // integer
        'message': 'error message text'
    ]
    'version': '3.0.0'
]

You may find all types of error message in src/Enums/ApiError.php, this file contains detailed description of many errors, so we won't detail them in here.

In general you may catch http error code 500 which is a general error of course.

You may also have errors that are not covered in the ApiError doc. This could happen even if all code of crm is tested, we encourage you to have a log supervision of your project.

You may use errors messages to display in your app. As for example the validationFailed error will always contain detailed information about why your request was rejected. This information will be in french language and could be displayed directly to your users. How ever you could also wrap all of this using only the error code.

Routes

Please refer to the Prerequisite section