【技术】如何在微信小程序中识别二维码?
一、前言
由于微信小程序的规则限制,在小程序内部是无法直接识别二维码的,这样对于想通过微信小程序给微信公众号引流的想法大抵都被扼杀了,偶然间发现微信官方小程序“微保”竟然做到了,而且他们竟是通过小程序客服消息这种曲线救国的方式实现的,于是好好研究了一番总算也把功能实现了,遂整理思绪记录一下实现过程和方法,为有想通过微信小程序给公众号引流想法的开发者提供借鉴(相信有此想法的还是大有人在的 哈哈~)。
二、如何实现二维码识别?
“微保”小程序的实现步骤如下:
1、用户在小程序中点击去关注的按钮跳转到客服消息聊天页面。
2、输入“666” 自动回复微信公众号关注的链接,点击链接进入微信公众号二维码页面(嗯 这骚操作还是挺6的)。
3、用户长按识别二维码直接跳转公众号关注页面,直接关注即可。
虽然规则限制不允许小程序给公众号引流,并做了很多技术手段上的规避,但通过这种方式能够实现也算是开了一扇小窗。
三、代码实现
1、小程序端代码实现
<button class="pay-button" open-type='contact' show-message-card='true' send-message-img='/images/icon_input.png' >
微信付款
</button>
呀呀呀~ 不是说小程序给公众号引流么?怎么扯到了微信付款,额..... 我这里做的正是在小程序中识别微信收款码的功能,不过原理都是一样的,只要实现了在小程序内识别二维码的功能,你将这个微信收款码换成公众号二维码不就成了么!! 好,言归正传,继续上代码。
代码释义:
open-type='contact' 指定按钮类型为唤起客服消息的按钮。
show-message-card 是否显示会话内消息卡片,设置此参数为 true,用户进入客服会话会在右下角显示"可能要发送的小程序"提示,用户点击后可以快速发送小程序消息。
send-message-title 官方文档解释为会话内消息卡片标题,我试过了并没有用,还有一点“微保”小程序点击按钮可自动输入并发送“666”,研究了半天我这边并不能如愿实现此功能,如有知道如何实现的还请告知一二,万分感谢~。
send-message-img 指定会话内消息卡片图片即会话窗口右下角自动展示的图片。如下图:
2、后端代码实现
我这里后端代码使用C#实现的,如有需要其他语言的实现代码还请自行百度。
1)、接口认证
对接微信客服消息前需要在微信公众平台配置消息推送Token以及我们自己的API地址并验证成功才行,这一步操作颇费了些功夫。
认证代码如下:
/// <summary>
/// 微信消息推送配置认证
/// </summary>
/// <param name="echostr">随机字符串</param>
/// <param name="signature">微信签名</param>
/// <param name="timestamp">时间戳</param>
/// <param name="nonce">随机数</param>
/// <returns></returns>
[HttpGet]
public HttpResponseMessage weixinchat(string echostr, string signature, string timestamp, string nonce)
{
try
{
string token = "xxxxx"; //写自己配置的token
if (!CheckSignature(token, signature, timestamp, nonce))
echostr = "验证不正确";
HttpResponseMessage responseMessage = new HttpResponseMessage { Content = new StringContent(echostr, Encoding.GetEncoding("UTF-8"), "text/plain") };
return responseMessage;
}
catch (Exception ex)
{
throw ex;
}
}
2)、接收消息内容并回复
当用户在客服会话发送消息、或由某些特定的用户操作引发事件推送时,微信服务器会将消息或事件的数据包发送到开发者填写的 URL,各消息类型的推送JSON、XML数据包结构如下:
文本消息
用户在客服会话中发送文本消息时将产生如下数据包:
JSON 格式
{
"ToUserName": "toUser",
"FromUserName": "fromUser",
"CreateTime": 1482048670,
"MsgType": "text",
"Content": "this is a test",
"MsgId": 1234567890123456
}
XML 格式
<xml>
<ToUserName><![CDATA[toUser]]></ToUserName>
<FromUserName><![CDATA[fromUser]]></FromUserName>
<CreateTime>1482048670</CreateTime>
<MsgType><![CDATA[text]]></MsgType>
<Content><![CDATA[this is a test]]></Content>
<MsgId>1234567890123456</MsgId>
</xml>
参数说明
图片消息
用户在客服会话中发送图片消息时将产生如下数据包:
JSON 格式
{
"ToUserName": "toUser",
"FromUserName": "fromUser",
"CreateTime": 1482048670,
"MsgType": "image",
"PicUrl": "this is a url",
"MediaId": "media_id",
"MsgId": 1234567890123456
}
XML 格式
<xml>
<ToUserName><![CDATA[toUser]]></ToUserName>
<FromUserName><![CDATA[fromUser]]></FromUserName>
<CreateTime>1482048670</CreateTime>
<MsgType><![CDATA[image]]></MsgType>
<PicUrl><![CDATA[this is a url]]></PicUrl>
<MediaId><![CDATA[media_id]]></MediaId>
<MsgId>1234567890123456</MsgId>
</xml>
还有小程序卡片消息、进入会话事件 等这里就不一一列举了,大家自己看官方文档 接收消息和事件 。
消息回复代码实现
/// <summary>
/// 接收用户消息并处理
/// </summary>
/// <returns></returns>
[HttpPost]
public HttpResponseMessage weixinchat()
{
var content = Request.Content.ReadAsStringAsync().Result;
wxMessageModel msgModel = JsonConvert.DeserializeObject<wxMessageModel>(content);
LogUtil.WriteLog("接收的客服消息:" + msgModel.Content);
if (IsNumber(msgModel.Content))
{
TradeOrderModel tmodel = new TradeOrderBLL().getModelByOrderNo(msgModel.Content);
string receivecode = "";
string username = "";
if (tmodel.retype == 1)
{
username = tmodel.reusername;
receivecode = new UserBLL().GetModel(tmodel.reuserid).receivecode;
}
else
{
username = tmodel.orderusername;
receivecode = new UserBLL().GetModel(tmodel.orderuserid).receivecode;
}
string payImage = "https://xxxx.com/" + receivecode; WxMessageUtil.SendMessage(msgModel.FromUserName, payImage, tmodel.totalmoney, username);
}
HttpResponseMessage responseMessage = new HttpResponseMessage();
return responseMessage;
}
/// <summary>
/// 接收到的消息模型
/// </summary>
public class wxMessageModel
{
public string FromUserName { get; set; }
public string MsgType { get; set; }
public string Content { get; set; }
}
/// <summary>
/// WxMessageUtil 发送消息
/// </summary>
/// <param name="touser"></param>
public static bool SendMessage(string touser, string payimg, decimal money,string reciveuser)
{
try
{
string accessToken = WeixinUtil.GetAccessToken();
string SendMessageApi = ConfigurationManager.AppSettings["SendMessageApi"];
string postUrl = SendMessageApi +
"?access_token=" + accessToken;
JObject data = new JObject();
data.Add("touser", touser);
data.Add("msgtype", "link");
data.Add("link", JObject.FromObject(new
{
title = "微信支付",
description = "点击链接进入扫码付款\r\n金额:¥" + money + "\r\n收款人:" + reciveuser,
url = payimg,
thumb_url = payimg
}));
LogUtil.WriteLog("客服消息发送用户:" + touser + "内容:" + payimg);
string postData = data.ToString();
var res = WeixinUtil.PostResponse(postUrl, postData);
RetMessage ret = JsonConvert.DeserializeObject<RetMessage>(res);
LogUtil.WriteLog("客服消息发送结果:" + ret.errmsg);
return ret.errmsg == "ok";
}
catch (Exception ex)
{
throw ex;
}
}
代码中涉及的两个Util类WeixinUtil,WxMessageUtil 链接:https://pan.baidu.com/s/1cJ-s48LGIrDvufCJXr38rw 密码:7pyc 取用自便。
最终实现效果如下:
参考资料:
小程序官方文档
微信小程序-消息推送服务器认证 C#