- Java锁的逻辑(结合对象头和ObjectMonitor)
- 还在用饼状图?来瞧瞧这些炫酷的百分比可视化新图形(附代码实现)⛵
- 自动注册实体类到EntityFrameworkCore上下文,并适配ABP及ABPVNext
- 基于Sklearn机器学习代码实战
微信小程序的订阅消息是小程序的重要能力之一,为实现服务的闭环提供更优的体验。订阅消息我们应该经常见到,比如下单成功之后的 服务通知 ,支付成功后的 支付成功通知 ,都属于小程序的订阅消息.
本文只实现 一次性订阅 的功能,至于 长期订阅 与 设备订阅 ,有机会碰到再进行研究.
在开始之前,我们先看看微信小程序订阅消息的介绍:
消息能力是小程序能力中的重要组成,我们为开发者提供了订阅消息能力,以便实现服务的闭环和更优的体验.
1. 一次性订阅消息 。
一次性订阅消息用于解决用户使用小程序后,后续服务环节的通知问题。用户自主订阅后,开发者可不限时间地下发一条对应的服务消息;每条消息可单独订阅或退订.
2. 长期订阅消息 。
一次性订阅消息可满足小程序的大部分服务场景需求,但线下公共服务领域存在一次性订阅无法满足的场景,如航班延误,需根据航班实时动态来多次发送消息提醒。为便于服务,我们提供了长期性订阅消息,用户订阅一次后,开发者可长期下发多条消息.
目前长期性订阅消息仅向政务民生、医疗、交通、金融、教育等线下公共服务开放,后期将逐步支持到其他线下公共服务业务.
所以我们普通小程序,在注册成功后,订阅消息的模板选择,只有一次性订阅的选项,没有长期订阅的选项.
3. 设备订阅消息 。
设备订阅消息是一种特殊类型的订阅消息,它属于长期订阅消息类型,且需要完成「设备接入」才能使用.
了解了小程序订阅消息之后,我们开始进入正题! 。
由于后面的文章还很长,注意事项优先发出来,可能看到这里已经解决了你的问题.
特别注意第三条,版本库是2.8.2及以上的时候,订阅消息必须发生点击行为或是发起支付回调后,才可以调起订阅消息的界面。这个点击行为没有特别要求。比如一个表单,点击提交按钮后,也是可以调起订阅消息界面的。支付后的回调不需要点击行为,也可以调起订阅消息界面.
在微信公众平台登录小程序,在订阅消息功能下,进入到我的模板,找到模板,并将模板id复制出来,如果没有模板,需要先添加模板,再获取模板id 。
要添加新模板,点击 选用 按钮,在公共模板库中选择需要的模板,添加就可以了.
有很多文章说, 如果没有合适的模板,可以创建自定义模板 。但如果你真想去创建自定义模板,会发现根本找不到地方。 如果想创建自定义模板,可通过以下方式进行。 1、点击 选用 按钮,来到公共模板库。(公共模板库中的模板,与你小程序的服务类目相关) 2、在搜索框中,输入比较长的关键词。 3、点击搜素,如果还是能匹配出模板来,则重新调整关键词,直到没有任何搜索结果为止。 4、点击页面中的 帮忙我们完善模板库 ,进行自定义模板设置.
创建自定义模板的时候,一定要仔细阅读申请模板的流程,尤其是第1条。我单拉出来重点标注一下,因为没仔细看第1条,第一次申请的几个模板白白等了好几天。 模板标题需体现具体的服务场景, 要求以“通知”或“提醒”结尾 ,如:物流到货通知、交易提醒.
看到这里,会发现以上大部分跟网上的文章没啥区别,别急,正文来了! 。
前端实现的是点击提交按钮,保存表单,保存成功后发送订阅消息,在 pages/index/index.vue 下编写如下代码:
<template>
<view>
<view class="setp">
<publishStep :list="setpList" :current="0" mode="number" active-color="#eb3572"></publishStep>
</view>
<view class="container">
<u-form :model="form" ref="uForm" :rules="rules" :error-type="errorType">
<u-form-item label="姓名" label-width="160rpx" :border-bottom="true" :label-style="{'font-size':'28rpx'}" prop="realName">
<u-input v-model="form.realName" placeholder="" input-align="right" />
</u-form-item>
<u-form-item label="服务时间" label-width="160rpx" :border-bottom="true" :label-style="{'font-size':'28rpx'}"
right-icon="arrow-right" prop="serviceTime">
<u-input v-model="form.serviceTime" placeholder="请选择服务时间" :disabled="true" input-align="right" @click="timeShow=true" />
</u-form-item>
<u-form-item label="服务地址" label-width="160rpx" :border-bottom="true" :label-style="{'font-size':'28rpx'}" prop="serviceAddress">
<u-input v-model="form.serviceAddress" placeholder="" input-align="right" @click="selectAddress" />
</u-form-item>
<u-form-item label="联系电话" label-width="160rpx" :border-bottom="true" :label-style="{'font-size':'28rpx'}"
prop="lxtel">
<u-input v-model="form.lxtel" type="number" placeholder="请输入联系电话" input-align="right" :clearable="false" />
</u-form-item>
<u-form-item label="需求描述" label-width="160rpx" :border-bottom="true" :label-style="{'font-size':'28rpx'}"
prop="remarks">
<u-input v-model="form.remarks" type="text" placeholder="请输入您的需求" input-align="right" :clearable="false" />
</u-form-item>
</u-form>
</view>
<view style="height: 160rpx;"></view>
<view class="bottom_nav">
<view class="buttom_box padding-horizontal-20 padding-vertical-10">
<u-button type="error" @click="submitForm" :loading="submit_loading" style="height: 100rpx; font-weight: bold; font-size: 36rpx;">确认提交</u-button>
</view>
</view>
<u-picker mode="time" v-model="timeShow" :params="timeParams" @confirm="timeConfirm"></u-picker>
</view>
</template>
<script>
export default {
data() {
return {
form:{
realName:"",
serviceTime:'',
serviceAddress:"",
lxtel:"",
remarks:""
},
rules:{
realName: [{
required: true,
message: "请填写您的姓名",
trigger: 'change'
}],
serviceTime: [{
required: true,
message: "请选择服务时间",
trigger: 'change'
}],
lxtel: [{
required: true,
message: "请输入联系电话",
trigger: 'change'
}],
},
errorType: ['toast'],
timeShow:false,
timeParams:{
year: true,
month: true,
day: true,
hour: false,
minute: false,
second: false
},
submit_loading:false,
}
},
onReady() {
this.$refs.uForm.setRules(this.rules);
},
onLoad(params) {
let that = this;
},
methods: {
timeConfirm(e){
let that = this;
that.form.serviceTime = e.year +"-"+e.month+"-"+e.day
},
gotoOrder(){
uni.redirectTo({
url:"/pages/order/order"
})
},
submitForm(){
let that = this;
this.$refs.uForm.validate(valid=>{
if (valid){
that.$u.api.submit_order(that.form).then(res => {
if (res.success) {
let data = res.data;
uni.showToast({
title: '提交成功',
icon: 'success'
})
// #ifdef MP-WEIXIN
uni.requestSubscribeMessage({
tmplIds:['XXXXXXXXXXX'], //这里填写tempid
success:function(subscribeMessageRes){
if(subscribeMessageRes.errMsg=="requestSubscribeMessage:ok"){
if(subscribeMessageRes.XXXXXXXXXXX=="accept"){
uni.login({
provider: 'weixin',
success:function(loginRes){
if(loginRes.errMsg=="login:ok"){
const code = loginRes.code;
that.$u.api.sendSubscribeMessage({
"code":code,
"orderId":data.orderId
}).then(res=>{
that.gotoOrder()
})
}else{
that.gotoOrder()
}
},
fail() {
that.gotoOrder()
}
})
}else{
that.gotoOrder()
}
}else{
that.gotoOrder()
}
},
fail:function(){
that.gotoOrder()
}
})
// #endif
} else {
uni.$u.toast(res.message);
}
});
}
})
}
}
}
</script>
<style>
.setp{ padding: 40rpx 0;}
.bottom_nav {
position: fixed;
width: 100%;
height: 100rpx;
left: 0;
bottom: 0;
z-index: 9999;
background: #FFFFFF;
border-top: 1rpx #f3f3f3 solid;
}
</style>
这里的流程分为3步: 1、提交表单,服务端返回订单号(orderId) 2、使用 uni.requestSubscribeMessage ,调起授权框,当点击同意后,进入第三步。调起授权后,如果用户同意,回调函数的参数 subscribeMessageRes 有两个对象: errMsg 和 XXXXXXXXXXX ,errMsg不必多说。主要是这个XXXXXXXXXXX是什么。XXXXXXXXXXX是授权生成的,目测来看就是模板Id。 3、使用 uni.login ,获取 code 。 4、将 code 与 orderId 发送到服务器,服务器通过 code 获取到 openId ,再根据 orderId 获取到具体订单数据。 5、发送模板消息.
如果不出意外的话,提交成功后,弹出如下授权框 。
服务端ORM使用 SqlSugar ,微信小程序接口使用 SKIT.FlurlHttpClient.Wechat 库.
提交订单 ,这里只做演示,具体的代码自己实现下就可以了! 。
[HttpPost]
public async Task<AjaxResult> SubmitOrder(order model)
{
//生成订单号
model.order_no = DateTime.Now.ToString("yyyyMMddHHssfffff");
model.addtime = DateTime.Now;
//ExecuteReturnIdentity方法会返回自增id
var id = await db.Insertable(model).ExecuteReturnIdentity();
return new AjaxResult(){
success=true,
data = id
};
}
AjaxResult.cs 。
public class AjaxResult
{
/// <summary>
/// 是否成功
/// </summary>
public bool success { get; set; } = true;
/// <summary>
/// 错误代码
/// </summary>
public int code { get; set; } = 0;
/// <summary>
/// 返回消息
/// </summary>
public string message { get; set; }
/// <summary>
/// 返回数据
/// </summary>
public object data{ get; set;}
}
order.cs 。
[SugarTable("order")]
public class order
{
/// <summary>
/// 主键,自增Id
/// </summary>
[SugarColumn(IsPrimaryKey = true)]
public int id { get; set; }
/// <summary>
/// 订单编号
/// </summary>
public string order_no { get; set; }
/// <summary>
/// 姓名
/// </summary>
public string realName { get; set; }
/// <summary>
/// 时间
/// </summary>
public DateTime serviceTime { get; set; }
/// <summary>
/// 地址
/// </summary>
public string serviceAddress { get; set; }
/// <summary>
/// 联系电话
/// </summary>
public string lxtel { get; set; }
/// <summary>
/// 备注
/// </summary>
public string remarks { get; set; }
/// <summary>
/// 创建时间
/// </summary>
public DateTime addtime { get; set; }
}
发送一次性订阅的模板消息,传的参数为前端获取的 code 与 orderId 。根据订单编号获取订单信息,以便在订阅消息中,设置小程序信息以及打开路径。 code 用于获取用户的 openId .
[HttpPost]
public async Task<AjaxResult> SendSubscribeMessage(string code,string orderId)
{
AjaxResult result = new AjaxResult();
if (string.IsNullOrEmpty(code) || string.IsNullOrEmpty(orderId))
{
result.success = false;
result.message = "参数错误";
return result;
}
var order_model = await db.Queryable<order>().InSingleAsync(orderId);
if(order_model is null)
{
result.success = false;
result.message = "参数错误";
return result;
}
//初始化WechatApiClient
var options = new WechatApiClientOptions()
{
AppId = "appId",
AppSecret = "appSecret "
};
var client = new WechatApiClient(options);
//获取openId
var request = new SnsJsCode2SessionRequest();
request.JsCode = code;
var response = await client.ExecuteSnsJsCode2SessionAsync(request);
string openId = response.OpenId;
//获取token
var tokenRequest = new CgibinTokenRequest();
var tokenResponse = await client.ExecuteCgibinTokenAsync(tokenRequest);
var token = tokenResponse.AccessToken;
//发送模板消息
var messageRequest = new CgibinMessageSubscribeSendRequest();
IDictionary<string, CgibinMessageSubscribeSendRequest.Types.DataItem> messageData = new Dictionary<string, CgibinMessageSubscribeSendRequest.Types.DataItem>
{
{
"params1",
new CgibinMessageSubscribeSendRequest.Types.DataItem() {Value=order_model.order_no}
},
{
"params1",
new CgibinMessageSubscribeSendRequest.Types.DataItem(){Value=order_model.userNmae}
},
{
"params3",
new CgibinMessageSubscribeSendRequest.Types.DataItem(){Value=order_model.serviceTime}
},
{
"params4",
new CgibinMessageSubscribeSendRequest.Types.DataItem(){Value=order_model.serviceAddress}
},
{
"params5",
new CgibinMessageSubscribeSendRequest.Types.DataItem(){Value=order_model.addtime.ToString("yyyy-MM-dd HH:ss")}
}
};
messageRequest.AccessToken = token;
messageRequest.ToUserOpenId = openId;
messageRequest.TemplateId = "XXXXXXXXXXX";
messageRequest.MiniProgramState = "developer";
//微信小程序要跳转的地址。可以加参数
messageRequest.MiniProgramPagePath = "/pages/order/order_details?id=" + order_model.id;
messageRequest.Data = messageData;
var messageResponse = await client.ExecuteCgibinMessageSubscribeSendAsync(messageRequest);
if(messageResponse.ErrorCode==0)
{
result.success=true;
result.message = "ok";
return result;
}
result.success = false;
result.message = "error";
return result;
}
构造模板消息的时候,使用 IDictionary<string, CgibinMessageSubscribeSendRequest.Types.DataItem> messageData = new Dictionary<string, CgibinMessageSubscribeSendRequest.Types.DataItem> 来进行构造, 假设一个模板消息的详细内容是这样的:
.DATA
前面的内容。 messageRequest.TemplateId
,要与前端的模板Id一致。 messageRequest.MiniProgramState
表示跳转微信小程序的类型。默认为正式版
如果不出意外的话,你的微信会收到服务通知。点击卡片后,进入小程序的订单详情页面! 。
1、其实微信小程序的订阅消息和公众号的订阅消息模板还是比较好申请的。如果在类目模板与历史模板中无法找到合适自己的模板,那么自己申请一个模板。审核的话,2-3天就可以收到通知了。 需要注意的是,申请模板的时候,最好把各项在本地保留一份。因为一旦提交申请,在公众号或小程序后台,你就找不到了。玩意审核没通过,再申请的时候,前面写的啥内容,已经忘的差不多了! 。
2、感谢 SqlSugar ,为.Net开发者提供这么强大的ORM。真的是太方便了。 3、感谢 SKIT.FlurlHttpClient.Wechat ,为.Net开发者提供这么便捷的工具。 4、 为了能快速表达清楚意思,以上前端与服务端代码,都是精简过的,万万不可直接使用! 。
作者: gmval 出处: https://www.cnblogs.com/gmval/p/17071237.html 本文版权归作者和博客园共有,写文不易,支持原创,欢迎转载【点赞】,转载请保留此段声明,且在文章页面明显位置给出原文连接,谢谢。 关注个人公众号,定时同步更新优秀资源及技术文章 。
最后此篇关于uni-app+.NET7实现微信小程序订阅消息推送的文章就讲到这里了,如果你想了解更多关于uni-app+.NET7实现微信小程序订阅消息推送的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。
我一直在读到,如果一个集合“被释放”,它也会释放它的所有对象。另一方面,我还读到,一旦集合被释放,集合就会释放它的对象。 但最后一件事可能并不总是发生,正如苹果所说。系统决定是否取消分配。在大多数情况
我有一个客户端-服务器应用程序,它使用 WCF 进行通信,并使用 NetDataContractSerializer 序列化对象图。 由于服务器和客户端之间传输了大量数据,因此我尝试通过微调数据成员的
我需要有关 JMS 队列和消息处理的帮助。 我有一个场景,需要针对特定属性组同步处理消息,但可以在不同属性组之间同时处理消息。 我了解了特定于每个属性的消息组和队列的一些知识。我的想法是,我想针对
我最近开始使用 C++,并且有一种强烈的冲动 #define print(msg) std::cout void print(T const& msg) { std::cout void
我已经为使用 JGroups 编写了简单的测试。有两个像这样的简单应用程序 import org.jgroups.*; import org.jgroups.conf.ConfiguratorFact
这个问题在这里已经有了答案: Firebase messaging is not supported in your browser how to solve this? (3 个回答) 7 个月前关
在我的 C# 控制台应用程序中,我正在尝试更新 CRM 2016 中的帐户。IsFaulted 不断返回 true。当我向下钻取时它返回的错误消息如下: EntityState must be set
我正在尝试通过 tcp 将以下 json 写入 graylog 服务器: {"facility":"GELF","file":"","full_message":"Test Message Tcp",
我正在使用 Django 的消息框架来指示成功的操作和失败的操作。 如何排除帐户登录和注销消息?目前,登录后登陆页面显示 已成功登录为“用户名”。我不希望显示此消息,但应显示所有其他成功消息。我的尝试
我通过编写禁用qDebug()消息 CONFIG(release, debug|release):DEFINES += QT_NO_DEBUG_OUTPUT 在.pro文件中。这很好。我想知道是否可以
我正在使用 ThrottleRequest 来限制登录尝试。 在 Kendler.php 我有 'throttle' => \Illuminate\Routing\Middleware\Throttl
我有一个脚本,它通过die引发异常。捕获异常时,我想输出不附加位置信息的消息。 该脚本: #! /usr/bin/perl -w use strict; eval { die "My erro
允许的消息类型有哪些(字符串、字节、整数等)? 消息的最大大小是多少? 队列和交换器的最大数量是多少? 最佳答案 理论上任何东西都可以作为消息存储/发送。实际上您不想在队列上存储任何内容。如果队列大部
基本上,我正在尝试创建一个简单的 GUI 来与 Robocopy 一起使用。我正在使用进程打开 Robocopy 并将输出重定向到文本框,如下所示: With MyProcess.StartI
我想将进入 MQ 队列的消息记录到数据库/文件或其他日志队列,并且我无法修改现有代码。是否有任何方法可以实现某种类似于 HTTP 嗅探器的消息记录实用程序?或者也许 MQ 有一些内置的功能来记录消息?
我得到了一个带有 single_selection 数据表和一个命令按钮的页面。命令按钮调用一个 bean 方法来验证是否进行了选择。如果不是,它应该显示一条消息警告用户。如果进行了选择,它将导航到另
我知道 MSVC 可以通过 pragma 消息做到这一点 -> http://support.microsoft.com/kb/155196 gcc 是否有办法打印用户创建的警告或消息? (我找不到谷
当存在大量节点或二进制数据时, native Erlang 消息能否提供合理的性能? 情况 1:有一个大约 50-200 台机器的动态池(erlang 节点)。它在不断变化,每 10 分钟大约添加或删
我想知道如何在用户登录后显示“欢迎用户,您已登录”的问候消息,并且该消息应在 5 秒内消失。 该消息将在用户成功登录后显示一次,但在同一 session 期间连续访问主页时不会再次显示。因为我在 ho
如果我仅使用Welcome消息,我的代码可以正常工作,但是当打印p->client_name指针时,消息不居中。 所以我的问题是如何将消息和客户端名称居中,就像它是一条消息一样。为什么它目前仅将消
我是一名优秀的程序员,十分优秀!