【PHP】とりあえずAPIのスタブをパパっと作る（JSONリクエスト版）

# 今度はJSONを受け取ってくれるAPIのスタブつくろう
[【PHP】とりあえずAPIのスタブをパパっと作る](https://qiita.com/sola-msr/items/609677e6e57e7f126487) では単純なPOSTを受け取るAPIは作ったんですが、
世の中にはJSONを受け取るAPIも存在するようで。
必要ならばつくらねばならない。~~めんどくさいが~~

# スタブAPI（JSONリクエスト版）
このPHPファイルを仮サーバーにおいてこいつと通信する。
例ではPOSTパラメータは`{"json":{"name":"*****"}}`の`name`を受け取って、その値に対して`'_RECEIVED'`を付加して、時間とともにjsonにして返す
てな感じの処理をしてます。（[APIのスタブとほぼ同じ](https://qiita.com/sola-msr/items/609677e6e57e7f126487)）
また、受け取ったlogも出力するようにしてます。

```api-json.php
// header('Access-Control-Allow-Origin: *'); // どこからでもアクセス許可するならワイルドカード
header('Access-Control-Allow-Origin: https://*******/post.php'); // 厳密なURL指定
header('Access-Control-Allow-Credentials: true'); // Basic認証やCookieのやり取りする際は必要（ワイルドカード使用すると使えない）
header('Access-Control-Allow-Headers: Content-Type');
header('Content-Type: application/json; charset=utf-8');

date_default_timezone_set('Asia/Tokyo');

// 設置するサーバーでfile_get_contents使えんかったら動かないです
$jsonParams = file_get_contents('php://input');

// 直後のIF文でエラーをキャッチする為の仮デコード処理
json_decode($jsonParams, true);

if(json_last_error() !== JSON_ERROR_NONE || strlen($jsonParams) <= 0) {

    $jsonArray['json']['name'] = '(JSON_DECODE_ERROR)';

} else {

    $jsonArray = json_decode($jsonParams, true);

    if (isset($jsonArray['json']) === true &&$jsonArray['json'] !== '') {
        if (isset($jsonArray['json']['name']) === false || $jsonArray['json']['name'] === '') {
            $jsonArray['json']['name'] = '(KEY_OR_VALUE_OF_NAME_IS_NOT_EXISIST)';
        }
    } else {
        $jsonArray['json']['name'] = '(KEY_OF_JSON_IS_NOT_EXISIST)';
    }

}

// API側で受け取ったよというマーク的なやつを付加
$name = htmlspecialchars($jsonArray['json']['name'], ENT_QUOTES) . '_RECEIVED';
 
$array = [
    'json' => [
        'name' => $name,
        'date' => date("Y-m-d H:i:s"),
    ]
];

$json = json_encode($array);

/* log出力 */
$file = new SplFileObject('api-json_log.txt', 'a');
$file->fwrite(
    "【→API】RequestParameter:" . $jsonParams . "\n【←API】ReturnParameter :" . $json . "\n----------\n"
);

echo $json;
exit;
```

logファイルにはリクエストパラメータと返すパラメータの両方を出力するようにしています。

```api-json_log.txt
【→API】RequestParameter:{"json":{"name":"POST_JSON_BY_FORM"}}
【←API】ReturnParameter :{"json":{"name":"POST_JSON_BY_FORM_RECEIVED","date":"2018-02-15 16:40:30"}}
----------
【→API】RequestParameter:{"json":{"name":"POST_JSON_BY_FORM"}}
【←API】ReturnParameter :{"json":{"name":"POST_JSON_BY_FORM_RECEIVED","date":"2018-02-15 17:08:29"}}
----------
```

**【→API】** とか **【←API】**見やすくないですか？あ、そうでもないですか・・・

# JSONをPOSTする側の実装

```post.php
/**
 * APIに対してJSONをPOST送信し返り値を取得する
 *
 * @param string $url
 * @param array $postParams
 * @return array
 */
function sendPostJsonToApiByCurl($url, $postParams)
{
    $ch = curl_init($url);

    $postOption = [
        CURLOPT_POST           => true,
        CURLOPT_TIMEOUT        => 10,
        CURLOPT_HTTPHEADER     => ['Content-Type: application/json'],
        CURLOPT_POSTFIELDS     => json_encode($postParams, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE); //JSON へエンコード処理（'/'をエスケープしない＆日本語をパースしない）
        CURLOPT_RETURNTRANSFER => true,
    ];

    curl_setopt_array($ch, $postOption);

    $content = curl_exec($ch); 
    $err     = curl_errno($ch); 
    $errmsg  = curl_error($ch);
    $header  = curl_getinfo($ch);

    curl_close($ch); // リソース開放

    /* errorチェック */
    if ($err !== 0) {
      if ($errmsg !== '') {
          return ['error' => $errmsg];    
      }
      return [];
    }

    if ($header['http_code'] !== 200) {
        if ($errmsg !== '') {
            return ['error' => $errmsg];
        }
        return ['http_code' => $header['http_code']];
    }

    return json_decode($content, true);
}
```


# おわり
- 今回もAPI側の`header`の設定箇所で指摘あれば教えてくださいです
- `$postOption`の設定も指摘あれば教えてください
- 今回も関数名ながくない？もうこれでいいか
- タイプヒンティング書いてないのはPHP7で動かす想定してないから

# 参考
- [PHPでJSON POSTを受け取る | CODE Q&A [日本語]](https://code.i-harness.com/ja/q/11fe18b)
- [PHP: json_encode, json_decodeのエラーを取得 – エラーの向こうへ](https://tech.mktime.com/entry/156)
- [JSON形式のデータをPOST送受信する方法(PHP) | 合同会社スマート](https://www.smartllc.jp/blog/20150811-how-to-post-json-in-php/)
- [JSONデータのPOST [メモとかメモのようなものとか（By ルーキーの中のひと）]](https://wiki.rookie-inc.com/development/language/php/postjson)