As per our discussion in the comments on your original post:
The primary issue is the length of time it takes the server to process the form submission which gives the user the opportunity to get impatient and refresh the page and then submit the same data twice.
Your external API call to get your drop shipping data is the process costing the most time.
So I would suggest getting the drop shipping data before allowing the final submission of the form. You could possibly do it as an Ajax request and keep the submit button disabled until the drop shipping data is returned.
That way when the user submits the form, the server-side processing time is minimised.
There is still a chance that processing time for the form submission could still be long enough for the user to refresh the page before the submission is complete.
I think the remaining process should be short enough for users not to have the opportunity to refresh the page before the submission is complete. If it is then you may need to look at any processes in the submission logic that take time and either prepare them prior to submission like with the drop shipping API call or push them out to queue workers.
You could also make your persistence to the database the final action in the submission process before returning its response. That way, if the user is able to refresh before the process is complete, there is a minimum possibility that data has been persisted meaning that if the form is submitted a second time, the data is least likely to be duplicated.
You could go down the route of setting a token in the form to ensure the form can only be loaded once or storing a "prospective" order throughout your previous steps and making the submission the simple action of marking the "prospective" order as a "real" order.
But these approaches feel an over-complication of the typical form submission request approach that assumes the request and response cycle would not be interrupted.