func (h *Handler) NewOrder(w http.ResponseWriter, r *http.Request) {
	ctx := r.Context()
	acc, err := accountFromContext(ctx)
	if err != nil {
		api.WriteError(w, err)
		return
	}
	prov, err := provisionerFromContext(ctx)
	if err != nil {
		api.WriteError(w, err)
		return
	}
	payload, err := payloadFromContext(ctx)
	if err != nil {
		api.WriteError(w, err)
		return
	}
	var nor NewOrderRequest
	if err := json.Unmarshal(payload.value, &nor); err != nil {
		api.WriteError(w, acme.WrapError(acme.ErrorMalformedType, err,
			"failed to unmarshal new-order request payload"))
		return
	}
	if err := nor.Validate(); err != nil {
		api.WriteError(w, err)
		return
	}
	now := clock.Now()
	o := &acme.Order{
		AccountID:        acc.ID,
		ProvisionerID:    prov.GetID(),
		Status:           acme.StatusPending,
		Identifiers:      nor.Identifiers,
		ExpiresAt:        now.Add(defaultOrderExpiry),
		AuthorizationIDs: make([]string, len(nor.Identifiers)),
		NotBefore:        nor.NotBefore,
		NotAfter:         nor.NotAfter,
	}
	for i, identifier := range o.Identifiers {
		az := &acme.Authorization{
			AccountID:  acc.ID,
			Identifier: identifier,
			ExpiresAt:  o.ExpiresAt,
			Status:     acme.StatusPending,
		}
		if err := h.newAuthorization(ctx, az); err != nil {
			api.WriteError(w, err)
			return
		}
		o.AuthorizationIDs[i] = az.ID
	}
	if o.NotBefore.IsZero() {
		o.NotBefore = now
	}
	if o.NotAfter.IsZero() {
		o.NotAfter = o.NotBefore.Add(prov.DefaultTLSCertDuration())
	}
	if nor.NotBefore.IsZero() {
		o.NotBefore = o.NotBefore.Add(-defaultOrderBackdate)
	}
	if err := h.db.CreateOrder(ctx, o); err != nil {
		api.WriteError(w, acme.WrapErrorISE(err, "error creating order"))
		return
	}
	h.linker.LinkOrder(ctx, o)
	w.Header().Set("Location", h.linker.GetLink(ctx, OrderLinkType, o.ID))
	api.JSONStatus(w, o, http.StatusCreated)
}
NewOrder ACME api for creating a new order.
package api
import (
	"context"
	"crypto/x509"
	"encoding/base64"
	"encoding/json"
	"net"
	"net/http"
	"strings"
	"time"
	"github.com/go-chi/chi"
	"github.com/smallstep/certificates/acme"
	"github.com/smallstep/certificates/api"
	"go.step.sm/crypto/randutil"
)
type NewOrderRequest struct {
	Identifiers []acme.Identifier `json:"identifiers"`
	NotBefore   time.Time         `json:"notBefore,omitempty"`
	NotAfter    time.Time         `json:"notAfter,omitempty"`
}
func (n *NewOrderRequest) Validate() error {
	if len(n.Identifiers) == 0 {
		return acme.NewError(acme.ErrorMalformedType, "identifiers list cannot be empty")
	}
	for _, id := range n.Identifiers {
		if !(id.Type == acme.DNS || id.Type == acme.IP) {
			return acme.NewError(acme.ErrorMalformedType, "identifier type unsupported: %s", id.Type)
		}
		if id.Type == acme.IP && net.ParseIP(id.Value) == nil {
			return acme.NewError(acme.ErrorMalformedType, "invalid IP address: %s", id.Value)
		}
	}
	return nil
}
type FinalizeRequest struct {
	CSR string `json:"csr"`
	csr *x509.CertificateRequest
}
func (f *FinalizeRequest) Validate() error {
	var err error
	csrBytes, err := base64.RawURLEncoding.DecodeString(f.CSR)
	if err != nil {
		return acme.WrapError(acme.ErrorMalformedType, err, "error base64url decoding csr")
	}
	f.csr, err = x509.ParseCertificateRequest(csrBytes)
	if err != nil {
		return acme.WrapError(acme.ErrorMalformedType, err, "unable to parse csr")
	}
	if err = f.csr.CheckSignature(); err != nil {
		return acme.WrapError(acme.ErrorMalformedType, err, "csr failed signature check")
	}
	return nil
}
var defaultOrderExpiry = time.Hour * 24
var defaultOrderBackdate = time.Minute