ShopifyのCheckout IDとは?
ShopifyのCheckout IDとは、カートの中身や顧客情報を保持できるトークンです。
主にURLのクエリに付与されます。
このCheckout IDが付与されたURLを覚えておけば、ユーザーがページを離脱してもカートの中身を保持できます。
Checkout IDをクエリに付与する実装法
Checkout IDは常にURLクエリに付与されていなければなりません。
そこで、ユーザーが初めてサイトに訪れた時に
- Checkout IDの発行
- URLクエリへ添付
- そのURLへリダイレクトする
実装を行います。
リダイレクト処理を実行するファイル
実装ファイルは「plugins」ディレクトリ以下に作成します。
Nuxtの「plugins」ディレクトリは、Nuxtインスタンス生成直後に1度だけ呼ばれます。
この仕組みを利用すれば、ユーザーが初めてサイトに訪れたときに、Checkout IDが付与したURLにリダイレクト処理を行うことができます。
後は発行したCheckout IDをクエリに付与しページ遷移を行えばOKです。
Shopify初期化ファイルをpluginsに移動する
Nuxt3では、「server/api」以下のファイルをインポートしようとするとエラーを吐きます。
こちらの記事で解説 importする自作プラグインはserver/apiには置けない
そこで前回作成したShopifyの初期化ファイル、
server/api/shopify/client.ts を =>plugins/shopify.server.ts へ
移動します。
まずpluginsディレクトリを作成しましょう。
% mkdir plugins
コードは同じなので、ファイルを
% mv server/api/shopify/client.ts plugins/shopify.server.ts
Shopifyの初期化プラグインが作成できました。
plugins/shopify.server.ts
import Client from 'shopify-buy'
const client = Client.buildClient({
domain: process.env.SHOPIFY_DOMAIN,
storefrontAccessToken: process.env.SHOPIFY_ACCESS_TOKEN,
language: 'ja-JP'
})
export default client
Nuxt3でサーバーサイドプラグインを作成する方法
Nuxt3では、サーバーサイドのみで稼働するプラグインファイルに.server
を付けます。
Nuxtはpluginsディレクトリにあるファイルを自動的に読み込んでロードします。
ファイル名に .server または .client というサフィックスを使用すると、サーバ側またはクライアント側でのみプラグインをロードすることができます。
補足として、plugins
プロパティに登録しなくても自動で読み込まれます。
「plugins」ディレクトリに作成したファイルは、デフォルトでサーバーとクライアントで呼ばれます。
今回のアプリでは、漏洩を防ぐためShopifyのアクセストークンをサーバーサイドでのみ参照する仕様としています。
ですのでプラグインファイルもサーバーのみで読み込まれる必要があるため、.server
ファイルとしています。
Shopify Clientのインポート文を変更する
「server/api/shopify」ディレクトリ以下の
get-product.ts とget-products.ts の
import
文を変更します。
server/api/shopify/get-product.ts & get-products.ts
// import先を変更
// import client from './client'
import client from '~/plugins/shopify.server'
これで下準備が整いました。
Checkout IDにリダイレクトする処理を実行
新たなサーバーサイドプラグインを作成します。
% touch plugins/redirect-checkout.server.ts
Shopify APIでCheckout ID を発行するにはcheckout.create()
メソッドを使用します。
await client.checkout.create()
.then(checkout => console.log(checkout.id))
それではリダイレクト処理を記述しましょう。
plugins/redirect-checkout.server.ts
import client from '~/plugins/shopify.server'
import Url from 'url'
type CheckoutId = string | number | string[]
export default defineNuxtPlugin(async (nuxtApp) => {
console.log('plugins/redirect-checkout.server.ts')
const url = Url.parse(nuxtApp.ssrContext.req.url, true)
let checkoutId: CheckoutId = url.query.checkoutId
// checkoutIdが存在する場合は処理を終了する
if (checkoutId) {
return
}
const pathname: string = url.pathname
await client.checkout.create()
.then(checkout => (checkoutId = checkout.id))
console.log('checkoutId', checkoutId)
// $router.replaceでリダイレクトした後もサーバーサイドプラグインは読み込まれるため、実質処理は2回走る
nuxtApp.$router.replace({
path: pathname,
query: { checkoutId }
})
console.log('----------------------------------')
})
let checkoutId: CheckoutId = url.query.checkoutId
... URLからクエリを取得。const pathname: string = url.pathname
... ユーザーがアクセスしようとしたパスを取得。$router.replace
... クエリを付与してアクセスURLにリダイレクト処理。replace
... URLの履歴を残さずページ遷移を行う。URLの履歴とは、クエリ添付前のURLのこと。
クエリを付与してリダイレクトを行うとフルパスが変更されるので、もう一度サーバーサイドプラグインが読み込まれます。
実質、
Url.parse(nuxtApp.ssrContext.req.url, true)
ユーザーがアクセスしようとしたURLをサーバーで取得し、Url
ライブラリを使用してオブジェクトに変換しています。
const url
の実態は以下の通りです。
urlオブジェクトの実態
const url = Url.parse(nuxtApp.ssrContext.req.url, true)
console.log(url)
// console
Url {
protocol: null,
slashes: null,
auth: null,
host: null,
port: null,
hostname: null,
hash: null,
search: null,
query: [Object: null prototype] {},
pathname: '/',
path: '/',
href: '/'
}
awaitの後にnavigateToが発火しない?
navigateTo
は、Nuxt3が用意しているリダイレクトを行うメソッドです。
navigateTo (route: string | Route)
プラグインやミドルウェア内で、指定されたルートへリダイレクトします。また、ページナビゲーションを行うために、クライアントサイドで直接呼び出すこともできます
Nuxt3のデフォルトの挙動なのか、私のコードが悪いのか?
await
の後にnavigateTo
を実行してもスルーします。
await client.checkout.create()
.then(checkout => (checkoutId = checkout.id))
// 実行されない
navigateTo({
path: pathname,
query: { checkoutId: checkoutId || 'aaa' }
})
await
を介さない処理の後は実行されることを確認しました。
ただこの場合、checkout.create()
の処理を終わるのを待たずにリダイレクト処理が実行されるので使い物になりません。
client.checkout.create()
.then(checkout => (checkoutId = checkout.id))
// 実行されるがcheckoutIdは発行されていないため、'aaa'が付与される
navigateTo({
path: pathname,
query: { checkoutId: checkoutId || 'aaa' }
})
対応
navigateTo
の実態は、VueRouterを使用してリダイレクトをおこなっています。
そこで、Nuxtインスタンスの$rouer.replace
でリダイレクト処理を行いました。
await client.checkout.create()
.then(checkout => (checkoutId = checkout.id))
nuxtApp.$router.replace({
path: pathname,
query: { checkoutId }
})
ブラウザで確認しよう
http://localhost:3000/
の状態でページをリロードしてください。
Checkout IDクエリが付与されたURLにリダイレクトされました。
実装は以上です。
まとめ
今回はShopifyのカート情報を保持するCheckout IDを、URLクエリにつけてリダイレクトを行う実装をしました。
このCheckout IDを常にURLに付与することで、どのページに遷移しても、サイトを離脱してもカートの中身を保持することができます。
また決済時には、このCheckout IDをShopify渡すことでカート情報を共有します。
ここら辺の実装はまだ調査中なので、分かり次第ここで共有します。それでは!