PHPでPayPayAPIにリクエスト投げて成功するまで

# PayPayAPIにリクエスト投げて成功するまでの記事です

## PayPay for Developers
[PayPay for Developers](https://developer.paypay.ne.jp/)で登録してAPI_KEY、API_SECRET、MERCHANT_IDの取得が必要(登録方法は割愛)

※MERCHANT_IDは
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/142784/b714f912-ff36-95cd-0215-0ef160d3b418.png)
ここで見れます

※API_KEYおよびAPI_SECRETはダッシュボードから見れます

## sdkインストール
`composer require paypayopa/php-sdk`

## 成功したソース
```php
<?php
namespace App\Helpers;

use PayPay\OpenPaymentAPI\Client;
use PayPay\OpenPaymentAPI\Models\CreateQrCodePayload;

class PayPay {
  protected Client $paypayClient;

  function __construct() {
    $paypayConfig = \Config::get('paypay');

    $this->paypayClient = new Client([
      'API_KEY' => $paypayConfig['API_KEY'],
      'API_SECRET' => $paypayConfig['API_SECRET'],
      'MERCHANT_ID' => $paypayConfig['MERCHANT_ID'],
    ], true); //Set True for Production Environment. By Default this is set False for Sandbox Environment.


    // Creating the payload to create a QR Code, additional parameters can be added basis the API Documentation
    $payload = new CreateQrCodePayload();
    $payload->setMerchantPaymentId("my_payment_id" . \time());
    $payload->setCodeType("ORDER_QR");
    $amount = [
        "amount" => 1,
        "currency" => "JPY"
    ];
    $payload->setAmount($amount);
    $payload->setRedirectType('WEB_LINK');
    $payload->setRedirectUrl('https://paypay.ne.jp/');
    $payload->setUserAgent('Mozilla/5.0 (iPhone; CPU iPhone OS 10_3 like Mac OS X) AppleWebKit/602.1.50 (KHTML, like Gecko) CriOS/56.0.2924.75 Mobile/14E5239e Safari/602.1');
    
    //=================================================================
    // Calling the method to create a qr code
    //=================================================================
    $response = $this->paypayClient->code->createQRCode($payload);
    // 処理がうまくいってなかったら抜ける
    if($response['resultInfo']['code'] !== 'SUCCESS') {
      return;
    }

    // Collectionに変換しておく
    $QRCodeResponse = collect($response['data']);

    //=================================================================
    // Calling the method to get payment details
    //=================================================================
    $response = $this->paypayClient->payment->getPaymentDetails($QRCodeResponse['merchantPaymentId']);
    // 処理がうまくいってなかったら抜ける
    if($response['resultInfo']['code'] !== 'SUCCESS') {
      return;
    }

    // Collectionに変換しておく
    $QRCodeDetails = collect($response['data']);

    //=================================================================
    // Calling the method to cancel a Payment
    //=================================================================
    $response = $this->paypayClient->payment->cancelPayment($QRCodeResponse['merchantPaymentId']);
    // 処理がうまくいってなかったら抜ける
    if($response['resultInfo']['code'] !== 'REQUEST_ACCEPTED') {
      return;
    }

    \Log::info(print_r($QRCodeResponse, true));
    \Log::info(print_r($QRCodeDetails, true));
    \Log::info(print_r($response, true));
  }

  function __destruct() {
  }
}
```

logの内容

```
[2020-07-30 06:53:42] local.INFO: Illuminate\Support\Collection Object
(
    [items:protected] => Array
        (
            [codeId] => 04-PKkfM9UDxn13nFfl
            [url] => https://qr-stg.sandbox.paypay.ne.jp/28180104PKkfM9UDxn13nFfl
            [expiryDate] => 1596081556
            [merchantPaymentId] => my_payment_id_1596093507
            [amount] => Array
                (
                    [amount] => 1
                    [currency] => JPY
                )

            [codeType] => ORDER_QR
            [redirectUrl] => https://paypay.ne.jp/
            [redirectType] => WEB_LINK
            [isAuthorization] => 
            [deeplink] => paypay://payment?link_key=https%3A%2F%2Fqr-stg.sandbox.paypay.ne.jp%2F28180104PKkfM9UDxn13nFfl
        )

)
  
[2020-07-30 06:53:42] local.INFO: Illuminate\Support\Collection Object
(
    [items:protected] => Array
        (
            [status] => CREATED
            [acceptedAt] => 0
            [requestedAt] => 0
        )

)
  
[2020-07-30 06:53:42] local.INFO: Array
(
    [resultInfo] => Array
        (
            [code] => REQUEST_ACCEPTED
            [message] => Request accepted
            [codeId] => 08100001
        )

    [data] => 
    [transit] => Array
        (
            [0] => HTTP/2 202 
            [1] => date: Thu, 30 Jul 2020 06:53:42 GMT
            [2] => content-type: application/json
            [3] => x-request-id: OPA4CE2D1787C11436F95A9B13DFEDFE3D6
            [4] => x-content-type-options: nosniff
            [5] => x-xss-protection: 1; mode=block
            [6] => cache-control: no-cache, no-store, max-age=0, must-revalidate
            [7] => pragma: no-cache
            [8] => expires: 0
            [9] => x-frame-options: DENY
            [10] => x-rate-limited: 1
            [11] => 
            [12] => 
        )

)
```

## つまづきポイント
### コメント文のミス？
サンプルコードでは

```php
use PayPay\OpenPaymentAPI\Client;

$client = new Client([
  'API_KEY' => 'YOUR_API_KEY',
  'API_SECRET'=>'YOUR_API_SECRET',
 'MERCHANT_ID'=>'YOUR_MERCHANT_ID'
],false); //Set True for Production Environment. By Default this is set False for Sandbox Environment.
```
`//Set True for Production Environment. By Default this is set False for Sandbox Environment.`
って書いてるけど`true`でステージング環境(開発用)になる

### サンプルソースのミスその１(ペイロード？を作るとき)
サンプルコードでは

```php
// Creating the payload to create a QR Code, additional parameters can be added basis the API Documentation
$payload =new PaypaySdkPayload();
$payload->set_merchant_payment_id("my_payment_id");
$payload->set_code_type("ORDER_QR");
$amount = [
    "amount" => 1,
    "currency" => "JPY"
];
$payload->set_amount($amount);
$payload->set_redirect_type('WEB_LINK');
$payload->set_redirect_url('https://paypay.ne.jp/');
$payload->set_user_agent('Mozilla/5.0 (iPhone; CPU iPhone OS 10_3 like Mac OS X) AppleWebKit/602.1.50 (KHTML, like Gecko) CriOS/56.0.2924.75 Mobile/14E5239e Safari/602.1');

// Calling the method to create a qr code
$response = $client->code->createQRCode($payload);
// Printing if the method call was SUCCESS
console.log($response['resultInfo']['code']);
```

こうなってるけど、`PaypaySdkPayload`のようなクラスはない、そして`set_`の関数もない

### サンプルソースのミスその２(詳細を見るとき)
```php

// Calling the method to get payment details
$response =  $client->code->getPaymentDetails('<merchantPaymentId>');
// Printing if the method call was SUCCESS, this does not mean the payment was a success
console.log($response['resultInfo']['code']);
// Printing if the transaction status for the code has COMPLETED/ AUTHORIZED
console.log($response['data']['status']);
```

`$client->code->getPaymentDetails('<merchantPaymentId>');`実際は`$client->payment->getPaymentDetails('<merchantPaymentId>');`


### サンプルソースのミスその３(キャンセルするとき)
```php
// Calling the method to cancel a Payment
$response =  $client->code->cancelPayment('merchantPaymentId');
// Printing if the method call was SUCCESS
console.log($response['resultInfo']['code']);
```

`$client->code->getPaymentDetails('<merchantPaymentId>');`実際は`$client->payment->getPaymentDetails('<merchantPaymentId>');`
および
`// Printing if the method call was SUCCESS`って書いてて、ああ上と一緒で`SUCCESS`なんだろうなぁって思うかもしれないけど、実際は`REQUEST_ACCEPTED`が帰ってきている(ちゃんと読め私ｗ