2016-01-22 11:11:09 u010976213 阅读数 10450
  • 自己开发一套微信支付接口(SDK)-微信开发15(PHP)

    会员免费看,http://edu.csdn.net/lecturer/842 边栏可办理会员卡。自己开发一套微信支付接口(SDK)是子恒老师《子恒说微信开发》视频教程的第15部。详细讲解了用php开发一套自己的微信支付接口。内容包含微信支付开发思路,基础类开发,微信支付接口应用,公众号发红包,企业付款等等。欢迎反馈,微信号:QQ68183131

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

第三方SDK接入–微信

说明


由于公司的需求,app需要使用微信登录以及分享到微信等功能,近期对微信的第三方登录、分享功能进行了少许研究,并记录如下。

注意点:
1、 需到“微信开放平台”进行注册;
2、 注册完后如果未进行“开发者资质认证“,微信开放平台帐号下的应用,只能拥有分享给朋友或者发送到朋友圈两个功能的权限。
3、 “开发者资质认证“通过后,微信开放平台帐号下的应用,将获得微信登录、智能接口、公众号第三方平台开发等高级能力。
4、 “开发者资质认证“的有效期为1年,有效期最后两个月可申请年审即可续期,审核费用为300元。


微信开放平台

微信集成

成功注册并登陆微信公众平台后可以看到如上页面,我们目前开发用的基本是“资源中心“,”管理中心“。

  • 资源中心中有许多的开发文档可供我们开发时进行参考。
  • 在管理中心我们就可以创建并浏览我们的应用了。

微信集成

注意在创建应用的时候我们不可以在应用的名字中包含“微信“等字样,我就是因为第一次写名称使用了”微信SDK测试“,结果审核不给通过。

微信集成

这里重要的就是应用的签名,关于签名的获取,我们需要先给自己的应用签名,无论你是使用Eclipse还是Android Studio开发都需要先给你自己的应用签名打包成Apk然后安装到手机上,然后使用微信资源中心提供的签名生成apk,安装到手机上。在手机上打开签名生成工具输入你应用的包名即可得到你应用的签名。

以下地址是微信资源中心签名工具的地址:
https://open.weixin.qq.com/cgi-bin/showdocument?action=dir_list&t=resource/res_list&verify=1&id=open1419319167&token=75dc8457c70c2f4324e9cfd255674d7965d65049&lang=zh_CN

填写完整并提交完毕后就需要耐心等待审核通过了,一般半天就会有结果的。审核通过后可以查看应用的信息如下,这里重要的就是应用的AppIDAppSecret,接下来集成SDK的时候要用到这两个值。

微信集成


APP集成微信SDK

1、 所需文件

1) 申请到的AppID。
2) 微信SDK,在资源中心—资源下载—Andoid资源下载中即可下载。微信SDK连接如下:https://open.weixin.qq.com/cgi-bin/showdocument?action=dir_list&t=resource/res_list&verify=1&id=open1419319167&lang=zh_CN

微信集成

下载完毕解压后里面最重要的文件就是libammsdk.jar这个jar包了,其他暂时不需要。

2、 应用中集成

2.1、Eclipse导入Jar包

在工程中新建一个libs目录,将开发工具包中libs目录下的libammsdk.jar复制到该目录中.

微信集成

右键单击工程,选择Build Path中的Configure Build Path…,选中Libraries这个tab,并通过Add Jars…导入工程libs目录下的libammsdk.jar文件。(如下图所示)

微信集成

2.2、Android Studio导入Jar包

将工程切换到Project视图,然后将开发工具包中libs目录下的libammsdk.jar复制到该工程的app→libs目录中。

微信集成

右键刚刚粘贴进来的libammsdk.jar文件,在弹出的菜单上点击Add As Library即可,如下图所示。

微信集成

2.3、在代码中使用Jar包

Jar包在导入的时候针对两种开发工具写了Eclipse和Android Studio两种导入方法,导入完毕后进行代码的开发时则不用区分不同开发工具的用法了。

2.3.1、分享给微信好友、分享到朋友圈或者添加到微信收藏

这一步比较简单不会涉及太多的东西。微信分享及收藏目前支持文字、图片、音乐、视频、网页共五种类型。

但是要使你的程序启动后微信终端能响应你的程序,必须在代码中向微信终端注册你的APPID。这一步的原理就相当于:你想联系一个人,那么你就必须先给他打个电话,电话接通了你们才能通话,否则则无法联系。所以这个“打电话”的过程是需要在你要分享之前执行的,你可以在Application中注册,也可以在一个Activity中注册,注意只需要注册一次就好了。其他时候也需要使用IWXAPI,但是不需要再注册了。

注册代码类似如下:

private static final String WECHAT_APP_ID = "你申请应用得到的APPID";
// IWXAPI是第三方app和微信通信的openapi接口
    private IWXAPI iwxapi;
/**
     * 将当前应用的APP_ID注册到微信
     */
    private void regToWx() {
        iwxapi = WXAPIFactory.createWXAPI(this,WECHAT_APP_ID, true);
        iwxapi.registerApp(WECHAT_APP_ID);
}

分享或收藏的目标场景,通过修改scene场景值实现(下文中红色代码处为修改分享的场景)。
发送到聊天界面——WXSceneSession
发送到朋友圈——WXSceneTimeline
添加到微信收藏——WXSceneFavorite
具体的分享的用法如下,在调用封装好的方法之前别忘了下面的两句代码。

private IWXAPI api;
api = WXAPIFactory.createWXAPI(this,WECHAT_APP_ID, true);
2.3.1.1文字类型分享示例

(以下代码中做了封装,与官网中开发文档中不符的以官方文档为主)

/**
     * 分享到微信
     *
     * @param text              文字内容
     * @param isShareToTimeline false表示分享给朋友,true表示分享到朋友圈
     */
    public static void sendReqText(String text, boolean isShareToTimeline) {
        // 初始化一个WXTextObject对象
        WXTextObject textObj = new WXTextObject();
        textObj.text = text;

        // 用WXTextObject对象初始化一个WXMediaMessage对象
        WXMediaMessage msg = new WXMediaMessage();
        msg.mediaObject = textObj;
        // 发送文本类型的消息时,title字段不起作用
        // msg.title = "Will be ignored";
        msg.description = text;

        // 构造一个Req
        SendMessageToWX.Req req = new SendMessageToWX.Req();
        req.transaction = buildTransaction("text"); // transaction字段用于唯一标识一个请求
        req.message = msg;
//要分享给好友还是分享到朋友圈
        req.scene = isShareToTimeline ? SendMessageToWX.Req.WXSceneTimeline : SendMessageToWX.Req.WXSceneSession;

        // 调用api接口发送数据到微信
        api.sendReq(req);
    }
2.3.1.2图片类型分享示例

(以下代码中做了封装,与官网中开发文档中不符的以官方文档为主)

/**
     * 发送图片到微信
     *
     * @param context           上下文
     * @param index             索引。0:表示Bitmap文件;1:表示手机本地图片;2:表示网络图片(图片的URL)
     * @param isShareToTimeline false表示分享给朋友,true表示分享到朋友圈
     */
    public static void sendReqImg(Context context, int index, boolean isShareToTimeline) {
        switch (index) {
            case 0: {
                Bitmap bmp = BitmapFactory.decodeResource(context.getResources(), R.mipmap.welcome);
                WXImageObject imgObj = new WXImageObject(bmp);

                WXMediaMessage msg = new WXMediaMessage();
                msg.mediaObject = imgObj;

                Bitmap thumbBmp = Bitmap.createScaledBitmap(bmp, THUMB_SIZE, THUMB_SIZE, true);
                bmp.recycle();
                msg.thumbData = Util.bmpToByteArray(thumbBmp, true);  // 设置缩略图

                SendMessageToWX.Req req = new SendMessageToWX.Req();
                req.transaction = buildTransaction("img");
                req.message = msg;
                //要分享给好友还是分享到朋友圈
                req.scene = isShareToTimeline ? SendMessageToWX.Req.WXSceneTimeline : SendMessageToWX.Req.WXSceneSession;
                api.sendReq(req);

                break;
            }
            case 1: {
                String path = SDCARD_ROOT + "/test.png";
                File file = new File(path);
                if (!file.exists()) {
                    String tip = "图片文件不存在";
                    Toast.makeText(context, tip + " path = " + path, Toast.LENGTH_LONG).show();
                    break;
                }

                WXImageObject imgObj = new WXImageObject();
                imgObj.setImagePath(path);

                WXMediaMessage msg = new WXMediaMessage();
                msg.mediaObject = imgObj;

                Bitmap bmp = BitmapFactory.decodeFile(path);
                Bitmap thumbBmp = Bitmap.createScaledBitmap(bmp, THUMB_SIZE, THUMB_SIZE, true);
                bmp.recycle();
                msg.thumbData = Util.bmpToByteArray(thumbBmp, true);

                SendMessageToWX.Req req = new SendMessageToWX.Req();
                req.transaction = buildTransaction("img");
                req.message = msg;
                //要分享给好友还是分享到朋友圈
                req.scene = isShareToTimeline ? SendMessageToWX.Req.WXSceneTimeline : SendMessageToWX.Req.WXSceneSession;
                api.sendReq(req);
                break;
            }
            case 2: {
                String url = "http://weixin.qq.com/zh_CN/htmledition/images/weixin/weixin_logo0d1938.png";

                try {
                    WXImageObject imgObj = new WXImageObject();
                    imgObj.imageUrl = url;

                    WXMediaMessage msg = new WXMediaMessage();
                    msg.mediaObject = imgObj;

                    Bitmap bmp = BitmapFactory.decodeStream(new URL(url).openStream());
                    Bitmap thumbBmp = Bitmap.createScaledBitmap(bmp, THUMB_SIZE, THUMB_SIZE, true);
                    bmp.recycle();
                    msg.thumbData = Util.bmpToByteArray(thumbBmp, true);

                    SendMessageToWX.Req req = new SendMessageToWX.Req();
                    req.transaction = buildTransaction("img");
                    req.message = msg;
                    //要分享给好友还是分享到朋友圈
                    req.scene = isShareToTimeline ? SendMessageToWX.Req.WXSceneTimeline : SendMessageToWX.Req.WXSceneSession;
                    api.sendReq(req);
                } catch (Exception e) {
                    e.printStackTrace();
                }

                break;
            }
            default:
                break;
        }
    }
2.3.1.3音乐类型分享示例

(以下代码中做了封装,与官网中开发文档中不符的以官方文档为主)

/**
     * 分享音乐到微信
     *
     * @param context           上下文
     * @param index             索引。0:表示发送音乐url;1表示发送低带宽音乐url
     * @param musicUrl          音乐的URL
     * @param title             标题
     * @param description       描述
     * @param isShareToTimeline false表示分享给朋友,true表示分享到朋友圈
     */
    public static void sendReqMusic(Context context, int index, String musicUrl, String title, String description, boolean isShareToTimeline) {
        switch (index) {
            case 0: {
                WXMusicObject music = new WXMusicObject();
                music.musicUrl = musicUrl;

                WXMediaMessage msg = new WXMediaMessage();
                msg.mediaObject = music;
                msg.title = title;
                msg.description = description;

                Bitmap thumb = BitmapFactory.decodeResource(context.getResources(), R.mipmap.ic_launcher);
                msg.thumbData = Util.bmpToByteArray(thumb, true);

                SendMessageToWX.Req req = new SendMessageToWX.Req();
                req.transaction = buildTransaction("music");
                req.message = msg;
                //要分享给好友还是分享到朋友圈
                req.scene = isShareToTimeline ? SendMessageToWX.Req.WXSceneTimeline : SendMessageToWX.Req.WXSceneSession;
                api.sendReq(req);
                break;
            }
            case 1: {
                WXMusicObject music = new WXMusicObject();
                music.musicLowBandUrl = musicUrl;

                WXMediaMessage msg = new WXMediaMessage();
                msg.mediaObject = music;
                msg.title = title;
                msg.description = description;

                Bitmap thumb = BitmapFactory.decodeResource(context.getResources(), R.mipmap.ic_launcher);
                msg.thumbData = Util.bmpToByteArray(thumb, true);

                SendMessageToWX.Req req = new SendMessageToWX.Req();
                req.transaction = buildTransaction("music");
                req.message = msg;
//要分享给好友还是分享到朋友圈
                req.scene = isShareToTimeline ? SendMessageToWX.Req.WXSceneTimeline : SendMessageToWX.Req.WXSceneSession;
                api.sendReq(req);
                break;
            }
            default:
                break;
        }
    }
2.3.1.4视频类型分享示例

(以下代码中做了封装,与官网中开发文档中不符的以官方文档为主)

/**
     * 分享视频到微信
     *
     * @param context           上下文
     * @param index             索引。0:表示发送视频url;1:表示发送低带宽视频url
     * @param title             标题
     * @param description       描述
     * @param isShareToTimeline false表示分享给朋友,true表示分享到朋友圈
     */
    public static void sendReqVideo(Context context, int index, String VideoUrl, String title, String description, boolean isShareToTimeline) {
        switch (index) {
            case 0: {
                WXVideoObject video = new WXVideoObject();
                video.videoUrl = VideoUrl;

                WXMediaMessage msg = new WXMediaMessage(video);
                msg.title = title;
                msg.description = description;
                Bitmap thumb = BitmapFactory.decodeResource(context.getResources(), R.mipmap.ic_launcher);
                msg.thumbData = Util.bmpToByteArray(thumb, true);

                SendMessageToWX.Req req = new SendMessageToWX.Req();
                req.transaction = buildTransaction("video");
                req.message = msg;
//要分享给好友还是分享到朋友圈
                req.scene = isShareToTimeline ? SendMessageToWX.Req.WXSceneTimeline : SendMessageToWX.Req.WXSceneSession;
                api.sendReq(req);
                break;
            }
            case 1: {
                WXVideoObject video = new WXVideoObject();
                video.videoLowBandUrl = VideoUrl;

                WXMediaMessage msg = new WXMediaMessage(video);
                msg.title = title;
                msg.description = description;

                SendMessageToWX.Req req = new SendMessageToWX.Req();
                req.transaction = buildTransaction("video");
                req.message = msg;
                //要分享给好友还是分享到朋友圈
                req.scene = isShareToTimeline ? SendMessageToWX.Req.WXSceneTimeline : SendMessageToWX.Req.WXSceneSession;
                api.sendReq(req);
                break;
            }
            default:
                break;
        }
    }
2.3.1.5网页类型分享示例

(以下代码中做了封装,与官网中开发文档中不符的以官方文档为主)

/**
     * 分享网址到微信
     *
     * @param context           上下文
     * @param webUrl            要分享的网址
     * @param title             标题
     * @param description       描述
     * @param isShareToTimeline false表示分享给朋友,true表示分享到朋友圈
     */
    public static void sendReqWeb(Context context, String webUrl, String title, String description, boolean isShareToTimeline) {
        WXWebpageObject webpage = new WXWebpageObject();
        webpage.webpageUrl = webUrl;
        WXMediaMessage msg = new WXMediaMessage(webpage);
        msg.title = title;
        msg.description = description;
        Bitmap thumb = BitmapFactory.decodeResource(context.getResources(), R.mipmap.ic_launcher);
        msg.thumbData = Util.bmpToByteArray(thumb, true);

        SendMessageToWX.Req req = new SendMessageToWX.Req();
        req.transaction = buildTransaction("webpage");
        req.message = msg;
//要分享给好友还是分享到朋友圈
        req.scene = isShareToTimeline ? SendMessageToWX.Req.WXSceneTimeline : SendMessageToWX.Req.WXSceneSession;
        api.sendReq(req);
    }

这样只要正确调用了上面的方法基本也就分享成功了,但是这里并不完善,因为分享完毕返回我们的app时微信还会返回给我们的app一些数据,来表示分享成功、失败或者取消的状态。但是这并不影响app的使用,具体的回调函数我们在下文中再做详解。


2.3.2、使用微信登录

使用微信登录会有三种情况:

1、 用户手机上没有微信,那么就提示没有微信,并引导用户下载(官方说法);
2、 用户手机上有微信,但是没有登录,那么需要用户使用账号密码登录;
3、 用户手机上有微信,并且已登录,那么只需要用户点击授权按钮即可;

这里会涉及到许多东西,我们先大概看一下整个请求微信登陆的过程。(这里也是我根据官方的文档然后自己的理解来的,如有错误纰漏之处还请指出)

微信集成

注: 实线代表客户端请求客户端或者服务端
虚线代表服务端相应客户端的请求

0、 首先,用户偷懒不想注册想使用微信的账号密码登录(额,好吧);
1、 用户在app中点击“微信登录”按钮,我们的app这时需要请求微信;
2、 集成好的app去调用微信,微信给出相应(开始提到的三种情况);
3、 用户下载好后,登录后者直接授权后,提交结果给微信服务器;
4、 微信服务器根据结果返回临时code(新版的jar包中返回的code名称改为了token,但实际仍为code的值,使用方法一致);
5、 App根据临时的code、AppID以及AppSecret换取微信的access_token。一同返回的还有refresh_token,因为access_token是有有效期的,过期后可以使用refresh_token进行刷新。但是refresh_token也是有有效期的,一般是30天,这个过期了就需要用户重新进行授权了;
6、 微信服务器响应,返回access_token等信息;
7、 根据得到的access_token可以拿到用户的基本信息,如下:

  • openid 普通用户的标识,对当前开发者帐号唯一
  • nickname 普通用户昵称
  • sex 普通用户性别,1为男性,2为女性
  • province 普通用户个人资料填写的省份
  • city 普通用户个人资料填写的城市
  • country 国家,如中国为CN
  • headimgurl 用户头像,最后一个数值代表正方形头像大小(有0、46、64、96、132数值可选,0代表640*640正方形头像),用户没有头像时该项为空
  • privilege 用户特权信息,json数组,如微信沃卡用户为(chinaunicom)
  • unionid 用户统一标识。针对一个微信开放平台帐号下的应用,同一用户的unionid是唯一的。;

到此,微信登录也就明朗了,代码就不必贴了吧,请参考微信的官方文档,剩下文章稍后完善。

2016-10-11 15:19:29 L18270919464 阅读数 18970
  • 自己开发一套微信支付接口(SDK)-微信开发15(PHP)

    会员免费看,http://edu.csdn.net/lecturer/842 边栏可办理会员卡。自己开发一套微信支付接口(SDK)是子恒老师《子恒说微信开发》视频教程的第15部。详细讲解了用php开发一套自己的微信支付接口。内容包含微信支付开发思路,基础类开发,微信支付接口应用,公众号发红包,企业付款等等。欢迎反馈,微信号:QQ68183131

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

微信公众平台开发:接入JS-SDK和实现分享功能

一、本文是实现微信公众号自定义的分享功能开发,也是亲自实践实现该功的一些总结体会。
首先贴上微信JS-SDK说明文档地址:http://mp.weixin.qq.com/wiki/7/aaa137b55fb2e0456bf8dd9148dd613f.html
其次,实现该功能分为四个步骤:
1. 绑定域名,先登录微信公众平台进入“公众号设置”的“功能设置”里填写“JS接口安全域名”;
2. 引入JS文件,在需要调用JS接口的页面引入JS文件,(支持https):http://res.wx.qq.com/open/js/jweixin-1.0.0.js
3. 通过config接口注入权限验证配置,所有需要使用JS-SDK的页面必须先注入配置信息,否则将无法调用(同一个url仅需调用一次,对于变化url的SPA的web app可在每次url变化时进行调用);
4. 通过ready接口处理成功验证。

       ![这里写图片描述](http://img.blog.csdn.net/20161011143315576)
 其中最重要的就是第三步,获取config配置的签名signature ,这里着重描述,如下:
 wx.config({
    debug: true, // 开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。
    appId: '', // 必填,公众号的唯一标识
    timestamp: , // 必填,生成签名的时间戳
    nonceStr: '', // 必填,生成签名的随机串
    signature: '',// 必填,签名,见附录1
    jsApiList: [] // 必填,需要使用的JS接口列表,所有JS接口列表见附录2
});

贴上微信 JS 接口签名校验工具

> http://mp.weixin.qq.com/debug/cgi-bin/sandbox?t=jsapisign

二、实例说明
1. 前端页面share.html

<!DOCTYPE html>
<head>
    <title>微信js分享接口</title>
    <meta charset="UTF-8">
    <script src="http://res.wx.qq.com/open/js/jweixin-1.0.0.js"></script>
    <script src="http://libs.baidu.com/jquery/1.2.3/jquery.min.js"></script>
</head>
<body>
测试测试测试
<script>
    $(document).ready(function(){
        initPage();
    });
    function initPage() {
        alert(window.location.href);/***用于获得当前连接url用**/
        /***用户点击分享到微信圈后加载接口接口*******/
        $.post("http://xxxxxxx.xxxxx.xxx/demo/wm/share.do",{"url":window.location.href},function(data,status){
            data=eval("("+data+")");
            console.log(data.appid+" "+data.timestamp+" "+data.nonceStr+" "+data.signature);
            wx.config({
                debug: true,
                appId: data.appid,
                timestamp:data.timestamp,
                nonceStr:data.nonceStr,
                signature:data.signature,
                jsApiList: [
                    'checkJsApi',
                    'onMenuShareTimeline',
                    'hideOptionMenu',
                ]
            });
            var shareTitle = "一起分享吧!";
            var shareImg = "http://imgsrc.baidu.com/baike/pic/item/509b9fcb7bf335ab52664fdb.jpg";
            wx.ready(function(){
                alert("准备分享");
                wx.onMenuShareTimeline({
                    title : shareTitle, // 分享标题
                    link : '', // 分享链接
                    imgUrl : shareImg, // 分享图标
                    success : function() {
                        // 用户确认分享后执行的回调函数
                        alert("分享成功");
                    },
                    cancel : function() {
                        // 用户取消分享后执行的回调函数
                        alert("分享取消");
                    }
                });
                //wx.hideOptionMenu();/***隐藏分享菜单****/
            });
        });
    }
</script>
</body>
</html>
  1. 后台处理请求
    WeixinController.java
    @RequestMapping(value = "/share", method = RequestMethod.POST)
    @ResponseBody
    public Map<String, String> share(String url) throws Exception {
        Map<String, String> ret = new HashMap<String, String>();
        String jsapi_ticket = WeixinUtil.getJsapiTicket();
        String timestamp = Long.toString(System.currentTimeMillis() / 1000);
        String nonceStr = UUID.randomUUID().toString();
        String signature = SignUtil.getSignature(
            jsapi_ticket, nonceStr, timestamp,
            url);
        ret.put("url", url);
        ret.put("jsapi_ticket", jsapi_ticket);
        ret.put("nonceStr", nonceStr);
        ret.put("timestamp", timestamp);
        ret.put("signature", signature);
        ret.put("appid", "wxc6599d2c37b5e478");
        return ret;
    }

3.获取accessToken

    /**
     * 获取accessToken
     * 
     * @return
     * @throws ParseException
     * @throws IOException
     */
    public static AccessToken getAccessToken() throws ParseException, IOException {
        AccessToken token = new AccessToken();
        String url = ACCESS_TOKEN_URL.replace("APPID", APPID).replace("APPSECRET", APPSECRET);
        JSONObject jsonObject = doGetStr(url);
        if (jsonObject != null) {
            token.setToken(jsonObject.getString("access_token"));
            token.setExpiresIn(jsonObject.getInt("expires_in"));
        }
        return token;
    }

4.获取jsapi_ticket

    /**
     * 
     * 获取jsapi_ticket
     * 
     * @return
     * @throws IOException
     * @throws ParseException
     */
    public static String getJsapiTicket() throws ParseException, IOException {
        AccessToken token = WeixinUtil.getAccessToken();
        String url = JSAPI_TICKET.replace("ACCESS_TOKEN", token.getToken());
        JSONObject jsonObject = doGetStr(url);
        String jsapi_ticket = null;
        if (jsonObject != null) {
            jsapi_ticket = jsonObject.getString("ticket");
        }
        return jsapi_ticket;
    }

5.获取签名
SignUtil .java

import java.security.MessageDigest;

public class SignUtil {

    /**
     * 获得分享链接的签名。
     * @param ticket
     * @param nonceStr
     * @param timeStamp
     * @param url
     * @return
     * @throws Exception
     */
    public static String getSignature(String ticket, String nonceStr, String timeStamp, String url) throws Exception {
        String sKey = "jsapi_ticket=" + ticket
                + "&noncestr=" + nonceStr + "&timestamp=" + timeStamp
                + "&url=" + url;
        System.out.println(sKey);
        return getSignature(sKey);
    }


 /**
     * 验证签名。
     * 
     * @param signature
     * @param timestamp
     * @param nonce
     * @return
     */
    public static String getSignature(String sKey) throws Exception {
        String ciphertext = null;
        MessageDigest md = MessageDigest.getInstance("SHA-1");
        byte[] digest = md.digest(sKey.toString().getBytes());
        ciphertext = byteToStr(digest);
        return ciphertext.toLowerCase();
    }

 /** 
     * 将字节数组转换为十六进制字符串 
     *  
     * @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;  
    }
}

以上是大部分代码,稍加修改就可实现
三、注意要点
1.invalid signature签名错误问题
首先需确认签名算法正确,可用 http://mp.weixin.qq.com/debug/cgi-bin/sandbox?t=jsapisign 页面工具进行校验。也就是你自己后台生成签名要和微信校验算法生成的签名一致才可以(可能大小写不同)。

1.1是否获取到需要填充字段的值
`console.log(data.appid+" "+data.timestamp+" "+data.nonceStr+" "+data.signature);`
1.2确认展示页面config接口注入权限验证配置文件对应字段是否一致
```
wx.config({
               debug: true,
               appId: data.appid,
               **timestamp:data**.**timestamp**,
               **nonceStr:data**.**nonceStr**,
               **signature:data**.**signature**,
               jsApiList: [
                   'checkJsApi',
                   'onMenuShareTimeline',
                   'hideOptionMenu',
               ]
           });
```
1.3确认url是页面完整的url(请在当前页面alert(location.href.split('#')[0])确认),包括'http(s)://'部分,以及'?'后面的参数部分,但不包括'#'hash后面的部分。记住签名用的url必须是调用JS接口页面的完整URL。

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

2.虽然是自定义的分享接口,但是只有当你用微信客户端打开,在最上面右边的 “分享到朋友圈”按钮按的时候效果才会出来。

wx.ready(function(){

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

3.根据自己的需求修改下面的内容,就可实现分享功能
获取“分享到朋友圈”按钮点击状态及自定义分享内容接口

wx.onMenuShareTimeline({
    title: '', // 分享标题
    link: '', // 分享链接
    imgUrl: '', // 分享图标
    success: function () { 
        // 用户确认分享后执行的回调函数
    },
    cancel: function () { 
        // 用户取消分享后执行的回调函数
    }
});

获取“分享给朋友”按钮点击状态及自定义分享内容接口

wx.onMenuShareAppMessage({
    title: '', // 分享标题
    desc: '', // 分享描述
    link: '', // 分享链接
    imgUrl: '', // 分享图标
    type: '', // 分享类型,music、video或link,不填默认为link
    dataUrl: '', // 如果type是music或video,则要提供数据链接,默认为空
    success: function () { 
        // 用户确认分享后执行的回调函数
    },
    cancel: function () { 
        // 用户取消分享后执行的回调函数
    }
});

4.确保一定缓存access_token和jsapi_ticket。由于使用的是微信测试账号所以没有做这方面的优化

以上是全部内容,本人只是实现基本功能,如有问题请指正

2016-03-01 16:26:16 violetjack0808 阅读数 3190
  • 自己开发一套微信支付接口(SDK)-微信开发15(PHP)

    会员免费看,http://edu.csdn.net/lecturer/842 边栏可办理会员卡。自己开发一套微信支付接口(SDK)是子恒老师《子恒说微信开发》视频教程的第15部。详细讲解了用php开发一套自己的微信支付接口。内容包含微信支付开发思路,基础类开发,微信支付接口应用,公众号发红包,企业付款等等。欢迎反馈,微信号:QQ68183131

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

首先说一句,微信SDK是我见过最坑的sdk,文档写的很简略,导致开发者走了好多弯路。

好了,说下实现微信开发接入的步骤

0. 附上demo

  为了便于理解,附上测试demo和生成的APK。

  DEMO下载地址

1. 申请微信开发平台账号、申请appID

  在微信开放平台申请账号,登录后到管理中心创建项目,我这里是Android项目,所以这里是创建移动项目。

  第一步:填应用信息上传应用缩略图,这个随意传。

  第二步:官网随便填(当时填了百度都没事),然后应用平台选择Android,特别注意包名要和需要开发的包名是完全一致的(如果不知道在Manifest中找),而签名则需要通过你KeyStone来决定(请看第二点)。

  第三步:提交审核,只有通过审核后你才能拿到AppID和AppSecret来开发,审核时间挺久的,耐心等待。

2. 签名生成与使用

  2.1 签名生成工具

    到微信开放平台的资源中心去下载签名生成工具并安装到测试手机上,(链接:签名生成工具

  2.2 对测试应用进行签名

    必须始终使用同一个KeyStore来签名。因为签名生成工具是通过应用的包名找到应用的KeyStore,以此来生成签名的。假如更改了KeyStore必须在重新生成签名并更新到微信开放平台。

    具体签名方法可以看blog(构建类型要选择release):Android Studio系列-签名打包

  2.3 安装签名过的APK,并使用签名生成工具生成签名。

  2.4 将生成的签名填在微信开放平台的应用签名中。

3. 实现过程

  3.1 下载jar包并导入

    下载地址:微信开放平台资源中心

  3.2 WXEntryActivity

    在包名下面创建wxapi的包,并在wxapi的包中创建WXEntryActivity继承Activity,实现IWXAPIEventHandler接口,最后在Manifest中设置Activity的exported属性为true。这条很重要,如果不是"包名.wxapi.WXEntryActivity"的路径,就获取不到返回值。下面的这个Activity的简单实现。

public class WXEntryActivity extends Activity implements IWXAPIEventHandler {
    // IWXAPI 是第三方app和微信通信的openapi接口
    private IWXAPI api;
    private static final String APP_ID = "wx5f30e72504c5d0c2";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        api = WXAPIFactory.createWXAPI(this, APP_ID, false);
        api.handleIntent(getIntent(), this);
        super.onCreate(savedInstanceState);
    }

    @Override
    public void onResp(BaseResp resp) {
        Toast.makeText(this, "errCode = " + resp.errCode, Toast.LENGTH_LONG).show();
        switch (resp.errCode) {
            case BaseResp.ErrCode.ERR_OK:
                //分享成功
                break;
            case BaseResp.ErrCode.ERR_USER_CANCEL:
                //分享取消
                break;
            case BaseResp.ErrCode.ERR_AUTH_DENIED:
                //分享拒绝
                break;
        }
        finish();
    }

    @Override
    public void onReq(BaseReq arg0) {

    }
}
     别忘了Manifest的exported属性

<activity
    android:name=".wxapi.WXEntryActivity"
    android:exported="true" />
    这个Activity出现的逻辑是:MainActivity --发送请求--> 微信分享界面 --退出该界面--> WXEntryActivity

    只有跳转到微信进行过操作后才会跳转到这个Activity。

  3.3 MainActivity

    我在这个类中发送了分享图片和文本到朋友圈的请求。

public class MainActivity extends Activity {

    private IWXAPI wxApi;
    private static final String APP_ID = "wx5f30e72504c5d0c2";
    private static final int THUMB_SIZE = 100;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        // 实例化
        wxApi = WXAPIFactory.createWXAPI(this, APP_ID);
        wxApi.registerApp(APP_ID);
        findViewById(R.id.btnImage).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                new AsyncTask<Void, Void, Void>() {
                    @Override
                    protected Void doInBackground(Void... params) {
                        sendImageToWX();
                        return null;
                    }
                }.execute();
            }
        });
        findViewById(R.id.btnText).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                sendTextToWX();
            }
        });
    }

    /**
     * 分享图片到微信朋友圈
     */
    private void sendImageToWX() {
        Bitmap bmp = getUrlBitmap();
        if (bmp != null) {
            WXImageObject imgObj = new WXImageObject(bmp);
            Bitmap thumbBmp = Bitmap.createScaledBitmap(bmp, THUMB_SIZE, THUMB_SIZE, true);
            bmp.recycle();

            WXMediaMessage msg = new WXMediaMessage();
            msg.mediaObject = imgObj;
            msg.thumbData = bmpToByteArray(thumbBmp, true);  // 设置缩略图

            SendMessageToWX.Req req = new SendMessageToWX.Req();
            req.transaction = buildTransaction("img");
            req.message = msg;
            req.scene = SendMessageToWX.Req.WXSceneTimeline;//发送到朋友圈
//            req.scene = SendMessageToWX.Req.WXSceneSession;//发送给微信好友
            wxApi.sendReq(req);
        }
    }

    /**
     * 获取图片
     *
     * @return
     */
    private Bitmap getUrlBitmap() {
        try {
            URL url = new URL("http://b.hiphotos.baidu.com/image/pic/item/fd039245d688d43f76b17dd4781ed21b0ef43bf8.jpg");
            Bitmap bitmap = BitmapFactory.decodeStream(url.openConnection().getInputStream());
            if (bitmap.getByteCount() > 4096000) {
                BitmapFactory.Options options = new BitmapFactory.Options();
                options.inSampleSize = bitmap.getByteCount() / 4096000;//缩放比例
                options.inJustDecodeBounds = false;
                bitmap = BitmapFactory.decodeStream(url.openConnection().getInputStream(), null, options);
            }
            return bitmap;
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    /**
     * 分享文本到朋友圈
     */
    private void sendTextToWX() {
        String text = "这是一段测试文本";
        // 初始化一个WXTextObject对象
        WXTextObject textObj = new WXTextObject();
        textObj.text = text;

        // 用WXTextObject对象初始化一个WXMediaMessage对象
        WXMediaMessage msg = new WXMediaMessage();
        msg.mediaObject = textObj;
        msg.description = text;

        // 构造一个Req
        SendMessageToWX.Req req = new SendMessageToWX.Req();
        req.transaction = buildTransaction("text"); // transaction字段用于唯一标识一个请求
        req.message = msg;
        req.scene = SendMessageToWX.Req.WXSceneTimeline;
//        req.scene = SendMessageToWX.Req.WXSceneSession;//发送给微信好友

        // 调用api接口发送数据到微信
        wxApi.sendReq(req);
    }

    private String buildTransaction(final String type) {
        return (type == null) ? String.valueOf(System.currentTimeMillis()) : type + System.currentTimeMillis();
    }

    private byte[] bmpToByteArray(Bitmap bmp, boolean needRecycle) {
        ByteArrayOutputStream output = new ByteArrayOutputStream();
        bmp.compress(Bitmap.CompressFormat.PNG, 100, output);
        if (needRecycle) {
            bmp.recycle();
        }
        byte[] result = output.toByteArray();
        try {
            output.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return result;
    }
}
    到此就可以实现微信的分享功能。

4. 微信SDK Sample的使用

  肯定会有同学和我遇到同样的问题,为什么微信提供的demo无法分享成功。事实是微信开发文档忘了告诉我们需要在运行demo之前将开发工具的Debug.keyStore换成它提供的KeyStore。KeyStore文件可以在SDK的demo中找到。

  由于是Eclipse项目,附上Eclipse修改debug.keystore的路径:Windows->Perferences->Android:Build->Custom debug keystore

  PS:发现SDK提供的demo中有许多分享失败的,暂时还不明真相。另外吐槽下,微信的SDK文档水平简直醉了。




2019-01-25 11:34:12 Z875983491 阅读数 534
  • 自己开发一套微信支付接口(SDK)-微信开发15(PHP)

    会员免费看,http://edu.csdn.net/lecturer/842 边栏可办理会员卡。自己开发一套微信支付接口(SDK)是子恒老师《子恒说微信开发》视频教程的第15部。详细讲解了用php开发一套自己的微信支付接口。内容包含微信支付开发思路,基础类开发,微信支付接口应用,公众号发红包,企业付款等等。欢迎反馈,微信号:QQ68183131

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

手机微信群控系统独立出来的微信二次开发SDK,可开发群控云控引擎,微信客服系统,快速研发微信营销工具软件、微信营销手机、微信群控云控系统、微信SCRM客服系统、微信淘宝客导购返利机器人,微信群管理机器人等!接入本SDK即可快速实现微信的二次开发,轻松开发出上述软件功能,SDK接入简单、兼容性好、拓展性强,始终支持微信官方最新版本,并定时维护升级!

微信二次开发SDK的部分API功能:

微信加好友功能API

1、导入手机通讯录

2、手机通讯录加好友

3、加指定微信群好友

4、自动通过微信好友请求

5、手机模拟定位

6、附近人加好友

7、各种账号加好友(QQ号、手机号、微信号)

8、陌陌自动回复引流加好友

9、探探自动回复引流加好友

10、摇一摇打招呼加好友

...上述这些API可开发手机微信群控系统、云控系统、微信营销手机等系列爆粉营销软件!

微信群发功能API

1、微信群发好友(文字、图片、长短视频、链接、名片)

2、微信群发群(文字、图片、长短视频、链接、名片)

3、微信群发收藏(文字、图片、长短视频、链接、名片)

...上述这些API可开发群控、云控等群发系列营销软件!

微信群管理功能API

1、入群欢迎语

2、指定群管理员

3、群管理统计(活跃度、发言数、总人数、邀请数、退出数等)

4、群管理员踢人

5、群关键词回复,群智能客服

6、建群、拉人功能接口

...上述这些API可开发微信群管家、群营销大师等系列微信群管理营销软件!

微信营销功能API

1、发朋友圈(图文、链接、长短视频)

2、发长视频到微信朋友圈

3、朋友圈点赞,按比例点赞,按数量点赞

4、发漂流瓶信息

5、智能自动回复

6、同步指定微信好友朋友圈

...这些API可开发群控、云控、营销手机等系列微信营销软件!

微信聊天对话功能API

1、微信上线通知

2、微信下线通知

3、微信新增好友通知

4、微信删除好友通知

5、微信好友发来信息通知

6、回复微信好友聊天消息

7、聊天执行结果通知

8、获取微信通讯录好友列表

9、获取群列表

10、好友请求添加好友的通知

11、获取手机客户端上微信的二维码

...这些API可开发群控、云控、微信客服系统等系列微信营销软件!

微信营销辅助工具API

1、打开微信

2、定时执行任务

3、任务执行结果通知

4、清理僵尸粉

5、清理微信空间

6、智能随机养号

7、智能抢红包服务

8、微信运动智能点赞

9、提取指定朋友圈内容

10、关注指定公众号

...这些API可辅助开发群控、云控、营销手机、微信客服系统等系列微信营销软件!

其他营销功能API

1、QQ发布说说(暂时未上线)

2、QQ群发好友、QQ群发群、QQ群发群好友(暂时未上线)

3、智能头条评论营销(暂时未上线)

...这些API可辅助开发全网营销系列软件!

没有将API功能全部写出,调用API接口有时候再写出来!SDK可按需定制!咨询请加微信tangjinjinwx

详细接口请参考http://www.yunlauncher.com/Blog/articles/119.html

2016-03-18 14:37:28 zhaixh_89 阅读数 3218
  • 自己开发一套微信支付接口(SDK)-微信开发15(PHP)

    会员免费看,http://edu.csdn.net/lecturer/842 边栏可办理会员卡。自己开发一套微信支付接口(SDK)是子恒老师《子恒说微信开发》视频教程的第15部。详细讲解了用php开发一套自己的微信支付接口。内容包含微信支付开发思路,基础类开发,微信支付接口应用,公众号发红包,企业付款等等。欢迎反馈,微信号:QQ68183131

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

    应公司项目要求,这段时间接手开始接入微信sdk,由于还未获取到微信的支付权限,所以这里只做了一下登录的记录,https://open.weixin.qq.com/cgi-bin/showdocument?action=dir_list&t=resource/res_list&verify=1&id=1417694084&token=9e8dccd0b7280c180642a80c08f21682c73e3b77&lang=zh_CN这是微信官方接入文档,看了下,感觉没什么叼用,就在网上查阅了众多资料,也是第一次接手ios代码,花了我整整三天的时间终于尘埃落定了,下面就一一做下记录。

      首先第一步,去官网下载微信sdk文件,SDK文件包括 libWeChatSDK.a,WXApi.h,WXApiObject.h 三个。下载链接:https://open.weixin.qq.com/cgi-bin/showdocument?action=dir_list&t=resource/res_list&verify=1&id=open1419319164&lang=zh_CN

     第二步:讲下载后的sdk文件libWeChatSDK.a,,WXApi.h,WXApiObject.h添加到你的工程中如下图(因为项目保密性,我就贴张官网上的图来说明问题)

(注:请使用xCode4.5及以上版本),

    第三步:微信开放平台新增了微信模块用户统计功能,便于开发者统计微信功能模块的用户使用和活跃情况。开发者需要在选中工程->build Phases->Link Binary With Libraries添加SystemConfiguration.framework,libz.dylib,libsqlite3.0.dylib,libc++.dylib库文件

    第四步:选中工程选项->info->URL Types添加"URL scheme”为你所注册的应用程序id(如下图所示)。

     第五步:在你准备使用微信终端API文件中import WXApi.h 头文件,并增加 WXApiDelegate 协议。如下:

                 

接下来开始编码了

1、要使你的程序启动后微信终端能够响应你的程序,必须在代码像微信注册你的应用id,如下:

         

2、重写AppDelegate的handleOpenURL和openURL方法,// 这个方法是用于从微信返回第三方App

      

这里提一下,刚开始做时,我在这两个函数的delegate参数给的是self,并且设置appController集成到WXApidelegate,然而并没有什么卵用,程序执行后点击确定授权不会跳转到-(void) onResp:(BaseResp*)resp函数,最后在论坛上发现有人建议直接使用你准备调用微信API所在类的对象即可,我便试了下关于果然如此。

3、接下来就开始做登录的逻辑了

-(void) goWXLogin
{
    if ([WXApi isWXAppInstalled]) {
        [self sendAuthRequest];
    }
    else{
        [self setupAlertController];
    }
}

 提示用户安装微信弹框

-(void) setupAlertController{
    UIAlertController* alert = [UIAlertController alertControllerWithTitle:@"温馨提示" message:
                                @"请先安装微信客户端" preferredStyle:UIAlertControllerStyleAlert];
    UIAlertAction *actionConfirm = [UIAlertAction actionWithTitle:@"确定" style:UIAlertActionStyleDefault handler:nil];
    [alert addAction:actionConfirm];
    //[self presentViewController :alert animated:YES completion:nil];
}

   note:
         a、目前移动应用上微信登录只提供原生的登录方式,需要用户安装微信客户端才能配合使用。
         b、对于Android应用,建议总是显示微信登录按钮,当用户手机没有安装微信客户端时,请引导用户下载安装微信客户端。
         c、对于iOS应用,考虑到iOS应用商店审核指南中的相关规定,建议开发者接入微信登录时,先检测用户手机是否已安装微信客户端(使用sdk中isWXAppInstalled函    数 ),对未安装的用户隐藏微信登录按钮,只提供其他登录方式(比如手机号注册登录、游客登录等)。

 //发送授权登录请求,这里的参数解释下 

      appid:应用唯一标识,在微信开放平台提交应用审核通过后获得

     score:应用授权作用域,如获取用户个人信息需要填写snsapi_userinfo什么是授权域

     state:用于保持请求和回调的状态,授权请求后原样带回给第三方。该参数可用于防止csrf攻击(跨站请求伪造攻击),建议第三方带上该参数,可设置为简单的随机数加  session进行校验

-(void)sendAuthRequest
{
    //构造SendAuthReq结构体
    SendAuthReq* req =[[SendAuthReq alloc ] init];
    req.scope = @"snsapi_userinfo"		;
    req.state = @"wechat_sdk_huaqianguyouxi" ;
    //第三方向微信发送一个SendAuthReq消息结构
    [WXApi sendReq:req];
}

运行返回大致为:

   appid: wxd477edab60670232
   scope: snsapi_userinfo
   state: wechat_sdk_demo

 到这里我们的应用便可以拉起微信授权界面了,在授权界面,我们点击确定之后会回调-(void) onResp:(BaseResp*)resp函数,先上代码,

-(void) onResp:(BaseResp*)resp
{
    SendAuthResp *aresp = (SendAuthResp *)resp;
    if (aresp.errCode== 0) {
        self->code = aresp.code;
        
        NSString* token = [[NSUserDefaults standardUserDefaults]objectForKey:@"access_token"];
        NSString* openId = [[NSUserDefaults standardUserDefaults]objectForKey:@"openid"];
        NSString* refreshToken = [[NSUserDefaults standardUserDefaults]objectForKey:@"refresh_token"];
        if (token && openId && refreshToken) {
            [self setUid:openId];
            [self setRefreshToken:refreshToken];
            [self checkValidToken:token uid:(NSString*)openId];
        }
        else
            [self getAccess_token];
        
    }
    else if (aresp.errCode == -2) {
        NSLog(@"用户取消登录");
    } else if (aresp.errCode == -4) {
        NSLog(@"用户拒绝登录");
    } else {
        NSLog(@"errCode = %d", aresp.errCode);
        NSLog(@"code = %@", aresp.code);
    }

}

这里的函数返回值有以下几个:

     ErrCode:错误码,ERR_OK = 0(用户同意),ERR_AUTH_DENIED = -4(用户拒绝授权)ERR_USER_CANCEL = -2(用户取消)
     code:用户换取access_token的code,仅在ErrCode为0时有效
     state:第三方程序发送时用来标识其请求的唯一性的标志,由第三方程序调用sendReq时传入,由微信终端回传,state字符串长度不能超过1K
     lang:微信客户端当前语言
     country:微信用户当前国家信息

这里我是把获取到的token保存在了本地,并没有加密,目的是为了token的有效性处理

获取了code之后可以会用官方提供的链接来获取access_token,链接为https://api.weixin.qq.com/sns/oauth2/access_token?appid=APPID&secret=SECRET&code=CODE&grant_type=authorization_code

代码如下:

//通过code获取access_token
-(void)getAccess_token
{
    NSString *url =[NSString stringWithFormat:@"https://api.weixin.qq.com/sns/oauth2/access_token?appid=%@&secret=%@&code=%@&grant_type=authorization_code",APP_ID,APP_KEY,self->code];
    
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        NSURL *zoneUrl = [NSURL URLWithString:url];
        NSString *zoneStr = [NSString stringWithContentsOfURL:zoneUrl encoding:NSUTF8StringEncoding error:nil];
        NSData *data = [zoneStr dataUsingEncoding:NSUTF8StringEncoding];
        dispatch_async(dispatch_get_main_queue(), ^{
            if (data) {
                NSDictionary *dic = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableContainers error:nil];
                NSString* token = [dic objectForKey:@"access_token"];
                NSString* openId = [dic objectForKey:@"openid"];
                NSString* refreshToken = [dic objectForKey:@"refresh_token"];
                [self setUid:openId];
                [self setRefreshToken:refreshToken];
                [self checkValidToken:token uid:(NSString*)openId];
            }
        });
    });
}

这个函数处理结果和刷新token函数的的返回值都是如下
     access_token:接口调用凭证
     expires_in:access_token接口调用凭证超时时间,单位(秒)
     refresh_token:用户刷新access_token
     openid:授权用户唯一标识
     scope:用户授权的作用域,使用逗号(,)分隔
     unionid:当且仅当该移动应用已获得该用户的userinfo授权时,才会出现该字段
程序到了这里,基本上已经可以利用微信登录到你的应用了。完整代码下载(只有登录的sdk调用,嵌入到项目中才能执行)

 

微信SDK接入

阅读数 1029

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