草庐IT

小程序如何向公众号推送消息

fbbqt 2023-11-11 原文

 如果你在开发公众号(跟小程序绑在同一个开发平台),那就可以直接使用公众号的相关接口去往用户的公众号推送消息。但你只开发小程序,没有开发公众号,可以参考方法给用户公众号推送消息。

小程序中的接口:下发小程序和公众号统一的服务

        意思就是小程序中的这个接口可以使用公众号的模板向用户公众号推送消息

uniformMessage.send | 微信开放文档微信开发者平台文档https://developers.weixin.qq.com/miniprogram/dev/api-backend/open-api/uniform-message/uniformMessage.send.html前提条件:

微信公众号:AppId和APPSecret(必须认证)
微信小程序:AppId和APPSecret(必须认证)
微信开放平台(小程序和公众号必须绑定到同一个开放平台,必须认证)

UnionID机制说明:

开发者可通过OpenID(每个应用都拥有自己的openID,它们的openID不一样)来获取用户基本信息。特别需要注意的是,如果开发者拥有多个移动应用、网站应用和公众帐号,可通过获取用户基本信息中的unionid来区分用户的唯一性,因为只要是同一个微信开放平台帐号下的移动应用、网站应用和公众帐号,用户的unionid是唯一的。换句话说,同一用户,对同一个微信开放平台下的不同应用,unionid是相同的。(其中的unionid绑定了开放者平台才会有的)

一、获取小程序用户信息

注:如果你已经开始开发小程序,或者已经得到了用户信息,可直接看第二步

1、小程序前端通过调用wx.login()会获取到一个用户登录凭证code(有效期五分钟),将code传给后台,后台通过appId、APPSecret和code能够获取到这个用户的微信基本信息。文档地址:

auth.code2Session | 微信开放文档微信开发者平台文档https://developers.weixin.qq.com/miniprogram/dev/api-backend/open-api/login/auth.code2Session.html接口如下:

GET 
https://api.weixin.qq.com/sns/jscode2session?appid=APPID&secret=SECRET&js_code=JSCODE&grant_type=authorization_code

(其中的unionID是小程序绑定了开放平台才会有的,如果绑定后还是没有unionID,那就是此用户没有关注与小程序相同主体的公众号)

2、将用户信息保存在自己的数据库中

3、通过小程序的AppId和AppSecret获取小程序的access_token(7200秒有效)并保存到数据库中,文档地址:auth.getAccessToken | 微信开放文档微信开发者平台文档https://developers.weixin.qq.com/miniprogram/dev/api-backend/open-api/access-token/auth.getAccessToken.html

https请求方式: GET(请使用https协议)
https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET

二、获取微信公众号的所有用户信息(公众号中的用户都是已经关注该公众号的)并存储在自己的数据库中

1、通过微信公众号的AppId和AppSecret(当前ip地址必须在微信公众号的白名单内)
获取微信公众号的access_token(7200秒有效),文档地址:

微信开放文档微信开发者平台文档https://developers.weixin.qq.com/doc/offiaccount/Basic_Information/Get_access_token.html

https请求方式: GET(请使用https协议)
https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET

2、通过刚才获取到的access_token去获取所有用户的openId,文档地址:

微信开放文档微信开发者平台文档https://developers.weixin.qq.com/doc/offiaccount/User_Management/Getting_a_User_List.html接口如下:

http请求方式: GET(请使用https协议)
https://api.weixin.qq.com/cgi-bin/user/get?access_token=ACCESS_TOKEN&next_openid=NEXT_OPENID

3、将所有的openId全部放在一个新的数组中,然后for循环,循环次数为openId的数组的长度,然后调用链接循环请求每个用户的基本信息,并存到数据库中,文档地址:
微信开放文档微信开发者平台文档https://developers.weixin.qq.com/doc/offiaccount/User_Management/Get_users_basic_information_UnionID.html#UinonId
接口如下:

http请求方式: GET(请使用https协议)
https://api.weixin.qq.com/cgi-bin/user/info?access_token=ACCESS_TOKEN&openid=OPENID&lang=zh_CN

三、微信公众号推送消息

现在,本地数据库中存放着小程序用户表和关注微信公众号的用户表,下一步就是向小程序用户推送微信公众号信息

1、在本地小程序用户表中获取一个用户M的信息,得到用户M的openId和unionId

2、通过M的unionId到本地微信公众号表里去查找对应的M用户的微信公众号openId

3、通过小程序中的 下发小程序和公众号统一的服务消息(uniformMessage.send)接口链接发送关注模板消息,接口链接如下。文档地址在文章开头。

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

注意参数:

1、access_token 这个接口中的access_token必须是小程序的access_token,不能使用公众号的,因为官方黑这个接口就是想大家在开发小程序的时候,如果要发送公众号消息直接使用这个接口就可以了,无需再去调用公众号的模板消息接口。

2、touser 用户openid,发送公众号模板消息,就必须用mp_template_msg.appid对应的公众号的openid   

//发送公众号模板消息(uniformMessage.send)下发小程序和公众号统一的服务消息
func SendUniformMessage() {
	//小程序的access_token
	var access_token = `52_f9pr1XSlC4B7UK9oQAjcrYLJ1qdgVzs7Dj-OjolTTi8y7fFKWazOGSHjFBny9Jjqjmgu1f4yzRrao7nlH2z7-Vu5MDHZOkagZJdTS5CZ74GBAkC6nDqfImQvwU1Qk7FOLnRJKtOW1iDM7Nq4UVJeAFAJKY`
	sender := weapp.UniformMsgSender{
		ToUser: "oIozb6u_3Mv8V4g3u5_JIUDvYdJ0", //公众号模板用公众号中用户的openid
		//UniformWeappTmpMsg: weapp.UniformWeappTmpMsg{
		//	TemplateID: "template-id",
		//	Page:       "page",
		//	FormID:     "form-id",
		//	Data: weapp.UniformMsgData{
		//		"keyword": {Value: "value"},
		//	},
		//	EmphasisKeyword: "keyword.DATA",
		//},
		UniformMpTmpMsg: weapp.UniformMpTmpMsg{
			AppID:      utils.Public_AppID,
			TemplateID: "W_bIT89e8JNzVXtV6arw8t5Fn3N6xrJjagHEWiXDSts",
			URL:        "http://weixin.qq.com/download",
			//Miniprogram: weapp.UniformMsgMiniprogram{"miniprogram-app-id", "page-path"},
			Data: weapp.UniformMsgData{
				"keyword": {"value", "#173177"},
			},
		},
	}

	res, err := sender.Send(access_token)
	if err != nil {
		// 处理一般错误信息
		log.Error("dddddddddddd: ", err)
		return
	}
	fmt.Printf("返回结果qqqq: %#v", res)
	if err := res.GetResponseError(); err != nil {
		// 处理微信返回错误信息
		log.Error("ccccccccccccc: ", err)
		return
	}

	fmt.Printf("返回结果: %#v", res)
}

四、需要注意的一些问题

在获取关注公众号的用户信息并存到本地数据库中时,要注意两者之间的同步。我的处理如下:

1、首先获取微信公众号的用户列表,得到一系列用户的openID,记为A;再从本地公众号数据库中获得之前关注的一系列用户openID,记为B

2、分别取两个集合之间的差集,进一步进行处理

1)、B与A的差集,记为Y,这些全是已取消关注微信公众号的用户(如果后面重新关注公众号,微信公众号会为这些用户重新按时间戳(秒)记录新的,因为关注公众号的用户要记录到本地,所以)

2)、A与B的差集,记为X,这些全是最新关注的用户(包括之前取消关注,再重新关注的用户)

3)、Y集合中的openID全是需要先去数据库删除的用户,X集合中的openID全是需要保存到本地的用户

3、根据自己的业务,定时去按照以上进行同步到本地

以上三步可以保证本地关注公众号的用户表是最新的。虽然效率不高,但也是想到比较好的方法了,如果有更好的想法,欢迎指点

有关小程序如何向公众号推送消息的更多相关文章

  1. ruby - 如何使用 Nokogiri 的 xpath 和 at_xpath 方法 - 2

    我正在学习如何使用Nokogiri,根据这段代码我遇到了一些问题:require'rubygems'require'mechanize'post_agent=WWW::Mechanize.newpost_page=post_agent.get('http://www.vbulletin.org/forum/showthread.php?t=230708')puts"\nabsolutepathwithtbodygivesnil"putspost_page.parser.xpath('/html/body/div/div/div/div/div/table/tbody/tr/td/div

  2. ruby - 如何从 ruby​​ 中的字符串运行任意对象方法? - 2

    总的来说,我对ruby​​还比较陌生,我正在为我正在创建的对象编写一些rspec测试用例。许多测试用例都非常基础,我只是想确保正确填充和返回值。我想知道是否有办法使用循环结构来执行此操作。不必为我要测试的每个方法都设置一个assertEquals。例如:describeitem,"TestingtheItem"doit"willhaveanullvaluetostart"doitem=Item.new#HereIcoulddotheitem.name.shouldbe_nil#thenIcoulddoitem.category.shouldbe_nilendend但我想要一些方法来使用

  3. ruby - 在 Ruby 程序执行时阻止 Windows 7 PC 进入休眠状态 - 2

    我需要在客户计算机上运行Ruby应用程序。通常需要几天才能完成(复制大备份文件)。问题是如果启用sleep,它会中断应用程序。否则,计算机将持续运行数周,直到我下次访问为止。有什么方法可以防止执行期间休眠并让Windows在执行后休眠吗?欢迎任何疯狂的想法;-) 最佳答案 Here建议使用SetThreadExecutionStateWinAPI函数,使应用程序能够通知系统它正在使用中,从而防止系统在应用程序运行时进入休眠状态或关闭显示。像这样的东西:require'Win32API'ES_AWAYMODE_REQUIRED=0x0

  4. python - 如何使用 Ruby 或 Python 创建一系列高音调和低音调的蜂鸣声? - 2

    关闭。这个问题是opinion-based.它目前不接受答案。想要改进这个问题?更新问题,以便editingthispost可以用事实和引用来回答它.关闭4年前。Improvethisquestion我想在固定时间创建一系列低音和高音调的哔哔声。例如:在150毫秒时发出高音调的蜂鸣声在151毫秒时发出低音调的蜂鸣声200毫秒时发出低音调的蜂鸣声250毫秒的高音调蜂鸣声有没有办法在Ruby或Python中做到这一点?我真的不在乎输出编码是什么(.wav、.mp3、.ogg等等),但我确实想创建一个输出文件。

  5. ruby-on-rails - 如何验证 update_all 是否实际在 Rails 中更新 - 2

    给定这段代码defcreate@upgrades=User.update_all(["role=?","upgraded"],:id=>params[:upgrade])redirect_toadmin_upgrades_path,:notice=>"Successfullyupgradeduser."end我如何在该操作中实际验证它们是否已保存或未重定向到适当的页面和消息? 最佳答案 在Rails3中,update_all不返回任何有意义的信息,除了已更新的记录数(这可能取决于您的DBMS是否返回该信息)。http://ar.ru

  6. ruby-on-rails - 'compass watch' 是如何工作的/它是如何与 rails 一起使用的 - 2

    我在我的项目目录中完成了compasscreate.和compassinitrails。几个问题:我已将我的.sass文件放在public/stylesheets中。这是放置它们的正确位置吗?当我运行compasswatch时,它不会自动编译这些.sass文件。我必须手动指定文件:compasswatchpublic/stylesheets/myfile.sass等。如何让它自动运行?文件ie.css、print.css和screen.css已放在stylesheets/compiled。如何在编译后不让它们重新出现的情况下删除它们?我自己编译的.sass文件编译成compiled/t

  7. ruby - 如何将脚本文件的末尾读取为数据文件(Perl 或任何其他语言) - 2

    我正在寻找执行以下操作的正确语法(在Perl、Shell或Ruby中):#variabletoaccessthedatalinesappendedasafileEND_OF_SCRIPT_MARKERrawdatastartshereanditcontinues. 最佳答案 Perl用__DATA__做这个:#!/usr/bin/perlusestrict;usewarnings;while(){print;}__DATA__Texttoprintgoeshere 关于ruby-如何将脚

  8. ruby - 如何指定 Rack 处理程序 - 2

    Rackup通过Rack的默认处理程序成功运行任何Rack应用程序。例如:classRackAppdefcall(environment)['200',{'Content-Type'=>'text/html'},["Helloworld"]]endendrunRackApp.new但是当最后一行更改为使用Rack的内置CGI处理程序时,rackup给出“NoMethodErrorat/undefinedmethod`call'fornil:NilClass”:Rack::Handler::CGI.runRackApp.newRack的其他内置处理程序也提出了同样的反对意见。例如Rack

  9. ruby - 在 Ruby 中编写命令行实用程序 - 2

    我想用ruby​​编写一个小的命令行实用程序并将其作为gem分发。我知道安装后,Guard、Sass和Thor等某些gem可以从命令行自行运行。为了让gem像二进制文件一样可用,我需要在我的gemspec中指定什么。 最佳答案 Gem::Specification.newdo|s|...s.executable='name_of_executable'...endhttp://docs.rubygems.org/read/chapter/20 关于ruby-在Ruby中编写命令行实用程序

  10. ruby - 如何每月在 Heroku 运行一次 Scheduler 插件? - 2

    在选择我想要运行操作的频率时,唯一的选项是“每天”、“每小时”和“每10分钟”。谢谢!我想为我的Rails3.1应用程序运行调度程序。 最佳答案 这不是一个优雅的解决方案,但您可以安排它每天运行,并在实际开始工作之前检查日期是否为当月的第一天。 关于ruby-如何每月在Heroku运行一次Scheduler插件?,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/questions/8692687/

随机推荐