1 创建安全临时QR令牌-德赢Vwin官网 网
×

创建安全临时QR令牌

消耗积分:0 | 格式:zip | 大小:0.31 MB | 2022-12-22

王雪

分享资料个

描述

介绍

“我在那里”创建由 Azure Sphere 设备签名的安全临时 QR 令牌(JSON Web 令牌)以供以后验证。

pYYBAGOSxb-AJZ0qAAFlX-IN9-k000.jpg
 

问题

在许多情况下,我们必须表明我们曾在某个地点和某个时间出现过。

我们不希望用户必须事先被识别,因此身份证(磁卡、芯片卡、非接触式卡或带有 NFC 标签的智能手机)等解决方案不值得我们使用。也不值得使用生物特征识别的解决方案。

典型用例

  • 奖励使用回收箱的市民。
  • 一名送货员或送货员,以证明她/他去了一个收集点。
  • 为那些来到某些商店的人提供忠诚度积分。
  • 记录内部和外部员工的签入和签出
  • 记录清洁工何时进入和离开清洁某个区域。

解决方案

IWT (I Was There) 生成带有日期标记的 QR 码,该标记独立于人,经过签名且是唯一的,以避免对其进行修改,以保证该标记以后未被修改。

IWT 的原型实施,用于奖励回收公民的计划:

 

它是如何工作的

  • 用户接近 IWT 设备。
  • 然后,用户按下按钮,或检测到门的关闭或打开事件,或者通过接近传感器通知设备生成新的二维码。
  • 设备离线生成一个新的二维码,其中包含签名的 JWT 令牌、JSON Web 令牌,包括唯一标识符和令牌发布的日期和时间。
  • 然后设备在低功耗电子纸显示器上显示二维码。
 
  • 异步地,设备向 Azure 云发送事件以记录和监控新的 QR 请求
  • 用户可以使用任何相机捕捉图像以供以后验证,或者可以使用特定的应用程序来验证令牌。
  • 在一段可配置的时间后,令牌从屏幕上消失,设备准备好生成下一个令牌。
  • 对于忠诚度计划,IWT 设备可以从 IOT Central 平台发出编程的奖励消息。

或者,该设备可以生成一个听不见的声音信号,该信号可以用任何录音设备录制(实施待定)。

挑战

在解决方案的设计过程中,我遇到了几个影响最终解决方案的问题:

  • 无法使用 Azure Sphere Pluton 安全子系统来加密数据。此外,Azure Sphere 目前不提供用于加密的 API。此外,也没有可用于检索设备标识符的 API 函数。
  • 官方 JSON Web Token (JWT) 库使用 OpenSSL 或 GnuTLS,这些库对于这个嵌入式系统来说太重了。
  • 没有用于 Azure Sphere 设备的 waveshare 电子纸显示库。

克服障碍

我的第一个决定是尝试合并一个加密处理器模块来执行加密、签名和存储加密密钥。不幸的是,我仍然没有按时收到密码模块,不得不选择软件解决方案。

  • 对于密码学,我决定使用 wolfCrypt 库。幸运的是,wolfSSL 发布了一个 Visual Studio 解决方案,其中包含用于 wolfCrypt 库的加密算法测试。
  • JWT 令牌直接使用字符串函数形成,无需使用任何临时库。
  • 我为waveshare 1.54英寸电子纸模块显示器做了一个STM32 EPD驱动的适配。

设计

硬件

硬件包括安富利 Azure Sphere MT320 入门套件开发套件和 Waveshare 1.54 英寸电子纸模块电子墨水显示器。

Microsoft Azure Sphere 解决方案的优势

pYYBAGOSxcWAIQH1AACsDGqV56s532.png
使用 Azure Sphere 解决方案的优势
 

Avnet Azure Sphere MT320 入门套件

  • Azure Sphere MT3620 入门套件支持使用 Avnet 认证的 Azure Sphere 模块进行快速原型制作,该模块基于 Microsoft MT3620AN 设备。
  • MT3620 是首款通过 Azure Sphere 认证的“微控制器”,是一款具有“端到端安全性”的 SoC 物联网设备。
  • 用户应用程序可以针对它的 500 MHz ARM Cortex-A7 内核以及两个旨在支持实时要求的通用 200 MHz ARM Cortex-M4F I/O 子系统内核。片上外设(GPIO、UART、I2C、SPI、I2S、PWM 和 ADC)可以映射到这三个用户可访问内核中的任何一个。
poYBAGOSxciAFwqbAADRrLJlyxY014.png
 

微雪1.54寸电子纸模组电子墨水屏

  • 选择电子墨水屏是因为它具有显示二维码的良好品质,并且在具有这些特性的项目中具有较低的功耗。
  • 它是一个电子墨水显示模块,1.54英寸,200 x 200分辨率,带有嵌入式控制器,通过SPI接口通信,支持局部刷新。
  • 特点:低功耗、宽视角、无电显示清晰。
poYBAGOSxcyATvtIAAAvI8thKWM176.png
Waveshare 1.54 电子纸模组 - 后视图
 
pYYBAGOSxc6AFGrmAAAke-9sVhQ879.png
Waveshare 1.54 电子纸模组 - 正视图
 

软件设计

状态图

  • 空闲显示“按A”
  • 奖励显示与 QR 关联的奖励(如果有)
  • JWT_QR问题并显示新的 QR 令牌
  • 时钟显示时间时钟
  • 设置显示设置
  • 同步设置 与 Azure 云同步设置
  • Azure 云异步任务发送/接收/同步云数据
poYBAGOSxdKAPpbDAAA-a2wIotY551.png
内河运输状态图
 

用户界面

 

空闲屏幕

在空闲状态期间,屏幕显示按下 A 按钮以获取新 QR 的指示

poYBAGOSxf2AUqLqAAmnlMz-32A505.jpg
空闲屏幕
 

奖励画面

如果收到下一个 QR 的新奖品状态,则按下按钮 A 后,将显示与 QR 关联的奖品。客户忠诚度计划的选项。

pYYBAGOSxieAWx77AAqzfsmgR70553.jpg
奖励画面
 

二维码屏幕

然后是包含签名的 JWT 令牌的新 QR 码。从 Azure 云中设置的时间将处于此状态。

poYBAGOSxlqAC25vAAoiWgiMDnA802.jpg
二维码屏幕
 

时钟屏幕和设置

按下 B 按钮时,会显示带有设备当前时间的时钟,如果再次按下,则会显示应用程序设置。

pYYBAGOSxn6AVbE2AAtljgsTe4k407.jpg
时钟屏幕和设置
 

 

创建 JWT 令牌 QR

JWT 令牌 QR 剖析

pYYBAGOSxoOAd1GoAACDxNl5MDk976.png
 

QR 码包含此字符串:

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJqdGkiOiJlMmRhNzc3My1hN2NkLTQ0YTAtODVkNy00M2ZlMDY1NGNiMjItN2RjNTQ4MTEtNWRjYjBjNzAiLCJpYXQiOjE1NzM1ODgwODB9.Dm8qKzv5n0EHMCcIECn08Ev_eppzPNc-hGtuICCNGK0

它是一种紧凑形式的 JSON Web 令牌。JWT 通常如下所示:xxxxx.yyyyy.zzzzz

JSON Web Token (JWT) 是一种紧凑的 URL 安全方式,用于表示要在两方之间传输的声明。JSON Web Token (JWT) 是一个开放标准 (RFC 7519)。JWT 中的声明被编码为 JSON 对象,用作 JSON Web 签名 (JWS) 结构的有效负载或用作 JSON Web 加密 (JWE) 结构的明文。此信息可以被验证和信任,因为它是经过数字签名的。JWT 可以使用秘密(使用 HMAC 算法)或使用 RSA 或 ECDSA 的公钥/私钥对进行签名。https://tools.ietf.org/html/rfc7519

它由以点(.)分隔的三部分组成,分别是:

  • 标头:包含令牌的元数据,它至少包含签名类型和加密算法。
  • Payload/Claim:包含我们要传输的信息,
  • Signature:使用header和payload计算得出,也可以验证内容没有被篡改。

这三部分的内容都是Base64Url编码的。对上述token的三部分进行解码:

poYBAGOSxoaAY579AAB2cdTAZgE878.png
 

Header :声明编码对象是一个 JSON Web Token,并且它是使用 HS256 算法签名的。

{
"alg": "HS256",
"typ": "JWT"
}

Payload /Claim :我们正在使用两个已注册的声明名称。在 JWT 的上下文中,声明可以定义为关于实体的声明,以及关于令牌本身的附加元数据。服务器可用于正确处理 JSON Web Token 身份验证的声明和声明。我们可以提供多种索赔;这些包括已注册的声明名称、公共声明名称和私人声明名称。

  • iat :“颁发于”时间,以 Unix 时间表示,颁发令牌
  • jti :JWT ID 声明为 JWT 提供了唯一标识符
{
"jti": "e2da7773-a7cd-44a0-85d7-43fe0654cb22-7dc54811-5dcb0c70",
"iat": 1573588080
}

https://tools.ietf.org/html/draft-ietf-oauth-json-web-token-32#section-10.1

签名:数字签名或消息验证代码 (MAC)。

https://tools.ietf.org/html/rfc7515

HMACSHA256(
  base64UrlEncode(header) + "." +
  base64UrlEncode(payload),
  [your-256-bit-secret]
)

保护 JWT 令牌

Azure sphere 不提供 API 来为来自 A7 和/或 M4 子系统的加密函数调用获取硬件支持/加速。所以我们正在使用 wolfSSL 嵌入式 SSL 库(以前称为 CyaSSL)

狼SSL

wolfSSL 嵌入式 SSL 库(以前称为 CyaSSL)是一个用 ANSI C 编写的轻量级 SSL/TLS 库,适用于嵌入式、RTOS 和资源受限环境——主要是因为它的体积小、速度快和功能集。由于其免版税定价和出色的跨平台支持,它也常用于标准操作环境。wolfSSL 支持当前 TLS 1.3 和 DTLS 1.2 级别的行业标准,比 OpenSSL 小 20 倍,wolfSSL 由 wolfCrypt 库提供支持。

https://github.com/wolfSSL/wolfssl/tree/master/IDE/VS-AZURE-SPHERE

键控哈希 HMAC

wolfCrypt 目前提供 HMAC 来满足消息摘要的需要。结构 Hmac 位于标题“wolfssl/wolfcrypt/hmac.h”中。

HMAC 初始化是用 wc_HmacSetKey() 完成的。对于我们使用 HMAC SHA-256 的项目

标头

{"alg":"HS256","typ":"JWT"}
BASE64     eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9
BASE64URL  eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9

有效载荷

{"sub":"1234567890","name":"John Doe","iat":1516239022}
BASE64  eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ==
BASE64URL  eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ

验证签名

HMACSHA256(
base64UrlEncode(header) + "." +
base64UrlEncode(payload),
0123456789ABCDEF0123456789ABCDEF )

结果是:

HMACSHA256(eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ,
0123456789ABCDEF0123456789ABCDEF)

最后:

HEX         A650E04A6412F8B67A06942E513556D35C9BE22FC8EA12D92970AACFB76B6EED
HEX2B64     plDgSmQS+LZ6BpQuUTVW01yb4i/I6hLZKXCqz7drbu0=
B642B64URL  plDgSmQS-LZ6BpQuUTVW01yb4i_I6hLZKXCqz7drbu0

编码令牌

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9
.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ
.plDgSmQS-LZ6BpQuUTVW01yb4i_I6hLZKXCqz7drbu0

hmac hmac;

byte        key[24];            /*fill key with keying material*/
byte        buffer[2048];   /*fill buffer with data to digest*/
byte        hmacDigest[SHA256_DIGEST_SIZE];
wc_HmacSetKey(&hmac, SHA256, key, sizeof(key));
wc_HmacUpdate(&hmac, buffer, sizeof(buffer));
wc_HmacFinal(&hmac, hmacDigest);

hmacDigest 现在包含缓冲区中散列数据的摘要。

生成二维码

我们正在使用 Richard Moore QR Code 库,这是一个用 C 语言生成 QR 码的简单库,针对处理和内存受限系统进行了优化。

特征:

  • 基于堆栈(不需要堆;但如果需要,您可以使用堆)
  • 低内存占用(相对)
  • 编译时剥离不必要的逻辑
  • 麻省理工学院执照;

https://github.com/ricmoo/QRCode

走向云端

实施步骤

  • 创建自定义 IoT Central 应用程序
  • 创建设备模板
  • 将 QR 请求事件添加到测量选项卡
  • 将切换控件添加到“设置”选项卡:RGB LED 控件、WWAN 和 APP LED 控件
  • 将应用程序信息添加到属性选项卡
  • 应用版本
  • 当前 SSID
  • BSSID
  • 当前的 Wi-Fi 射频

资源

https://www.element14.com/community/groups/azuresphere/blog/2019/05/09/avnets-azure-sphere-starter-kit-out-of-box-demo-part-3-of-3

监控 Qr 请求

每当新的每周 QR 码异步发布到 Azure 云时,在构建应用程序时发送到 Azure IoT Central 或 Azure IoT Hub。

下图中看到的点对应于按下 A 按钮后或当簧片开关检测到从打开到关闭的步骤时生成 QR 码的事件。

pYYBAGOSxo6Abxg1AADicOdqEE8280.png
Azure IoT 门户中的 QR 请求事件
 
pYYBAGOSxpaAOB96AADdJm0hKHM946.png
QR 请求事件的详细列表视图
 

我们可以看到带有生成的 QR ID 的事件的详细列表视图。

编程显示新消息

新的奖励或信息消息可以从 IoT Central 编程或完全禁用。

poYBAGOSxpiAN1QpAADO6Ka39FY052.png
 

获取设备信息

特性

Key               Value
userLedRed        true | false    enables/disables the red LED of the user RGB LED
userLedGreen      true | false    enables/disables the green LED of the user RGB LED
userLedBlue       true | false    enables/disables the blue LED of the user RGB LED
appLed            true | false    enables/disables the application LED
wifiLed           true | false    enables/disables the WI-FI LED

集成电子纸显示

Waveshare 1.54inch e-Paper V2概述

1.54英寸电子纸V2是一款有源矩阵电泳显示器(AMEPD),具有接口和参考系统设计。1.54”活动区包含200×200像素,具有1位黑白全显示能力。集成电路包含栅极缓冲器、源极缓冲器、接口、时序控制逻辑、振荡器、DC-DC。SRAM.LUT、VCOM 和边框随每个面板提供。

https://www.waveshare.com/wiki/1.54inch_e-Paper_Module

pYYBAGOSxpuABJ_nAAA-ePFZoPk686.png
电子纸 - 引脚符号说明
 

引脚图

此表显示了 eINK click 上的引脚分配如何对应于 mikroBUS™ 插座上的引脚分配(后者显示在中间的两列中)。

poYBAGOSxp6AHxmMAACp70IdFoc193.png
引脚图
 

单击 Socket #1 引脚分配

poYBAGOSxqCAOOn3AADheb6NmZc923.png
AVNET KIT 点击套接字#| 引出线
 

源代码引脚定义

#define AVT_MODULE_GPIO31_SCLK1_TXD1 (GPIO_Id)31
#define AVT_MODULE_GPIO32_MOSI1_RTS1_CLK1 (GPIO_Id)32
#define AVT_MODULE_GPIO33_MISO1_RXD1_DATA1 (GPIO_Id)33
#define AVT_MODULE_GPIO34_CSA1_CTS1 (GPIO_Id)34
#define EPAPER_DC (GPIO_Id)0
#define EPAPER_BUSY (GPIO_Id)2
#define EPAPER_RESET (GPIO_Id)16
#define EPAPER_SCLK AVT_MODULE_GPIO31_SCLK1_TXD1
#define EPAPER_MOSI AVT_MODULE_GPIO32_MOSI1_RTS1_CLK1
#define EPAPER_CS AVT_MODULE_GPIO34_CSA1_CTS1

通讯协议

SPI接口

pYYBAGOSxqKAeJHWAABYTf0H_ao828.png
 

与传统的SPI协议不同,从机到主机的数据线是隐藏的,因为设备只有显示需求。

CS为slave片选,当CS为低电平时,芯片使能。(CS#) 是连接到 MCU 的片选输入。该芯片启用 MCU 通信:仅当 CS# 被拉低时。

DC为数据/命令控制引脚,DC=0时写命令,DC=1时写数据。(D/C#) 是连接到 MCU 的数据/命令控制引脚。当引脚被拉高时,数据将被解释为数据。当引脚被拉低时,数据将被解释为命令。

SCLK 是 SPI 通信时钟。

SDIN是SPI通信中主机到从机的数据线。

(RES#)为复位信号输入。复位为低电平有效。注 1.5-4:此引脚(BUSY)为忙状态输出引脚。当 Busy 为高电平时,芯片的运行不应中断,也不应向模块发出任何命令。当驱动 IC 工作时,驱动 IC 会将 Busy 引脚置为高电平,例如: - 输出显示波形;或 - 与数字温度通信。

(BS1) 用于 3 线 SPI 或 4 线 SPI 选择。当它为“低”时,选择 4 线 SPI。当它为“高”时,选择 3 线 SPI(9 位 SPI)。

SPI通信有数据传输时序,由CPHA和CPOL组合而成。

  • 1. CPOL 决定空闲状态下串行同步时钟的电平。当 CPOL = 0 时,电平为 Low。然而,CPOL对传输影响不大。
  • 2、CPHA决定数据是在串行同步时钟的第一个时钟沿还是第二个时钟沿采集;当 CPHL = 0 时,在第一个时钟边沿收集数据。

SPI有4种通信模式。常用SPI0,其中CPHL=0,CPOL=0。

数据传输在SCLK的第一个下降沿开始,在一个时钟周期内传输8位数据。这里使用SPI0,数据按位传输,MSB在前。

感知用户

除了在按下按钮时启动新的二维码之外,我们还可以在它检测到用户何时使用接近传感器使用回收容器时激活它。

#define AVT_MODULE_GPIO42_ADC1	MT3620_GPIO42
#define AVT_SK_CM1_AN AVT_MODULE_GPIO42_ADC1
#define PROXIMITY_GPIO AVT_SK_CM1_AN

我们使用干簧管和磁铁来检测用户是否打开了容器门。

我们将使用的簧片开关是常开的。我们有两种选择来检测门何时完全关闭或门何时完全打开。对于这个项目,我们将使用第一个替代方案:

检测门完全关闭:当门关闭时,磁铁使干簧管闭合,并一直处于该状态,直到门被打开。我们将干簧管接地,然后通过 4.7K 拉高 GPIO 引脚 42。在关闭状态下将读取低。当从高到低时,将发送新 QR 的事件,即当门再次完全关闭时,奖励用户在使用后关闭门 :D。

poYBAGOj1OmAMOmlAAAE1Zw0wSE613.png
GPIO42 检测关门
 

 

pYYBAGOj1RKAQGYQAAnaZMtzxME591.jpg
垃圾回收箱内的干簧管和磁铁
 

 

开发工具

验证二维码

从带有 QR 扫描仪的 Android 设备:

pYYBAGOj1ReAKTLqAAG1oMBuloU012.png
从 Android 设备验证二维码
 

验证 JWT

使用 JWT 调试器验证签名:https ://jwt.io/#debugger

poYBAGOj1RqAEQ0HAACJHTDpPxI568.png
JWT调试器
 

 

 


声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表德赢Vwin官网 网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

评论(0)
发评论

下载排行榜

全部0条评论

快来发表一下你的评论吧 !

'+ '

'+ '

'+ ''+ '
'+ ''+ ''+ '
'+ ''+ '' ); $.get('/article/vipdownload/aid/'+webid,function(data){ if(data.code ==5){ $(pop_this).attr('href',"//www.hzfubeitong.com/m/login/index.html"); return false } if(data.code == 2){ //跳转到VIP升级页面 window.location.href="https://m.elecfans.com/vip/index?aid=" + webid return false } //是会员 if (data.code > 0) { $('body').append(htmlSetNormalDownload); var getWidth=$("#poplayer").width(); $("#poplayer").css("margin-left","-"+getWidth/2+"px"); $('#tips').html(data.msg) $('.download_confirm').click(function(){ $('#dialog').remove(); }) } else { var down_url = $('#vipdownload').attr('data-url'); isBindAnalysisForm(pop_this, down_url, 1) } }); }); //是否开通VIP $.get('/article/vipdownload/aid/'+webid,function(data){ if(data.code == 2 || data.code ==5){ //跳转到VIP升级页面 $('#vipdownload>span').text("开通VIP 免费下载") return false }else{ // 待续费 if(data.code == 3) { vipExpiredInfo.ifVipExpired = true vipExpiredInfo.vipExpiredDate = data.data.endoftime } $('#vipdownload .icon-vip-tips').remove() $('#vipdownload>span').text("VIP免积分下载") } }); }).on("click",".download_cancel",function(){ $('#dialog').remove(); }) var setWeixinShare={};//定义默认的微信分享信息,页面如果要自定义分享,直接更改此变量即可 if(window.navigator.userAgent.toLowerCase().match(/MicroMessenger/i) == 'micromessenger'){ var d={ title:'创建安全临时QR令牌',//标题 desc:$('[name=description]').attr("content"), //描述 imgUrl:'https://'+location.host+'/static/images/ele-logo.png',// 分享图标,默认是logo link:'',//链接 type:'',// 分享类型,music、video或link,不填默认为link dataUrl:'',//如果type是music或video,则要提供数据链接,默认为空 success:'', // 用户确认分享后执行的回调函数 cancel:''// 用户取消分享后执行的回调函数 } setWeixinShare=$.extend(d,setWeixinShare); $.ajax({ url:"//www.hzfubeitong.com/app/wechat/index.php?s=Home/ShareConfig/index", data:"share_url="+encodeURIComponent(location.href)+"&format=jsonp&domain=m", type:'get', dataType:'jsonp', success:function(res){ if(res.status!="successed"){ return false; } $.getScript('https://res.wx.qq.com/open/js/jweixin-1.0.0.js',function(result,status){ if(status!="success"){ return false; } var getWxCfg=res.data; wx.config({ //debug: true, // 开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。 appId:getWxCfg.appId, // 必填,公众号的唯一标识 timestamp:getWxCfg.timestamp, // 必填,生成签名的时间戳 nonceStr:getWxCfg.nonceStr, // 必填,生成签名的随机串 signature:getWxCfg.signature,// 必填,签名,见附录1 jsApiList:['onMenuShareTimeline','onMenuShareAppMessage','onMenuShareQQ','onMenuShareWeibo','onMenuShareQZone'] // 必填,需要使用的JS接口列表,所有JS接口列表见附录2 }); wx.ready(function(){ //获取“分享到朋友圈”按钮点击状态及自定义分享内容接口 wx.onMenuShareTimeline({ title: setWeixinShare.title, // 分享标题 link: setWeixinShare.link, // 分享链接 imgUrl: setWeixinShare.imgUrl, // 分享图标 success: function () { setWeixinShare.success; // 用户确认分享后执行的回调函数 }, cancel: function () { setWeixinShare.cancel; // 用户取消分享后执行的回调函数 } }); //获取“分享给朋友”按钮点击状态及自定义分享内容接口 wx.onMenuShareAppMessage({ title: setWeixinShare.title, // 分享标题 desc: setWeixinShare.desc, // 分享描述 link: setWeixinShare.link, // 分享链接 imgUrl: setWeixinShare.imgUrl, // 分享图标 type: setWeixinShare.type, // 分享类型,music、video或link,不填默认为link dataUrl: setWeixinShare.dataUrl, // 如果type是music或video,则要提供数据链接,默认为空 success: function () { setWeixinShare.success; // 用户确认分享后执行的回调函数 }, cancel: function () { setWeixinShare.cancel; // 用户取消分享后执行的回调函数 } }); //获取“分享到QQ”按钮点击状态及自定义分享内容接口 wx.onMenuShareQQ({ title: setWeixinShare.title, // 分享标题 desc: setWeixinShare.desc, // 分享描述 link: setWeixinShare.link, // 分享链接 imgUrl: setWeixinShare.imgUrl, // 分享图标 success: function () { setWeixinShare.success; // 用户确认分享后执行的回调函数 }, cancel: function () { setWeixinShare.cancel; // 用户取消分享后执行的回调函数 } }); //获取“分享到腾讯微博”按钮点击状态及自定义分享内容接口 wx.onMenuShareWeibo({ title: setWeixinShare.title, // 分享标题 desc: setWeixinShare.desc, // 分享描述 link: setWeixinShare.link, // 分享链接 imgUrl: setWeixinShare.imgUrl, // 分享图标 success: function () { setWeixinShare.success; // 用户确认分享后执行的回调函数 }, cancel: function () { setWeixinShare.cancel; // 用户取消分享后执行的回调函数 } }); //获取“分享到QQ空间”按钮点击状态及自定义分享内容接口 wx.onMenuShareQZone({ title: setWeixinShare.title, // 分享标题 desc: setWeixinShare.desc, // 分享描述 link: setWeixinShare.link, // 分享链接 imgUrl: setWeixinShare.imgUrl, // 分享图标 success: function () { setWeixinShare.success; // 用户确认分享后执行的回调函数 }, cancel: function () { setWeixinShare.cancel; // 用户取消分享后执行的回调函数 } }); }); }); } }); } function openX_ad(posterid, htmlid, width, height) { if ($(htmlid).length > 0) { var randomnumber = Math.random(); var now_url = encodeURIComponent(window.location.href); var ga = document.createElement('iframe'); ga.src = 'https://www1.elecfans.com/www/delivery/myafr.php?target=_blank&cb=' + randomnumber + '&zoneid=' + posterid+'&prefer='+now_url; ga.width = width; ga.height = height; ga.frameBorder = 0; ga.scrolling = 'no'; var s = $(htmlid).append(ga); } } openX_ad(828, '#berry-300', 300, 250);