Skip to main content

Payment & Refund Requirements

หน้านี้รวม Functional Requirements, Acceptance Criteria และ Business Rule Matrix สำหรับ QA/BA
อ้างอิง: ccr-payment-service, PaymentTransactionService.cs, RefundController, Omise webhook docs


US-P01: ชำระเงิน Booking (Customer)

As a ลูกค้า
I want to ชำระเงินค่าจอง
So that booking ถูก confirm และฉันได้รับการยืนยันการจอง

Acceptance Criteria

#เงื่อนไขผลลัพธ์ที่คาดหวัง
AC1เลือกชำระผ่าน PromptPay/TrueMoneyแสดง QR Code ที่สแกนได้ (ScannableCodeUri)
AC2เลือกชำระผ่านบัตรเครดิต/เดบิต (ใหม่)แสดง form กรอกข้อมูลบัตร; บัตร Member ถูกบันทึกเพื่อใช้ครั้งต่อไป
AC3Member เลือกบัตรที่บันทึกไว้ชำระเงินโดยไม่ต้องกรอกข้อมูลบัตรใหม่
AC4ชำระเงินสำเร็จ (Omise webhook charge.complete + status = successful)Booking สถานะ Confirm, ลูกค้าได้รับ email confirmation
AC5ชำระเงินไม่สำเร็จ (Omise webhook status ≠ successful)Transaction NotCompleted, payment status Failed, แจ้งลูกค้า
AC6ไม่ชำระเงินภายในเวลาที่กำหนดBooking สถานะ Expired, ไม่สามารถชำระได้อีก
AC7Guest พยายามชำระ booking ของ Memberระบบ reject
AC8Member พยายามชำระ booking ของคนอื่นระบบ reject

Business Rules

BR#Ruleตัวอย่าง
BR-P01-1Guest payment: booking ต้องไม่มี CreatedByBooking ที่สร้างโดย Guest ไม่มี customerId
BR-P01-2Member payment: booking.CreatedBy ต้องตรงกับ customerId ใน tokenMember A ชำระได้แค่ booking ตัวเอง
BR-P01-3Expired booking: status = Expired หรือ now >= ExpireAt → rejectถ้าหมดเวลา ระบบปฏิเสธการชำระ
BR-P01-4ยอดชำระ = AdditionalAmount ถ้าบวก; ไม่งั้นใช้ booking.AmountEdit เพิ่มเงิน 500 → ต้องชำระ 500 ไม่ใช่ยอดเต็ม
BR-P01-5ทุกการชำระ: สร้าง transaction status Pending ก่อนเรียก Omiseป้องกัน duplicate charge
BR-P01-6Non-card (PromptPay/TrueMoney): flow CreateChargeWithSourceAsyncได้ AuthorizeUri และ ScannableCodeUri
BR-P01-7Member ชำระด้วยบัตรใหม่: save CustomerToken ใน SavedPaymentMethodsครั้งต่อไปเลือกบัตรเดิมได้

US-P02: Payment Timeout และ Retry

As a ลูกค้า
I want to รู้ว่า QR code / payment link หมดอายุ
So that ฉันสามารถดำเนินการต่อได้อย่างถูกต้อง

Acceptance Criteria

#เงื่อนไขผลลัพธ์ที่คาดหวัง
AC1QR code / payment timeoutแสดง modal payment-time-expired
AC2Booking status Expiredลูกค้าไม่สามารถชำระเงินซ้ำได้, ต้องสร้าง booking ใหม่
AC3ชำระ PromptPay แล้วรอ webhook ส่งมาช้า (Omise processing)แสดง pending state; ไม่ confirm ทันที

US-P03: Refund หลังยกเลิก Booking

As a ลูกค้า
I want to ได้รับเงินคืนหลังยกเลิก booking
So that ฉันมั่นใจว่าได้เงินตาม cancellation policy

Acceptance Criteria

#เงื่อนไขผลลัพธ์ที่คาดหวัง
AC1ยกเลิก booking สำเร็จระบบสร้าง Refund record สถานะ Created อัตโนมัติ
AC2Payment method = PromptPay / TrueMoneyระบบร้องขอ bank account (bank code, account number, account name, image)
AC3Payment method = บัตรเครดิตระบบ refund ผ่าน Omise (สถานะขึ้นกับ Backoffice workflow)
AC4Backoffice อัปเดต refund status ตาม workflowแสดงสถานะล่าสุดให้ลูกค้าเห็น
AC5Refund amount ถูกคำนวณถูกต้องRefund = TotalPrice - CancellationFee

:::warning ขอบเขต Phase 1 Auto Refund อยู่นอก Phase 1 — การคืนเงินเป็น Manual Workflow โดย Backoffice ทั้งหมด :::

Refund Allocation Rule

Ruleรายละเอียดตัวอย่าง
ลำดับการตัดยอดตัดจาก transaction ที่ PaidAt เก่าที่สุดก่อนจ่าย 2 ครั้ง: 2,000 (วันที่ 1) และ 1,000 (วันที่ 3) → refund 1,500 → ตัดจาก 2,000 ก่อน
Bank accountRequired เมื่อ payment method เป็น transfer-like method (PromptPay, TrueMoney)ถ้าไม่มี bank account → flow หยุด

US-P04: Backoffice — ดำเนินการ Refund

As a Staff (Backoffice)
I want to อัปเดตสถานะ refund ตาม workflow
So that ลูกค้าได้รับเงินคืนอย่างถูกต้องและมีการตรวจสอบหลายระดับ

Acceptance Criteria

#เงื่อนไขผลลัพธ์ที่คาดหวัง
AC1Staff มี permission operation:refund:update-sale-checkedสามารถเปลี่ยนสถานะเป็น SaleChecked ได้
AC2Staff มี permission operation:refund:update-sale-approvedสามารถเปลี่ยนสถานะเป็น SaleApproved ได้
AC3Staff มี permission operation:refund:update-accounting-approvedสามารถเปลี่ยนสถานะเป็น AccountingApproved ได้
AC4Staff มี permission operation:refund:update-refundedสามารถเปลี่ยนสถานะเป็น Refunded ได้
AC5ข้ามขั้นตอน เช่น CreatedAccountingApprovedระบบ reject (ต้องทำตามลำดับ)
AC6Refund ถูก Rejected แล้วไม่สามารถเปลี่ยนสถานะต่อได้
AC7Staff ไม่มี permissionปุ่ม action ไม่แสดง, API ตอบ 403

Refund Status Workflow

Created


SaleChecked ◄── sale team ตรวจสอบ (permission: update-sale-checked)


SaleApproved ◄── sale team อนุมัติ (permission: update-sale-approved)


AccountingApproved ◄── accounting อนุมัติ (permission: update-accounting-approved)


Refunded ◄── บันทึกว่าโอนเงินแล้ว (permission: update-refunded)

ทุก stage สามารถ → Rejected

US-P05: Edit Booking ที่ต้องชำระเพิ่ม

As a ลูกค้า
I want to ชำระเงินส่วนต่างหลังแก้ไข booking
So that booking ถูก confirm กลับมาหลังชำระส่วนต่าง

Acceptance Criteria

#เงื่อนไขผลลัพธ์ที่คาดหวัง
AC1Edit booking และราคาใหม่สูงกว่าเดิมBooking กลับเป็น Created พร้อม AdditionalAmount
AC2ลูกค้าชำระส่วนต่างสำเร็จBooking กลับเป็น Confirm
AC3ลูกค้าไม่ชำระส่วนต่างภายในเวลาที่กำหนดBooking Expired
AC4Edit booking และราคาใหม่ต่ำกว่าเดิมBooking ยังสถานะ Confirm มี RefundAmount รอดำเนินการ Backoffice

Business Rule Summary — Payment & Refund

IDRuleค่า
BR-P-01Guest ชำระ booking ที่ไม่มี CreatedByต้องไม่มี CreatedBy
BR-P-02Member ชำระ booking ที่ CreatedBy == customerIdต้องตรงกัน
BR-P-03Booking expired เมื่อ status = Expired หรือ now >= ExpireAtreject payment
BR-P-04Additional amount: ใช้ AdditionalAmount ถ้าบวกชำระแค่ส่วนต่าง
BR-P-05Non-card flowCreateChargeWithSourceAsync → QR
BR-P-06Card saveMember ชำระด้วยบัตรใหม่ → save token
BR-P-07Webhook charge.complete + successful → Confirm bookingOmise callback
BR-P-08Refund allocation: ตัดจาก transaction เก่าก่อนPaidAt ascending
BR-P-09Bank account required เมื่อ refund ผ่าน PromptPay/TrueMoneyต้องกรอกก่อน
BR-P-10Refund Phase 1 = Manual WorkflowAuto refund ยังไม่มี
BR-P-11Refund ต้องทำตาม workflow ตามลำดับข้ามขั้นตอนไม่ได้