Il est possible d'envoyer un message via les API GraphQL. Mais avant cela, voici un petit tour d'horizon du fonctionnement :
3 étapes :
1. Vous demandez a notre API une authorisation pour uploader un fichier sur notre object storage.
Cette requete implique de décrire le fichier que vous allez envoyer : le filename, byteSize, checksum (un digest md5, base64digesté) et son contenu. Ceci pour nous permettre de valider que nous echangeons le meme fichier, qu'il n'a pas été altéré etc.. Nous vous renvoyons :
les crédentials pour communiquer avec notre object storage
l'identifiant du fichier (blob_signed_id) a utiliser dans une autre requete pour le lier à une autre mutation
2. Vous uploadez le fichier sur notre object storage, en réutilisant les crédentials de la 1ere requete
3. Vous, client, faites une requete pour lier ce fichier (maintenant sur nos serveurs, identifié par le signed_blob_id) a un message
1ere étape : demander les crédentials
Utiliser la mutation createDirectUpload. Voici un exemple complet de script que vous pouvez executer :
FILE=./file.txt \
FILE_TYPE="text/plain" \
API_TOKEN="VOTRE_TOKEN" \
DOSSIER_ID="un identifiant de dossier, cf: dossiers.id (ce n'est pas le numero de dossier)" \
ruby ./get_credentials.rb
get_credentials.rb
require 'net/http'
require 'uri'
require 'json'
require 'byebug'
require 'digest'
ENDPOINT = URI('https://www.demarches-simplifiees.fr/api/v2/graphql')
QUERY_UPLOAD_REQUEST = "
mutation createDirectUpload($input: CreateDirectUploadInput!) {
createDirectUpload(input: $input) {
directUpload {
url
headers
blobId
signedBlobId
}
}
}
"
### that's the HTTP part
# open an http connexion to our GraphQL endpoint
def open_http_connection
http = Net::HTTP.new(ENDPOINT.host, ENDPOINT.port)
if ENDPOINT.scheme == 'https'
http.use_ssl = true
http.verify_mode = OpenSSL::SSL::VERIFY_NONE
end
http
end
# the headers of our http query, include auth
def request_headers
{
"Content-Type" => "application/json",
"Authorization" => "Bearer #{ENV.fetch('API_TOKEN') { raise 'missing env var API_TOKEN=xxx' }}"
}
end
def compute_checksum_in_chunks(io)
Digest::MD5.new.tap do |checksum|
while (chunk = io.read(5242880))
checksum << chunk
end
io.rewind
end.base64digest
end
def request_direct_upload_credentials(http, file)
data = {
"query" => QUERY_UPLOAD_REQUEST,
"operationName" => "createDirectUpload",
"variables" => {
"input" => {
"dossierId" => ENV.fetch("DOSSIER_ID") { raise "missing env var DOSSIER_ID=xxx" },
"filename" => file.path,
"byteSize" => file.size,
"checksum" => compute_checksum_in_chunks(file),
"contentType" => ENV.fetch("FILE_TYPE") { raise 'missing file type' }
}
}
}
pp "SENT DATA : #{data.inspect}"
req = Net::HTTP::Post.new(ENDPOINT, request_headers)
req.body = data.to_json
http.request(req)
end
fp = ENV.fetch('FILE') { raise 'missing env var FILE' }
File.open(fp, 'r') do |file|
http = open_http_connection
response = request_direct_upload_credentials(http, file)
body = JSON.parse(response.body)
puts body.inspect
credentials = body['data']['createDirectUpload']['directUpload']
credentials_headers = JSON.parse(credentials['headers'])
puts <<~CURL
curl -vvv \
--data-binary @#{file.path} \
-X PUT \
-H "Content-Type: #{credentials_headers['Content-Type']}" \
-H "ETag: #{credentials_headers['ETag']}" \
"#{credentials['url']}"
CURL
end
Aussi notre script echo un exemple pour uploader le fichier via curl, il vous suffit de le copier/coller pour envoyer le même fichier sur notre object storage
2eme étape : Uploader le fichier en utilisant les crédentials
curl -vvv --data-binary @./file.txt -X PUT -H "Content-Type: LE type de votre fichier" -H "ETag: LAVALEUR PRESENTE DANS LA REPONSE, au niveau de headers.etag [attention, c'est un json a parser]" "data[createDirectUpload][directUpload][url]"
3eme étape : Associer ce fichier lors d'un envoie de message à un usager.
En préambule, il vous faut envoyer ce message au nom d'un instructeur, nous vous renvoyons à la documentation pour lister les id des instructeurs.
Utiliser la mutation dossierEnvoyerMessage. Voici un exemple complet de script que vous pouvez executer :
API_TOKEN="VOTRE TOKEN" DOSSIER_ID="L'ID DU DOSSIER (faire comme pour les instructeur)" INSTRUCTEUR_ID="L'ID de l'instructeur" SIGNED_BLOB_ID="le signed_blob id de la reponse a votre mutation de createDirectUpload de l'etape 1 " ruby send_message_with_uploaded_file.rb
send_message_with_uploaded_file.rb
require 'net/http'
require 'uri'
require 'json'
require 'byebug'
ENDPOINT = URI('https://www.demarches-simplifiees.fr/api/v2/graphql')
QUERY = "
mutation dossierEnvoyerMessage($input: DossierEnvoyerMessageInput!) {
dossierEnvoyerMessage(input: $input) {
message {
body
}
errors {
message
}
}
}
"
### that's the HTTP part
# open an http connexion to our GraphQL endpoint
def open_http_connection
http = Net::HTTP.new(ENDPOINT.host, ENDPOINT.port)
if ENDPOINT.scheme == 'https'
http.use_ssl = true
http.verify_mode = OpenSSL::SSL::VERIFY_NONE
end
http
end
# the headers of our http query, include auth
def request_headers
{
"Content-Type" => "application/json",
"Authorization" => "Bearer #{ENV.fetch('API_TOKEN') { raise 'missing env var API_TOKEN=xxx' }}"
}
end
def send_message_and_attach_prior_uploaded_file(http)
data = {
"query" => QUERY,
"operationName" => "dossierEnvoyerMessage",
"variables" => {
"input" => {
"dossierId" => ENV.fetch('DOSSIER_ID') { raise 'missing env var DOSSIER_ID' },
"instructeurId" => ENV.fetch('INSTRUCTEUR_ID') { raise 'missing env var INSTRUCTEUR_ID' },
"body" => "pouf pouf un pouf autre message",
"attachment" => ENV.fetch('SIGNED_BLOB_ID') { raise 'missing SIGNED_BLOB_ID env var' }
}
}
}
req = Net::HTTP::Post.new(ENDPOINT, request_headers)
req.body = data.to_json
response = http.request(req)
pp JSON.parse(response.body)
end
http = open_http_connection
puts send_message_and_attach_prior_uploaded_file(http)