-->

signed

QiShunwang

“诚信为本、客户至上”

uniapp中使用微信jssdk

2021/6/3 15:13:39   来源:

首先找到官方文档地址 https://developers.weixin.qq.com/doc/offiaccount/OA_Web_Apps/JS-SDK.html#0

1.1 JSSDK使用步骤
1.1.1 步骤一:绑定域名
1.1.2 步骤二:引入JS文件
1.1.3 步骤三:通过config接口注入权限验证配置。在附录一中有签名算法
1.1.4 步骤四:通过ready接口处理成功验证
1.1.5 步骤五:通过error接口处理失败验证

uniapp端

按照官方文档说明,增加index.html文件放到项目根目录下,其中引入jweixin

<!DOCTYPE html>
<html lang="zh-CN">
    <head>
        <meta charset="utf-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <title>
            <%= htmlWebpackPlugin.options.title %>
        </title>
        <!-- Open Graph data -->
        <!-- <meta property="og:title" content="Title Here" /> -->
        <!-- <meta property="og:url" content="http://www.example.com/" /> -->
        <!-- <meta property="og:image" content="http://example.com/image.jpg" /> -->
        <!-- <meta property="og:description" content="Description Here" /> -->
        <script>
            var coverSupport = 'CSS' in window && typeof CSS.supports === 'function' && (CSS.supports('top: env(a)') || CSS.supports('top: constant(a)'))
            document.write('<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0' + (coverSupport ? ', viewport-fit=cover' : '') + '" />')
        </script>
        <link rel="stylesheet" href="<%= BASE_URL %>static/index.<%= VUE_APP_INDEX_CSS_HASH %>.css" />
    </head>
    <body>
        <noscript>
            <strong>Please enable JavaScript to continue.</strong>
        </noscript>
        <div id="app"></div>
        <!-- built files will be auto injected -->
    </body>
	<script src="http://res.wx.qq.com/open/js/jweixin-1.6.0.js"></script>
	
</html>

在js或vue文件的js板块中都可以写引用代码

const ua = window.navigator.userAgent;
			if ( ua.indexOf("MicroMessenger") <= 0 ) {
			    alert("请在微信中打开");
				// window.opener=null;
				// window.open('','_self');
				// window.close();
			}
			// 检查微信环境
			let url = document.URL.substring(0, location.href.indexOf("#"))
			uni.request({
				url: 'http://这里的地址写自己服务器地址/jssdk/jsapiSignature?appid=wxa6a51f9e8f6b84bd&requestUrl=' + url,
				success: (res) => {
					const signature = res.data.content
					wx.config({
						debug: false, // 开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。
						beta: true,
						appId: signature.appid, // 必填,公众号的唯一标识
						timestamp: signature.timestamp, // 必填,生成签名的时间戳
						nonceStr: signature.nonceStr, // 必填,生成签名的随机串
						signature: signature.signature, // 必填,签名
						jsApiList: ['configWXDeviceWiFi',
							'openWXDeviceLib',
							'scanQRCode'
						] // 必填,需要使用的JS接口列表
					});
					/* wx.hideAllNonBaseMenuItem(); */
					wx.checkJsApi({
						jsApiList: ['configWXDeviceWiFi',
							'openWXDeviceLib',
							'scanQRCode'
						], // 需要检测的JS接口列表,所有JS接口列表见附录2,
						success: function(res2) {
							// 以键值对的形式返回,可用的api值true,不可用为false
							// 如:{"checkResult":{"chooseImage":true},"errMsg":"checkJsApi:ok"}
							if (res.checkResult.configWXDeviceWiFi == 'no') {
								alert("当前环境不支持设备wifi配网")
							}
							if (res.checkResult.scanQRCode == 'no') {
								alert("当前环境不支持扫码")
							}
						}
					});
					wx.ready(function(res2) {
						// alert("环境已经准备好")
						// config信息验证后会执行ready方法,所有接口调用都必须在config接口获得结果之后,config是一个客户端的异步操作,所以如果需要在页面加载时就调用相关接口,则须把相关接口放在ready函数中调用来确保正确执行。对于用户触发时才调用的接口,则可以直接调用,不需要放在ready函数中。
					});
					wx.error(function(res2) {
						// alert("环境准备失败,需要在微信中访问")
						// config信息验证失败会执行error函数,如签名过期导致验证失败,具体错误信息可以打开config的debug模式查看,也可以在返回的res参数中查看,对于SPA可以在这里更新签名。
					});
				}
			})

在method中写调用代码

methods: {
			scanCode() {
				const _this = this
				wx.scanQRCode({
					needResult: 1, // 默认为0,扫描结果由微信处理,1则直接返回扫描结果,
					scanType: ["qrCode", "barCode"], // 可以指定扫二维码还是一维码,默认二者都有
					success: function(res) {
						const result = res.resultStr; // 当needResult 为 1 时,扫码返回的结果
						_this.formData.nodeId = result
					},
				})
			}
		}
<u-form-item label="设备编号" prop="nodeId" required>
				<u-input type="text" v-model="formData.nodeId" placeholder="请输入设备编号" :disabled="!!deviceId">
				</u-input>
				<u-icon name="scan" size="55rpx" slot="right" type="success" @click="scanCode()"></u-icon>
			</u-form-item>

服务端接口

提供获取签名的接口

	@Autowired
	RedisTemplate<String, String> redisTemplate;
	
	@Autowired
	TokenService tokenService;
/**
	 * 这个是请求页面中使用jssdk的
	 * @param request
	 * @param appid
	 * @param model
	 * @return
	 * @throws WxErrorException
	 * @throws AesException
	 */
	@GetMapping("/jsapiSignature")
    public R<Map<String,Object>> getJsapiTicket(HttpServletRequest request, String appid, String requestUrl) throws WxErrorException, AesException {
		String authorizer_access_token = redisTemplate.opsForHash().entries(appid).get("authorizer_access_token").toString();
		// 正常情况下,jsapi_ticket的有效期为7200秒,通过access_token来获取。由于获取jsapi_ticket的api调用次数非常有限,频繁刷新jsapi_ticket会导致api调用受限,影响自身业务,开发者必须在自己的服务全局缓存jsapi_ticket 。
		// 这里使用的时候才有必要,所以也不必是必须要定时更新。用的时候发现没有后再去取即可
		String ticket = tokenService.getTicket(authorizer_access_token);
		
		// 这里对签名相关的信息也可以做缓存,应该不需要每次都重新获取,根据appid获取即可
		String nonceStr = Wxutil.getNoncestr();
		String timestamp = Wxutil.getTimestamp();
//		String url = request.getRequestURL().toString() + "?" + request.getQueryString();
		String signature = JsUtil.generateConfigSignature(nonceStr, ticket, timestamp, requestUrl);
		
		// 获取解密后的内容
//		String xml = XmlKit.decryptXml(request);
//		System.out.println("这里是解密之后的内容:" + signature);
//		String jsticket = new WxMpServiceImpl().getJsapiTicket();
		Map<String, Object> model = new HashMap<String, Object>();
		model.put("signature", signature);
		model.put("appid", appid);
		model.put("nonceStr", nonceStr);
		model.put("timestamp", timestamp);
		return R.ok(model);
    }
@Service
public class TokenService {

	public String getTicket(String authorizer_access_token) {
		Ticket t = TicketAPI.ticketGetticket(authorizer_access_token);
		// 这里可以取到ticket
		String ticket = t.getTicket();
		return ticket;
	}

}

public class Wxutil {

	public static String getNoncestr(){
        String noncestr = UUID.randomUUID().toString().replace("-", "").substring(0, 16);
        return noncestr;
    }

    public static String getTimestamp(){
        String timestamp = String.valueOf(System.currentTimeMillis() / 1000);
        return timestamp;
    }
}