H5关于微信二次分享实现

实现方案:

       1、主要通过使用微信JS-SDK实现;

       2、微信相关文档 https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421141115

相关配置:

       1、调用微信的分享需要提供微信公众号的AppID和AppSecret(注意AppSecret是保密的,如果重置可能会影响以前的使用场景)

       2、本次所使用的   AppID: ******      AppSecret: ******

       3、通过AppID和AppSecret获取微信的access_token,注意需要配置微信的ip白名单

       4、使用微信的sdk分享还需要配置JS接口安全域名(具体配置规则微信的文档里面有详细介绍)

       5、后端需要根据微信文档做权限算法解析,并返回前端所需要的字段

后端代码:

package com.fairy.fshop.util;

import java.io.IOException;
import java.net.URISyntaxException;

import org.apache.http.client.ClientProtocolException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import com.fairy.scsowing.common.HttpUtil;
import com.sowing.common.exception.ServiceException;

import net.sf.json.JSONObject;

/**
 * 微信分享工具类
 * @author dwj
 *
 */
@Component
public class WeiXinShareUtil {
	
	private static final Logger LOG = LoggerFactory.getLogger(WeiXinShareUtil.class);
	
	public static String wx_appid = "wx51a9d9d6e19f9bef";
	
	public static String wx_secret = "c10df335f8723f4198fe19d4c0137a04";
	
	public static String wx_ticketUrl = "https://api.weixin.qq.com/cgi-bin/ticket/getticket?type=jsapi&access_token=";
	
	public static String wx_accessTokenUrl = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential";

    //以上值为测试用

	public WeiXinShareUtil(){}
	
	@Value("${share.weixin.appid}")
	public void setAppid(String appid) {
		wx_appid = appid;
	}
	@Value("${share.weixin.secret}")
	public void setSecret(String secret) {
		wx_secret = secret;
	}
	@Value("${share.weixin.ticketUrl}")
	public void setWeixinTicketUrl(String weixinTicketUrl) {
		wx_ticketUrl = weixinTicketUrl;
	}
	@Value("${share.weixin.accessTokenUrl}")
	public void setWeixinAccessTokenUrl(String weixinAccessTokenUrl) {
		wx_accessTokenUrl = weixinAccessTokenUrl;
	}


	/**
	 * 获取微信认证token(有效期7200s)
	 * @return
	 * @throws ClientProtocolException
	 * @throws URISyntaxException
	 * @throws IOException
	 */
	public static String getWXAccessToken() {
		try {
			HttpUtil httpUtil = new HttpUtil();
			String access_token = httpUtil.doGetForString(wx_accessTokenUrl + wx_appid + "&secret=" + wx_secret);
			LOG.info("获取微信accessToken接口返回参数:{}", access_token);
			Object json =JSONObject.fromObject(access_token).get("access_token");
			return json.toString();
		} catch (Exception e) {
			LOG.error("获取微信accessToken异常,原因:{}", e);
			throw new ServiceException("获取微信accessToken异常");
		}
		
	}
	
	/**
	 * 通过获取的微信token获取ticket
	 * @param accessToken
	 * @return
	 * @throws IOException 
	 * @throws URISyntaxException 
	 * @throws ClientProtocolException 
	 */
	public static String getWXTicket(String accessToken) {
		try {
			HttpUtil httpUtil = new HttpUtil();
			String ticket = httpUtil.doGetForString(wx_ticketUrl + accessToken);
			LOG.info("获取微信ticket接口返回参数:{}", ticket);
			Object json =JSONObject.fromObject(ticket).get("ticket");
			return json.toString();
		} catch (Exception e) {
			LOG.error("获取微信ticket异常,原因:", e);
			throw new ServiceException("获取微信ticket异常");
		}
		
	}
}
package com.sowing.hsh.api.controller;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URISyntaxException;
import java.net.URLDecoder;
import java.security.MessageDigest;
import java.util.Formatter;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;

import com.fairy.fshop.system.redis.RedisService;
import com.fairy.fshop.util.WeiXinShareUtil;
import com.fairy.scsowing.common.HttpUtil;

/**
 * 微信分享
 */
@RestController
public class WeixinShareController {
	
	private static final Logger LOG = LoggerFactory.getLogger(WeixinShareController.class);
	
	private static String weixinTicketUrl = "https://api.weixin.qq.com/cgi-bin/ticket/getticket?type=jsapi&access_token=";
	@Resource
	private RedisService redisService;
	/**
	 * 获取微信分享的ticket
	 *
	 * @param accessToken
	 * @return
	 * @throws IOException
	 * @throws URISyntaxException
	 */
	@RequestMapping("/weixin/shareTicket")
	public static void getWeixinTicket(@RequestParam("accessToken") String accessToken, HttpServletResponse response)
			throws IOException, URISyntaxException {
		HttpUtil httpUtil = new HttpUtil();
		String ticket = httpUtil.doGetForString(weixinTicketUrl + accessToken);
		response.getOutputStream().write(ticket.getBytes());
	}

	/**
	 * 获取微信分享js-sdk权限验证签名
	 * @param url 分享地址
	 * @return
	 */
	@RequestMapping("/weixin/share/sign")
	@ResponseBody
	public  Map<String, String> getWXSign(@RequestParam("shareUrl") String shareUrl) {
		
		try {
			shareUrl = URLDecoder.decode(shareUrl, "UTF-8");
		} catch (UnsupportedEncodingException e) {
			LOG.error("分享url解码异常:{}", e.getMessage());
		}   
		 
		//通过redis做缓存,防止获取微信token和ticket超过请求限制
		String accessToken = redisService.getString("weixin_access_token_redis_key");
		String jsapi_ticket = redisService.getString("weixin_ticket_redis_key");
		if(StringUtils.isBlank(accessToken)) {
			accessToken = WeiXinShareUtil.getWXAccessToken();
			redisService.setString("weixin_access_token_redis_key", accessToken, 7000);
		}
	
		if(StringUtils.isBlank(jsapi_ticket)) {
			jsapi_ticket = WeiXinShareUtil.getWXTicket(accessToken);
			redisService.setString("weixin_ticket_redis_key", jsapi_ticket, 7000);
		}
		String nonce_str = createNonceStr();
		String timestamp = createTimestamp();
		String signature;

		// 注意这里参数名必须全部小写,且必须有序
		String signatureStr = "jsapi_ticket=" + jsapi_ticket + "&noncestr=" + nonce_str + "&timestamp=" + timestamp + "&url=" + shareUrl;
		LOG.info("微信分享加密字符串:{}", signatureStr);

		try {
			MessageDigest crypt = MessageDigest.getInstance("SHA-1");
			crypt.reset();
			crypt.update(signatureStr.getBytes("UTF-8"));
			signature = byteToHex(crypt.digest());
		} catch (Exception e) {
			LOG.error("获取微信签名signature异常,原因:{}", e);
			return null;
		} 
		Map<String, String> ret = new HashMap<String, String>();
		ret.put("url", shareUrl);
		ret.put("jsapi_ticket", jsapi_ticket);
		ret.put("nonceStr", nonce_str);
		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;
	}

	/**
	 * 随机字符串
	 * @return
	 */
	private static String createNonceStr() {
		return UUID.randomUUID().toString();
	}

	/**
	 * 获取系统时间戳
	 * @return
	 */
	private static String createTimestamp() {
		return Long.toString(System.currentTimeMillis() / 1000);
	}
}

前端代码:

export const wxApi = {
    wxRegister(option){    //获取签名算法解析之后的相关字段
        Axios.get(`${process.env.VUE_APP_URL}weixin/share/sign?`,{
            params: {
                shareUrl: decodeURIComponent(location.href)           
            }
        }).then(function (res) {
           
            let data = res.data;
            if(res){
                wx.config({    //根据微信的文档进行config接口注入权限验证配置
                    debug:  true, // 开启调试模式
                    appId: data.appId || 'wx53c4a6dcfd495e12', // 必填,公众号的唯一标识
                    timestamp: data.timestamp, // 必填,生成签名的时间戳
                    nonceStr: data.nonceStr, // 必填,生成签名的随机串
                    signature: data.signature, // 必填,签名,见附录1
                    jsApiList: ['updateAppMessageShareData','updateTimelineShareData','onMenuShareTimeline'] // 必填,需要使用的JS接口列表,所有JS接口列表见附录2
                  })

                  wx.ready(() => {   //通过ready接口处理成功验证
                    if (option) {
                      wxApi.updateAppMessageShareData(option);
                      wxApi.updateTimelineShareData(option);
                      wxApi.onMenuShareTimeline(option)
                    }
                  })

            }
        })
        .catch(function (err) {
            console.log(err);
        })

        
    },


    updateAppMessageShareData(option){
        wx.updateAppMessageShareData({ 
            title: option.title, // 分享标题
            desc: '刚在惠生活发现了一个好东西,我猜你也感兴趣,快来看看吧!',
            link: option.link, // 分享链接,该链接域名或路径必须与当前页面对应的公众号JS安全域名一致
            imgUrl: option.imgUrl, // 分享图标
            success: function () {
              // 设置成功
            }
        })
    },

    updateTimelineShareData(option){
        wx.updateTimelineShareData({ 
            title: option.title, // 分享标题
            link: option.link, // 分享链接,该链接域名或路径必须与当前页面对应的公众号JS安全域名一致
            imgUrl: option.imgUrl, // 分享图标
            success: function () {
              // 设置成功
            }
        })
    },

    onMenuShareTimeline(option){
        wx.onMenuShareTimeline({
            title: option.title, // 分享标题
            link: option.link, // 分享链接,该链接域名或路径必须与当前页面对应的公众号JS安全域名一致
            imgUrl: option.imgUrl, // 分享图标
            success: function () {
            // 用户点击了分享后执行的回调函数
            }
        })
    }

}

使用方法:

解构并调用wxRegister方法,此方法需传递一个option对象前端使用:

option:{

   title: '', // 分享标题
   link: '', // 分享链接,该链接域名或路径必须与当前页面对应的公众号JS安全域名一致
   imgUrl: '', // 分享图标
}

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在Vue H5页面中实现微信分享,可以按照以下步骤进行: 第一步,获取微信分享所需的相关配置: 在Vue项目中引入微信开放平台的JS-SDK,然后通过微信开放平台接口获取到当前页面的分享配置信息,包括标题、描述、链接和图片等信息。 第二步,调用微信JS-SDK进行分享: 在Vue的组件中,通过引入微信JS-SDK提供的方法,如`wx.onMenuShareTimeline`和`wx.onMenuShareAppMessage`等,来实现对应的分享功能。可以将这些方法封装成一个单独的util文件,方便在项目中多次调用。 第三步,配置分享参数: 调用微信JS-SDK的分享方法前,需要将获取到的分享配置信息传入相应的参数中,如标题、链接、描述和分享图等。可以根据当前页面的不同内容来动态设置分享的参数。 第四步,设置微信签名: 在Vue页面中,可以使用`vue-router`插件进行路由控制,当进入到需要分享的页面时,通过异步请求来获取当前页面的分享配置信息和签名,然后将签名设置给微信JS-SDK。 第五步,调用分享方法: 在上面的配置完成后,即可通过微信JS-SDK提供的分享方法,如`wx.onMenuShareTimeline`和`wx.onMenuShareAppMessage`等,来实现对应的分享功能。可以按需选择分享到朋友圈、发送给好友或分享到QQ等渠道。 需要注意的是,Vue H5页面在与微信分享时,由于所处的环境和限制会有所不同,可能需要在不同的事件中触发分享,比如在路由切换完成后触发分享方法。 以上是实现Vue H5页面分享微信的一般步骤,具体实现还需要根据项目的需求和微信开放平台的接口文档进行调整。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值