Hello all! I also
wanted to provide a solution for people who use PHP. I hope this helps someone
who might run into problems.
Here an example how
you can access the encoded attachment data by calling the /preDownload
endpoint, decode the attachment payload and process it.
// get the request
$raw_input = file_get_contents('php://input');
$data = json_decode(gzdecode($raw_input), true);
// check if there are attachments
if(!isset($data['attachments']) || empty($data['attachments'])) {
return false;
}
// jwt for Authorization for the preDownload
$jwt_payload = [
'iss' => <MSP_ID>,
'iat' => time()
];
// iterate through all attachments
foreach($this->data['attachments'] as $k => $attachment) {
//get hex encoded signature and convert to base64
$hex_encoded_signature = $attachment['signature'];
$base64_encoded_signature = base64_encode(pack('H*', $hex_encoded_signature));
$predownload_headers = [
"Authorization" => 'Bearer '.utf8_decode(jwt_encode($jwt_payload, base64_decode(<MSP_SECRET>))),
"source-id" => <BUSINESS_CHAT_ID>,
"MMCS-Url" => $attachment['url'],
"MMCS-Signature" => $base64_encoded_signature,
"MMCS-Owner" => $attachment['owner']
];
// get the download url of the attachment
$pre_download_data = json_decode(perform_pre_download($predownload_headers), true);
$download_url = $pre_download_data['download-url'];
// Now that we have the url to download the encrypted payload we have to decode the payload data
// get the encoded file and the key to decode it
$binary = @file_get_contents($download_url);
$decrypted_key = $attachment['key'];
// decode via openssl
$binary = openssl_decrypt(
base64_encode($binary),
"aes-256-ctr",
pack("H*", substr($decrypted_key, 2)),
OPENSSL_ZERO_PADDING,
pack("H*", "00000000000000000000000000000000")
);
// from here on you can access the decoded image and process it in your code
// you can add specific checks to validate the attachments like:
$image = @getimagesizefromstring($binary);
// check for valid mime types
if (empty($image['mime']) && !in_array($image['mime'], ['image/jpeg','image/png', 'image/gif'])) {
continue; // skip this attachment
}
// make sure to store the image on your server since the 'download-url' from the perform_pre_download function will not
// be accessable after some time
file_put_contents(<PATH_TO_THE_FILE>, $binary);
}
// function to access the url where you can get the encoded attachment data
function perform_pre_download($headers) {
//prepare headers
$request_header = [];
//parse headers
foreach($headers as $k => $v) {
$request_header[] = $k.': '.$v;
}
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, <URL_TO_PREDOWNLOAD_ENDPOINT>);
curl_setopt($ch, CURLOPT_HTTPHEADER, $request_header);
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_TIMEOUT, 5);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
// get response body
$return = curl_exec($ch);
// end curl request
curl_close($ch);
return $return;
}
// create jwt token
function jwt_encode(array $payload, string $secret):string
{
$header = encode_base64_url_safe(json_encode(['typ' => 'JWT', 'alg' => 'HS256']));
$payload = encode_base64_url_safe(json_encode($payload));
$signature = encode_base64_url_safe(hash_hmac('sha256', $header.'.'.$payload, $secret, true));
return $header.'.'.$payload.'.'.$signature;
}