次の方法で共有


サーバー例外のテスト

概要

PlayReady テスト サーバーには、さまざまなサーバー例外をプログラムでトリガーするための特別な機能が含まれています。 この機能を使用すると、クライアント開発者は、運用環境でのライセンス取得中に発生する可能性があるさまざまなエラー条件に対して、デバイスとアプリケーションがどのように応答するかをテストできます。

サーバー例外テスト

クライアント開発者は、これらのサーバー例外コマンドを使用して、実装でのエラー処理を検証できます。 これには、デバイスの失効、内部サーバー エラー、プロトコルの不一致、ドメイン関連の例外などのテスト シナリオが含まれます。

トランザクションの例

サーバー例外のしくみの例を次に示します。

要求 URL:

http://test.playready.microsoft.com/service/rightsmanager.asmx?cfg=(errorcode:0x8004c065)

サーバーの応答:

HTTP/1.1 500 Internal Server Error
Cache-Control: private
Content-Length: 764
Content-Type: text/xml; charset=utf-8

<?xml version="1.0" encoding="utf-8" ?>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" 
               xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
               xmlns:xsd="http://www.w3.org/2001/XMLSchema">
    <soap:Body>
        <soap:Fault>
            <faultcode>soap:Server</faultcode>
            <faultstring>
                System.Web.Services.Protocols.SoapException: Device Certificate Revoked.
                at Microsoft.Media.Drm.RightsManager.ConvertRmServerException(RMServerException ex)
                at Microsoft.Media.Drm.RightsManager.AcquireLicense(XmlDocument challenge)
            </faultstring>
            <faultactor>http://prtsprod-rightsmanager.azurewebsites.net/rightsmanager.asmx?cfg=(errorcode:0x8004c065)</faultactor>
            <detail>
                <Exception>
                    <StatusCode>0x8004c065</StatusCode>
                </Exception>
            </detail>
        </soap:Fault>
    </soap:Body>
</soap:Envelope>

例外パラメーター

ジェネリック例外パラメーター

パラメーター 説明 例の URL
errorcode:XXXXXXXX 特定の例外で応答するようにサーバーに要求する http://test.playready.microsoft.com/service/rightsmanager.asmx?cfg=(errorcode:0xXXXXXXXX)

デバイスとクライアントの例外

失効したデバイス証明書

パラメーター 例外 説明
errorcode:8004C065 DRM_E_DEVCERT_REVOKED サーバーがライセンスを失効したクライアント デバイスに配信できない

例:

http://test.playready.microsoft.com/service/rightsmanager.asmx?cfg=(errorcode:0x8004c065)

使用法: クライアントがデバイス失効シナリオを処理する方法をテストします。

サーバー内部例外

内部サーバー エラー

パラメーター 例外 説明
errorcode:8004C600 DRM_E_SERVER_INTERNAL_ERROR サーバーが内部サーバー例外をスローする

例:

http://test.playready.microsoft.com/service/rightsmanager.asmx?cfg=(errorcode:0x8004c600)

使用法: サーバー側の内部エラーに対するクライアントの回復性をテストします。

無効なメッセージ

パラメーター 例外 説明
errorcode:8004C601 DRM_E_SERVER_INVALID_MESSAGE サーバーに送信された要求が無効でした

例:

http://test.playready.microsoft.com/service/rightsmanager.asmx?cfg=(errorcode:0x8004c601)

使用法: 形式が正しくない要求応答のクライアント処理をテストします。

プロトコル バージョンの不一致

パラメーター 例外 説明
errorcode:8004C60B DRM_E_SERVER_PROTOCOL_VERSION_MISMATCH 要求で指定されたプロトコル バージョンがサーバーでサポートされていませんでした

例:

http://test.playready.microsoft.com/service/rightsmanager.asmx?cfg=(errorcode:0x8004c60b)

使用法: サポートされていないプロトコル バージョンでクライアントの動作をテストします。

サービス固有の例外

パラメーター 例外 説明
errorcode:8004C604 DRM_E_SERVER_SERVICE_SPECIFIC サーバーがサービス固有の例外をスローする (通常はライセンス ハンドラーから)

例:

http://test.playready.microsoft.com/service/rightsmanager.asmx?cfg=(errorcode:0x8004c604)

使用法: サービス固有のエラーのクライアント処理をテストします。

プロトコルとリダイレクトの例外

プロトコル リダイレクト

パラメーター 例外 説明
errorcode:8004C60D DRM_E_SERVER_PROTOCOL_REDIRECT プロトコルにリダイレクトがある

例:

http://test.playready.microsoft.com/service/rightsmanager.asmx?cfg=(errorcode:0x8004c60d)

使用法: サーバー リダイレクトのクライアント処理をテストします。

ドメインが必要

パラメーター 例外 説明
errorcode:8004C605 DRM_E_SERVER_DOMAIN_REQUIRED サーバーはクライアントから標準ライセンス要求を受け取り、ドメイン バインド ライセンスを受け取るためにクライアントがドメインに参加する必要がある

例:

http://test.playready.microsoft.com/service/rightsmanager.asmx?cfg=(errorcode:0x8004c605)

使用法: ドメイン参加シナリオとクライアント ドメイン認識をテストします。

ドメインの更新

パラメーター 例外 説明
errorcode:8004C606 DRM_E_SERVER_RENEW_DOMAIN サーバーは、古いドメイン バージョンを含むドメイン証明書を使用してクライアントから要求を受信しました。 クライアントがドメイン証明書を更新する必要があります

例:

http://test.playready.microsoft.com/service/rightsmanager.asmx?cfg=(errorcode:0x8004c606)

使用法: ドメイン証明書の更新プロセスをテストします。

デバイスの制限に達しました

パラメーター 例外 説明
errorcode:8004C602 DRM_E_SERVER_DEVICE_LIMIT_REACHED サーバーはクライアントをドメイン アカウントに追加する予定でしたが、アカウントは既にデバイスの数の制限に達しています

例:

http://test.playready.microsoft.com/service/rightsmanager.asmx?cfg=(errorcode:0x8004c602)

使用法: ドメイン デバイス制限のクライアント処理をテストします。

ドメイン メンバーではない

パラメーター 例外 説明
errorcode:8004C60A DRM_E_SERVER_NOT_A_MEMBER サーバーはクライアントから有効なドメイン バインド ライセンス要求を受け取りましたが、クライアントは以前にサービスによってドメインから削除されています

例:

http://test.playready.microsoft.com/service/rightsmanager.asmx?cfg=(errorcode:0x8004c60a)

使用法: ドメインから削除された場合のクライアント動作をテストします。

不明なアカウント ID

パラメーター 例外 説明
errorcode:8004C60C DRM_E_SERVER_UNKNOWN_ACCOUNTID サーバーは、特定のアカウント ID に対するドメイン バインド ライセンス要求をクライアントから受信しましたが、この ID はサービスに対して不明です

例:

http://test.playready.microsoft.com/service/rightsmanager.asmx?cfg=(errorcode:0x8004c60c)

使用法: 不明なドメイン アカウント シナリオのクライアント処理をテストします。

テスト シナリオ

基本的な例外テスト

async function testServerExceptions() {
    const exceptions = [
        { name: 'Device Revoked', code: '0x8004c065' },
        { name: 'Internal Error', code: '0x8004c600' },
        { name: 'Invalid Message', code: '0x8004c601' },
        { name: 'Protocol Mismatch', code: '0x8004c60b' }
    ];
    
    const results = [];
    for (const exception of exceptions) {
        try {
            const url = `http://test.playready.microsoft.com/service/rightsmanager.asmx?cfg=(errorcode:${exception.code})`;
            const response = await testLicenseAcquisition(url);
            results.push({
                test: exception.name,
                result: 'UNEXPECTED_SUCCESS',
                error: 'Expected exception but got success'
            });
        } catch (error) {
            results.push({
                test: exception.name,
                result: 'EXPECTED_EXCEPTION',
                errorCode: error.statusCode,
                message: error.message
            });
        }
    }
    
    return results;
}

ドメイン例外テスト

async function testDomainExceptions() {
    const domainExceptions = [
        { name: 'Domain Required', code: '0x8004c605' },
        { name: 'Renew Domain', code: '0x8004c606' },
        { name: 'Device Limit Reached', code: '0x8004c602' },
        { name: 'Not a Member', code: '0x8004c60a' },
        { name: 'Unknown Account', code: '0x8004c60c' }
    ];
    
    const results = [];
    for (const exception of domainExceptions) {
        try {
            const url = `http://test.playready.microsoft.com/service/rightsmanager.asmx?cfg=(errorcode:${exception.code})`;
            await testLicenseAcquisition(url);
            results.push({
                test: exception.name,
                result: 'FAIL',
                reason: 'Expected domain exception but got success'
            });
        } catch (error) {
            results.push({
                test: exception.name,
                result: 'PASS',
                exceptionType: exception.name,
                statusCode: error.statusCode
            });
        }
    }
    
    return results;
}

クライアント堅牢性テスト

async function testClientRobustness() {
    // Test how client handles rapid exception scenarios
    const rapidTests = [
        '0x8004c065', // Device revoked
        '0x8004c600', // Internal error  
        '0x8004c601', // Invalid message
        '0x8004c60b'  // Protocol mismatch
    ];
    
    const startTime = Date.now();
    const promises = rapidTests.map(code => {
        const url = `http://test.playready.microsoft.com/service/rightsmanager.asmx?cfg=(errorcode:${code})`;
        return testLicenseAcquisitionWithTimeout(url, 5000);
    });
    
    const results = await Promise.allSettled(promises);
    const endTime = Date.now();
    
    return {
        totalTime: endTime - startTime,
        results: results.map((result, index) => ({
            errorCode: rapidTests[index],
            status: result.status,
            handled: result.status === 'rejected' // We expect rejections
        }))
    };
}

クライアント実装ガイドライン

例外処理のベスト プラクティス

class PlayReadyExceptionHandler {
    handleLicenseAcquisitionError(error) {
        switch (error.statusCode) {
            case 0x8004C065: // Device revoked
                return this.handleDeviceRevoked();
                
            case 0x8004C600: // Internal server error
                return this.handleServerError(error);
                
            case 0x8004C601: // Invalid message
                return this.handleInvalidMessage(error);
                
            case 0x8004C60B: // Protocol version mismatch
                return this.handleProtocolMismatch(error);
                
            case 0x8004C605: // Domain required
                return this.handleDomainRequired(error);
                
            case 0x8004C606: // Renew domain
                return this.handleDomainRenewal(error);
                
            default:
                return this.handleUnknownError(error);
        }
    }
    
    handleDeviceRevoked() {
        // Device is revoked - cannot proceed
        throw new Error('Device has been revoked and cannot play protected content');
    }
    
    handleServerError(error) {
        // Retry with exponential backoff
        return this.retryWithBackoff(error.originalRequest);
    }
    
    handleDomainRequired(error) {
        // Initiate domain joining process
        return this.joinDomain(error.domainServiceUrl);
    }
    
    handleDomainRenewal(error) {
        // Renew domain certificate
        return this.renewDomainCertificate(error.domainServiceUrl);
    }
}

C# 例外処理

public class PlayReadyExceptionHandler
{
    public async Task<bool> HandleLicenseException(Exception ex)
    {
        if (ex is SoapException soapEx)
        {
            var statusCode = ExtractStatusCode(soapEx);
            
            switch (statusCode)
            {
                case 0x8004C065: // Device revoked
                    return HandleDeviceRevoked();
                    
                case 0x8004C600: // Internal server error
                    return await HandleServerError(soapEx);
                    
                case 0x8004C605: // Domain required
                    return await HandleDomainRequired(soapEx);
                    
                case 0x8004C606: // Renew domain
                    return await HandleDomainRenewal(soapEx);
                    
                default:
                    return HandleUnknownError(soapEx);
            }
        }
        
        return false;
    }
    
    private uint ExtractStatusCode(SoapException soapEx)
    {
        // Extract status code from SOAP fault detail
        var detail = soapEx.Detail;
        var statusNode = detail?.SelectSingleNode("//StatusCode");
        
        if (statusNode != null && uint.TryParse(statusNode.InnerText.Replace("0x", ""), 
            NumberStyles.HexNumber, null, out uint statusCode))
        {
            return statusCode;
        }
        
        return 0;
    }
}

検証とテスト

予期される動作

サーバー例外を使用してテストする場合は、クライアントが次の点を検証します。

  1. 例外を正しく解析する - エラー コードとメッセージを正しく抽出する
  2. 正常に処理 する - 例外でクラッシュまたはハングしない
  3. ユーザー フィードバックを提供 する - ユーザーに適切なエラー メッセージを表示する
  4. 再試行ロジックを実装 する - バックオフを使用して適切なエラーを再試行する
  5. ドメイン操作のサポート - ドメイン関連の例外を正しく処理する

テスト検証チェックリスト

  • [ ] クライアントが例外の種類を正しく識別する
  • [ ] 適切なユーザー メッセージが表示される
  • [ ] 任意の例外の種類でクライアントがクラッシュしない
  • [ ] 再試行ロジックは回復可能なエラーに対して機能します
  • [ ] ドメイン参加/更新プロセスが正しくトリガーされる
  • [ ] デバイスの失効は安全に処理されます
  • [ ] エラー条件下でもパフォーマンスは引き続き許容されます

ベスト プラクティス

クライアント開発

  1. 包括的なエラー処理 - 文書化されたすべての例外の種類を処理する
  2. ユーザー エクスペリエンス - 明確で実用的なエラー メッセージを提供する
  3. 再試行戦略 - 一時的なエラーに対して適切な再試行ロジックを実装する
  4. セキュリティ - デバイスの失効がコンテンツ アクセスを防ぐ
  5. テスト - 開発中にすべての例外シナリオをテストする

エラーの回復

  1. 正常な低下 - 可能な場合は操作を続行する
  2. 明確なコミュニケーション - 問題と解決策をユーザーに通知する
  3. 自動回復 - 必要に応じて自動解決を試みます
  4. フォールバック オプション - 代替コンテンツまたはサービスを提供する
  5. ログ 記録 - デバッグと分析の例外をログに記録する

サポート リソース

ビジネス クエリ

操作クエリ

テクニカル サポート

トレーニング情報


© Microsoft Corporation。 All rights reserved. 商標 | プライバシー