LoginSignup
1
1

More than 1 year has passed since last update.

Shopify WebhookをAPI GatewayからLambdaで処理する

Posted at

概要

備忘録、ハマったポイントを重点的に書く。
ShopifyのWebHookを利用して、注文があった際に注文内容を受信する。
この記事では、Shopifyへ即レスポンス返す方法や、webhookの認証についてまとめる。

前提

Shopifyのプライベートアプリとして運用します。
公式にアプリとして使用する場合は、Shopify-> APIgateway->Lambdaではなく、Shopify-> EventBridge -> Lambdaという形を使用した方が良い為、下記の公式ブログ記事を見て下さい。

ShopifyアプリMechanicの開発者はEventBridgeでどのようにスケーリングしたのか

1. Lambdaでの処理

webHookを受信した時の処理されるLambda関数を作成します。

Shopify WebHookを3秒以内に返す

Shopify WebHookを3秒以内にレスポンスを返す必要があります。レスポンスが遅い場合や失敗した場合はリトライが合計3回行われ、何度も失敗するとwebhookが削除されます。

Lambdaは、呼び出しタイプをEVENTにし、非同期で実行します。これよりLambdaが実行が開始されるとスグに成功したというレスポンスが返ります。
呼び出しをEVENTにすると、処理でエラーが発生した際に2回リトライされる仕様になっています。
私の場合、これを防ぐために、try-catch節でエラーが出ないようにしています。

WebHookの完全性の認証

WebHookが不正なものでないか認証する機能がShopifyにはあります。
サンプルコードのverify_webhookをいうのがそれに当たります。
SHARED_SECRETはWebHookを設定する画面で確認することができます。(後述 -> Shopifyでの設定)

サンプルコード

import crypto from 'crypto'
const SHARED_SECRET = "" // ご自身の共有鍵をここに入力
export const handler=async(event:any, context:Context, callback:Callback)=>{
  try{
   await verify_webhook(event,event.headers['X-Shopify-Hmac-Sha256'])
   // 何からしらの処理
   return
 }catch(e){
    // SlackにPOSTするなど、エラーの確認処理
    return
  }
}

const verify_webhook = async(event:any, hmac_header:any)=>{
  const buffer = (Buffer.from(event.rawbody, 'utf8'))

  const generated = crypto
    .createHmac('sha256',SHARED_SECRET)
    .update(buffer)
    .digest('base64')
  if(generated === hmac_header) return true
  throw new Error('不正なWebHookを受信しました。');
}

デプロイしたら完了です。

2. API Gatewayの設定

  1. APIを作成し、ソースを作成します。本記事ではリソース名を「order-shopify-2」としています。
  2. WebHookを受信するためにPOSTメソッドを作成します。
  3. 先程作成したLambdaメソッドを指定します。

dbb1293b-b9c7-4351-93f3-2d2cb849a840.jpeg

APIGatewayからLambdaを非同期で呼び出す。

統合リクエスト -> HTTPヘッダーを下記に設定します。
名前:X-Amz-Invocation-Type
マッピング元:'Event'
スクリーンショット 2021-11-14 16.13.04.png

マッピングテンプレート

WebHookの完全性を認証するのに必要になります。逆に完全性を認証処理を加えないのであれば、設定しなくても大丈夫です。
統合リクエスト -> HTTPヘッダーを下記に設定します。
リクエスト本文のパススルー:テンプレートが定義されていない場合(推奨)
Content-Type: application/json
テンプレート

{
  "rawbody": "$util.escapeJavaScript($input.body)",
  "headers": {
    #foreach($header in $input.params().header.keySet())
      "$header": "$util.escapeJavaScript($input.params().header.get($header))" #if($foreach.hasNext),#end
    #end
  },
  "method": "$context.httpMethod",
  "params": {
    #foreach($param in $input.params().path.keySet())
      "$param": "$util.escapeJavaScript($input.params().path.get($param))" #if($foreach.hasNext),#end

    #end
  },
  "query": {
    #foreach($queryParam in $input.params().querystring.keySet())
    "$queryParam": "$util.escapeJavaScript($input.params().querystring.get($queryParam))" #if($foreach.hasNext),#end
    #end
  }
}

863e3e0f-763d-4128-a72e-2fb1a0bb957b.jpeg

保存をクリックし、デプロイして下さい。

POST先のURL

こんなフォーマットになると思います
https://{あなたのAPI}.execute-api.ap-northeast-1.amazonaws.com/Stage/order-shopify-2

3. Shopifyでの設定

WeHookの設定

Shopify管理画面から「設定」、「通知」と行き、1番下までスクロール
「WebHookを作成」をクリック。
スクリーンショット 2021-11-14 16.22.40.png

注文があった際に、WebHookを受け取りたいのであれば、イベントは「注文作成」にします。
その他は画像の通り。
URLは先程、APIGatewayで作成したURLを入力。

共有鍵

「すべてのWebhookは****************************************************でサインされるので、完全性を検証することができます。」書かれていると思うのでキーをコピーしてLambdaに入力して下さい。
忘れずに再度、Lambdaでデプロイします。

WebHookのテスト

bfeacbf8-19bf-4083-8811-970b30b619a7.jpeg

作成したWebHookを右へスクロールすると、「テスト通知を送信する」というボタンがあります。これをクリックするとWebHookをテスト出来ます。

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1