【Shopify.dev和訳】Apps/Checkout/Payment methods/Rename a method
この記事について
この記事は、Apps/Checkout/Payment methods/Rename a methodの記事を和訳したものです。
記事内で使用する画像は、公式ドキュメント内の画像を引用して使用させていただいております。
Shopify アプリのご紹介
Shopify アプリである、「商品ページ発売予告アプリ | リテリア Coming Soon」は、商品ページを買えない状態のまま、発売日時の予告をすることができるアプリです。Shopify で Coming Soon 機能を実現することができます。
Shopify アプリである、「らくらく日本語フォント設定|リテリア Font Picker」は、ノーコードで日本語フォントを使用できるアプリです。日本語フォントを導入することでブランドを演出することができます。
決済方法の名称変更
このチュートリアルでは、Shopify Scripts を使って、マーチャントがチェックアウト時に顧客に提供する支払い方法の名前をカスタマイズできるようにする Payment Methods スクリプトを作成します。
学べる内容
このチュートリアルを終えると、以下のことができるようになります。
- 最初の支払い方法の名前を変更するスクリプトの作成
- スクリプトのロジックをテストする
- スクリプトを Shopify プラットフォームにデプロイし、カスタムアプリと関連付ける
- Shopify のストアでスクリプトを有効にする
- パートナーダッシュボードでスクリプトの実行時間を確認する
- コードを再利用できるように設定を追加することに慣れる
次の図は、ワークフローを完成させるための手順を示しています。
要件
- Shopify CLIをインストールしていること。
- カスタムアプリを作成していること。Shopify Scripts は現在、カスタムアプリのみをサポートしています。
- カスタムアプリをストアにインストールします。
Step 1: 決済スクリプトを作成する
Shopify CLIを使って、以下のコマンドを実行します。
shopify script create --extension-point=payment_methods --name="Rename payment method"
決済スクリプトの更新
src/script.ts
にある決済スクリプトの内容を、以下のコードで置き換えます。これは、PaymentMethods.RenameProposal
の配列を返すrenamePaymentMethod
関数を導入しています。この例では、最初の payment method の名前を Hello Payments
に変更しています。
import {PaymentMethods, Configuration, CheckoutDomain as Domain} from '@shopify/scripts-checkout-apis';
export function paymentMethodsHandler(
input: PaymentMethods.Input,
configuration: Configuration,
): PaymentMethods.Result {
const sortResponse = new PaymentMethods.SortResponse([]);
const filterResponse = new PaymentMethods.FilterResponse([]);
const renameResponse = renamePaymentMethod(input.paymentMethods);
return new PaymentMethods.Result(sortResponse, filterResponse, renameResponse);
}
function renamePaymentMethod(paymentMethods: Domain.PaymentMethod[]): PaymentMethods.RenameResponse {
var renameProposals = new Array<PaymentMethods.RenameProposal>();
if (paymentMethods.length > 0) {
const renameProposal = PaymentMethods.RenameProposal.rename(paymentMethods[0], 'Hello Payments');
renameProposals.push(renameProposal);
}
return new PaymentMethods.RenameResponse(renameProposals);
}
Step 2: 作成したスクリプトをテストする
スクリプトのロジックをテストするには、script.spec.ts
にユニットテストを作成して、npm test
コマンドで実行します。
Payment スクリプトの test/script.spec.ts
の内容を以下のコードで置き換えて、いくつかのテストを追加します。createPurchaseProposal
関数を使って、テストで使用する 1 つのラインアイテムを持つテストカートを作成します。最初の支払い方法の名前だけが Hello Payments
に変更されていることをチェックするテストが 1 つあります。
import {
CheckoutDomain as Domain,
PaymentMethods,
Currencies,
Configuration,
Money,
} from '@shopify/scripts-checkout-apis';
import {paymentMethodsHandler} from '../src/script';
function newPaymentMethod(name: string, cards: string[] = []): Domain.PaymentMethod {
return new Domain.PaymentMethod(1, name, cards);
}
/**
* この関数は、Domain.TestHelperのbuilder classを使用して、
* チェックアウトなどの偽の入力オブジェクトを簡単に作成します。
* この関数を編集したり、コピーを作成したりして、
* 独自のカスタムチェックアウトオブジェクトを定義し、
* それに対してテストを行います。
*/
function createPurchaseProposal(): Domain.PurchaseProposal {
return new Domain.TestHelper.PurchaseProposalBuilder()
.setLines([
Domain.TestHelper.PurchaseProposalBuilder.line(
new Domain.TestHelper.VariantBuilder()
.withProduct(new Domain.TestHelper.ProductBuilder().titled('Red Delicious').addTag('fruits').buildWithId(1))
.buildWithId(1),
1,
Money.fromAmount(1, Currencies.CAD),
)
])
.build();
}
describe('paymentMethodsHandler', () => {
it('renames first method only', () => {
const purchaseProposal: Domain.PurchaseProposal = createPurchaseProposal();
const paymentMethods = [
newPaymentMethod('2'),
newPaymentMethod('3', ['visa', 'mc', 'amex']),
newPaymentMethod('1'),
newPaymentMethod('4'),
];
const result: PaymentMethods.Result = paymentMethodsHandler(
new PaymentMethods.Input(purchaseProposal, paymentMethods),
new Configuration([]),
);
const renameResponse = result.renameResponse!;
expect(renameResponse.renameProposals[0].name).toBe('Hello Payments');
expect(renameResponse.renameProposals.length).toBe(1);
});
});
ターミナルで,テストスイート(テストセット)を実行します。
npm test
[Describe]: paymentMethodsHandler
[Success]: ✔ renames first method only
[File]: test/script.spec.ts
[Groups]: 2 pass, 2 total
[Result]: ✔ PASS
[Snapshot]: 0 total, 0 added, 0 removed, 0 different
[Summary]: 1 pass, 0 fail, 1 total
[Time]: 6.157ms
✔ test/script.spec.ts Pass: 1 / 1 Todo: 0 Time: 6.157ms
[Result]: ✔ PASS
[Files]: 1 total
[Groups]: 2 count, 2 pass
[Tests]: 1 pass, 0 fail, 1 total
[Time]: 2141.536ms
Step 3: スクリプトをデプロイする
スクリプトを Shopify プラットフォームにデプロイし、アプリに関連付けるには、以下のコマンドを実行します。
shopify script push
スクリプトをデプロイすると、Shopify プラットフォームにアップロードされ、アプリに登録されます。shopify script push --force
コマンドを使用してスクリプトを再度デプロイすると、スクリプトの現在のバージョンが上書きされます。スクリプトがストアで有効になっている場合は、上書きされた後も有効な状態が維持されます。スクリプトに設定値が設定されていた場合は、新しいスクリプトでもその設定値が使用されます。
スクリプトを再デプロイする
次回、shopify script push
コマンドを実行すると、Shopify CLI は.env
ファイルを読み込んで、以下のことを行います。
-
.env
に記載されているアプリに接続します。 - UUID にマッチするスクリプトがないかアプリをチェックする
スクリプトを別のアプリにデプロイする
スクリプトを別のアプリにデプロイしたい場合は、.env
ファイルを削除して、shopify script push
を実行します。
Step 4: スクリプトの有効化
デフォルトでは、アプリがインストールされたストアでスクリプトが使用できるようになっていますが、有効になっていません。チェックアウトの動作を変更するには、スクリプトを有効にする必要があります。
- ストアの Shopify 管理画面で、設定をクリックします。
- 支払いをクリックします。
- 支払い方法のカスタマイズセクションで、カスタマイズの作成をクリックします。
- 有効にするスクリプトを選択し、ステータスをオンに更新します。
- Saveをクリックします。
Step 5: スクリプトの監視とデバッグ
Partner Dashboard のアプリのExtensionsセクションから、スクリプトを監視し、エラーを調査することができます。
-
Partner Dashboard で、Appsをクリックします。
-
アプリの名前をクリックします。
-
拡張機能をクリックします。
-
Checkout をクリックし、スクリプト名をクリックします。
スクリプトの実行時間とエラー情報が表示されます。実行結果が Partner Dashboard に表示されるまでには、最大で 2 分かかることがあります。
エラーの種類
スクリプトのすべてのエラーは、Partner Dashboard では RunErrors と表示されます。以下のようなエラーが発生することがあります。
-
実行タイムアウト - これらのエラーは、スクリプトの実行に時間がかかりすぎた場合に発生します。例えば、無限ループなど、スクリプトが無限に実行されるようなエラーが発生する場合があります。src/shopify_main.ts
export function shopify_main(): void { while(true) {} }
-
ランタイムエラー - これらのエラーは、コンパイル時には特定できない一般的なエラーです。以下のようなエラーが含まれます。
- スタックオーバーフロー
- ゼロによる整数の割り算
- unreachable (コードに追加したスローエラーを含む)
スクリプトに src/shopify_\__main.ts
ファイルが含まれていない場合、スクリプトは失敗しますが、Partner ダッシュボードにはエラーは表示されません。
スクリプトのデバッグ
スクリプトにメッセージログを追加すると、エラー発生時のデバッグに役立ちます。
Console.log
や as-pect's log 関数を使って、スクリプトやテストからのメッセージをログに記録します。どちらも使用する前に、以下の注意点を確認してください。
- AssemblyScript では、
Console.log
は引数として文字列しか受け付けません。 -
as-pect's log 関数は、複数のデータ型を受け入れ、その出力がより適切にフォーマットされているので、より使いやすいです。プッシュする前にスクリプトから削除すれば、ユニットテストやスクリプトの中で
log
を使用することができます。
破壊的な変更を避ける
新しいスクリプトをプッシュすると、アプリ上の現在のライブスクリプトが置き換えられます。新しいスクリプトの設定スキーマに下位互換性がない場合は、設定値も更新されることを確認してください。
構成に関連する一般的なランタイムエラーには、次のような問題があります。
- Missing configuration values (構成値の欠落)
- Type casting errors (タイプキャスティングエラー)
- Renaming configuration keys (構成キーの名前変更)
スクリプトのダウンタイムを最小限に抑えるには、店舗に連絡してスタッフと協力し、カスタマイズを削除して再作成することが必要です。また、スクリプトにチェックを入れることで、エラーをより適切に処理することができます。たとえば、設定値が存在しない場合、スクリプトは代わりにデフォルト値を使用することができます。
スクリプトとアプリの削除
Partner Dashboard を使用して、アプリからスクリプトを削除することができます。スクリプトを削除する前に、すべてのストアでそのスクリプトのステータスがオフになっていることを確認してください。
スクリプトを追加したアプリは削除しないでください。
Step 6: configurations
コードの再利用性を高めるために、スクリプト内のハードコードされた変数を configuration で置き換えることができます。configuration では、マーチャントやスタッフが Shopify 管理画面で値やオプションを入力して、スクリプトをカスタマイズすることができます。スクリプトが実行されると、これらの値はキーと値のペアで入力としてスクリプトに渡されます。
スクリプトの schema
プロパティは、スクリプトがユーザー設定可能なプロパティを持つかどうかを決定します。設定は単一の値または値のリストを受け付けることができます。
設定可能な値を追加
script.json
には、設定可能な 2 つの値として、名前を変更するペイメントゲートウェイと新しいゲートウェイの名前を入れます。
{
"version": "1",
"title": "Rename payment method",
"description": "Rename a payment method",
"configurationUi": true,
"configuration": {
"type": "single",
"schema": [
{
"key": "nameToMatch",
"name": "Payment method name",
"type": "single_line_text_field",
"helpText": "The payment method to rename",
"defaultValue": "Cash on Delivery (COD)"
},
{
"key": "renameTo",
"name": "Rename to",
"type": "single_line_text_field",
"helpText": "The new payment method name",
"defaultValue": "Hello Payments"
}
]
}
}
設定値の取得
スクリプトでは、configuration.getメソッドを使って設定値を取得します。これは、renamePaymentMethod
関数にconfiguration
を渡して、設定値をキーごとに取得するというものです。これで、すべてのペイメントメソッドを繰り返し処理して、設定値と一致するペイメントメソッドの名前を変更することができます。
スクリプトの configuration.get
メソッドのキーが、構成スキーマの key の値と一致していることを確認してください。構成がリストの場合は、ConfigurationList クラスを使用して構成を操作することもできます。
import {PaymentMethods, Configuration, CheckoutDomain as Domain} from '@shopify/scripts-checkout-apis';
export function paymentMethodsHandler(
input: PaymentMethods.Input,
configuration: Configuration,
): PaymentMethods.Result {
const sortResponse = new PaymentMethods.SortResponse([]);
const filterResponse = new PaymentMethods.FilterResponse([]);
const renameResponse = renamePaymentMethod(input.paymentMethods, configuration);
return new PaymentMethods.Result(sortResponse, filterResponse, renameResponse);
}
function renamePaymentMethod(paymentMethods: Domain.PaymentMethod[], configuration: Configuration): PaymentMethods.RenameResponse {
var renameProposals = new Array<PaymentMethods.RenameProposal>();
for (let i=0; i<paymentMethods.length; i++) {
if (paymentMethods[i].name == nameMatchConfiguration(configuration)) {
const renameProposal = PaymentMethods.RenameProposal.rename(paymentMethods[i], renameConfiguration(configuration));
renameProposals.push(renameProposal);
}
}
return new PaymentMethods.RenameResponse(renameProposals);
}
function nameMatchConfiguration(configuration: Configuration): string {
const defaultNameFilter = 'Unknown';
return configuration.exists('nameToMatch') ? configuration.get('nameToMatch')! : defaultNameFilter;
}
function renameConfiguration(configuration: Configuration): string {
const defaultNameFilter = 'Unknown';
return configuration.exists('renameTo') ? configuration.get('renameTo')! : defaultNameFilter;
}
設定内容のテスト
以下のコードを test/script.spec.ts
にコピーして、テストを更新します。
import {
CheckoutDomain as Domain,
PaymentMethods,
Currencies,
Configuration,
Money,
} from '@shopify/scripts-checkout-apis';
import {paymentMethodsHandler} from '../src/script';
function newPaymentMethod(name: string, cards: string[] = []): Domain.PaymentMethod {
return new Domain.PaymentMethod(1, name, cards);
}
/**
* この関数は、Domain.TestHelperのbuilderクラスを使用して、
* チェックアウトなどの偽の入力オブジェクトを簡単に作成します。
* この関数を編集したり、コピーを作成したりして、
* 独自のカスタムチェックアウトオブジェクトを定義し、
* それに対してテストを行います。
*/
function createPurchaseProposal(): Domain.PurchaseProposal {
return new Domain.TestHelper.PurchaseProposalBuilder()
.setLines([
Domain.TestHelper.PurchaseProposalBuilder.line(
new Domain.TestHelper.VariantBuilder()
.withProduct(new Domain.TestHelper.ProductBuilder().titled('Red Delicious').addTag('fruits').buildWithId(1))
.buildWithId(1),
1,
Money.fromAmount(1, Currencies.CAD),
),
])
.build();
}
describe('paymentMethodsHandler', () => {
it('does nothing when not configured', () => {
const purchaseProposal: Domain.PurchaseProposal = createPurchaseProposal();
const paymentMethods = [
newPaymentMethod('2'),
newPaymentMethod('3', ['visa', 'mc', 'amex']),
newPaymentMethod('1'),
newPaymentMethod('4'),
];
const result: PaymentMethods.Result = paymentMethodsHandler(
new PaymentMethods.Input(purchaseProposal, paymentMethods),
new Configuration([]),
);
expect(result.renameResponse!.renameProposals.length).toBe(0);
});
it('renames payment method when configured', () => {
const purchaseProposal: Domain.PurchaseProposal = createPurchaseProposal();
const paymentMethods = [
newPaymentMethod('2'),
newPaymentMethod('3', ['visa', 'mc', 'amex']),
newPaymentMethod('1'),
newPaymentMethod('4'),
];
var configurations = new Map<string, string>();
configurations.set('nameToMatch', '2');
const renameTo = 'Hello Payments'
configurations.set('renameTo', renameTo);
const result: PaymentMethods.Result = paymentMethodsHandler(
new PaymentMethods.Input(purchaseProposal, paymentMethods),
Configuration.fromMap(configurations),
);
const renameResponse = result.renameResponse!;
expect(renameResponse.renameProposals[0].name).toBe('Hello Payments');
expect(renameResponse.renameProposals.length).toBe(1);
});
});
ターミナルで、テストスイートを実行します。
npm test
[Success]: ✔ renames payment method when configured
[File]: test/script.spec.ts
[Groups]: 2 pass, 2 total
[Result]: ✔ PASS
[Snapshot]: 0 total, 0 added, 0 removed, 0 different
[Summary]: 2 pass, 0 fail, 2 total
[Time]: 5.018ms
✔ test/script.spec.ts Pass: 2 / 2 Todo: 0 Time: 5.018ms
[Result]: ✔ PASS
[Files]: 1 total
[Groups]: 2 count, 2 pass
[Tests]: 2 pass, 0 fail, 2 total
[Time]: 1937.873ms
スクリプトの再デプロイ
更新したコードを push
コマンドで Shopify にデプロイします。今回は、既存のスクリプトを上書きするために、--force
オプションを使用する必要があります。
shopify script push --force
Payment settingsページで、スクリプトに 2 つの新しい設定値を入力して、チェックアウトでテストすることができます。現在のところ、チェックアウトで変更が反映されるまでに、最大で 5 分かかることがあります。
お金と通貨に関するヒント
次のセクションでは、スクリプトで通貨と貨幣の値を使用する際のヒントを紹介します。
国際価格と多通貨はサポートされていません
Shopify スクリプトでは、国際価格や多通貨を使用することはできません。お金の値はすべてお客様の通貨(請求通貨とも呼ばれます)を使用します。Shopify は国際価格や多通貨をサポートしていないので、請求通貨はストアの通貨と同じになります。
設定を使ってお金の値を指定する
スクリプトに金額をハードコーディングしないでください。代わりに設定を使用して金額をスクリプトに提供します。設定値は文字列として保存されるため、以下の作業が必要となります。
- 文字列をサブユニットの値に変換します。
- 変換されたサブユニットの値で
Money
オブジェクトを作成します。通貨はストアの通貨と同じである必要があります。
例
import {MoneyI64 as Money, Currencies} from '@shopify/scripts-sdk-as'
...
const monetaryValue = Money.fromAmount(<f64>safeParseInt(configuration.get('amount')!), Currencies.CAD)
...
Money
オブジェクトの操作順序
Money
オブジェクトは、乗算、除算、加算などの一般的な二項演算をオーバーライドします。これらの二項演算は、Money
オブジェクトと、float などの数値を用いて適用することもできます。この場合、演算の順序が重要になります。順番が重要なのは、二項演算が単なるMoney
クラスのメソッド呼び出しであり、パラメータとして数値を受け取るからです。その結果、Money * 4
は動作しますが、4 * Money
は動作しません。
ParseInt の代わりに SafeParseInt を使用する。
AssemblyScript では、文字列を数値に解析する際にいくつかの特殊なケースがあります。例えば、I32.parseInt("bad")
は 0 を返しますが、F64.parseInt("bad")
は NaN を返します。F64 は AssemblyScript の中で最も柔軟な数値型なので、ぜひ使ってみてください。
parseInt の複雑さを避けるには、safeParseInt関数を使います。safeParseInt
は、渡された文字列が数値でない場合に例外を投げます。safeParseInt
は Scripts library で定義されているので、すべてのスクリプトで使用することができます。
次のステップ
- Shopify がスクリプトの UI をレンダリングできるように、configuration schemaを作成します。
- スクリプト内の支払い方法名をLocalizeして、複数の言語や文化で顧客にサービスを提供している店舗が利用できるようにします。
- Shopify Scripts のpayment methods API reference documentationを読んでください。
Shopify アプリのご紹介
Shopify アプリである、「商品ページ発売予告アプリ | リテリア Coming Soon」は、商品ページを買えない状態のまま、発売日時の予告をすることができるアプリです。Shopify で Coming Soon 機能を実現することができます。
Shopify アプリである、「らくらく日本語フォント設定|リテリア Font Picker」は、ノーコードで日本語フォントを使用できるアプリです。日本語フォントを導入することでブランドを演出することができます。
Author And Source
この問題について(【Shopify.dev和訳】Apps/Checkout/Payment methods/Rename a method), 我々は、より多くの情報をここで見つけました https://zenn.dev/unreact/articles/apps-checkout-payment-methods-rename-jp著者帰属:元の著者の情報は、元のURLに含まれています。著作権は原作者に属する。
Collection and Share based on the CC protocol