feat: add payment reconciliation cron job#2
Open
feelautom wants to merge 1 commit intowearestancer:mainfrom
Open
feat: add payment reconciliation cron job#2feelautom wants to merge 1 commit intowearestancer:mainfrom
feelautom wants to merge 1 commit intowearestancer:mainfrom
Conversation
Stancer does not support webhooks. If a customer closes the browser or
loses connectivity after payment, the redirect to the validation
controller never fires and the local payment stays "pending" forever —
no PrestaShop order is created even though the payment was captured.
This commit adds a reconciliation mechanism with two entry points:
controllers/front/cron.php — StancerCronModuleFrontController
Accessible at /module/stancer/cron?token=STANCER_CRON_TOKEN.
Queries ps_stancer_payment for rows with status="pending", no
associated order, and date_add older than 15 minutes. For each:
- Fetches the real payment status from the Stancer API.
- If to_capture or captured: calls module->validateOrder() to create
the PrestaShop order and saves the new id_order on the local record.
(CAPTURE and CAPTURE_SENT are intermediate states — skipped until
the status progresses to a value that maps to PS_OS_PAYMENT in
StancerApiPayment::getOrderState().)
- If refused / failed / canceled / expired: logs a PS warning. No
order is created for this payment.
- Returns a JSON summary { processed, reconciled, skipped, errors }.
The endpoint is secured with hash_equals() token comparison.
stancer.php
- Adds STANCER_CRON_TOKEN to getConfigurationsList() (generated once
on install via random_bytes(), stored as a hidden setting).
- Adds actionCronJob to the hooks list for compatibility with the
PrestaShop CronJobs module (ps_cronjobs) as an alternative trigger.
- Adds hookActionCronJob() implementing the same reconciliation logic
for shops using ps_cronjobs instead of a server cron job.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
Stancer does not support webhooks. When a customer completes payment on the Stancer hosted page, the
validation.phpcontroller handles the return and creates the PrestaShop order. However, if the redirect never happens (browser closed, network error, session expired), the local payment stayspendingindefinitely — no order is ever created, even though the payment was captured by Stancer.This affects all shops running in redirect mode and results in captured payments with no corresponding order on the merchant side.
Solution
Add a reconciliation cron job that polls the Stancer API every 15 minutes for pending payments older than 15 minutes and creates the PrestaShop order when the payment has been captured.
Implementation
New file:
controllers/front/cron.phpClass
StancerCronModuleFrontControlleraccessible at:Recommended crontab:
Logic:
ps_stancer_paymentfor rows withstatus = pending, noid_order, anddate_addolder than 15 minutes (threshold allows in-progress redirect flows to complete first)to_captureorcaptured→ callsmodule->validateOrder()to create the PS order, savesid_orderon the local record, logs successrefused,failed,canceled,expired→ logs a warning, marks the payment as processed (no order will be created)capture,capture_sentand other intermediate statuses → skipped until next run (these do not reliably map to a valid PS order state viagetOrderState()){ processed, reconciled, skipped, errors }hash_equals()token comparisonModified:
stancer.phpgetConfigurationsList(): addsSTANCER_CRON_TOKEN(generated once on install viarandom_bytes(16), stored as a hidden configuration key)$hooks: addsactionCronJobfor compatibility with the PrestaShop CronJobs module (ps_cronjobs)hookActionCronJob(): implements the same reconciliation logic for shops using ps_cronjobs as an alternative to a server cron jobNotes
StancerApiPayment::getOrderState()is reused as-is — onlyto_captureandcapturedare handled as they reliably map toPS_OS_PAYMENTSTANCER_CRON_TOKENis generated on install and never exposed in the admin UI — merchants retrieve it from the PS configuration table or via a future admin settingStancerCronModuleFrontControllerobject type