一文入门微信公众号和小程序

概述

抽出来一点时间,梳理一下微信公众号和小程序应用的实践,梳理总结的一点心得体会,公众号和小程序产品定位不同,公众号开发的权限和自由度比较高,消息事件类型丰富,而小程序更注重的体验,认证权限也相对严格,发布时需要审核和发版等等。

开发接入流程

下图分别是公众号和小程序的开发接入流程图,如果有不理解的小伙伴可以先看阅读官网,官网讲解的较为仔细,下面我从几个重要的方面进行阐述:

  • user:用户
  • PublicWechat:部署的H5服务的打包文件
  • PublicWechatApi:部署需要请求/响应我方的Http Web服务
  • MiniWechatApi:需要请求/响应我方Http Web服务
  • Weixin-Server:微信服务

安全策略

1、AppID、AppSecret、Ip白名单

微信的公众号和小程序都有自己的安全策略,第一点就是AppID和AppSecret,如果发现异常可以重置或冻结AppSecret。

公众号在设置与开发->功能设置中设置业务域名、JS接口安全域名、网页授权域名,需要在设置中下载加密文件放置在域名的根目录下:

shell 复制代码
[root@iZ2zeh51ud3t9tccbqys3oZ]# tree -L 1
.
├── assets
├── favicon.png
├── index.html
├── MP_verify_tsTXlFOVduuAyTbT.txt
└── wx.html

小程序的设置路径在开发与服务->开发设置,有服务器域名选项,小程序比公众号多了开发者Ip白名单和小程序上传代码Ip白名单,Ip白名单默认是关闭的。

2、用户认证

微信网页授权是通过OAuth2.0机制实现的,可以操作的Api比小程序多,小程序通过js_codelai来获取到用户的OpenID,每个用户在同一个应用同一个OpenID,OpenID相对于用户的唯一标识。

1、引导用户进入授权页面同意授权,获取code 2、通过code换取网页授权access_token(与基础支持中的access_token不同) 3、如果需要,开发者可以刷新网页授权access_token,避免过期 4、通过网页授权access_token和openid获取用户基本信息(支持UnionID机制)

公众号Web授权步骤,公众号网页授权官方文档URL,点击前往,一般开发到步骤2的时候,就可以使用code获取OpenID,有了OpenID确定用户身份,才有后面的一系列操作,略有不同的是,小程序的需要通过生成的js_code来获取,服务端代码如下:

PHP 复制代码
//小程序
class Talent extends MY_Controller
{
	const LOGIN = 'https://api.weixin.qq.com/sns/jscode2session';
	private function getOpenid($js_code)
	{
		$appid = isset($this->cf['wechat_appId']) ? $this->cf['wechat_appId'] : '';
		$secret = isset($this->cf['wechat_appSecret']) ? $this->cf['wechat_appSecret'] : '';
		if (empty($appid) && empty($secret)) {
			show_result(1000, '联系管理员,是否绑定小程序');
		}

		$data = [
			'appid' => $appid,
			'secret' => $secret,
			'js_code' => $js_code,
			'grant_type' => 'authorization_code'
		];
		$res = curl_json(self::LOGIN . '?' . http_build_query($data));
		if (isset($res['openid'])) {
			return $res['openid'];
		} else {
			show_result(1000, '没有获取到有效的OpenId');
		}
	}
}

事件与响应

在接入的请求秩序上公众号和小程序有很大的不同,在公众号的后台设置一个url让微信公众号的服务回调这个url,在绑定之前需要一个token的验证,设置不对会提示token不正确的提示,微信公众号的 $echostr 和 自定义的匹配上说明调用成功,成功后就可以进行交互,如果有不清楚的地方可以查看我之前的博客微信公众号推送消息笔记

公众号上有大量丰富的事件,小程序就显得比较单一了许多,小程序获取到用户的OpenID更多的是调用内部的WechatApi,下面的代码是公众号的事件。

php 复制代码
class Request extends MY_Wechat
{
    public function console(){
    	//关注公众号推送
    	$posts = $this->posts;
    	$this->openid = isset($posts['openid']) ? $posts['openid'] : '';
    	if(!isset($_GET['openid'])){
    		$res = $this->checkSignature();
    		if($res){
    			echo $res;
    			return true;
    		}else{
    			return false;
    		}
    	}
    	$this->log(['openid' => $this->openid]);
    	$msgType = isset($posts['MsgType']) ? $posts['MsgType'] : '';
    	$event = isset($posts['Event']) ? $posts['Event'] : '';
    	switch ($event){
    		case 'subscribe':
    			$this->subscribe($posts);
    			break;
    		case 'unsubscribe':
    			$this->unsubscribe();
    			break;
    	}
    }
}

推送消息

公众号主要是发送模版消息,小程序主要是订阅消息,公众号消息比小程序的推送消息优点是几乎没有限制,而小程序的主动权在于用户,首先用户需要先订阅消息授权,有了权限才可以进行推送,用户未授权推送的错误信息如下:

php 复制代码
# 公众号错误状态码
{"errcode":43004,"errmsg":"require subscribe rid: 657c07fa-7c3f3c23-2e1c7d41"}
# 小程序错误状态码
{"errcode":43101,"errmsg":"user refuse to accept the msg rid: 674d4fb2-7ac109d7-356532c2"}

1、获取Access_Token

Access_Token过期时间为7200s,把Access_Token可以存储到本地文件 或 Redis缓存中,神奇的是公众号和小程序使用获取Access_Token的Api是公用的。

php 复制代码
#GET https://api.weixin.qq.com/cgi-bin/token

#Redis 存储
private function _get_access_token()
{
	$this->load->library('RedisBase');
	$access_token = $this->redisbase->get('access_token');
	if (isset($access_token) && !empty($access_token)) {
		$this->access_token = $access_token;
		return true;
	}

	
	$access_token_url = $this->params_format(self::GET_ACCESS_TOKEN_URL, $params);
	$json = file_get_contents($access_token_url);
	$result = json_decode($json, true);

    
	$this->access_token = $result['access_token'];
	$expires = intval($result['expires_in']) - 100;
	$this->redisbase->set("access_token", $result['access_token'], $expires);
	return true;
}

#文件缓存
protected function _get_access_token()
{
    $file = $this->config->config['site_dir'] . 'cache/wechat_access_token.php';
    if (!file_exists(dirname($file))) {
        mkdir(dirname($file), 0777, true);
    }
    if (file_exists($file)) {
        //读取内容
        $con = file_get_contents($file);
        $data = json_decode($con, true);
        if (!empty($data['access_token']) && !empty($data['expires_in'])) {
            if ($data['expires_in'] > time()) {
                return $data['access_token'];
            }
        }
    }

    //略
    //写入缓存文件
    $con = [
        'access_token' => $res['access_token'],
        'expires_in' => time() + $res['expires_in'],
    ];
    $json = json_encode($con, JSON_UNESCAPED_UNICODE);
    $count = file_put_contents($file, $json);
    if ($count <= 0) {
        return false;
    }
    return $res['access_token'];
}

小程序和公众号在推送消息的前提条件是获得access_token,下面是小程序的推送,模版字段格式、模版ID、长度需要提前做好格式化,否则会抛出错误信息:{"errcode":40037,"errmsg":"invalid template_id rid: 674d2d3f-71b47cf9-2f1c71ee"}

模版数据大致相当,模版ID和结构要保证正确,不能超出规定字符,大致Json结构为:

json 复制代码
{
    "thing17": {
        "value": "面访方案审批"
    },
    "thing49": {
        "value": "济南龙腾人力资源管理有限公司"
    },
    "thing6": {
        "value": "无"
    },
    "name1": {
        "value": "邢海燕"
    },
    "time2": {
        "value": "2024-11-30 13:31:14"
    }
}

使用PHP语言,编写的小程序和公众号推送的Demo

php 复制代码
#小程序推送Demo
#POST https://api.weixin.qq.com/cgi-bin/message/subscribe/send

$template_data = json_decode($json, true);
$data = [
    'template_id' => $push_message['examine_template'],
    'page' => $push_message['push_url'],
    'touser' => $push_message['to_openid'],
    'data' => $template_data,
    'miniprogram_state' => 'formal',//formal
    'lang' => 'zh_CN'
];
$result = curl_json(self::SEND_MESSAGE . '?access_token=' . $access_token, $data);

## 公众号推送

$url = "https://api.weixin.qq.com/cgi-bin/message/template/send?access_token=". $this->_get_access_token();
$params = [
    'touser' => $push_info['to_openid'],
    'template_id' => $push_info['examine_template'],
    'page' => $this->cf['base_url'],
    'miniprogram' => [
        'appid' => $this->cf['wechat_AppID'],
        'pagepath' => $push_info['push_url'],
    ],
    'data' => json_decode($push_info['push_content'], true),
];

$result = $this->curl_json($url, $params);
相关推荐
fcopy3 小时前
sylar:日志管理
服务器·开发语言·c++·后端
Mercury_@223 小时前
功能篇:springboot实现防盗链功能
java·spring boot·后端
界面开发小八哥4 小时前
智能高效的IDE GoLand v2024.3全新发布——支持最新Go语言
开发语言·后端·golang·go·开发工具
LuckyLay5 小时前
Golang中的go.mod和go.sum
开发语言·后端·golang
ladymorgana6 小时前
【日常笔记】Spring boot:编写 Content type = ‘text/plain‘ 接口
spring boot·笔记·后端·text/plain
小乖兽技术6 小时前
解决几个常见的ASP.NET Core Web API 中多线程并发写入数据库失败的问题
数据库·后端·asp.net·dotnet
编程乐趣6 小时前
ASP.NET Core 9.0的7个方面重大更新!
后端·asp.net
DoorToZen6 小时前
【开发日志】ASP.NET Core Minimal APIs开发日志
后端·asp.net
日落ོ࿆ྂ6 小时前
利用 0day 双杀-java 环境-宏感染-安卓客户端渗透
后端·安全·web安全·网络安全
Olrookie7 小时前
从源码构建安装Landoop kafka-connect-ui
大数据·linux·后端·kafka