企业微信开发案例1
背景知识
由同一企业主体下的公众号,企业微信、小程序使用unionid来标识同一个用户对象,而openid只用于一种应用标识用户
Redis是一种基于key-value的数据库,一般用于缓存(cache)
PHP使用REDIS hGetAll 命令/方法/函数(PHP_Redis)-代潇瑞博客
1 设计目的
通过已知客户的unionid,来修改客户备注信息,手机号
2 实现方法
2.1 通过企业微信的第三方应用开发接口调用来实现
使用第三方应用开发接口来开发,需要注册第三方服务商的资质,目前无法注册第三方服务提供商。暂且不表。
2.2 通过企业微信的企业内部开发接口调用来实现
A 通过枚具备客户联系功能的企业成员(follow)得到一个follow_list,企业微信的API接口描述如下
B 通过批量获取客户详情功能,逐个的获取每个follow下的所有客户详情,主要需要的客户的(unionid, external_userid, remark_mobiles)
接口的描述如下
C 将获得到的一个follow下的所有客户信息,以hash方式放到redis中key为unionid, field value为一个多元组
D 需要修改remark mobile号的客户unionid给定在一个数组中,遍历之并查询redis,调用如下描述的修改客户备注信息接口来修改客户的remark mobile
3 项目源代码:
<?php
class JSSDK {
private $appId;
private $appSecret;
public function __construct($appId, $appSecret) {
$this->appId = $appId;
$this->appSecret = $appSecret;
}
public function api_notice_increment($url, $data){
$ch = curl_init();
curl_setopt($ch,CURLOPT_URL, $url);
if(stripos($url,"https://")!==FALSE){
curl_setopt($ch, CURLOPT_SSLVERSION, 1); //1 - CURL_SSLVERSION_TLSv1
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE);
} else {
curl_setopt($ch,CURLOPT_SSL_VERIFYPEER,TRUE);
curl_setopt($ch,CURLOPT_SSL_VERIFYHOST,2);//严格校验
}
//设置header
curl_setopt($ch, CURLOPT_HEADER, FALSE);
//要求结果为字符串且输出到屏幕上
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_TIMEOUT, 3);
//post提交方式
curl_setopt($ch, CURLOPT_POST, TRUE);
curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
$tmpInfo = curl_exec($ch);
//var_dump($tmpInfo);
/*if (curl_errno($ch)) {
$tmpInfo = curl_exec($ch);
}*/
curl_close($ch);
return $tmpInfo;
}
public function httpGet($url) {
$curl = curl_init();
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
curl_setopt($curl, CURLOPT_TIMEOUT, 5);
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, false);
curl_setopt($curl, CURLOPT_URL, $url);
$res = curl_exec($curl);
curl_close($curl);
return $res;
}
public function getAccessToken() {
// access_token 应该全局存储与更新,以下代码以写入到文件中做示例
$data = file_get_contents("access_token.json");
if ($data != false) {
$data = json_decode($data);
if ($data->expire_time > time()) {
return $data->access_token;
}
}
// 如果是企业号用以下URL获取access_token
$url = "https://qyapi.weixin.qq.com/cgi-bin/gettoken?corpid=$this->appId&corpsecret=$this->appSecret";
// $url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=$this->appId&secret=$this->appSecret";
$res = json_decode($this->httpGet($url));
$access_token = $res->access_token;
if ($access_token) {
$data->expire_time = time() + 3600;
$data->access_token = $access_token;
//$fp = fopen("./access_token.json", "w");
$fp = fopen("access_token.json", "w");
fwrite($fp, json_encode($data));
fclose($fp);
}
return $access_token;
}
}
class WeChat {
private $jssdk;
public $errcode;
public function __construct() {
$this->jssdk = new JSSDK("wwbce72cb895ea9678", "EMRcSyvbkXUfa-WTaHZ3nkBFm_WQUVmQI2LjXBibkPo");
$this->errcode = 0;
}
public function getFollows() {
$token = $this->jssdk->getAccessToken();
$url = "https://qyapi.weixin.qq.com/cgi-bin/externalcontact/get_follow_user_list?access_token=" . $token;
$res = $this->jssdk->httpGet($url);
$obj = json_decode($res);
$ret = $obj->follow_user;
$this->errcode = $obj->errcode;
return $ret;
}
public function getExtIDbyFollow($follow, $icur, &$ocur) {
$token = $this->jssdk->getAccessToken();
$url = "https://qyapi.weixin.qq.com/cgi-bin/externalcontact/batch/get_by_user?access_token=" . $token;
$data = (object)[];
$data->userid = $follow;
$data->limit = 100;
if (strlen($icur) > 0)
$data->cursor = $icur;
$jsonobj = json_encode($data);
$res = $this->jssdk->api_notice_increment($url, $jsonobj);
$res = json_decode($res);
if ($res->errcode != 0) {
$this->errcode = $res->errcode;
return;
}
$ocur = $res->next_cursor;
$elist = $res->external_contact_list;
$ret = array();
foreach($elist as $item) {
if (!isset($item->external_contact->unionid) ||
!isset($item->external_contact->external_userid)) {
continue;
}
$pair = (object)[];
$pair->unionid = $item->external_contact->unionid;
$pair->external_userid = $item->external_contact->external_userid;
if (count($item->follow_info->remark_mobiles) > 0)
$pair->mobile = $item->follow_info->remark_mobiles[0];
else
$pair->mobile = "";
$ret[] = $pair;
}
return $ret;
}
public function changePhoneMarkbyExtID($uid, $eid, $phone) {
$token = $this->jssdk->getAccessToken();
$url = "https://qyapi.weixin.qq.com/cgi-bin/externalcontact/remark?access_token=" . $token."&debug=1";
$jobj = array('userid'=>$uid, 'external_userid'=>$eid);
$jobj['remark_mobiles'] = array("$phone");
$jstr = json_encode($jobj);
$res = $this->jssdk->api_notice_increment($url, $jstr);
$res = json_decode($res);
if ($res->errcode == 0)
return true;
return false;
}
}
class Logger {
private $filename;
public function __construct($name, $flag=false) {
$this->filename = $name;
if ($flag == true) {
$fp = fopen($this->filename, "a+");
if ($fp) {
ftruncate($fp, 0);
fclose($fp);
}
}
}
public function log($info) {
$fp = fopen($this->filename, "a+");
if ($fp) {
fwrite($fp, date("Y-m-d H:i:s")." ".$info."\n\n");
echo date("Y-m-d H:i:s")." ".$info."\n\n";
fclose($fp);
}
}
}
define("UNCHANGED", 0);
define("CHANGED", 1);
define("ERROR", 2);
//----------------------------------------
//Step1 Prepare database and wechat context
//----------------------------------------
$wechat = new WeChat();
$logger = new Logger("/home/w.log");
$redis = new Redis();
$redis->connect('127.0.0.1', 6379);
$redis->select(15);
$conn = "mysql:host=localhost;dbname=kk_zuhao360_com;port=3306";
$pdo = new PDO($conn, "kk_zuhao360_com", "LbBdbHJxyrJ7G6nC");
$pdo->exec("SET NAMES UTF8");
$pdo->exec("SET character_set_client=utf8");
$pdo->exec("SET character_set_results=utf8");
//-------------------------------------------------
//Step2 query DB for unreported customers
//-------------------------------------------------
//Get unreported customers from DB
$rset = $pdo->query("select i.unionid,u.mobile from zjhj_bd_user_info as i,zjhj_bd_user as u where i.upload=0 and length(u.mobile)>10 and i.user_id=u.id");
if ($rset == false)
exit(0);
$cs_infos = $rset->fetchAll(PDO::FETCH_ASSOC);
if (count($cs_infos) <= 0)
exit(0);
//Add err flag for successful upload
foreach($cs_infos as &$cs) {
$cs['status'] = UNCHANGED;
}
$logger->log("request upload = ".count($cs_infos));
//-------------------------------------------------
//Step3 Loop follows and change customers' mobile
//-------------------------------------------------
//Get all follows
$follows = $wechat->getFollows();
$logger->log("total follows = ".count($follows));
//Loop follow for customers
foreach($follows as $follow) {
$icur = "";
$ocur = "";
//Loop for paging downloading and put to redis
$custom_cnt = 0;
$custom_redis_cnt = 0;
$redis->flushdb();
do {
//Get customer by follow
$euids = $wechat->getExtIDbyFollow($follow, $icur, $ocur);
$icur = $ocur;
$custom_cnt += count($euids);
foreach($euids as $eu) {
//Make sure insert data
if ($redis->hMset($eu->unionid, array('0'=>$eu->external_userid, '1'=>$eu->mobile)) == true)
$custom_redis_cnt++;
}
}
while (strlen($ocur) != 0);
$logger->log("follow($follow) has $custom_cnt customers, load $custom_redis_cnt to redis");
//Loop cs_infos for external_userid
foreach($cs_infos as &$cs) {
$rres = $redis->hMget($cs['unionid'],array('0', '1'));
// This customer does not belong to this follow
if ($rres['0'] === false) {
continue;
}
//mobile has been remarked
$mobile = $cs['mobile'];
if ($mobile == $rres['1']) {
$logger->log("({$cs['unionid']} : $mobile) has been changed");
$cs["status"] = CHANGED;
continue;
}
$eid = $rres['0'];
$ret = $wechat->changePhoneMarkbyExtID($follow, $eid, $mobile);
if ($ret == false) {
$logger->log("({$cs['unionid']} : $mobile) failed to change");
$cs['status'] = ERROR;
}
else {
$cs['status'] = CHANGED;
}
}
}
$redis->flushdb();
$redis->close();
$redis = null;
$pdo = null;
$finish_cnt = 0;
foreach($cs_infos as $cs) {
if ($cs['status'] == CHANGED)
$finish_cnt++;
}
$logger->log("total $finish_cnt customers finish changing mobile");
/* Test code
$uid="ZhouShiChun";
$eid="wmmWd-CgAATwRz6cJuKpduKezVX2h-sg";
$rdata='{"userid":"ZhouShiChun","external_userid":"wmmWd-CgAATwRz6cJuKpduKezVX2h-sg","remark_mobiles":["13800000002"]}';
$r2data='{
"unionid":"owxhs51dkeYBz6pv4r_PWkXu_KZs"
}';
$jssdk = new JSSDK("wwbce72cb895ea9678", "EMRcSyvbkXUfa-WTaHZ3nkBFm_WQUVmQI2LjXBibkPo");
$token = $jssdk->getAccessToken();
echo $rdata."\n";
$url="https://qyapi.weixin.qq.com/cgi-bin/externalcontact/remark?access_token=".$token;
$res=$jssdk->api_notice_increment($url, $rdata);
//$url="https://qyapi.weixin.qq.com/cgi-bin/externalcontact/list?access_token=".$token."&userid=".$uid;
//$url = "https://qyapi.weixin.qq.com/cgi-bin/externalcontact/get?access_token=".$token."&external_userid=".$eid;
//$res = $jssdk->httpGet($url);
var_dump($res);
exit(0);
*/
//Get all follows
/*
$token = $jssdk->getAccessToken();
$url = "https://qyapi.weixin.qq.com/cgi-bin/externalcontact/get_follow_user_list?access_token=".$token;
$res = $jssdk->httpGet($url);
$obj = json_decode($res);
if ($obj["errcode"] == 0) {
$follows = $obj["follow_user"];
}
foreach($userid in $follows) {
$url
}
$uid="ZhouShiChun";
$eid="wmmWd-CgAATwRz6cJuKpduKezVX2h-sg";
$rdata='{
"userid": "ZhouShiChun",
"external_userid": "wmmWd-CgAATwRz6cJuKpduKezVX2h-sg",
"remark_mobiles": ["13800000002"] }';
$r2data='{
"unionid":"owxhs51dkeYBz6pv4r_PWkXu_KZs"
}';
//$url="https://qyapi.weixin.qq.com/cgi-bin/externalcontact/list?access_token=".$token."&userid=".$uid;
//$url="https://qyapi.weixin.qq.com/cgi-bin/externalcontact/remark?access_token=".$token;
$url = "https://qyapi.weixin.qq.com/cgi-bin/externalcontact/unionid_to_external_userid?access_token=".$token;
$res=$jssdk->api_notice_increment($url, $r2data);
//$url="https://qyapi.weixin.qq.com/cgi-bin/externalcontact/get_follow_user_list?access_token=".$token;
//$url="https://qyapi.weixin.qq.com/cgi-bin/externalcontact/get?access_token=".$token."&external_userid=".$eid;
$res = $jssdk->httpGet($url);
*/
本文介绍了一个使用企业微信内部开发接口通过unionid来修改客户备注信息和手机号的案例。首先,讲解了unionid在企业微信平台的作用以及Redis作为缓存的用途。然后,详细阐述了设计目的,即通过已知unionid修改客户备注和手机号,并提供了实现方法,包括获取客户详情、使用Redis存储数据以及调用企业微信接口进行修改。最后,提供了部分PHP代码实现。

4318

被折叠的 条评论
为什么被折叠?



