เช็คสลิปโอนเงินด้วย PHP ต่อ API ตรวจสลิปในร้านของคุณ

เช็คสลิปโอนเงินด้วย PHP: ตัวอย่างโค้ดส่งสลิปแล้วได้ผลพบรายการ

ร้านที่รับโอนเงินหลายสิบออเดอร์ต่อวัน เปิดแอปธนาคารเทียบสลิปทีละใบไม่ทัน บทความนี้พาต่อระบบหลังร้านที่เขียนด้วย PHP เข้ากับ Checkslip API ให้ระบบเช็คสลิปกับธนาคารเองทุกออเดอร์ ลูกค้าอัปโหลดสลิป ระบบได้ผลจากธนาคารภายในไม่กี่วินาที แล้วร้านตัดสินใจยืนยันออเดอร์จากข้อมูลนั้น

ขั้นตอนเช็คสลิปด้วย PHP: ลูกค้าอัปโหลดสลิป ระบบร้านส่งไป Checkslip API ดึงข้อมูลจากธนาคาร แล้วเทียบยอดกับออเดอร์

สิ่งที่ต้องมีก่อนเริ่ม

  • PHP 7.4 ขึ้นไป ที่เปิด curl (เว็บโฮสติ้งทั่วไปเปิดไว้แล้ว)
  • API key ของ Checkslip สมัครแล้วออก key ได้ที่หน้า API key ตาม เริ่มต้นใช้งาน บัญชีใหม่ได้เครดิตทดลองฟรี
  • เก็บ key ไว้ในตัวแปรสภาพแวดล้อม CHECKSLIP_API_KEY บนเซิร์ฟเวอร์ ห้ามใส่ในโค้ดหน้าเว็บ

ขั้นที่ 1: ส่งรูปสลิปไปเช็คกับธนาคาร

ฟังก์ชันนี้รับไฟล์สลิปที่ลูกค้าอัปโหลด ส่งไปที่ API แล้วคืนคำตอบเป็น array

<?php
function checkslip_lookup(string $imagePath, string $idempotencyKey): array
{
    $ch = curl_init('https://api.checkslip.com/api/slips/lookup');
    curl_setopt_array($ch, [
        CURLOPT_POST => true,
        CURLOPT_RETURNTRANSFER => true,
        CURLOPT_TIMEOUT => 30,
        CURLOPT_HTTPHEADER => [
            'Authorization: Bearer ' . getenv('CHECKSLIP_API_KEY'),
            'Idempotency-Key: ' . $idempotencyKey,
        ],
        CURLOPT_POSTFIELDS => ['image' => new CURLFile($imagePath)],
    ]);
    $body = curl_exec($ch);
    $status = curl_getinfo($ch, CURLINFO_RESPONSE_CODE);
    curl_close($ch);
    if ($body === false) {
        throw new RuntimeException('เชื่อมต่อ API ไม่ได้ ให้ส่งซ้ำด้วย Idempotency-Key เดิม');
    }
    $data = json_decode($body, true) ?? [];
    $data['_http_status'] = $status;
    return $data;
}

รูปที่ส่งต้องเป็น JPEG, PNG หรือ WebP ขนาดไม่เกิน 10 MB และไม่เกิน 50 ล้านพิกเซล รูป HEIC (ค่าเริ่มต้นของกล้อง iPhone), GIF และ PDF จะได้ 422 invalid-file และไม่หักเครดิต ส่วนรูปที่ใหญ่เกิน 10 MB ได้ 413 ถ้าลูกค้าส่งรูปจาก iPhone ให้แปลงเป็น JPEG ก่อนส่ง

ถ้าอ่านข้อความใน QR บนสลิปไว้แล้ว ส่ง QR แทนรูปได้ เปลี่ยน CURLOPT_POSTFIELDS เป็น json_encode(['qr' => $qrText]) และเพิ่ม header Content-Type: application/json

ขั้นที่ 2: ตัดสินจากผลที่ได้

ให้ดู outcome ใน body ไม่ใช่ HTTP status ผลที่ร้านใช้บ่อยมี 3 แบบ:

  • FOUND: พบรายการ ธนาคารมีรายการโอนนี้ ระบบหัก 1 เครดิต
  • NOT_FOUND: ไม่พบรายการ ณ เวลาที่ถาม ไม่หักเครดิต
  • DUPLICATE: บัญชีของร้านเคยเช็คสลิปใบนี้แล้ว ไม่หักเครดิต

ผลอื่น เช่น PENDING (รอธนาคาร) และความหมายของทุกผล ดูได้ที่ ผลตรวจรายการโอน

ขั้นที่ 3: เทียบกับออเดอร์ก่อนยืนยัน

ผล FOUND บอกว่าธนาคารมีรายการนี้ ร้านยังต้องเทียบยอดเงินและบัญชีผู้รับกับออเดอร์เอง ยอดเงินมาเป็นสตางค์ (5000 = 50 บาท) และบัญชีผู้รับมาเป็นเลข 4 หลักท้าย

<?php
function decide_order(array $result, int $orderSatang, string $shopAccountLast4): string
{
    switch ($result['outcome'] ?? '') {
        case 'FOUND':
            $slip = $result['slip'];
            if ($slip['amount']['satang'] !== $orderSatang) {
                return 'ยอดไม่ตรงกับออเดอร์';
            }
            if (($slip['receiver']['account'] ?? '') !== $shopAccountLast4) {
                return 'โอนเข้าบัญชีอื่น';
            }
            return 'ยืนยันออเดอร์ได้';
        case 'DUPLICATE':
            return 'สลิปนี้เคยใช้กับร้านแล้ว ดูออเดอร์เดิมจาก duplicate_of.request_id';
        case 'NOT_FOUND':
            return 'ไม่พบรายการ ขอหลักฐานเพิ่มจากลูกค้า';
        case 'PENDING':
            return 'รอธนาคาร ระบบจะส่งผลทาง webhook';
        default:
            return 'เช็คไม่ได้ ดูรายละเอียดใน type ของคำตอบ';
    }
}

$result = checkslip_lookup($_FILES['slip']['tmp_name'], 'order-1042-slip-1');
echo decide_order($result, 5000, '9681');

ใช้ Idempotency-Key ให้ถูก

ตั้ง Idempotency-Key ให้ผูกกับออเดอร์และสลิปใบนั้น เช่น order-1042-slip-1 ถ้าเน็ตหลุดก่อนได้คำตอบ ส่งคำขอเดิมซ้ำด้วยคีย์เดิม จะได้คำตอบเดิมกลับมาและไม่หักเครดิตเพิ่ม ถ้าส่งซ้ำด้วยคีย์ใหม่ ครั้งที่สองจะได้ DUPLICATE แล้วโค้ดอาจเข้าใจผิดว่าลูกค้าใช้สลิปซ้ำ

ใช้กับ WordPress ได้ไหม?

ได้ ฟังก์ชันข้างบนเป็น PHP ธรรมดา วางในปลั๊กอินหรือ functions.php ของธีม แล้วเรียกตอนลูกค้าอัปโหลดสลิปในหน้าชำระเงิน ใช้ wp_handle_upload รับไฟล์ก่อน แล้วส่ง path ของไฟล์ให้ checkslip_lookup

ต่อจากนี้