yahoo の FastPay を使ってみた

# Yahooウォレット FastPay に関する情報が少ない

[Yahooウォレット FastPay](https://fastpay.yahoo.co.jp/)、来年2月でサービスインして1年みたいですが、あんまり良さげなリソースに当たらない。

参考にできるものが少なくて苦労したんですが、
https://github.com/taman777/fastpay_test
この辺とかどストライクそうだった。

でも、v1とか文字があるので最初の頃のAPI。

少し参考にはしたけど、今のv2でステータスコードやエラーオブジェクトの取り方が違ってた。

# 準備

[公式ドキュメント](https://fastpay.yahoo.co.jp/docs/library)見たら全部載ってるけど

* 入ってなければ、composer
* composer.json 用意

```json:composer.json
{
  "require":{
    "fastpay/fastpay-php":"~1.1.0"
  }
}
```

```bash
$ php composer.phar install --prefer-source --no-interaction
```

だけです。

# POSTされたトークンを受け取るポップアップ型にした

ポップアップ（POSTされたトークンを受ける）と画面遷移（GETでトークンくっつけて指定URLに戻ってくる）があるんですが、ポップアップだとローカル、ステージング、本番のredirect先urlを指定しなくて良かったのでポップアップにしただけです。

## 送信する方

fastpayでアカウント作れば[このページ](https://fastpay.yahoo.co.jp/docs/flow/popup)に自分用のkey含んだコードが出てる。

```html
<form action="charge.php" method="POST">
<script
    src="https://s.yimg.jp/images/wallet/fastpay/js/fastpay-v2-current.js" class="fastpay-button"
    data-key="xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
    data-amount="666"
>
</script>
</form>
```

これを送信側へ。

要はこのスクリプト貼ると、ポップアップでYahooウォレットの画面=>カード情報入力完了、トークンを返して戻ってくる仕組み。POSTで戻ってくるのは2つだけ。

* fastpayToken
* amout

## 受ける方

APPID、シークレットキーみたいなの別でdefineして呼んだ方がセキュアなのかと思って短絡的にそうしてみた。あと試運転環境と本番環境でIDもキーも変わってくるし環境変更時に変更しやすい。

```php:fastpay.php
<?php
//アプリケーションID
define('FASTPAY_APPID', 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx');
// シークレットキー
define('FASTPAY_SECRET_KEY', 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx');
?>
```

### POSTで帰ってきたamoutを整数型にしないといけない 

POSTで戻ってきたamountをそのままままオブジェクトに格納して投げつけるとstring型で拒否られた。整数型じゃないと受け取ってくれない様子なので、途中 `intval()` みたいなことしている。

### v1, v2 でステータスコード、エラーオブジェクトの取り方が違ってた

さっき言った通り、[この内容](https://github.com/taman777/fastpay_test/blob/master/post.php)を参考にしたんですが、このままだとステータスコードやエラーオブジェクトが取れない。

https://github.com/yahoojapan/fastpay-php/blob/master/src/FastPay/Error/FastPayError.php

大元見たらだいたい全部書いてある。

などなどあって、ざっくりだが下記のような感じで課金作成できた。

```php:charge.php
<?php
require "vendor/autoload.php";
require 'settlement/fastpay.php'; // ここで上のキーとか呼んでる
use FastPay\FastPay;

// エラーフラグとエラーメッセージのための変数
$error_msg = '';
$error_flg = FALSE;

// Fastpay に課金作成をトライ & エラー処理
try {
  $token = $_POST["fastpayToken"];
  $price = $_POST["amount"];

  // price の 数字、int型 チェック
  if (is_nan($price)) {
    $error_msg .= '不正な文字列を入力されています。';
    $error_flg = TRUE;
  } else {
    // 型を整数にする
    // ママAPIに送るとstring型でAPIで問い合わせられないため）
    $price = intval($price);
  }

 if ( !$error_flg ){
    $fastpay = new FastPay(FASTPAY_SECRET_KEY);
    $charge_array = array(
      "amount" => $price,
      "card" => $token,
      "description" => "hogehoge",
      // true で課金確定。falseにしておけば未確定のままダッシュボードには残る
      // false でひとまず未確定にしてあとで引っ張りだして確定というのも出来そう
      "capture" => "true", 
    );
    // ここで課金を作成します
    $charge = $fastpay->charge->create($charge_array);
  }
} catch (Exception $e) {
  // ステータス
  $e_status = $e->getHttpStatus();
  // ボディ
  $e_body = $e->getHttpBody();
  // タイプ
  $e_type = $e_body->error->type;
  // メッセージ
  $e_message = $e_body->error->message;
  // コード
  $e_code = $e_body->error->code;
  // パラメータ
  $e_param = $e_body->error->param;

  // ステータスが200を返せばエラーなし
  if ( $e_status != "200" ) {
    $error_flg = TRUE;
  }
  /**
  下記エラーステータス時のメッセージ
  200 OK - リクエストは成功しました。
  400 Bad Request - 必要なパラメータがありません。
  401 Unauthorized - API keyの認証に失敗しました。
  402 Request Failed - パラメータは有効でしたが、現在のステータスではこのリクエストは実行できません。
  404 Not Found - リクエストされた内容が存在しません。
  500, 502, 503, 504 Server errors - Yahoo!ウォレット FastPay側のシステムエラーです。
  */
  switch ($e_status) {
    case "400" :
      $error_msg .= "必要なパラメータがありません。";
      break;
    case "401" :
      $error_msg .= "APIキーの認証に失敗しました。"; // 再送信なども含まれる
      break;
    case "402" :
      $error_msg .= "支払い処理が完了していません。";
      // タイプでエラーを判別
      switch ($e_type) {
        case 'invalid_request_error':
          $error_msg .= "送信されたデータが異常です。";
          break;
        case 'api_error':
          $error_msg .= "Yahoo!ウォレット FastPay側のシステムでエラーになっています。";
          break;
        case 'card_error':
          // カードエラーをコードで判別
          switch ($e_code) {
            case 'incorrect_number':
              $error_msg .= 'カード番号が正しくありません。';
              break;
            case 'invalid_number':
              $error_msg .= '有効なカード番号ではありません。';
              break;
            case 'invalid_expiry_month':
            case 'invalid_expiry_year':
              $error_msg .= 'カードの有効期限が無効です。';
              break;
            case 'invalid_cvc':
            case 'incorrect_cvc':
              $error_msg .= 'セキュリティコードが正しくありません。';
              break;
            case 'expired_card':
              $error_msg .= '有効期限が切れています。';
              break;
            case 'card_declined':
              $error_msg .= 'カード決済に失敗しました。';
              break;
            case 'processing_error':
              $error_msg .= '決済処理中にエラーが発生しました。';
              break;
            default:
              // $error_msg .= 'other card error';
              break;
          }
        break;
      }
      break;
    case "404" :
      $error_msg .= "リクエストされた内容が存在しません。";
      break;
    case "500":
    case "502":
    case "503":
    case "504":
      $error_msg .= "Yahoo!ウォレット FastPay側のシステムでエラーになっています。";
      break;
    // 課金作成成功
    // case "200" :
    //   break;
  }
}

if ($error_flg) { // エラーが生じている場合
  echo $e_status.':'.$error_msg;
} else {
  // var_dump($charge->getArray()); // 作成した課金オブジェクトをダンプ
  $html .= '<table>
    <tbody>
      <tr>
        <th>決済金額</th>
        <td>'. $charge->amount .'円</td>
      </tr>
      <tr>
        <th>通貨</th>
        <td>'. $charge->currency .'</td>
      </tr>
      <tr>
        <th>カード種類</th>
        <td>'. $charge->card->type .'</td>
      </tr>
      <tr>
        <th>カード番号（下4桁のみ）</th>
        <td>****-****-****-'. $charge->card->last4 .'</td>
      </tr>
    </tbody>
  </table>';
  echo $html;
}
?>
```

本日は以上です。