PHPとAmazon Payを使ったクレジットカード決済サンプル


# はじめに
「Amazon Pay」はAmazon以外のサイトで、Amazonアカウントのクレジットカードや住所を使って決済ができるサービスです。
https://pay.amazon.com/jp

今回はPHPを使ってAmazon Payのクレジットカード決済を試してみたので、サンプルコードをご紹介します。

前提条件として、Amazon Payの申し込みが済んでいて、Sandbox用の各種ID（出品者ID、クライアントIDなど）が発行されているものとします。

# Amazonログインのウェブ設定
まずは使用するサイトのドメインと、Amazonログイン後のリダイレクト先URLを設定します。Amazon Payの管理画面でヘッダーのセレクトボックスから「Amazonログイン」を選択して、表示されたウェブ設定から「JavaScriptの種類」と「リダイレクトURL」を設定します。
<img width="585" alt="qiita.png" src="https://qiita-image-store.s3.amazonaws.com/0/278715/d4e38304-0d24-e9c6-0df3-01a4ea2a15d3.png">

# Amazonログインボタン表示ページ
Amazonのログインボタンを表示するページです。

```html:amazon_pay.html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Amazon Pay</title>
</head>

<body>
<script async="async" src='https://static-fe.payments-amazon.com/OffAmazonPayments/jp/sandbox/lpa/js/Widgets.js'></script>
<div id="AmazonPayButton"></div>
<script>
    window.onAmazonLoginReady = function () {
        amazon.Login.setClientId('--- CLIENT_ID ---');
    };
    window.onAmazonPaymentsReady = function() {
        showButton();
    };
</script>
<script>
function showButton() {
    var authRequest;
    OffAmazonPayments.Button("AmazonPayButton", "--- MERCHANT_ID ---", {
        type: "PwA",
        color: "Gold",
        size: "large",
        language: "jp",
        authorization: function () {
            loginOptions = { scope: "profile payments:widget", popup: true };
            authRequest = amazon.Login.authorize(loginOptions, "--- REDIRECT_URL ---");
        },
        onError: function(error) {
            // error handling
        }
    });
};
</script>
</body>
</html>
```

Amazonのログインボタンが表示されます。
![q2.png](https://qiita-image-store.s3.amazonaws.com/0/278715/4fe45f62-695e-9162-f865-d1c9389719d5.png)

ボタンを押すと、Amazonのログイン画面がポップアップで表示されます。
![q1.png](https://qiita-image-store.s3.amazonaws.com/0/278715/9d1a12e5-2461-f3ae-a2c3-24c4dc613fec.png)


Amazon Payのテストアカウントでユーザー名とアカウントを入力してログインします。
要求された権限を許可すると、--- REDIRECT_URL ---で設定したURLにaccess_tokenをパラメータにしてリダイレクトされます。

--- REDIRECT_URL ---はAmazonログインのウェブ設定で設定したURLを入力します。

# クレジットカード選択ページ
Amazonアカウントに登録してあるクレジットカードを選択するページです。パラメータのaccess_tokenは後ほど使うのでSESSIONに保存しておきます。

```php:select_card.php
<?php
    session_start();
    $_SESSION['access_token'] = $_GET['access_token'];
?>
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>クレジットカード選択ページ</title>
</head>

<body>
<div id="walletWidgetDiv" style="width:300px; height:240px;"></div>
<script>
    window.onAmazonLoginReady = function() {
        amazon.Login.setClientId('--- CLIENT_ID ---');
    };
</script>
<script src='https://static-fe.payments-amazon.com/OffAmazonPayments/jp/sandbox/lpa/js/Widgets.js'></script>
<script type="text/javascript">
    new OffAmazonPayments.Widgets.Wallet({
        sellerId: '--- MERCHANT_ID ---',
        onOrderReferenceCreate: function (orderReference) {
            orderReferenceId = orderReference.getAmazonOrderReferenceId();
            document.getElementById("orderReferenceId").value = orderReferenceId;
        },
        onPaymentSelect: function () {
        },
        design: {
            designMode: 'responsive'
        },
        onError: function (error) {
        }
    }).bind("walletWidgetDiv");
</script>
<form action="/payment.php" method="POST">
    <input type="hidden" id="orderReferenceId" name="orderReferenceId">
    <input type="submit" value="購入する">
</form>
</body>
</html>
```
Amazonのテストアカウントに登録してあるクレジットカード情報が表示されます。
![q3.png](https://qiita-image-store.s3.amazonaws.com/0/278715/a64680dc-edb3-1c10-49f7-26a1c1cf147b.png)
クレジットカードを選択して「購入する」ボタンを押します。
# クレジットカード決済処理
クレジットカード選択ページから送られてきたorderReferenceIdを使ってクレジットカード決済を実行します。

処理の流れとしては、
(1) Clientインスタンスを作成
(2) 注文情報をセット
(3) 注文情報を確定
(4) オーソリをリクエスト
(5) 注文を確定
となります。

Amazon Pay SDK (PHP)をダウンロードしておきます。composerでインストールも可能です。
https://github.com/amzn/amazon-pay-sdk-php

```php:payment.php
<?php
require '/home/hoge/amazon/AmazonPay/Client.php';

Use AmazonPay\Client;

class Payment
{
    const MERCHANT_ID = '--- MERCHANT_ID ---';
    // 決済金額
    const AMOUNT = 100;

    public function execute()
    {
        $referenceId = $_REQUEST['orderReferenceId'];

        // (1) Clientインスタンスを作成
        $config = array(
            'merchant_id' => self::MERCHANT_ID,
            'access_key' => '--- ACCESS_KEY ---',
            'secret_key' => '--- SECRET_KEY---',
            'client_id' => '--- CLIENT_ID ---',
            'currency_code' => 'jpy',
            'region' => 'jp',
            'sandbox' => true,
        );
        $client = new Client($config);

        // (2) 注文情報をセット
        $setOrderParams = array(
            'merchant_id' => self::MERCHANT_ID,
            'amazon_order_reference_id' => $referenceId,
            'amount' => self::AMOUNT,
            'currency_code' => 'JPY',
            'seller_note' => 'ご購入ありがとうございます',
            'seller_order_id' => 'Order_' . time(),
            'store_name' => 'ショップ名',
        );
        $client->SetOrderReferenceDetails($setOrderParams);

        if ($client->success === false) {
            header('Location: /error.html');
            exit;
        }

        // (3) 注文情報を確定
        $confirmOrderParams = array(
            'amazon_order_reference_id' => $referenceId
        );
        $client->confirmOrderReference($confirmOrderParams);

        if ($client->success === false) {
            header('Location: /error.html');
            exit;
        }

        // (4) オーソリをリクエスト
        $authorizeParams = array(
            'amazon_order_reference_id' => $referenceId,
            'authorization_amount' => self::AMOUNT,
            'authorization_reference_id' => 'Order_' . time(),
            'seller_authorization_note' => 'Authorizing payment',
            'transaction_timeout' => 0,
        );
        $response = $client->authorize($authorizeParams);
        $result = $response->toArray();

        // オーソリが成功したか確認
        $amazonAuthorizationId = $result['AuthorizeResult']['AuthorizationDetails']['AmazonAuthorizationId'];
        if (empty($amazonAuthorizationId)) {
            header('Location: /error.html');
            exit;
        }
        if ($client->success === false) {
            header('Location: /error.html');
            exit;
        }

        // (5) 注文を確定
        $captureParams = array(
            'amazon_authorization_id' => $amazonAuthorizationId,
            'capture_amount' => self::AMOUNT,
            'currency_code' => 'JPY',
            'capture_reference_id' => 'Order_' . time(),
            'seller_capture_note' => '購入が完了しました',
        );
        $response = $client->capture($captureParams);
        $result = $response->toArray();

        // 注文の確定に失敗したらオーソリを取り消して、注文をクローズする
        if ($result['ResponseStatus'] !== '200') {
            $cancelParams = array(
                'merchant_id' => self::MERCHANT_ID,
                'amazon_order_reference_id' => $referenceId,
            );
            $client->cancelOrderReference($cancelParams);
            $closeParams = array(
                'merchant_id' => self::MERCHANT_ID,
                'amazon_authorization_id' => $amazonAuthorizationId,
            );
            $client->closeAuthorization($closeParams);

            header('Location: /error.html');
            exit;
        }

        header('Location: /success.html');
        exit;
    }
}

$payment = new Payment();
$payment->execute();
?>
```

デジタルコンテンツの販売であればこのように注文確定までやってしまってよいと思いますが、商品の発送がある物販の場合はオーソリだけしておいて、商品の確保後や発送後にAmazon Payの管理画面から注文を確定するなどします。

# access_tokenを使った情報の取得
Amazonログイン後に発行されたaccess_tokenを使って許可されたユーザー情報にアクセスすることができます。

### APIリクエストサンプル

```php
<?php
    $token = "--- ACCESS_TOKEN ---";
    $curl = curl_init('https://api.sandbox.amazon.com/user/profile');
    curl_setopt($curl, CURLOPT_HTTPHEADER, array('Authorization: bearer ' . $token));
    curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);

    $response = curl_exec($curl);
    curl_close($curl);
    $data = json_decode($response, true);
    var_dump($data);
?>
```

### レスポンスサンプル

```
array(3) {
  ["user_id"]=>
  string(42) "AmazonのユーザーID"
  ["name"]=>
  string(9) "テスト太郎"
  ["email"]=>
  string(21) "hoge@example.com"
}
```

# まとめ

このようにAmazonアカウントを使って簡単にクレジットカード決済ができました。ユーザーにとってはAmazonアカウントを使うことで新規アカウント登録の手間が省け、運営する側としてもユーザー管理の手間が省けます。

サンプルコードの環境は
php 5.4.16
Amazon Pay SDK (PHP) 3.2.0
を使っています。

# ※ 2025/2/17 追記 

この記事で紹介しているのはAmazon Payの「CV1」です。新しいバージョン「CV2」のサンプルは下の記事に書きました。

「Amazon Pay CV2のクレジットカード決済サンプル」
https://qiita.com/p_s_m_t/items/88a8a3fec7fbd711db56