1 はじめに
ミニ プログラムのサービス機能を強化し、サービス品質を向上させるために、WeChat はミニ プログラムの顧客サービス メッセージング機能を提供し、ミニ プログラム ユーザーがミニ プログラム サービス プロバイダーと便利かつ迅速に通信できるようにします。
2. 機能紹介
ユーザーは、ミニ プログラムのカスタマー サービス メッセージ機能を使用して、ミニ プログラムのカスタマー サービス担当者と通信できます。
カスタマー サービス メッセージ セッション エントリは 2 つあります。
1. アプレット内: 開発者はアプレットにカスタマー サービス メッセージ ボタン コンポーネントを追加します。ユーザーはアプレットでカスタマー サービス セッション ページを呼び出し、アプレットにメッセージを送信できます。
2. 使用されたミニ プログラム カスタマー サービス メッセージは、WeChat セッションの [ミニ プログラム カスタマー サービス メッセージ] ボックスに集約されて表示され、ユーザーはミニ プログラム外で過去のカスタマー サービス メッセージを表示したり、ミニ プログラムにメッセージを送信したりできます。
カスタマー サービス メッセージの送信条件: ミニ プログラム ユーザーがミニ プログラムでカスタマー サービス セッションを開始するか、ユーザーがミニ プログラム カスタマー サービスにメッセージを送信する 具体的な送信時間、有効期間、メッセージ数の制限については、お問い合わせください。カスタマーサービスメッセージの送信条件を参照してください。
カスタマー サービス メッセージ タイプ: 現在、テキスト、画像、およびミニ プログラム カード タイプのメッセージをサポートしています。
ミニ プログラム開発者のニーズにできる限り応えるために、ミニ プログラムは次の 3 つの方法でカスタマー サービス メッセージを送信できます: 1. API を呼び出してカスタマー サービス メッセージを送信する; 2. Web 上のカスタマー サービス ツールを使用する;プログラム。
3. 発行条件説明
ユーザーが特定のアクション (特定のアクション リストについては以下の説明を参照) を使用してミニ プログラム カスタマー サービスと対話すると、ミニ プログラムはユーザーにカスタマー サービス メッセージを送信できます。
現在許可されているアクションのリストは次のとおりです。さまざまなアクションがトリガーされた後、送信できるメッセージの数と送信の制限時間が異なります。送信スレッド数が上限に達した場合はエラーコードが返されます。
ユーザーアクション |
許可されるスレッド数の制限 |
解放期限 |
ユーザーがメッセージを送信 |
5ピース |
48時間 |
送信できるカスタマー サービス メッセージの数は蓄積されません。上記のユーザー アクションにより、送信できるメッセージの数と配信の制限時間が更新されます。送信できるメッセージの数は、次のように更新されます。現在送信できるメッセージ数の最大制限。この制限は最大有効時間でも更新されます。
4. カスタマー サービス メッセージ インターフェイスを呼び出してカスタマー サービス メッセージを送信します
ユーザーがミニ プログラム カスタマー サービスにメッセージを送信すると、WeChat サーバーは、開発者が入力した URL にメッセージ (またはイベント) データ パケット (JSON または XML 形式) を POST します。リクエストを受信した後、開発者は非同期応答のためにインターフェイスを呼び出すことができます。
ミニ プログラムのカスタマー サービス メッセージ権限セットがサードパーティ プラットフォームに承認されている場合、すべてのカスタマー サービス メッセージはサードパーティ プラットフォームのサーバーにプッシュされ、開発者のサーバーやカスタマー サービス ツールの Web バージョン
メッセージプッシュ設定を入力します
アプレットにログインし、「設定-開発設定-メッセージプッシュ」でメッセージプッシュ機能を有効にし、関連情報(サーバーアドレス、トークン、暗号化方式など)の設定を完了します。
サーバー構成を有効にして設定すると、ユーザーが送信したメッセージと開発者が必要とするイベント プッシュが WeChat によって開発者 URL に転送されます。
インターフェース呼び出し
ミニ プログラム カスタマー サービス メッセージ API ドキュメント
5. 事例紹介
関連 Web サイト:
カスタマー サービス メッセージの送信: https://developers.weixin.qq.com/miniprogram/dev/OpenApiDoc/kf-mgnt/kf-message/sendCustomMessage.html
カスタマー サービス機能ガイド: https://developers.weixin。 qq.com/miniprogram/introduction/custom.htmlServer
-mini プログラム カスタマー サービス ニュース: https://developers.weixin.qq.com/miniprogram/dev/OpenApiDoc/#%E5%B0%8F%E7%A8%8B% E5 %BA%8F%E5%AE%A2%E6%9C%8D
アプレット メッセージ SDK: リンク: https://pan.baidu.com/s/1ekDtfwfnegRngKOOGzMK1g 抽出コード: n1tr
フレームワークはケースとして yii2 を使用します
<?php
/**
* 微信消息回复
*/
namespace frontend\controllers;
use Yii;
/**
* Class WxMsgController
* @package frontend\controllers
*/
class WxMsgController extends BaseController
{
/**
* 入口
* @throws \Exception
*/
public function actionIndex()
{
//校验服务器地址URL
if (isset($_GET['echostr'])) {
$this->valid();
} else {
$this->responseMsg();
}
}
/**
* 校验
*/
public function valid()
{
$echoStr = $_GET["echostr"];
if ($this->checkSignature()) {
header('content-type:text');
echo $echoStr;
exit;
} else {
echo $echoStr . '+++' . Yii::$app->params['payment.wx']['token'];
exit;
}
}
private function checkSignature()
{
$signature = $_GET["signature"];
$timestamp = $_GET["timestamp"];
$nonce = $_GET["nonce"];
$token = Yii::$app->params['wx']['token']; // 小程序消息通知token
$tmpArr = array($token, $timestamp, $nonce);
sort($tmpArr, SORT_STRING);
$tmpStr = implode($tmpArr);
$tmpStr = sha1($tmpStr);
if ($tmpStr == $signature) {
return true;
} else {
return false;
}
}
/**
* 接受消息和事件:https://developers.weixin.qq.com/miniprogram/dev/framework/open-ability/customer-message/receive.html
* 发送消息:https://developers.weixin.qq.com/miniprogram/dev/api-backend/open-api/customer-message/customerServiceMessage.send.html
* @throws \Exception
*/
public function responseMsg()
{
//小程序相关sdk
$dir = Yii::getAlias('@common/lib/wx-applet-service-crypto-php');
require_once $dir . '/wxBizMsgCrypt.php';
//获取微信服务端发送请求
$postStr = file_get_contents('php://input');
$timeStamp = $_GET["timestamp"];
$msgSignature = $_GET["msg_signature"];
$nonce = $_GET["nonce"];
//微信相关配置
$config = Yii::$app->params['wx'];
//小程序应用ID
$appId = $config['app_id'];
//小程序消息通知 消息加密密钥
$encodingAesKey = $config['encodingAESKey'];
//小程序消息通知token
$token = $config['token'];
try {
$pc = new \WXBizMsgCrypt($token, $encodingAesKey, $appId);
// 第三方收到公众号平台发送的消息
$msg = '';
//校验
$errCode = $pc->decryptMsg($msgSignature, $timeStamp, $nonce, $postStr, $msg);
if ($errCode != 0) {
throw new \Exception('in errCode: ' . $errCode);
}
$postObj = simplexml_load_string($msg, 'SimpleXMLElement', LIBXML_NOCDATA);
if (!empty($msg) && is_object($postObj)) {
$fromUsername = (string)$postObj->FromUserName;
$createTime = (string)$postObj->CreateTime;
$msgType = (string)$postObj->MsgType;
$event = (string)$postObj->Event;
if (!empty($msgType) && $msgType == 'text') { //发送文本消息
// 发送文案
$content = '扫码,加我,咨询';
$data = array(
"touser" => $fromUsername,
"msgtype" => "text",
"text" => array("content" => $content)
);
$json = json_encode($data, JSON_UNESCAPED_UNICODE); //php5.4+
$this->requestAPI($json);
} elseif (!empty($msgType) && $msgType == 'image') { //发送图片消息
// 发送图片
$imgurl = '/images/service_code.png'; //二维码,相对路径,修改为自己的
$media_id = $this->getMediaId($imgurl); // 输入想要回复的图片消息的media_id
$data = array(
"touser" => $fromUsername,
"msgtype" => "image",
"image" => array("media_id" => $media_id)
);
$param = json_encode($data, JSON_UNESCAPED_UNICODE); //php5.4以上版本才可使用
$this->requestAPI($param);
} elseif (!empty($msgType) && $msgType == 'link') { //用户发送图文链接
//构建向微信客服发送的参数
$text = [
'url' => "www.xxx.com",
'thumb_url' => 'thumb_url',
'title' => "测试",
'description' => "测试des",
];
// 发送图文链接
$data = array(
"touser" => $fromUsername,
"msgtype" => "link",
"text" => $text
);
$json = json_encode($data, JSON_UNESCAPED_UNICODE); //php5.4+
$this->requestAPI($json);
} elseif (!empty($msgType) && $msgType == 'miniprogrampage') { //用户发送小程序卡片
//逻辑代码
} elseif ($msgType == 'event' && $event == 'user_enter_tempsession') { //用户发送小程序卡片
//解决接收用户消息重复发送:腾讯那边迟迟接不到回音,就会重复请求,这样就会重复发三次客服消息
$key = sprintf("service_msg:%s:%s", $fromUsername, $createTime);
//判断redis中key是否存在
$redisUser = Yii::$app->redis_user;
if ($redisUser->exists($key)) {
exit;
}
$redisUser->set($key, 1);
$redisUser->expire($key, 15);
//逻辑代码
}
} else {
throw new \Exception('in empty msgType: ' . $msg);
exit;
}
} catch (\Exception $e) {
// 发送error文案
$content = $e->getMessage();
$data = array(
"touser" => $fromUsername,
"msgtype" => "text",
"text" => array("content" => $content)
);
$json = json_encode($data, JSON_UNESCAPED_UNICODE); //php5.4+
$this->requestAPI($json);
throw $e;
}
}
/**
* @param $param
*/
public function requestApi($param, $type = 'json')
{
$access_token = $this->get_accessToken();
/*
* POST发送https请求客服接口api
*/
$url = "https://api.weixin.qq.com/cgi-bin/message/custom/send?access_token=" . $access_token;
if ($type == 'xml') {
//以'xml'格式发送post的https请求
$header[] = "Content-type: text/xml";
$curl = curl_init();
curl_setopt($curl, CURLOPT_URL, $url);
curl_setopt($curl, CURLOPT_POST, 1);
if (!empty($param)) {
curl_setopt($curl, CURLOPT_POSTFIELDS, $param);
}
curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($curl, CURLOPT_HTTPHEADER, $header);
$output = curl_exec($curl);
if (curl_errno($curl)) {
echo 'Errno' . curl_error($curl);//捕抓异常
}
curl_close($curl);
if ($output == 0) {
echo 'success';
}
} else {
//以'json'格式发送post的https请求
$curl = curl_init();
curl_setopt($curl, CURLOPT_URL, $url);
curl_setopt($curl, CURLOPT_POST, 1); // 发送一个常规的Post请求
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, false);
if (!empty($param)) {
curl_setopt($curl, CURLOPT_POSTFIELDS, $param);
}
curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
//curl_setopt($curl, CURLOPT_HTTPHEADER, $headers );
$output = curl_exec($curl);
if (curl_errno($curl)) {
echo 'Errno' . curl_error($curl);//捕抓异常
}
curl_close($curl);
if ($output == 0) {
echo 'success';
}
}
}
/**
* 获取上传图片的media_id
* @param $imgurl
* @return null
*/
public function getMediaId($imgurl)
{
$mediaKey = 'media_key';
$mediaId = Yii::$app->cache->get($mediaKey);
if ($mediaId) {
return $mediaId;
}
$token = $this->get_accessToken();
$url = "https://api.weixin.qq.com/cgi-bin/media/upload?access_token={$token}&type=image";
$ch1 = curl_init();
$timeout = 10;
$real_path = "{$_SERVER['DOCUMENT_ROOT']}$imgurl";//自动转成图片文件绝对路径,如果图片发送失败,检查PHP的$_SERVER['DOCUMENT_ROOT'的配置
$data = array("media" => new \CURLFile("{$real_path}"));//php5.6(含)以上版本使用此方法
curl_setopt($ch1, CURLOPT_URL, $url);
curl_setopt($ch1, CURLOPT_POST, 1);
curl_setopt($ch1, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch1, CURLOPT_CONNECTTIMEOUT, $timeout);
curl_setopt($ch1, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch1, CURLOPT_SSL_VERIFYHOST, false);
curl_setopt($ch1, CURLOPT_POSTFIELDS, $data);
$result = curl_exec($ch1);
// echo $result;
curl_close($ch1);
if ($result) {
$result = json_decode($result, true);
Yii::$app->cache->set($mediaKey, $result['media_id'], 3600 * 21 * 3);
return $result['media_id'];
} else {
return null;
}
}
/**
* 调用微信api,获取access_token,有效期7200s -xzz0704
* @return mixed
*/
public function get_accessToken()
{
//微信配置
$config = Yii::$app->params['wx'];
//小程序应用ID
$appId = $config['app_id'];
//小程序应用秘钥
$secret = $config['applet_secret'];
$tokenKey = "access_token";
$access_token = Yii::$app->cache->get($tokenKey);
if (!$access_token) {
$url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=$appId&secret=$secret";
$res = json_decode($this->httpGet($url));
$access_token = $res->access_token;
if ($access_token) {
Yii::$app->cache->set($tokenKey, $access_token, 7000);
}
}
return $access_token;
}
private function httpGet($url)
{
$curl = curl_init();
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
curl_setopt($curl, CURLOPT_TIMEOUT, 500);
// 为保证第三方服务器与微信服务器之间数据传输的安全性,所有微信接口采用https方式调用,必须使用下面2行代码打开ssl安全校验。
// 如果在部署过程中代码在此处验证失败,请到 http://curl.haxx.se/ca/cacert.pem 下载新的证书判别文件。
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, true);
curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, true);
curl_setopt($curl, CURLOPT_URL, $url);
$res = curl_exec($curl);
curl_close($curl);
return $res;
}
}