uni-app(7):微信浏览器分享链接卡片

1 准备工作

        在微信浏览器内部实现分享链接卡片效果,如下所示:

1.1 注册公众号 

        首先需要注册一个公众号,进入微信公众平台,点击立即注册。

        选择公众号。

        设置邮箱和密码,选择中国大陆(只有一个选项),个人只能选择公众号,企业可以选择服务号。

        主体类型要选择企业,否则会导致权限不足,无法实现分享卡片。

        设置一些公众号的基本信息完成注册。

1.2 设置

        在公众号界面的开发接口管理选项设置AppID和AppSecret,这两个值一定要记住后面会用到。

        确认此处是否为已获得状态,当前演示为个人账户,此处无法通过。

        在帐号设置 - 功能设置添加js安全域名,添加要分享的域名地址。

        下载验证文件,然后将该文件放入到域名所对应的前端项目部署所在目录下才可以设置成功。

        在设置与开发 - 安全中心中添加域名所对应的公网ip,例如:10.1.20.25

2 前端

        在项目中安装微信开发工具包。

npm i weixin-js-sdk

         在要分享的页面设置分享卡片信息,其中appId、timestamp、nonceStr、signature这四个值需要后端服务器提供。

// 初始化微信配置
const wechatConfig = () => {
  if (/micromessenger/i.test(navigator.userAgent)) {
    let currentUrl = window.location.href
    currentUrl = currentUrl.split('#')[0] // 移除hash部分
    const encodedUrl = encodeURIComponent(currentUrl) // 对URL进行编码
    // 获取配置信息,需要将当前页面地址传入到后端
    getWechatConfigApi(encodedUrl).then((res) => {
      wx.config({
        debug: false,
        appId: res.appId,
        timestamp: res.timestamp,
        nonceStr: res.nonceStr,
        signature: res.signature,
        jsApiList: ['updateAppMessageShareData', 'updateTimelineShareData'],
      })
      // 配置成功后,调用分享接口
      wx.ready(function () {
        // 分享到朋友
        wx.updateAppMessageShareData({
          title: '分享标题',
          desc: '美化结果',
          link: currentUrl, // 分享链接
          imgUrl: 'https://xxx.png', // 卡片图片,只能是https请求
          success: function () {
            console.log('分享内容设置成功')
          },
          fail: function (err) {
            console.error('分享内容设置失败:', err)
          },
        })
        // 分享到朋友圈
        wx.updateTimelineShareData({
          title: '分享标题',
          link: currentUrl, // 分享链接
          imgUrl: 'https://xxx.png', // 卡片图片,只能是https请求
          success: function () {
            console.log('分享内容设置成功')
          },
          fail: function (err) {
            console.error('分享内容设置失败:', err)
          },
        })
      })
      wx.error(function (res) {
        console.error('微信JS-SDK配置失败:', res)
      })
    })
  }
}

onMounted(() => {
  wechatConfig()
})

3 后端

        此处使用java代码进行演示,根据URL获取微信JS-SDK服务

package org.dromara.bkk.common.config;

import com.alibaba.fastjson.JSONObject;
import jakarta.annotation.Resource;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;

import java.time.Duration;
import java.util.Map;

/**
 * 类描述 -> 微信JS-SDK服务
 *
 * @Author: ywz
 * @Date: 2025/07/03
 */
@Service
public class WechatJsSdkService {

    // 微信相关配置,从公众号获取(上面1.2章节中)
    @Value("${wx.appId}")
    private String appId;
    @Value("${wx.appSecret}")
    private String appSecret;
    @Resource
    private StringRedisTemplate stringRedisTemplate;

    private final RestTemplate restTemplate = new RestTemplate();


    // 获取access_token的URL
    private static final String ACCESS_TOKEN_URL =
        "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid={appid}&secret={secret}";
    // 获取jsapi_ticket的URL
    private static final String JSAPI_TICKET_URL =
        "https://api.weixin.qq.com/cgi-bin/ticket/getticket?type=jsapi&access_token={access_token}";

    /**
     * 获取JS-SDK配置所需的所有参数
     *
     * @param url 当前页面URL
     * @return 包含所有配置参数的Map
     */
    public Map<String, String> getJsSdkConfig(String url) {
        // 1. 获取jsapi_ticket
        String jsapiTicket = stringRedisTemplate.opsForValue().get("jsapi_ticket:" + url);
        if (StringUtils.isBlank(jsapiTicket)) {
            // 从微信服务器获取jsapi_ticket
            jsapiTicket = getJsapiTicket();
            // 获取jsapi_ticket每日有次数限制,需要缓存jsapi_ticket,有效期为7200秒
            stringRedisTemplate.opsForValue().set("jsapi_ticket:" + url, jsapiTicket, Duration.ofSeconds(7200));
        }
        if (StringUtils.isBlank(jsapiTicket)) {
            throw new RuntimeException("获取jsapi_ticket失败");
        }
        // 2. 生成签名
        Map<String, String> config = WechatJsSdkSignGenerator.generateSignature(jsapiTicket, url);
        // 添加appId
        config.put("appId", appId);
        return config;
    }

    /**
     * 获取jsapi_ticket
     */
    private String getJsapiTicket() {
        // 1. 获取access_token
        String accessTokenUrl = ACCESS_TOKEN_URL.replace("{appid}", appId).replace("{secret}", appSecret);
        String result = restTemplate.getForObject(accessTokenUrl, String.class);
        JSONObject json = JSONObject.parseObject(result);
        String accessToken = json.getString("access_token");
        if (StringUtils.isBlank(accessToken)) {
            throw new RuntimeException("获取access_token失败: " + result);
        }

        // 2. 获取jsapi_ticket
        String jsapiTicketUrl = JSAPI_TICKET_URL.replace("{access_token}", accessToken);
        result = restTemplate.getForObject(jsapiTicketUrl, String.class);
        json = JSONObject.parseObject(result);
        if (json.getIntValue("errcode") == 0) {
            return json.getString("ticket");
        } else {
            throw new RuntimeException("获取jsapi_ticket失败: " + result);
        }
    }
}

        微信JS-SDK签名生成器

package org.dromara.bkk.common.config;

import lombok.extern.slf4j.Slf4j;

import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.util.Formatter;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;

/**
 * 类描述 -> 微信JS-SDK签名生成器
 *
 * @Author: ywz
 * @Date: 2025/07/03
 */
@Slf4j
public class WechatJsSdkSignGenerator {

    /**
     * 生成JS-SDK配置所需的签名
     *
     * @param jsapiTicket jsapi_ticket
     * @param url         当前网页的URL,不包含#及其后面部分
     * @return 包含签名所需各项参数的Map
     */
    public static Map<String, String> generateSignature(String jsapiTicket, String url) {
        Map<String, String> ret = new HashMap<>();
        // 生成随机字符串
        String nonceStr = createNonceStr();
        // 生成时间戳
        String timestamp = createTimestamp();
        String signature = "";
        // 注意这里参数的顺序要按照 key 的 ASCII 码从小到大排序
        String string1 = "jsapi_ticket=" + jsapiTicket +
            "&noncestr=" + nonceStr +
            "&timestamp=" + timestamp +
            "&url=" + url;

        try {
            MessageDigest crypt = MessageDigest.getInstance("SHA-1");
            crypt.reset();
            crypt.update(string1.getBytes(StandardCharsets.UTF_8));
            signature = byteToHex(crypt.digest());
        } catch (Exception e) {
            log.error("生成签名失败", e);
        }

        ret.put("url", url);
        ret.put("jsapi_ticket", jsapiTicket);
        ret.put("nonceStr", nonceStr);
        ret.put("timestamp", timestamp);
        ret.put("signature", signature);
        return ret;
    }

    private static String byteToHex(final byte[] hash) {
        Formatter formatter = new Formatter();
        for (byte b : hash) {
            formatter.format("%02x", b);
        }
        String result = formatter.toString();
        formatter.close();
        return result;
    }

    private static String createNonceStr() {
        return UUID.randomUUID().toString();
    }

    private static String createTimestamp() {
        return Long.toString(System.currentTimeMillis() / 1000);
    }
}
### UniApp Share 功能详解 #### 一、UniApp 分享功能概述 UniApp 提供了一种跨平台的分享机制,允许开发者轻松实现应用内的内容分享功能。该功能可以适配多个目标平台,包括但不限于微信小程序、H5 和原生 App 环境[^2]。 在实际开发过程中,`uni.share()` 是用于调用分享功能的核心方法。它支持多种参数配置,能够满足不同场景下的需求。 --- #### 二、`uni.share()` 的基本语法与参数说明 以下是 `uni.share()` 方法的基本结构: ```javascript uni.share({ provider: '', // 分享渠道提供商,例如 'weixin' 表示微信分享 scene: '', // 场景模式(仅适用于某些特定平台) type: 0, // 被分享资源的类型,默认为纯文本 (text/plain) summary: '', // 描述文字 title: '', // 标题 href: '', // 链接地址 imageUrl: '',// 图片链接 success(res) { /* 成功回调 */ }, fail(err) { /* 失败回调 */ } }); ``` - **provider**: 指定分享的目标平台,比如 `'weixin'`, `'sinaweibo'` 等。 - **scene**: 对于微信分享而言,可以选择不同的场景 (`WXSceneSession`: 好友会话;`WXSenceTimeline`: 朋友圈)[^1]。 - **type**: 定义被分享的内容形式,常见的有文本(`0`)、图片(`1`)、音频(`2`)、视频(`3`) 或文件(`4`)- **summary**, **title**, **href**, **imageUrl**: 这些字段分别对应分享卡片中的摘要、标题、跳转链接和封面图。 --- #### 三、常见问题及其解决方案 ##### 1. 微信小程序中无法正常显示分享按钮 如果发现微信小程序环境下的分享功能不可用,请确认以下几点: - 是否已在项目根目录下找到并编辑了 `manifest.json` 文件,在其中正确设置了 `"mp-weixin"` 平台的相关权限[^3]。 - 如果需要自定义菜单,则需通过设置页面对象里的 `onShareAppMessage` 属性来完成定制化逻辑。 ##### 2. H5 页面上的分享失败 对于运行在浏览器端的应用来说,由于安全策略限制,可能遇到一些特殊状况。此时建议采用第三方 SDK 来增强兼容性处理能力,或者引导用户复制链接手动转发给他人。 ##### 3. Android/iOS Native Apps 中缺少必要的依赖库 当构建打包后的 APK/IPA 文件安装至设备上测试时,若出现异常情况可能是因未引入对应的社交插件所致。务必按照官方指引添加所需模块后再重新尝试部署操作。 --- #### 四、代码实例演示 下面给出一段完整的例子展示如何利用 `uni.share()` 实现向微信好友发送消息的功能: ```javascript function performWeChatSharing() { uni.share({ provider: "weixin", scene: "WXSceneSession", type: 0, summary: "这是一条来自我的应用程序的消息。", title: "欢迎体验我们的服务!", href: "https://example.com/", imageUrl: "https://example.com/image.png", success(res) { console.log("成功执行分享:", res); }, fail(err) { console.error("发生错误:", err); } }); } ``` 上述脚本片段展示了标准流程,其中包括指定接收方为微信朋友聊天窗口,并附带一条简单的介绍语句连同指向外部网站的一个超链接以及一张预览缩略图一起传递出去。 --- ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

游王子og

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值