Square APIで登録済商品に対する決済を実行する

Square APIを使って自社ECサイトに決済機能を実装しました。
Square APIの導入、サンプルの実装については@goofmintさんの[PHPでSquare Eコマース決済を試す](https://qiita.com/goofmint/items/c89fc7d711a665cb9d2a)を参考にしました。

サンプルでは金額を指定したリクエストを作成し、Transactions API の Charge を実行して決済を行いました。

```php

\SquareConnect\Configuration::getDefaultConfiguration()->setAccessToken($access_token);
$transactions_api = new \SquareConnect\Api\TransactionsApi();

//リクエストを作成
$request_body = array (
  "card_nonce" => $nonce,
  "amount_money" => array (
    "amount" => 100,
    "currency" => "JPY"
  ),
  "idempotency_key" => uniqid()
);

try {
  //決済実行
  $result = $transactions_api->charge($location_id, $request_body);
} catch (\SquareConnect\ApiException $e) {
  echo "Caught exception!<br/>";
  $result = $e->getResponseBody();		
}

```

今回、Squareダッシュボードであらかじめ登録されている商品に対して決済を実行することにより
ダッシュボード上で在庫の管理や上位売上商品のチェックなどができるようにします。

##　商品に対する決済を実行する流れ
サンプルで使用している  Transactions API、 Locations APIに加えて、
Catalog API、 Orders APIを使って決済を実行していきます。

1. Squareダッシュボード上で商品を登録
2. Catalog API の SearchCatalogObjectsRequest を実行して商品リストを取得
3. CreateOrderRequestLineItem を作成
4. Order API の createOrder を実行
5. Order Idを指定して Transactions API のChargeを実行

商品は登録されていることを前提に、2からの実装を見ていきます。

##　2. Catalog APIで商品リストを取得

Catalog APIのオブジェクトを作成し、SearchCatalogObjectRequestを実行します。
ここで1点ハマるポイントが、**現時点でCatalog APIはsandbox環境での動作に対応していません。**
なのでこのテストを行う際には各環境IDは本番のものを使用してください。
5のChargeまで実行すると当然ですがカードに対し課金が行われてしまうため、
テスト後にSquareダッシュボードより売上の払い戻しを行ってください。


```php

$catalog_api = new SquareConnect\Api\CatalogApi();
$body = new \SquareConnect\Model\SearchCatalogObjectsRequest();

try {
    $result = $catalog_api->searchCatalogObjects($body);
    echo "<pre>";
    print_r($result);
    echo "</pre>";
} catch (Exception $e) {
    echo 'Exception when calling CatalogApi->searchCatalogObjects: ', $e->getMessage(), PHP_EOL;
}
```
登録商品リスト(SearchCatalogObjectsResponse Object)が取得できました。
※ 空の項目が非常に多いため今回重要ではない部分について一部略しています

```
SquareConnect\Model\SearchCatalogObjectsResponse Object
(
    [errors:protected] => 
    [cursor:protected] => 
    [objects:protected] => Array
    (
        [0] => SquareConnect\Model\CatalogObject Object
        (
             [type:protected] => ITEM
             [id:protected] => IRNEEEFLOKSIWONIPCZNRUHF
             [updated_at:protected] => 2019-01-23T01:56:57.294Z
             [version:protected] => 1548208617294
             [present_at_all_locations:protected] => 1
             [item_data:protected] => SquareConnect\Model\CatalogItem Object
             (
                 [name:protected] => 塩バターパン
                 [description:protected] => ほんのりバター香る人気No.1のパンです
                 ...(略)...
                 [tax_ids:protected] => Array
                 (
                     [0] => HFCCV3RNRA5V75JEMD4QTLDF
                 )
                 [modifier_list_info:protected] => 
                 [image_url:protected] => 
                 [variations:protected] => Array
                 (
                     [0] => SquareConnect\Model\CatalogObject Object
                     (
                         [type:protected] => ITEM_VARIATION
                         [id:protected] => QBORT2E36FKXPNLY42EMWPBA
                         [updated_at:protected] => 2019-01-23T01:56:57.294Z
                         [version:protected] => 1548208617294
                         [item_variation_data:protected]=>SquareConnect\Model\CatalogItemVariation Object
                         (
                             [item_id:protected] => IRNEEEFLOKSIWONIPCZNRUHF
                             [name:protected] => 販売価格
                             [sku:protected] => 
                             [upc:protected] => 
                             [pricing_type:protected] => FIXED_PRICING
                             [price_money:protected] => SquareConnect\Model\Money Object
                             (
                                 [amount:protected] => 160
                                 [currency:protected] => JPY
                             )
                          )
                      )
                  )
             )
        )
    )
)
```

##　3.CreateOrderRequestLineItem を作成
Orders APIにリクエストするための商品（LineItem）を作成します。
2 で取得したSearchCatalogObjectsResponse Objectのvaridations内のidを抽出し、
CreateOrderRequestLineItemにid、個数をセットし、arrayに格納します。
購入する商品が複数ある場合はここで追加していくことになります。

```php

$item_id = $result['objects'][0]['item_data']['variations'][0][id];
$item = new \SquareConnect\Model\CreateOrderRequestLineItem;
$item->setCatalogObjectId($item_id);
$item->setQuantity('1');

$lineItems = array();	
array_push($lineItems, $item);
```

##　4.Order API の createOrder を実行
3で作成したLineItemsとuniqid()を設定したCreateOrderRequestを作成して、
Orders APIの createOrder を実行します。

```php
$orders_api = new SquareConnect\Api\OrdersApi();
$request = new \SquareConnect\Model\CreateOrderRequest();
$request->setIdempotencyKey(uniqid());
$request->setLineItems($lineItems);
	
try {
    $result = $orders_api->createOrder($location_id, $request);

}catch (Exception $e) {
    echo '<pre>';
    echo 'Exception when calling OrdersApi->createOrder:', $e->getMessage(), PHP_EOL;
}
```

これで商品を指定したオーダーが作成されました。
CreateOrderResponseは以下のようになります。(一部省略)

```
SquareConnect\Model\CreateOrderResponse Object
(
    [order:protected] => SquareConnect\Model\Order Object
    (
    　   [id:protected] => WBOP7aUfNxFGuSZk8wsgmswFsVHZY
         [location_id:protected] => 325X8D9WZ2239
         [reference_id:protected] => 
         [line_items:protected] => Array
         (
             [0] => SquareConnect\Model\OrderLineItem Object
             (
                 [name:protected] => 塩バターパン
                 [quantity:protected] => 1
                 [note:protected] => 
                 [catalog_object_id:protected] => QBORT2E36FKXPNLY42EMWPBA
                 [variation_name:protected] => 販売価格
               　・・・(略)・・・
                 [total_money:protected] => SquareConnect\Model\Money Object
                 (
                     [amount:protected] => 160
                     [currency:protected] => JPY
                 )
            )
      )
     [total_money:protected] => SquareConnect\Model\Money Object
     (
         [amount:protected] => 160
         [currency:protected] => JPY
     )
     ・・・(略)・・・
  )
    [errors:protected] => 
)
```
## 5. Order Idを指定して Transactions API のChargeを実行

4のレスポンスからChargeRequestに指定するためのOrder Idとtotal_moneyを抽出し、
ChargeRequestを作成します。サンプルでは$request_bodyとしてarrayを直接作成していましたが、
今回はそれぞれ値をsetして作成しています。

```php
$order_id = $result['order']['id'];
$amount_money = $result['order']['total_money']; 
		
$chargeRequest = new \SquareConnect\Model\ChargeRequest();
$chargeRequest->setIdempotencyKey(uniqid());
$chargeRequest->setAmountMoney($amount_money);
$chargeRequest->setCardNonce($nonce);
$chargeRequest->setOrderId($order_id);

try {
    $result = $transactions_api->charge($location_id, $chargeRequest);

} catch (\SquareConnect\ApiException $e) {
    echo "Caught exception!<br/>";
    print_r("<strong>Response body:</strong><br/>");
    echo "<pre>"; var_dump($e->getResponseBody()); echo "</pre>";
    echo "<br/><strong>Response headers:</strong><br/>";
    echo "<pre>"; var_dump($e->getResponseHeaders()); echo "</pre>";
}
```

chargeが正常に行われると以下のようなレスポンスが返ってきます。
order_idに正しく設定されていることが確認できます。

```
SquareConnect\Model\ChargeResponse Object
(
    [errors:protected] => 
    [transaction:protected] => SquareConnect\Model\Transaction Object
        (
            [id:protected] => WBOP7aUfNxFGuSZk8wsgmswFsVHZY
            [location_id:protected] => 325X8D9WZ2239
            [created_at:protected] => 2019-01-23T04:27:33Z
            [tenders:protected] => Array
                (
                    [0] => SquareConnect\Model\Tender Object
                        (
                            [id:protected] => BxL59X98I4YkuJaURkBR3vMF
                            [location_id:protected] => 325X8D9WZ2239
                            [transaction_id:protected] => WBOP7aUfNxFGuSZk8wsgmswFsVHZY
                            [created_at:protected] => 2019-01-23T04:27:31Z
                            [note:protected] => Online Transaction
                            [amount_money:protected] => SquareConnect\Model\Money Object
                                (
                                    [amount:protected] => 160
                                    [currency:protected] => JPY
                                )
                            [processing_fee_money:protected] => 
                            [customer_id:protected] => 
                            [type:protected] => CARD
                            [card_details:protected] => SquareConnect\Model\TenderCardDetails Object
                                (
                                    [status:protected] => CAPTURED
                                    [card:protected] => SquareConnect\Model\Card Object
                                        (
                                            [id:protected] => 
                                            [card_brand:protected] => VISA
                                            [last_4:protected] => 2362
                                        )
                                    [entry_method:protected] => KEYED
                                )
                            [cash_details:protected] => 
                        )
                )
            [refunds:protected] => 
            [reference_id:protected] => 
            [product:protected] => EXTERNAL_API
            [client_id:protected] => 
            [shipping_address:protected] => 
            [order_id:protected] => WBOP7aUfNxFGuSZk8wsgmswFsVHZY
        )
)
```
Squareダッシュボード上でも商品に対する売上が反映されていることが確認できました。
![スクリーンショット 2019-01-23 13.33.26.png](https://qiita-image-store.s3.amazonaws.com/0/347435/9db2a745-4bde-4f66-9b20-308d91fa718d.png)

## おわりに
まだまだ日本語の文献が少なく、Stack Overflowで検索したり、リファレンスを翻訳しながら読み進めて実装しました。質問はもちろん間違いなどありましたらコメントを頂けますと幸いです。