Golang日历客户端库与服务账户的使用指南

Golang日历客户端库与服务账户的使用指南 我正在使用日历客户端库与服务账户配合,但无法让 CalendarList.List().Do 按预期工作。如果我直接使用 HTTP 请求,它可以正常工作。虽然我可以通过变通方法继续推进,但我想知道是我的实现有问题还是库代码存在问题。任何帮助都将不胜感激。代码如下:

package main

import (
    "io/ioutil"
    "log"
		"fmt"
    "golang.org/x/oauth2/google"
	  "golang.org/x/oauth2"
    "google.golang.org/api/calendar/v3"
)

func main() {

    var theFile = "./testingServiceAccount.json"
    cred, err := ioutil.ReadFile(theFile)
    if err != nil {
        log.Fatalf("Unable to read JSON credentials config %v", err)
    }

    conf, err := google.JWTConfigFromJSON(cred, "https://www.googleapis.com/auth/calendar")
    if err != nil {
        log.Fatalf("Unable to obtain JWT conf %v", err)
    }
    conf.Subject = "jmore@tele-metron.com"
    conf.Expires = 3600
	  fmt.Printf("JWT Configuration Using %v  private key file \n Email %v\n Private Key\n %s\n Scopes %v\n Token URL %v \n Subject %v\n Expires %v\n",theFile,conf.Email,conf.PrivateKey,conf.Scopes,conf.TokenURL,conf.Subject,conf.Expires)
    client := conf.Client(oauth2.NoContext)
     // 变通方法 //
    //此调用按预期成功获取日历列表
    resp, err := client.Get("https://www.googleapis.com/calendar/v3/users/me/calendarList")
    if err != nil {
        log.Fatalf("Unable to retrieve calendar list %v", err)
    }
    defer resp.Body.Close()
    bodyBytes, err := ioutil.ReadAll(resp.Body)
    bodyString := string(bodyBytes)
    fmt.Printf("The response body \n%v\n ",bodyString)
    fmt.Printf("The original request body \n%v\n ",resp.Request)

    // 问题区域 //
    // 使用此方法时没有返回任何内容。它使用相同的客户端获取日历服务,我可以使用日历服务
    // 通过 CalendarList.Get("calendar id").Do() 获取特定日历,因此凭据没有问题
    srv, err := calendar.New(client)
    if err != nil {
        log.Fatalf("Unable to retrieve calendar Client %v", err)
    }
   calendars, err := srv.CalendarList.List().Fields("*").Context(oauth2.NoContext).Do()
    if err != nil {
        log.Fatalf("Unable to retrieve calendar list %v", err)
    }
	fmt.Printf("Calendars  %v\n",calendars)
}

更多关于Golang日历客户端库与服务账户的使用指南的实战教程也可以访问 https://www.itying.com/category-94-b0.html

1 回复

更多关于Golang日历客户端库与服务账户的使用指南的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


在您的代码中,问题可能出现在服务账户的域范围委托配置或库的使用方式上。以下是具体的分析和解决方案:

1. 域范围委托配置检查 服务账户需要正确配置域范围委托,并在Google Cloud Console中为服务账户添加必要的Calendar API权限。确保:

  • 在Google Cloud Console的"IAM和管理" -> "服务账户"中,已为服务账户启用域范围委托
  • 在G Suite管理控制台中,已为服务账户的客户端ID授权日历API范围(https://www.googleapis.com/auth/calendar

2. 代码实现修正 以下是修正后的代码示例,主要优化了JWT配置和API调用:

package main

import (
	"context"
	"fmt"
	"log"

	"golang.org/x/oauth2/google"
	"google.golang.org/api/calendar/v3"
	"google.golang.org/api/option"
)

func main() {
	ctx := context.Background()
	var theFile = "./testingServiceAccount.json"
	
	// 使用更明确的JWT配置
	conf, err := google.JWTConfigFromJSONWithParams(
		[]byte(`your_service_account_json_here`), // 替换为实际JSON内容或保持文件读取
		google.JWTParams{
			Scopes:   []string{"https://www.googleapis.com/auth/calendar"},
			Subject:  "jmore@tele-metron.com",
			Audience: "https://www.googleapis.com/oauth2/v4/token",
		},
	)
	if err != nil {
		log.Fatalf("Unable to create JWT config: %v", err)
	}

	client := conf.Client(ctx)

	// 创建日历服务时明确指定HTTP客户端
	srv, err := calendar.NewService(ctx, option.WithHTTPClient(client))
	if err != nil {
		log.Fatalf("Unable to create calendar service: %v", err)
	}

	// 使用最小化字段进行测试
	calendars, err := srv.CalendarList.List().MaxResults(10).Do()
	if err != nil {
		log.Fatalf("Unable to retrieve calendar list: %v", err)
	}

	fmt.Printf("Found %d calendars:\n", len(calendars.Items))
	for _, cal := range calendars.Items {
		fmt.Printf("- %s (ID: %s)\n", cal.Summary, cal.Id)
	}
}

3. 关键修改点说明

  • 使用context.Background()替代已弃用的oauth2.NoContext
  • 通过option.WithHTTPClient()显式传递配置的HTTP客户端
  • CalendarList.List()调用中先使用MaxResults而非Fields("*")进行简化测试
  • 添加了更清晰的错误处理和结果输出

4. 调试建议 如果问题仍然存在,可以添加HTTP请求日志来比较两种方式的差异:

import "net/http/httputil"

// 在client创建后添加
client.Transport = &logTransport{underlying: client.Transport}

type logTransport struct {
	underlying http.RoundTripper
}

func (t *logTransport) RoundTrip(req *http.Request) (*http.Response, error) {
	dump, _ := httputil.DumpRequestOut(req, true)
	fmt.Printf("Request:\n%s\n", dump)
	resp, err := t.underlying.RoundTrip(req)
	if resp != nil {
		dump, _ = httputil.DumpResponse(resp, true)
		fmt.Printf("Response:\n%s\n", dump)
	}
	return resp, err
}

这个实现应该能解决您遇到的CalendarList.List().Do()不返回数据的问题。问题通常出现在服务账户委托配置或库客户端的初始化方式上。

回到顶部