#0. はじめに
AppStoreに有料AddInを公開する場合に使える、購入済みユーザーかどうかを確認する仕組みをAutodeskが提供しています。それをEntitlement APIと呼びます。
実際にcodeを書くにあたっての注意点をまとめます。
#1. 大まかな流れ
権限確認は、次のフローで行います。
- 前提として、AppStoreに登録してApplication IDを取得しておく。
- CWebServicesManagerを使って、UserIdを取得する。
- Application IDとUserIdをAutodeskのServerに送る(REST)。
- 権限情報(json)が返ってくる。
#2. Application IDの取得
このIDは、AppStoreに登録すると発行されます。多くの場合は、このIDをAddInにハードコードすることでしょう。
「登録するAddInに『登録すると発行されるID』をハードコードするなら、デッドロック(鶏と卵)じゃないか!」と思われた方は、正しいです。
厳密には、登録完了しなくても、下書き状態でIDが発行されるので、それを組み込んで提出してください。
上図の赤枠で囲った部分が、Application IDです。ステータスが不完全でも発行されています。
#3. CWebServicesManagerを使う
#3.1 これは何をするもの?
Autodesk Accountのユーザー名は後から変更される可能性があるので、Autodesk内では一意のUserIdがAccountに対して割り当てられているようです。
AutodeskにServerに権限確認するには、このUserIdが必要なので、CWebServicesManagerを使って取得します。
#3.2 CWebServicesManagerはどこにあるの?
<Inventorのinstall場所>\Bin\AddinNETFramework.AdWebServicesWrapper.dll
が実体です。
#3.3 アセンブリが署名されていない!!
非常に残念なことに、AddinNETFramework.AdWebServicesWrapper.dll
は署名されていません。ですので、AddIn自体に署名するならば、参照することが出来ません。
(署名されたアセンブリから、署名がないアセンブリを参照できない)
こういった場合は、次の2つの解決方法があります。
- 自分で勝手に署名する。
- 実行時にDLLを指定して動的Loadする。
(3. 開発元に署名してもらう)
もちろん3.がお勧めなのですが、現実的ではないので「2つの解決方法」としました。
ここでは、2.の方法を取ります。
#3.4 アセンブリの動的Load
実行時にLoadすると、署名されてなくても警告もでないので、この方法で行きます。Load済みのDLLを再Load(重複Load)すると異常な挙動を取らないか心配でしたが、これは問題がありませんでした。
実際のcodeは以下の通りです。
/// <summary>
/// Autodesk User Idを取得します。
/// </summary>
/// <returns>取得に成功すれば、true。</returns>
private bool TryGetUserInformation()
{
try
{
var cwsmAsm = System.Reflection.Assembly.LoadFrom(InventorApplication.InstallPath + @"\Bin\AddinNETFramework.AdWebServicesWrapper.dll");
var typeInfo = cwsmAsm.GetType("Autodesk.WebServices.CWebServicesManager");
using dynamic mgr = Activator.CreateInstance(typeInfo);
bool isInitialized = mgr.Initialize();
if (isInitialized)
{
InventorApplication.Login();
string userId = "";
mgr.GetUserId(ref userId);
UserId = userId;
string userName = "";
mgr.GetLoginUserName(ref userName);
UserName = userName;
}
}
catch
{
return false;
}
if (!string.IsNullOrWhiteSpace(UserId))
{
return true;
}
else
{
return false;
}
}
注意点として、Autodesk AccountにLoginしていない状態では、GetUserId()
が空文字列を返すことです。ですので、本当に取得できたかどうかはUserIdの中身を確認する必要があります。
#4. Autodeskの権限Serverとの通信
この内容は、RESTfulやjsonで検索すると優秀な情報があるでしょうから、最終codeを示しておきます。
/// <summary>
/// Autodeskのサーバーに権限を問い合わせます。
/// </summary>
/// <returns></returns>
private async Task GetEntitlement()
{
try
{
// 通信設定、データの下準備
var parameters = new Dictionary<string, string>()
{
{ "userid", UserId },
{ "appid", AppId },
};
var handler = new HttpClientHandler()
{
Proxy = WebRequest.GetSystemWebProxy(), // システムのProxyを使う
};
using var client = new HttpClient(handler)
{
Timeout = TimeSpan.FromSeconds(timeOut), // TimeOut秒数
};
client.DefaultRequestHeaders.ConnectionClose = true; // KeepAliveしない
// 通信する
var response = await client.GetAsync($"https://apps.autodesk.com/webservices/checkentitlement?{await new FormUrlEncodedContent(parameters).ReadAsStringAsync()}");
var st = await response.Content.ReadAsStreamAsync();
if (response.StatusCode != HttpStatusCode.OK)
{
SetResult(Result.HttpStatusCodeIsNotOk, $"{response.ReasonPhrase} ({(int)response.StatusCode})");
return;
}
// 得られたjsonを解析する
var serializer = new DataContractJsonSerializer(typeof(ServerResponse));
var serverResponse = (ServerResponse)serializer.ReadObject(st);
// 結果の判定
if (serverResponse.IsValid != true)
{
SetResult(Result.EntitlementIsNotValid, serverResponse.IsValid.ToString());
}
else if (serverResponse.Message?.ToUpper() != "OK")
{
SetResult(Result.MessageIsNotOk, serverResponse.Message ?? "(null)");
}
else
{
SetResult(Result.Success);
}
}
catch (HttpRequestException ex)
{
SetResult(Result.HttpRequestException, ex.Message);
}
catch (Exception ex)
{
SetResult(Result.ExceptionThrown, ex.ToString());
}
finally
{
IsGetEntitlementRunning = false;
}
}
public class ServerResponse
{
public string? UserId;
public string? AppId;
public bool IsValid;
public string? Message;
}
SetResult()
は結果を保存するための自作関数です。排他制御が必要だったため、直接メンバ変数を変更せずに、関数経由で結果を保存しています。
その他にも名前しか出てこない変数がありますが、適宜調整してください。
#5. 参考資料
- Mod the Machine: Entitlement API changes in Inventor 2020
- Autodesk デベロッパー ネットワーク/App Store その中でも、特に、
- デスクトップ アプリ用の Entitlement API
#99. 親の記事に戻る
Autodesk Inventor API Hacking (概略)