【snake】 Section: 16 Accepting Recurring Payments ①

Signing up with Stripe

なぜstripeを使うのか。

以下の3社があるがStripeが良い。
Stripe PayPal SPIKE
Paypalはアカウント持ってないといけない。
APIが優れている。

IDを作る f:id:yukking3:20180716153537p:plain

Going over the requirements.txt Changes

新しく以下の2つを導入する。 
mock==1.3.0 mockでリアルAPIを使う前にAPIのテストをすることができる。
stripe==1.32.0 stripeのAPIを使えるようになる。 f:id:yukking3:20180716155054p:plain


Configuring the App to Handle Payments

config/setting.pyの49行目からBillingが追記される。 f:id:yukking3:20180716174028p:plain instance/setting.pyにAPIキーを登録する。 f:id:yukking3:20180716174105p:plain

Adding the Billing Blueprint

app.pyファイルをセットする。

16行目から21行目でインポートする。
78行目と79行目でAPIを読みこむ。
89行目から91行目でblueprintをregisterする。 f:id:yukking3:20180716174849p:plain f:id:yukking3:20180716174838p:plain

Visualizing the Data Model Relationships

データベースのモデルに関して

Creating Subscription Plans

データベースをリセットするには以下のコマンド

$ docker-compose exec website snakeeyes db reset --with-testdb
$ docker-compose exec website snakeeyes add all

プランが記載されている。
metadataの部分をtrueにするとオススメになる。 f:id:yukking3:20180716211129p:plain
cmd_stripe.pyでコマンドを登録する。
プランをシンクさせる。
プランをdaleateする
プランのリストを記載する
f:id:yukking3:20180716211249p:plain


for _, これはキーは関係ないということ。
キーはプランなので0、1、2のどれかになる。
28行目以降でPlanはupdateかcreateの2択である。
f:id:yukking3:20180716213018p:plain
stripecom.pyでプランを検索する(retrieve plan)
もしエラーが発生した際はprint(e)する。
f:id:yukking3:20180716213233p:plain
gateways/stripe.pyのupdateメソッドに関して、
263行目からはupdate functionである。
282行目でプランを検索する。
287行目でsaveする。かなりシンプルである。
f:id:yukking3:20180716213634p:plain


gateways/stripe.pyのcreateメソッドに関して、
249行目のidでプランを読み込んで、stripe APIを送る。
f:id:yukking3:20180716214014p:plain
それでは実際にシンクさせてみる。コマンドは以下。

$ docker-compose exec website snakeeyes stripe sync_plans

次にリスト表示をさせる。シンクしたプランを表示する。

$ docker-compose exec website snakeeyes stripe list_plans

cmd_stripe.pyに list_plansが記載されている。 f:id:yukking3:20180716214549p:plain stripecom.pyでclsが記載されている。 f:id:yukking3:20180716214701p:plain

次にdeleteをさせる。

$ docker-compose exec website snakeeyes stripe delete_plans bronze

cmd_stripe.pyにlelete_plansが記載されている。
nargs=-1はなに?
52行目のdelete(plan_id)でデリートする。 f:id:yukking3:20180716215139p:plain
stripecom.pyで記載されている。
これも同じで簡単である、
retrieveして、deleteするるだけ。
f:id:yukking3:20180716215304p:plain

Rendering Pricing Tables

ログインしてない状態でプライステーブルをみるとsign in表示で出る f:id:yukking3:20180716220941p:plain ログインしてからみるをcontinueになる。 f:id:yukking3:20180716221257p:plain ちなみmain.cssの47行目でtransformで若干大きくしている。 f:id:yukking3:20180716222609p:plain

template/billing/pricing.htmlでページが構成され、
ブロンズ、ゴールド、シルバーが設定されている。
また、call billing.planとマクロが設定されている。
f:id:yukking3:20180716222805p:plain

次にマクロフォルダーのbilling.htmlでマクロをみる。
以下で振り分けが構成されている。
if current_user.is_authenticated → Sign up
if current_user.subscription → Continue
if plan == active_plan → Change plan
f:id:yukking3:20180716223606p:plain また、50行目の{ plan.amount | format_currency }は、
カレンシーを変更するようになっている。
app.pyでformat_currencyがインポートされている。
f:id:yukking3:20180716223738p:plain
template_processors.pyでformat_currency functionをみる。
少数2位以下を切り捨てる。また、セントをドルに変換して表示する。
f:id:yukking3:20180716224020p:plain
cents_to_dollars funcはlibフォルダーのmoney.pyに記載されている。 f:id:yukking3:20180716224506p:plain


Subscribing to a Plan (Front-End) Java Scripに関して

f:id:yukking3:20180717212715p:plain

base.htmlに以下をセットする。

script src="https://js.stripe.com/v2/"

f:id:yukking3:20180717211657p:plain

4行目から14行目はpayment処理に関して、 f:id:yukking3:20180717211950p:plain

21行目は、payment formに関して?
34行目は、アラートセットする。
f:id:yukking3:20180717213126p:plain 60行目から75行目はセレクトボックスになっていてカード情報を登録できる。 { '%04d' % year }であれば4桁の数字
current_year()+15) %であれば、現在から15年先まで。
f:id:yukking3:20180717212839p:plain

spinnerクラスにgifがあって、hiddenになっているが、
javascrioptよくわからん。この講座の80%がjsに関して。。
jsよくわからん

Subscribing to a Plan (Back-End)

billing.pyに関して f:id:yukking3:20180717220354p:plain
@handle_stripe_exceptionsに関して
500エラーのみをただ表示しないように設定をする。
例えば、42行目はAPIキーが正しいか確認する。
45行目はコネクションエラーが発生したときにflashメッセを表示する。
CardError、InvalidRequestError、StripeErrorなどはSTRIPE側で設定されている。 f:id:yukking3:20180717220508p:plain


57行目はsubscriptionをチェックして、ダメならredirectさせる。
63行目のget_plan_by_idに関して、
もし、id と planがマッチしたらreturnする。
f:id:yukking3:20180717221400p:plain
64行目は、無いプランを選択したり、POSTではなくGETで送信された場合はエラーメッセージを表示するようにした。
もし、問題なければ69行目でPublic Keyを取得して、formを確認する。
f:id:yukking3:20180717221938p:plain

72行目でもしformが有効であればcreate new subscriptionを実行する。
もし成功すれば80行目でthanksメッセージで処理する。
失敗したら83行目でメッセージを表示させる。


creatメソッドをみる前にsubscriptionメソッドでdata modelとuser modelを確認する。

テーブルsubscriptionsにはprimarykeyでid登録があり。またuser idもある。
ForeignKeyで設定しているのでunique keyである。
ForeignKeyとは外部キーである。すでにある番号でここから選べよって意味。
ON DELETE CASCADE オプションは、親表で行が削除されたときに、
子表の対応する行を削除する場合に使用します。
planとcouponのデータベースもある。 f:id:yukking3:20180717233012p:plain

subscription.pyに関して、 83行目でno tokenの場合はfalseにする。 85行目でcouponを大文字で表記する。 88行目でgateway/stripcom.pyのSubscriptionFuncを呼ぶ。 gateway/stripcom.pyに関して f:id:yukking3:20180717235132p:plain

customerが定義されていて、customerがそのままdbに保存される。 また、updateする際は、nameとかも定義してある。 f:id:yukking3:20180717235846p:plain

103行目は、もしクーポンがあった場合はそのように処理をする。 108行目はcustomer functionを使う。 CreditCard を使うには、user_idを渡す。 また、extract_card_params パラメータも使う。

CreditCard modelを確認する。 データベースが'credit_cards' user_idはsubscriptionと同じでforeignKeyとcascadeを使う。 そして、brand,last4number,expdateなどを格納できるようにする。 f:id:yukking3:20180718000428p:plain

extract_card_paramsに関して、 70行目と71行目からstripからカードデータを取得する。 73行目でデータを辞書に格納する。 f:id:yukking3:20180718001240p:plain

Updating Your Payment Method

payment_method.htmlに関して、
今回はis_createでは無いので11行目から13行目で処理する。
また、同じように30行目で処理をする。 f:id:yukking3:20180718080414p:plain
related modelって何や?
billing.pyに関して
152行目でif not current_user.credit_cardを確認する。
156行目から161行目でクレカ情報を取得する。
165行目で有効な場合はupdateする。update内容はform.getで取得。
174行目でupdateが成功したらflashメッセージ表示
177行目ではダメだった場合はseting.ページへ飛ばす。
182行目でカードの4桁をpayment_method.htmlへ渡す。
f:id:yukking3:20180718092022p:plain

165行目のupdate_payment_methodに関して
f:id:yukking3:20180718092237p:plain 190行目でトークンを確認する。
あれば必要情報を入力してsessionをcommitする。

updateメソッドに関して、 f:id:yukking3:20180718092825p:plain

Informing Users of Expiring Credit Cards

クレジットカードの有効期限が切れそうになった場合はwarningメッセを出す。
このメッセージはどのページに行っても表示される。
f:id:yukking3:20180718093127p:plain

2行目はmacroを呼び出している。 f:id:yukking3:20180718093326p:plain htmlのbody欄の一番上がbilling.card_expiring_warning担っている。f:id:yukking3:20180718093608p:plain 実際にどのようなマクロが仕込まれているかを確認する。
billing/macro/billing.htmlの一番上を確認すると、
もし、is_authenticatedでsubscriptionがis_expiringだった場合、
card_expiring_warning()発動するようになっている。
f:id:yukking3:20180718223046p:plain

is_expiringはクレジットカードモデルフォルダーの
credit_card.pyで定義されている。
CreditCard Classがあって、データベースに情報が格納されるようになっている。 f:id:yukking3:20180718224523p:plain

extract_card_paramsメソッドで格納できるようパラメータ設定される。
このメソッドを使ってカード情報を読み取る。
f:id:yukking3:20180718224743p:plain

ではどのように、有効期限が近いかを判断する。
最初にカードの有効期限が2ヶ月か設定されている。
f:id:yukking3:20180718225305p:plain

次に期限月とtimedelta_monthsを比較する。<=で残りの数字がわかる。
returnはbool値でTrueまたはFalseで結果が出る。
f:id:yukking3:20180718230322p:plain

ちなみに、timedelta_monthsは、lib/uti_datetime.pyで現在時刻を表示する。 f:id:yukking3:20180718225951p:plain

ページをロードするたびにこれをチェックししすると莫大なエネルギーがかかる。そこで毎日決まった時間に確認タスクを実行するようにする。
mark_old_credit_cardsメソッドで期限切れを確認する。
f:id:yukking3:20180718231131p:plain 次にtask.pyでceleryを使ってtaskを登録する。
f:id:yukking3:20180718231353p:plain

config/setting.pyでCeleryを登録する。
登録方法は、名前をつけて、実行するtaskを設定して、スケジュールを決める。
crontabを使って00時に実行するように設定する。hour=23はpm11時。
f:id:yukking3:20180718231533p:plain

Docker Compose fileも変更する
celery worker -b ハートビートのb
f:id:yukking3:20180718232222p:plain

Updating Your Subscription Plan

プラン変更に関して f:id:yukking3:20180719002200p:plain

どのようなマクロが設定されているか? pricing.htmlを確認する。 ユーザーがsubscriptionならYou're about to change plans f:id:yukking3:20180719002609p:plain

次にbilling.htmlを見る もし、active_planだったらcurrent plant もし違う場合はchange plan f:id:yukking3:20180719003947p:plain

次にviews/billing.pyを確認する。 f:id:yukking3:20180719003140p:plain

次に@subscription_requiredをdecorator.pyで確認する。
このデコレーターでエラー起こさないようにプロテクトする。
16行目でsubscriptionじゃなければテーブルプランにリダイレクトする。
サブスククリプションないとbilling.pyのupdateに進めないようになっている。
f:id:yukking3:20180719003446p:plain


そして、billing.pyへ戻る。以下を順に確認する。
current_plan → 現在プランに加入しているか
active_plan → get_plan_by_idメソッドで現在のプラン
new_plan → get_new_planメソッドで
f:id:yukking3:20180719003140p:plain
get_new_planメソッドとは、
最初にマクロは以下のようになっている。
submitをクリックするとplan.idが飛ぶ?
plan.id →goldとか
f:id:yukking3:20180719085839p:plain

billing.pyのrequest.form.keys()には全プランが入っている。
次にsubscription.pyのget_new_planメソッドである。
submitをsplitで区切る。
keyって何入ってるの?どこで入った?
60行目から62行目がよくわからん。
f:id:yukking3:20180719090225p:plain

splitメソッドとは、
区切る文字も区切る回数も自由
一行ずつ分割したいならsplitlinesを使用
f:id:yukking3:20180719091653p:plain

この時点でactive_planとnew_planが決まった。
billing.pyへ戻る。
102行目から106行目は、
もし同じプランだった場合、プランが存在しない場合
billing.updateでリダイレクトさせる。

110行目でsubmitionに問題あるか確認する。 f:id:yukking3:20180719092725p:plain

108行目でクーポンあるかformで確認する。 f:id:yukking3:20180719092930p:plain

subscription.pyを確認する。 f:id:yukking3:20180719093306p:plain

stripecom.pyを確認する。 f:id:yukking3:20180719093220p:plain