چرا verify مهمترین خط کد پرداخت شماست
پارامترهای بازگشتی مرورگر قابل اعتماد نیستند. توضیح میدهیم چرا تأیید سمت سرور تنها راه قطعی کردن پرداخت است و چطور آن را درست پیاده کنید.
· ۶ دقیقه مطالعه · تیم شیپی
بعد از پرداخت، مشتری با چند پارامتر در آدرس به سایت شما برمیگردد؛ مثلاً status=success. این پارامترها را مرورگر مشتری میفرستد و هر کسی میتواند آنها را دستی تغییر دهد. اگر سفارش را بر اساس همین پارامترها تحویل دهید، کافی است کسی نشانی بازگشت را باstatus=success باز کند تا بدون پرداخت کالا بگیرد.
تأیید سمت سرور چه میکند؟
در شیپی، سرور شما با کلید API محرمانه، درخواست POST /api/v1/payments/:id/verify را با مبلغ سفارش میفرستد. پاسخ این درخواست از سرور به سرور میآید و قابل جعل نیست. اگر وضعیت verified بود، پرداخت قطعی است و مبلغ وارد چرخه تسویه میشود.
سه نکته که اغلب فراموش میشود
- شناسه پرداخت را از سفارش خودتان بخوانید، نه از پارامترهای آدرس. هنگام ایجاد پرداخت،
payment.idرا کنار سفارش ذخیره کنید. - مبلغ را بفرستید. verify با مبلغ سفارش شما مقایسه میشود؛ اگر کسی مبلغ را در مسیر دستکاری کرده باشد، خطای
payment_amount_mismatchمیگیرید. - تکرار verify بیخطر است. اگر پاسخ را دریافت نکردید، دوباره صدا بزنید؛ درخواست تکراری با
already_verified: trueپاسخ میگیرد و پرداخت دوباره ثبت نمیشود. پس سفارش را هم بهصورت idempotent نهایی کنید.
اگر verify نکنید؟
پرداختی که در مهلت مشخص (فیلد verify_deadline_at) تأیید نشود، بهصورت خودکار به کارت مشتری برمیگردد. این رفتار عمدی است: مشتری برای سفارشی که سیستم شما هرگز آن را ثبت نکرده، پول پرداخت نمیکند.
وضعیت pending
گاهی ارتباط با بانک در لحظه بازگشت قطع میشود. در این حالت پرداخت در وضعیت pending میماند و سامانه بهصورت خودکار از بانک استعلام میگیرد. verify در این زمان خطای 409 با details.status = pending برمیگرداند؛ چند ثانیه بعد دوباره تلاش کنید یا منتظر وبهوکpayment.success بمانید.
const { payment, already_verified } = await verify(order.paymentId, order.amountRial);
if (already_verified || payment.status === 'verified') await fulfil(order); // safe to call twiceجزئیات کامل در مستندات verify.