読者です 読者をやめる 読者になる 読者になる

akiyoko blog

akiyoko の IT技術系ブログです

「ビットコインとか勉強会#4」に参加してきました

勉強会 仮想通貨

会場

株式会社ミクシィ 休憩スペース
東京都渋谷区東1-2-20(住友不動産渋谷ファーストタワー7F)

Twitter

twitter.com

 

全体の感想など

この年始にまた 急騰&暴落 した今アツアツのビットコインについての勉強会に初めて参加してきたのですが、新しく耳にする話ばかりですごく刺激的でした。

(参考)Bitcoin Price Index - Real-time Bitcoin Price Charts


さすがに事前情報無しでは全く着いていけないなと思ったので、事前に一冊読んでおきました。初歩の初歩から分かりやすく解説されていて、内容も非常に面白かったです。ビットコインの概要、メリット・デメリットなどがバッチリ理解できました。気軽に読めるページ量(75ページ)だったのも+1。



ちょうど勉強会の前日にアップされていたホットエントリーの記事です。こちらも非常に勉強になりました。

blog.clock-up.jp



あと、こちらの記事も分かりやすかったです。

bitcoin.peryaudo.org

Bitcoinは、

  • 電子署名を使い、コインを取引のかたまりとして表現し、
  • 二重譲渡をブロックチェーンと仕事の証明により防ぎ、
  • ブロックの生成者には報酬が与えられる。(マイニング)

うーん、実に簡潔で分かりやすいです。



ところで、「ビットコイン解説本」でも勉強会でも話に挙がったように、ビットコインは前途洋々、完全無欠の仮想通貨というわけではないようです。cameong 氏が懸念していたのは(例えば中国の)一国集中。半減期が来るなどして difficulty が上がって採掘に掛かるマシンパワーのコストに対して報酬がペイしなくなってくると、中国のチームだけがマイナーとして残っていくと予想され、そうなったときに例えば当局がグレートファイアーウォールで干渉したりすると、支払いがいつまで経っても承認されないという事態も起こり得るとのこと。

あるいは、2100万BTC が掘り尽くされた後の世界はどうなるのか。ビットコインが今後どうなっていくのか、どのように世界の経済を変えていくのか、まだまだ何が起こるか予測不可能な未来が待っているのだなぁと感じました。


あと、この暗号通貨読書会グループで「CoinTip」という Twitter 上で使える Bitcoin 投げ銭アプリを作ったらしいです。



 

ビットコイン 超入門概論(仮)

Kawagoe Koji 氏


  • 仕組み
    • ウォレット・・・ユーザがビットコインを管理するためのアプリ
    • トランザクション・・・ウォレットから他者への送金処理
    • マイニング・・・送金を承認し、新たなブロックを台帳(ブロックチェーン)に繋ぐ作業
  • 何が革新的か?
    • PoW(Proof of Work)と非中央集権

 

コマンドラインで色んな暗号通貨を送金してみよう

cameong


  • 今回紹介された仮想通貨
    • Bitcoin・・・王道。ブロック生成時間は10分と長め
    • NEM・・・PoI。Bitcoin 2.0(ユーザ独自通貨発行 etc)
    • Zcash・・・ゼロ知識証明。匿名性高い
  • 用語
    • Full node・・・全トランザクションを保有するノード。Bitcoin の全トランザクションは現時点で 100GBくらいある
    • SPV node・・・いわゆるライトウォレット。送金に特化したノード

2016年の akiyoko blog 振り返り

その他

f:id:akiyoko:20170103161118j:plain:w500

明けましておめでとうございます。今年も小網神社に初詣に行ってきました。

というわけで新年明けまして少し経ちましたが、昨年(2016年)の akiyoko blog を振り返っておきたいと思います。


ちなみに 2015年の振り返りはこんな感じでした。

<過去記事>
akiyoko.hatenablog.jp



2016年の akiyoko blog 振り返り

2012年6月から開始したこのブログですが、昨年12月に累計 100万PVを突破していました。
ありがとうございます!


ところで、昨年一年間で作成した記事は合計 44本でした。

ブログを開始して以来初めて週一本ペースがキープできませんでした。しかしながら、実戦に力を入れなければいけなかった一年でブログをやり過ぎないように多少気をつけていたので、まあ仕方ないところでしょう。


全記事 44本中、Python 関連の記事が 18本で全体の 4割以上(そのうち Django 関連が 13本、Mezzanine 関連が 7本)、決済関連が 8本でした。Django や Mezzanine の記事を書いてもアクセスが全然跳ねないのは重々承知なのですが 他にネタもないので 書かないわけにはいきません。今後もどんどん書いていきますよー!


また昨年は、社外の勉強会に11回参加し、その内 8本を記事としてアップしましたが(とあるワークショップに参加した3回分については記事を書いていません)、こちらもアクセスは全然でした。まあ、こちらも想定内ですが。。


そして前回に引き続き、各記事ごとのアクセス数ランキングです。
昨年のアクセス数(*1)ランキング上位 30本をリストアップしてみたのですが、昨年の記事 44本中 30位以内に入ったのはわずか 6本でした。 *2


ブログ記事ごとのアクセス数ランキング(akiyoko blog 2016年)

# 昨年比 タイトル 作成日 ポイント
1 「プロジェクトマネージャ試験」に一発合格するための三か条 - akiyoko blog 2014/10/26 169.5
2 AppStore 登録前の iOSアプリを Ad-Hoc で配布してインストールする方法 - akiyoko blog 2014/08/23 87.4
3 Git で コミットを無かったことにする方法 (git revert の使い方) - akiyoko blog 2014/08/21 65.5
4 Video.js を使って HLS形式の動画をストリーミング再生する - akiyoko blog 2015/08/11 65.2
5 Python でリストのソートまとめ - akiyoko blog 2014/09/26 49.5
6 日本統計学会認定「統計検定2級」に合格しました - akiyoko blog 2014/12/30 39.1
7 「道は開ける」を読んだ - akiyoko blog 2014/04/13 36.2
8 「Python 3 エンジニア認定基礎試験」に合格しました! - akiyoko blog 2016/12/21 36.0
9 Windows で R(統計解析ツール)を使う - akiyoko blog 2014/11/07 33.3
10 初心者がプルリクまでに覚えるべきたった 9つの厳選 Gitコマンド - akiyoko blog 2014/12/02 29.5
11 Python で Selenium WebDriver を使ったブラウザテストをする方法 - akiyoko blog 2014/04/29 27.1
12 Backbone.js を基礎からやってみよう - akiyoko blog 2015/08/07 26.1
13 nodebrew で Mac の Node.js 環境をスッキリさせた - akiyoko blog 2015/06/20 21.8
14 Open BroadCaster Software (OBS) で YouTube ライブストリーミングを使った動画配信をする方法 - akiyoko blog 2016/01/26 20.4
15 jQuery で Ajax を使ってみる - akiyoko blog 2014/07/21 19.5
16 Ansible 初心者なら、まずは Ansible Galaxy から始めてみよう - akiyoko blog 2015/12/06 18.5
17 MongoDB の使い方まとめ - akiyoko blog 2014/08/01 18.3
18 知的財産管理技能検定2級を受験してきました - akiyoko blog 2012/11/25 17.4
19 Pythonでヒストグラム - akiyoko blog 2013/06/07 16.7
20 Apple Developer Program の有効期限が切れてしまったときの対処方法 - akiyoko blog 2015/11/13 16.3
21 iMovie の設定あれこれ - akiyoko blog 2016/02/01 15.5
22 今年の流行語大賞「JPAP」(Jupyter / Python / Anaconda / Pyenv)〜 ゼロからはじめる Jupyter Notebook 〜 - akiyoko blog 2016/12/06 15.3
23 iPad上でアプリ内課金 (In-App Purchase) の実機テストをする方法メモ - akiyoko blog 2013/11/09 15.0
24 初めてのTOEIC受験で800点オーバーを取るための勉強法 - akiyoko blog 2013/09/05 14.7
25 ベスト・オブ・Django本! - akiyoko blog 2016/12/05 14.6
26 Python, Django 界隈の単体テスト事情(unittest / nose / django-nose) - akiyoko blog 2015/01/01 13.9
27 【ポケモンGO】富士山頂でポケモン獲ったどーー! 頂上でゲットしたポケモンは一体何だった?? - akiyoko blog 2016/08/10 13.5
28 「AWS認定 ソリューションアーキテクト - アソシエイト試験」に合格しました - akiyoko blog 2015/06/09 13.3
29 Pythonのself - akiyoko blog 2012/06/27 12.6
30 見よ!これが Python製の WordPress風フルスタックCMSフレームワーク「Mezzanine(メザニン)」だ! - akiyoko blog 2015/12/23 11.2



#27 の「【ポケモンGO】富士山頂でポケモン獲ったどーー! 頂上でゲットしたポケモンは一体何だった?? - akiyoko blog」は、これまでないテイスト(技術的な事柄には一切触れていません)で実験的に書いた記事だったのですが、思いのほか伸びませんでした。。アクセスを集めるのは本当に難しいですね。

akiyoko.hatenablog.jp



そのほか、個人的に頑張って書いたのにアクセスが全然だったと感じている記事のワースト3は以下になります。

PayPal や Django に関する記事のニーズが単純に少ないというだけかもしれませんし、いずれも 10,000字を超える超長文記事だったので Google 神にスパムと見なされてしまったのかもしれません。。

暇を持て余している方は是非お読みになってくださいませ。

akiyoko.hatenablog.jp
akiyoko.hatenablog.jp
akiyoko.hatenablog.jp



今年の目標

ユーザーの満足度を示す指標値と巷で言われている「ページ/セッション」は「1.18」でした。前回「1.19」だったのでほとんど変わらずですが、昨年終盤に Google Analytics の数値がスパムに汚されてしまったので、信頼性は若干低いかもしれません。


昨年は長文で重めの記事が多かったので、今年はもう少し的を絞った記事を書いていきたいと思います。

あと、今年は仕事が忙しくなりそうなので投稿数は少なめになるかもしれません。
悪しからず。


 

*1:純粋な PV数ではなく、作成日からの日数で割ったポイントで算出しました。

*2:作成日のところを黄色く塗っています。

2016年に読んだ本のリスト

年末ということで今年の読書歴を振り返ってみたのですが、2016年は、雑誌やマンガ、技術系の本を除いて11冊の本を読んでいました。

今年はなるべく、流行りの本よりも多くの人に読まれている古典系の本を読みたいと考えていたのですが、本を読むのが本当に遅いので月にほぼ一冊ペースになってしまいました。来年はもう少しペースを上げて読んでいきたいと思います。


 

ビジネス系

1.ビジョナリー・カンパニー

オススメ度:★★★★★


今年のはじめに「リーン・スタートアップ ムダのない起業プロセスでイノベーションを生みだす」に続けて読んだ本。 「リーン・スタートアップ」がスタートアップ(*1)が成功するためのビジネス開発手法を説く本であるのに対して、「ビジョナリー・カンパニー」は時代を超えて繁栄する偉大な企業の「真理」を描き出した、1995年発刊の経営書です。

原題は「Built to Last: Successful Habits of Visionary Companies」で、永遠に続く企業の秘訣、という意味でしょうか。この本の一番の特徴は、厳しい条件から選び出した18社の偉大なトップ企業とそのライバル企業(前者を金メダリストとすると銀・銅メダリストクラス)を比較して、ビジョナリー・カンパニーをビジョナリー・カンパニーたらしめている要素をあぶり出すというその分析手法にあります。なお、紹介されている 36社のうち日本企業はソニーくらいで、あまり馴染みのない企業ばかりという印象が否めませんでした。


本書を貫く主題として、ビジョナリー・カンパニーの「ビジョン」は、

ビジョン=基本理念(長期に渡って維持される基本理念)+進歩(将来の理想に向けた進歩)

であり、基本理念を熱心に維持すると同時に、進歩を促すための具体的でしっかりした仕組みを持った組織をつくることが、ビジョナリー・カンパニーの基本とされています。またここで、基本理念は「我々が何者で、何のために存在し、何をやっているのかを示すもの」であり、

基本理念=基本的価値観(組織にとって不可欠で不変の主義)+目的(単なるカネ儲けを超えた会社の根本的な存在理由)

と書かれています。
なお、進歩については、ビジョナリー・カンパニーは組織に活力をみなぎらせるためにきわめて大胆で興奮を呼び起こす「BHAG(ビーハグ:社運を賭けた大胆な目標)」を掲げる傾向があるとし、さらに BHAG に続く第二の種類の進歩として「進化による進歩(枝分かれと剪定)」を積極的に促すとしています。


最後に、本書から気になった一節を抜粋。

ビジョナリー・カンパニーの創業者はどこまでも粘り抜き、「絶対に、絶対に、絶対にあきらめない」を座右の銘としている。しかし、何を粘り抜くのか。答えは会社である。アイデアはあきらめたり、変えたり、発展させることはあるが、会社は絶対にあきらめない。会社の成功とは、あるアイデアの成功だと考える起業家や経営幹部が多いが、(中略)善し悪しは別にして、ひとつのアイデアにこだわることなく、長く続くすばらしい組織をつくり上げることを目指して、粘り抜くことができる。

後に述べる「GRIT」にも繋がっている話で、非常に興味深い一節だと思いました。


 

2.ビジョナリー・カンパニー2

オススメ度:★★★★★


原題「Good to Great: Why Some Companies Make the Leap...And Others Don't」(良好から偉大へ)が示す通り、偉大な企業へ飛躍を遂げた企業の転換点に着目して分析し、前著「ビジョナリー・カンパニー」では取り上げられなかった「どうすれば偉大な企業になれるのか」「良好な企業から抜け出せない病を治療するにはどうすればよいのか」といったテーマを取り上げた、2001年発刊のベストセラー経営書です。

「ビジョナリー・カンパニー」シリーズは、2010年発刊の三作目「ビジョナリーカンパニー3 衰退の五段階」までが特に有名ですが(*2)、三作目は衰退した企業の特徴がテーマということで、まずは成功の秘訣を知りたいという経営者や起業家の興味から外れてしまい、一作目と二作目だけを読むという人も多いようです。あと、本の内容から二作目を読んでから一作目を読む方がよいと言う人も中にはいるようですが、私はそのまま一作目を読んでから二作目を読むというので全然問題ないと思いました。


内容をひと言で言えば、良い組織を偉大な実績を持続できる組織に変える法則として、

第五水準の指導者がいて、適切な人をバスに乗せ、厳しい現実を直視する規律を持ち、真実に耳を傾ける社風を作り出し、評議会を作って三つの円が重なる部分で活動し、すべての決定を単純明快な針鼠の概念に従って下し、虚勢ではなく現実の理解に基づいて行動すればよい。

と書かれています。

「ビジョナリー・カンパニー」シリーズを通して言えますが、独特な比喩や言い回しやあって、実際に本を読んでいない人には全然ピンと来ません。逆に、一度理解してしまえば長期間記憶が定着するのでしょう。


私が一番好きなフレーズは、針鼠の概念(本質を見極めて単純化した概念)で、

  • 自社が世界一になれるもの
  • 経済的原動力になるもの
  • 情熱を持って取り組めるもの

の交点を徹底的に見極め、それに矛盾しない社運を賭けた大胆な目標(BHAG)を立ち上げ、そこに向かっていくことがビジョナリー・カンパニーへの道だということです。

f:id:akiyoko:20170101112722p:plain:w500

そのほか全体を通して、規律の文化(規律のある人材・規律のある考え・規律のある行動)をいかに作り上げるか、が組織にとって非常に重要とのことです。


最後に、「ストックデールの逆説」と著者が呼んでいる一節があるのですが、

どれほどの困難にぶつかっても、最後には必ず勝つという確信を失ってはならない。そして同時にそれがどんなものであれ、自分が置かれている現実の中でもっとも厳しい事実を直視しなければならない。

これも GRIT に通じる考え方なのかな、と思いました。



 

3.ゼロ・トゥ・ワン

オススメ度:★★★★★


PayPal 創業者で、最近ではドナルド・トランプの政権移行チームのメンバーにもなったという起業家で投資家の ピーター・ティール の本です。ビジョナリー・カンパニー1・2の二冊とまとめて一気読みしました。

著者のピーター・ティールは採用面接で「賛成する人がほとんどいない、大切な真実とは何か?」と必ず訊くと言います。その理由は、本当に社会のためになる新しいものを生み出す(ゼロから1を生み出す)ためにはこれまでと「違う」ものに着目しなければならず、それが新たな市場の独占を可能にし、企業に利益をもたらすからだと説きます。

要するに「常識を疑え」ということなのですが、未来はどうなるか分からないという「常識」さえも疑ってしまえ、というのが彼の考え方です。

2014年発刊のこの本は、2000年4月に崩壊したドットコム・バブルの反省から生まれた「リーン」(計画せずに製品を柔軟に改良するという開発手法)の考え方は現代のスタートアップビジネスには合わないとし、そのアンチパターンとして、

  • 大胆に賭ける
  • 成功を実現するための計画をする(出来が悪くても無いよりはマシ)
  • 競争せず独占する
  • 製品だけでなく販売にも力を入れる

を良しとしています。

f:id:akiyoko:20170101185655p:plain

また最後に、優れたビジネスプランは、次の七つの質問にしっかりと答えを出すことが求められると書いています。

  • エンジニアリング(ブレイクスルーとなる技術を開発できるか?)
  • タイミング(今がこのビジネスを始めるのに適切なタイミングか?)
  • 独占(大きなシェアが取れるような小さな市場から始めているか?)
  • 人材(正しいチーム作りができているか?)
  • 販売(プロダクトを届ける方法があるか?)
  • 永続性(この先10年、20年と生き残れるポジショニングができているか?)
  • 隠れた真実(他社が気付いていない独自のチャンスを見つけているか?)


「ビジョナリー・カンパニー」「リーン・スタートアップ」を読んで、この「ゼロ・トゥ・ワン」までを一気に読むと、主張の違いや同じ考え方の部分が明確になって非常に面白かったです。


 

4.フリー

オススメ度:★★★☆☆

フリー(無料)経済を事例を交えて丁寧に解き明かした本。年末に読んだのですが、想像以上にボリュームがあって読むのにすごく時間が掛かってしまいました。

著者の クリス・アンダーソン は、米「WIRED」紙の元編集長で、「ロングテール」の名付け親として有名です。


まず、著者はフリー経済を以下の四つに大別しています。

  • ① 直接的内部相互補助 ・・・フリーでない他のものでフリーを補填する
  • ② 三者間市場 ・・・第三者がスポンサーとしてお金を払う
  • ③ フリーミアム ・・・少数の有料利用者が無料利用者を支えるモデル
  • ④ 非貨幣市場 ・・・評判や関心を動機とした贈与経済や無償の労働など

さらに、

潤沢な情報は無料になりたがる(逆に、稀少な情報は高価になりたがる)

という「フリーの万有引力」が働くため、低い限界費用で複製・伝達できる情報を扱う場合はこれまでとは違った新しいビジネスの仕組みを考える必要があり、例えばフリーによって得た評判や注目をどのように金銭に変えるかを創造的に考えなくてはならない、としています。


なおこの本自体も、出版された当初に期間限定でデジタル版が無料公開されていたそうです。


 

教養系

2016年の中旬は、教養とは何か?というのをふと考えていました。

5.ビジネスに効く最強の「読書」

オススメ度:★★★★★

著者の 出口治明 氏は、ライフネット生命の代表取締役会長兼CEOで、無類の読書家で旅行好きとしても知られています。ビジネス本も多数執筆していますが、何冊か教養についての本を出していてその中の一冊がこの本です。


本書では、教養については、

人間が賢くなる方法は、人に会い、本を読み、世界を旅すること以外にない

と書かれていて、読書については、

読書は知識を得るためではなく、自分の頭で考える材料を得るためにある

と書かれています。なるほど、「本の中に答えはない。本を材料にして自分自身で考えよ」ということでしょうか。読書で考え方の幅を広げる訓練をすることで教養が磨かれるということであれば、読書は「量」というよりも「質」が物を言うのかもしれません(もちろんある程度の量は必要という前提で)。


なお本書は、目次が

  • Part 1:リーダーシップを磨くうえで役に立つ本
  • Part 2:人間力を高めたいと思うあなたに相応しい本
  • Part 3:仕事上の意思決定に悩んだ時に背中を押してくれる本
  • Part 4:自分の頭で未来を予測する時にヒントになる本
  • Part 5:複雑な現在をひもとくために不可欠な本
  • Part 6:国家と政治を理解するために押さえるべき本
  • Part 7:グローバリゼーションに対する理解を深めてくれる本
  • Part 8:老いを実感したあなたが勇気づけられる本
  • Part 9:生きることに迷った時に傍らに置く本
  • Part 10:新たな人生に旅立つあなたに捧げる本

といった章立てになっていて目的別にカテゴリ分けされて本が紹介されているため、興味のあるところからどこからでも読み始めることもできます。

いろいろなジャンルから108冊の本が紹介されていますが、歴史書や小説が意外と多い印象を受けました。歴史書については、

様々な角度から「歴史」を知って、他人と自分の「今」を俯瞰的に眺め、さらに時間軸、空間軸から自分の立ち位置を読み取る。そうした感覚を研ぎ澄ませることは、ビジネスの世界を生きるうえでも大きな武器になるに違いありません。歴史は間違いなくビジネスに効くのです。

と言っています。なお、古典については、

ビジネスを進める上で本当に役立つ本は、圧倒的に古典に多いと思います。なぜなら、そこには様々な人間がリアルに描かれているからです。つまり、古典を読めば人間力(人間に対する観察力)が高まるのです。ビジネス書を10冊読むよりも、古典1冊を読んだ方がよほど役に立つ。

と考えており、「韓非子」「ブッデンブローク家の人びと」「王書」の三冊を紹介しています。


最後に、紹介されていた108冊から私が個人的に気になった本をいくつかピックアップ。


 

6.おとなの教養

オススメ度:★★★☆☆

テレビでお馴染みの池上彰さんの本。

「私たちはどこから来て、どこへ行くのか?」という問いかけに答えるための真摯な取り組みが「リベラルアーツ」という古来からある学問であり、様々な偏見や束縛から逃れ、自由な発想や思考を展開していくことができる教養を学べるものとしています。

また教養とは、「進歩の速い世の中にあっても陳腐化しないスキル」であり、

すぐに役に立つことは、世の中に出て、すぐ役に立たなくなる。すぐには役に立たないことが、実は長い目で見ると、役に立つ。

ということが書かれています。「長い人生を生きていく上で、自分を支える基盤になるもの」というのが教養である、という考え方です。

先の「ビジネスに効く最強の「読書」」のように本の紹介をするというスタイルではなく、宗教、宇宙、人類の起源、免疫学、経済学、歴史、日本の起源などの各ジャンルごとに池上さんが分かりやすい説明をしていくというスタイルの本です。


7.孫子・戦略・クラウゼヴィッツ

オススメ度:★★★★☆

「孫子」と「戦争論」という二大戦略書を対比させながら分かりやすく解説した本。タイトルに惹かれて買ったのですが、たまたま今年の4月頃に gacco の「中国古典に見る指導者の条件」というオンライン講座を受講していたのですが、この本の著者である 守屋淳 氏が件のオンライン講座の講師をされていた 守屋洋 教授のご子息だったのはちょっとした偶然でした。

以前、会社の勉強会で「孫子 (戦略論大系)」を輪読していたことがあり孫子は少し囓っていたのですが、クラウゼヴィッツは初(と思ったら、マンガ版「戦争論 ─まんがで読破─」を読んだことがありました。面白くないのでオススメしませんが・・)。曰く、軍人目線、一対一で戦争を考えるクラウゼヴィッツに対して、政治家目線で複数のライバルを視野に入れる孫武ということで、経営者や起業家であれば孫子の兵法の方が合っているように感じました。しかしながら、政治家や君主によって開戦を決定づけられた後に表舞台に立たされるというクラウゼヴィッツの立場を考えると、プロジェクトマネージャーであれば戦争論の方がしっくり来るのかもしれません。


本書では「王道のクラウゼヴィッツ」に対して「詭道の孫子」とも書かれていますが、どちらの戦略書が勝っているかというよりは、両者の置かれた背景に大きな違いがあるため一概に優劣はつけられません。繰り返し同じ相手と戦うことがあり負けてもある程度やり直しが利くナポレオン時代のプロイセンと、周囲をライバルに囲まれ不敗が求められた戦国時代の呉ではあまりにも状況が違い過ぎます。またここで筆者が、戦争論が野球選手や囲碁・将棋の棋士たちの状況に当てはまるとして、落合博満氏の「勝負の方程式」や羽生善治氏の「決断力 (角川新書)」から考え方を引いているのが斬新でした。


なお教養については、筆者は、

教養とは、新たな視点、異なる立場の宝庫に他ならない

と言っています。
いろいろな視点や立場を比較して俯瞰することで、教養が磨かれていくのでしょう。



 

GRIT(グリット)系

8.やり抜く力

オススメ度:★★★★★

教育業界で話題になっている「GRIT(グリット)」(*3)の本。ひと言で言えば、「努力と才能のどちらが大事か?」というテーマについて書かれた本でしょうか。

著者は心理学者の アンジェラ・ダックワース 教授です。専門は心理学者ということですが、本の内容はデータ重視で説得力があります。この本を読んでから、TED の「アンジェラ・リー・ダックワース 『成功のカギは、やり抜く力』」を見ると、動画の内容がさらによく理解できます。


www.ted.com


本書では、GRIT(やり抜く力)とは「情熱」+「粘り強さ」とされ、両者は一見似ていますが、

  • 「情熱」・・・自分の最も重要な目標に対して興味を持ち続け、ひたむきに取り組むこと
  • 「粘り強さ」・・・困難や挫折を味わってもあきらめずに努力を続けること

として明確に区別しています。またさらに情熱は、「興味」と「目的」に支えられているとしています。


才能がなくても一万時間練習を続ければその道のエキスパートになれるというマルコム・グラッドウェルが提唱する「一万時間の法則」というものがありますが、本書では、エキスパートたちはただ何千時間もの練習を積み重ねているだけではなく、「意図的な練習」(並外れた努力を要する極めて過酷な練習)をおこなっており、楽な練習はいくら続けても意味がないと言います。なるほど言われてみれば確かにそうで、単に惰性で続けていても得られるものは少ないですよね。小学校の頃に何年もスイミングスクールに通っていたのに、嫌々続けていたからか全然上手くならなかったつらい過去を思い出しました。。


また成功の秘訣は、「GRIT」に加えて「成長思考のマインドセット」としていて、子どもの頃の「褒められ方」が一生を左右するとも述べています(才能ではなく努力を褒める方がよい)。

以前に読んだ「「学力」の経済学」でも、具体的な努力を褒めた場合は子どもの成績が伸びたのに対して子どもの元々の能力を称賛した場合は成績が落ちたということが実験結果から実証されており、本書の主張とも合致します。


他にもいろいろな教訓や示唆があり、大変興味深かったです。教育関係の人は必読かも。


 

9.Think Simple

オススメ度:★★★☆☆

GRIT の本に続けて、スティーブ・ジョブズの本を読みました。

これまでスティーブ・ジョブズの本としては、「スティーブ・ジョブズ I」「スティーブ・ジョブズ II」「スティーブ・ジョブズ 驚異のプレゼン」を読んできましたが、スティーブ・ジョブズの特徴を表す「現実歪曲フィールド」と双極をなす「シンプルの杖」(シンプルに対する熱狂的哲学)をフィーチャーした本です。

シンプルであることは、複雑であることよりも難しい。
物事をシンプルにするためには、懸命に努力して思考を明瞭にしなければならないからだ。
だが、それだけの価値はある。
なぜなら、ひとたびそこに到達できれば、山をも動かせるからだ。

とスティーブ・ジョブズが言ったように、彼は不可能を疑い、逆境を逆境と思わず、自分が信じるものに対しては最後までやり抜くという「GRIT」を具備した人物であると感じました。


 

10.志高く 孫正義正伝

オススメ度:★★★☆☆

続けて、スティーブ・ジョブズとも交流があった、ソフトバンクグループ代表取締役社長の 孫正義 氏の半生を描いた伝記を読みました。生い立ちから少年時代、トタン屋根の会社で始めたソフトバンクを売上高9兆円の一大グループ企業まで育て上げた 2015年までの、地道な努力を惜しまず本質を見極めて素早く対処する「行動力」、人に喜んでもらえる仕事がしたいという「情熱」、志を絶対に成し遂げるという「意思」について、孫氏の類稀なる非凡なエピソードが描かれていました。


ここまで「やり抜く力」「Think Simple」「志高く 孫正義正伝」と続けて読んできて、この三冊が私の中で「GRIT」という点で繋がりました。

スティーブ・ジョブズと孫正義氏は両氏とも、青年時代の成功体験によって世界は変えられると信じた「成長思考」の持ち主であり、自分が信じるものに対しては最後までやり抜く「GRIT」の精神を兼ね備えた人物です。結果論かもしれませんが、GRIT と成功の繋がりを強く感じることができました。



その他

11.究極のセールスレター

オススメ度:★★★★☆

ライティングのコツを身につけるために、ライティングのレジェンドと言われる ダン・ケネディ の本を今年の半ばに読んでみました。具体的なライティングのコツについて書かれた、超実践的な本です。

2006年に出版された少し古い本で、元々はセールスレター向けに書かれたものですが、DM や SEO にも応用が効くと思います。

  • セールス術とは技術であり、慣れである
  • 買うのは感情(買ってから自分の選択を理屈で正当化する)
  • 送り手の関心事ではなく、受け取り手の関心事に単刀直入に的を絞れ
  • オファーの不利な点を認めて正直に伝えると、信頼できると評価してもらえる
  • AIDA の法則
  • 喜んで受け取ってもらうには、重要で、知る価値があって、ためになると思ってもらえることを伝えればよい
  • 価格の件が曖昧になるような比較をする
  • 問題を誇張し、まったくひどい災難だと思わせる
  • 焦らせる、投資収益率を説明する、自尊心に訴える、しっかり保証する
  • 見込み客がどんな反応をするかをしっかり理解する。疑問や反論の起こりそうなあらゆる可能性に用心深く対処する
  • 買ってくれそうな人のために書く
  • 何度でも言う。単刀直入に、例を挙げて、実話で、証言・証明で、お客・専門家・その他の代弁者の言葉で、番号を振った要約で
  • 簡単に「うん」とうなづいてもらえるような質問を次々にすることで同意する癖をつけさせる

これらを思い浮かべながら深夜のテレビショッピングを見ていると、実際これらのテクニックを意識して作られているなぁと恐ろしいほど実感することができます。

*1:本書では「とてつもなく不確実な状態で新しい製品やサービスを創り出さなければならない人的組織」を指すとされる。ベンチャー企業とスタートアップの違いについては、ベンチャー企業とスタートアップの違い | freshtrax | デザイン会社 btrax ブログ も参照

*2:2012年発刊の第四弾「ビジョナリーカンパニー4 自分の意志で偉大になる」もあります。

*3:GRIT は、Guts(度胸)、Resilience(復元力)、Initiative(自発性)、Tenacity(執念)の頭文字とされています。

Stripe 決済の最新事情 〜 Django と Stripe と私 〜

Django Stripe Python 決済

この投稿は 「Django Advent Calendar 2016 - Qiita」 の 4日目の記事です。



今日は クリスマス Advent Calendar の最終日ですが、4日目の記事を書いています。
というのも、自分が担当した 12/5 の「ベスト・オブ・Django本! - akiyoko blog」の前日だけ何故かずーっと空いていて、気持ち悪かったので。。

f:id:akiyoko:20161224150324p:plain



この記事では、「Django で Stripe 決済」を実装・検証します。


Django Advent Calendar 22日目に書いた「Django と Paypal と私(主に PayPal 決済の最新事情について) - akiyoko blog」のスピンオフ的な位置付けです。


<過去記事>
akiyoko.hatenablog.jp



 

Stripe とは

まず、「Stripe とは何ぞや?」から説明します。

Stripe は、2016年10月に日本で本番サービスイン した、新しい決済代行サービスです。後発サービスだけに、導入が簡単だったり、API が洗練されていて使いやすかったり、管理画面(ダッシュボード)がスッキリしていて直感的に分かりやすかったりと、なかなかイケてるサービスなのです。

なお、決済サービスの接続方式は「直接決済方式」で、他のサイトへの画面遷移を伴わず、離脱が少ない決済フローが実現できるのも特徴です。 *1


本社は米国カリフォルニア州サンフランシスコで、立ち上げが 2011年という比較的新しいスタートアップですが、今や世界中で数千社、年間数十億ドルの支払いを処理しており、飛ぶ鳥を落とす勢いの一大企業にまで成長しています。 *2


現時点で 世界25ヶ国でサービスを展開 しており、日本企業であれば、世界中のあらゆる国のエンドユーザから利用してもらうことが可能です。ちなみに私は、これを「世界25ヶ国でしか使えない」と勘違いしていたのですが、気になって問い合わせてみたところ、

「25 ヶ国に展開」という意味につきましては、Stripeのアカウントを作成し、オンラインで決済を受けることができる国数が25か国、という意味となります。


御社のサービス・プロダクトを購入されるエンドユーザに関しては、国の制限なく利用可能です。御社のターゲットとなるお客様に合わせた通貨を指定することで、その通貨でエンドユーザは決済を行うことができ、購入体験を損なうことなく決済が完結いたします。そして、日本以外の通貨でお支払いを受けた際には、Stripeが自動で円換算を行い、御社の銀行口座へ毎週お振込みいたします。


という丁寧な返事がすぐに返ってきました。
私の勘違いで危うく Stripe を候補から外してしまうところでした。。 念のため問い合わせしておいて良かったぁ。俺、グッジョブ!!



なお、私が必要としている決済サービスとしては、

  • 海外からの決済が可能(JPY以外の通貨が扱える) *3

というのを最低条件としていて、調査前は PayPal を第一候補、Stripe を第二候補と考えていたのですが、実際に両者を触って検討してみた現在の率直な感想では、Stripe の方が使い勝手が良さそうな印象です。


PayPal の最新事情については、以下の過去記事を参考にしてください。


<過去記事>
akiyoko.hatenablog.jp



Stripe については、以下の公式サイトのほか、


以下のサイトを参考にしました(本番サービスイン前の少し古い情報もあるのでご注意を)。


 

Stripe のメリットとデメリットは?

私が思いつく限りの、Stripe のメリット(プラス面)とデメリット(マイナス面)を挙げてみます。

メリット(プラス面)
  • 固定費用なし(決済成立ごとに手数料 3.6%) *4
  • 導入(≒実装)がめちゃくちゃ簡単
  • 直接決済方式(画面遷移がない)のため、離脱が少ない
  • クレジットカード情報の入力フォームを用意しなくても、checkout.js や stripe.js でセキュア(PCI-DSS に準拠)なフォームを簡単に作成できる
    • フォームの自動ローカライズにも対応 *5
  • 管理画面(ダッシュボード)が見やすい
  • 三井住友カードが全面バックアップしている(らしい)ので安心 *6
  • 売上金の円建て振り込みが可能(手数料は週一回の振り込みまで無料)
  • 定期支払い(継続課金)も利用可能
  • Stripe Radar, CVC, ZIP code などによる不正使用対策が充実

 

デメリット(マイナス面)
  • 現時点で JCB カードが利用不可 *7, *8
  • 銀行振込み・コンビニ支払いは利用不可(クレジットカードのみ)


現状、大きなデメリットは JCBカードが使えないというほぼ一点のみかと思われます。
それを許容できるのであれば、Stripe は決済サービスの筆頭候補になり得るはずです。


(参考)


 

Stripe 決済の仕組みは?

Stripe が推奨しているオンライン即時決済フローは、下図のようなものになります。
f:id:akiyoko:20161224150344p:plain

① ショッピングカート画面(「Stripe で支払う」ボタン)
    ↓
② 決済モーダルウィンドウ(「支払う」ボタン)
    ↓
③ 決済完了画面


 
すごくシンプルですよね。

Stripe 決済の接続方式は「直接決済方式」で、Stripe サイト等にリダイレクトされることなく決済を完了させることができます。つまり、エンドユーザが「Stripe」を意識することがないので、ユーザの離脱防止に効果が期待できます。




次に、Stripe がユーザのクレジット情報を処理するまでの詳細な仕組みについて、順を追って説明します。

Step 1:Securely collecting payment information

(参考)Card Payments Quickstart

  1. フォームに Stripe 謹製の「checkout.js」を設置しておく。
  2. ユーザがボタンをクリックすると、クレジットカード(およびその他の)情報を入力するためのモーダルウィンドウが立ち上がる。
  3. モーダルウィンドウ内でクレジットカード情報を入力して決済ボタンをクリックすると、checkout.js が裏側で Stripe の API とやり取りをおこない、数分間だけ有効になるトークンを生成してから、自サーバのアクションに POSTリクエストを実行する(トークンを「stripeToken」というパラメータで送信)。

 

Step 2:Creating Charges

(参考)Card Payments Quickstart

  1. 自サーバ側でトークンを受け取り、Stripe の API を利用して決済処理を実行する(トークンも渡す)


たったこれだけ。

フォームに埋め込むスクリプトもほんの数行だけですし、サーバ側の処理もリクエストからトークンを受け取って Stripe API を使って即時決済を実行するだけです。


ユーザが入力したクレジットカード情報は、Stripe API によって自動的にトークンとして自前に暗号化され、自サーバ側には流れてこないので安全 です。ただし、Stripe API とのやり取りをセキュアに保つためには、フォームを置くサイトを SSL化しておく必要があります。



なお、Step 1 でトークンを生成する手段は、

  • Checkout.js(簡単標準フォーム)
  • Stripe.js(カスタマイズ可能なフォーム)
  • Mobile SDKs

の 3種類が用意されており、ECサイトのオンライン決済では上の二つのいずれかを利用すればよいでしょう。

なお、checkout.js のパラメータをいろいろとカスタマイズできるようになっているので、ほとんどの場合は標準フォーム(checkout.js)の方で事足りるのではないでしょうか。

(参考)Checkout Reference



 

実装

購入する商品と合計金額が表示されたカート画面から Stripe 決済をおこなうことを想定した、「shop」アプリケーションを作ってみます。

/opt/webapps/myproject/
├── config
│   ├── __init__.py
│   ├── local_settings.py
│   ├── settings.py
│   ├── urls.py
│   └── wsgi.py
├── manage.py
├── shop
│   ├── apps.py
│   ├── __init__.py
│   ├── urls.py
│   └── views.py
└── templates
    ├── base.html
    ├── error.html
    └── shop
        ├── base_shop.html
        ├── cart.html
        └── complete.html


動作確認をおこなった Python および Django のバージョンは以下の通りです。

  • Python 2.7.6
  • Django 1.10



ソースコードは GitHub に置きました。
github.com



 

Settings

conf/settings.py (抜粋)

# Application definition

INSTALLED_APPS = [
    ...
    'shop',
]
...
TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [os.path.join(BASE_DIR, 'templates')],
        ...
        },
    },
]
...
# LOCAL SETTINGS
PROJECT_APP_PATH = os.path.dirname(os.path.abspath(__file__))
PROJECT_APP = os.path.basename(PROJECT_APP_PATH)
f = os.path.join(PROJECT_APP_PATH, 'local_settings.py')
if os.path.exists(f):
    import sys
    import imp
    module_name = '%s.local_settings' % PROJECT_APP
    module = imp.new_module(module_name)
    module.__file__ = f
    sys.modules[module_name] = module
    exec (open(f, 'rb').read())


conf/local_settings.py (抜粋)

DEBUG = True

##############
# STRIPE KEY #
##############
STRIPE_API_KEY = '<stripe-api-key>'
STRIPE_PUBLISHABLE_KEY = '<stripe-publishable-key>'


上記 2つのキーには、管理画面(ダッシュボード)の[Your account]>[Account settings]>[API Keys]で確認できる、「Test Secret Key」と「Test Publishable Key」をそれぞれ設定します。

https://dashboard.stripe.com/account/apikeys
f:id:akiyoko:20161224194651p:plain



 

URLConfs

shop/urls.py

from django.conf.urls import url

from . import views

urlpatterns = [
    url(r'^cart$', views.ShowCartView.as_view(), name='cart'),
    url(r'^checkout$', views.CheckoutView.as_view(), name='checkout'),
]

 

Views

shop/views.py

import logging

from django.conf import settings
from django.contrib import messages
from django.shortcuts import render
from django.views.generic import View
import stripe

logger = logging.getLogger(__name__)


class ShowCartView(View):
    def get(self, request, *args, **kwargs):
        return render(request, 'shop/cart.html', {
            'data_key': settings.STRIPE_PUBLISHABLE_KEY,
            'data_amount': 500,  # Amount in cents
            'data_name': 'akiyoko blog',
            'data_description': 'TEST',
        })


class CheckoutView(View):
    def post(self, request, *args, **kwargs):
        # Set your secret key: remember to change this to your live secret key in production
        # See your keys here: https://dashboard.stripe.com/account/apikeys
        stripe.api_key = settings.STRIPE_API_KEY

        # Get the credit card details submitted by the form
        token = request.POST['stripeToken']

        # Create a charge: this will charge the user's card
        try:
            charge = stripe.Charge.create(
                amount=500,  # Amount in cents
                currency='usd',
                source=token,
                description='This is a test.',
            )
        except stripe.error.CardError as e:
            # The card has been declined
            return render(request, 'error.html', {
                'message': "Your payment cannot be completed. The card has been declined.",
            })

        logger.info("Charge[{}] created successfully.".format(charge.id))
        messages.info(request, "Your payment has been completed successfully.")
        return render(request, 'shop/complete.html', {
            'charge': charge,
        })

 
バックエンドの実装は、Card Payments Quickstart のサンプルのほぼコピペです。



なお、Stripe API を利用するための Python パッケージが必要となるので、pip でインストールしておきます。

$ pip install stripe

 

Templates

shop/cart.html

{% extends "./base_shop.html" %}

{% block title %}Cart{% endblock title %}

{% block content %}
{{ block.super }}
<form action="{% url 'shop:checkout' %}" method="POST">
    <script
        src="https://checkout.stripe.com/checkout.js" class="stripe-button"
        data-key="{{ data_key }}"
        data-amount="{{ data_amount }}"
        data-name="{{ data_name }}"
        data-description="{{ data_description }}"
        data-image="https://stripe.com/img/documentation/checkout/marketplace.png"
        data-locale="auto">
    </script>
    {% csrf_token %}
</form>
{% endblock content %}


POST送信時に「csrfmiddlewaretoken」というパラメータを付与しないと 403エラーになるのは、Django に詳しい皆さんには釈迦に説法ですよね。



shop/complete.html

{% extends "./base_shop.html" %}

{% block title %}Complete{% endblock title %}

{% block content %}
<span style="font-size: 0.7rem;">{{ charge }}</span>
{% endblock content %}


 

動作確認

最後に、実際に検証環境で画面を動かしながら、動作を確認してみます。


ブラウザで「http://localhost:8000/shop/cart」にアクセスし、Stripe のチェックアウトボタン(今回は公式サンプルと同じく「Pay with Card」のまま)をクリックします。
f:id:akiyoko:20161224210831p:plain

モーダルウィンドウが起動して、クレジットカードの入力フォームが表示されるので、テスト用のクレジットカード情報(*9)を入力して、支払いボタンをクリックします。(なお、テスト用クレジットカード番号を入力した場合は、カードの有効期限、CVC は適当で構いません。)
f:id:akiyoko:20161224210853p:plain

自サーバ側で Stripe API の即時決済が実行され、shop/complete.html に charge オブジェクトの中身がダンプされました。
f:id:akiyoko:20161224210908p:plain



 

Django ベースの ECパッケージとの連携

これまで、クレジットカードの入力フォームを用意していない場合に Stripe の標準フォーム(checkout.js あるいは stripe.js)を利用する方法について解説してきました。

Django Oscar*10)や Cartridge*11)などの Django ベースの ECパッケージを使ってクレジットカード情報の入力フォームを利用している場合は、さらに簡単に Stripe API を使うことができます。


例えば、このような感じで(Stripe の標準フォームを使わなくても)サーバ側の処理のみで決済を完結させることができます。


cartridge/shop/payment/stripe_api.py

def process(request, order_form, order):
    """
    Payment handler for the stripe API.
    """
    data = {
        "amount": int((order.total * 100).to_integral()),
        "currency": getattr(settings, "STRIPE_CURRENCY", "usd"),
        "card": {
            'number': request.POST["card_number"].strip(),
            'exp_month': request.POST["card_expiry_month"].strip(),
            'exp_year': request.POST["card_expiry_year"][2:].strip(),
            'cvc': request.POST["card_ccv"].strip(),
            'address_line1': request.POST['billing_detail_street'],
            'address_city': request.POST['billing_detail_city'],
            'address_state': request.POST['billing_detail_state'],
            'address_zip': request.POST['billing_detail_postcode'],
            'country': request.POST['billing_detail_country'],
        },
    }
    try:
        response = stripe.Charge.create(**data)
    except stripe.CardError:
        raise CheckoutError(_("Transaction declined"))
    except Exception as e:
        raise CheckoutError(_("A general error occured: ") + str(e))
    return response.id

https://github.com/stephenmcd/cartridge/blob/0.12.0/cartridge/shop/payment/stripe_api.py#L24-L49




ほかにも、dj-stripe というパッケージは、「Two Scoops of Django: Best Practices for Django 1.8」の著者として有名な Daniel Greenfeld もプロジェクトに参加しているため、比較的信頼できるプロダクトになっていると推測されます(私自身は全然使ったことはありませんが)。




 

まとめ

Stripe を使ってみた印象をひと言で言うと、「超絶シンプル」です。これ以上簡単に使える決済サービスが果たしてあるのか?と思ってしまうくらいシンプルです。


PayPal や GMOペイメントゲートウェイなど他の決済代行サービスと比較して、面倒な実装が削ぎ落とされていて最低限の実装だけで決済 API を利用することができたり、管理画面(ダッシュボード)が直感的に使えたりするなど、「開発者に優しい決済サービス」になっている思います。




うぉぉぉぉ!! これが噂の Stripe ってやつか!
熱いぜ! 熱いぜぇぇぇぇぇ!

f:id:akiyoko:20161221075723p:plain:w350



Stripe、今後日本ですごく流行る予感がします。



オススメ Django 本

最後に、Django のベストプラクティス本の紹介です。

Two Scoops of Django: Best Practices for Django 1.8

Two Scoops of Django: Best Practices for Django 1.8


記事を書きましたので、是非ご参考に。


<過去記事>
akiyoko.hatenablog.jp

*1:決済サービスの接続方式については、過去記事「Django と Paypal と私(主に PayPal 決済の最新事情について) - akiyoko blog」を参考のこと

*2:Stripe: Press resources より

*3:2017年4月末でのサービス終了が宣言された「WebPay」では、海外向けでの販売のみを前提とした利用はできないと規定されていました。 https://webpay.jp/faq#constraints

*4:Stripe: Pricing を参照

*5:「data-locale」パラメータを「auto」に設定することで実現可能。パラメータの詳細については Checkout Reference を参照

*6:Stripeが日本で正式ローンチ、三井住友カードが資本参加を発表 | TechCrunch Japan より

*7:Which cards and payment types can I accept with Stripe? : Stripe: Help & Support より

*8:【徹底比較】話題の5大オンライン決済サービスPayPal、SPIKE、Stripe、WebPay、Yahoo!ウォレット FastPay、を比べてみた(比較表有り) には「順次対応予定」とは書いてありましたが。。

*9:https://stripe.com/docs/testing#cards にテストで使用できるクレジットカード情報がリストアップされています

*10:過去記事「ゼロからはじめる Django で ECサイト構築(その3:Django Oscar の機能を調べる) - akiyoko blog」を参照

*11:Cartridge は、Mezzanine 専用に作られた、Mezzanine に ECサイト機能を搭載するためのアプリケーションです。Mezzanine 公式ページには「Ecommerce / Shopping cart module」と紹介されています。

PayPal 決済の最新事情 〜 Django と Paypal と私 〜

Django PayPal Python 決済

この投稿は 「Django Advent Calendar 2016 - Qiita」 の 22日目の記事です。



この記事では、「Django と PayPal REST API で In-Context Window による PayPal 決済フロー」を実装・検証します。

はじめに謝罪しておきますが、「Django Advent Calendar」にも関わらず、結果として Django はオマケ程度にしか扱っていません。。


 

はじめに

オンライン決済の仕組み

ECサイトの決済処理の仕組みを簡単に図解すると、以下のようになります。

f:id:akiyoko:20160515172525p:plain
10 Safe and Popular Gateways for Online Payment Processing | InstantShift を参考に作成)


決済業者と直接契約するのはいろいろと面倒なので、代わりに決済代行業者と契約することで、Visa や Master Card などの各種クレジットカード(決済代行サービスによっては銀行振込やコンビニ決済も)が ECサイトで利用できるようになります。



少し細かい話になりますが、決済代行サービスごとに、決済処理システムとのやり取りの方式が異なります。

決済処理システムとの接続方式には、大きく分けて次の二種類があります。

接続方式 説明
リンク(画面遷移)方式 決済代行サービスのサイトに一旦遷移してクレジットカード情報(あるいは決済代行サービスのアカウント)などを入力させる方式
直接決済方式 画面遷移をおこなわず、バックエンドで直接決済処理をおこなう方式。実現方式や実装方法によってさらに細分化される。 *1


現在のところ、PayPal の接続方式は「リンク方式」のみ となっています。PayPal には「Direct Credit Card Payments」という直接決済方式の決済サービスもあるのですが、残念ながら(利用できるのは UKのみで)日本では利用できません。 *2

なお、GMOペイメントゲートウェイゼウス などの決済代行業者ではそれぞれの方式の決済代行サービスが各種取り揃えられています。また、最近本番サービスインとなった話題の Stripe は「直接決済方式」となっています。


なぜ PayPal?

私が必要としている決済サービスとしては、

  • 海外からの決済が可能(JPY以外の通貨が扱える) *3

というのを最低条件としていました。

そのほか、

  • PayPal に慣れている
  • PayPal のビジネスアカウントを既に持っている

という理由から、PayPal を第一候補に考えています。


PayPal の ECサイト用オンライン決済にもいろいろと実装方式(使用する API の種類など)があるのですが、

  • Braintree v.zero がプロダクション利用できるのは 2017年以降(2018年?)
  • Classic API よりも REST API を使いたい
  • In-Context Window を使ったフローの方が離脱が少ない

という事情を勘案して、「In-Context Window による決済フローを PayPal REST API で実装」するのがベストな選択肢であるという結論に達しました。


 

In-Context Window とは?

今回検証した PayPal のオンライン決済パターンは、下図のようなものになります。

f:id:akiyoko:20161222132204p:plain
NVP/SOAP Integration - PayPal Developer の図を元に作成。緑枠:自サイト、青枠:PayPal サイト)

① ショッピングカート画面(「PayPal で支払う」ボタン)
    ↓
② (In-Context Window 内)ログイン画面(「ログイン」ボタン)
    ↓
③ (In-Context Window 内)支払承認画面(「支払いに同意」ボタン)
    ↓
④ 決済完了画面


In-Context Window は、過去記事 の「5. ポップアップウィンドウ型(In-Context Window)」(小さなポップアップを立ち上げてその内部で PayPal サイトを表示させる新しいタイプの画面遷移パターン)に該当する決済フローです。

これまでの Express Checkout と違って、全画面が PayPal 決済ページにリダイレクトされることなく、小さなポップアップが立ち上がってその中で PayPal 決済ページを表示するというのが最大の特徴です。


<過去記事>
akiyoko.hatenablog.jp



これが、PayPal の数あるオンライン決済パターンの中で一番シンプルで最も新しいパターンになるかと思います。


また PayPal の公式ページでも、

PayPal no longer recommends full-page redirects to PayPal for Express Checkout. Instead, Express Checkout only requires a payment ID generated by the REST Payments API, or a payment token generated by the legacy NVP/SOAP APIs, to initiate and finalize a payment.


https://developer.paypal.com/docs/integration/direct/express-checkout/integration-jsv4/other-integrations/

ということで、全画面をリダイレクトするような画面遷移は今後はオススメしないということなので、今後の PayPal 決済では In-Context Window 型のフローが増えてくると思われます。



In-Context Window 型の通常決済(Checkout)を利用するには、フロント側に「checkout.js」という PayPal 謹製の JSライブラリを読み込ませて(*4)、あとは決まったやり方に則って実装するだけで OK です。

checkout.js は少し前まで V 3.5.0 だったのですが、現在の最新バージョンは V.4.0.0 となって、実装方法が若干変更されています。 *5


今回、V 4.0.0 で検証する前に V 3.5.0 でも実装・検証してみたのですが、より簡単に、よりセキュアに実装できるようになったという印象です。

具体的には、V 4.0.0 になって、

  • PayPal ボタン生成のときに、PAYPAL_CLIENT_ID を画面に晒さなくてよくなった
  • Create Payment のときに、生成した Payment から「redirect_url」を取り出してリダイレクトしなくてよくなった *6

などのうれしい変更点がありました。


 

PayPal REST API とは?

PayPal REST API は、PayPal が提供する様々な決済サービスを利用することができる RESTful API です。現時点で、PayPal が実現できるほぼ全ての決済サービスを網羅しているようです。 *7


なお、PayPal REST API は OAuth 2.0 プロトコルによる認可システムを採用しており、PayPal Developer サイトで作成した売り手アカウントの Credential(Client ID および Secret)を使用して各 API 呼び出しに必要なトークンを払い出します。 *8


Credential の作成方法については、ここでは説明を省略します。 *9



先に述べたように、PayPal REST API には様々な API の種類がありますが、オンライン決済処理ではその中から「Payments API」を使用すれば事足りるでしょう。 *10


PayPal REST API を便利に利用するためのライブラリとして、Python であれば PayPal Python SDK が 本家 PayPal から提供されていますので(Python のほかにも Java, PHP, .NET, Ruby, Node.js など各種言語向けの SDK が揃っています)、 pip でインストールして使います。


 

Django パッケージは使わないの?

Django Packages : Payment ProcessingDjango Packages : django SHOP plugins などで、PayPal に対応している決済パッケージをチェックしてみたのですが、

  • Django 1.10
  • PayPal REST API
  • In-Context Window(checkout.js V 4.0.0)

に対応しているものは今のところ見当たりません。


スターの多い順に確認してみると、django-merchant は「PayPal Website Payments Pro」のみ対応ということで日本では利用不可、django-lfs は「PayPal Payments Standard」のみ対応ということで API が古くて NG、django-paypal も「PayPal Payments Standard」または「PayPal Website Payments Pro」のみ対応ということで先の二つと同じでした。


そもそも「PayPal REST API で In-Context Window 決済」は自前で実装してもそんなに大変ではなくて、Django パッケージをわざわざ使うまでもないといった印象です。




ということで、前置きがずいぶん長くなってしまいましたが、「Django と PayPal REST API で In-Context Window による PayPal 決済フロー」を実際に試していきます。



実装前には、以下のドキュメントをざっと読んでおくことをお勧めします。


 

実装

購入する商品と合計金額が表示されたカート画面から PayPal 決済をおこなうことを想定した、「shop」アプリケーションを作ってみます。

/opt/webapps/myproject/
├── config
│   ├── __init__.py
│   ├── local_settings.py
│   ├── settings.py
│   ├── urls.py
│   └── wsgi.py
├── manage.py
├── shop
│   ├── apps.py
│   ├── __init__.py
│   ├── urls.py
│   └── views.py
└── templates
    ├── base.html
    ├── error.html
    └── shop
        ├── base_shop.html
        ├── cart.html
        └── complete.html


動作確認をおこなった Python および Django のバージョンは以下の通りです。

  • Python 2.7.6
  • Django 1.10



ソースコードは GitHub に置きました。
github.com



 

Settings

conf/settings.py (抜粋)

# Application definition

INSTALLED_APPS = [
    ...
    'shop',
]
...
TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [os.path.join(BASE_DIR, 'templates')],
        ...
        },
    },
]
...
# LOCAL SETTINGS
PROJECT_APP_PATH = os.path.dirname(os.path.abspath(__file__))
PROJECT_APP = os.path.basename(PROJECT_APP_PATH)
f = os.path.join(PROJECT_APP_PATH, 'local_settings.py')
if os.path.exists(f):
    import sys
    import imp
    module_name = '%s.local_settings' % PROJECT_APP
    module = imp.new_module(module_name)
    module.__file__ = f
    sys.modules[module_name] = module
    exec (open(f, 'rb').read())


conf/local_settings.py (抜粋)

DEBUG = True

# PayPal
PAYPAL_MODE = '<paypal-mode>'  # 'sandbox' or 'live'
PAYPAL_CLIENT_ID = '<paypal-client-id>'
PAYPAL_CLIENT_SECRET = '<paypal-client-secret>'

 

URLConfs

shop/urls.py

from django.conf.urls import url

from . import views

urlpatterns = [
    url(r'^cart$', views.ShowCartView.as_view(), name='cart'),
    url(r'^create-payment$', views.CreatePaymentView.as_view(), name='create-payment'),
    url(r'^execute-payment$', views.ExecutePaymentView.as_view(), name='execute-payment'),
]

 

Views

shop/views.py

import logging

from django.conf import settings
from django.contrib import messages
from django.http import JsonResponse, Http404
from django.shortcuts import render, reverse
from django.views.generic import View
import paypalrestsdk

logger = logging.getLogger(__name__)


class ShowCartView(View):
    def get(self, request, *args, **kwargs):
        return render(request, 'shop/cart.html', {
            'paypal_mode': settings.PAYPAL_MODE,
        })


class CreatePaymentView(View):
    def post(self, request, *args, **kwargs):
        paypalrestsdk.configure({
            'mode': settings.PAYPAL_MODE,
            'client_id': settings.PAYPAL_CLIENT_ID,
            'client_secret': settings.PAYPAL_CLIENT_SECRET,
        })

        payment = paypalrestsdk.Payment({
            'intent': 'sale',

            # Payer
            'payer': {
                'payment_method': 'paypal',
            },

            # Redirect URLs
            'redirect_urls': {
                'return_url': request.build_absolute_uri(reverse('shop:execute-payment')),
                'cancel_url': request.build_absolute_uri(reverse('shop:cart')),
            },

            # Transaction
            # Note: This is dummy. If production, transaction should be created with reference to cart items.
            'transactions': [{
                # Item List
                'item_list': {
                    'items': [{
                        'name': 'item',
                        'sku': 'item',
                        'price': '5.00',
                        'currency': 'USD',
                        'quantity': 1,
                    }]
                },
                # Amount
                'amount': {
                    'total': '5.00',
                    'currency': 'USD',
                },
                'description': 'This is the payment transaction description.',
            }]
        })

        # Create Payment
        if payment.create():
            logger.info("Payment[{}] created successfully.".format(payment.id))
            return JsonResponse({'success': True, 'paymentId': payment.id})
        else:
            logger.error("Payment failed to create. {}".format(payment.error))
            return JsonResponse({'success': False, 'error': "Error occurred while creating your payment."}, status=500)


class ExecutePaymentView(View):
    def get(self, request, *args, **kwargs):
        # Query strings are always in request.GET
        payment_id = request.GET.get('paymentId', None)
        payer_id = request.GET.get('PayerID', None)

        try:
            payment = paypalrestsdk.Payment.find(payment_id)
        except paypalrestsdk.ResourceNotFound as err:
            logger.error("Payment[{}] was not found.".format(payment_id))
            return Http404

        # Execute Payment
        if payment.execute({'payer_id': payer_id}):
            logger.info("Payment[{}] executed successfully.".format(payment.id))
            messages.info(request, "Your payment has been completed successfully.")
            return render(request, 'shop/complete.html', {
                'payment': payment,
            })
        else:
            logger.error("Payment[{}] failed to execute.".format(payment.id))
            messages.error(request, "Error occurred while executing your payment.")
            return render(request, 'error.html')

Create Payment は
PayPal-Python-SDK/create_with_paypal.py at master · paypal/PayPal-Python-SDK · GitHub
を参考に、Execute Payment は
PayPal-Python-SDK/execute.py at master · paypal/PayPal-Python-SDK · GitHub
を参考にしました。


なお、例外処理は全然ケアしていないので、本番で使う場合には要注意です。


 

Templates

shop/cart.html

{% extends "./base_shop.html" %}

{% block title %}Cart{% endblock title %}

{% block content %}
{{ block.super }}
<div id="paypal-button"></div>

<script src="https://www.paypalobjects.com/api/checkout.js" data-version-4></script>
<script>
    paypal.Button.render({
        env: '{{ paypal_mode }}',
        payment: function (resolve, reject) {
            paypal.request.post('{% url "shop:create-payment" %}', {csrfmiddlewaretoken: '{{ csrf_token }}'})
                .then(function (data) {
                    console.log("data=", data);
                    if (data.success) {
                        resolve(data.paymentId);
                    } else {
                        reject(data.error);
                    }
                })
                .catch(function (err) {
                    console.log("err=", err);
                    reject(err);
                });
        },
        onAuthorize: function (data, actions) {
            return actions.redirect();
        },
        onCancel: function (data, actions) {
            return actions.redirect();
        },
        onError: function (err) {
            // Show an error page here, when an error occurs
        }
    }, '#paypal-button');
</script>
{% endblock content %}

フロントのスクリプトは、

などを参考にしていただければ。


また、POST送信時に「csrfmiddlewaretoken」というパラメータを付与しないと 403エラーになるのは、Django に詳しい皆さんにはお馴染みですよね。



shop/complete.html

{% extends "./base_shop.html" %}

{% block title %}Complete{% endblock title %}

{% block content %}
<span style="font-size: 0.7rem;">{{ payment }}</span>
{% endblock content %}

 

処理概要

ここで、In-Context Window の処理フローを少し解説すると以下のようになります。

  1. paypal.Button.render で PayPal ボタンを表示
  2. ユーザがボタンをクリックすると、paypal.requet.post() で '/shop/create-payment' にリクエストを POST する
  3. サーバ側で商品情報や合計金額、およびPayPal からリダイレクトさせる URL を含めた Payment を create して、payment.id を JSON で返す
  4. checkout.js が勝手に PayPalサイトにリダイレクトしてくれる
  5. In-Conetxt Window 内でユーザが決済を承認して同意すると、onAuthorize、キャンセルすると onCancel がコールバックされるので、それぞれのコールバック関数の中で適宜リダイレクトをする(ここでは勝手にリダイレクトされない)
  6. 「/shop/execute-payment?paymentId=xxx&token=yyy&PayerID=zzz」という URL でリクエストされるので、サーバ側で paymentId, PayerID を取得して Payment を execute して、決済完了画面を表示させる


実装を見ながら、処理の流れをチェックすると分かりやすいかと思います。


 

動作確認

最後に、実際に検証環境で画面を動かしながら、動作を確認してみます。


ブラウザで「http://localhost:8000/shop/cart」にアクセスし、PayPal のチェックアウトボタンをクリックします。
f:id:akiyoko:20161221135159p:plain

In-Context Window(モーダルウィンドウみたいなもの)が起動して、PayPal サイト(サンドボックス)のログイン画面が表示されます。
PayPal の買い手アカウント情報を入力してログインし、
f:id:akiyoko:20161221145000p:plain

「同意して続行」をクリックします。
f:id:akiyoko:20161221145025p:plain

onAuthorize がコールバックされ、return_url の「/shop/execute-payment」に redirect() され、shop/complete.html に payment オブジェクトの中身がダンプされました。
f:id:akiyoko:20161221145046p:plain



 

まとめ

Django で PayPal 決済を検討しているのであれば、今回紹介したように、フロントは「In-Context Window の checkout.js V 4.0.0」、バックエンドは「PayPal REST API 」という現時点での最新スタイルがオススメです。

ドキュメントや記事がまだ少ないのが欠点ですが、PayPal の日本チームもそこには今後力を入れていくそうなので期待しましょう。

PayPal の決済フローもドキュメントも、現在進行形でどんどん進化していますよ!!


最後にひと言。

PayPal REST API で In-Context Window 決済はいいぞ!


ご拝読ありがとうございました。「Django と Paypal と私」でした。




明日は、luizs81 さんの 23日目の記事です。よろしくお願いします。


オススメ Django 本

Django のベストプラクティス本です。
全編英語ですが絶対オススメです。

Two Scoops of Django: Best Practices for Django 1.8

Two Scoops of Django: Best Practices for Django 1.8


記事を書きましたので、是非ご参考に。


<過去記事>
akiyoko.hatenablog.jp

*1:決済代行業者によって呼び方も異なる。例えば、GMOペイメントゲートウェイ では「プロトコルタイプ」「モジュールタイプ」、ゼウス では「トークン(JavaScript)型」「データ伝送(API)型」などと呼ばれるが、いずれも画面遷移を伴わない直接決済方式である。

*2:https://developer.paypal.com/docs/classic/api/#website-payments-pro

*3:2017年4月末でのサービス終了が宣言された「WebPay」では、海外向けでの販売のみを前提とした利用はできないと規定されていました。 https://webpay.jp/faq#constraints

*4:常に最新版のものを利用するために、PayPal の CDN を利用することが推奨されています。

*5:V 3.5.0 から V 4.0.0 への移行方法については、「Upgrade checkout.js to V4.0.0 - PayPal Developer」を参照

*6:payment_id を JSON形式で返すだけで、後は checkout.js が勝手にリダイレクトしてくれるようになりました。

*7:利用できる API の種類については「REST API reference - PayPal Developer」を参照

*8:詳しい仕組みについては「How PayPal uses OAuth 2.0 - PayPal Developer」を参照

*9:https://www.paypal-knowledge.com/infocenter/index?page=content&id=FAQ1949 が新しくて参考になりそうです。

*10:本番では「Payment Experience API」を組み合わせて使うこともありますが今回は利用しません。

「Python 3 エンジニア認定基礎試験」に合格しました!

Python 資格

この投稿は 「Python Advent Calendar 2016 - Qiita」 の 21日目の記事です。


このたび、「Python 3 エンジニア認定基礎試験」に合格することができましたー! パチパチパチ〜!!


f:id:akiyoko:20161221021155p:plain:w450


と、Python Advent Calendar で報告しようと思ったのですが、残念ながら12月21日現在、まだ合格通知が届いていません。試験(ベータ版)を受けたのが 11月7日で、結果通知が約一ヶ月後ということだったのですが、まだ何の音沙汰もありません。。



仕方ないのでここはひとつ、合格したという体で書かせていただきます(!!)。


 

はじめに

まずはじめに「Python 3 エンジニア認定基礎試験」は、「一般社団法人Pythonエンジニア育成推進協会」主催・監修により 2017年春から本試験開始を予定している Pythonエンジニアのための認定試験で、Python 3系の基礎文法が問われます。


Python 3 エンジニア認定基礎試験
概要:文法基礎を問う試験
受験料金:1万円(外税) 学割5千円(外税)
問題数:40問(すべて選択問題)
合格ライン:正答率70%


Python試験 | 一般社団法人Pythonエンジニア育成推進協会」より



Pythonの普及推進、Pythonicの理解促進:Pythonエンジニア育成推進協会 発起人会が発足、2017年春にPython試験を実施予定 - @IT」の記事に「これから Python を習得し始める人などを対象」と書かれているように、どちらかと言うと Python 初級者のための試験 であると考えられます。



認定教材は今のところこの一冊のみで、「基礎文法部分から出題」されます。

私も試験直前にひと通り目を通しましたが、Python 初学者にベストな参考書かどうかは議論の余地はあるかもしれませんが、内容は非常によくまとまっていると感じました。




一方、「一般社団法人Pythonエンジニア育成推進協会」は、その設立背景を

ビッグデータ、機械学習、Webサービス開発など、幅広い分野で注目が集まっているPythonは米国ではすでに求人件数がJavaに次ぐ2位となり4万件を超えています。日本でも2年間で求人数が2倍になっており、近い将来、人材不足になる可能性が高く、エンジニア育成を推進する業界団体を設立するに至りました。

と説明しており、ビッグデータ分析や機械学習などで今後ますます注目株となる Pythonエンジニアの認定資格は、データサイエンティストを求める企業やスキルを証明したい個人にとってそれなりにニーズがありそうです。


かくいう私も、早速履歴書に書いてアピールしていく予定です!!





なお、「基礎試験」以外に、データ分析に特化した上位の「Python 3 エンジニア認定データ解析試験」も開催される予定です。

Python 3 エンジニア認定データ解析試験
概要:Pythonを使ったデータ分析の基礎や方法を問う試験
受験料金:1万円(外税) 学割5千円(外税)
問題数:40問(すべて選択問題)
合格ライン:正答率70%



「Python 3 エンジニア認定データ解析試験」の認定教材は、次の一冊となっています。




 

感想

私はその昔、主に Java やら PHP を嗜んでいたサーバサイドエンジニアですが、5年ほど前から業務で Python を使うようになって以来ずっと Python(Python 2!)を使い続けています。なので現在、Python歴 5年(うち Django歴 3年)といったところです。

今回受験したのはいわゆる「ベータ試験」と言われる本番前のプレ試験なのですが、合格すれば本番試験と同等の資格が得られるとのことで、早速一般向けの第一回ベータ試験に参加してきたのでした。 *1

pythonic-exam.connpass.com



今回の試験に向けて、直前に参考書をひと通り読んでいたのですが、実際の試験は意外と難しかったです。参考書を読まなければ間違っていた問題もいくつかあったかと思います。 *2 「70%」という合格ラインをクリアするのはそんなに難しくないのですが、満点を取るにはちょっと基礎知識に抜けがあったかな?というのが正直な感想です。


試験が終わって、きちんと理解していなかった部分をすぐに参考書で復習できたのが、今回一番の成果だったように思います。


何はともあれ、一発合格できてよかったです。
これでめでたく私も Pythonic の一員になれたというわけですね。 *3


うぉぉぉぉ!! これが Pythonic ってやつか!
力がみなぎってくるぜぇぇ!

f:id:akiyoko:20161221075723p:plain:w350


というわけで、まだまだ認知度の低い「Python 3 エンジニア認定基礎試験」ですが、もっともっと盛り上がるといいな!!と思いました。




明日は、kaneshin さんの 22日目の記事です。
よろしくお願いします。

*1:本試験は、全国のオデッセイ コミュニケーションズ CBTテストセンターで行われる予定。

*2:どんな問題が出題されたかについては守秘義務があるため詳細を言えないので悪しからず。

*3:Pythonエンジニア育成推進協会の設立目的の一つが「プログラミングフィロソフィー「Pythonic」の普及推進を行う」となっています。

「PayPal API体験ハンズオンセミナー!世界のFintechを味見しませんか!」に参加してきました

勉強会 決済 PayPal

主催

IoT ALGYAN(あるじゃん)


IoTの基本要素を網羅する自学自習可能コンテンツ「IoT Kit Hands-on Training Site


会場

Microsoft 品川本社
東京都港区港南 2-16-3 品川グランドセントラルタワー


Twitter

twitter.com




f:id:akiyoko:20161129191245j:plain


 

全体の感想など

先月末、この PayPal のハンズオンイベントに参加しました。


以前に少し PayPal の調査を個人的にしていたので、とても興味深かったです。

<過去記事>
akiyoko.hatenablog.jp


Braintree については、今年の 3月あたりにサンドボックスを Python で一度試してみたのですが、あれから 8ヶ月くらい経っているのにまだサンドボックスなのですね。。 Braintree API は ドキュメント が(英語ですが)一通り揃っていて実装もしやすいので、早く本番利用できるようになって欲しいところです。


今回、ハンズオン形式で Node.js の express アプリを作って Braintree API を試してみたのですが、express アプリ自体も簡単に作れて実装もシンプルなので、ハンズオンとしてピッタリだったかもしれません。


あと、懇親会で登壇者の岡村氏に直接質問もできて非常に有益でした。
貴重な情報もゲットできました。




 

PayPal / Braintree Hands-on

岡村 純一氏(PayPal Pte.Ltd.)


最近は、エンジニアSF漫画で有名とのこと。
【新連載】エンジニアSF漫画「GRAMMERS #1」 プロローグ~予知能力を持った青年 | geechs magazine



  • 昨年 eBay から独立して再上場
  • venmo は個人間送金、US だけ
  • PayPal は Braintree を API の基盤にする方針
    • v.zero(=Braintree's API) を充実させようとしている
  • Classic API はグローバルで最も使われているのでまだ無くならない
  • 「都度決済」(Checkout)、「定期支払」(Recurring Payment)、「従量課金」(Reference Transaction)、「マーケットプレイス用決済」、「送金」(Payout)が可能
    • カッコ内は API の名前
    • 従量課金は別途審査が必要
    • マーケットプレイスは複数受け取りの場合
    • 送金も別途審査が必要
  • 開発者向け日本語サイト も拡充中


 

v.zero Node.js SDK による PayPal 実装

Braintree でクレジットカードを扱うには Braintree アカウントが必要ですが、PayPal を使うだけであれば Braintree のアカウントは必要はないとのことです(PayPal アカウントがあればよい)。

なお、Braintree の本番アカウントはまだ日本では使えないとのこと(現在はサンドボックスアカウントの作成・利用が可能)。


 

1.PayPal のサンドボックスアカウントを作成

Developer サイト にログインし、ダッシュボードを表示します。

f:id:akiyoko:20161216000336p:plain

次に、[Sandbox]>[Accounts]から、パーソナル(買い手)アカウント および ビジネス(売り手)アカウントを作成します。
https://developer.paypal.com/developer/accounts/

f:id:akiyoko:20161212080822p:plain


 

2.v.zero SDK の Credential を作成

続けて、PayPal Developer サイトで[My Apps & Credentials]から「Generate Credential」ボタンをクリックして、ビジネスアカウントに対して Credential(認証情報)を発行します。

f:id:akiyoko:20161216000938p:plain

作成したビジネスアカウントを選択して「Generate Credential」ボタンをクリック。

f:id:akiyoko:20161216001212p:plain

[My Apps & Credentials]の「v.zero SDK」の「Sandbox Account」のリストから、Credential を作成したアカウントをクリックして、Access Token を確認します。

f:id:akiyoko:20161216001911p:plain


 

3.Node.js, npm をインストール

Homebrew を使って Mac に nodebrew をインストールし、Node.js および npm の最新版をインストールをします。


<過去記事>
akiyoko.hatenablog.jp



 

4.express アプリを作成してサーバを起動

express アプリを作成してサーバを起動します。

$ cd ~/dev

$ npm install express-generator -g
$ express myapp
$ cd myapp
$ npm install
$ npm start

(参考)express実践入門 · GitHub




Braintree Node.js SDK をインストールします。

$ npm install braintree
myapp@0.0.0 /Users/akiyoko/dev/myapp
└─┬ braintree@1.43.0
  ├── dateformat@1.0.1-1.2.3
  ├─┬ readable-stream@1.1.10
  │ ├── core-util-is@1.0.2
  │ ├── debuglog@0.0.2
  │ └── string_decoder@0.10.31
  ├── semver@5.1.0
  ├─┬ source-map-support@0.2.9
  │ └── source-map@0.1.32
  ├── underscore@1.8.3
  └─┬ xml2js@0.1.13
    └── sax@1.2.1

(参考)Set Up Your Server | Node.js - Braintree Developer Documentation



あとは、Set Up Your Server - PayPal Developer に沿って実装していきます。

ちなみに岡村氏の正解コードはこちら。
GitHub - benzookapi/VZeroNodeDemo: Braintree v.zero hands-on code



修正したのは以下の 2ファイルです。


routes/index.js

var express = require('express');
var router = express.Router();
var braintree = require('braintree')

/* GET home page. */
router.get('/', function(req, res, next) {
  var gateway = braintree.connect({
    accessToken: 'access_token$sandbox$xxxxxxxx$xxxxxxxxxxxxxxxxxxxxxxxx'
  });
  gateway.clientToken.generate({}, function (err, response) {
    res.render('index', { title: 'Express', clientToken: response.clientToken });
  });
});

router.post('/checkout', function (req, res) {
  var gateway = braintree.connect({
    accessToken: 'access_token$sandbox$xxxxxxxx$xxxxxxxxxxxxxxxxxxxxxxxx'
  });
  var saleRequest = {
    amount: req.body.amount,
    merchantAccountId: 'JPY',
    paymentMethodNonce: req.body.payment_method_nonce,
    options: {
      submitForSettlement: true
    }
  };
  gateway.transaction.sale(saleRequest, function (err, result) {
    if (err) {
      res.send('<h1>Error: ' + err + '</h1>');
    } else if (result.success) {
      res.send('<h1>Success! Transaction ID: ' + result.transaction.id + '</h1>');
    } else {
      res.send('<h1>Error: ' + result.message + '</h1>');
    }
  });
});

module.exports = router;


views/index.jade

div#paypal.
  <script src="https://js.braintreegateway.com/web/3.5.0/js/client.min.js"></script>
  <script src="https://js.braintreegateway.com/web/3.5.0/js/paypal.min.js"></script>

  <script src="https://www.paypalobjects.com/api/button.js?"
     data-merchant="braintree"
     data-id="paypal-button"
     data-button="checkout"
     data-color="gold"
     data-size="medium"
     data-shape="pill"
     data-button_type="submit"
     data-button_disabled="false"
     data-locale="ja_JP"
  ></script>


  <script>
  var paypalButton = document.getElementById('paypal-button');
  // Create a Client component
  braintree.client.create({
    authorization: '#{clientToken}'
  }, function (clientErr, clientInstance) {
    // Create PayPal component
    braintree.paypal.create({
      client: clientInstance
    }, function (err, paypalInstance) {
      paypalButton.addEventListener('click', function () {
      // Tokenize here!
      paypalInstance.tokenize({
        flow: 'checkout', // Required
        amount: 1000, // Required
        currency: 'JPY', // Required
        locale: 'ja_JP'
        }, function (err, tokenizationPayload) {
          // Tokenization complete
          // Send tokenizationPayload.nonce to server
          var form = document.createElement('form');
          document.body.appendChild(form);
          var inputNonce = document.createElement('input');
          inputNonce.setAttribute('type', 'hidden');
          inputNonce.setAttribute('name', 'payment_method_nonce');
          inputNonce.setAttribute('value', tokenizationPayload.nonce);
          form.appendChild(inputNonce);
          var inputAmount = document.createElement('input');
          inputAmount.setAttribute('type', 'hidden');
          inputAmount.setAttribute('name', 'amount');
          inputAmount.setAttribute('value', '1000');
          form.appendChild(inputAmount);

          form.setAttribute('action', '/checkout');
          form.setAttribute('method', 'post');
          form.submit();
        });
      });
    });
  });
  </script>

ここで、「Access Token」は知られてはいけないもの、「Client Token」はどうしても見えてしまうが見せても大丈夫なもの、「Nonce」はライブラリが Client Token を使って生成するワンタイムトークンみたいなもの、ということでした。(スライド p.28)


 
また、form を使っている部分は、jQuery を使ったりして今風にしてもらって構わないとのことです。


5.試してみる

ブラウザで http://localhost:3000/ にアクセスします。

f:id:akiyoko:20161216005405p:plain

「PayPal で支払う」ボタンをクリックすると、In-Context Window が立ち上がります。
f:id:akiyoko:20161216072235p:plain:w400

サンドボックスのパーソナルアカウント でログインして、「同意して続行」をクリックします。
f:id:akiyoko:20161216072249p:plain:w400

「/checkout」に post されて決済が実行され、画面に結果が表示されます。
f:id:akiyoko:20161216005435p:plain



最後に、決済が完了したかどうか、PayPal サイトのマイアカウントで確認をおこないます。


https://www.sandbox.paypal.com/
にアクセスし、サンドボックスのビジネスアカウント でログインします。

f:id:akiyoko:20161216072441p:plain
f:id:akiyoko:20161216072519p:plain

(仮想の)1,000円が入金されていることが確認できました。
f:id:akiyoko:20161216072538p:plain





あとは、本番で使いたい場合には、

  • Access Token を入れ替えるだけ
  • 実際にお金を引き落としするには、本人確認が必要

ということでした。

しかし残念ながら、Braintree v.zero の本番アカウントは日本ではまだ作成することができません。PayPal としても頑張っているけど、体制とサポートの問題で遅れているらしいです。。

いいニュースとしては来年、PayPal に大幅な機能改善があるそうです。ヒントとしては、US で使えていたものが順次入るとのこと。何だろうなぁ。。気になります。



オススメ本

PayPal 創業者のピーター・ティール(Peter Andreas Thiel)の本。
今年の前半に読みました。

ゼロ・トゥ・ワン―君はゼロから何を生み出せるか

ゼロ・トゥ・ワン―君はゼロから何を生み出せるか