easywechat Api大全

一、入门

文档

1.1 安装

环境要求:

  • PHP >= 7.0
  • PHP cURL 扩展
  • PHP OpenSSL 扩展
  • PHP SimpleXML 扩展
  • PHP fileinfo 拓展

使用 composer:

$ composer require overtrue/wechat:~4.0 -vvv

Laravel 5 拓展包: overtrue/laravel-wechat

二、公众号

2.1 公众号

公众号的各模块相对比较统一,用法如下:

use EasyWeChat\Factory;

$config = [
    'app_id' => 'wx3cf0f39249eb0exx',
    'secret' => 'f1c242f4f28f735d4687abb469072axx',

    // 指定 API 调用返回结果的类型:array(default)/collection/object/raw/自定义类名
    'response_type' => 'array',

    //...
];

$app = Factory::officialAccount($config);

$app 在所有相关公众号的文档都是指 Factory::officialAccount 实例,就不在每个页面单独写了。

2.2 快速开始

安装完成后,即可很快的开始使用它了。

以服务器端验证与接收响应用户消息为例,首先要了解下微信交互的运行流程:

+------+    +---------------+               +-------------+
|      |--->|               |-post/get/put->|             |
| user |    | wechat server |               | your server |
|      |<---|               |<--------------|             |
+------+    +---------------+               +-------------+

那要做的就是图中微信服务器把用户消息转到自有服务器(虚线返回部分)后的处理过程。

2.2.1 服务端验证

在微信接入开始有个 “服务器验证” 的过程,这一步就是微信服务器向自有服务器发起个请求(上图实线部分),传了个名称为 echostr 字符串过来,只需原样返回就好了。

微信后台只能填写一个服务器地址,所以 服务器验证与消息的接收与回复,都在这个链接内完成交互。

考虑到这些,把验证这步给封装到 SDK 里,可完全忽略这步。

下面来配置个基本的服务端,假设自有服务器域名叫 easywechat.com,在服务器上准备个文件server.php:

// server.php

use EasyWeChat\Factory;

$config = [
    'app_id' => 'wx3cf0f39249eb0xxx',
    'secret' => 'f1c242f4f28f735d4687abb469072xxx',
    'token' => 'TestToken',
    'response_type' => 'array',
    //...
];

$app = Factory::officialAccount($config);
$response = $app->server->serve();

// 将响应输出
$response->send();exit; // Laravel 里请使用:return $response;

❤ 安全模式下一定要配置 aes_key

一个服务端带验证功能的代码已完成,对消息的处理后面再讲。

先分析上面代码:

// 引入我们的主项目工厂类。
use EasyWeChat\Factory;

// 一些配置
$config = [...];

// 使用配置来初始化一个公众号应用实例。
$app = Factory::officialAccount($config);
$response = $app->server->serve();

// 将响应输出
$response->send(); exit; // Laravel 请用:return $response;

最后这行有必要详细讲一下:

  1. $app->server->serve() 是执行服务端业务,它的返回值是个 Symfony\Component\HttpFoundation\Response 实例。
  2. 这里是直接调用它的 send() 方法,即直接输出(echo),在一些框架不能直接输出,那就直接拿到 Response 实例后做相应的操作即可,如 Laravel 可直接 return $app->server->serve();

有了上面代码,按 微信官方的接入指引 在公众号后台完成配置并启用,并相应修改上面的 $config 的相关配置。

URL 是 http://easywechat.com/server.php,这里我是举例哦。

这样,点击提交验证就OK了。

一定要将微信后台的开发者模式 “启用” ,看到红色 “停用” 才真正启用。 最后,不要用浏览器访问这个地址,它是给微信服务器访问的。

2.2.2 接收 & 回复用户消息

服务端验证通过了,就来试下接收消息吧。

上面代码最后一行 $app->server->serve()->send(); 前面调用 $app->serverpush() 来注册消息处理器,这里用了 PHP 闭包

// ...
$app->server->push(function ($message) {
    return "您好!欢迎使用 EasyWeChat!";
});

$response = $app->server->serve();

// 将响应输出
$response->send(); // Laravel 里请使用:return $response;

注意:send() 方法已包含 echo ,请不要再加 echo 在前面。

打开你的微信客户端,向你的公众号发送任意一条消息,会收到回复:您好!欢迎使用 EasyWeChat!

没收到回复?看到“你的公众号暂时无法提供服务” ?那检查下日志吧,配置里写了日志路径了(__DIR__.'/wechat.log')。

{warning} 注意:在 Laravel 框架应用时,因 POST 请求默认有 CSRF 验证,所以要在 App\Http\Middleware\VerifyCsrfTokenexcept 数组中添加微信请求,否则会提示“你的公众号暂时无法提供服务”。

一个基本的服务端验证就完成了。

2.2.3 总结

  1. 所有的应用服务都通过主入口 EasyWeChat\Factory 类来创建:

    // 公众号
    $app = Factory::officialAccount($config);
    
    // 小程序
    $app = Factory::miniProgram($config);
    
    // 开放平台
    $app = Factory::openPlatform($config);
    
    // 企业微信
    $app = Factory::work($config);
    
    // 企业微信开放平台
    $app = Factory::openWork($config);
    
    // 微信支付
    $app = Factory::payment($config);
    

2.3 配置

常用的配置参数较少,因为除非有特别的定制,否则基本上默认值就可以:

use EasyWeChat\Factory;

$config = [
    'app_id' => 'wx3cf0f39249eb0exx',
    'secret' => 'f1c242f4f28f735d4687abb469072axx',

    'response_type' => 'array',     // 指定 API 调用返回结果的类型:array(default)/collection/object/raw/自定义类名
    //...
];

$app = Factory::officialAccount($config);

下面是个完整的配置样例:

不建议在配置时弄这么多,因为大部分用默认值即可。



return [
    /**
     * 账号基本信息,请从微信公众平台/开放平台获取
     */
    'app_id'  => 'your-app-id',         // AppID
    'secret'  => 'your-app-secret',     // AppSecret
    'token'   => 'your-token',          // Token
    'aes_key' => '',   // EncodingAESKey,兼容与安全模式下请一定要填写!!!

     /**
      * 指定 API 调用返回结果的类型:array(default)/collection/object/raw/自定义类名
      * 使用自定义类名时,构造函数将会接收一个 `EasyWeChat\Kernel\Http\Response` 实例
      */
    'response_type' => 'array',

    /**
     * 日志配置
     * level: 日志级别, 可选为:debug/info/notice/warning/error/critical/alert/emergency
     * path:日志文件位置(绝对路径!!!),要求可写权限
     */
    'log' => [
        'default' => 'dev', // 默认 channel,生产环境可改为下面的 prod
        'channels' => [
            // 测试环境
            'dev' => [
                'driver' => 'single',
                'path' => '/tmp/easywechat.log',
                'level' => 'debug',
            ],
            // 生产环境
            'prod' => [
                'driver' => 'daily',
                'path' => '/tmp/easywechat.log',
                'level' => 'info',
            ],
        ],
    ],

    /**
     * 接口请求相关配置,超时时间等,具体参数请参考:
     * http://docs.guzzlephp.org/en/stable/request-config.html
     *
     * - retries: 重试次数,默认 1,当 http 请求失败时重试次数。
     * - retry_delay: 重试延迟间隔(单位:ms),默认 500
     * - log_template: 指定 HTTP 日志模板,请参考:https://github.com/guzzle/guzzle/blob/master/src/MessageFormatter.php
     */
    'http' => [
        'max_retries' => 1,
        'retry_delay' => 500,
        'timeout' => 5.0,
        // 'base_uri' => 'https://api.weixin.qq.com/', // 如果在国外想覆盖默认的 url 时才用,根据不同的模块配置不同的 uri
    ],

    /**
     * OAuth 配置
     *
     * scopes:公众平台(snsapi_userinfo / snsapi_base),开放平台:snsapi_login
     * callback:OAuth授权完成后的回调页地址
     */
    'oauth' => [
        'scopes'   => ['snsapi_userinfo'],
        'callback' => '/examples/oauth_callback.php',
    ],
];

❤ 安全模式下请一定要填写 aes_key

2.3.1 日志配置

可配置多个日志的 channel,每个 channel 的 driver 对应不同的日志驱动,内置可用 driver 如下表:

名称 描述
stack 复合型,可包含下面多种驱动的混合模式
single 基于 StreamHandler 单一文件日志,参数有 pathlevel
daily 基于 RotatingFileHandler 按日期生成日志文件,参数有 pathleveldays(默认 7 天)
slack 基于 SlackWebhookHandler 的 Slack 组件,参数请参考源码:LogManager.php
syslog 基于 SyslogHandler Monolog 驱动,参数有 facility 默认为 LOG_USERlevel
errorlog 记录日志到系统错误日志,基于 ErrorLogHandler,参数有 type,默认 ErrorLogHandler::OPERATING_SYSTEM

2.3.2 自定义日志驱动

由于日志用的 Monolog,所以除默认文件式日志外,可自定义日志处理器:

use Monolog\Logger;
use Monolog\Handler\RotatingFileHandler;

// 注册自定义日志
$app->logger->extend('mylog', function($app, $config){
    return new Logger($this->parseChannel($config), [
        $this->prepareHandler(new RotatingFileHandler(
            $config['path'], $config['days'], $this->level($config)
        )),
    ]);
});

在自定义的闭包函数中,可用 EasyWeChat\Kernel\Log\LogManager 的方法,具体查看 SDK 源代码。

配置文件中在 driver 部分即可使用自定义的驱动:

'log' => [
    'default' => 'dev', // 默认使用的 channel,生产环境可以改为下面的 prod
    'channels' => [
        // 测试环境
        'dev' => [
            'driver' => 'mylog',
            'path' => '/tmp/easywechat.log',
            'level' => 'debug', 
            'days' => 5,
        ],

        //...
    ],
],

2.4 基础接口

2.4.1 清理接口调用次数

此接口官方有每月调用限制,不可随意调用

$app->base->clearQuota();

2.4.2 获取微信服务器 IP (或IP段)

$app->base->getValidIps();

2.5 服务端

在入门小教程一节以服务端为例讲解了一个基本的消息的处理。

服务端的作用,在整个微信开发中主要是负责 接收用户发送过来的消息,还有 用户触发的一系列事件

首先得理清消息与事件的回复逻辑,当收到用户消息后(消息由微信服务器推送到自有服务器),在对消息进行处理后,不管是选择回复消息还是什么不都回给用户,也应给微信服务器一个 “答复”,如果是选择回复一条消息,就直接返回一个消息xml,如果选择不作任何回复,也得回复个空字符串或字符串 SUCCESS(不然用户会看到 该公众号暂时无法提供服务)。

2.5.1 基本使用

在 SDK 中用 $app->server->push(callable $callback) 设置消息处理器:

$app->server->push(function ($message) {
    // $message['FromUserName'] // 用户的 openid
    // $message['MsgType'] // 消息类型:event, text....
    return "您好!欢迎使用 EasyWeChat";
});

// 在 laravel 中:
$response = $app->server->serve();
// $response 为 `Symfony\Component\HttpFoundation\Response` 实例
// 对于需要直接输出响应的框架,或原生 PHP 环境下
$response->send();

// 而 laravel 中直接返回即可:
return $response;

这里用 push 传入个 闭包(Closure),该闭包接收个参数 $message 为消息对象(类型取决于配置中 response_type),可在全局消息处理器中对消息类型筛选:

$app->server->push(function ($message) {
    switch ($message['MsgType']) {
        case 'event':
            return '收到事件消息';
            break;
        case 'text':
            return '收到文字消息';
            break;
        case 'image':
            return '收到图片消息';
            break;
        case 'voice':
            return '收到语音消息';
            break;
        case 'video':
            return '收到视频消息';
            break;
        case 'location':
            return '收到坐标消息';
            break;
        case 'link':
            return '收到链接消息';
            break;
        case 'file':
            return '收到文件消息';
        // ... 其它消息
        default:
            return '收到其它消息';
            break;
    }

    // ...
});

因为这里 push 接收个 callable 的参数,所以不一定要传入个 Closure 闭包,可选择传入个函数名,一个 [$class, $method]Foo::bar 类型。

某些情况,需直接用 $message 参数,那怎么在 push 的闭包外调用呢?

    $message = $server->getMessage();

注意:$message 类型取决于配置中 response_type

2.5.2 注册多个消息处理器

有时要对消息记日志,或一系列的自定义操作,可注册多个 handler:

$app->server->push(MessageLogHandler::class);
$app->server->push(MessageReplyHandler::class);
$app->server->push(OtherHandler::class);
$app->server->push(...);

注意:

  1. 最后个非空返回值将作为最终应答给用户的消息内容,如果中间某 handler 返回 false, 则终止整个调用链,不调用后续 handlers。
  2. 传入自定义 Handler 类需实现 \EasyWeChat\Kernel\Contracts\EventHandlerInterface

2.5.3注册指定消息类型的消息处理器

对特定类型的消息应用不同的处理器,可在第二个参数传入类型筛选:

注意:参数二是 \EasyWeChat\Kernel\Messages\Message 类的常量。

use EasyWeChat\Kernel\Messages\Message;

$app->server->push(ImageMessageHandler::class, Message::IMAGE); // 图片消息
$app->server->push(TextMessageHandler::class, Message::TEXT); // 文本消息

// 同时处理多种类型的处理器
$app->server->push(MediaMessageHandler::class, Message::VOICE|Message::VIDEO|Message::SHORT_VIDEO); // 当消息为 三种中任意一种都可触发

2.5.4 请求消息的属性

当接收到用户的消息时,可能会提取消息中的相关属性,参考:

请求消息基本属性(以下所有消息都有的基本属性):

  • ToUserName 接收方帐号(该公众号 ID)
  • FromUserName 发送方帐号(OpenID, 代表用户的唯一标识)
  • CreateTime 消息创建时间(时间戳)
  • MsgId 消息 ID(64位整型)
2.5.2.1 文本:
  • MsgType text
  • Content 文本消息内容
2.5.2.2 图片:
  • MsgType image
  • MediaId 图片消息媒体id,可调用多媒体文件下载接口拉数据
  • PicUrl 图片链接
2.5.2.3 语音:
  • MsgType voice
  • MediaId 语音消息媒体id,可调用多媒体文件下载接口拉数据
  • Format 语音格式,如 amr,speex 等
  • Recognition 开通语音识别后才有

注意,开通语音识别后,用户每次发送语音给公众号时,微信会在推送的语音消息XML数据包中,增加一个 Recongnition 字段

2.5.2.4 视频:
  • MsgType video
  • MediaId 视频消息媒体id,可调用多媒体文件下载接口拉数据
  • ThumbMediaId 视频消息缩略图的媒体id,可调用多媒体文件下载接口拉数据
2.5.2.5 小视频:
  • MsgType shortvideo
  • MediaId 视频消息媒体id,可调用多媒体文件下载接口拉数据
  • ThumbMediaId 视频消息缩略图的媒体id,可调用多媒体文件下载接口拉数据
2.5.2.6 事件:
  • MsgType event
  • Event 事件类型 (如:subscribe(订阅)、unsubscribe(取消订阅) …, CLICK 等)
2.5.2.7 扫描带参数二维码事件
  • EventKey 事件KEY值,如:qrscene_123123,qrscene_为前缀,后面为二维码的参数值
  • Ticket 二维码的 ticket,可用来换取二维码图片
2.5.2.8 上报地理位置事件
  • Latitude 23.137466 地理位置纬度
  • Longitude 113.352425 地理位置经度
  • Precision 119.385040 地理位置精度
2.5.2.9 自定义菜单事件
  • EventKey 事件KEY值,与自定义菜单接口中KEY值对应,如:CUSTOM_KEY_001, www.qq.com
2.5.2.10 地理位置:
  • MsgType location
  • Location_X 地理位置纬度
  • Location_Y 地理位置经度
  • Scale 地图缩放大小
  • Label 地理位置信息
2.5.2.11 链接:
  • MsgType link
  • Title 消息标题
  • Description 消息描述
  • Url 消息链接
2.5.2.12 文件:

MsgType file Title 文件名 Description 文件描述,可能为null FileKey 文件KEY FileMd5 文件MD5值 FileTotalLen 文件大小,单位字节

2.5.5 回复消息

回复的消息可为 null,此时 SDK 会返回给微信一个 “SUCCESS”,也可回复个普通字符串,如:欢迎关注 overtrue.,此时 SDK 会对它进行封装,产生个 EasyWeChat\Kernel\Messages\Text 类型消息并在最后的 $app->server->serve(); 时生成对应的消息 XML 格式。

如果想返回手动拼的原生 XML 格式消息,请返回个 EasyWeChat\Kernel\Messages\Raw 实例。

2.5.6 消息转发给客服系统

参见:多客服消息转发

关于消息的使用,请参考 消息 章节。

2.6 消息

把微信的 API 里的所有“消息”都按类型抽象出来,即不用区分它是回消息还是推送消息,免去手动拼装微信的 XML 及乱七八糟命名不统一的 JSON。

在阅读以下内容时请忽略是 接收消息 还是 回复消息,后面会讲它们的区别。

2.6.1 消息类型

消息分:文本图片视频声音链接坐标图文文章 和特殊的 原始消息

另外还有种特殊的消息类型:素材消息,用于群发或客服时发送已有素材。

注意:回复消息与客服消息里的图文类型为:图文,群发与素材中的图文为文章

消息类都在 EasyWeChat\Kernel\Messages 命名空间下, 下面分开讲解:

2.6.1.1 文本消息

属性列表:

  • content 文本内容
use EasyWeChat\Kernel\Messages\Text;

$text = new Text('您好!overtrue。');

// or
$text = new Text();
$text->content = '您好!overtrue。';

// or
$text = new Text();
$text->setAttribute('content', '您好!overtrue。');
2.6.1.2 图片消息

属性列表:

- media_id 媒体资源 ID
use EasyWeChat\Kernel\Messages\Image;

$image = new Image($mediaId);
2.6.1.3 视频消息

属性列表:

  • title 标题
  • description 描述
  • media_id 媒体资源 ID
  • thumb_media_id 封面资源 ID
use EasyWeChat\Kernel\Messages\Video;

$video = new Video($mediaId, [
        'title' => $title,
        'description' => '...',
    ]);
2.6.1.4 声音消息

属性列表:

  • media_id 媒体资源 ID
use EasyWeChat\Kernel\Messages\Voice;

$voice = new Voice($mediaId);
2.6.1.5 链接消息

微信目前不支持回复链接消息

2.6.1.6 坐标消息

微信目前不支持回复坐标消息

2.6.1.7 图文消息

图文消息分: NewsItemNewsNewsItem 为图文内容条目。

10月12日起,被动回复消息与客服消息接口的图文消息类型中图文数目只能为一条

NewsItem 属性:

  • title 标题
  • description 描述
  • image 图片链接
  • url 链接 URL
use EasyWeChat\Kernel\Messages\News;
use EasyWeChat\Kernel\Messages\NewsItem;

$items = [
    new NewsItem([
        'title'       => $title,
        'description' => '...',
        'url'         => $url,
        'image'       => $image,
        // ...
    ]),
];
$news = new News($items);
2.6.1.8 文章

属性列表:

  • title 标题
  • author 作者
  • content 具体内容
  • thumb_media_id 图文消息的封面图片素材id(必须是永久mediaID)
  • digest 图文消息的摘要,仅单图文消息才有摘要,多图文为空
  • source_url 来源 URL
  • show_cover 是否显示封面,0 为 false不显示,1 为 true显示
use EasyWeChat\Kernel\Messages\Article;

$article = new Article([
        'title'   => 'EasyWeChat',
        'author'  => 'overtrue',
        'content' => 'EasyWeChat 是一个开源的微信 SDK',
        // ...
    ]);

// or
$article = new Article();
$article->title   = 'EasyWeChat';
$article->author  = 'overtrue';
$article->content = '微信 SDK ...';
// ...
2.6.1.10 素材消息

素材消息用于群发与客服消息时使用。

素材消息不支持被动回复,如需被动回复素材消息,首先组装后,再 News 方法返回。

属性就一个:media_id

在构造时有两个参数:

$type 素材类型,支持:mpnewsmpvideovoiceimage 等。

$mediaId 素材 ID,从接口查询或者上传后得到。

use EasyWeChat\Kernel\Messages\Media;

$media = new Media($mediaId, 'mpnews');

以上是所有微信支持的基本消息类型。

注意,无需关心微信的消息字段叫啥,因为这里用了更标准的命名,然后最终在中间做了转换。

2.6.3 原始消息

原始消息是种特殊的消息,它的场景是:不想使用其它消息类型,想自己手动拼消息。如,回复消息时,自己拼 XML,那就直接用它就可以了:

use EasyWeChat\Kernel\Messages\Raw;

$message = new Raw('


12345678




');

如,要用于客服消息(客服消息是JSON结构):

use EasyWeChat\Kernel\Messages\Raw;

$message = new Raw('{
    "touser":"OPENID",
    "msgtype":"text",
    "text":
    {
         "content":"Hello World"
    }
}');

总之,直接写微信接口要求的格式内容就好,此类型消息在 SDK 中不存在转换行为,所以请注意不要写错格式。

2.6.2 在 SDK 中使用消息

2.6.3 在服务端回复消息

在 服务端 一节中,讲了回复消息的写法:

// ... 前面部分省略
$app->server->push(function ($message) {
    return "您好!欢迎关注我!";
});

$response = $server->serve();

上面 return 一句普通的文本内容,这里只为方便大家,实际上最后会有个隐式转换为 Text 类型的动作。

如果要回复其它类型消息,需返回个具体的实例,如回复个图片类型的消息:

use EasyWeChat\Kernel\Messages\Image;
// ...
$app->server->push(function ($message) {
    return new Image('media-id');
});
// ...
2.6.4.1 回复多图文消息

10月12日起,被动回复消息与客服消息接口的图文消息类型中图文数目只能为一条

多图文消息就是单图文消息的一个数组而已了:

use EasyWeChat\Kernel\Messages\News;
use EasyWeChat\Kernel\Messages\NewsItem;

// ...
$app->server->push(function ($message) {
   $news = new NewsItem(...);
   return new News([$news]);
});
// ...

2.6.4 作为客服消息发送

在客服消息里的使用也一样,都是直接传入消息实例即可:

use EasyWeChat\Kernel\Messages\Text;

$message = new Text('Hello world!');

$result = $app->customer_service->message($message)->to($openId)->send();
//...
2.6.4.1 发送多图文消息

10月12日起,被动回复消息与客服消息接口的图文消息类型中图文数目只能为一条

多图文消息其实就是单图文消息组成的一个 News 对象而已:

$news1 = new NewsItem(...);
$news = new News([$news1]);

$app->customer_service->message($news)->to($openId)->send();

2.6.5 群发消息

请参考:群发消息

2.6.3 消息转发给客服系统

参见:多客服消息转发

2.7 多客服消息转发

多客服的消息转发绝对是超级的简单,转发的消息类型为 transfer

use EasyWeChat\Kernel\Messages\Transfer;

// 转发收到的消息给客服
$app->server->push(function($message) {
  return new Transfer();
});

$response = $app->server->serve();

当然,也可指定转发给某个客服:

use EasyWeChat\Kernel\Messages\Transfer;

$app->server->push(function($message) {
    return new Transfer($account);
});

2.8 群发

微信的群发消息接口有各种注意事项及限制,具体请阅读微信官方文档。

2.8.1 发送消息

以下所有方法均有第二个参数 $to 用于指定接收对象:

  • $to 为整型时为标签 id
  • $to 为数组时为用户 openid 列表(至少两个用户的 openid)
  • $tonull 时表示全部用户
$app->broadcasting->sendMessage(Message $message, array | int $to = null);

下面的别名方法 sendXXX 是基于上面 sendMessage 方法的封装。

2.8.1.1 文本消息
$app->broadcasting->sendText("大家好!欢迎使用 EasyWeChat。");

// 指定目标用户
// 至少两个用户的 openid,必须是数组。
$app->broadcasting->sendText("大家好!欢迎使用 EasyWeChat。", [$openid1, $openid2]);

// 指定标签组用户
$app->broadcasting->sendText("大家好!欢迎使用 EasyWeChat。", $tagId); // $tagId 必须是整型数字
2.8.1.2 图文消息
$app->broadcasting->sendNews($mediaId);
$app->broadcasting->sendNews($mediaId, [$openid1, $openid2]);
$app->broadcasting->sendNews($mediaId, $tagId);
2.8.1.3 图片消息
$app->broadcasting->sendImage($mediaId);
$app->broadcasting->sendImage($mediaId, [$openid1, $openid2]);
$app->broadcasting->sendImage($mediaId, $tagId);
2.8.1.4 语音消息
$app->broadcasting->sendVoice($mediaId);
$app->broadcasting->sendVoice($mediaId, [$openid1, $openid2]);
$app->broadcasting->sendVoice($mediaId, $tagId);
2.8.1.5 视频消息

用于群发的视频消息,需先创建消息对象,

// 1. 先上传视频素材用于群发:
$video = '/path/to/video.mp4';
$videoMedia = $app->media->uploadVideoForBroadcasting($video, '视频标题', '视频描述');

// 结果如下:
//{
//  "type":"video",
//  "media_id":"IhdaAQXuvJtGzwwc0abfXnzeezfO0NgPK6AQYShD8RQYMTtfzbLdBIQkQziv2XJc",
//  "created_at":1398848981
//}

// 2. 使用上面得到的 media_id 群发视频消息
$app->broadcasting->sendVideo($videoMedia['media_id']);
2.8.1.5 卡券消息
$app->broadcasting->sendCard($cardId);
$app->broadcasting->sendCard($cardId, [$openid1, $openid2]);
$app->broadcasting->sendCard($cardId, $tagId);
2.8.1.6 发送预览群发消息给指定的 openId 用户
$app->broadcasting->previewText($text, $openId);
$app->broadcasting->previewNews($mediaId, $openId);
$app->broadcasting->previewVoice($mediaId, $openId);
$app->broadcasting->previewImage($mediaId, $openId);
$app->broadcasting->previewVideo($message, $openId);
$app->broadcasting->previewCard($cardId, $openId);
2.8.1.7 发送预览群发消息给指定的微信号用户

$wxanme 是用户微信号,如:notovertrue

$app->broadcasting->previewTextByName($text, $wxname);
$app->broadcasting->previewNewsByName($mediaId, $wxname);
$app->broadcasting->previewVoiceByName($mediaId, $wxname);
$app->broadcasting->previewImageByName($mediaId, $wxname);
$app->broadcasting->previewVideoByName($message, $wxname);
$app->broadcasting->previewCardByName($cardId, $wxname);
2.8.1.8 删除群发消息
$app->broadcasting->delete($msgId);
2.8.1.9 查询群发消息发送状态
$app->broadcasting->status($msgId);

2.9 模板消息

模板消息仅用于公众号向用户发送重要的服务通知,只能用于符合其要求的服务场景中,如信用卡刷卡通知,商品购买成功通知等。不支持广告等营销类消息及其它所有可能对用户造成骚扰的消息。

2.9.1 修改账号所属行业

$app->template_message->setIndustry($industryId1, $industryId2);

2.9.2 获取支持的行业列表

$app->template_message->getIndustry();

2.9.3 添加模板

在公众号后台获取 $shortId 并添加到账户。

$app->template_message->addTemplate($shortId);

2.9.4 获取所有模板列表

$app->template_message->getPrivateTemplates();

2.9.5 删除模板

$app->template_message->deletePrivateTemplate($templateId);

2.9.6 发送模板消息

$app->template_message->send([
        'touser' => 'user-openid',
        'template_id' => 'template-id',
        'url' => 'https://easywechat.org',
        'miniprogram' => [
                'appid' => 'xxxxxxx',
                'pagepath' => 'pages/xxx',
        ],
        'data' => [
            'key1' => 'VALUE',
            'key2' => 'VALUE2',
            ...
        ],
    ]);

如果 url 和 miniprogram 字段都传,会优先跳转小程序。

2.9.7 发送一次性订阅消息

$app->template_message->sendSubscription([
        'touser' => 'user-openid',
        'template_id' => 'template-id',
        'url' => 'https://easywechat.org',
        'scene' => 1000,
        'data' => [
            'key1' => 'VALUE',
            'key2' => 'VALUE2',
            ...
        ],
    ]);

如果想为发送的内容字段指定颜色,可将 “data” 部分写成下面 4 种不同样式,不写 color 将默认黑色:

'data' => [
    'foo' => '你好',  // 不需要指定颜色
    'bar' => ['你好', '#F00'], // 指定为红色
    'baz' => ['value' => '你好', 'color' => '#550038'], // 与第二种一样
    'zoo' => ['value' => '你好'], // 与第一种一样
]

2.10 用户

用户信息的获取是微信开发中较常用的功能,以下所有的用户信息的获取与更新,都基于微信的 openid ,且是已关注当前账号,其它情况可能无法使用。

2.10.1 获取用户信息

获取单个:

$user = $app->user->get($openId);

获取多个:

$users = $app->user->select([$openId1, $openId2, ...]);

2.10.2 获取用户列表

$app->user->list($nextOpenId = null);  // $nextOpenId 可选

示例:

 $users = $app->user->list();

// result
 {
  "total": 2,
  "count": 2,
  "data": {
    "openid": [
      "OPENID1",
      "OPENID2"
    ]
  },
  "next_openid": "NEXT_OPENID"
}

2.10.3 修改用户备注

$app->user->remark($openId, $remark); // 成功返回boolean

示例:

$app->user->remark($openId, "僵尸粉");

2.10.4 拉黑用户

$app->user->block('openidxxxxx');
// 或多个用户
$app->user->block(['openid1', 'openid2', 'openid3', ...]);

2.10.5 取消拉黑用户

$app->user->unblock('openidxxxxx');
// 或多个用户
$app->user->unblock(['openid1', 'openid2', 'openid3', ...]);

2.10.6 获取黑名单

$app->user->blacklist($beginOpenid = null); // $beginOpenid 可选

2.10.7 账号迁移 openid 转换

账号迁移从这里了解:https://kf.qq.com/product/weixinmp.html#hid=2488

微信用户关注不同的公众号,对应 OpenID 不一样,迁移成功后,粉丝的 OpenID 以目标帐号(即新公众号)对应的 OpenID 为准。但开发者可通过开发接口转换 OpenID,开发文档参考: 提供个 openid 转换的 API 接口,当帐号迁移后,可通过该接口:

  1. 将原帐号粉丝的 openid 转换为新帐号的 openid。
  2. 将有授权关系用户的 openid 转换为新帐号的 openid。
  3. 将卡券关联用户的 openid 转换为新帐号的 openid。

原帐号:准备迁移的帐号,当审核完成且管理员确认后即被回收。

新帐号:接纳粉丝的帐号。新帐号在整个流程中均能正常使用。

一定要按照下面的步骤操作。

  1. 一定要在原帐号被冻结前,最好准备提交审核前,获取原帐号的用户列表。如果没有原帐号的用户列表,用不了转换工具。如果原账号被回收,这时也没办法调用接口获取用户列表。

    {info} 如何获取用户列表见这里:https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421140840

  2. 转换 openid 的 API 接口如下,可在帐号迁移审核完成后开始调用,并最多保留15天。若帐号迁移没完成,调用时无返回结果或报错。帐号迁移15天后,该转换接口将会失效、无法拉取到数据。

    $app->user->changeOpenid($oldAppId, $openidList);
    

返回值样例:

{
   "errcode":0,
   "errmsg":"ok",
   "result_list":[
      {
         "ori_openid":"oEmYbwN-n24jxvk4Sox81qedINkQ",
         "new_openid":"o2FwqwI9xCsVadFah_HtpPfaR-X4",
         "err_msg":"ok"
      },
      {
         "ori_openid":"oEmYbwH9uVd4RKJk7ZZg6SzL6tTo",
         "err_msg":"ori_openid error"
      }
   ]
}

2.11 用户标签

2.11.1 获取所有标签

$app->user_tag->list();

示例:

$tags = $app->user_tag->list();

// {
//     "tags": [
//         {
//             "id": 0,
//             "name": "标签1",
//             "count": 72596
//         },
//         {
//             "id": 1,
//             "name": "标签2",
//             "count": 36
//         },
//         ...
//     ]
// }

2.11.2 创建标签

$app->user_tag->create($name);

示例:

$app->user_tag->create('测试标签');

2.11.3 修改标签信息

$app->user_tag->update($tagId, $name);

示例:

$app->user_tag->update(12, "新的名称");

2.11.4 删除标签

$app->user_tag->delete($tagId);

2.11.5 获取指定 openid 用户所属的标签

$userTags = $app->user_tag->userTags($openId);

// {
//     "tagid_list":["标签1","标签2"]
// }

2.11.6 获取标签下用户列表

$app->user_tag->usersOfTag($tagId, $nextOpenId = '');
// $nextOpenId:第一个拉取的OPENID,不填默认从头开始拉取

// {
//   "count":2, // 这次获取的粉丝数量
//   "data":{ // 粉丝列表
//      "openid":[
//          "ocYxcuAEy30bX0NXmGn4ypqx3tI0",
//          "ocYxcuBt0mRugKZ7tGAHPnUaOW7Y"
//      ]
//   },
//   "next_openid":"ocYxcuBt0mRugKZ7tGAHPnUaOW7Y"//拉取列表最后一个用户的openid
// }

2.11.7 批量为用户添加标签

$openIds = [$openId1, $openId2, ...];
$app->user_tag->tagUsers($openIds, $tagId);

2.11.8 批量为用户移除标签

$openIds = [$openId1, $openId2, ...];
$app->user_tag->untagUsers($openIds, $tagId);

2.12 网页授权

2.12.1 关于 OAuth2.0

OAuth是个关于授权(authorization)的开放网络标准,在全世界得到广泛应用,目前版本是2.0版。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存直接上传(img-xvHNyPrS-1601215335631)(https://user-images.githubusercontent.com/1472352/29310178-5a7a91cc-81df-11e7-9468-b66e150bfba1.png)]

步骤解释:

(A)用户打开客户端以后,客户端要求用户给予授权。
(B)用户同意给予客户端授权。
(C)客户端使用上一步获得的授权,向认证服务器申请令牌。
(D)认证服务器对客户端进行认证以后,确认无误,同意发放令牌。
(E)客户端使用令牌,向资源服务器申请获取资源。
(F)资源服务器确认令牌无误,同意向客户端开放资源。

关于 OAuth 协议,请参考 Google 相关资料

2.12.2 微信 OAuth

微信的 OAuth 有两种:公众平台网页授权获取用户信息、开放平台网页登录。

它们区别有两处,授权地址不同,scope 不同。

公众平台网页授权获取用户信息 授权 URL: https://open.weixin.qq.com/connect/oauth2/authorize Scopes: snsapi_basesnsapi_userinfo

开放平台网页登录 授权 URL: https://open.weixin.qq.com/connect/qrconnect Scopes: snsapi_login

他们的逻辑都一样:

  1. 用户尝试访问个业务页面,如: /user/profile
  2. 如果用户已登录,则正常显示该页面
  3. 系统检查当前访问的用户未登录(从 session 或其它方式检查),则跳转到微信授权服务器(上面两种中一种授权 URL ),并告知微信授权服务器的回调URL(redirect_uri=callback.php),此时用户看到蓝色的授权确认页面(scopesnsapi_base 时不显示)
  4. 用户点击确定完成授权,浏览器跳到回调URL: callback.php 并带上 code?code=CODE&state=STATE
  5. callback.php 得到 code 后,通过 code 再次向微信服务器请求得到 网页授权 access_tokenopenid
  6. 可选择拿 openid 去请求 API 得到用户信息(可选)
  7. 将用户信息写入 SESSION。
  8. 跳转到第 3 步写入的 target_url 页面(/user/profile)。

看懵了?没事,使用 SDK,你不用管这么多。

注意,上面第3步:redirect_uri=callback.php在 callback.php 后会带上授权目标页面 user/profile,所以完整的 redirect_uri 如下:'redirect_uri='.urlencode('callback.php?target=user/profile') 结果:redirect_uri=callback.php%3Ftarget%3Duser%2Fprofile

2.12.3 逻辑组成

从上面描述的授权流程来看,至少有3个页面:

  1. 业务页面,需要授权才能访问的页面。
  2. 发起授权页,此页面其实可省略,可做成个中间件,全局检查未登录就发起授权。
  3. 授权回调页,接收用户授权后的状态,并获取用户信息,写入用户会话状态(SESSION)。

2.12.4 开始之前

在开始前一定要记住,先登录公众号后台,找到边栏 “开发” 模块下的 “接口权限”,点击 “网页授权获取用户基本信息” 后的修改,添加网页授权域名。

如果授权地址为:http://www.abc.com/xxxxx,那请填写 www.abc.com,即请填写与网址匹配的域名,前者如果填写 abc.com 是通过不了的。

2.12.5 SDK 中 OAuth 模块的 API

在 SDK 中,用 oauth 模块来完成授权服务,主要用到以下两个 API:

2.12.5.1 发起授权
$response = $app->oauth->scopes(['snsapi_userinfo'])
                          ->redirect();

当应用是分布式架构且没有会话保持时,需自行设置请求对象以实现会话共享。如在 Laravel 框架中支持Session储存在Redis中,需这样:

$response = $app->oauth->scopes(['snsapi_userinfo'])
                          ->setRequest($request)
                          ->redirect();

//回调后获取user时也要设置$request对象
//$user = $app->oauth->setRequest($request)->user();

当然也可在发起授权时指定回调URL,如设置回调URL为当前页面:

$response = $app->oauth->scopes(['snsapi_userinfo'])
                          ->redirect($request->fullUrl());

它的返回值 $response 是个 Symfony\Component\HttpFoundation\RedirectResponse 实例。

可选择在框架中做些正确响应,如在 Laravel 框架中控制器方法是要求返回响应值的:

return $response;

在有的框架 (如yii2) 中是直接 echo$this->display() 时,就直接:

$response->send(); // Laravel 里请使用:return $response;
2.12.5.2 获取已授权用户
$user = $app->oauth->user();
// $user 可以用的方法:
// $user->getId();  // 对应微信的 OPENID
// $user->getNickname(); // 对应微信的 nickname
// $user->getName(); // 对应微信的 nickname
// $user->getAvatar(); // 头像网址
// $user->getOriginal(); // 原始API返回的结果
// $user->getToken(); // access_token, 比如用于地址共享时使用

$user 是 Overtrue\Socialite\User 对象,可从该对象拿到更多的信息。

注意:$user 里没有 openid$user->idopenid. 如果想拿微信返回的原样信息,请用:$user->getOriginal();

scopesnsapi_base$oauth->user(); 对象里只有 id

2.12.6 网页授权实例

这里用原生 PHP 举例,oauth_callback 是授权回调URL (未urlencode编码的URL), user/profile 是需授权才能访问的页面,PHP 代码如下:

// http://easywechat.org/user/profile


use EasyWeChat\Factory;

$config = [
  // ...
  'oauth' => [
      'scopes'   => ['snsapi_userinfo'],
      'callback' => '/oauth_callback',
  ],
  // ..
];

$app = Factory::officialAccount($config);
$oauth = $app->oauth;

// 未登录
if (empty($_SESSION['wechat_user'])) {
  $_SESSION['target_url'] = 'user/profile';
  return $oauth->redirect();
  // 这里不一定return,如果框架action不是返回内容就得用 $oauth->redirect()->send();
}

// 已登录过
$user = $_SESSION['wechat_user'];

授权回调页:

// http://easywechat.org/oauth_callback


use EasyWeChat\Factory;

$config = [
  // ...
];

$app = Factory::officialAccount($config);
$oauth = $app->oauth;

// 获取 OAuth 授权结果用户信息
$user = $oauth->user();
$_SESSION['wechat_user'] = $user->toArray();
$targetUrl = empty($_SESSION['target_url']) ? '/' : $_SESSION['target_url'];

header('location:'. $targetUrl); // 跳转到 user/profile

上面例子都是基于 $_SESSION 保持会话,在微信客户端中,可结合 COOKIE 存储,但有效期平台不一样时间也不一样,Android 失效会快一些,不过基本也够用了。

2.13 JSSDK

微信 JSSDK 官方文档:https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421141115

2.13.1 API

2.13.1.1 获取JSSDK的配置数组
$app->jssdk->buildConfig(array $APIs, $debug = false, $beta = false, $json = true);

默认返回 JSON 字符串,当 $jsonfalse 时返回数组,可直接用到网页中

2.13.1.2 设置当前URL
$app->jssdk->setUrl($url)

如果不想用默认读取的URL,可用此方法手动设置,通常不需要。

示例

//可生成js配置文件:
<script src="https://res.wx.qq.com/open/js/jweixin-1.4.0.js" type="text/javascript" charset="utf-8"></script>
<script type="text/javascript" charset="utf-8">
    wx.config(<?php echo $app->jssdk->buildConfig(array('updateAppMessageShareData', 'updateTimelineShareData'), true) ?>);
</script>

结果如下:

<script src="https://res.wx.qq.com/open/js/jweixin-1.4.0.js" type="text/javascript" charset="utf-8"></script>
<script type="text/javascript" charset="utf-8">
wx.config({
    debug: true, // 请在上线前删除它
    appId: 'wx3cf0f39249eb0e60',
    timestamp: 1430009304,
    nonceStr: 'qey94m021ik',
    signature: '4F76593A4245644FAE4E1BC940F6422A0C3EC03E',
    jsApiList: ['updateAppMessageShareData', 'updateTimelineShareData']
});
</script>

2.14 临时素材

上传的临时多媒体文件有格式和大小限制,如下:

图片(image): 2M,支持 JPG 格式

语音(voice):2M,播放长度不超过 60s,支持 AMR\MP3 格式

视频(video):10MB,支持 MP4 格式

缩略图(thumb):64KB,支持 JPG 格式

2.14.1 上传图片

注意:微信图片上传服务有敏感检测系统,图片内容如含有敏感内容,如色情,商品推广,虚假信息等,上传可能失败。

$app->media->uploadImage($path);

2.14.2 上传声音

$app->media->uploadVoice($path);

2.14.3 上传视频

$app->media->uploadVideo($path, $title, $description);

2.14.4 上传缩略图

用于视频封面或音乐封面。

$app->media->uploadThumb($path);

2.14.5 上传群发视频

上传视频获取 media_id 用以创建群发消息用。

$app->media->uploadVideoForBroadcasting($path, $title, $description);

//{
//  "media_id": "rF4UdIMfYK3efUfyoddYRMU50zMiRmmt_l0kszupYh_SzrcW5Gaheq05p_lHuOTQ",
//  "title": "TITLE",
//  "description": "Description"
//}

2.14.6 创建群发消息

不要与 上传群发视频 搞混了,上面是上传视频得到 media_id,这个是用该 media_id 加标题描述 创建条消息素材 发送给用户。详情参见:消息群发

$app->media->createVideoForBroadcasting($mediaId, $title, $description);

//{
//  "type":"video",
//  "media_id":"IhdaAQXuvJtGzwwc0abfXnzeezfO0NgPK6AQYShD8RQYMTtfzbLdBIQkQziv2XJc",
//  "created_at":1398848981
//}

2.14.7 获取临时素材内容

如图片、语音等二进制流内容,响应为 EasyWeChat\Kernel\Http\StreamResponse 实例。

$stream = $app->media->get($mediaId);

if ($stream instanceof \EasyWeChat\Kernel\Http\StreamResponse) {
  // 以内容 md5 为文件名存到本地
  $stream->save('保存目录');

  // 自定义文件名,不需要带后缀
  $stream->saveAs('保存目录', '文件名');
}

2.14.8 获取 JSSDK 上传的高清语音

$stream = $app->media->getJssdkMedia($mediaId);
$stream->saveAs('保存目录', 'custom-name.speex');

2.15 二维码

目前有 2 种类型的二维码:

  1. 临时二维码,有过期时间,最长可设置为在二维码生成后的 30天后过期,但能生成较多数量。临时二维码主要用于帐号绑定等不要求二维码永久保存的业务场景
  2. 永久二维码,是无过期时间的,但数量较少(目前最多10万个)。永久二维码主要用于适用于帐号绑定、用户来源统计等场景。

2.15.1 创建临时二维码

$result = $app->qrcode->temporary('foo', 6 * 24 * 3600);

// Array
// (
//     [ticket] => gQFD8TwAAAAAAAAAAS5odHRwOi8vd2VpeGluLnFxLmNvbS9xLzAyTmFjVTRWU3ViUE8xR1N4ajFwMWsAAgS2uItZAwQA6QcA
//     [expire_seconds] => 518400
//     [url] => http://weixin.qq.com/q/02NacU4VSubPO1GSxj1p1k
// )

2.15.2 创建永久二维码

$result = $app->qrcode->forever(56);// 或者 $app->qrcode->forever("foo");
// Array
// (
//     [ticket] => gQFD8TwAAAAAAAAAAS5odHRwOi8vd2VpeGluLnFxLmNvbS9xLzAyTmFjVTRWU3ViUE8xR1N4ajFwMWsAAgS2uItZAwQA6QcA
//     [url] => http://weixin.qq.com/q/02NacU4VSubPO1GSxj1p1k
// )

2.15.3 获取二维码网址

$url = $app->qrcode->url($ticket);
// https://api.weixin.qq.com/cgi-bin/showqrcode?ticket=TICKET

2.15.4 获取二维码内容

$url = $app->qrcode->url($ticket);
$content = file_get_contents($url); // 得到二进制图片内容
file_put_contents(__DIR__ . '/code.jpg', $content); //写文件

2.16 短网址服务

使用场景: 开发者用于生成二维码的原链接(商品、支付二维码等)太长导致扫码速度和成功率下降,将原长链接通过此接口转成短链接再生成二维码将大大提升扫码速度和成功率。

2.16.1 长链接转短链接

$shortUrl = $app->url->shorten('https://easywechat.com');
//
(
    [errcode] => 0
    [errmsg] => ok
    [short_url] => https://w.url.cn/s/Aq7jWrd
)

2.17 素材管理

微信里的图片,音乐,视频等都需先上传到微信服务器作为素材才可在消息中使用。

2.17.1 上传图片

注意:微信图片上传服务有敏感检测系统,图片内容如果含有敏感内容,如色情,商品推广,虚假信息等,上传可能失败。

$result = $app->material->uploadImage("/path/to/your/image.jpg");
// {
//    "media_id":MEDIA_ID,
//    "url":URL
// }

url 只有上传图片素材有返回值。

2.17.2 上传语音

语音 大小不超 5M长度不超 60 秒,支持 mp3/wma/wav/amr 格式。

$result = $app->material->uploadVoice("/path/to/your/voice.mp3");
// {
//    "media_id":MEDIA_ID,
// }

2.17.3 上传视频

$result = $app->material->uploadVideo("/path/to/your/video.mp4", "视频标题", "视频描述");
// {
//    "media_id":MEDIA_ID,
// }

2.17.4 上传缩略图

用于视频封面或者音乐封面。

$result = $app->material->uploadThumb("/path/to/your/thumb.jpg");
// {
//    "media_id":MEDIA_ID,
// }

2.17.5 上传图文消息

use EasyWeChat\Kernel\Messages\Article;

// 上传单篇图文
$article = new Article([
    'title' => 'xxx',
    'thumb_media_id' => $mediaId,
    //...
  ]);
$app->material->uploadArticle($article);

// 或多篇图文
$app->material->uploadArticle([$article, $article2, ...]);

2.17.6 修改图文消息

有三个参数:

  • $mediaId 更新文章的 mediaId
  • $article 文章内容,Article 实例或 全字段数组
  • $index 要更新的文章在图文消息中的位置(多图文消息时,此字段才有意义,单图片忽略此参数),第一篇为 0;
$result = $app->material->updateArticle($mediaId, new Article(...));

// or
$result = $app->material->updateArticle($mediaId, [
   'title' => 'EasyWeChat 4.0 发布了!',
    'thumb_media_id' => 'qQFxUQGO21Li4YrSn3MhnrqtRp9Zi3cbM9uBsepvDmE', // 封面图 mediaId
    'author' => 'overtrue', // 作者
    'show_cover' => 1, // 是否在文章内容显示封面图片
    'digest' => '这里是文章摘要',
    'content' => '这里是文章内容,你可以放很长的内容',
    'source_url' => 'https://www.easywechat.com',
  ]);

// 指定更新多图文中的第 2 篇
$result = $app->material->updateArticle($mediaId, new Article(...), 1); // 第 2 篇

2.17.7 上传图文消息图片

返回值中 url 是上传图片的 URL,可用于后续群发中,放置到图文消息中。

$result = $app->material->uploadArticleImage($path);
//{
//    "url":  "http://mmbiz.qpic.cn/mmbiz/gLO17UPS6FS2xsypf378iaNhWacZ1G1UplZYWEYfwvuU6Ont96b1roYsCNFwaRrSaKTPCUdBK9DgEHicsKwWCBRQ/0"
//}

2.17.8 获取永久素材

$resource = $app->material->get($mediaId);

如果请求的素材为图文消息,则响应如下:

{
 "news_item": [
       {
       "title":TITLE,
       "thumb_media_id"::THUMB_MEDIA_ID,
       "show_cover_pic":SHOW_COVER_PIC(0/1),
       "author":AUTHOR,
       "digest":DIGEST,
       "content":CONTENT,
       "url":URL,
       "content_source_url":CONTENT_SOURCE_URL
       },
       //多图文消息有多篇文章
    ]
  }

如果返回的是视频消息素材,则内容如下:

{
  "title":TITLE,
  "description":DESCRIPTION,
  "down_url":DOWN_URL,
}

其他类型的素材消息,则响应为 EasyWeChat\Kernel\Http\StreamResponse 实例,开发者可自行保存为文件。如

$stream = $app->material->get($mediaId);

if ($stream instanceof \EasyWeChat\Kernel\Http\StreamResponse) {
    // 以内容 md5 为文件名
    $stream->save('保存目录');
    // 自定义文件名,不需要带后缀
    $stream->saveAs('保存目录', '文件名');
}

2.17.9 获取永久素材列表

  • $type 素材的类型,图片(image)、视频(video)、语音 (voice)、图文(news
  • $offset 从全部素材的该偏移位置开始返回,可选,默认 0,0 表示从第一个素材 返回
  • $count 返回素材的数量,可选,默认 20, 取值在 1 到 20 间
$app->material->list($type, $offset, $count);

示例:

$list = $app->material->list('image', 0, 10);

图片、语音、视频 等类型的返回如下

{
   "total_count": TOTAL_COUNT,
   "item_count": ITEM_COUNT,
   "item": [{
       "media_id": MEDIA_ID,
       "name": NAME,
       "update_time": UPDATE_TIME,
       "url":URL
   },
   //可能会有多个素材
   ]
}

永久图文消息素材列表的响应如下:

{
   "total_count": TOTAL_COUNT,
   "item_count": ITEM_COUNT,
   "item": [{
       "media_id": MEDIA_ID,
       "content": {
           "news_item": [{
               "title": TITLE,
               "thumb_media_id": THUMB_MEDIA_ID,
               "show_cover_pic": SHOW_COVER_PIC(0 / 1),
               "author": AUTHOR,
               "digest": DIGEST,
               "content": CONTENT,
               "url": URL,
               "content_source_url": CONTETN_SOURCE_URL
           },
           //多图文消息会在此处有多篇文章
           ]
        },
        "update_time": UPDATE_TIME
    },
    //可能有多个图文消息item结构
  ]
}

2.17.10 获取素材计数

$stats = $app->material->stats();

// {
//   "voice_count":COUNT,
//   "video_count":COUNT,
//   "image_count":COUNT,
//   "news_count":COUNT
// }

2.17.11 删除永久素材;

$app->material->delete($mediaId);

2.17.12 文章预览

文章预览请参阅 “消息群发” 章节。

2.18 自定义菜单

2.18.1 读取(查询)已设置菜单

$list = $app->menu->list();

2.18.2 获取当前菜单

$current = $app->menu->current();

2.18.3 添加菜单

2.18.3.1 添加普通菜单
$buttons = [
    [
        "type" => "click",
        "name" => "今日歌曲",
        "key"  => "V1001_TODAY_MUSIC"
    ],
    [
        "name"       => "菜单",
        "sub_button" => [
            [
                "type" => "view",
                "name" => "搜索",
                "url"  => "http://www.soso.com/"
            ],
            [
                "type" => "view",
                "name" => "视频",
                "url"  => "http://v.qq.com/"
            ],
            [
                "type" => "click",
                "name" => "赞一下我们",
                "key" => "V1001_GOOD"
            ],
        ],
    ],
];
$app->menu->create($buttons);

以上会创建一个普通菜单。

2.18.3.2 添加个性化菜单

与普通菜单不同,需在 create() 方法中将个性化匹配规则作为第二个参数:

$buttons = [
    // ...
];
$matchRule = [
    "tag_id" => "2",
    "sex" => "1",
    "country" => "中国",
    "province" => "广东",
    "city" => "广州",
    "client_platform_type" => "2",
    "language" => "zh_CN"
];
$app->menu->create($buttons, $matchRule);

2.18.4 删除菜单

有两种删除方式,一种是全部删除,另一种是根据菜单 ID 来删除(删除个性化菜单时用,ID 从查询接口获取):

$app->menu->delete(); // 全部
$app->menu->delete($menuId);

2.18.5 测试个性化菜单

$app->menu->match($userId);

$userId 可是粉丝的 OpenID,也可是粉丝微信号。

返回 $menu 与指定的 $userId 匹配的菜单项。

2.19 卡券

2.19.1 获取实例

$card = $app->card;

2.19.2 通用功能

2.19.2.1 获取卡券颜色
$card->colors();
2.19.2.2 卡券开放类目查询
$card->categories();
2.19.2.3 创建卡券

创建卡券接口,用于创建新卡券,获取card_id,创建成功并通过审核后,商家可通过接口将卡券下发给用户,每次成功领取,库存数量相应扣除。

$card->create($cardType = 'member_card', array $attributes);
  • attributes array 卡券信息

示例:



    $cardType = 'GROUPON';

    $attributes = [
      'base_info' => [
          'brand_name' => '微信餐厅',
          'code_type' => 'CODE_TYPE_TEXT',
          'title' => '132元双人火锅套餐',
          //...
      ],
      'advanced_info' => [
          'use_condition' => [
              'accept_category' => '鞋类',
              'reject_category' => '阿迪达斯',
              'can_use_with_other_discount' => true,
          ],
          //...
      ],
    ];

$result = $card->create($cardType, $attributes);
2.19.2.4 获取卡券详情
$cardInfo = $card->get($cardId);
2.19.2.5 批量查询卡列表
$card->list($offset = 0, $count = 10, $statusList = 'CARD_STATUS_VERIFY_OK');

offset int - 查询卡列表的起始偏移量,从0开始

count int - 需要查询的卡片的数量

statusList - 支持开发者拉出指定状态的卡券列表,详见 example

示例:

// CARD_STATUS_NOT_VERIFY, 待审核;
// CARD_STATUS_VERIFY_FAIL, 审核失败;
// CARD_STATUS_VERIFY_OK, 通过审核;
// CARD_STATUS_USER_DELETE,卡券被商户删除;
// CARD_STATUS_DISPATCH,在公众平台投放过的卡券;

$result = $card->list($offset, $count, 'CARD_STATUS_NOT_VERIFY');
2.19.2.6 更改卡券信息接口

支持更新所有卡券类型的部分通用字段及特殊卡券中特定字段的信息。

$card->update($cardId, $type, $attributes = []);

type string - 卡券类型

示例:

$cardId = 'pdkJ9uCzKWebwgNjxosee0ZuO3Os';

$type = 'groupon';

$attributes = [
  'base_info' => [
    'logo_url' => 'http://mmbiz.qpic.cn/mmbiz/2aJY6aCPatSeibYAyy7yct9zJXL9WsNVL4JdkTbBr184gNWS6nibcA75Hia9CqxicsqjYiaw2xuxYZiaibkmORS2oovdg/0',
    'center_title' => '顶部居中按钮',
    'center_sub_title' => '按钮下方的wording',
    'center_url' => 'http://www.easywechat.com',
    'custom_url_name' => '立即使用',
    'custom_url' => 'http://www.qq.com',
    'custom_url_sub_title' => '6个汉字tips',
    'promotion_url_name' => '更多优惠',
    'promotion_url' => 'http://www.qq.com',
  ],
  //...
];

$result = $card->update($cardId, $type, $attributes);
2.19.2.7 删除卡券
$card->delete($cardId);
2.19.2.8 创建二维码

开发者可调用该接口生成一张卡券二维码供用户扫码后添加卡券到卡包。

自定义 Code 码的卡券调用接口时,POST 数据需指定 code,非自定义 code 不需指定,指定 openid 同理。指定后的二维码只能被用户扫描领取一次。

$card->createQrCode($cards);

cards array - 卡券相关信息

示例:

// 领取单张卡券
$cards = [
    'action_name' => 'QR_CARD',
    'expire_seconds' => 1800,
    'action_info' => [
      'card' => [
        'card_id' => 'pdkJ9uFS2WWCFfbbEfsAzrzizVyY',
        'is_unique_code' => false,
        'outer_id' => 1,
      ],
    ],
  ];

$result = $card->createQrCode($cards);
// 领取多张卡券
$cards = [
    'action_name' => 'QR_MULTIPLE_CARD',
    'action_info' => [
      'multiple_card' => [
        'card_list' => [
          ['card_id' => 'pdkJ9uFS2WWCFfbbEfsAzrzizVyY'],
        ],
      ],
    ],
  ];

$result = $card->createQrCode($cards);

请求成功返回值示例:

{
 "errcode": 0,
 "errmsg": "ok",
 "ticket": "gQHB8DoAAAAAAAAAASxodHRwOi8vd2VpeGluLnFxLmNvbS9xL0JIV3lhX3psZmlvSDZmWGVMMTZvAAIEsNnKVQMEIAMAAA==",//获取ticket后需调用换取二维码接口获取二维码图片,详情见字段说明。
 "expire_seconds": 1800,
 "url": "http://weixin.qq.com/q/BHWya_zlfioH6fXeL16o ",
 "show_qrcode_url": "https://mp.weixin.qq.com/cgi-bin/showqrcode?  ticket=gQH98DoAAAAAAAAAASxodHRwOi8vd2VpeGluLnFxLmNvbS9xL0czVzRlSWpsamlyM2plWTNKVktvAAIE6SfgVQMEgDPhAQ%3D%3D"
 }
2.19.2.9 ticket 换取二维码图片

获取二维码 ticket 后,开发者可用 ticket 换取二维码图片。

$card->getQrCode($ticket);

ticket string> - 获取的二维码 ticket,凭借此 ticket 可在有效时间内换取二维码。

示例:

$ticket = 'gQFF8DoAAAAAAAAAASxodHRwOi8vd2VpeGluLnFxLmNvbS9xL01VTzN0T0hsS1BwUlBBYUszbVN5AAIEughxVwMEAKd2AA==';
$result = $card->getQrCode($ticket);
2.19.2.10 ticket 换取二维码链接
$card->getQrCodeUrl($ticket);

示例:

$ticket = 'gQFF8DoAAAAAAAAAASxodHRwOi8vd2VpeGluLnFxLmNvbS9xL01VTzN0T0hsS1BwUlBBYUszbVN5AAIEughxVwMEAKd2AA==';
$card->getQrCodeUrl($ticket);
2.19.2.11 创建货架接口

开发者需调用该接口创建货架链接,用于卡券投放。创建货架时需填写投放路径的场景字段。

$card->createLandingPage($banner, $pageTitle, $canShare, $scene, $cards);
  • banner string -页面的 banner 图;
  • pageTitle string - 页面的 title
  • canShare bool - 页面是不是可以分享,true 或 false
  • scene string - 投放页面的场景值,具体请参考下面的 example
  • cards array - 卡券列表,每个元素有两个字段

示例:

$banner = 'http://mmbiz.qpic.cn/mmbiz/iaL1LJM1mF9aRKPZJkmG8xXhiaHqkKSVMMWeN3hLut7X7hicFN';
$pageTitle = '惠城优惠大派送';
$canShare  = true;

//SCENE_NEAR_BY          附近
//SCENE_MENU             自定义菜单
//SCENE_QRCODE             二维码
//SCENE_ARTICLE             公众号文章
//SCENE_H5                 h5页面
//SCENE_IVR                 自动回复
//SCENE_CARD_CUSTOM_CELL 卡券自定义cell
$scene = 'SCENE_NEAR_BY';

$cardList = [
    ['card_id' => 'pdkJ9uLRSbnB3UFEjZAgUxAJrjeY', 'thumb_url' => 'http://test.digilinx.cn/wxApi/Uploads/test.png'],
    ['card_id' => 'pdkJ9uJ37aU-tyRj4_grs8S45k1c', 'thumb_url' => 'http://test.digilinx.cn/wxApi/Uploads/aa.jpg'],
];

$result = $card->createLandingPage($banner, $pageTitle, $canShare, $scene, $cardList);
2.19.2.12 图文消息群发卡券

注意:目前该接口仅支持填入非自定义 code 的卡券,自定义 code 的卡券需先进行 code 导入后调用。

$card->getHtml($cardId);

示例:

$cardId = 'pdkJ9uLCEF_HSKO7JdQOUcZ-PUzo';

$result = $card->getHtml($cardId);
2.19.2.13 设置测试白名单

同时支持“openid”、“username”两种字段设置白名单,总数上限为10个。

$card->setTestWhitelist($openids); // 使用 openid
$card->setTestWhitelistByName($usernames); // 使用 username
  • openids array - 测试的openid列表
  • usernames array> - 测试的微信号列表

示例:

// by openid
$openids   = [$openId, $openId2, $openid3...];
$result = $card->setTestWhitelist($openids);

// by username
$usernames = ['tianye0327', 'iovertrue'];
$result = $card->setTestWhitelistByName($usernames);
2.19.2.14 获取用户已领取卡券接口

获取用户卡包里属于该appid下所有可用卡券,包括正常状态和未生效状态

$card->getUserCards($openid, $cardId);

示例:

$openid  = 'odkJ9uDUz26RY-7DN1mxkznfo9xU';
$cardId = ''; // 卡券ID。不填写时默认查询当前 appid 下的卡券。

$result = $card->getUserCards($openid, $cardId);
2.19.2.15 设置微信买单接口
$card->setPayCell($cardId, $isOpen = true);
  • isOpen string - 是否开启买单功能,填 true/false,默认 true

示例:

$cardId = 'pdkJ9uH7u11R-Tu1kilbaW_zDFow';

$result = $card->setPayCell($cardId); // isOpen = true
$result = $card->setPayCell($cardId, $isOpen);
2.19.2.16 修改库存接口
$card->increaseStock($cardId, $amount); // 增加库存
$card->reductStock($cardId, $amount); // 减少库存
  • cardId string - 卡券 ID
  • amount int - 修改多少库存

示例:

$cardId = 'pdkJ9uLRSbnB3UFEjZAgUxAJrjeY';

$result = $card->increaseStock($cardId, 100);

2.19.3 卡券 Code

2.19.3.1 导入code接口

在自定义code卡券成功创建且通过审核后,必须将自定义code按照与发券方的约定数量调用导入code接口导入微信后台。

$card->code->deposit($cardId, $codes);
  • cardId string - 要导入code的卡券ID
  • codes array - 要导入微信卡券后台的自定义 code,最多100个

示例:

$cardId = 'pdkJ9uLCEF_HSKO7JdQOUcZ-PUzo';
$codes    = ['11111', '22222', '33333'];

$result = $card->code->deposit($cardId, $codes);
2.19.3.2 查询导入code数目
$card->code->getDepositedCount($cardId);  // 要导入 code 的卡券 ID

示例:

$cardId = 'pdkJ9uLCEF_HSKO7JdQOUcZ-PUzo';
$result = $card->code->getDepositedCount($cardId);
2.19.3.3 核查 code 接口

为避免出现导入差错,强烈建议开发者在查询完 code 数目时核查 code 接口校验 code 导入微信后台的情况。

$card->code->check($cardId, $codes);

示例:

$cardId = 'pdkJ9uLCEF_HSKO7JdQOUcZ-PUzo';
$codes = ['807732265476', '22222', '33333'];
$result = $card->code->check($cardId, $codes);
2.19.3.4 查询 Code 接口
$card->code->get($code, $cardId, $checkConsume = true);
  • checkConsume 是否校验code核销状态,true和false

示例:

$code = '736052543512';
$cardId = 'pdkJ9uDgnm0pKfrTb1yV0dFMO_Gk';

$result = $card->code->get($code, $cardId);
$result = $card->code->get($code, $cardId, false); // check_consume = false
2.19.3.5 核销Code接口
$card->code->consume($code);
// 或指定 cardId
$card->code->consume($code, $cardId);

示例:

$code = '789248558333';
$cardId = 'pdkJ9uDmhkLj6l5bm3cq9iteQBck';

$result = $card->code->consume($code);
// 或
$result = $card->code->consume($code, $cardId);
2.19.3.6 Code 解码接口
$card->code->decrypt($encryptedCode);

示例:

$encryptedCode = 'XXIzTtMqCxwOaawoE91+VJdsFmv7b8g0VZIZkqf4GWA60Fzpc8ksZ/5ZZ0DVkXdE';

$result = $card->code->decrypt($encryptedCode);
2.19.3.7 更改 Code 接口
$card->code->update($code, $newCode, $cardId);
  • newCode string - 变更后的有效 Code 码

示例:

$code = '148246271394';
$newCode = '659266965266';
$cardId = '';

$result = $card->code->update($code, $newCode, $cardId);
2.19.3.8 设置卡券失效
$card->code->disable($code, $cardId);

示例:

$code    = '736052543512';
$cardId = '';

$result = $card->code->disable($code, $cardId);

2.19.4 通用卡券

2.19.5 卡券激活

$result = $card->general_card->activate($info);

2.19.6 撤销激活

$result = $card->general_card->deactivate(string $cardId, string $code);

2.19.7 更新用户信息

$result = $card->general_card->updateUser(array $info);

2.19.8 会员卡

2.19.8.1 会员卡激活
$result = $card->member_card->activate($info);
  • info - 需激活的会员卡信息

示例:

$info = [
      'membership_number'        => '357898858', //会员卡编号,由开发者填入,作为序列号显示在用户的卡包里。可与Code码保持等值。
      'code'                     => '916679873278', //创建会员卡时获取的初始code。
      'activate_begin_time'      => '1397577600', //激活后的有效起始时间。若不填写默认以创建时的 data_info 为准。Unix时间戳格式
      'activate_end_time'        => '1422724261', //激活后的有效截至时间。若不填写默认以创建时的 data_info 为准。Unix时间戳格式。
      'init_bonus'               => '持白金会员卡到店消费,可享8折优惠。', //初始积分,不填为0。
      'init_balance'             => '持白金会员卡到店消费,可享8折优惠。', //初始余额,不填为0。
      'init_custom_field_value1' => '白银', //创建时字段custom_field1定义类型的初始值,限制为4个汉字,12字节。
      'init_custom_field_value2' => '9折', //创建时字段custom_field2定义类型的初始值,限制为4个汉字,12字节。
      'init_custom_field_value3' => '200', //创建时字段custom_field3定义类型的初始值,限制为4个汉字,12字节。
];

$result = $card->member_card->activate($info);
2.19.8.2 设置开卡字段
$card->member_card->setActivationForm($cardId, $settings);
  • settings array - 会员卡激活时的选项

示例:

$cardId = 'pdkJ9uJYAyfLXsUCwI2LdH2Pn1AU';

$settings = [
    'required_form' => [
        'common_field_id_list' => [
            'USER_FORM_INFO_FLAG_MOBILE',
            'USER_FORM_INFO_FLAG_LOCATION',
            'USER_FORM_INFO_FLAG_BIRTHDAY',
        ],
        'custom_field_list' => [
            '喜欢的食物',
        ],
    ],
    'optional_form' => [
        'common_field_id_list' => [
            'USER_FORM_INFO_FLAG_EMAIL',
        ],
        'custom_field_list' => [
            '喜欢的食物',
        ],
    ],
];

$result = $card->member_card->setActivationForm($cardId, $settings);
2.19.8.3 拉取会员信息
$card->member_card->getUser($cardId, $code);

示例:

$cardId = 'pbLatjtZ7v1BG_ZnTjbW85GYc_E8';
$code    = '916679873278';

$result = $card->member_card->getUser($cardId, $code);
2.19.8.4 更新会员信息
$card->member_card->updateUser($info);
  • info array - 可更新的会员信息

示例:

$info = [
    'code'                => '916679873278', //卡券Code码。
    'card_id'             => 'pbLatjtZ7v1BG_ZnTjbW85GYc_E8', //卡券ID。
    'record_bonus'        => '消费30元,获得3积分', //商家自定义积分消耗记录,不超过14个汉字。
    'bonus'               => '100', //需要设置的积分全量值,传入的数值会直接显示,如果同时传入add_bonus和bonus,则前者无效。
    'balance'             => '持白金会员卡到店消费,可享8折优惠。', //需要设置的余额全量值,传入的数值会直接显示,如果同时传入add_balance和balance,则前者无效。
    'record_balance'      => '持白金会员卡到店消费,可享8折优惠。', //商家自定义金额消耗记录,不超过14个汉字。
    'custom_field_value1' => '100', //创建时字段custom_field1定义类型的最新数值,限制为4个汉字,12字节。
    'custom_field_value2' => '200', //创建时字段custom_field2定义类型的最新数值,限制为4个汉字,12字节。
    'custom_field_value3' => '300', //创建时字段custom_field3定义类型的最新数值,限制为4个汉字,12字节。
];

$result = $card->member_card->updateUser($info);

2.19.8 子商户

2.19.8.1 添加子商户
$card->sub_merchant->create(array $attributes); 

示例:

$attributes = [
    'brand_name' => 'overtrue',
    'logo_url' => 'http://mmbiz.qpic.cn/mmbiz/iaL1LJM1mF9aRKPZJkmG8xXhiaHqkKSVMMWeN3hLut7X7hicFNjakmxibMLGWpXrEXB33367o7zHN0CwngnQY7zb7g/0',
    'protocol' => 'qIqwTfzAdJ_1-VJFT0fIV53DSY4sZY2WyhkzZzbV498Qgdp-K5HJtZihbHLS0Ys0',
    'end_time' => '1438990559',
    'primary_category_id' => 1,
    'secondary_category_id' => 101,
    'agreement_media_id' => '',
    'operator_media_id' => '',
    'app_id' => '',
];

$result = $card->sub_merchant->create($attributes);
2.19.8.2 更新子商户
$card->sub_merchant->update(int $merchantId, array $info);
  • $merchantId int - 子商户 ID
  • $info array - 参数与创建子商户参数一样

示例:

$info = [
  //...
];
$result = $card->sub_merchant->update('12', $info);

2.19.9 特殊票券

2.19.9.1 机票值机
$card->boarding_pass->checkin(array $params);
2.19.9.2 更新会议门票 - 更新用户
$card->meeting_ticket->updateUser(array $params);
2.19.9.3 更新电影门票 - 更新用户
$card->movie_ticket->updateUser(array $params);

2.19.10 JSAPI

2.19.10.1 卡券批量下发到用户
$cards = [
    ['card_id' => 'pdkJ9uLRSbnB3UFEjZAgUxAJrjeY', 'outer_id' => 2],
    ['card_id' => 'pdkJ9uJ37aU-tyRj4_grs8S45k1c', 'outer_id' => 3],
];
$json = $card->jssdk->assign($cards); // 返回 json 格式

返回 json,在模板里的用法:

wx.addCard({
    cardList: , // 需要打开的卡券列表
    success: function (res) {
        var cardList = res.cardList; // 添加的卡券列表信息
    }
});
2.19.10.2 获取 Ticket
$card->jssdk->getTicket();
// 强制刷新
$card->jssdk->getTicket(true);

2.20 门店

2.20.1 创建门店

用 POI 接口新建门店时所用的图片 url 必须为微信自己域名的 url,因此需先用上传图片接口上传图片并获取 url,再创建门店。上传的图片限制文件大小限制 1MB,支持 JPG 格式,图片接口请参考:临时素材

$app->poi->create($baseInfo);
  • $baseInfo 为门店的基本信息数组

示例:



$info = array(
         "sid"             => "33788392",
         "business_name"   => "麦当劳",
         "branch_name"     => "艺苑路店",
         "province"        => "广东省",
         "city"            => "广州市",
         "district"        => "海珠区",
         "address"         => "艺苑路 11 号",
         "telephone"       => "020-12345678",
         "categories"      => array("美食,快餐小吃"),
         "offset_type"     => 1,
         "longitude"       => 115.32375,
         "latitude"        => 25.097486,
         "photo_list"      => array(
                               array("photo_url" => "https://XXX.com"),
                               array("photo_url" => "https://XXX.com"),
                             ),
         "recommend"       => "麦辣鸡腿堡套餐,麦乐鸡,全家桶",
         "special"         => "免费 wifi,外卖服务",
         "introduction"    => "麦当劳是全球大型跨国连锁餐厅,1940 年创立于美国,在世界上大约拥有 3  万间分店。主要售卖汉堡包,以及薯条、炸鸡、汽水、冰品、沙拉、水果等 快餐食品",
         "open_time"       => "8:00-20:00",
         "avg_price"       => 35,
    );

$result = $app->poi->create($info); // true or exception

注意:新创建的门店在审核通过后,会以事件形式推送给商户填写的回调 URL

2.20.2 获取指定门店信息

$app->poi->get($poiId);
  • $poiId 为门店ID

示例:

$info = $app->poi->get(271262077);

2.20.3 获取门店列表

$app->poi->list($begin, $limit);// begin:0, limit:10
  • $begin 就是查询起点,MySQL 里的 offset
  • $limit 查询条数,同 MySQL 里的 limit

两参数均可选

示例:

$pois = $app->poi->list(0, 2);// 取2条记录
//
//[
//  {
//    "sid": "100",
//    "poi_id": "271864249",
//    "business_name": "麦当劳",
//    "branch_name": "艺苑路店",
//    "address": "艺苑路 11 号",
//    "available_state": 3
//  },
//  {
//    "sid": "101",
//    "business_name": "麦当劳",
//    "branch_name": "赤岗路店",
//    "address": "赤岗路 102 号",
//    "available_state": 4
//  }
//]

2.20.4 修改门店信息

商户可通过该接口,修改门店的服务信息,包括:图片列表、营业时间、推荐、特色服务、简 介、人均价格、电话 7 个字段。目前基础字段包括(名称、坐标、地址等不可修改)。

$app->poi->update($poiId, $data);

$poiId 为门店ID

$data 需更新的部分数据,若有填写内容则为覆盖更新,反之不修改,维持原内容。photo_list 字段为全列表覆盖,若要增加图片,需将之前图片放入 list 中,在其后增加新增图片。如:已有 A、B、C 三张图,又要增加 D、E 两张,则需调 用该接口,photo_list 传入 A、B、C、D、E 五张图片的链接。

示例:

$data = array(
         "telephone" => "020-12345678",
         "recommend" => "麦辣鸡腿堡套餐,麦乐鸡,全家桶",
         //...
        );

$res = $app->poi->update(271262077, $data); //true or exception

2.20.5 删除门店

$app->poi->delete($poiId);

示例:

$app->poi->delete(271262077);// true or exception

2.21 客服

使用客服系统可向用户发送消息及群发消息,客服的管理等功能。

2.21.1 客服管理

2.21.1.1 获取所有客服
$app->customer_service->list();
2.21.1.2 获取所有在线的客服
$app->customer_service->online();
2.21.1.3 添加客服
$app->customer_service->create('foo@test', '客服1');
2.21.1.4 修改客服
$app->customer_service->update('foo@test', '客服1');
2.21.1.5 删除账号
$app->customer_service->delete('foo@test');
2.21.1.6 设置客服头像
$app->customer_service->setAvatar('foo@test', $avatarPath); // $avatarPath 为本地图片路径,非 URL
2.21.1.7 获取客服与客户聊天记录
$app->customer_service->messages($startTime, $endTime, $msgId = 1, $number = 10000);

示例:

$records = $app->customer_service->messages('2015-06-07', '2015-06-21', 1, 20000);
2.21.1.8 主动发送消息给用户
$app->customer_service->message($message)->to($openId)->send();

$message 为消息对象或文本,请参考:消息

示例:

$app->customer_service->message('hello')
                  >  ->to('oV-gpwdOIwSI958m9osAhGBFxxxx')
                  >  ->send();
2.21.1.9 指定客服发送消息
$app->customer_service->message($message)
                      >  ->from('account@test')
                      >  ->to($openId)
                      >  ->send();

$message 为消息对象或文本,请参考:消息

示例:

$app->customer_service->message('hello')
                  >  ->from('kf2001@gh_176331xxxx')
                  >  ->to('oV-gpwdOIwSI958m9osAhGBFxxxx')
                  >  ->send();
2.21.1.10 邀请微信用户加入客服

以账号 foo@test 邀请 微信号 为 xxxx 的微信用户加入客服。

$app->customer_service->invite('foo@test', 'xxxx');

2.21.2 客服会话控制

2.21.2.1 创建会话
$app->customer_service_session->create('test1@test', 'OPENID');
2.21.2.2 关闭会话
$app->customer_service_session->close('test1@test', 'OPENID');
2.21.2.3 获取客户会话状态
$app->customer_service_session->get('OPENID');
2.21.2.4 获取客服会话列表
$app->customer_service_session->list('test1@test');
2.21.2.5 获取未接入会话列表
$app->customer_service_session->waiting();

2.22 摇一摇周边

摇一摇周边是微信在线下的全新功能, 为线下商户提供近距离连接用户的能力, 并支持线下商户向周边用户提供个性化营销、互动及信息推荐等服务。

2.22.1 获取实例

$shakearound = $app->shake_around;

2.22.2 说明

提醒: 1、下述接口调用的方法参数都要严格按照方法参数前的类型传入相应类型的实参,否则会得到非预期的结果。 2、涉及要传入设备id( d e v i c e I d e n t i f i e r ) 的 参 数 时 , 该 参 数 是 个 以 ‘ d e v i c e i d ‘ 或 含 ‘ u u i d ‘ ‘ m a j o r ‘ ‘ m i n o r ‘ 为 k e y 的 关 联 数 组 。 3 、 涉 及 要 传 入 设 备 i d 列 表 ( deviceIdentifier)的参数时,该参数是个以 `device_id` 或含 `uuid` `major` `minor` 为key的关联数组。 3、涉及要传入设备id列表( deviceIdentifierdeviceiduuidmajorminorkey3iddeviceIdentifiers)的参数时,该参数是个二维数组,第一层为索引类型,第二层为关联类型($deviceIdentifier)。

// 参数 $deviceIdentifier 的实参形式:
['device_id' => 10097]
// 或
[
    'uuid' => 'FDA50693-A4E2-4FB1-AFCF-C6EB07647825',
    'major' => 10001,
    'minor' => 12102,
]
// 参数$deviceIdentifiers的实参形式:
[
    ['device_id' => 10097],
    ['device_id' => 10098],
]
// 或
[
    [
        'uuid' => 'FDA50693-A4E2-4FB1-AFCF-C6EB07647825',
        'major' => 10001,
        'minor' => 12102,
    ],
    [
        'uuid' => 'FDA50693-A4E2-4FB1-AFCF-C6EB07647825',
        'major' => 10001,
        'minor' => 12103,
    ]
]

2.22.3 开通摇一摇周边

提示: 若不是做 公众号第三方平台 开发,建议直接在微信管理后台申请开通摇一摇周边功能。

2.22.3.1 申请开通

申请开通摇一摇周边功能。成功提交申请请求后,工作人员会在三个工作日内完成审核。若审核不通过,可重新提交申请请求。若是审核中,请耐心等待工作人员审核,在审核中状态不能再提交申请请求。

方法

$shakearound->register($data)

注意: 1、相关资质文件的图片是使用本页面下方的素材管理的接口上传的,切勿和另一个 素材管理 接口混淆。 2、行业代码请务必传入字符串类型的实参,否则以数字0开头的行业代码将会被当成八进制数处理(将转换为十进制数),这可能不是期望的。

2.22.3.2 查询审核状态

查询已提交的开通摇一摇周边功能申请的审核状态。在申请提交后,工作人员会在三个工作日内完成审核。

方法

$shakearound->status()
2.22.3.3 获取摇一摇的设备及用户信息

获取设备信息,包括UUID、major、minor,以及距离、openID等信息。

方法

$shakearound->user($ticket);
// 或者需要返回门店poi_id
$shakearound->user($ticket, true);

2.22.4 设备管理

2.22.4.1 申请设备 ID

申请配置设备所需的UUID、Major、Minor。申请成功后返回批次ID,可用返回的批次ID通过“查询设备ID申请状态”接口查询目前申请的审核状态。 一个公众账号最多可申请100000个设备ID,如需申请的设备ID数超过最大限额,请邮件至[email protected],邮件格式如下:

标题:申请提升设备ID额度 内容: 1、公众账号名称及appid(wx开头的字符串,在mp平台可查看) 2、用途 3、预估需要多少设备ID

方法

$shakearound->device->apply($data)
2.22.4.2 查询设备 ID 申请审核状态

查询设备ID申请的审核状态。若单次申请的设备ID数量小于等于500个,系统会快速审核;若单次申请的设备ID数量大于500个,则在三日内完成审核。

方法

$shakearound->device->status($applyId) // $applyId 批次ID,申请设备ID时所返回的批次ID
2.22.4.3 编辑设备信息

仅能修改设备的备注信息。

方法

$shakearound->device->update(array $deviceIdentifier, string $comment)

参数

$deviceIdentifier 设备id,设备编号device_id或UUID、major、minor的关联数组,若二者都填,则以设备编号为优先 $comment 设备的备注信息,不超过15个汉字或30个英文字母

示例

$result = $shakearound->device->update(['device_id' => 10011], 'test');
// 或
$result = $shakearound->device->update(['uuid' => 'FDA50693-A4E2-4FB1-AFCF-C6EB07647825',
                                          'major' => 1002,
                                          'minor' => 1223,
], 'test');

/* 返回结果
{
    "data": {
    },
    "errcode": 0,
    "errmsg": "success."
}
*/
var_dump($result['errcode']) // 0
2.22.4.4 配置设备与门店/其他公众账号门店的关联关系

关联本公众账号门店时,支持创建门店后直接关联在设备上,无需为审核通过状态,摇周边后台自动更新门店的最新信息和状态。 关联其他公众账号门店时,支持设备关联其他公众账号的门店,门店需为审核通过状态。

因为第三方门店不归属本公众账号,所以未保存到设备详情中,查询设备列表接口与获取摇周边的设备及用户信息接口不会返回第三方门店。

方法

$shakearound->device->bindPoi(array $deviceIdentifier, $poiId)

//或者 绑定第三方
$shakearound->device->bindThirdPoi(array $deviceIdentifier, $poiId, $poiAppId)

参数

$deviceIdentifier 设备 id,设备编号 device_id 或 UUID、major、minor 的关联数组,若二者都填,则以设备编号为优先 $poiId 设备关联的门店 ID,关联门店后,在门店 1KM 的范围内有优先摇出信息的机会。当值为0时,将清除设备已关联的门店 ID $poiAppId 关联门店所归属的公众账号的 APP ID

示例

// 关联本公众账号门店
$result = $shakearound->device->bindLocation(['device_id' => 10011], 1231);
// 或
$result = $shakearound->device->bindLocation([
  'uuid' => 'FDA50693-A4E2-4FB1-AFCF-C6EB07647825',
  'major' => 1002,
  'minor' => 1223,
], 1231);

// 关联其他公众账号门店
// wxappid 为关联门店所归属的公众账号的 APP ID
$result = $shakearound->device->bindThirdPoi(['device_id' => 10011], 1231, 'wxappid');

// 或
$result = $shakearound->device->bindThirdPoi([
  'uuid' => 'FDA50693-A4E2-4FB1-AFCF-C6EB07647825',
  'major' => 1002,
  'minor' => 1223,
], 1231, 'wxappid');

/* 返回结果
{
    "data": {
    },
    "errcode": 0,
    "errmsg": "success."
}
*/

2.22.5 查询设备列表

查询已有设备 ID、UUID、Major、Minor、激活状态、备注信息、关联门店、关联页面等信息。

2.22.5.1 根据设备id批量取回设备数据

方法

$shakearound->device->listByIds(array $deviceIdentifiers)

参数

$deviceIdentifiers 设备id列表

示例

$result = $shakearound->device->listByIds([
  ['device_id' => 10097],
  ['device_id' => 10098],
]);
// 或
$result = $shakearound->device->listByIds([
  [
    'uuid' => 'FDA50693-A4E2-4FB1-AFCF-C6EB07647825',
   'major' => 10001,
   'minor' => 12102,
  ],
  [
    'uuid' => 'FDA50693-A4E2-4FB1-AFCF-C6EB07647825',
   'major' => 10001,
   'minor' => 12103,
  ]
]);

/* 返回结果
{
    "data": {
        "devices": [
            {
                "comment": "",
                "device_id": 10097,
                "major": 10001,
                "minor": 12102,
                "status": 1,
                "last_active_time":1437276018,
                "poi_id": 0,
                "uuid": "FDA50693-A4E2-4FB1-AFCF-C6EB07647825"
            },
            {
                "comment": "",
                "device_id": 10098,
                "major": 10001,
                "minor": 12103,
                "status": 1,
                "last_active_time":1437276018,
                "poi_appid":"wxe3813f5d8c546fc7"
                "poi_id": 123,
                "uuid": "FDA50693-A4E2-4FB1-AFCF-C6EB07647825"
            }
        ],
        "total_count": 151
    },
    "errcode": 0,
    "errmsg": "success."
}
*/
2.22.5.2 分页批量取回设备数据

方法

$shakearound->device->list(int $lastId, int $count)

参数

$lastId 前一次查询列表末尾的设备编号 device_id,第一次查询 lastId 为 0 $count 待查询的设备数量,不能超50个

示例

$result = $shakearound->device->list(10097, 3);
// 返回结果同上
2.22.5.3 根据申请时的批次 ID 分页批量取回设备数据

方法

$shakearound->device->listByApplyId(int $applyId, int $lastId, int $count)

参数

$applyId 批次ID,申请设备ID时所返回的批次ID $lastId 前一次查询列表末尾的设备编号device_id,第一次查询 lastId 为 0 $count 待查询的设备数量,不能超50个

示例

$result = $shakearound->device->listByApplyId(1231, 10097, 3);
// 返回结果同上

2.22.6 页面管理

2.22.6.1 新增页面

新增摇一摇的页面信息,包括在摇一摇页面的主标题、副标题、图片和点击进去的超链接。图片必为用素材管理接口上传至微信侧服务器后返回的链接。

注意: 图片用本页下方的素材管理的接口上传的,切勿和另一个 素材管理 接口混淆。

方法

$shakearound->page->create($data)

参数

$title 摇一摇页面展示的主标题,不超6个汉字或12个英文字母 $description 摇一摇页面展示的副标题,不超7个汉字或14个英文字母 $pageUrl 点击进去的超链接 $iconUrl 在摇一摇页面展示的图片。图片需先上传至微信侧服务器,用“素材管理-上传图片素材”接口上传图片,返回的图片URL再配置在此处 $comment 可选,页面的备注信息,不超过15个汉字或30个英文字母

示例

$result = $shakearound->page->create($data);

/* 返回结果
{
   "data": {
       "page_id": 28840
   }
   "errcode": 0,
   "errmsg": "success."
}
*/
2.22.6.2 编辑页面信息

编辑摇一摇的页面信息,包括在摇一摇页面出现的主标题、副标题、图片和点击进去的超链接。

方法

$shakearound->page->update(int $pageId, array $data)

参数

$pageId 摇周边页面唯一ID $data 需要更新的信息

示例

$result = $shakearound->page->update(28840, [
    'title' => '主标题',
    'description' => '副标题',
    //...
]);

2.22.7 查询页面列表

查询已有页面,包括在摇一摇页面出现的主标题、副标题、图片和点进去的超链接。

2.22.7.1 根据页面id批量取回页面数据

方法

$shakearound->page->listByIds(array $pageIds)

参数

$pageIds 页面的id列表,索引数组

示例

$result = $shakearound->page->listByIds([28840, 28842]);

/* 返回结果
{
   "data": {
       "pages": [
           {
               "comment": "just for test",
               "description": "test",
               "icon_url": "https://www.baidu.com/img/bd_logo1",
               "page_id": 28840,
               "page_url": "http://xw.qq.com/testapi1",
               "title": "测试1"
           },
           {
               "comment": "just for test",
               "description": "test",
               "icon_url": "https://www.baidu.com/img/bd_logo1",
               "page_id": 28842,
               "page_url": "http://xw.qq.com/testapi2",
               "title": "测试2"
           }
       ],
       "total_count": 2
   },
   "errcode": 0,
   "errmsg": "success."
}
*/
2.22.7.2 分页批量取回页面数据

方法

$shakearound->page->list(int $begin, int $count)

参数

$begin 页面列表的起始索引值 $count 待查询的页面数,不能超50个

示例

$result = $shakearound->page->list(0,2);
// 返回结果同上
2.22.7.3 删除页面

删除已有页面,包括在摇一摇页面的主标题、副标题、图片和点进去的链接。

注意: 只有页面与设备没有关联关系时,才可被删除。

方法

$shakearound->page->delete(int $pageId)

参数

$pageId 页面的id

示例

$result = $shakearound->page->delete(34567);

/* 返回结果
{
    "data": {
    },
    "errcode": 0,
    "errmsg": "success."
}
*/
2.22.7.4 素材管理

上传在摇一摇功能用到的图片素材,素材保存在微信侧服务器上。图片格式限定为:jpg,jpeg,png,gif。 若图片为在摇一摇页面展示的图片,则其素材为 icon 类型的图片,图片大小建议 120px*120 px ,限制不超过 200 px *200 px ,图片需为 正方形 。 若图片为申请开通摇一摇周边功能需要上传的资质文件图片,则其素材为 license 类型的图片,图片的文件大小不超过 2MB ,尺寸不限,形状不限。

方法

$shakearound->material->uploadImage(string $path [, string $type = ‘icon’])

参数

$path 图片所在路径 $type 可选,值为icon或license

示例

$result = $shakearound->material->uploadImage(__DIR__ . '/stubs/image.jpg');

/* 返回结果
{
    "data": {
        "pic_url": http://shp.qpic.cn/wechat_shakearound_pic/0/1428377032e9dd2797018cad79186e03e8c5aec8dc/120"
    },
    "errcode": 0,
    "errmsg": "success."
}
*/

2.22.8 管理设备与页面的关系

通过接口申请的设备ID,需先配置页面,若未配置页面,则摇不出页面信息。

2.22.8.1 配置设备与页面的关联关系

配置完成后,在此设备的信号范围内,即可摇出关联的页面信息。 若设备配置多个页面,则随机出现页面信息。一个设备最多可配置30个关联页面。

注意: 1、配置时传入该设备需关联的页面id列表,该设备原有的关联关系将被直接清除。 2、页面的id列表允许为空(传入空数组),当页面的id列表为空时则会清除该设备的所有关联关系。

方法

$shakearound->relation->bindPage(array $deviceIdentifier, array $pageIds)

参数

$deviceIdentifier 设备id,设备编号device_id或UUID、major、minor的关联数组,若二者都填,则以设备编号为优先 $pageIds 页面的id列表,索引数组

示例

$result = $shakearound->relation->bindPage(['device_id' => 10011], [12345, 23456, 334567]);
// 或
$result = $shakearound->relation->bindPage(['uuid' => 'FDA50693-A4E2-4FB1-AFCF-C6EB07647825', 'major' => 1002, 'minor' => 1223,], [12345, 23456, 334567]);

/* 返回结果
{
    "data": {
    },
    "errcode": 0,
    "errmsg": "success."
}
*/
var_dump($result->errcode) // 0
2.22.8.2 查询设备与页面的关联关系

查询指定设备所关联的页面

根据设备ID或完整UUID、Major、Minor查询该设备关联的所有页面信息

方法

$shakearound->relation->listByDeviceId(array $deviceIdentifier [, boolean $raw = false])

注意: 该方法默认对返回的数据处理后返回一个包含页面id的索引数组。若要返回和 getDeviceByPageId 方法类似的数据,请传入 true 作为第二个参数。

参数

$deviceIdentifier 设备id,设备编号device_id或UUID、major、minor的关联数组,若二者都填,则以设备编号为优先 $raw 可选,当为true时,返回值和getDeviceByPageId方法类似,否则返回页面的id列表(索引数组,无关联时为空数组)

示例

$result = $shakearound->relation->listByDeviceId(['device_id' => 10011]);
// 或
$result = $shakearound->relation->listByDeviceId([
  'uuid' => 'FDA50693-A4E2-4FB1-AFCF-C6EB07647825',
  'major' => 1002,
  'minor' => 1223,
]);

// 返回结果
var_dump($result) // [50054,50055]
查询指定页面所关联的设备

指定页面ID分页查询该页面所关联的所有的设备信息

方法

$shakearound->relation->listByPageId(int $pageId, int $begin, int $count)

参数

$pageId 指定的页面id $begin 关联关系列表的起始索引值 $count 待查询的关联关系数量,不能超过50个

示例

$result = $shakearound->relation->listByPageId(50054, 0, 3);

/* 返回结果
{
  "data": {
      "relations": [
          {
              "device_id": 797994,
              "major": 10001,
              "minor": 10023,
              "page_id": 50054,
              "uuid": "FDA50693-A4E2-4FB1-AFCF-C6EB07647825"
          },
          {
              "device_id": 797995,
              "major": 10001,
              "minor": 10024,
              "page_id": 50054,
              "uuid": "FDA50693-A4E2-4FB1-AFCF-C6EB07647825"
          }
      ],
      "total_count": 2
  },
  "errcode": 0,
  "errmsg": "success."
}
*/
2.22.8.3 摇一摇数据统计

此接口无法获取当天数据,最早只能获取前一天数据。 由于系统在凌晨处理前一天的数据,太早调用此接口可能获取不到数据,建议在早上8:00后调用此接口。

2.22.8.4 以设备为维度的数据统计

查询单个设备进行摇周边操作的人数、次数,点击摇周边消息的人数、次数。

注意: 查询的最长时间跨度为 30 天。只能查询最近 90 天的数据。

方法

$shakearound->stats->deviceSummary(array $deviceIdentifier, int $beginDate, int $endDate)

参数

$deviceIdentifier 设备id,设备编号device_id或UUID、major、minor的关联数组,若二者都填,则以设备编号为优先 $beginDate 起始日期时间戳,最长时间跨度为30天,单位为秒 $endDate 结束日期时间戳,最长时间跨度为30天,单位为秒

示例

$result = $shakearound->stats->deviceSummary(['device_id' => 10011], 1425052800, 1425139200);
// 或
$result = $shakearound->stats->deviceSummary(['uuid' => 'FDA50693-A4E2-4FB1-AFCF-C6EB07647825', 'major' => 1002, 'minor' => 1223, ], 1425052800, 1425139200);

/* 返回结果
{
   "data": [
       {
           "click_pv": 0,
           "click_uv": 0,
           "ftime": 1425052800,
           "shake_pv": 0,
           "shake_uv": 0
       },
       {
           "click_pv": 0,
           "click_uv": 0,
           "ftime": 1425139200,
           "shake_pv": 0,
           "shake_uv": 0
       }
   ],
   "errcode": 0,
   "errmsg": "success."
}
*/
2.22.8.5 批量查询设备统计数据

查询指定时间商家帐号下的每个设备进行摇周边操作的人数、次数,点击摇周边消息的人数、次数。

只能查最近90天内的数据,且一次只能查询一天。

注意: 对于摇周边人数、摇周边次数、点击摇周边消息的人数、点击摇周边消息的次数都为0的设备,不在结果列表中返回。

方法

$shakearound->stats->devicesSummary(int $timestamp, int $pageIndex)

参数

$timestamp 指定查询日期时间戳,单位秒 $pageIndex 指定查询的结果页序号,返回结果按摇周边人数降序排序,每50条记录为一页

示例

$result = $shakearound->stats->devicesSummary(1435075200, 1);

/* 返回结果
{
    "data": {
        "devices": [
            {
                "device_id": 10097,
                "major": 10001,
                "minor": 12102,
                "uuid": "FDA50693-A4E2-4FB1-AFCF-C6EB07647825"
                "shake_pv": 1
                "shake_uv": 2
                "click_pv": 3
                "click_uv": 4
            },
            {
                "device_id": 10098,
                "major": 10001,
                "minor": 12103,
                "uuid": "FDA50693-A4E2-4FB1-AFCF-C6EB07647825"
                "shake_pv": 1
                "shake_uv": 2
                "click_pv": 3
                "click_uv": 4
            }
        ],
    },
    "date":1435075200
    "total_count": 151
    "page_index":1
    "errcode": 0,
    "errmsg": "success."
}
*/
2.22.8.6 以页面为维度的数据统计

查询单个页面通过摇周边摇出来的人数、次数,点击摇周边页面的人数、次数

注意: 查询的最长时间为30天。只能查最近90天的数据。

方法

$shakearound->stats->pageSummary(int $pageId, int $beginDate, int $endDate);

参数

$pageId 指定页面ID $beginDate 起始日期时间戳,最长时间跨度为30天,单位为秒 $endDate 结束日期时间戳,最长跨度为30天,单位秒

示例

$result = $shakearound->stats->pageSummary(12345, 1425052800, 1425139200);

/* 返回结果
{
   "data": [
       {
           "click_pv": 0,
           "click_uv": 0,
           "ftime": 1425052800,
           "shake_pv": 0,
           "shake_uv": 0
       },
       {
           "click_pv": 0,
           "click_uv": 0,
           "ftime": 1425139200,
           "shake_pv": 0,
           "shake_uv": 0
       }
   ],
   "errcode": 0,
   "errmsg": "success."
}
*/
2.22.8.7 批量查询页面统计数据

查询指定时间商家帐号下的每个页面进行摇周边操作的人数、次数,点击摇周边消息的人数、次数。

注意: 对于摇周边人数、摇周边次数、点击摇周边消息的人数、点击摇周边消息的次数都为0的页面,不在结果列表中返回。

方法

$shakearound->stats->pagesSummary(int $timestamp, int $pageIndex);

参数

$timestamp 指定查询日期时间戳,单位为秒 $pageIndex 指定查询的结果页序号,返回结果按摇周边人数降序排序,每50条记录为一页

示例

$result = $shakearound->stats->pagesSummary(1435075200, 1);

/* 返回结果
{
    "data": {
        "pages": [
            {
                "page_id":1234
                "click_pv": 1,
                "click_uv": 3,
                "shake_pv": 0,
                "shake_uv": 0
            },
            {
                "page_id":5678
                "click_pv": 1,
                "click_uv": 2,
                "shake_pv": 0,
                "shake_uv": 0
            },
        ],
    },
    "date":1435075200
    "total_count": 151
    "page_index":1
    "errcode": 0,
    "errmsg": "success."
}
*/

2.22.9 设备分组管理

调用H5页面获取设备信息 JS API接口,需要先把设备分组,微信客户端只会返回已在分组中的设备信息。

2.22.9.1 新增分组

新建设备分组,每个帐号下最多只有1000个分组。

方法

$shakearound->group->create(string $name)
//参数
// $name 分组名称,不超过100汉字或200个英文字母

//示例
$result = $shakearound->group->create('test');

/* 返回结果
{
  "data": {
      "group_id" : 123,
      "group_name" : "test"
  },
  "errcode": 0,
  "errmsg": "success."
}
*/
2.22.9.2 编辑分组信息

编辑设备分组信息,目前只能改分组名。

方法

$shakearound->group->update(int $groupId, string $name)

参数

$groupId 分组唯一标识,全局唯一 $name 分组名称,不超过100汉字或200个英文字母

示例

$result = $shakearound->group->update(123, 'newName');

/* 返回结果
{
    "data": {
    },
    "errcode": 0,
    "errmsg": "success."
}
*/
2.22.9.3 删除分组

删除设备分组,若分组中还存在设备,则不能删除成功。需把设备移除以后,才能删除。

在执行删除前,最好先用 get 方法查询分组详情,若分组内有设备,先用 removeDevices 方法移除。

方法

$shakearound->group->delete(int $groupId)

参数

$groupId 分组唯一标识,全局唯一

示例

$result = $shakearound->group->delete(123);

/* 返回结果
{
    "data": {
    },
    "errcode": 0,
    "errmsg": "success."
}
*/
2.22.9.4 查询分组列表

查询账号下所有的分组。

方法

$shakearound->group->list(int $begin, int $count)

参数

$begin 分组列表的起始索引值 $count 待查询的分组数量,不能超1000个

示例

$result = $shakearound->group->list(0, 2);

/* 返回结果
{
    "data": {
        "groups":[
            {
                "group_id" : 123,
                "group_name" : "test1"
            },
            {
                "group_id" : 124,
                "group_name" : "test2"
            }
        ],
        "total_count": 100
    },
    "errcode": 0,
    "errmsg": "success."
}
*/
2.22.9.5 查询分组详情

查询分组详情,包括分组名,分组id,分组里的设备列表。

方法

$shakearound->group->get(int $groupId, int $begin, int $count)

参数

$groupId 分组唯一标识,全局唯一 $begin 分组里设备的起始索引值 $count 待查询的分组里设备的数量,不能超1000个

示例

$result = $shakearound->group->get(123, 0, 2);

/* 返回结果
{
    "data": {
        "group_id" : 123,
        "group_name" : "test",
        "total_count": 100,
        "devices" :[
            {
                "device_id" : 123456,
                "uuid" : "FDA50693-A4E2-4FB1-AFCF-C6EB07647825",
                "major" : 10001,
                "minor" : 10001,
                "comment" : "test device1",
                "poi_id" : 12345,
            },
            {
                "device_id" : 123457,
                "uuid" : "FDA50693-A4E2-4FB1-AFCF-C6EB07647825",
                "major" : 10001,
                "minor" : 10002,
                "comment" : "test device2",
                "poi_id" : 12345,
            }
        ]
    },
    "errcode": 0,
    "errmsg": "success."
}
*/
2.22.9.6 添加设备到分组

添加设备到分组,每个分组能够持有的设备上限为10000,并且每次添加操作的添加上限为1000。

只有在摇周边申请的设备才能添加到分组。

方法

$shakearound->group->addDevices(int $groupId, array $deviceIdentifiers)

参数

$groupId 分组唯一标识,全局唯一 $deviceIdentifiers 设备id列表

示例

$result = $shakearound->group->addDevices(123, [
  ['device_id' => 10097],
  ['device_id' => 10098],
]);

// 或
$result = $shakearound->group->addDevices(123, [
  [
    'uuid' => 'FDA50693-A4E2-4FB1-AFCF-C6EB07647825',
    'major' => 10001,
    'minor' => 12102,
  ],
  [
    'uuid' => 'FDA50693-A4E2-4FB1-AFCF-C6EB07647825',
    'major' => 10001,
    'minor' => 12103,
  ]
]);

/* 返回结果
{
    "data": {
    },
    "errcode": 0,
    "errmsg": "success."
}
*/
2.22.9.7 从分组中移除设备

从分组中移除设备,每次删除操作的上限为 1000。

方法

$shakearound->group->removeDevices(int $groupId, array $deviceIdentifiers)

参数

$groupId 分组唯一标识,全局唯一 $deviceIdentifiers 设备id列表

示例

$result = $shakearound->group->removeDevices(123, [
  ['device_id' => 10097],['device_id' => 10098],]);
// 或
$result = $shakearound->group->removeDevices(123, [
    [
      'uuid' => 'FDA50693-A4E2-4FB1-AFCF-C6EB07647825',
      'major' => 10001,
      'minor' => 12102,
    ],
    [
      'uuid' => 'FDA50693-A4E2-4FB1-AFCF-C6EB07647825',
      'major' => 10001,
      'minor' => 12103,
    ]
]);

2.22.10 摇一摇事件通知

用户进入摇一摇界面,在“周边”页卡下摇一摇时,微信会把这个事件推送到开发者填写的URL(登录公众平台开发者中心设置)。推送内容包含摇一摇时“周边”页卡展示出来的页面所对应的设备信息,以及附近最多五个属于该公众账号的设备的信息。当摇出列表时,此事件不推送。

摇一摇事件的事件类型:ShakearoundUserShake

关于事件的处理请移步: 事件

2.23 数据统计与分析

通过数据接口,开发者可以获取与公众平台官网统计模块类似但更灵活的数据,还可根据需要进行高级处理。

  1. 接口侧的公众号数据的数据库中仅存了 2014年12月1日之后的数据,查不到在此之前的日期,即使查到,也是不可信的脏数据;
  2. 开发者在调用接口获取数据后,将数据保存在自身数据库中,即加快下次用户的访问速度,也降低微信侧接口调用的损耗。
  3. 注意,获取图文群发每日数据接口的结果中,只有中间页阅读人数+原文页阅读人数+分享转发人数+分享转发次数+收藏次数 >=3 结果才得到统计,过小的阅读量的图文消息无法统计。

示例

$userSummary = $app->data_cube->userSummary('2014-12-07', '2014-12-08');
var_dump($userSummary);

//[
//    {
//        "ref_date": "2014-12-07",
//        "user_source": 0,
//        "new_user": 0,
//        "cancel_user": 0
//    }
//    //后续还有ref_date在begin_date和end_date之间的数据
// ]

API

$from   示例: `2014-02-13` 获取数据的起始日期
$to     示例: `2014-02-18` 获取数据的结束日期,`$to`允许设置的最大值为昨日

`$from` 和 `$to` 的差值需小于 “最大时间跨度”(比如最大时间跨度为 1 时,`$from` 和 `$to` 的差值只能为 0,才能小于 1 ),否则会报错
  • array userSummary(string $from, string $to) 获取用户增减数据, 最大时间跨度:7;
  • array userCumulate(string $from, string $to) 获取累计用户数据, 最大时间跨度:7;
  • array articleSummary(string $from, string $to) 获取图文群发每日数据, 最大时间跨度:1;
  • array articleTotal(string $from, string $to) 获取图文群发总数据, 最大时间跨度:1;
  • array userReadSummary(string $from, string $to) 获取图文统计数据, 最大时间跨度:3;
  • array userReadHourly(string $from, string $to) 获取图文统计分时数据, 最大时间跨度:1;
  • array userShareSummary(string $from, string $to) 获取图文分享转发数据, 最大时间跨度:7;
  • array userShareHourly(string $from, string $to) 获取图文分享转发分时数据, 最大时间跨度:1;
  • array upstreamMessageSummary(string $from, string $to) 获取消息发送概况数据, 最大时间跨度:7;
  • array upstreamMessageHourly(string $from, string $to) 获取消息发送分时数据, 最大时间跨度:1;
  • array upstreamMessageWeekly(string $from, string $to) 获取消息发送周数据, 最大时间跨度:30;
  • array upstreamMessageMonthly(string $from, string $to) 获取消息发送月数据, 最大时间跨度:30;
  • array upstreamMessageDistSummary(string $from, string $to) 获取消息发送分布数据, 最大时间跨度:15;
  • array upstreamMessageDistWeekly(string $from, string $to) 获取消息发送分布周数据, 最大时间跨度:30;
  • array upstreamMessageDistMonthly(string $from, string $to) 获取消息发送分布月数据, 最大时间跨度:30;
  • array interfaceSummary(string $from, string $to) 获取接口分析数据, 最大时间跨度:30;
  • array interfaceSummaryHourly(string $from, string $to) 获取接口分析分时数据, 最大时间跨度:1;
  • array cardSummary(string $from, string $to, int $condSource = 0) 获取普通卡券分析分时数据, 最大时间跨度:1;
  • array freeCardSummary(string $from, string $to, int $condSource = 0, string $cardId = '') 获取免费券分析分时数据, 最大时间跨度:1;
  • array memberCardSummary(string $from, string $to, int $condSource = 0) 获取会员卡分析分时数据, 最大时间跨度:1;

2.24 语义理解

貌似此接口已下线,调用无正确返回值

  • query($keyword, $categories, $optional = []) 语义理解:
    • $keyword 为关键字
    • $categories 需要使用的服务类型,多个用 “,” 隔开字符串,不能为空;
    • $optional 为其它属性:
    • latitude float 纬度坐标,与经度同时传入;与城市二选一传入
    • longitude float 经度坐标,与纬度同时传入;与城市二选一传入
    • city string 城市名称,与经纬度二选一传入
    • region string 区域名称,在城市存在的情况下可省;与经纬度二选一传入
    • uid string 用户唯一id(非开发者id),用户区分公众号下的不同用户(建议填入用户openid),如果为空,则无法使用上下文理解功能。appid和uid同时存在的情况下,才可以使用上下文理解功能。

注:单类别意图比较明确,识别的覆盖率比较大,所以如果只要使用特定某个类别,建议将 category 只设置为该类别。

示例:

$result = $app->semantic->query('查一下明天从北京到上海的南航机票', "flight,hotel", array('city' => '北京', 'uid' => '123456'));
// 查询参数:
// {
//    "query":"查一下明天从北京到上海的南航机票",
//    "city":"北京",
//    "category": "flight,hotel",
//    "appid":"wxaaaaaaaaaaaaaaaa",
//    "uid":"123456"
// }

返回值示例:

{
    "errcode":0,
    "query":"查一下明天从北京到上海的南航机票",
    "type":"flight",
    "semantic":{
        "details":{
            "start_loc":{
                "type":"LOC_CITY",
                "city":"北京市",
                "city_simple":"北京",
                "loc_ori":"北京"
                },
            "end_loc": {
                "type":"LOC_CITY",
                "city":"上海市",
                "city_simple":"上海",
                "loc_ori":"上海"
              },
            "start_date": {
                "type":"DT_ORI",
                "date":"2014-03-05",
                "date_ori":"明天"
              },
           "airline":"中国南方航空公司"
        },
    "intent":"SEARCH"
}

2.25 自动回复

2.25.1 获取当前设置的回复规则

$app->auto_reply->current();

2.26 评论数据管理

2.26.1 打开已群发文章评论

$app->comment->open($msgId, $index = null);

2.26.2 关闭已群发文章评论

$app->comment->close($msgId, $index = null);

2.26.3 查看指定文章的评论数据

$app->comment->list(string $msgId, int $index, int $begin, int $count, int $type = 0);

2.26.4 将评论标记精选

$app->comment->markElect(string $msgId, int $index, int $commentId);

2.26.5 将评论取消精选

$app->comment->unmarkElect(string $msgId, int $index, int $commentId);

2.26.6 删除评论

$app->comment->delete(string $msgId, int $index, int $commentId);

2.26.7 回复评论

$app->comment->reply(string $msgId, int $index, int $commentId, string $content);

2.26.8 删除回复

$app->comment->deleteReply(string $msgId, int $index, int $commentId);

2.27 返佣商品

微信文档:https://mp.weixin.qq.com/cgi-bin/announce?action=getannouncement&key=11533749572M9ODP&version=1&lang=zh_CN&platform=2

2.27.1 导入商品

每次调用支持批量导入不超1000条的商品信息。每分钟单商户全局调用次数不得超200次。每天调用次数不得超100万次。每次请求包大小不超过2M。

$data = [
    [
        'pid' => 'pid001',
        'image_info' => [
            'main_image_list' => [
                [
                    'url' => 'http://www.google.com/a.jpg',
                ],
                [
                    'url' => 'http://www.google.com/b.jpg',
                ],
            ],
        ],
        //...
    ],
    //...
];

$result = $app->goods->add($data);

// $result:
//{
//    "errcode": 0,
//    "errmsg": "ok",
//    "status_ticket": "115141102647330200"
//}

status_ticket 用于获取此次导入的详细结果。

2.27.2 更新商品

更新时,字段不填代表不更新该字段(此处的字段不填,代表无此字段,而不是把字段的值设为空,设为空即代表更新该字段为空)。

对于字符串类型的选填字段,如副标题,若清空不展示,则可设置为空;对于数字类型的选填字段,如原价,若清空不展示,则需设置为0。

基本字段更新中 pid 为必填字段,且无法修改

$data = [
    [
        'pid' => 'pid001',
        'image_info' => [
            'main_image_list' => [
                [
                    'url' => 'http://www.baidu.com/c.jpg',
                ],
                [
                    'url' => 'http://www.baidu.com/d.jpg',
                ],
            ],
        ],

        //...
    ],

    //...
];

$result = $app->goods->update($data);

// $result:
//{
//    "errcode": 0,
//    "errmsg": "ok",
//    "status_ticket": "115141102647330200"
//}

说明:导入商品和更新商品使用的是同一个接口。

2.27.3 查询导入/更新商品状态

用于查询导入或更新商品的结果,当导入或更新商品失败时,若为系统错误可进行重试;若为其他错误,请排查解决后进行重试。

$status_ticket = '115141102647330200';

$result = $app->goods->status($status_ticket);

// $result:
//{
//    "errcode": 0,
//    "errmsg": "ok",
//    "result": {
//        "succ_cnt": 2,
//        "fail_cnt": 0,
//        "total_cnt": 2,
//        "progress": "100.00%",
//        "statuses": [
//            {
//                "pid": "pid001",
//                "ret": 0,
//                "err_msg": "success",
//                "err_msg_zh_cn": "成功"
//            },
//            {
//                "pid": "pid002",
//                "ret": 0,
//                "err_msg": "success",
//                "err_msg_zh_cn": "成功"
//            }
//        ]
//    }
//}

2.27.4 获取单个商品信息

使用该接口获取已导入的商品信息,供验证信息及抽查导入情况使用。

$pid = 'pid001';
$app->goods->get($pid);

返回结果中的 product 字段与 导入商品接口 字段一致,导入时未设置的值有可能获取时仍会返回,但显示为空

2.27.5 分页获取商品信息

使用该接口可获取已导入的全量商品信息,供全量验证信息使用。

$context = '';  // page 为 1 时传空即可。当 page 大于 1 时必填,填入上一次访问本接口返回的 page_context。
$page = 1;      // 页码
$size = 10;     // 每页数据大小,目前限为100内,注意一次全量验证过程中该参数的值需保持不变

$app->goods->list($context, $page, $size);

返回结果中的 product 字段与 导入商品接口 字段一致,导入时未设置的值有可能获取时仍会返回,但显示为空。 page_context 字段用于获取下一页数据时使用。

三、微信支付

3.1 入门

你在阅读本文之前确认你已经仔细阅读了:微信支付 | 商户平台开发文档。

3.1.1 配置

配置在前面的例子中已经提到过了,支付的相关配置如下:

use EasyWeChat\Factory;

$config = [
    // 必要配置
    'app_id'  => 'xxxx',
    'mch_id'  => 'your-mch-id',
    'key'     => 'key-for-signature', //API密钥

    // 如需使用敏感接口(如退款、发送红包等)需要配置 API 证书路径(登录商户平台下载 API 证书)
    'cert_path'  => 'path/to/your/cert.pem', //绝对路径!
    'key_path'   => 'path/to/your/key',  //绝对路径!

    'notify_url' => '默认的订单回调地址', // 也可在下单时单独设置覆盖它
];

$app = Factory::payment($config);

3.1.2 服务商

设置子商户信息

$app->setSubMerchant('sub-merchant-id', 'sub-app-id');  // 子商户 AppID 为可选项

3.1.3 刷卡支付

官方文档

$result = $app->pay([
    'body' => 'image形象店-深圳腾大- QQ公仔',
    'out_trade_no' => '1217752501201407033233368018',
    'total_fee' => 888,
    'auth_code' => '120061098828009406',
]);

3.1.4 授权码查询OPENID接口

$app->authCodeToOpenid($authCode);

3.1.5 沙箱模式

微信支付沙箱环境,是提供给微信支付商户的开发者,用于模拟支付及回调通知。以验证商户是否理解回调通知、账单格式,及是否对异常做正确的处理。EasyWeChat SDK 对于这一功能封装,开发者只需一步即可在沙箱模式和常规模式间切换,方便开发与最终的部署。

// 在实例化的时候传入配置即可
$app = Factory::payment([
    // ...
    'sandbox' => true, // 设为 false 或注释则关闭沙箱模式
]);
// 判断当前是否为沙箱模式:
bool $app->inSandbox();

注意,沙箱模式对测试用例有严格要求,若使用用例与规定不符,将导致测试失败。具体用例可关注公众号“微信支付商户接入验收助手”(WXPayAssist)查看。

3.2 订单

3.2.1 统一下单

H5 支付,公众号支付,扫码支付,支付中签约,全都用这个接口下单。

参数 appid, mch_id, nonce_str, sign, sign_type 可不用传入

服务商模式下, 需用 sub_openid, 并传入sub_mch_idsub_appid

$result = $app->order->unify([
    'body' => '腾讯充值中心-QQ会员充值',
    'out_trade_no' => '20150806125346',
    'total_fee' => 88,
    'spbill_create_ip' => '123.12.12.123', // 可选,如不传该参数,SDK 将会自动获取相应 IP 地址
    'notify_url' => 'https://pay.weixin.qq.com/wxpay/pay.action', // 支付结果通知网址,如不设置则会用配置的默认地址
    'trade_type' => 'JSAPI', // 请对应换成支付方式对应的值类型
    'openid' => 'oUpF8uMuAJO_M2pxb1Q9zNjWeS6o',
]);

// $result:
//{
//    "return_code": "SUCCESS",
//    "return_msg": "OK",
//    "appid": "wx2421b1c4390ec4sb",
//    "mch_id": "10000100",
//    "nonce_str": "IITRi8Iabbblz1J",
//    "openid": "oUpF8uMuAJO_M2pxb1Q9zNjWeSs6o",
//    "sign": "7921E432F65EB8ED0CE9755F0E86D72F2",
//    "result_code": "SUCCESS",
//    "prepay_id": "wx201411102639507cbf6ffd8b0779950874",
//    "trade_type": "JSAPI"
//}

第二个参数为是否支付中签约,默认 false

支付中签约相关参数 contract_mchid, contract_appid, request_serial 可不用传入

$isContract = true;

$result = $app->order->unify([
    'body' => '腾讯充值中心-QQ会员充值',
    'out_trade_no' => '20150806125346',
    'total_fee' => 88,
    'spbill_create_ip' => '123.12.12.123', // 可选,如不传该参数,SDK 将会自动获取相应 IP 地址
    'notify_url' => 'https://pay.weixin.qq.com/wxpay/pay.action', // 支付结果通知网址,如果不设置则会使用配置里的默认地址
    'trade_type' => 'JSAPI', // 请对应换成你的支付方式对应的值类型
    'openid' => 'oUpF8uMuAJO_M2pxb1Q9zNjWeS6o',

    'plan_id' => 123,// 协议模板id
    'contract_code' => 100001256,// 签约协议号
    'contract_display_account' => '腾讯充值中心',// 签约用户的名称
    'contract_notify_url' => 'http://easywechat.org/contract_notify'
], $isContract);

//$result:
//{
//  "return_code": "SUCCESS",
//  "return_msg": "OK",
//  "appid": "wx123456",
//  "mch_id": "10000100",
//  "nonce_str": "CfOcMkDFblzulYvI",
//  "sign": "B53F4AFEE7FA6AD5739581486A5CB9C9",
//  "result_code": "SUCCESS",
//  "prepay_id": "wx08175759731015754a5c13791522969400",
//  "trade_type": "JSAPI",
//  "plan_id": "123",
//  "request_serial": "1565258279",
//  "contract_code": "100001256",
//  "contract_display_account": "腾讯充值中心",
//  "out_trade_no": "201908088195558331565258279",
//  "contract_result_code": "SUCCESS"
//}

3.2.2 查询订单

该接口提供所有微信支付订单的查询,商户可通过该接口主动查询订单状态,完成下步的业务逻辑。

需调用查询接口的情况:

  • 当商户后台、网络、服务器等出现异常,商户系统最终未接收到支付通知;
  • 调用支付接口后,返回系统错误或未知交易状态情况;
  • 调用被扫支付 API,返回 USERPAYING 的状态;
  • 调用关单或撤销接口 API 之前,需确认支付状态;

3.2.3 根据商户订单号查询

$app->order->queryByOutTradeNumber("商户系统内部的订单号(out_trade_no)");

3.2.4 根据微信订单号查询

$app->order->queryByTransactionId("微信订单号(transaction_id)");

3.2.5 关闭订单

注意:订单生成后不能马上调用关单接口,最短调用时间间隔为5分钟

$app->order->close(商户系统内部的订单号(out_trade_no)

3.3 退款

3.3.1 申请退款

当交易发生后一段时间内,由于买家或者卖家原因需退款时,卖家可通过退款接口将支付款退给买家,微信支付将在收到退款请求且验证成功后,按退款规则将支付款按原路退到买家帐号上。

注意:

1、交易时间超一年的订单无法提交退款; 2、微信支付退款支持单笔交易分多次退款,多次退款需提交原支付订单的商户订单号和设置不同的退款单号。一笔退款失败后重新提交,要采用原退款单号。总退款金额不能超过用户实际支付金额。

参考:https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_4

3.3.2 根据微信订单号退款

// 参数分别为:微信订单号、商户退款单号、订单金额、退款金额、其他参数
$app->refund->byTransactionId(string $transactionId, string $refundNumber, int $totalFee, int $refundFee, array $config = []);

// Example:
$result = $app->refund->byTransactionId('transaction-id-xxx', 'refund-no-xxx', 10000, 10000, [
    // 可在此处传入其他参数,详细参数见微信支付文档
    'refund_desc' => '商品已售完',
]);

3.3.3 根据商户订单号退款

// 参数分别为:商户订单号、商户退款单号、订单金额、退款金额、其他参数
$app->refund->byOutTradeNumber(string $number, string $refundNumber, int $totalFee, int $refundFee, array $config = []);

// Example:
$result = $app->refund->byOutTradeNumber('out-trade-no-xxx', 'refund-no-xxx', 20000, 1000, [
    // 可在此处传入其他参数,详细参数见微信支付文档
    'refund_desc' => '退运费',
]);

$refundNumber 为商户退款单号,自己生成用于自己识别即可。

3.3.4 查询退款

提交退款申请后,通过调用该接口查询退款状态。退款有延时,用零钱支付的退款20分钟内到账,银行卡支付的退款3个工作日后重新查询退款状态。

可通过 4 种不同类型的单号查询:

  • 微信订单号 => queryByTransactionId($transactionId)
  • 商户订单号 => queryByOutTradeNumber($outTradeNumber)
  • 商户退款单号 => queryByOutRefundNumber($outRefundNumber)
  • 微信退款单号 => queryByRefundId($refundId)

3.4 对账单

https://github.com/easywechat/docs/edit/4.1/payment/bill.md)

3.4.1 下载对账单

调用参数正确会返回个 EasyWeChat\Kernel\Http\StreamResponse 对象,否则会返回相应错误信息

Example:

$bill = $app->bill->get('20140603'); // type: ALL
// or
$bill = $app->bill->get('20140603', 'SUCCESS'); // type: SUCCESS

// 调用正确,`$bill` 为 csv 格式的内容,保存为文件:
$bill->saveAs('your/path/to', 'file-20140603.csv');

第二个参数为账单类型,参考:https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_6 中 bill_type,默认为 ALL

3.5 通知

3.5.1 支付结果通知

在用户成功支付后,微信服务器会向该订单中设置的回调URL 发起 POST 请求,请求内容为 XML。里面包含所有的详细信息,具体请参考:支付结果通知

而对于用户的退款操作,在退款成功后也有个异步回调通知。

本 SDK 内预置了相关方法,以方便开发者处理这些通知,具体用法如下:

只需在控制器中用 handlePaidNotify() 方法,在其中对自己的业务进行处理并向微信服务器发送个响应。

$response = $app->handlePaidNotify(function ($message, $fail) {
    // 你的逻辑
    return true;
    // 或者错误消息
    $fail('Order not exists.');
});

$response->send(); // Laravel 里请使用:return $response;

注意:

  1. 退款结果通知和扫码支付通知的使用方法均类似。

  2. handlePaidNotify 只接收个 Closure 匿名函数。

  3. 该匿名函数接收两个参数,这两个参数分别为:

    $message 为微信推送过来的通知信息,为一个数组;

    $fail 为一个函数,触发该函数可向微信服务器返回对应的错误信息,微信会稍后重试再通知

  4. 该函数返回值告诉微信 “我是否处理完成”。如果你触发 $fail 函数,那微信会在稍后再次继续通知你,直到明确的告诉它:“我已处理完成”,只有在函数里 return true; 才代表处理完成。

  5. handlePaidNotify 返回值 $response 是个 Response 对象,如果要直接输出,使用 $response->send(), 在一些框架里(如 Laravel)不是输出而是返回:return $response

通常处理逻辑大概是下面这样(以下只是伪代码):

$response = $app->handlePaidNotify(function($message, $fail){
    // 使用通知里的 "微信支付订单号" 或 "商户订单号" 去自己数据库找订单
    $order = 查询订单($message['out_trade_no']);

    if (!$order || $order->paid_at) { // 如果订单不存在 或 订单已支付过
        return true; // 告诉微信,已经处理完了,订单没找到,别再通知了
    }

    // <- 建议在这里调用微信的【订单查询】接口查下该笔订单情况,确认已支付 //

    if ($message['return_code'] === 'SUCCESS') { // return_code 表示通信状态,不代表支付状态
        // 用户是否支付成功
        if (array_get($message, 'result_code') === 'SUCCESS') {
            $order->paid_at = time(); //更新支付时间为当前时间
            $order->status = 'paid';

        // 用户支付失败
        } elseif (array_get($message, 'result_code') === 'FAIL') {
            $order->status = 'paid_fail';
        }
    } else {
        return $fail('通信失败,请稍后再通知我');
    }

    $order->save(); // 保存订单
    return true; // 返回处理完成
});

$response->send(); // return $response;

注意:请把 “支付成功与否” 与 “是否处理完成” 分开,它俩没必然关系。 如:微信通知用户支付完成,但支付失败了(result_code 为 ‘FAIL’),应更新订单为支付失败,但要告诉微信处理完成

3.5.2 退款结果通知

使用示例:

$response = $app->handleRefundedNotify(function ($message, $reqInfo, $fail) {
    // 其中 $message['req_info'] 获取到的是加密信息
    // $reqInfo 为 message['req_info'] 解密后的信息
    // 你的业务逻辑...
    return true; // 返回 true 告诉微信“我已处理完成”
    // 或返回错误原因 $fail('参数格式校验错误');
});

$response->send();

3.5.3 扫码支付通知

扫码支付【模式一】:https://pay.weixin.qq.com/wiki/doc/api/native.php?chapter=6_4

// 扫码支付通知接收第三个参数 `$alert`,如果触发该函数,会返回“业务错误”到微信服务器,触发 `$fail` 则返回“通信错误”
$response = $app->handleScannedNotify(function ($message, $fail, $alert) use ($app) {
    // 如:$alert('商品已售空');
    // 如业务流程正常,则要调用“统一下单”接口,并返回 prepay_id 字符串,代码如下
    $result = $app->order->unify([
        'trade_type' => 'NATIVE',
        'product_id' => $message['product_id'],
        // ...
    ]);
    return $result['prepay_id'];
});
$response->send();

3.6 红包

在阅读本文之前确认你已经仔细阅读了:微信支付 | 现金红包文档 。

3.6.1 配置

与支付接口一样,红包接口也要配置如下参数,注意,红包相关的全部接口都要用 SSL 证书,因此cert_path 及 cert_key 必须正确配置

use EasyWeChat\Factory;

$config = [
    'app_id'    => 'you-app-id',
    'mch_id'    => 'your-mch-id',
    'key'       => 'key-for-signature',
    'cert_path' => 'path/to/your/cert.pem',
    'key_path'  => 'path/to/your/key',
    // ...
];

$payment = Factory::payment($config);

$redpack = $payment->redpack;

3.6.2 发送红包

微信的现金红包分为普通红包裂变红包两类。SDK 对其分别封装,同时也提供一个统一的调用方法。

默认,通过接口发送的红包金额应该在200元内,但可通过在调用发送接口时传递场景 ID (scene_id)来发送特定场景的红包,不同场景红包可由商户自己登录商户平台设置最大金额。scene_id 的可选值及对应含义可参阅微信支付官方文档。

3.6.3 发送普通红包接口

$redpackData = [
    'mch_billno'   => 'xy123456',
    'send_name'    => '测试红包',
    're_openid'    => 'oxTWIuGaIt6gTKsQRLau2M0yL16E',
    'total_num'    => 1,  //固定为1,可不传
    'total_amount' => 100,  //单位为分,不小于100
    'wishing'      => '祝福语',
    'client_ip'    => '192.168.0.1',  //可不传,不传则由 SDK 取当前客户端 IP
    'act_name'     => '测试活动',
    'remark'       => '测试备注',
    // ...
];

$result = $redpack->sendNormal($redpackData);

3.6.4 发送裂变红包接口

$redpackData = [
    'mch_billno'   => 'xy123456',
    'send_name'    => '测试红包',
    're_openid'    => 'oxTWIuGaIt6gTKsQRLau2M0yL16E',
    'total_num'    => 3,  //不小于3
    'total_amount' => 300,  //单位为分,不小于300
    'wishing'      => '祝福语',
    'act_name'     => '测试活动',
    'remark'       => '测试备注',
    'amt_type'     => 'ALL_RAND',  //可不传
    // ...
];

$result = $redpack->sendGroup($redpackData);

3.6.5 红包预下单接口

红包预下单接口是为摇一摇红包接口配合使用的,在开发摇一摇周边的摇红包相关功能时,需要调用本接口获取红包单号。详情参见官方文档

$redpackData = [
    'hb_type'      => 'NORMAL',  //NORMAL 或 GROUP
    'mch_billno'   => 'xy123456',
    'send_name'    => '测试红包',
    're_openid'    => 'oxTWIuGaIt6gTKsQRLau2M0yL16E',
    'total_num'    => 1,  //普通红包固定为1,裂变红包不小于3
    'total_amount' => 100,  //单位为分,普通红包不小于100,裂变红包不小于300
    'wishing'      => '祝福语',
    'client_ip'    => '192.168.0.1',  //可不传,不传则由 SDK 取当前客户端 IP
    'act_name'     => '测试活动',
    'remark'       => '测试备注',
    'amt_type'     => 'ALL_RAND',
    // ...
];

$result = $redpack->prepare($redpackData);

3.6.6 查询红包信息

用于商户对已发放的红包进行查询红包的具体信息及领取情况 ,普通红包和裂变包均用这一接口查询。

$mchBillNo = "商户系统内部的订单号(mch_billno)";
$redpack->info($mchBillNo);

3.7 扫码支付

3.7.1 模式一:先生成产品二维码,扫码下单后支付

先熟悉流程:https://pay.weixin.qq.com/wiki/doc/api/native.php?chapter=6_4

3.7.1.1 生成产品二维码内容
$content = $app->scheme($productId); // $productId 为产品/商品ID,用于回调时带回,自己识别即可

//结果示例:weixin://wxpay/bizpayurl?sign=XXXXX&appid=XXXXX&mch_id=XXXXX&product_id=XXXXXX&time_stamp=XXXXXX&nonce_str=XXXXX

$content 生成二维码,SDK 并不内置二维码生成库,使用熟悉的工具创建二维码即可,比如 PHP 部分有以下工具可以选择:

  • https://github.com/endroid/qr-code
  • https://github.com/SimpleSoftwareIO/simple-qrcode
  • https://github.com/aferrandini/PHPQRCode
3.7.1.2 处理回调

当用户扫码时,回调接口会收到个通知,调用统一下单接口创建订单后返回 prepay_id,可用下面的代码处理扫码通知:

// 扫码支付通知接收第三个参数 `$alert`,如果触发该函数,会返回“业务错误”到微信服务器,触发 `$fail` 则返回“通信错误”
$response = $app->handleScannedNotify(function ($message, $fail, $alert) use ($app) {
    // 如:$alert('商品已售空');
    // 如业务流程正常,调用“统一下单”接口,并返回 prepay_id 字符串
    $result = $app->order->unify([
        'trade_type' => 'NATIVE',
        'product_id' => $message['product_id'], // $message['product_id'] 则为生成二维码时的产品 ID
        // ...
    ]);
    return $result['prepay_id'];
});

$response->send();

用户在手机上付完钱以后,会再收到付款结果通知,这时请参考:处理微信支付通知 更新您的订单状态。

3.7.2 模式二:先下单,生成订单后创建二维码

请熟悉流程:https://pay.weixin.qq.com/wiki/doc/api/native.php?chapter=6_5

3.7.2.1 根据用户选购的商品生成订单

调用统一下单接口创建订单:

$result = $app->order->unify([
      'trade_type' => 'NATIVE',
      'product_id' => $message['product_id'], // $message['product_id'] 则为生成二维码时的产品 ID
      // ...
  ]);
3.7.2.2 生成二维码

版本 4.1.7+ 支持

从上步得到的 $result['code_url'] 得到二维码内容:

$result['code_url'] 生成二维码图片向用户展示即可扫码,生成工具上面找下即可。 SDK 不内置

3.7.2.3 支付通知

这种方式的通知就只有付款结果通知了,这时候请参考:处理微信支付通知 更新您的订单状态。

3.8 JSSDK

JSSDK 模块用于生成调起微信支付以及共享收货地址的调用所需的配置参数。

3.8.1 配置

use EasyWeChat\Factory;

$config = [
    // 前面的appid什么的也得保留哦
    'app_id'             => 'xxxx',
    'mch_id'             => 'your-mch-id',
    'key'                => 'key-for-signature',
    'cert_path'          => 'path/to/your/cert.pem', // XXX: 绝对路径!!!!
    'key_path'           => 'path/to/your/key',      // XXX: 绝对路径!!!!
    'notify_url'         => '默认的订单回调地址',     // 你也可以在下单时单独设置来想覆盖它
    // 'device_info'     => '013467007045764',
    // 'sub_app_id'      => '',
    // 'sub_merchant_id' => '',
    // ...
];

$payment = Factory::payment($config);

$jssdk = $payment->jssdk;

3.8.2 生成支付 JS 配置

有三种发起支付的方式:WeixinJSBridge, JSSDK, 小程序

  1. WeixinJSBridge:

    $json = $jssdk->bridgeConfig($prepayId); // 返回 json 字符串,如果想返回数组,传第二个参数 false
    

    javascript:

    ...
    WeixinJSBridge.invoke(
           'getBrandWCPayRequest', <?= $json ?>,
           function(res){
               if(res.err_msg == "get_brand_wcpay_request:ok" ) {
                 //用以上方式判断前端返回,微信团队郑重提示:
                 // res.err_msg将在用户支付成功后返回
                 // ok,但并不保证它绝对可靠。
               }
           }
       );
    ...
    
  2. JSSDK:

    $config = $jssdk->sdkConfig($prepayId); // 返回数组
    

    javascript:

    wx.chooseWXPay({
        timestamp: <?= $config['timestamp'] ?>,
        nonceStr: 'nonceStr'] ?>',
        package: 'package'] ?>',
        signType: 'signType'] ?>',
        paySign: 'paySign'] ?>', // 支付签名
        success: function (res) {
            // 支付成功后的回调函数
        }
    });
    
  3. 小程序:

    $config = $jssdk->bridgeConfig($prepayId, false); // 返回数组
    

    javascript:

    wx.requestPayment({
        timeStamp: <?= $config['timeStamp'] ?>, //注意 timeStamp 的格式
        nonceStr: 'nonceStr'] ?>',
        package: 'package'] ?>',
        signType: 'signType'] ?>',
        paySign: 'paySign'] ?>', // 支付签名
        success: function (res) {
            // 支付成功后的回调函数
        }
    });
    

3.8.3 生成共享收货地址 JS 配置

  1. 发起 OAuth 授权,获取用户 $accessToken,参考网页授权章节。
  2. 使用 $accessToken 获取配置
$configForPickAddress = $jssdk->shareAddressConfig($token);

// 拿着这个生成好的配置 $configForPickAddress 去订单页(或者直接显示订单页)写 js 调用了
// ...

3.8.4 生成 APP 支付配置

$config = $jssdk->appConfig($prepayId);

$config 为数组格式,你可以用 API 返回给客户端

3.8.5 二维码生成工具推荐

你也许需要生成二维码,那么以下这些供参考:

  • https://github.com/endroid/QrCode
  • https://github.com/Bacon/BaconQrCode
  • https://github.com/SimpleSoftwareIO/simple-qrcode (Bacon/BaconQrCode 的 Laravel 版本)
  • https://github.com/aferrandini/PHPQRCode

3.9 企业付款

EasyWeChat 4.0.7+

该模块需要用到双向证书,请参考:https://pay.weixin.qq.com/wiki/doc/api/tools/mch_pay.php?chapter=4_3

3.9.1 企业付款到用户零钱

$app->transfer->toBalance([
    'partner_trade_no' => '1233455', // 商户订单号,需保持唯一性(只能是字母或者数字,不能包含有符号)
    'openid' => 'oxTWIuGaIt6gTKsQRLau2M0yL16E',
    'check_name' => 'FORCE_CHECK', // NO_CHECK:不校验真实姓名, FORCE_CHECK:强校验真实姓名
    're_user_name' => '王小帅', // 如果 check_name 设置为FORCE_CHECK,则必填用户真实姓名
    'amount' => 10000, // 企业付款金额,单位为分
    'desc' => '理赔', // 企业付款操作说明信息。必填
]);

3.9.2 查询付款到零钱的订单

$partnerTradeNo = 1233455;
$app->transfer->queryBalanceOrder($partnerTradeNo);

3.9.3 企业付款到银行卡

企业付款到银行卡需要对银行卡号与姓名进行 RSA 加密,所以这里需要先下载 RSA 公钥到本地(服务器),我们提供了一个命令行工具:EasyWeChat/console,请使用 composer 安装完成。

$ composer require easywechat/console -vvv

然后,在项目根目录执行以下命令下载公钥:

$ ./vendor/bin/easywechat payment:rsa_public_key \
  >  --mch_id=14339221228 \
  >  --api_key=36YTbDmLgyQ52noqdxgwGiYy \
  >  --cert_path=/Users/overtrue/www/demo/apiclient_cert.pem \
  >  --key_path=/Users/overtrue/www/demo/apiclient_key.pem

将在当前目录生成个 ./public-14339221228.pem 文件,可将它移动到敏感目录,然后在支付配置文件中加如以下选项:

use EasyWeChat\Factory;

$config = [
    // 必要配置
    'app_id'   => 'xxxx',
    'mch_id'   => 'your-mch-id',
    'key'      => 'key-for-signature', //API 密钥

    // 如需用敏感接口(如退款、发送红包等)需配置 API 证书路径(登录商户平台下载 API 证书)
    'cert_path' => '/path/to/your/cert.pem', //绝对路径!
    'key_path'  => '/path/to/your/key',      //绝对路径!

    // 将上面得到的公钥存放路径填写在这里
    'rsa_public_key_path' => '/path/to/your/rsa/publick/key/public-14339221228.pem', // <<<----------
    'notify_url'         => '默认的订单回调地址',     // 也可在下单时单独设置来覆盖
];

$app = Factory::payment($config);
$result = $app->transfer->toBankCard([
    'partner_trade_no' => '1229222022',
    'enc_bank_no' => '6214830901234564', // 银行卡号
    'enc_true_name' => '安正超',   // 银行卡对应的用户真实姓名
    'bank_code' => '1001', // 银行编号
    'amount' => 100,  // 单位:分
    'desc' => '测试',
]);

3.9.4 查询付款到银行卡的订单

$partnerTradeNo = 1233455;
$app->transfer->queryBankCardOrder($partnerTradeNo);

3.10 撤销订单

目前只有 刷卡支付 有此功能。

调用支付接口后请勿立即调用撤销订单API,建议支付后至少15s后再调用撤销订单接口。

3.10.1 通过内部订单号撤销订单

$app->reverse->byOutTradeNumber("商户系统内部的订单号(out_trade_no)");

3.10.2 通过微信订单号撤销订单

$app->reverse->byTransactionId("微信的订单号(transaction_id)");

3.11 安全与风控

EasyWeChat 4.0.7+

3.11.1 获取 RSA 公钥

$result = $app->security->getPublicKey();
// 存成文件
file_put_contents('./public.pem', $result);

将会得到 PKCS#1 格式密钥:

-----BEGIN RSA PUBLIC KEY-----
MIIBCgKCAQEArT82k67xybiJS9AD8nNAeuDYdrtCRaxkS6cgs8L9h83eqlDTlrdw
zBVSv5V4imTq/URbXn4K0V/KJ1TwDrqOI8hamGB0fvU13WW1NcJuv41RnJVua0QA
lS3tS1JzOZpMS9BEGeFvyFF/epbi/m9+2kUWG94FccArNnBtBqqvFncXgQsm98JB
3a62NbS1ePP/hMI7Kkz+JNMyYsWkrOUFDCXAbSZkWBJekY4nGZtK1erqGRve8Jbx
TWirAm/s08rUrjOuZFA21/EI2nea3DidJMTVnXVPY2qcAjF+595shwUKyTjKB8v1
REPB3hPF1Z75O6LwuLfyPiCrCTmVoyfqjwIDAQAB
-----END RSA PUBLIC KEY-----

使用 OpenSSL 转换 PKCS#1 为 PKCS#8 格式密钥:

openssl rsa -RSAPublicKey_in -in public.pem -out public.pem

PKCS#8 格式密钥:

-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEArT82k67xybiJS9AD8nNA
euDYdrtCRaxkS6cgs8L9h83eqlDTlrdwzBVSv5V4imTq/URbXn4K0V/KJ1TwDrqO
I8hamGB0fvU13WW1NcJuv41RnJVua0QAlS3tS1JzOZpMS9BEGeFvyFF/epbi/m9+
lkUWG94FccArNnBtBqqvFncXgQsm98JB3a42NbS1ePP/hMI7Kkz+JNMyYsWkrOUF
DCXAbSZkWBJekY4nGZtK1erqGRve8JbxTWirAm/s08rUrjOuZFA21/EI2nea3Did
JMTVnXVPY2qcAjF+595shwUKyTjKB8v1REPB3hPF1Z75O6LwuLfyPiCrCTmVoyfq
jwIDAQAB
-----END PUBLIC KEY-----

四、小程序

4.1 入门

use EasyWeChat\Factory;

$config = [
    'app_id' => 'wx3cf0f39249eb0exx',
    'secret' => 'f1c242f4f28f735d4687abb469072axx',

    // 下面为可选项
    // 指定 API 调用返回结果的类型:array(default)/collection/object/raw/自定义类名
    'response_type' => 'array',

    'log' => [
        'level' => 'debug',
        'file' => __DIR__.'/wechat.log',
    ],
];

$app = Factory::miniProgram($config);

$app 在所有相关小程序的文档都是指 Factory::miniProgram 实例,就不在每个页面单独写了。

4.2 小程序码

4.2.1 获取小程序码

接口A: 适用于需要的码数量较少的业务场景,API:

$app->app_code->get(string $path, array $optional = []);

其中 $optional 为以下可选参数:

  • width Int - 默认 430 二维码的宽度
  • auto_color 默认 false 自动配置线条颜色,如果颜色黑色,则说明不建议配置主色调
  • line_color 数组,auto_colorfalse 时生效,使用 rgb 设置颜色 例如 ,示例:["r" => 0,"g" => 0,"b" => 0]

示例代码:

$response = $app->app_code->get('path/to/page');
// 或者
$response = $app->app_code->get('path/to/page', [
    'width' => 600,
    //...
]);

// 或者指定颜色
$response = $app->app_code->get('path/to/page', [
    'width' => 600,
    'line_color' => [
        'r' => 105,
        'g' => 166,
        'b' => 134,
    ],
]);

// $response 成功时为 EasyWeChat\Kernel\Http\StreamResponse 实例,失败时为数组或者你指定的 API 返回格式

// 保存小程序码到文件
if ($response instanceof \EasyWeChat\Kernel\Http\StreamResponse) {
    $filename = $response->save('/path/to/directory');
}

// 或
if ($response instanceof \EasyWeChat\Kernel\Http\StreamResponse) {
    $filename = $response->saveAs('/path/to/directory', 'appcode.png');
}

接口B:适用于需要的码数量极多,或仅临时使用的业务场景API:

$app->app_code->getUnlimit(string $scene, array $optional = []);

其中 s c e n e 必 填 , scene 必填, sceneoptinal 与 get 方法一致,多个 page 参数。

示例代码:

$response = $app->app_code->getUnlimit('scene-value', [
    'page'  => 'path/to/page',
    'width' => 600,
]);
// $response 成功时为 EasyWeChat\Kernel\Http\StreamResponse 实例,失败为数组或你指定的 API 返回类型

// 保存小程序码到文件
if ($response instanceof \EasyWeChat\Kernel\Http\StreamResponse) {
    $filename = $response->save('/path/to/directory');
}
// 或
if ($response instanceof \EasyWeChat\Kernel\Http\StreamResponse) {
    $filename = $response->saveAs('/path/to/directory', 'appcode.png');
}

4.2.2 获取小程序二维码 API:

$app->app_code->getQrCode(string $path, int $width = null);

其中 $path 必填,其余参数可留空。

示例代码:

$response = $app->app_code->getQrCode('/path/to/page');
// $response 成功时为 EasyWeChat\Kernel\Http\StreamResponse 实例,失败为数组或你指定的 API 返回类型

// 保存小程序码到文件
if ($response instanceof \EasyWeChat\Kernel\Http\StreamResponse) {
    $filename = $response->save('/path/to/directory');
}
// 或
if ($response instanceof \EasyWeChat\Kernel\Http\StreamResponse) {
    $filename = $response->saveAs('/path/to/directory', 'appcode.png');
}

4.3 客服消息

4.3.1 获取实例

$service = $app->customer_service;

使用方法详看公众号-客服消息章节。

4.4 数据统计与分析

获取小程序概况趋势:

$app->data_cube->summaryTrend('20170313', '20170313')

开始日期与结束日期的格式为 yyyymmdd。

//API
summaryTrend(string $from, string $to); //概况趋势
dailyVisitTrend(string $from, string $to); //访问日趋势
weeklyVisitTrend(string $from, string $to); //访问周趋势
monthlyVisitTrend(string $from, string $to); //访问月趋势
visitDistribution(string $from, string $to); //访问分布
dailyRetainInfo(string $from, string $to); //访问日留存
weeklyRetainInfo(string $from, string $to); //访问周留存
monthlyRetainInfo(string $from, string $to); //访问月留存
visitPage(string $from, string $to); 		//访问页面
userPortrait(string $from, string $to); //用户画像分布数据

4.5 微信登录

根据 jsCode 获取用户 session 信息。API:

$app->auth->session(string $code);

4.6 模板消息

获取小程序模板库标题列表

$app->template_message->list($offset, $count);

获取模板库某个模板标题下关键词库

$app->template_message->get($id);

组合模板并添加至帐号下的个人模板库

$app->template_message->add($id, $keywordIdList);

获取帐号下已存在的模板列表

$app->template_message->getTemplates($offset, $count);

删除帐号下的某个模板

$app->template_message->delete($templateId);

发送模板消息

$app->template_message->send([
    'touser' => 'user-openid',
    'template_id' => 'template-id',
    'page' => 'index',
    'form_id' => 'form-id',
    'data' => [
        'keyword1' => 'VALUE',
        'keyword2' => 'VALUE2',
        // ...
    ],
]);

4.7 微信小程序消息解密

比如获取电话等功能,信息是加密的,需要解密。API:

$decryptedData = $app->encryptor->decryptData($session, $iv, $encryptedData);

4.8 内容安全接口

4.8.1 文本安全内容检测

用于校验一段文本是否含有违法内容。

频率限制:单个appid调用上限为2000次/分钟,1,000,000次/天

调用示例

// 传入要检测的文本内容,长度不超过500K字节
$content = '你好';
$result = $app->content_security->checkText($content);

// 正常返回 0
{
    "errcode": "0",
    "errmsg": "ok"
}

//当 $content 内含有敏感信息,则返回 87014
{
    "errcode": 87014,
    "errmsg": "risky content"
}

4.8.2 图片安全内容检测

用于校验一张图片是否含敏感信息。如涉黄、敏感人脸(通常是政治人物)。

频率限制:单个appid调用上限为1000次/分钟,100,000次/天

调用示例

// 所传参数为要检测的图片文件的绝对路径,图片支持PNG、JPEG、JPG、GIF格式, 像素不超750 x 1334,同时文件大小不超过 300K,否则可能报错
$result = $app->content_security->checkImage('/path/to/the/image');

// 正常返回 0
{"errcode": "0", "errmsg": "ok"}

// 当图片文件内含有敏感内容,则返回 87014
{"errcode": 87014, "errmsg": "risky content"}

4.8.3 重要说明

目前上述两个接口仅支持在小程序,示例中的 $app 表示小程序实例,即:

use EasyWeChat\Factory;

$config = [
    'app_id' => 'wx3cf0f39249eb0exx',
    'secret' => 'f1c242f4f28f735d4687abb469072axx',

    // 下面为可选项
    // 指定 API 调用返回结果的类型:array(default)/collection/object/raw/自定义类名
    'response_type' => 'array',

    'log' => [
        'level' => 'debug',
        'file' => __DIR__.'/wechat.log',
    ],
];

$app = Factory::miniProgram($config);

4.9 物流助手 电子面单

4.9.1 获取支持的快递公司列表

https://developers.weixin.qq.com/miniprogram/dev/api-backend/open-api/express/by-business/logistics.getAllDelivery.html

$app->express->listProviders();

{
  "count": 8,
  "data": [
    {
      "delivery_id": "BEST",
      "delivery_name": "百世快递"
    },
    ...
  ]
}

4.9.2 生成运单

https://developers.weixin.qq.com/miniprogram/dev/api-backend/open-api/express/by-business/logistics.addOrder.html

$app->express->createWaybill($data);

// 成功返回
{
  "order_id": "01234567890123456789",
  "waybill_id": "123456789",
  "waybill_data": [
    {
      "key": "SF_bagAddr",
      "value": "广州"
    },
    {
      "key": "SF_mark",
      "value": "101- 07-03 509"
    }
  ]
}

// 失败返回
{
  "errcode": 9300501,
  "errmsg": "delivery logic fail",
  "delivery_resultcode": 10002,
  "delivery_resultmsg": "客户密码不正确"
}

4.9.3 取消运单

https://developers.weixin.qq.com/miniprogram/dev/api-backend/open-api/express/by-business/logistics.cancelOrder.html

$app->express->deleteWaybill($data);

4.9.4 获取运单数据

https://developers.weixin.qq.com/miniprogram/dev/api-backend/open-api/express/by-business/logistics.getOrder.html

$app->express->getWaybill($data);

4.9.5 查询运单轨迹

https://developers.weixin.qq.com/miniprogram/dev/api-backend/open-api/express/by-business/logistics.getPath.html

$app->express->getWaybillTrack($data);

4.9.6 获取电子面单余额。

仅在使用加盟类快递公司时,才可以调用。

https://developers.weixin.qq.com/miniprogram/dev/api-backend/open-api/express/by-business/logistics.getQuota.html

$app->express->getBalance($deliveryId, $bizId);
// 例如:
$app->express->getBalance('YTO', 'xyz');

4.9.7 绑定打印员

若要用微信打单 PC 软件,才需要调用。

https://developers.weixin.qq.com/miniprogram/dev/api-backend/open-api/express/by-business/logistics.updatePrinter.html

$app->express->bindPrinter($openid);

4.9.8 解绑打印员

若需要使用微信打单 PC 软件,才需要调用。

https://developers.weixin.qq.com/miniprogram/dev/api-backend/open-api/express/by-business/logistics.updatePrinter.html

$app->express->unbindPrinter($openid);

4.10 生物认证

4.10.1 生物认证秘钥签名验证

https://developers.weixin.qq.com/miniprogram/dev/api-backend/open-api/soter/soter.verifySignature.html

$app->soter->verifySignature($openid, $json, $signature);

返回值示例:

{"is_ok": true}

参数说明:

  • string $openid - 用户 openid
  • string $json - 通过 wx.startSoterAuthentication 成功回调获得的 resultJSON 字段
  • string $signature - 通过 wx.startSoterAuthentication 成功回调获得的 resultJSONSignature 字段

4.11 插件管理

微信文档:https://developers.weixin.qq.com/miniprogram/dev/api-backend/open-api/plugin-management/pluginManager.applyPlugin.html

4.11.1 申请使用插件

$pluginAppId = 'xxxxxxxxx';

$app->plugin->apply($pluginAppId);

4.11.2 删除已添加的插件

$pluginAppId = 'xxxxxxxxx';

$app->plugin->unbind($pluginAppId);

4.11.3 查询已添加的插件

$app->plugin->list();

4.11.4 获取当前所有插件使用方

$page = 1;
$size = 10;

$app->plugin_dev->getUsers($page, $size);

4.11.5 同意插件使用申请

$appId = 'wxxxxxxxxxxxxxx';

$app->plugin_dev->agree($appId);

4.11.6 拒绝插件使用申请

$app->plugin_dev->refuse('拒绝理由');

4.11.7 删除已拒绝的申请者

$app->plugin_dev->delete();

4.12 附近的小程序

微信文档:https://developers.weixin.qq.com/miniprogram/dev/api-backend/open-api/nearby-poi/nearbyPoi.add.html

4.12.1 添加地点

$params = [
    'kf_info' => '{"open_kf":true,"kf_headimg":"http://mmbiz.qpic.cn/mmbiz_jpg/kKMgNtnEfQzDKpLXYhgo3W3Gndl34gITqmP914zSwhajIEJzUPpx40P7R8fRe1QmicneQMhFzpZNhSLjrvU1pIA/0?wx_fmt=jpeg","kf_name":"Harden"}',
    'pic_list' => '{"list":["http://mmbiz.qpic.cn/mmbiz_jpg/kKMgNtnEfQzDKpLXYhgo3W3Gndl34gITqmP914zSwhajIEJzUPpx40P7R8fRe1QmicneQMhFzpZNhSLjrvU1pIA/0?wx_fmt=jpeg","http://mmbiz.qpic.cn/mmbiz_jpg/kKMgNtnEfQzDKpLXYhgo3W3Gndl34gITRneE5FS9uYruXGMmrtmhsBySwddEWUGOibG8Ze2NT5E3Dyt79I0htNg/0?wx_fmt=jpeg"]}',
    'service_infos' => '{"service_infos":[{"id":2,"type":1,"name":"快递","appid":"wx1373169e494e0c39","path":"index"},{"id":0,"type":2,"name":"自定义","appid":"wx1373169e494e0c39","path":"index"}]}',
    'store_name' => '羊村小马烧烤',
    'contract_phone' => '111111111',
    'hour' => '00:00-11:11',
    'company_name' => '深圳市腾讯计算机系统有限公司',
    'credential' => '156718193518281',
    'address' => '新疆维吾尔自治区克拉玛依市克拉玛依区碧水路15-1-8号(碧水云天广场)',
    'qualification_list' => '3LaLzqiTrQcD20DlX_o-OV1-nlYMu7sdVAL7SV2PrxVyjZFZZmB3O6LPGaYXlZWq',
];

$app->nearby_poi->add($params);

4.12.2 更新地点

$poiId = 'xxxxxxxx';

$params = [
    'kf_info' => '{"open_kf":true,"kf_headimg":"http://mmbiz.qpic.cn/mmbiz_jpg/kKMgNtnEfQzDKpLXYhgo3W3Gndl34gITqmP914zSwhajIEJzUPpx40P7R8fRe1QmicneQMhFzpZNhSLjrvU1pIA/0?wx_fmt=jpeg","kf_name":"Harden"}',
    'pic_list' => '{"list":["http://mmbiz.qpic.cn/mmbiz_jpg/kKMgNtnEfQzDKpLXYhgo3W3Gndl34gITqmP914zSwhajIEJzUPpx40P7R8fRe1QmicneQMhFzpZNhSLjrvU1pIA/0?wx_fmt=jpeg","http://mmbiz.qpic.cn/mmbiz_jpg/kKMgNtnEfQzDKpLXYhgo3W3Gndl34gITRneE5FS9uYruXGMmrtmhsBySwddEWUGOibG8Ze2NT5E3Dyt79I0htNg/0?wx_fmt=jpeg"]}',
    'service_infos' => '{"service_infos":[{"id":2,"type":1,"name":"快递","appid":"wx1373169e494e0c39","path":"index"},{"id":0,"type":2,"name":"自定义","appid":"wx1373169e494e0c39","path":"index"}]}',
    'contract_phone' => '111111111',
    'hour' => '00:00-11:11',
    'company_name' => '深圳市腾讯计算机系统有限公司',
    'credential' => '156718193518281',
    'address' => '新疆维吾尔自治区克拉玛依市克拉玛依区碧水路15-1-8号(碧水云天广场)',
    'qualification_list' => '3LaLzqiTrQcD20DlX_o-OV1-nlYMu7sdVAL7SV2PrxVyjZFZZmB3O6LPGaYXlZWq',
];
$app->nearby_poi->update($poiId, $params);

4.12.3 删除地点

$poiId = 'xxxxxxxx';
$app->nearby_poi->delete($poiId);

4.12.4 地点列表

$page = 1;
$pageRows = 10;
$app->nearby_poi->list($page, $pageRows);

4.12.5 设置地点展示状态

$poiId = 'xxxxxxxx';
$status = 0; // 0: 不展示,1:展示
$app->nearby_poi->setVisibility($poiId, $status);

4.13 订阅消息

微信文档:https://developers.weixin.qq.com/miniprogram/dev/api-backend/open-api/subscribe-message/subscribeMessage.addTemplate.html

4.13.1 组合模板并添加至帐号下的个人模板库

$tid = 563;     // 模板标题 id,可通过接口获取,也可登录小程序后台查看获取
$kidList = [1, 2];      // 开发者自行组合好的模板关键词列表,可以通过 `getTemplateKeywords` 方法获取
$sceneDesc = '提示用户图书到期';    // 服务场景描述,非必填

$app->subscribe_message->addTemplate($tid, $kidList, $sceneDesc);

4.13.2 删除帐号下的个人模板

$templateId = 'bDmywsp2oEHjwAadTGKkUHpC0RgBVPvfAM7Cu1s03z8';

$app->subscribe_message->deleteTemplate($templateId);

4.13.3 获取小程序账号的类目

$app->subscribe_message->getCategory();

4.13.4 获取模板标题的关键词列表

$tid = 563; //模板标题id,可通过接口获取,也可登小程序后台查看获取
$app->subscribe_message->getTemplateKeywords($tid);

4.13.5 获取帐号所属类目下的公共模板标题

$ids = [612, 613];  // 类目 id
$start = 0;         // 用于分页,从 start 开始。从 0 开始计数。  
$limit = 30;        // 用于分页,表拉取 limit 条记录。最大 30。

$app->subscribe_message->getTemplateTitles($ids, $start, $limit);

4.13.6 获取当前帐号下的个人模板列表

$app->subscribe_message->getTemplates();

4.13.7 发送订阅消息

$data = [
    'template_id' => 'bDmywsp2oEHjwAadTGKkUJ-eJEiMiOf7H-dZ7wjdw80', // 所需下发的订阅模板id
    'touser' => 'oSyZp5OBNPBRhG-7BVgWxbiNZm',     // 接收者(用户)的 openid
    'page' => '',       // 点击模板卡片后的跳转页面,仅限本小程序内的页面。支持带参数,(示例index?foo=bar)。该字段不填则模板无跳转。
    'data' => [         // 模板内容,格式形如 { "key1": { "value": any }, "key2": { "value": any } }
        'date01' => [
            'value' => '2019-12-01',
        ],
        'number01' => [
            'value' => 10,
        ],
    ],
];

$app->subscribe_message->send($data);

五、开放平台

六、企业微信

七、企业微信开放平台

八、小微商户

九、自定义

你可能感兴趣的:(wechat开发)