Showing preview only (528K chars total). Download the full file or copy to clipboard to get everything.
Repository: dodgepudding/wechat-php-sdk
Branch: master
Commit: c18ee0176392
Files: 44
Total size: 508.9 KB
Directory structure:
gitextract_4iqk6cac/
├── .gitignore
├── Codeigniter/
│ └── CI_Wechat.php
├── README.md
├── Thinkphp/
│ ├── EasyWechat.class.php
│ ├── JsSdkPay.class.php
│ ├── TPWechat.class.php
│ └── Wxauth.class.php
├── composer.json
├── demo.php
├── errCode.php
├── old_version/
│ ├── Thinkphp/
│ │ ├── Snoopy.class.php
│ │ ├── Wechatauth.class.php
│ │ ├── Wechatext.class.php
│ │ └── Wechatpay.class.php
│ ├── snoopy.class.php
│ ├── test/
│ │ ├── test2.php
│ │ ├── test3.php
│ │ └── weshare.html
│ ├── wechat.js
│ ├── wechatauth.class.php
│ ├── wechatext.class.php
│ └── wechatpay.class.php
├── qyerrCode.php
├── qywechat.class.php
├── test/
│ ├── auth.php
│ ├── getQRCode_test.php
│ ├── jsapi/
│ │ ├── jsapi-demo-6.1.js
│ │ ├── jsapi_demo.php
│ │ └── style.css
│ ├── merchanttest.php
│ ├── qydemo.php
│ ├── test-upload-shake-around-media.php
│ └── test1.php
├── wechat.class.php
└── wiki/
├── API接口错误码.md
├── Home.md
├── README.md
├── 为开发框架进行适配.md
├── 企业号API类库.md
├── 内嵌JS.md
├── 官方API类库.md
├── 授权登陆类库.md
├── 旧版微信支付V2接口类库.md
└── 非官方扩展类库.md
================================================
FILE CONTENTS
================================================
================================================
FILE: .gitignore
================================================
/nbproject/private/
.buildpath
/pages/
/my/
================================================
FILE: Codeigniter/CI_Wechat.php
================================================
<?php
defined('BASEPATH') OR exit('No direct script access allowed');
/**
* 微信公众平台PHP-SDK, Codeigniter实例
* @author nigelvon@gmail.com
* @link https://github.com/dodgepudding/wechat-php-sdk
* usage:
* $this->load->library('CI_Wechat');
* $this->ci_wechat->valid();
* ...
*
*/
require_once(dirname(__FILE__) . '/wechat-php-sdk/wechat.class.php');
class CI_Wechat extends Wechat {
protected $_CI;
public function __construct() {
$this->_CI =& get_instance();
$this->_CI->config->load('wechat');
$options = $this->_CI->config->item('wechat');
$this->_CI->load->driver('cache', array('adapter' => 'apc', 'backup' => 'file'));
parent::__construct($options);
}
/**
* 重载设置缓存
* @param string $cachename
* @param mixed $value
* @param int $expired
* @return boolean
*/
protected function setCache($cachename, $value, $expired) {
return $this->_CI->cache->save($cachename, $value, $expired);
}
/**
* 重载获取缓存
* @param string $cachename
* @return mixed
*/
protected function getCache($cachename) {
return $this->_CI->cache->get($cachename);
}
/**
* 重载清除缓存
* @param string $cachename
* @return boolean
*/
protected function removeCache($cachename) {
return $this->_CI->cache->delete($cachename);
}
}
/* End of file CI_Wechat.php */
/* Location: ./application/libraries/CI_Wechat.php */
================================================
FILE: README.md
================================================
wechat-php-sdk
==============
微信公众平台php开发包,细化各项接口操作,支持链式调用,欢迎Fork此项目
weixin developer SDK.
项目地址:**https://github.com/dodgepudding/wechat-php-sdk**
项目blog:**http://binsee.github.io/wechat-php-sdk**
## 使用详解
使用前需先打开微信帐号的开发模式,详细步骤请查看微信公众平台接口使用说明:
微信公众平台: http://mp.weixin.qq.com/wiki/
微信企业平台: http://qydev.weixin.qq.com/wiki/
微信支付接入文档:
https://mp.weixin.qq.com/cgi-bin/readtemplate?t=business/course2_tmpl&lang=zh_CN
微信多客服:http://dkf.qq.com
## 目录
> **[wechat.class.php 官方API类库](#user-content-1-wechatclassphp-官方api类库)**
> **[qywechat.class.php 企业号API类库](#user-content-6-qywechatclassphp-企业号api类库)**
> **[errCode.php|qyerrCode.php 全局返回码类](#user-content-5-errcodephp-全局返回码类)**
> **[old_version/wechatpay.class.php 旧版微信支付V2接口类库](#user-content-7-wechatpayclassphp-旧版微信支付V2接口类库)**
> ~~**[old_version/wechatext.class.php 非官方扩展API(停止维护)](#user-content-2-wechatextclassphp-非官方扩展api)**~~
> ~~**[old_version/wechatauth.class.php 授权登陆(停止维护)](#user-content-3-wechatauthclassphp-授权登陆)**~~
> ~~**[old_version/wechat.js 内嵌JS(已废弃)](#user-content-4-wechatjs-内嵌js)**~~
> **[为开发框架进行适配](#user-content-为开发框架进行适配)**
> **[调用示例](#user-content-调用示例)**
----------
## 1. wechat.class.php 官方API类库
调用官方API,具有更灵活的消息分类响应方式,支持链式调用操作 ;
### 主要功能
- 接入验证 **(初级权限)**
- 自动回复(文本、图片、语音、视频、音乐、图文) **(初级权限)**
- 菜单操作(查询、创建、删除) **(菜单权限)**
- 客服消息(文本、图片、语音、视频、音乐、图文) **(认证权限)**
- 二维码(创建临时、永久二维码,获取二维码URL) **(服务号、认证权限)**
- 长链接转短链接接口 **(服务号、认证权限)**
- 分组操作(查询、创建、修改、移动用户到分组) **(认证权限)**
- 网页授权(基本授权,用户信息授权) **(服务号、认证权限)**
- 用户信息(查询用户基本信息、获取关注者列表) **(认证权限)**
- 多客服功能(客服管理、获取客服记录、客服会话管理) **(认证权限)**
- 媒体文件(上传、获取) **(认证权限)**
- 高级群发 **(认证权限)**
- 模板消息(设置所属行业、添加模板、发送模板消息) **(服务号、认证权限)**
- 卡券管理(创建、修改、删除、发放、门店管理等) **(认证权限)**
- 语义理解 **(服务号、认证权限)**
- 获取微信服务器IP列表 **(初级权限)**
- 微信JSAPI授权(获取ticket、获取签名) **(初级权限)**
- 数据统计(用户、图文、消息、接口分析数据) **(认证权限)**
> 备注:
> 初级权限:基本权限,任何正常的公众号都有此权限
> 菜单权限:正常的服务号、认证后的订阅号拥有此权限
> 认证权限:分为订阅号、服务号认证,如前缀服务号则仅认证的服务号有此权限,否则为认证后的订阅号、服务号都有此权限
> 支付权限:仅认证后的服务号可以申请此权限
### 初始化动作
```php
$options = array(
'token'=>'tokenaccesskey', //填写你设定的key
'encodingaeskey'=>'encodingaeskey', //填写加密用的EncodingAESKey
'appid'=>'wxdk1234567890', //填写高级调用功能的app id, 请在微信开发模式后台查询
'appsecret'=>'xxxxxxxxxxxxxxxxxxx' //填写高级调用功能的密钥
);
$weObj = new Wechat($options); //创建实例对象
//TODO:调用$weObj各实例方法
```
### 被动接口方法:
* valid() 验证连接,被动接口处于加密模式时必须调用
*
* getRev() 获取微信服务器发来信息(不返回结果),被动接口必须调用
* getRevData() 返回微信服务器发来的信息(数组)
* getRevFrom() 返回消息发送者的userid
* getRevTo() 返回消息接收者的id(即公众号id)
* getRevType() 返回接收消息的类型
* getRevID() 返回消息id
* getRevCtime() 返回消息发送时间
* getRevContent() 返回消息内容正文或语音识别结果(文本型)
* getRevPic() 返回图片信息(图片型信息) 返回数组{'mediaid'=>'','picurl'=>''}
* getRevLink() 接收消息链接(链接型信息) 返回数组{'url'=>'','title'=>'','description'=>''}
* getRevGeo() 返回地理位置(位置型信息) 返回数组{'x'=>'','y'=>'','scale'=>'','label'=>''}
* getRevEventGeo() 返回事件地理位置(事件型信息) 返回数组{'x'=>'','y'=>'','precision'=>''}
* getRevEvent() 返回事件类型(事件型信息) 返回数组{'event'=>'','key'=>''}
* getRevScanInfo() 获取自定义菜单的扫码推事件信息,事件类型为`scancode_push`或`scancode_waitmsg` 返回数组array ('ScanType'=>'qrcode','ScanResult'=>'123123')
* getRevSendPicsInfo() 获取自定义菜单的图片发送事件信息,事件类型为`pic_sysphoto`或`pic_photo_or_album`或`pic_weixin` 数组结构见php文件内方法说明
* getRevSendGeoInfo() 获取自定义菜单的地理位置选择器事件推送,事件类型为`location_select` 数组结构见php文件内方法说明
* getRevVoice() 返回语音信息(语音型信息) 返回数组{'mediaid'=>'','format'=>''}
* getRevVideo() 返回视频信息(视频型信息) 返回数组{'mediaid'=>'','thumbmediaid'=>''}
* getRevTicket() 返回接收TICKET(扫描带参数二维码,关注或SCAN事件) 返回二维码的ticket值
* getRevSceneId() 返回二维码的场景值(扫描带参数二维码的关注事件) 返回二维码的参数值
* getRevTplMsgID() 返回主动推送的消息ID(群发或模板消息事件) 返回MsgID值
* getRevStatus() 返回模板消息发送状态(模板消息事件) 返回文本:success(成功)|failed:user block(用户拒绝接收)|failed: system failed(发送失败(非用户拒绝))
* getRevResult() 返回群发或模板消息发送结果(群发或模板消息事件) 返回数组,内容依事件类型而不同,参考开发文档中群发、模板消息推送事件
* getRevKFCreate() 返回多客服-接入会话的客服账号(多客服-接入会话事件) 返回文本型
* getRevKFClose() 返回多客服-处理会话的客服账号(多客服-接入会话事件) 返回文本型
* getRevKFSwitch() 返回多客服-转接会话信息(多客服-转接会话事件) 返回数组 {'FromKfAccount' => '','ToKfAccount' => ''}
* getRevCardPass() 返回卡券-审核通过的卡券ID(卡券-卡券审核事件) 返回文本型
* getRevCardGet() 返回卡券-用户领取卡券的相关信息(卡券-领取卡券事件) 返回数组{'CardId' => '','IsGiveByFriend' => '','UserCardCode' => ''}
* getRevCardDel() 返回卡券-用户删除卡券的相关信息(卡券-删除卡券事件) 返回数组{'CardId' => '','UserCardCode' => ''}
*
* text($text) 设置文本型消息,参数:文本内容
* image($mediaid) 设置图片型消息,参数:图片的media_id
* voice($mediaid) 设置语音型消息,参数:语音的media_id
* video($mediaid='',$title,$description) 设置视频型消息,参数:视频的media_id、标题、摘要
* music($title,$desc,$musicurl,$hgmusicurl='',$thumbmediaid='') 设置回复音乐,参数:音乐标题、音乐描述、音乐链接、高音质链接、缩略图的媒体id
* news($newsData) 设置图文型消息,参数:数组。数组结构见php文件内方法说明
* Message($msg = '',$append = false) 设置发送的消息(一般不需要调用这个方法)
* transfer_customer_service($customer_account = '') 转接多客服,如不指定客服可不提供参数,参数:指定客服的账号
* reply() 将以上已经设置好的消息,回复给微信服务器
### 预定义常量列表:
```php
////消息类型,使用实例调用getRevType()方法取得
const MSGTYPE_TEXT = 'text';
const MSGTYPE_IMAGE = 'image';
const MSGTYPE_LOCATION = 'location';
const MSGTYPE_LINK = 'link';
const MSGTYPE_EVENT = 'event';
const MSGTYPE_MUSIC = 'music';
const MSGTYPE_NEWS = 'news';
const MSGTYPE_VOICE = 'voice';
const MSGTYPE_VIDEO = 'video';
////事件类型,使用实例调用getRevEvent()方法取得
const EVENT_SUBSCRIBE = 'subscribe'; //订阅
const EVENT_UNSUBSCRIBE = 'unsubscribe'; //取消订阅
const EVENT_SCAN = 'SCAN'; //扫描带参数二维码
const EVENT_LOCATION = 'LOCATION'; //上报地理位置
const EVENT_MENU_VIEW = 'VIEW'; //菜单 - 点击菜单跳转链接
const EVENT_MENU_CLICK = 'CLICK'; //菜单 - 点击菜单拉取消息
const EVENT_MENU_SCAN_PUSH = 'scancode_push'; //菜单 - 扫码推事件(客户端跳URL)
const EVENT_MENU_SCAN_WAITMSG = 'scancode_waitmsg'; //菜单 - 扫码推事件(客户端不跳URL)
const EVENT_MENU_PIC_SYS = 'pic_sysphoto'; //菜单 - 弹出系统拍照发图
const EVENT_MENU_PIC_PHOTO = 'pic_photo_or_album'; //菜单 - 弹出拍照或者相册发图
const EVENT_MENU_PIC_WEIXIN = 'pic_weixin'; //菜单 - 弹出微信相册发图器
const EVENT_MENU_LOCATION = 'location_select'; //菜单 - 弹出地理位置选择器
const EVENT_SEND_MASS = 'MASSSENDJOBFINISH'; //发送结果 - 高级群发完成
const EVENT_SEND_TEMPLATE = 'TEMPLATESENDJOBFINISH';//发送结果 - 模板消息发送结果
const EVENT_KF_SEESION_CREATE = 'kfcreatesession'; //多客服 - 接入会话
const EVENT_KF_SEESION_CLOSE = 'kfclosesession'; //多客服 - 关闭会话
const EVENT_KF_SEESION_SWITCH = 'kfswitchsession'; //多客服 - 转接会话
const EVENT_CARD_PASS = 'card_pass_check'; //卡券 - 审核通过
const EVENT_CARD_NOTPASS = 'card_not_pass_check'; //卡券 - 审核未通过
const EVENT_CARD_USER_GET = 'user_get_card'; //卡券 - 用户领取卡券
const EVENT_CARD_USER_DEL = 'user_del_card'; //卡券 - 用户删除卡券
```
### 主动接口方法:
* checkAuth($appid,$appsecret,$token) 此处传入公众后台高级接口提供的appid和appsecret, 或者手动指定$token为access_token。函数将返回access_token操作令牌
* resetAuth($appid='') 删除验证数据
* resetJsTicket($appid='') 删除JSAPI授权TICKET
* getJsTicket($appid='',$jsapi_ticket='') 获取JSAPI授权TICKET
* getJsSign($url, $timestamp=0, $noncestr='', $appid='') 获取JsApi使用签名信息数组,可只提供url地址
* createMenu($data) 创建菜单 $data菜单结构详见 **[自定义菜单创建接口](http://mp.weixin.qq.com/wiki/index.php?title=自定义菜单创建接口)**
* getServerIp() 获取微信服务器IP地址列表 返回数组array('127.0.0.1','127.0.0.1')
* getMenu() 获取菜单
* deleteMenu() 删除菜单
* uploadMedia($data, $type) 上传临时素材,有效期为3天(注意上传大文件时可能需要先调用 set_time_limit(0) 避免超时)
* getMedia($media_id,$is_video=false) 获取临时素材(含接收到的音频、视频媒体文件)
* uploadForeverMedia($data, $type,$is_video=false,$video_info=array()) 上传永久素材,可以在公众平台官网素材管理模块中看到
* uploadForeverArticles($data) 上传永久图文素材
* updateForeverArticles($media_id,$data,$index=0) 修改永久图文素材(认证后的订阅号可用)
* getForeverMedia($media_id,$is_video=false) 获取永久素材
* delForeverMedia($media_id) 删除永久素材
* getForeverList($type,$offset,$count) 获取永久素材列表(认证后的订阅号可用)
* getForeverCount() 获取永久素材总数
* uploadMpVideo($data) 上传视频素材,当需要群发视频时,必须使用此方法得到的MediaID,否则无法显示
* uploadArticles($data) 上传图文消息素材
* sendMassMessage($data) 高级群发消息
* sendGroupMassMessage($data) 高级群发消息(全体或分组群发)
* deleteMassMessage($msg_id) 删除群发图文消息
* previewMassMessage($data) 预览群发消息
* queryMassMessage($msg_id) 查询群发消息发送状态
* getQRCode($scene_id,$type=0,$expire=1800) 获取推广二维码ticket字串
* getQRUrl($ticket) 获取二维码图片地址
* getShortUrl($long_url) 长链接转短链接接口
* getUserList($next_openid) 批量获取关注用户列表
* getUserInfo($openid) 获取关注者详细信息
* updateUserRemark($openid,$remark) 设置用户备注名
* getGroup() 获取用户分组列表
* getUserGroup($openid) 获取用户所在分组
* createGroup($name) 新增自定分组
* updateGroup($groupid,$name) 更改分组名称
* updateGroupMembers($groupid,$openid) 移动用户分组
* batchUpdateGroupMembers($groupid,$openid_list) 批量移动用户分组
* sendCustomMessage($data) 发送客服消息
* getOauthRedirect($callback,$state,$scope) 获取网页授权oAuth跳转地址
* getOauthAccessToken() 通过回调的code获取网页授权access_token
* getOauthRefreshToken($refresh_token) 通过refresh_token对access_token续期
* getOauthUserinfo($access_token,$openid) 通过网页授权的access_token获取用户资料
* getOauthAuth($access_token,$openid) 检验授权凭证access_token是否有效
* getSignature($arrdata,'sha1') 生成签名字串
* generateNonceStr($length=16) 获取随机字串
* setTMIndustry($id1,$id2='') 模板消息,设置所属行业
* addTemplateMessage($tpl_id) 模板消息,添加消息模板
* sendTemplateMessage($data) 发送模板消息
*
* 多客服接口:
* getCustomServiceMessage($data) 获取多客服会话记录
* transfer_customer_service($customer_account) 转发多客服消息
* getCustomServiceKFlist() 获取多客服客服基本信息
* getCustomServiceOnlineKFlist() 获取多客服在线客服接待信息
* createKFSession($openid,$kf_account,$text='') 创建指定多客服会话
* closeKFSession($openid,$kf_account,$text='') 关闭指定多客服会话
* getKFSession($openid) 获取用户会话状态
* getKFSessionlist($kf_account) 获取指定客服的会话列表
* getKFSessionWait() 获取未接入会话列表
* addKFAccount($account,$nickname,$password) 添加客服账号
* updateKFAccount($account,$nickname,$password) 修改客服账号信息
* deleteKFAccount($account) 删除客服账号
* setKFHeadImg($account,$imgfile) 上传客服头像
*
* querySemantic($uid,$query,$category,$latitude=0,$longitude=0,$city="",$region="") 语义理解接口 参数含义及返回的json内容请查看 **[微信语义理解接口](http://mp.weixin.qq.com/wiki/index.php?title=语义理解)**
* getDatacube($type,$subtype,$begin_date,$end_date='') 获取统计数据 参数需注意$type与$subtype的定义
> 获取统计数据方法 参数定义
>
| 数据分类 | $type值(字符串) | 数据子分类 | $subtype值(字符串) | 时间跨度(天) |
| --------- | :-------: | --------- | :------: | ----: |
| 用户分析 | 'user' | 获取用户增减数据 | 'summary' | 7 |
| 用户分析 | 'user' | 获取累计用户数据 | 'cumulate' | 7 |
| 图文分析 | 'article' | 获取图文群发每日数据 | 'summary' | 1 |
| 图文分析 | 'article' | 获取图文群发总数据 | 'total' | 1 |
| 图文分析 | 'article' | 获取图文统计数据 | 'read' | 3 |
| 图文分析 | 'article' | 获取图文统计分时数据 | 'readhour' | 1 |
| 图文分析 | 'article' | 获取图文分享转发数据 | 'share' | 7 |
| 图文分析 | 'article' | 获取图文分享转发分时数据 | 'sharehour' | 1 |
| 消息分析 | 'upstreammsg' | 获取消息发送概况数据 | 'summary' | 7 |
| 消息分析 | 'upstreammsg' | 获取消息分送分时数据 | 'hour' | 1 |
| 消息分析 | 'upstreammsg' | 获取消息发送周数据 | 'week' | 30 |
| 消息分析 | 'upstreammsg' | 获取消息发送月数据 | 'month' | 30 |
| 消息分析 | 'upstreammsg' | 获取消息发送分布数据 | 'dist' | 15 |
| 消息分析 | 'upstreammsg' | 获取消息发送分布周数据 | 'distweek' | 30 |
| 消息分析 | 'upstreammsg' | 获取消息发送分布月数据 | 'distmonth' | 30 |
| 接口分析 | 'interface' | 获取接口分析数据 | 'summary' | 30 |
| 接口分析 | 'interface' | 获取接口分析分时数据 | 'summaryhour' | 1 |
需要注意 `begin_date`和`end_date`的差值需小于“最大时间跨度”(比如最大时间跨度为1时,`begin_date`和`end_date`的差值只能为0,才能小于1)
*
* 卡券接口:
* createCard($data) 创建卡券
* updateCard($data) 修改卡券
* delCard($card_id) 删除卡券
* getCardInfo($card_id) 查询卡券详情
* getCardColors() 获取颜色列表
* getCardLocations() 拉取门店列表
* addCardLocations($data) 批量导入门店信息
* createCardQrcode($card_id) 生成卡券二维码
* consumeCardCode($code) 消耗 code
* decryptCardCode($encrypt_code) code 解码
* checkCardCode($code) 获取 code 的有效性
* getCardIdList($data) 批量查询卡列表
* updateCardCode($code,$card_id,$new_code) 更改 code
* unavailableCardCode($code,$card_id='') 设置卡券失效**(不可逆)**
* modifyCardStock($data) 库存修改
* activateMemberCard($data) 激活/绑定会员卡,参数结构请参看卡券开发文档(6.1.1 激活/绑定会员卡)章节
* updateMemberCard($data) 会员卡交易,参数结构请参看卡券开发文档(6.1.2 会员卡交易)章节
* updateLuckyMoney($code,$balance,$card_id='') 更新红包金额
* setCardTestWhiteList($openid=array(),$user=array()) 设置卡券测试白名单
*
* 摇一摇周边接口:
* applyShakeAroundDevice($data) 申请设备ID
* updateShakeAroundDevice($data) 编辑设备的备注信息
* searchShakeAroundDevice($data) 查询设备列表
* bindLocationShakeAroundDevice($device_id,$poi_id,$uuid='',$major=0,$minor=0) 配置设备与门店的关联关系
* bindPageShakeAroundDevice($device_id,$page_ids=array(),$bind=1,$append=1,$uuid='',$major=0,$minor=0) 配置设备与页面的关联关系
* uploadShakeAroundMedia($data) 上传在摇一摇页面展示的图片素材
* addShakeAroundPage($title,$description,$icon_url,$page_url,$comment='') 新增摇一摇出来的页面信息
* updateShakeAroundPage($page_id,$title,$description,$icon_url,$page_url,$comment='') 编辑摇一摇出来的页面信息
* searchShakeAroundPage($page_ids=array(),$begin=0,$count=1) 查询摇一摇已有的页面
* deleteShakeAroundPage($page_ids=array()) 删除摇一摇已有的页面,必须是未与设备关联的页面
* getShakeInfoShakeAroundUser($ticket) 获取摇周边的设备及用户信息
* deviceShakeAroundStatistics($device_id,$begin_date,$end_date,$uuid='',$major=0,$minor=0) 以设备为维度的数据统计接口
* pageShakeAroundStatistics($page_id,$begin_date,$end_date) 以页面为维度的数据统计接口
## ~~2. wechatext.class.php 非官方扩展API~~
**此扩展类库已经不再更新,原因是官方对公众号开放了众多接口,此类库继续维护的意义不大**
非官方扩展API,需要配置公众平台账户和密码,能实现对已关注用户的点对点微信,此方式不保证长期有效。
类方法里提及的用户id在接口返回结构里表述为FakeId, 属同一概念, 在下面wechatauth类里则表示为Uin, 用户id对应的微信号必须通过getInfo()方法通过返回数组的Username值获取, 但非关注关系用户资料不能获取.
调用下列方法前必须经过login()方法和checkValid()验证方法才能获得调用权限. 有的账户无法通过登陆可能因为要求提供验证码, 可以手动登陆后把获取到的cookie写进程序存放cookie的文件解决.
程序使用了经过修改的snoopy兼容式HTTP类方法, 在类似BAE/SAE云服务器上可能不能正常运行, 因为云服务的curl方法是经过重写的, 某些header参数如网站来源参数不被支持.
### 类主要方法:
* send($id,$content) 向某用户id发送微信文字信息
* sendNews($id,$msgid) 发送图文消息, 可通过getNewsList获取$msgid
* getUserList($page,$pagesize,$groupid) 获取用户信息
* getGroupList($page,$pagesize) 获取群组信息
* getNewsList($page,$pagesize) 获取图文信息列表
* uploadFile($filepath,$type) 上传附件,包括图片/音频/视频/缩略图
* getFileList($type,$page,$pagesize) 获取素材库文件列表
* sendImage($id,$fid) 发送图片消息
* sendAudio($id,$fid) 发送音频消息
* sendVideo($id,$fid) 发送视频消息
* getInfo($id) 根据id获取用户资料,注: 非关注关系用户资料不能获取
* getNewMsgNum($lastid) 获取从$lastid算起新消息的数目
* getTopMsg() 获取最新一条消息的数据, 此方法获取的消息id可以作为检测新消息的$lastid依据
* getMsg($lastid,$offset=0,$perpage=50,$day=0,$today=0,$star=0) 获取最新的消息列表, 列表将返回消息id, 用户id, 消息类型, 文字消息等参数
* 消息返回结构: {"id":"消息id","type":"类型号(1为文字,2为图片,3为语音)","fileId":"0","hasReply":"0","fakeId":"用户uid","nickName":"昵称","dateTime":"时间戳","content":"文字内容"}
* getMsgImage($msgid,$mode='large') 若消息type类型为2, 调用此方法获取图片数据
* getMsgVoice($msgid) 若消息type类型为3, 调用此方法获取语音数据
## ~~3. wechatauth.class.php 授权登陆~~
**此扩展类库已经不再更新,原因是官方开放平台对网站应用开放的有授权登陆接口,更标准,更好用。请查看:[微信开放平台](http://open.weixin.qq.com)**
通过微信二维码登陆微信的API, 能实现第三方网站同步登陆, 首先程序分别通过get_login_code和get_code_image方法获取授权二维码图片, 然后利用微信手机客户端扫描二维码图片后将自动跳出授权页面, 用户点击授权后即可获取对应的用户资料和头像信息. 详细验证步骤请看test3.php例子.
### 类主要方法:
* get_login_code() 获取登陆授权码, 通过授权码才能获取二维码
* get_code_image($code='') 将上面获取的授权码转换为图片二维码
* verify_code() 鉴定是否登陆成功,返回200为最终授权成功.
* get_login_info() 鉴定成功后调用此方法即可获取用户基本信息
* get_avatar($url) 获取用户头像图片数据
* logout() 注销登陆
## ~~4. wechat.js 内嵌JS~~
**此JS脚本已经废弃不再更新,原因是官方在微信6.0.2版本开放了全新的JSAPI接口,更全面好用。请查看:[微信公众平台WIKI](http://mp.weixin.qq.com/wiki)**
### 微信内嵌网页特殊功能js调用:
* WeixinJS.hideOptionMenu() 隐藏右上角按钮
* WeixinJS.showOptionMenu() 显示右上角按钮
* WeixinJS.hideToolbar() 隐藏工具栏
* WeixinJS.showToolbar() 显示工具栏
* WeixinJS.getNetworkType() 获取网络状态
* WeixinJS.closeWindow() 关闭窗口
* WeixinJS.scanQRCode() 扫描二维码
* WeixinJS.openUrlByExtBrowser(url) 使用浏览器打开网址
* WeixinJS.jumpToBizProfile(username) 跳转到指定公众账号页面
* WeixinJS.sendEmail(title,content) 发送邮件
* WeixinJS.openProductView(latitude,longitude,name,address,scale,infoUrl) 查看地图
* WeixinJS.addContact(username) 添加微信账号
* WeixinJS.imagePreview(urls,current) 调出微信内图片预览
* WeixinJS.payCallback(appId,package,timeStamp,nonceStr,signType,paySign,callback) 微信JsApi支付接口
* WeixinJS.editAddress(appId,addrSign,timeStamp,nonceStr,callback) 微信JsApi支付接口
* 通过定义全局变量dataForWeixin配置触发分享的内容:
```javascript
var dataForWeixin={
appId:"",
MsgImg:"消息图片路径",
TLImg:"时间线图路径",
url:"分享url路径",
title:"标题",
desc:"描述",
fakeid:"",
callback:function(){}
};
```
## 5. errCode.php 全局返回码类
当调用API接口失败时,可以用此类来获取失败原因的中文说明。
注意:微信公众号引用`errCode.php`,企业号引用`qyerrCode.php`。
### 使用方法:
```php
include "errCode.php"; //或 qyerrCode.php
$ret=ErrCode::getErrText(48001); //错误码可以通过公众号类库的公开变量errCode得到
if ($ret)
echo $ret;
else
echo "未找到对应的内容";
```
## 6. qywechat.class.php 企业号API类库
调用官方API,具有更灵活的消息分类响应方式,支持链式调用操作 ;
### 主要功能
- 接入验证
- 自动回复(文本、图片、语音、视频、音乐、图文)
- 菜单操作(查询、创建、删除)
- 部门管理(创建、更新、删除、获取部门列表)
- 成员管理(创建、更新、删除、获取成员信息,获取部门成员列表)
- 标签管理(创建、更新、删除、获取成员、添加成员、删除成员,获取标签列表)
- 媒体文件管理(上传、获取)
- 二次验证
- OAuth2(生成授权url、获取成员信息)
- 获取企业微信服务器IP列表
- 微信JSAPI授权(获取ticket、获取签名)
### 初始化动作
```php
$options = array(
'token'=>'tokenaccesskey', //填写应用接口的Token
'encodingaeskey'=>'encodingaeskey', //填写加密用的EncodingAESKey
'appid'=>'wxdk1234567890', //填写高级调用功能的app id
'appsecret'=>'xxxxxxxxxxxxxxxxxxx', //填写高级调用功能的密钥
'agentid'=>'1', //应用的id
'debug'=>false, //调试开关
'_logcallback'=>'logg', //调试输出方法,需要有一个string类型的参数
);
$weObj = new Wechat($options); //创建实例对象
//TODO:调用$weObj各实例方法
```
### 被动接口方法:
* valid() 验证连接,被动接口必须调用
*
* getRev() 获取微信服务器发来信息(不返回结果),被动接口必须调用
* getRevData() 返回微信服务器发来的信息(数组)
* getRevPostXml() 返回微信服务器发来的原始加密xml信息
* getRevFrom() 返回消息发送者的userid
* getRevTo() 返回消息接收者的id(即公众号id,一般与等同appid一致)
* getRevAgentID() 返回接收消息的应用id
* getRevType() 返回接收消息的类型
* getRevID() 返回消息id
* getRevCtime() 返回消息发送事件
* getRevContent() 返回消息内容正文(文本型消息)
* getRevPic() 返回图片信息(图片型信息) 返回数组{'mediaid'=>'','picurl'=>''}
* getRevGeo() 返回地理位置(位置型信息) 返回数组{'x'=>'','y'=>'','scale'=>'','label'=>''}
* getRevEventGeo() 返回事件地理位置(事件型信息) 返回数组{'x'=>'','y'=>'','precision'=>''}
* getRevEvent() 返回事件类型(事件型信息) 返回数组{'event'=>'','key'=>''}
* getRevScanInfo() 获取自定义菜单的扫码推事件信息,事件类型为`scancode_push`或`scancode_waitmsg` 返回数组array ('ScanType'=>'qrcode','ScanResult'=>'123123')
* getRevSendPicsInfo() 获取自定义菜单的图片发送事件信息,事件类型为`pic_sysphoto`或`pic_photo_or_album`或`pic_weixin` 数组结构见php文件内方法说明
* getRevSendGeoInfo() 获取自定义菜单的地理位置选择器事件推送,事件类型为`location_select` 数组结构见php文件内方法说明
* getRevVoice() 返回语音信息(语音型信息) 返回数组{'mediaid'=>'','format'=>''}
* getRevVideo() 返回视频信息(视频型信息) 返回数组{'mediaid'=>'','thumbmediaid'=>''}
*
* text($text) 设置文本型消息,参数:文本内容
* image($mediaid) 设置图片型消息,参数:图片的media_id
* voice($mediaid) 设置语音型消息,参数:语音的media_id
* video($mediaid='',$title,$description) 设置视频型消息,参数:视频的media_id、标题、摘要
* news($newsData) 设置图文型消息,参数:数组。数组结构见php文件内方法说明
* image($mediaid) 设置图片型消息,参数:图片的media_id
* Message($msg = '',$append = false) 设置发送的消息(一般不需要调用这个方法)
* reply() 将已经设置好的消息,回复给微信服务器
### 预定义常量列表:
```php
////消息类型,使用实例调用getRevType()方法取得
const MSGTYPE_TEXT = 'text';
const MSGTYPE_IMAGE = 'image';
const MSGTYPE_LOCATION = 'location';
const MSGTYPE_LINK = 'link'; //暂不支持
const MSGTYPE_EVENT = 'event';
const MSGTYPE_MUSIC = 'music'; //暂不支持
const MSGTYPE_NEWS = 'news';
const MSGTYPE_VOICE = 'voice';
const MSGTYPE_VIDEO = 'video';
////事件类型,使用实例调用getRevEvent()方法取得
const EVENT_SUBSCRIBE = 'subscribe'; //订阅
const EVENT_UNSUBSCRIBE = 'unsubscribe'; //取消订阅
const EVENT_LOCATION = 'LOCATION'; //上报地理位置
const EVENT_ENTER_AGENT = 'enter_agent'; //用户进入应用
const EVENT_MENU_VIEW = 'VIEW'; //菜单 - 点击菜单跳转链接
const EVENT_MENU_CLICK = 'CLICK'; //菜单 - 点击菜单拉取消息
const EVENT_MENU_SCAN_PUSH = 'scancode_push'; //菜单 - 扫码推事件(客户端跳URL)
const EVENT_MENU_SCAN_WAITMSG = 'scancode_waitmsg'; //菜单 - 扫码推事件(客户端不跳URL)
const EVENT_MENU_PIC_SYS = 'pic_sysphoto'; //菜单 - 弹出系统拍照发图
const EVENT_MENU_PIC_PHOTO = 'pic_photo_or_album'; //菜单 - 弹出拍照或者相册发图
const EVENT_MENU_PIC_WEIXIN = 'pic_weixin'; //菜单 - 弹出微信相册发图器
const EVENT_MENU_LOCATION = 'location_select'; //菜单 - 弹出地理位置选择器
const EVENT_SEND_MASS = 'MASSSENDJOBFINISH'; //发送结果 - 高级群发完成
const EVENT_SEND_TEMPLATE = 'TEMPLATESENDJOBFINISH';//发送结果 - 模板消息发送结果
```
### 主动接口方法:
* checkAuth($appid='',$appsecret='',$token='') 通用auth验证方法,也用来换取ACCESS_TOKEN 。仅在需要手动指定access_token时才用`$token`
* resetAuth($appid='') 清除记录的ACCESS_TOKEN
* resetJsTicket($appid='') 删除JSAPI授权TICKET
* getJsTicket($appid='',$jsapi_ticket='') 获取JSAPI授权TICKET
* getJsSign($url, $timestamp=0, $noncestr='', $appid='') 获取JsApi使用签名信息数组,可只提供url地址
* getSignature($arrdata,'sha1') 生成签名字串
* generateNonceStr($length=16) 获取随机字串
* createMenu($data,$agentid='') 创建菜单,参数:菜单内容数组,要创建菜单应用id
* getMenu($agentid='') 获取菜单内容,参数:要获取菜单内容的应用id
* deleteMenu($agentid='') 删除菜单,参数:要删除菜单的应用id
* uploadMedia($data, $type) 上传媒体文件,参数请看php文件内方法说明(注意上传大文件时可能需要先调用 set_time_limit(0) 避免超时)
* getMedia($media_id) 根据媒体文件ID获取媒体文件,参数:媒体id
* getServerIp() 获取企业微信服务器IP地址列表 返回数组array('127.0.0.1','127.0.0.1')
* createDepartment($data) 创建部门,参数: array("name"=>"邮箱产品组","parentid"=>"1","order" => "1")
* updateDepartment($data) 更新部门,参数: array("id"=>"1","name"=>"邮箱产品组","parentid"=>"1","order" => "1")
* deleteDepartment($id) 删除部门,参数:要删除的部门id
* moveDepartment($data) 移动部门,参数:array("department_id" => "5","to_parentid" => "2","to_position" => "1")
* getDepartment() 获取部门列表,返回部门数组。其中department部门列表数据。以部门的order字段从小到大排列
* createUser($data) 创建成员,参数请看php文件内方法说明
* updateUser($data) 更新成员,参数请看php文件内方法说明
* deleteUser($userid) 删除成员,参数:员工UserID
* deleteUsers($userids) 批量删除成员,参数:员工UserID数组
* getUserInfo($userid) 获取成员信息,参数:员工UserID
* getUserList($department_id,$fetch_child=0,$status=0) 获取部门成员,参数:部门id,是否递归获取子部门,获取类型。
> 0获取全部员工,1获取已关注成员列表,2获取禁用成员列表,4获取未关注成员列表。status可叠加
* getUserListInfo($department_id,$fetch_child=0,$status=0) 获取部门成员详情,参数同上
* getUserId($code,$agentid) 根据code获取员工UserID与手机设备号,参数:Oauth2.0或者二次验证返回的code值,跳转链接时所在的企业应用ID
* sendInvite($userid,$invite_tips='') 邀请成员关注
* createTag($data) 创建标签,参数:array("tagname" => "UI")
* updateTag($data) 更新标签,参数:array("tagid" => "1","tagname" => "UI")
* deleteTag($tagid) 删除标签,参数:标签TagID
* getTag($tagid) 获取标签成员,参数:标签TagID
* addTagUser($data) 增加标签成员,参数请看php文件内方法说明
* delTagUser($data) 删除标签成员,参数请看php文件内方法说明
* getTagList() 获取标签列表,返回标签数组
* sendMessage($data) 主动发送信息接口,参数请看php文件内方法说明
* authSucc($userid) 二次验证,参数: 员工UserID
* getOauthRedirect($callback,$state='STATE',$scope='snsapi_base') 组合授权跳转接口url
## 7. wechatpay.class.php 旧版微信支付V2接口类库
旧版微信支付类库(微信支付V2),已移动至old_version目录下。
自2014年8月开始申请到的微信支付都是V3接口,据官方说V2的会陆续升级为V3接口,但时间及升级渠道未确认。
### 主要功能
- 获取access_token **(初级权限)**
- 调用地址组件 **(支付权限)**
- 生成订单签名数据 **(支付权限)**
- 订单成功回调 **(支付权限)**
- 发货通知 **(支付权限)**
- 支付订单查询 **(支付权限)**
> 备注:
> 初级权限:基本权限,任何正常的公众号都有此权限
> 菜单权限:正常的服务号、认证后的订阅号拥有此权限
> 认证权限:分为订阅号、服务号认证,如前缀服务号则仅认证的服务号有此权限,否则为认证后的订阅号、服务号都有此权限
> 支付权限:仅认证后的服务号可以申请此权限
### 初始化动作
```php
$options = array(
'appid'=>'wxdk1234567890', //填写高级调用功能的app id, 请在微信开发模式后台查询
'appsecret'=>'xxxxxxxxxxxxxxxxxxx', //填写高级调用功能的密钥
'partnerid'=>'88888888', //财付通商户身份标识,支付权限专用,没有可不填
'partnerkey'=>'', //财付通商户权限密钥Key,支付权限专用
'paysignkey'=>'' //商户签名密钥Key,支付权限专用
);
$weObj = new Wechat($options); //创建实例对象
//TODO:调用$weObj各实例方法
```
### 主动接口方法:
* checkAuth($appid='',$appsecret='',$token='') 获取access_token。可根据appid和appsecret获取,或手动指定access_token
* resetAuth($appid='') 删除验证数据
* getSignature($arrdata,'sha1') 生成签名字串
* generateNonceStr($length=16) 获取随机字串
* createNativeUrl($productid) 生成原生支付url
* createPackage($out_trade_no,$body,$total_fee,$notify_url,$spbill_create_ip,$fee_type=1,$bank_type="WX",$input_charset="UTF-8",$time_start="",$time_expire="",$transport_fee="",$product_fee="",$goods_tag="",$attach="") 生成订单package字符串
* getPaySign($package, $timeStamp, $nonceStr) 支付签名(paySign)生成方法
* checkOrderSignature($orderxml='') 回调通知签名验证
* sendPayDeliverNotify($openid,$transid,$out_trade_no,$status=1,$msg='ok') 发货通知
* getPayOrder($out_trade_no) 查询订单信息
* setUserToken($user_token) 设置用户授权密钥
* getAddrSign($url, $timeStamp, $nonceStr, $user_token='') 获取收货地址JS的签名
## 为开发框架进行适配
为不同的开发框架进行适配缓存操作(保存access_token、jsapi_ticket),及输出调试日志。
由于微信api需要缓存access_token与jsapi_ticket,而在不同框架下的缓存方式不同,所以原先在Wechat.class.php和QYWechat.class.php中缓存代码做了TODO标志。
需要各位在使用不同框架时再进行修改,但确实很麻烦,因为对结构进行了修改。
>取消了原先同步维护的Thinkphp版本,为Wechat类增加操作缓存3个重载方法`setCache`, `getCache`, `removeCache`,以及修改`log`方法可以重载。
>分别来实现在不同开发框架下的设置缓存、读取缓存、清除缓存、日志输出4个功能。
在不同的开发框架下使用Wechat类库,请继承Wechat类,根据需要实现这4个方法。
可参考Thinkphp版的`TPWechat.class.php`为不同框架进行适配。
欢迎提交其他框架的适配文件到项目库来。
为Thinkphp进行适配的示例如下:
```php
/**
* 微信公众平台PHP-SDK, ThinkPHP实例
* @author dodgepudding@gmail.com
* @link https://github.com/dodgepudding/wechat-php-sdk
* @version 1.2
* usage:
* $options = array(
* 'token'=>'tokenaccesskey', //填写你设定的key
* 'encodingaeskey'=>'encodingaeskey', //填写加密用的EncodingAESKey
* 'appid'=>'wxdk1234567890', //填写高级调用功能的app id
* 'appsecret'=>'xxxxxxxxxxxxxxxxxxx' //填写高级调用功能的密钥
* );
* $weObj = new TPWechat($options);
* $weObj->valid();
* ...
*
*/
class TPWechat extends Wechat
{
/**
* log overwrite
* @see Wechat::log()
*/
protected function log($log){
if ($this->debug) {
if (function_exists($this->logcallback)) {
if (is_array($log)) $log = print_r($log,true);
return call_user_func($this->logcallback,$log);
}elseif (class_exists('Log')) {
Log::write('wechat:'.$log, Log::DEBUG);
}
}
return false;
}
/**
* 重载设置缓存
* @param string $cachename
* @param mixed $value
* @param int $expired
* @return boolean
*/
protected function setCache($cachename,$value,$expired){
return S($cachename,$value,$expired);
}
/**
* 重载获取缓存
* @param string $cachename
* @return mixed
*/
protected function getCache($cachename){
return S($cachename);
}
/**
* 重载清除缓存
* @param string $cachename
* @return boolean
*/
protected function removeCache($cachename){
return S($cachename,null);
}
}
```
# 调用示例
----------
## 官方Wechat调用示例:
```php
//test1.php
include "wechat.class.php";
$options = array(
'token'=>'tokenaccesskey', //填写你设定的key
'encodingaeskey'=>'encodingaeskey' //填写加密用的EncodingAESKey,如接口为明文模式可忽略
);
$weObj = new Wechat($options);
$weObj->valid();//明文或兼容模式可以在接口验证通过后注释此句,但加密模式一定不能注释,否则会验证失败
$type = $weObj->getRev()->getRevType();
switch($type) {
case Wechat::MSGTYPE_TEXT:
$weObj->text("hello, I'm wechat")->reply();
exit;
break;
case Wechat::MSGTYPE_EVENT:
break;
case Wechat::MSGTYPE_IMAGE:
break;
default:
$weObj->text("help info")->reply();
}
```
## 企业号API类库调用示例:
可参考**test**目录下的**qydemo.php**
```php
include "wechat.class.php";
$options = array(
'token'=>'9Ixxxxxxx', //填写应用接口的Token
'encodingaeskey'=>'d4o9WVg8sxxxxxxxxxxxxxxxxxxxxxx',//填写加密用的EncodingAESKey
'appid'=>'wxa07979baxxxxxxxx', //填写高级调用功能的appid
);
$weObj = new Wechat($options);
$weObj->valid(); //注意, 企业号与普通公众号不同,必须打开验证,不要注释掉
$type = $weObj->getRev()->getRevType();
switch($type) {
case Wechat::MSGTYPE_TEXT:
$weObj->text("hello, I'm wechat")->reply();
exit;
break;
case Wechat::MSGTYPE_EVENT:
break;
case Wechat::MSGTYPE_IMAGE:
break;
default:
$weObj->text("help info")->reply();
}
```
## 扩展包Wechatext调用示例:
```php
// old_version/test/test2.php
include "wechatext.class.php";
function logdebug($text){
file_put_contents('./data/log.txt',$text."\n",FILE_APPEND);
};
$options = array(
'account'=>'demo@domain.com',
'password'=>'demo',
'datapath'=>'./data/cookie_',
'debug'=>true,
'logcallback'=>'logdebug'
);
$wechat = new Wechatext($options);
if ($wechat->checkValid()) {
// 获取用户信息
$data = $wechat->getInfo('3974255');
var_dump($data);
// 获取最新一条消息
$topmsg = $wechat->getTopMsg();
var_dump($topmsg);
// 主动回复消息
if ($topmsg && $topmsg['has_reply']==0)
$wechat->send($topmsg['fakeid'],'hi '.$topmsg['nick_name'].',rev:'.$topmsg['content']);
}
```
## 微信二维码Wechatauth登陆示例:
```php
// old_version/test/test3.php
include "../wechatauth.class.php";
session_start();
$sid = session_id();
$options = array(
'account'=>$sid,
'datapath'=>'../data/cookiecode_',
);
$wechat = new Wechatauth($options);
if (isset($_POST['code'])) {
$logincode = $_POST['code'];
$vres = $wechat->set_login_code($logincode)->verify_code();
if ($vres===false) {
$result = array('status'=>0);
} else {
$result = array('status'=>$vres);
if ($vres==200) {
$result['info'] = $wechat->get_login_info();
$result['cookie'] = $wechat->get_login_cookie(true);
}
}
die(json_encode($result));
}
$logincode = $wechat->get_login_code(); //获取授权码
$qrimg = $wechat->get_code_image(); //待输出的二维码图片
```
HTML部分请看old_version/test/test3.php, 主要是定时ajax查询是否已经授权成功
## 新版微信JSAPI调用DEMO:
请看test/jsapi目录
License
-------
This is licensed under the GNU LGPL, version 2.1 or later.
For details, see: http://creativecommons.org/licenses/LGPL/2.1/
================================================
FILE: Thinkphp/EasyWechat.class.php
================================================
<?php
/**
* 微信公众平台PHP-SDK, 简单缓存实例
* @author binsee@163.com
* @link https://github.com/binsee/wechat-php-sdk
* @version 0.1
* usage:
* $options = array(
* 'token'=>'tokenaccesskey', //填写你设定的key
* 'encodingaeskey'=>'encodingaeskey', //填写加密用的EncodingAESKey
* 'appid'=>'wxdk1234567890', //填写高级调用功能的app id
* 'cachedir'=>'./cache/', //填写缓存目录,默认为当前运行目录的子目录cache下
* 'logfile'=>'run.log' //填写日志输出文件,可选项。如果没有提供logcallback回调,且设置了输出文件则将日志输出至此文件,如果省略则不输出
* );
* $weObj = new EasyWechat($options);
* $weObj->valid();
* ...
*
*/
class EasyWechat extends Wechat
{
private $cachedir = '';
private $logfile = '';
public function __construct($options)
{
$this->cachedir = isset($options['cachedir']) ? dirname($options['cachedir'].'/.cache') . '/' : 'cache/';
$this->logfile = isset($options['logfile']) ? $options['logfile'] : '';
if ($this->cachedir) $this->checkDir($this->cachedir);
parent::__construct($options);
}
/**
* log overwrite
* @param string|array $log
*/
protected function log($log){
if (is_array($log)) $log = print_r($log,true);
if ($this->debug) {
if (function_exists($this->logcallback)) {
return call_user_func($this->logcallback,$log);
}elseif ($this->logfile) {
return file_put_contents($this->logfile, $log."\n", FILE_APPEND) > 0 ? true : false;
}
}
return false;
}
/**
* 重载设置缓存
* @param string $cachename
* @param mixed $value
* @param int $expired 缓存秒数,如果为0则为长期缓存
* @return boolean
*/
protected function setCache($cachename,$value,$expired=0){
$file = $this->cachedir . $cachename . '.cache';
$data = array(
'value' => $value,
'expired' => $expired ? time() + $expired : 0
);
return file_put_contents( $file, serialize($data) ) ? true : false;
}
/**
* 重载获取缓存
* @param string $cachename
* @return mixed
*/
protected function getCache($cachename){
$file = $this->cachedir . $cachename . '.cache';
if (!is_file($file)) {
return false;
}
$data = unserialize(file_get_contents( $file ));
if (!is_array($data) || !isset($data['value']) || (!empty($data['value']) && $data['expired']<time())) {
@unlink($file);
return false;
}
return $data['value'];
}
/**
* 重载清除缓存
* @param string $cachename
* @return boolean
*/
protected function removeCache($cachename){
$file = $this->cachedir . $cachename . '.cache';
if ( is_file($file) ) {
@unlink($file);
}
return true;
}
private function checkDir($dir, $mode=0777) {
if (!$dir) return false;
if(!is_dir($dir)) {
if (!file_exists($dir) && @mkdir($dir, $mode, true))
return true;
return false;
}
return true;
}
}
================================================
FILE: Thinkphp/JsSdkPay.class.php
================================================
<?php
/**
* 官方文档:http://mp.weixin.qq.com/wiki/7/aaa137b55fb2e0456bf8dd9148dd613f.html
* 微信支付:http://pay.weixin.qq.com/wiki/doc/api/index.php?chapter=9_1#
* 官方示例:http://demo.open.weixin.qq.com/jssdk/sample.zip
* UCToo示例:http://git.oschina.net/uctoo/uctoo/blob/master/Addons/Jssdk/Controller/JssdkController.class.php
*
* 微信JSSDK支付类,主要实现了微信JSSDK支付,参考官方提供的示例文档,
* @命名空间版本
* @author uctoo (www.uctoo.com)
* @date 2015-5-15 14:10
*/
namespace Com;
class JsSdkPay {
private $appId;
private $appSecret;
public $debug = false;
public $weObj; //微信类实例
public $parameters;//获取prepay_id时的请求参数
//受理商ID,身份标识
public $MCHID = '';
//商户支付密钥Key。审核通过后,在微信商户平台中查看 https://pay.weixin.qq.com
public $KEY = '';
//=======【JSAPI路径设置】===================================
//获取access_token过程中的跳转uri,通过跳转将code传入jsapi支付页面
public $JS_API_CALL_URL = '';
//=======【证书路径设置】=====================================
//证书路径,注意应该填写绝对路径
public $SSLCERT_PATH = '/xxx/xxx/xxxx/WxPayPubHelper/cacert/apiclient_cert.pem';
public $SSLKEY_PATH = '/xxx/xxx/xxxx/WxPayPubHelper/cacert/apiclient_key.pem';
//=======【异步通知url设置】===================================
//异步通知url,商户根据实际开发过程设定
//C('url')."admin.php/order/notify_url.html";
public $NOTIFY_URL = '';
//=======【curl超时设置】===================================
//本例程通过curl使用HTTP POST方法,此处可修改其超时时间,默认为30秒
public $CURL_TIMEOUT = 30;
public $prepay_id;
public function __construct($options) {
$this->appId = $options['appid'];
$this->appSecret = $options['appsecret'];
$this->weObj = new TPWechat($options);
}
//微信支付相关方法
/**
* 作用:格式化参数,签名过程需要使用
*/
function formatBizQueryParaMap($paraMap, $urlencode)
{
$buff = "";
ksort($paraMap);
foreach ($paraMap as $k => $v)
{
if($urlencode)
{
$v = urlencode($v);
}
//$buff .= strtolower($k) . "=" . $v . "&";
$buff .= $k . "=" . $v . "&";
}
$reqPar = "";
if (strlen($buff) > 0)
{
$reqPar = substr($buff, 0, strlen($buff)-1);
}
return $reqPar;
}
/**
* 作用:设置jsapi的参数
*/
public function getParameters()
{
$jsApiObj["appId"] = $this->appId; //请求生成支付签名时需要,js调起支付参数中不需要
$timeStamp = time();
$jsApiObj["timeStamp"] = "$timeStamp"; //用大写的timeStamp参数请求生成支付签名
$jsParamObj["timestamp"] = $timeStamp; //用小写的timestamp参数生成js支付参数,还要注意数据类型,坑!
$jsParamObj["nonceStr"] = $jsApiObj["nonceStr"] = $this->weObj->generateNonceStr();
$jsParamObj["package"] = $jsApiObj["package"] = "prepay_id=$this->prepay_id";
$jsParamObj["signType"] = $jsApiObj["signType"] = "MD5";
$jsParamObj["paySign"] = $jsApiObj["paySign"] = $this->getSign($jsApiObj);
$jsParam = json_encode($jsParamObj);
return $jsParam;
}
/**
* 获取prepay_id
*/
function getPrepayId()
{
$result = $this->xmlToArray($this->postXml());
$prepay_id = $result["prepay_id"];
return $prepay_id;
}
/**
* 作用:将xml转为array
*/
public function xmlToArray($xml)
{
//将XML转为array
$array_data = json_decode(json_encode(simplexml_load_string($xml, 'SimpleXMLElement', LIBXML_NOCDATA)), true);
return $array_data;
}
/**
* 作用:post请求xml
*/
function postXml()
{
$xml = $this->createXml();
return $this->postXmlCurl($xml,"https://api.mch.weixin.qq.com/pay/unifiedorder",$this->CURL_TIMEOUT);
}
/**
* 作用:以post方式提交xml到对应的接口url
*/
public function postXmlCurl($xml,$url,$second=30)
{
//初始化curl
$ch = curl_init();
//设置超时
curl_setopt($ch,CURLOP_TIMEOUT, $this->CURL_TIMEOUT);
//这里设置代理,如果有的话
//curl_setopt($ch,CURLOPT_PROXY, '8.8.8.8');
//curl_setopt($ch,CURLOPT_PROXYPORT, 8080);
curl_setopt($ch,CURLOPT_URL, $url);
curl_setopt($ch,CURLOPT_SSL_VERIFYPEER,FALSE);
curl_setopt($ch,CURLOPT_SSL_VERIFYHOST,FALSE);
//设置header
curl_setopt($ch, CURLOPT_HEADER, FALSE);
//要求结果为字符串且输出到屏幕上
curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
//post提交方式
curl_setopt($ch, CURLOPT_POST, TRUE);
curl_setopt($ch, CURLOPT_POSTFIELDS, $xml);
//运行curl
$data = curl_exec($ch);
curl_close($ch);
//返回结果
if($data)
{
curl_close($ch);
return $data;
}
else
{
$error = curl_errno($ch);
echo "curl出错,错误码:$error"."<br>";
echo "<a href='http://curl.haxx.se/libcurl/c/libcurl-errors.html'>错误原因查询</a></br>";
curl_close($ch);
return false;
}
}
/**
* 作用:设置标配的请求参数,生成签名,生成接口参数xml
*/
function createXml()
{
$this->parameters["appid"] = $this->appId;//公众账号ID
$this->parameters["mch_id"] = $this->MCHID;//商户号
$this->parameters["nonce_str"] = $this->weObj->generateNonceStr();//随机字符串
$this->parameters["sign"] = $this->getSign($this->parameters);//签名
return $this->arrayToXml($this->parameters);
}
/**
* 作用:array转xml
*/
function arrayToXml($arr)
{
$xml = "<xml>";
foreach ($arr as $key=>$val)
{
if (is_numeric($val))
{
$xml.="<".$key.">".$val."</".$key.">";
}
else
$xml.="<".$key."><![CDATA[".$val."]]></".$key.">";
}
$xml.="</xml>";
return $xml;
}
/**
* 作用:生成签名
*/
public function getSign($Obj)
{
foreach ($Obj as $k => $v)
{
$Parameters[$k] = $v;
}
//签名步骤一:按字典序排序参数
ksort($Parameters);
$String = $this->formatBizQueryParaMap($Parameters, false);
//echo '【string1】'.$String.'</br>';
//签名步骤二:在string后加入KEY
$String = $String."&key=".$this->KEY;
//echo "【string2】".$String."</br>";
//签名步骤三:MD5加密
$String = md5($String);
//echo "【string3】 ".$String."</br>";
//签名步骤四:所有字符转为大写
$result_ = strtoupper($String);
//echo "【result】 ".$result_."</br>";
return $result_;
}
}
================================================
FILE: Thinkphp/TPWechat.class.php
================================================
<?php
/**
* 微信公众平台PHP-SDK, ThinkPHP实例
* @author dodgepudding@gmail.com
* @link https://github.com/dodgepudding/wechat-php-sdk
* @version 1.2
* usage:
* $options = array(
* 'token'=>'tokenaccesskey', //填写你设定的key
* 'encodingaeskey'=>'encodingaeskey', //填写加密用的EncodingAESKey
* 'appid'=>'wxdk1234567890', //填写高级调用功能的app id
* 'appsecret'=>'xxxxxxxxxxxxxxxxxxx' //填写高级调用功能的密钥
* );
* $weObj = new TPWechat($options);
* $weObj->valid();
* ...
*
*/
class TPWechat extends Wechat
{
/**
* log overwrite
* @see Wechat::log()
*/
protected function log($log){
if ($this->debug) {
if (function_exists($this->logcallback)) {
if (is_array($log)) $log = print_r($log,true);
return call_user_func($this->logcallback,$log);
}elseif (class_exists('Log')) {
Log::write('wechat:'.$log, Log::DEBUG);
return true;
}
}
return false;
}
/**
* 重载设置缓存
* @param string $cachename
* @param mixed $value
* @param int $expired
* @return boolean
*/
protected function setCache($cachename,$value,$expired){
return S($cachename,$value,$expired);
}
/**
* 重载获取缓存
* @param string $cachename
* @return mixed
*/
protected function getCache($cachename){
return S($cachename);
}
/**
* 重载清除缓存
* @param string $cachename
* @return boolean
*/
protected function removeCache($cachename){
return S($cachename,null);
}
}
================================================
FILE: Thinkphp/Wxauth.class.php
================================================
<?php
/**
* 微信oAuth认证示例
* 官方文档:http://mp.weixin.qq.com/wiki/17/c0f37d5704f0b64713d5d2c37b468d75.html
* UCToo示例:http://git.oschina.net/uctoo/uctoo/blob/master/Addons/Ucuser/UcuserAddon.class.php
*
* 微信oAuth认证类,适配Thinkphp框架,
* @命名空间版本
* @author uctoo (www.uctoo.com)
* @date 2015-5-15 14:10
*/
namespace Com;
class Wxauth {
private $options;
public $open_id;
public $wxuser;
public function __construct($options){
$this->options = $options;
$this->wxoauth();
}
public function wxoauth(){
$scope = 'snsapi_base';
$code = isset($_GET['code'])?$_GET['code']:'';
$token_time = isset($_SESSION['token_time'])?$_SESSION['token_time']:0;
if(!$code && isset($_SESSION['open_id']) && isset($_SESSION['user_token']) && $token_time>time()-3600)
{
if (!$this->wxuser) {
$this->wxuser = $_SESSION['wxuser'];
}
$this->open_id = $_SESSION['open_id'];
return $this->open_id;
}
else
{
$options = array(
'token'=>$this->options["token"], //填写你设定的key
'encodingaeskey'=>$this->options["encodingaeskey"], //填写加密用的EncodingAESKey
'appid'=>$this->options["appid"], //填写高级调用功能的app id
'appsecret'=>$this->options["appsecret"] //填写高级调用功能的密钥
);
$we_obj = new TPWechat($options);
if ($code) {
$json = $we_obj->getOauthAccessToken();
if (!$json) {
unset($_SESSION['wx_redirect']);
die('获取用户授权失败,请重新确认');
}
$_SESSION['open_id'] = $this->open_id = $json["openid"];
$access_token = $json['access_token'];
$_SESSION['user_token'] = $access_token;
$_SESSION['token_time'] = time();
$userinfo = $we_obj->getUserInfo($this->open_id);
if ($userinfo && !empty($userinfo['nickname'])) {
$this->wxuser = array(
'open_id'=>$this->open_id,
'nickname'=>$userinfo['nickname'],
'sex'=>intval($userinfo['sex']),
'location'=>$userinfo['province'].'-'.$userinfo['city'],
'avatar'=>$userinfo['headimgurl']
);
} elseif (strstr($json['scope'],'snsapi_userinfo')!==false) {
$userinfo = $we_obj->getOauthUserinfo($access_token,$this->open_id);
if ($userinfo && !empty($userinfo['nickname'])) {
$this->wxuser = array(
'open_id'=>$this->open_id,
'nickname'=>$userinfo['nickname'],
'sex'=>intval($userinfo['sex']),
'location'=>$userinfo['province'].'-'.$userinfo['city'],
'avatar'=>$userinfo['headimgurl']
);
} else {
return $this->open_id;
}
}
if ($this->wxuser) {
$_SESSION['wxuser'] = $this->wxuser;
$_SESSION['open_id'] = $json["openid"];
unset($_SESSION['wx_redirect']);
return $this->open_id;
}
$scope = 'snsapi_userinfo';
}
if ($scope=='snsapi_base') {
$url = 'http://'.$_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI'];
$_SESSION['wx_redirect'] = $url;
} else {
$url = $_SESSION['wx_redirect'];
}
if (!$url) {
unset($_SESSION['wx_redirect']);
die('获取用户授权失败');
}
$oauth_url = $we_obj->getOauthRedirect($url,"wxbase",$scope);
redirect ( $oauth_url );
}
}
}
//$options = array(
// 'token'=>'uctoo', //填写你设定的key
// 'appid'=>'wxdk1234567890', //填写高级调用功能的app id, 请在微信开发模式后台查询
// 'appsecret'=>'xxxxxxxxxxxxxxxxxxx', //填写高级调用功能的密钥
//);
//$auth = new Wxauth($options);
//var_dump($auth->wxuser);
================================================
FILE: composer.json
================================================
{
"name" : "dodgepudding/wechat-php-sdk",
"description" : "the wechat api library without framework dependency",
"version" : "1.1",
"require" : {
"php" : ">=5.1.0"
},
"authors" : [ {
"name" : "dodgepudding",
"email" : "dodgepudding@gmail.com"
}, {
"name" : "binsee",
"email" : "binsee@163.com"
} ],
"keywords" : [ "wechat", "weixin", "thinkphp", "sample" ],
"support" : {
"issues" : "https://github.com/dodgepudding/wechat-php-sdk/issues",
"wiki" : "https://github.com/dodgepudding/wechat-php-sdk/wiki",
"source" : "https://github.com/dodgepudding/wechat-php-sdk"
},
"autoload" : {
"psr-4" : {
"dodgepudding\\wechat\\sdk\\" : ""
}
},
"type" : "library",
"license" : "LGPL"
}
================================================
FILE: demo.php
================================================
<?php
include "wechat.class.php";
$options = array(
'token'=>'tokenaccesskey', //填写你设定的key
'encodingaeskey'=>'encodingaeskey' //填写加密用的EncodingAESKey,如接口为明文模式可忽略
);
$weObj = new Wechat($options);
$weObj->valid();//明文或兼容模式可以在接口验证通过后注释此句,但加密模式一定不能注释,否则会验证失败
$type = $weObj->getRev()->getRevType();
switch($type) {
case Wechat::MSGTYPE_TEXT:
$weObj->text("hello, I'm wechat")->reply();
exit;
break;
case Wechat::MSGTYPE_EVENT:
break;
case Wechat::MSGTYPE_IMAGE:
break;
default:
$weObj->text("help info")->reply();
}
================================================
FILE: errCode.php
================================================
<?php
/**
* 微信公众平台PHP-SDK, 全局返回码类
* @author binsee <binsee@163.com>
* @link https://github.com/binsee/wechat-php-sdk
* @version 1.0
* usage:
* $ret=ErrCode::getErrText(40001); //错误码可以通过公众号类库的公开变量errCode得到
* if ($ret)
* echo $ret;
* else
* echo "未找到对应的内容";
*/
class ErrCode
{
public static $errCode=array(
'-1'=>'系统繁忙',
'0'=>'请求成功',
'40001'=>'获取access_token时AppSecret错误,或者access_token无效',
'40002'=>'不合法的凭证类型',
'40003'=>'不合法的OpenID',
'40004'=>'不合法的媒体文件类型',
'40005'=>'不合法的文件类型',
'40006'=>'不合法的文件大小',
'40007'=>'不合法的媒体文件id',
'40008'=>'不合法的消息类型',
'40009'=>'不合法的图片文件大小',
'40010'=>'不合法的语音文件大小',
'40011'=>'不合法的视频文件大小',
'40012'=>'不合法的缩略图文件大小',
'40013'=>'不合法的APPID',
'40014'=>'不合法的access_token',
'40015'=>'不合法的菜单类型',
'40016'=>'不合法的按钮个数',
'40017'=>'不合法的按钮类型',
'40018'=>'不合法的按钮名字长度',
'40019'=>'不合法的按钮KEY长度',
'40020'=>'不合法的按钮URL长度',
'40021'=>'不合法的菜单版本号',
'40022'=>'不合法的子菜单级数',
'40023'=>'不合法的子菜单按钮个数',
'40024'=>'不合法的子菜单按钮类型',
'40025'=>'不合法的子菜单按钮名字长度',
'40026'=>'不合法的子菜单按钮KEY长度',
'40027'=>'不合法的子菜单按钮URL长度',
'40028'=>'不合法的自定义菜单使用用户',
'40029'=>'不合法的oauth_code',
'40030'=>'不合法的refresh_token',
'40031'=>'不合法的openid列表',
'40032'=>'不合法的openid列表长度',
'40033'=>'不合法的请求字符,不能包含\uxxxx格式的字符',
'40035'=>'不合法的参数',
'40038'=>'不合法的请求格式',
'40039'=>'不合法的URL长度',
'40050'=>'不合法的分组id',
'40051'=>'分组名字不合法',
'40099'=>'该 code 已被核销',
'41001'=>'缺少access_token参数',
'41002'=>'缺少appid参数',
'41003'=>'缺少refresh_token参数',
'41004'=>'缺少secret参数',
'41005'=>'缺少多媒体文件数据',
'41006'=>'缺少media_id参数',
'41007'=>'缺少子菜单数据',
'41008'=>'缺少oauth code',
'41009'=>'缺少openid',
'42001'=>'access_token超时',
'42002'=>'refresh_token超时',
'42003'=>'oauth_code超时',
'42005'=>'调用接口频率超过上限',
'43001'=>'需要GET请求',
'43002'=>'需要POST请求',
'43003'=>'需要HTTPS请求',
'43004'=>'需要接收者关注',
'43005'=>'需要好友关系',
'44001'=>'多媒体文件为空',
'44002'=>'POST的数据包为空',
'44003'=>'图文消息内容为空',
'44004'=>'文本消息内容为空',
'45001'=>'多媒体文件大小超过限制',
'45002'=>'消息内容超过限制',
'45003'=>'标题字段超过限制',
'45004'=>'描述字段超过限制',
'45005'=>'链接字段超过限制',
'45006'=>'图片链接字段超过限制',
'45007'=>'语音播放时间超过限制',
'45008'=>'图文消息超过限制',
'45009'=>'接口调用超过限制',
'45010'=>'创建菜单个数超过限制',
'45015'=>'回复时间超过限制',
'45016'=>'系统分组,不允许修改',
'45017'=>'分组名字过长',
'45018'=>'分组数量超过上限',
'45024'=>'账号数量超过上限',
'46001'=>'不存在媒体数据',
'46002'=>'不存在的菜单版本',
'46003'=>'不存在的菜单数据',
'46004'=>'不存在的用户',
'47001'=>'解析JSON/XML内容错误',
'48001'=>'api功能未授权',
'50001'=>'用户未授权该api',
'61450'=>'系统错误',
'61451'=>'参数错误',
'61452'=>'无效客服账号',
'61453'=>'账号已存在',
'61454'=>'客服帐号名长度超过限制(仅允许10个英文字符,不包括@及@后的公众号的微信号)',
'61455'=>'客服账号名包含非法字符(英文+数字)',
'61456'=>'客服账号个数超过限制(10个客服账号)',
'61457'=>'无效头像文件类型',
'61458'=>'客户正在被其他客服接待',
'61459'=>'客服不在线',
'61500'=>'日期格式错误',
'61501'=>'日期范围错误',
'7000000'=>'请求正常,无语义结果',
'7000001'=>'缺失请求参数',
'7000002'=>'signature 参数无效',
'7000003'=>'地理位置相关配置 1 无效',
'7000004'=>'地理位置相关配置 2 无效',
'7000005'=>'请求地理位置信息失败',
'7000006'=>'地理位置结果解析失败',
'7000007'=>'内部初始化失败',
'7000008'=>'非法 appid(获取密钥失败)',
'7000009'=>'请求语义服务失败',
'7000010'=>'非法 post 请求',
'7000011'=>'post 请求 json 字段无效',
'7000030'=>'查询 query 太短',
'7000031'=>'查询 query 太长',
'7000032'=>'城市、经纬度信息缺失',
'7000033'=>'query 请求语义处理失败',
'7000034'=>'获取天气信息失败',
'7000035'=>'获取股票信息失败',
'7000036'=>'utf8 编码转换失败',
);
public static function getErrText($err) {
if (isset(self::$errCode[$err])) {
return self::$errCode[$err];
}else {
return false;
};
}
}
?>
================================================
FILE: old_version/Thinkphp/Snoopy.class.php
================================================
<?php
/*************************************************
Snoopy - the PHP net client
Author: Monte Ohrt <monte@ispi.net>
Copyright (c): 1999-2008 New Digital Group, all rights reserved
Version: 1.2.4
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
You may contact the author of Snoopy by e-mail at:
monte@ohrt.com
The latest version of Snoopy can be obtained from:
http://snoopy.sourceforge.net/
*************************************************/
class Snoopy
{
/**** Public variables ****/
/* user definable vars */
var $host = "www.php.net"; // host name we are connecting to
var $port = 80; // port we are connecting to
var $proxy_host = ""; // proxy host to use
var $proxy_port = ""; // proxy port to use
var $proxy_user = ""; // proxy user to use
var $proxy_pass = ""; // proxy password to use
var $agent = "Mozilla/5.0"; // agent we masquerade as
var $referer = ""; // referer info to pass
var $cookies = array(); // array of cookies to pass
// $cookies["username"]="joe";
var $rawheaders = array(); // array of raw headers to send
// $rawheaders["Content-type"]="text/html";
var $maxredirs = 5; // http redirection depth maximum. 0 = disallow
var $lastredirectaddr = ""; // contains address of last redirected address
var $offsiteok = true; // allows redirection off-site
var $maxframes = 0; // frame content depth maximum. 0 = disallow
var $expandlinks = true; // expand links to fully qualified URLs.
// this only applies to fetchlinks()
// submitlinks(), and submittext()
var $passcookies = true; // pass set cookies back through redirects
// NOTE: this currently does not respect
// dates, domains or paths.
var $user = ""; // user for http authentication
var $pass = ""; // password for http authentication
// http accept types
var $accept = "application/json, text/javascript, */*; q=0.01";
var $results = ""; // where the content is put
var $error = ""; // error messages sent here
var $response_code = ""; // response code returned from server
var $headers = array(); // headers returned from server sent here
var $maxlength = 500000; // max return data length (body)
var $read_timeout = 0; // timeout on read operations, in seconds
// supported only since PHP 4 Beta 4
// set to 0 to disallow timeouts
var $timed_out = false; // if a read operation timed out
var $status = 0; // http request status
var $temp_dir = "/tmp"; // temporary directory that the webserver
// has permission to write to.
// under Windows, this should be C:\temp
var $curl_path = "/usr/local/bin/curl";
// Snoopy will use cURL for fetching
// SSL content if a full system path to
// the cURL binary is supplied here.
// set to false if you do not have
// cURL installed. See http://curl.haxx.se
// for details on installing cURL.
// Snoopy does *not* use the cURL
// library functions built into php,
// as these functions are not stable
// as of this Snoopy release.
/**** Private variables ****/
var $_maxlinelen = 4096; // max line length (headers)
var $_httpmethod = "GET"; // default http request method
var $_httpversion = "HTTP/1.0"; // default http request version
var $_submit_method = "POST"; // default submit method
var $_submit_type = "application/x-www-form-urlencoded"; // default submit type
var $_mime_boundary = ""; // MIME boundary for multipart/form-data submit type
var $_redirectaddr = false; // will be set if page fetched is a redirect
var $_redirectdepth = 0; // increments on an http redirect
var $_frameurls = array(); // frame src urls
var $_framedepth = 0; // increments on frame depth
var $_isproxy = false; // set if using a proxy server
var $_fp_timeout = 30; // timeout for socket connection
/*======================================================================*\
Function: fetch
Purpose: fetch the contents of a web page
(and possibly other protocols in the
future like ftp, nntp, gopher, etc.)
Input: $URI the location of the page to fetch
Output: $this->results the output text from the fetch
\*======================================================================*/
function fetch($URI)
{
//preg_match("|^([^:]+)://([^:/]+)(:[\d]+)*(.*)|",$URI,$URI_PARTS);
$URI_PARTS = parse_url($URI);
if (!empty($URI_PARTS["user"]))
$this->user = $URI_PARTS["user"];
if (!empty($URI_PARTS["pass"]))
$this->pass = $URI_PARTS["pass"];
if (empty($URI_PARTS["query"]))
$URI_PARTS["query"] = '';
if (empty($URI_PARTS["path"]))
$URI_PARTS["path"] = '';
switch(strtolower($URI_PARTS["scheme"]))
{
case "http":
$this->host = $URI_PARTS["host"];
if(!empty($URI_PARTS["port"]))
$this->port = $URI_PARTS["port"];
if($this->_connect($fp))
{
if($this->_isproxy)
{
// using proxy, send entire URI
$this->_httprequest($URI,$fp,$URI,$this->_httpmethod);
}
else
{
$path = $URI_PARTS["path"].($URI_PARTS["query"] ? "?".$URI_PARTS["query"] : "");
// no proxy, send only the path
$this->_httprequest($path, $fp, $URI, $this->_httpmethod);
}
$this->_disconnect($fp);
if($this->_redirectaddr)
{
/* url was redirected, check if we've hit the max depth */
if($this->maxredirs > $this->_redirectdepth)
{
// only follow redirect if it's on this site, or offsiteok is true
if(preg_match("|^http://".preg_quote($this->host)."|i",$this->_redirectaddr) || $this->offsiteok)
{
/* follow the redirect */
$this->_redirectdepth++;
$this->lastredirectaddr=$this->_redirectaddr;
$this->fetch($this->_redirectaddr);
}
}
}
if($this->_framedepth < $this->maxframes && count($this->_frameurls) > 0)
{
$frameurls = $this->_frameurls;
$this->_frameurls = array();
while(list(,$frameurl) = each($frameurls))
{
if($this->_framedepth < $this->maxframes)
{
$this->fetch($frameurl);
$this->_framedepth++;
}
else
break;
}
}
}
else
{
return false;
}
return true;
break;
case "https":
if (!function_exists('curl_init')) {
if(!$this->curl_path)
return false;
if(function_exists("is_executable"))
if (!is_executable($this->curl_path))
return false;
}
$this->host = $URI_PARTS["host"];
if(!empty($URI_PARTS["port"]))
$this->port = $URI_PARTS["port"];
if($this->_isproxy)
{
// using proxy, send entire URI
$this->_httpsrequest($URI,$URI,$this->_httpmethod);
}
else
{
$path = $URI_PARTS["path"].($URI_PARTS["query"] ? "?".$URI_PARTS["query"] : "");
// no proxy, send only the path
$this->_httpsrequest($path, $URI, $this->_httpmethod);
}
if($this->_redirectaddr)
{
/* url was redirected, check if we've hit the max depth */
if($this->maxredirs > $this->_redirectdepth)
{
// only follow redirect if it's on this site, or offsiteok is true
if(preg_match("|^https://".preg_quote($this->host)."|i",$this->_redirectaddr) || $this->offsiteok)
{
/* follow the redirect */
$this->_redirectdepth++;
$this->lastredirectaddr=$this->_redirectaddr;
$this->fetch($this->_redirectaddr);
}
}
}
if($this->_framedepth < $this->maxframes && count($this->_frameurls) > 0)
{
$frameurls = $this->_frameurls;
$this->_frameurls = array();
while(list(,$frameurl) = each($frameurls))
{
if($this->_framedepth < $this->maxframes)
{
$this->fetch($frameurl);
$this->_framedepth++;
}
else
break;
}
}
return true;
break;
default:
// not a valid protocol
$this->error = 'Invalid protocol "'.$URI_PARTS["scheme"].'"\n';
return false;
break;
}
return true;
}
/*======================================================================*\
Function: submit
Purpose: submit an http form
Input: $URI the location to post the data
$formvars the formvars to use.
format: $formvars["var"] = "val";
$formfiles an array of files to submit
format: $formfiles["var"] = "/dir/filename.ext";
Output: $this->results the text output from the post
\*======================================================================*/
function submit($URI, $formvars="", $formfiles="")
{
unset($postdata);
$postdata = $this->_prepare_post_body($formvars, $formfiles);
$URI_PARTS = parse_url($URI);
if (!empty($URI_PARTS["user"]))
$this->user = $URI_PARTS["user"];
if (!empty($URI_PARTS["pass"]))
$this->pass = $URI_PARTS["pass"];
if (empty($URI_PARTS["query"]))
$URI_PARTS["query"] = '';
if (empty($URI_PARTS["path"]))
$URI_PARTS["path"] = '';
switch(strtolower($URI_PARTS["scheme"]))
{
case "http":
$this->host = $URI_PARTS["host"];
if(!empty($URI_PARTS["port"]))
$this->port = $URI_PARTS["port"];
if($this->_connect($fp))
{
if($this->_isproxy)
{
// using proxy, send entire URI
$this->_httprequest($URI,$fp,$URI,$this->_submit_method,$this->_submit_type,$postdata);
}
else
{
$path = $URI_PARTS["path"].($URI_PARTS["query"] ? "?".$URI_PARTS["query"] : "");
// no proxy, send only the path
$this->_httprequest($path, $fp, $URI, $this->_submit_method, $this->_submit_type, $postdata);
}
$this->_disconnect($fp);
if($this->_redirectaddr)
{
/* url was redirected, check if we've hit the max depth */
if($this->maxredirs > $this->_redirectdepth)
{
if(!preg_match("|^".$URI_PARTS["scheme"]."://|", $this->_redirectaddr))
$this->_redirectaddr = $this->_expandlinks($this->_redirectaddr,$URI_PARTS["scheme"]."://".$URI_PARTS["host"]);
// only follow redirect if it's on this site, or offsiteok is true
if(preg_match("|^http://".preg_quote($this->host)."|i",$this->_redirectaddr) || $this->offsiteok)
{
/* follow the redirect */
$this->_redirectdepth++;
$this->lastredirectaddr=$this->_redirectaddr;
if( strpos( $this->_redirectaddr, "?" ) > 0 )
$this->fetch($this->_redirectaddr); // the redirect has changed the request method from post to get
else
$this->submit($this->_redirectaddr,$formvars, $formfiles);
}
}
}
if($this->_framedepth < $this->maxframes && count($this->_frameurls) > 0)
{
$frameurls = $this->_frameurls;
$this->_frameurls = array();
while(list(,$frameurl) = each($frameurls))
{
if($this->_framedepth < $this->maxframes)
{
$this->fetch($frameurl);
$this->_framedepth++;
}
else
break;
}
}
}
else
{
return false;
}
return true;
break;
case "https":
if (!function_exists('curl_init')) {
if(!$this->curl_path)
return false;
if(function_exists("is_executable"))
if (!is_executable($this->curl_path))
return false;
}
$this->host = $URI_PARTS["host"];
if(!empty($URI_PARTS["port"]))
$this->port = $URI_PARTS["port"];
if($this->_isproxy)
{
// using proxy, send entire URI
$this->_httpsrequest($URI, $URI, $this->_submit_method, $this->_submit_type, $postdata);
}
else
{
$path = $URI_PARTS["path"].($URI_PARTS["query"] ? "?".$URI_PARTS["query"] : "");
// no proxy, send only the path
$this->_httpsrequest($path, $URI, $this->_submit_method, $this->_submit_type, $postdata);
}
if($this->_redirectaddr)
{
/* url was redirected, check if we've hit the max depth */
if($this->maxredirs > $this->_redirectdepth)
{
if(!preg_match("|^".$URI_PARTS["scheme"]."://|", $this->_redirectaddr))
$this->_redirectaddr = $this->_expandlinks($this->_redirectaddr,$URI_PARTS["scheme"]."://".$URI_PARTS["host"]);
// only follow redirect if it's on this site, or offsiteok is true
if(preg_match("|^https://".preg_quote($this->host)."|i",$this->_redirectaddr) || $this->offsiteok)
{
/* follow the redirect */
$this->_redirectdepth++;
$this->lastredirectaddr=$this->_redirectaddr;
if( strpos( $this->_redirectaddr, "?" ) > 0 )
$this->fetch($this->_redirectaddr); // the redirect has changed the request method from post to get
else
$this->submit($this->_redirectaddr,$formvars, $formfiles);
}
}
}
if($this->_framedepth < $this->maxframes && count($this->_frameurls) > 0)
{
$frameurls = $this->_frameurls;
$this->_frameurls = array();
while(list(,$frameurl) = each($frameurls))
{
if($this->_framedepth < $this->maxframes)
{
$this->fetch($frameurl);
$this->_framedepth++;
}
else
break;
}
}
return true;
break;
default:
// not a valid protocol
$this->error = 'Invalid protocol "'.$URI_PARTS["scheme"].'"\n';
return false;
break;
}
return true;
}
/*======================================================================*\
Function: fetchlinks
Purpose: fetch the links from a web page
Input: $URI where you are fetching from
Output: $this->results an array of the URLs
\*======================================================================*/
function fetchlinks($URI)
{
if ($this->fetch($URI))
{
if($this->lastredirectaddr)
$URI = $this->lastredirectaddr;
if(is_array($this->results))
{
for($x=0;$x<count($this->results);$x++)
$this->results[$x] = $this->_striplinks($this->results[$x]);
}
else
$this->results = $this->_striplinks($this->results);
if($this->expandlinks)
$this->results = $this->_expandlinks($this->results, $URI);
return true;
}
else
return false;
}
/*======================================================================*\
Function: fetchform
Purpose: fetch the form elements from a web page
Input: $URI where you are fetching from
Output: $this->results the resulting html form
\*======================================================================*/
function fetchform($URI)
{
if ($this->fetch($URI))
{
if(is_array($this->results))
{
for($x=0;$x<count($this->results);$x++)
$this->results[$x] = $this->_stripform($this->results[$x]);
}
else
$this->results = $this->_stripform($this->results);
return true;
}
else
return false;
}
/*======================================================================*\
Function: fetchtext
Purpose: fetch the text from a web page, stripping the links
Input: $URI where you are fetching from
Output: $this->results the text from the web page
\*======================================================================*/
function fetchtext($URI)
{
if($this->fetch($URI))
{
if(is_array($this->results))
{
for($x=0;$x<count($this->results);$x++)
$this->results[$x] = $this->_striptext($this->results[$x]);
}
else
$this->results = $this->_striptext($this->results);
return true;
}
else
return false;
}
/*======================================================================*\
Function: submitlinks
Purpose: grab links from a form submission
Input: $URI where you are submitting from
Output: $this->results an array of the links from the post
\*======================================================================*/
function submitlinks($URI, $formvars="", $formfiles="")
{
if($this->submit($URI,$formvars, $formfiles))
{
if($this->lastredirectaddr)
$URI = $this->lastredirectaddr;
if(is_array($this->results))
{
for($x=0;$x<count($this->results);$x++)
{
$this->results[$x] = $this->_striplinks($this->results[$x]);
if($this->expandlinks)
$this->results[$x] = $this->_expandlinks($this->results[$x],$URI);
}
}
else
{
$this->results = $this->_striplinks($this->results);
if($this->expandlinks)
$this->results = $this->_expandlinks($this->results,$URI);
}
return true;
}
else
return false;
}
/*======================================================================*\
Function: submittext
Purpose: grab text from a form submission
Input: $URI where you are submitting from
Output: $this->results the text from the web page
\*======================================================================*/
function submittext($URI, $formvars = "", $formfiles = "")
{
if($this->submit($URI,$formvars, $formfiles))
{
if($this->lastredirectaddr)
$URI = $this->lastredirectaddr;
if(is_array($this->results))
{
for($x=0;$x<count($this->results);$x++)
{
$this->results[$x] = $this->_striptext($this->results[$x]);
if($this->expandlinks)
$this->results[$x] = $this->_expandlinks($this->results[$x],$URI);
}
}
else
{
$this->results = $this->_striptext($this->results);
if($this->expandlinks)
$this->results = $this->_expandlinks($this->results,$URI);
}
return true;
}
else
return false;
}
/*======================================================================*\
Function: set_submit_multipart
Purpose: Set the form submission content type to
multipart/form-data
\*======================================================================*/
function set_submit_multipart()
{
$this->_submit_type = "multipart/form-data";
}
/*======================================================================*\
Function: set_submit_normal
Purpose: Set the form submission content type to
application/x-www-form-urlencoded
\*======================================================================*/
function set_submit_normal()
{
$this->_submit_type = "application/x-www-form-urlencoded";
}
/*======================================================================*\
Private functions
\*======================================================================*/
/*======================================================================*\
Function: _striplinks
Purpose: strip the hyperlinks from an html document
Input: $document document to strip.
Output: $match an array of the links
\*======================================================================*/
function _striplinks($document)
{
preg_match_all("'<\s*a\s.*?href\s*=\s* # find <a href=
([\"\'])? # find single or double quote
(?(1) (.*?)\\1 | ([^\s\>]+)) # if quote found, match up to next matching
# quote, otherwise match up to next space
'isx",$document,$links);
// catenate the non-empty matches from the conditional subpattern
while(list($key,$val) = each($links[2]))
{
if(!empty($val))
$match[] = $val;
}
while(list($key,$val) = each($links[3]))
{
if(!empty($val))
$match[] = $val;
}
// return the links
return $match;
}
/*======================================================================*\
Function: _stripform
Purpose: strip the form elements from an html document
Input: $document document to strip.
Output: $match an array of the links
\*======================================================================*/
function _stripform($document)
{
preg_match_all("'<\/?(FORM|INPUT|SELECT|TEXTAREA|(OPTION))[^<>]*>(?(2)(.*(?=<\/?(option|select)[^<>]*>[\r\n]*)|(?=[\r\n]*))|(?=[\r\n]*))'Usi",$document,$elements);
// catenate the matches
$match = implode("\r\n",$elements[0]);
// return the links
return $match;
}
/*======================================================================*\
Function: _striptext
Purpose: strip the text from an html document
Input: $document document to strip.
Output: $text the resulting text
\*======================================================================*/
function _striptext($document)
{
// I didn't use preg eval (//e) since that is only available in PHP 4.0.
// so, list your entities one by one here. I included some of the
// more common ones.
$search = array("'<script[^>]*?>.*?</script>'si", // strip out javascript
"'<[\/\!]*?[^<>]*?>'si", // strip out html tags
"'([\r\n])[\s]+'", // strip out white space
"'&(quot|#34|#034|#x22);'i", // replace html entities
"'&(amp|#38|#038|#x26);'i", // added hexadecimal values
"'&(lt|#60|#060|#x3c);'i",
"'&(gt|#62|#062|#x3e);'i",
"'&(nbsp|#160|#xa0);'i",
"'&(iexcl|#161);'i",
"'&(cent|#162);'i",
"'&(pound|#163);'i",
"'&(copy|#169);'i",
"'&(reg|#174);'i",
"'&(deg|#176);'i",
"'&(#39|#039|#x27);'",
"'&(euro|#8364);'i", // europe
"'&a(uml|UML);'", // german
"'&o(uml|UML);'",
"'&u(uml|UML);'",
"'&A(uml|UML);'",
"'&O(uml|UML);'",
"'&U(uml|UML);'",
"'ß'i",
);
$replace = array( "",
"",
"\\1",
"\"",
"&",
"<",
">",
" ",
chr(161),
chr(162),
chr(163),
chr(169),
chr(174),
chr(176),
chr(39),
chr(128),
"�",
"�",
"�",
"�",
"�",
"�",
"�",
);
$text = preg_replace($search,$replace,$document);
return $text;
}
/*======================================================================*\
Function: _expandlinks
Purpose: expand each link into a fully qualified URL
Input: $links the links to qualify
$URI the full URI to get the base from
Output: $expandedLinks the expanded links
\*======================================================================*/
function _expandlinks($links,$URI)
{
preg_match("/^[^\?]+/",$URI,$match);
$match = preg_replace("|/[^\/\.]+\.[^\/\.]+$|","",$match[0]);
$match = preg_replace("|/$|","",$match);
$match_part = parse_url($match);
$match_root =
$match_part["scheme"]."://".$match_part["host"];
$search = array( "|^http://".preg_quote($this->host)."|i",
"|^(\/)|i",
"|^(?!http://)(?!mailto:)|i",
"|/\./|",
"|/[^\/]+/\.\./|"
);
$replace = array( "",
$match_root."/",
$match."/",
"/",
"/"
);
$expandedLinks = preg_replace($search,$replace,$links);
return $expandedLinks;
}
/*======================================================================*\
Function: _httprequest
Purpose: go get the http data from the server
Input: $url the url to fetch
$fp the current open file pointer
$URI the full URI
$body body contents to send if any (POST)
Output:
\*======================================================================*/
function _httprequest($url,$fp,$URI,$http_method,$content_type="",$body="")
{
$cookie_headers = '';
if($this->passcookies && $this->_redirectaddr)
$this->setcookies();
$URI_PARTS = parse_url($URI);
if(empty($url))
$url = "/";
$headers = $http_method." ".$url." ".$this->_httpversion."\r\n";
if(!empty($this->agent))
$headers .= "User-Agent: ".$this->agent."\r\n";
if(!empty($this->host) && !isset($this->rawheaders['Host'])) {
$headers .= "Host: ".$this->host;
if(!empty($this->port) && $this->port!=80)
$headers .= ":".$this->port;
$headers .= "\r\n";
}
if(!empty($this->accept))
$headers .= "Accept: ".$this->accept."\r\n";
if(!empty($this->referer))
$headers .= "Referer: ".$this->referer."\r\n";
if(!empty($this->cookies))
{
if(!is_array($this->cookies))
$this->cookies = (array)$this->cookies;
reset($this->cookies);
if ( count($this->cookies) > 0 ) {
$cookie_headers .= 'Cookie: ';
foreach ( $this->cookies as $cookieKey => $cookieVal ) {
$cookie_headers .= $cookieKey."=".urlencode($cookieVal)."; ";
}
$headers .= substr($cookie_headers,0,-2) . "\r\n";
}
}
if(!empty($this->rawheaders))
{
if(!is_array($this->rawheaders))
$this->rawheaders = (array)$this->rawheaders;
while(list($headerKey,$headerVal) = each($this->rawheaders))
$headers .= $headerKey.": ".$headerVal."\r\n";
}
if(!empty($content_type)) {
$headers .= "Content-type: $content_type";
if ($content_type == "multipart/form-data")
$headers .= "; boundary=".$this->_mime_boundary;
$headers .= "\r\n";
}
if(!empty($body))
$headers .= "Content-length: ".strlen($body)."\r\n";
if(!empty($this->user) || !empty($this->pass))
$headers .= "Authorization: Basic ".base64_encode($this->user.":".$this->pass)."\r\n";
//add proxy auth headers
if(!empty($this->proxy_user))
$headers .= 'Proxy-Authorization: ' . 'Basic ' . base64_encode($this->proxy_user . ':' . $this->proxy_pass)."\r\n";
$headers .= "\r\n";
// set the read timeout if needed
if ($this->read_timeout > 0)
socket_set_timeout($fp, $this->read_timeout);
$this->timed_out = false;
fwrite($fp,$headers.$body,strlen($headers.$body));
$this->_redirectaddr = false;
unset($this->headers);
while($currentHeader = fgets($fp,$this->_maxlinelen))
{
if ($this->read_timeout > 0 && $this->_check_timeout($fp))
{
$this->status=-100;
return false;
}
if($currentHeader == "\r\n")
break;
// if a header begins with Location: or URI:, set the redirect
if(preg_match("/^(Location:|URI:)/i",$currentHeader))
{
// get URL portion of the redirect
preg_match("/^(Location:|URI:)[ ]+(.*)/i",chop($currentHeader),$matches);
// look for :// in the Location header to see if hostname is included
if (!empty($matches)) {
if(!preg_match("|\:\/\/|",$matches[2]))
{
// no host in the path, so prepend
$this->_redirectaddr = $URI_PARTS["scheme"]."://".$this->host.":".$this->port;
// eliminate double slash
if(!preg_match("|^/|",$matches[2]))
$this->_redirectaddr .= "/".$matches[2];
else
$this->_redirectaddr .= $matches[2];
}
else
$this->_redirectaddr = $matches[2];
}
}
if(preg_match("|^HTTP/|",$currentHeader))
{
if(preg_match("|^HTTP/[^\s]*\s(.*?)\s|",$currentHeader, $status))
{
$this->status= $status[1];
}
$this->response_code = $currentHeader;
}
$this->headers[] = $currentHeader;
}
$results = '';
do {
$_data = fread($fp, $this->maxlength);
if (strlen($_data) == 0) {
break;
}
$results .= $_data;
} while(true);
if ($this->read_timeout > 0 && $this->_check_timeout($fp))
{
$this->status=-100;
return false;
}
// check if there is a a redirect meta tag
if(preg_match("'<meta[\s]*http-equiv[^>]*?content[\s]*=[\s]*[\"\']?\d+;[\s]*URL[\s]*=[\s]*([^\"\']*?)[\"\']?>'i",$results,$match))
{
$this->_redirectaddr = $this->_expandlinks($match[1],$URI);
}
// have we hit our frame depth and is there frame src to fetch?
if(($this->_framedepth < $this->maxframes) && preg_match_all("'<frame\s+.*src[\s]*=[\'\"]?([^\'\"\>]+)'i",$results,$match))
{
$this->results[] = $results;
for($x=0; $x<count($match[1]); $x++)
$this->_frameurls[] = $this->_expandlinks($match[1][$x],$URI_PARTS["scheme"]."://".$this->host);
}
// have we already fetched framed content?
elseif(is_array($this->results))
$this->results[] = $results;
// no framed content
else
$this->results = $results;
return true;
}
/*======================================================================*\
Function: _httpsrequest
Purpose: go get the https data from the server using curl
Input: $url the url to fetch
$URI the full URI
$body body contents to send if any (POST)
Output:
\*======================================================================*/
function _httpsrequest($url,$URI,$http_method,$content_type="",$body="")
{
if($this->passcookies && $this->_redirectaddr)
$this->setcookies();
$headers = array();
$URI_PARTS = parse_url($URI);
if(empty($url))
$url = "/";
// GET ... header not needed for curl
//$headers[] = $http_method." ".$url." ".$this->_httpversion;
if(!empty($this->agent))
$headers[] = "User-Agent: ".$this->agent;
if(!empty($this->host))
if(!empty($this->port) && $this->port!=80)
$headers[] = "Host: ".$this->host.":".$this->port;
else
$headers[] = "Host: ".$this->host;
if(!empty($this->accept))
$headers[] = "Accept: ".$this->accept;
if(!empty($this->referer))
$headers[] = "Referer: ".$this->referer;
if(!empty($this->cookies))
{
if(!is_array($this->cookies))
$this->cookies = (array)$this->cookies;
reset($this->cookies);
if ( count($this->cookies) > 0 ) {
$cookie_str = 'Cookie: ';
foreach ( $this->cookies as $cookieKey => $cookieVal ) {
$cookie_str .= $cookieKey."=".urlencode($cookieVal)."; ";
}
$headers[] = substr($cookie_str,0,-2);
}
}
if(!empty($this->rawheaders))
{
if(!is_array($this->rawheaders))
$this->rawheaders = (array)$this->rawheaders;
while(list($headerKey,$headerVal) = each($this->rawheaders))
$headers[] = $headerKey.": ".$headerVal;
}
if(!empty($content_type)) {
if ($content_type == "multipart/form-data")
$headers[] = "Content-type: $content_type; boundary=".$this->_mime_boundary;
else
$headers[] = "Content-type: $content_type";
}
if(!empty($body))
$headers[] = "Content-length: ".strlen($body);
if(!empty($this->user) || !empty($this->pass))
$headers[] = "Authorization: BASIC ".base64_encode($this->user.":".$this->pass);
if (function_exists('curl_init')) {
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $URI);
curl_setopt($ch, CURLOPT_HEADER, true);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch, CURLOPT_TIMEOUT, $this->read_timeout);
if(!empty($body)) {
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $body);
}
$data = curl_exec($ch);
if ($data === false) {
$this->error = "Error: Curl error ".curl_error($ch);
return false;
}
$parts = explode("\r\n\r\n",$data,2);
$result_headers = explode("\r\n",$parts[0]);
$results = $parts[1];
unset($parts);
} else {
for($curr_header = 0; $curr_header < count($headers); $curr_header++) {
$safer_header = strtr( $headers[$curr_header], "\"", " " );
$cmdline_params .= " -H \"".$safer_header."\"";
}
if(!empty($body))
$cmdline_params .= " -d \"$body\"";
if($this->read_timeout > 0)
$cmdline_params .= " -m ".$this->read_timeout;
$headerfile = tempnam($temp_dir, "sno");
exec($this->curl_path." -k -D \"$headerfile\"".$cmdline_params." \"".escapeshellcmd($URI)."\"",$results,$return);
if($return)
{
$this->error = "Error: cURL could not retrieve the document, error $return.";
return false;
}
$results = implode("\r\n",$results);
$result_headers = file("$headerfile");
}
$this->_redirectaddr = false;
unset($this->headers);
for($currentHeader = 0; $currentHeader < count($result_headers); $currentHeader++)
{
// if a header begins with Location: or URI:, set the redirect
if(preg_match("/^(Location: |URI: )/i",$result_headers[$currentHeader]))
{
// get URL portion of the redirect
preg_match("/^(Location: |URI:)\s+(.*)/",chop($result_headers[$currentHeader]),$matches);
// look for :// in the Location header to see if hostname is included
if (!empty($matches)) {
if(!preg_match("|\:\/\/|",$matches[2]))
{
// no host in the path, so prepend
$this->_redirectaddr = $URI_PARTS["scheme"]."://".$this->host;
// eliminate double slash
if(!preg_match("|^/|",$matches[2]))
$this->_redirectaddr .= "/".$matches[2];
else
$this->_redirectaddr .= $matches[2];
}
else
$this->_redirectaddr = $matches[2];
}
}
if(preg_match("|^HTTP/|",$result_headers[$currentHeader]))
$this->response_code = $result_headers[$currentHeader];
$this->headers[] = $result_headers[$currentHeader];
}
// check if there is a a redirect meta tag
if(preg_match("'<meta[\s]*http-equiv[^>]*?content[\s]*=[\s]*[\"\']?\d+;[\s]*URL[\s]*=[\s]*([^\"\']*?)[\"\']?>'i",$results,$match))
{
$this->_redirectaddr = $this->_expandlinks($match[1],$URI);
}
// have we hit our frame depth and is there frame src to fetch?
if(($this->_framedepth < $this->maxframes) && preg_match_all("'<frame\s+.*src[\s]*=[\'\"]?([^\'\"\>]+)'i",$results,$match))
{
$this->results[] = $results;
for($x=0; $x<count($match[1]); $x++)
$this->_frameurls[] = $this->_expandlinks($match[1][$x],$URI_PARTS["scheme"]."://".$this->host);
}
// have we already fetched framed content?
elseif(is_array($this->results))
$this->results[] = $results;
// no framed content
else
$this->results = $results;
if (isset($headerfile) && file_exists($headerfile))
unlink($headerfile);
return true;
}
/*======================================================================*\
Function: setcookies()
Purpose: set cookies for a redirection
\*======================================================================*/
function setcookies()
{
for($x=0; $x<count($this->headers); $x++)
{
if(preg_match('/^set-cookie:[\s]+([^=]+)=([^;]+)/i', $this->headers[$x],$match))
$this->cookies[$match[1]] = urldecode($match[2]);
}
}
/*======================================================================*\
Function: _check_timeout
Purpose: checks whether timeout has occurred
Input: $fp file pointer
\*======================================================================*/
function _check_timeout($fp)
{
if ($this->read_timeout > 0) {
$fp_status = socket_get_status($fp);
if ($fp_status["timed_out"]) {
$this->timed_out = true;
return true;
}
}
return false;
}
/*======================================================================*\
Function: _connect
Purpose: make a socket connection
Input: $fp file pointer
\*======================================================================*/
function _connect(&$fp)
{
if(!empty($this->proxy_host) && !empty($this->proxy_port))
{
$this->_isproxy = true;
$host = $this->proxy_host;
$port = $this->proxy_port;
}
else
{
$host = $this->host;
$port = $this->port;
}
$this->status = 0;
if($fp = fsockopen(
$host,
$port,
$errno,
$errstr,
$this->_fp_timeout
))
{
// socket connection succeeded
return true;
}
else
{
// socket connection failed
$this->status = $errno;
switch($errno)
{
case -3:
$this->error="socket creation failed (-3)";
case -4:
$this->error="dns lookup failure (-4)";
case -5:
$this->error="connection refused or timed out (-5)";
default:
$this->error="connection failed (".$errno.")";
}
return false;
}
}
/*======================================================================*\
Function: _disconnect
Purpose: disconnect a socket connection
Input: $fp file pointer
\*======================================================================*/
function _disconnect($fp)
{
return(fclose($fp));
}
/*======================================================================*\
Function: _prepare_post_body
Purpose: Prepare post body according to encoding type
Input: $formvars - form variables
$formfiles - form upload files
Output: post body
\*======================================================================*/
function _prepare_post_body($formvars, $formfiles)
{
settype($formvars, "array");
settype($formfiles, "array");
$postdata = '';
if (count($formvars) == 0 && count($formfiles) == 0)
return;
if (is_string($formvars)) return $formvars;
if((count($formvars) == 1) && isset($formvars[0])) return $formvars[0];
switch ($this->_submit_type) {
case "application/x-www-form-urlencoded":
reset($formvars);
while(list($key,$val) = each($formvars)) {
if (is_array($val) || is_object($val)) {
while (list($cur_key, $cur_val) = each($val)) {
$postdata .= urlencode($key)."[]=".urlencode($cur_val)."&";
}
} else
$postdata .= urlencode($key)."=".urlencode($val)."&";
}
break;
case "multipart/form-data":
$this->_mime_boundary = "--------".md5(uniqid(microtime()));
reset($formvars);
while(list($key,$val) = each($formvars)) {
if (is_array($val) || is_object($val)) {
while (list($cur_key, $cur_val) = each($val)) {
$postdata .= "--".$this->_mime_boundary."\r\n";
$postdata .= "Content-Disposition: form-data; name=\"$key\[\]\"\r\n\r\n";
$postdata .= "$cur_val\r\n";
}
} else {
$postdata .= "--".$this->_mime_boundary."\r\n";
$postdata .= "Content-Disposition: form-data; name=\"$key\"\r\n\r\n";
$postdata .= "$val\r\n";
}
}
reset($formfiles);
while (list($field_name, $file_names) = each($formfiles)) {
settype($file_names, "array");
while (list(, $file_name) = each($file_names)) {
$file_content = file_get_contents($file_name);
if (!$file_content) continue;
$base_name = basename($file_name);
$postdata .= "--".$this->_mime_boundary."\r\n";
$postdata .= "Content-Disposition: form-data; name=\"$field_name\"; filename=\"$base_name\"\r\nContent-Type: image/jpeg\r\n\r\n";
$postdata .= "$file_content\r\n";
}
}
$postdata .= "--".$this->_mime_boundary."--\r\n";
break;
}
return $postdata;
}
}
================================================
FILE: old_version/Thinkphp/Wechatauth.class.php
================================================
<?php
/**
* 微信公众平台PHP-SDK
* Wechatauth为非官方微信登陆API
* 用户通过扫描网页提供的二维码实现登陆信息获取
* 主要实现如下功能:
* get_login_code() 获取登陆授权码, 通过授权码才能获取二维码
* get_code_image($code='') 将上面获取的授权码转换为图片二维码
* verify_code() 鉴定是否登陆成功,返回200为最终授权成功.
* get_login_info() 鉴定成功后调用此方法即可获取用户基本信息
* get_avatar($url) 获取用户头像图片数据
* @author dodge <dodgepudding@gmail.com>
* @link https://github.com/dodgepudding/wechat-php-sdk
* @version 1.1
*
*/
include "Snoopy.class.php";
class Wechatauth
{
private $cookie;
private $skey;
private $_cookiename;
private $_cookieexpired = 3600;
private $_account = 'test';
private $_datapath = './data/cookie_';
private $debug;
private $_logcallback;
public $login_user; //当前登陆用户, 调用get_login_info后获取
public function __construct($options)
{
$this->_account = isset($options['account'])?$options['account']:'';
$this->_datapath = isset($options['datapath'])?$options['datapath']:$this->_datapath;
$this->debug = isset($options['debug'])?$options['debug']:false;
$this->_logcallback = isset($options['logcallback'])?$options['logcallback']:false;
$this->_cookiename = $this->_datapath.$this->_account;
$this->getCookie($this->_cookiename);
}
/**
* 把cookie写入缓存
* @param string $filename 缓存文件名
* @param string $content 文件内容
* @return bool
*/
public function saveCookie($filename,$content){
return S($filename,$content,$this->_cookieexpired);
}
/**
* 读取cookie缓存内容
* @param string $filename 缓存文件名
* @return string cookie
*/
public function getCookie($filename){
$data = S($filename);
if ($data) $this->cookie = $data;
return $this->cookie;
}
/*
* 删除cookie
*/
public function deleteCookie($filename) {
$this->cookie = '';
S($filename,null);
return true;
}
private function log($log){
if ($this->debug && function_exists($this->_logcallback)) {
if (is_array($log)) $log = print_r($log,true);
return call_user_func($this->_logcallback,$log);
}
}
/**
* 获取登陆二维码对应的授权码
*/
public function get_login_code(){
if ($this->_logincode) return $this->_logincode;
$t = time().strval(mt_rand(100,999));
$codeurl = 'https://login.weixin.qq.com/jslogin?appid=wx782c26e4c19acffb&redirect_uri=https%3A%2F%2Fwx.qq.com%2Fcgi-bin%2Fmmwebwx-bin%2Fwebwxnewloginpage&fun=new&lang=zh_CN&_='.$t;
$send_snoopy = new Snoopy;
$send_snoopy->fetch($codeurl);
$result = $send_snoopy->results;
if ($result) {
preg_match("/window.QRLogin.uuid\s+=\s+\"([^\"]+)\"/",$result,$matches);
if(count($matches)>1) {
$this->_logincode = $matches[1];
$_SESSION['login_step'] = 0;
return $this->_logincode;
}
}
return $result;
}
/**
* 通过授权码获取对应的二维码图片地址
* @param string $code
* @return string image url
*/
public function get_code_image($code=''){
if ($code=='') $code = $this->_logincode;
if (!$code) return false;
return 'http://login.weixin.qq.com/qrcode/'.$this->_logincode.'?t=webwx';
}
/**
* 设置二维码对应的授权码
* @param string $code
* @return class $this
*/
public function set_login_code($code) {
$this->_logincode = $code;
return $this;
}
/**
* 二维码登陆验证
*
* @return status:
* >=400: invaild code; 408: not auth and wait, 400,401: not valid or expired
* 201: just scaned but not confirm
* 200: confirm then you can get user info
*/
public function verify_code() {
if (!$this->_logincode) return false;
$t = time().strval(mt_rand(100,999));
$url = 'https://login.weixin.qq.com/cgi-bin/mmwebwx-bin/login?uuid='.$this->_logincode.'&tip=0&_='.$t;
$send_snoopy = new Snoopy;
$send_snoopy->referer = "https://wx.qq.com/";
$send_snoopy->fetch($url);
$result = $send_snoopy->results;
$this->log('step1:'.$result);
if ($result) {
preg_match("/window\.code=(\d+)/",$result,$matches);
if(count($matches)>1) {
$status = intval($matches[1]);
if ($status==201) $_SESSION['login_step'] = 1;
if ($status==200) {
preg_match("/ticket=([0-9a-z-_]+)&lang=zh_CN&scan=(\d+)/",$result,$matches);
preg_match("/window.redirect_uri=\"([^\"]+)\"/",$result,$matcheurl);
$this->log('step2:'.print_r($matches,true));
if (count($matcheurl)>1) {
$ticket = $matches[1];
$scan = $matches[2];
//$loginurl = 'https://wx2.qq.com/cgi-bin/mmwebwx-bin/webwxnewloginpage?ticket='.$ticket.'&lang=zh_CN&scan='.$scan.'&fun=new';
$loginurl = str_replace("wx.qq.com", "wx2.qq.com", $matcheurl[1]).'&fun=old';
$urlpart = parse_url($loginurl);
$send_snoopy = new Snoopy;
$send_snoopy->referer = "https://{$urlpart['host']}/cgi-bin/mmwebwx-bin/webwxindex?t=chat";
$send_snoopy->fetch($loginurl);
$result = $send_snoopy->results;
$xml = simplexml_load_string($result);
if ($xml->ret=="0") $this->skey = $xml->skey;
foreach ($send_snoopy->headers as $key => $value) {
$value = trim($value);
if(strpos($value,'Set-Cookie: ') !== false){
$tmp = str_replace("Set-Cookie: ","",$value);
$tmparray = explode(';', $tmp);
$item = trim($tmparray[0]);
$cookie.=$item.';';
}
}
$cookie .="Domain=.qq.com;";
$this->cookie = $cookie;
$this->log('step3:'.$loginurl.';cookie:'.$cookie.';respond:'.$result);
$this->saveCookie($this->_cookiename,$this->cookie);
}
}
return $status;
}
}
return false;
}
/**
* 获取登陆的cookie
*
* @param bool $is_array 是否以数值方式返回,默认否,返回字符串
* @return string|array
*/
public function get_login_cookie($is_array = false){
if (!$is_array) return $this->cookie;
$c_arr = explode(';',$this->cookie);
$cookie = array();
foreach($c_arr as $item) {
$kitem = explode('=',trim($item));
if (count($kitem)>1) {
$key = trim($kitem[0]);
$val = trim($kitem[1]);
if (!empty($val)) $cookie[$key] = $val;
}
}
return $cookie;
}
/**
* 授权登陆后获取用户登陆信息
*/
public function get_login_info(){
if (!$this->cookie) return false;
$t = time().strval(mt_rand(100,999));
$send_snoopy = new Snoopy;
$submit = 'https://wx2.qq.com/cgi-bin/mmwebwx-bin/webwxinit?r='.$t.'&skey='.urlencode($this->skey);
$send_snoopy->rawheaders['Cookie']= $this->cookie;
$send_snoopy->referer = "https://wx2.qq.com/";
$citems = $this->get_login_cookie(true);
$post = array(
"BaseRequest"=>array(
array(
"Uin"=>$citems['wxuin'],
"Sid"=>$citems['wxsid'],
"Skey"=>$this->skey,
"DeviceID"=>''
)
)
);
$send_snoopy->submit($submit,json_encode($post));
$this->log('login_info:'.$send_snoopy->results);
$result = json_decode($send_snoopy->results,true);
if ($result['BaseResponse']['Ret']<0) return false;
$this->_login_user = $result['User'];
return $result;
}
/**
* 获取头像
* @param string $url 传入从用户信息接口获取到的头像地址
*/
public function get_avatar($url) {
if (!$this->cookie) return false;
if (strpos($url, 'http')===false) {
$url = 'http://wx2.qq.com'.$url;
}
$send_snoopy = new Snoopy;
$send_snoopy->rawheaders['Cookie']= $this->cookie;
$send_snoopy->referer = "https://wx2.qq.com/";
$send_snoopy->fetch($url);
$result = $send_snoopy->results;
if ($result)
return $result;
else
return false;
}
/**
* 登出当前登陆用户
*/
public function logout(){
if (!$this->cookie) return false;
preg_match("/wxuin=(\w+);/",$this->cookie,$matches);
if (count($matches)>1) $uid = $matches[1];
preg_match("/wxsid=(\w+);/",$this->cookie,$matches);
if (count($matches)>1) $sid = $matches[1];
$this->log('logout: uid='.$uid.';sid='.$sid);
$send_snoopy = new Snoopy;
$submit = 'https://wx2.qq.com/cgi-bin/mmwebwx-bin/webwxlogout?redirect=1&type=1';
$send_snoopy->rawheaders['Cookie']= $this->cookie;
$send_snoopy->referer = "https://wx2.qq.com/";
$send_snoopy->submit($submit,array('uin'=>$uid,'sid'=>$sid));
$this->deleteCookie($this->_cookiename);
return true;
}
}
================================================
FILE: old_version/Thinkphp/Wechatext.class.php
================================================
<?php
/**
* 微信公众平台PHP-SDK
* Wechatext为非官方微信发送API
* 注: 用户id为通过getMsg()方法获取的FakeId值
* 主要实现如下功能:
* send($id,$content) 向某用户id发送微信文字信息
* getUserList($page,$pagesize,$groupid) 获取用户信息
* getGroupList($page,$pagesize) 获取群组信息
* sendNews($id,$msgid) 发送图文消息
* getNewsList($page,$pagesize) 获取图文信息列表
* uploadFile($filepath,$type) 上传附件,包括图片/音频/视频
* addPreview($title,$author,$summary,$content,$photoid,$srcurl='') 创建新的图文信息
* getFileList($type,$page,$pagesize) 获取素材库文件列表
* sendImage($id,$fid) 发送图片消息
* sendAudio($id,$fid) 发送音频消息
* sendVideo($id,$fid) 发送视频消息
* getInfo($id) 根据id获取用户资料
* getNewMsgNum($lastid) 获取从$lastid算起新消息的数目
* getTopMsg() 获取最新一条消息的数据, 此方法获取的消息id可以作为检测新消息的$lastid依据
* getMsg($lastid,$offset=0,$perpage=50,$day=0,$today=0,$star=0) 获取最新的消息列表, 列表将返回消息id, 用户id, 消息类型, 文字消息等参数
* 消息返回结构: {"id":"消息id","type":"类型号(1为文字,2为图片,3为语音)","fileId":"0","hasReply":"0","fakeId":"用户uid","nickName":"昵称","dateTime":"时间戳","content":"文字内容"}
* getMsgImage($msgid,$mode='large') 若消息type类型为2, 调用此方法获取图片数据
* getMsgVoice($msgid) 若消息type类型为3, 调用此方法获取语音数据
* quickSetInterface($url, $token) 快速设置接口信息
* @author dodge <dodgepudding@gmail.com>
* @link https://github.com/dodgepudding/wechat-php-sdk
* @version 1.2
*
*/
include "Snoopy.class.php";
class Wechatext
{
private $cookie;
private $_cookiename;
private $_cookieexpired = 3600;
private $_account;
private $_password;
private $_datapath = './data/cookie_';
private $debug;
private $_logcallback;
private $_token;
public function __construct($options)
{
$this->_account = isset($options['account'])?$options['account']:'';
$this->_password = isset($options['password'])?$options['password']:'';
$this->_datapath = isset($options['datapath'])?$options['datapath']:$this->_datapath;
$this->debug = isset($options['debug'])?$options['debug']:false;
$this->_logcallback = isset($options['logcallback'])?$options['logcallback']:false;
$this->_cookiename = $this->_datapath.$this->_account;
$this->cookie = $this->getCookie($this->_cookiename);
}
/**
* 主动发消息
* @param string $id 用户的uid(即FakeId)
* @param string $content 发送的内容
*/
public function send($id,$content)
{
$send_snoopy = new Snoopy;
$post = array();
$post['tofakeid'] = $id;
$post['type'] = 1;
$post['token'] = $this->_token;
$post['content'] = $content;
$post['ajax'] = 1;
$send_snoopy->referer = "https://mp.weixin.qq.com/cgi-bin/singlesendpage?t=message/send&action=index&tofakeid=$id&token={$this->_token}&lang=zh_CN";
$send_snoopy->rawheaders['Cookie']= $this->cookie;
$submit = "https://mp.weixin.qq.com/cgi-bin/singlesend?t=ajax-response";
$send_snoopy->submit($submit,$post);
$this->log($send_snoopy->results);
return $send_snoopy->results;
}
/**
* 群发功能 纯文本
* @param string $content
* @return string
*/
public function mass($content) {
$send_snoopy = new Snoopy;
$post = array();
$post['type'] = 1;
$post['token'] = $this->_token;
$post['content'] = $content;
$post['ajax'] = 1;
$post['city']='';
$post['country']='';
$post['f']='json';
$post['groupid']='-1';
$post['imgcode']='';
$post['lang']='zh_CN';
$post['province']='';
$post['random']= rand(0, 1);
$post['sex']=0;
$post['synctxnews']=0;
$post['synctxweibo']=0;
$post['t']='ajax-response';
$send_snoopy->referer = "https://mp.weixin.qq.com/cgi-bin/masssendpage?t=mass/send&token={$this->_token}&lang=zh_CN";
$send_snoopy->rawheaders['Cookie']= $this->cookie;
$submit = "https://mp.weixin.qq.com/cgi-bin/masssend";
$send_snoopy->submit($submit,$post);
$this->log($send_snoopy->results);
return $send_snoopy->results;
}
/**
* 群发功能 图文素材
* @param int $appmsgid 图文素材ID
* @return string
*/
function massNews($appmsgid){
$send_snoopy = new Snoopy;
$post = array();
$post['type'] = 10;
$post['token'] = $this->_token;
$post['appmsgid'] = $appmsgid;
$post['ajax'] = 1;
$post['city']='';
$post['country']='';
$post['f']='json';
$post['groupid']='-1';
$post['imgcode']='';
$post['lang']='zh_CN';
$post['province']='';
$post['random']= rand(0, 1);
$post['sex']=0;
$post['synctxnews']=0;
$post['synctxweibo']=0;
$post['t']='ajax-response';
$send_snoopy->referer = "https://mp.weixin.qq.com/cgi-bin/masssendpage?t=mass/send&token={$this->_token}&lang=zh_CN";
$send_snoopy->rawheaders['Cookie']= $this->cookie;
$submit = "https://mp.weixin.qq.com/cgi-bin/masssend";
$send_snoopy->submit($submit,$post);
$this->log($send_snoopy->results);
return $send_snoopy->results;
}
/**
* 获取用户列表列表
* @param $page 页码(从0开始)
* @param $pagesize 每页大小
* @param $groupid 分组id
* @return array ({contacts:[{id:12345667,nick_name:"昵称",remark_name:"备注名",group_id:0},{}....]})
*/
function getUserList($page=0,$pagesize=10,$groupid=0){
$send_snoopy = new Snoopy;
$t = time().strval(mt_rand(100,999));
$send_snoopy->referer = "https://mp.weixin.qq.com/cgi-bin/contactmanage?t=user/index&pagesize=".$pagesize."&pageidx=".$page."&type=0&groupid=0&lang=zh_CN&token=".$this->_token;
$send_snoopy->rawheaders['Cookie']= $this->cookie;
$submit = "https://mp.weixin.qq.com/cgi-bin/contactmanage?t=user/index&pagesize=".$pagesize."&pageidx=".$page."&type=0&groupid=$groupid&lang=zh_CN&f=json&token=".$this->_token;
$send_snoopy->fetch($submit);
$result = $send_snoopy->results;
$this->log('userlist:'.$result);
$json = json_decode($result,true);
if (isset($json['contact_list'])) {
$json = json_decode($json['contact_list'],true);
if (isset($json['contacts']))
return $json['contacts'];
}
return false;
}
/**
* 获取分组列表
*
*/
function getGroupList(){
$send_snoopy = new Snoopy;
$t = time().strval(mt_rand(100,999));
$send_snoopy->referer = "https://mp.weixin.qq.com/cgi-bin/contactmanage?t=user/index&pagesize=10&pageidx=0&type=0&groupid=0&lang=zh_CN&token=".$this->_token;
$send_snoopy->rawheaders['Cookie']= $this->cookie;
$submit = "https://mp.weixin.qq.com/cgi-bin/contactmanage?t=user/index&pagesize=10&pageidx=0&type=0&groupid=0&lang=zh_CN&f=json&token=".$this->_token;
$send_snoopy->fetch($submit);
$result = $send_snoopy->results;
$this->log('userlist:'.$result);
$json = json_decode($result,true);
if (isset($json['group_list'])){
$json = json_decode($json['group_list'],true);
if (isset($json['groups']))
return $json['groups'];
}
return false;
}
/**
* 获取图文信息列表
* @param $page 页码(从0开始)
* @param $pagesize 每页大小
* @return array
*/
public function getNewsList($page,$pagesize=10) {
$send_snoopy = new Snoopy;
$t = time().strval(mt_rand(100,999));
$type=10;
$begin = $page*$pagesize;
$send_snoopy->referer = "https://mp.weixin.qq.com/cgi-bin/masssendpage?t=mass/send&token=".$this->_token."&lang=zh_CN";
$send_snoopy->rawheaders['Cookie']= $this->cookie;
$submit = "https://mp.weixin.qq.com/cgi-bin/appmsg?token=".$this->_token."&lang=zh_CN&type=$type&action=list&begin=$begin&count=$pagesize&f=json&random=0.".$t;
$send_snoopy->fetch($submit);
$result = $send_snoopy->results;
$this->log('newslist:'.$result);
$json = json_decode($result,true);
if (isset($json['app_msg_info'])) {
return $json['app_msg_info'];
}
return false;
}
/**
* 获取与指定用户的对话内容
* @param $fakeid
* @return array
*/
public function getDialogMsg($fakeid) {
$send_snoopy = new Snoopy;
$t = time().strval(mt_rand(100,999));
$send_snoopy->referer = "https://mp.weixin.qq.com/cgi-bin/masssendpage?t=mass/send&token=".$this->_token."&lang=zh_CN";
$send_snoopy->rawheaders['Cookie']= $this->cookie;
$submit = "https://mp.weixin.qq.com/cgi-bin/singlesendpage?t=message/send&action=index&tofakeid=".$fakeid."&token=".$this->_token."&lang=zh_CN&f=json&random=".$t;
$send_snoopy->fetch($submit);
$result = $send_snoopy->results;
$this->log('DialogMsg:'.$result);
$json = json_decode($result,true);
if (isset($json['page_info'])) {
return $json['page_info'];
}
return false;
}
/**
* 发送图文信息,必须从图文库里选取消息ID发送
* @param string $id 用户的uid(即FakeId)
* @param string $msgid 图文消息id
*/
public function sendNews($id,$msgid)
{
$send_snoopy = new Snoopy;
$post = array();
$post['tofakeid'] = $id;
$post['type'] = 10;
$post['token'] = $this->_token;
$post['fid'] = $msgid;
$post['appmsgid'] = $msgid;
$post['error'] = 'false';
$post['ajax'] = 1;
$send_snoopy->referer = "https://mp.weixin.qq.com/cgi-bin/singlemsgpage?fromfakeid={$id}&msgid=&source=&count=20&t=wxm-singlechat&lang=zh_CN";
$send_snoopy->rawheaders['Cookie']= $this->cookie;
$submit = "https://mp.weixin.qq.com/cgi-bin/singlesend?t=ajax-response";
$send_snoopy->submit($submit,$post);
$this->log($send_snoopy->results);
return $send_snoopy->results;
}
/**
* 上传附件(图片/音频/视频)
* @param string $filepath 本地文件地址
* @param int $type 文件类型: 2:图片 3:音频 4:视频
*/
public function uploadFile($filepath,$type=2) {
$send_snoopy = new Snoopy;
$send_snoopy->referer = "http://mp.weixin.qq.com/cgi-bin/indexpage?t=wxm-upload&lang=zh_CN&type=2&formId=1";
$t = time().strval(mt_rand(100,999));
$post = array('formId'=>'');
$postfile = array('uploadfile'=>$filepath);
$send_snoopy->rawheaders['Cookie']= $this->cookie;
$send_snoopy->set_submit_multipart();
$submit = "http://mp.weixin.qq.com/cgi-bin/uploadmaterial?cgi=uploadmaterial&type=$type&token=".$this->_token."&t=iframe-uploadfile&lang=zh_CN&formId= file_from_".$t;
$send_snoopy->submit($submit,$post,$postfile);
$tmp = $send_snoopy->results;
$this->log('upload:'.$tmp);
preg_match("/formId,.*?\'(\d+)\'/",$tmp,$matches);
if (isset($matches[1])) {
return $matches[1];
}
return false;
}
/**
* 创建图文消息
* @param array $title 标题
* @param array $summary 摘要
* @param array $content 内容
* @param array $photoid 素材库里的图片id(可通过uploadFile上传后获取)
* @param array $srcurl 原文链接
* @return json
*/
public function addPreview($title,$author,$summary,$content,$photoid,$srcurl='') {
$send_snoopy = new Snoopy;
$send_snoopy->referer = 'https://mp.weixin.qq.com/cgi-bin/operate_appmsg?lang=zh_CN&sub=edit&t=wxm-appmsgs-edit-new&type=10&subtype=3&token='.$this->_token;
$submit = "https://mp.weixin.qq.com/cgi-bin/operate_appmsg?lang=zh_CN&t=ajax-response&sub=create&token=".$this->_token;
$send_snoopy->rawheaders['Cookie']= $this->cookie;
$send_snoopy->set_submit_normal();
$post = array(
'token'=>$this->_token,
'type'=>10,
'lang'=>'zh_CN',
'sub'=>'create',
'ajax'=>1,
'AppMsgId'=>'',
'error'=>'false',
);
if (count($title)==count($author)&&count($title)==count($summary)&&count($title)==count($content)&&count($title)==count($photoid))
{
$i = 0;
foreach($title as $v) {
$post['title'.$i] = $title[$i];
$post['author'.$i] = $author[$i];
$post['digest'.$i] = $summary[$i];
$post['content'.$i] = $content[$i];
$post['fileid'.$i] = $photoid[$i];
if ($srcurl[$i]) $post['sourceurl'.$i] = $srcurl[$i];
$i++;
}
}
$post['count'] = $i;
$post['token'] = $this->_token;
$send_snoopy->submit($submit,$post);
$tmp = $send_snoopy->results;
$this->log('step2:'.$tmp);
$json = json_decode($tmp,true);
return $json;
}
/**
* 发送媒体文件
* @param $id 用户的uid(即FakeId)
* @param $fid 文件id
* @param $type 文件类型
*/
public function sendFile($id,$fid,$type) {
$send_snoopy = new Snoopy;
$post = array();
$post['tofakeid'] = $id;
$post['type'] = $type;
$post['token'] = $this->_token;
$post['fid'] = $fid;
$post['fileid'] = $fid;
$post['error'] = 'false';
$post['ajax'] = 1;
$send_snoopy->referer = "https://mp.weixin.qq.com/cgi-bin/singlemsgpage?fromfakeid={$id}&msgid=&source=&count=20&t=wxm-singlechat&lang=zh_CN";
$send_snoopy->rawheaders['Cookie']= $this->cookie;
$submit = "https://mp.weixin.qq.com/cgi-bin/singlesend?t=ajax-response";
$send_snoopy->submit($submit,$post);
$result = $send_snoopy->results;
$this->log('sendfile:'.$result);
$json = json_decode($result,true);
if ($json && $json['ret']==0)
return true;
else
return false;
}
/**
* 获取素材库文件列表
* @param $type 文件类型: 2:图片 3:音频 4:视频
* @param $page 页码(从0开始)
* @param $pagesize 每页大小
* @return array
*/
public function getFileList($type,$page,$pagesize=10) {
$send_snoopy = new Snoopy;
$t = time().strval(mt_rand(100,999));
$begin = $page*$pagesize;
$send_snoopy->referer = "https://mp.weixin.qq.com/cgi-bin/masssendpage?t=mass/send&token=".$this->_token."&lang=zh_CN";
$send_snoopy->rawheaders['Cookie']= $this->cookie;
$submit = "https://mp.weixin.qq.com/cgi-bin/filepage?token=".$this->_token."&lang=zh_CN&type=$type&random=0.".$t."&begin=$begin&count=$pagesize&f=json";
$send_snoopy->fetch($submit);
$result = $send_snoopy->results;
$this->log('filelist:'.$result);
$json = json_decode($result,true);
if (isset($json['page_info']))
return $json['page_info'];
else
return false;
}
/**
* 发送图文信息,必须从库里选取文件ID发送
* @param string $id 用户的uid(即FakeId)
* @param string $fid 文件id
*/
public function sendImage($id,$fid)
{
return $this->sendFile($id,$fid,2);
}
/**
* 发送语音信息,必须从库里选取文件ID发送
* @param string $id 用户的uid(即FakeId)
* @param string $fid 语音文件id
*/
public function sendAudio($id,$fid)
{
return $this->sendFile($id,$fid,3);
}
/**
* 发送视频信息,必须从库里选取文件ID发送
* @param string $id 用户的uid(即FakeId)
* @param string $fid 视频文件id
*/
public function sendVideo($id,$fid)
{
return $this->sendFile($id,$fid,4);
}
/**
* 发送预览图文消息
* @param string $account 账户名称(user_name)
* @param string $title 标题
* @param string $summary 摘要
* @param string $content 内容
* @param string $photoid 素材库里的图片id(可通过uploadFile上传后获取)
* @param string $srcurl 原文链接
* @return json
*/
public function sendPreview($account,$title,$summary,$content,$photoid,$srcurl='') {
$send_snoopy = new Snoopy;
$submit = "https://mp.weixin.qq.com/cgi-bin/operate_appmsg?sub=preview&t=ajax-appmsg-preview";
$send_snoopy->set_submit_normal();
$send_snoopy->rawheaders['Cookie']= $this->cookie;
$send_snoopy->referer = 'https://mp.weixin.qq.com/cgi-bin/operate_appmsg?sub=edit&t=wxm-appmsgs-edit-new&type=10&subtype=3&lang=zh_CN';
$post = array(
'AppMsgId'=>'',
'ajax'=>1,
'content0'=>$content,
'count'=>1,
'digest0'=>$summary,
'error'=>'false',
'fileid0'=>$photoid,
'preusername'=>$account,
'sourceurl0'=>$srcurl,
'title0'=>$title,
);
$post['token'] = $this->_token;
$send_snoopy->submit($submit,$post);
$tmp = $send_snoopy->results;
$this->log('sendpreview:'.$tmp);
$json = json_decode($tmp,true);
return $json;
}
/**
* 获取用户的信息
* @param string $id 用户的uid(即FakeId)
* @return array {fake_id:100001,nick_name:'昵称',user_name:'用户名',signature:'签名档',country:'中国',province:'广东',city:'广州',gender:'1',group_id:'0'},groups:{[id:0,name:'未分组',cnt:20]}
*/
public function getInfo($id)
{
$send_snoopy = new Snoopy;
$send_snoopy->rawheaders['Cookie']= $this->cookie;
$t = time().strval(mt_rand(100,999));
$send_snoopy->referer = "https://mp.weixin.qq.com/cgi-bin/getmessage?t=wxm-message&lang=zh_CN&count=50&token=".$this->_token;
$submit = "https://mp.weixin.qq.com/cgi-bin/getcontactinfo";
$post = array('ajax'=>1,'lang'=>'zh_CN','random'=>'0.'.$t,'token'=>$this->_token,'t'=>'ajax-getcontactinfo','fakeid'=>$id);
$send_snoopy->submit($submit,$post);
$this->log($send_snoopy->results);
$result = json_decode($send_snoopy->results,true);
if(isset($result['contact_info'])){
return $result['contact_info'];
}
return false;
}
/**
* 获得头像数据
*
* @param FakeId $fakeid
* @return JPG二进制数据
*/
public function getHeadImg($fakeid){
$send_snoopy = new Snoopy;
$send_snoopy->rawheaders['Cookie']= $this->cookie;
$send_snoopy->referer = "https://mp.weixin.qq.com/cgi-bin/getmessage?t=wxm-message&lang=zh_CN&count=50&token=".$this->_token;
$url = "https://mp.weixin.qq.com/misc/getheadimg?fakeid=$fakeid&token=".$this->_token."&lang=zh_CN";
$send_snoopy->fetch($url);
$result = $send_snoopy->results;
$this->log('Head image:'.$fakeid.'; length:'.strlen($result));
if(!$result){
return false;
}
return $result;
}
/**
* 获取消息更新数目
* @param int $lastid 最近获取的消息ID,为0时获取总消息数目
* @return int 数目
*/
public function getNewMsgNum($lastid=0){
$send_snoopy = new Snoopy;
$send_snoopy->rawheaders['Cookie']= $this->cookie;
$send_snoopy->referer = "https://mp.weixin.qq.com/cgi-bin/getmessage?t=wxm-message&lang=zh_CN&count=50&token=".$this->_token;
$submit = "https://mp.weixin.qq.com/cgi-bin/getnewmsgnum?t=ajax-getmsgnum&lastmsgid=".$lastid;
$post = array('ajax'=>1,'token'=>$this->_token);
$send_snoopy->submit($submit,$post);
$this->log($send_snoopy->results);
$result = json_decode($send_snoopy->results,1);
if(!$result){
return false;
}
return intval($result['newTotalMsgCount']);
}
/**
* 获取最新一条消息
* @return array {"id":"最新一条id","type":"类型号(1为文字,2为图片,3为语音)","fileId":"0","hasReply":"0","fakeId":"用户uid","nickName":"昵称","dateTime":"时间戳","content":"文字内容","playLength":"0","length":"0","source":"","starred":"0","status":"4"}
*/
public function getTopMsg(){
$send_snoopy = new Snoopy;
$send_snoopy->rawheaders['Cookie']= $this->cookie;
$send_snoopy->referer = "https://mp.weixin.qq.com/cgi-bin/message?t=message/list&count=20&day=7&lang=zh_CN&token=".$this->_token;
$submit = "https://mp.weixin.qq.com/cgi-bin/message?t=message/list&f=json&count=20&day=7&lang=zh_CN&token=".$this->_token;
$send_snoopy->fetch($submit);
$this->log($send_snoopy->results);
$result = $send_snoopy->results;
$json = json_decode($result,true);
if (isset($json['msg_items'])) {
$json = json_decode($json['msg_items'],true);
if(isset($json['msg_item']))
return array_shift($json['msg_item']);
}
return false;
}
/**
* 获取新消息
* @param $lastid 传入最后的消息id编号,为0则从最新一条起倒序获取
* @param $offset lastid起算第一条的偏移量
* @param $perpage 每页获取多少条
* @param $day 最近几天消息(0:今天,1:昨天,2:前天,3:更早,7:五天内)
* @param $today 是否只显示今天的消息, 与$day参数不能同时大于0
* @param $star 是否星标组信息
* @return array[] 同getTopMsg()返回的字段结构相同
*/
public function getMsg($lastid=0,$offset=0,$perpage=20,$day=7,$today=0,$star=0){
$send_snoopy = new Snoopy;
$send_snoopy->rawheaders['Cookie']= $this->cookie;
$send_snoopy->referer = "https://mp.weixin.qq.com/cgi-bin/message?t=message/list&lang=zh_CN&count=50&token=".$this->_token;
$lastid = $lastid===0 ? '':$lastid;
$addstar = $star?'&action=star':'';
$submit = "https://mp.weixin.qq.com/cgi-bin/message?t=message/list&f=json&lang=zh_CN{$addstar}&count=$perpage&timeline=$today&day=$day&frommsgid=$lastid&offset=$offset&token=".$this->_token;
$send_snoopy->fetch($submit);
$this->log($send_snoopy->results);
$result = $send_snoopy->results;
$json = json_decode($result,true);
if (isset($json['msg_items'])) {
$json = json_decode($json['msg_items'],true);
if(isset($json['msg_item']))
return $json['msg_item'];
}
return false;
}
/**
* 获取图片消息
* @param int $msgid 消息id
* @param string $mode 图片尺寸(large/small)
* @return jpg二进制文件
*/
public function getMsgImage($msgid,$mode='large'){
$send_snoopy = new Snoopy;
$send_snoopy->rawheaders['Cookie']= $this->cookie;
$send_snoopy->referer = "https://mp.weixin.qq.com/cgi-bin/getmessage?t=wxm-message&lang=zh_CN&count=50&token=".$this->_token;
$url = "https://mp.weixin.qq.com/cgi-bin/getimgdata?token=".$this->_token."&msgid=$msgid&mode=$mode&source=&fileId=0";
$send_snoopy->fetch($url);
$result = $send_snoopy->results;
$this->log('msg image:'.$msgid.';length:'.strlen($result));
if(!$result){
return false;
}
return $result;
}
/**
* 获取语音消息
* @param int $msgid 消息id
* @return mp3二进制文件
*/
public function getMsgVoice($msgid){
$send_snoopy = new Snoopy;
$send_snoopy->rawheaders['Cookie']= $this->cookie;
$send_snoopy->referer = "https://mp.weixin.qq.com/cgi-bin/getmessage?t=wxm-message&lang=zh_CN&count=50&token=".$this->_token;
$url = "https://mp.weixin.qq.com/cgi-bin/getvoicedata?token=".$this->_token."&msgid=$msgid&fileId=0";
$send_snoopy->fetch($url);
$result = $send_snoopy->results;
$this->log('msg voice:'.$msgid.';length:'.strlen($result));
if(!$result){
return false;
}
return $result;
}
/**
* 开启开发者模式
*/
public function openDevModel()
{
$send_snoopy = new Snoopy;
$send_snoopy->rawheaders['Cookie']= $this->cookie;
$send_snoopy->referer = "https://mp.weixin.qq.com/advanced/advanced?action=dev&t=advanced/dev&lang=zh_CN&token=".$this->_token;
$submit = "https://mp.weixin.qq.com/misc/skeyform?form=advancedswitchform&lang=zh_CN";
$post['flag']=1;
$post['type']=2;
$post['token']=$this->_token;
$send_snoopy->submit($submit,$post);
$result = $send_snoopy->results;
$this->log($send_snoopy->results);
$json = json_decode($result,true);
if(!$result){
return false;
}
return true;
}
/**
* 关闭编辑模式
*/
public function closeEditModel()
{
$send_snoopy = new Snoopy;
$send_snoopy->rawheaders['Cookie']= $this->cookie;
$send_snoopy->referer = "https://mp.weixin.qq.com/advanced/advanced?action=dev&t=advanced/dev&lang=zh_CN&token=".$this->_token;
$submit = "https://mp.weixin.qq.com/misc/skeyform?form=advancedswitchform&lang=zh_CN";
$post['flag']=0;
$post['type']=1;
$post['token']=$this->_token;
$send_snoopy->submit($submit,$post);
$result = $send_snoopy->results;
$this->log($send_snoopy->results);
$json = json_decode($result,true);
if(!$result){
return false;
}
return true;
}
/**
* 配置接口信息
* @param string $url 接口回调URL
* @param string $token 接口Token
*/
public function setUrlToken($url, $token)
{
$send_snoopy = new Snoopy;
$send_snoopy->rawheaders['Cookie']= $this->cookie;
$send_snoopy->referer = "https://mp.weixin.qq.com/advanced/advanced?action=interface&t=advanced/interface&lang=zh_CN&token=".$this->_token;
$submit = "https://mp.weixin.qq.com/advanced/callbackprofile?t=ajax-response&lang=zh_CN&token=".$this->_token;
$post['url'] = $url;
$post['callback_token'] = $token;
$send_snoopy->submit($submit,$post);
$result = $send_snoopy->results;
$this->log($send_snoopy->results);
$json = json_decode($result,true);
if ($json && $json['ret']==0)
return true;
return false;
}
/**
* 快速设置接口
* @param string $url 接口回调URL
* @param string $token 接口Token
*/
public function quickSetInterface($url, $token)
{
if ($this->closeEditModel() && $this->openDevModel() && $this->setUrlToken($url, $token))
return true;
return false;
}
/**
* 模拟登录获取cookie
* @return [type] [description]
*/
public function login(){
$snoopy = new Snoopy;
$submit = "https://mp.weixin.qq.com/cgi-bin/login?lang=zh_CN";
$post["username"] = $this->_account;
$post["pwd"] = md5($this->_password);
$post["f"] = "json";
$post["imgcode"] = "";
$snoopy->referer = "https://mp.weixin.qq.com/";
$snoopy->submit($submit,$post);
$cookie = '';
$this->log($snoopy->results);
$result = json_decode($snoopy->results,true);
if (!isset($result['base_resp']) || $result['base_resp']['ret'] != 0) {
return false;
}
foreach ($snoopy->headers as $key => $value) {
$value = trim($value);
if(preg_match('/^set-cookie:[\s]+([^=]+)=([^;]+)/i', $value,$match))
$cookie .=$match[1].'='.$match[2].'; ';
}
preg_match("/token=(\d+)/i",$result['redirect_url'],$matches);
if($matches){
$this->_token = $matches[1];
$this->log('token:'.$this->_token);
}
$cookies='{"cookie":"'.$cookie.'","token":"'.$this->_token.'"}';
$this->saveCookie($this->_cookiename,$cookies);
return $cookie;
}
/**
* 把cookie写入缓存
* @param string $filename 缓存文件名
* @param string $content 文件内容
* @return bool
*/
public function saveCookie($filename,$content){
return S($filename,$content,$this->_cookieexpired);
}
/**
* 读取cookie缓存内容
* @param string $filename 缓存文件名
* @return string cookie
*/
public function getCookie($filename){
$data = S($filename);
if($data){
$login=json_decode($data,true);
$send_snoopy = new Snoopy;
$send_snoopy->rawheaders['Cookie']= $login['cookie'];
$send_snoopy->maxredirs = 0;
$url = "https://mp.weixin.qq.com/cgi-bin/home?t=home/index&lang=zh_CN&token=".$login['token'];
$send_snoopy->fetch($url);
$header = $send_snoopy->headers;
$this->log('header:'.print_r($send_snoopy->headers,true));
if( strstr($header[3], 'EXPIRED')){
return $this->login();
}else{
$this->_token =$login['token'];
return $login['cookie'];
}
}else{
return $this->login();
}
}
/**
* 验证cookie的有效性
* @return bool
*/
public function checkValid()
{
if (!$this->cookie || !$this->_token) return false;
$send_snoopy = new Snoopy;
$post = array('ajax'=>1,'token'=>$this->_token);
$submit = "https://mp.weixin.qq.com/cgi-bin/getregions?id=1017&t=ajax-getregions&lang=zh_CN";
$send_snoopy->rawheaders['Cookie']= $this->cookie;
$send_snoopy->submit($submit,$post);
$result = $send_snoopy->results;
if(json_decode($result,1)){
return true;
}else{
return false;
}
}
private function log($log){
if ($this->debug ) {
if (function_exists($this->_logcallback)) {
if (is_array($log)) $log = print_r($log,true);
return call_user_func($this->_logcallback,$log);
}elseif (class_exists('Log')) {
Log::write('wechat:'.$log, Log::DEBUG);
}
}
return false;
}
}
================================================
FILE: old_version/Thinkphp/Wechatpay.class.php
================================================
<?php
/**
* 微信公众平台PHP-SDK, 旧版微信支付接口(微信支付V2)
* @author dodge <dodgepudding@gmail.com>
* @link https://github.com/dodgepudding/wechat-php-sdk
* @version 1.2
* 参考旧版文档 https://mp.weixin.qq.com/cgi-bin/readtemplate?t=business/course2_tmpl&lang=zh_CN
* usage:
* $options = array(
* 'appid'=>'wxdk1234567890', //填写高级调用功能的app id
* 'appsecret'=>'xxxxxxxxxxxxxxxxxxx', //填写高级调用功能的密钥
* 'partnerid'=>'88888888', //财付通商户身份标识
* 'partnerkey'=>'', //财付通商户权限密钥Key
* 'paysignkey'=>'' //商户签名密钥Key
* );
* $payObj = new Wechatpay($options);
* $package = $payObj->createPackage($out_trade_no,$body,$total_fee,$notify_url,$spbill_create_ip,$fee_type,$bank_type,$input_charset,$time_start,$time_expire,$transport_fee,$product_fee,$goods_tag,$attach);
*
*/
class Wechatpay
{
const API_URL_PREFIX = 'https://api.weixin.qq.com/cgi-bin';
const AUTH_URL = '/token?grant_type=client_credential&';
const API_BASE_URL_PREFIX = 'https://api.weixin.qq.com'; //以下API接口URL需要使用此前缀
const PAY_DELIVERNOTIFY = '/pay/delivernotify?';
const PAY_ORDERQUERY = '/pay/orderquery?';
private $appid;
private $appsecret;
private $access_token;
private $user_token;
private $partnerid;
private $partnerkey;
private $paysignkey;
public $debug = false;
public $errCode = 40001;
public $errMsg = "no access";
private $_logcallback;
public function __construct($options)
{
$this->appid = isset($options['appid'])?$options['appid']:'';
$this->appsecret = isset($options['appsecret'])?$options['appsecret']:'';
$this->partnerid = isset($options['partnerid'])?$options['partnerid']:'';
$this->partnerkey = isset($options['partnerkey'])?$options['partnerkey']:'';
$this->paysignkey = isset($options['paysignkey'])?$options['paysignkey']:'';
$this->debug = isset($options['debug'])?$options['debug']:false;
$this->_logcallback = isset($options['logcallback'])?$options['logcallback']:false;
}
private function log($log){
if ($this->debug ) {
if (function_exists($this->_logcallback)) {
if (is_array($log)) $log = print_r($log,true);
return call_user_func($this->_logcallback,$log);
}elseif (class_exists('Log')) {
Log::write('wechat:'.$log, Log::DEBUG);
}
}
return false;
}
/**
* GET 请求
* @param string $url
*/
private function http_get($url){
$oCurl = curl_init();
if(stripos($url,"https://")!==FALSE){
curl_setopt($oCurl, CURLOPT_SSL_VERIFYPEER, FALSE);
curl_setopt($oCurl, CURLOPT_SSL_VERIFYHOST, FALSE);
curl_setopt($oCurl, CURLOPT_SSLVERSION, 1); //CURL_SSLVERSION_TLSv1
}
curl_setopt($oCurl, CURLOPT_URL, $url);
curl_setopt($oCurl, CURLOPT_RETURNTRANSFER, 1 );
$sContent = curl_exec($oCurl);
$aStatus = curl_getinfo($oCurl);
curl_close($oCurl);
if(intval($aStatus["http_code"])==200){
return $sContent;
}else{
return false;
}
}
/**
* POST 请求
* @param string $url
* @param array $param
* @param boolean $post_file 是否文件上传
* @return string content
*/
private function http_post($url,$param,$post_file=false){
$oCurl = curl_init();
if(stripos($url,"https://")!==FALSE){
curl_setopt($oCurl, CURLOPT_SSL_VERIFYPEER, FALSE);
curl_setopt($oCurl, CURLOPT_SSL_VERIFYHOST, false);
curl_setopt($oCurl, CURLOPT_SSLVERSION, 1); //CURL_SSLVERSION_TLSv1
}
if (is_string($param) || $post_file) {
$strPOST = $param;
} else {
$aPOST = array();
foreach($param as $key=>$val){
$aPOST[] = $key."=".urlencode($val);
}
$strPOST = join("&", $aPOST);
}
curl_setopt($oCurl, CURLOPT_URL, $url);
curl_setopt($oCurl, CURLOPT_RETURNTRANSFER, 1 );
curl_setopt($oCurl, CURLOPT_POST,true);
curl_setopt($oCurl, CURLOPT_POSTFIELDS,$strPOST);
$sContent = curl_exec($oCurl);
$aStatus = curl_getinfo($oCurl);
curl_close($oCurl);
if(intval($aStatus["http_code"])==200){
return $sContent;
}else{
return false;
}
}
/**
* 获取access_token
* @param string $appid 如在类初始化时已提供,则可为空
* @param string $appsecret 如在类初始化时已提供,则可为空
* @param string $token 手动指定access_token,非必要情况不建议用
*/
public function checkAuth($appid='',$appsecret='',$token=''){
if (!$appid || !$appsecret) {
$appid = $this->appid;
$appsecret = $this->appsecret;
}
$authname = 'wechat_access_token'.$appid;
if ($token) { //手动指定token,优先使用
$this->access_token=$token;
return $this->access_token;
}
if ($rs = S($authname)) {
$this->access_token = $rs;
return $rs;
}
$result = $this->http_get(self::API_URL_PREFIX.self::AUTH_URL.'appid='.$appid.'&secret='.$appsecret);
if ($result)
{
$json = json_decode($result,true);
if (!$json || isset($json['errcode'])) {
$this->errCode = $json['errcode'];
$this->errMsg = $json['errmsg'];
return false;
}
$this->access_token = $json['access_token'];
$expire = $json['expires_in'] ? intval($json['expires_in'])-100 : 3600;
S($authname,$this->access_token,$expire);
return $this->access_token;
}
return false;
}
/**
* 删除验证数据
* @param string $appid
*/
public function resetAuth($appid=''){
if (!$appid) $appid = $this->appid;
$this->access_token = '';
$authname = 'wechat_access_token'.$appid;
S($authname,null);
return true;
}
/**
* 微信api不支持中文转义的json结构
* @param array $arr
*/
static function json_encode($arr) {
$parts = array ();
$is_list = false;
//Find out if the given array is a numerical array
$keys = array_keys ( $arr );
$max_length = count ( $arr ) - 1;
if (($keys [0] === 0) && ($keys [$max_length] === $max_length )) { //See if the first key is 0 and last key is length - 1
$is_list = true;
for($i = 0; $i < count ( $keys ); $i ++) { //See if each key correspondes to its position
if ($i != $keys [$i]) { //A key fails at position check.
$is_list = false; //It is an associative array.
break;
}
}
}
foreach ( $arr as $key => $value ) {
if (is_array ( $value )) { //Custom handling for arrays
if ($is_list)
$parts [] = self::json_encode ( $value ); /* :RECURSION: */
else
$parts [] = '"' . $key . '":' . self::json_encode ( $value ); /* :RECURSION: */
} else {
$str = '';
if (! $is_list)
$str = '"' . $key . '":';
//Custom handling for multiple data types
if (!is_string ( $value ) && is_numeric ( $value ) && $value<2000000000)
$str .= $value; //Numbers
elseif ($value === false)
$str .= 'false'; //The booleans
elseif ($value === true)
$str .= 'true';
else
$str .= '"' . addslashes ( $value ) . '"'; //All other things
// :TODO: Is there any more datatype we should be in the lookout for? (Object?)
$parts [] = $str;
}
}
$json = implode ( ',', $parts );
if ($is_list)
return '[' . $json . ']'; //Return numerical JSON
return '{' . $json . '}'; //Return associative JSON
}
/**
* 获取签名
* @param array $arrdata 签名数组
* @param string $method 签名方法
* @return boolean|string 签名值
*/
public function getSignature($arrdata,$method="sha1") {
if (!function_exists($method)) return false;
ksort($arrdata);
$paramstring = "";
foreach($arrdata as $key => $value)
{
if(strlen($paramstring) == 0)
$paramstring .= $key . "=" . $value;
else
$paramstring .= "&" . $key . "=" . $value;
}
$paySign = $method($paramstring);
return $paySign;
}
/**
* 生成随机字串
* @param number $length 长度,默认为16,最长为32字节
* @return string
*/
public function generateNonceStr($length=16){
// 密码字符集,可任意添加你需要的字符
$chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
$str = "";
for($i = 0; $i < $length; $i++)
{
$str .= $chars[mt_rand(0, strlen($chars) - 1)];
}
return $str;
}
/**
* 生成原生支付url
* @param number $productid 商品编号,最长为32字节
* @return string
*/
public function createNativeUrl($productid){
$nativeObj["appid"] = $this->appid;
$nativeObj["appkey"] = $this->paysignkey;
$nativeObj["productid"] = urlencode($productid);
$nativeObj["timestamp"] = time();
$nativeObj["noncestr"] = $this->generateNonceStr();
$nativeObj["sign"] = $this->getSignature($nativeObj);
unset($nativeObj["appkey"]);
$bizString = "";
foreach($nativeObj as $key => $value)
{
if(strlen($bizString) == 0)
$bizString .= $key . "=" . $value;
else
$bizString .= "&" . $key . "=" . $value;
}
return "weixin://wxpay/bizpayurl?".$bizString;
//weixin://wxpay/bizpayurl?sign=XXXXX&appid=XXXXXX&productid=XXXXXX×tamp=XXXXXX&noncestr=XXXXXX
}
/**
* 生成订单package字符串
* @param string $out_trade_no 必填,商户系统内部的订单号,32个字符内,确保在商户系统唯一
* @param string $body 必填,商品描述,128 字节以下
* @param int $total_fee 必填,订单总金额,单位为分
* @param string $notify_url 必填,支付完成通知回调接口,255 字节以内
* @param string $spbill_create_ip 必填,用户终端IP,IPV4字串,15字节内
* @param int $fee_type 必填,现金支付币种,默认1:人民币
* @param string $bank_type 必填,银行通道类型,默认WX
* @param string $input_charset 必填,传入参数字符编码,默认UTF-8,取值有UTF-8和GBK
* @param string $time_start 交易起始时间,订单生成时间,格式yyyyMMddHHmmss
* @param string $time_expire 交易结束时间,也是订单失效时间
* @param int $transport_fee 物流费用,单位为分
* @param int $product_fee 商品费用,单位为分,必须保证 transport_fee + product_fee=total_fee
* @param string $goods_tag 商品标记,优惠券时可能用到
* @param string $attach 附加数据,notify接口原样返回
* @return string
*/
public function createPackage($out_trade_no,$body,$total_fee,$notify_url,$spbill_create_ip,$fee_type=1,$bank_type="WX",$input_charset="UTF-8",$time_start="",$time_expire="",$transport_fee="",$product_fee="",$goods_tag="",$attach=""){
$arrdata = array("bank_type" => $bank_type, "body" => $body, "partner" => $this->partnerid, "out_trade_no" => $out_trade_no, "total_fee" => $total_fee, "fee_type" => $fee_type, "notify_url" => $notify_url, "spbill_create_ip" => $spbill_create_ip, "input_charset" => $input_charset);
if ($time_start) $arrdata['time_start'] = $time_start;
if ($time_expire) $arrdata['time_expire'] = $time_expire;
if ($transport_fee) $arrdata['transport_fee'] = $transport_fee;
if ($product_fee) $arrdata['product_fee'] = $product_fee;
if ($goods_tag) $arrdata['goods_tag'] = $goods_tag;
if ($attach) $arrdata['attach'] = $attach;
ksort($arrdata);
$paramstring = "";
foreach($arrdata as $key => $value)
{
if(strlen($paramstring) == 0)
$paramstring .= $key . "=" . $value;
else
$paramstring .= "&" . $key . "=" . $value;
}
$stringSignTemp = $paramstring . "&key=" . $this->partnerkey;
$signValue = strtoupper(md5($stringSignTemp));
$package = http_build_query($arrdata) . "&sign=" . $signValue;
return $package;
}
/**
* 支付签名(paySign)生成方法
* @param string $package 订单详情字串
* @param string $timeStamp 当前时间戳(需与JS输出的一致)
* @param string $nonceStr 随机串(需与JS输出的一致)
* @return string 返回签名字串
*/
public function getPaySign($package, $timeStamp, $nonceStr){
$arrdata = array("appid" => $this->appid, "timestamp" => $timeStamp, "noncestr" => $nonceStr, "package" => $package, "appkey" => $this->paysignkey);
$paySign = $this->getSignature($arrdata);
return $paySign;
}
/**
* 回调通知签名验证
* @param array $orderxml 返回的orderXml的数组表示,留空则自动从post数据获取
* @return boolean
*/
public function checkOrderSignature($orderxml=''){
if (!$orderxml) {
$postStr = file_get_contents("php://input");
if (!empty($postStr)) {
$orderxml = (array)simplexml_load_string($postStr, 'SimpleXMLElement', LIBXML_NOCDATA);
} else return false;
}
$arrdata = array('appid'=>$orderxml['AppId'],'appkey'=>$this->paysignkey,'timestamp'=>$orderxml['TimeStamp'],'noncestr'=>$orderxml['NonceStr'],'openid'=>$orderxml['OpenId'],'issubscribe'=>$orderxml['IsSubscribe']);
$paySign = $this->getSignature($arrdata);
if ($paySign!=$orderxml['AppSignature']) return false;
return true;
}
/**
* 发货通知
* @param string $openid 用户open_id
* @param string $transid 交易单号
* @param string $out_trade_no 第三方订单号
* @param int $status 0:发货失败;1:已发货
* @param string $msg 失败原因
* @return boolean|array
*/
public function sendPayDeliverNotify($openid,$transid,$out_trade_no,$status=1,$msg='ok'){
if (!$this->access_token && !$this->checkAuth()) return false;
$postdata = array(
"appid"=>$this->appid,
"appkey"=>$this->paysignkey,
"openid"=>$openid,
"transid"=>strval($transid),
"out_trade_no"=>strval($out_trade_no),
"deliver_timestamp"=>strval(time()),
"deliver_status"=>strval($status),
"deliver_msg"=>$msg,
);
$postdata['app_signature'] = $this->getSignature($postdata);
$postdata['sign_method'] = 'sha1';
unset($postdata['appkey']);
$result = $this->http_post(self::API_BASE_URL_PREFIX.self::PAY_DELIVERNOTIFY.'access_token='.$this->access_token,self::json_encode($postdata));
if ($result)
{
$json = json_decode($result,true);
if (!$json || !empty($json['errcode'])) {
$this->errCode = $json['errcode'];
$this->errMsg = $json['errmsg'];
return false;
}
return $json;
}
return false;
}
/**
* 查询订单信息
* @param string $out_trade_no 订单号
* @return boolean|array
*/
public function getPayOrder($out_trade_no) {
if (!$this->access_token && !$this->checkAuth()) return false;
$sign = strtoupper(md5("out_trade_no=$out_trade_no&partner={$this->partnerid}&key={$this->partnerkey}"));
$postdata = array(
"appid"=>$this->appid,
"appkey"=>$this->paysignkey,
"package"=>"out_trade_no=$out_trade_no&partner={$this->partnerid}&sign=$sign",
"timestamp"=>strval(time()),
);
$postdata['app_signature'] = $this->getSignature($postdata);
$postdata['sign_method'] = 'sha1';
unset($postdata['appkey']);
$result = $this->http_post(self::API_BASE_URL_PREFIX.self::PAY_ORDERQUERY.'access_token='.$this->access_token,self::json_encode($postdata));
if ($result)
{
$json = json_decode($result,true);
if (!$json || !empty($json['errcode'])) {
$this->errCode = $json['errcode'];
$this->errMsg = $json['errmsg'].json_encode($postdata);
return false;
}
return $json["order_info"];
}
return false;
}
/**
* 设置用户授权密钥
* @param string $user_token
* @return string
*/
public function setUserToken($user_token) {
return $this->user_token = $user_token;
}
/**
* 获取收货地址JS的签名
* @tutorial 参考weixin.js脚本的WeixinJS.editAddress方法调用
* @param string $appId
* @param string $url
* @param int $timeStamp
* @param string $nonceStr
* @param string $user_token
* @return Ambigous <boolean, string>
*/
public function getAddrSign($url, $timeStamp, $nonceStr, $user_token=''){
if (!$user_token) $user_token = $this->user_token;
if (!$user_token) {
$this->errMsg = 'no user access token found!';
return false;
}
$url = htmlspecialchars_decode($url);
$arrdata = array(
'appid'=>$this->appid,
'url'=>$url,
'timestamp'=>strval($timeStamp),
'noncestr'=>$nonceStr,
'accesstoken'=>$user_token
);
return $this->getSignature($arrdata);
}
}
================================================
FILE: old_version/snoopy.class.php
================================================
<?php
/*************************************************
Snoopy - the PHP net client
Author: Monte Ohrt <monte@ispi.net>
Copyright (c): 1999-2008 New Digital Group, all rights reserved
Version: 1.2.4
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
You may contact the author of Snoopy by e-mail at:
monte@ohrt.com
The latest version of Snoopy can be obtained from:
http://snoopy.sourceforge.net/
*************************************************/
class Snoopy
{
/**** Public variables ****/
/* user definable vars */
var $host = "www.php.net"; // host name we are connecting to
var $port = 80; // port we are connecting to
var $proxy_host = ""; // proxy host to use
var $proxy_port = ""; // proxy port to use
var $proxy_user = ""; // proxy user to use
var $proxy_pass = ""; // proxy password to use
var $agent = "Mozilla/5.0"; // agent we masquerade as
var $referer = ""; // referer info to pass
var $cookies = array(); // array of cookies to pass
// $cookies["username"]="joe";
var $rawheaders = array(); // array of raw headers to send
// $rawheaders["Content-type"]="text/html";
var $maxredirs = 5; // http redirection depth maximum. 0 = disallow
var $lastredirectaddr = ""; // contains address of last redirected address
var $offsiteok = true; // allows redirection off-site
var $maxframes = 0; // frame content depth maximum. 0 = disallow
var $expandlinks = true; // expand links to fully qualified URLs.
// this only applies to fetchlinks()
// submitlinks(), and submittext()
var $passcookies = true; // pass set cookies back through redirects
// NOTE: this currently does not respect
// dates, domains or paths.
var $user = ""; // user for http authentication
var $pass = ""; // password for http authentication
// http accept types
var $accept = "application/json, text/javascript, */*; q=0.01";
var $results = ""; // where the content is put
var $error = ""; // error messages sent here
var $response_code = ""; // response code returned from server
var $headers = array(); // headers returned from server sent here
var $maxlength = 500000; // max return data length (body)
var $read_timeout = 0; // timeout on read operations, in seconds
// supported only since PHP 4 Beta 4
// set to 0 to disallow timeouts
var $timed_out = false; // if a read operation timed out
var $status = 0; // http request status
var $temp_dir = "/tmp"; // temporary directory that the webserver
// has permission to write to.
// under Windows, this should be C:\temp
var $curl_path = "/usr/local/bin/curl";
// Snoopy will use cURL for fetching
// SSL content if a full system path to
// the cURL binary is supplied here.
// set to false if you do not have
// cURL installed. See http://curl.haxx.se
// for details on installing cURL.
// Snoopy does *not* use the cURL
// library functions built into php,
// as these functions are not stable
// as of this Snoopy release.
/**** Private variables ****/
var $_maxlinelen = 4096; // max line length (headers)
var $_httpmethod = "GET"; // default http request method
var $_httpversion = "HTTP/1.0"; // default http request version
var $_submit_method = "POST"; // default submit method
var $_submit_type = "application/x-www-form-urlencoded"; // default submit type
var $_mime_boundary = ""; // MIME boundary for multipart/form-data submit type
var $_redirectaddr = false; // will be set if page fetched is a redirect
var $_redirectdepth = 0; // increments on an http redirect
var $_frameurls = array(); // frame src urls
var $_framedepth = 0; // increments on frame depth
var $_isproxy = false; // set if using a proxy server
var $_fp_timeout = 30; // timeout for socket connection
/*======================================================================*\
Function: fetch
Purpose: fetch the contents of a web page
(and possibly other protocols in the
future like ftp, nntp, gopher, etc.)
Input: $URI the location of the page to fetch
Output: $this->results the output text from the fetch
\*======================================================================*/
function fetch($URI)
{
//preg_match("|^([^:]+)://([^:/]+)(:[\d]+)*(.*)|",$URI,$URI_PARTS);
$URI_PARTS = parse_url($URI);
if (!empty($URI_PARTS["user"]))
$this->user = $URI_PARTS["user"];
if (!empty($URI_PARTS["pass"]))
$this->pass = $URI_PARTS["pass"];
if (empty($URI_PARTS["query"]))
$URI_PARTS["query"] = '';
if (empty($URI_PARTS["path"]))
$URI_PARTS["path"] = '';
switch(strtolower($URI_PARTS["scheme"]))
{
case "http":
$this->host = $URI_PARTS["host"];
if(!empty($URI_PARTS["port"]))
$this->port = $URI_PARTS["port"];
if($this->_connect($fp))
{
if($this->_isproxy)
{
// using proxy, send entire URI
$this->_httprequest($URI,$fp,$URI,$this->_httpmethod);
}
else
{
$path = $URI_PARTS["path"].($URI_PARTS["query"] ? "?".$URI_PARTS["query"] : "");
// no proxy, send only the path
$this->_httprequest($path, $fp, $URI, $this->_httpmethod);
}
$this->_disconnect($fp);
if($this->_redirectaddr)
{
/* url was redirected, check if we've hit the max depth */
if($this->maxredirs > $this->_redirectdepth)
{
// only follow redirect if it's on this site, or offsiteok is true
if(preg_match("|^http://".preg_quote($this->host)."|i",$this->_redirectaddr) || $this->offsiteok)
{
/* follow the redirect */
$this->_redirectdepth++;
$this->lastredirectaddr=$this->_redirectaddr;
$this->fetch($this->_redirectaddr);
}
}
}
if($this->_framedepth < $this->maxframes && count($this->_frameurls) > 0)
{
$frameurls = $this->_frameurls;
$this->_frameurls = array();
while(list(,$frameurl) = each($frameurls))
{
if($this->_framedepth < $this->maxframes)
{
$this->fetch($frameurl);
$this->_framedepth++;
}
else
break;
}
}
}
else
{
return false;
}
return true;
break;
case "https":
if (!function_exists('curl_init')) {
if(!$this->curl_path)
return false;
if(function_exists("is_executable"))
if (!is_executable($this->curl_path))
return false;
}
$this->host = $URI_PARTS["host"];
if(!empty($URI_PARTS["port"]))
$this->port = $URI_PARTS["port"];
if($this->_isproxy)
{
// using proxy, send entire URI
$this->_httpsrequest($URI,$URI,$this->_httpmethod);
}
else
{
$path = $URI_PARTS["path"].($URI_PARTS["query"] ? "?".$URI_PARTS["query"] : "");
// no proxy, send only the path
$this->_httpsrequest($path, $URI, $this->_httpmethod);
}
if($this->_redirectaddr)
{
/* url was redirected, check if we've hit the max depth */
if($this->maxredirs > $this->_redirectdepth)
{
// only follow redirect if it's on this site, or offsiteok is true
if(preg_match("|^https://".preg_quote($this->host)."|i",$this->_redirectaddr) || $this->offsiteok)
{
/* follow the redirect */
$this->_redirectdepth++;
$this->lastredirectaddr=$this->_redirectaddr;
$this->fetch($this->_redirectaddr);
}
}
}
if($this->_framedepth < $this->maxframes && count($this->_frameurls) > 0)
{
$frameurls = $this->_frameurls;
$this->_frameurls = array();
while(list(,$frameurl) = each($frameurls))
{
if($this->_framedepth < $this->maxframes)
{
$this->fetch($frameurl);
$this->_framedepth++;
}
else
break;
}
}
return true;
break;
default:
// not a valid protocol
$this->error = 'Invalid protocol "'.$URI_PARTS["scheme"].'"\n';
return false;
break;
}
return true;
}
/*======================================================================*\
Function: submit
Purpose: submit an http form
Input: $URI the location to post the data
$formvars the formvars to use.
format: $formvars["var"] = "val";
$formfiles an array of files to submit
format: $formfiles["var"] = "/dir/filename.ext";
Output: $this->results the text output from the post
\*======================================================================*/
function submit($URI, $formvars="", $formfiles="")
{
unset($postdata);
$postdata = $this->_prepare_post_body($formvars, $formfiles);
$URI_PARTS = parse_url($URI);
if (!empty($URI_PARTS["user"]))
$this->user = $URI_PARTS["user"];
if (!empty($URI_PARTS["pass"]))
$this->pass = $URI_PARTS["pass"];
if (empty($URI_PARTS["query"]))
$URI_PARTS["query"] = '';
if (empty($URI_PARTS["path"]))
$URI_PARTS["path"] = '';
switch(strtolower($URI_PARTS["scheme"]))
{
case "http":
$this->host = $URI_PARTS["host"];
if(!empty($URI_PARTS["port"]))
$this->port = $URI_PARTS["port"];
if($this->_connect($fp))
{
if($this->_isproxy)
{
// using proxy, send entire URI
$this->_httprequest($URI,$fp,$URI,$this->_submit_method,$this->_submit_type,$postdata);
}
else
{
$path = $URI_PARTS["path"].($URI_PARTS["query"] ? "?".$URI_PARTS["query"] : "");
// no proxy, send only the path
$this->_httprequest($path, $fp, $URI, $this->_submit_method, $this->_submit_type, $postdata);
}
$this->_disconnect($fp);
if($this->_redirectaddr)
{
/* url was redirected, check if we've hit the max depth */
if($this->maxredirs > $this->_redirectdepth)
{
if(!preg_match("|^".$URI_PARTS["scheme"]."://|", $this->_redirectaddr))
$this->_redirectaddr = $this->_expandlinks($this->_redirectaddr,$URI_PARTS["scheme"]."://".$URI_PARTS["host"]);
// only follow redirect if it's on this site, or offsiteok is true
if(preg_match("|^http://".preg_quote($this->host)."|i",$this->_redirectaddr) || $this->offsiteok)
{
/* follow the redirect */
$this->_redirectdepth++;
$this->lastredirectaddr=$this->_redirectaddr;
if( strpos( $this->_redirectaddr, "?" ) > 0 )
$this->fetch($this->_redirectaddr); // the redirect has changed the request method from post to get
else
$this->submit($this->_redirectaddr,$formvars, $formfiles);
}
}
}
if($this->_framedepth < $this->maxframes && count($this->_frameurls) > 0)
{
$frameurls = $this->_frameurls;
$this->_frameurls = array();
while(list(,$frameurl) = each($frameurls))
{
if($this->_framedepth < $this->maxframes)
{
$this->fetch($frameurl);
$this->_framedepth++;
}
else
break;
}
}
}
else
{
return false;
}
return true;
break;
case "https":
if (!function_exists('curl_init')) {
if(!$this->curl_path)
return false;
if(function_exists("is_executable"))
if (!is_executable($this->curl_path))
return false;
}
$this->host = $URI_PARTS["host"];
if(!empty($URI_PARTS["port"]))
$this->port = $URI_PARTS["port"];
if($this->_isproxy)
{
// using proxy, send entire URI
$this->_httpsrequest($URI, $URI, $this->_submit_method, $this->_submit_type, $postdata);
}
else
{
$path = $URI_PARTS["path"].($URI_PARTS["query"] ? "?".$URI_PARTS["query"] : "");
// no proxy, send only the path
$this->_httpsrequest($path, $URI, $this->_submit_method, $this->_submit_type, $postdata);
}
if($this->_redirectaddr)
{
/* url was redirected, check if we've hit the max depth */
if($this->maxredirs > $this->_redirectdepth)
{
if(!preg_match("|^".$URI_PARTS["scheme"]."://|", $this->_redirectaddr))
$this->_redirectaddr = $this->_expandlinks($this->_redirectaddr,$URI_PARTS["scheme"]."://".$URI_PARTS["host"]);
// only follow redirect if it's on this site, or offsiteok is true
if(preg_match("|^https://".preg_quote($this->host)."|i",$this->_redirectaddr) || $this->offsiteok)
{
/* follow the redirect */
$this->_redirectdepth++;
$this->lastredirectaddr=$this->_redirectaddr;
if( strpos( $this->_redirectaddr, "?" ) > 0 )
$this->fetch($this->_redirectaddr); // the redirect has changed the request method from post to get
else
$this->submit($this->_redirectaddr,$formvars, $formfiles);
}
}
}
if($this->_framedepth < $this->maxframes && count($this->_frameurls) > 0)
{
$frameurls = $this->_frameurls;
$this->_frameurls = array();
while(list(,$frameurl) = each($frameurls))
{
if($this->_framedepth < $this->maxframes)
{
$this->fetch($frameurl);
$this->_framedepth++;
}
else
break;
}
}
return true;
break;
default:
// not a valid protocol
$this->error = 'Invalid protocol "'.$URI_PARTS["scheme"].'"\n';
return false;
break;
}
return true;
}
/*======================================================================*\
Function: fetchlinks
Purpose: fetch the links from a web page
Input: $URI where you are fetching from
Output: $this->results an array of the URLs
\*======================================================================*/
function fetchlinks($URI)
{
if ($this->fetch($URI))
{
if($this->lastredirectaddr)
$URI = $this->lastredirectaddr;
if(is_array($this->results))
{
for($x=0;$x<count($this->results);$x++)
$this->results[$x] = $this->_striplinks($this->results[$x]);
}
else
$this->results = $this->_striplinks($this->results);
if($this->expandlinks)
$this->results = $this->_expandlinks($this->results, $URI);
return true;
}
else
return false;
}
/*======================================================================*\
Function: fetchform
Purpose: fetch the form elements from a web page
Input: $URI where you are fetching from
Output: $this->results the resulting html form
\*======================================================================*/
function fetchform($URI)
{
if ($this->fetch($URI))
{
if(is_array($this->results))
{
for($x=0;$x<count($this->results);$x++)
$this->results[$x] = $this->_stripform($this->results[$x]);
}
else
$this->results = $this->_stripform($this->results);
return true;
}
else
return false;
}
/*======================================================================*\
Function: fetchtext
Purpose: fetch the text from a web page, stripping the links
Input: $URI where you are fetching from
Output: $this->results the text from the web page
\*======================================================================*/
function fetchtext($URI)
{
if($this->fetch($URI))
{
if(is_array($this->results))
{
for($x=0;$x<count($this->results);$x++)
$this->results[$x] = $this->_striptext($this->results[$x]);
}
else
$this->results = $this->_striptext($this->results);
return true;
}
else
return false;
}
/*======================================================================*\
Function: submitlinks
Purpose: grab links from a form submission
Input: $URI where you are submitting from
Output: $this->results an array of the links from the post
\*======================================================================*/
function submitlinks($URI, $formvars="", $formfiles="")
{
if($this->submit($URI,$formvars, $formfiles))
{
if($this->lastredirectaddr)
$URI = $this->lastredirectaddr;
if(is_array($this->results))
{
for($x=0;$x<count($this->results);$x++)
{
$this->results[$x] = $this->_striplinks($this->results[$x]);
if($this->expandlinks)
$this->results[$x] = $this->_expandlinks($this->results[$x],$URI);
}
}
else
{
$this->results = $this->_striplinks($this->results);
if($this->expandlinks)
$this->results = $this->_expandlinks($this->results,$URI);
}
return true;
}
else
return false;
}
/*======================================================================*\
Function: submittext
Purpose: grab text from a form submission
Input: $URI where you are submitting from
Output: $this->results the text from the web page
\*======================================================================*/
function submittext($URI, $formvars = "", $formfiles = "")
{
if($this->submit($URI,$formvars, $formfiles))
{
if($this->lastredirectaddr)
$URI = $this->lastredirectaddr;
if(is_array($this->results))
{
for($x=0;$x<count($this->results);$x++)
{
$this->results[$x] = $this->_striptext($this->results[$x]);
if($this->expandlinks)
$this->results[$x] = $this->_expandlinks($this->results[$x],$URI);
}
}
else
{
$this->results = $this->_striptext($this->results);
if($this->expandlinks)
$this->results = $this->_expandlinks($this->results,$URI);
}
return true;
}
else
return false;
}
/*======================================================================*\
Function: set_submit_multipart
Purpose: Set the form submission content type to
multipart/form-data
\*======================================================================*/
function set_submit_multipart()
{
$this->_submit_type = "multipart/form-data";
}
/*======================================================================*\
Function: set_submit_normal
Purpose: Set the form submission content type to
application/x-www-form-urlencoded
\*======================================================================*/
function set_submit_normal()
{
$this->_submit_type = "application/x-www-form-urlencoded";
}
/*======================================================================*\
Private functions
\*======================================================================*/
/*======================================================================*\
Function: _striplinks
Purpose: strip the hyperlinks from an html document
Input: $document document to strip.
Output: $match an array of the links
\*======================================================================*/
function _striplinks($document)
{
preg_match_all("'<\s*a\s.*?href\s*=\s* # find <a href=
([\"\'])? # find single or double quote
(?(1) (.*?)\\1 | ([^\s\>]+)) # if quote found, match up to next matching
# quote, otherwise match up to next space
'isx",$document,$links);
// catenate the non-empty matches from the conditional subpattern
while(list($key,$val) = each($links[2]))
{
if(!empty($val))
$match[] = $val;
}
while(list($key,$val) = each($links[3]))
{
if(!empty($val))
$match[] = $val;
}
// return the links
return $match;
}
/*======================================================================*\
Function: _stripform
Purpose: strip the form elements from an html document
Input: $document document to strip.
Output: $match an array of the links
\*======================================================================*/
function _stripform($document)
{
preg_match_all("'<\/?(FORM|INPUT|SELECT|TEXTAREA|(OPTION))[^<>]*>(?(2)(.*(?=<\/?(option|select)[^<>]*>[\r\n]*)|(?=[\r\n]*))|(?=[\r\n]*))'Usi",$document,$elements);
// catenate the matches
$match = implode("\r\n",$elements[0]);
// return the links
return $match;
}
/*======================================================================*\
Function: _striptext
Purpose: strip the text from an html document
Input: $document document to strip.
Output: $text the resulting text
\*======================================================================*/
function _striptext($document)
{
// I didn't use preg eval (//e) since that is only available in PHP 4.0.
// so, list your entities one by one here. I included some of the
// more common ones.
$search = array("'<script[^>]*?>.*?</script>'si", // strip out javascript
"'<[\/\!]*?[^<>]*?>'si", // strip out html tags
"'([\r\n])[\s]+'", // strip out white space
"'&(quot|#34|#034|#x22);'i", // replace html entities
"'&(amp|#38|#038|#x26);'i", // added hexadecimal values
"'&(lt|#60|#060|#x3c);'i",
"'&(gt|#62|#062|#x3e);'i",
"'&(nbsp|#160|#xa0);'i",
"'&(iexcl|#161);'i",
"'&(cent|#162);'i",
"'&(pound|#163);'i",
"'&(copy|#169);'i",
"'&(reg|#174);'i",
"'&(deg|#176);'i",
"'&(#39|#039|#x27);'",
"'&(euro|#8364);'i", // europe
"'&a(uml|UML);'", // german
"'&o(uml|UML);'",
"'&u(uml|UML);'",
"'&A(uml|UML);'",
"'&O(uml|UML);'",
"'&U(uml|UML);'",
"'ß'i",
);
$replace = array( "",
"",
"\\1",
"\"",
"&",
"<",
">",
" ",
chr(161),
chr(162),
chr(163),
chr(169),
chr(174),
chr(176),
chr(39),
chr(128),
"�",
"�",
"�",
"�",
"�",
"�",
"�",
);
$text = preg_replace($search,$replace,$document);
return $text;
}
/*======================================================================*\
Function: _expandlinks
Purpose: expand each link into a fully qualified URL
Input: $links the links to qualify
$URI the full URI to get the base from
Output: $expandedLinks the expanded links
\*======================================================================*/
function _expandlinks($links,$URI)
{
preg_match("/^[^\?]+/",$URI,$match);
$match = preg_replace("|/[^\/\.]+\.[^\/\.]+$|","",$match[0]);
$match = preg_replace("|/$|","",$match);
$match_part = parse_url($match);
$match_root =
$match_part["scheme"]."://".$match_part["host"];
$search = array( "|^http://".preg_quote($this->host)."|i",
"|^(\/)|i",
"|^(?!http://)(?!mailto:)|i",
"|/\./|",
"|/[^\/]+/\.\./|"
);
$replace = array( "",
$match_root."/",
$match."/",
"/",
"/"
);
$expandedLinks = preg_replace($search,$replace,$links);
return $expandedLinks;
}
/*======================================================================*\
Function: _httprequest
Purpose: go get the http data from the server
Input: $url the url to fetch
$fp the current open file pointer
$URI the full URI
$body body contents to send if any (POST)
Output:
\*======================================================================*/
function _httprequest($url,$fp,$URI,$http_method,$content_type="",$body="")
{
$cookie_headers = '';
if($this->passcookies && $this->_redirectaddr)
$this->setcookies();
$URI_PARTS = parse_url($URI);
if(empty($url))
$url = "/";
$headers = $http_method." ".$url." ".$this->_httpversion."\r\n";
if(!empty($this->agent))
$headers .= "User-Agent: ".$this->agent."\r\n";
if(!empty($this->host) && !isset($this->rawheaders['Host'])) {
$headers .= "Host: ".$this->host;
if(!empty($this->port) && $this->port!=80)
$headers .= ":".$this->port;
$headers .= "\r\n";
}
if(!empty($this->accept))
$headers .= "Accept: ".$this->accept."\r\n";
if(!empty($this->referer))
$headers .= "Referer: ".$this->referer."\r\n";
if(!empty($this->cookies))
{
if(!is_array($this->cookies))
$this->cookies = (array)$this->cookies;
reset($this->cookies);
if ( count($this->cookies) > 0 ) {
$cookie_headers .= 'Cookie: ';
foreach ( $this->cookies as $cookieKey => $cookieVal ) {
$cookie_headers .= $cookieKey."=".urlencode($cookieVal)."; ";
}
$headers .= substr($cookie_headers,0,-2) . "\r\n";
}
}
if(!empty($this->rawheaders))
{
if(!is_array($this->rawheaders))
$this->rawheaders = (array)$this->rawheaders;
while(list($headerKey,$headerVal) = each($this->rawheaders))
$headers .= $headerKey.": ".$headerVal."\r\n";
}
if(!empty($content_type)) {
$headers .= "Content-type: $content_type";
if ($content_type == "multipart/form-data")
$headers .= "; boundary=".$this->_mime_boundary;
$headers .= "\r\n";
}
if(!empty($body))
$headers .= "Content-length: ".strlen($body)."\r\n";
if(!empty($this->user) || !empty($this->pass))
$headers .= "Authorization: Basic ".base64_encode($this->user.":".$this->pass)."\r\n";
//add proxy auth headers
if(!empty($this->proxy_user))
$headers .= 'Proxy-Authorization: ' . 'Basic ' . base64_encode($this->proxy_user . ':' . $this->proxy_pass)."\r\n";
$headers .= "\r\n";
// set the read timeout if needed
if ($this->read_timeout > 0)
socket_set_timeout($fp, $this->read_timeout);
$this->timed_out = false;
fwrite($fp,$headers.$body,strlen($headers.$body));
$this->_redirectaddr = false;
unset($this->headers);
while($currentHeader = fgets($fp,$this->_maxlinelen))
{
if ($this->read_timeout > 0 && $this->_check_timeout($fp))
{
$this->status=-100;
return false;
}
if($currentHeader == "\r\n")
break;
// if a header begins with Location: or URI:, set the redirect
if(preg_match("/^(Location:|URI:)/i",$currentHeader))
{
// get URL portion of the redirect
preg_match("/^(Location:|URI:)[ ]+(.*)/i",chop($currentHeader),$matches);
// look for :// in the Location header to see if hostname is included
if (!empty($matches)) {
if(!preg_match("|\:\/\/|",$matches[2]))
{
// no host in the path, so prepend
$this->_redirectaddr = $URI_PARTS["scheme"]."://".$this->host.":".$this->port;
// eliminate double slash
if(!preg_match("|^/|",$matches[2]))
$this->_redirectaddr .= "/".$matches[2];
else
$this->_redirectaddr .= $matches[2];
}
else
$this->_redirectaddr = $matches[2];
}
}
if(preg_match("|^HTTP/|",$currentHeader))
{
if(preg_match("|^HTTP/[^\s]*\s(.*?)\s|",$currentHeader, $status))
{
$this->status= $status[1];
}
$this->response_code = $currentHeader;
}
$this->headers[] = $currentHeader;
}
$results = '';
do {
$_data = fread($fp, $this->maxlength);
if (strlen($_data) == 0) {
break;
}
$results .= $_data;
} while(true);
if ($this->read_timeout > 0 && $this->_check_timeout($fp))
{
$this->status=-100;
return false;
}
// check if there is a a redirect meta tag
if(preg_match("'<meta[\s]*http-equiv[^>]*?content[\s]*=[\s]*[\"\']?\d+;[\s]*URL[\s]*=[\s]*([^\"\']*?)[\"\']?>'i",$results,$match))
{
$this->_redirectaddr = $this->_expandlinks($match[1],$URI);
}
// have we hit our frame depth and is there frame src to fetch?
if(($this->_framedepth < $this->maxframes) && preg_match_all("'<frame\s+.*src[\s]*=[\'\"]?([^\'\"\>]+)'i",$results,$match))
{
$this->results[] = $results;
for($x=0; $x<count($match[1]); $x++)
$this->_frameurls[] = $this->_expandlinks($match[1][$x],$URI_PARTS["scheme"]."://".$this->host);
}
// have we already fetched framed content?
elseif(is_array($this->results))
$this->results[] = $results;
// no framed content
else
$this->results = $results;
return true;
}
/*======================================================================*\
Function: _httpsrequest
Purpose: go get the https data from the server using curl
Input: $url the url to fetch
$URI the full URI
$body body contents to send if any (POST)
Output:
\*======================================================================*/
function _httpsrequest($url,$URI,$http_method,$content_type="",$body="")
{
if($this->passcookies && $this->_redirectaddr)
$this->setcookies();
$headers = array();
$URI_PARTS = parse_url($URI);
if(empty($url))
$url = "/";
// GET ... header not needed for curl
//$headers[] = $http_method." ".$url." ".$this->_httpversion;
if(!empty($this->agent))
$headers[] = "User-Agent: ".$this->agent;
if(!empty($this->host))
if(!empty($this->port) && $this->port!=80)
$headers[] = "Host: ".$this->host.":".$this->port;
else
$headers[] = "Host: ".$this->host;
if(!empty($this->accept))
$headers[] = "Accept: ".$this->accept;
if(!empty($this->referer))
$headers[] = "Referer: ".$this->referer;
if(!empty($this->cookies))
{
if(!is_array($this->cookies))
$this->cookies = (array)$this->cookies;
reset($this->cookies);
if ( count($this->cookies) > 0 ) {
$cookie_str = 'Cookie: ';
foreach ( $this->cookies as $cookieKey => $cookieVal ) {
$cookie_str .= $cookieKey."=".urlencode($cookieVal)."; ";
}
$headers[] = substr($cookie_str,0,-2);
}
}
if(!empty($this->rawheaders))
{
if(!is_array($this->rawheaders))
$this->rawheaders = (array)$this->rawheaders;
while(list($headerKey,$headerVal) = each($this->rawheaders))
$headers[] = $headerKey.": ".$headerVal;
}
if(!empty($content_type)) {
if ($content_type == "multipart/form-data")
$headers[] = "Content-type: $content_type; boundary=".$this->_mime_boundary;
else
$headers[] = "Content-type: $content_type";
}
if(!empty($body))
$headers[] = "Content-length: ".strlen($body);
if(!empty($this->user) || !empty($this->pass))
$headers[] = "Authorization: BASIC ".base64_encode($this->user.":".$this->pass);
if (function_exists('curl_init')) {
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $URI);
curl_setopt($ch, CURLOPT_HEADER, true);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE);
curl_setopt($ch, CURLOPT_SSLVERSION,3);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch, CURLOPT_TIMEOUT, $this->read_timeout);
if(!empty($body)) {
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $body);
}
$data = curl_exec($ch);
if ($data === false) {
$this->error = "Error: Curl error ".curl_error($ch);
return false;
}
$parts = explode("\r\n\r\n",$data,2);
$result_headers = explode("\r\n",$parts[0]);
$results = $parts[1];
unset($parts);
} else {
for($curr_header = 0; $curr_header < count($headers); $curr_header++) {
$safer_header = strtr( $headers[$curr_header], "\"", " " );
$cmdline_params .= " -H \"".$safer_header."\"";
}
if(!empty($body))
$cmdline_params .= " -d \"$body\"";
if($this->read_timeout > 0)
$cmdline_params .= " -m ".$this->read_timeout;
$headerfile = tempnam($temp_dir, "sno");
exec($this->curl_path." -k -D \"$headerfile\"".$cmdline_params." \"".escapeshellcmd($URI)."\"",$results,$return);
if($return)
{
$this->error = "Error: cURL could not retrieve the document, error $return.";
return false;
}
$results = implode("\r\n",$results);
$result_headers = file("$headerfile");
}
$this->_redirectaddr = false;
unset($this->headers);
for($currentHeader = 0; $currentHeader < count($result_headers); $currentHeader++)
{
// if a header begins with Location: or URI:, set the redirect
if(preg_match("/^(Location: |URI: )/i",$result_headers[$currentHeader]))
{
// get URL portion of the redirect
preg_match("/^(Location: |URI:)\s+(.*)/",chop($result_headers[$currentHeader]),$matches);
// look for :// in the Location header to see if hostname is included
if (!empty($matches)) {
if(!preg_match("|\:\/\/|",$matches[2]))
{
// no host in the path, so prepend
$this->_redirectaddr = $URI_PARTS["scheme"]."://".$this->host;
// eliminate double slash
if(!preg_match("|^/|",$matches[2]))
$this->_redirectaddr .= "/".$matches[2];
else
$this->_redirectaddr .= $matches[2];
}
else
$this->_redirectaddr = $matches[2];
}
}
if(preg_match("|^HTTP/|",$result_headers[$currentHeader]))
$this->response_code = $result_headers[$currentHeader];
$this->headers[] = $result_headers[$currentHeader];
}
// check if there is a a redirect meta tag
if(preg_match("'<meta[\s]*http-equiv[^>]*?content[\s]*=[\s]*[\"\']?\d+;[\s]*URL[\s]*=[\s]*([^\"\']*?)[\"\']?>'i",$results,$match))
{
$this->_redirectaddr = $this->_expandlinks($match[1],$URI);
}
// have we hit our frame depth and is there frame src to fetch?
if(($this->_framedepth < $this->maxframes) && preg_match_all("'<frame\s+.*src[\s]*=[\'\"]?([^\'\"\>]+)'i",$results,$match))
{
$this->results[] = $results;
for($x=0; $x<count($match[1]); $x++)
$this->_frameurls[] = $this->_expandlinks($match[1][$x],$URI_PARTS["scheme"]."://".$this->host);
}
// have we already fetched framed content?
elseif(is_array($this->results))
$this->results[] = $results;
// no framed content
else
$this->results = $results;
if (isset($headerfile) && file_exists($headerfile))
unlink($headerfile);
return true;
}
/*======================================================================*\
Function: setcookies()
Purpose: set cookies for a redirection
\*======================================================================*/
function setcookies()
{
for($x=0; $x<count($this->headers); $x++)
{
if(preg_match('/^set-cookie:[\s]+([^=]+)=([^;]+)/i', $this->headers[$x],$match))
$this->cookies[$match[1]] = urldecode($match[2]);
}
}
/*======================================================================*\
Function: _check_timeout
Purpose: checks whether timeout has occurred
Input: $fp file pointer
\*======================================================================*/
function _check_timeout($fp)
{
if ($this->read_timeout > 0) {
$fp_status = socket_get_status($fp);
if ($fp_status["timed_out"]) {
$this->timed_out = true;
return true;
}
}
return false;
}
/*======================================================================*\
Function: _connect
Purpose: make a socket connection
Input: $fp file pointer
\*======================================================================*/
function _connect(&$fp)
{
if(!empty($this->proxy_host) && !empty($this->proxy_port))
{
$this->_isproxy = true;
$host = $this->proxy_host;
$port = $this->proxy_port;
}
else
{
$host = $this->host;
$port = $this->port;
}
$this->status = 0;
if($fp = fsockopen(
$host,
$port,
$errno,
$errstr,
$this->_fp_timeout
))
{
// socket connection succeeded
return true;
}
else
{
// socket connection failed
$this->status = $errno;
switch($errno)
{
case -3:
$this->error="socket creation failed (-3)";
case -4:
$this->error="dns lookup failure (-4)";
case -5:
$this->error="connection refused or timed out (-5)";
default:
$this->error="connection failed (".$errno.")";
}
return false;
}
}
/*======================================================================*\
Function: _disconnect
Purpose: disconnect a socket connection
Input: $fp file pointer
\*======================================================================*/
function _disconnect($fp)
{
return(fclose($fp));
}
/*======================================================================*\
Function: _prepare_post_body
Purpose: Prepare post body according to encoding type
Input: $formvars - form variables
$formfiles - form upload files
Output: post body
\*======================================================================*/
function _prepare_post_body($formvars, $formfiles)
{
settype($formvars, "array");
settype($formfiles, "array");
$postdata = '';
if (count($formvars) == 0 && count($formfiles) == 0)
return;
if (is_string($formvars)) return $formvars;
if((count($formvars) == 1) && isset($formvars[0])) return $formvars[0];
switch ($this->_submit_type) {
case "application/x-www-form-urlencoded":
reset($formvars);
while(list($key,$val) = each($formvars)) {
if (is_array($val) || is_object($val)) {
while (list($cur_key, $cur_val) = each($val)) {
$postdata .= urlencode($key)."[]=".urlencode($cur_val)."&";
}
} else
$postdata .= urlencode($key)."=".urlencode($val)."&";
}
break;
case "multipart/form-data":
$this->_mime_boundary = "--------".md5(uniqid(microtime()));
reset($formvars);
while(list($key,$val) = each($formvars)) {
if (is_array($val) || is_object($val)) {
while (list($cur_key, $cur_val) = each($val)) {
$postdata .= "--".$this->_mime_boundary."\r\n";
$postdata .= "Content-Disposition: form-data; name=\"$key\[\]\"\r\n\r\n";
$postdata .= "$cur_val\r\n";
}
} else {
$postdata .= "--".$this->_mime_boundary."\r\n";
$postdata .= "Content-Disposition: form-data; name=\"$key\"\r\n\r\n";
$postdata .= "$val\r\n";
}
}
reset($formfiles);
while (list($field_name, $file_names) = each($formfiles)) {
settype($file_names, "array");
while (list(, $file_name) = each($file_names)) {
$file_content = file_get_contents($file_name);
if (!$file_content) continue;
$base_name = basename($file_name);
$postdata .= "--".$this->_mime_boundary."\r\n";
$postdata .= "Content-Disposition: form-data; name=\"$field_name\"; filename=\"$base_name\"\r\nContent-Type: image/jpeg\r\n\r\n";
$postdata .= "$file_content\r\n";
}
}
$postdata .= "--".$this->_mime_boundary."--\r\n";
break;
}
return $postdata;
}
}
================================================
FILE: old_version/test/test2.php
================================================
<?php
/**
* 微信扩展接口测试
*/
include("../wechatext.class.php");
function logdebug($text){
file_put_contents('../data/log.txt',$text."\n",FILE_APPEND);
};
$options = array(
'account'=>'demo@domain.com',
'password'=>'demo',
'datapath'=>'../data/cookie_',
'debug'=>true,
'logcallback'=>'logdebug'
);
$wechat = new Wechatext($options);
if ($wechat->checkValid()) {
//获取分组列表
$grouplist = $wechat->getGroupList();
var_dump($grouplist);
//获取用户列表
$userlist = $wechat->getUserlist(0,10);
var_dump($userlist);
$user = $userlist[0];
// 获取用户信息
$userdata = $wechat->getInfo($user['id']);
var_dump($userdata);
// 获取已保存的图文消息
$newslist = $wechat->getNewsList(0,10);
var_dump($newslist);
//获取用户最新消息
$topmsg = $wechat->getTopMsg();
var_dump($topmsg);
$msglist = $wechat->getMsg();
var_dump($msglist);
// 主动回复消息
if ($topmsg && $topmsg['has_reply']==0){
$wechat->send($user['id'],'hi '.$topmsg['nick_name'].',rev:'.$topmsg['content']);
$content = '这是一条Wechatext发出的测试微信';
$imgdata = file_get_contents('http://github.global.ssl.fastly.net/images/modules/dashboard/bootcamp/octocat_fork.png');
$img = '../data/send.png';
file_put_contents($img,$imgdata);
//上传图片
$fileid = $wechat->uploadFile($img);
echo 'fileid:'.$fileid;
//if ($fileid) $re = $wechat->sendImage($user['id'],$fileid);
//发送图文信息
$re = $wechat->sendPreview($userdata['user_name'],$content,$content,$content,$fileid,'http://github.com/dodgepudding/wechat-php-sdk');
var_dump($re);
//发送视频
//$re = $wechat->sendVideo($user['id'],$fileid);
$re = $wechat->getFileList(2,0,10);
var_dump($re);
} else {
echo 'no top msg';
}
} else {
echo "login error";
}
================================================
FILE: old_version/test/test3.php
================================================
<?php
/**
* 微信二维码登陆测试
*/
include("../wechatauth.class.php");
session_start();
function logdebug($text){
file_put_contents('../log/logwechat.txt',$text."\n",FILE_APPEND);
};
$sid = session_id();
$options = array(
'account'=>$sid,
'datapath'=>'../log/cookiecode_',
'debug'=>true,
'logcallback'=>'logdebug'
);
$wechat = new Wechatauth($options);
if (isset($_POST['code'])) {
$logincode = $_POST['code'];
$vres = $wechat->set_login_code($logincode)->verify_code();
if ($vres===false) {
$result = array('status'=>0);
} else {
$result = array('status'=>$vres);
if ($vres==200) {
$result['info'] = $wechat->get_login_info();
$result['cookie'] = $wechat->get_login_cookie(true);
}
}
die(json_encode($result));
}
$logincode = $wechat->get_login_code();
$qrimg = $wechat->get_code_image();
?>
<!DOCTYPE html>
<html>
<head>
<meta content="text/html; charset=utf-8" http-equiv="Content-Type">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<script type="text/javascript" src="http://code.jquery.com/jquery-1.9.1.min.js"></script>
<title>微信二维码登陆接口</title>
</head>
<body>
<h2>微信里扫描以下二维码实现登陆</h2>
<div id="content">
<img src="<?php echo $qrimg;?>" />
</div>
<script type="text/javascript">
var ajaxlock = false;
var ajaxhandle;
function synclogin(){
if (!ajaxlock) {
ajaxlock = true;
$.post(location.href,{code:'<?php echo $logincode;?>'},function(json){
//console.log(json);
if (json.status) {
console.log(json.status);
if (json.status==200) {
var nick,uid,username,sex,avatar;
if (json.info && json.info.User){
uid = json.info.User.Uin;
nick = json.info.User.NickName;
username = json.info.User.UserName;
sex = json.info.User.Sex;
avatar = json.info.User.HeadImgUrl;
$('#content').html('<h2>用户信息</h2><ul><li><b>Uid:</b>'+uid
+'</li><li><b>Nick:</b>'+nick
+'</li><li><b>username:</b>'+username
+'</li><li><b>sex:</b>'+(sex==1?'男':'女')
+'</li><li><b>avatar:</b>'+avatar
+'</li></ul>');
}
alert('login success, welcome '+nick);
clearInterval(ajaxhandle);
}
}
ajaxlock = false;
},'json');
}
}
$(function(){
ajaxhandle = setInterval("synclogin()",5000);
});
</script>
</body>
================================================
FILE: old_version/test/weshare.html
================================================
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<script src="../wechat.js" type="text/javascript"></script>
<script>
var dataForWeixin={
appId:"",
MsgImg:"https://open.weixin.qq.com/zh_CN/htmledition/res/assets/res-design-download/icon_res_download_wxlogo.png",
TLImg:"https://open.weixin.qq.com/zh_CN/htmledition/res/assets/res-design-download/icon_res_download_wxlogo.png",
url:"https://raw.githubusercontent.com/dodgepudding/wechat-php-sdk/master/test/weshare.html",
title:"微信分享测试文件",
desc:"这里演示了微信分享前调和回调方法",
fakeid:"",
prepare:function(e){
var log = '';
for (var i in e) {
log+= i+':'+e[i]+';';
}
alert(log);
},
callback:function(e){
var log = '';
for (var i in e) {
log+= i+':'+e[i]+';';
}
alert(log);
}
};
WeixinJS.hideToolbar();
WeixinJS.getNetworkType(
function(e){
alert(e);
});
</script>
<title>weshare</title>
</head>
<body>
<h3>这里演示了微信分享前调和回调方法,点击微信右上角分享相关的功能,即可看到各类返回的alert信息</h3>
</body>
</html>
================================================
FILE: old_version/wechat.js
================================================
/**
* 微信网页端调用JS(官方于微信6.0.2版本发布新版JSAPI接口,此接口文件废弃)
* @author dodge
* @contact dodgepudding@gmail.com
* @link http://blog.4wer.com/wechat-timeline-share
* @version 1.1
*
* 自定义分享使用:
* WeixinJS.hideOptionMenu() 隐藏右上角按钮
* WeixinJS.showOptionMenu() 显示右上角按钮
* WeixinJS.hideToolbar() 隐藏工具栏
* WeixinJS.showToolbar() 显示工具栏
* WeixinJS.getNetworkType() 获取网络状态
* WeixinJS.closeWindow() 关闭窗口
* WeixinJS.scanQRCode() 扫描二维码
* WeixinJS.openUrlByExtBrowser(url) 使用浏览器打开网址
* WeixinJS.jumpToBizProfile(username) 跳转到指定公众账号页面
* WeixinJS.sendEmail(title,content) 发送邮件
* WeixinJS.openProductView(latitude,longitude,name,address,scale,infoUrl) 查看地图
* WeixinJS.addContact(username) 添加微信账号
* WeixinJS.imagePreview(urls,current) 调出微信内图片预览
* WeixinJS.payCallback(appId,package,timeStamp,nonceStr,signType,paySign,callback) 微信JsApi支付接口
* WeixinJS.editAddress(appId,addrSign,timeStamp,nonceStr,callback) 微信JsApi支付接口
* 自定义分享内容数据格式:
* var dataForWeixin={
appId:"",
MsgImg:"消息图片路径",
TLImg:"时间线图路径",
url:"分享url路径",
title:"标题",
desc:"描述",
fakeid:"",
prepare:function(argv){
if (typeof argv.shareTo!='undefined')
switch(argv.shareTo) {
case 'friend':
//发送给朋友
alert(argv.scene); //friend
break;
case 'timeline':
//发送给朋友
break;
case 'weibo':
//发送到微博
alert(argv.url);
break;
case 'favorite':
//收藏
alert(argv.scene);//favorite
break;
case 'connector':
//分享到第三方应用
alert(argv.scene);//connector
break;
default:
}
},
callback:function(res){
//发送给好友或应用
if (res.err_msg=='send_app_msg:confirm') {
//todo:func1();
alert(res.err_desc);
}
if (res.err_msg=='send_app_msg:cancel') {
//todo:func2();
alert(res.err_desc);
}
//分享到朋友圈
if (res.err_msg=='share_timeline:ok') {
//todo:func1();
alert(res.err_desc);
}
if (res.err_msg=='share_timeline:cancel') {
//todo:func1();
alert(res.err_desc);
}
//分享到微博
if (res.err_msg=='share_weibo:confirm') {
//todo:func1();
alert(res.err_desc);
}
if (res.err_msg=='share_weibo:cancel') {
//todo:func1();
alert(res.err_desc);
}
//收藏或分享到应用
if (res.err_msg=='send_app_msg:ok') {
//todo:func1();
alert(res.err_desc);
}
}
};
*/
WeixinJS = typeof WeixinJS!='undefined' || {};
//隐藏右上角按钮
WeixinJS.hideOptionMenu = function() {
document.addEventListener('WeixinJSBridgeReady', function onBridgeReady() {
if (typeof WeixinJSBridge!='undefined') WeixinJSBridge.call('hideOptionMenu');
});
};
//显示右上角按钮
WeixinJS.showOptionMenu = function() {
document.addEventListener('WeixinJSBridgeReady', function onBridgeReady() {
if (typeof WeixinJSBridge!='undefined') WeixinJSBridge.call('showOptionMenu');
});
};
//隐藏底部导航栏
WeixinJS.hideToolbar = function() {
document.addEventListener('WeixinJSBridgeReady', function onBridgeReady() {
if (typeof WeixinJSBridge!='undefined') WeixinJSBridge.call('hideToolbar');
});
};
//显示底部导航栏
WeixinJS.showToolbar = function() {
document.addEventListener('WeixinJSBridgeReady', function onBridgeReady() {
if (typeof WeixinJSBridge!='undefined') WeixinJSBridge.call('showToolbar');
});
};
//网页获取用户网络状态
netType={"network_type:wifi":"wifi网络","network_type:edge":"非wifi,包含3G/2G","network_type:fail":"网络断开连接","network_type:wwan":"2g或者3g"};
WeixinJS.getNetworkType = function(callback) {
document.addEventListener('WeixinJSBridgeReady', function onBridgeReady() {
if (typeof WeixinJSBridge!='undefined') WeixinJSBridge.invoke('getNetworkType',{},
function(res){
//result: network_type:wifi,network_type:edge,network_type:fail,network_type:wwan
//netType[e.err_msg]
callback(res.err_msg);
});
});
};
//关闭窗口
WeixinJS.closeWindow = function() {
if (typeof WeixinJSBridge!='undefined') WeixinJSBridge.invoke("closeWindow", {});
};
//扫描二维码
WeixinJS.scanQRCode = function() {
if (typeof WeixinJSBridge!='undefined') WeixinJSBridge.invoke("scanQRCode", {});
};
//使用浏览器打开网址
WeixinJS.openUrlByExtBrowser=function(url){
if (typeof WeixinJSBridge!='undefined') WeixinJSBridge.invoke("openUrlByExtBrowser",{"url" : url});
};
//跳转到指定公众账号页面
WeixinJS.jumpToBizProfile=function(username){
if (typeof WeixinJSBridge!='undefined') WeixinJSBridge.invoke("jumpToBizProfile",{"tousername" : username});
};
//发送邮件
WeixinJS.sendEmail=function(title,content){
if (typeof WeixinJSBridge!='undefined') WeixinJSBridge.invoke("sendEmail",{
"title" : title,
"content" : content
});
};
//查看地图
WeixinJS.openProductView=function(latitude,longitude,name,address,scale,infoUrl){
if (typeof WeixinJSBridge!='undefined') WeixinJSBridge.invoke("openProductView",{
"latitude" : latitude, //纬度
"longitude" : longitude, //经度
"name" : name, //名称
"address" : address, //地址
"scale" : scale, //地图缩放级别
"infoUrl" : infoUrl, //查看位置界面底部的超链接
});
};
//添加微信账号
WeixinJS.addContact=function weixinAddContact(username){
if (typeof WeixinJSBridge!='undefined') WeixinJSBridge.invoke("addContact", {
"webtype": "1",
"username": username
}, function(e) {
WeixinJSBridge.log(e.err_msg);
//e.err_msg:add_contact:added 已经添加
//e.err_msg:add_contact:cancel 取消添加
//e.err_msg:add_contact:ok 添加成功
if(e.err_msg == 'add_contact:added' || e.err_msg == 'add_contact:ok'){
//关注成功,或者已经关注过
}
});
};
/**
* 调出微信内图片预览scrollview
* @param array urls 图片url数组
* @param string current 当前图片url
*/
WeixinJS.imagePreview = function(urls,current) {
if (typeof WeixinJSBridge!='undefined')
WeixinJSBridge.invoke("imagePreview", {
current: current,
urls: urls
});
};
//微信JsApi支付接口
WeixinJS.payCallback = function(appId,package,timeStamp,nonceStr,signType,paySign,callback){
if (typeof WeixinJSBridge!='undefined')
WeixinJSBridge.invoke('getBrandWCPayRequest',{
"appId" : appId.toString(),
"timeStamp" : timeStamp.toString(),
"nonceStr" : nonceStr.toString(),
"package" : package.toString(),
"signType" : signType.toString(),
"paySign" : paySign.toString()
},function(res){
// res.err_msg == "get_brand_wcpay_request:ok" return true;
// res.err_msg == "get_brand_wcpay_request:cancel" return false;
callback(res);
});
};
//编辑收货地址
WeixinJS.editAddress = function(appId,addrSign,timeStamp,nonceStr,callback){
var postdata = {
"appId" : appId.toString(),
"scope" : "jsapi_address",
"signType" : "sha1",
"addrSign" : addrSign.toString(),
"timeStamp" : timeStamp.toString(),
"nonceStr" : nonceStr.toString()
};
if (typeof WeixinJSBridge!='undefined')
WeixinJSBridge.invoke('editAddress',postdata, function(res){
//return res.proviceFirstStageName,res.addressCitySecondStageName,res.addressCountiesThirdStageName,res.addressDetailInfo,res.userName,res.addressPostalCode,res.telNumber
//error return res.err_msg
callback(res);
});
};
(function(){
if (typeof dataForWeixin=="undefined") return;
var onBridgeReady=function(){
WeixinJSBridge.on('menu:share:appmessage', function(argv){
(dataForWeixin.prepare)(argv);
WeixinJSBridge.invoke('sendAppMessage',{
"appid":dataForWeixin.appId,
"img_url":dataForWeixin.MsgImg,
"img_width":"120",
"img_height":"120",
"link":dataForWeixin.url,
"desc":dataForWeixin.desc,
"title":dataForWeixin.title
}, function(res){(dataForWeixin.callback)(res);});
});
WeixinJSBridge.on('menu:share:timeline', function(argv){
(dataForWeixin.prepare)(argv);
WeixinJSBridge.invoke('shareTimeline',{
"img_url":dataForWeixin.TLImg,
"img_width":"120",
"img_height":"120",
"link":dataForWeixin.url,
"desc":dataForWeixin.desc,
"title":dataForWeixin.title
}, function(res){(dataForWeixin.callback)(res);});
});
WeixinJSBridge.on('menu:share:weibo', function(argv){
(dataForWeixin.prepare)(argv);
WeixinJSBridge.invoke('shareWeibo',{
"content":dataForWeixin.title,
"url":dataForWeixin.url
}, function(res){(dataForWeixin.callback)(res);});
});
WeixinJSBridge.on('menu:share:facebook', function(argv){
(dataForWeixin.prepare)(argv);
WeixinJSBridge.invoke('shareFB',{
"img_url":dataForWeixin.TLImg,
"img_width":"120",
"img_height":"120",
"link":dataForWeixin.url,
"desc":dataForWeixin.desc,
"title":dataForWeixin.title
}, function(res){(dataForWeixin.callback)(res);});
});
};
if(document.addEventListener){
document.addEventListener('WeixinJSBridgeReady', onBridgeReady, false);
}else if(document.attachEvent){
document.attachEvent('WeixinJSBridgeReady' , onBridgeReady);
document.attachEvent('onWeixinJSBridgeReady' , onBridgeReady);
}
})();
================================================
FILE: old_version/wechatauth.class.php
================================================
<?php
/**
* 微信公众平台PHP-SDK
* Wechatauth为非官方微信登陆API
* 用户通过扫描网页提供的二维码实现登陆信息获取
* 主要实现如下功能:
* get_login_code() 获取登陆授权码, 通过授权码才能获取二维码
* get_code_image($code='') 将上面获取的授权码转换为图片二维码
* verify_code() 鉴定是否登陆成功,返回200为最终授权成功.
* get_login_info() 鉴定成功后调用此方法即可获取用户基本信息
* get_avatar($url) 获取用户头像图片数据
* @author dodge <dodgepudding@gmail.com>
* @link https://github.com/dodgepudding/wechat-php-sdk
* @version 1.1
*
*/
include "snoopy.class.php";
class Wechatauth
{
private $cookie;
private $skey;
private $_cookiename;
private $_cookieexpired = 3600;
private $_account = 'test';
private $_datapath = './data/cookie_';
private $debug;
private $_logcallback;
public $login_user; //当前登陆用户, 调用get_login_info后获取
public function __construct($options)
{
$this->_account = isset($options['account'])?$options['account']:'';
$this->_datapath = isset($options['datapath'])?$options['datapath']:$this->_datapath;
$this->debug = isset($options['debug'])?$options['debug']:false;
$this->_logcallback = isset($options['logcallback'])?$options['logcallback']:false;
$this->_cookiename = $this->_datapath.$this->_account;
$this->getCookie($this->_cookiename);
}
/**
* 把cookie写入缓存
* @param string $filename 缓存文件名
* @param string $content 文件内容
* @return bool
*/
public function saveCookie($filename,$content){
return file_put_contents($filename,$content);
}
/**
* 读取cookie缓存内容
* @param string $filename 缓存文件名
* @return string cookie
*/
public function getCookie($filename){
if (file_exists($filename)) {
$mtime = filemtime($filename);
if ($mtime<time()-$this->_cookieexpired) return false;
$data = file_get_contents($filename);
if ($data) $this->cookie = $data;
}
return $this->cookie;
}
/*
* 删除cookie
*/
public function deleteCookie($filename) {
$this->cookie = '';
@unlink($filename);
return true;
}
private function log($log){
if ($this->debug && function_exists($this->_logcallback)) {
if (is_array($log)) $log = print_r($log,true);
return call_user_func($this->_logcallback,$log);
}
}
/**
* 获取登陆二维码对应的授权码
*/
public function get_login_code(){
if ($this->_logincode) return $this->_logincode;
$t = time().strval(mt_rand(100,999));
$codeurl = 'https://login.weixin.qq.com/jslogin?appid=wx782c26e4c19acffb&redirect_uri=https%3A%2F%2Fwx.qq.com%2Fcgi-bin%2Fmmwebwx-bin%2Fwebwxnewloginpage&fun=new&lang=zh_CN&_='.$t;
$send_snoopy = new Snoopy;
$send_snoopy->fetch($codeurl);
$result = $send_snoopy->results;
if ($result) {
preg_match("/window.QRLogin.uuid\s+=\s+\"([^\"]+)\"/",$result,$matches);
if(count($matches)>1) {
$this->_logincode = $matches[1];
$_SESSION['login_step'] = 0;
return $this->_logincode;
}
}
return $result;
}
/**
* 通过授权码获取对应的二维码图片地址
* @param string $code
* @return string image url
*/
public function get_code_image($code=''){
if ($code=='') $code = $this->_logincode;
if (!$code) return false;
return 'http://login.weixin.qq.com/qrcode/'.$this->_logincode.'?t=webwx';
}
/**
* 设置二维码对应的授权码
* @param string $code
* @return class $this
*/
public function set_login_code($code) {
$this->_logincode = $code;
return $this;
}
/**
* 二维码登陆验证
*
* @return status:
* >=400: invaild code; 408: not auth and wait, 400,401: not valid or expired
* 201: just scaned but not confirm
* 200: confirm then you can get user info
*/
public function verify_code() {
if (!$this->_logincode) return false;
$t = time().strval(mt_rand(100,999));
$url = 'https://login.weixin.qq.com/cgi-bin/mmwebwx-bin/login?uuid='.$this->_logincode.'&tip=0&_='.$t;
$send_snoopy = new Snoopy;
$send_snoopy->referer = "https://wx.qq.com/";
$send_snoopy->fetch($url);
$result = $send_snoopy->results;
$this->log('step1:'.$result);
if ($result) {
preg_match("/window\.code=(\d+)/",$result,$matches);
if(count($matches)>1) {
$status = intval($matches[1]);
if ($status==201) $_SESSION['login_step'] = 1;
if ($status==200) {
preg_match("/ticket=([0-9a-z-_]+)&lang=zh_CN&scan=(\d+)/",$result,$matches);
preg_match("/window.redirect_uri=\"([^\"]+)\"/",$result,$matcheurl);
$this->log('step2:'.print_r($matches,true));
if (count($matcheurl)>1) {
$ticket = $matches[1];
$scan = $matches[2];
//$loginurl = 'https://wx2.qq.com/cgi-bin/mmwebwx-bin/webwxnewloginpage?ticket='.$ticket.'&lang=zh_CN&scan='.$scan.'&fun=new';
$loginurl = str_replace("wx.qq.com", "wx2.qq.com", $matcheurl[1]).'&fun=old';
$urlpart = parse_url($loginurl);
$send_snoopy = new Snoopy;
$send_snoopy->referer = "https://{$urlpart['host']}/cgi-bin/mmwebwx-bin/webwxindex?t=chat";
$send_snoopy->fetch($loginurl);
$result = $send_snoopy->results;
$xml = simplexml_load_string($result);
if ($xml->ret=="0") $this->skey = $xml->skey;
foreach ($send_snoopy->headers as $key => $value) {
$value = trim($value);
if(strpos($value,'Set-Cookie: ') !== false){
$tmp = str_replace("Set-Cookie: ","",$value);
$tmparray = explode(';', $tmp);
$item = trim($tmparray[0]);
$cookie.=$item.';';
}
}
$cookie .="Domain=.qq.com;";
$this->cookie = $cookie;
$this->log('step3:'.$loginurl.';cookie:'.$cookie.';respond:'.$result);
$this->saveCookie($this->_cookiename,$this->cookie);
}
}
return $status;
}
}
return false;
}
/**
* 获取登陆的cookie
*
* @param bool $is_array 是否以数值方式返回,默认否,返回字符串
* @return string|array
*/
public function get_login_cookie($is_array = false){
if (!$is_array) return $this->cookie;
$c_arr = explode(';',$this->cookie);
$cookie = array();
foreach($c_arr as $item) {
$kitem = explode('=',trim($item));
if (count($kitem)>1) {
$key = trim($kitem[0]);
$val = trim($kitem[1]);
if (!empty($val)) $cookie[$key] = $val;
}
}
return $cookie;
}
/**
* 授权登陆后获取用户登陆信息
*/
public function get_login_info(){
if (!$this->cookie) return false;
$t = time().strval(mt_rand(100,999));
$send_snoopy = new Snoopy;
$submit = 'https://wx2.qq.com/cgi-bin/mmwebwx-bin/webwxinit?r='.$t.'&skey='.urlencode($this->skey);
$send_snoopy->rawheaders['Cookie']= $this->cookie;
$send_snoopy->referer = "https://wx2.qq.com/";
$citems = $this->get_login_cookie(true);
$post = array(
"BaseRequest"=>array(
array(
"Uin"=>$citems['wxuin'],
"Sid"=>$citems['wxsid'],
"Skey"=>$this->skey,
"DeviceID"=>''
)
)
);
$send_snoopy->submit($submit,json_encode($post));
$this->log('login_info:'.$send_snoopy->results);
$result = json_decode($send_snoopy->results,true);
if ($result['BaseResponse']['Ret']<0) return false;
$this->_login_user = $result['User'];
return $result;
}
/**
* 获取头像
* @param string $url 传入从用户信息接口获取到的头像地址
*/
public function get_avatar($url) {
if (!$this->cookie) return false;
if (strpos($url, 'http')===false) {
$url = 'http://wx2.qq.com'.$url;
}
$send_snoopy = new Snoopy;
$send_snoopy->rawheaders['Cookie']= $this->cookie;
$send_snoopy->referer = "https://wx2.qq.com/";
$send_snoopy->fetch($url);
$result = $send_snoopy->results;
if ($result)
return $result;
else
return false;
}
/**
* 登出当前登陆用户
*/
public function logout(){
if (!$this->cookie) return false;
preg_match("/wxuin=(\w+);/",$this->cookie,$matches);
if (count($matches)>1) $uid = $matches[1];
preg_match("/wxsid=(\w+);/",$this->cookie,$matches);
if (count($matches)>1) $sid = $matches[1];
$this->log('logout: uid='.$uid.';sid='.$sid);
$send_snoopy = new Snoopy;
$submit = 'https://wx2.qq.com/cgi-bin/mmwebwx-bin/webwxlogout?redirect=1&type=1';
$send_snoopy->rawheaders['Cookie']= $this->cookie;
$send_snoopy->referer = "https://wx2.qq.com/";
$send_snoopy->submit($submit,array('uin'=>$uid,'sid'=>$sid));
$this->deleteCookie($this->_cookiename);
return true;
}
}
================================================
FILE: old_version/wechatext.class.php
================================================
<?php
/**
* 微信公众平台PHP-SDK
* Wechatext为非官方微信发送API
* 注: 用户id为通过getMsg()方法获取的FakeId值
* 主要实现如下功能:
* send($id,$content) 向某用户id发送微信文字信息
* getUserList($page,$pagesize,$groupid) 获取用户信息
* getGroupList($page,$pagesize) 获取群组信息
* sendNews($id,$msgid) 发送图文消息
* getNewsList($page,$pagesize) 获取图文信息列表
* uploadFile($filepath,$type) 上传附件,包括图片/音频/视频
* addPreview($title,$author,$summary,$content,$photoid,$srcurl='') 创建新的图文信息
* getFileList($type,$page,$pagesize) 获取素材库文件列表
* sendImage($id,$fid) 发送图片消息
* sendAudio($id,$fid) 发送音频消息
* sendVideo($id,$fid) 发送视频消息
* getInfo($id) 根据id获取用户资料
* getNewMsgNum($lastid) 获取从$lastid算起新消息的数目
* getTopMsg() 获取最新一条消息的数据, 此方法获取的消息id可以作为检测新消息的$lastid依据
* getMsg($lastid,$offset=0,$perpage=50,$day=0,$today=0,$star=0) 获取最新的消息列表, 列表将返回消息id, 用户id, 消息类型, 文字消息等参数
* 消息返回结构: {"id":"消息id","type":"类型号(1为文字,2为图片,3为语音)","fileId":"0","hasReply":"0","fakeId":"用户uid","nickName":"昵称","dateTime":"时间戳","content":"文字内容"}
* getMsgImage($msgid,$mode='large') 若消息type类型为2, 调用此方法获取图片数据
* getMsgVoice($msgid) 若消息type类型为3, 调用此方法获取语音数据
* quickSetInterface($url, $token) 快速设置接口信息
* getCommonInfo($dir) 获取公众账号基本信息, 其中包含:nickname,avatar,type,qrcode,appid,appsecret
* @author dodge <dodgepudding@gmail.com>
* @link https://github.com/dodgepudding/wechat-php-sdk
* @version 1.2
*
*/
include "snoopy.class
gitextract_4iqk6cac/
├── .gitignore
├── Codeigniter/
│ └── CI_Wechat.php
├── README.md
├── Thinkphp/
│ ├── EasyWechat.class.php
│ ├── JsSdkPay.class.php
│ ├── TPWechat.class.php
│ └── Wxauth.class.php
├── composer.json
├── demo.php
├── errCode.php
├── old_version/
│ ├── Thinkphp/
│ │ ├── Snoopy.class.php
│ │ ├── Wechatauth.class.php
│ │ ├── Wechatext.class.php
│ │ └── Wechatpay.class.php
│ ├── snoopy.class.php
│ ├── test/
│ │ ├── test2.php
│ │ ├── test3.php
│ │ └── weshare.html
│ ├── wechat.js
│ ├── wechatauth.class.php
│ ├── wechatext.class.php
│ └── wechatpay.class.php
├── qyerrCode.php
├── qywechat.class.php
├── test/
│ ├── auth.php
│ ├── getQRCode_test.php
│ ├── jsapi/
│ │ ├── jsapi-demo-6.1.js
│ │ ├── jsapi_demo.php
│ │ └── style.css
│ ├── merchanttest.php
│ ├── qydemo.php
│ ├── test-upload-shake-around-media.php
│ └── test1.php
├── wechat.class.php
└── wiki/
├── API接口错误码.md
├── Home.md
├── README.md
├── 为开发框架进行适配.md
├── 企业号API类库.md
├── 内嵌JS.md
├── 官方API类库.md
├── 授权登陆类库.md
├── 旧版微信支付V2接口类库.md
└── 非官方扩展类库.md
SYMBOL INDEX (489 symbols across 24 files)
FILE: Codeigniter/CI_Wechat.php
class CI_Wechat (line 16) | class CI_Wechat extends Wechat {
method __construct (line 18) | public function __construct() {
method setCache (line 35) | protected function setCache($cachename, $value, $expired) {
method getCache (line 44) | protected function getCache($cachename) {
method removeCache (line 53) | protected function removeCache($cachename) {
FILE: Thinkphp/EasyWechat.class.php
class EasyWechat (line 20) | class EasyWechat extends Wechat
method __construct (line 25) | public function __construct($options)
method log (line 37) | protected function log($log){
method setCache (line 56) | protected function setCache($cachename,$value,$expired=0){
method getCache (line 70) | protected function getCache($cachename){
method removeCache (line 88) | protected function removeCache($cachename){
method checkDir (line 96) | private function checkDir($dir, $mode=0777) {
FILE: Thinkphp/JsSdkPay.class.php
class JsSdkPay (line 15) | class JsSdkPay {
method __construct (line 46) | public function __construct($options) {
method formatBizQueryParaMap (line 56) | function formatBizQueryParaMap($paraMap, $urlencode)
method getParameters (line 79) | public function getParameters()
method getPrepayId (line 98) | function getPrepayId()
method xmlToArray (line 107) | public function xmlToArray($xml)
method postXml (line 116) | function postXml()
method postXmlCurl (line 125) | public function postXmlCurl($xml,$url,$second=30)
method createXml (line 165) | function createXml()
method arrayToXml (line 176) | function arrayToXml($arr)
method getSign (line 195) | public function getSign($Obj)
FILE: Thinkphp/TPWechat.class.php
class TPWechat (line 19) | class TPWechat extends Wechat
method log (line 25) | protected function log($log){
method setCache (line 45) | protected function setCache($cachename,$value,$expired){
method getCache (line 54) | protected function getCache($cachename){
method removeCache (line 63) | protected function removeCache($cachename){
FILE: Thinkphp/Wxauth.class.php
class Wxauth (line 14) | class Wxauth {
method __construct (line 19) | public function __construct($options){
method wxoauth (line 24) | public function wxoauth(){
FILE: errCode.php
class ErrCode (line 14) | class ErrCode
method getErrText (line 135) | public static function getErrText($err) {
FILE: old_version/Thinkphp/Snoopy.class.php
class Snoopy (line 31) | class Snoopy
method fetch (line 122) | function fetch($URI)
method submit (line 274) | function submit($URI, $formvars="", $formfiles="")
method fetchlinks (line 437) | function fetchlinks($URI)
method fetchform (line 466) | function fetchform($URI)
method fetchtext (line 494) | function fetchtext($URI)
method submitlinks (line 518) | function submitlinks($URI, $formvars="", $formfiles="")
method submittext (line 552) | function submittext($URI, $formvars = "", $formfiles = "")
method set_submit_multipart (line 586) | function set_submit_multipart()
method set_submit_normal (line 597) | function set_submit_normal()
method _striplinks (line 617) | function _striplinks($document)
method _stripform (line 651) | function _stripform($document)
method _striptext (line 671) | function _striptext($document)
method _expandlinks (line 740) | function _expandlinks($links,$URI)
method _httprequest (line 780) | function _httprequest($url,$fp,$URI,$http_method,$content_type="",$bod...
method _httpsrequest (line 945) | function _httpsrequest($url,$URI,$http_method,$content_type="",$body="")
method setcookies (line 1113) | function setcookies()
method _check_timeout (line 1129) | function _check_timeout($fp)
method _connect (line 1147) | function _connect(&$fp)
method _disconnect (line 1200) | function _disconnect($fp)
method _prepare_post_body (line 1214) | function _prepare_post_body($formvars, $formfiles)
FILE: old_version/Thinkphp/Wechatauth.class.php
class Wechatauth (line 18) | class Wechatauth
method __construct (line 30) | public function __construct($options)
method saveCookie (line 45) | public function saveCookie($filename,$content){
method getCookie (line 54) | public function getCookie($filename){
method deleteCookie (line 63) | public function deleteCookie($filename) {
method log (line 69) | private function log($log){
method get_login_code (line 79) | public function get_login_code(){
method get_code_image (line 102) | public function get_code_image($code=''){
method set_login_code (line 113) | public function set_login_code($code) {
method verify_code (line 126) | public function verify_code() {
method get_login_cookie (line 185) | public function get_login_cookie($is_array = false){
method get_login_info (line 203) | public function get_login_info(){
method get_avatar (line 233) | public function get_avatar($url) {
method logout (line 252) | public function logout(){
FILE: old_version/Thinkphp/Wechatext.class.php
class Wechatext (line 33) | class Wechatext
method __construct (line 45) | public function __construct($options)
method send (line 61) | public function send($id,$content)
method mass (line 83) | public function mass($content) {
method massNews (line 115) | function massNews($appmsgid){
method getUserList (line 149) | function getUserList($page=0,$pagesize=10,$groupid=0){
method getGroupList (line 171) | function getGroupList(){
method getNewsList (line 195) | public function getNewsList($page,$pagesize=10) {
method getDialogMsg (line 218) | public function getDialogMsg($fakeid) {
method sendNews (line 239) | public function sendNews($id,$msgid)
method uploadFile (line 263) | public function uploadFile($filepath,$type=2) {
method addPreview (line 291) | public function addPreview($title,$author,$summary,$content,$photoid,$...
method sendFile (line 337) | public function sendFile($id,$fid,$type) {
method getFileList (line 367) | public function getFileList($type,$page,$pagesize=10) {
method sendImage (line 389) | public function sendImage($id,$fid)
method sendAudio (line 399) | public function sendAudio($id,$fid)
method sendVideo (line 409) | public function sendVideo($id,$fid)
method sendPreview (line 424) | public function sendPreview($account,$title,$summary,$content,$photoid...
method getInfo (line 455) | public function getInfo($id)
method getHeadImg (line 478) | public function getHeadImg($fakeid){
method getNewMsgNum (line 497) | public function getNewMsgNum($lastid=0){
method getTopMsg (line 516) | public function getTopMsg(){
method getMsg (line 543) | public function getMsg($lastid=0,$offset=0,$perpage=20,$day=7,$today=0...
method getMsgImage (line 568) | public function getMsgImage($msgid,$mode='large'){
method getMsgVoice (line 587) | public function getMsgVoice($msgid){
method openDevModel (line 604) | public function openDevModel()
method closeEditModel (line 626) | public function closeEditModel()
method setUrlToken (line 650) | public function setUrlToken($url, $token)
method quickSetInterface (line 672) | public function quickSetInterface($url, $token)
method login (line 683) | public function login(){
method saveCookie (line 722) | public function saveCookie($filename,$content){
method getCookie (line 731) | public function getCookie($filename){
method checkValid (line 757) | public function checkValid()
method log (line 773) | private function log($log){
FILE: old_version/Thinkphp/Wechatpay.class.php
class Wechatpay (line 20) | class Wechatpay
method __construct (line 41) | public function __construct($options)
method log (line 52) | private function log($log){
method http_get (line 68) | private function http_get($url){
method http_post (line 94) | private function http_post($url,$param,$post_file=false){
method checkAuth (line 130) | public function checkAuth($appid='',$appsecret='',$token=''){
method resetAuth (line 165) | public function resetAuth($appid=''){
method json_encode (line 177) | static function json_encode($arr) {
method getSignature (line 227) | public function getSignature($arrdata,$method="sha1") {
method generateNonceStr (line 247) | public function generateNonceStr($length=16){
method createNativeUrl (line 263) | public function createNativeUrl($productid){
method createPackage (line 302) | public function createPackage($out_trade_no,$body,$total_fee,$notify_u...
method getPaySign (line 332) | public function getPaySign($package, $timeStamp, $nonceStr){
method checkOrderSignature (line 343) | public function checkOrderSignature($orderxml=''){
method sendPayDeliverNotify (line 365) | public function sendPayDeliverNotify($openid,$transid,$out_trade_no,$s...
method getPayOrder (line 399) | public function getPayOrder($out_trade_no) {
method setUserToken (line 430) | public function setUserToken($user_token) {
method getAddrSign (line 444) | public function getAddrSign($url, $timeStamp, $nonceStr, $user_token=''){
FILE: old_version/snoopy.class.php
class Snoopy (line 31) | class Snoopy
method fetch (line 122) | function fetch($URI)
method submit (line 274) | function submit($URI, $formvars="", $formfiles="")
method fetchlinks (line 437) | function fetchlinks($URI)
method fetchform (line 466) | function fetchform($URI)
method fetchtext (line 494) | function fetchtext($URI)
method submitlinks (line 518) | function submitlinks($URI, $formvars="", $formfiles="")
method submittext (line 552) | function submittext($URI, $formvars = "", $formfiles = "")
method set_submit_multipart (line 586) | function set_submit_multipart()
method set_submit_normal (line 597) | function set_submit_normal()
method _striplinks (line 617) | function _striplinks($document)
method _stripform (line 651) | function _stripform($document)
method _striptext (line 671) | function _striptext($document)
method _expandlinks (line 740) | function _expandlinks($links,$URI)
method _httprequest (line 780) | function _httprequest($url,$fp,$URI,$http_method,$content_type="",$bod...
method _httpsrequest (line 945) | function _httpsrequest($url,$URI,$http_method,$content_type="",$body="")
method setcookies (line 1114) | function setcookies()
method _check_timeout (line 1130) | function _check_timeout($fp)
method _connect (line 1148) | function _connect(&$fp)
method _disconnect (line 1201) | function _disconnect($fp)
method _prepare_post_body (line 1215) | function _prepare_post_body($formvars, $formfiles)
FILE: old_version/test/test2.php
function logdebug (line 7) | function logdebug($text){
FILE: old_version/test/test3.php
function logdebug (line 7) | function logdebug($text){
FILE: old_version/wechatauth.class.php
class Wechatauth (line 18) | class Wechatauth
method __construct (line 30) | public function __construct($options)
method saveCookie (line 45) | public function saveCookie($filename,$content){
method getCookie (line 54) | public function getCookie($filename){
method deleteCookie (line 67) | public function deleteCookie($filename) {
method log (line 73) | private function log($log){
method get_login_code (line 83) | public function get_login_code(){
method get_code_image (line 106) | public function get_code_image($code=''){
method set_login_code (line 117) | public function set_login_code($code) {
method verify_code (line 130) | public function verify_code() {
method get_login_cookie (line 189) | public function get_login_cookie($is_array = false){
method get_login_info (line 207) | public function get_login_info(){
method get_avatar (line 237) | public function get_avatar($url) {
method logout (line 256) | public function logout(){
FILE: old_version/wechatext.class.php
class Wechatext (line 34) | class Wechatext
method __construct (line 46) | public function __construct($options)
method send (line 62) | public function send($id,$content)
method mass (line 84) | public function mass($content) {
method massNews (line 116) | function massNews($appmsgid){
method getUserList (line 150) | function getUserList($page=0,$pagesize=10,$groupid=0){
method getGroupList (line 172) | function getGroupList(){
method getNewsList (line 196) | public function getNewsList($page,$pagesize=10) {
method getDialogMsg (line 219) | public function getDialogMsg($fakeid) {
method sendNews (line 240) | public function sendNews($id,$msgid)
method uploadFile (line 264) | public function uploadFile($filepath,$type=2) {
method addPreview (line 292) | public function addPreview($title,$author,$summary,$content,$photoid,$...
method sendFile (line 338) | public function sendFile($id,$fid,$type) {
method getFileList (line 368) | public function getFileList($type,$page,$pagesize=10) {
method sendImage (line 390) | public function sendImage($id,$fid)
method sendAudio (line 400) | public function sendAudio($id,$fid)
method sendVideo (line 410) | public function sendVideo($id,$fid)
method sendPreview (line 425) | public function sendPreview($account,$title,$summary,$content,$photoid...
method getInfo (line 456) | public function getInfo($id)
method getHeadImg (line 479) | public function getHeadImg($fakeid){
method getNewMsgNum (line 498) | public function getNewMsgNum($lastid=0){
method getTopMsg (line 517) | public function getTopMsg(){
method getMsg (line 544) | public function getMsg($lastid=0,$offset=0,$perpage=20,$day=7,$today=0...
method getMsgImage (line 569) | public function getMsgImage($msgid,$mode='large'){
method getMsgVoice (line 588) | public function getMsgVoice($msgid){
method openDevModel (line 605) | public function openDevModel()
method closeEditModel (line 627) | public function closeEditModel()
method setUrlToken (line 651) | public function setUrlToken($url, $token)
method quickSetInterface (line 673) | public function quickSetInterface($url, $token)
method getCommonInfo (line 685) | public function getCommonInfo($dir)
method downloadImage (line 765) | public function downloadImage($from, $dir)
method checkImgType (line 789) | public function checkImgType($imgName){
method login (line 818) | public function login(){
method saveCookie (line 857) | public function saveCookie($filename,$content){
method getCookie (line 866) | public function getCookie($filename){
method checkValid (line 900) | public function checkValid()
method log (line 916) | private function log($log){
FILE: old_version/wechatpay.class.php
class Wechatpay (line 20) | class Wechatpay
method __construct (line 41) | public function __construct($options)
method log (line 52) | private function log($log){
method http_get (line 63) | private function http_get($url){
method http_post (line 89) | private function http_post($url,$param,$post_file=false){
method checkAuth (line 125) | public function checkAuth($appid='',$appsecret='',$token=''){
method resetAuth (line 156) | public function resetAuth($appid=''){
method json_encode (line 167) | static function json_encode($arr) {
method getSignature (line 217) | public function getSignature($arrdata,$method="sha1") {
method generateNonceStr (line 237) | public function generateNonceStr($length=16){
method createNativeUrl (line 253) | public function createNativeUrl($productid){
method createPackage (line 292) | public function createPackage($out_trade_no,$body,$total_fee,$notify_u...
method getPaySign (line 322) | public function getPaySign($package, $timeStamp, $nonceStr){
method checkOrderSignature (line 333) | public function checkOrderSignature($orderxml=''){
method sendPayDeliverNotify (line 355) | public function sendPayDeliverNotify($openid,$transid,$out_trade_no,$s...
method getPayOrder (line 389) | public function getPayOrder($out_trade_no) {
method setUserToken (line 420) | public function setUserToken($user_token) {
method getAddrSign (line 434) | public function getAddrSign($url, $timeStamp, $nonceStr, $user_token=''){
FILE: qyerrCode.php
class ErrCode (line 14) | class ErrCode
method getErrText (line 175) | public static function getErrText($err) {
FILE: qywechat.class.php
class Wechat (line 19) | class Wechat
method __construct (line 101) | public function __construct($options)
method log (line 112) | protected function log($log){
method data_to_xml (line 124) | public static function data_to_xml($data) {
method xmlSafeStr (line 136) | public static function xmlSafeStr($str)
method xml_encode (line 151) | public function xml_encode($data, $root='xml', $item='item', $attr='',...
method json_encode (line 172) | static function json_encode($arr) {
method _auto_text_filter (line 221) | private function _auto_text_filter($text) {
method http_get (line 230) | private function http_get($url){
method http_post (line 256) | private function http_post($url,$param,$post_file=false){
method checkSignature (line 293) | private function checkSignature($str)
method valid (line 313) | public function valid($return=false)
method getRev (line 365) | public function getRev()
method getRevData (line 382) | public function getRevData()
method getRevPostXml (line 390) | public function getRevPostXml()
method getRevFrom (line 398) | public function getRevFrom() {
method getRevTo (line 408) | public function getRevTo() {
method getRevAgentID (line 418) | public function getRevAgentID() {
method getRevType (line 428) | public function getRevType() {
method getRevID (line 438) | public function getRevID() {
method getRevCtime (line 448) | public function getRevCtime() {
method getRevContent (line 458) | public function getRevContent(){
method getRevPic (line 468) | public function getRevPic(){
method getRevGeo (line 481) | public function getRevGeo(){
method getRevEventGeo (line 496) | public function getRevEventGeo(){
method getRevEvent (line 510) | public function getRevEvent(){
method getRevScanInfo (line 537) | public function getRevScanInfo(){
method getRevSendPicsInfo (line 573) | public function getRevSendPicsInfo(){
method getRevSendGeoInfo (line 613) | public function getRevSendGeoInfo(){
method getRevVoice (line 638) | public function getRevVoice(){
method getRevVideo (line 651) | public function getRevVideo(){
method text (line 666) | public function text($text='')
method image (line 684) | public function image($mediaid='')
method voice (line 702) | public function voice($mediaid='')
method video (line 720) | public function video($mediaid='',$title='',$description='')
method news (line 751) | public function news($newsData=array())
method Message (line 774) | public function Message($msg = '',$append = false){
method reply (line 795) | public function reply($msg=array(),$return = false)
method generate (line 827) | private function generate($encrypt, $signature, $timestamp, $nonce)
method setCache (line 846) | protected function setCache($cachename,$value,$expired){
method getCache (line 856) | protected function getCache($cachename){
method removeCache (line 866) | protected function removeCache($cachename){
method checkAuth (line 877) | public function checkAuth($appid='',$appsecret='',$token=''){
method resetAuth (line 914) | public function resetAuth($appid=''){
method resetJsTicket (line 926) | public function resetJsTicket($appid=''){
method getJsTicket (line 939) | public function getJsTicket($appid='',$jsapi_ticket=''){
method getJsSign (line 977) | public function getJsSign($url, $timestamp=0, $noncestr='', $appid=''){
method getSignature (line 1009) | public function getSignature($arrdata,$method="sha1") {
method generateNonceStr (line 1029) | public function generateNonceStr($length=16){
method createMenu (line 1095) | public function createMenu($data,$agentid=''){
method getMenu (line 1118) | public function getMenu($agentid=''){
method deleteMenu (line 1141) | public function deleteMenu($agentid=''){
method uploadMedia (line 1173) | public function uploadMedia($data, $type){
method getMedia (line 1194) | public function getMedia($media_id){
method getServerIp (line 1214) | public function getServerIp(){
method createDepartment (line 1246) | public function createDepartment($data){
method updateDepartment (line 1278) | public function updateDepartment($data){
method deleteDepartment (line 1303) | public function deleteDepartment($id){
method moveDepartment (line 1333) | public function moveDepartment($data){
method getDepartment (line 1371) | public function getDepartment(){
method createUser (line 1408) | public function createUser($data){
method updateUser (line 1445) | public function updateUser($data){
method deleteUser (line 1470) | public function deleteUser($userid){
method deleteUsers (line 1500) | public function deleteUsers($userids){
method getUserInfo (line 1539) | public function getUserInfo($userid){
method getUserList (line 1572) | public function getUserList($department_id,$fetch_child=0,$status=0){
method getUserListInfo (line 1616) | public function getUserListInfo($department_id,$fetch_child=0,$status=0){
method getUserId (line 1645) | public function getUserId($code,$agentid=0){
method sendInvite (line 1675) | public function sendInvite($userid,$invite_tips=''){
method createTag (line 1709) | public function createTag($data){
method updateTag (line 1738) | public function updateTag($data){
method deleteTag (line 1763) | public function deleteTag($tagid){
method getTag (line 1794) | public function getTag($tagid){
method addTagUser (line 1828) | public function addTagUser($data){
method delTagUser (line 1862) | public function delTagUser($data){
method getTagList (line 1890) | public function getTagList(){
method sendMessage (line 1978) | public function sendMessage($data){
method authSucc (line 2008) | public function authSucc($userid){
method getOauthRedirect (line 2030) | public function getOauthRedirect($callback,$state='STATE',$scope='snsa...
class PKCS7Encoder (line 2043) | class PKCS7Encoder
method encode (line 2052) | function encode($text)
method decode (line 2075) | function decode($text)
class Prpcrypt (line 2092) | class Prpcrypt
method __construct (line 2096) | function __construct($k) {
method Prpcrypt (line 2103) | function Prpcrypt($k)
method encrypt (line 2113) | public function encrypt($text, $appid)
method decrypt (line 2147) | public function decrypt($encrypted, $appid)
method getRandomStr (line 2192) | function getRandomStr()
class ErrorCode (line 2210) | class ErrorCode
method getErrText (line 2238) | public static function getErrText($err) {
FILE: test/auth.php
class wxauth (line 6) | class wxauth {
method __construct (line 11) | public function __construct($options){
method wxoauth (line 17) | public function wxoauth(){
FILE: test/getQRCode_test.php
function logdebug (line 8) | function logdebug($text){
FILE: test/jsapi/jsapi-demo-6.1.js
function upload (line 312) | function upload() {
function download (line 340) | function download() {
FILE: test/qydemo.php
function logg (line 4) | function logg($text){
FILE: test/test1.php
function logdebug (line 8) | function logdebug($text){
FILE: wechat.class.php
class Wechat (line 44) | class Wechat
method __construct (line 242) | public function __construct($options)
method checkSignature (line 255) | private function checkSignature($str='')
method valid (line 279) | public function valid($return=false)
method Message (line 333) | public function Message($msg = '',$append = false){
method setFuncFlag (line 350) | public function setFuncFlag($flag) {
method log (line 360) | protected function log($log){
method getRev (line 370) | public function getRev()
method getRevData (line 385) | public function getRevData()
method getRevFrom (line 393) | public function getRevFrom() {
method getRevTo (line 403) | public function getRevTo() {
method getRevType (line 413) | public function getRevType() {
method getRevID (line 423) | public function getRevID() {
method getRevCtime (line 433) | public function getRevCtime() {
method getRevContent (line 443) | public function getRevContent(){
method getRevPic (line 455) | public function getRevPic(){
method getRevLink (line 468) | public function getRevLink(){
method getRevGeo (line 482) | public function getRevGeo(){
method getRevEventGeo (line 497) | public function getRevEventGeo(){
method getRevEvent (line 511) | public function getRevEvent(){
method getRevScanInfo (line 538) | public function getRevScanInfo(){
method getRevSendPicsInfo (line 574) | public function getRevSendPicsInfo(){
method getRevSendGeoInfo (line 614) | public function getRevSendGeoInfo(){
method getRevVoice (line 639) | public function getRevVoice(){
method getRevVideo (line 652) | public function getRevVideo(){
method getRevTicket (line 665) | public function getRevTicket(){
method getRevSceneId (line 675) | public function getRevSceneId (){
method getRevTplMsgID (line 688) | public function getRevTplMsgID(){
method getRevStatus (line 698) | public function getRevStatus(){
method getRevResult (line 709) | public function getRevResult(){
method getRevKFCreate (line 736) | public function getRevKFCreate(){
method getRevKFClose (line 748) | public function getRevKFClose(){
method getRevKFSwitch (line 764) | public function getRevKFSwitch(){
method getRevCardPass (line 781) | public function getRevCardPass(){
method getRevCardGet (line 793) | public function getRevCardGet(){
method getRevCardDel (line 813) | public function getRevCardDel(){
method getRevOrderId (line 830) | public function getRevOrderId(){
method xmlSafeStr (line 837) | public static function xmlSafeStr($str)
method data_to_xml (line 847) | public static function data_to_xml($data) {
method xml_encode (line 869) | public function xml_encode($data, $root='xml', $item='item', $attr='',...
method _auto_text_filter (line 890) | private function _auto_text_filter($text) {
method text (line 900) | public function text($text='')
method image (line 919) | public function image($mediaid='')
method voice (line 939) | public function voice($mediaid='')
method video (line 959) | public function video($mediaid='',$title='',$description='')
method music (line 986) | public function music($title,$desc,$musicurl,$hgmusicurl='',$thumbmedi...
method news (line 1022) | public function news($newsData=array())
method reply (line 1047) | public function reply($msg=array(),$return = false)
method generate (line 1083) | private function generate($encrypt, $signature, $timestamp, $nonce)
method http_get (line 1099) | private function http_get($url){
method http_post (line 1125) | private function http_post($url,$param,$post_file=false){
method setCache (line 1179) | protected function setCache($cachename,$value,$expired){
method getCache (line 1189) | protected function getCache($cachename){
method removeCache (line 1199) | protected function removeCache($cachename){
method checkAuth (line 1210) | public function checkAuth($appid='',$appsecret='',$token=''){
method resetAuth (line 1247) | public function resetAuth($appid=''){
method resetJsTicket (line 1259) | public function resetJsTicket($appid=''){
method getJsTicket (line 1272) | public function getJsTicket($appid='',$jsapi_ticket=''){
method getJsSign (line 1310) | public function getJsSign($url, $timestamp=0, $noncestr='', $appid=''){
method getCardSign (line 1346) | public function getCardSign($card_type='',$card_id='',$code='',$locati...
method json_encode (line 1371) | static function json_encode($arr) {
method getSignature (line 1381) | public function getSignature($arrdata,$method="sha1") {
method getJsCardTicket (line 1401) | public function getJsCardTicket($appid='',$api_ticket=''){
method getTicketSignature (line 1436) | public function getTicketSignature($arrdata,$method="sha1") {
method generateNonceStr (line 1452) | public function generateNonceStr($length=16){
method getServerIp (line 1467) | public function getServerIp(){
method createMenu (line 1536) | public function createMenu($data){
method getMenu (line 1556) | public function getMenu(){
method deleteMenu (line 1576) | public function deleteMenu(){
method addconditionalMenu (line 1598) | public function addconditionalMenu($data){
method delconditionalMenu (line 1620) | public function delconditionalMenu($data){
method trymatchMenu (line 1642) | public function trymatchMenu($data){
method uploadMedia (line 1667) | public function uploadMedia($data, $type){
method getMedia (line 1690) | public function getMedia($media_id,$is_video=false){
method uploadImg (line 1719) | public function uploadImg($data){
method uploadForeverMedia (line 1748) | public function uploadForeverMedia($data, $type,$is_video=false,$video...
method uploadForeverArticles (line 1775) | public function uploadForeverArticles($data){
method updateForeverArticles (line 1799) | public function updateForeverArticles($media_id,$data,$index=0){
method getForeverMedia (line 1824) | public function getForeverMedia($media_id,$is_video=false){
method delForeverMedia (line 1856) | public function delForeverMedia($media_id){
method getForeverList (line 1886) | public function getForeverList($type,$offset,$count){
method getForeverCount (line 1918) | public function getForeverCount(){
method uploadArticles (line 1939) | public function uploadArticles($data){
method uploadMpVideo (line 1970) | public function uploadMpVideo($data){
method sendMassMessage (line 2003) | public function sendMassMessage($data){
method sendGroupMassMessage (line 2036) | public function sendGroupMassMessage($data){
method deleteMassMessage (line 2057) | public function deleteMassMessage($msg_id){
method previewMassMessage (line 2087) | public function previewMassMessage($data){
method queryMassMessage (line 2112) | public function queryMassMessage($msg_id){
method getQRCode (line 2135) | public function getQRCode($scene_id,$type=0,$expire=604800){
method getQRUrl (line 2191) | public function getQRUrl($ticket) {
method getShortUrl (line 2200) | public function getShortUrl($long_url){
method getDatacube (line 2228) | public function getDatacube($type,$subtype,$begin_date,$end_date=''){
method getUserList (line 2254) | public function getUserList($next_openid=''){
method getUserInfo (line 2277) | public function getUserInfo($openid, $lang = 'zh_CN'){
method getUsersInfo (line 2298) | public function getUsersInfo($openids){
method updateUserRemark (line 2320) | public function updateUserRemark($openid,$remark){
method getGroup (line 2344) | public function getGroup(){
method getUserGroup (line 2365) | public function getUserGroup($openid){
method createGroup (line 2389) | public function createGroup($name){
method updateGroup (line 2414) | public function updateGroup($groupid,$name){
method updateGroupMembers (line 2439) | public function updateGroupMembers($groupid,$openid){
method batchUpdateGroupMembers (line 2465) | public function batchUpdateGroupMembers($groupid,$openid_list){
method sendCustomMessage (line 2490) | public function sendCustomMessage($data){
method getOauthRedirect (line 2511) | public function getOauthRedirect($callback,$state='',$scope='snsapi_us...
method getOauthAccessToken (line 2519) | public function getOauthAccessToken(){
method getOauthRefreshToken (line 2542) | public function getOauthRefreshToken($refresh_token){
method getOauthUserinfo (line 2565) | public function getOauthUserinfo($access_token,$openid){
method getOauthAuth (line 2586) | public function getOauthAuth($access_token,$openid){
method setTMIndustry (line 2607) | public function setTMIndustry($id1,$id2=''){
method addTemplateMessage (line 2630) | public function addTemplateMessage($tpl_id){
method sendTemplateMessage (line 2675) | public function sendTemplateMessage($data){
method getCustomServiceMessage (line 2695) | public function getCustomServiceMessage($data){
method transfer_customer_service (line 2716) | public function transfer_customer_service($customer_account = '')
method getCustomServiceKFlist (line 2736) | public function getCustomServiceKFlist(){
method getCustomServiceOnlineKFlist (line 2767) | public function getCustomServiceOnlineKFlist(){
method createKFSession (line 2795) | public function createKFSession($openid,$kf_account,$text=''){
method closeKFSession (line 2828) | public function closeKFSession($openid,$kf_account,$text=''){
method getKFSession (line 2860) | public function getKFSession($openid){
method getKFSessionlist (line 2893) | public function getKFSessionlist($kf_account){
method getKFSessionWait (line 2929) | public function getKFSessionWait(){
method addKFAccount (line 2958) | public function addKFAccount($account,$nickname,$password){
method updateKFAccount (line 2992) | public function updateKFAccount($account,$nickname,$password){
method deleteKFAccount (line 3024) | public function deleteKFAccount($account){
method setKFHeadImg (line 3052) | public function setKFHeadImg($account,$imgfile){
method querySemantic (line 3079) | public function querySemantic($uid,$query,$category,$latitude=0,$longi...
method createCard (line 3115) | public function createCard($data) {
method updateCard (line 3136) | public function updateCard($data) {
method delCard (line 3158) | public function delCard($card_id) {
method getCardInfo (line 3181) | public function getCardInfo($card_id) {
method getUserCardList (line 3214) | public function getUserCardList($openid,$card_id) {
method getCardColors (line 3238) | public function getCardColors() {
method getCardLocations (line 3260) | public function getCardLocations($offset=0,$count=0) {
method addCardLocations (line 3285) | public function addCardLocations($data) {
method createCardQrcode (line 3312) | public function createCardQrcode($card_id,$code='',$openid='',$expire_...
method consumeCardCode (line 3358) | public function consumeCardCode($code,$card_id='') {
method decryptCardCode (line 3386) | public function decryptCardCode($encrypt_code) {
method checkCardCode (line 3419) | public function checkCardCode($code) {
method getCardIdList (line 3449) | public function getCardIdList($offset=0,$count=50) {
method updateCardCode (line 3479) | public function updateCardCode($code,$card_id,$new_code) {
method unavailableCardCode (line 3506) | public function unavailableCardCode($code,$card_id='') {
method modifyCardStock (line 3531) | public function modifyCardStock($data) {
method updateMeetingCard (line 3551) | public function updateMeetingCard($data) {
method activateMemberCard (line 3571) | public function activateMemberCard($data) {
method updateMemberCard (line 3592) | public function updateMemberCard($data) {
method updateLuckyMoney (line 3614) | public function updateLuckyMoney($code,$balance,$card_id='') {
method setCardTestWhiteList (line 3641) | public function setCardTestWhiteList($openid=array(),$user=array()) {
method applyShakeAroundDevice (line 3701) | public function applyShakeAroundDevice($data){
method updateShakeAroundDevice (line 3740) | public function updateShakeAroundDevice($data){
method searchShakeAroundDevice (line 3827) | public function searchShakeAroundDevice($data){
method bindLocationShakeAroundDevice (line 3863) | public function bindLocationShakeAroundDevice($device_id,$poi_id,$uuid...
method bindPageShakeAroundDevice (line 3922) | public function bindPageShakeAroundDevice($device_id,$page_ids=array()...
method uploadShakeAroundMedia (line 3974) | public function uploadShakeAroundMedia($data){
method addShakeAroundPage (line 4011) | public function addShakeAroundPage($title,$description,$icon_url,$page...
method updateShakeAroundPage (line 4056) | public function updateShakeAroundPage($page_id,$title,$description,$ic...
method searchShakeAroundPage (line 4137) | public function searchShakeAroundPage($page_ids=array(),$begin=0,$coun...
method deleteShakeAroundPage (line 4183) | public function deleteShakeAroundPage($page_ids=array()){
method getShakeInfoShakeAroundUser (line 4233) | public function getShakeInfoShakeAroundUser($ticket){
method deviceShakeAroundStatistics (line 4292) | public function deviceShakeAroundStatistics($device_id,$begin_date,$en...
method pageShakeAroundStatistics (line 4365) | public function pageShakeAroundStatistics($page_id,$begin_date,$end_da...
method getOrderByID (line 4391) | public function getOrderByID($order_id){
method getOrderByFilter (line 4419) | public function getOrderByFilter($status = null, $begintime = null, $e...
method setOrderDelivery (line 4456) | public function setOrderDelivery($order_id, $need_delivery = 0, $deliv...
method closeOrder (line 4490) | public function closeOrder($order_id){
method parseSkuInfo (line 4512) | private function parseSkuInfo($skuInfo) {
method getRevOrderSkuInfo (line 4530) | public function getRevOrderSkuInfo(){
class PKCS7Encoder (line 4542) | class PKCS7Encoder
method encode (line 4551) | function encode($text)
method decode (line 4574) | function decode($text)
class Prpcrypt (line 4591) | class Prpcrypt
method __construct (line 4595) | function __construct($k) {
method Prpcrypt (line 4602) | function Prpcrypt($k)
method encrypt (line 4612) | public function encrypt($text, $appid){
method decrypt (line 4632) | public function decrypt($encrypted, $appid){
method getRandomStr (line 4669) | function getRandomStr()
class ErrorCode (line 4687) | class ErrorCode
method getErrText (line 4715) | public static function getErrText($err) {
Condensed preview — 44 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (570K chars).
[
{
"path": ".gitignore",
"chars": 43,
"preview": "/nbproject/private/\n.buildpath\n/pages/\n/my/"
},
{
"path": "Codeigniter/CI_Wechat.php",
"chars": 1477,
"preview": "<?php\ndefined('BASEPATH') OR exit('No direct script access allowed');\n\n/**\n * 微信公众平台PHP-SDK, Codeigniter实例\n * @author "
},
{
"path": "README.md",
"chars": 28318,
"preview": "wechat-php-sdk\n==============\n\n微信公众平台php开发包,细化各项接口操作,支持链式调用,欢迎Fork此项目 \nweixin developer SDK.\n项目地址:**https://github.com/"
},
{
"path": "Thinkphp/EasyWechat.class.php",
"chars": 3123,
"preview": "<?php\n/**\n * 微信公众平台PHP-SDK, 简单缓存实例\n * @author binsee@163.com\n * @link https://github.com/binsee/wechat-php-sdk\n * "
},
{
"path": "Thinkphp/JsSdkPay.class.php",
"chars": 5780,
"preview": "<?php\n/**\n * 官方文档:http://mp.weixin.qq.com/wiki/7/aaa137b55fb2e0456bf8dd9148dd613f.html\n * 微信支付:http://pay.weixin.qq.com/"
},
{
"path": "Thinkphp/TPWechat.class.php",
"chars": 1397,
"preview": "<?php\n/**\n *\t微信公众平台PHP-SDK, ThinkPHP实例\n * @author dodgepudding@gmail.com\n * @link https://github.com/dodgepudding/wech"
},
{
"path": "Thinkphp/Wxauth.class.php",
"chars": 3296,
"preview": "<?php\n/**\n * 微信oAuth认证示例\n * 官方文档:http://mp.weixin.qq.com/wiki/17/c0f37d5704f0b64713d5d2c37b468d75.html\n * UCToo示例:http:/"
},
{
"path": "composer.json",
"chars": 750,
"preview": "{\n \"name\" : \"dodgepudding/wechat-php-sdk\",\n \"description\" : \"the wechat api library without framework dependency\",\n \""
},
{
"path": "demo.php",
"chars": 544,
"preview": "<?php\ninclude \"wechat.class.php\";\n$options = array(\n\t\t'token'=>'tokenaccesskey', //填写你设定的key\n 'encodingaeskey'=>'"
},
{
"path": "errCode.php",
"chars": 4237,
"preview": "<?php\n/**\n * 微信公众平台PHP-SDK, 全局返回码类\n * @author binsee <binsee@163.com>\n * @link https://github.com/binsee/wechat-ph"
},
{
"path": "old_version/Thinkphp/Snoopy.class.php",
"chars": 38208,
"preview": "<?php\n/*************************************************\n\nSnoopy - the PHP net client\nAuthor: Monte Ohrt <monte@ispi.net"
},
{
"path": "old_version/Thinkphp/Wechatauth.class.php",
"chars": 7871,
"preview": "<?php\n/**\n *\t微信公众平台PHP-SDK\n * Wechatauth为非官方微信登陆API\n * 用户通过扫描网页提供的二维码实现登陆信息获取\n * 主要实现如下功能:\n * get_login_code() 获取登陆授"
},
{
"path": "old_version/Thinkphp/Wechatext.class.php",
"chars": 25495,
"preview": "<?php\n/**\n *\t微信公众平台PHP-SDK\n * Wechatext为非官方微信发送API\n * 注: 用户id为通过getMsg()方法获取的FakeId值\n * 主要实现如下功能:\n * send($id,$conte"
},
{
"path": "old_version/Thinkphp/Wechatpay.class.php",
"chars": 14864,
"preview": "<?php\n/**\n *\t微信公众平台PHP-SDK, 旧版微信支付接口(微信支付V2)\n * @author dodge <dodgepudding@gmail.com>\n * @link https://github.com/do"
},
{
"path": "old_version/snoopy.class.php",
"chars": 38253,
"preview": "<?php\n/*************************************************\n\nSnoopy - the PHP net client\nAuthor: Monte Ohrt <monte@ispi.net"
},
{
"path": "old_version/test/test2.php",
"chars": 1756,
"preview": "<?php\n/**\n * 微信扩展接口测试\n */\n\tinclude(\"../wechatext.class.php\");\n\t\n\tfunction logdebug($text){\n\t\tfile_put_contents('../data/"
},
{
"path": "old_version/test/test3.php",
"chars": 2289,
"preview": "<?php\n/**\n * 微信二维码登陆测试\n */\n\tinclude(\"../wechatauth.class.php\");\n\tsession_start();\n\tfunction logdebug($text){\n\t\tfile_put_"
},
{
"path": "old_version/test/weshare.html",
"chars": 1192,
"preview": "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\""
},
{
"path": "old_version/wechat.js",
"chars": 8960,
"preview": "/**\n * 微信网页端调用JS(官方于微信6.0.2版本发布新版JSAPI接口,此接口文件废弃)\n * @author dodge\n * @contact dodgepudding@gmail.com\n * @link http://bl"
},
{
"path": "old_version/wechatauth.class.php",
"chars": 8011,
"preview": "<?php\n/**\n *\t微信公众平台PHP-SDK\n * Wechatauth为非官方微信登陆API\n * 用户通过扫描网页提供的二维码实现登陆信息获取\n * 主要实现如下功能:\n * get_login_code() 获取登陆授"
},
{
"path": "old_version/wechatext.class.php",
"chars": 30974,
"preview": "<?php\n/**\n *\t微信公众平台PHP-SDK\n * Wechatext为非官方微信发送API\n * 注: 用户id为通过getMsg()方法获取的FakeId值\n * 主要实现如下功能:\n * send($id,$conte"
},
{
"path": "old_version/wechatpay.class.php",
"chars": 14594,
"preview": "<?php\n/**\n *\t微信公众平台PHP-SDK, 旧版微信支付接口(微信支付V2)\n * @author dodge <dodgepudding@gmail.com>\n * @link https://github.com/do"
},
{
"path": "qyerrCode.php",
"chars": 5463,
"preview": "<?php\n/**\n *\t微信公众平台企业号PHP-SDK, 全局返回码类\n * @author binsee <binsee@163.com>\n * @link https://github.com/binsee/wechat-ph"
},
{
"path": "qywechat.class.php",
"chars": 63914,
"preview": "<?php\n/**\n *\t微信公众平台企业号PHP-SDK, 官方API类库\n * @author binsee <binsee@163.com>\n * @link https://github.com/binsee/wechat-p"
},
{
"path": "test/auth.php",
"chars": 2966,
"preview": "<?php\n/**\n * 微信oAuth认证示例\n */\ninclude(\"../wechat.class.php\");\nclass wxauth {\n\tprivate $options;\n\tpublic $open_id;\n\tpublic"
},
{
"path": "test/getQRCode_test.php",
"chars": 1001,
"preview": "<?php\n/**\n * 微信公共接口测试\n *\n */\ninclude(\"../wechat.class.php\");\n\nfunction logdebug($text){\n\tfile_put_contents('../data/log."
},
{
"path": "test/jsapi/jsapi-demo-6.1.js",
"chars": 14763,
"preview": "wx.ready(function () {\n\talert(\"启动jsapi!\");\n // 1 判断当前版本是否支持指定 JS 接口,支持批量判断\n document.querySelector('#checkJsApi').oncl"
},
{
"path": "test/jsapi/jsapi_demo.php",
"chars": 8478,
"preview": "<?php\r\ninclude \"wechat.class.php\";\r\ninclude 'errCode.php';\r\n\r\n$opt = array(\r\n 'appsecret'=>'xxxxxxxxxxxxxxxxxxxxx"
},
{
"path": "test/jsapi/style.css",
"chars": 3614,
"preview": "html {\r\n -ms-text-size-adjust: 100%;\r\n -webkit-text-size-adjust: 100%;\r\n -webkit-user-select: none;\r\n user-select: n"
},
{
"path": "test/merchanttest.php",
"chars": 396,
"preview": "<?php\ninclude \"../wechat.class.php\";\n\n$options = array(\n\t\t'token'=>'XXXXXX', //填写你设定的key\n\t\t'encodingaeskey'=>'XXXXXX', /"
},
{
"path": "test/qydemo.php",
"chars": 781,
"preview": "<?php\ninclude \"../qywechat.class.php\";\n\nfunction logg($text){\n file_put_contents('./log.txt',$text.\"\\r\\n\\r\\n\",FILE_AP"
},
{
"path": "test/test-upload-shake-around-media.php",
"chars": 283,
"preview": "<?php\n/**\n * 微信摇一摇周边上传素材测试\n * \n */\n\tinclude(\"../wechat.class.php\");\n\n\t$options = array(\n\t\t'appid' => '', //填写高"
},
{
"path": "test/test1.php",
"chars": 614,
"preview": "<?php\n/**\n * 微信公共接口测试\n * \n */\n\tinclude(\"../wechat.class.php\");\n\t\n\tfunction logdebug($text){\n\t\tfile_put_contents('../data"
},
{
"path": "wechat.class.php",
"chars": 148444,
"preview": "<?php\n/**\n *\t微信公众平台PHP-SDK, 官方API部分\n * @author dodge <dodgepudding@gmail.com>\n * @link https://github.com/dodgepuddin"
},
{
"path": "wiki/API接口错误码.md",
"chars": 322,
"preview": "## errCode.php\r\n### 关于API接口错误码有两个版本:\r\n**一个是普通公众号平台的errCode.php;\r\n一个是企业号平台的 qyerrCode.php\r\n用法都是一样的。**\r\n\r\n当调用API接口失败时,可以用此"
},
{
"path": "wiki/Home.md",
"chars": 1189,
"preview": "# wechat-php-sdk\r\n\r\n微信公众平台php开发包,细化各项接口操作,支持链式调用 \r\n项目地址:**https://github.com/dodgepudding/wechat-php-sdk** \r\n项目wiki:**"
},
{
"path": "wiki/README.md",
"chars": 1263,
"preview": "wiki目录说明\r\n==============\r\n这个目录是wechat-php-sdk项目的wiki文档\r\nMake By:binsee\r\n\r\n##说明 \r\n**这里的wiki文档可以让你更好的了解`wechat-php-sdk`项目,"
},
{
"path": "wiki/为开发框架进行适配.md",
"chars": 1951,
"preview": "#为开发框架进行适配\r\n\r\n为不同的开发框架进行适配缓存操作(保存access_token、jsapi_ticket),及输出调试日志。\r\n\r\n由于微信api需要缓存access_token与jsapi_ticket,而在不同框架下的缓存方"
},
{
"path": "wiki/企业号API类库.md",
"chars": 6590,
"preview": "# qywechat.class.php\r\n\r\n## 企业号API类库\r\n调用官方API,具有更灵活的消息分类响应方式,支持链式调用操作 ; \r\n\r\n## 主要功能 \r\n- 接入验证\r\n- 自动回复(文本、图片、语音、视频、音乐、图文)\r\n"
},
{
"path": "wiki/内嵌JS.md",
"chars": 1146,
"preview": "#wechat.js\r\n\r\n**此JS脚本已经废弃不再更新,原因是官方在微信6.0.2版本开放了全新的JSAPI接口,更全面好用。请查看:[微信公众平台WIKI](http://mp.weixin.qq.com/wiki)**\r\n\r\n##微"
},
{
"path": "wiki/官方API类库.md",
"chars": 11323,
"preview": "# wechat.class.php\r\n\r\n调用官方API,具有更灵活的消息分类响应方式,支持链式调用操作 ; \r\n\r\n## 主要功能 \r\n- 接入验证 **(初级权限)**\r\n- 自动回复(文本、图片、语音、视频、音乐、图文) **(初级"
},
{
"path": "wiki/授权登陆类库.md",
"chars": 1354,
"preview": "# wechatauth.class.php \r\n\r\n**此扩展类库已经不再更新,原因是官方开放平台对网站应用开放的有授权登陆接口,更标准,更好用。请查看:[微信开放平台](http://open.weixin.qq.com)** \r\n"
},
{
"path": "wiki/旧版微信支付V2接口类库.md",
"chars": 1672,
"preview": "# wechatpay.class.php \r\n\r\n旧版微信支付类库(微信支付V2),已移动至old_version目录下。 \r\n自2014年8月开始申请到的微信支付都是V3接口,据官方说V2的会陆续升级为V3接口,但时间及升级渠道未确认"
},
{
"path": "wiki/非官方扩展类库.md",
"chars": 2170,
"preview": "# wechatext.class.php\r\n\r\n**此扩展类库已经不再更新,原因是官方对公众号开放了众多接口,此类库继续维护的意义不大** \r\n\r\n非官方扩展API,需要配置公众平台账户和密码,能实现对已关注用户的点对点微信,此方式不保"
}
]
About this extraction
This page contains the full source code of the dodgepudding/wechat-php-sdk GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 44 files (508.9 KB), approximately 169.4k tokens, and a symbol index with 489 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.