APIの設定
このセクションでは、APIとの統合を成功させるための重要なステップについて説明します。Webhooks経由でプッシュイベントを受信したい場合も、エンドポイントからデータをプルしたい場合も、弊社にお任せください。
- プッシュAPI: TAAPおよびWhite Label Travel Platformパートナーに最適なプッシュイベントは、real-timeの更新をお客様のシステムに直接配信します。サブスクリプションの設定、認証の管理、再試行の処理方法について説明します。
- プルAPI: White Label Travel Platformパートナー向けに設計されており、必要なときにデータをリクエストできます。安全なアクセスのためのtoken-based認証の設定について説明します。
以下のガイダンスに従って、スムーズな統合と安全なデータ転送を実現してください。
Push-based配達
TAAPまたはWhite Label Travel Platformのパートナーで、旅程データにご興味のある方は、こちらをご覧ください。プッシュイベントはWebhook経由で配信され、お客様が指定したURLにHTTP POST メッセージとして送信されます。
イベントの受信を開始するには、イベント タイプを購読し、エクスペディアを送信者として認証する必要があります。
購読とイベント
弊社のSubscriptions APIを使用すると、push-based配信サービスを通じて受信したいイベントを作成および管理できます。現在、旅程更新イベントの購読を作成および管理することができます。
APIクライアントIDとシークレットが必要です。
サブスクリプションAPIへのアクセス
すべてのAPIリクエストに、あなたのビジネスに固有のアクセストークンを含めます。HTTPベーシック認証の仕組みを使って、API認証情報を使ってこのトークンをリクエストします。
- トークンのエンドポイントに、APIクライアントIDとsecretをBase64エンコードした文字列を含むAuthorizationヘッダを追加します
https://analytics.ean.com/*/v1/oauth/token。URLの*を、パートナーシップに応じて、templateまたはtaapに置き換えてください。 - トークン・エンドポイントは、以降のAPIリクエストで使用するアクセストークンを返します。詳細については、Subscriptions API詳細 を参照してください。
- 今後のAPIエンドポイントリクエストにアクセストークンの値を含めます。
初期認証ヘッダの例
Authorization: Basic base64.b64encode({client-id}:{client-secret})トークン・リクエストの例
securitySchemes:
oauth:
type: oauth2
flows:
clientCredentials:
tokenUrl: https://analytics.ean.com/taap/v1/oauth/token認証済み認可ヘッダの例
Authorization: Bearer {access-token}サブスクリプションの管理
Subscription APIで認証されると、既存のサブスクリプションのリストを作成したり、新しいサブスクリプションを作成したり、適用されなくなったサブスクリプションを削除したりするなど、サブスクリプションを管理できます。
サブスクリプションの作成
サブスクリプションを作成する際に指定する必要があります:
- イベントを受信するエンドポイントURL。
- サブスクライブするイベントのタイプ。パートナーシップのインジケータも含みます:
taap.itinerary.changeまたはtemplate.itinerary.change。
注意:複数のサブスクリプションを作成できますが、サブスクリプションが重複すると、イベントの配信が重複します。これを避けるには、新しいサブスクリプションを作成する前に、既存のサブスクリプションをリストアップしてください。
サブスクリプションが作成されると、イベント配信に含まれるHMAC(hash-basedメッセージ認証コード)を検証するための一意のシークレットキーを受け取ります。
サブスクリプションを一覧表示または削除するには、それぞれHTTP GET /subscriptions またはHTTP DELETE /subscriptions/{subscription_id} エンドポイントを使用します。有効なトークンを使用する必要があります。
詳細については、Subscriptions API詳細 を参照してください。
エクスペディアを送信者として認証
各イベントの認証ヘッダーには、hash-basedメッセージ認証コード (HMAC) 署名が含まれています。サブスクリプションを作成するときに提供する共有秘密を使用して、安全で信頼できるデータ伝送を保証するために、この署名を検証する必要があります。
認証ヘッダーの例
"authorization": "MAC ts='1731524372777',nonce='f88e57ed-aaf5-4edd-8e58-9105817fb4cb',bodyhash='8YLHy71r5dx3PQjdcOkRuVYXaakjhbJSROEnlreQEIA=',mac='bDxvx41INtDxtkbZwTmAMADZGiFl6/xyXC1lE5ixPuY='"プッシュ・イベントを受信するエンドポイントに以下のロジックを追加して、HMAC署名を検証します。これにより、お客様が受信するイベントがエクスペディアからのものであり、送信中に改ざんされていないことが保証されます。
注: この例では、Javaでこの検証ロジックを実装する方法を示します。ロジックはお好みのプログラミング言語に合わせることができますが、核となるステップは変わりません。
ステップ1:認可ヘッダーの解析
文字列を基本コンポーネントに解析することで、認可ヘッダーから必要な情報を抽出します。
コードサンプル
/**
* Parse the signature string into components
* @param signature The signature string in format "MAC ts='...', nonce='...', bodyhash='...', mac='...'"
* @return Map of signature components
*/
private Map<String, String> parseSignature(String signature) {
// Pattern for key='value' or key="value"
Pattern pattern = Pattern.compile("([a-zA-Z]+)=['"]([^'"]*)['"]");
Matcher matcher = pattern.matcher(signature);
Map<String, String> components = new HashMap<>();
while (matcher.find()) {
components.put(matcher.group(1), matcher.group(2));
}
return components;
}ステップ2:必要なコンポーネントの検証
必要なコンポーネントts(タイムスタンプ)、nonce、bodyhash、mac が存在し、正しくフォーマットされていることを確認します。
コードサンプル
private Boolean validateSignatureComponents(Map<String, String> components) {
if (components.isEmpty()) {
return false;
}
return components.containsKey("ts") &&
components.containsKey("nonce") &&
components.containsKey("bodyhash") &&
components.containsKey("mac");
}ステップ3:ボディハッシュの生成と検証
HMAC SHA-256とsharedSecretKey を使ってボディハッシュを生成し、リクエストボディのハッシュと一致することを確認することで、データの完全性を保証します。
コードサンプル
/**
* Compute body hash (HMAC-SHA256 of the request body)
* @param body The raw request body
* @return Base64 encoded body hash
*/
private String computeBodyHash(String body) {
try {
Mac mac = Mac.getInstance(HMAC_SHA256);
SecretKeySpec secretKeySpec = new SecretKeySpec(
sharedSecretKey.getBytes(StandardCharsets.UTF_8),
HMAC_SHA256);
mac.init(secretKeySpec);
byte[] hmacBytes = mac.doFinal(body.getBytes(StandardCharsets.UTF_8));
return bytesToBase64(hmacBytes);
} catch (Exception e) {
throw new RuntimeException("Failed to compute body hash", e);
}
}
private Boolean validateBodyHash(String requestBody, String bodyHashFromHeader) {
String computedBodyHash = computeBodyHash(requestBody != null ? requestBody : "");
return computedBodyHash.equals(components.get('bodyhash'));
}ステップ4:HMAC署名の生成と検証
タイムスタンプ、nonce、HTTPメソッド、リクエスト・パス、ホスト・ドメイン、ポート、生成されたボディ・ハッシュを含むHMAC署名を生成し、真正性を保証するためにヘッダーの受信値と照合して検証します。
コードサンプル
/**
* Generate HMAC signature using the provided components
* @param components Parsed signature components
* @param computedBodyHash Computed body hash
* @param method HTTP method (e.g., "POST", "GET")
* @param path Request path (e.g., "/api/webhooks/events")
* @param host Host name (e.g., "api.example.com")
* @param port Port number
* @return Base64 encoded HMAC signature
*/
private String generateHmacSignature(Map<String, String> components, String computedBodyHash,
String method, String path, String host, int port) {
try {
// Normalize port (use 443 for standard HTTPS ports)
String portString = (port == 80 || port == 443) ? DEFAULT_PORT : String.valueOf(port);
// Build signature string with newline-delimited components
String signatureString = String.format("%s\n%s\n%s\n%s\n%s\n%s\n%s\n",
components.get("ts"),
components.get("nonce"),
method.toUpperCase(),
path,
host,
portString,
computedBodyHash);
return calculateHMAC(signatureString);
} catch (Exception e) {
throw new RuntimeException("Failed to generate HMAC signature", e);
}
}
/**
* Calculate HMAC-SHA256
* @param data Data to hash
* @return Base64 encoded HMAC
*/
private String calculateHMAC(String data) {
try {
Mac mac = Mac.getInstance(HMAC_SHA256);
SecretKeySpec secretKeySpec = new SecretKeySpec(
sharedSecretKey.getBytes(StandardCharsets.UTF_8),
HMAC_SHA256);
mac.init(secretKeySpec);
byte[] hmacBytes = mac.doFinal(data.getBytes(StandardCharsets.UTF_8));
return bytesToBase64(hmacBytes);
} catch (Exception e) {
throw new RuntimeException("Failed to calculate HMAC", e);
}
}
private Boolean validateHmacSignature(Map<String, String> components, String computedBodyHash,
String method, String path, String host, int port) {
String generatedHmacSignature = generateHmacSignature(components, computedBodyHash, method, path, host, port);
return generatedHmacSignature.equals(components.get("mac"));
}イベント失敗のリトライ
イベントが失敗した場合、システムは7日間にわたり指数バックオフパターンを使用して再試行します。失敗した場合は再試行します:
- 200以外のHTTPステータスコード
- タイムアウト
- エンドポイントからの例外
購読APIの詳細
Subscriptions APIの詳細については、OpenAPI仕様をダウンロードしてください。
Pull-based配達
White Label Travel Platformサイトをお持ちの場合、使用しているAPIに応じて、旅程やロイヤルティEarnデータのpull-based配信を実装できます。
ロイヤルティのEarnとItinerariesエンドポイントにアクセスするには、APIクライアントIDとシークレットが必要です。すべてのAPIリクエストに、あなたのビジネスに固有のアクセストークンを含めます。HTTPベーシック認証の仕組みを使って、API認証情報を使ってこのトークンをリクエストします。
- トークンのエンドポイント
https://analytics.ean.com/template/v1/oauth/tokenに、APIクライアントIDとシークレットをBase64エンコードした文字列を含むAuthorizationヘッダーを追加します。 - トークン・エンドポイントは、以降のAPIリクエストで使用するアクセストークンを返します。詳細については、OpenAPIの仕様を参照してください。
- 今後のAPIエンドポイントリクエストにアクセストークンの値を含めます。
初期認証ヘッダの例
Authorization: Basic base64.b64encode({client-id}:{client-secret})トークン・リクエストの例
securitySchemes:
oauth:
type: oauth2
flows:
clientCredentials:
tokenUrl: https://analytics.ean.com/template/v1/oauth/token認証済み認可ヘッダの例
Authorization: Bearer {token}トークンを受け取ったら、ロイヤルティEarnまたはItinerariesエンドポイントに対してリクエストを開始できます。
サービスをリクエストする際には、APIのバージョンを指定する必要があります。ダウンロード可能なOpenAPI仕様ファイルの一番上にあるservers.url。これは常に、あなたがテストしているAPIサービスのバージョン番号と一致します。
URLはこの構造に従ってください:
https://analytics.ean.com/[product]/[API version]/[path]
パスを置き換えることでエンドポイントを切り替えることができますが、OpenAPI仕様で規定されているプロトコル、ドメイン指定、製品、APIバージョン番号は必ず保持してください。
エンドポイントの例
https://analytics.ean.com/template/v1/loyalty/earn/last_update
https://analytics.ean.com/template/v1/itinerariesデータスコープとAPIコンフィギュレーションを調べるには、APIデリバリーのスキーマを参照してください:
旅程API配信
ロイヤルティアーンAPI配信