勉強したことのメモ

Webエンジニア / プログラマが勉強したことのメモ。

PHPとPAY.JPを用いてサイト内にクレカ決済及びキャンセル機能を実装する方法

   2025/06/19  PHP

先日PHPとStripeを用いてサイト内にクレカ決済及びキャンセル機能を実装する方法をメモしたが、手数料の比較であったりスキルの引き出しを増やす意味で他の決済システムも使えるようになっておきたい。調べたところPAY.JPが国産且つテスト可能っぽいので、PAY.JPを用いて決済及びキャンセル(返金)処理の実装方法をメモ。

 

PAY.JP

公式サイト

https://pay.jp/

 

下準備

アカウント作成

公式サイトでアカウントを作成しておく。

左メニューのAPI設定に進むと「テスト秘密鍵」「テスト公開鍵」が発行されるのでメモしておく。

ライブラリのインストール

サーバにSSH接続し適当なディレクトリに移動後、以下でライブラリをインストールする。

composer require payjp/payjp-php

ライブラリの要件はPHP5.6以降とのこと。尚、当方の環境はPHP8.3.3になる。

テスト用クレジットカード

テスト用のクレジットカードはこちらのページより確認できる。有効期限は「12 / 34」等の未来日付、セキュリティコードは「123」等の任意の3桁の数値となる。

 

クレジットカード決済機能の実装方法

index.php(カード情報入力ページ)

公開鍵部分は適宜変更すること。

<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<script src="https://js.pay.jp/v2/pay.js"></script>
</head>
<body>
    <h1>カード情報入力</h1>
    <form id="payment-form" method="post" action="checkout.php">
        <div id="card-element">
        </div>
        <input type="hidden" name="card_token" id="card-token">
        <button type="submit">支払う</button>
    </form>

    <script>
        document.addEventListener('DOMContentLoaded', function () {
            const payjp = Payjp('pk_test_xxxxx'); //公開鍵
            const elements = payjp.elements();
            const card = elements.create('card');
            card.mount('#card-element');

            const form = document.getElementById('payment-form');
            form.addEventListener('submit', async function (e) {
                e.preventDefault();

                const result = await payjp.createToken(card);

                if (result.error) {
                    console.error(result.error.message);
                    alert('カード情報のトークン化に失敗しました: ' + result.error.message);
                } else {
                    const token = result.id;
                    document.getElementById('card-token').value = token; 
                    form.submit();
                }
            });
        });
    </script>
</body>
</html>

checkout.php(決済処理ページ)

秘密鍵、金額部分は適宜変更すること。

また、コメントにも記述しているが決済成功後の「$result->id」は後述のキャンセル(返金)時に必要になるためMySQL等に保存すること。

<?php
require 'vendor/autoload.php';
use Payjp\Payjp;

if( $_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['card_token']) ){
    $apiKey = 'sk_test_xxxxx'; //秘密鍵
    $amount = 500; //金額
    $currency = 'jpy';
    $cardToken = $_POST['card_token'];

    function chargeCreditCard($apiKey, $amount, $currency, $cardToken) {
        Payjp::setApiKey($apiKey);

        try{
            $charge = \Payjp\Charge::create([
                "amount" => $amount,
                "currency" => $currency,
                "card" => $cardToken,
                "description" => "Sample Charge"
            ]);
            return $charge;

        }catch(\Payjp\Error\Base $e){
            $error_body = $e->getJsonBody();
            $error_message = $error_body['error']['message'];
            return "Error: " . $error_message;
        }
    }

    $result = chargeCreditCard($apiKey, $amount, $currency, $cardToken);

    //決済成功時の処理
    if( is_object($result) && $result->paid ){

        var_dump($result->id); //「ch_xxxxxxx」のようなIDが出力されるので、こちらをデータベースに保存すること。

    //決済失敗時の処理
    }else{

    }

//その他エラー
}else{

}

 

決済キャンセル(返金)処理の実装方法

cancel.php

秘密鍵、決済成功時に発行されたID部分は適宜変更すること。

尚、成功時はオブジェクトが返り、失敗時は「Error: Charge "ch_xxxxx" has already been refunded.」のようなエラーメッセージが返ってくる。

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

use Payjp\Payjp;

function retrieveCreditCard($apiKey, $id) {
    Payjp::setApiKey($apiKey);

    try{
        $charge = \Payjp\Charge::retrieve($id);
        $charge->refund();
        return $charge;

    }catch(\Payjp\Error\Base $e){
        $error_body = $e->getJsonBody();
        $error_message = $error_body['error']['message'];
        return "Error: " . $error_message;
    }
}

$apiKey = 'sk_test_xxxxx'; //秘密鍵
$id = 'ch_xxxxx'; //決済成功時に発行されたID

$result = retrieveCreditCard($apiKey, $id);
var_dump($result);

 

手数料について

Stripeは公式ページを見ると初期費用無料、月額費や追加手数料なしで国内カード決済の場合1件あたり3.6%の手数料。ただ、取引額が多いような場合は要問い合わせで多少は勉強してもらえるかも。

PAY.JPは公式ページを見ると3段階のプランがあり、月額費用無料の場合だと1件あたり3.6%、月額費用有料の場合は2.59~2.78%とのこと。

 

所感

PAY.JPは国産のためかリファレンスが日本語なのが助かる。また、Stripeより利用者が少ないのかダッシュボードが軽い(Stripeは非常に重い)。

デメリットとしてStripeより利用者がすくないためか検索しても情報量が少ない。

基本的にはStripeを使っていく方が安心だろうけど、PAY.JPも引き出しとして覚えておきたいところ。

 

参考サイト

https://qiita.com/keitakei777/items/d781ea95984cb9235967

https://docs.pay.jp/v1/api/?php#%E8%BF%94%E9%87%91%E3%81%99%E3%82%8B

 

 - PHP

  関連記事

Stripeでキャンセル処理を行う際に「$config must be a string ~」エラーが出る場合の対応方法

Stripeにて先日メモした内容でキャンセル(返金)処理をしようとしたところ1件 ...

PHPとStripeを使ってサイト内でクレジットカード決済処理の実装方法

PHPとStripeの組み合わせでWebサービスにクレジットカード決済処理を導入 ...

PHPにてサイトにPayPay決済システム及び決済キャンセル機能を実装する方法

ここのところクレジットカード決済関連のメモを書いているが、他の決済方法についても ...

Stripe Checkoutにてクレジットカード決済の際に3Dセキュア対応にする方法

先日Stripe Checkoutを用いたクレジットカード決済機能についてメモし ...

PHPとStripeで定額課金(サブスクリプション)実装する方法

PHPとStripeで1ヶ月ごとに500円でサイト内のサービスを使い放題、といっ ...