外部サービス連携

SandboxでSIMの登録・有効化・無効化を試す手順

本番のSIMを操作する前に、SORACOMのSandbox環境で呼び出し順序を確かめられます。認証キーの扱い方と、Apexから呼ぶときの注意点をまとめます。

2023.11.10

なぜSandboxで確かめるのか

SORACOMのSIMを有効化・無効化するAPIは、本番のSIMに対してそのまま働きます。実装のミスがあると、実在するSIMの通信を止めてしまいます。Sandbox環境は、架空のオペレータと架空のSIMを使って、同じ呼び出し順序を安全に試せる環境です。本番のアカウントやSIMには影響しません。

SalesforceからSORACOMを呼ぶ実装を作るときは、まずSandboxで一連の流れ(オペレータ作成→SIM作成→登録→有効化→無効化)を通してから、本番のエンドポイントに向けます。

呼び出す順番

Sandboxでは、次の順番でAPIを呼びます。前の呼び出しの結果が、次の呼び出しの材料になります。

順番エンドポイント渡すものもらえるもの
1/v1/sandbox/initSORACOMアカウントのメールアドレス・パスワードと、認証キー(authKeyId・authKey)Sandbox用のapiKey・token・operatorId
2/v1/sandbox/subscribers/create契約プラン・バンドル架空SIMのimsi・registrationSecret
3/v1/subscribers/{imsi}/registerregistrationSecret登録完了(ステータスがreadyに)
4/v1/subscribers/{imsi}/activateなしステータスがactiveに
5/v1/subscribers/{imsi}/deactivateなしステータスがinactiveに

⚠️ 2回目以降の呼び出しは、X-Soracom-API-Key・X-Soracom-Tokenヘッダーに、1回目の応答で受け取ったapiKey・tokenを載せます。この2つは24時間で失効するため、期限が切れたら/sandbox/initからやり直します。

認証キーを作る

authKeyId・authKeyは、本番のSORACOMアカウントでSAM(SORACOM Access Management)ユーザーを作り、そのユーザーに対して発行します。Sandboxへの/sandbox/init呼び出しは、この認証キーとアカウントのメールアドレス・パスワードをボディに入れて送ります。

この認証キーとパスワードは、Apexのクラスに直接書きません。private string authKey = '...'のように書くと、ソースを見られる人全員に本番アカウントの認証情報が渡ります。外部資格情報(External Credential)に認証キーとパスワードを登録し、名前付き認証情報(Named Credential)でエンドポイントと紐づけます。Apexはcallout:Soracom_Sandbox/v1/sandbox/initのような形でエンドポイントを呼ぶだけで済み、コードには認証キーもパスワードも出てきません。

プラン名やタイムアウト秒数のような、秘密ではない設定値は、カスタムメタデータ型に持たせる方法もあります。カスタムメタデータ型はデプロイで環境ごとに値を変えられますが、秘匿性はありません。認証キーやパスワードのような秘密の値は、必ず外部資格情報・名前付き認証情報の側に置いてください。

Apexで一連の呼び出しを実装する

この記事を最初に書いた当時は、この5つの呼び出しを2枚のVisualforceページとコントローラ拡張に分けて実装していました。ボタンで押す作りは変えず、呼び出し本体は1つのクラスにまとめています。JSONは文字列連結ではなくJSON.serialize()で組み立て、応答のtoken・apiKeyをそのまま出すSystem.debugも外しました。

public class SoracomSandboxDemo {
    private static HttpResponse post(String endpoint, Map<String, Object> body, String apiKey, String token) {
        Http http = new Http();
        HttpRequest req = new HttpRequest();
        req.setEndpoint('https://api-sandbox.soracom.io/v1' + endpoint);
        req.setHeader('Content-Type', 'application/json');
        if (apiKey != null) {
            req.setHeader('X-Soracom-API-Key', apiKey);
            req.setHeader('X-Soracom-Token', token);
        }
        req.setTimeout(30000);
        req.setBody(JSON.serialize(body));
        req.setMethod('POST');
        return http.send(req);
    }

    // 1. オペレータを作成し、Sandbox用のapiKey・tokenを受け取る
    public static HttpResponse sandboxInit(String email, String password) {
        Map<String, Object> body = new Map<String, Object>{
            'email' => email,
            'password' => password,
            'authKeyId' => 'keyId-xxxxxxxxxxxxxxxxxxxx',
            'authKey' => 'secret-xxxxxxxxxxxxxxxxxxxx',
            'registerPaymentMethod' => true,
            'coverageTypes' => new List<String>{'jp'}
        };
        return post('/sandbox/init', body, null, null);
    }

    // 2. 架空のSIMを作成し、imsi・registrationSecretを受け取る
    public static HttpResponse createSubscriber() {
        Map<String, Object> body = new Map<String, Object>{
            'subscription' => 'plan-D',
            'bundles' => new List<String>{'D-300MB'}
        };
        return post('/sandbox/subscribers/create', body, null, null);
    }

    // 3. SIMを登録する
    public static HttpResponse registerSubscriber(String imsi, String registrationSecret, String apiKey, String token) {
        return post('/subscribers/' + imsi + '/register',
            new Map<String, Object>{ 'registrationSecret' => registrationSecret }, apiKey, token);
    }

    // 4. SIMを有効化する
    public static HttpResponse activateSubscriber(String imsi, String apiKey, String token) {
        return post('/subscribers/' + imsi + '/activate', new Map<String, Object>(), apiKey, token);
    }

    // 5. SIMを無効化する
    public static HttpResponse deactivateSubscriber(String imsi, String apiKey, String token) {
        return post('/subscribers/' + imsi + '/deactivate', new Map<String, Object>(), apiKey, token);
    }
}

Sandboxへの5つの呼び出しをまとめたクラスです。前の呼び出しの結果を、次のメソッドの引数として渡します。

動かして確かめる

  1. オペレータとSIMを作成する

    sandboxInitとcreateSubscriberを呼びます。応答にapiKey・token・imsi・registrationSecretが入っています。

  2. 登録する

    手順1で得た4つの値をregisterSubscriberに渡します。ステータスがreadyになります。

  3. 有効化・無効化を試す

    activateSubscriber・deactivateSubscriberを呼ぶたびに、ステータスがactive・inactiveへと変わります。

各メソッドをVisualforceのボタンや画面フローのApexアクションから呼べば、下の画像と同じ操作画面になります。

ボタンが2つ並んだ画面。架空のオペレーターを作成、架空のIoT SIMを作成
1枚目の操作画面です。上のボタンでオペレータを、下のボタンで架空のSIMを作ります。押す順番が呼び出しの順番です。
ボタンが3つ並んだ画面。SIMの登録、使用中への変更、休止中への変更
2枚目の操作画面です。登録してから使用中、休止中の順にボタンを押すと、ステータスが切り替わることを確かめられます。

ここで間違えやすい

間違い何が起きるか
apiKey・tokenを24時間を超えて使い回す呼び出しが失敗します。/sandbox/initからやり直します
SandboxのapiKey・tokenを本番エンドポイントに向けて送る本番とSandboxは別の認証情報なので通りません
認証キー・パスワードをApexのクラスに直書きするソースコードを見られる人全員に本番の認証情報が渡ります
imsiを手で打ち間違える別のSubscriberを操作してしまいます

確認した環境

  • 2026年9月、developers.soracom.io の公式ドキュメント(API Sandbox Usage Guide、API Sandbox Reference)で、Sandboxの呼び出し順序・認証ヘッダー・ベースURLを確認しています
  • ご自身のSORACOMアカウントで認証キーを発行し、Sandbox環境で確かめてください

まとめ

  • SORACOMのSandbox環境は、架空のオペレータとSIMで、本番に影響を与えずにAPIの呼び出し順序を試せます
  • 呼び出しは/sandbox/init→/sandbox/subscribers/create→/register→/activate→/deactivateの順です
  • 2回目以降の呼び出しはX-Soracom-API-KeyとX-Soracom-Tokenヘッダーが必要で、24時間で失効します
  • 認証キーやパスワードはApexに直書きせず、外部資格情報と名前付き認証情報に置きます
  • JSONは文字列連結ではなくJSON.serialize()で組み立てると、値の中の記号で壊れません

Salesforceの導入・運用についてご相談ください

導入前の検討から、お使いの環境の改修・運用、AIとの連携まで承ります。状況を伺ったうえで、進め方をご提案します。