PHP(Laravel)でLINE Pay(v3)のAPI Authenticationに対処する

# PHPでLINE Pay(v3)のAPI Authenticationに対処する

前提： 加盟店申請が終わっている

管理画面から
- `Channel ID`
- `Channel Secret Key`
の2つを入手しましょう。

これらの連動キーは「決済連動管理 > 連動キー管理」から入手します。


# API Authenticationとは

[公式Document](https://pay.line.me/jp/developers/apis/onlineApis?locale=ja_JP)

|Key	| Data Type |	Requirement	| Description|
|-|-|-|-|
|Content-Type|	String	|Y|	application/json|
|X-LINE-ChannelId|	String|	Y	|Payment Integration Information - Channel ID|
|X-LINE-MerchantDeviceProfileId|	String|	N	|Offline Support - Device Type|
|X-LINE-Authorization-Nonce|	String	|Y	|UUID or Request timestamp|
|X-LINE-Authorization|	String	|Y|	HMAC Base64 Signature|

上記のうち `X-LINE-MerchantDeviceProfileId` を除く4つは**必須**です。

`X-LINE-Authorization` の生成に少し手間取ったので、結論を記します。


# PHP(Laravel)でX-LINE-Authorizationの値を生成する

```php

use Illuminate\Support\Str;

class LinePayController extends Controller
{
    private $channelId;
    private $channelSecretKey;

    public function __construct()
    {
        $this->channelId = '****';
        $this->channelSecretKey = '****';
    }

    private function getAuthSignature($channelSecretKey, $uri, $requestBody, $nonce)
    {
        $data = $channelSecretKey . $uri . json_encode($requestBody) . $nonce;
        $hash = hash_hmac('sha256', $data, $channelSecretKey, true);
        return base64_encode($hash);
    }

    public function index() {
       $nonce = Str::uuid();
       $requestUri = '/v3/payments/request';
       $requestBody = [
                "amount" => ...,
                "currency" => ...,
                "orderId" => ...,
                "packages" => [
                    [
                        "id" => ...,
                        "amount" => ...,
                        "products" => [
                            [
                                "name" => ...,
                                "quantity" => ...,
                                "price" => ...,
                            ],
                        ],
                    ],
                ],
                "redirectUrls" => [
                    "confirmUrl" => ...,
                    "cancelUrl" => ...,
                ],
            ];

       // この$signatureをX-LINE-AuthorizationにセットすればOK
       $signature = $this->getAuthSignature($this->channelSecretKey, $requestUri, $requestBody, $nonce);

       // ヘッダーをつけてLINE PayサーバーにAPIリクエストを送信する
       $header = [
            "Content-Type: application/json",
            "X-LINE-ChannelId: {$this->channelId}",
            "X-LINE-Authorization-Nonce: {$nonce}",
            "X-LINE-Authorization: {$signature}",
        ];

       // 以下略
    }
}

```

以下、上記のコードの解説です。

まず Laravel の `Str` を使って `UUID （version4）` を生成しています。

```php
$nonce = Str::uuid();
```

いきなり Laravel 特有の関数でお茶を濁してすみません...
Laravel 以外の人は、何かしらの方法でUUIDを作成しましょう。

公式によれば、 `UUID` の代わりに `timestamp` でも大丈夫です。
`$nonce` は繰り返しの不正リクエストを防ぐ目的で使用されるので、時刻に応じて刻一刻と変わる値であれば要件をクリアするようです。

この先は Laravel は関係ありません。

次に今回のメインテーマである `X-LINE-Authorization` の値を生成します。

```php
private function getAuthSignature($channelSecretKey, $uri, $requestBody, $nonce)
    {
        $data = $channelSecretKey . $uri . json_encode($requestBody) . $nonce;
        $hash = hash_hmac('sha256', $data, $channelSecretKey, true);
        return base64_encode($hash);
    }
```


登場する関数は以下の2つです。
- [base64_encode](https://www.php.net/manual/ja/function.base64-encode.php)：MIME base64 方式でデータをエンコードする
- [hash_hmac](https://www.php.net/manual/ja/function.hash-hmac.php)： HMAC 方式を使用してハッシュ値を生成する

`hash_hmac` の第3引数は暗号化に使用する秘密鍵です。ここで `Channel Secret Key` を使うわけですね。

また `hash_hmac（）` の第4引数を `true` にセットしましょう。生のバイナリデータが返ります。

私はここを `false` にしたままで、エラーを繰り返してしまいました。

# その他

LINE Pay の実装に関して、全体的な方針は以下の記事が参考になりました。
- [アプリにLINE Pay決済を導入する簡易手引き(LINE Pay API - v3)](https://qiita.com/suzu_D/items/aaa568933e89ee029e00#confirm-api-%E3%81%AE%E3%81%96%E3%81%A3%E3%81%8F%E3%82%8A%E3%81%A8%E3%81%97%E3%81%9F%E8%AA%AC%E6%98%8E)

[公式Document](https://pay.line.me/jp/developers/apis/onlineApis?locale=ja_JP)も充実していると思いますが、慣れない表現に戸惑ってしまいました。「技術支援の問合せ先」が明記されているのは実装に先当たって好印象でした。安心感が増します。

あとは以下の SDK の GitHub の生コードを読み漁り、理解を深めました。
パッケージの導入はしませんでしたが、コーディングの良い指針となりました。
- [line-pay-sdk-php](https://github.com/yidas/line-pay-sdk-php)