Go对接三方API实践

本文涉及的产品
云数据库 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语言性能优化实践:案例分析与解决方案
【2月更文挑战第18天】本文将通过具体的案例分析,探讨Go语言性能优化的实践方法和解决方案。我们将分析几个典型的性能瓶颈问题,并详细介绍如何通过优化代码、调整并发模型、改进内存管理等方式来提升程序的性能。通过本文的学习,读者将能够掌握一些实用的Go语言性能优化技巧,为实际项目开发中的性能优化工作提供指导。
|
1月前
|
运维 网络协议 安全
长连接网关技术专题(十):百度基于Go的千万级统一长连接服务架构实践
本文将介绍百度基于golang实现的统一长连接服务,从统一长连接功能实现和性能优化等角度,描述了其在设计、开发和维护过程中面临的问题和挑战,并重点介绍了解决相关问题和挑战的方案和实践经验。
84 1
|
7天前
|
API Go
使用Go语言通过API获取代理IP并使用获取到的代理IP
使用Go语言通过API获取代理IP并使用获取到的代理IP
|
16天前
|
JSON 监控 API
在API接口对接中关键示例问题(1)
在API接口对接中,有几个关键的问题需要注意,以确保接口的稳定性、安全性和易用性。以下是这些问题及部分示例代码的简要概述
|
27天前
|
XML JSON 安全
谈谈你对RESTful API设计的理解和实践。
RESTful API是基于HTTP协议的接口设计,通过URI标识资源,利用GET、POST、PUT、DELETE等方法操作资源。设计注重无状态、一致性、分层、错误处理、版本控制、文档、安全和测试,确保易用、可扩展和安全。例如,`/users/{id}`用于用户管理,使用JSON或XML交换数据,提升系统互操作性和可维护性。
18 4
|
1月前
|
消息中间件 缓存 API
微服务架构下的API网关性能优化实践
在现代的软件开发中,微服务架构因其灵活性和可扩展性被广泛采用。随着服务的细分与增多,API网关作为微服务架构中的关键组件,承担着请求路由、负载均衡、权限校验等重要职责。然而,随着流量的增长和业务复杂度的提升,API网关很容易成为性能瓶颈。本文将深入探讨API网关在微服务环境中的性能优化策略,包括缓存机制、连接池管理、异步处理等方面的具体实现,旨在为开发者提供实用的性能提升指导。
|
1月前
|
缓存 负载均衡 监控
构建高效微服务架构:API网关的作用与实践
【2月更文挑战第31天】 在当今的软件开发领域,微服务架构已成为实现系统高度模块化和易于扩展的首选方法。然而,随着微服务数量的增加,确保通信效率和管理一致性变得尤为重要。本文将探讨API网关在微服务架构中的核心角色,包括其在请求路由、安全性、负载均衡以及聚合功能方面的重要性。我们将通过具体案例分析,展示如何利用API网关优化后端服务,并讨论实施过程中的最佳实践和常见挑战。
|
1月前
|
搜索推荐 数据挖掘 API
1688商品详情API在电商平台中的应用与实践
随着电子商务的迅猛发展,越来越多的商家选择利用API(应用程序编程接口)来提升其在线业务的效率和用户体验。特别是在商品信息展示方面,1688商品详情API作为连接商家和消费者的重要桥梁,扮演着至关重要的角色。本文将深入探讨1688商品详情API的功能、应用场景以及如何通过该API提高电商平台的商品信息展示质量。
|
1月前
|
人工智能 JavaScript API
互联网人的福利!『昆仑天工』4款AI产品开源!提供API对接!
互联网人的福利!『昆仑天工』4款AI产品开源!提供API对接!
180 0
|
1月前
|
Kubernetes Go 开发者
Go语言与Docker容器结合的实践应用与案例分析
【2月更文挑战第23天】本文通过分析实际案例,探讨了Go语言与Docker容器技术结合的实践应用。通过详细阐述Go语言在容器化环境中的开发优势,以及Docker容器技术在Go应用部署中的重要作用,本文旨在为读者提供Go语言与Docker容器结合的具体实现方法和实际应用场景。