# Custom implementation [Back](../../readme.md) ***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`` - This contains the api routes. You can have more explications on different routes in [docs/usages/custom/routes.md](custom/routes.md). ## 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](http://www.faqs.org/rfcs/rfc3986.html). 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×tamp=2021- 12-29%2021%3A10%3A31 This string will be used to calculate our signature using [hmac, rfc2104](http://www.faqs.org/rfcs/rfc2104.html) 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](https://www.rfc-editor.org/rfc/rfc4627) instead of [RFC-8259](https://www.rfc-editor.org/rfc/rfc8259) 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](#prerequisite)