Вариантов много, 2 очевидных -
1)
пользователь может создать заказ, использовать промо-код, но оплату не произвести. При этом использование (счетчик -1) засчитывается.
. Пользователь сам себе злой буратина, предупреждать о "зависших" транзакциях с промо тикетами, смотрите в гугле тему "конверсия брошенных корзин".
2) Не снимать промо до оплаты, но тут возникает другая проблема - если человек проводит одновременно несколько оплат - промо на счету остаются, и можно начать процедуру оплаты по промо неограниченного количества товаров, решается только дополнительным полем, в которое пишется количество открытых транзакций на промо покупку. Если лимит транзакций достигнут, а счетчик промокодов еще не 0, выдавать предупреждение типа "Возможно у вас исчерпан лимит на промо, проверьте все ли товары купленные по промо оплачены и подтверждены." При отмене покупки - возвращать +1 к промо.