Go对接三方API实践

本文涉及的产品
Redis 开源版,标准版 2GB
推荐场景:
搭建游戏排行榜
云数据库 Tair(兼容Redis),内存型 2GB
简介: 今天这篇分享:使用Go语言对接三方API实践。

知识点分析


  1. 网络请求
  2. 缓存
  3. 获得token
  4. 刷新token
  5. redis的使用


关键代码


定义结构体


关键点


  1. 能复用的一定要复用
  2. 能分层的一定要分层


type Config struct {
   ApiUrl    string
   AppKey    string
   AppSecret string
   Version   string
}
type Client struct {
   *Config
   AccessToken  string
   RefreshToken string
}
type CommonReq struct {
   AppKey      string      `json:"app_key"`
   Version     string      `json:"version"`
   Method      string      `json:"method"`
   AccessToken string      `json:"access_token"`
   Timestamp   string      `json:"timestamp"`
   Param       interface{} `json:"param"`
   Sign        string      `json:"sign,omitempty"`
}
type CommonPageReq struct {
   PageNo   int `json:"pageNo"`
   PageSize int `json:"pageSize"`
}
type CommonPageRes struct {
   PageSize   int `json:"pageSize"`
   PageNo     int `json:"pageNo"`
   TotalPage  int `json:"totalPage"`
   TotalCount int `json:"totalCount"`
}
type CommonRes struct {
   Code    string `json:"code"`
   Message string `json:"message"`
   SubCode string `json:"sub_code"`
   SubMsg  string `json:"sub_msg"`
}


签名相关


  1. 根据三方要求进行签名(验签)
  2. 比如我这里示例的:md5加密


func (s *Client) sign(req g.Map) string {
   data := gjson.New(req)
   _ = data.Remove("sign")
   return gstr.ToUpper(gmd5.MustEncryptString(server.AppSecret + data.MustToJsonString() + server.AppSecret))
}


封装请求


func (s *Client) post(ctx context.Context, method string, req interface{}) (str string, err error) {
   Start := gtime.TimestampMilli()
   allparams := &CommonReq{
      AppKey:      server.AppKey,
      Version:     server.Version,
      Method:      method,
      AccessToken: server.AccessToken,
      Timestamp:   gtime.Now().String(),
      Param:       req,
   }
   allparams.Sign = s.sign(gconv.Map(allparams))
   Request := g.Client()
   Request.SetHeader("Content-Type", "application/json")
   resp, err := Request.Timeout(time.Second*5).Post(server.ApiUrl, allparams)
   defer func() {
      paramStr := gjson.New(req).MustToJsonString()
      ctx = context.WithValue(ctx, "Method", "POST")
      ctx = context.WithValue(ctx, "URI", method)
      if err != nil {
         logs.Errorf(ctx, pkgName, logs.FormatErr, paramStr, err.Error(), gtime.TimestampMilli()-Start)
      } else {
         logs.Infof(ctx, pkgName, logs.FormatSuc, paramStr, str, gtime.TimestampMilli()-Start)
      }
   }()
   str = resp.ReadAllString()
   return
}
func (s *Client) requestApi(ctx context.Context, method string, req interface{}) (str string, err error) {
   err = s.getAccessToken(ctx)
   if err != nil {
      return
   }
   str, err = s.post(ctx, method, req)
   return
}


管理token


  1. 注意看redis的使用
  2. token一般都是有有效期的,token应该缓存起来,不应该每次都请求获得新的token
  3. 刷新token一般有两种方式:一种是刷新token的有效期,一种是在有效期内使用旧token获得新token


type accessToken struct {
   AppKey           string `json:"appKey"`
   AccessToken      string `json:"access_token"`
   RefreshToken     string `json:"refresh_token"`
   ExpiresInSeconds int64  `json:"expiresInSeconds"`
   CreateTime       string `json:"createTime"`
}
//getAccessToken 获取token
func (s *Client) getAccessToken(ctx context.Context) (err error) {
   var token *accessToken
   cache, _ := g.Redis().DoVar("HGETALL", CacheKey)
   if !cache.IsEmpty() {
      _ = cache.Scan(&token)
      if gtime.NewFromStr(token.CreateTime).Timestamp()+token.ExpiresInSeconds > gtime.Timestamp()-3600 {
         s.AccessToken = token.AccessToken
         return
      }
      return s.refreshToken(ctx, token)
   }
   res, err := Token.Get(ctx)
   if err != nil {
      return
   }
   if res.Code != "4000" {
      err = errors.New(res.Message)
      return
   }
   _, err = g.Redis().Do("HMSET", append(g.Slice{CacheKey}, gutil.MapToSlice(gconv.Map(res.Data))...)...)
   if err != nil {
      logs.Errorf(ctx, pkgName, logs.FormatErr, err.Error())
   }
   s.AccessToken = res.Data.AccessToken
   return
}
//refreshToken 刷新token
func (s *Client) refreshToken(ctx context.Context, req *accessToken) (err error) {
   if gtime.NewFromStr(req.CreateTime).Timestamp()+req.ExpiresInSeconds < gtime.Timestamp() {
      _, err = g.Redis().DoVar("DEL", CacheKey)
      return s.getAccessToken(ctx)
   }
   res, err := Token.Refresh(ctx, req.RefreshToken)
   if err != nil {
      return
   }
   if res.Code != "4000" {
      err = errors.New(res.Message)
      return
   }
   _, _ = g.Redis().Do("HMSET", append(g.Slice{CacheKey}, gutil.MapToSlice(gconv.Map(res.Data))...)...)
   s.AccessToken = res.Data.AccessToken
   return
}


相关实践学习
基于Redis实现在线游戏积分排行榜
本场景将介绍如何基于Redis数据库实现在线游戏中的游戏玩家积分排行榜功能。
云数据库 Redis 版使用教程
云数据库Redis版是兼容Redis协议标准的、提供持久化的内存数据库服务,基于高可靠双机热备架构及可无缝扩展的集群架构,满足高读写性能场景及容量需弹性变配的业务需求。 产品详情:https://www.aliyun.com/product/kvstore &nbsp; &nbsp; ------------------------------------------------------------------------- 阿里云数据库体验:数据库上云实战 开发者云会免费提供一台带自建MySQL的源数据库&nbsp;ECS 实例和一台目标数据库&nbsp;RDS实例。跟着指引,您可以一步步实现将ECS自建数据库迁移到目标数据库RDS。 点击下方链接,领取免费ECS&amp;RDS资源,30分钟完成数据库上云实战!https://developer.aliyun.com/adc/scenario/51eefbd1894e42f6bb9acacadd3f9121?spm=a2c6h.13788135.J_3257954370.9.4ba85f24utseFl
相关文章
|
1月前
|
Go 调度 开发者
Go语言中的并发编程:深入理解与实践###
探索Go语言在并发编程中的独特优势,揭秘其高效实现的底层机制。本文通过实例和分析,引导读者从基础到进阶,掌握Goroutines、Channels等核心概念,提升并发处理能力。 ###
|
15天前
|
监控 Go API
Go语言在微服务架构中的应用实践
在微服务架构的浪潮中,Go语言以其简洁、高效和并发处理能力脱颖而出,成为构建微服务的理想选择。本文将探讨Go语言在微服务架构中的应用实践,包括Go语言的特性如何适应微服务架构的需求,以及在实际开发中如何利用Go语言的特性来提高服务的性能和可维护性。我们将通过一个具体的案例分析,展示Go语言在微服务开发中的优势,并讨论在实际应用中可能遇到的挑战和解决方案。
|
13天前
|
JSON API 数据格式
淘宝 / 天猫官方商品 / 订单订单 API 接口丨商品上传接口对接步骤
要对接淘宝/天猫官方商品或订单API,需先注册淘宝开放平台账号,创建应用获取App Key和App Secret。之后,详细阅读API文档,了解接口功能及权限要求,编写认证、构建请求、发送请求和处理响应的代码。最后,在沙箱环境中测试与调试,确保API调用的正确性和稳定性。
|
17天前
|
Prometheus 监控 Java
深入探索:自制Agent监控API接口耗时实践
在微服务架构中,监控API接口的调用耗时对于性能优化至关重要。通过监控接口耗时,我们可以识别性能瓶颈,优化服务响应速度。本文将分享如何自己动手实现一个Agent来统计API接口的调用耗时,提供一种实用的技术解决方案。
27 3
|
20天前
|
监控 安全 应用服务中间件
微服务架构下的API网关设计策略与实践####
本文深入探讨了在微服务架构下,API网关作为系统统一入口点的设计策略、实现细节及其在实际应用中的最佳实践。不同于传统的摘要概述,本部分将直接以一段精简的代码示例作为引子,展示一个基于NGINX的简单API网关配置片段,随后引出文章的核心内容,旨在通过具体实例激发读者兴趣,快速理解API网关在微服务架构中的关键作用及实现方式。 ```nginx server { listen 80; server_name api.example.com; location / { proxy_pass http://backend_service:5000;
|
25天前
|
XML API 网络架构
深入理解RESTful API设计原则与实践
【10月更文挑战第26天】在数字化浪潮中,API(应用程序编程接口)成为连接不同软件组件的桥梁。本文将深入浅出地探讨如何根据REST(Representational State Transfer)原则设计高效、易于维护和扩展的API,同时分享一些实用的代码示例,帮助开发者构建更加健壮和用户友好的服务。
|
1月前
|
Cloud Native Go API
Go语言在微服务架构中的创新应用与实践
本文深入探讨了Go语言在构建高效、可扩展的微服务架构中的应用。Go语言以其轻量级协程(goroutine)和强大的并发处理能力,成为微服务开发的首选语言之一。通过实际案例分析,本文展示了如何利用Go语言的特性优化微服务的设计与实现,提高系统的响应速度和稳定性。文章还讨论了Go语言在微服务生态中的角色,以及面临的挑战和未来发展趋势。
|
1月前
|
监控 安全 测试技术
如何确保API对接过程中的数据安全?
确保API对接过程中的数据安全至关重要。最佳实践包括:使用HTTPS协议、强化身份验证和授权、数据加密、输入验证、访问控制、限流限速、日志记录和监控、安全测试、数据脱敏、错误处理、API网关、Web应用程序防火墙(WAF)、审计和合规性。这些措施能有效提升API的安全性,保护数据免受恶意攻击和泄露风险。
|
1月前
|
Go 开发者
Go语言中的并发编程:从基础到实践
在当今的软件开发中,并发编程已经成为了一项不可或缺的技能。Go语言以其简洁的语法和强大的并发支持,成为了开发者们的首选。本文将带你深入了解Go语言中的并发编程,从基础概念到实际应用,帮助你掌握这一重要的编程技能。
|
22天前
|
NoSQL 测试技术 Go
自动化测试在 Go 开源库中的应用与实践
本文介绍了 Go 语言的自动化测试及其在 `go mongox` 库中的实践。Go 语言通过 `testing` 库和 `go test` 命令提供了简洁高效的测试框架,支持单元测试、集成测试和基准测试。`go mongox` 库通过单元测试和集成测试确保与 MongoDB 交互的正确性和稳定性,使用 Docker Compose 快速搭建测试环境。文章还探讨了表驱动测试、覆盖率检查和 Mock 工具的使用,强调了自动化测试在开源库中的重要性。
下一篇
无影云桌面