Loading [MathJax]/jax/output/CommonHTML/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >专栏 >微信公众号发布提醒(微信公众号模板消息接口)

微信公众号发布提醒(微信公众号模板消息接口)

作者头像
全栈程序员站长
发布于 2022-07-26 01:26:19
发布于 2022-07-26 01:26:19
12.2K00
代码可运行
举报
运行总次数:0
代码可运行

大家好,又见面了,我是你们的朋友全栈君。

本文主要内容:
  • 1. 项目简介
    • 功能描述:
    • 特点对比

  • 2. 项目截图
  • 3. 开发准备
    • 3.1 开发工具
    • 3.2 环境支持
      • 1、获取公众号开发信息:
      • 2、设置IP白名单
      • 3、配置域名
      • 4、添加开发者
  • 4. 官方参考文档解读
    • 4.1 网页授权登录解读
      • 1. 获取code
      • 2. 换取access_token
      • 3. 获取用户信息
    • 4.2 模板消息推送解读
      • 1. 获取基础access_token
      • 2. 发送消息模板
  • 5. 网页授权登录实现(PHP为例)
    • 5.1 工具类GetWX
    • 5.2 获取code
    • 5.3 换取access_token
    • 5.4 获取用户信息
    • 5.5 另一种完整的示例
  • 6. 模板消息推送实现(PHP为例)
    • 6.1 官方JSSDK文档(PHP)
    • 6.2 模板消息JSON
    • 6.3 发送模板消息
  • 7. 后记与源码

1. 项目简介

灵感来源于学校的 每日健康日报,要求使用微信小程序进行每日健康打卡。所以此项目的功能类似于 QQ群机器人,或者是 每日闹钟

功能描述:

用户访问给定的页面,进行 授权登录 ,然后确认自己的身份(本科生或研究生),并 开启通知 ,即可每天在约定时间收到微信服务号的消息提醒。当然,用户可以自定义每日通知的时间,也可以随时开启或关闭每日通知。

特点对比
  • 和QQ群机器人、闹钟相比,该功能的实现,方便用户一键直达小程序
  • 但是该方法需关注服务号,同时开发门槛较高。

2. 项目截图

左图:用户订阅的页面,中图:用户修改通知时间的页面,右图:用户收到的消息提醒

3. 开发准备

3.1 开发工具

1、编码工具:用于项目开发。如果使用 Java 实现,可使用 IntelliJ IDEA,如果使用 PHP 开发,可使用 JetBrains PhpStorm

2、运行工具:用于本地测试。如果是PHP开发,可选择phpstudy_pro作为PHP项目的运行部署环境;

3、测试工具:只能使用 微信开发者工具 ,开发模式选择 公众号网页调试

微信开发者工具下载地址:https://developers.weixin.qq.com/miniprogram/dev/devtools/download.html

因为涉及到微信授权登录功能,所以测试工具必须使用 微信开发者工具,而普通浏览器无法实现该功能。

微信开发者工具的使用和调试方法,与普通浏览器一致

3.2 环境支持

1、任意域名一枚,需要开启SSL(即https访问);

2、微信服务号一个,必须通过认证;

3、具有外网IP的服务器一台。

如果仅仅是学习技术,满足前两项即可。如果项目需要上线,上述三者必不可少。 对于第2条,没有服务号,也可以在微信开放平台 中创建网站应用。不过微信开放平台同样需要企业认证。

在上述环境均满足的情况下,接下来需要对微信服务号进行一些配置。主要有:

1、获取公众号开发信息:

公众号的开发信息主要是 开发者ID(AppID)开发者密码(AppSecret)

某些接口必须使用开发者ID和开发者密码才能进行调用请求。

获取路径是:微信公众号后台 → 开发 → 基本配置

2、设置IP白名单

只有IP白名单中的IP地址才可以调用 获取access_token接口,其中access_token是进行其他操作,如发送消息模板等的必备参数。

3、配置域名

配置域名的页面访问路径是:公众号后台 → 设置 → 公众号设置 → 功能设置

需要配置的域名主要有三个:

① 业务域名

设置业务域名后,在微信内访问该域名下页面时,不会被重新排版。用户在该域名上进行输入时,不出现安全提示。比如在微信内打开网页,输入表单的时候,不会出现“请勿输入QQ密码”等安全提示。

② JS接口安全域名

设置JS接口安全域名后,公众号开发者可在该域名下调用微信开放的JS接口。比如前文中的access_token的获取,需要使用此域名。

③ 网页授权域名

用户在网页授权页同意授权给公众号后,微信会将授权数据传给一个回调页面,回调页面需在此域名下,以确保安全可靠。

4、添加开发者

只有已添加的开发者,才可以使用web开发者工具进行对应公众号的开发和调试。

添加开发者页面的访问路径是:微信公众号后台 → 开发 → 开发者工具 → web开发者工具

5、添加模板

添加功能插件模块中,添加模板消息功能

然后在模板库中,搜索合适的模板,进行添加:

其中模板ID是开发用到的参数。

4. 官方参考文档解读

关于微信公众号的开发技术,及其实现路线,在官网中均有介绍。

官方文档:https://developers.weixin.qq.com/doc/offiaccount/Getting_Started/Overview.html

打开官方开发文档,第一单元标题为开发前必读,开发者规范和全局返回码说明章节还是有必要读一读的

开发时,不能违反微信的相关规范,否则容易被封号,然后全局返回码可以帮助快速定位问题所在。

4.1 网页授权登录解读

打开官方开发文档,第5章微信网页开发中,第2节即为网页授权的参考文档。

直达链接:https://developers.weixin.qq.com/doc/offiaccount/OA_Web_Apps/Wechat_webpage_authorization.html

该章节的目录之前,有一段关于网页授权的一些说明。

第一点关于网页授权回调域名的说明,即前文中关于域名的配置。 第二点关于网页授权的两种scope的区别说明,主要说明的是两种授权模式,一种是静默登录授权形式,这种形式只能获取到用户的OpenID,另一种是获取用户基本信息的形式,这种形式会弹窗,需要用户手动点击登录。两种实现方式,主要是修改登录链接中的scope参数的值。后文详述。 第三点关于网页授权access_token和普通access_token的区别,可参考文档。其实主要说明的是网页授权access_token的安全性更高,必须通过code来获取access_token,而且不同code获取的access_token不同,每一个access_token有效期2小时(7200秒),每个access_token在这2小时内,只对同一个用户有效。而普通access_token(即基础支持中的“获取access_token”接口获取到的)可以直接获取,不同场景可重复使用,有效期也为2小时,过时需要刷新。

具体而言,网页授权流程分为四步:

1、引导用户进入授权页面同意授权,获取code

2、通过code换取网页授权access_token(与基础支持中的access_token不同)

3、如果需要,开发者可以刷新网页授权access_token,避免过期

4、通过网页授权access_token和openid获取用户基本信息(支持UnionID机制)

1. 获取code

首先需要使用户访问如下链接,才能进行登录:

https://open.weixin.qq.com/connect/oauth2/authorize?appid=APPID&redirect_uri=REDIRECT_URI&response_type=code&scope=SCOPE&state=STATE#wechat_redirect

该链接中,大写字母标识的字段,需要进行替换(下同)。

上述链接中的各个参数详细说明如下:

参数

是否必须

说明

appid

公众号的唯一标识

redirect_uri

授权后重定向的回调链接地址, 请使用 urlEncode 对链接进行处理

response_type

返回类型,只能填写code

scope

应用授权作用域,只能为snsapi_base (不弹出授权页面,直接跳转,只能获取用户openid)或snsapi_userinfo(弹出授权页面,可通过openid拿到昵称、性别、所在地。并且, 即使在未关注的情况下,只要用户授权,也能获取其信息 )

state

重定向后会带上state参数,开发者可以填写a-zA-Z0-9的参数值,最多128字节

#wechat_redirect

无论直接打开还是做页面302重定向时候,必须带此参数

用户确定登录后,即可在授权后重定向的回调链接地址中获取到code,格式如下:

redirect_uri/?code=CODE&state=STATE

这里的CODE是接下来换取access_token的必须参数,而STATE是开发者自定义的其他信息。

2. 换取access_token

上面获取到了code,接下来需要使用这个code来换取access_token。

请求链接如下(GET方式):

https://api.weixin.qq.com/sns/oauth2/access_token?appid=APPID&secret=SECRET&code=CODE&grant_type=authorization_code

上述链接中的各个参数详细说明如下:

参数

是否必须

说明

appid

公众号的唯一标识、开发者ID

secret

公众号的appsecret、开发者密码

code

填写第一步获取的code参数

grant_type

只能为:authorization_code

请求成功后,返回的JSON数据包格式如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
{ 
   
  "access_token":"ACCESS_TOKEN",
  "expires_in":7200,
  "refresh_token":"REFRESH_TOKEN",
  "openid":"OPENID",
  "scope":"SCOPE" 
}

关于该JSON数据包的各个字段说明如下:

参数

说明

access_token

网页授权接口调用凭证,注意:此access_token与基础支持的access_token不同

expires_in

access_token接口调用凭证超时时间,单位(秒)

refresh_token

用户刷新access_token,有效期30天。当access_token超时后,可以使用refresh_token进行刷新。

openid

用户唯一标识,请注意,在未关注公众号时,用户访问公众号的网页,也会产生一个用户和公众号唯一的OpenID

scope

用户授权的作用域,使用逗号(,)分隔

下面是可选操作,一般用不到:

使用refresh_token获取access_token的链接如下(GET方式):

https://api.weixin.qq.com/sns/oauth2/refresh_token?appid=APPID&grant_type=refresh_token&refresh_token=REFRESH_TOKEN

上述链接中的各个参数详细说明如下:

参数

是否必须

说明

appid

公众号的唯一标识

grant_type

填写为refresh_token

refresh_token

填写通过access_token获取到的refresh_token参数

正确返回的JSON格式和上面的一致。

一些说明: 执行到这里,我们已经拿到了用户的OpenID。如果仅仅做用户唯一性校验,至此结束即可。同样,对于发送模板消息,也只需要用户的OpenID。

3. 获取用户信息

如果网页授权作用域为 snsapi_userinfo ,则此时开发者可以通过 access_tokenopenid 拉取用户信息了。

请求链接如下(GET方式、需使用https协议):

https://api.weixin.qq.com/sns/userinfo?access_token=ACCESS_TOKEN&openid=OPENID&lang=zh_CN

上述链接的参数说明如下:

参数

描述

access_token

网页授权接口调用凭证,即前面步骤获取到的access_token。

openid

用户的唯一标识

lang

返回国家地区语言版本,zh_CN 简体,zh_TW 繁体,en 英语

请求成功后返回的JSON数据包格式如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
{ 
      
  "openid":" OPENID",
  "nickname": NICKNAME,
  "sex":"1",
  "province":"PROVINCE",
  "city":"CITY",
  "country":"COUNTRY",
  "headimgurl":       "http://thirdwx.qlogo.cn/mmopen/g3MonUZtNHkdmzicIlibx6iaFqAc56vxLSUfpb6n5WKSYVY0ChQKkiaJSgQ1dZuTOgvLLrhJbERQQ4eMsv84eavHiaiceqxibJxCfHe/46",
  "privilege":[ "PRIVILEGE1" "PRIVILEGE2"     ],
  "unionid": "o6_bmasdasdsad6_2sgVt7hMZOPfL"
}

上述JSON数据包的参数详细说明如下:

参数

描述

openid

用户的唯一标识

nickname

用户昵称

sex

用户的性别,值为1时是男性,值为2时是女性,值为0时是未知

province

用户个人资料填写的省份

city

普通用户个人资料填写的城市

country

国家,如中国为CN

headimgurl

用户头像,最后一个数值代表正方形头像大小(有0、46、64、96、132数值可选,0代表640*640正方形头像),用户没有头像时该项为空。若用户更换头像,原有头像URL将失效。

privilege

用户特权信息,json 数组,如微信沃卡用户为(chinaunicom)

unionid

只有在用户将公众号绑定到微信开放平台帐号后,才会出现该字段。

附:检验授权凭证(access_token)是否有效

请求链接(GET方法、需使用https协议):

https://api.weixin.qq.com/sns/auth?access_token=ACCESS_TOKEN&openid=OPENID

上述链接的参数说明如下:

参数

描述

access_token

网页授权接口调用凭证,注意:此access_token与基础支持的access_token不同

openid

用户的唯一标识

正确的JSON数据包返回结果如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
{ 
    "errcode":0,"errmsg":"ok"}

错误时的JSON返回示例:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
{ 
    "errcode":40003,"errmsg":"invalid openid"}

使用该方法可以检测access_token是否过期,以保证项目的高可用性。

4.2 模板消息推送解读

打开官方开发文档,第4章 消息管理 中,第7节即为 模板消息接口 的参考文档。

直达链接:https://developers.weixin.qq.com/doc/offiaccount/Message_Management/Template_Message_Interface.html

在官方文档中,该模块很大篇幅所叙述的内容,是针对第三方微信服务商,所以有一些是个人开发者用不到的。

总结模板消息推送的实际过程,主要流程如下:

1. 获取基础access_token

请求链接如下(GET方式):

https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET

该链接中的参数详细说明如下:

参数

是否必须

说明

grant_type

获取access_token填写client_credential

appid

第三方用户唯一凭证

secret

第三方用户唯一凭证密钥,即appsecret

请求成功返回的JSON数据包格式如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
{ 
   "access_token":"ACCESS_TOKEN","expires_in":7200}

JSON数据包参数说明:

参数

说明

access_token

获取到的凭证

expires_in

凭证有效时间,单位:秒

2. 发送消息模板

请求链接如下(POST方式):

https://api.weixin.qq.com/cgi-bin/message/template/send?access_token=ACCESS_TOKEN

该链接中只需要 access_token 一个参数,即第一步获取到的 access_token

POST数据包格式为JSON格式,示例如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
 { 
   
           "touser":"OPENID",
           "template_id":"ngqIpbwh8bUfcSsECmogfXcV14J0tQlEpBO27izEYtY",
           "url":"http://weixin.qq.com/download",  
           "miniprogram":{ 
   
             "appid":"xiaochengxuappid12345",
             "pagepath":"pages/index?foo=bar"
           },          
           "data":{ 
   
                   "first": { 
   
                       "value":"恭喜你购买成功!",
                       "color":"#173177"
                   },
                   "keyword1":{ 
   
                       "value":"巧克力",
                       "color":"#173177"
                   },
                   "keyword2": { 
   
                       "value":"39.8元",
                       "color":"#173177"
                   },
                   "keyword3": { 
   
                       "value":"2014年9月22日",
                       "color":"#173177"
                   },
                   "remark":{ 
   
                       "value":"欢迎再次购买!",
                       "color":"#173177"
                   }
           }
       }

该JSON数据包中的各个参数详细说明如下:

参数

是否必填

说明

touser

接收者openid

template_id

模板ID,前文配置中添加模板消息后获得的一串字符

url

模板跳转链接(海外帐号没有跳转能力)

miniprogram

跳小程序所需数据,不需跳小程序可不用传该数据。当链接和小程序都存在时,优先跳转小程序。

appid

所需跳转到的小程序appid(该小程序appid必须与发模板消息的公众号是绑定关联关系,暂不支持小游戏)

pagepath

所需跳转到小程序的具体页面路径,支持带参数,(示例pages/index?foo=bar),要求该小程序已发布,暂不支持小游戏

data

模板数据。这里的数据个数,需要与消息模板中的参数对应,如下图所示。

color

模板内容字体颜色,不填默认为黑色

请求成功后,返回的JSON数据包格式如下所示:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
 { 
   
    "errcode":0,
     "errmsg":"ok",
     "msgid":200228332
  }

这时,用户手机微信将收到对应的提醒。

行文至此,讲述的主要是授权登录和发送模板消息的大致实现流程。

下文,将结合实际的项目,对上述功能的实现流程,以项目源码的形式,进行更加详细的演示。

5. 网页授权登录实现(PHP为例)

5.1 工具类GetWX

该工具类的主要功能是根据微信授权登录的实现流程,进行链接请求和数据获取。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
<?php

/** * 获取微信用户信息 */
class GetWX
{ 
   
    //公众号的开发信息
    private $appid = 'APPID';
    private $appsecret = 'APPSECERT';

    /** * 功能:用户授权并获取code * * @param $callback */
    public function get_code($callback)
    { 
   
        $appid = $this->appid;
        $scope = 'snsapi_userinfo';
        $state = md5(uniqid(rand(), TRUE));//唯一ID标识符绝对不会重复
        $url = 'https://open.weixin.qq.com/connect/oauth2/authorize?appid=' . $appid . '&redirect_uri=' . urlencode($callback) . '&response_type=code&scope=' . $scope . '&state=' . $state . '#wechat_redirect';
        header("Location:$url");
    }

    /** * 功能:通过code获取access_token * * @param $code * @return mixed */
    public function get_access_token($code)
    { 
   
        $appid = $this->appid;
        $appsecret = $this->appsecret;
        $url = 'https://api.weixin.qq.com/sns/oauth2/access_token?appid=' . $appid . '&secret=' . $appsecret . '&code=' . $code . '&grant_type=authorization_code';
        $data = json_decode(file_get_contents($url));//返回的json数组转换成array数组
        return $data;
    }

    /** * 功能:使用access_token获取用户信息 * * @param $access_token * @param $openid * @return mixed */
    public function get_user_info($access_token, $openid)
    { 
   
        $url = 'https://api.weixin.qq.com/sns/userinfo?access_token=' . $access_token . '&openid=' . $openid . '&lang=zh_CN';
        $data = json_decode(file_get_contents($url));//返回的json数组转换成array数组
        return $data;
    }
}

?>

关于该工具类的具体实现方法不唯一。后文中有第二种完整的示例。

5.2 获取code

登录回调页面(login.php)的源码如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
<?php
include 'getWX.php';

$getWX = new GetWX();

//如果没有GET到code,则执行登录操作
if (!isset($_GET['code'])) { 
   
    //微信服务器回调url,这里是本页url
    $protocol = (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off' || $_SERVER['SERVER_PORT'] == 443) ? "https://" : "http://";
    $callback = $protocol . $_SERVER['HTTP_HOST'] . $_SERVER['PHP_SELF'];
    //获取code
    $getWX->get_code($callback);
} //GET到了code,可以执行后续操作
else { 
   

}

如上源码所示,这时访问https://XXXX.cn/test/login.php,执行到if语句处,判断链接中没有code这个参数,所以获取了当前链接的URL地址(callback参数),并将其交给get_code方法,该方法将构造登录链接,并前往该页面,然后弹出登录授权页面,如下所示:

用户点击 同意 之后,返回到$callback链接。这时,链接中携带code参数,以及开发者自定义的state参数。如下图所示:

我们暂时用到的是code参数。

5.3 换取access_token

接下来,使用该 code换取access_token,继续完善login.php代码,具体如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
<?php
include 'getWX.php';

$getWX = new GetWX();

//如果没有GET到code,则执行登录操作
if (!isset($_GET['code'])) { 
   
    //微信服务器回调url,这里是本页url
    $protocol = (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off' || $_SERVER['SERVER_PORT'] == 443) ? "https://" : "http://";
    $callback = $protocol . $_SERVER['HTTP_HOST'] . $_SERVER['PHP_SELF'];
    //获取code
    $getWX->get_code($callback);
} //GET到了code,可以执行后续操作
else { 
   
    //从链接中拿code
    $code = $_GET['code'];
    //获取网页授权access_token和用户openid
    $data = $getWX->get_access_token($code);
    //测试输出
    echo 'access_token:' . $data->access_token . '<br>';
    echo 'expires_in:' . $data->expires_in . '<br>';
    echo 'refresh_token:' . $data->refresh_token . '<br>';
    echo 'openid:' . $data->openid . '<br>';
    echo 'scope:' . $data->scope . '<br>';
}

输出的信息如下:

5.4 获取用户信息

上面拿到了 access_tokenOpenID,接下来可以使用这两个参数来获取用户的基本信息。

继续完善login.php,如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
<?php
include 'getWX.php';

$getWX = new GetWX();

//如果没有GET到code,则执行登录操作
if (!isset($_GET['code'])) { 
   
    //微信服务器回调url,这里是本页url
    $protocol = (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off' || $_SERVER['SERVER_PORT'] == 443) ? "https://" : "http://";
    $callback = $protocol . $_SERVER['HTTP_HOST'] . $_SERVER['PHP_SELF'];
    //获取code
    $getWX->get_code($callback);
} //GET到了code,可以执行后续操作
else { 
   
    //从链接中拿code
    $code = $_GET['code'];
    //获取网页授权access_token和用户openid
    $data = $getWX->get_access_token($code);
    //获取微信用户信息
    $userInfo = $getWX->get_user_info($data->access_token, $data->openid);
    //测试输出:
    echo 'openid:' . $userInfo->openid . '<br>';
    echo 'nickname:' . $userInfo->nickname . '<br>';
    echo 'sex:' . $userInfo->sex . '<br>';
    echo 'province:' . $userInfo->province . '<br>';
    echo 'city:' . $userInfo->city . '<br>';
    echo 'country:' . $userInfo->country . '<br>';
    echo 'headimgurl:' . $userInfo->headimgurl . '<br>';
}

执行结果如下图所示:

这时,我们就拿到了用户的基本信息,之后就可以将这些基本信息保存到数据库,用户ID等可以保存到session或者cookie中,等等,进行各种其他操作。

5.5 另一种完整的示例

工具类:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
<?php

/** * 获取微信用户信息 * 本源码来自互联网 */
class GetWxUser
{ 
   
    private $appid = '';
    private $appsecret = '';

    /** * 1、获取微信用户信息,判断有没有code,有使用code换取access_token,没有去获取code。 * @return array 微信用户信息数组 */
    public function get_user_all()
    { 
   
        if (!isset($_GET['code'])) { 
   //没有code,去微信接口获取code码
            //微信服务器回调url,这里是本页url
            $protocol = (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off' || $_SERVER['SERVER_PORT'] == 443) ? "https://" : "http://";
            $callback = $protocol . $_SERVER['HTTP_HOST'] . $_SERVER['PHP_SELF'];
            //获取code
            $this->get_code($callback);
        } else { 
   //获取code后跳转回来到这里了
            $code = $_GET['code'];
            $data = $this->get_access_token($code);//获取网页授权access_token和用户openid
            $userInfo = $this->get_user_info($data['access_token'], $data['openid']);//获取微信用户信息
            return $userInfo;
        }
    }

    /** * 2、用户授权并获取code * @param string $callback 微信服务器回调链接url */
    public function get_code($callback)
    { 
   
        $appid = $this->appid;
        $scope = 'snsapi_userinfo';
        $state = md5(uniqid(rand(), TRUE));//唯一ID标识符绝对不会重复
        $url = 'https://open.weixin.qq.com/connect/oauth2/authorize?appid=' . $appid . '&redirect_uri=' . urlencode($callback) . '&response_type=code&scope=' . $scope . '&state=' . $state . '#wechat_redirect';
        header("Location:$url");
    }

    /** * 3、使用code换取access_token * @param string 用于换取access_token的code,微信提供 * @return array access_token和用户openid数组 */
    public function get_access_token($code)
    { 
   
        $appid = $this->appid;
        $appsecret = $this->appsecret;
        $url = 'https://api.weixin.qq.com/sns/oauth2/access_token?appid=' . $appid . '&secret=' . $appsecret . '&code=' . $code . '&grant_type=authorization_code';
        $user = json_decode(file_get_contents($url));
        if (isset($user->errcode)) { 
   
            echo 'error:' . $user->errcode . '<hr>msg :' . $user->errmsg;
            exit;
        }
        $data = json_decode(json_encode($user), true);//返回的json数组转换成array数组
        return $data;
    }

    /** * 4、使用access_token获取用户信息 * @param string access_token * @param string 用户的openid * @return array 用户信息数组 */
    public function get_user_info($access_token, $openid)
    { 
   
        $url = 'https://api.weixin.qq.com/sns/userinfo?access_token=' . $access_token . '&openid=' . $openid . '&lang=zh_CN';
        $user = json_decode(file_get_contents($url));
        if (isset($user->errcode)) { 
   
            echo 'error:' . $user->errcode . '<hr>msg :' . $user->errmsg;
            exit;
        }
        $data = json_decode(json_encode($user), true);//返回的json数组转换成array数组
        return $data;
    }
}

?>

登录页login.php:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
<?php
header("Content-Type: text/html;charset=utf-8");
//设置时区
date_default_timezone_set('Asia/Chongqing');

include 'getWXUser.php';

$getWxUser = new GetWxUser();

//主页的URL
$homeUrl = 'https://mzxy.cxhit.cn';

//没有code,去微信接口获取code码
if (!isset($_GET['code'])) { 
   
    //微信服务器回调url,这里是本页url
    $protocol = (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off' || $_SERVER['SERVER_PORT'] == 443) ? "https://" : "http://";
    $callback = $protocol . $_SERVER['HTTP_HOST'] . $_SERVER['PHP_SELF'];

    $getWxUser->get_code($callback);
} //获取code后跳转回来到这里了
else { 
   
    $code = $_GET['code'];
    //获取网页授权access_token和用户openid
    $data = $getWxUser->get_access_token($code);
    //获取微信用户信息(数组)
    $userInfo = $getWxUser->get_user_info($data['access_token'], $data['openid']);

    //保存到数据库
    if ($userInfo['openid'] != '') { 
   
        saveUserInfo($userInfo['openid'], $userInfo['nickname'], $userInfo['sex'], $userInfo['province'], $userInfo['city'], $userInfo['country'], $userInfo['headimgurl']);
    }

    //保存到cookie里
    setcookie('openid', $userInfo['openid'], time() + 3600 * 24 * 30, "/");

    //返回主页
    header("Location:" . $homeUrl);
}
?>

6. 模板消息推送实现(PHP为例)

6.1 官方JSSDK文档(PHP)

SDK实现了各种参数的获取,源码如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
<?php

class JSSDK
{ 
   
    private $appId;
    private $appSecret;

    public function __construct($appId, $appSecret)
    { 
   
        $this->appId = $appId;
        $this->appSecret = $appSecret;
    }

    public function getSignPackage()
    { 
   
        $jsapiTicket = $this->getJsApiTicket();

        // 注意 URL 一定要动态获取,不能 hardcode.
        $protocol = (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off' || $_SERVER['SERVER_PORT'] == 443) ? "https://" : "http://";
        $url = "$protocol$_SERVER[HTTP_HOST]$_SERVER[REQUEST_URI]";

        $timestamp = time();
        $nonceStr = $this->createNonceStr();

        // 这里参数的顺序要按照 key 值 ASCII 码升序排序
        $string = "jsapi_ticket=$jsapiTicket&noncestr=$nonceStr&timestamp=$timestamp&url=$url";

        $signature = sha1($string);

        $signPackage = array(
            "appId" => $this->appId,
            "nonceStr" => $nonceStr,
            "timestamp" => $timestamp,
            "url" => $url,
            "signature" => $signature,
            "rawString" => $string
        );
        return $signPackage;
    }

    private function createNonceStr($length = 16)
    { 
   
        $chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
        $str = "";
        for ($i = 0; $i < $length; $i++) { 
   
            $str .= substr($chars, mt_rand(0, strlen($chars) - 1), 1);
        }
        return $str;
    }

    private function getJsApiTicket()
    { 
   
        // jsapi_ticket 应该全局存储与更新,以下代码以写入到文件中做示例
        $data = json_decode($this->get_php_file("jsapi_ticket.php"));
        if ($data->expire_time < time()) { 
   
            $accessToken = $this->getAccessToken();
            // 如果是企业号用以下 URL 获取 ticket
            // $url = "https://qyapi.weixin.qq.com/cgi-bin/get_jsapi_ticket?access_token=$accessToken";
            $url = "https://api.weixin.qq.com/cgi-bin/ticket/getticket?type=jsapi&access_token=$accessToken";
            $res = json_decode($this->httpGet($url));
            $ticket = $res->ticket;
            if ($ticket) { 
   
                $data->expire_time = time() + 7000;
                $data->jsapi_ticket = $ticket;
                $this->set_php_file("jsapi_ticket.php", json_encode($data));
            }
        } else { 
   
            $ticket = $data->jsapi_ticket;
        }

        return $ticket;
    }

    public function getAccessToken()
    { 
   
        // access_token 应该全局存储与更新,以下代码以写入到文件中做示例
        $data = json_decode($this->get_php_file("access_token.php"));
        if ($data->expire_time < time()) { 
   
            // 如果是企业号用以下URL获取access_token
            // $url = "https://qyapi.weixin.qq.com/cgi-bin/gettoken?corpid=$this->appId&corpsecret=$this->appSecret";
            $url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=$this->appId&secret=$this->appSecret";
            $res = json_decode($this->httpGet($url));
            $access_token = $res->access_token;
            if ($access_token) { 
   
                $data->expire_time = time() + 7000;
                $data->access_token = $access_token;
                $this->set_php_file("access_token.php", json_encode($data));
            }
        } else { 
   
            $access_token = $data->access_token;
        }
        return $access_token;
    }

    private function httpGet($url)
    { 
   
        $curl = curl_init();
        curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($curl, CURLOPT_TIMEOUT, 500);
        // 为保证第三方服务器与微信服务器之间数据传输的安全性,所有微信接口采用https方式调用,必须使用下面2行代码打开ssl安全校验。
        // 如果在部署过程中代码在此处验证失败,请到 http://curl.haxx.se/ca/cacert.pem 下载新的证书判别文件。
        curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, true);
        curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, true);
        curl_setopt($curl, CURLOPT_URL, $url);

        $res = curl_exec($curl);
        curl_close($curl);

        return $res;
    }

    private function get_php_file($filename)
    { 
   
        return trim(substr(file_get_contents($filename), 15));
    }

    private function set_php_file($filename, $content)
    { 
   
        $fp = fopen($filename, "w");
        fwrite($fp, "<?php exit();?>" . $content);
        fclose($fp);
    }
}
6.2 模板消息JSON化

这里以下面这个模板消息为实例,进行演示。模板 详细内容 处的内容需要牢记,因为在构造JSON时,要用这些信息。

然后定义一个函数,主要功能是实现发送数据的JSON格式化

函数源码:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
//模板消息JSON格式化
function json_tempalte($openid, $appid, $nickname, $time)
{ 
   
    //模板消息
    $template = array(
        'touser' => $openid,  //用户openid
        'template_id' => 'XXXX', //在公众号下配置的模板id
        'url' => 'https://XXXX.cn', //点击模板消息会跳转的链接
        'miniprogram' => array(
            'appid' => $appid,
            'pagepath' => 'pages/main/login/login?foo=bar'
        ),
        'data' => array(
            'first' => array('value' => '完成今日健康日报了吗?未完成,请尽快哦~', 'color' => "#FF0000"),
            'keyword1' => array('value' => $nickname, 'color' => '#173177'),  //keyword需要与配置的模板消息对应
            'keyword2' => array('value' => $time, 'color' => '#173177'),
            'remark' => array('value' => '点击此处前往填报。本通知由您订阅产生,切换身份、更改通知时间及退订管理,请访问菜单栏『学习助手』模块。', 'color' => '#FF0000'),
        )
    );
    $json_template = json_encode($template);
    return $json_template;
}

这个函数返回的结果是JSON数据包。

6.3 发送模板消息

关键源码如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
include("jssdk.php");
$jssdk = new JSSDK("APPID", "APPSECRET");
//定义消息模板JSON
$json_template = json_tempalte('APPID', 'wxa0738e54aae84423', '拾年之璐' . '(本科生)', date("Y-m-d"));
//获取AccessToken
$accessToken = $jssdk->getAccessToken();
//POST 的链接
$url = "https://api.weixin.qq.com/cgi-bin/message/template/send?access_token=" . $accessToken;
//提交
list($returnCode, $returnContent) = http_post_json($url, $json_template);
//打印日志(JSON格式)
echo '发送结果如下:' . $returnContent . '\n';

其中,上面代码中的 http_post_json 函数如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
//发送POST请求
function http_post_json($url, $jsonStr)
{ 
   
    $ch = curl_init();
    curl_setopt($ch, CURLOPT_POST, 1);
    curl_setopt($ch, CURLOPT_URL, $url);
    curl_setopt($ch, CURLOPT_POSTFIELDS, $jsonStr);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
    curl_setopt($ch, CURLOPT_HTTPHEADER, array(
            'Content-Type: application/json; charset=utf-8',
            'Content-Length: ' . strlen($jsonStr)
        )
    );
    $response = curl_exec($ch);
    $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
    curl_close($ch);

    return array($httpCode, $response);
}

该函数是自己封装的进行POST请求。当然各种

执行完成后,用户即可收到消息模板。

7. 后记与源码

行文至此,关于微信授权登录和微信模板消息推送的主要使用方法讲解完毕。

前文中虽然有提到过每日提醒的模板消息推送功能,但这里将不再论述。

源码下载:https://mianbaoduo.com/o/bread/YZuVk5dp

以上。

发布者:全栈程序员栈长,转载请注明出处:https://javaforall.cn/128618.html原文链接:https://javaforall.cn

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2022年4月1,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
公众平台认证订阅号接口调整 增加群发接口等,可授权登录
  微信公众平台昨日宣布向已微信认证的订阅号开放更多的接口,包括群发接口、客服接口、用户管理接口、上传下载多媒体文件接口,甚至可以通过公众号授权登录第三方开发平台。微信是越来越开放的节奏! 公众平台认
ytkah
2018/03/05
1.1K0
公众平台认证订阅号接口调整 增加群发接口等,可授权登录
第三方平台正式支持接入微信公众平台JS-SDK
  之前微信公众平台面向开发者开放微信内网页开发工具包,现在第三方平台也能正式支持接入微信公众平台JS-SDK了,第三方平台可以在获得公众号的授权后,通过JS-SDK帮助公众号开发和实现网页业务。  
ytkah
2018/03/05
3.6K0
第三方平台正式支持接入微信公众平台JS-SDK
一周简报|红桃微信,专注于应用的微信公众号第三方管理平台
编辑导语 红桃微信,专注于应用的微信公众号第三方管理平台; AnySDK 更新至2.2.0版,新增广告追踪功能;亲加SDK与APICloud达成战略合作,缩短视频直播研发周期;环信SDK更新至4.8,
BestSDK
2018/02/27
2.4K0
一周简报|红桃微信,专注于应用的微信公众号第三方管理平台
微信公众平台多客服新增自定义客服头像和消息转发接口功能
  多客服一般是开放给微信认证服务号的一个便捷功能,可以将消息转发到多客服方便回复。对有些“选择综合症“的客服,看到那一层不变的客服头像就想吐槽。现在好了,多客服新增自定义客服头像和接口功能,也可以自
ytkah
2018/03/05
2.9K0
微信公众平台多客服新增自定义客服头像和消息转发接口功能
第三方平台也能为未微信认证的订阅号调用自定义菜单接口和素材管理接口
  3月20号已认证微信公众号可通过第三方平台管理微信公众平台素材,现在自定义菜单接口和素材管理接口向第三方平台旗下未认证订阅号开放,未认证订阅号也可以授权给第三方平台,让第三方平台开发者帮助实现自定义菜单和素材管理业务。但请注意,为了避免接口安全风险,公众号自身仍旧没有上述接口权限,无法调用这些接口。   未认证订阅号的自定义菜单接口能力,与公众平台官网内能力是相同的,具体如下:   1. 点击菜单后,公众号回复一条消息,支持图文消息、图片、语音、视频类型,不支持文本消息;   2. 点击菜单后,跳转到公
ytkah
2018/03/05
1.9K0
微信开放平台之第三方平台开发,从哪里入手?
疫情之下,最近有不少兄弟没有挺进决赛,半途成了小羊人,可谓是出师未捷身先死。话说回来,不管怎么样,尽量保护好自己,能越晚变羊越好。
悟空码字
2022/12/25
1.5K0
微信开放平台之第三方平台开发,从哪里入手?
微信公众号三方平台开发【component_verify_ticket篇】
上期咱们讲完了微信开放平台开发者帐号注册以及第三方平台的创建工作,从今天开始,咱们就开始正式的开发部分咯,跟进袁小威的脚步,莫掉队哦~~~
用户2619822
2022/06/10
2.2K0
微信携手第三方再造新平台 - 公众号第三方平台介绍
  微信携手第三方,再造新平台,即我们平常所说的公众号第三方平台,是通过微信公众号登录授权,帮助各行各业公众号解决业务需求的第三方网站。是必须基于公众号登录授权,提供解决方案而非一律外包的第三方网站,
ytkah
2018/03/06
2K0
微信携手第三方再造新平台 - 公众号第三方平台介绍
微信里的“授权”到底是几个意思?
作为普通用户,在使用微信的过程中,我们经常会看到各种“授权”,体验着当领导的感觉的同时,也会担心自己的隐私是否会暴露的问题。并且,即使是互联网从业者,也未必都能搞清楚这些“授权”到底是什么意思。那么下面我们就来看看,不同场景下的“授权”到底意味着什么。
姬小光
2018/09/05
2K0
微信里的“授权”到底是几个意思?
小程序(公众号)授权给第三方平台流程梳理和实现
在第三方平台应用上点击授权的时候会获取授权的预授权码(preauthcode),有效期为10分钟。
benny
2020/02/25
5.3K1
微信公众号三方平台开发【帐号注册、平台创建】
上一期咱们简单介绍了一下什么是公众号第三方平台,今天咱们讲具体如何操作来创建属于你自己的微信第三方平台。
用户2619822
2022/06/10
2.1K0
微信公众号三方平台开发【帐号注册、平台创建】
手机端公众号内的微信第三方登录
OAuth(开放授权)是一个开放标准,允许用户让第三方应用访问该用户在某一网站上存储的私密的资源(如照片,视频,联系人列表),而无需将用户名和密码提供给第三方应用。
山河木马
2019/03/05
3.2K0
手机端公众号内的微信第三方登录
微信公众号三方平台开发【获取授权方的授权信息以及基本信息】
今天开始之前,先对上期的内容做一个小的补充,第三方平台在开发(即待全网发布)模式下,用来测试的微信公众号必须为第二期里说到的“授权测试公众号列表”(即测试白名单)里填写的微信公众号,否则会出现授权失败提示。
用户2619822
2022/06/10
1.7K0
微信公众号三方平台开发【获取授权方的授权信息以及基本信息】
微信公众号第三方平台开发概况
  首先要知道为什么要用公众号第三方平台,公众号第三方平台的开放,是为了让公众号运营者,在面向垂直行业需求时,可以一键登录授权给第三方的公众号运营平台,通过第三方开发者提供的公众号第三方平台来完成相关
欢醉
2018/03/02
3.4K0
微信公众号第三方平台开发概况
新能力连发!微信广告组件开放内测,还有 50 多个接口更新等你发现
又有新能力了!最近微信新动作频频,知晓程序也在第一时间做了能力解读,这次也一样。知晓君很欣慰,至少这次,微信不是周五晚上发布新能力的了。 接下来就和知晓君一起,了解一下这次微信搞的幺蛾子……哦不,新能力吧! 这次更新,都有什么新能力? 1. 小程序广告组件启动内测 只要开发者开通流量主模块,就可以通过创建广告单元,使用广告组件将广告卡片灵活配置在小程序页面内,而广告主也可以到小程序上投广告啦! 2. 第三方可以快速创建并认证小程序 微信公众平台针对已认证公众号,新增「快速注册小程序」API 权限集。第三方平
知晓君
2018/07/04
4320
微信公众号系列之入门教程
随着微信的迅猛发展,现在微信公众号开发已经越来越流行了!本文介绍微信公众号的一些入门知识及账号的注册!
SmileNicky
2022/05/07
1.4K0
微信公众号系列之入门教程
公众号 unionid_微信公众号免费模板
在关注者与公众号产生消息交互后,公众号可获得关注者的OpenID(加密后的微信号,每个用户对每个公众号的OpenID是唯一的。对于不同公众号,同一用户的openid不同)。公众号可通过本接口来根据OpenID获取用户基本信息,包括昵称、头像、性别、所在城市、语言和关注时间。
全栈程序员站长
2022/09/20
2.9K0
微信公众号开发基本流程
背景: 过年前后做了个微信公众号项目,已经过去一段时间了,抽空回忆总结下基本流程吧,不然很快估计自己就忘了。。
全栈程序员站长
2022/09/06
3.6K0
微信公众号开发基本流程
干货丨微信开放、公众、商户平台简介
用户可将第三方程序的内容发布给好友或分享至朋友圈,第三方内容借助微信平台获得更广泛的传播。
齿轮易创说互联网
2018/09/30
5.4K1
干货丨微信开放、公众、商户平台简介
第三方登录:微信扫码登录(OAuth2.0
  OAuth(开放授权)是一个开放标准,允许用户让第三方应用访问该用户在某一网站上存储的私密的资源(如照片,视频,联系人列表),而无需将用户名和密码提供给第三方应用。
朝雨忆轻尘
2019/06/18
57.8K1
推荐阅读
相关推荐
公众平台认证订阅号接口调整 增加群发接口等,可授权登录
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
查看详情【社区公告】 技术创作特训营有奖征文
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验