【PHP】API実行ツールを作ってみよう(その4)

#はじめに
PHPでツール作成の6回目です。
[前回](https://qiita.com/noji505/items/49941dba6d5d4f12e73f)はChrome拡張機能でクライアントを作成しましたが、
今回はPHPで作成しようと思います。

#クライアント作成
クライアントから作成してみましょう。
作成場所は「<b>c:￥xampp￥htdocs￥temp_api_php</b>」フォルダになります。
「<b>temp_api_php</b>」フォルダ内に「<b>client.php</b>」ファイルを作成します。
中身は下記になります。

```php:client.php
<?php
//------------------------------------------------------
// client.php   API送信クライアント
// 
// 実行コマンド
// cd C:\xampp\htdocs\api_temp_php\
// php client.php upload.csv
//------------------------------------------------------

// アプリケーショントークンキー
define( "APPLICATION_TOKEN", "apikey" );

// 引数チェック
if( count($argv) < 2 ){
    echo "エラー:引数が足りません\n";
    echo "EX:\n";
    echo "php client.php upload.csv\n";
    exit;
}
$uploadFileName = $argv[1];

$url = "http://localhost/api_temp_php/server.php";       // 接続先URL

echo "-----[api start]-----\n";

$ret = sendApi( $url, $uploadFileName );

echo "-----[api end]-----\n";

// API実行
function sendApi( $url, $uploadFileName ) {

    // プロキシ情報
    $proxy_host = "proxy_ipaddress";
    $proxy_port = "port_no";
    $proxy_user = "username";
    $proxy_pass = "password";
    $proxy_auth = base64_encode("$proxy_user:$proxy_pass");

    // アップロードファイルチェック
    if( !file_exists($uploadFileName) ){
        echo "エラー:アップロードファイルがありません。\n";
        echo "uploadFile:".$uploadFileName."\n";
        exit;
    }

    $uploadFile = file_get_contents( $uploadFileName );
    $content = $uploadFile;

    // ヘッダデータ作成
    $header = array(
        "Content-Type: application/x-www-form-urlencoded;",
        "Content-Length: ".strlen($content),
        "applicationtoken: ".APPLICATION_TOKEN."",    // アプリケーショントークンキー
    //    "Proxy-Authorization: Basic ".$proxy_auth
    );

    $contextOptions = array(
        "http" => array(
            "protocol_version" => 1.1,
            "method"  => "POST",
            "header"  => implode( "\r\n", $header ),
            "ignore_errors" => true,
    //        "proxy" => "tcp://$proxy_host:$proxy_port",
            "request_fulluri" => true,
            "content" => $content
        )
    );
    $sslContext = stream_context_create( $contextOptions );
    
    // API実行
    $response = file_get_contents( $url, false, $sslContext );

    // リクエストパラメータ保存
    file_put_contents( "./request.txt", $content );

    // レスポンスパラメータ保存
    file_put_contents( "./response.txt", $response );

	return $response;
}
?>
```
#コード解説
- 12行目・・アプリケーショントークンキーを設定しています。
- 14～20行目・・実行時に引数が指定されているかチェックしています。
- 32行目・・API実行を行うメソッドです。
- 34～39行目・・外部接続時にプロキシ接続が必要な場合の設定です、もし必要であれば書き換えて下さい。
- 55行目・・ヘッダにアプリケーショントークンキーをセットしています。
- 56、65行目・・上記のプロキシ接続が必要な場合に限り、コメントアウトを解除して下さい。
- 73行目・・APIを実行しています。
- 76～79行目・・送信したリクエストパラメータと受信したレスポンスを、テキストファイルに保存しています。

#サーバ作成
続いてサーバ側を作成します。
「<b>temp_api_php</b>」フォルダ内に「<b>server.php</b>」ファイルを作成します。
中身は下記になります。

```php:server.php
<?php
// アプリケーショントークンキー
define( "APPLICATION_TOKEN", "apikey" );

$saveFolderName = "./file";

// ヘッダトークンチェック
if( !isset($_SERVER['HTTP_APPLICATIONTOKEN']) ){
    echo "エラー:アプリケーショントークンがありません。";
    return;
}
$apiToken = $_SERVER['HTTP_APPLICATIONTOKEN'];
if( $apiToken != APPLICATION_TOKEN ){
    echo "エラー:アプリケーショントークンが一致しません。";
    return;
}

// ファイル保存
$params = file_get_contents('php://input');
if( strlen($params) <= 0 ){
    echo "エラー:ファイルが不正です。";
    return;
}
$extName = "csv";
$outputFile = "".$saveFolderName."/".date("Y-m-d_His")."_".substr(explode(".", (microtime(true) . ""))[1], 0, 3).".".$extName."";
file_put_contents( $outputFile, $params );

// レスポンス
echo "Success";
?>
```
#コード解説
- 3行目・・アプリケーショントークンキーを設定しています。
- 8～16行目・・アプリケーショントークンキーのチェックを行っています。
- 19～26行目・・クライアントから送られてきたデータをファイルに保存しています。
- 29行目・・クライアントにレスポンスを返しています。

#最後に
基本的な処理の流れは[前回](https://qiita.com/noji505/items/49941dba6d5d4f12e73f)と変わっていないのですが、
一つ大きな変更点として「<b>アプリケーショントークンキー</b>」の追加があります。
これはクライアントとサーバ間で事前に値を決めておき、それを通信データに含めておくことで簡易な認証として機能させる役割になります。
これを設定しておくことにより、他の第三者からサーバへ通信された際に不正な通信として弾ける可能性が高まります。
実際にAPIを業務で使用する際は、よく使う手法なので覚えておくと良いと思います。