본문으로 건너뛰기

เนื้อหาภาษาไทย / 태국어 콘텐츠

시스템 가이드 검수 완료된 콘텐츠

ทดสอบการชำระเงิน: Stripe

บทความนี้อธิบายวิธีการทดสอบการชำระเงินผ่าน Stripe โดยใช้คลาส `StripePayment` ที่สร้างไว้ในบทก่อนหน้า โดยเริ่มต้นจากการเตรียม Stripe API Keys และสร้าง Form รับข้...

ทดสอบการชำระเงิน: Stripe

ในบทที่แล้ว เราได้สร้าง PaymentGatewayFactory ซึ่งเป็น Factory Pattern ที่ช่วยให้เราสร้าง Instance ของคลาส StripePayment และ PayPalPayment ได้อย่างง่ายดาย ในบทนี้ เราจะมาทดสอบการชำระเงินผ่าน Stripe โดยใช้คลาส StripePayment ที่เราได้สร้างไว้

เตรียมความพร้อม: Stripe API Keys

ก่อนที่เราจะเริ่มทดสอบการชำระเงินได้ เราจะต้องมี Stripe API Keys เสียก่อน Stripe API Keys ประกอบด้วย:

  • Publishable Key: ใช้ใน Frontend เพื่อแสดง Stripe Elements (เช่น Form สำหรับกรอกข้อมูลบัตรเครดิต)
  • Secret Key: ใช้ใน Backend เพื่อเรียกใช้ API ของ Stripe (เช่น การเรียกเก็บเงิน)

คุณสามารถรับ Stripe API Keys ได้โดยการสร้าง Account บน Stripe และเข้าไปที่ Dashboard เพื่อดู Keys ของคุณ

ข้อควรระวัง: อย่าเปิดเผย Secret Key ของคุณให้ใครทราบ เพราะมันสามารถใช้ในการเรียกเก็บเงินจาก Account ของคุณได้

สร้าง Form สำหรับรับข้อมูลบัตรเครดิต

เราจะเริ่มต้นด้วยการสร้าง Form สำหรับรับข้อมูลบัตรเครดิตจากผู้ใช้ โดยเราจะใช้ Stripe Elements ซึ่งเป็นชุด Component UI ที่ Stripe เตรียมไว้ให้ เพื่อให้การสร้าง Form เป็นเรื่องง่ายและปลอดภัย

Stripe Elements ช่วยลดภาระในการจัดการข้อมูลบัตรเครดิตที่ละเอียดอ่อน ทำให้เราไม่ต้องกังวลเรื่อง PCI compliance มากนัก เพราะ Stripe จะจัดการข้อมูลเหล่านี้ให้เราโดยตรง

สร้างไฟล์ payment.php และใส่โค้ดต่อไปนี้:

<?php
require_once 'vendor/autoload.php';

// Replace with your Stripe Publishable Key
$stripePublishableKey = 'YOUR_STRIPE_PUBLISHABLE_KEY';
?>

<!DOCTYPE html>
<html>
<head>
  <title>Stripe Payment</title>
  <script src="https://js.stripe.com/v3/"></script>
</head>
<body>
  <h2>Stripe Payment</h2>

  <form action="charge.php" method="post" id="payment-form">
    <div class="form-row">
      <label for="card-element">
        Credit or debit card
      </label>
      <div id="card-element">
        <!-- A Stripe Element will be inserted here. -->
      </div>

      <!-- Used to display form errors. -->
      <div id="card-errors" role="alert"></div>
    </div>

    <button>Submit Payment</button>
  </form>

  <script>
    // Create a Stripe client.
    var stripe = Stripe('<?php echo $stripePublishableKey; ?>');

    // Create an instance of Elements.
    var elements = stripe.elements();

    // Create an instance of the card Element.
    var card = elements.create('card');

    // Add an instance of the card Element into the `card-element` div.
    card.mount('#card-element');

    // Handle real-time validation errors from the card Element.
    card.on('change', function(event) {
      var displayError = document.getElementById('card-errors');
      if (event.error) {
        displayError.textContent = event.error.message;
      } else {
        displayError.textContent = '';
      }
    });

    // Handle form submission.
    var form = document.getElementById('payment-form');
    form.addEventListener('submit', function(event) {
      event.preventDefault();

      stripe.createToken(card).then(function(result) {
        if (result.error) {
          // Inform the user if there was an error.
          var errorElement = document.getElementById('card-errors');
          errorElement.textContent = result.error.message;
        } else {
          // Send the token to your server.
          stripeTokenHandler(result.token);
        }
      });
    });

    // Submit the form with the token ID.
    function stripeTokenHandler(token) {
      // Insert the token ID into the form so it gets submitted to the server
      var form = document.getElementById('payment-form');
      var hiddenInput = document.createElement('input');
      hiddenInput.setAttribute('type', 'hidden');
      hiddenInput.setAttribute('name', 'stripeToken');
      hiddenInput.setAttribute('value', token.id);
      form.appendChild(hiddenInput);

      // Submit the form
      form.submit();
    }
  </script>
</body>
</html>

คำอธิบายโค้ด:

  • เรา include vendor/autoload.php เพื่อให้ Composer โหลด Class ต่างๆ ที่เราใช้
  • เรากำหนด $stripePublishableKey ด้วย Publishable Key ของ Stripe
  • เราใช้ Stripe JavaScript library เพื่อสร้าง Form สำหรับรับข้อมูลบัตรเครดิต
  • เมื่อผู้ใช้ Submit Form, Stripe จะสร้าง Token ซึ่งเป็น Representation ของข้อมูลบัตรเครดิต
  • เราส่ง Token ไปยัง Server (charge.php) เพื่อทำการเรียกเก็บเงิน

เรียกใช้ method `charge()`

สร้างไฟล์ charge.php และใส่โค้ดต่อไปนี้:

<?php
require_once 'vendor/autoload.php';

use PaymentGateway\PaymentGatewayFactory;

// Replace with your Stripe Secret Key
$stripeSecretKey = 'YOUR_STRIPE_SECRET_KEY';

// Set your secret key: remember to switch to your live secret key in production
\Stripe\Stripe::setApiKey($stripeSecretKey);

if ($_SERVER['REQUEST_METHOD'] === 'POST') {
  $token = $_POST['stripeToken'];
  $amount = 1000; // Amount in cents (e.g., $10.00)
  $currency = 'usd';

  try {
    // Create a charge: this will charge the user's card
    $factory = new PaymentGatewayFactory();
    $stripePayment = $factory->create('stripe');

    // Assuming charge() method accepts amount, currency, and token
    $chargeResult = $stripePayment->charge($amount, $currency, $token);

    if ($chargeResult['status'] === 'succeeded') {
      echo '<h2>Payment Successful!</h2>';
      echo '<p>Charge ID: ' . $chargeResult['id'] . '</p>';
    } else {
      echo '<h2>Payment Failed!</h2>';
      echo '<p>Error: ' . $chargeResult['message'] . '</p>';
    }

  } catch (\Stripe\Exception\CardException $e) {
    // Since it's a decline, \Stripe\Exception\CardException will be caught
    echo '<h2>Payment Declined!</h2>';
    echo '<p>Status is: ' . $e->getHttpStatus() . '</p>';
    echo '<p>Error is: ' . $e->getMessage() . '</p>';
  } catch (\Stripe\Exception\RateLimitException $e) {
    // Too many requests made to the API too quickly
    echo '<h2>Rate Limit Exceeded!</h2>';
    echo '<p>Error: ' . $e->getMessage() . '</p>';
  } catch (\Stripe\Exception\InvalidRequestException $e) {
    // Invalid parameters were supplied to Stripe's API
    echo '<h2>Invalid Request!</h2>';
    echo '<p>Error: ' . $e->getMessage() . '</p>';
  } catch (\Stripe\Exception\AuthenticationException $e) {
    // Authentication with Stripe's API failed
    // (maybe you changed API keys recently)
    echo '<h2>Authentication Failed!</h2>';
    echo '<p>Error: ' . $e->getMessage() . '</p>';
  } catch (\Stripe\Exception\ApiConnectionException $e) {
    // Network communication with Stripe failed
    echo '<h2>Network Error!</h2>';
    echo '<p>Error: ' . $e->getMessage() . '</p>';
  } catch (\Stripe\Exception\ApiErrorException $e) {
    // Display a very generic error to the user, and maybe send
    // yourself an email
    echo '<h2>Generic Error!</h2>';
    echo '<p>Error: ' . $e->getMessage() . '</p>';
  } catch (Exception $e) {
    // Something else happened, completely unrelated to Stripe
    echo '<h2>Unexpected Error!</h2>';
    echo '<p>Error: ' . $e->getMessage() . '</p>';
  }
} else {
  echo '<h2>Invalid Request!</h2>';
  echo '<p>This page should be accessed via POST method.</p>';
}
?>

คำอธิบายโค้ด:

  • เรา include vendor/autoload.php เพื่อให้ Composer โหลด Class ต่างๆ ที่เราใช้
  • เรากำหนด $stripeSecretKey ด้วย Secret Key ของ Stripe
  • เราดึง Token ที่ส่งมาจาก Form
  • เราสร้าง Instance ของ StripePayment โดยใช้ PaymentGatewayFactory
  • เราเรียกใช้ method charge() ของ StripePayment เพื่อทำการเรียกเก็บเงิน
  • เราตรวจสอบผลลัพธ์และแสดงผลให้ผู้ใช้
  • เราจัดการ Exception ต่างๆ ที่อาจเกิดขึ้นระหว่างการเรียกเก็บเงิน

ข้อควรระวัง: ใน Production environment, คุณควรเก็บ Secret Key ใน Environment variable หรือ Configuration file ที่ปลอดภัย ไม่ควร Hardcode Secret Key ในโค้ด

ตรวจสอบผลลัพธ์

เมื่อคุณกรอกข้อมูลบัตรเครดิตใน Form และ Submit, ระบบจะทำการเรียกเก็บเงินผ่าน Stripe และแสดงผลลัพธ์ให้คุณ

ถ้าการชำระเงินสำเร็จ, คุณจะเห็นข้อความ "Payment Successful!" พร้อม Charge ID

ถ้าการชำระเงินไม่สำเร็จ, คุณจะเห็นข้อความ "Payment Failed!" พร้อม Error message

คุณสามารถตรวจสอบรายละเอียดของการชำระเงินได้ใน Stripe Dashboard

เหตุผลเชิงออกแบบและแนวปฏิบัติที่ดี

การใช้ Factory Pattern ในการสร้าง Instance ของ StripePayment ช่วยให้เราสามารถสลับ Payment Gateway ได้อย่างง่ายดาย โดยไม่ต้องแก้ไขโค้ดที่เรียกใช้ Payment Gateway

การใช้ Stripe Elements ช่วยให้เราไม่ต้องกังวลเรื่อง PCI compliance มากนัก เพราะ Stripe จะจัดการข้อมูลบัตรเครดิตให้เราโดยตรง

การจัดการ Exception ต่างๆ ที่อาจเกิดขึ้นระหว่างการเรียกเก็บเงิน ช่วยให้ระบบของเรามีความ Robust มากขึ้น

Trade-offs: การใช้ Stripe Elements อาจทำให้เราสูญเสียความยืดหยุ่นในการปรับแต่ง Form แต่แลกมาด้วยความปลอดภัยและความสะดวกในการใช้งาน

ในบทถัดไป เราจะมาทดสอบการชำระเงินผ่าน PayPal

Office.in.th Custom Service

이 구조를 바탕으로 시스템을 개발하거나 맞춤 변경하고 싶으신가요?

Office.in.th는 엔터프라이즈 웹 애플리케이션, API 연동, 공공/민간 업무 관리 시스템을 설계·개발하며 장기 지원을 제공합니다.

소프트웨어 개발 서비스 보기