"Login Required" 尝试使用 YoutubeV3 创建直播时出错 API

"Login Required" error when trying to create live broadcast using YoutubeV3 API

我正在尝试使用 google-api-ruby-client

创建一个新广播
YT = Google::Apis::YoutubeV3
client = YT::YouTubeService.new
client.key = 'my-api-key-here'
metadata = {
  snippet: {
    title: 'test',
    scheduled_start_time: '2018-02-23T14:50:00.000Z'
  },
  status: {
    privacy_status: 'public'
  }
}
part = 'snippet'
client.insert_live_broadcast(part, metadata, {})

当我执行这段代码时,我得到 Error -# <Google::Apis::AuthorizationError: Unauthorized>

[5] pry(main)> CreateYoutubeBroadcast.execute
Sending HTTP post https://www.googleapis.com/youtube/v3/liveBroadcasts?key=my-api-key&part=snippet
401
#<HTTP::Message:0x007f8d5356fdc8 @http_header=#<HTTP::Message::Headers:0x007f8d5356fda0 @http_version="1.1", @body_size=0, @chunked=false, @request_method="POST", @request_uri=#<Addressable::URI:0x3fc6a61124c8 URI:https://www.googleapis.com/youtube/v3/liveBroadcasts?key=my-api-key&part=snippet>, @request_query=nil, @request_absolute_uri=nil, @status_code=401, @reason_phrase="Unauthorized", @body_type=nil, @body_charset=nil, @body_date=nil, @body_encoding=#<Encoding:UTF-8>, @is_request=false, @header_item=[["Vary", "Origin"], ["Vary", "X-Origin"], ["WWW-Authenticate", "Bearer realm=\"https://accounts.google.com/\""], ["Content-Type", "application/json; charset=UTF-8"], ["Content-Encoding", "gzip"], ["Date", "Thu, 15 Feb 2018 12:59:45 GMT"], ["Expires", "Thu, 15 Feb 2018 12:59:45 GMT"], ["Cache-Control", "private, max-age=0"], ["X-Content-Type-Options", "nosniff"], ["X-Frame-Options", "SAMEORIGIN"], ["X-XSS-Protection", "1; mode=block"], ["Server", "GSE"], ["Alt-Svc", "hq=\":443\"; ma=2592000; quic=51303431; quic=51303339; quic=51303338; quic=51303337; quic=51303335,quic=\":443\"; ma=2592000; v=\"41,39,38,37,35\""], ["Transfer-Encoding", "chunked"]], @dumped=false>, @peer_cert=#<OpenSSL::X509::Certificate: subject=#<OpenSSL::X509::Name:0x007f8d5247d290>, issuer=#<OpenSSL::X509::Name:0x007f8d5247d268>, serial=#<OpenSSL::BN:0x007f8d5247d240>, not_before=2018-01-30 08:56:10 UTC, not_after=2018-04-24 08:30:00 UTC>, @http_body=#<HTTP::Message::Body:0x007f8d5356fd28 @body="{\n \"error\": {\n  \"errors\": [\n   {\n    \"domain\": \"global\",\n    \"reason\": \"required\",\n    \"message\": \"Login Required\",\n    \"locationType\": \"header\",\n    \"location\": \"Authorization\"\n   }\n  ],\n  \"code\": 401,\n  \"message\": \"Login Required\"\n }\n}\n", @size=0, @positions=nil, @chunk_size=nil>, @previous=nil>
Caught error Unauthorized
Error - #<Google::Apis::AuthorizationError: Unauthorized>

Retrying after authentication failure
Google::Apis::AuthorizationError: Unauthorized

我完成了

知道为什么会出现这个错误吗?谢谢

似乎无法通过 API 密钥创建预定的广播,我使用 google OAuth 2.0 策略来完成此操作。

# lib/youtube_api/o_auth_client.rb

require 'google/api_client/auth/storage'
require 'google/api_client/auth/storages/file_store'
require 'google/api_client/auth/installed_app'

module YoutubeApi
  class OAuthClient
    YOUTUBE_SCOPE = 'https://www.googleapis.com/auth/youtube'
    CREDENTIALS_FILE = Rails.root.join('tmp', 'google_api_credentials.json')

    def initialize
      @credentials_storage = ::Google::APIClient::Storage.new(
        ::Google::APIClient::FileStore.new(CREDENTIALS_FILE)
      )
    end

    def authorize
      @credentials_storage.authorize || begin
        installed_app_flow = ::Google::APIClient::InstalledAppFlow.new(
          client_id:     Rails.application.secrets.youtube_client_id,
          client_secret: Rails.application.secrets.youtube_client_secret,
          scope:         [YOUTUBE_SCOPE]
        )
        installed_app_flow.authorize(@credentials_storage)
      end
    end
  end
end

和我的 create_broadcast 服务对象

require 'service'
require 'youtube_api'
require 'google/apis/youtube_v3'


class CreateBroadcast
  include Service

  YT = Google::Apis::YoutubeV3
  BROADCAST_PRIVACY = 'public'

  def initialize(title, description, start_time)
    @client = YT::YouTubeService.new
    @client.authorization = YoutubeApi.authorize_via_google_oauth_2
    @title = title
    @description = description
    @start_time = start_time
  end

  def execute
    @client.insert_live_broadcast(part, metadata, {})
  end

  private

    def part
      'id,snippet,contentDetails,status'
    end

    def metadata
      {
        snippet: {
          title: @title,
          description: @description,
          scheduled_start_time: @start_time,
        },
        status: {
          privacy_status: BROADCAST_PRIVACY
        }
      }
    end
end

lib/youtube_api.rb我有

# frozen_string_literal: true

require 'youtube_api/o_auth_client'

module YoutubeApi
  def self.authorize_via_google_oauth_2
    oauth_client = OAuthClient.new
    oauth_client.authorize
  end
end