Stripe subscription และสถานะใบเรียกเก็บเงิน

การตั้งค่าของการเรียกชำระเงินแบบ subscription บน Stripe.com นั้นค่อนข้างจะมีปัญหากันมาก และที่พบบ่อยคือ แม้เมื่อรายการ subscription นั้นๆจะถูกยกเลิกไปแล้ว (canceled) จากการเรียกเก็บเงินไม่สำเร็จ แต่ในหน้า customer portal ยังคงมีการเรียกเก็บเงินอยู่ดี และเมื่อลูกค้าชำระเงินก็จะพบว่าเป็นการชำระไปยังรายการเรียกเก็บเงินเก่า แต่สถานะ subscription อาจยังคงเป็นการยกเลิกเหมือนเดิมไม่เปลี่ยนแปลงแม้จะไล่ชำระจนหมดแล้วก็ตาม.

ด้วยเหตุนี้เราจึงจะมาทดสอบการตั้งค่าต่างๆ เพื่อดูว่ามันจะมีผลเป็นอย่างไรในหน้า customer portal.

การทดสอบ

โค้ดที่ใช้ในการทดสอบ checkout.

$checkoutParams = [
    'line_items' => [[
        'price_data' => [
            'currency' => 'thb',
            'product_data' => [
                'name' => 'Made',
            ],
            'recurring' => [
                'interval' => 'day',
                'interval_count' => 1,
            ],
            'unit_amount' => 30000,
        ],
        'quantity' => 1,
    ]],
    'mode' => 'subscription',
    'customer_email' => 'user@test.localhost',
    'success_url' => 'success.html',
    'cancel_url' => 'canceled.html',
];
$checkout_session = \Stripe\Checkout\Session::create($checkoutParams);

การตั้งค่า Manage failed payments ให้ไปยังหน้า Settings แล้วคลิกเลือกที่เมนู Billing > Subscriptions and emails.

ในขั้นตอนการทดสอบ ให้เริ่มชำระเงินด้วยบัตรที่ใช้ได้ดังในหน้าเอกสาร. จากนั้นก่อนที่จะ Simulation ไปยังวันถัดไป ให้กดเข้า customer portal แล้วแก้ไขโดยเพิ่มบัตรที่ใช้ไม่ได้ ( Decline after attaching ) แล้วลบบัตรที่ใช้ได้ออก จากนั้นจึงค่อย Simulation ไปยังวันถัดไป.

Subscription: cancel; Invoice: past-due

Subscription: cancel; Invoice: past-due
Dashboard
Customer portal

จากตัวอย่างจะพบว่าแม้สถานะ subscription จะยกเลิกไปแล้วแต่หน้า customer portal ก็จะยังคงมีปุ่มเรียกเก็บเงิน และจากที่เคยทดสอบมา เมื่อกดชำระจนครบก็จะไม่เปลี่ยนสถานะ subscription ให้กลับมาเป็น active ได้อยู่ดี.

Subscription: cancel; Invoice: uncollectible

Subscription: cancel; Invoice: uncollectible
Dashboard

สิ่งที่แตกต่างออกไปคือ สถานะใบเรียกเก็บเงินจะเป็น uncollectible แค่นั้น.

Customer portal

จากการทดสอบนี้ พบว่า หน้า customer portal จะยังคงมีปุ่มเรียกเก็บเงินเช่นเดียวกัน เนื่องจากตั้งค่าสถานะ payment fail สำหรับ subscription เป็น cancel. และการชำระเงินจนครบก็ไม่ช่วยเปลี่ยนสถานะเช่นเคย.

Subscription: unpaid; Invoice: past-due

Subscription: unpaid; Invoice: past-due
Dashboard

ในหน้า Dashboard นั้น จากการ Run simulation ข้ามเวลาไปเรื่อยๆจะพบว่าแม้เลยขีดกำหนดไปเรื่อยๆเท่าไหร่ มันก็จะยังคงสร้าง draft ของใบเรียกเก็บเงินออกมาอยู่เรื่อยไป และสถานะของ subscription จะเป็น Unpaid ไม่ใช่ Canceled.

Customer portal

จากตัวอย่างการตั้งค่าแบบนี้ จะพบว่าในหน้า Customer portal รายการ subscription จะยังคงไม่ถูกยกเลิก มีเพียงรายการเรียกเก็บเงินที่แจ้งว่าล้มเหลว (Failed) และเมื่อทดลอง Run simulation ข้ามเวลาไปเรื่อยๆก็จะพบว่ามันยังคงอยู่เหมือนเดิมไม่มีการยกเลิก แต่จะมีปุ่มให้กดยกเลิกด้วยตัวเอง.

Subscription: unpaid; Invoice: uncollectible

Subscription: unpaid; Invoice: uncollectible
Dashboard

ในหน้า Dashboard จะพบว่าแม้เลยกำหนดชำระเงินไปนานเท่าใด ก็จะยังคงสร้าง draft ใบเรียกเก็บเงินออกมาเรื่อยๆ.

Customer portal

จากตัวอย่างจะพบว่าสิ่งที่แตกต่างจากการทดลองก่อนหน้าคือสถานะใบเรียกเก็บเงินจะเป็น Past due แทนที่จะเป็น Failed แต่สถานะ subscription จะยังคงไม่ยกเลิกและมีปุ่มให้ยกเลิกด้วยตัวเองเช่นเดิม.

การแก้ไข

สำหรับการแก้ไขให้ยกเลิกใบเรียกเก็บเงินนั้น ณ ปัจจุบัน จะยังคงไม่สามารถทำได้ผ่านการตั้งค่าบน Stripe แต่จะต้องใช้การโค้ดผ่าน webhooks ดังกรณีศึกษาจาก 2 เว็บไซต์ต่อไปนี้.

  1. https://stackoverflow.com/questions/77981419/how-to-void-a-invoice-automatically-in-stripe-after-automated-retries-have-faile
  2. https://www.reddit.com/r/stripe/comments/1f9xtnq/the_option_mark_the_invoice_as_uncollectible/

ใส่ความเห็น

อีเมลของคุณจะไม่แสดงให้คนอื่นเห็น ช่องข้อมูลจำเป็นถูกทำเครื่องหมาย *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>