Amazon Pay CV2のクレジットカード決済サンプル

PHPを使って「Amazon Pay CV2」のクレジットカード決済のサンプルを書いてみます。住所情報は取得せず、一回限りのクレジットカード決済です。

# 環境
```
PHP 8.0.30
Amazon Pay API SDK (PHP) 2.6.6
CentOS Stream release 9
```

Amazon PayのSDKはComposerでインストールします。

※ 前提条件として、Amazon Payの申し込みが済んでいて、SANDBOX用のキーペア発行など、開発の準備は済んでいるものとします。

# 決済フロー

CV2ではAPBフローという「今すぐ支払う」機能があります。

自サイトの注文確認画面を挟まず、Amazon Payがホストするページからそのまま支払いができる決済フローです。

今回はAPBフローを利用します。

# 支払いボタンを表示するページ
まずは支払いボタンを表示するページです。

手順としては、
(1) Clientインスタンス作成
(2) JSONペイロードを作成
(3) JSONペイロードの署名
(4) Amazon Payのボタンを表示

といった流れです。

```php:payment.php
<?php
    require '/home/example/vendor/autoload.php';

    // (1) Clientインスタンス作成
    $config = [
        'public_key_id' => '--- PUBLIC_KEY ---',
        'private_key' => '/home/example/private_key.pem',
        'region' => 'jp',
        'sandbox' => true,
    ];
    $client = new Amazon\Pay\API\Client($config);

    // (2) JSONペイロードを作成
    $payload = [
        'webCheckoutDetails' => [
            'checkoutResultReturnUrl' => 'https://www.example.com/charge.php',
            'checkoutCancelUrl' => 'https://www.example.com/payment.php',
            'checkoutMode' => 'ProcessOrder',
        ],
        'storeId' => '--- CLIENT_ID ---',
        'chargePermissionType' => 'OneTime',
        'merchantMetadata' => [
            'merchantReferenceId' => 'Order_' . time(),
            'merchantStoreName' => '--- SHOP_NAME ---',
            'noteToBuyer' => '料金のお支払いです',
        ],
        'paymentDetails' => [
            'paymentIntent' => 'AuthorizeWithCapture',
            'chargeAmount' => [
                'amount' => '100',
                'currencyCode' => 'JPY',
            ],
        ],
        'scopes' => [
            'name',
            'email',
        ],
    ];
    // 全角文字があるので JSON_UNESCAPED_UNICODE を指定する
    $payloadJson = json_encode($payload, JSON_UNESCAPED_UNICODE);

    // (3) JSONペイロードの署名
    $signature = $client->generateButtonSignature($payloadJson);
?>
<html>
  <head>
    <meta charset="utf-8">
    <title>Amazon Pay サンプルページ</title>
  </head>
  
  <body>
    <!-- (4) Amazon Payのボタンを表示 -->
    <div style="width:300px;margin:auto;">
      <div id="AmazonPayButton" style="max-width:100%;"></div>
    </div>
    <script src="https://static-fe.payments-amazon.com/checkout.js"></script>
    <script type="text/javascript" charset="utf-8">
      amazon.Pay.renderButton('#AmazonPayButton', {
        merchantId : '--- MERCHANT_ID ---',
        ledgerCurrency : 'JPY',
        sandbox : true,
        checkoutLanguage : 'ja_JP',
        productType : 'PayOnly',
        placement : 'Cart',
        buttonColor : 'Gold',
        createCheckoutSessionConfig : {
          payloadJSON : '<?php echo $payloadJson?>',
          signature : '<?php echo $signature?>',
          publicKeyId : '--- PUBLIC_KEY ---'
        }
      });
    </script>
  </div>
</body>
```
--- PUBLIC_KEY ---や、リダイレクト先URLなどの値は、環境に合わせて書き換えてください。

json_encodeしたペイロードの文字列と、署名した結果のsignatureの文字列をJavaScriptの値に入れます。

問題なくページが開くと、Amazon Payのボタンが表示されます。

![スクリーンショット 2025-02-15 161413.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/278715/0686b8bd-6e09-4ca8-97ec-bbafb9483d52.png)

# Amazon Payで支払う

Amazon Payのボタンを押して、購入者テストアカウントでログインします。

![login.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/278715/f53a1956-cf53-427b-af0e-e7058374aef4.png)

クレジットカードを選択して、今すぐ支払うボタンを押します。

成功するとペイロードのcheckoutResultReturnUrlで指定した、支払い完了ページにリダイレクトされます。

この時点ではオーソリ（仮売上）状態となっているので、リダイレクト先で売上を請求して、注文を完了する必要があります。

# 支払い完了ページ

Amazon Pay側で支払いをした後、戻ってくるリダイレクト先のページです。

リダイレクトされるときにGETでamazonCheckoutSessionIdのパラメーターが渡されるので、その値を使って売上を請求します。

手順としては、
(1) パラメーターを取得
(2) Clientインスタンス作成
(3) 注文情報を取得
(4) 売上請求処理
(5) 支払い完了ページを表示

といった流れです。

```php:charge.php
<?php
    require '/home/example/vendor/autoload.php';

    // (1) パラメーターを取得
    $amazonCheckoutSessionId = $_GET['amazonCheckoutSessionId'];
    if (empty($amazonCheckoutSessionId)) {
        header('Location: /parameter_error.html');
        exit;
    }

    // (2) Clientインスタンス作成
    $config = [
        'public_key_id' => '--- PUBLIC_KEY ---',
        'private_key' => '/home/example/private_key.pem',
        'region' => 'jp',
        'sandbox' => true,
    ];
    $client = new Amazon\Pay\API\Client($config);

    // (3) 注文情報を取得
    $result = $client->getCheckoutSession($amazonCheckoutSessionId);
    $response = json_decode($result['response'], true);

    // 購入者のemailアドレスを確認
    $email = $response['buyer']['email'];
    if (empty($email)) {
        header('Location: /email_error.html');
        exit;
    }

    // (4) 売上請求処理
    $payload = [
        'chargeAmount' => [
            'amount' => '100',
            'currencyCode' => 'JPY',
        ],
    ];
    $checkoutResponse = $client->completeCheckoutSession($amazonCheckoutSessionId, $payload);

    // 完了ステータスを確認
    if ($checkoutResponse['status'] !== 200) {
        header('Location: /checkout_error.html');
        exit;
    }
?>
<html>
  <head>
  <meta charset="utf-8">
  <title>Amazon Pay 支払い完了ページ</title>
</head>
<body>
  <!-- (5) 支払い完了ページを表示 -->
  <p>支払いが完了しました</p>
  <p>email: <?php echo $email;?></p>
</body>
```

--- PUBLIC_KEY ---などの値は、環境に合わせて書き換えてください。

支払い完了メッセージと、emailが表示されると完了です。

![message.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/278715/c5296ec6-e58c-4cc4-9c9f-d48c167ab9aa.png)

# まとめ

以上でサンプルを終了します。

簡単そうに書いてますが、JSONペイロードとシグネチャーのところ理解するのに結構時間かかりました:sweat_smile: