文章目录

  • 微信公众号生成个性化推广二维码
    • 目标
    • 环境要求
    • 实现思路
    • 获取二维码流程
      • 概述
      • 获取ticket
      • 获取二维码下载地址
    • 代码实现
      • 核心代码
      • 运行结果

微信公众号生成个性化推广二维码

目标

针对不同的推广场景,生成特定的公众号二维码,以便系统统计用户来源,提供个性化服务;

环境要求

  1. 后台语言:Java
  2. IDE:IDEA
  3. JDK:1.8
  4. 微信服务号

实现思路

通过微信公众号提供的生成带参数的二维码来实现用户来源的识别。

目前有两类带参数的二维码:

  1. 临时二维码,是有过期时间的,最长可以设置为在二维码生成后的30天(即2592000秒)后过期,但能够生成较多数量。临时二维码主要用于帐号绑定等不要求二维码永久保存的业务场景
  2. 永久二维码,是无过期时间的,但数量较少(目前为最多10万个)。永久二维码主要用于适用于帐号绑定、用户来源统计等场景。

当用户扫描带场景的二维码时,微信系统将向响应系统(什么是微信系统和响应系统?点击传送门)推送以下两种事件:

  1. 已关注用户将自动进入会话,微信系统将向响应系统推送带有场景值的扫描事件;
  2. 未关注用户则会先进入关注页面,如果用户选择关注公众号,那么微信系统将先推送关注事件给响应系统,然后再推送带有场景值的扫描事件;

获取二维码流程

概述

获取二维码一共分两步:

  1. 获取ticket:每次创建二维码ticket需要提供一个开发者自行设定的参数(scene_id),也就是场景值,该值即为响应系统接收扫描事件的场景值,该值可以为整型数字,可以为字符串;
  2. 通过ticket换取二维码:通过ticket换取二维码下载地址,该地址任何人都可访问;

获取ticket

因为有两种二维码,所以也有两种ticket

获取临时二维码ticket:

请求方式: POST
地址: https://api.weixin.qq.com/cgi-bin/qrcode/create?access_token=TOKEN
数据格式:json
数据示例:场景值为整型数字:{"expire_seconds": 604800, "action_name": "QR_SCENE", "action_info": {"scene": {"scene_id": 123}}}场景值为字符串:{"expire_seconds": 604800, "action_name": "QR_STR_SCENE", "action_info": {"scene": {"scene_str": "test"}}}

获取永久二维码ticket:

请求方式: POST
地址: https://api.weixin.qq.com/cgi-bin/qrcode/create?access_token=TOKEN
数据格式:json
数据示例:场景值为整型数字:{"action_name": "QR_LIMIT_SCENE", "action_info": {"scene": {"scene_id": 123}}}场景值为字符串:{"action_name": "QR_LIMIT_STR_SCENE", "action_info": {"scene": {"scene_str": "test"}}}

返回结果说明:

{"ticket":"gQH47joAAAAAAAAAASxodHRwOi8vd2VpeGluLnFxLmNvbS9xL2taZ2Z3TVRtNzJXV1Brb3ZhYmJJAAIEZ23sUwMEmm
3sUw==","expire_seconds":60,"url":"http://weixin.qq.com/q/kZgfwMTm72WWPkovabbI"}

首先贴上官方对参数的说明:

参数 说明
expire_seconds 该二维码有效时间,以秒为单位。 最大不超过2592000(即30天),此字段如果不填,则默认有效期为30秒。
action_name 二维码类型,QR_SCENE为临时的整型参数值,QR_STR_SCENE为临时的字符串参数值,QR_LIMIT_SCENE为永久的整型参数值,QR_LIMIT_STR_SCENE为永久的字符串参数值
action_info 二维码详细信息
scene_id 场景值ID,临时二维码时为32位非0整型,永久二维码时最大值为100000(目前参数只支持1–100000)
scene_str 场景值ID(字符串形式的ID),字符串类型,长度限制为1到64

个人觉得不好理解的是action_name。

首先我们可以发现获取临时和永久ticket的地址是一样的!这说明我们需要传递一些信息告诉微信系统我们需要的是什么;然后我们可以发现的就是json的属性不一样,于是就产生了这样的疑问:是不是通过expire_seconds这个字段判断的呢?

接下里看参数说明,action_name的介绍为:“QR_SCENE为临时的整型参数值”。我没明白的是QR_SCENE到底是一个整型参数值,还是一个标记值。因为看到了参数值,所以就理解为“可变”的了,加上我们也的确有判断是否是永久的方法(expire_seconds存在与否),于是似乎理所当然。。。就出错了。

事实上,它是一个标记值,也就是微信系统应该是通过action_name来判断我们的目的是什么。不过问题也不大,程序跑起来就能明白这个问题到底是什么了,因为随意指定该属性的值会抛错:“invalid action name”;

获取二维码下载地址

获得ticket的同时,我们也获得了一个URL,这个URL即为二维码解析后的地址,此时我们就可以自己为该地址生成二维码图片了,比如美化一下什么的。不过我们也可以从微信系统那里获取下载地址。

GET请求(请使用https协议)https://mp.weixin.qq.com/cgi-bin/showqrcode?ticket=TICKET
提醒:TICKET记得进行UrlEncode

访问该地址即可获得对应场景、对应生命周期的二维码图片下载地址;

代码实现

核心代码

public class Main {public static void main(String[] args){//获取临时推广、场景值为字符串的二维码String temporaryQRCodeUrl= WeChatQRCodeManager.getTemporaryStrQRCodeDownloadUrl("teacher_wang");System.out.println(temporaryQRCodeUrl);//获取永久推广、场景值为字符串的二维码String permanentQRCodeUrl= WeChatQRCodeManager.getPermanentStrQRCodeDownloadUrl("teacher_liu");System.out.println(permanentQRCodeUrl);//获取临时推广、场景值为整型的二维码temporaryQRCodeUrl= WeChatQRCodeManager.getTemporaryIntQRCodeDownloadUrl(120);System.out.println(temporaryQRCodeUrl);//获取永久推广、场景值为整型的二维码permanentQRCodeUrl= WeChatQRCodeManager.getPermanentIntQRCodeDownloadUrl(119);System.out.println(permanentQRCodeUrl);}
}
public class WeChatQRCodeManager {/*** 获取临时特定场景推广二维码下载地址* @param sceneStr 临时特定场景的字符串标记* @return 二维码的下载地址* @see QRCodeInfo*/public static String getTemporaryStrQRCodeDownloadUrl(String sceneStr){QRCodeInfo info=new QRCodeInfo(false);info.setSceneStrId(sceneStr);return getQRCodeDownloadUrl(info);}/*** 获取永久特定场景推广二维码下载地址* @param sceneStr 永久特定场景的字符串标记* @return 二维码的下载地址* @see QRCodeInfo*/public static String getPermanentStrQRCodeDownloadUrl(String sceneStr){QRCodeInfo info=new QRCodeInfo(true);info.setSceneStrId(sceneStr);return getQRCodeDownloadUrl(info);}/*** 获取临时特定场景推广二维码下载地址* @param sceneInt 临时特定场景的整型标记* @return 二维码的下载地址* @see QRCodeInfo*/public static String getTemporaryIntQRCodeDownloadUrl(int sceneInt){QRCodeInfo info=new QRCodeInfo(false);info.setSceneIntId(sceneInt);return getQRCodeDownloadUrl(info);}/*** 获取永久特定场景推广二维码下载地址* @param sceneInt 永久特定场景的整型标记* @return 二维码的下载地址* @see QRCodeInfo*/public static String getPermanentIntQRCodeDownloadUrl(int sceneInt){QRCodeInfo info=new QRCodeInfo(true);info.setSceneIntId(sceneInt);return getQRCodeDownloadUrl(info);}/*** 获取二维码下载地址* @param info 二维码信息载体* @return 二维码下载地址* @see QRCodeInfo*/private static String getQRCodeDownloadUrl(QRCodeInfo info) {String responseString= HttpUtils.doPostJson(WeChatUrlManager.getQrCodeTicketUrl(),info.toJsonString());String ticket= JsonUtils.getTargetStringInfo("ticket",responseString);return WeChatUrlManager.getQrCodeUrl(ticket);}
}
/*** @author Shao Lixuan  2019/3/7 16:43*/
public class QRCodeInfo {private int expireSeconds;private String sceneStrId;private boolean isTemporary;private int sceneIntId;private boolean sceneIsStr;public QRCodeInfo(boolean temporary){isTemporary=temporary;sceneIsStr=true;}public boolean isTemporary() {return isTemporary;}public void setTemporary(boolean temporary) {isTemporary = temporary;}public int getExpireSeconds() {return expireSeconds;}public void setExpireSeconds(int expireSeconds) {this.expireSeconds = expireSeconds;}public String getSceneStrId() {return sceneStrId;}public void setSceneStrId(String sceneStrId) {this.sceneStrId = sceneStrId;sceneIsStr=true;}public int getSceneIntId() {return sceneIntId;}public void setSceneIntId(int sceneIntId) {this.sceneIntId = sceneIntId;sceneIsStr=false;}public String toJsonString(){String template;if(isTemporary){if(sceneIsStr) {template = "{\"expire_seconds\": %d, \"action_name\":\"QR_STR_SCENE\", \"action_info\": {\"scene\": {\"scene_str\": \"%s\"}}}";return String.format(template, expireSeconds, sceneStrId);}else{template = "{\"expire_seconds\": %d, \"action_name\":\"QR_SCENE\", \"action_info\": {\"scene\": {\"scene_str\": %d}}}";return String.format(template, expireSeconds, sceneIntId);}}else {if(sceneIsStr) {template = "{\"action_name\": \"QR_LIMIT_STR_SCENE\", \"action_info\": {\"scene\": {\"scene_str\": \"%s\"}}}";return String.format(template, sceneStrId);}else{template = "{\"action_name\": \"QR_LIMIT_SCENE\", \"action_info\": {\"scene\": {\"scene_str\": %d}}}";return String.format(template, sceneStrId);}}}
}

运行结果

https://mp.weixin.qq.com/cgi-bin/showqrcode?ticket=gQGh8TwAAAAAAAAAAS5odHRwOi8vd2VpeGluLnFxLmNvbS9xLzAyQllPSkFXRnVmRUMxMDAwMHcwN0QAAgRA5IBcAwQAAAAA
https://mp.weixin.qq.com/cgi-bin/showqrcode?ticket=gQGG8DwAAAAAAAAAAS5odHRwOi8vd2VpeGluLnFxLmNvbS9xLzAyMEtZaEJYRnVmRUMxS3NBMTFzY18AAgRg5IFcAwQ8AAAA
https://mp.weixin.qq.com/cgi-bin/sho wqrcode?ticket=gQHH8TwAAAAAAAAAAS5odHRwOi8vd2VpeGluLnFxLmNvbS9xLzAyaGFiTEFiRnVmRUMxMDAwMGcwM1EAAgTj04FcAwQAAAAA
https://mp.weixin.qq.com/cgi-bin/showqrcode?ticket=gQGK8DwAAAAAAAAAAS5odHRwOi8vd2VpeGluLnFxLmNvbS9xLzAyRVZNMUJTRnVmRUMxS3NBMXhzMW4AAgRg5IFcAwQ8AAAA

项目源码CSDN下载

微信公众号生成个性化推广二维码相关推荐

  1. 微信公众号扫描带参数二维码实现自动分组?

    2019独角兽企业重金招聘Python工程师标准>>> 最近很多人都在问微信公众号扫描带参数二维码实现自动分组,通过微号帮平台操作实现,这个功能不止如此,微信二维码来源统计分析.微信 ...

  2. Java实现微信公众号直接发送参数二维码给用户

    文章目录 前言 一.参数二维码的作用 二.功能实现 1. 生成带参数二维码 2. 上传二维码图片 3. 发送带参数二维码给用户 总结 前言 公众号开发近些年是一个比较热门的方向,今天为大家讲解的是用J ...

  3. 微信公众号扫描带参数二维码实现自动分组

    学习交流: CSDN资源下载地址:https://download.csdn.net/download/naruto668/10624558 之前的几个老客户找到我最近要做一个微信公众号生成带参数海报 ...

  4. 微信公众号开发:渠道二维码生成/粉丝来源归属统计打标签

    作为一个运营人?离不开一个话题:推广公号.每天打开公号后台第一眼:粉丝数 继续点开,统计--用户分析 用户增长:昨日/每天,每一样的数据(新增,取关,净增,累积) 用户属性:性别,年龄,地域等 那如果 ...

  5. 微信公众号开发,扫描二维码事件推送丢失参数问题

    需求场景: 每个用户都有自己的推广二维码,分享自己推广二维码,别人扫码后跳转关注公众号,关注后绑定推荐关系. 用到技术点: 1.生成带参数二维码 2.接收事件推送,这里主要是关注和扫带参数二维码两个事 ...

  6. 微信渠道二维码怎么做?微信公众号怎么做渠道二维码?

    因为公众平台没有生成渠道二维码功能,如果想要实现公众号的渠道二维码,可以用第三方平台微号帮提供的渠道二维码生成在线功能实现,渠道二维码主要用于统计各个渠道来源的粉丝,为公众号实现精准化推广,为公众号节 ...

  7. 渠道码是什么意思?微信公众号怎么设置渠道二维码?

    渠道码是一种带参数的二维码,可以自动统计到渠道引流效果,可以对公众号的粉丝来源渠道进行统计. 渠道码的作用一般包括自定义回复.粉丝标签自定义管理.粉丝来源数据自动统计. 我们在公众号推广时可以使用渠道 ...

  8. 最新在线客服系统php代码微信软件公众号小程序app二维码聊天网站源码

    最新在线客服系统php代码微信软件公众号小程序app二维码聊天网站源码 管理界面 独家长期更新日志(欢迎反馈BUG) 1.添加手机端前后台声音提示 2.添加后台客户管理显示在线离线 3.添加清空当前对 ...

  9. 微信公众号 订阅号 生成带参数二维码

    1.公众号的任意一篇文章页链接 例如: http://mp.weixin.qq.com/s?__biz=MjM5NzAwNzMwMQ==&mid=2655787844&idx=3&am ...

  10. 利用微信公共号的带参数二维码做(扫码登录)

    <script type="text/javascript">var t2 ='';$(function() {var rand = parseInt(Math.ran ...

最新文章

  1. 基于macos的Homebrew常用命令和使用教程(你得看❤️)
  2. numpy.arange详解
  3. 事务策略: 了解事务陷阱--转
  4. 分摊、分配、定期重过账
  5. Oracle ASM Cluster File Systems (ACFS)应用指南
  6. python--Time(时间)模块
  7. .NET中多线程调试的一个办法
  8. 模拟——生活大爆炸版石头剪刀布(洛谷 P1328)
  9. Linux中main和初启函数,main 中的 argv和argc 到底是个啥意思?
  10. QMutexLocker作用范围
  11. ORACLE 指令基础学习
  12. 爆销产品标题怎么写_7个让销量暴增的商品标题文案套路
  13. 动态域名解析NAT版结合绿盾加密解密软件使用方法
  14. 「教程」Windows程序未响应,怎么分析确认具体原因
  15. 微信小程序 时间轴(时间线)特效
  16. swoole php配置文件,EasySwoole分离配置文件
  17. 2022煤炭生产经营单位(安全生产管理人员)判断题及在线模拟考试
  18. android命令大全 pdf,android调试桥(adb)常用命令.pdf
  19. MySQL数据库 引擎
  20. 如何正确的对安卓手机进行数据恢复?

热门文章

  1. GATK RNA-Seq Snps Indel 分析
  2. 笔记本dns服务器怎么修改,笔记本电脑DNS怎么设置
  3. 国产linux系统对打印机的支持,Linux系统下对打印机进行配置
  4. Sqlite3实现脏读
  5. 测试工程之测试计划之里程碑计划
  6. 使用流程图描述程序的功能与流程
  7. Ctfhub解题 彩蛋
  8. 计算机声卡驱动程序,教大家如何安装声卡驱动【详细步骤】
  9. ipv6单播地址包括哪两种类型_IPV6详细讲解
  10. 18104 练习使用多case解题(3种多case的情况)(c语言或c++)