Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added support for retrieving certificates when asynchronous order finalization is enabled on the ACME server-side. #64

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
54 changes: 46 additions & 8 deletions src/Client.php
Original file line number Diff line number Diff line change
Expand Up @@ -157,14 +157,17 @@ public function getOrder($id): Order
$domains[] = $identifier['value'];
}

$certificate = (!empty($data['certificate'])) ? $data['certificate'] : '';

return new Order(
$domains,
$url,
$data['status'],
$data['expires'],
$data['identifiers'],
$data['authorizations'],
$data['finalize']
$data['finalize'],
$certificate,
);
}

Expand Down Expand Up @@ -311,10 +314,11 @@ public function validate(Challenge $challenge, int $maxAttempts = 15): bool
* Return a certificate
*
* @param Order $order
* @param int $maxAttempts
* @return Certificate
* @throws \Exception
*/
public function getCertificate(Order $order): Certificate
public function getCertificate(Order $order, int $maxAttempts = 15): Certificate
{
$privateKey = Helper::getNewKey($this->getOption('key_length', 4096));
$csr = Helper::getCsr($order->getDomains(), $privateKey);
Expand All @@ -329,15 +333,34 @@ public function getCertificate(Order $order): Certificate
);

$data = json_decode((string)$response->getBody(), true);
$certificateResponse = $this->request(
$data['certificate'],
$this->signPayloadKid(null, $data['certificate'])
);
$chain = $str = preg_replace('/^[ \t]*[\r\n]+/m', '', (string)$certificateResponse->getBody());

$chain = '';

if (!empty($data['certificate'])) {
$chain = $this->getCertificateChain($data['certificate']);
} else {
if ('processing' == $data['status']) {
sleep(ceil(15 / $maxAttempts));
do {
$order = $this->getOrder($order->getId());

if ('valid' == $order->getStatus()) {
$chain = $this->getCertificateChain($order->getCertificate());
break;
}

$maxAttempts--;
} while ($maxAttempts > 0);
}
}

if (empty($chain)) {
throw new \Exception('Could not obtain certificate');
}

return new Certificate($privateKey, $csr, $chain);
}


/**
* Return LE account information
*
Expand All @@ -362,6 +385,21 @@ public function getAccount(): Account
return new Account($data['contact'], $date, ($data['status'] == 'valid'), $data['initialIp'], $accountURL);
}

/**
* Return certificate chain
*
* @param string $certificate
* @return string
*/
private function getCertificateChain($certificate): string
{
$certificateResponse = $this->request(
$certificate,
$this->signPayloadKid(null, $certificate)
);
return preg_replace('/^[ \t]*[\r\n]+/m', '', (string)$certificateResponse->getBody());
}

/**
* Returns the ACME api configured Guzzle Client
* @return HttpClient
Expand Down
19 changes: 18 additions & 1 deletion src/Data/Order.php
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,11 @@ class Order
*/
protected $finalizeURL;

/**
* @var string
*/
protected $certificate;

/**
* @var array
*/
Expand All @@ -50,6 +55,7 @@ class Order
* @param array $identifiers
* @param array $authorizations
* @param string $finalizeURL
* @param string $certificate
* @throws \Exception
*/
public function __construct(
Expand All @@ -59,7 +65,8 @@ public function __construct(
string $expiresAt,
array $identifiers,
array $authorizations,
string $finalizeURL
string $finalizeURL,
string $certificate = '',
) {
//Handle the microtime date format
if (strpos($expiresAt, '.') !== false) {
Expand All @@ -72,6 +79,7 @@ public function __construct(
$this->identifiers = $identifiers;
$this->authorizations = $authorizations;
$this->finalizeURL = $finalizeURL;
$this->certificate = $certificate;
}


Expand Down Expand Up @@ -138,6 +146,15 @@ public function getFinalizeURL(): string
return $this->finalizeURL;
}

/**
* Returns certificate
* @return string
*/
public function getCertificate(): string
{
return $this->certificate;
}

/**
* Returns domains for the order
* @return array
Expand Down