رفتن به محتوای اصلی

پرداخت ناقص و مبلغ تکمیلی

وقتی مشتری کمتر از مبلغ واریز می‌کند چه می‌شود، تیم شما چطور بخشی از یک رسید را تأیید می‌کند و بقیهٔ پول چطور روی همان پرداخت گرفته می‌شود.

مشتری‌ها مبلغ را اشتباه تایپ می‌کنند و بعضی در دو انتقال پرداخت می‌کنند. در بیشتر روش‌های کارت‌به‌کارت، واریز کمتر یعنی بن‌بست: سفارش گیر می‌کند و باید تلفنی حلش کرد. در بزن به کارت، پرداخت آن‌قدر واریز جمع می‌کند تا به مبلغش برسد.

واریز کمتر چطور مدیریت می‌شود

فرض کنید پرداخت ۱۲٬۵۰۰٬۴۷۰ ریال می‌خواهد و مشتری ۱۰٬۰۰۰٬۰۰۰ ریال می‌فرستد.

  1. رسید مشتری ۱۰٬۰۰۰٬۰۰۰ ریال را نشان می‌دهد و تیم شما همین مبلغ را تأیید می‌کند. (یا پیامک بانکِ واریز کمتر از روی کارت پرداخت‌کننده پیدا می‌شود، یا شما واریز را دستی وصل می‌کنید.)
  2. پرداخت کم‌واریزpartially_paid می‌شود: amount_received برابر ۱۰٬۰۰۰٬۰۰۰ و amount_remaining برابر ۲٬۵۰۰٬۰۰۰ است.
  3. همان لحظه یک مبلغ تکمیلی باز می‌شود: یک expected_amount یکتای تازه برای باقی‌مانده، تا واریز بعدی هم مثل اولی روشن از بقیه جدا شود.
  4. همان checkout_url حالا نوار پیشرفت، مبلغ رسیده و مبلغ تازه را نشان می‌دهد. مشتری آن را می‌پردازد و رسید دوم را می‌فرستد.
  5. وقتی بقیه تأیید شود، پرداخت موفقsucceeded می‌شود.

اگر مشتری بعداً همان مبلغ اول را بفرستد هم پیدا می‌شود: پرداخت همهٔ مبلغ‌هایی را که خواسته به یاد دارد. تا وقتی رسیدی که تیم شما برای بخش اول تأیید کرده هنوز منتظر پیامک بانکی خودش است، پیامک بانکی با مبلغ اول به‌جای آن در بررسی و اصلاح منتظر می‌ماند و برای همین پرداخت پیشنهاد می‌شود، چون ممکن است همان انتقال آن رسید باشد. وقتی پیامک خود بخش اول روی پرداخت آمده باشد، پیامک بعدی با مبلغ اول به پرداخت وصل می‌شود و آنچه بیشتر از مبلغ برسد بیش‌واریزی است که باید تکلیفش را روشن کنید.

Text
amount            12,500,000
expected_amount   12,500,470   ← first transfer asked for
received          10,000,000   → partially_paid
expected_amount    2,500,820   ← top-up for the remainder
received          12,500,820   → succeeded

تأیید بخشی از یک رسید

همان مقداری را تأیید کنید که واقعاً به شما رسیده است. در رسیدها پیش از زدن تأیید رسید مبلغ را عوض کنید؛ در API آن را با amount بفرستید. بدون مبلغ، تأیید مبلغ خود رسید را می‌گیرد، وگرنه مبلغی که پرداخت هنگام فرستادن رسید خواسته بود (برای رسیدی که بعد از اولین تأیید بخشی فرستاده شده، همان مبلغ تکمیلی)، وگرنه مبلغی که پرداخت الان انتظار دارد، وگرنه باقی‌مانده. رسیدی که مبلغی ننوشته و پیامک بانک علامتش زده، از مبلغ همان پیامک شروع می‌شود؛ نسخهٔ تکراری رسید در انتظار دیگری که مبلغی ننوشته هم از مبلغ پیامک بانکی شروع می‌شود که با رسید اصلی تطبیق خورده. در پرداختی که تیم شما با کسری بسته، تأیید بخشی از مبلغ آن را موفقsucceeded نگه می‌دارد و آنچه هنوز کم است، کسری پذیرفته‌شده آن می‌ماند.

curl
curl https://a.bezanbecard.com/v1/receipts/rcp_…/approve \
  -H "Authorization: Bearer sk_test_…" \
  -H "Idempotency-Key: approve-rcp_…" \
  -H "Content-Type: application/json" \
  -d '{"amount":10000000}'

رسیدی که پیامک بانک پیش‌تر تطبیقش داده و همان مبلغ پیامک را نوشته، فقط با مبلغ بانک تأیید می‌شود. بقیهٔ قاعده‌ها در رسیدها و بررسی است.

خبر دادن به مشتری

صفحهٔ پرداخت خودش بقیهٔ مبلغ را می‌خواهد. اگر می‌خواهید به مشتری یادآوری هم کنید، به رویداد payment.partially_paid گوش دهید و او را با مبلغ باقی‌مانده به checkout_url برگردانید:

if (event.type === 'payment.partially_paid') {
  const payment = event.data.object;
  await sms.send(customerPhone, `Received ${payment.amount_received} rial. Pay the remaining ${payment.amount_remaining} here: ${payment.checkout_url}`);
}

افزونه‌های فروشگاهی این کار را خودشان می‌کنند: سفارش در حالت انتظار می‌رود و یادداشتی با مبلغ رسیده و باقی‌مانده می‌گیرد.

وقتی صفحهٔ پرداخت زودتر بسته شود

بعد از expires_at مبلغ تکمیلی خودکار صادر نمی‌شود. پرداختی که هنگام بسته شدن صفحه هنوز ناقص است، یا بعد از بسته شدن واریز کمتری می‌گیرد، با review.reason برابر expired_partial به نیاز به بررسیrequires_review می‌رود. آن وقت انتخاب با شماست:

وقتی صفحهٔ پرداخت زودتر بسته شود
کارAPIنتیجه
خواستن بقیهPOST /v1/payments/:id/topup با expires_inیک مبلغ یکتای تازه برای باقی‌مانده و زمان انقضای تازه. دوباره checkout_url را برای مشتری بفرستید.
پذیرفتن مبلغ رسیدهPOST /v1/payments/:id/approve با reasonپرداخت موفق می‌شود و تفاوت در amount_shortfall ثبت می‌شود.
کنار گذاشتنPOST /v1/payments/:id/cancelپرداخت لغو می‌شود و پول رسیده بدهی شما به مشتری ثبت می‌شود.
curl https://a.bezanbecard.com/v1/payments/pay_…/topup \
  -H "Authorization: Bearer sk_test_…" \
  -H "Idempotency-Key: topup-1042-1" \
  -H "Content-Type: application/json" \
  -d '{"expires_in":1800}'

خاموش کردن پرداخت ناقص

پرداخت ناقص به‌طور پیش‌فرض روشن است. آن را برای کل حساب در تنظیمات پرداخت داشبورد خاموش کنید، یا برای یک پرداخت با "allow_partial": false. در این صورت واریز کمتر یا تأیید بخشی از مبلغ، پرداخت را با review.reason برابر partial_disabled به نیاز به بررسیrequires_review می‌برد و یک نفر تصمیم می‌گیرد.

امتحان در حالت آزمایشی

با رسید، بدون هیچ پیامکی:

  1. یک پرداخت آزمایشی بسازید، checkout_url آن را باز کنید، هر عکسی را به‌عنوان رسید بارگذاری کنید و «فرستادن رسید» را بزنید.
  2. در رسیدها آن را با مبلغ ۱۰٬۰۰۰٬۰۰۰ ریال تأیید کنید. پرداخت کم‌واریزpartially_paid می‌شود و صفحهٔ پرداخت مبلغ تازه را نشان می‌دهد.
  3. از صفحهٔ پرداخت رسید دومی بفرستید و آن را با مبلغ پیش‌فرض، یعنی همان مبلغ تکمیلی، تأیید کنید. پرداخت موفق می‌شود.

یا با واریز بانکی شبیه‌سازی‌شده: واریز کمتر را شبیه‌سازی و وصل کنید و بعد بقیه را شبیه‌سازی کنید:

const deposit = await bezanbecard.testHelpers.deposits.create({ payment: 'pay_…', amount: 10_000_000 });
await bezanbecard.payments.attachDeposit('pay_…', { deposit: deposit.id });
await bezanbecard.testHelpers.deposits.create({ payment: 'pay_…' }); // the new expected amount

واریز کمتری که هیچ نشانه‌ای ندارد، درست مثل یک واریز واقعی وصل‌نشده می‌ماند؛ برای همین نمونه آن را دستی وصل می‌کند. وقتی تأیید خودکار خاموش است (پیش‌فرض)، آخرین واریز پرداخت را با auto_disabled در بررسی نگه می‌دارد تا تأییدش کنید، همان‌طور که پیامک واقعی بانک هم می‌کند.