private function doPost($resource, array $payload)
{
if (!is_string($resource)) {
throw new InvalidArgumentException(sprintf("\$resource must be of type string, %s given.", gettype($resource)));
}
$privateKey = openssl_pkey_get_private($this->keyPair->getPrivate());
$details = openssl_pkey_get_details($privateKey);
if ($details["type"] !== OPENSSL_KEYTYPE_RSA) {
throw new \RuntimeException("Only RSA keys are supported right now.");
}
$uri = (yield $this->getResourceUri($resource));
$attempt = 0;
do {
$attempt++;
if ($attempt > 3) {
throw new AcmeException("POST request to {$uri} failed, received too many badNonce errors.");
}
$enc = new Base64UrlSafeEncoder();
$jws = new SimpleJWS(["alg" => "RS256", "jwk" => ["kty" => "RSA", "n" => $enc->encode($details["rsa"]["n"]), "e" => $enc->encode($details["rsa"]["e"])], "nonce" => (yield $this->getNonce($uri))]);
$payload["resource"] = isset($payload["resource"]) ? $payload["resource"] : $resource;
$jws->setPayload($payload);
$jws->sign($privateKey);
$request = (new Request())->setMethod("POST")->setUri($uri)->setBody($jws->getTokenString());
try {
/** @var Response $response */
$response = (yield $this->http->request($request));
$this->saveNonce($response);
if ($response->getStatus() === 400) {
$info = json_decode($response->getBody());
if ($info && isset($info->type) && ($info->type === "urn:acme:badNonce" or $info->type === "urn:acme:error:badNonce")) {
continue;
}
}
} catch (Throwable $e) {
throw new AcmeException("POST request to {$uri} failed: " . $e->getMessage(), null, $e);
} catch (Exception $e) {
throw new AcmeException("POST request to {$uri} failed: " . $e->getMessage(), null, $e);
}
(yield new CoroutineResult($response));
return;
} while (true);
}