2015-11-12 22:44:25 u014454539 阅读数 7285
  • 微信支付开发-微信公众号开发12-微信开发php

    微信公众平台开发之微信支付开发是子恒老师《微信公众平台开发》视频教程的第12部。详细讲解了用php进行微信支付的开发。内容包含获取支付密钥,微信公众号支付开发,扫码支付,微信刷卡支付,异步处理支付结果等等。欢迎反馈,微信/QQ:68183131

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

       最近已经是第四次开发微信公众号,这一次的开发任务是完成一个微信企业号的开发, 主要是利用微信企业号进行办公管理。而其中很重要的一个功能即为本地通讯录与微信服务器上的通讯录保持同步。

       而基本的实现逻辑为:在本地数据库进行增、删、改操作以后,获得执行返回结果,如果本地操作成功,则调用微信企业号管理通讯录接口,实现对微信服务器上数据的同步操作。但是在这个基本的业务逻辑中,可能会出现微信服务器和本地数据库的数据不统一的情况,其中常见的场景为一下两种:

①本地执行数据增加操作以后,获得返回结果,正要执行微信同步操作时,网络异常,那么会出现本地数据未能同步到微信服务器上——本地存在微信服务器没有的数据。

②本地执行数据删除操作以后,获得返回结果,正要执行微信同步操作时,网络异常,那么会出现本地数据未能同步到微信服务器上——微信服务器存在本地没有的数据。

在没有通讯录异步更新功能之前,我们采取的方法,即是定期利用算法对本地数据与微信数据进行比较,执行相应同步操作,其中带来的系统消耗较大,如果数据量较大,常常出现一些差错,导致两边数据无法维护。

现在来说说微信公众号更新的异步任务接口(位置:管理通讯录—异步任务接口)。有两点说明:①主要用于本地通讯录与微信服务器通讯录的同步。②此接口为异步响应的接口,需要调用获取异步任务结果接口获取操作结果。由于是第三方微信公众号应用,则原则上用户只能在一端实现数据维护,更好的选择即是在第三方的微信应用上进行通讯录的操作,来保证两边的数据同步。


接口关键说明:

1.文件中存在、通讯录中也存在的部门,执行修改操作
2.文件中存在、通讯录中不存在的部门,执行添加操作
3.文件中不存在、通讯录中存在的部门,当部门下没有任何成员或子部门时,执行删除操作
4.CSV文件中,部门名称、部门ID、父部门ID为必填字段,部门ID必须为数字;排序为可选字段,置空或填0不修改排序

接口调用次序

通讯录更新接口提供三种更新方法:1) 增量更新成员 2)全量覆盖成员 3) 全量覆盖部门。如果企业要做到与企业号通讯录完全一致,可先调用全量覆盖部门接口,再调用全量覆盖成员接口,即可保持通讯录完全一致。


根据微信企业号的文档,我们需要实现以下四步操作:

①根据微信企业号文档规定的文档格式,将本地数据库的数据对应生成相应的CSV文件(此处贴出生成CSV文件的PHP示例代码)

/**
     * 输出csv文件
     * @param $data 上传数组
     * @param $filetype 上传文件类型(batch_user/ batch_group)
     */
    public function  outputCsvFile($data, $fileTypeName) {
        $filename = $fileTypeName.time();
        $output_url = "source/weixin_upload_room/csv_upload/".$filename.'.csv';
        $fp = fopen($output_url, 'w');
        fwrite($fp,"\xEF\xBB\xBF");
        foreach ($data as $row) {
            fputcsv($fp, $row);
        }
        fclose($fp);
        return $output_url;
    }
②调用上传临时素材文件接口(管理素材文件—上传临时素材文件)将生成的CSV文件上传到微信服务器。此处出现了本次开发的第一个难关,因为必须采用非表单上传文件,将指定路径的文件用PHP代码上传到服务器。查阅资料后发现可以使用php curl技术模拟表单上传文件,因此决定采取curl的方法,可是一直调试不成功。再后来发现curl的调用方法也是随着PHP版本的变化,发生了变化,调了两天都一直调不出结果,最后在google上找到了解决方法。

③调用全量覆盖部门接口,进行部门的更新。

④调用全量覆盖成员接口,进行成员的更新。

以下贴出全部的php

curl 模拟 https请求

<span style="font-size:18px;">/**
      * 功能:php模拟发送https post请求
      * @param $url 请求的链接
      * @param $params get请求的所带的参数
      * 参数格式为:$params = "a=b&c=d&e=f&g=" . urlencode('全仔');
     */
    function https_post($url, $params){
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);    // https请求 不验证证书和hosts
        curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE);
        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);    // 要求结果为字符串且输出到屏幕上
        curl_setopt($ch, CURLOPT_HEADER, 0); // 不要http header 加快效率
        curl_setopt($ch, CURLOPT_USERAGENT, 'Mozilla/5.0 (compatible; MSIE 5.01; Windows NT 5.0)');
        curl_setopt($ch, CURLOPT_TIMEOUT, 15);
         
        curl_setopt($ch, CURLOPT_POST, 1);  // post 提交方式
        curl_setopt($ch, CURLOPT_POSTFIELDS, $params);
         
        $output = curl_exec($ch);
        curl_close($ch);
        return $output;
    }</span>
全量覆盖部门

/**
     * 企业号通讯录数据同步:全量覆盖部门
     * 原理:将本地数据库与微信企业号全量覆盖。
     * 接口限制:应说明清楚本功能,且限制调用次数。且本功能应和全量覆盖成员同步使用!
     * @param 无
     * @return array("errcode"=>"错误码","errmsg"=>"错误信息","id"=>"微信id") 操作成功错误码为0
     */
    public function synchronous_area_to_weixin(){
        $res = $this -> db -> get('area');
        if($res -> num_rows()){
            $area_array[] = array('部门名称','部门ID','父部门ID','排序');
            foreach($res -> result_array() as $row){
                $area_array[] = array($row['name'],$row['weixin_id'],$row['parent_id'],0);
            }
        }else{
            return false;
        }
        $file_url = $this -> mytool -> outputCsvFile($area_array,'batch_group');
        $access_token = $this -> session -> userdata("access_token");
        //判断当前php版本是否支持curlfile
        if (class_exists('\CURLFile')) {
            $field = array('media' => new \CURLFile(realpath($file_url)));
        } else {
            $field = array('media' => '@' . realpath($file_url));
        }
        $media_res = $this->mytool->https_post('https://qyapi.weixin.qq.com/cgi-bin/media/upload?access_token='.$access_token['access_token'].'&type=file',$field);
        $media_res_obj = json_decode($media_res);
        if($media_res_obj -> media_id){
            $batch_group = array('media_id' => urlencode($media_res_obj -> media_id));
            $batch_group_json = urldecode(json_encode($batch_group));
            $batch_group_res = $this->mytool->https_post('https://qyapi.weixin.qq.com/cgi-bin/batch/replaceparty?access_token='.$access_token['access_token'],$batch_group_json);
            $batch_group_res_obj = json_decode($batch_group_res);
            $errmsg = $this->myweixintranslation->tranalation($batch_group_res_obj->errcode);
            $res_array = array("errcode" => $batch_group_res_obj->errcode,"errmsg" => $errmsg);
        }else{
            $errmsg = $this->myweixintranslation->tranalation($media_res_obj->errcode);
            $res_array = array("errcode" => $media_res_obj->errcode,"errmsg" => $errmsg);
        }
        return $res_array;
    }
全量覆盖成员

/**
     * 企业号通讯录数据同步:全量覆盖成员
     * 原理:将本地数据库与微信企业号全量覆盖。
     * 接口限制:应说明清楚本功能,且限制调用次数。且本功能应和全量覆盖部门同步使用!
     * @param 无
     * @return array("errcode"=>"错误码","errmsg"=>"错误信息","id"=>"微信id") 操作成功错误码为0
     */
    public function synchronous_distribution_member_to_weixin(){
        $res = $this -> db -> get('distribution_member');
        if($res -> num_rows()){
            $area_array[] = array('姓名','帐号','微信号','手机号','邮箱','所在部门','职位');
            foreach($res -> result_array() as $row){
                $area_array[] = array($row['name'],$row['weixin_id'],'',$row['phone'],$row['email'],$row['area_id'],'');
            }
        }else{
            return false;
        }
        $file_url = $this -> mytool -> outputCsvFile($area_array,'batch_user');
        //判断当前php版本是否支持curlfile
        if (class_exists('\CURLFile')) {
            $field = array('media' => new \CURLFile(realpath($file_url)));
        } else {
            $field = array('media' => '@' . realpath($file_url));
        }
        $media_res = $this->mytool->https_post('https://qyapi.weixin.qq.com/cgi-bin/media/upload?access_token='.$access_token['access_token'].'&type=file',$field);
        $media_res_obj = json_decode($media_res);
        if($media_res_obj -> media_id){
            $batch_user = array('media_id' => urlencode($media_res_obj -> media_id));
            $batch_user_json = urldecode(json_encode($batch_user));
            $batch_user_res = $this->mytool->https_post('https://qyapi.weixin.qq.com/cgi-bin/batch/replaceuser?access_token='.$access_token['access_token'],$batch_user_json);
            $batch_user_res_obj = json_decode($batch_user_res);
            $errmsg = $this->myweixintranslation->tranalation($batch_user_res_obj->errcode);
            $res_array = array("errcode" => $batch_user_res_obj->errcode,"errmsg" => $errmsg);
        }else{
            $errmsg = $this->myweixintranslation->tranalation($media_res_obj->errcode);
            $res_array = array("errcode" => $media_res_obj->errcode,"errmsg" => $errmsg);
        }
        return $res_array;
    }
更多关于微信接入、微信请求、微信细节处理的方法可详细参见我的其他博客内容。








2016-08-06 00:39:48 linxi7 阅读数 1533
  • 微信支付开发-微信公众号开发12-微信开发php

    微信公众平台开发之微信支付开发是子恒老师《微信公众平台开发》视频教程的第12部。详细讲解了用php进行微信支付的开发。内容包含获取支付密钥,微信公众号支付开发,扫码支付,微信刷卡支付,异步处理支付结果等等。欢迎反馈,微信/QQ:68183131

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

最近在练习自定义view,找了一些资料,模仿了一下微信通讯录的实现效果,首先看一下效果图:
这里写图片描述

记录下来当做笔记以备后用。
第一步:是绘制26个字母的view:
在每个构造方法中调用下面的init()方法实现画笔的初始化

private void init() {
        //去掉字母锯齿的参数
        mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        mPaint.setColor(Color.WHITE);
        // mPaint.setTypeface(Typeface.DEFAULT_BOLD);
        mPaint.setTextSize(40);//设置字母大小
    }

然后是onDraw()方法进行绘制:

@Override
    protected void onDraw(Canvas canvas) {
        //这里用来绘制背景,当字母被触摸的时候会变成灰色
        if (mTouched) {
            canvas.drawColor(0x30000000);
        }

        for (int i = 0; i < letterLength; i++) {
            String text = LETTERS[i];
            // 计算坐标
            int x = (int) (cellWidth / 2.0f - mPaint.measureText(text) / 2.0f);
            // 获取文本的高度
            Rect bounds = new Rect();// 矩形
            mPaint.getTextBounds(text, 0, text.length(), bounds);
            int textHeight = bounds.height();
            int y = (int) (cellHeight / 2.0f + textHeight / 2.0f + i* cellHeight);

            // 设置文本颜色
            mPaint.setColor(Color.BLACK);


            // 绘制文本A-Z
            canvas.drawText(text, x, y, mPaint);
        }
    }

根据注释可以清楚的知道绘制的原理,就是计算26个字母的x和y坐标,x左边不变的,y坐标规律的增加。

接下来重写onTouchEvent()方法

boolean mTouched = false;
int touchIndex = -1;

    @Override
public boolean onTouchEvent(MotionEvent event) {
        int index = -1;
        switch (event.getAction()) {
        case MotionEvent.ACTION_DOWN:
        case MotionEvent.ACTION_MOVE:
            // 获取当前触摸到的字母索引
            index = (int) (event.getY() / cellHeight);
            if (index >= 0 && index < LETTERS.length) {
                // 判断是否跟上一次触摸到的一样
            if (index != touchIndex) {

                if (listener != null) {
                                    listener.onLetterUpdate(LETTERS[index]);
                    }

                    touchIndex = index;
                }
            }
            mTouched = true;
            break;
        case MotionEvent.ACTION_UP:
            if (listener != null) {
                listener.onFinished();
            }
            touchIndex = -1;
            mTouched = false;
            break;

        default:
            break;
        }
        invalidate();

        return true;
    }

原理就是根据两个索引值,即当前按下字母的索引是否和上次的一样,如果不一样才会调用接口把字母暴露给调用方,否则如果不进行判断的话,就会导致当手指在快速索引条上移动的时候总是会弹出相同的字母。还有就是记录了一个按下的mTouched值,如果按下或者移动设置为true,否则为false。这样就可以根据是否按下来绘制背景改变颜色了。再看一下ACTION_UP事件中暴露onFinished()方法给调用方,主要是为了将弹出的字母隐藏掉。这样当手指按下的时候会弹出当前的字母,当手指抬起就会立即消失。

当view的大小发生变化时获取单元格的宽和高

@Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);
        // 获取单元格的宽和高

        cellWidth = getMeasuredWidth();

        int mHeight = getMeasuredHeight();
        cellHeight = mHeight * 1.0f / LETTERS.length;

    }

接下来就是回调接口:

    /**
     * 暴露一个字母的监听
     */
    public interface OnLetterUpdateListener {
        void onLetterUpdate(String letter);

        void onFinished();
    }

    private OnLetterUpdateListener listener;

    /**
     * 设置字母更新监听
     * 
     * @param listener
     */
    public void setListener(OnLetterUpdateListener listener) {
        this.listener = listener;
    }

以上就是快速索引条的绘制过程。

接下来看一下MainActivity.java的主要代码:

// 设置监听
bar.setListener(new OnLetterUpdateListener() {
            @Override
    public void onLetterUpdate(String letter) {
        showLetter(letter);
        // 根据字母定位ListView, 找到集合中第一个以letter为拼音首字母的对象,得到索引
        for (int i = 0; i < persons.size(); i++) {
            Person person = persons.get(i);
            String l = person.getPinyin().charAt(0) + "";
            if (TextUtils.equals(letter, l)) {
                // 匹配成功
                mMainList.setSelection(i);
                break;
            }
        }
    }

    @Override
    public void onFinished() {
        tv_center.setVisibility(View.GONE);
    }
});

这就是实现回调方法,弹出显示字母框和隐藏字母的功能。
还有一个就是对ListView中联系人拼音的第一个字母和手指此刻按下的字母进行比较,如果相等的话,就会将ListView位置定位到这个字母,也就是把该字母显示在第一个位置。

这个是显示字母的代码:

/**
* 显示字母
*/
protected void showLetter(String letter) {
    tv_center.setVisibility(View.VISIBLE);
    tv_center.setText(letter);
}

这个是对通讯录进行排序的方法:

private void fillAndSortData(ArrayList<Person> persons) {
    List<String> nameList = PhoneContactsUtils.getContactsName(this);
    // 填充数据
    for (int i = 0; i < nameList.size(); i++) {
        String name = nameList.get(i);
        persons.add(new Person(name));
    }

    // 进行排序
    Collections.sort(persons);
    }

以上就是主要的代码,还有工具类、实体类和适配器的代码没有贴出来,感觉太多了贴出来不方便阅读。实体类就是一个名字和拼音两个成员变量,并且要实现Comparable接口以便进行联系人根据字母排序。还有读取手机通讯录联系人等没什么好讲的,直接放到源码包中就好了。

源码下载地址:Android自定义view实现微信通讯录一模一样效果

2017-08-20 21:27:00 didi9310 阅读数 73
  • 微信支付开发-微信公众号开发12-微信开发php

    微信公众平台开发之微信支付开发是子恒老师《微信公众平台开发》视频教程的第12部。详细讲解了用php进行微信支付的开发。内容包含获取支付密钥,微信公众号支付开发,扫码支付,微信刷卡支付,异步处理支付结果等等。欢迎反馈,微信/QQ:68183131

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

一、本节要点

1.获取通讯录密钥

获取方式:

       登录企业微信—>管理工具—>通讯录同步助手—>开启“API接口同步”  ; 开启后,即可看到通讯录密钥,也可设置通讯录API的权限:读取或者编辑通讯录。

获取通讯录密钥的目的:

        通过企业ID(CorpId)和 通讯录密钥可以获取通讯录相关接口的使用凭证(AccessToken)。有了AccessToken,就可以使用通讯录相关接口了。

凭证的获取方式有两种(此处暂时存疑,以待勘误)

通讯录AccessToken:CorpId+通讯录密钥

其他AccessToken:CorpId+应用密钥

 

 2.json序列化

2.1序列化和反序列化的概念

  把对象转换为字节序列的过程称为对象的序列化

  把字节序列恢复为对象的过程称为对象的反序列化

2.2对象的序列化的目的

  1) 把对象的字节序列永久地保存到硬盘上,通常存放在一个文件中;
  2) 在网络上传送对象的字节序列。

2.3java序列化方式

(1)java原生序列化

(2)json序列化  

而json序列化可使用 ① json-lib

                                 ②fastJson

                                 ③gson

2.4json序列化与反序列化

这里我们采用gson来实现java对象的序列化,需要引入  gson-2.7.jar 包。

(1)简单的Jason

{
   "userid": "zhangsan",
   "name": "张三",
   "english_name": "jackzhang"
 
}

 

使用gson.toJson(user)即可将user对象顺序转成json字符串,如下

    Gson gson = new Gson(); 
    String jsonU1 =gson.toJson(user); 

(2)带数组的json

将department设为list<Integer>类型即可

{
   "userid": "zhangsan",
   "name": "张三",
   "english_name": "jackzhang"
   "department": [1, 2],

}

 

(3)包含子对象的json

以下代码为文本消息的json字符串,将text属性类型设为Text,Text类中包含content属性。然后使用 gson.toJson(user) 

{
   "msgtype" : "text",
   "agentid" : 1,
   "text" : {
       "content" : "你的快递已到,请携带工卡前往邮件中心领取。\n出发前可查看<a href=\"http://work.weixin.qq.com\">邮件中心视频实况</a>,聪明避开排队。"
   },
 
}

 

关于Json序列化,读者在 Java企业微信开发_05_消息推送之发送消息 这一节会有更深刻的理解,这一周将会继续总结。

 

3.企业微信开发思路

企业微信的开发大体可分为以下几步:

(1)封装实体类

       参考官方文档给出的请求包、回包(即响应包),封装对应的java实体类。

(2)java对象的序列化

       将java对象序列化为json格式的字符串

(3)获取AccessToken,拼接请求接口url

 

(4)调用接口发送http请求

封装好http请求方法:httpRequest(请求url, 请求方法POST/GET, 请求包);  

 1 /**
 2      * 1.发起https请求并获取结果 
 3      *  
 4      * @param requestUrl 请求地址 
 5      * @param requestMethod 请求方式(GET、POST) 
 6      * @param outputStr 提交的数据 
 7      * @return JSONObject(通过JSONObject.get(key)的方式获取json对象的属性值) 
 8      */  
 9     public static JSONObject httpRequest(String requestUrl, String requestMethod, String outputStr) {  
10         JSONObject jsonObject = null;  
11         StringBuffer buffer = new StringBuffer();  
12         try {  
13             // 创建SSLContext对象,并使用我们指定的信任管理器初始化  
14             TrustManager[] tm = { new MyX509TrustManager() };  
15             SSLContext sslContext = SSLContext.getInstance("SSL", "SunJSSE");  
16             sslContext.init(null, tm, new java.security.SecureRandom());  
17             // 从上述SSLContext对象中得到SSLSocketFactory对象  
18             SSLSocketFactory ssf = sslContext.getSocketFactory();  
19 
20             URL url = new URL(requestUrl);  
21             HttpsURLConnection httpUrlConn = (HttpsURLConnection) url.openConnection();  
22             httpUrlConn.setSSLSocketFactory(ssf);  
23 
24             httpUrlConn.setDoOutput(true);  
25             httpUrlConn.setDoInput(true);  
26             httpUrlConn.setUseCaches(false);  
27             // 设置请求方式(GET/POST)  
28             httpUrlConn.setRequestMethod(requestMethod);  
29 
30             if ("GET".equalsIgnoreCase(requestMethod))  
31                 httpUrlConn.connect();  
32 
33             // 当有数据需要提交时  
34             if (null != outputStr) {  
35                 OutputStream outputStream = httpUrlConn.getOutputStream();  
36                 // 注意编码格式,防止中文乱码  
37                 outputStream.write(outputStr.getBytes("UTF-8"));  
38                 outputStream.close();  
39             }  
40 
41             // 将返回的输入流转换成字符串  
42             InputStream inputStream = httpUrlConn.getInputStream();  
43             InputStreamReader inputStreamReader = new InputStreamReader(inputStream, "utf-8");  
44             BufferedReader bufferedReader = new BufferedReader(inputStreamReader);  
45 
46             String str = null;  
47             while ((str = bufferedReader.readLine()) != null) {  
48                 buffer.append(str);  
49             }  
50             bufferedReader.close();  
51             inputStreamReader.close();  
52             // 释放资源  
53             inputStream.close();  
54             inputStream = null;  
55             httpUrlConn.disconnect();  
56             jsonObject = JSONObject.fromObject(buffer.toString());  
57         } catch (ConnectException ce) {  
58             log.error("Weixin server connection timed out.");  
59         } catch (Exception e) {  
60             log.error("https request error:{}", e);  
61         }  
62         return jsonObject;  
63     }  
View Code

 

二、代码实现

相关jar包:

 

2.1 工具类之微信参数封装类——WeiXinParamesUtil.java

此类封装了微信的相关参数,如企业id、应用凭证、通讯录凭证等。封装起来更易维护,实现一处修改多处改变。

 1 package com.ray.util;
 2 /**
 3  * 微信参数
 4  * @author shirayner
 5  *
 6  */
 7 public class WeiXinParamesUtil {
 8     //1.微信参数
 9     //token
10     public final static String token = "ray";
11     // encodingAESKey
12     public final static String encodingAESKey = "z2W9lyOAR1XjY8mopEmiSqib0TlBZzCFiCLp6IdS2Iv";
13     //企业ID
14     public final static String corpId = "ww92f5da92bb24696e";
15 
16     //应用的凭证密钥
17     public final static String agentSecret = "I73733veH3uCs6H_ijPvIq0skjTaOePsFF4MyCEi3Ag";
18     //通讯录秘钥
19     public final static String contactsSecret = "1m_9XP62YrXjSiYtL5ThbexiLVWBThukiK5sH7wm1TM";
20 
21     //企业应用的id,整型。可在应用的设置页面查看
22     public final static int agentId = 1000002;
23 
24 }
View Code

 

2.2 工具类之微信辅助类——WeiXinUtil.java

此类封装了http请求、https请求、获取accessToken的方法

  1 package com.ray.util;
  2 
  3 import java.io.BufferedReader;
  4 import java.io.InputStream;
  5 import java.io.InputStreamReader;
  6 import java.io.OutputStream;
  7 import java.net.ConnectException;
  8 import java.net.HttpURLConnection;
  9 import java.net.URL;
 10 import javax.net.ssl.HttpsURLConnection;
 11 import javax.net.ssl.SSLContext;
 12 import javax.net.ssl.SSLSocketFactory;
 13 import javax.net.ssl.TrustManager;
 14 import org.slf4j.Logger;
 15 import org.slf4j.LoggerFactory;
 16 import com.ray.pojo.AccessToken;
 17 import net.sf.json.JSONException;
 18 import net.sf.json.JSONObject;
 19 
 20 public class WeiXinUtil {
 21 
 22     private static Logger log = LoggerFactory.getLogger(WeiXinUtil.class);  
 23     //微信的请求url
 24     //获取access_token的接口地址(GET) 限200(次/天)  
 25     public final static String access_token_url = "https://qyapi.weixin.qq.com/cgi-bin/gettoken?corpid={corpId}&corpsecret={corpsecret}";  
 26 
 27 
 28 
 29     /**
 30      * 1.发起https请求并获取结果 
 31      *  
 32      * @param requestUrl 请求地址 
 33      * @param requestMethod 请求方式(GET、POST) 
 34      * @param outputStr 提交的数据 
 35      * @return JSONObject(通过JSONObject.get(key)的方式获取json对象的属性值) 
 36      */  
 37     public static JSONObject httpRequest(String requestUrl, String requestMethod, String outputStr) {  
 38         JSONObject jsonObject = null;  
 39         StringBuffer buffer = new StringBuffer();  
 40         try {  
 41             // 创建SSLContext对象,并使用我们指定的信任管理器初始化  
 42             TrustManager[] tm = { new MyX509TrustManager() };  
 43             SSLContext sslContext = SSLContext.getInstance("SSL", "SunJSSE");  
 44             sslContext.init(null, tm, new java.security.SecureRandom());  
 45             // 从上述SSLContext对象中得到SSLSocketFactory对象  
 46             SSLSocketFactory ssf = sslContext.getSocketFactory();  
 47 
 48             URL url = new URL(requestUrl);  
 49             HttpsURLConnection httpUrlConn = (HttpsURLConnection) url.openConnection();  
 50             httpUrlConn.setSSLSocketFactory(ssf);  
 51 
 52             httpUrlConn.setDoOutput(true);  
 53             httpUrlConn.setDoInput(true);  
 54             httpUrlConn.setUseCaches(false);  
 55             // 设置请求方式(GET/POST)  
 56             httpUrlConn.setRequestMethod(requestMethod);  
 57 
 58             if ("GET".equalsIgnoreCase(requestMethod))  
 59                 httpUrlConn.connect();  
 60 
 61             // 当有数据需要提交时  
 62             if (null != outputStr) {  
 63                 OutputStream outputStream = httpUrlConn.getOutputStream();  
 64                 // 注意编码格式,防止中文乱码  
 65                 outputStream.write(outputStr.getBytes("UTF-8"));  
 66                 outputStream.close();  
 67             }  
 68 
 69             // 将返回的输入流转换成字符串  
 70             InputStream inputStream = httpUrlConn.getInputStream();  
 71             InputStreamReader inputStreamReader = new InputStreamReader(inputStream, "utf-8");  
 72             BufferedReader bufferedReader = new BufferedReader(inputStreamReader);  
 73 
 74             String str = null;  
 75             while ((str = bufferedReader.readLine()) != null) {  
 76                 buffer.append(str);  
 77             }  
 78             bufferedReader.close();  
 79             inputStreamReader.close();  
 80             // 释放资源  
 81             inputStream.close();  
 82             inputStream = null;  
 83             httpUrlConn.disconnect();  
 84             jsonObject = JSONObject.fromObject(buffer.toString());  
 85         } catch (ConnectException ce) {  
 86             log.error("Weixin server connection timed out.");  
 87         } catch (Exception e) {  
 88             log.error("https request error:{}", e);  
 89         }  
 90         return jsonObject;  
 91     }  
 92 
 93     /** 
 94      * 2.发起http请求获取返回结果 
 95      *  
 96      * @param requestUrl 请求地址 
 97      * @return 
 98      */  
 99     public static String httpRequest(String requestUrl) {  
100         StringBuffer buffer = new StringBuffer();  
101         try {  
102             URL url = new URL(requestUrl);  
103             HttpURLConnection httpUrlConn = (HttpURLConnection) url.openConnection();  
104 
105             httpUrlConn.setDoOutput(false);  
106             httpUrlConn.setDoInput(true);  
107             httpUrlConn.setUseCaches(false);  
108 
109             httpUrlConn.setRequestMethod("GET");  
110             httpUrlConn.connect();  
111 
112             // 将返回的输入流转换成字符串  
113             InputStream inputStream = httpUrlConn.getInputStream();  
114             InputStreamReader inputStreamReader = new InputStreamReader(inputStream, "utf-8");  
115             BufferedReader bufferedReader = new BufferedReader(inputStreamReader);  
116 
117             String str = null;  
118             while ((str = bufferedReader.readLine()) != null) {  
119                 buffer.append(str);  
120             }  
121             bufferedReader.close();  
122             inputStreamReader.close();  
123             // 释放资源  
124             inputStream.close();  
125             inputStream = null;  
126             httpUrlConn.disconnect();  
127 
128         } catch (Exception e) {  
129         }  
130         return buffer.toString();  
131     }  
132 
133 
134     /** 
135      * 3.获取access_token 
136      *  
137      * @param appid 凭证 
138      * @param appsecret 密钥 
139      * @return 
140      */  
141     public static AccessToken getAccessToken(String appid, String appsecret) {  
142         AccessToken accessToken = null;  
143 
144         String requestUrl = access_token_url.replace("{corpId}", appid).replace("{corpsecret}", appsecret);  
145         JSONObject jsonObject = httpRequest(requestUrl, "GET", null);  
146         // 如果请求成功  
147         if (null != jsonObject) {  
148             try {  
149                 accessToken = new AccessToken();  
150                 accessToken.setToken(jsonObject.getString("access_token"));  
151                 accessToken.setExpiresIn(jsonObject.getInt("expires_in"));  
152             } catch (JSONException e) {  
153                 accessToken = null;  
154                 // 获取token失败  
155                 log.error("获取token失败 errcode:{} errmsg:{}", jsonObject.getInt("errcode"), jsonObject.getString("errmsg"));  
156             }  
157         }  
158         return accessToken;  
159     }  
160 
161 
162 }
View Code

 

发送https请求需要一个证书信任管理器,所以此类依赖于MyX509TrustManager.java

 1 package com.ray.util;  
 2   
 3 import java.security.cert.CertificateException;  
 4 import java.security.cert.X509Certificate;  
 5   
 6 import javax.net.ssl.X509TrustManager;  
 7   
 8 /** 
 9  * 证书信任管理器(用于https请求) 
10  *  
11  * @author liufeng 
12  * @date 2013-08-08 
13  */  
14 public class MyX509TrustManager implements X509TrustManager {  
15   
16     public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {  
17     }  
18   
19     public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {  
20     }  
21   
22     public X509Certificate[] getAcceptedIssuers() {  
23         return null;  
24     }  
25 }  
View Code

 

2.3 实体类之凭证封装类——AccessToken.java

 1 package com.ray.pojo;  
 2   
 3 /**
 4  * @desc  : 微信通用接口凭证 
 5  * 
 6  * @author: shirayner
 7  * @date  : 2017-8-20 下午9:35:11
 8  */
 9 public class AccessToken {  
10     // 获取到的凭证  
11     private String token;  
12     // 凭证有效时间,单位:秒  
13     private int expiresIn;  
14   
15     public String getToken() {  
16         return token;  
17     }  
18   
19     public void setToken(String token) {  
20         this.token = token;  
21     }  
22   
23     public int getExpiresIn() {  
24         return expiresIn;  
25     }  
26   
27     public void setExpiresIn(int expiresIn) {  
28         this.expiresIn = expiresIn;  
29     }  
30 }  
View Code

 

2.4 实体类之用户类——User.java

注:这两个实体类只添加了User的部分属性,如有需要,读者可根据官方文档自行添加相关属性。

 1 package com.ray.pojo;
 2 
 3 public class User {
 4     private String userid;
 5     private String name;
 6     private int department;
 7     private String mobile;
 8     private String email;
 9     private String position;
10     private String gender;
11     
12     public User(){};
13     public User(String userid, String name, int department, String mobile,
14             String email, String position, String gender) {
15         super();
16         this.userid = userid;
17         this.name = name;
18         this.department = department;
19         this.mobile = mobile;
20         this.email = email;
21         this.position = position;
22         this.gender = gender;
23     }
24     public String getUserid() {
25         return userid;
26     }
27     public void setUserid(String userid) {
28         this.userid = userid;
29     }
30     public String getName() {
31         return name;
32     }
33     public void setName(String name) {
34         this.name = name;
35     }
36 
37     public int getDepartment() {
38         return department;
39     }
40     public void setDepartment(int department) {
41         this.department = department;
42     }
43     public String getMobile() {
44         return mobile;
45     }
46     public void setMobile(String mobile) {
47         this.mobile = mobile;
48     }
49     public String getEmail() {
50         return email;
51     }
52     public void setEmail(String email) {
53         this.email = email;
54     }
55     public String getPosition() {
56         return position;
57     }
58     public void setPosition(String position) {
59         this.position = position;
60     }
61     public String getGender() {
62         return gender;
63     }
64     public void setGender(String gender) {
65         this.gender = gender;
66     }
67     @Override
68     public String toString() {
69         return "User [userid=" + userid + ", name=" + name + ", department="
70                 + department + ", mobile=" + mobile + ", email=" + email
71                 + ", position=" + position + ", gender=" + gender + "]";
72     }
73     
74     public String toJson(){
75          String str="{\"userid\": %s,\"name\": %s,\"department\": [1],\"mobile\": %s,\"email\": %s,\"gender\": %s}";  
76 
77         return String.format(str,this.userid,this.name,this.mobile,this.email,this.gender); 
78     }
79     
80     
81 }
View Code

 

2.5 实体类之部门类——Department.java

 1 package com.ray.pojo;
 2 
 3 public class Department {
 4     private int id ;
 5     private String name;
 6     private int parentid;
 7     private int order;
 8     
 9     
10     
11     public Department(int id, String name, int parentid) {
12         super();
13         this.id = id;
14         this.name = name;
15         this.parentid = parentid;
16     }
17     public int getId() {
18         return id;
19     }
20     public void setId(int id) {
21         this.id = id;
22     }
23     public String getName() {
24         return name;
25     }
26     public void setName(String name) {
27         this.name = name;
28     }
29     public int getParentid() {
30         return parentid;
31     }
32     public void setParentid(int parentid) {
33         this.parentid = parentid;
34     }
35     public int getOrder() {
36         return order;
37     }
38     public void setOrder(int order) {
39         this.order = order;
40     }
41     
42     
43 }
View Code

 

2.6 业务类之通讯录用户业务类——Contacts_UserService

  1 package com.ray.service;
  2 
  3 import java.util.HashMap;
  4 import java.util.List;
  5 import java.util.Map;
  6 
  7 import net.sf.json.JSONObject;
  8 
  9 import org.slf4j.Logger;
 10 import org.slf4j.LoggerFactory;
 11 
 12 import com.google.gson.Gson;
 13 import com.ray.pojo.User;
 14 import com.ray.test.UserTest;
 15 import com.ray.util.WeiXinUtil;
 16 
 17 public class Contacts_UserService {
 18     private static Logger log = LoggerFactory.getLogger(UserTest.class);  
 19 
 20     private  static  String createUser_url="https://qyapi.weixin.qq.com/cgi-bin/user/create?access_token=ACCESS_TOKEN";  
 21     private  static  String getUser_url="https://qyapi.weixin.qq.com/cgi-bin/user/get?access_token=ACCESS_TOKEN&userid=USERID";  
 22     private  static  String updateUser_url="https://qyapi.weixin.qq.com/cgi-bin/user/update?access_token=ACCESS_TOKEN";  
 23     private  static  String deleteUser_url="https://qyapi.weixin.qq.com/cgi-bin/user/delete?access_token=ACCESS_TOKEN&userid=USERID";  
 24     private  static  String batchdeleteUser_url="https://qyapi.weixin.qq.com/cgi-bin/user/batchdelete?access_token=ACCESS_TOKEN";  
 25     private  static  String getDepartmentUser_url="https://qyapi.weixin.qq.com/cgi-bin/user/simplelist?access_token=ACCESS_TOKEN&department_id=DEPARTMENT_ID&fetch_child=FETCH_CHILD";  
 26     private  static  String getDepartmentUserDetails_url="https://qyapi.weixin.qq.com/cgi-bin/user/list?access_token=ACCESS_TOKEN&department_id=DEPARTMENT_ID&fetch_child=FETCH_CHILD";  
 27 
 28     
 29     //1.创建成员
 30     public void createUser(String accessToken,User user) {
 31 
 32         //1.获取json字符串:将user对象转换为json字符串    
 33         Gson gson = new Gson(); 
 34         String jsonU1 =gson.toJson(user);      //使用gson.toJson(user)即可将user对象顺序转成json
 35         System.out.println("jsonU1:"+jsonU1);
 36 
 37 
 38         //2.获取请求的url  
 39         createUser_url=createUser_url.replace("ACCESS_TOKEN", accessToken);
 40 
 41         //3.调用接口,发送请求,创建成员
 42         JSONObject jsonObject = WeiXinUtil.httpRequest(createUser_url, "POST", jsonU1);  
 43         System.out.println("jsonObject:"+jsonObject.toString());
 44 
 45         //4.错误消息处理
 46         if (null != jsonObject) {  
 47             if (0 != jsonObject.getInt("errcode")) {  
 48                 log.error("创建成员失败 errcode:{} errmsg:{}", jsonObject.getInt("errcode"), jsonObject.getString("errmsg"));  
 49             }  
 50         }  
 51     }
 52 
 53     //2.获取成员
 54     public void getUser(String accessToken,String userId) {
 55 
 56         //1.获取请求的url  
 57         getUser_url=getUser_url.replace("ACCESS_TOKEN", accessToken)
 58                 .replace("USERID", userId);
 59 
 60         //2.调用接口,发送请求,获取成员
 61         JSONObject jsonObject = WeiXinUtil.httpRequest(getUser_url, "GET", null);  
 62         System.out.println("jsonObject:"+jsonObject.toString());
 63 
 64         //3.错误消息处理
 65         if (null != jsonObject) {  
 66             if (0 != jsonObject.getInt("errcode")) {  
 67                 log.error("获取成员失败 errcode:{} errmsg:{}", jsonObject.getInt("errcode"), jsonObject.getString("errmsg"));  
 68             }  
 69         }  
 70     }
 71 
 72     //3.更新成员
 73     public void updateUser(String accessToken,User user) {
 74 
 75         //1.获取json字符串:将user对象转换为json字符串    
 76         Gson gson = new Gson(); 
 77         String jsonU1 =gson.toJson(user);      //使用gson.toJson(user)即可将user对象顺序转成json
 78         System.out.println("jsonU1:"+jsonU1);
 79 
 80 
 81         //2.获取请求的url  
 82         updateUser_url=updateUser_url.replace("ACCESS_TOKEN", accessToken);
 83 
 84         //3.调用接口,发送请求,创建成员
 85         JSONObject jsonObject = WeiXinUtil.httpRequest(updateUser_url, "POST", jsonU1);  
 86         System.out.println("jsonObject:"+jsonObject.toString());
 87 
 88         //4.错误消息处理
 89         if (null != jsonObject) {  
 90             if (0 != jsonObject.getInt("errcode")) {  
 91                 log.error("更新成员失败 errcode:{} errmsg:{}", jsonObject.getInt("errcode"), jsonObject.getString("errmsg"));  
 92             }  
 93         }  
 94     }
 95 
 96     //4.删除成员
 97     public void deleteUser(String accessToken,String userId) {    
 98 
 99         //1.获取请求的url  
100         deleteUser_url=deleteUser_url.replace("ACCESS_TOKEN", accessToken)
101                 .replace("USERID", userId);
102 
103         //2.调用接口,发送请求,删除成员
104         JSONObject jsonObject = WeiXinUtil.httpRequest(deleteUser_url, "GET", null);  
105         System.out.println("jsonObject:"+jsonObject.toString());
106 
107         //3.错误消息处理
108         if (null != jsonObject) {  
109             if (0 != jsonObject.getInt("errcode")) {  
110                 log.error("删除成员失败 errcode:{} errmsg:{}", jsonObject.getInt("errcode"), jsonObject.getString("errmsg"));  
111             }  
112         }  
113     }
114 
115     //5.批量删除成员
116     public void batchdeleteUser(String accessToken,List<String> userIdList){
117         //1.获取json字符串:将user对象转换为json字符串    
118         Map<String, Object> content = new HashMap<String, Object>();  
119         content.put("useridlist", userIdList);  
120 
121         Gson gson=new Gson();
122         String useridlist=gson.toJson(content);
123         System.out.println(useridlist);
124 
125         //2.获取请求的url  
126         batchdeleteUser_url=batchdeleteUser_url.replace("ACCESS_TOKEN", accessToken);
127 
128         //3.调用接口,发送请求,创建成员
129         JSONObject jsonObject = WeiXinUtil.httpRequest(batchdeleteUser_url, "POST", useridlist);  
130         System.out.println("jsonObject:"+jsonObject.toString());
131 
132         //4.错误消息处理
133         if (null != jsonObject) {  
134             if (0 != jsonObject.getInt("errcode")) {  
135                 log.error("批量删除成员失败 errcode:{} errmsg:{}", jsonObject.getInt("errcode"), jsonObject.getString("errmsg"));  
136             }  
137         }  
138     }
139 
140 
141     //6.获取部门成员
142     public void getDepartmentUser(String accessToken,String departmentId,String fetchChild) {
143 
144         //1.获取请求的url  
145         getDepartmentUser_url=getDepartmentUser_url.replace("ACCESS_TOKEN", accessToken)
146                 .replace("DEPARTMENT_ID", departmentId)
147                 .replace("FETCH_CHILD", fetchChild);
148 
149         //2.调用接口,发送请求,获取部门成员
150         JSONObject jsonObject = WeiXinUtil.httpRequest(getDepartmentUser_url, "GET", null);  
151         System.out.println("jsonObject:"+jsonObject.toString());
152 
153         //3.错误消息处理
154         if (null != jsonObject) {  
155             if (0 != jsonObject.getInt("errcode")) {  
156                 log.error("获取部门成员失败 errcode:{} errmsg:{}", jsonObject.getInt("errcode"), jsonObject.getString("errmsg"));  
157             }  
158         }  
159     }
160 
161 
162     //7.获取部门成员详情
163     public void getDepartmentUserDetails(String accessToken,String departmentId,String fetchChild) {
164         //1.获取请求的url  
165         getDepartmentUserDetails_url=getDepartmentUserDetails_url.replace("ACCESS_TOKEN", accessToken)
166                 .replace("DEPARTMENT_ID", departmentId)
167                 .replace("FETCH_CHILD", fetchChild);
168 
169         //2.调用接口,发送请求,获取部门成员
170         JSONObject jsonObject = WeiXinUtil.httpRequest(getDepartmentUserDetails_url, "GET", null);  
171         System.out.println("jsonObject:"+jsonObject.toString());
172 
173         //3.错误消息处理
174         if (null != jsonObject) {  
175             if (0 != jsonObject.getInt("errcode")) {  
176                 log.error("获取部门成员详情失败 errcode:{} errmsg:{}", jsonObject.getInt("errcode"), jsonObject.getString("errmsg"));  
177             }  
178         }  
179     }
180 
181 }
View Code

 

2.7 业务类之通讯录部门业务类

  1 package com.ray.service;
  2 
  3 import net.sf.json.JSONObject;
  4 import org.slf4j.Logger;
  5 import org.slf4j.LoggerFactory;
  6 import com.google.gson.Gson;
  7 import com.ray.pojo.Department;
  8 import com.ray.test.DepartmentTest;
  9 import com.ray.util.WeiXinUtil;
 10 
 11 public class Contacts_DepartmentService {
 12     private static Logger log = LoggerFactory.getLogger(DepartmentTest.class);  
 13 
 14     private  static  String createDepartment_url="https://qyapi.weixin.qq.com/cgi-bin/department/create?access_token=ACCESS_TOKEN";  
 15     private  static  String updateDepartment_url="https://qyapi.weixin.qq.com/cgi-bin/department/update?access_token=ACCESS_TOKEN";  
 16     private  static  String deleteDepartment_url="https://qyapi.weixin.qq.com/cgi-bin/department/delete?access_token=ACCESS_TOKEN&id=ID";  
 17     private  static  String getDepartmentList_url="https://qyapi.weixin.qq.com/cgi-bin/department/list?access_token=ACCESS_TOKEN&id=ID";  
 18 
 19     
 20     //1.创建部门
 21     public void createDepartment(String accessToken,Department department) {
 22 
 23         //1.获取json字符串:将Department对象转换为json字符串    
 24         Gson gson = new Gson(); 
 25         String jsonDepartment =gson.toJson(department);      //使用gson.toJson(jsonDepartment)即可将jsonDepartment对象顺序转成json
 26         System.out.println("jsonDepartment:"+jsonDepartment);
 27         //2.拼接请求的url
 28         createDepartment_url=createDepartment_url.replace("ACCESS_TOKEN", accessToken);
 29 
 30         //3.调用接口,发送请求,创建部门
 31         JSONObject jsonObject = WeiXinUtil.httpRequest(createDepartment_url, "POST", jsonDepartment);  
 32         System.out.println("jsonObject:"+jsonObject.toString());
 33         if (null != jsonObject) {  
 34             if (0 != jsonObject.getInt("errcode")) {  
 35 
 36                 log.error("创建部门失败 errcode:{} errmsg:{}", jsonObject.getInt("errcode"), jsonObject.getString("errmsg"));  
 37             }  
 38         }  
 39     }
 40 
 41     //2.更新部门
 42     public void updateDepartment(String accessToken,Department department) {
 43 
 44         //1.获取json字符串:将Department对象转换为json字符串    
 45         Gson gson = new Gson(); 
 46         String jsonDepartment =gson.toJson(department);      //使用gson.toJson(jsonDepartment)即可将jsonDepartment对象顺序转成json
 47         System.out.println("jsonDepartment:"+jsonDepartment);
 48         //2.拼接请求的url
 49         updateDepartment_url=updateDepartment_url.replace("ACCESS_TOKEN", accessToken);
 50 
 51         //3.调用接口,发送请求,更新部门
 52         JSONObject jsonObject = WeiXinUtil.httpRequest(updateDepartment_url, "POST", jsonDepartment);  
 53         System.out.println("jsonObject:"+jsonObject.toString());
 54         if (null != jsonObject) {  
 55             if (0 != jsonObject.getInt("errcode")) {  
 56 
 57                 log.error("更新部门失败 errcode:{} errmsg:{}", jsonObject.getInt("errcode"), jsonObject.getString("errmsg"));  
 58             }  
 59         }  
 60     }
 61     
 62 
 63     //3.删除部门
 64     public void deleteDepartment(String accessToken,String departmentId) {    
 65 
 66         //1.获取请求的url  
 67         deleteDepartment_url=deleteDepartment_url.replace("ACCESS_TOKEN", accessToken)
 68                 .replace("ID", departmentId);
 69 
 70         //2.调用接口,发送请求,删除部门
 71         JSONObject jsonObject = WeiXinUtil.httpRequest(deleteDepartment_url, "GET", null);  
 72         System.out.println("jsonObject:"+jsonObject.toString());
 73 
 74         //3.错误消息处理
 75         if (null != jsonObject) {  
 76             if (0 != jsonObject.getInt("errcode")) {  
 77                 log.error("删除部门失败 errcode:{} errmsg:{}", jsonObject.getInt("errcode"), jsonObject.getString("errmsg"));  
 78             }  
 79         }  
 80     }
 81     
 82     
 83     
 84     //4.获取部门列表
 85     public void getDepartmentList(String accessToken,String departmentId) {
 86 
 87         //1.获取请求的url  
 88         getDepartmentList_url=getDepartmentList_url.replace("ACCESS_TOKEN", accessToken)
 89                 .replace("ID", departmentId);
 90 
 91         //2.调用接口,发送请求,获取成员
 92         JSONObject jsonObject = WeiXinUtil.httpRequest(getDepartmentList_url, "GET", null);  
 93         System.out.println("jsonObject:"+jsonObject.toString());
 94 
 95         //3.错误消息处理
 96         if (null != jsonObject) {  
 97             if (0 != jsonObject.getInt("errcode")) {  
 98                 log.error("获取部门列表 errcode:{} errmsg:{}", jsonObject.getInt("errcode"), jsonObject.getString("errmsg"));  
 99             }  
100         }  
101     }
102 
103 
104 }
View Code

 

2.8 测试类之用户测试类-UserTest.java

  1 package com.ray.test;
  2 
  3 import java.util.Arrays;
  4 import java.util.List;
  5 
  6 import org.junit.Test;
  7 
  8 import com.ray.pojo.User;
  9 import com.ray.service.Contacts_UserService;
 10 import com.ray.util.WeiXinParamesUtil;
 11 import com.ray.util.WeiXinUtil;
 12 
 13 /**
 14  * 成员管理
 15  * @author shirayner
 16  *
 17  *要注意的地方:
 18  *1.开启通讯录同步之后,才能进行通讯录的相关操作
 19  *2.对通讯录操作的凭证access_token,由企业id-cropId和通讯录秘钥secret(而不是应用秘钥)获取。
 20  *3.创建成员需要开启通讯录的编辑权限。(管理工具-通讯录同步)
 21  *4.java对象转json: 用gson.toJson(user)即可将user对象顺序转成json
 22  */
 23 
 24 public class UserTest {
 25 
 26     //1.创建成员
 27     @Test
 28     public void testCreateUser() {
 29         //1.创建user对象
 30         //User user = new User("3", "ray", 1,"13886086292","3057046319@qq.com","技术顾问","1");  
 31         User user = new User("4", "jack", 1,"13986086293","4057046319@qq.com","咨询顾问","1");  
 32         //User user = new User("5", "tom", 1,"14986086294","5057046319@qq.com","产品经理","1");  
 33 
 34         //2.获取access_token:根据企业id和通讯录密钥获取access_token,并拼接请求url
 35         String accessToken= WeiXinUtil.getAccessToken(WeiXinParamesUtil.corpId, WeiXinParamesUtil.contactsSecret).getToken();
 36         System.out.println("accessToken:"+accessToken);
 37 
 38         //3.创建成员
 39         Contacts_UserService cus=new Contacts_UserService();
 40         cus.createUser(accessToken,user);
 41 
 42     }
 43 
 44 
 45     //2.获取成员
 46     @Test
 47     public void testGetUser() {
 48         //1.获取userId
 49         //String userId="ShiRui";
 50         String userId="4";
 51 
 52         //2.获取access_token:根据企业id和通讯录密钥获取access_token,并拼接请求url
 53         String accessToken= WeiXinUtil.getAccessToken(WeiXinParamesUtil.corpId, WeiXinParamesUtil.contactsSecret).getToken();
 54         System.out.println("accessToken:"+accessToken);
 55 
 56         //3.获取成员
 57         Contacts_UserService cus=new Contacts_UserService();
 58         cus.getUser(userId, accessToken);
 59     }
 60 
 61     //3.更新成员
 62     @Test
 63     public void testUpdateUser() {
 64 
 65         //1.更改user对象信息
 66         //User user = new User("3", "ray", 1,"13886086292","3057046319@qq.com","技术顾问","1");  
 67         //User user = new User("4", "jack", 1,"13986086293","4057046319@qq.com","咨询顾问","1");  
 68         User user = new User("3", "ray", 1,"13889086292","3057946319@qq.com","咨询顾问","1");  
 69 
 70         //2.获取access_token:根据企业id和通讯录密钥获取access_token,并拼接请求url
 71         String accessToken= WeiXinUtil.getAccessToken(WeiXinParamesUtil.corpId, WeiXinParamesUtil.contactsSecret).getToken();
 72         System.out.println("accessToken:"+accessToken);
 73 
 74         //3.创建成员
 75         Contacts_UserService cus=new Contacts_UserService();
 76         cus.updateUser( accessToken,user);
 77 
 78     }
 79 
 80     //4.删除成员
 81     @Test
 82     public void testDeleteUser() {
 83         //1.获取userId
 84         //String userId="ShiRui";
 85         String userId="4";
 86 
 87         //2.获取access_token:根据企业id和通讯录密钥获取access_token,并拼接请求url
 88         String accessToken= WeiXinUtil.getAccessToken(WeiXinParamesUtil.corpId, WeiXinParamesUtil.contactsSecret).getToken();
 89         System.out.println("accessToken:"+accessToken);
 90 
 91         //3.创建成员
 92         Contacts_UserService cus=new Contacts_UserService();
 93         cus.deleteUser(userId, accessToken);
 94     }
 95 
 96 
 97     //5.批量删除成员
 98     @Test
 99     public void testbatchdeleteUser() {
100         //1.获取userIdList
101         String userId1="3";
102         String userId2="4";
103         List<String> userIdList = Arrays.asList(userId1, userId2);  //此时将userIdList转json,则结果为:["3","4"],会报错:{"errcode":40063,"errmsg":"some parameters are empty"}
104 
105         //2.获取access_token:根据企业id和通讯录密钥获取access_token,并拼接请求url
106         String accessToken= WeiXinUtil.getAccessToken(WeiXinParamesUtil.corpId, WeiXinParamesUtil.contactsSecret).getToken();
107         System.out.println("accessToken:"+accessToken);
108 
109         //3.批量删除成员
110         Contacts_UserService cus=new Contacts_UserService();
111         cus.batchdeleteUser(accessToken,userIdList);
112     }
113 
114 
115     //6.获取部门成员
116     @Test
117     public void testGetDepartmentUser() {
118         //1.获取部门ID以及是否获取子部门成员
119         String departmentId="1";
120         String fetchChild="0";
121 
122         //2.获取accessToken:根据企业id和通讯录密钥获取access_token,并拼接请求url
123         String accessToken= WeiXinUtil.getAccessToken(WeiXinParamesUtil.corpId, WeiXinParamesUtil.contactsSecret).getToken();
124         System.out.println("accessToken:"+accessToken);
125 
126         //3.获取部门成员
127         Contacts_UserService cus=new Contacts_UserService();
128         cus.getDepartmentUser(accessToken, departmentId, fetchChild);
129     }
130 
131 
132     //7.获取部门成员详情
133     @Test 
134     public void testGetDepartmentUserDetails() {
135         //1.获取部门ID以及是否获取子部门成员
136         String departmentId="1";
137         String fetchChild="0";
138 
139         //2.获取accessToken:根据企业id和通讯录密钥获取access_token,并拼接请求url
140         String accessToken= WeiXinUtil.getAccessToken(WeiXinParamesUtil.corpId, WeiXinParamesUtil.contactsSecret).getToken();
141         System.out.println("accessToken:"+accessToken);
142 
143         //3.获取部门成员
144         Contacts_UserService cus=new Contacts_UserService();
145         cus.getDepartmentUserDetails(accessToken, departmentId, fetchChild);
146     }
147 }
View Code

 

 2.9 测试类之部门测试类-DepartmentTest.java

 1 package com.ray.test;
 2 
 3 import org.junit.Test;
 4 import com.ray.pojo.Department;
 5 import com.ray.service.Contacts_DepartmentService;
 6 import com.ray.util.WeiXinParamesUtil;
 7 import com.ray.util.WeiXinUtil;
 8 
 9 /**
10  * 部门管理
11  * @author shirayner
12  *
13  *
14  */
15 
16 public class DepartmentTest {
17 
18 
19     //1.创建部门
20     @Test
21     public void testCreateDepartment() {
22         //1.创建Department对象,并将对象转换成json字符串  
23         Department department = new Department(3, "HEC武汉分公司", 2);  
24         //Department department = new Department(2, "HEC技术中心", 1);  
25 
26         //2.获取access_token:根据企业id和通讯录密钥获取access_token,并拼接请求url
27         String accessToken= WeiXinUtil.getAccessToken(WeiXinParamesUtil.corpId, WeiXinParamesUtil.contactsSecret).getToken();
28         System.out.println("accessToken:"+accessToken);
29 
30         //3.创建部门
31         Contacts_DepartmentService cds= new Contacts_DepartmentService();
32         cds.createDepartment(accessToken, department);
33     }
34 
35 
36     //2.更新部门
37     @Test
38     public void testUpdateDepartment() {
39         //1.创建Department对象,并将对象转换成json字符串  
40         Department department = new Department(2, "HEC技术服务中心", 1);  
41 
42 
43         //2.获取access_token:根据企业id和通讯录密钥获取access_token,并拼接请求url
44         String accessToken= WeiXinUtil.getAccessToken(WeiXinParamesUtil.corpId, WeiXinParamesUtil.contactsSecret).getToken();
45         System.out.println("accessToken:"+accessToken);
46 
47         //3.更新部门
48         Contacts_DepartmentService cds= new Contacts_DepartmentService();
49         cds.updateDepartment(accessToken, department);
50     }
51 
52     //3.删除部门
53     @Test
54     public void testDeleteDepartment() {
55         //1.获取userId
56         String departmentId="3";
57 
58         //2.获取access_token:根据企业id和通讯录密钥获取access_token,并拼接请求url
59         String accessToken= WeiXinUtil.getAccessToken(WeiXinParamesUtil.corpId, WeiXinParamesUtil.contactsSecret).getToken();
60         System.out.println("accessToken:"+accessToken);
61 
62         //3.删除部门
63         Contacts_DepartmentService cds= new Contacts_DepartmentService();
64         cds.deleteDepartment(accessToken, departmentId);
65     }
66 
67 
68     /**
69      * 4.获取部门列表
70      * 参数                  必须    说明
71      * access_token    是    调用接口凭证
72      * id                    否     部门id。获取指定部门及其下的子部门。 如果不填,默认获取全量组织架构
73      */
74     @Test
75     public void testGetDepartmentList() {
76         //1.获取departmentId
77         String departmentId="1";
78 
79         //2.获取access_token:根据企业id和通讯录密钥获取access_token,并拼接请求url
80         String accessToken= WeiXinUtil.getAccessToken(WeiXinParamesUtil.corpId, WeiXinParamesUtil.contactsSecret).getToken();
81         System.out.println("accessToken:"+accessToken);
82 
83         //3.调用接口,发送请求,删除部门
84         Contacts_DepartmentService cds= new Contacts_DepartmentService();
85         cds.getDepartmentList(accessToken, departmentId);
86     }
87 
88 
89 }
View Code

 

三、参考资料

1.微信企业号官方开发文档:https://work.weixin.qq.com/api/doc#10016

 

转载于:https://www.cnblogs.com/shirui/p/7401514.html

2016-03-07 13:16:26 yanbinzou 阅读数 3435
  • 微信支付开发-微信公众号开发12-微信开发php

    微信公众平台开发之微信支付开发是子恒老师《微信公众平台开发》视频教程的第12部。详细讲解了用php进行微信支付的开发。内容包含获取支付密钥,微信公众号支付开发,扫码支付,微信刷卡支付,异步处理支付结果等等。欢迎反馈,微信/QQ:68183131

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

  首先来看微信官方的文档

创建成员

  • 请求说明

Https请求方式: POST

https://qyapi.weixin.qq.com/cgi-bin/user/create?access_token=ACCESS_TOKEN

请求包结构体为:

{
   "userid": "zhangsan",
   "name": "张三",
   "department": [1, 2],
   "position": "产品经理",
   "mobile": "15913215421",
   "gender": "1",
   "email": "zhangsan@gzdev.com",
   "weixinid": "zhangsan4dev",
   "avatar_mediaid": "2-G6nrLmr5EC3MNb_-zL1dDdzkd0p7cNliYu9V5w7o8K0",
   "extattr": {"attrs":[{"name":"爱好","value":"旅游"},{"name":"卡号","value":"1234567234"}]}
}
  • 参数说明
参数 必须 说明
access_token 调用接口凭证
userid 成员UserID。对应管理端的帐号,企业内必须唯一。长度为1~64个字节
name 成员名称。长度为1~64个字节
department 成员所属部门id列表
position 职位信息。长度为0~64个字节
mobile 手机号码。企业内必须唯一,mobile/weixinid/email三者不能同时为空
gender 性别。1表示男性,2表示女性
email 邮箱。长度为0~64个字节。企业内必须唯一
weixinid 微信号。企业内必须唯一。(注意:是微信号,不是微信的名字)
avatar_mediaid 成员头像的mediaid,通过多媒体接口上传图片获得的mediaid
extattr 扩展属性。扩展属性需要在WEB管理端创建后才生效,否则忽略未知属性的赋值
  • 权限说明

管理组须拥有指定部门的管理权限。

  • 返回结果
{
   "errcode": 0,
   "errmsg": "created"
}


  以下步骤是建立到已经获取到accessToken,我们开始

首先新建一个类,用来存放数据,大概数据结构。以下代码别复制 自己手动创建实体类
    public String userid;//员工UserID。对应管理端的帐号,企业内必须唯一。长度为1~64个字符
    public String name;//成员名称。长度为1~64个字符
    /**成员所属部门id列表,多个部门请用逗号隔开。<p>注意,每个部门的直属员工上限为1000个*/
    public List<Department> department;//
    public String position;//职位信息。长度为0~64个字符
    public String mobile;//手机号码。企业内必须唯一,mobile/weixinid/email三者不能同时为空
    public String email;//邮箱。长度为0~64个字符。企业内必须唯一
    public String weixinid;//微信号。企业内必须唯一。(注意:是微信号,不是微信的名字)
    public String enable="1";//启用/禁用成员。1表示启用成员,0表示禁用成员
    public String avatar;//头像url。注:如果要获取小图将url最后的"/0"改成"/64"即可
    public String status;//关注状态: 1=已关注,2=已冻结,4=未关注
    public Extattr extattr;//扩展属性。扩展属性需要在WEB管理端创建后才生效,否则忽略未知属性的赋值


        /// <summary>
        /// 把实体转换为 json
        /// </summary>
        /// <returns></returns>
        public String getUserJsonStr(ViewUserQY qy)
        {
            StringBuilder sBuilder = new StringBuilder();
            sBuilder.Append("{");
            sBuilder.Append("\"userid\": \"" + qy.UserId + "\",");
            sBuilder.Append("\"name\": \"" + qy.Name + "\",");
            StringBuilder dBuilder = new StringBuilder();
            for (int i = 0; i < this.department.size(); i++)
            {
                if (i != 0)
                {
                    dBuilder.Append("," + this.department.get(i).getId());
                }
                else
                {
                    dBuilder.Append(this.department.get(i).getId());
                }
            }
            sBuilder.Append("\"department\": [" + dBuilder + "],");
            sBuilder.Append("\"position\": \"" + qy.Position + "\",");
            sBuilder.Append("\"mobile\": \"" + qy.Mobile + "\",");
            sBuilder.Append("\"email\": \"" + qy.Email + "\",");
            sBuilder.Append("\"weixinid\": \"" + qy.WeixinId + "\",");
            sBuilder.Append("\"enable\": " + 0 + ",");
            sBuilder.Append("\"extattr\": {}");
            sBuilder.Append("}");
            return sBuilder.ToString();
        }
    }

添加成员代码,把实体类的数据转成json格式,然后向微信服务器发送一个post请求。 accessToken 需先拿到
string postUrl = "https://qyapi.weixin.qq.com/cgi-bin/user/create?access_token=" + accessToken;
            String jsonStr = getUserJsonStr(entity);
            byte[] bytes = Encoding.UTF8.GetBytes(jsonStr);
            HttpWebRequest request = (HttpWebRequest)WebRequest.Create(postUrl);
            request.Method = "POST";
            request.ContentLength = bytes.Length;
            request.ContentType = "text/xml";
            Stream reqstream = request.GetRequestStream();
            reqstream.Write(bytes, 0, bytes.Length);

            //声明一个HttpWebRequest请求
            request.Timeout = 90000;
            //设置连接超时时间
            request.Headers.Set("Pragma", "no-cache");
            HttpWebResponse response = (HttpWebResponse)request.GetResponse();
            Stream streamReceive = response.GetResponseStream();
            Encoding encoding = Encoding.UTF8;

            StreamReader streamReader = new StreamReader(streamReceive, encoding);
            string strResult = streamReader.ReadToEnd();
            streamReceive.Dispose();
            streamReader.Dispose();

  总结:把所需要的数据拿到之后,拼装成json数据吗,然后向微信post请求,结果会返回出来

2018-04-26 11:21:43 m0_38004957 阅读数 617
  • 微信支付开发-微信公众号开发12-微信开发php

    微信公众平台开发之微信支付开发是子恒老师《微信公众平台开发》视频教程的第12部。详细讲解了用php进行微信支付的开发。内容包含获取支付密钥,微信公众号支付开发,扫码支付,微信刷卡支付,异步处理支付结果等等。欢迎反馈,微信/QQ:68183131

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

 企业号所需信息及详细设置看官方文档,如题所示,这里涉及通讯录管理和消息发送,详情如下:

  • 基础设置部分

              先测试是否可以正常获取ACCESS_TOKEN

        //获取token
        String corpid = "";
        String corpsecret = "";//
        String TOKEN_URL = "https://qyapi.weixin.qq.com/cgi-bin/gettoken";
        Map<String,Object> params = new HashMap<String,Object>();
        params.put("corpid", corpid);
        params.put("corpsecret", corpsecret);
        String rtn_token = HttpRequestUtils.sendGet(TOKEN_URL, params);
        String access_token = SinaWeiboMid2Id.parserJson(rtn_token, "access_token");
        System.out.println("get token result "+access_token);

  • 通讯录管理

              创建部门(跟部门的id为1,后台手动创建的部门会分配默认id,可通过查询部门列表查看)

        //创建部门测试
        String CREATE_DEPARTMET = "https://qyapi.weixin.qq.com/cgi-bin/department/create?access_token=ACCESS_TOKEN";
        CREATE_DEPARTMET = CREATE_DEPARTMET.replace("ACCESS_TOKEN", access_token);
        String postJson = "{\"name\":\"%s\",\"parentid\": %s,\"id\": %s}";  
        String outputStr=String.format(postJson, "大数据营销部",1,3);
        System.out.println(outputStr);
        rtn_token = HttpRequestUtils.wxPost(CREATE_DEPARTMET,outputStr);
        System.out.println("create part return "+rtn_token);

              查找部门来了(id如果不传,查询所有的部门)

        //查找部门测试
        String SEARCH_DEPARTMET = "https://qyapi.weixin.qq.com/cgi-bin/department/list";
        params = new HashMap<String,Object>();
        params.put("access_token", access_token);
        params.put("id", 3);
        rtn_token = HttpRequestUtils.sendGet(SEARCH_DEPARTMET, params);
        System.out.println("get department result "+rtn_token);

              查找部门所有成员

        //查找部门成员信息
        String SEARCH_DEPARTMET_USER = "https://qyapi.weixin.qq.com/cgi-bin/user/simplelist";
        params = new HashMap<String,Object>();
        params.put("access_token", access_token);
        params.put("department_id", 3);
        rtn_token = HttpRequestUtils.sendGet(SEARCH_DEPARTMET_USER, params);
        System.out.println("get department user result "+rtn_token);

              创建部门成员

        //创建成员测试
        String CREATE_USER = "https://qyapi.weixin.qq.com/cgi-bin/user/create?access_token=ACCESS_TOKEN";
        CREATE_USER = CREATE_USER.replace("ACCESS_TOKEN", access_token);
        postJson = "{\"userid\":\"%s\",\"name\": \"%s\",\"mobile\": \"%s\",\"department\":%d,\"gender\":%d}"; 
        outputStr=String.format(postJson, "4_#","开发人员","**",3,1);
        rtn_token = HttpRequestUtils.wxPost(CREATE_USER,outputStr);
        System.out.println("create user return "+rtn_token);

              查询某成员信息

        //查询成员测试
        String SERACH_USER = "https://qyapi.weixin.qq.com/cgi-bin/user/get";
        params = new HashMap<String,Object>();
        params.put("access_token", access_token);
        params.put("userid", "3_**");
        rtn_token = HttpRequestUtils.sendGet(SERACH_USER, params);
        System.out.println("get user result "+rtn_token);
  • 企业号发送消息给成员

              一对一或者一对多发送

        //向指定成员发消息
        String SEND_USER = "https://qyapi.weixin.qq.com/cgi-bin/message/send?access_token=ACCESS_TOKEN";
        SEND_USER = SEND_USER.replace("ACCESS_TOKEN", access_token);
        postJson = "{\"touser\":\"%s\",\"toparty\": %d,\"msgtype\": \"%s\",\"agentid\":\"%s\",\"textcard\":{\"title\":\"%s\",\"description\":\"%s\",\"url\":\"%s\",\"btntxt\":\"%s\"}}"; 
        outputStr=String.format(postJson, "##",3,"textcard","**","领奖通知","<div class=\\\"gray\\\">2016年9月26日</div> <div class=\\\"normal\\\">恭喜你抽中iPhone 7一台,领奖码:xxxx</div><div class=\\\"highlight\\\">请于2016年10月10日前联系行政同事领取</div>","www.baidu.com","领取");
        System.out.println(outputStr);
        rtn_token = HttpRequestUtils.wxPost(SEND_USER,outputStr);
        System.out.println("send user return "+rtn_token);
注:代码中涉及的json内容提取,请求方法等可以谷歌或者度娘

C# 微信企业号 部门创建例子

博文 来自: WXbluethink
没有更多推荐了,返回首页