It sounds like your ACME client is assuming that finalization is going to succeed on the first request. But that’s not always the case. You need to have a finalization loop.
From https://tools.ietf.org/html/rfc8555#section-7.4 ,
If a request to finalize an order is successful, the server will
return a 200 (OK) with an updated order object. The status of the
order will indicate what action the client should take:
o “invalid”: The certificate will not be issued. Consider this
order process abandoned.
o “pending”: The server does not believe that the client has
fulfilled the requirements. Check the “authorizations” array for
entries that are still pending.
o “ready”: The server agrees that the requirements have been
fulfilled, and is awaiting finalization. Submit a finalization
o “processing”: The certificate is being issued. Send a POST-as-GET
request after the time given in the Retry-After header field of
the response, if any.
o “valid”: The server has issued the certificate and provisioned its
URL to the “certificate” field of the order. Download the
So the client needs to behave like this:
- Confirm that the order status is
- Submit the CSR in the finalize call
- Check the status:
a. If it is
processing, wait some time, and check the status again with a POST-as-GET request.
b. if it is
valid, you can download the certificate
c. Any other status is an error and you need to abort