我正在尝试连接到 Azure 通信 API 以使用 REST 终结点发送 SMS 消息。
API 说明的链接位于:https://learn.microsoft.com/en-us/azure/azure-app-configuration/rest-api-authentication-hmac
我的PHP代码如下:
public static function send(array $phoneNumbers, string $message)
{
$body = json_encode([
'from' => config("azure.sms_phone_number"),
'message' => $message,
'smsRecipients' => array_map(fn ($num) => ['to' => $num], $phoneNumbers)
]);
$endpoint = parse_url(config("azure.sms_endpoint"));
$headers = [
'Date' => gmdate("D, d M y H:i:s T"),
'host' => $endpoint['host'],
'x-ms-content-sha256' => base64_encode(hash('sha256', $body, true)),
'Content-Type' => 'application/json',
'Accept' => '*/*'
];
$stringToSign = utf8_encode("POST\n" . $endpoint['path'] . "?" . $endpoint['query'] . "\n" . implode(";", array_values($headers)));
$headers['Authorization'] = implode("&", [
"HMAC-SHA256 Credential=" . config("azure.sms_key_id"),
"SignedHeaders=" . implode(";", array_keys($headers)),
'Signature=' . base64_encode(hash_hmac('sha256', $stringToSign, base64_decode(config("azure.sms_key")), true))
]);
$client = new Client();
$client->post(config("azure.sms_endpoint"), [
'headers' => $headers,
'body' => $body,
'debug' => true
]);
}
下面是一些变量
$body = '{"from":"+1844295xxx","message":"hi","smsRecipients":[{"to":"2019160xxx"}]};';
$stringToSign = 'POST
/sms?api-version=2021-03-07
Mon, 14 Mar 22 17:09:17 GMT;testxxxxxx.communication.azure.com;UXoK8141pppkVedAkc+eSQBqKOWciyoiq+AG/xxxxxx=;application/json;*/*;';
$headers =
(
[Date] => Mon, 14 Mar 22 17:09:17 GMT
[host] => testxxxxx.communication.azure.com
[x-ms-content-sha256] => UXoK8141pppkVedAkc+eSQBqKOWciyoiq+AG/xxxxxx=
[Content-Type] => application/json
[Accept] => */*
[Authorization] => HMAC-SHA256 Credential=primaryKey&SignedHeaders=Date;host;x-ms-content-sha256;Content-Type;Accept&Signature=R8M7+fODzXaxXHbdcV5CHXiEq5R/7Fvd9VGYxxxxxxx=
)
我得到的结果是这样的:
Client error: `POST https://test.communication.azure.com/sms?api-version=2021-03-07` resulted in a `401 Unauthorized` response:
{"error":{"code":"Denied","message":"Given value does not match HMAC header structure."}}
访问 key 和名称来自此命令:
PS C:\Users\manko> az communication list-key --name scotttestingsms --resource-group smsresourcegroup
{
"primaryConnectionString": "endpoint=https://scotttestingsms.communication.azure.com/;accesskey=E7lrdL/yyg/snSO++rbaZMEUF/bC5/0R9XBVGcFclt3fEN/MpWRb5kHB9t59NLtek9xsUYXHyAXxxxxxxx==",
"primaryKey": "E7lrdL/yyg/snSO++rbaZMEUF/bC5/0R9XBVGcFclt3fEN/MpWRb5kHB9t59NLtek9xsUYXHyAXxxxxxx==",
"secondaryConnectionString": "endpoint=https://scotttestingsms.communication.azure.com/;accesskey=IIK094eGVfkNG0uFii/32j+HVsEHJ4/QUOx06TVsqwLub7A/cv1AKKnkkZQbKiJKMn/KRx9o1biWQ5txxxxxx==",
"secondaryKey": "IIK094eGVfkNG0uFii/32j+HVsEHJ4/QUOx06TVsqwLub7A/cv1AKKnkkZQbKiJKMn/KRx9o1biWQ5txxxxxx=="
}
最佳答案
花了相当长的时间进行试验和错误,但下面的代码可以工作。请参阅 https://learn.microsoft.com/en-us/azure/communication-services/tutorials/hmac-header-tutorial 了解更多信息。
use GuzzleHttp\Client;
public static function send(array $phoneNumbers, string $message)
{
$body = [
'from' => config("azure.sms_phone_number"),
'message' => $message,
'smsRecipients' => array_map(fn ($num) => ['to' => $num], $phoneNumbers)
];
$endpoint = parse_url(config("azure.sms_endpoint"));
$headers = [
'Date' => gmdate("D, d M Y H:i:s T"),
'host' => $endpoint['host'],
'x-ms-content-sha256' => base64_encode(hash('sha256', json_encode($body), true)),
];
$stringToSign = utf8_encode(implode("\n", [
"POST",
$endpoint['path'] . "?" . $endpoint['query'],
implode(";", array_values($headers))
]));
$headers['Authorization'] = implode("&", [
"HMAC-SHA256 SignedHeaders=" . implode(";", array_keys($headers)),
'Signature=' . base64_encode(hash_hmac('sha256', $stringToSign, base64_decode(config("azure.sms_key")), true))
]);
$client = new Client(); // <-- this is guzzle
$response = $client->post(config("azure.sms_endpoint"), [
'headers' => $headers,
'json' => $body
]);
}
您只需要三条数据。
config("azure.sms_phone_number")
是原始电话号码。它必须是 E.164 格式,例如“+12024561414”config("azure.sms_endpoint")
是完整端点,例如“https://test.communication.azure.com/sms?api-version=2021-03-07”config("azure.sms_key")
是从 Azure 门户以 Base64 格式复制的应用程序 key ,例如“E7lrdL/yyg/snSO++rbaZMEUF/d1G/0R9XBVGch0tq3xxxxxxxxxxxx==”
关于php - PHP 中的 Azure REST Api 给出 "Given value does not match HMAC header structure",我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/71439439/