@takeshita0x0201

Are you sure you want to delete the question?

If your question is resolved, you may close it.

Leaving a resolved question undeleted may help others!

We hope you find it useful!

【Google Maps API】REQUEST_DENIED & ApiNotActivatedMapError を解消できない…課金も有効・リファラ制限なし・API有効化済みなのにエラーになる原因は?

解決したいこと

現在、Google Maps JavaScript API を使ったウェブアプリをCodePen上で試作しています。
地図自体は正しく表示されているのですが、オートコンプリート(Places)や経路検索(Directions)を実行すると REQUEST_DENIED エラーが出てしまい、どうしても解決できずに困っています。

やりたいこと

・CodePenで簡単なGoogle Mapアプリを作成
・検索オートコンプリート(google.maps.places.Autocomplete)
・経路検索(DirectionsService)

環境

CodePen
Google Cloud Console
課金アカウント:有効
プロジェクト:課金アカウントにリンク済み

有効にしているAPI:

Maps SDK for Android
Maps Elevation API
Maps Embed API
Geocoding API
Geolocation API
Maps JavaScript API
Roads API
Maps SDK for iOS
Time Zone API
Maps Static API
Street View Static API
Map Tiles API
Routes API
Navigation SDK
Address Validation API
Maps Platform Datasets API
Air Quality API
Solar API
Aerial View API
Places API (New)
Street View Publish API
Pollen API
Route Optimization API
Places UI Kit
リファラ制限:なし(現在は外しています)

発生している問題・エラー

  1. オートコンプリートを使うために
<script src="https://maps.googleapis.com/maps/api/js?key=~&libraries=places&callback=initMap">

を読み込んでいるが、
入力フォームに地名を入れると、「このページではGoogleマップが正しく読み込まれませんでした」や「REQUEST_DENIED」のエラーが発生

2.経路検索(DirectionsService)を使うときも、同様に REQUEST_DENIED が返ってくる

いずれも「マップ表示」自体は正常なので、Maps JavaScript API は動作しているように見えます。

試したこと

Places API (New) と Directions API を有効化
Google Cloud Consoleで確認済み。
同じプロジェクトのAPIキーを利用
プロジェクトが異なっていないか再三チェック。
リファラ制限
いったん制限を外して「無し」にしてもエラーが変わらず。
課金アカウント
ステータスは「有効」になっており、他のプロジェクトでは正常に利用できています。
反映のタイムラグ
数十分待っても状況変わらず。

該当するソースコード

下記は簡略化したサンプルです。(実際にはCodePenでHTML/CSS/JSを分けて書いています)

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title>Google Map Web App</title>
    <style>
      /* ベーススタイル */
      body {
        font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;
        margin: 0;
        padding: 0;
        background-color: #f4f4f4;
        color: #333;
      }
      header {
        background-color: #fff;
        padding: 20px;
        text-align: center;
        box-shadow: 0 2px 4px rgba(0,0,0,0.1);
      }
      h1 {
        margin: 0;
        font-size: 24px;
      }
      .container {
        width: 90%;
        max-width: 800px;
        margin: 20px auto;
      }
      /* 地図エリア */
      #map {
        width: 100%;
        height: 500px;
        margin-top: 20px;
      }
      /* 検索用エリア */
      .search-container {
        background: #fff;
        padding: 15px;
        box-shadow: 0 2px 4px rgba(0,0,0,0.1);
      }
      .search-container input[type="text"] {
        width: 100%;
        padding: 10px;
        border: 1px solid #ddd;
        border-radius: 4px;
        font-size: 16px;
      }
      /* 経路検索フォーム */
      form {
        display: flex;
        flex-wrap: wrap;
        align-items: center;
        background: #fff;
        padding: 15px;
        margin-top: 20px;
        box-shadow: 0 2px 4px rgba(0,0,0,0.1);
      }
      form input[type="text"],
      form select {
        flex: 1 1 200px;
        margin: 5px;
        padding: 10px;
        border: 1px solid #ddd;
        border-radius: 4px;
        font-size: 16px;
      }
      form button {
        margin: 5px;
        padding: 10px 20px;
        background-color: #4285f4;
        border: none;
        border-radius: 4px;
        color: #fff;
        font-size: 16px;
        cursor: pointer;
      }
      form button:hover {
        background-color: #357ae8;
      }
    </style>
  </head>
  <body>
    <header>
      <h1>Google Map Web App</h1>
    </header>
    <div class="container">
      <!-- オートコンプリート検索 -->
      <div class="search-container">
        <input id="search-input" type="text" placeholder="場所を検索">
      </div>
      <!-- 地図表示エリア -->
      <div id="map"></div>
      <!-- 経路検索フォーム -->
      <form id="route-form">
        <input id="origin" type="text" placeholder="出発地点" required>
        <input id="destination" type="text" placeholder="目的地" required>
        <select id="mode">
          <option value="DRIVING"></option>
          <option value="WALKING">徒歩</option>
          <option value="BICYCLING">自転車</option>
          <option value="TRANSIT">公共交通機関</option>
        </select>
        <button type="submit">経路検索</button>
      </form>
    </div>
    
    <!-- JavaScript: Google Maps APIのコールバックとしてinitMapを呼び出す -->
    <script>
      // Google Maps API読み込み後に呼ばれるコールバック関数
      function initMap() {
        // 地図の初期表示(例:東京周辺)
        const map = new google.maps.Map(document.getElementById('map'), {
          center: { lat: 35.6895, lng: 139.6917 },
          zoom: 13,
          mapTypeControl: false,
          streetViewControl: false
        });
        
        // オートコンプリート機能
        const input = document.getElementById('search-input');
        const autocomplete = new google.maps.places.Autocomplete(input);
        autocomplete.bindTo('bounds', map);
        
        autocomplete.addListener('place_changed', () => {
          const place = autocomplete.getPlace();
          if (!place.geometry) {
            alert("選択した場所の情報が見つかりませんでした: '" + place.name + "'");
            return;
          }
          if (place.geometry.viewport) {
            map.fitBounds(place.geometry.viewport);
          } else {
            map.setCenter(place.geometry.location);
            map.setZoom(17);
          }
        });
        
        // 経路検索機能
        const directionsService = new google.maps.DirectionsService();
        const directionsRenderer = new google.maps.DirectionsRenderer();
        directionsRenderer.setMap(map);
        
        document.getElementById('route-form').addEventListener('submit', (e) => {
          e.preventDefault();
          calculateRoute(directionsService, directionsRenderer);
        });
      }
      
      // 経路検索を実行する関数
      function calculateRoute(directionsService, directionsRenderer) {
        const origin = document.getElementById('origin').value;
        const destination = document.getElementById('destination').value;
        const travelMode = document.getElementById('mode').value; // DRIVING, WALKING, BICYCLING, TRANSIT
        
        const request = {
          origin: origin,
          destination: destination,
          travelMode: google.maps.TravelMode[travelMode]
        };
        
        directionsService.route(request, (result, status) => {
          if (status === 'OK') {
            directionsRenderer.setDirections(result);
          } else {
            alert("経路検索に失敗しました: " + status);
          }
        });
      }
    </script>
    <!-- Google Maps APIの読み込み (async, defer, callback指定) -->
    <script async defer src="https://maps.googleapis.com/maps/api/js?key={MY_API_KEY}
&libraries=places&callback=initMap"></script>
  </body>
</html>

質問・アドバイスをいただきたい点

すでに「Maps JavaScript API」「Places API (New)」「Directions API」を同一プロジェクトで有効化し、課金アカウントも有効、リファラ制限は外した状態です。それでも REQUEST_DENIED が出る原因として、他に何が考えられるでしょうか?
CodePen特有の cdpn.io ドメインも関係していない(リファラ制限なし)はずなのに、なぜリクエストが拒否されるのか…。似たような経験や解決事例があれば教えていただきたいです。

0 likes

1Answer

Autocomplete ウィジェットを追加する
重要: このウィジェットを使用するには、プロジェクトで Places API(従来版)を有効にする必要があります。Places(新規)サービスには、プレビュー版で利用可能な同等のウィジェットが用意されています。
引用元: Maps Javascript APIのドキュメント

とのことですので、Places API(New) ではなく Places API の方を有効化する必要があるんだと思います。

APIを使って何かを実装するときは、公式のドキュメントにも目を通すことをお勧めします。

0Like

Your answer might help someone💌