概要
従来の饿了么(Ele.me)OpenAPI では、店舗をバインドする際にメールによる申請が必要であり、処理に時間を要する課題がありました。しかし、OpenAPI 2.0 のリリースにより、OAuth 2.0 標準プロトコルを採用した自助式の認証フローが可能になりました。これにより、開発者と店舗側だけで完結する迅速な連携が実現します。本稿では、.NET 環境において饿了么 OpenAPI 2.0 を統合し、注文データを同期する具体的な実装手順について解説します。
開発環境のセットアップ
まず、饿了么開放平台 にアクセスし、開発者として登録を行います。登録後、開発者資格認証を行い、必要な情報を提出して審査を待ちます。審査通過後、開発者センターにてアプリケーションを作成します。
アプリケーション作成後は、サンドボックス環境の設定を行います。主な設定項目は以下の通りです。
- コールバック URL: 店舗授权後のリダイレクト先
- プッシュ URL: 新注文やステータス変更などの通知受信エンドポイント
- 通知タイプ: 受信が必要なメッセージ種類の選択
これらの設定が完了すれば、コード実装に移ることができます。
OAuth 2.0 による店舗認証の実装
饿了么 OpenAPI 2.0 では、国際標準の OAuth 2.0 プロトコルを用いて店舗の認証と授权を行います。.NET 向けの公式 SDK は提供されていないため、HTTP リクエストを直接構築して実装する必要があります。
認証フローの核心となるクラス実装例を以下に示します。ここでは、認証 URL の生成とアクセストークンの取得処理を実装しています。
public class ElemeOAuthService
{
private readonly HttpRequest _request;
private readonly ConfigSettings _config;
public ElemeOAuthService(HttpRequest request, ConfigSettings config)
{
_request = request;
_config = config;
}
/// <summary>
/// 認証用 URL の構築
/// </summary>
public string ConstructAuthEndpoint(int merchantId)
{
var redirectUri = HttpUtility.UrlEncode(_config.AuthCallbackUrl);
var queryParams = $"response_type=code&client_id={_config.AppKey}&redirect_uri={redirectUri}&state={merchantId}&scope=all";
return $"{_config.AuthBaseUrl}?{queryParams}";
}
/// <summary>
/// アクセストークンの取得
/// </summary>
public AccessTokenResponse FetchToken()
{
var code = _request.Params["code"];
var state = _request.Params["state"];
var authHeader = Convert.ToBase64String(Encoding.UTF8.GetBytes($"{_config.AppKey}:{_config.AppSecret}"));
var httpClient = new HttpClient();
httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", authHeader);
var content = new FormUrlEncodedContent(new[]
{
new KeyValuePair<string, string>("grant_type", "authorization_code"),
new KeyValuePair<string, string>("code", code),
new KeyValuePair<string, string>("redirect_uri", _config.AuthCallbackUrl),
new KeyValuePair<string, string>("client_id", _config.AppKey)
});
var response = httpClient.PostAsync(_config.TokenUrl, content).Result;
var jsonString = response.Content.ReadAsStringAsync().Result;
var tokenInfo = JsonConvert.DeserializeObject<AccessTokenResponse>(jsonString);
if (tokenInfo != null)
{
tokenInfo.MerchantId = Convert.ToInt32(state);
}
return tokenInfo;
}
}
実装時の注意点として、トークン取得リクエストの HTTP ヘッダーには、Authorization フィールドが必要です。この値は、app_key と app_secret をコロンで連結した文字列を Base64 エンコードしたもので構成されます(例:Basic base64(key:secret))。
署名アルゴリズムの実装
API リクエストには署名が必要であり、これが実装において最も注意を要する部分です。署名生成のロジックは独自仕様が含まれているため、ドキュメント仕様に厳密に従う必要があります。
主なポイントは以下の通りです。
- 署名対象のパラメータは、JSON オブジェクト内の
metasおよびparams属性のみを含みます。 - パラメータの結合は
key=json_encode(value)形式で行います。データ型(数値と文字列)によって JSON エンコード後の表現が異なるため、型変換に注意が必要です。 - 結合後の文字列はソートされ、
action、token、secretと連結された後、MD5 ハッシュ化されます。
署名生成メソッドの実装例は以下の通りです。
public string ComputeSignatureHash(string action, string accessToken)
{
var sortedParams = new StringBuilder();
var paramList = _signatureParams.Keys.OrderBy(k => k).ToList();
foreach (var key in paramList)
{
var value = JsonConvert.SerializeObject(_signatureParams[key]);
sortedParams.Append($"{key}={value}");
}
var rawString = $"{action}{accessToken}{sortedParams.ToString()}{_config.AppSecret}";
var hashBytes = MD5.Create().ComputeHash(Encoding.UTF8.GetBytes(rawString));
var sb = new StringBuilder();
foreach (var b in hashBytes)
{
sb.Append(b.ToString("X2"));
}
return sb.ToString().ToUpper();
}
API リクエストを送信する際は、Content-Type を application/json;charset=utf-8 に設定し、id パラメータには GUID を生成して使用します。POST データはハッシュテーブル等に保存されたパラメータを JSON シリアライズして送信します。
注文通知の受信と処理
サンドボックス環境で設定したプッシュ URL に対して、饿了么 サーバーから注文ステータスの変更通知が HTTP POST で送信されます。通知本体はストリーム形式で送信されるため、リクエストストリームから読み取る必要があります。
テスト環境では、商品価格が 0.1 元の場合、刷单(注文の水増し)と判定され自動的にキャンセルされる仕様があります。正常にテストを行うためには、商品価格を 1 元以上に設定する必要があります。
通知受信ハンドラーの実装例を示します。
public void HandlePushNotification()
{
var stream = HttpContext.Current.Request.InputStream;
if (stream == null || stream.Length <= 10) return;
string jsonPayload;
using (var reader = new StreamReader(stream))
{
jsonPayload = reader.ReadToEnd();
}
var notification = JsonConvert.DeserializeObject<PushNotification>(jsonPayload);
switch (notification.Type)
{
case 12: // 新注文
ProcessNewOrder(notification);
break;
case 14:
case 15:
case 17:
case 23:
case 25:
case 35: // 注文キャンセル系
ProcessCancelOrder(notification);
break;
default:
break;
}
}
private void ProcessCancelOrder(PushNotification notice)
{
var orderData = JsonConvert.DeserializeObject<OrderDetail>(notice.Message);
var systemOrderId = "e" + orderData.OrderId;
// システム内の注文ステータスを更新
var sql = $"UPDATE Custorder SET OrderStatus=5 WHERE OrderID='{systemOrderId}'";
DatabaseUtility.Execute(sql);
}
本番環境への移行
サンドボックス環境での動作確認が完了したら、本番環境用のパラメータを設定し、プラットフォーム側で審査申請を行います。承認されれば、実際の注文データがシステムに同期されるようになります。
同期された注文は、既存の配送スケジューリングシステムと連携させることで、配送員への自動割り当てや配車最適化など、業務効率化のための次のステップへ進むことが可能です。