微信JS-SDK实现微信会员卡功能(给用户微信卡包里发送会员卡)


Posted in Javascript onJuly 25, 2019

需求:点击我们公司的微信公众号,从菜单栏中进入会员中心,如果是新会员则需绑定注册,注册完跳转到用户中心页面,然后给用户发会员卡,如果是老会员,如果以前没有的会员卡的,发一张会员卡给他,如果有,则不做任何处理。
实现:我的思路是这样的,进入会员中心,调用微信API接口,判断用户是否领过卡,若没有领取,则调用微信JS-JDK的addCard()接口。具体实现过程如下(用C#实现):

1创建会员卡

1) 先打开微信开发者文档,先调用创建会员卡接口,在文档的4.1 创建会员卡接口,直接用postman,详情见文档。

微信JS-SDK实现微信会员卡功能(给用户微信卡包里发送会员卡)

创建的时候要特别注意”use_custom_code”: false,”bind_openid“:false两个字段

微信JS-SDK实现微信会员卡功能(给用户微信卡包里发送会员卡) 

第一个为是否自定义code,第二个是否绑定openid,这个很重要,很重要,很重要!!!因为后面调用JS-JDK的addCard接口所需要的签名会根据这两个的值决定是否加入openid和code进行签名的生成(被坑了很久)。后面会详细说明这个签名,先一步步来,记住这两个参数一定要注意。按照这个文档说明,创建会员卡应该没有什么问题,对了, “sku”: { “quantity”: 50000000 }这个是库存,要添加一点库存。

2调用微信JS-SDK

1)引入微信js

<script type="text/javascript" src="http://res.wx.qq.com/open/js/jweixin-1.2.0.js"></script>

2)通过config接口注入权限验证配置

<script>
  $(function () {
  //判断是否已经领取会员卡
    $.ajax({
        url: '/User/ExitCard',
        type: 'GET',
        success: function (data) {
         if (data.Status == 1) 
         //1代表没有存在卡,0代表存在卡
            wxAddCard();
        }
      });
  }

 //微信添加卡券
    function wxAddCard() {

       //微信sdk config
      wx.config({
        debug: false, // 开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。
        appId: '', // 必填,公众号的唯一标识
        timestamp: '', // 必填,生成签名的时间戳
        nonceStr: '', // 必填,生成签名的随机串
        signature: '',// 必填,签名,见附录1
        jsApiList: ['onMenuShareTimeline',
          'onMenuShareAppMessage',
          'onMenuShareQQ',
          'onMenuShareWeibo',
          'onMenuShareQZone',
          'startRecord',
          'stopRecord',
          'onVoiceRecordEnd',
          'playVoice',
          'pauseVoice',
          'stopVoice',
          'onVoicePlayEnd',
          'uploadVoice',
          'downloadVoice',
          'chooseImage',
          'previewImage',
          'uploadImage',
          'downloadImage',
          'translateVoice',
          'getNetworkType',
          'openLocation',
          'getLocation',
          'hideOptionMenu',
          'showOptionMenu',
          'hideMenuItems',
          'showMenuItems',
          'hideAllNonBaseMenuItem',
          'showAllNonBaseMenuItem',
          'closeWindow',
          'scanQRCode',
          'chooseWXPay',
          'openProductSpecificView',
          'addCard',
          'chooseCard',
          'openCard'] // 必填,需要使用的JS接口列表,所有JS接口列表见附录2
      });

        wx.ready(function () {
          wx.addCard({
            cardList: [{
              cardId: '',
              cardExt: '{"code":"","openid": "", "timestamp": "","nonce_str": "", "signature": ""}'
            }],
            success: function (res) {
              $.ajax({
                url: '/User/ActiveCard',
                type: 'GET',
                success: function (data) {
                  if (data.Status == 0)
                    alert("成功激活");
                }
              });
            },
            cancel: function (res) {
              alert(JSON.stringify(res))
            }
          });

        });

    }
 </script>

我这里是进入页面就调取接口看是否已经领卡,没有领卡,则调用微信接口,用户点击领取,然后调取激活接口,将会员卡激活,下面讲述签名的生成。

3)签名的配置

上一小节中的wx.config中appid为公众号的唯一标识,自己填自身微信公众号的,timestamp,nonceStr,signature三个签名其实就是为了加密吧。(以下代码都是用C#实现)
timestamp的生成:

/// <summary>
    /// 创建时间戳       ///本代码来自开源微信SDK项目:https://github.com/night-king/weixinSDK
    /// </summary>
    /// <returns></returns>
    public long CreatenTimestamp()
    {
      return (DateTime.Now.ToUniversalTime().Ticks - 621355968000000000) / 10000000;
    }

nonceStr的生成:

/// <summary>
    /// 创建随机字符串     ///本代码来自开源微信SDK项目:https://github.com/night-king/weixinSDK
    /// </summary>
    /// <returns></returns>
    public string CreatenNonce_str()
    {
      Random r = new Random();
      var sb = new StringBuilder();
      var length = strs.Length;
      for (int i = 0; i < 15; i++)
      {
        sb.Append(strs[r.Next(length - 1)]);
      }
      return sb.ToString();
    }

signature生成(这里是wx.config中的signature生成),signature签名的生成是由jsapi_ticket,noncestr,timestamp,url四个参数,先使用ASCII算法排序(其实就是看他们的字母顺序 j,n,t,u排序,如果首字母相等看第二位,以此类推),先等键进行排序,然后拼接例如jsapi_ticket=xxx&noncestr=&….我这里已经自己手动排序了,所以没实现ASCCII排序,排序完之后,使用sha1加密,代码如下:

/// <summary>
    /// 签名算法    ///本代码来自开源微信SDK项目:https://github.com/night-king/weixinSDK
    /// </summary>
    /// <param name="jsapi_ticket">jsapi_ticket</param>
    /// <param name="noncestr">随机字符串(必须与wx.config中的nonceStr相同)</param>
    /// <param name="timestamp">时间戳(必须与wx.config中的timestamp相同)</param>
    /// <param name="url">当前网页的URL,不包含#及其后面部分(必须是调用JS接口页面的完整URL)</param>
    /// <returns></returns>
    public string GetSignature(string jsapi_ticket, string noncestr, long timestamp, string url)
    {
      var string1Builder = new StringBuilder();
      string1Builder.Append("jsapi_ticket=").Append(jsapi_ticket).Append("&")
             .Append("noncestr=").Append(noncestr).Append("&")
             .Append("timestamp=").Append(timestamp).Append("&")
             .Append("url=").Append(url.IndexOf("#") >= 0 ? url.Substring(0, url.IndexOf("#")) : url);
      return ShaEncrypt.SHA1Encrypt(string1Builder.ToString()).ToLower();
    }
public static string SHA1Encrypt(string data)
    {
      //也给不了全部的代码,只需知道拼接后sha1加密 网上可以找到
      var hash = SHA1.Create();
      var encoder = new System.Text.ASCIIEncoding();
      var combined = encoder.GetBytes(data);
      var result = hash.ComputeHash(combined);

      StringBuilder strbul = new StringBuilder(40);
      for (int i = 0; i < result.Length; i++)
      {
        strbul.Append(result[i].ToString("x2"));//加密结果"x2"结果为32位,"x3"结果为48位,"x4"结果为64位

      }
      return strbul.ToString();
    }

返回wx.config所需要的四个参数appId,timestamp,nonceStr,signature。

没有意外的话可以成功,成功自动进入 wx.ready(function () {}中。

wx.addCard({
    cardList: [{
        cardId: '',//吧你前面创建会员卡成功返回的参数中的cardId写进去
        cardExt: '{"code":"","openid": "", "timestamp": "","nonce_str": "", "signature": ""}'
      }],
      success: function (res) {
        $.ajax({
          url: '/User/ActiveCard',
          type: 'GET',
          success: function (data) {
            if (data.Status == 0)
              alert("成功激活");
          }
        });
      },
      cancel: function (res) {
        alert(JSON.stringify(res))
      }
    });

cardExt的signature签名生成由你创建会员卡的时候设置的”use_custom_code”: false,”bind_openid“:false决定,当两个为false时,则吧 paramList.Add(code);paramList.Add(openId);注释掉,哪个为fasle,哪个就不要。
下面代码的api_ticket与上面的jsapi_ticket完全不同,不是同一个东西,我会最最下面放出他们获取的方法

//意思就是这里有几个参数,那么对应的上面的 paramList.Add();就要添加几个
//而这里的code和openid的填写与否取决与创建会员卡是填写的两个字段,上面已经提及
 cardExt: '{"code":"","openid": "", "timestamp": "","nonce_str": "", "signature": ""}'

意思就是这里有几个参数,那么对应的上面的 paramList.Add();就要添加几个,而这里的code和openid的填写与否取决与创建会员卡是填写的两个字段,上面已经提及


微信JS-SDK实现微信会员卡功能(给用户微信卡包里发送会员卡)

3.下面贴上面后台接口主要的代码

1)/User/ExitCard(post微信接口,然后根据返回消息判断是否已经领取卡,领取则为true,未领取则为false)

public bool ExitCard(string openId, string token,string code, string cardId)//token为access_token code为自定义code号
//code我这里是自定义的会员卡号
// cardId为创建会员卡时微信返回的cardId
   {

   var data = new Hashtable();
   data.Add("openid", openId);
   data.Add("card_id", cardId);
   var res = HttpHelper.HttpComm(
   string.Format("https://api.weixin.qq.com/card/user/getcardlist?access_token={0}", token),
     "POST",
     JSONHelper.ToJson(data));
   var resObj = JSONHelper.FromJsonToAnonymousType(res,
     new
     {
       error_code = 0,
       errmsg = "ok",
       has_share_card = false,
       card_list = Enumerable.Repeat(new { card_id = string.Empty, code = string.Empty }, 1).ToList()
     });
   //var resObj = JSONHelper.FromJsonTo<Dictionary<string, object>>(res);
   //object info = new object();
   //var str = resObj.TryGetValue("card_list", out info);
   if (resObj.card_list.Count == 0 || resObj.card_list == null)
     return false;
   var temp = false;
   for (var i = 0; i < resObj.card_list.Count; i++)
   {
     if (resObj.card_list[i].code == code)
     {
       temp = true;
       break;
     }
   }
   return temp;
    }

2)/User/ActiveCard(激活会员卡)

//激活会员卡
    public Boolean ActiveCard(string accessToken,string bonus,string cardNo,string cardId)
    //bonus为用户积分 cardNo 卡号 cardId卡ID
    {

      var data = new Hashtable();
      data.Add("init_bonus", bonus);
      data.Add("membership_number", cardNo);
      data.Add("code", cardNo);//上面跟这个设置相同,自定义code放在微信会员卡卡上面
      data.Add("card_id", cardId);
      var res = HttpHelper.HttpComm(
      string.Format("https://api.weixin.qq.com/card/membercard/activate?access_token={0}", accessToken),
        "POST",
        JSONHelper.ToJson(data));
      var resObj = JSONHelper.FromJsonToAnonymousType(res,new { errcode = "0", errmsg = "ok" });
      if (resObj.errcode == "0")
        return true;//激活成功
      return false;
    }

上面的HttpHelper.HttpComm只是一种自己封装定义的http请求的工具类,

自己去实现发送post请求即可,就不贴出来了。

4)总结与心得

总体流程大概就是如上,我觉得已经够详细了,写这篇博客的理由就是网上关于微信这一块的知识有,但是没有很详细的,让刚接触的人不知道如何下手,虽说看文档可以看懂,但是微信官方文档有很多坑,往往在文档中一个小小的细节就让人搞个大半天,而且报的错误都比较笼统,所以就打算自己写一份比较详细的,一个呢自己总结一下经验,有助于自身成长,另一个为后来人铺路,让他们少走点弯路,往后有机会接微信其他接口,会吧流程继续贴出来,以供参考。

获取api_ticket的微信接口:这里写链接内容

也就是在下图目录下的13.1,当然也可以在第二张图上找到,都是一样的

微信JS-SDK实现微信会员卡功能(给用户微信卡包里发送会员卡) 

微信JS-SDK实现微信会员卡功能(给用户微信卡包里发送会员卡)

获取jsapi_ticket的微信接口在附录一,也就是目录下的16节

这里写链接内容

微信JS-SDK实现微信会员卡功能(给用户微信卡包里发送会员卡)

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
使用TextRange获取输入框中光标的位置的代码
Mar 08 Javascript
jQuery最佳实践完整篇
Aug 20 Javascript
ajax处理php返回json数据的实例代码
Jan 24 Javascript
基于jQuery插件实现环形图标菜单旋转切换特效
May 15 Javascript
JS实现带有抽屉效果的产品类网站多级导航菜单代码
Sep 15 Javascript
JavaScript多并发问题如何处理
Oct 28 Javascript
谷歌showModalDialog()方法不兼容出现对话窗口的解决办法
Feb 15 Javascript
数据结构中的各种排序方法小结(JS实现)
Jul 23 Javascript
jquery基本选择器匹配多个元素的实现方法
Sep 05 Javascript
JS ES6中setTimeout函数的执行上下文示例
Apr 27 Javascript
jQuery、layer实现弹出层的打开、关闭功能
Jun 28 jQuery
webpack 动态批量加载文件的实现方法
Mar 19 Javascript
微信小程序实现收货地址左滑删除
Nov 18 #Javascript
jquery-ui 进度条功能示例【测试可用】
Jul 25 #jQuery
微信小程序实现左滑动删除效果
Mar 30 #Javascript
jquery ui 实现 tab标签功能示例【测试可用】
Jul 25 #jQuery
小程序实现左滑删除效果
Jul 25 #Javascript
微信公众号获取用户地理位置并列出附近的门店的示例代码
Jul 25 #Javascript
详解Vue.js和layui日期控件冲突问题解决办法
Jul 25 #Javascript
You might like
屏蔽机器人从你的网站搜取email地址的php代码
2012/11/14 PHP
PHP获取php,mysql,apche的版本信息示例代码
2014/01/16 PHP
php单元测试phpunit入门实例教程
2017/11/17 PHP
PHP时间日期增减操作示例【date strtotime实现加一天、加一月等操作】
2018/12/21 PHP
js中将URL中的参数提取出来作为对象的实现代码
2011/08/16 Javascript
表格单元格交错着色实现思路及代码
2013/04/01 Javascript
jquery ui dialog实现弹窗特效的思路及代码
2013/08/03 Javascript
js判断undefined类型,undefined,null, 的区别详细解析
2013/12/16 Javascript
javascipt:filter过滤介绍及使用
2014/09/10 Javascript
jQuery+PHP+MySQL实现无限级联下拉框效果
2016/02/19 Javascript
jQuery代码性能优化的10种方法
2016/06/21 Javascript
AngularJS 路由详解和简单实例
2016/07/28 Javascript
vue页面使用阿里oss上传功能的实例(二)
2017/08/09 Javascript
node通过express搭建自己的服务器
2017/09/30 Javascript
详解vue 数组和对象渲染问题
2018/09/21 Javascript
详解Vue一个案例引发「内容分发slot」的最全总结
2018/12/02 Javascript
微信小程序地图导航功能实现完整源代码附效果图(推荐)
2019/04/28 Javascript
react结合bootstrap实现评论功能
2020/05/30 Javascript
Python中除法使用的注意事项
2014/08/21 Python
Python使用Pycrypto库进行RSA加密的方法详解
2016/06/06 Python
python实现决策树ID3算法的示例代码
2018/05/30 Python
PyTorch: 梯度下降及反向传播的实例详解
2019/08/20 Python
vscode 配置 python3开发环境的方法
2019/09/19 Python
python实现while循环打印星星的四种形状
2019/11/23 Python
使用Pyhton集合set()实现成果查漏的例子
2019/11/24 Python
利用Python实现Json序列化库的方法步骤
2020/09/09 Python
python如何实现图片压缩
2020/09/11 Python
使用Python实现音频双通道分离
2020/12/25 Python
美体小铺加拿大官方网站:The Body Shop加拿大
2016/10/30 全球购物
Opodo英国旅游网站:预订廉价航班、酒店和汽车租赁
2018/07/14 全球购物
荷兰游戏商店:Allyouplay
2019/03/16 全球购物
电子商务专业毕业生工作推荐信
2013/11/17 职场文书
区域销售经理岗位职责
2013/12/10 职场文书
作风建设剖析材料
2014/10/06 职场文书
2014年保洁工作总结
2014/11/24 职场文书
Python开发五子棋小游戏
2022/04/28 Python