gitee.com/larksuite/oapi-sdk-go/v3@v3.0.3/README.md (about) 1 # 飞书开放接口SDK 2 3 旨在让开发者便捷的调用飞书开放API、处理订阅的消息事件、处理服务端推送的卡片行为。 4 5 ## 目录 6 7 8 <!-- toc --> 9 10 - [安装](#安装) 11 - [API Client](#api-client) 12 - [创建API Client](#创建api-client) 13 - [配置API Client](#配置api-client) 14 15 - [API调用](#api调用) 16 - [基本用法](#基本用法) 17 - [设置请求选项](#设置请求选项) 18 - [原生API调用方式](#原生api调用方式) 19 20 - [处理消息事件回调](#处理消息事件回调) 21 - [基本用法](#基本用法-1) 22 - [消息处理器内给对应租户发消息](#消息处理器内给对应租户发消息) 23 - [集成gin框架](#集成gin框架) 24 - [安装集成包](#安装集成包) 25 - [集成示例](#集成示例) 26 27 - [处理卡片行为回调](#处理卡片行为回调) 28 - [基本用法](#基本用法-2) 29 - [返回卡片消息](#返回卡片消息) 30 - [返回自定义消息](#返回自定义消息) 31 - [卡片行为处理器内给对应租户发消息](#卡片行为处理器内给对应租户发消息) 32 - [集成gin框架](#集成gin框架) 33 - [安装集成包](#安装集成包) 34 - [集成示例](#集成示例) 35 36 <!-- tocstop --> 37 38 ## 安装 39 40 ```go 41 go get -u gitee.com/larksuite/oapi-sdk-go/v3@v3.0.2 42 ``` 43 44 ## API Client 45 46 开发者在调用 API 前,需要先创建一个 API Client,然后才可以基于 API Client 发起 API 调用。 47 48 ### 创建API Client 49 50 - 对于自建应用,可使用下面代码来创建一个 API Client 51 52 ```go 53 var client = lark.NewClient("appID", "appSecret") // 默认配置为自建应用 54 ``` 55 56 - 对于商店应用,需在创建 API Client 时,使用 lark.WithMarketplaceApp 方法指定 AppType 为商店应用 57 58 ```go 59 var client = lark.NewClient("appID", "appSecret",lark.WithMarketplaceApp()) // 设置App为商店应用 60 ``` 61 62 ### 配置API Client 63 64 创建 API Client 时,可对 API Client 进行一定的配置,比如我们可以在创建 API Client 时设置日志级别、设置 http 请求超时时间等等: 65 66 ```go 67 var client = lark.NewClient("appID", "appSecret", 68 lark.WithLogLevel(larkcore.LogLevelDebug), 69 lark.WithReqTimeout(3*time.Second), 70 lark.WithEnableTokenCache(true), 71 lark.WithHelpdeskCredential("id", "token"), 72 lark.WithHttpClient(http.DefaultClient)) 73 ``` 74 75 每个配置选项的具体含义,如下表格: 76 77 <table> 78 <thead align=left> 79 <tr> 80 <th> 81 配置选项 82 </th> 83 <th> 84 配置方式 85 </th> 86 <th> 87 描述 88 </th> 89 </tr> 90 </thead> 91 <tbody align=left valign=top> 92 <tr> 93 <th> 94 <code>AppType</code> 95 </th> 96 <td> 97 <code>lark.WithMarketplaceApp()</code> 98 </td> 99 <td> 100 设置 App 类型为 商店应用 ,ISV 开发者必须要设置该选项。 101 </td> 102 </tr> 103 <tr> 104 <th> 105 <code>LogLevel</code> 106 </th> 107 <td> 108 <code>lark.WithLogLevel(logLevel larkcore.LogLevel)</code> 109 </td> 110 <td> 111 设置 API Client 的日志输出级别(默认为 Info 级别),枚举值如下: 112 113 - LogLevelDebug 114 - LogLevelInfo 115 - LogLevelWarn 116 - LogLevelError 117 118 </td> 119 </tr> 120 121 <tr> 122 <th> 123 <code>Logger</code> 124 </th> 125 <td> 126 <code>lark.WithLogger(logger larkcore.Logger)</code> 127 </td> 128 <td> 129 设置API Client的日志器,默认日志输出到标准输出。 130 131 开发者可通过实现下面的 Logger 接口,来设置自定义的日志器: 132 133 ```go 134 type Logger interface { 135 Debug(context.Context, ...interface{}) 136 Info(context.Context, ...interface{}) 137 Warn(context.Context, ...interface{}) 138 Error(context.Context, ...interface{}) 139 } 140 ``` 141 142 </td> 143 </tr> 144 145 <tr> 146 <th> 147 <code>LogReqAtDebug</code> 148 </th> 149 <td> 150 <code>lark.WithLogReqAtDebug(printReqRespLog bool)</code> 151 </td> 152 <td> 153 设置是否开启 Http 请求参数和响应参数的日志打印开关;开启后,在 debug 模式下会打印 http 请求和响应的 headers,body 等信息。 154 155 在排查问题时,开启该选项,有利于问题的排查。 156 157 </td> 158 </tr> 159 160 161 <tr> 162 <th> 163 <code>BaseUrl</code> 164 </th> 165 <td> 166 <code>lark.WithOpenBaseUrl(baseUrl string)</code> 167 </td> 168 <td> 169 设置飞书域名,默认为FeishuBaseUrl,可用域名列表为: 170 171 ```go 172 // 飞书域名 173 var FeishuBaseUrl = "https://open.feishu.cn" 174 175 // Lark域名 176 var LarkBaseUrl = "https://open.larksuite.com" 177 ``` 178 179 </td> 180 </tr> 181 182 <tr> 183 <th> 184 <code>TokenCache</code> 185 </th> 186 <td> 187 <code>lark.WithTokenCache(cache larkcore.Cache)</code> 188 </td> 189 <td> 190 设置 token 缓存器,用来缓存 token 和 appTicket, 默认实现为内存。 191 192 如开发者想要定制 token 缓存器,需实现下面 Cache 接口: 193 194 ```go 195 type Cache interface { 196 Set(ctx context.Context, key string, value string, expireTime time.Duration) error 197 Get(ctx context.Context, key string) (string, error) 198 } 199 ``` 200 201 对于 ISV 开发者来说,如需要 SDK 来缓存 appTicket,需要实现该接口,实现提供分布式缓存。 202 203 </td> 204 </tr> 205 206 207 <tr> 208 <th> 209 <code>EnableTokenCache</code> 210 </th> 211 <td> 212 <code>lark.WithEnableTokenCache(enableTokenCache bool)</code> 213 </td> 214 <td> 215 设置是否开启 TenantAccessToken 的自动获取与缓存。 216 217 默认开启,如需要关闭可传递 false。 218 </td> 219 </tr> 220 221 <tr> 222 <th> 223 <code>HelpDeskId、HelpDeskToken</code> 224 </th> 225 <td> 226 <code>lark.WithHelpdeskCredential(helpdeskID, helpdeskToken string)</code> 227 </td> 228 <td> 229 该选项仅在调用服务台业务的 API 时需要配置。 230 </td> 231 </tr> 232 233 234 <tr> 235 <th> 236 <code>ReqTimeout</code> 237 </th> 238 <td> 239 <code>lark.WithReqTimeout(time time.Duration)</code> 240 </td> 241 <td> 242 设置 SDK 内置的 Http Client 的请求超时时间,默认为0代表永不超时。 243 </td> 244 </tr> 245 246 <tr> 247 <th> 248 <code>HttpClient</code> 249 </th> 250 <td> 251 <code>lark.WithHttpClient(httpClient larkcore.HttpClient)</code> 252 </td> 253 <td> 254 设置 HttpClient,用于替换 SDK 提供的默认实现。 255 256 开发者可通过实现下面的 HttpClient 接口来设置自定义的 HttpClient: 257 258 ```go 259 type HttpClient interface { 260 Do(*http.Request) (*http.Response, error) 261 } 262 263 ``` 264 265 </td> 266 </tr> 267 268 </tbody> 269 </table> 270 271 ## API调用 272 创建完毕 API Client,我们可以使用 ``Client.业务域.资源.方法名称`` 来定位具体的 API 方法,然后对具体的 API 发起调用。 273 274  275 276 飞书开放平台开放的所有 API 列表,可点击[这里查看](https://open.feishu.cn/document/ukTMukTMukTM/uYTM5UjL2ETO14iNxkTN/server-api-list) 277 278 ### 基本用法 279 280 如下示例我们通过 client 调用文档业务的 Create 方法,创建一个文档: 281 282 ``` go 283 import ( 284 "context" 285 "fmt" 286 "net/http" 287 "os" 288 289 "gitee.com/larksuite/oapi-sdk-go/v3" 290 "gitee.com/larksuite/oapi-sdk-go/v3/core" 291 "gitee.com/larksuite/oapi-sdk-go/v3/service/docx/v1" 292 ) 293 294 295 func main() { 296 // 创建 client 297 client := lark.NewClient("appID", "appSecret") 298 299 // 发起请求 300 resp, err := client.Docx.Document.Create(context.Background(), larkdocx.NewCreateDocumentReqBuilder(). 301 Body(larkdocx.NewCreateDocumentReqBodyBuilder(). 302 FolderToken("token"). 303 Title("title"). 304 Build()). 305 Build()) 306 307 //处理错误 308 if err != nil { 309 // 处理err 310 return 311 } 312 313 // 服务端错误处理 314 if !resp.Success() { 315 fmt.Println(resp.Code, resp.Msg, resp.RequestId()) 316 return 317 } 318 319 // 业务数据处理 320 fmt.Println(larkcore.Prettify(resp.Data)) 321 } 322 ``` 323 324 更多 API 调用示例:[./sample/api/im.go](./sample/api/im.go) 325 326 ### 设置请求选项 327 328 开发者在每次发起 API 调用时,可以设置请求级别的一些参数,比如传递 UserAccessToken ,自定义 Headers 等: 329 330 ```go 331 import ( 332 "context" 333 "fmt" 334 "net/http" 335 "os" 336 337 "gitee.com/larksuite/oapi-sdk-go/v3" 338 "gitee.com/larksuite/oapi-sdk-go/v3/core" 339 "gitee.com/larksuite/oapi-sdk-go/v3/service/docx/v1" 340 ) 341 342 func main() { 343 // 创建client 344 client := lark.NewClient("appID", "appSecret") 345 346 // 自定义请求headers 347 header := make(http.Header) 348 header.Add("k1", "v1") 349 header.Add("k2", "v2") 350 351 // 发起请求 352 resp, err := client.Docx.Document.Create(context.Background(), larkdocx.NewCreateDocumentReqBuilder(). 353 Body(larkdocx.NewCreateDocumentReqBodyBuilder(). 354 FolderToken("token"). 355 Title("title"). 356 Build(), 357 ). 358 Build(), 359 larkcore.WithHeaders(header), // 设置自定义headers 360 ) 361 362 //处理错误 363 if err != nil { 364 // 处理err 365 return 366 } 367 368 // 服务端错误处理 369 if !resp.Success() { 370 fmt.Println(resp.Code, resp.Msg, resp.RequestId()) 371 return 372 } 373 374 // 业务数据处理 375 fmt.Println(larkcore.Prettify(resp.Data)) 376 } 377 378 ``` 379 380 如下表格,展示了所有请求级别可设置的选项: 381 382 <table> 383 <thead align=left> 384 <tr> 385 <th> 386 配置选项 387 </th> 388 <th> 389 配置方式 390 </th> 391 <th> 392 描述 393 </th> 394 </tr> 395 </thead> 396 <tbody align=left valign=top> 397 <tr> 398 <th> 399 <code>Header</code> 400 </th> 401 <td> 402 <code>larkcore.WithHeaders(header http.Header)</code> 403 </td> 404 <td> 405 设置自定义请求头,开发者可在发起请求时,这些请求头会被透传到飞书开放平台服务端。 406 407 </td> 408 </tr> 409 410 <tr> 411 <th> 412 <code>UserAccessToken</code> 413 </th> 414 <td> 415 <code>larkcore.WithUserAccessToken(userAccessToken string)</code> 416 </td> 417 <td> 418 设置用户token,当开发者需要以用户身份发起调用时,需要设置该选项的值。 419 420 </td> 421 </tr> 422 423 <tr> 424 <th> 425 <code>TenantAccessToken</code> 426 </th> 427 <td> 428 <code>larkcore.WithTenantAccessToken(tenantAccessToken string)</code> 429 </td> 430 <td> 431 设置租户 token,当开发者自己维护租户 token 时(即创建Client时EnableTokenCache设置为了false),需通过该选项传递 租户 token。 432 433 </td> 434 </tr> 435 436 <tr> 437 <th> 438 <code>TenantKey</code> 439 </th> 440 <td> 441 <code>larkcore.WithTenantKey(tenantKey string)</code> 442 </td> 443 <td> 444 设置租户 key, 当开发者开发商店应用时,必须设置该选项。 445 </td> 446 </tr> 447 448 449 <tr> 450 <th> 451 <code>RequestId</code> 452 </th> 453 <td> 454 <code>larkCore.WithRequestId(requestId string)</code> 455 </td> 456 <td> 457 设置请求 ID,用来做请求的唯一标识,该 ID 会被透传到飞书开放平台服务端。 458 459 </td> 460 </tr> 461 462 </tbody> 463 </table> 464 465 ### 原生API调用方式 466 467 有些老版本的开放接口,不能生成结构化的 API, 导致 SDK 内无法提供结构化的使用方式,这时可使用原生模式进行调用: 468 469 ```go 470 import ( 471 "context" 472 "fmt" 473 "os" 474 475 "gitee.com/larksuite/oapi-sdk-go/v3" 476 "gitee.com/larksuite/oapi-sdk-go/v3/core" 477 ) 478 479 func main() { 480 // 创建 API Client 481 var appID, appSecret = os.Getenv("APP_ID"), os.Getenv("APP_SECRET") 482 var cli = lark.NewClient(appID, appSecret, lark.WithLogReqAtDebug(true), lark.WithLogLevel(larkcore.LogLevelDebug)) 483 484 // 发起请求 485 resp, err := cli.Do(context.Background(), 486 &larkcore.ApiReq{ 487 HttpMethod: http.MethodGet, 488 ApiPath: "https://open.feishu.cn/open-apis/contact/v3/users/:user_id", 489 Body: nil, 490 QueryParams: larkcore.QueryParams{"user_id_type": []string{"open_id"}}, 491 PathParams: larkcore.PathParams{"user_id": "ou_c245b0a7dff2725cfa2fb104f8b48b9d"}, 492 SupportedAccessTokenTypes: []larkcore.AccessTokenType{larkcore.AccessTokenTypeUser}, 493 }, 494 larkcore.WithUserAccessToken("u-3Sr1oTO4V1FWxTFTFYuFCqhk2Vs4h5IbhMG00gmw0CXh"), 495 ) 496 497 // 错误处理 498 if err != nil { 499 fmt.Println(err) 500 return 501 } 502 503 // 获取请求 ID 504 fmt.Println(resp.RequestId()) 505 506 // 处理请求结果 507 fmt.Println(resp.StatusCode) // http status code 508 fmt.Println(resp.Header) // http header 509 fmt.Println(string(resp.RawBody)) // http body 510 } 511 ``` 512 513 更多 API 调用示例:[./sample/callrawapi/api.go](./sample/callrawapi/api.go) 514 515 ## 处理消息事件回调 516 关于消息订阅相关的知识,可以点击[这里查看](https://open.feishu.cn/document/ukTMukTMukTM/uUTNz4SN1MjL1UzM) 517 518 飞书开放平台开放的所有事件列表,可点击[这里查看](https://open.feishu.cn/document/ukTMukTMukTM/uYDNxYjL2QTM24iN0EjN/event-list) 519 ### 基本用法 520 521 开发者订阅消息事件后,可以使用下面代码,对飞书开放平台推送的消息事件进行处理,如下代码基于 go-sdk 原生 http server 启动一个 httpServer: 522 523 ```go 524 import ( 525 "context" 526 "fmt" 527 "net/http" 528 529 "gitee.com/larksuite/oapi-sdk-go/v3/core" 530 "gitee.com/larksuite/oapi-sdk-go/v3/event" 531 "gitee.com/larksuite/oapi-sdk-go/v3/event/dispatcher" 532 "gitee.com/larksuite/oapi-sdk-go/v3/core/httpserverext" 533 "gitee.com/larksuite/oapi-sdk-go/v3/service/contact/v3" 534 "gitee.com/larksuite/oapi-sdk-go/v3/service/im/v1" 535 ) 536 537 func main() { 538 // 注册消息处理器 539 handler := dispatcher.NewEventDispatcher("verificationToken", "eventEncryptKey").OnP2MessageReceiveV1(func(ctx context.Context, event *larkim.P2MessageReceiveV1) error { 540 // 处理消息 event,这里简单打印消息的内容 541 fmt.Println(larkcore.Prettify(event)) 542 fmt.Println(event.RequestId()) 543 return nil 544 }).OnP2MessageReadV1(func(ctx context.Context, event *larkim.P2MessageReadV1) error { 545 // 处理消息 event,这里简单打印消息的内容 546 fmt.Println(larkcore.Prettify(event)) 547 fmt.Println(event.RequestId()) 548 return nil 549 }) 550 551 // 注册 http 路由 552 http.HandleFunc("/webhook/event", httpserverext.NewEventHandlerFunc(handler, larkevent.WithLogLevel(larkcore.LogLevelDebug))) 553 554 // 启动 http 服务 555 err := http.ListenAndServe(":9999", nil) 556 if err != nil { 557 panic(err) 558 } 559 } 560 561 562 ``` 563 564 其中 NewEventDispatcher 方法的参数用于签名验证和消息解密使用,默认可以传递为空串;但是如果开发者的应用在 [控制台](https://open.feishu.cn/app?lang=zh-CN) 的【事件订阅】里面开启了加密,则必须传递控制台上提供的值。 565 566  567 568 需要注意的是注册处理器时,比如使用 OnP2MessageReceiveV1 注册接受消息事件回调时,其中的P2为消息协议版本,当前飞书开放平台存在 [两种消息协议](https://open.feishu.cn/document/ukTMukTMukTM/uUTNz4SN1MjL1UzM#8f960a4b) ,分别为1.0和2.0。 569 570 如下图开发者在注册消息处理器时,需从 [事件列表](https://open.feishu.cn/document/ukTMukTMukTM/uYDNxYjL2QTM24iN0EjN/event-list) 中查看自己需要的是哪种协议的事件。 571 如果是1.0的消息协议,则注册处理器时,需要找以OnP1xxxx开头的。如果是2.0的消息协议,则注册处理器时,需要找以OnP2xxxx开头的。 572 573 574 575 576  577 578 更多事件订阅示例:[./sample/event/event.go](./sample/event/event.go) 579 580 ## 消息处理器内给对应租户发消息 581 针对 ISV 开发者,如果想在消息处理器内给对应租户的用户发送消息,则需先从消息事件内获取租户 key,然后使用下面方式调用消息 API 进行消息发送: 582 583 ```go 584 import ( 585 "context" 586 "fmt" 587 "net/http" 588 589 "gitee.com/larksuite/oapi-sdk-go/v3/core" 590 "gitee.com/larksuite/oapi-sdk-go/v3/event" 591 "gitee.com/larksuite/oapi-sdk-go/v3/event/dispatcher" 592 "gitee.com/larksuite/oapi-sdk-go/v3/core/httpserverext" 593 "gitee.com/larksuite/oapi-sdk-go/v3/service/contact/v3" 594 "gitee.com/larksuite/oapi-sdk-go/v3/service/im/v1" 595 ) 596 597 func main() { 598 // 注册消息处理器 599 handler := dispatcher.NewEventDispatcher("verificationToken", "eventEncryptKey").OnP2MessageReceiveV1(func(ctx context.Context, event *larkim.P2MessageReceiveV1) error { 600 // 处理消息 event,这里简单打印消息的内容 601 fmt.Println(larkcore.Prettify(event)) 602 fmt.Println(event.RequestId()) 603 604 // 获取租户 key 并发送消息 605 tenanKey := event.TenantKey() 606 607 // ISV 给指定租户发送消息 608 resp, err := client.Im.Message.Create(context.Background(), larkim.NewCreateMessageReqBuilder(). 609 ReceiveIdType(larkim.ReceiveIdTypeOpenId). 610 Body(larkim.NewCreateMessageReqBodyBuilder(). 611 MsgType(larkim.MsgTypePost). 612 ReceiveId("ou_c245b0a7dff2725cfa2fb104f8b48b9d"). 613 Content("text"). 614 Build(), larkcore.WithTenantKey(tenanKey)). 615 Build()) 616 617 // 发送结果处理,resp,err 618 619 return nil 620 }) 621 622 // 注册 http 路由 623 http.HandleFunc("/webhook/event", httpserverext.NewEventHandlerFunc(handler, larkevent.WithLogLevel(larkcore.LogLevelDebug))) 624 625 // 启动 http 服务 626 err := http.ListenAndServe(":9999", nil) 627 if err != nil { 628 panic(err) 629 } 630 } 631 632 ``` 633 634 635 更多事件订阅示例:[./sample/event/event.go](./sample/event/event.go) 636 637 638 ### 集成Gin框架 639 如果开发者当前应用使用的是 Gin Web 框架,并且不想要使用 Go-Sdk 提供的原生的 Http Server,则可使用下面方式,把当前应用的 Gin 服务与 SDK进行集成。 640 641 要想把 SDK 集成已有 Gin 框架,开发者需要引入集成包 [oapi-sdk-gin](https://github.com/larksuite/oapi-sdk-gin) 642 643 #### 安装集成包 644 645 ```go 646 go get -u github.com/larksuite/oapi-sdk-gin 647 ``` 648 649 #### 集成示例 650 651 ```go 652 import ( 653 "context" 654 "fmt" 655 656 "github.com/gin-gonic/gin" 657 "github.com/larksuite/oapi-sdk-gin" 658 "gitee.com/larksuite/oapi-sdk-go/v3/card" 659 "gitee.com/larksuite/oapi-sdk-go/v3/core" 660 "gitee.com/larksuite/oapi-sdk-go/v3/event/dispatcher" 661 "gitee.com/larksuite/oapi-sdk-go/v3/service/contact/v3" 662 "gitee.com/larksuite/oapi-sdk-go/v3/service/im/v1" 663 ) 664 665 func main() { 666 // 注册消息处理器 667 handler := dispatcher.NewEventDispatcher("verificationToken", "eventEncryptKey").OnP2MessageReceiveV1(func(ctx context.Context, event *larkim.P2MessageReceiveV1) error { 668 fmt.Println(larkcore.Prettify(event)) 669 fmt.Println(event.RequestId()) 670 return nil 671 }).OnP2MessageReadV1(func(ctx context.Context, event *larkim.P2MessageReadV1) error { 672 fmt.Println(larkcore.Prettify(event)) 673 fmt.Println(event.RequestId()) 674 return nil 675 }).OnP2UserCreatedV3(func(ctx context.Context, event *larkcontact.P2UserCreatedV3) error { 676 fmt.Println(larkcore.Prettify(event)) 677 fmt.Println(event.RequestId()) 678 return nil 679 }) 680 681 ... 682 683 // 在已有 Gin 实例上注册消息处理路由 684 gin.POST("/webhook/event", sdkginext.NewEventHandlerFunc(handler)) 685 } 686 ``` 687 688 689 ## 处理卡片行为回调 690 691 关于卡片行为相关的知识,可点击[这里查看](https://open.feishu.cn/document/ukTMukTMukTM/uczM3QjL3MzN04yNzcDN) 692 ### 基本用法 693 694 开发者配置消息卡片回调地址后,可以使用下面代码,对飞书开放平台推送的卡片行为进行处理,如下代码基于go-sdk原生http server启动一个httpServer: 695 696 ```go 697 import ( 698 "context" 699 "fmt" 700 "net/http" 701 702 "gitee.com/larksuite/oapi-sdk-go/v3/card" 703 "gitee.com/larksuite/oapi-sdk-go/v3/core" 704 "gitee.com/larksuite/oapi-sdk-go/v3/core/httpserverext" 705 ) 706 707 func main() { 708 // 创建 card 处理器 709 cardHandler := larkcard.NewCardActionHandler("v", "", func(ctx context.Context, cardAction *larkcard.CardAction) (interface{}, error) { 710 // 处理 cardAction, 这里简单打印卡片内容 711 fmt.Println(larkcore.Prettify(cardAction)) 712 fmt.Println(cardAction.RequestId()) 713 // 无返回值示例 714 return nil, nil 715 }) 716 717 // 注册处理器 718 http.HandleFunc("/webhook/card", httpserverext.NewCardActionHandlerFunc(cardHandler, larkevent.WithLogLevel(larkcore.LogLevelDebug))) 719 720 // 启动 http 服务 721 err := http.ListenAndServe(":9999", nil) 722 if err != nil { 723 panic(err) 724 } 725 } 726 727 ``` 728 729 如上示例,如果不需要处理器内返回业务结果给飞书服务端,则直接使用这种无返回值用法 730 731 更多卡片行为处理示例:[./sample/card/card.go](./sample/card/card.go) 732 733 ### 返回卡片消息 734 735 如开发者需要卡片处理器内同步返回用于更新消息卡片的消息体,则可使用下面方法方式进行处理: 736 737 ```go 738 739 import ( 740 "context" 741 "fmt" 742 "net/http" 743 744 "gitee.com/larksuite/oapi-sdk-go/v3/card" 745 "gitee.com/larksuite/oapi-sdk-go/v3/core" 746 "gitee.com/larksuite/oapi-sdk-go/v3/core/httpserverext" 747 ) 748 749 func main() { 750 // 创建card处理器 751 cardHandler := larkcard.NewCardActionHandler("v", "", func(ctx context.Context, cardAction *larkcard.CardAction) (interface{}, error) { 752 fmt.Println(larkcore.Prettify(cardAction)) 753 fmt.Println(cardAction.RequestId()) 754 755 // 创建卡片信息 756 messageCard := larkcard.NewMessageCard(). 757 Config(config). 758 Header(header). 759 Elements([]larkcard.MessageCardElement{divElement, processPersonElement}). 760 CardLink(cardLink). 761 Build() 762 763 return messageCard, nil 764 }) 765 766 // 注册处理器 767 http.HandleFunc("/webhook/card", httpserverext.NewCardActionHandlerFunc(cardHandler, larkevent.WithLogLevel(larkcore.LogLevelDebug))) 768 769 // 启动http服务 770 err := http.ListenAndServe(":9999", nil) 771 if err != nil { 772 panic(err) 773 } 774 } 775 776 ``` 777 778 更多卡片行为处理示例:[./sample/card/card.go](./sample/card/card.go) 779 780 ### 返回自定义消息 781 782 如开发者需卡片处理器内返回自定义内容,则可以使用下面方式进行处理: 783 784 ```go 785 import ( 786 "context" 787 "fmt" 788 "net/http" 789 790 "gitee.com/larksuite/oapi-sdk-go/v3/card" 791 "gitee.com/larksuite/oapi-sdk-go/v3/core" 792 "gitee.com/larksuite/oapi-sdk-go/v3/core/httpserverext" 793 ) 794 795 func main() { 796 // 创建 card 处理器 797 cardHandler := larkcard.NewCardActionHandler("v", "", func(ctx context.Context, cardAction *larkcard.CardAction) (interface{}, error) { 798 fmt.Println(larkcore.Prettify(cardAction)) 799 fmt.Println(cardAction.RequestId()) 800 801 // 创建 http body 802 body := make(map[string]interface{}) 803 body["content"] = "hello" 804 805 i18n := make(map[string]string) 806 i18n["zh_cn"] = "你好" 807 i18n["en_us"] = "hello" 808 i18n["ja_jp"] = "こんにちは" 809 body["i18n"] = i18n 810 811 // 创建自定义消息:http状态码,body内容 812 resp := &larkcard.CustomResp{ 813 StatusCode: 400, 814 Body: body, 815 } 816 817 return resp, nil 818 }) 819 820 // 注册处理器 821 http.HandleFunc("/webhook/card", httpserverext.NewCardActionHandlerFunc(cardHandler, larkevent.WithLogLevel(larkcore.LogLevelDebug))) 822 823 // 启动 http 服务 824 err := http.ListenAndServe(":9999", nil) 825 if err != nil { 826 panic(err) 827 } 828 } 829 830 ``` 831 832 更多卡片行为处理示例:[./sample/card/card.go](./sample/card/card.go) 833 834 835 ### 卡片行为处理器内给对应租户发消息 836 837 针对 ISV 开发者,如果想在卡片行为处理器内给对应租户的用户发送消息,则需先从卡片行为内获取租户 key ,然后使用下面方式调用消息 API 进行消息发送: 838 839 840 ```go 841 import ( 842 "context" 843 "fmt" 844 "net/http" 845 846 "gitee.com/larksuite/oapi-sdk-go/v3/card" 847 "gitee.com/larksuite/oapi-sdk-go/v3/core" 848 "gitee.com/larksuite/oapi-sdk-go/v3/core/httpserverext" 849 ) 850 851 func main() { 852 // 创建 card 处理器 853 cardHandler := larkcard.NewCardActionHandler("v", "", func(ctx context.Context, cardAction *larkcard.CardAction) (interface{}, error) { 854 855 // 处理 cardAction, 这里简单打印卡片内容 856 fmt.Println(larkcore.Prettify(cardAction)) 857 fmt.Println(cardAction.RequestId()) 858 859 // 获取租户 key 并发送消息 860 tenanKey := cardAction.TenantKey 861 862 // ISV 给指定租户发送消息 863 resp, err := client.Im.Message.Create(context.Background(), larkim.NewCreateMessageReqBuilder(). 864 ReceiveIdType(larkim.ReceiveIdTypeOpenId). 865 Body(larkim.NewCreateMessageReqBodyBuilder(). 866 MsgType(larkim.MsgTypePost). 867 ReceiveId("ou_c245b0a7dff2725cfa2fb104f8b48b9d"). 868 Content("text"). 869 Build(), larkcore.WithTenantKey(tenanKey)). 870 Build()) 871 872 // 发送结果处理,resp,err 873 874 return nil, nil 875 }) 876 877 // 注册处理器 878 http.HandleFunc("/webhook/card", httpserverext.NewCardActionHandlerFunc(cardHandler, larkevent.WithLogLevel(larkcore.LogLevelDebug))) 879 880 // 启动 http 服务 881 err := http.ListenAndServe(":9999", nil) 882 if err != nil { 883 panic(err) 884 } 885 } 886 887 ``` 888 889 更多卡片行为处理示例:[./sample/card/card.go](./sample/card/card.go) 890 891 892 ### 集成gin框架 893 894 如果开发者当前应用使用的是 Gin Web 框架,并且不想要使用 Go-Sdk 提供的原生的 Http Server,则可使用下面方式,把当前应用的 Gin 服务与 SDK进行集成。 895 896 要想把 SDK 集成已有 Gin 框架,开发者需要引入集成包 [oapi-sdk-gin](https://github.com/larksuite/oapi-sdk-gin) 897 898 #### 安装集成包 899 900 ```go 901 go get -u github.com/larksuite/oapi-sdk-gin 902 ``` 903 904 #### 集成示例 905 906 ```go 907 import ( 908 "context" 909 "fmt" 910 911 "github.com/gin-gonic/gin" 912 "github.com/larksuite/oapi-sdk-gin" 913 "gitee.com/larksuite/oapi-sdk-go/v3/card" 914 "gitee.com/larksuite/oapi-sdk-go/v3/core" 915 ) 916 917 918 func main() { 919 // 创建 card 处理器 920 cardHandler := larkcard.NewCardActionHandler("v", "", func(ctx context.Context, cardAction *larkcard.CardAction) (interface{}, error) { 921 fmt.Println(larkcore.Prettify(cardAction)) 922 fmt.Println(cardAction.RequestId()) 923 924 return nil, nil 925 }) 926 ... 927 // 在已有的 Gin 实例上注册卡片处理路由 928 gin.POST("/webhook/card", sdkginext.NewCardActionHandlerFunc(cardHandler)) 929 ... 930 } 931 ``` 932 933 ## License 934 使用 MIT 935 936 937