2016-07-06 10:04:58 qq_27159627 阅读数 1170
  • 微信沙箱开发微信社交立减金接口升级

    会员免费看,http://edu.csdn.net/lecturer/842右侧可办理会员卡。微信沙箱也叫微信仿真测试系统,微信沙箱开发是子恒老师《子恒说微信开发》视频教程的第18部。详细讲解了微信沙箱开发过程,内容包含微信沙箱作用,获取微信沙箱验签秘钥KEY,在沙箱中实现社交立减金接口升级等等。欢迎反馈,微信号:QQ68183131

    7156 人正在学习 去看看 秦子恒

基本的配置在微信公众平台里面已经有详细的描述了,我在这里只是针对我自己在开发过程中碰到的问题进行叙述。谢谢!


1.首先得到当前页面的url信息不包含#及后面部分  var url = location.href.split('#')[0];(这个加密的url我在开发的时候一直在用后台生成的导致老是签名失败!苦恼大哭

2.将url传递到后台就行加密


后台c#代码

Dictionary<string, string> parameters = new Dictionary<string, string>();
parameters.Add("url", url);
//得到jsapi_ticket
string ticket = WeiXinInter.WeiXinTicket.jsapi_ticket;
parameters.Add("jsapi_ticket", ticket);
//生成时间戳
string ts = GenerateTimeStamp();
//获得nonceStr: '',  生成签名的随机串
string noncestr = GenerateNonceStr();
parameters.Add("timestamp", ts);
 parameters.Add("noncestr", noncestr);
//ASCII码从小到大排序并且进行sha1加密

string signature = CreateSignString(parameters);


        /// <summary>
        /// 生成时间戳,标准北京时间,时区为东八区,自1970年1月1日 0点0分0秒以来的秒数
        /// </summary>
        /// <returns></returns>
        private static string GenerateTimeStamp()
        {
            TimeSpan ts = DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0, 0);
            return Convert.ToInt64(ts.TotalSeconds).ToString();
        }


        /// <summary>
        /// 获得nonceStr: '',  生成签名的随机串
        /// </summary>
        /// <returns></returns>
        private static string GenerateNonceStr()
        {
            return Guid.NewGuid().ToString().Replace("-", "");
        }

      

        //将集合 M 内非空参数值的参数按照参数名ASCII码从小到大排序(字典序)

        static string CreateSignString(Dictionary<string, string> parameters)
        {
            foreach (var key in parameters.Keys.Where(key => string.IsNullOrEmpty(parameters[key])))
            {
                parameters.Remove(key);
            }


            //第一步,设所有収送戒者接收到的数据为集合 M,将集合 M 内非空参数值的参数按照参数名ASCII码从小到大排序(字典序),
            //使用URL键值对的格式(即key1=value1&key2=value2…)拼接成字符串 stringA。
            //特别注意以下重要规则:
            //1.参数名 ASCII 码从小到大排序(字典序) ;
            //2.如果参数的值为空不参与签名;
            //3.参数名区分大小写;
            //4.验证调用返回戒微信主劢通知签名时,传送的 sign 参数不参与签名,将生成的签名与该 sign 值作校验。
            var keyArray = parameters.Keys.ToArray();
            Array.Sort(keyArray);
            var keyString = keyArray.Aggregate("", (current, t) => current + (t + "=" + parameters[t] + "&"));


            //第二步,在 stringA 最后拼接上 key=商户支付密钥得到 stringSignTemp 字符串,
            //并对 stringSignTemp 进行 MD5 运算,再将得到的字符串所有字符转换为大写,得到 sign的值 signValue
            keyString = keyString.Substring(0, keyString.Length - 1);
            //
            return SHA1(keyString).ToLower();
        }

       //sha1加密

        private static string SHA1(string text)
        {
            byte[] cleanBytes = Encoding.Default.GetBytes(text);
            byte[] hashedBytes = System.Security.Cryptography.SHA1.Create().ComputeHash(cleanBytes);
            return BitConverter.ToString(hashedBytes).Replace("-", "");
        }

----------------------------------------------------------------------------------------------------------------------------------------------------------------------------

web前端代码,微信公众平台文档有详细说明

                 wx.config({
                    debug: true, // 开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。
                    appId:res.dataPacket.appId, // 必填,公众号的唯一标识
                    timestamp: res.dataPacket.timestamp, // 必填,生成签名的时间戳
                    nonceStr: res.dataPacket.nonceStr, // 必填,生成签名的随机串
                    signature: res.dataPacket.signature,// 必填,签名,见附录1
                    jsApiList: [
                        'checkJsApi',
                        'onMenuShareTimeline',
                        'onMenuShareAppMessage'
                    ] // 必填,需要使用的JS接口列表,所有JS接口列表见附录2
                });

           wx.ready(function(){
            console.log("----");
            // config信息验证后会执行ready方法,所有接口调用都必须在config接口获得结果之后,config是一个客户端的异步操作,所以如果需要在页面加载时就调用相关接口,则须把相关接口放在ready函数中调用来确保正确执行。对于用户触发时才调用的接口,则可以直接调用,不需要放在ready函数中。
            //分享到朋友圈
            //console.log("进入ready");
            wx.onMenuShareTimeline({
                title: Sharetitle, // 分享标题(这个分享的url可以自己定义,与加密的url不同,加密的url必须是当前页面的url不包含#及后面的部分)
                link: ShareLink, // 分享链接
                imgUrl: imgurl, // 分享图标
                success: function () {
                    // 用户确认分享后执行的回调函数
                },
                cancel: function () {
                    // 用户取消分享后执行的回调函数
                }
            });
            //分享给朋友
            wx.onMenuShareAppMessage({
                title: Sharetitle, // 分享标题
                desc: Sharecontent, // 分享描述
                link: ShareLink, // 分享链接
                imgUrl: imgurl, // 分享图标
                type: 'link', // 分享类型,music、video或link,不填默认为link
                dataUrl: '', // 如果type是music或video,则要提供数据链接,默认为空
                success: function () {
                    // 用户确认分享后执行的回调函数
                },
                cancel: function () {
                    // 用户取消分享后执行的回调函数
                }
            });
        });


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





2017-01-16 15:47:38 u014783753 阅读数 2982
  • 微信沙箱开发微信社交立减金接口升级

    会员免费看,http://edu.csdn.net/lecturer/842右侧可办理会员卡。微信沙箱也叫微信仿真测试系统,微信沙箱开发是子恒老师《子恒说微信开发》视频教程的第18部。详细讲解了微信沙箱开发过程,内容包含微信沙箱作用,获取微信沙箱验签秘钥KEY,在沙箱中实现社交立减金接口升级等等。欢迎反馈,微信号:QQ68183131

    7156 人正在学习 去看看 秦子恒



微信页面分享到朋友圈、分享朋友等等,默认的是有分享格式的,比如分享给朋友,默认的图标是页面的第一张图片,内容是该页面的url,这个显然有些场景是不满足的。对于挑剔的产品经理一定是会有自己的设计的,比如图片、内容等。

微信js-sdk提供了关于这部分的接口,现将过程说明如下。

文档路径,在登录公众号后路径如下:点击打开链接,在左侧“微信网页开发”--“微信JS-SDK说明文档”菜单栏中

点击“3.2 获取“分享给朋友”按钮点击状态及自定义分享内容接口”我们可以看到如下内容:

wx.onMenuShareAppMessage({
    title: '', // 分享标题
    desc: '', // 分享描述
    link: '', // 分享链接
    imgUrl: '', // 分享图标
    type: '', // 分享类型,music、video或link,不填默认为link
    dataUrl: '', // 如果type是music或video,则要提供数据链接,默认为空
    success: function () { 
        // 用户确认分享后执行的回调函数
    },
    cancel: function () { 
        // 用户取消分享后执行的回调函数
    }
});
在以上代码片段中我们看到了我们可以定义“微信分享视图”中的这些项:标题、描述、连接、图片以及类型。为了举例,我们只说标题和描述。

看了以上代码段,问题来了,wx这个对象我们怎么定义以及怎么配置呢?
在改说明文档下的步骤一、步骤二和步骤三说明了我们怎么使用wx这个对象以及怎么配置,如下:

JSSDK使用步骤
步骤一:绑定域名
先登录微信公众平台进入“公众号设置”的“功能设置”里填写“JS接口安全域名”。
备注:登录后可在“开发者中心”查看对应的接口权限。
步骤二:引入JS文件
在需要调用JS接口的页面引入如下JS文件,(支持https):http://res.wx.qq.com/open/js/jweixin-1.0.0.js
如需使用摇一摇周边功能,请引入 http://res.wx.qq.com/open/js/jweixin-1.1.0.js
备注:支持使用 AMD/CMD 标准模块加载方法加载
步骤三:通过config接口注入权限验证配置
所有需要使用JS-SDK的页面必须先注入配置信息,否则将无法调用(同一个url仅需调用一次,对于变化url的SPA的web app可在每次url变化时进行调用,目前Android微信客户端不支持pushState的H5新特性,所以使用pushState来实现web app的页面会导致签名失败,此问题会在Android6.2中修复)。
wx.config({
    debug: true, // 开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。
    appId: '', // 必填,公众号的唯一标识
    timestamp: , // 必填,生成签名的时间戳
    nonceStr: '', // 必填,生成签名的随机串
    signature: '',// 必填,签名,见附录1
    jsApiList: [] // 必填,需要使用的JS接口列表,所有JS接口列表见附录2
});

以上代码段我们需要注意wx.config({})中定义的参数:

debug我们不再赘述

appId,就是公众号的Id

timestamp,暂时看就是一个时间戳文本

nonceStr,暂时看就是一个随机串,

jsApiList,需要使用的js接口列表,这个看上去也没有什么问题,应该是js接口列表中列出的接口的一个array

需要我们注意的是signature以及signature和timestamp和nonceStr的关系。根据以上代码段列出的备注,我们看附录一。

附录一描述如下

附录1-JS-SDK使用权限签名算法
jsapi_ticket
生成签名之前必须先了解一下jsapi_ticket,jsapi_ticket是公众号用于调用微信JS接口的临时票据。正常情况下,jsapi_ticket的有效期为7200秒,通过access_token来获取。由于获取jsapi_ticket的api调用次数非常有限,频繁刷新jsapi_ticket会导致api调用受限,影响自身业务,开发者必须在自己的服务全局缓存jsapi_ticket 。
1.参考以下文档获取access_token(有效期7200秒,开发者必须在自己的服务全局缓存access_token):../15/54ce45d8d30b6bf6758f68d2e95bc627.html
2.用第一步拿到的access_token 采用http GET方式请求获得jsapi_ticket(有效期7200秒,开发者必须在自己的服务全局缓存jsapi_ticket):https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=ACCESS_TOKEN&type=jsapi
成功返回如下JSON:
{
"errcode":0,
"errmsg":"ok",
"ticket":"bxLdikRXVbTPdHSM05e5u5sUoXNKd8-41ZO3MhKoyN5OfkWITDGgnr2fwJ0m9E8NYzWKVZvdVtaUgWvsdshFKA",
"expires_in":7200
}
获得jsapi_ticket之后,就可以生成JS-SDK权限验证的签名了。
通过阅读以上代码段说明的文本,我们可以看出来,要想生成signature这个参数,不许要生成ticket这个“票据”。

需要我们注意的是,生成这个“票据”又需要我们获得access_token,根据以上../15/54....这段说明我们看下怎么生成access_token这个参数。

说明如下:

获取access token
access_token是公众号的全局唯一票据,公众号调用各接口时都需使用access_token。开发者需要进行妥善保存。access_token的存储至少要保留512个字符空间。access_token的有效期目前为2个小时,需定时刷新,重复获取将导致上次获取的access_token失效。

公众平台的API调用所需的access_token的使用及生成方式说明:

1、为了保密appsecrect,第三方需要一个access_token获取和刷新的中控服务器。而其他业务逻辑服务器所使用的access_token均来自于该中控服务器,不应该各自去刷新,否则会造成access_token覆盖而影响业务;
2、目前access_token的有效期通过返回的expire_in来传达,目前是7200秒之内的值。中控服务器需要根据这个有效时间提前去刷新新access_token。在刷新过程中,中控服务器对外输出的依然是老access_token,此时公众平台后台会保证在刷新短时间内,新老access_token都可用,这保证了第三方业务的平滑过渡;
3、access_token的有效时间可能会在未来有调整,所以中控服务器不仅需要内部定时主动刷新,还需要提供被动刷新access_token的接口,这样便于业务服务器在API调用获知access_token已超时的情况下,可以触发access_token的刷新流程。
如果第三方不使用中控服务器,而是选择各个业务逻辑点各自去刷新access_token,那么就可能会产生冲突,导致服务不稳定。

公众号可以使用AppID和AppSecret调用本接口来获取access_token。AppID和AppSecret可在微信公众平台官网-开发者中心页中获得(需要已经成为开发者,且帐号没有异常状态)。注意调用所有微信接口时均需使用https协议。

接口调用请求说明

http请求方式: GET
https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET
参数说明

参数	是否必须	说明
grant_type	是	获取access_token填写client_credential
appid	是	第三方用户唯一凭证
secret	是	第三方用户唯一凭证密钥,即appsecret
返回说明

正常情况下,微信会返回下述JSON数据包给公众号:

{"access_token":"ACCESS_TOKEN","expires_in":7200}
参数	说明
access_token	获取到的凭证
expires_in	凭证有效时间,单位:秒

错误时微信会返回错误码等信息,JSON数据包示例如下(该示例为AppID无效错误):

{"errcode":40013,"errmsg":"invalid appid"}
通过以上代码段列出的文本我们很快可以看到,只要传入appid和appsecret以及grant_type这三个参数给列出的url既可以获得返回的access_token这个参数,这里我们不再赘述。

需要注意的是我在处理这块儿的时候想当然的使用oauth认证的access_token来获取“票据”,最后证明返回一直是invalid,即参数错误是不行的。不行的方式如下:

Get:
https://api.weixin.qq.com/sns/oauth2/access_token
传入:
appid
secretid
以及code
其中code是微信回调方法传入的,这里我们不再赘述
事实证明,这种方式获得access_token不能获得“票据”

必须用以上的以上代码段描述的方式获得。谢谢。

根据文档描述,在获得代码段后我们就可以生成“签名了”,其中签名的算法如下:

签名算法
签名生成规则如下:参与签名的字段包括noncestr(随机字符串), 有效的jsapi_ticket, timestamp(时间戳), url(当前网页的URL,不包含#及其后面部分) 。对所有待签名参数按照字段名的ASCII 码从小到大排序(字典序)后,使用URL键值对的格式(即key1=value1&key2=value2…)拼接成字符串string1。这里需要注意的是所有参数名均为小写字符。对string1作sha1加密,字段名和字段值都采用原始值,不进行URL 转义。
即signature=sha1(string1)。 示例:
noncestr=Wm3WZYTPz0wzccnW
jsapi_ticket=sM4AOVdWfPE4DxkXGEs8VMCPGGVi4C3VM0P37wVUCFvkVAy_90u5h9nbSlYy3-Sl-HhTdfl2fzFy1AOcHKP7qg
timestamp=1414587457
url=http://mp.weixin.qq.com?params=value
步骤1. 对所有待签名参数按照字段名的ASCII 码从小到大排序(字典序)后,使用URL键值对的格式(即key1=value1&key2=value2…)拼接成字符串string1:
jsapi_ticket=sM4AOVdWfPE4DxkXGEs8VMCPGGVi4C3VM0P37wVUCFvkVAy_90u5h9nbSlYy3-Sl-HhTdfl2fzFy1AOcHKP7qg&noncestr=Wm3WZYTPz0wzccnW×tamp=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.出于安全考虑,开发者必须在服务器端实现签名的逻辑。

以上的1步骤也就回答了signature和noncestr和timestamp的关系。

至此我们就能争取的配置wx.config,不出意外的情况下,调用“发送给朋友”的接口就能个性化配置分享的试图了。


这里附上后端生成signature的java实现

import java.util.UUID;
import java.util.Map;
import java.util.HashMap;
import java.util.Formatter;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.io.UnsupportedEncodingException;  

class Sign {
    public static void main(String[] args) {
        String jsapi_ticket = "jsapi_ticket";

        // 注意 URL 一定要动态获取,不能 hardcode
        String url = "http://example.com";
        Map<String, String> ret = sign(jsapi_ticket, url);
        for (Map.Entry entry : ret.entrySet()) {
            System.out.println(entry.getKey() + ", " + entry.getValue());
        }
    };

    public static Map<String, String> sign(String jsapi_ticket, String url) {
        Map<String, String> ret = new HashMap<String, String>();
        String nonce_str = create_nonce_str();
        String timestamp = create_timestamp();
        String string1;
        String signature = "";

        //注意这里参数名必须全部小写,且必须有序
        string1 = "jsapi_ticket=" + jsapi_ticket +
                  "&noncestr=" + nonce_str +
                  "×tamp=" + timestamp +
                  "&url=" + url;
        System.out.println(string1);

        try
        {
            MessageDigest crypt = MessageDigest.getInstance("SHA-1");
            crypt.reset();
            crypt.update(string1.getBytes("UTF-8"));
            signature = byteToHex(crypt.digest());
        }
        catch (NoSuchAlgorithmException e)
        {
            e.printStackTrace();
        }
        catch (UnsupportedEncodingException e)
        {
            e.printStackTrace();
        }

        ret.put("url", url);
        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;
    }

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

    private static String create_timestamp() {
        return Long.toString(System.currentTimeMillis() / 1000);
    }
}





2017-07-19 16:06:36 Swimming_hacker 阅读数 575
  • 微信沙箱开发微信社交立减金接口升级

    会员免费看,http://edu.csdn.net/lecturer/842右侧可办理会员卡。微信沙箱也叫微信仿真测试系统,微信沙箱开发是子恒老师《子恒说微信开发》视频教程的第18部。详细讲解了微信沙箱开发过程,内容包含微信沙箱作用,获取微信沙箱验签秘钥KEY,在沙箱中实现社交立减金接口升级等等。欢迎反馈,微信号:QQ68183131

    7156 人正在学习 去看看 秦子恒

目的:开发分享功能,将第三方APP中的文字、图片、视频、网页等内容分享到微信的联系人或者朋友圈。
步骤:
1.到微信开放平台申请自己的APP,获取AppID。
地址:http://open.weixin.qq.com/
2.到官网下载sdk相关的包,即libammsdk.jar包
地址:Android资源下载
3.将下载的包导入到项目的lib包中
这里写图片描述
4.开始撸代码:
参考文章:Android接入指南
1)导入相关的包
2)在manifest文件中添加权限

  • NTERNET
  • WIFI_STATE
  • READ_PHONE_STATE
  • WRITE_EXTERNAL_STORAGE

3)注册微信api

final public String App_ID = " wx88888888888";//自己申请的AppID。
private IWXAPI api;//IWXAPI是微信与第三方APP同学的开放接口
public void regToWX(){
    api = WXAPIFactory.createWXAPI(this,App_ID,true);//实例化接口
    api.registerApp(App_ID);//将接口注册到微信

}

4)发送请求到微信
主要通过IWXAPI的sendReq方法发送请求
以发送文字为例:

 //a.初始化一个WXTextObject对象
 WXTextObject textObject = new WXTextObject();
 textObject = text;//text 就是要发送的文字内容
//b.初始化一个WXMediaMessage对象
WXMediaMessage msg = new WXMediaMessage();
msg.mediaObject  = textObject;
//c.构造一个req对象
SendMessageToWX.Req req = new SenMessageToWX.Req();
req.transaction = String.ValueOf(text);//transaction字段用于唯一标识一个请求
req.message = msg;
//d.调用api接口发送请求
api.sendReq(req);

其他内容如图片、视频、网页链接的分享与上面的类似,主要是四步:
构建WXObject对象、构建WXMediaMessage对象、构建req对象、发送请求。
主要不同点在与WXObject对象和WXMediaMessage对象的构建上有所区别,具体详见:分享与收藏功能开发文档(Android应用)

2017.7.19更
待续

2018-04-24 20:02:24 qq_39879632 阅读数 531
  • 微信沙箱开发微信社交立减金接口升级

    会员免费看,http://edu.csdn.net/lecturer/842右侧可办理会员卡。微信沙箱也叫微信仿真测试系统,微信沙箱开发是子恒老师《子恒说微信开发》视频教程的第18部。详细讲解了微信沙箱开发过程,内容包含微信沙箱作用,获取微信沙箱验签秘钥KEY,在沙箱中实现社交立减金接口升级等等。欢迎反馈,微信号:QQ68183131

    7156 人正在学习 去看看 秦子恒

Java微信分享,步骤是

1、根据当前的url,获取signature,nonceStr,timestamp 和appId。 
2、通过signature,nonceStr,timestamp 和appId来配置微信 wx.config。 
3、通过wx.ready实现微信分享功能。

1、html端

引入微信JS-SDK.

<script src="http://res.wx.qq.com/open/js/jweixin-1.0.0.js"></script>

//分享核心js代码
$(document).ready(function () {
    //通过ajax,在页面加载的时候获取微信分享接口signature,nonceStr,timestamp 和appId
    $.ajax({
        type: "post",
        url: "/weixin/share",
        dataType: "json",
        data:"url="+window.location.href,
        success: function (data) {
            wx.config({
                debug: false,
                appId: data.appId,
                timestamp: data.timestamp,
                nonceStr: data.nonceStr,
                signature: data.signature,
                jsApiList: ['onMenuShareAppMessage', 'onMenuShareTimeline', 'hideAllNonBaseMenuItem', 'showMenuItems']
                // 功能列表,我们要使用JS-SDK的什么功能
            });
            wx.ready(function () {
                // 获取“分享给朋友”按钮点击状态及自定义分享内容接口
                wx.onMenuShareAppMessage({
                    title: "分享自定义标题", // 分享标题
                    desc: "分享自定义描述", // 分享描述
                    link: "http://localhost/weixin/share?openId=1",//分享点击之后的链接
                    imgUrl:'/images/photo/1.jpg', // 分享图标
                    type: 'link', // 分享类型,music、video或link,不填默认为link
                    success: function () {
                        //成功之后的回调
                    }
                });
                wx.hideAllNonBaseMenuItem();
                wx.showMenuItems({
                    menuList: ['menuItem:share:appMessage', 'menuItem:share:timeline'] // 要隐藏的菜单项,只能隐藏“传播类”和“保护类”按钮,所有menu项见附录3
                });
                wx.onMenuShareTimeline({
                    title: "分享自定义标题", // 分享标题
                    desc: "分享自定义描述", // 分享描述
                    link: "http://localhost/weixin/share?openId=1",//分享点击之后的链接
                    imgUrl:'/images/photo/1.jpg', // 分享图标
                    type: 'link', // 分享类型,music、video或link,不填默认为link
                    success: function () {
                        //成功之后的回调
                    }
                    cancel: function () {
                        // 用户取消分享后执行的回调函数
                    }
                });
            });
            wx.error(function (res) {
                //打印错误消息。及把 debug:false,设置为debug:ture就可以直接在网页上看到弹出的错误提示
            });
        }
    })
});

2、Java代码,获取 signature,nonceStr,timestamp 和appId

    @RequestMapping(value = "/share", method = RequestMethod.POST)
    @ResponseBody
    public Map<String, Object> share(HttpServletRequest request) {
        String urlTemp = "http://" + request.getServerName() + request.getContextPath();
        String urlpath = "http://" + request.getServerName();
        String appUrl = request.getParameter("url");
        if (request.getParameter("code") != null) {
            appUrl += "&code=" + request.getParameter("code");
        }
        if (request.getParameter("state") != null) {
            appUrl += "&state=" + request.getParameter("state");
        }
        return WxConfigUtil.getSignature(appUrl, ContentValues.APPID, ContentValues.SECRET, urlTemp, urlpath);
    }

工具类我就把整个贴上来了,其中有些方法是没有用到的。

getSignature()整个方法是微信分享中的核心方法,用来获取signature,nonceStr,timestamp 和appId这几个核心参数。

package com.blog.common.util;

import com.alibaba.fastjson.JSONObject;
import com.blog.common.model.Token;

import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.ConnectException;
import java.net.URL;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;


/**
 * 公众平台通用接口工具类
 *
 * @author james
 * @date 2015-02-27
 */
public class WxConfigUtil {
    // 获取access_token的接口地址(GET) 限2000(次/天)
    public final static String access_token_url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET";
    // 获取jsapi_ticket的接口地址(GET) 限2000(次/天)
    public final static String jsapi_ticket_url = "https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=ACCESS_TOKEN&type=jsapi";
    // 缓存添加的时间
    public static String cacheAddTime = null;
    // token,ticket缓存
    public static Map<String, Token> TOKEN_TICKET_CACHE = new HashMap<String, Token>();
    // token对应的key
    private static final String TOKEN = "token";
    // ticket对应的key
    private static final String TICKET = "ticket";

    /**
     * 外部获取签名入口类
     *
     * @param appUrl    应用的url
     * @return
     */
    public static Map<String, Object> getSignature(String appUrl, String appId, String secret, String url, String urlpath) {
        // 生成签名的随机串
        String noncestr = RandomUtil.getStringRandom(4);
        if (appUrl == null || "".equals(appUrl)) {
            return null;
        }
        String signature = null;
        Token accessTocken = getToken(appId, secret, System.currentTimeMillis() / 1000);
        Token accessTicket = getTicket(accessTocken.getToken(), System.currentTimeMillis() / 1000);
        signature = signature(accessTicket.getTicket(), cacheAddTime, noncestr, appUrl);
        System.out.println("-=-=-=-=-=-=-=-=appUrl:" + appUrl);
        System.out.println("-=-=-=-=-=-=-=-=token:" + accessTocken.getToken());
        System.out.println("-=-=-=-=-=-=-=-=ticket:" + accessTicket.getTicket());
        System.out.println("-=-=-=-=-=-=-=-=signature:" + signature);
        System.out.println("-=-=-=-=-=-=-=-=timestamp:" + cacheAddTime);
        Map<String, Object> map = new HashMap<>();
        map.put("appId", appId);
        map.put("timestamp", cacheAddTime);
        map.put("nonceStr", noncestr);
        map.put("appUrl", appUrl);
        map.put("signature", signature);
        map.put("url", url);
        map.put("urlpath", urlpath);
        return map;
    }

    /**
     * 获得Token
     *
     * @return
     */
    public static String getToken(String appId, String secret) {
        Token accessTocken = getToken(appId, secret, System.currentTimeMillis() / 1000);
        return accessTocken.getToken();
    }

    /**
     * 签名
     *
     * @param timestamp
     * @return
     */
    private static String signature(String jsapi_ticket, String timestamp, String noncestr, String url) {
        jsapi_ticket = "jsapi_ticket=" + jsapi_ticket;
        timestamp = "timestamp=" + timestamp;
        noncestr = "noncestr=" + noncestr;
        url = "url=" + url;
        String[] arr = new String[]{jsapi_ticket, noncestr, timestamp, url};
        // 将token、timestamp、nonce,url参数进行字典序排序
        Arrays.sort(arr);
        StringBuilder content = new StringBuilder();
        for (int i = 0; i < arr.length; i++) {
            content.append(arr[i]);
            if (i != arr.length - 1) {
                content.append("&");
            }
        }
        MessageDigest md = null;
        String tmpStr = null;

        try {
            md = MessageDigest.getInstance("SHA-1");
            // 将三个参数字符串拼接成一个字符串进行sha1加密
            byte[] digest = md.digest(content.toString().getBytes());
            tmpStr = byteToStr(digest);
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        }

        content = null;
        return tmpStr;
    }

    /**
     * 获取access_token
     *
     * @param appid     凭证
     * @param appsecret 密钥
     * @return
     */
    public static Token getToken(String appid, String appsecret, long currentTime) {
        Token tockenTicketCache = getTokenTicket(TOKEN);
        Token Token = null;

        if (tockenTicketCache != null && (currentTime - tockenTicketCache.getAddTime() <= tockenTicketCache.getExpiresIn())) {// 缓存存在并且没过期
            System.out.println("==========缓存中token已获取时长为:" + (currentTime - tockenTicketCache.getAddTime()) + "毫秒,可以重新使用");
            return tockenTicketCache;
        }
        System.out.println("==========缓存中token不存在或已过期===============");
        String requestUrl = access_token_url.replace("APPID", appid).replace("APPSECRET", appsecret);
        JSONObject jsonObject = httpRequest(requestUrl, "GET", null);
        // 如果请求成功
        if (null != jsonObject) {
            Token = new Token();
            Token.setToken(jsonObject.getString("access_token"));
            Token.setExpiresIn(jsonObject.getIntValue("expires_in") / 2);// 正常过期时间是7200秒,此处设置3600秒读取一次
            System.out.println("==========tocket缓存过期时间为:" + Token.getExpiresIn() + "毫秒");
            Token.setAddTime(currentTime);
            updateToken(TOKEN, Token);
        }
        return Token;
    }

    /**
     * 获取ticket
     *
     * @param token
     * @return
     */
    private static Token getTicket(String token, long currentTime) {
        Token tockenTicketCache = getTokenTicket(TICKET);
        Token Token = null;
        if (tockenTicketCache != null && (currentTime - tockenTicketCache.getAddTime() <= tockenTicketCache.getExpiresIn())) {// 缓存中有ticket
            System.out.println("==========缓存中ticket已获取时长为:" + (currentTime - tockenTicketCache.getAddTime()) + "毫秒,可以重新使用");
            return tockenTicketCache;
        }
        System.out.println("==========缓存中ticket不存在或已过期===============");
        String requestUrl = jsapi_ticket_url.replace("ACCESS_TOKEN", token);
        JSONObject jsonObject = httpRequest(requestUrl, "GET", null);
        // 如果请求成功
        if (null != jsonObject) {
            Token = new Token();
            Token.setTicket(jsonObject.getString("ticket"));
            Token.setExpiresIn(jsonObject.getIntValue("expires_in") / 2);// 正常过期时间是7200秒,此处设置3600秒读取一次
            System.out.println("==========ticket缓存过期时间为:" + Token.getExpiresIn() + "毫秒");
            Token.setAddTime(currentTime);
            updateToken(TICKET, Token);
        }
        return Token;
    }

    /**
     * 发起https请求并获取结果
     *
     * @param requestUrl    请求地址
     * @param requestMethod 请求方式(GET、POST)
     * @param outputStr     提交的数据
     * @return JSONObject(通过JSONObject.get(key)的方式获取json对象的属性值)
     */
    private static JSONObject httpRequest(String requestUrl, String requestMethod, String outputStr) {
        JSONObject jsonObject = null;
        StringBuffer buffer = new StringBuffer();
        try {
            // 创建SSLContext对象,并使用我们指定的信任管理器初始化
            TrustManager[] tm = {new MyX509TrustManager()};
            SSLContext sslContext = SSLContext.getInstance("SSL", "SunJSSE");
            sslContext.init(null, tm, new java.security.SecureRandom());
            // 从上述SSLContext对象中得到SSLSocketFactory对象
            SSLSocketFactory ssf = sslContext.getSocketFactory();

            URL url = new URL(requestUrl);
            HttpsURLConnection httpUrlConn = (HttpsURLConnection) url.openConnection();
            httpUrlConn.setSSLSocketFactory(ssf);

            httpUrlConn.setDoOutput(true);
            httpUrlConn.setDoInput(true);
            httpUrlConn.setUseCaches(false);
            // 设置请求方式(GET/POST)
            httpUrlConn.setRequestMethod(requestMethod);

            if ("GET".equalsIgnoreCase(requestMethod))
                httpUrlConn.connect();

            // 当有数据需要提交时
            if (null != outputStr) {
                OutputStream outputStream = httpUrlConn.getOutputStream();
                // 注意编码格式,防止中文乱码
                outputStream.write(outputStr.getBytes("UTF-8"));
                outputStream.close();
            }

            // 将返回的输入流转换成字符串
            InputStream inputStream = httpUrlConn.getInputStream();
            InputStreamReader inputStreamReader = new InputStreamReader(inputStream, "utf-8");
            BufferedReader bufferedReader = new BufferedReader(inputStreamReader);

            String str = null;
            while ((str = bufferedReader.readLine()) != null) {
                buffer.append(str);
            }
            bufferedReader.close();
            inputStreamReader.close();
            // 释放资源
            inputStream.close();
            inputStream = null;
            httpUrlConn.disconnect();
            jsonObject = JSONObject.parseObject(buffer.toString());
            // jsonObject = JSONObject.fromObject(buffer.toString());
        } catch (ConnectException ce) {
            System.out.println("Weixin server connection timed out.");
        } catch (Exception e) {
            System.out.println("https request error:{}" + e.getMessage());
        }
        return jsonObject;
    }

    /**
     * 将字节数组转换为十六进制字符串
     *
     * @param byteArray
     * @return
     */
    private static String byteToStr(byte[] byteArray) {
        String strDigest = "";
        for (int i = 0; i < byteArray.length; i++) {
            strDigest += byteToHexStr(byteArray[i]);
        }
        return strDigest;
    }

    /**
     * 将字节转换为十六进制字符串
     *
     * @param mByte
     * @return
     */
    private static String byteToHexStr(byte mByte) {

        char[] Digit = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
        char[] tempArr = new char[2];
        tempArr[0] = Digit[(mByte >>> 4) & 0X0F];
        tempArr[1] = Digit[mByte & 0X0F];

        String s = new String(tempArr);
        return s;
    }

    /**
     * 从缓存中读取token或者ticket
     *
     * @return
     */
    private static Token getTokenTicket(String key) {
        if (TOKEN_TICKET_CACHE != null && TOKEN_TICKET_CACHE.get(key) != null) {
            System.out.println("==========从缓存中获取到了" + key + "成功===============");
            return TOKEN_TICKET_CACHE.get(key);
        }
        return null;
    }

    /**
     * 更新缓存中token或者ticket
     *
     * @return
     */
    private static void updateToken(String key, Token accessTocken) {
        if (TOKEN_TICKET_CACHE != null && TOKEN_TICKET_CACHE.get(key) != null) {
            TOKEN_TICKET_CACHE.remove(key);
            System.out.println("==========从缓存中删除" + key + "成功===============");
        }
        TOKEN_TICKET_CACHE.put(key, accessTocken);
        cacheAddTime = String.valueOf(accessTocken.getAddTime());// 更新缓存修改的时间
        System.out.println("==========更新缓存中" + key + "成功===============");
    }

}

友情链接:https://blog.csdn.net/shrmuscles/article/details/77987185https://blog.csdn.net/qq_29057491/article/details/61191566

2019-11-08 14:01:48 sinat_27535209 阅读数 25
  • 微信沙箱开发微信社交立减金接口升级

    会员免费看,http://edu.csdn.net/lecturer/842右侧可办理会员卡。微信沙箱也叫微信仿真测试系统,微信沙箱开发是子恒老师《子恒说微信开发》视频教程的第18部。详细讲解了微信沙箱开发过程,内容包含微信沙箱作用,获取微信沙箱验签秘钥KEY,在沙箱中实现社交立减金接口升级等等。欢迎反馈,微信号:QQ68183131

    7156 人正在学习 去看看 秦子恒

安卓微信的api,个人微信开发API协议,微信 ipad sdk,微信ipad协议,微信web版接口api,微信网页版接口,微信电脑版sdk,微信开发sdk,微信开发API,微信协议,微信接口文档sdk,替代微信ipad协议的api接口,网页个人微信api分享,微信机器人SDK接口API,个人微信号API接口,微信群API接口

1、基础消息类型
1、客户端发送的心跳包HeartBeatReq = 1001; 
2、消息接收确认回复(接收或拒绝接收)MsgReceivedAck = 1002; 
3、错误单独提升为一种消息类型Error = 1003; 
4、通用任务执行结果通知TaskResultNotice = 1025; 
2、设备客户端授权类消息
1、设备(手机客户端、客服客户端)获取通信token请求与响应DeviceAuthReq = 1010; 
设备(手机客户端、客服客户端)获取通信token响应DeviceAuthRsp = 1011;
2、设备授权后退出(仅用于服务端内部)DeviceExitNotice = 1012; 
3、账号强制下线通知 AccountForceOfflineNotice = 1013; 
3、手机客户端上传的通知类消息
1、手机客户端微信上线通知 WeChatOnlineNotice = 1020; 
2、手机客户端微信下线通知 WeChatOfflineNotice = 1021; 
3、微信个人号新增好友通知FriendAddNotice = 1022;
4、微信个人号移除好友通知FriendDelNotice = 1023; 
5、微信好友发来聊天消息通知FriendTalkNotice = 1024; 
6、手机上回复好友的聊天消息通知WeChatTalkToFriendNotice = 1026; 
7、有好友请求添加好友的通知FriendAddReqeustNotice = 1027; 
8、手机上发送了朋友圈通知CircleNewPublishNotice = 1031; 
9、手机上删除朋友圈返回通知CircleDelNotice = 1032; 
10、手机检测到有人点赞/取消点赞通知CircleLikeNotice = 1033; 
11、手机检测到有人评论/删除朋友圈通知CircleCommentNotice = 1034; 
12、消息标记为已读PostMessageReadNotice = 1035; 
13、群聊新增通知ChatRoomAddNotice = 1037; 
14、群聊信息变更通知ChatRoomChangedNotice = 1042;
15、群聊删除通知返回ChatRoomDelNotice = 1041; 
16、联系人标签新增,修改通知ContactLabelAddNotice = 1038; 
17、联系人标签删除通知ContactLabelDelNotice = 1044; // 联系人标签删除通知
18、新增公众号通知BizContactAddNotice = 2038; // 新增公众号通知
19、手机端推送当前sdk的安装版本通知PostDeviceInfoNotice = 2027; 
4、服务端、客服客户端发给设备的指令类消息(sdk咨询微信836869520)
1、给好友发消息任务TalkToFriendTask = 1070; 
返回聊天执行结果TalkToFriendTaskResultNotice = 1028; 
2、发送朋友圈任务及结果返回PostSNSNewsTask = 1071; 
返回发送朋友圈数据结果PostSNSNewsTaskResultNotice = 1073; 
3、删除朋友圈任务与结果返回DeleteSNSNewsTask = 1074; 
返回通用任务执行结果
4、主动添加好友任务及返回结果AddFriendsTask = 1072; 
返回通用任务执行结果
5、接受好友请求任务及返回结果AcceptFriendAddRequestTask = 1075; 
返回通用任务执行结果
6、群发消息任务WeChatGroupSendTask = 1076; 
返回通用任务执行结果
7、执行养号动作命令任务WeChatMaintenanceTask = 1077; 
返回通用任务执行结果
8、养号任务停止任务及返回结果PostStopWeChatMaintenanceTask = 1100; 
返回通用任务执行结果
9、清粉任务及返回结果PostFriendDetectTask = 1095; 
返回:每隔一段时间手机端回传检测清粉好友数PostFriendDetectCountNotice = 2028; 
10、终止清粉任务及返回结果PostStopFriendDetectTask = 1096; 
返回通用任务执行结果
11、请求聊天图片或视频消息的详细内容任务与结果返回RequestTalkDetailTask = 1078; 
返回聊天图片或视频消息的详细内容结果RequestTalkDetailTaskResultNotice = 1029; 
12、要求手机上传当前微信二维码任务及返回PullWeChatQrCodeTask = 1079; 
返回手机端微信的二维码PullWeChatQrCodeTaskResultNotice = 1030; 
13、触发手机推送好友列表任务及结果返回TriggerFriendPushTask = 1080; 
返回一:手机端推送好友列表(分页,每页100)FriendPushNotice = 2026;
返回二:手机端推送标签列表
14、触发手机推送朋友圈列表任务及结果返回TriggerCirclePushTask = 1081; 
返回手机朋友圈数据(分页,每页20)CirclePushNotice = 2029; 
15、朋友圈评论删除任务及结果返回CircleCommentDeleteTask = 1082; 
朋友圈评论删除任务反馈 CircleCommentDeleteTaskResultNotice = 1083; 
16、朋友圈评论回复任务及结果返回CircleCommentReplyTask = 1084; 
朋友圈评论回复反馈CircleCommentReplyTaskResultNotice = 1085; 
17、通知手机将某个聊天窗口置为已读TriggerMessageReadTask = 1086; 
无返回
18、消息撤回任务RevokeMessageTask = 1087; 
返回通用任务执行结果
19、转发消息任务ForwardMessageTask = 1088;
返回通用任务执行结果
20、通知手机推送历史聊天记录任务及返回TriggerHistoryMsgPushTask = 1089; 
返回历史消息(分页,每页50)HistoryMsgPushNotice = 2033; 
21、获取群聊二维码任务及结果返回PullChatRoomQrCodeTask = 1090; 
返回群二维码PullChatRoomQrCodeTaskResultNotice = 1043;
22、朋友圈点赞任务及结果返回PostMomentsPraiseTask = 1098; 
返回朋友圈点赞数量PostMomentsPraiseCountNotice = 2030; 
23、停止朋友圈点赞任务PostStopMomentsPraiseTask = 1099; 
返回通用任务执行结果
24、修改联系人备注任务ModifyFriendMemoTask = 1101; 
返回通用任务执行结果
25、领取红包或转账收钱任务及返回TakeLuckyMoneyTask = 1200; 
返回收钱任务执行结果TakeMoneyTaskResultNotice = 1039; 
26、获取指定好友朋友圈任务及返回PullFriendCircleTask = 1201; 
返回手机朋友圈数据CirclePushNotice = 2029; 
27、获取朋友圈的图片任务及返回PullCircleDetailTask = 1202; 
返回朋友圈图片上传信息CircleDetailNotice = 1040; 
28、单条朋友圈点赞任务CircleLikeTask = 1203; 
返回通用任务执行结果
29、触发手机推送群聊列表任务及结果返回TriggerChatroomPushTask = 1210; 
返回一:手机端推送群聊列表(分页,每页2个)ChatroomPushNotice = 2031; 
返回二:群成员(陌生人)信息列表(分页,每页100)ChatRoomMembersNotice = 2034; 
30、请求具体群聊的详细信息任务RequestChatRoomInfoTask = 1211; 
返回ChatRoomAddNotice 群聊新增通知
31、获取联系人详细信息任务及返回
(不一定是好友,如群聊成员)RequestContactsInfoTask = 1212; 
返回联系人信息ContactsInfoNotice = 1036; 
32、群聊管理任务及返回ChatRoomActionTask = 1213; 
返回通用任务执行结果
返回群聊通知类返回结果
33、群内加好友任务AddFriendInChatRoomTask = 1214;
返回通用任务执行结果
34、通讯录加好友任务AddFriendFromPhonebookTask = 1215; 
返回通用任务执行结果
35、删除好友任务及返回DeleteFriendTask = 1216;  
返回通用任务执行结果
微信个人号移除好友通知
36、发红包任务及返回  
github地址https://www.wuliaokankan.cn/url301/138.html

SendLuckyMoneyTask = 1217; 返回:通用任务执行结果,成功ErrMsg=sendId
37、获取聊天消息的原始内容(主要是xml内容)任务及返回RequestTalkContentTask = 1218; 
返回聊天消息的原始内容RequestTalkContentTaskResultNotice = 1219; 
38、转发消息内容任务及返回ForwardMessageByContentTask = 1220; 
返回通用任务执行结果
39、群主通过入群申请任务及返回ChatRoomInviteApproveTask = 1221;
返回通用任务执行结果
40、设置联系人标签任务及返回ContactLabelTask = 1224; // 设置联系人标签
返回联系人标签新增,修改通知;
返回通用任务执行结果
41、删除联系人标签任务及返回ContactLabelDeleteTask = 1225; // 删除联系人标签
返回通用任务执行结果
返回联系人标签删除通知
42、语音消息转文字命令及返回VoiceTransTextTask = 1226; // 语音消息转文字
返回:通用任务执行结果,成功ErrMsg=文字内容
43、查找微信联系人任务及返回FindContactTask = 1227; // 查找微信联系人
返回查找微信联系人结果
FindContactTaskResult = 1228; // 查找微信联系人结果
44、同意加入群聊命令及返回AgreeJoinChatRoomTask = 1229; // 同意加入群聊
返回通用任务执行结果
45、清空聊天记录任务及返回ClearAllChatMsgTask= 1230; // 清空聊天记录
返回通用任务执行结果
46、聊天界面发送朋友验证任务及返回(别人把你删掉了,你发消息会出现一个发送朋友验证的链接,此处有用到)
返回通用任务执行结果
47、获取会话列表任务及返回TriggerConversationPushTask = 1232; // 会话列表推送
返回聊天会话列表(分页)ConversationPushNotice = 2035; // 会话列表
48、微信设置(改昵称,头像)任务及返回WechatSettingTask = 1233; // 微信设置:改昵称,头像
返回通用任务执行结果
49、获取加好友请求列表任务及返回结果PullFriendAddReqListTask = 1234; //获取加好友请求列表
返回请求加好友列表FriendAddReqListNotice = 2036; // 加好友请求列表
50、获取公众号列表任务及结果返回TriggerBizContactPushTask = 1235; // 获取公众号列表
返回公众号列表BizContactPushNotice = 2037; // 公众号列表推送
51、获取时间段内的所有聊天消息msgSvrId及结果返回TriggerChatMsgIdsPushTask = 1251;
52、名片加好友任务及结果返回AddFriendNameCardTask = 1236; // 名片加好友
返回通用任务执行结果
53、根据msgSvrId获取聊天消息及结果返回RequestTalkMsgTask = 1252;  // 根据msgSvrId获取聊天消息
返回RequestTalkMsgTaskResultNotice = 1253;  
5、服务端通知执行的命令 微信sdk
1、微信账号登出命令WechatLogoutTask = 1222;
无返回;微信退出会触发微信离线通知(WeChatOfflineNoticeMessage)
2、手机操作指令(重启手机等)PhoneActionTask = 1223; // 手机操作指令
返回:通用任务执行结果,(上传本地文件:ErrMsg=文件url)
3、通知手机客户端软件升级UpgradeDeviceAppNotice = 1094; 
无返回
4、服务端删除设备通知手机端PostDeleteDeviceNotice = 1097; 
无返回
安卓微信的api,个人微信开发API协议,微信 ipad sdk,微信ipad协议,微信web版接口api,微信网页版接口,微信电脑版sdk,微信开发sdk,微信开发API,微信协议,微信接口文档sdk,替代微信ipad协议的api接口,网页个人微信api分享,微信机器人SDK接口API,个人微信号API接口,微信群API接口


微信网页版接口

阅读数 62

没有更多推荐了,返回首页