@@ -262,6 +262,9 @@ public async Task<EnrollmentResult> Enroll(
262262 // Create order
263263 var order = await acmeClient . CreateOrderAsync ( identifiers , null ) ;
264264
265+ _logger . LogInformation ( "Order created. OrderUrl: {OrderUrl}, Status: {Status}" ,
266+ order . OrderUrl , order . Payload ? . Status ) ;
267+
265268 // Store pending order immediately
266269 var accountId = accountDetails . Kid . Split ( '/' ) . Last ( ) ;
267270
@@ -271,26 +274,33 @@ public async Task<EnrollmentResult> Enroll(
271274 // Finalize with original CSR bytes
272275 order = await acmeClient . FinalizeOrderAsync ( order , csrBytes ) ;
273276
277+ // Extract order identifier (path only) for database storage
278+ var orderIdentifier = ExtractOrderIdentifier ( order . OrderUrl ) ;
279+
274280 // If order is valid immediately, download cert
275281 if ( order . Payload ? . Status == "valid" && ! string . IsNullOrEmpty ( order . Payload . Certificate ) )
276282 {
277283 var certBytes = await acmeClient . GetCertificateAsync ( order ) ;
278284 var certPem = EncodeToPem ( certBytes , "CERTIFICATE" ) ;
279285
286+ _logger . LogInformation ( "✅ Enrollment completed successfully. OrderUrl: {OrderUrl}, CARequestID: {OrderId}, Status: GENERATED" ,
287+ order . OrderUrl , orderIdentifier ) ;
288+
280289 return new EnrollmentResult
281290 {
282- CARequestID = order . Payload . Finalize ,
291+ CARequestID = orderIdentifier ,
283292 Certificate = certPem ,
284293 Status = ( int ) EndEntityStatus . GENERATED
285294 } ;
286295 }
287296 else
288297 {
289- _logger . LogInformation ( "⏳ Order not valid yet — will be synced later. Status: {Status}" , order . Payload ? . Status ) ;
298+ _logger . LogInformation ( "⏳ Order not valid yet — will be synced later. OrderUrl: {OrderUrl}, CARequestID: {OrderId}, Status: {Status}" ,
299+ order . OrderUrl , orderIdentifier , order . Payload ? . Status ) ;
290300 // Order stays saved for next sync
291301 return new EnrollmentResult
292302 {
293- CARequestID = order . Payload . Finalize ,
303+ CARequestID = orderIdentifier ,
294304 Status = ( int ) EndEntityStatus . FAILED ,
295305 StatusMessage = "Could not retrieve order in allowed time."
296306 } ;
@@ -314,6 +324,34 @@ public async Task<EnrollmentResult> Enroll(
314324
315325
316326
327+ /// <summary>
328+ /// Extracts the order path from the full ACME order URL for use as a unique identifier.
329+ /// This removes the scheme, host, and port, keeping only the path portion.
330+ /// </summary>
331+ /// <param name="orderUrl">Full order URL (e.g., https://dv.acme-v02.api.pki.goog/order/ABC123)</param>
332+ /// <returns>Order path without leading slash (e.g., "order/ABC123")</returns>
333+ /// <example>
334+ /// Input: "https://dv.acme-v02.api.pki.goog/order/IlYl06mPl5VcAQpx3pzR6w"
335+ /// Output: "order/IlYl06mPl5VcAQpx3pzR6w"
336+ /// </example>
337+ private static string ExtractOrderIdentifier ( string orderUrl )
338+ {
339+ if ( string . IsNullOrWhiteSpace ( orderUrl ) )
340+ return orderUrl ;
341+
342+ try
343+ {
344+ var uri = new Uri ( orderUrl ) ;
345+ // Remove leading slash and return the path
346+ return uri . AbsolutePath . TrimStart ( '/' ) ;
347+ }
348+ catch ( Exception )
349+ {
350+ // If URL parsing fails, return the original (shouldn't happen with valid ACME URLs)
351+ return orderUrl ;
352+ }
353+ }
354+
317355 /// <summary>
318356 /// Extracts the domain name from X.509 subject string
319357 /// </summary>
0 commit comments