オンラインコンテンツのダウンロードページの作り方
Silicon Valley Super Ware
2020年9月21日
オンラインコンテンツのダウンロードページの作り方
オンラインで決済を行った後にオンラインコンテンツのダウンロードページをどのように実装するかは、販売サイトを作る上での課題の一つです。今日は、サーバー側でダウンロードページを作る方法を紹介します。
サーバ側でレンダリングする
最近では、サーバーサイドのレンダリングのフレームワークとして、「Next」や「Nuxt」を利用するケースも増えています。
今回は、ダウンロードページを作るだけなのでもう少しシンプルな方法で作る方法を紹介します。
基本は、すでに実装しているExpressともう一つ「express-handlbars」というモジュールを使います。これは、サーバ側で用意したテンプレートを使ってクライアント側(ブラウザー)で表示するページを作る方法です。
手順は
- 「npm install express-handlebars」でモジュールをインストール
- 「functions」のフォルダーの下に「views」というフォルダーを作成
- 「views」のフォルダーの下に、さらに「layouts」というフォルダーを作成
- テンプレートのページの作成
になります。モジュールのインストールは実行するだけですので特に説明は必要ないかと思います。
「views」の下は、クライアント側で表示するHTMLファイルの「素」を入れておくフォルダーです。「layouts」はページの構造(基本レイアウト)を記述したファイルを置くホルダーです。
layoutsフォルダーの下に置く「layout.hbs」の例です。
この「express-handlebars」でページを作る際に、ページに埋め込む情報を指定するとそれを取り込んだページを作ってくれます。
「{{xxxxx}}」は通常のテキストとして埋め込みます。
「{{{xxxxx}}}」はHTMLで記述されたテキストを読み込むことができます。
下の例では
- title (text)
- body (html)
- sub_section (html)
- copyright (text)
を必要に応じて指定して埋め込む事ができます。
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>{{ title }}</title>
</head>
<body>
<nav class="navbar navbar-expand-lg navbar-dark bg-primary">
<a class="navbar-brand" href="#">Menu</a>
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarColor01"
aria-controls="navbarColor01" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarColor01">
<ul class="navbar-nav mr-auto">
<li class="nav-item">
<router-link class="nav-link" to="/">Home</router-link>
</li>
</ul>
</div>
</nav>
<div id="contents">
{{{ body }}}
{{{ sub_section }}}
</div>
<div class="footer">
<footer>{{ copyright }}</footer>
</div>
</body>
</html>
viewsの下には、「downloadPage.hbs」というダウンロードページのテンプレートを作ります。
downloadPage.hbs と layout.hbsを組み合わせてページを作ります!
以下が、downloadPage.hbsの例です。
{{#if condition}}
<div class="sub_header">
<h2>ご購入どうもありがとうございます。</h2>
<p>以下のリンクからダウンロードしてください。なおリンクは購入後24時間有効です。</p>
</div>
{{else}}
<div class="sub_header">
<h2>購入手続きでエラーが発生しました</h2>
<p>お手数ですが、tomonori.hirai@siliconvalleysw.comまでお知らせください。</p>
<ul>
<li>お名前</li>
<li>E-mailアドレス</li>
<li>購入商品名</li>
</ul>
<p>お問合せの際は上記を明記してお送りください。</p>
<p>お手数をおかけします。</p>
</div>
{{/if}}
ご覧になるとお分かりかと思いますが、条件によって表示する部分を変える事ができます。
ルーティングの処理
あとは、ルーティングの処理は他のバックエンドの処理と同じです。this.app.get("/download", async (req, res) => {
// Gets the session information
if (req.query.session_id) {
const params: any = req.query;
const session: any = await stripe.checkout.sessions.retrieve(
params.session_id
);
if (session && session.payment_status === "paid") {
page.condition = true;
/* データベースから必要な情報を取得するための処理が入ります!*/
page.title = "ダウンロードページ";
page.clearSubSection();
page.sub_section = [
'<a class="download" href="' + url + '">Download<a>',
];
page.condition = true;
res.setHeader("Set-Cookie", "HttpOnly;Secure;SameSite=Strict");
res.render("downloadPage", page.getPage());
} else {
res.redirect("/");
}
} else {
res.redirect("/");
}
});
この例では「page」とういう表示の為のオブジェクトを作って、それに情報を設定して、先ほどの埋め込む情報をexpress-handlbarsに渡します。
express-handlebarの設定は以下の様になります。
import * as TYPE from "./types";
import * as CONSTANT from "./constants";
import Page from "./page";
const bodyParser = require("body-parser");
const hbs = require("express-handlebars");
const path = require("path");
const page = new Page();
class AppServer {
public app: express.Express = express();
constructor() {
// Initialize a page template
page.title = "";
page.logo = CONSTANT.PAGE_LOGO;
page.copyright = CONSTANT.COPYRIGHT;
page.menu = CONSTANT.PAGE_MENU;
page.sub_section = [];
// Initializes middleware
// Handle Bars
this.app.engine(
"hbs",
hbs({
extname: "hbs",
defaultLayout: "layout",
layoutDir: path.join(__dirname, "../views/layouts"),
})
);
this.app.set("views", path.join("views"));
this.app.set("view engine", "hbs");
this.init();
}
express-handlebarsの設定は、ファイルの拡張子(例では「hbs」に設定)やフォルダーの構造を設定しています。既に説明した「views」や「layouts」の設定を行えばOKです。
基本的には、「express」にレンダリングエンジンとして「express-handlebars」を使うと教える感じになります。
「Page」は便宜上クラスを作っていますが、express-handlebarsに渡すのはJSON形式のデータで、
const page = {
title: this.title,
logo: this.logo,
menu: this.getMenu(),
copyright: this.copyright,
condition: this.condition,
sub_section: this.sub_section,
};
のようなデータを作って渡しているだけなので、直接JSONを書いても問題ありません。
これで、メインのドメイン xxxx.xxxx/downloadでページにアクセスできます。
Stripeから決済のセッションIDを受けっとって処理
あとは、例に書いている様に、このURLをStripeに決済のセッションんを要求する時に渡します。決済が成功した際は、セッションIDが一緒に渡されるので、データベースからデータを受け取ってURLを取得します。
その情報を基にダウンロードページを生成してフロントエンドに渡します。
成功した場合と失敗した場合でコンディション(condition)の値を変えてあげれば、表示する内容を変えられます。
別のやり方は、ページの生成をフロントエンド(ブラウザー)で行う方法もあります。
どちらでやってもOKです。違いはセキュリティです!
バックエンドで処理を行うと、最終的なリンク情報以外は、利用者は見る事ができません。
一方で、フロントエンドの処理は、JavaScriptになるのでブラウザーから参照することが可能です。
データベースへのアクセスはFirebaseの場合セキュリティールールをきちんと書けばアクセスは制限できるので、多くの場合フロントエンドで作っても管理は可能です。
バックエンドの場合、多くの処理を隠せるのでセキュリティ上は有利です。
使用するアプリケーションによってどちらが良いかを決めます。
興味のある方は今すぐお問合せください!
またよろしければ、ニュースレターの登録をお願いします!大体週一回お届けしています。ブログよりは一歩踏み込んだもっと濃い内容を発信しています。
コメント
コメントを投稿