はじめに
Partner event sourcesからShopify選択
手順を確認する
Shopify側でAmazon EventBridgeソース作成
- Shopify parnters画面 > アプリ選択 > Configuration選択
- Amazon EventBridgeを選択する
- AWS account IDを入力する
- リージョンを選択する
- ソース名:shopify-app-s3lab-app-2 <Event bus名と同じにする>
Partner event sourcesの関連付け
Event busの確認
前述のAssociate実行でソースと同名のbusが作成されたことを確認する。
ここで、イベントバスとは、イベントを受信するルーターであり、ゼロ個以上の送信先やターゲットに配信します。イベントバスは、イベントをさまざまなソースから多数のターゲットにルーティングするのに適しており、オプションでターゲットに配信する前にイベントを変換できます。
Shopifyアプリ側の設定
shopify.app.toml
Partner event source ARNを以下に設定する
※ Event busではなく、Event sourceのARNを設定する
[[webhooks.subscriptions]]
topics = ["orders/create"]
uri = "arn:aws:events:<AWS-REGION>::event-source/aws.partner/shopify.com/<APP-ID>/<EVENT-SOURCE-NAME>"
ルールの作成
- 名前:shopify-app-s3lab-app-2-rule-1
- Event bus: 前述のEvent bus
- Rule type: Rule with an event pattern
- Event source: Aws events or EventBridge partner events
- Creation method: use pattern form
- Event pattern
- Event source: EventBridge patners
- Partner: Shopify
- Event type: All events
- Target types: AWS service
- Target: Lambda function
- Function: shopify-webhook-test-1
Lambdaの例
- index.mjs
export const handler = async (event) => {
console.info("EVENT\n" + JSON.stringify(event, null, 2))
const response = {
statusCode: 200,
body: JSON.stringify('Hello from Lambda!'),
};
return response;
};
CloudwatchのLambdaのログを確認
- shopifyのユーザーへのショップ画面で、注文をいれる
- webhookのログがCloudwatchログに出力されることを確認する
WebhookがLambdaに渡すeventオブジェクト例
2024-08-03T18:40:20.105Z xxxxx INFO EVENT
{
"version": "0",
"id": "xxxxx",
"detail-type": "shopifyWebhook",
"source": "aws.partner/shopify.com/xxx/shopify-appname",
"account": "xxxxx",
"time": "2024-08-03T18:40:19Z",
"region": "ap-northeast-1",
"resources": [],
"detail": {
"payload": {
"id": 12345,
"admin_graphql_api_id": "gid://shopify/Order/12345",
"app_id": xxx,
"browser_ip": "ipaddress",
"buyer_accepts_marketing": true,
"cancel_reason": null,
"cancelled_at": null,
"cart_token": "xxxxx",
"checkout_id": 00000,
"checkout_token": "xxxxx",
"client_details": {
"accept_language": "en-JP",
"browser_height": null,
"browser_ip": "ipaddress",
"browser_width": null,
"session_hash": null,
"user_agent": "Mozilla/...."
},
"closed_at": null,
"company": null,
"confirmation_number": "xxxxx",
"confirmed": true,
"contact_email": "mail@domain",
"created_at": "2024-08-03T14:40:15-04:00",
"currency": "JPY",
"current_subtotal_price": "1025",
"current_subtotal_price_set": {
"shop_money": {
"amount": "1025",
"currency_code": "JPY"
},
"presentment_money": {
"amount": "1025",
"currency_code": "JPY"
}
},
"current_total_additional_fees_set": null,
"current_total_discounts": "0",
"current_total_discounts_set": {
"shop_money": {
"amount": "0",
"currency_code": "JPY"
},
"presentment_money": {
"amount": "0",
"currency_code": "JPY"
}
},
"current_total_duties_set": null,
"current_total_price": "2128",
"current_total_price_set": {
"shop_money": {
"amount": "2128",
"currency_code": "JPY"
},
"presentment_money": {
"amount": "2128",
"currency_code": "JPY"
}
},
"current_total_tax": "103",
"current_total_tax_set": {
"shop_money": {
"amount": "103",
"currency_code": "JPY"
},
"presentment_money": {
"amount": "103",
"currency_code": "JPY"
}
},
"customer_locale": "en-JP",
"device_id": null,
"discount_codes": [],
"email": "mail@domain",
"estimated_taxes": false,
"financial_status": "paid",
"fulfillment_status": null,
"landing_site": "/password",
"landing_site_ref": null,
"location_id": null,
"merchant_of_record_app_id": null,
"name": "#1021",
"note": null,
"note_attributes": [],
"number": 21,
"order_number": 1021,
"order_status_url": "https://shopname.myshopify.com/78901/orders/xxxxx/authenticate?key=yyyyy",
"original_total_additional_fees_set": null,
"original_total_duties_set": null,
"payment_gateway_names": [
"bogus"
],
"phone": null,
"po_number": null,
"presentment_currency": "JPY",
"processed_at": "2024-08-03T14:40:13-04:00",
"reference": "xxxxx",
"referring_site": "",
"source_identifier": "xxxxx",
"source_name": "web",
"source_url": null,
"subtotal_price": "1025",
"subtotal_price_set": {
"shop_money": {
"amount": "1025",
"currency_code": "JPY"
},
"presentment_money": {
"amount": "1025",
"currency_code": "JPY"
}
},
"tags": "",
"tax_exempt": false,
"tax_lines": [
{
"price": "103",
"rate": 0.1,
"title": "CT",
"price_set": {
"shop_money": {
"amount": "103",
"currency_code": "JPY"
},
"presentment_money": {
"amount": "103",
"currency_code": "JPY"
}
},
"channel_liable": false
}
],
"taxes_included": false,
"test": true,
"token": "xxxxx",
"total_discounts": "0",
"total_discounts_set": {
"shop_money": {
"amount": "0",
"currency_code": "JPY"
},
"presentment_money": {
"amount": "0",
"currency_code": "JPY"
}
},
"total_line_items_price": "1025",
"total_line_items_price_set": {
"shop_money": {
"amount": "1025",
"currency_code": "JPY"
},
"presentment_money": {
"amount": "1025",
"currency_code": "JPY"
}
},
"total_outstanding": "0",
"total_price": "2128",
"total_price_set": {
"shop_money": {
"amount": "2128",
"currency_code": "JPY"
},
"presentment_money": {
"amount": "2128",
"currency_code": "JPY"
}
},
"total_shipping_price_set": {
"shop_money": {
"amount": "1000",
"currency_code": "JPY"
},
"presentment_money": {
"amount": "1000",
"currency_code": "JPY"
}
},
"total_tax": "103",
"total_tax_set": {
"shop_money": {
"amount": "103",
"currency_code": "JPY"
},
"presentment_money": {
"amount": "103",
"currency_code": "JPY"
}
},
"total_tip_received": "0",
"total_weight": 0,
"updated_at": "2024-08-03T14:40:16-04:00",
"user_id": null,
"billing_address": {
"first_name": "Firstname",
"address1": "address1",
"phone": null,
"city": "city",
"zip": "zip",
"province": "provice",
"country": "Japan",
"last_name": "Lastname",
"address2": "address2",
"company": null,
"latitude": null,
"longitude": null,
"name": "Firstname Lastname",
"country_code": "JP",
"province_code": "JP-xx"
},
"customer": {
"id": 567890,
"email": "mail@domain",
"created_at": "2024-08-01T23:42:58-04:00",
"updated_at": "2024-08-03T14:40:15-04:00",
"first_name": "Firstname",
"last_name": "Lastname",
"state": "disabled",
"note": null,
"verified_email": true,
"multipass_identifier": null,
"tax_exempt": false,
"phone": null,
"email_marketing_consent": {
"state": "subscribed",
"opt_in_level": "single_opt_in",
"consent_updated_at": "2024-08-01T23:43:00-04:00"
},
"sms_marketing_consent": null,
"tags": "",
"currency": "JPY",
"tax_exemptions": [],
"admin_graphql_api_id": "gid://shopify/Customer/567890",
"default_address": {
"id": 00000,
"customer_id": 567890,
"first_name": "Firstname",
"last_name": "Lastname",
"company": null,
"address1": "address1",
"address2": "address2",
"city": "city",
"province": "provice",
"country": "Japan",
"zip": "zip",
"phone": null,
"name": "Firstname Lastname",
"province_code": "JP-xx",
"country_code": "JP",
"country_name": "Japan",
"default": true
}
},
"discount_applications": [],
"fulfillments": [],
"line_items": [
{
"id": 11111,
"admin_graphql_api_id": "gid://shopify/LineItem/11111",
"attributed_staffs": [],
"current_quantity": 1,
"fulfillable_quantity": 1,
"fulfillment_service": "manual",
"fulfillment_status": null,
"gift_card": false,
"grams": 0,
"name": "The Collection Snowboard: Oxygen",
"price": "1025",
"price_set": {
"shop_money": {
"amount": "1025",
"currency_code": "JPY"
},
"presentment_money": {
"amount": "1025",
"currency_code": "JPY"
}
},
"product_exists": true,
"product_id": 22222,
"properties": [],
"quantity": 1,
"requires_shipping": true,
"sku": "",
"taxable": true,
"title": "The Collection Snowboard: Oxygen",
"total_discount": "0",
"total_discount_set": {
"shop_money": {
"amount": "0",
"currency_code": "JPY"
},
"presentment_money": {
"amount": "0",
"currency_code": "JPY"
}
},
"variant_id": 33333,
"variant_inventory_management": "shopify",
"variant_title": null,
"vendor": "Hydrogen Vendor",
"tax_lines": [
{
"channel_liable": false,
"price": "103",
"price_set": {
"shop_money": {
"amount": "103",
"currency_code": "JPY"
},
"presentment_money": {
"amount": "103",
"currency_code": "JPY"
}
},
"rate": 0.1,
"title": "CT"
}
],
"duties": [],
"discount_allocations": []
}
],
"payment_terms": null,
"refunds": [],
"shipping_address": {
"first_name": "Firstname",
"address1": "address1",
"phone": null,
"city": "city",
"zip": "zip",
"province": "provice",
"country": "Japan",
"last_name": "Lastname",
"address2": "address2",
"company": null,
"latitude": 00.0000000,
"longitude": 000.0000000,
"name": "Firstname Lastname",
"country_code": "JP",
"province_code": "JP-xx"
},
"shipping_lines": [
{
"id": 44444,
"carrier_identifier": "xxxxx",
"code": "通常配送",
"discounted_price": "1000",
"discounted_price_set": {
"shop_money": {
"amount": "1000",
"currency_code": "JPY"
},
"presentment_money": {
"amount": "1000",
"currency_code": "JPY"
}
},
"is_removed": false,
"phone": null,
"price": "1000",
"price_set": {
"shop_money": {
"amount": "1000",
"currency_code": "JPY"
},
"presentment_money": {
"amount": "1000",
"currency_code": "JPY"
}
},
"requested_fulfillment_service_id": null,
"source": "shopify",
"title": "通常配送",
"tax_lines": [],
"discount_allocations": []
}
]
},
"metadata": {
"Content-Type": "application/json",
"X-Shopify-Topic": "orders/create",
"X-Shopify-Shop-Domain": "shopname.myshopify.com",
"X-Shopify-Order-Id": "12345",
"X-Shopify-Test": "true",
"X-Shopify-Hmac-SHA256": "xxxxx",
"X-Shopify-Webhook-Id": "xxxxx",
"X-Shopify-API-Version": "2024-07",
"X-Shopify-Event-Id": "xxxxx",
"X-Shopify-Triggered-At": "2024-08-03T18:40:16.807368200Z"
}
}
}
主なデータ
- detail.payload.idが注文ID
- detail.payload.nameが注文表示ID(例 “#1021″)