0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

pay.jp 3D セキュア導入 php checkout編

0
Last updated at Posted at 2024-10-11

分かりづらいので、リダイレクト型で入れてみる

3Dセキュア導入してって

EMV3Dセキュアにつきましては、
2025年3月末までに、必須項目の追加および義務化
取引の安全性を高めらしい

参考

うーん複雑。超複雑。

2025/01/10 追記

スケジュールは?
https://pay.jp/info/2024/10/29/140000

ようは、2月4日から4月1日までは両方使えるから、
その期間に切り替えてね。

不安なら3Dセキュアのプレリリース版でテストしてね
ということか。
わかりづらすぎだろ。

自分の場合のデバッグ時の注意

デバッグする際は、2回目以降の同じカードの決済は tok エラーが出るので、
customer_idを使うようにする。
自分の場合は payjpテーブルからデータを抹消しないこと。
退会処理するときも、そもそもpayjpテーブルからデータを消していない。

既存から変更するには?

・エンドポイントは2月4日以降なら4月1日まで、そのままで利用できるよ
・メールアドレス必須だから追加してね
・checkout利用時は、一度 3d認証してからtokenを取得する手間が増える
・tokenを取得したらサーバーに送る

php側は、今までと同じだよ。

という流れにする。
たったこれだけのことをよくまーわかりづらく延々と・・・

自分の場合は rental-ojisan の kigengire2.ctp を参考に。。。

動くようになったのでphpのサンプル

流れ
・クレジットカード番号を入力
・ポップアップが開いて3D認証画面へ
・成功すると自動的にポップアップは閉じて、フォームを送信

スマホの場合はポップアップせずに画面が勝手に3dセキュアに切り替わる
親切設計。

だったら、リダイレクトなんて作らず、サブウィンドウだけでいいだろ。。。

pay.ctp
<script type="text/javascript">
    // トークン生成直後のコールバック
    function onCreatedToken(response) {
        console.log('onCreatedToken:', response);
        // 画面表示用など。ここではsubmitしない
        document.querySelector('#created-token').textContent = response.id;
    }

    // 一定間隔で監視して、トークンが入ったらフォーム送信
    setInterval(function() {
        const tokenSpan = document.querySelector('#created-token');
        if (tokenSpan && tokenSpan.textContent.trim() !== '') {
            // すでに値があれば、自動的にフォームを送信して終了
            const form = document.getElementById('payjp-form');
            if (form) {
                form.submit();
            }
        }
    }, 1000);


</script>

<form id="payjp-form" action="/payjp3ds/keizoku2/" method="post">

    <div>
        <div>
            <script
                    type="text/javascript"
                    src="https://checkout.pay.jp/prerelease"
                    data-payjp-key="<?=$config['key'];?>"
                    data-payjp-three-d-secure="true"
                    data-payjp-three-d-secure-workflow="subwindow"
                    data-payjp-partial="true"
                    data-payjp-extra-attribute-email="your@email.com"
                    data-payjp-on-created="onCreatedToken"
            ></script>
        </div>
        <div>
            <small>
                <span id="created-token"></span>
            </small>
        </div>
    </div>

    <br>
    <!-- value は何でも良いみたい -->
    <input type="hidden" name="csrf_token" value="csrf">
    <button type="submit">支払う</button>
</form>

サブウィンドウではなく、リダイレクトでもできたけど、
シンプルにしといたほうが後々楽なのでシンプルで行こう。

ちなみに、リダイレクト方式は以下

tokenCheck.php
    public function tokenCheck()
    {
        $secretKey = PAY_JP_TEST_SECRET;
        $publicKey = PAY_JP_TEST_KEY;

// トークンを取得
        $payjpToken = $_POST['payjp-token'] ?? '';

// セッションに保存
        $_SESSION['tds_input_data'] = [
            'payjp_token' => $payjpToken,
        ];

// ================================================
// 1) JWTの要素を準備
// ================================================

// ヘッダー部
        $header = [
            'alg' => 'HS256',
            'typ' => 'JWT'
        ];

// ペイロード部(今回は back_url 用の 'url' を設定)
        $payload = [
            'url' => 'https://your.com/payjp3ds/comp/',
        ];

// ================================================
// 2) Base64URLエンコード関数を用意
// ================================================
        function base64url_encode($data) {
            // 通常のBase64エンコード
            $b64 = base64_encode($data);
            // '+' → '-' , '/' → '_' , '=' を削除
            return rtrim(strtr($b64, '+/', '-_'), '=');
        }

// ================================================
// 3) header と payload をBase64URL化
// ================================================
        $base64Header  = base64url_encode(json_encode($header));
        $base64Payload = base64url_encode(json_encode($payload));

// ================================================
// 4) 署名を作成 (HS256)
// ================================================
        $signature = hash_hmac(
            'sha256',
            $base64Header . '.' . $base64Payload,
            $secretKey,
            true
        );

// Base64URLエンコード
        $base64Signature = base64url_encode($signature);

// ================================================
// 5) JWT(=JWS)文字列を生成 (header.payload.signature)
// ================================================
        $jws = $base64Header . '.' . $base64Payload . '.' . $base64Signature;

// ================================================
// 6) リダイレクト
// ================================================



        
        header("Location: https://api.pay.jp/v1/tds/{$payjpToken}/start?publickey={$publicKey}&back_url={$jws}");


        die();
    }
    

3dsセキュア認証画面

本番
成功したら、自動的にポップアップが閉じられる

名称未設定-2.png

テストのときは、ポップアップ後に
成功かエラーかを選ぶ必要がある

2024/11/01 追記

以下では、駄目。

2025年2月4日に3Dセキュア版にするから、エンドポイントを変更して3Dセキュア版を試してね。とのこと。

以下のように変更してみた。


<form action="/pays/teiki/" method="post">
    <input type="hidden" id="selected-plan" name="plan" value="1000">
    <input type="hidden" id="user_id" name="user_id" value="<?=u('id');?>">
    <script src="https://checkout.pay.jp/prerelease/" class="payjp-button" data-key="<?=$key;?>" data-text="申し込み"></script>
</form>

んーテストしてみたけど
今までと何も変わらない。
まぁ、これでいいんでしょうね。

checkout と payjp.js の 2種類

僕はすべてのサイトにchecktoutを使っている
ただ、なんかバグってたから3Dセキュア導入はもう少し待ってとのこと。

問題が発生したため、リリースを延期いたしました。
https://pay.jp/info/2024/07/31/110000

改めて、10月中旬〜下旬にプレリリース方式での先行配布を実施予定です。
https://pay.jp/info/2024/10/04/151500

導入方法?

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?