第一步、订阅号随手记笔记功能演示效果
第二步安装fastadmin框架和创建随手记表
1、安装fastadmin框架
2、创建数据表fa_note
CREATE TABLE `fa_note` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`ToUserName` varchar(50) DEFAULT NULL COMMENT '微信用户标识',
`FromUserName` varchar(50) DEFAULT NULL COMMENT '用户id',
`title` varchar(20) DEFAULT NULL COMMENT '标题',
`Content` text COMMENT '内容',
`CreateTime` varchar(30) DEFAULT NULL COMMENT '添加时间',
`UpdateTime` varchar(30) DEFAULT NULL COMMENT '修改时间',
`MsgType` varchar(30) DEFAULT NULL COMMENT '文本类型',
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=37 DEFAULT CHARSET=utf8mb4 COMMENT='笔记列表';
第三步、配置公众号和订阅号配置
fastadmin公众号服务器配置,安装微信管理点击参考下面
安装好后打开权限显示微信管理
第四步、公众号配置自动回复,修改index.php文件
1、接受回复记录和处理返回 增加消息处理方法
if ($message['MsgType'] == 'text'||$message['MsgType'] == 'image') {
$return= $this->note($message) ;
if($return){
return $return;
}
}
message示例:
{"ToUserName":"gh_02c4fcb1e983","FromUserName":"o-iwh0oy9SJZ66Azl6F8eRMQlHec","CreateTime":"1690609936","MsgType":"text","Content":"第一个笔记","MsgId":"24203713717141674"}
2、完整代码如下
<?php
namespace addons\wechat\controller;
use addons\wechat\library\Config;
use addons\wechat\model\WechatAutoreply;
use addons\wechat\model\WechatCaptcha;
use addons\wechat\model\WechatContext;
use addons\wechat\model\WechatResponse;
use addons\wechat\model\WechatConfig;
use EasyWeChat\Factory;
use addons\wechat\library\Wechat as WechatService;
use addons\wechat\library\Config as ConfigService;
use think\Log;
use think\Db;
/**
* 微信接口
*/
class Index extends \think\addons\Controller
{
public $app = null;
public function _initialize()
{
parent::_initialize();
$this->app = Factory::officialAccount(Config::load());
}
/**
*
*/
public function index()
{
$this->error("当前插件暂无前台页面");
}
/**
* 微信API对接接口
*/
public function api()
{
$this->app->server->push(function ($message) {
$wechatService = new WechatService;
$matches = null;
$openid = $message['FromUserName'];
$to_openid = $message['ToUserName'];
$unknownMessage = WechatConfig::getValue('default.unknown.message');
$unknownMessage = $unknownMessage ? $unknownMessage : "";
switch ($message['MsgType']) {
case 'event': //事件消息
$event = $message['Event'];
$eventkey = $message['EventKey'] ? $message['EventKey'] : $message['Event'];
//验证码消息
if (in_array($event, ['subscribe', 'SCAN']) && preg_match("/^captcha_([a-zA-Z0-9]+)_([0-9\.]+)/", $eventkey, $matches)) {
return WechatCaptcha::send($openid, $matches[1], $matches[2]);
}
switch ($event) {
case 'subscribe'://添加关注
$subscribeMessage = WechatConfig::getValue('default.subscribe.message');
$subscribeMessage = $subscribeMessage ?: "欢迎关注我们!";
return $subscribeMessage;
case 'unsubscribe'://取消关注
return '';
case 'LOCATION'://获取地理位置
return '';
case 'VIEW': //跳转链接,eventkey为链接
return '';
case 'SCAN': //扫码
return '';
default:
break;
}
$wechatResponse = WechatResponse::where(["eventkey" => $eventkey, 'status' => 'normal'])->find();
if ($wechatResponse) {
$responseContent = (array)json_decode($wechatResponse['content'], true);
$wechatContext = WechatContext::where(['openid' => $openid])->order('id', 'desc')->find();
$data = ['eventkey' => $eventkey, 'command' => '', 'refreshtime' => time(), 'openid' => $openid];
if ($wechatContext) {
$wechatContext->save($data);
} else {
$wechatContext = WechatContext::create($data, true);
}
$result = $wechatService->response($this, $openid, '', $responseContent, $wechatContext);
if ($result) {
return $result;
}
}
return $unknownMessage;
case 'text': //文字消息
case 'image': //图片消息
case 'voice': //语音消息
case 'video': //视频消息
case 'location': //坐标消息
case 'link': //链接消息
default: //其它消息
if ($message['MsgType'] == 'text'||$message['MsgType'] == 'image') {
$return= $this->note($message) ;
if($return){
return $return;
}
}
//自动回复处理
if ($message['MsgType'] == 'text') {
$autoreply = null;
$autoreplyList = WechatAutoreply::where('status', 'normal')->cache(true)->order('weigh DESC,id DESC')->select();
foreach ($autoreplyList as $index => $item) {
//完全匹配和正则匹配
if ($item['text'] == $message['Content'] || (in_array(mb_substr($item['text'], 0, 1), ['#', '~', '/']) && preg_match($item['text'], $message['Content'], $matches))) {
$autoreply = $item;
break;
}
}
if ($autoreply) {
$wechatResponse = WechatResponse::where(["eventkey" => $autoreply['eventkey'], 'status' => 'normal'])->find();
if ($wechatResponse) {
$responseContent = (array)json_decode($wechatResponse['content'], true);
$wechatContext = WechatContext::where(['openid' => $openid])->order('id', 'desc')->find();
$result = $wechatService->response($this, $openid, $message['Content'], $responseContent, $wechatContext, $matches);
if ($result) {
return $result;
}
}
}
}
return $unknownMessage;
}
return ""; //SUCCESS
});
$response = $this->app->server->serve();
// 将响应输出
$response->send();
return;
}
//小记功能
private function note($message){
if ($message['MsgType'] == 'text') {
$title="";
$message['Content']=trim($message['Content']);
if($message['Content']){
if(in_array($message['Content'][0],array("!","@","#"))){
$firstpex=$message['Content'][0];
preg_match('/'.$firstpex.'(.*?)'.$firstpex.'/', $message['Content'], $matches);
if (isset($matches[1])) {
$title = $matches[1];
preg_match('/'.$firstpex.'.*?'.$firstpex.'(.*$)/', $message['Content'], $Content);
if (isset($Content[1])) {
$message['Content'] = $Content[1];
} else {
// 第二个#或者?或者!后面没有内容
$message['Content'] = mb_substr($message['Content'], 0, 9);
}
}
}else{
$title=mb_substr($message['Content'], 0, 9);
}
}
}
if($message['MsgType'] == 'image'){
$title="图".date("YmdHis");
$message['Content']= $message['PicUrl'];
}
$data=[
"title"=>$title,
"ToUserName"=>$message['ToUserName'],
"FromUserName"=>$message['FromUserName'],
"CreateTime"=>$message['CreateTime'],
"UpdateTime"=>$message['CreateTime'],
"MsgType"=>$message['MsgType'],
"Content"=>$message['Content'],
];
$id= Db::table('fa_note')->insertGetId($data);
if($id){
return '已存笔记,点查看 <a href="'.request()->domain().'/index.php/index/wechat/index/?user='.$message['ToUserName'].'&id='.$id.'">链接</a>';
}
return false;
}
/**
* 登录回调
*/
public function callback(){
}
/**
* 支付回调
*/
public function notify()
{
Log::record(file_get_contents('php://input'), "notify");
$response = $this->app->handlePaidNotify(function ($message, $fail) {
// 你的逻辑
return true;
// 或者错误消息
$fail('Order not exists.');
});
$response->send();
return;
}
}
第五步创建随手详情页面和列表页面
1、创建控制器Wechat.php
<?php
namespace app\index\controller;
use app\common\controller\Frontend;
use think\Db;
class Wechat extends Frontend
{
protected $noNeedLogin = '*';
protected $noNeedRight = '*';
protected $layout = '';
public function index()
{
$user = $this->request->get("user");
$id = $this->request->get("id");
if(!$id||!$user) {
die();
}
$note= Db::table("fa_note")->where('ToUserName',$user)->where('id',$id)->find();
if(!$note){
die();
}
$this->view->assign("row", $note);
return $this->view->fetch();
}
public function lst()
{
$user = $this->request->get("user");
if(!$user) {
die();
}
$note= Db::table("fa_note")->where('ToUserName',$user)->order("id desc")->select();
if(!$note){
die();
}
foreach ($note as &$value) {
// code...
$value['time']=date("Y-m-d H:i:s",$value['CreateTime']);
}
$this->view->assign("user", $user);
$this->view->assign("list", json_encode($note));
return $this->view->fetch();
}
}
2、创建随手记详情和列表html
详情index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>笔记</title>
<style>
body {
font-family: Arial, sans-serif;
margin: 0;
padding: 0;
}
header {
background-color: #333;
color: #fff;
padding: 10px;
text-align: center;
}
main {
padding: 20px;
}
.button {
display: inline-block;
padding: 10px 20px;
background-color: #555;
color: #fff;
text-decoration: none;
border-radius: 5px;
}
@media only screen and (max-width: 600px) {
header {
font-size: 18px;
}
main {
font-size: 16px;
}
}
</style>
</head>
<body>
<header>
<a href="/index.php/index/wechat/lst/?user={$row['ToUserName']}" class="button">列表</a>
<h3>{$row.title}</h3>
</header>
<main>
<h6>添加于{$row.CreateTime|date="Y-m-d H:i:s",###}</h6>
<div style="font-size: larger; font-weight: bold;">
{if $row.MsgType=='text'}{$row.Content}{/if}
{if $row.MsgType=='image'}<img src="{$row['Content']}" style="width:100%;"/>{/if}
</div>
</main>
</body>
</html>
列表lst.html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>我的笔记</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<style>
body {
font-family: Arial, sans-serif;
margin: 0;
padding: 0;
}
.container {
max-width: 800px;
margin: 0 auto;
padding: 20px;
}
h1 {
font-size: 24px;
margin-bottom: 10px;
}
ul {
list-style-type: none;
padding: 0;
}
li {
margin-bottom: 20px;
border: 1px solid #ccc;
padding: 10px;
}
.pagination {
display: flex;
justify-content: center;
margin-top: 20px;
}
.pagination a {
display: inline-block;
padding: 5px 10px;
margin: 0 5px;
border: 1px solid #ccc;
text-decoration: none;
color: #333;
}
.pagination .active {
background-color: #ccc;
}
a {
text-decoration: none;
}
</style>
</head>
<body>
<div class="container">
<h1>我的笔记</h1>
<ul id="list"></ul>
<div class="pagination" id="pagination"></div>
</div>
<script>
// 模拟数据
var data = {$list};
var user= "{$user}";
var currentPage = 1; // 当前页码
var pageSize = 1000000; // 每页显示的数量
function renderList() {
var startIndex = (currentPage - 1) * pageSize;
var endIndex = startIndex + pageSize;
var listHtml = "";
for (var i = startIndex; i < endIndex && i < data.length; i++) {
listHtml += `<a href="/index.php/index/wechat/index/?user=${user}&id=${data[i].id}"><li><strong>${data[i].title}</strong> - 添加时间:${data[i].time}</li></a>`;
}
document.getElementById("list").innerHTML = listHtml;
}
function renderPagination() {
var totalPages = Math.ceil(data.length / pageSize);
var paginationHtml = "";
for (var i = 1; i <= totalPages; i++) {
paginationHtml += `<a href="#" class="${i === currentPage ? 'active' : ''}" onclick="changePage(${i})">${i}</a>`;
}
// document.getElementById("pagination").innerHTML = paginationHtml;
}
function changePage(page) {
currentPage = page;
renderList();
renderPagination();
}
// 初始化页面
renderList();
renderPagination();
</script>
</body>
</html>