رسیدها و بررسی
مشتری رسید بانکیاش را چطور میفرستد، تیم شما چطور در یک صف آن را کامل یا بخشی تأیید یا رد میکند، و چرا رسید و پیامک بانک هیچوقت یک واریز را دو بار حساب نمیکنند.
رسید سند مشتری برای یک پرداخت است: عکس، اسکرینشات یا PDF که اپ بانکی به او داده، همراه با چیزهایی که کنارش نوشته است. بزن به کارت از رسید شروع میکند. مشتری از بانک خودش به کارت یا حساب شما پول میفرستد، رسید را روی صفحهٔ پرداخت بارگذاری میکند و تیم شما در یک صف تصمیم میگیرد. تا یکی از اعضای تیم شما تأیید نکند هیچ چیزی تأیید نمیشود، مگر اینکه تأیید خودکار را روشن کرده باشید. بررسیکنندهها همیشه تیم خود شما هستند، هرگز کارکنان بزن به کارت.
فرستادن رسید
مشتری در صفحهٔ پرداخت بعد از پرداخت تا سه فایل اضافه میکند و «فرستادن رسید» را میزند. میتواند کد پیگیری رسید، مبلغی که فرستاده و زمان پرداخت را هم بنویسد و در زبانهٔ انتقال بانکی میگوید کدام نوع انتقال را انجام داده است.
- فایلها: JPEG، PNG، WebP، HEIC یا PDF، هر کدام حداکثر ۱۰ مگابایت، که از روی محتوایشان شناخته میشوند. دقیقاً همانطور که بارگذاری شدهاند نگه داشته میشوند، با اثر انگشت SHA-256 هر کدام (سند پرداخت را ببینید).
- فایل بهطور پیشفرض الزامی است. اگر در تنظیمات صفحهٔ پرداخت خاموشش کنید، مشتری میتواند بدون فایل هم واریز را اعلام کند؛ این هم یک رسید است، فقط بدون فایل.
- پرداخت در انتظار تأیید
processingمیشود و منتظر تیم شما میماند. هیچوقت با گذشت زمان به بررسی نمیرود: صف رسیدها خودش همان بررسی است. - بیش از یکی: مشتریای که در دو انتقال پرداخت کرده دو رسید میفرستد. رسید اصلاحشده (مثلاً عکسی واضحتر) بهجای آن، جای رسید در انتظار قبلیاش را میگیرد.
- از راه دیگر: وقتی مشتری رسید را در پیامرسان فرستاده یا حضوری داده، یکی از اعضای تیم آن را از صفحهٔ پرداخت در داشبورد اضافه میکند، یا سرور شما آن را با
POST /میفرستد.v1/ payments/ :id/ receipts
مشتری هر رسیدش را با وضعیتش روی صفحهٔ پرداخت میبیند و اگر رد شود دلیلش را هم. بزن به کارت دربارهٔ هیچ تصمیمی به مشتری پیام نمیدهد. تیم شما از هر رسید تازه با تلگرام و ایمیل خبردار میشود (اعلان receipt که برای مالک، مدیر و پشتیبان بهطور پیشفرض روشن است) و سرور شما با وبهوک receipt.created.
صف بررسی
بخش رسیدها در داشبورد همهٔ رسیدها را، اول رسیدهای در انتظار، فهرست میکند و رسیدهای تازه را زنده نشان میدهد. هر رسید کنار پرداختش مینشیند: مبلغی که پرداخت انتظار دارد، فایلها، چیزهایی که مشتری نوشته، هشدار وقتی تکراری به نظر برسد و یادداشت وقتی پیامک بانک تطبیق داده باشد. بر اساس وضعیت و نوع انتقال فیلتر کنید، یا با کد پیگیری، نام پرداختکننده یا شناسه جستوجو کنید.
| وضعیت | معنی |
|---|---|
در انتظار بررسیpending | منتظر تیم شما. |
تأیید شدهapproved | یکی از اعضا (یا تأیید خودکار) آن را پذیرفته و پولش روی پرداخت نشسته است. |
رد شدهrejected | یکی از اعضا آن را با دلیلی که مشتری میبیند رد کرده است. |
جایگزین شدهwithdrawn | رسید اصلاحشدهٔ همان مشتری جایش را گرفته است. |
مالک، مدیر و پشتیبان میتوانند رسیدها را تأیید، رد و دوباره باز کنند. توسعهدهنده و «فقط مشاهده» میبینند ولی تصمیم نمیگیرند.
تأیید
تأیید یعنی «این پول به ما رسیده است». مبلغ تأیید، اگر مشتری مبلغی نوشته باشد همان مبلغ رسید است، وگرنه مبلغی که پرداخت هنگام فرستادن رسید خواسته بود (تا رقمهای یکتای آن حتی بعد از منقضی شدن صفحهٔ پرداخت بمانند)، وگرنه مبلغی که پرداخت الان انتظار دارد، وگرنه باقیمانده. رسیدی که نسخهٔ تکراری رسید در انتظار دیگری است و مبلغی ننوشته، از مبلغ پیامک بانکی شروع میشود که با رسید اصلی تطبیق خورده؛ پس اگر این نسخه را زودتر تأیید کنید، همان پیامک به کار میرود. تأیید دقیقاً به مبلغی که پرداخت انتظار دارد، کل پرداخت را میپردازد: رقمهای یکتای آن هیچوقت اضافه یا کم حساب نمیشوند. اگر بانکتان رقم دیگری نشان میدهد، پیش از تأیید آن را عوض کنید.
- کل مبلغ: پرداخت موفق
succeededمیشود. - بخشی از مبلغ: همان مقداری را که واقعاً رسیده تأیید کنید. پرداخت کمواریز
partially_paidمیشود با یک مبلغ یکتای تازه برای بقیه، و صفحهٔ پرداخت آن را از مشتری میخواهد. وقتی پرداخت چندمرحلهای خاموش است، یا مهلت صفحهٔ پرداخت گذشته، پرداخت بهجای آن در نیاز به بررسیrequires_reviewمیماند تا تیم شما باقیمانده را بخواهد یا کسری را بپذیرد؛ پنجرهٔ تأیید میگوید کدام میشود. در پرداختی که تیم شما با کسری بسته، تأیید بخشی از مبلغ آن را موفقsucceededنگه میدارد و آنچه هنوز کم است، کسری پذیرفتهشده آن میماند. پرداخت ناقص را ببینید. - بیشتر از مبلغ خواستهشده: تأییدی که بیشتر از مبلغی که پرداخت هنوز لازم دارد ثبت کند، مازاد را بهعنوان بیشواریز ثبت میکند؛ پس تا وقتی بیشواریز را تأیید نکنید (
overpay: true) باreceipt_payment_settledرد میشود. داشبورد پیش از تأیید شما همان رقم را نشان میدهد. وصل کردن پیامک بانک به رسید از صندوق بررسی و اصلاح هم وقتی بیشواریز بسازد، همین تأیید را میخواهد. - پرداختی که چیزی از آن باقی نمانده: هر پولی که تأیید اضافه کند بیشواریز است؛ پس همان تأیید بیشواریز لازم است (
overpay: true). اگر رسید مبلغی ندارد،amountرا هم بفرستید؛ مبلغ مورد انتظار قبلی پرداخت دوباره ثبت نمیشود (receipt_amount_required). پرداختی که تیم شما با کسری بسته، پول جامانده را بدون این تأیید هم میگیرد. - پرداخت لغوشده یا منقضیشده: تأیید آن را دوباره باز میکند، پس داشبورد اول همین را از شما میپرسد. بعد واریزهای پرداخت وضعیتش را دوباره تعیین میکنند و فقط پولی که بیش از مبلغ خواستهشده رسیده، بدهی برگشت به مشتری میماند. اگر پول آن به مشتری برگشته باشد (بازپرداخت یا اعتبار)، هیچ رسیدی روی آن تأیید نمیشود:
receipt_payment_refunded. برای واریز تازه، پرداخت تازهای بسازید. اگر با این حال واریزی دیرهنگام آن را دوباره باز کند، پولی که برگشته همچنان چیزی نمیپردازد و رسیدی که بعد از آن تصمیم فرستاده شده هیچوقت روی آن پول نمیایستد و با پیامک آن علامت نمیخورد: تأیید چنین رسیدی واریز خودش را اضافه میکند. - پرداختی که بیشواریزش را پیشتر تعیین تکلیف کردهاید: تأیید پولی که آن را بیش از آنچه تعیین تکلیف کردهاید بیشواریز کند، با
receipt_overpayment_resolvedرد میشود. - رسیدی که پیامک بانک تطبیقش داده و همان مبلغ پیامک را نوشته، فقط با همان مبلغ تأیید میشود؛ هر مبلغ دیگری
receipt_amount_mismatchمیگیرد. اگر بانک و رسید با هم نمیخوانند، اول واریز پیامکی را جدا کنید. رسیدی که مبلغی ننوشته از مبلغ پیامک شروع میشود؛ اگر واریز دیگری است، آن را با مبلغ خودش تأیید کنید تا آن پیامک برای رسید خودش روی پرداخت بماند.
پشتوانهٔ هر تأیید دقیقاً یک واریز روی همان پرداخت است: واریز پیامکی که با آن تطبیق داده، واریز وصلنشدهای که خودتان انتخاب میکنید، یا یک واریز تازه با منبع receipt. اگر واریزی با این مبلغ پشتوانهٔ رسید تأییدشدهٔ دیگری باشد، آن رسید ممکن است به واریز دیگری با مبلغ خودش روی همین پرداخت منتقل شود که با آن جور است، تا هر کدام روی واریز خودش بایستد: هیچ پولی جابهجا نمیشود و تاریخچهٔ رسید منتقلشده این را نشان میدهد. دو بار کلیک یا درخواست تکراری فقط یک بار تأیید میکند. وقتی دو نفر از تیم همزمان دربارهٔ یک رسید تصمیم بگیرند، یکی برنده میشود و دیگری receipt_action_unavailable میگیرد: دربارهٔ آن رسید تصمیم گرفته شده است. در داشبورد، receipt_already_changed یعنی آنچه پنجرهٔ تأیید نشان داده بود دیگر درست نیست: گفته بود تأیید پولی اضافه نمیکند یا پرداختی را دوباره باز نمیکند، یا رقم بیشواریزی را نشان داده بود، و در این فاصله تصمیم همتیمی، جدا کردن یک واریز یا لغو پرداخت آن را عوض کرده است. پنجره بعد از آن نشان میدهد تأیید الان چه میکند. تغییرهای پول یک پرداخت یکییکی انجام میشوند: اگر تغییر دیگری روی همان پرداخت هنوز در جریان باشد، درخواست شما چند ثانیه صبر میکند و بعد بدون انجام هیچ کاری payment_already_changed میگیرد، و تکرار آن با همان Idempotency-Key اجرا میشود.
curl https://a.bezanbecard.com/v1/receipts/rcp_…/approve \
-H "Authorization: Bearer sk_test_…" \
-H "Idempotency-Key: <a new UUID per decision>" \
-H "Content-Type: application/json" \
-d '{"amount":10000000,"note":"Bank app shows 10,000,000"}'برای هر تصمیم یک Idempotency-Key تازه بسازید و فقط برای تکرار همان درخواست دوباره به کارش ببرید. رسیدی که به حالت در انتظار برگشته (به بررسی برگردانده شده یا واریزش جدا شده) برای تصمیم بعدی کلید تازه میخواهد؛ کلید قبلی فقط همان پاسخ اول را تکرار میکند.
رد کردن
با یکی از این دلیلها رد کنید. مشتری دلیل را روی صفحهٔ پرداخت میبیند؛ یادداشت شما پیش تیمتان میماند.
reason | آنچه مشتری میخواند |
|---|---|
not_received | واریزی با این مشخصات به حساب نرسید. |
amount_mismatch | مبلغ رسید با مبلغ سفارش یکی نیست. |
unreadable | رسید خوانا نیست. |
duplicate | این رسید پیشتر فرستاده شده است. |
other | رسید پذیرفته نشد. |
رد کردن هیچوقت پولی را جابهجا نمیکند. وقتی پرداخت رسید در انتظار دیگری نداشته باشد، دوباره منتظر مشتری میماند: در انتظار واریزrequires_payment، یا اگر بخشی رسیده باشد کمواریزpartially_paid. آن وقت مشتری میتواند پیش از بسته شدن صفحهٔ پرداخت رسید دیگری بفرستد.
curl https://a.bezanbecard.com/v1/receipts/rcp_…/reject \
-H "Authorization: Bearer sk_test_…" \
-H "Idempotency-Key: <a new UUID per decision>" \
-H "Content-Type: application/json" \
-d '{"reason":"unreadable","note":"Blurred photo"}'نظرتان عوض شد؟ روی صفحهٔ رسید ردشده در داشبورد برگرداندن به بررسی را بزنید: به حالت در انتظار برمیگردد و پرداخت به در انتظار تأییدprocessing. رسید تأییدشده با جدا کردن واریزش دوباره باز میشود که خودبهخود آن را به حالت در انتظار برمیگرداند (اصلاحها را ببینید).
هشدار رسید تکراری
وقتی رسیدی میرسد، اثر انگشت هر فایل و کد پیگیریاش با همهٔ رسیدهای دیگر کسبوکار شما در همان حالت مقایسه میشود. اگر مشابهی پیدا شود، به بررسیکننده هشدار داده میشود و پیوند رسید دیگر را هم میبیند؛ ولی هیچوقت رد نمیشود، چون فقط تیم شما میداند ارسال دوباره است یا همان رسید برای سفارش دیگری به کار رفته است. در API رسید duplicate: true دارد.
پیامک بانک و تأیید خودکار (اختیاری)
هیچکدام از اینها لازم نیست. با وصل کردن اپ دریافت پیامک، پیامک واریزی که بانک میفرستد کنار رسید خودش مینشیند:
- پیامک بانکی که به این پرداخت تطبیق میخورد، روی کارت یا حساب همان پرداخت، قدیمیترین رسید در انتظاری را که با آن جور است تطبیق میدهد: با مبلغی که رسید نوشته، و با کارت پرداختکننده، اگر هر دو معلوم باشند. رسیدی که بدون نوشتن مبلغ فرستاده شود، همان مبلغی را ادعا میکند که پرداخت در آن لحظه میخواست، یعنی رقمی که صفحهٔ پرداخت نشان میداد؛ پس پیامک بخش قبلی هیچوقت رسیدی را که برای باقیمانده فرستاده شده از آنِ خود نمیکند. نسخهٔ تکراری رسید دیگر، مبلغی از خودش ادعا نمیکند. هر پیامک فقط یک رسید را علامت میزند. نسخهٔ دوم همان رسید، یا قسط دومی با همان مبلغ و همان کارت، با آن علامت نمیخورد و منتظر پیامک خودش میماند. صف نشان میدهد پیامک بانک تطبیق داده و تأیید با یک کلیک همان واریز را به کار میبرد.
- رسیدی که بعد از رسیدن پیامکش اضافه شود هم همینطور علامت میخورد، به شرطی که آن پیامک مال رسید دیگری نشده باشد.
- تأیید رسید روی واریز پیامک بانکی که خودتان انتخاب میکنید، یا وصل کردن آن پیامک به رسید از صندوق بررسی و اصلاح، هم رسید را تطبیقیافته با پیامک بانک نشان میدهد، اگر مبلغ و کارت پرداختکنندهای که رسید نوشته با پیامک جور باشد. وصل کردن دستی پیامک بانک به پرداخت هم همان لحظه قدیمیترین رسید در انتظاری را که با آن جور است علامت میزند.
- اگر اول نسخهٔ دوم یا رسید دوم را با مبلغ پیامک تأیید کنید و پیامک با آن هم جور باشد، تأیید همان پیامک را به کار میبرد و پولی اضافه نمیکند: علامت به این رسید منتقل میشود تا یک واریز هیچوقت دو بار حساب نشود. نسخهٔ دومی که مبلغی ننوشته، از همان مبلغ شروع میشود. رسید دیگر وقتی تأییدش کنید پول خودش را اضافه میکند، یا آن را بهعنوان تکراری رد میکنید. پیامکی که رسید تأییدشدهای روی آن ایستاده، یا رسید دیگری را علامت زده و با این رسید جور نیست، برای این رسید به کار نمیرود. پیامکی که از کارتی غیر از کارت نوشتهشده در رسید آمده، فقط وقتی پرداخت کامل شده باشد برای این رسید به کار میرود؛ تا وقتی پولی مانده، بخش دیگر یک انتقال چندتکه است و تأیید پول خودش را اضافه میکند که بعداً پیامک خود رسید جایش را میگیرد.
- وقتی رسید علامتخوردهای را رد میکنید، یا مشتری رسید اصلاحشدهای به جایش میفرستد، علامت به قدیمیترین رسید در انتظار دیگری میرسد که با پیامک جور باشد.
- واریزی که دستی ثبت میکنید یا از راه API ثبت میشود هیچ رسیدی را تطبیقیافته با پیامک بانک نشان نمیدهد. تأیید رسید با مبلغ همان واریز باز هم روی همان واریز میایستد و واریز دومی ساخته نمیشود.
- تأیید خودکار تنظیمی در تنظیمات پرداخت است که بهطور پیشفرض خاموش است. وقتی روشن باشد، پرداخت فقط یک رسید در انتظار داشته باشد، پیامک با آن جور باشد و پرداخت نه به دلیل دیگری در بررسی باشد و نه لغو یا منقضی شده باشد، سامانه رسید را تأیید میکند. واریزی که دیر برسد، پرداخت لغوشده یا منقضیشده را اول دوباره باز میکند و بعد رسیدی که با آن جور است تأیید میشود؛ اگر پول تازهای نرسد، پرداخت لغوشده یا منقضیشده بسته میماند و رسیدش منتظر یک نفر میماند. رسیدی که نسخهٔ تکراری رسید دیگری شناخته شده فقط علامت میخورد و یک نفر تصمیم میگیرد. با چند رسید در انتظار فقط قدیمیترینی را که با پیامک جور است علامت میزند و یک نفر تصمیم میگیرد.
بدون اپ هم برای مشتری هیچ چیزی عوض نمیشود: شما اپ بانکتان را نگاه میکنید و تأیید میکنید.
هر واریز، یک بار
تأییدی که پیش از رسیدن پیامک بانک انجام شود روی یک واریز موقت با منبع receipt میایستد. وقتی بعداً پیامک همان واریز برسد (همان کارت یا حساب و همان مبلغ، نه از کارت پرداختکنندهای غیر از کارتی که رسید نوشته، با دقیقاً یک واریز رسید از این دست، روی پرداختی که هنوز باز است یا در ۷ روز گذشته موفق شده)، واریز پیامکی جای آن را میگیرد:
- واریز پیامکی به پرداخت وصل میشود.
- واریز رسید برگشتخورده
reversedمیشود، چون پیامک جایش را گرفته است. در API، واریز پیامکی و رویدادdeposit.matchedآن، این واریز رسید را درreplacesنام میبرند (یک شناسهٔdep_…، وگرنهnull)؛ پولی که برای آن واریز رسید ثبت کردهاید همین انتقال است، نه پول تازه. - رسید از این به بعد روی واریز پیامکی میایستد، و اگر پیامک با مبلغ و کارت پرداختکنندهای که رسید نوشته جور باشد، رسید را تطبیقیافته هم نشان میدهد.
وقتی مبلغها یکی باشند، amount_received تغییر نمیکند. اگر سامانه دو واریز رسید ممکن پیدا کند یا هیچ، یا رسید در انتظار پرداخت دیگری همین مبلغ را نوشته باشد، پیامک با پیشنهادی که رسیدها را نام میبرد در بررسی و اصلاح منتظر میماند تا یکی از اعضا دستی وصلش کند. وصل کردن دستی آن به پرداختی که واریز رسید را دارد، همانطور جای آن واریز را میگیرد؛ اگر دو واریز رسید یا بیشتر آنجا ممکن است همین انتقال باشند، وصل کردن شما جای قدیمیترینشان را میگیرد. وصل کردن پیامک به رسیدی که روی واریز رسید ایستاده، فقط با پیامکی به همان مبلغ جای آن واریز را میگیرد، چون جایگزینی هیچوقت پول را جابهجا نمیکند؛ مبلغ دیگر receipt_amount_mismatch میگیرد. اول واریز رسید را جدا کنید، بعد پیامک را به همان رسید که دوباره در انتظار است وصل کنید. در همهٔ این مراحل:
- هر رسید تأییدشده دقیقاً یک واریز وصلشده پشتش دارد؛
- هیچ واریزی دو بار حساب نمیشود و
amount_receivedهمیشه جمع واریزهای وصلشده است؛ - هر پیامک بانک حداکثر یک رسید را علامت میزند؛
- رد کردن هیچوقت پولی را جابهجا نمیکند؛
- جدا کردن واریز یک رسید، آن رسید را به حالت در انتظار برمیگرداند.
مبلغ یکتا، روشن یا خاموش
بهطور پیشفرض هر پرداخت باز روی یک کارت یا حساب expected_amount خودش را میخواهد که چند ریال با بقیه فرق دارد. آن وقت رسیدها راحت با صورتحساب بانکی مقایسه میشوند و هر پیامک بانک دقیقاً به یک پرداخت میخورد.
مبلغ یکتا را میتوانید در تنظیمات پرداخت خاموش کنید. آن وقت expected_amount با amount برابر است، صفحهٔ پرداخت دربارهٔ رقمهای اضافه چیزی نمیگوید و چند پرداخت باز ممکن است یک رقم را بخواهند. رسیدها درست مثل قبل کار میکنند. ولی پیامک بانک دیگر نمیتواند این پرداختها را از هم جدا کند: هیچوقت حدس نمیزند و در بررسی و اصلاح منتظر یک نفر میماند. اگر به اپ دریافت پیامک تکیه میکنید، مبلغ یکتا را روشن نگه دارید.
رسیدها در API
| فیلد | توضیح |
|---|---|
id | rcp_… |
payment | پرداختی که این رسید سند آن است. |
status | pending، approved، rejected یا withdrawn. |
channel | card، pol، paya، satna، internal، یا null وقتی مشتری نگفته باشد. |
reference | کد پیگیریای که مشتری نوشته، با حرف و رقم لاتین. |
amount | مبلغی که مشتری میگوید فرستاده؛ null یعنی همان مبلغ مورد انتظار. |
paid_at، payer_name، payer_last4 | چیزهایی که مشتری دربارهٔ پرداخت گفته است. |
files | [{ id, size, sha256 }]: هرگز نشانی فایل نیست. API هیچوقت خود فایلها را برنمیگرداند. |
duplicate، corroborated | دو هشدار: رسید دیگری با همان فایل یا کد پیگیری، و پیامک بانکِ همان واریز. |
review | بعد از تصمیم: { decision, amount, reason, reviewed_at }. |
created | ثانیهٔ یونیکس. |
| درخواست | کار |
|---|---|
GET /v1/receipts | رسیدها را از جدید به قدیم فهرست میکند و بر اساس status (pending همان صف است)، channel، payment و created فیلتر میشود. |
GET /v1/receipts/:id | یک رسید را برمیگرداند. |
POST / | رسید میفرستد: JSON، یا multipart/form-data با فایلها در files. فیلدها همان فیلدهای صفحهٔ پرداخت هستند و paid_at به ثانیهٔ یونیکس است. |
POST / | تأیید میکند، با amount، deposit (یک dep_… وصلنشده برای ایستادن روی آن)، overpay و note اختیاری. |
POST /v1/receipts/:id/reject | رد میکند، با reason و note اختیاری. |
پرداخت با expand[]=receipts رسیدهایش را هم همراه دارد. کلید محدود دسترسی receipts لازم دارد و فرستادن رسید payments و receipts را با write میخواهد. رویدادها receipt.created، receipt.approved و receipt.rejected هستند؛ شیء رسید را دارند و هیچ راهی برای خواندن فایلهایش ندارند. API نمیگوید کدام واریز پشت یک رسید است: واریزهای پرداخت را بخوانید.
curl https://a.bezanbecard.com/v1/payments/pay_…/receipts \
-H "Authorization: Bearer sk_test_…" \
-H "Idempotency-Key: receipt-1042-1" \
-F channel=paya \
-F reference=140508041234 \
-F amount=12500470 \
-F [email protected]امتحان در حالت آزمایشی
- یک پرداخت آزمایشی بسازید و
checkout_urlآن را باز کنید. - هر عکسی را بهعنوان رسید بارگذاری کنید و «فرستادن رسید» را بزنید.
- آن را در رسیدها تأیید کنید. پرداخت روی یک واریز با منبع
receiptموفق میشود. - نقش پیامک بانکِ همان واریز را با
POST /وv1/ test_helpers/ deposits {"payment":"pay_…","amount":<the expected amount>}بازی کنید. واریز پیامکی جای واریز رسید را میگیرد، رسید نشان میدهد بانک تطبیق داده وamount_receivedتغییر نمیکند.