首页 > 其他分享 >美团闪购对接---授权

美团闪购对接---授权

时间:2023-04-05 17:47:08浏览次数:30  
标签:code string url 美团 --- 闪购 var new app

      .net 难道真的不行了吗?真无奈呀,上次做支付对接,官方示例没有C#语言案例,这次做美团和饿了吗对接也没有C#示例的影子,大多都是java和php示例。做支付的时候,可以在网上搜一些案例,也有开源的人家封装好的案例,做起来有样板容易很多。这次做美团接口对接。哎,让我无语了,C#案例的我一个都没搜到。在网上一根毛都找不到。突然没有案例,这让我这个程序小裁缝怎末办?没办法只能自己根据api文档慢慢调试了,还好做了好几年开发,老脸还是保住了,经过一番折腾,终于接通了。哈哈哈哈。。。

     要做美团接口对接,自己要注册一个开发者账号,不过要提交审核资质,注意:这个必须通过真正的企业去认证,过程中要上传营业执照的。这样审核才能通过。哎,真是搞不懂,你就不能给开发者留条路,设了这个门槛,要测试对接就没法做了。如果要测试只能审核通过才能申请一个测试门店。

     至于如何注册这里就不多说了,自己根据官方文档一步一步来就行了。注册好后,申请一个测试门店,通过后如下可以查看门店信息:

 

 

 

 

 

 

这里我们需要几个重要字段: 1,appid:应用Id  2app screte 应用密钥   3,三方门店ID

 有了这两个重要参数,接下来就是如何调用接口了,根据官方文档介绍,如果要调用接口,必须要获得ISV安全认证,也就是应用授权。如何授权,请看:https://open-shangou.meituan.com/home/guide/market/10686

 

 

 这个流程看起来很详细,但是操作起来就麻烦了,我大致说一下啊流程:

  OAuth认证要两种方式,一种是官方推荐使用的,需要两步才能获取access_token,一种是快捷方式,只需要一步就能获取access_token值。

   第一种方式:先调用https://waimaiopen.meituan.com/api/v1/oauth/authorize 获取Code值,然后在把Code值作为参数传入接口:https://waimaiopen.meituan.com/api/v1/oauth/token 获取acces_token值,后续调用其它接口都需要携带这个access_token值才能访问。

 

 

 

 

第二种方式:直接调用https://waimaiopen.meituan.com/api/v1/oauth/authorize 就可以获取access_token值。

 

 这两种方式唯一区别就是authorize 接口参数response_type的值不行同,如何response_type=  code 获取的就是code值,需要两部才能获取到access_token.  如果response_type=token 就会直接获取access_token值。不要以为这样就可以了,这个过程你还需要对传入的参数尽心加密,也就是生签,对应参数sig,这里的加密方式是用MD5 32位加密方式对url和参数一起进行加密。具体加密方式请看:(https://opendj.meituan.com/home/guide/market/10683 )注意这里坑很多,不要粗略的看,要仔细,参数拼接是按照参数字母拍寻拼接的,不是随意拼接参数。我这里举个例子。就以生成code为例:

   需要参数:

 

 注意这里面有坑,需要一个timestamp时间戳参数。而这里面并没有给。所以记得加上。

   第一步:拼接参数:注意:拼接的时候要按照参数字母排序,至于怎末排序,后续我会给方法。

  排序后后拼接参数:app_Id=123&app_poi_code=34223&response_type=code&timestamp=124324324

第二步:url+"?"+拼接后的参数+app secret(应用密钥)

    url+app_Id=123&app_poi_code=34223&response_type=code&timestamp=124324324+app secret(注意:这里直接把密钥值放在后面,不要加参数)

第三步:对整个url路径进行MD5加密;加密后获取sig值;

sig=md5(url+app_Id=123&app_poi_code=34223&response_type=code&timestamp=124324324+app secret)

第四步:在将sig作为参数放在url路径中:

 url+app_Id=123&app_poi_code=34223&response_type=code&timestamp=124324324&sig=sig值(注意:这里不要在app secret密钥了)

这里流程大概就是这样了。

下面直接上代码:

首先是Post和Get请求,已经封装好了,直接调用就行了。注意(美团开放接口用的https,所以请求的时候要忽略认证。代码我已经做了忽略认证了,可以直接用)

  public class HttpHelper
  {


    /// <summary>
    /// 
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="requestUrl"></param>
    /// <returns></returns>
    public async  static Task<T> DoGet<T>(string requestUrl, object paraModel) where T : new()
    {
      var res = new T();
      using (var httpClientHandler = new HttpClientHandler())
      {
        httpClientHandler.ServerCertificateCustomValidationCallback = (message, cert, chain, errors) => { return true; };
        using (var client = new HttpClient(httpClientHandler))
        {

          string url = GetUrl(requestUrl, paraModel);
          client.BaseAddress = new Uri(url);
          var result = await client.GetStringAsync(url);//.GetAwaiter().GetResult();
          res = (T)JsonConvert.DeserializeObject<T>(result);
        }
      }
      return res;
    }
    public static async Task<T> DoPost<T>(string requestUrl, object paraModel, string accessToken = "") where T : new()
    {
      var res = new T();
      using (var httpClientHandler = new HttpClientHandler())
      {
        httpClientHandler.ServerCertificateCustomValidationCallback = (message, cert, chain, errors) => { return true; };
        using (var client = new HttpClient(httpClientHandler))
        {
          try
          {
         
           
            string url = GetUrl(requestUrl, paraModel);
            HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Post,url);
            request.Headers.Add("Accept", "application/x-www-form-urlencoded");
            //if (!string.IsNullOrEmpty(accessToken))
            //{
            //  string value =$"Bearer {accessToken}";
            //  request.Headers.Add("Authorization", value);

            //}
              HttpResponseMessage response = client.SendAsync(request).Result;
              var respStr = await response.Content.ReadAsStringAsync();
              res = respStr.ToObject<T>();

          }
          catch (Exception ex)
          {

            throw;
          }
        }
      }
      return res;
    }

   /// <summary>
    /// 拼接Url请求路径(生成sig签名)
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="url"></param>
    /// <param name="TModel"></param>
    /// <returns></returns>
    public static string GetUrl<T>(string url, T TModel)
    {
      Hashtable hash = new Hashtable();
      var timestamp = DateTimeOffset.Now.ToUnixTimeSeconds();
      hash.Add("app_id", ConfigHelper.appid);
      hash.Add("timestamp", timestamp);
      if (TModel != null)
      {
        //取得m的Type实例
        Type t = TModel.GetType();
        //获取所有属性 
        PropertyInfo[] properties = t.GetProperties();

        //取得类的属性名并获取属性值
        foreach (PropertyInfo s in t.GetProperties())
        {
          hash.Add(s.Name, TModel.GetType().GetProperty(s.Name).GetValue(TModel, null).ToString());
        }
      }
      ArrayList keys = new ArrayList(hash.Keys);
      keys.Sort(); //按字母顺序进行排序
      string strSig = "";
      foreach (string key in keys)
      {
        if (key != null && key != "" && key != "sign")
        {
          strSig += "&" + key + "=" + hash[key];
        }
      }
      strSig = strSig.TrimStart('&');
      string strUrl = url + "?" + strSig ;
      string createSig = MD5Encrypt.Get32MD5(strUrl + ConfigHelper.appsecret).ToLower();
      string requestUrl = strUrl + "&sig=" + createSig;
      return requestUrl;
    }
   
  }

model 用来反序化返回值:

 public class AuthorizeResult
  {
    public int status { get; set; }
    public string code { get; set; }
    public string state { get; set; }
    public string message { get; set; }
  }

 md5 32位加密:

  /// <summary>
    /// 此代码示例通过创建哈希字符串适用于任何 MD5 哈希函数 (在任何平台) 上创建 32 个字符的十六进制格式哈希字符串
    /// 官网案例改编
    /// </summary>
    /// <param name="source"></param>
    /// <returns></returns>
    public static string Get32MD5(string source)
    {
      using (MD5 md5Hash = MD5.Create())
      {
        byte[] data = md5Hash.ComputeHash(Encoding.UTF8.GetBytes(source));
        StringBuilder sBuilder = new StringBuilder();
        for (int i = 0; i < data.Length; i++)
        {
          sBuilder.Append(data[i].ToString("x2"));
        }

        string hash = sBuilder.ToString();
        return hash.ToUpper();
      }
    }

 

业务处理:

  /// <summary>
    /// 获取商家授权码code的接口  (Get)
    /// </summary>
    public async static Task<AuthorizeResult> Authorize()
    {
      var model = new
      {
        app_poi_code = ConfigHelper.GoodId,    //门店代码。
        response_type = "code"                //授权方式,此处response_type=code。
      };
      var result = await HttpHelper.DoGet<AuthorizeResult>(ConfigHelper.GetAuthorize, model);
      return result;
    }

调用:

 var result = OauthAPI.Authorize().Result;

 

 

 

这里已经成功了,之所以报这个问题,是因为我已经获取的授权码了,如果授权码不过期,或者自己不调用刷新接口刷新。调用用就会出现已经发放的问题。

有一个案例后续其实都一样的。我对接了一笑部分,基本都差不多,封装好后就是直接调用了。

 

 

 

 

 

 对接美团接口的过程中,我发现美团的官方api是真的乱。

 1,参数部分没有明确说明:比如每次请求必带有appid和timestamp,但是api接口没有给。

2,参数返回值的类型,根本不统一,很乱。

3,出现层级参数,好多都需要转换成json字符串传入,不能传入对象。

 

标签:code,string,url,美团,---,闪购,var,new,app
From: https://www.cnblogs.com/zpy1993-09/p/17289737.html

相关文章

  • 第四十四篇 vue - 进阶主题 - 渲染函数 & JSX
    渲染函数&JSX在绝大多数情况下,Vue推荐使用模板语法来创建应用。然而在某些使用场景下,我们真的需要用到JavaScript完全的编程能力。这时渲染函数就派上用场了基本用法1、创建VnodesVue提供了一个h()函数用于创建vnodesimport{h}from'vue'constvnode=h(......
  • 第四十三篇 vue - 进阶主题 - 渲染机制
    渲染机制Vue是如何将一份模板转换为真实的DOM节点的,又是如何高效地更新这些节点的呢?我们接下来就将尝试通过深入研究Vue的内部渲染机制来解释这些问题虚拟DOM你可能已经听说过“虚拟DOM”的概念了,Vue的渲染系统正是基于这个概念构建的虚拟DOM(VirtualDOM,简称VDOM......
  • 第四十六篇 vue - 进阶主题 - 动画技巧
    动画技巧Vue提供了<Transition>和<TransitionGroup>组件来处理元素进入、离开和列表顺序变化的过渡效果。但除此之外,还有许多其他制作网页动画的方式在Vue应用中也适用。这里我们会探讨一些额外的技巧基于CSSclass的动画对于那些不是正在进入或离开DOM的元素,我们可......
  • 第四十五篇 vue - 进阶主题 - Vue 与 Web Components
    Vue与WebComponentsWebComponents是一组web原生API的统称,允许开发者创建可复用的自定义元素(customelements)Vue和WebComponents是互补的技术。Vue为使用和创建自定义元素提供了出色的支持。无论你是将自定义元素集成到现有的Vue应用中,还是使用Vue来构建和......
  • 第四十七篇 vue - vue2 和 vue3 的对比
    vue2和vue3不同点汇总1、生命周期2、多根节点3、CompositionApi4、异步组件5、响应式原理6、Teleport7、虚拟Dom8、事件缓存9、Diff算法优化10、打包优化11、TypeScript支持生命周期1、Vue3生命周期整体上变化不大,Vue3在大部分生命周期钩子名称......
  • Java笔记(9) GUI->Frame和Panel
    仅作为笔记GUI继承体系图Frame创建publicclassTest{publicstaticvoidmain(String[]args){//新建FrameFrameframe=newFrame("Thisisframetitle");//设置可见性frame.setVisible(true);//设置窗口大小frame.setSize(400,400);......
  • WebGL-实例化绘制
    今天来学习webgl一个重要功能:InstancedDrawing(实例化绘制),内容翻译自webgl学习网站webglfundamentals(由于英语水平尽量按原文翻译):https://webglfundamentals.org/webgl/lessons/webgl-instanced-drawing.html。WebGL下个版本(WebGL2.0)有一个功能叫实例化绘制。它的基本思想......
  • 【230405-5】有6名男医生,5名女医生,从中选出2名男生,一名女生组成一个医疗小组,则不同的
    ......
  • 信息系统项目管理师学习-230405 学习笔记
    1.第一章节信息的特征,动态性,依附性,传递性,主要这3个,其他的忽略。比如一个小狗,可以叫小狗,可以是个图片,可以是旺旺,体现了信息的依附性信息的质量属性,精确性、完整性、可靠性、及时性、经济行、可验证、安全。比如银行需要安全,市场上要及时性。香农定理简单看一下。 信息传......
  • 【230405-6】从4台甲型和5台乙型电视机取3台,其中至少有甲乙各一台,则不同的取法有几种?
    ......