ECサイト運営開発記

PHPフレームワーク Laravelの使い方を中心とした通販サイトの開発日記

okudo 東京の担々麺

f:id:nohohon_x:20180524213654j:plain

新宿御苑駅から徒歩5分以内、担々麺が人気のお店「okudo 東京」の担々麺 750円。
非激辛系担々麺の中では一番美味しかったと思う。
近い内に、また再訪して、期間限定の麻婆麺を食べたい。きっと美味しいはず。

okudo 東京

食べログ okudo 東京

Linux版のcomposerがダイムアウトになって動かない場合

Linux版のComposerをいくら実行してもタイムアウトになって、いろいろとググってみると、
名前解決のところでトラブっている様子。
以下のコマンドを実行して、無事、Composerが動作し解決。

sudo sh -c "echo 'precedence ::ffff:0:0/96 100' >> /etc/gai.conf"

ideapad320SにUbuntu Linuxをインストールする イントール設定&再起動トラブル解決編

Lenovo ideapad320SにUbuntu Linux 17.04をインストールする。
インストールしてみると、ちょっとした問題もあったので、解決方法も含めて残しておく。

手順1
WindowsRufusUbuntuのisoイメージをダウンロードして、ブータブルUSBを作成。
forest.watch.impress.co.jp

手順2
BIOSの設定メニューからUSB Bootを有効にする。
推奨する BIOSの起動方法 - IdeaPad/Lenovo ノートブック

手順3
USBを指してF12キーを押して、USBメモリを選択して起動。

手順4
try ubuntu(試用)を選択して無線LAN、キーボード、タッチパッドが正常に動くかどうか確かめる。

手順5
インストールウィザードに従って作業を進めて再起動。

しかし、この後、問題発生。
この再起動でうまい具合に期待通りに再起動してくれない場合がある。
また、その時は再起動に成功しても、その後の再起動やシャットダウンで失敗することがある。
なぜだろう?そこで、ログを参照してみると、こんなメッセージがある。

~$ cat /var/log/kern.log 
pcieport 0000:00:1c.5: PCIe Bus Error: severity=Corrected, type=Data Link Layer, id=00e5(Transmitter ID)


とりあえず、それっぽいキーワードでググってみると、Ubuntuのフォーラムに、同じような事例があった。
askubuntu.com

【解決策】
まず、テキストエディタvimをインストールしておく

~$ sudo apt install vim 
~$ sudo vim /etc/default/grub

# If you change this file, run 'update-grub' afterwards to update
# /boot/grub/grub.cfg.
# For full documentation of the options in this file, see:
#   info -f grub -n 'Simple configuration'

GRUB_DEFAULT=0
GRUB_HIDDEN_TIMEOUT=0
GRUB_HIDDEN_TIMEOUT_QUIET=true
GRUB_TIMEOUT=10
GRUB_DISTRIBUTOR=`lsb_release -i -s 2> /dev/null || echo Debian`
GRUB_CMDLINE_LINUX_DEFAULT="quiet splash"
GRUB_CMDLINE_LINUX=""

どこを編集するかというと、 GRUB_CMDLINE_LINUX_DEFAULTの末尾にpci=noaerというオプションを付け加えればいいだけ。
そして、編集を終えて再起動。

GRUB_CMDLINE_LINUX_DEFAULT="quiet splash pci=noaer"

~$ sudo update-grub
~$ reboot

これで、今の所、ほぼ問題なくUbuntuが使えるようになりました。

Lenovo ideapad320S にUbuntuを入れて贅沢なLinuxマシンにする 購入編

Linux専用に使っていた初代XPS13がお亡くなりになったので、新しいLinux専用マシンが欲しくてノートパソコンを物色。
Lenovoで発売されているideap320Sがいい感じだな〜と思っていたが、メモリ4GBで10万円を超える量販店モデルしか取り扱っておらず、NTT-Xストアをを見ていると、メモリ8GB版が8万円台で売っているのを発見。

www3.lenovo.com


nttxstore.jp

これはお得すぎる!!!
早速、ゴールドモデルを購入し、早速、使ってみた。


f:id:nohohon_x:20171216020358j:plain
ideapad320S

【ideap320Sの良い所!】

  • フルHDの非光沢ディスプレイ
  • 重さ1.1kgと軽量で持ち運びにも苦にならない
  • 第8世代の4コアCPU Corei5-8250Uで高速。
  • SSDも256GB NTT-Xストアのモデルはお買い得!
  • 180度開閉も可能
  • 動作音がそこそこ静か (初代XPS13との比較)ファンレス設計ではないです。

f:id:nohohon_x:20171216020351j:plain
非光沢ディスプレイのideapd320S

【ideap320Sの悪いところ】

  • USB Type Cポートが付いているが電源供給はできない
  • 外部ポートもう少し省いて軽量化しても良かったのでは?

現在もNTT-Xストアでグレーもゴールドも売っているので、量販店モデルしか知らない人はこちらもチェックすることをオススメする。

Ubuntuのインストールについては次のエントリーで。

Stripe APIで決済手数料を取得する方法

Stripe APIで決済(Charge)の手数料の取得方法がわからず、四苦八苦していましたが、Balance Transactionで取得するらしいので、
その方法を残しておくことにする。

nohohox.hateblo.jp

  • BalanceTransaction APIでsourceにCharge IDを渡してあげればいいだけ。
<?php

  // キーの設定
  \Stripe\Stripe::setApiKey(Config::get("services.stripe.secret"));

  $balanceTransaction=\Stripe\BalanceTransaction::all(
    ["source"=>"ch_19***************"]
  );

  dd($balanceTransaction);

  • 結果

f:id:nohohon_x:20170120142204p:plain


シンプルにChargeから取得できれば言うことないんですが、ちょっと回りくどい印象。
他に方法はなさそうなのがちょっと残念。

Laraveを使ってStripeの決済を導入する

Laravelで利用可能なインターネット決済APIの「Stripe」を試してみたので、基本的な利用方法をまとめておく。

f:id:nohohon_x:20161029025137p:plain

「Stripeの特徴」

  • 月額固定料金なし
  • 1取引あたり3.6%の手数料
  • JavaScriptのコードを貼り付けるだけで、ネット決済システムを導入可能
  • 定期支払も可能。
  • PHPRubyPythonJavaなど様々な言語やプラットフォームに対応
  • Apple Payにも対応
  • シンプルでわかりやすいAPIが用意されている
  • APIから決済成立/全額払い戻す/一部返金など様々な操作が可能

アカウントの作成

アカウントの作成はメールアドレスとパスワードの登録だけで可能。テスト環境はそれだけで用意ができます。

Stripe: Register


テスト環境のAPIキーの確認

StripeのAPIにアクセスするために、ダッシュボードの右上のアカウント情報からAPIキーを確認しておきましょう。Laravelでは、基本的にSecretKeyのみを使います。
f:id:nohohon_x:20161029030528p:plain


テスト環境と本番環境のAPIキーが表示されている。今回はテスト環境のAPIを使用。
f:id:nohohon_x:20161029030522p:plain


Laravelで環境をセットアップ

以下、Laravelは5.3を前提として解説します。

  • composer.jsonに"laravel/cashier": "~7.0"を追加して、composer update。
  • config/app.phpのServiceProviderにLaravel\Cashier\CashierServiceProviderを追加
<?php

    'providers' => [
      /* 中略*/
      Laravel\Cashier\CashierServiceProvider::class,
    ],

  • config/services.phpのstripeの項目にテスト用のSecret Keyを設定する。.envに記述してもOK。
<?php

    'stripe' => [
        'model' => App\User::class,
        'secret' => env('STRIPE_SECRET'),
    ],
  • 今回はモデルには決済機能を組み込まないのでスルー。

Stripe APIを使ってカードのトークンを作り、決済手続きをする。(エラーチェックは省きます)

  • /routes/web.phpにサンプルコードを記述
    • 手順はシンプル
      • 入力フォムから受け取ったカード番号、有効年、有効月、セキュリティコードをAPIに送信すると、クレジットカードのトークンが作成される
        • 作ったトークンを元に、決済オブジェクトの作成を行う。基本的にはこれで手続きは終わり。とても簡単。
        • amountは金額、captureをfalseにしておくと、仮売上の状態。デフォルトはtrueの実売上。
<?php

  <form class="card-block" method="post" action="{{URL::to("/payment")}}">
    <div class="card">
      <div class="card-header">カード情報入力</div>
      <div class="card-block">
        <fieldset>
          <legend>CARD INFO</legend>
          <div class="form-group">
            <label>NAME</label>
            <input type="text" class="form-control" name="name" placeholder="YOUR NAME" value="PIKO TAROU">
          </div>
          <div class="form-group">
            <label>NUMBER</label>
            <input type="text" class="form-control" name="number" placeholder="カード番号" value="4242424242424242" >
          </div>
          <div class="form-group">
            <label>EXPIRE</label>
            <div class="row">
              <div class="col-lg-3">
                <input type="number" class="form-control" name="exp_month" placeholder="" value="10">
              </div>
              <div class="col-lg-3">
                <input type="number" class="form-control" name="exp_year" placeholder="" value="2020">
              </div>
            </div>
          </div>
          <div class="form-group">
            <label>CVC</label>
            <input type="number" class="form-control" name="cvc" placeholder="***" value="123">
          </div>
        </fieldset>
        <fieldset>
          <legend>CHARGE OPTIONS</legend>
          <div class="form-group">
            <label>PRICE</label>
            <input type="text" class="form-control" name="amount" placeholder="金額" value="1000" >
          </div>
          <div class="form-group">
            <label>DESRIPTION</label>
            <input type="text" class="form-control" name="description" placeholder="説明文" value="hogehoge" >
          </div>
        </fieldset>
      </div>
      <div class="card-footer">
        <input type="submit" class="btn btn-block btn-danger" value="決済">
      </div>
    </div>
  </form>
<?php

Route::post("/payment",function(Request $request){

  // キーの設定
  \Stripe\Stripe::setApiKey(Config::get("services.stripe.secret"));

  // トークンを作る
  $token=\Stripe\Token::create(array(
    "card" =>  [
      "number" => $request->input("number"),
      "exp_month" => $request->input("exp_month"),
      "exp_year" => $request->input("exp_year"),
      "cvc" => $request->input("cvc"),
      "name" => $request->input("name")
    ]
  ));


  // 決済
  $charge=\Stripe\Charge::create(array(
    "amount" => $request->input("amount"),
    "currency" => "jpy",
    "source" => $token,
    "description" => $request->input("description"),
    "capture"=>false
  ));

  // dd($charge);

  return back();
}
  • 決済オブジェクト一覧を取得する
<?php

Route::post("/index",function(Request $request){

  // キーの設定
  \Stripe\Stripe::setApiKey(Config::get("services.stripe.secret"));

  // 決済一覧を50件取得
  $chargeList=\Stripe\Charge::all(array("limit" =>50));

  return view("stripe/index",["chargeList"=>$chargeList]);

}
  • 決済オブジェクト一覧をbladeのViewで表示する
<?php


      @forelse ($chargeList->data as $key => $value)
        <tr>
          <td>
            <a href="{{URL::to("/view/".$value->id)}}">{{$value->id}}</a>
          </td>
          <td>
            {{$value->source->name}}
          </td>
          <td class="text-xs-center">&yen;{{$value->amount}}</td>
          <td class="text-xs-center">{{$value->source->brand}}</td>
          <td class="text-xs-center">
            @if($value->refunded==true)
              払い戻し済み
            @else
              @if($value->captured)
                実売上
              @else
                仮売上
              @endif
            @endif
          </td>
          <td class="text-xs-center">
            @if($value->refunded==false)
              @if($value->captured==false)
                <a href="{{URL::to("/capture/".$value->id)}}">実売上にする</a>
                /
              @endif
              <a href="{{URL::to("/refund/".$value->id)}}">払い戻す</a>
            @endif
          </td>
        </tr>
      @empty
      @endforelse

  • 決済を仮売上から実売上にする
<?php

Route::any("capture/{id}",function($id){

  // キーの設定
  \Stripe\Stripe::setApiKey(Config::get("services.stripe.secret"));

  // 実売上に変更
  $ch = \Stripe\Charge::retrieve($id);
  $ch->capture();

  return back();

});
  • 決済を全額払い戻し
<?php

Route::any("refund/{id}",function($id){

  // キーの設定
  \Stripe\Stripe::setApiKey(Config::get("services.stripe.secret"));

  // 払い戻し
  $re = \Stripe\Refund::create(array(
    "charge" => $id
  ));

  return back();

});
  • 決済を一部払い戻し
<?php

Route::post("refund-amount/",function(Request $request){

  // キーの設定
  \Stripe\Stripe::setApiKey(Config::get("services.stripe.secret"));

  // 払い戻し
  $re = \Stripe\Refund::create(array(
    "charge" => $request->input("id"),
    "amount" =>$request->input("amount",0),
  ));

  return back();

});


申し込みからテストまで簡単にできるので、Web決済に悩んでいる方はStripeはとてもオススメです。
ただし、日本語ドキュメントはまだ揃っていないことに加え、ダッシュボードもまだ英語なので、そこはWebPayに軍配が上がる感じです。

stripe.com

祖師ヶ谷大蔵の麻婆麺 あかずきん

祖師ヶ谷大蔵に麻婆麺が食べられるお店が出来たらしいので、小田急祖師ヶ谷大蔵駅まで遠出。新宿から各駅停車に乗って12駅、意外と疲れる距離。

 

「あかずきんの外観」

f:id:nohohon_x:20161007133144j:plain

 

 店の入口にある券売機で麻婆麺の食券を購入して店員さんに渡すと、辛さを選べます。1~3まで選べて、1辛はカレーの中辛よりちょっと辛い程度だそうです。で、2辛を頼むことに。見た目は超激辛なビジュアル。しかし、麻婆豆腐自体は甘めでとろみのあるスープでやみつきになる美味さ。辛さが物足りない場合は、卓上の胡椒、山椒、花椒などを入れて辛さと刺激を調節することができるので、2辛でも問題ないかも。中本でいうと、蒙古卵麺くらいの辛さ?

追加料金で追い飯も可能らしいので、ミニ麻婆飯も食べられるので、大食漢の人も満足できる。

f:id:nohohon_x:20161007132033j:plain

麻婆麺はスープが醤油系のスープで薄味になりがちな店が多い中、この店はとろみのある濃厚スープなので、中毒性も高くまた来たくなる味だった。場所が祖師ヶ谷大蔵なのでちょっと遠いのが難点。次食べるときは、激辛に挑んでみたい。

 

関連ランキング:中華麺(その他) | 祖師ケ谷大蔵駅成城学園前駅