اتصال درگاه پرداخت در مسیر عادی ساده است: کاربر را میفرستید، پول میدهد و برمیگردد. سختی کار در مسیرهای غیرعادی است. اینترنت کاربر قطع میشود، صفحه دو بار رفرش میشود یا پیام درگاه دیر میرسد. این اصول به نام هیچ درگاه خاصی نیست و تقریباً همهجا صدق میکند.
اصل اول: برگشت کاربر چیزی را ثابت نمیکند
شایعترین خطای خطرناک این است که وقتی کاربر با پارامتر «موفق» به سایت برگشت، سفارش را پرداختشده بدانیم. کاربر میتواند آن نشانی را دستکاری کند. قاعده درست این است:
- برگشت کاربر فقط یعنی «بررسی کن».
- سرور شما مستقیم از درگاه استعلام میکند.
- مبلغ و شماره سفارش پاسخ با سفارش شما مقایسه میشود.
- فقط در این صورت سفارش پرداختشده حساب میشود.
مبلغ را هم همیشه از سفارش سمت سرور بخوانید و هیچوقت از فرم مرورگر نگیرید.
اصل دوم: هر پیام ممکن است چند بار برسد
شبکه قابل اعتماد نیست، پس سیستمهای پرداخت پیامها را دوباره میفرستند. Stripe در مستندات خود میگوید ممکن است یک رویداد چند بار به شما برسد و ترتیب رسیدن رویدادها را هم تضمین نمیکند. اگر کد شما برای هر پیام یک بار فایل تحویل بدهد یا موجودی کم کند، کاربر چند بار سود میبرد یا موجودی منفی میشود.
راهحل استاندارد این است که عملیات تکرارپذیر باشد:
- شناسه هر رویداد را با محدودیت یکتا در پایگاه داده ذخیره کنید. اگر قبلاً پردازش شده، کاری نکنید.
- تغییر وضعیت سفارش را در تراکنش و با قفل روی همان سفارش انجام دهید.
- پیش از هر کاری بررسی کنید سفارش هنوز پرداختنشده باشد.
کلید یکتایی برای درخواستها
مشکل مشابهی در مسیر برعکس وجود دارد. اگر سرور شما به درگاه درخواست بدهد و پاسخ به خاطر قطعی نرسد، نمیدانید عملیات انجام شده یا نه. اگر دوباره بفرستید شاید دو بار انجام شود.
برای همین API خوب از کلید یکتایی پشتیبانی میکند. در Stripe، کلاینت کلیدی تصادفی میسازد و همراه درخواست POST میفرستد. اگر همان کلید دوباره بیاید، پاسخ ذخیرهشده قبلی برمیگردد و عملیات تکرار نمیشود. این کلید میتواند پس از دستکم ۲۴ ساعت حذف شود و اگر پارامترها با درخواست اول نخواند، خطا برمیگردد. نباید در کلید هم اطلاعات حساس مثل ایمیل گذاشت.
اگر API خودتان را میسازید، همین الگو را برای عملیات مهم مثل ثبت سفارش پیاده کنید.
وبهوک امن
اگر درگاه شما پیام خودکار میفرستد، این چند نکته را رعایت کنید:
- امضا را بررسی کنید. نشانی وبهوک عمومی است و هر کسی میتواند به آن درخواست بفرستد. Stripe تأکید میکند بررسی امضا به متن خام درخواست نیاز دارد و هر دستکاری در آن بررسی را خراب میکند.
- سریع پاسخ بدهید. کار سنگین را بعد از پاسخ موفق در صف انجام دهید تا درگاه به خاطر تأخیر پیام را تکرار نکند.
- همه را ثبت کنید. بدون اطلاعات حساس، ولی طوری که بتوانید بعداً ببینید چه رسیده است.
حالتهایی که باید از اول طراحی شوند
- پول کم شد ولی کاربر برنگشت. به همین دلیل استعلام دورهای یا وبهوک لازم است.
- پرداخت پس از انقضای سفارش رسید. آن را خودکار فعال نکنید و به صف بررسی دستی بفرستید.
- دو بار کلیک روی دکمه پرداخت. دکمه را غیرفعال کنید و در سرور هم جلویش را بگیرید.
- بازپرداخت. قابلیت دانلود یا اشتراک مرتبط باید همزمان باطل شود.
- مغایرت. گزارش روزانه تراکنشهای درگاه را با سفارشهای خودتان مقایسه کنید. این سادهترین راه پیدا کردن خطاهای پنهان است.
نکته امنیتی آخر
کلید API درگاه باید فقط در تنظیمات سرور باشد و هرگز وارد کد، مخزن گیت یا مرورگر نشود. اطلاعات کارت هم نباید از سرور شما رد شود؛ بگذارید کاربر آن را در صفحه درگاه وارد کند. این کار هم امنتر است و هم بار مسئولیت شما را کم میکند.
پیش از رفتن روی محیط واقعی
با محیط آزمایشی همه این سناریوها را امتحان کنید: پرداخت موفق، لغو توسط کاربر، بستن مرورگر وسط پرداخت، تکرار پیام و قطع ارتباط با درگاه. اگر میخواهید این اتصال را با اطمینان بسازید یا بررسی کنید، صفحه توسعه و یکپارچهسازی API را ببینید.