微信开发(一)基于Wx-java的微信分享功能

最近在做微信服务号开发,简单总结一下,便于自己学习积累和分享给大家:

环境介绍:

Spring+ Spring MVC +Mybatis

开发语言:

JAVA

微信公众平台的开发中,微信只公布了一个基于Http协议的接口和加解密的算法sdk,在开发的过程中可以自己根据需求来配置数据,调用相关接口,也可以引用比较成熟的基于java语言的微信公众号sdk。笔者引用的是目前比较流行的

weixin-java-tools

可以参考:点击打开链接

项目中引入了weixin-java-mp 就可直接调用相关功能接口和完成jssdk认证

        <dependency>
            <groupId>com.github.binarywang</groupId>
            <artifactId>weixin-java-mp</artifactId>
            <version>3.3.0</version>
        </dependency>
<dependency>
  <groupId>com.github.binarywang</groupId>
  <artifactId>(不同模块参考下文)</artifactId>
  <version>3.3.0</version>
</dependency>
  • 各模块的artifactId

    • 微信小程序:weixin-java-miniapp
    • 微信支付:weixin-java-pay
    • 微信开放平台:weixin-java-open
    • 公众号(包括订阅号和服务号):weixin-java-mp
    • 企业号/企业微信:weixin-java-cp

https://gitee.com/binary/weixin-java-tools

MP_js_api
相关官方文档

WxMpService提供了以下几个方法:

public String getJsapiTicket() throws WxErrorException;

public String getJsapiTicket(boolean forceRefresh) throws WxErrorException;

public WxJsapiSignature createJsapiSignature(String url) throws WxErrorException;

https://gitee.com/binary/weixin-java-tools/wikis/MP_js_api?sort_id=154599

分享接口:

1.后台准备:
建一个公用控制类: WeXinJsSdkController ,通过ajax 访问完成jssdk认证:

import me.chanjar.weixin.common.bean.WxJsapiSignature;
import me.chanjar.weixin.common.error.WxErrorException;
import me.chanjar.weixin.mp.api.WxMpService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.servlet.http.HttpServletRequest;

@Controller
@RequestMapping("jssdk")
public class WeXinJsSdkController {

    @Autowired
    private WxMpService wxMpService;

    @RequestMapping(value = "/config", method = RequestMethod.GET)
    @ResponseBody
    public WxJsapiSignature wxJsSdkConfig(HttpServletRequest request, String url) {
        try { // 直接调用wxMpServer 接口
            WxJsapiSignature wxJsapiSignature = wxMpService.createJsapiSignature(url);
            return wxJsapiSignature;
        } catch (WxErrorException e) {
            return null;
        }
    }

}
package me.chanjar.weixin.common.bean;

import java.beans.ConstructorProperties;
import java.io.Serializable;

public class WxJsapiSignature implements Serializable {
    private static final long serialVersionUID = -1116808193154384804L;
    private String appId;//参数名均为小写字符
    private String nonceStr; //参数名均为小写字符
    private long timestamp; //参数名均为小写字符
    private String url;//包括‘http(s)://‘部分,以及‘?‘后面的GET参数部分,但不包括‘#‘hash后面的部分。
    private String signature; //参数名均为小写字符

    public static WxJsapiSignature.WxJsapiSignatureBuilder builder() {
        return new WxJsapiSignature.WxJsapiSignatureBuilder();
    }

    public String getAppId() {
        return this.appId;
    }

    public String getNonceStr() {
        return this.nonceStr;
    }

    public long getTimestamp() {
        return this.timestamp;
    }

    public String getUrl() {
        return this.url;
    }

    public String getSignature() {
        return this.signature;
    }

    public void setAppId(String appId) {
        this.appId = appId;
    }

    public void setNonceStr(String nonceStr) {
        this.nonceStr = nonceStr;
    }

    public void setTimestamp(long timestamp) {
        this.timestamp = timestamp;
    }

    public void setUrl(String url) {
        this.url = url;
    }

    public void setSignature(String signature) {
        this.signature = signature;
    }

    public boolean equals(Object o) {
        if (o == this) {
            return true;
        } else if (!(o instanceof WxJsapiSignature)) {
            return false;
        } else {
            WxJsapiSignature other = (WxJsapiSignature)o;
            if (!other.canEqual(this)) {
                return false;
            } else {
                label63: {
                    Object this$appId = this.getAppId();
                    Object other$appId = other.getAppId();
                    if (this$appId == null) {
                        if (other$appId == null) {
                            break label63;
                        }
                    } else if (this$appId.equals(other$appId)) {
                        break label63;
                    }

                    return false;
                }

                Object this$nonceStr = this.getNonceStr();
                Object other$nonceStr = other.getNonceStr();
                if (this$nonceStr == null) {
                    if (other$nonceStr != null) {
                        return false;
                    }
                } else if (!this$nonceStr.equals(other$nonceStr)) {
                    return false;
                }

                if (this.getTimestamp() != other.getTimestamp()) {
                    return false;
                } else {
                    Object this$url = this.getUrl();
                    Object other$url = other.getUrl();
                    if (this$url == null) {
                        if (other$url != null) {
                            return false;
                        }
                    } else if (!this$url.equals(other$url)) {
                        return false;
                    }

                    Object this$signature = this.getSignature();
                    Object other$signature = other.getSignature();
                    if (this$signature == null) {
                        if (other$signature != null) {
                            return false;
                        }
                    } else if (!this$signature.equals(other$signature)) {
                        return false;
                    }

                    return true;
                }
            }
        }
    }

    protected boolean canEqual(Object other) {
        return other instanceof WxJsapiSignature;
    }

    public int hashCode() {
        int PRIME = true;
        int result = 1;
        Object $appId = this.getAppId();
        int result = result * 59 + ($appId == null ? 43 : $appId.hashCode());
        Object $nonceStr = this.getNonceStr();
        result = result * 59 + ($nonceStr == null ? 43 : $nonceStr.hashCode());
        long $timestamp = this.getTimestamp();
        result = result * 59 + (int)($timestamp >>> 32 ^ $timestamp);
        Object $url = this.getUrl();
        result = result * 59 + ($url == null ? 43 : $url.hashCode());
        Object $signature = this.getSignature();
        result = result * 59 + ($signature == null ? 43 : $signature.hashCode());
        return result;
    }

    public String toString() {
        return "WxJsapiSignature(appId=" + this.getAppId() + ", nonceStr=" + this.getNonceStr() + ", timestamp=" + this.getTimestamp() + ", url=" + this.getUrl() + ", signature=" + this.getSignature() + ")";
    }

    public WxJsapiSignature() {
    }

    @ConstructorProperties({"appId", "nonceStr", "timestamp", "url", "signature"})
    public WxJsapiSignature(String appId, String nonceStr, long timestamp, String url, String signature) {
        this.appId = appId;
        this.nonceStr = nonceStr;
        this.timestamp = timestamp;
        this.url = url;
        this.signature = signature;
    }

    public static class WxJsapiSignatureBuilder {
        private String appId;
        private String nonceStr;
        private long timestamp;
        private String url;
        private String signature;

        WxJsapiSignatureBuilder() {
        }

        public WxJsapiSignature.WxJsapiSignatureBuilder appId(String appId) {
            this.appId = appId;
            return this;
        }

        public WxJsapiSignature.WxJsapiSignatureBuilder nonceStr(String nonceStr) {
            this.nonceStr = nonceStr;
            return this;
        }

        public WxJsapiSignature.WxJsapiSignatureBuilder timestamp(long timestamp) {
            this.timestamp = timestamp;
            return this;
        }

        public WxJsapiSignature.WxJsapiSignatureBuilder url(String url) {
            this.url = url;
            return this;
        }

        public WxJsapiSignature.WxJsapiSignatureBuilder signature(String signature) {
            this.signature = signature;
            return this;
        }

        public WxJsapiSignature build() {
            return new WxJsapiSignature(this.appId, this.nonceStr, this.timestamp, this.url, this.signature);
        }

        public String toString() {
            return "WxJsapiSignature.WxJsapiSignatureBuilder(appId=" + this.appId + ", nonceStr=" + this.nonceStr + ", timestamp=" + this.timestamp + ", url=" + this.url + ", signature=" + this.signature + ")";
        }
    }
}

2.页面初始化js 配置相关接口:

<%--通过config接口注入权限验证配置--%>
/* 初始化jssdk 分享功能 */
$.get("${basePath}/jssdk/config.do",{url:window.location.href},function(data,status){
if(status == "success"){
wx.config({
debug: false, // 开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。
appId: data.appId, // 必填,公众号的唯一标识
timestamp: data.timestamp, // 必填,生成签名的时间戳
nonceStr: data.nonceStr, // 必填,生成签名的随机串
signature: data.signature,// 必填,签名,见附录1
jsApiList: [‘checkJsApi‘, ‘onMenuShareTimeline‘, ‘onMenuShareAppMessage‘, ‘onMenuShareQQ‘] // 必填,需要使用的JS接口列表,所有JS接口列表见附录2

}); 

wx.ready(function(){
//    layer.msg("jssdk初始化成功");
// config信息验证后会执行ready方法,所有接口调用都必须在config接口获得结果之后,config是一个客户端的异步操作,
//所以如果需要在页面加载时就调用相关接口,则须把相关接口放在ready函数中调用来确保正确执行。
//对于用户触发时才调用的接口,则可以直接调用,不需要放在ready函数中。

<%-- 分型内容 分享给朋友、朋友圈、 --%>
var shareData = {
title: ‘${requestScope.atc.trainsubject}‘,
desc: ‘${description}‘,
// link: ‘https://www.baidu.com‘, // 分享域名要和当前域名保持一致!!
imgUrl: ‘http://www.cyfd.cn/tektcrm/EventNoti/images/attendance.png‘,
success: function (res) {
// alert(‘已分享‘);
},
cancel: function (res) {
// alert(‘已取消‘);
},
fail: function (res) {
// alert(JSON.stringify(res));
}
}; 

<%--分享给朋友接口--%>
wx.onMenuShareAppMessage(shareData);
<%--分享到朋友圈接口--%>
wx.onMenuShareTimeline(shareData);
<%--分享到QQ朋友接口--%>
wx.onMenuShareQQ(shareData); 

});
wx.error(function(res){
// config信息验证失败会执行error函数,如签名过期导致验证失败,具体错误信息可以打开config的debug模式查看,
//也可以在返回的res参数中查看,对于SPA可以在这里更新签名。
//    layer.msg(res);
});

}
},"json");

学习在于不断地探索、思考和总结记录,欢迎喜欢的朋友们在下方留言,与君共同进步!
---------------------
作者:Java小爬虫
来源:CSDN
原文:https://blog.csdn.net/qq_36500554/article/details/80732334
版权声明:本文为博主原创文章,转载请附上博文链接!

签名算法

签名生成规则如下:参与签名的字段包括noncestr(随机字符串), 有效的jsapi_ticket, timestamp(时间戳), url(当前网页的URL,不包含#及其后面部分) 。对所有待签名参数按照字段名的ASCII 码从小到大排序(字典序)后,使用URL键值对的格式(即key1=value1&key2=value2…)拼接成字符串string1。这里需要注意的是所有参数名均为小写字符。对string1作sha1加密,字段名和字段值都采用原始值,不进行URL 转义。

即signature=sha1(string1)。 示例:

noncestr=Wm3WZYTPz0wzccnWjsapi_ticket=sM4AOVdWfPE4DxkXGEs8VMCPGGVi4C3VM0P37wVUCFvkVAy_90u5h9nbSlYy3-Sl-HhTdfl2fzFy1AOcHKP7qgtimestamp=1414587457url=http://mp.weixin.qq.com?params=value

步骤1. 对所有待签名参数按照字段名的ASCII 码从小到大排序(字典序)后,使用URL键值对的格式(即key1=value1&key2=value2…)拼接成字符串string1:

jsapi_ticket=sM4AOVdWfPE4DxkXGEs8VMCPGGVi4C3VM0P37wVUCFvkVAy_90u5h9nbSlYy3-Sl-HhTdfl2fzFy1AOcHKP7qg&noncestr=Wm3WZYTPz0wzccnW&timestamp=1414587457&url=http://mp.weixin.qq.com?params=value

步骤2. 对string1进行sha1签名,得到signature:

0f9de62fce790f9a083d5c99e95740ceb90c27ed

注意事项

1.签名用的noncestr和timestamp必须与wx.config中的nonceStr和timestamp相同。

2.签名用的url必须是调用JS接口页面的完整URL。

3.出于安全考虑,开发者必须在服务器端实现签名的逻辑。

如出现invalid signature 等错误详见附录5常见错误及解决办法。

附录5-常见错误及解决方法
调用config 接口的时候传入参数 debug: true 可以开启debug模式,页面会alert出错误信息。以下为常见错误及解决方法:

1.invalid url domain当前页面所在域名与使用的appid没有绑定,请确认正确填写绑定的域名,仅支持80(http)和443(https)两个端口,因此不需要填写端口号(一个appid可以绑定三个有效域名,见 ]目录1.1.1)。

2.invalid signature签名错误。建议按如下顺序检查:

1.确认签名算法正确,可用http://mp.weixin.qq.com/debug/cgi-bin/sandbox?t=jsapisign 页面工具进行校验。

2.确认config中nonceStr(js中驼峰标准大写S), timestamp与用以签名中的对应noncestr, timestamp一致。

3.确认url是页面完整的url(请在当前页面alert(location.href.split(‘#‘)[0])确认),包括‘http(s)://‘部分,以及‘?‘后面的GET参数部分,但不包括‘#‘hash后面的部分。

4.确认 config 中的 appid 与用来获取 jsapi_ticket 的 appid 一致。

5.确保一定缓存access_token和jsapi_ticket。

6.确保你获取用来签名的url是动态获取的,动态页面可参见实例代码中php的实现方式。如果是html的静态页面在前端通过ajax将url传到后台签名,前端需要用js获取当前页面除去‘#‘hash部分的链接(可用location.href.split(‘#‘)[0]获取,而且需要encodeURIComponent),因为页面一旦分享,微信客户端会在你的链接末尾加入其它参数,如果不是动态获取当前链接,将导致分享后的页面签名失败。

3.the permission value is offline verifying这个错误是因为config没有正确执行,或者是调用的JSAPI没有传入config的jsApiList参数中。建议按如下顺序检查:

1.确认config正确通过。

2.如果是在页面加载好时就调用了JSAPI,则必须写在wx.ready的回调中。

3.确认config的jsApiList参数包含了这个JSAPI。

4.permission denied该公众号没有权限使用这个JSAPI,或者是调用的JSAPI没有传入config的jsApiList参数中(部分接口需要认证之后才能使用)。

5.function not exist当前客户端版本不支持该接口,请升级到新版体验。

6.为什么6.0.1版本config:ok,但是6.0.2版本之后不ok(因为6.0.2版本之前没有做权限验证,所以config都是ok,但这并不意味着你config中的签名是OK的,请在6.0.2检验是否生成正确的签名以保证config在高版本中也ok。)

7.在iOS和Android都无法分享(请确认公众号已经认证,只有认证的公众号才具有分享相关接口权限,如果确实已经认证,则要检查监听接口是否在wx.ready回调函数中触发)

8.服务上线之后无法获取jsapi_ticket,自己测试时没问题。(因为access_token和jsapi_ticket必须要在自己的服务器缓存,否则上线后会触发频率限制。请确保一定对token和ticket做缓存以减少2次服务器请求,不仅可以避免触发频率限制,还加快你们自己的服务速度。目前为了方便测试提供了1w的获取量,超过阀值后,服务将不再可用,请确保在服务上线前一定全局缓存access_token和jsapi_ticket,两者有效期均为7200秒,否则一旦上线触发频率限制,服务将不再可用)。

9.uploadImage怎么传多图(目前只支持一次上传一张,多张图片需等前一张图片上传之后再调用该接口)

10.没法对本地选择的图片进行预览(chooseImage接口本身就支持预览,不需要额外支持)

11.通过a链接(例如先通过微信授权登录)跳转到b链接,invalid signature签名失败(后台生成签名的链接为使用jssdk的当前链接,也就是跳转后的b链接,请不要用微信登录的授权链接进行签名计算,后台签名的url一定是使用jssdk的当前页面的完整url除去‘#‘部分)

12.出现config:fail错误(这是由于传入的config参数不全导致,请确保传入正确的appId、timestamp、nonceStr、signature和需要使用的jsApiList)

13.如何把jsapi上传到微信的多媒体资源下载到自己的服务器(请参见文档中uploadVoice和uploadImage接口的备注说明)

14.Android通过jssdk上传到微信服务器,第三方再从微信下载到自己的服务器,会出现杂音(微信团队已经修复此问题,目前后台已优化上线)

15.绑定父级域名,是否其子域名也是可用的(是的,合法的子域名在绑定父域名之后是完全支持的)

16.在iOS微信6.1版本中,分享的图片外链不显示,只能显示公众号页面内链的图片或者微信服务器的图片,已在6.2中修复

17.是否需要对低版本自己做兼容(jssdk都是兼容低版本的,不需要第三方自己额外做更多工作,但有的接口是6.0.2新引入的,只有新版才可调用)

18.该公众号支付签名无效,无法发起该笔交易(请确保你使用的jweixin.js是官方线上版本,不仅可以减少用户流量,还有可能对某些bug进行修复,拷贝到第三方服务器中使用,官方将不对其出现的任何问题提供保障,具体支付签名算法可参考 JSSDK微信支付一栏)

19.目前Android微信客户端不支持pushState的H5新特性,所以使用pushState来实现web app的页面会导致签名失败,此问题已在Android6.2中修复

20.uploadImage在chooseImage的回调中有时候Android会不执行,Android6.2会解决此问题,若需支持低版本可以把调用uploadImage放在setTimeout中延迟100ms解决

21.require subscribe错误说明你没有订阅该测试号,该错误仅测试号会出现

22.getLocation返回的坐标在openLocation有偏差,因为getLocation返回的是gps坐标,openLocation打开的腾讯地图为火星坐标,需要第三方自己做转换,6.2版本开始已经支持直接获取火星坐标

23.查看公众号(未添加): "menuItem:addContact"不显示,目前仅有从公众号传播出去的链接才能显示,来源必须是公众号

24.ICP备案数据同步有一天延迟,所以请在第二日绑定

示例代码:

http://demo.open.weixin.qq.com/jssdk/sample.zip

备注:链接中包含php、java、nodejs以及python的示例代码供第三方参考,第三方切记要对获取的accesstoken以及jsapi_ticket进行缓存以确保不会触发频率限制。

https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421141115

原文地址:https://www.cnblogs.com/softidea/p/10351916.html

时间: 2024-08-24 14:11:45

微信开发(一)基于Wx-java的微信分享功能的相关文章

微信开发学习总结(二)——微信开发入门

上一篇<微信开发学习总结(一)——微信开发环境搭建>我们已经完成了微信开发的准备工作,准备工作完成之后,就要开始步入正题了. 一.微信公众平台的基本原理 在开始做之前,先简单介绍了微信公众平台的基本原理. 微信服务器就相当于一个转发服务器,终端(手机.Pad等)发起请求至微信服务器,微信服务器然后将请求转发给我们的应用服务器.应用服务器处理完毕后,将响应数据回发给微信服务器,微信服务器再将具体响应信息回复到微信App终端. 通信协议为:HTTP 数据传输格式为:XML 具体的流程如下图所示:

微信开发学习总结(一)—微信开发环境搭建

目前移动App开发领域主要分为以下几种类型: 一.微信开发环境搭建 1.要有一个用来测试的公众号. 2.用来调式代码的开发环境 1.1.注册测试公众号 微信公众号分为服务号.订阅号.企业号,订阅号可以个人申请,服务号和企业号要有企业资质才可以. 我们所说的微信公众号开发指的是订阅号和服务号. 关于订阅号和服务号的区别,官方是这样解释的 服务号:主要偏向于服务交互(功能类似12315,114,银行,提供绑定信息,服务交互),每月可群发4条消息:服务号适用人群:媒体.企业.政府或其他组织. 订阅号:

微信开发学习总结(一)微信开发环境搭建

目前移动开发处于比较火的的趋势,很多的开发者都跃跃欲试,目前移动App开发领域主要分为以下几种类型 我在平时的工作中接触得比较多的就是基于Android的Native App开发和基于微信公众号的Light App开发,今天就来带领大家快速进入微信公众号的开发领域. 一.微信开发环境搭建 工欲善其事,必先利其器.要做微信公众号开发,那么要先准备好两样必不可少的东西: 1.要有一个用来测试的公众号. 2.用来调式代码的开发环境. 1.1.注册测试公众号 微信公众号分为服务号.订阅号.企业号,订阅号

微信开发学习总结(一)——微信开发环境搭建(转)

目前移动开发处于比较火的的趋势,很多的开发者都跃跃欲试,目前移动App开发领域主要分为以下几种类型 我在平时的工作中接触得比较多的就是基于Android的Native App开发和基于微信公众号的Light App开发,今天就来带领大家快速进入微信公众号的开发领域. 一.微信开发环境搭建 工欲善其事,必先利其器.要做微信公众号开发,那么要先准备好两样必不可少的东西: 1.要有一个用来测试的公众号. 2.用来调式代码的开发环境. 1.1.注册测试公众号 微信公众号分为服务号.订阅号.企业号,订阅号

微信开发学习总结(一)——微信开发环境搭建

目前移动开发处于比较火的的趋势,很多的开发者都跃跃欲试,目前移动App开发领域主要分为以下几种类型 我在平时的工作中接触得比较多的就是基于Android的Native App开发和基于微信公众号的Light App开发,今天就来带领大家快速进入微信公众号的开发领域. 一.微信开发环境搭建 工欲善其事,必先利其器.要做微信公众号开发,那么要先准备好两样必不可少的东西: 1.要有一个用来测试的公众号. 2.用来调式代码的开发环境. 1.1.注册测试公众号 微信公众号分为服务号.订阅号.企业号,订阅号

微信开发第五篇手机端微信公众号自定义菜单及OAuth2.0授权页面

说到自定义菜单,首先要想到调用微信的接口,其实微信公众号开发本身就是看对不对微信公众号接口的熟悉程度,我也是在项目中才开始接触微信公众号开发的,很感谢公司能给我这个项目机会.其实对于一个程序员来说最宝贵的是他的学习能力,而不是经验,不扯没用的了. 菜单上一篇讲到了怎么查看微信开发文档,那么很容易找到自定义菜单管理,根据里面的内容可以做一下思路 手机微信客户端与微信服务器交互,再由微信服务器与咱们自己的服务器交互,在第一次交互时先删除原始的那种可以打字的那种菜单,之后设置自己新的菜单,最后把自己的

微信开发教程:用户账号绑定到微信公众号的方法分享

时间:2015-02-26    作者:Abyssly   来源:Abyssly Blog 最近由于工作需要,接触了微信公众号的开发.业务上要求绑定微信用户和系统用户,以便用户在一次绑定后能够通过系统用户的身份去使用一些功能.我关注的招行信用卡公众号实现了这个功能,所以估计还是可行的,在网上搜索了一下,发现这个问题没什么好的答案,很多都说取不到微信用户名实现不了,甚至有说实现了这个功能的应该是与微信有内部合作的. 搜索无果,遂自己动手实验,后发现其实完全可以的,看来实践才是检验真理的唯一标准,方

微信小程序之wx.requestPayment 发起微信支付

wx.requestPayment 发起微信支付 timeStamp 时间戳 nonceStr 随机字符串 package 统一下单接口返回的 prepay_id 参数值 signType 签名算法 paySign 支付签名 success 接口成功回调 fail 接口失败回调 complete 接口完成回调(成功,失败都执行) 1.先调用后台接口,生产基本数据 // 获取店铺信息 Api.BalancePay({ openid: openid, amount: amount, bid: bid

Java企业微信开发_09_素材管理之下载微信临时素材到本地服务器

一.本节要点 1.获取临时素材接口 请求方式:GET(HTTPS) 请求地址:https://qyapi.weixin.qq.com/cgi-bin/media/get?access_token=ACCESS_TOKEN&media_id=MEDIA_ID 2.获取临时素材接口的返回结果 企业微信官方开发文档中说明的返回结果如下: 若你以为这就是返回结果,然后跟之前一样,先访问接口,从http连接的输入流中的获取回结果的文本内容,你会发现你接收到的结果是一堆乱码. 这是为何? 以图片为例,此处千

.NET 微信开发 JSSDK配置 wx.config调用 invalid signature签名错误分析

官方文档 要认真看一遍之后,开始搞 JSSDK是网页调用微信功能的配置文件.在这里浪费了大量时间  所以记录一下.(吐槽下微信返回的错误信息,也是没谁了...) 页面先配置一下.注释里几个参数,可以用ajax会获取. <script type="text/javascript"> wx.config({ debug: false, // 开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端