微信开放平台 – 永夜 https://www.shuijingwanwq.com 没有不值得去解决的问题,也没有不值得去学习的技术! Fri, 15 May 2026 14:49:57 +0000 zh-Hans hourly 1 https://wordpress.org/?v=7.0 在微信中,使用支付宝在线支付时,需要跳转至系统浏览器中,用户登录状态的丢失的解决方案 https://www.shuijingwanwq.com/2025/07/03/9184/ https://www.shuijingwanwq.com/2025/07/03/9184/#respond Thu, 03 Jul 2025 02:31:19 +0000 https://www.shuijingwanwq.com/?p=9184 浏览量: 247 1、现有的实现,一个接口,是在微信中获取支付宝的支付链接(需要登录),还有一个回调接口(需要验签),还有一个查询接口(需要登录)。现在由于支付在线支付只能够在系统浏览器中进行,那么查询接口需要设置为游客可访问。为了保证安全性,决定做一个签名认证 2、在获取支付链接的接口中,如下实现
<?php

namespace api\helpers;

class AlipayQuerySignerHelper
{
    /**
     * 获取签名
     *
     * @param array $data 待签名数据(键值对)
     * @param string $secret 签名密钥
     * @return string 返回签名字符串
     */
    public static function sign(array $data, string $secret): string
    {
        // 确保按 key 升序排列,签名一致
        ksort($data);

        // 拼接成 key=value&key2=value2 的格式
        $queryString = http_build_query($data, '', '&', PHP_QUERY_RFC3986);

        // 生成签名
        return hash_hmac('sha256', $queryString, $secret);
    }

    /**
     * 验证签名
     *
     * @param array $data 待验证的数据(必须包含 query_sign 字段)
     * @param string $secret 签名密钥
     * @param int $timeout 签名超时时间(默认 600 秒)
     * @return bool
     */
    public static function verify(array $data, string $secret, int $timeout = 6000): bool
    {
        if (!isset($data['query_sign'], $data['query_timestamp'])) {
            return false;
        }

        // 判断时间是否超出容忍范围(默认 ±5 分钟)
        if (abs(time() - $data['query_timestamp']) > $timeout) {
            return false;
        }

        $providedSign = $data['query_sign'];
        unset($data['query_sign']);

        $expectedSign = self::sign($data, $secret);

        return hash_equals($expectedSign, $providedSign);
    }
}

$payload = [
	'query_order_id' => $order->id,
	'query_user_id' => $order->user_id,
	'query_timestamp' => time(),
];

$secret = Yii::$app->params['alipayQuerySignatureKey'];

$sign = AlipayQuerySignerHelper::sign($payload, $secret);

$query = array_merge($payload, ['query_sign' => $sign]);

$queryString = http_build_query($query);

$returnUrl = Yii::$app->params['frontendDomainHttps'] . '/convention/#/pages/ticket_payment_result/ticket_payment_result?convention_id=' . $ticketOrder->convention_id . '&ticket_id=' . $ticketOrder->id . '&_version=2&' . $queryString;

3、在查询接口中如下实现,接口响应,如图1
在查询接口中如下实现,接口响应

图1

        $params = Yii::$app->request->post();
        $secret = Yii::$app->params['alipayQuerySignatureKey'];

        if (!AlipayQuerySignerHelper::verify($params, $secret)) {
            return [
                'code' => 10010,
                'message' => '签名验证失败',
            ];
        }

//        if (strcmp($order->user_id, Yii::$app->user->id) != 0) {
//            return [
//                'code' => 10008,
//                'message' => '您没权限进行该操作',
//            ];
//        }
]]>
https://www.shuijingwanwq.com/2025/07/03/9184/feed/ 0
在请求 获取不限制的小程序码 接口时,可能响应:图片 Buffer 。可能响应:JSON 字符串。设置了响应格式为:raw-urlencoded 。如何判断接口请求是成功还是失败? https://www.shuijingwanwq.com/2025/05/12/9017/ https://www.shuijingwanwq.com/2025/05/12/9017/#respond Mon, 12 May 2025 01:38:25 +0000 https://www.shuijingwanwq.com/?p=9017 浏览量: 110 1、PHP 代码实现如下


    /**
     * 获取不限制的小程序码
     * @param $accessToken
     * @param $scene
     * @param $page
     * @param $width
     * @return mixed
     * @throws ServerErrorHttpException
     */
    public function getUnlimitedQRCode($accessToken, $scene, $page = null, $width = 430)
    {
        $response = $this->httpClient->createRequest()
            ->setMethod('POST')
            ->setUrl('wxa/getwxacodeunlimit?access_token=' . $accessToken)
            ->setFormat(Client::FORMAT_JSON)
            ->setData([
                'scene' => $scene,
                'page' => $page,
                'width' => $width,
                'check_path' => false,
                'env_version' => 'trial'
            ])
            ->send();

        // 设置响应格式为 raw-urlencoded(二进制数据)
        $response->format = Client::FORMAT_RAW_URLENCODED;

        // 检查响应状态码是否等于20x
        if ($response->isOk) {
            // 检查业务逻辑是否成功
            if (isset($response->data['errcode']) && isset($response->data['errcode'])) {
                throw new ServerErrorHttpException('获取不限制的小程序码失败,errcode:' . $response->data['errcode'] . ',errmsg:' . $response->data['errmsg'], 20021);
            }
        } else {
            throw new ServerErrorHttpException('获取不限制的小程序码失败,status_code:' . $response->statusCode, 20022);
        }

        return $response->content;
    }


2、当响应为非 图片 Buffer 时,写入图片文件中的数据有误。图片无法打开。最终决定通过 响应头 Content-Type 来进行区分。如图1
当响应为非 图片 Buffer 时,写入图片文件中的数据有误。图片无法打开。最终决定通过 响应头 Content-Type 来进行区分

图1



application/json; encoding=utf-8
image/jpeg




    /**
     * 获取不限制的小程序码
     * @param $accessToken
     * @param $scene
     * @param $page
     * @param $width
     * @return mixed
     * @throws ServerErrorHttpException
     */
    public function getUnlimitedQRCode($accessToken, $scene, $page = null, $width = 430)
    {
        $response = $this->httpClient->createRequest()
            ->setMethod('POST')
            ->setUrl('wxa/getwxacodeunlimit?access_token=' . $accessToken)
            ->setFormat(Client::FORMAT_JSON)
            ->setData([
                'scene' => $scene,
                'page' => $page,
                'width' => $width,
                'check_path' => false,
                'env_version' => 'trial'
            ])
            ->send();

        // 检查响应状态码是否等于20x
        if ($response->isOk) {
            $contentType = $response->getHeaders()->get('Content-Type');
            if (strpos($contentType, 'image/') !== false) {
                return $response->content;
            } elseif (strpos($contentType, 'application/json') !== false && isset($response->data['errcode']) && isset($response->data['errcode'])) {
                throw new ServerErrorHttpException('获取不限制的小程序码失败,错误码:' . $response->data['errcode'] . ',错误信息:' . $response->data['errmsg'], 20021);
            } else {
                // 未知响应类型
                throw new ServerErrorHttpException('获取不限制的小程序码失败,未知响应类型:' . $contentType, 20023);
            }
        } else {
            throw new ServerErrorHttpException('获取不限制的小程序码失败,HTTP 状态码:' . $response->statusCode, 20022);
        }
    }


3、当响应为非 图片 Buffer 时,yii\web\ServerErrorHttpException: 获取不限制的小程序码失败,错误码:40001,错误信息:invalid credential。如图2
当响应为非 图片 Buffer 时,yii\web\ServerErrorHttpException: 获取不限制的小程序码失败,错误码:40001,错误信息:invalid credential

图2



{
    "code": 10000,
    "message": "生成微信小程序二维码成功",
    "data": {
        "url": "/mini-program-qr-codes/644d4a4c0fff836ec9ac17d86d0911aa.png"
    }
}


yii\web\ServerErrorHttpException: 获取不限制的小程序码失败,错误码:40001,错误信息:invalid credential, access_token is invalid or not latest, could get access_token by getStableAccessToken, more details at https://mmbizurl.cn/s/JtxxFh33r rid: 67d90e17-47a89f95-26c1c8de 


]]>
https://www.shuijingwanwq.com/2025/05/12/9017/feed/ 0
在请求微信小程序接口:获取不限制的小程序码 时,一些问题的排查分析(errcode:41030,errmsg:invalid page rid、errcode:47001,errmsg:data format error rid、Unrecognized format ”) https://www.shuijingwanwq.com/2025/04/27/8990/ https://www.shuijingwanwq.com/2025/04/27/8990/#respond Sun, 27 Apr 2025 08:26:32 +0000 https://www.shuijingwanwq.com/?p=8990 浏览量: 257 1、在请求微信小程序接口:获取不限制的小程序码 时,报错:errcode:47001,errmsg:data format error rid。如图1
在请求微信小程序接口:获取不限制的小程序码 时,报错:errcode:47001,errmsg:data format error rid

图1



POST https://api.weixin.qq.com/wxa/getwxacodeunlimit?access_token={token}
Content-Type: application/x-www-form-urlencoded; charset=UTF-8

scene=1825203750690640&page=pages%2Findex%2Findex


2、调整请求参数的 Content-Type ,得以解决。然后报另外一个错误:errcode:41030,errmsg:invalid page rid。如图2
调整请求参数的 Content-Type ,得以解决。然后报另外一个错误:errcode:41030,errmsg:invalid page rid

图2



POST https://api.weixin.qq.com/wxa/getwxacodeunlimit?access_token={token}
Content-Type: application/json; charset=UTF-8

{"scene":"1825203750690640","page":"pages\/index\/index","width":null}


3、调整请求参数的 “check_path”:false ,得以解决。然后报另外一个错误:Unrecognized format ”。如图3
调整请求参数的 "check_path":false ,得以解决。然后报另外一个错误:Unrecognized format ''

图3



POST https://api.weixin.qq.com/wxa/getwxacodeunlimit?access_token={token}
Content-Type: application/json; charset=UTF-8

{"scene":"1825203750690640","page":"pages\/index\/index","width":null,"check_path":false}


4、调整响应格式为 raw-urlencoded,得以解决


        $response = $this->httpClient->createRequest()
            ->setMethod('POST')
            ->setUrl('wxa/getwxacodeunlimit?access_token=' . $accessToken)
            ->setFormat(Client::FORMAT_JSON)
            ->setData([
                'scene' => $scene,
                'page' => $page,
                'width' => $width,
                'check_path' => false,
                'env_version' => 'trial'
            ])
            ->send();

        // 设置响应格式为 raw-urlencoded(二进制数据)
        $response->format = Client::FORMAT_RAW_URLENCODED;


]]>
https://www.shuijingwanwq.com/2025/04/27/8990/feed/ 0
在微信公众帐号授权后,点击 继续访问 按钮无反应 的排查分析 https://www.shuijingwanwq.com/2021/10/29/5421/ https://www.shuijingwanwq.com/2021/10/29/5421/#respond Fri, 29 Oct 2021 02:41:52 +0000 https://www.shuijingwanwq.com/?p=5421 浏览量: 629 1、在微信中打开链接,公众帐号申请获得:获取你的昵称、头像,点击 允许 按钮。如图1
在微信中打开链接,公众帐号申请获得:获取你的昵称、头像,点击 允许 按钮。

图1

2、在微信公众帐号授权后,该网页可能不是由微信提供,微信无法确保内容的安全性,如果要继续访问,请注意保护好个人信息。点击 继续访问 按钮无反应。如图2
在微信公众帐号授权后,该网页可能不是由微信提供,微信无法确保内容的安全性,如果要继续访问,请注意保护好个人信息。点击 继续访问 按钮无反应。

图2

3、查看公众号设置,网页授权域名,是没有问题的。如图3
查看公众号设置,网页授权域名,是没有问题的。

图3

4、点击右上角 …,在浏览器中打开。如图4
点击右上角 ...,在浏览器中打开。

图4

5、在浏览器中点击 继续访问 按钮,弹出安全警告 该网站的安全证书有问题。点击 继续。如图5
在浏览器中点击 继续访问 按钮,弹出安全警告 该网站的安全证书有问题。点击 继续。

图5

6、在浏览器中访问成功。如图6
在浏览器中访问成功。

图6

7、使用微信扫一扫链接所对应的二维码。如图7
使用微信扫一扫链接所对应的二维码。

图7

8、发现扫码后打开空白。但是 Nginx 日志中有相应的请求日志。如图8
发现扫码后打开空白。但是 Nginx 日志中有相应的请求日志。

图8

9、但是 Nginx 日志中有相应的请求日志。请求网址为 redirect_uri 的值。响应状态码为 500。如图9
但是 Nginx 日志中有相应的请求日志。请求网址为 redirect_uri 的值。响应状态码为 500。

图9



{"request":{"headers":{"referer":"-","host":"morefun.webtv.xxx.cn","x-request-id":"8f7867eafed70458126b8451fa701860","x-forwarded-for":"101.207.139.251","user-agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.131 Safari/537.36"},"method":"GET","uri":"/wechat/activities/?id=a4676e6e-acdd-4213-bb46-99fcb30327fd&group_id=3b592c75ee1974509679e28ec2b4fce4","url":"http://morefun.webtv.xxx.cn/wechat/activities/?id=a4676e6e-acdd-4213-bb46-99fcb30327fd&group_id=3b592c75ee1974509679e28ec2b4fce4","@timestamp":"2021-10-28T19:51:38+08:00","upstreamaddr":"127.0.0.1:9000","response":{"responsetime":"1.715","upstream_response_time":"1.714"},"size":"40924","status":"500","module_name":"default-app"}}


10、将跳转网址在浏览器中直接打开,响应 500。原因在于缺少 code 参数。如图10
将跳转网址在浏览器中直接打开,响应 500。原因在于缺少 code 参数。

图10



Authorize Failed: 
{
  "errcode": 41008,
  "errmsg": "missing code, rid: 617a8ec9-02397612-437533f9"
}


11、在浏览器中打开链接,分析请求参数,发现 redirect_uri 的值发生了变化。


Request URL: https://open.weixin.qq.com/connect/oauth2/authorize?appid=wx9dbacb0dd5847fc4&redirect_uri=https%3A%2F%2Fmorefun.webtv.xxx.cn%2Fwechat%2Factivities%2F%3Fid%3Da4676e6e-acdd-4213-bb46-99fcb30327fd%26group_id%3D3b592c75ee1974509679e28ec2b4fce4&response_type=code&scope=snsapi_userinfo&state=47fc4bd999d70f7f8239b6264ec4be32&connect_redirect=1
Request Method: GET

appid: wx9dbacb0dd5847fc4
redirect_uri: https://morefun.webtv.xxx.cn/wechat/activities/?id=a4676e6e-acdd-4213-bb46-99fcb30327fd&group_id=3b592c75ee1974509679e28ec2b4fce4
response_type: code
scope: snsapi_userinfo
state: 47fc4bd999d70f7f8239b6264ec4be32
connect_redirect: 1


12、JS接口安全域名,添加:morefun.webtv.xxx.cn。如图11
JS接口安全域名,添加:morefun.webtv.xxx.cn。

图11

13、优先解决证书的问题,将 redirect_uri 的 https 协议替换为 http 协议。点击 继续访问 按钮跳转至 redirect_uri 的地址。备注:此处不能够直接替换链接中的协议,需要从新授权进入。如图12
优先解决证书的问题,将 redirect_uri 的 https 协议替换为 http 协议。点击 继续访问 按钮跳转至 redirect_uri 的地址。备注:此处不能够直接替换链接中的协议,需要从新授权进入。

图12

14、使用微信扫一扫链接所对应的二维码。扫码后也能够打开成功,不再空白。 15、总结:在微信公众帐号授权后,点击 继续访问 按钮无反应,原因在于 该网站的安全证书有问题,如果证书问题无法解决,可将 https 协议替换为 http 协议。      ]]>
https://www.shuijingwanwq.com/2021/10/29/5421/feed/ 0
在 Yii 2.0 中实现国际化,翻译英文描述中的一部分为中文描述(微信接口返回的英文信息) https://www.shuijingwanwq.com/2021/08/05/5144/ https://www.shuijingwanwq.com/2021/08/05/5144/#respond Thu, 05 Aug 2021 02:30:28 +0000 https://www.shuijingwanwq.com/?p=5144 浏览量: 112 1、在请求微信接口时,返回码:45028,返回的英文信息:has no masssend quota rid: 6103df2e-1505ba73-0eb14e1c。如图1
在请求微信接口时,返回码:45028,返回的英文信息:has no masssend quota rid: 6103df2e-1505ba73-0eb14e1c

图1



{
  "errcode": 45028,
  "errmsg": "has no masssend quota rid: 6103df2e-1505ba73-0eb14e1c"
}


2、代码实现如下


$responseData = $wxServiceApi::wxMessageSendAll($requestData);
if (!isset($responseData['msg_id'])) {
    $errcode = array_key_exists('errcode',$responseData)?$responseData['errcode']:205100;
    throw new ServerErrorHttpException(Yii::t('error', Yii::t('error', Yii::t('error', '205100'), ['error_code' => $errcode, 'error_msg' => $responseData['errmsg']])), 205100);
}


3、计划将错误信息:has no masssend quota rid: 6103df2e-1505ba73-0eb14e1c 翻译为:没有群发配额。rid: 6103df2e-1505ba73-0eb14e1c。如图2
计划将错误信息:has no masssend quota rid: 6103df2e-1505ba73-0eb14e1c 翻译为:没有群发配额。rid: 6103df2e-1505ba73-0eb14e1c

图2

4、添加文件 common/messages/en-US/wx.php、common/messages/zh-CN/wx.php、wx/messages/en-US/wx.php、wx/messages/zh-CN/wx.php。如图3
添加文件 common/messages/en-US/wx.php、common/messages/zh-CN/wx.php、wx/messages/en-US/wx.php、wx/messages/zh-CN/wx.php

图3

common/messages/en-US/wx.php
<pre class="wp-block-syntaxhighlighter-code">

<?php
return [
];


</pre>
common/messages/zh-CN/wx.php
<pre class="wp-block-syntaxhighlighter-code">

<?php
return [
    'has no masssend quota' => '没有群发配额(订阅号为每天 1 次,服务号为每月 4 次)。',
    'invalid content' => '无效内容(内容中包含音频)。',
];


</pre>
wx/messages/en-US/wx.php
<pre class="wp-block-syntaxhighlighter-code">

<?php
$commonMessages = require __DIR__ . '/../../../common/messages/en-US/wx.php';
$messages = [
];
return $commonMessages + $messages;


</pre>
wx/messages/zh-CN/wx.php
<pre class="wp-block-syntaxhighlighter-code">

<?php
$commonMessages = require __DIR__ . '/../../../common/messages/zh-CN/wx.php';
$messages = [
];
return $commonMessages + $messages;


</pre>
5、代码实现如下。其中代码:substr($responseData[‘errmsg’], 0, $pos) 的结果为:has no masssend quota。其中代码:substr($responseData[‘errmsg’], $pos) 的结果为: rid: 6103df2e-1505ba73-0eb14e1c。将:has no masssend quota 翻译为:没有群发配额。后,再拼接上: rid: 6103df2e-1505ba73-0eb14e1c。


$responseData = $wxServiceApi::wxMessageSendAll($requestData);
if (!isset($responseData['msg_id'])) {
    $errcode = $responseData['errcode'] ?? 205100;
    $pos = strpos($responseData['errmsg'], ' rid:');
    $errorMsg = Yii::t('wx', substr($responseData['errmsg'], 0, $pos)) . substr($responseData['errmsg'], $pos);
    throw new ServerErrorHttpException(Yii::t('error', Yii::t('error', Yii::t('error', '205100'), ['error_code' => $errcode, 'error_msg' => $errorMsg])), 205100);
}


6、针对返回的英文信息:invalid content hint: [pzRHda0286d228] rid: 61041ffe-5cefd269-6c9611ff,完善后的代码如下。根源在于源语言的消息不支持模糊匹配。


$responseData = $wxServiceApi::wxMessageSendAll($requestData);
if (!isset($responseData['msg_id'])) {
    $errcode = $responseData['errcode'] ?? 205100;
    $errorMsg = '';
    $pos = strpos($responseData['errmsg'], ' hint:');
    if ($pos === false) {
        $pos = strpos($responseData['errmsg'], ' rid:');
    }
    if ($pos !== false) {
        $errorMsg = Yii::t('wx', substr($responseData['errmsg'], 0, $pos)) . substr($responseData['errmsg'], $pos);
    }
    throw new ServerErrorHttpException(Yii::t('error', Yii::t('error', Yii::t('error', '205100'), ['error_code' => $errcode, 'error_msg' => $errorMsg])), 205100);
}


7、测试翻译结果,has no masssend quota rid: 610a50c5-26966176-7cceb46e 已经被翻译为:没有群发配额(订阅号为每天 1 次,服务号为每月 4 次)。rid: 610a50c5-26966176-7cceb46e。符合预期。如图4
测试翻译结果,has no masssend quota rid: 610a50c5-26966176-7cceb46e 已经被翻译为:没有群发配额(订阅号为每天 1 次,服务号为每月 4 次)。rid: 610a50c5-26966176-7cceb46e。符合预期

图4

8、测试翻译结果,invalid content hint: [dN7TKA0474d139] rid: 610a5a7a-5907e6c6-270b8278 已经被翻译为:无效内容(内容中包含音频)。 hint: [dN7TKA0474d139] rid: 610a5a7a-5907e6c6-270b8278。符合预期。如图5
测试翻译结果,invalid content hint: [dN7TKA0474d139] rid: 610a5a7a-5907e6c6-270b8278 已经被翻译为:无效内容(内容中包含音频)。 hint: [dN7TKA0474d139] rid: 610a5a7a-5907e6c6-270b8278。符合预期

图5

9、由于 invalid image size 还未被添加至语言包中,因此:invalid image size hint: [cl_6Oa0457mp13] rid: 6103c6d0-481a4bed-73e7120a 保持原样。符合预期。
<pre class="wp-block-syntaxhighlighter-code">

<?php
return [
    'has no masssend quota' => '没有群发配额(订阅号为每天 1 次,服务号为每月 4 次)。',
    'invalid content' => '无效内容(内容中包含音频)。',
    'invalid image size' => '图片尺寸太大(大小必须在10MB以下)。',
];


</pre>
11、测试翻译结果,invalid image size hint: [flp8Ba0298w689] rid: 610a6969-72bb79c0-4b069755 已经被翻译为:invalid image size hint: [flp8Ba0298w689] rid: 610a6969-72bb79c0-4b069755。蓝框中是翻译前的英文信息,红框中是翻译后的中文信息。符合预期。如图6
测试翻译结果,invalid image size hint: [flp8Ba0298w689] rid: 610a6969-72bb79c0-4b069755 已经被翻译为:invalid image size hint: [flp8Ba0298w689] rid: 610a6969-72bb79c0-4b069755。蓝框中是翻译前的英文信息,红框中是翻译后的中文信息。符合预期

图6

]]>
https://www.shuijingwanwq.com/2021/08/05/5144/feed/ 0
微信第三方应用的授权设计与实现(component_verify_ticket、component_access_token、pre_auth_code) https://www.shuijingwanwq.com/2021/07/20/5093/ https://www.shuijingwanwq.com/2021/07/20/5093/#respond Tue, 20 Jul 2021 10:19:26 +0000 https://www.shuijingwanwq.com/?p=5093 浏览量: 136 1、查看网址:https://developers.weixin.qq.com/doc/oplatform/Third-party_Platforms/2.0/api/Before_Develop/creat_token.html 。微信服务器 每隔 10 分钟会向第三方的消息接收地址推送一次 component_verify_ticket,用于获取第三方平台接口调用凭据。在接口:接收验证票据(接收微信服务器推送) 实现中,获取与缓存第三方平台令牌、获取与缓存第三方平台预授权码。


// 解密成功
if ($errCode === 0) {
    $ticketData = simplexml_load_string($msg, 'SimpleXMLElement', LIBXML_NOCDATA);
    if (isset($ticketData->ComponentVerifyTicket)) {
        $redisCommandkeyPrefix = Yii::$app->params['redisCommand']['keyPrefix'];
        $componentVerifyTicketKey = $redisCommandkeyPrefix . 'component_verify_ticket:' . $ticketData->AppId;
        Yii::$app->redis->set($componentVerifyTicketKey, $ticketData->ComponentVerifyTicket);
        // 获取第三方平台令牌
        WxOpenAuthService::getComponentAccessToken($appId, $appSecret);
        // 获取第三方平台预授权码
        WxOpenAuthService::getComponentPreAuthCode($appId);
    }
}


2、获取第三方平台令牌的实现中,参考网址:https://www.shuijingwanwq.com/2021/07/05/5020/ 。代码如下
<pre class="wp-block-syntaxhighlighter-code">

    /**
     * 获取第三方平台令牌
     *
     * @param $appId string  第三方平台 appId
     * @param $appSecret string 第三方平台 appSecret
     * @return bool
     * @throws ServerErrorHttpException
     * @throws NotFoundHttpException
     */
    public static function getComponentAccessToken($appId, $appSecret)
    {
        $time = time();
        $redis = Yii::$app->redis;
        $redisCommandkeyPrefix = Yii::$app->params['redisCommand']['keyPrefix'];
        $componentVerifyTicketKey = $redisCommandkeyPrefix . 'component_verify_ticket:' . $appId;
        $componentVerifyTicket = $redis->get($componentVerifyTicketKey);
        if (!$componentVerifyTicket) {
            throw new NotFoundHttpException(Yii::t('error', 205059), 205059);
        }
        $componentAccessTokenKey = $redisCommandkeyPrefix . 'component_access_token:' . $appId;
        // 获取 Redis 中的 component_access_token
        $componentAccessToken = $redis->get($componentAccessTokenKey);

        // 判断 Redis 中的 component_access_token 是否存在
        if ($componentAccessToken) {
            $componentAccessToken = unserialize($componentAccessToken);
        }
        if (!$componentAccessToken || (($componentAccessToken['expires_at'] - 900) < $time) ) {
            $data = [
                'component_appid' => $appId,
                'component_appsecret' => $appSecret,
                'component_verify_ticket' => $componentVerifyTicket,
            ];
            $httpWxAuthAccessToken = new HttpWxAuthAccessToken();
            // http 请求获取 component_access_token
            $httpWxAuthAccessTokenResult = $httpWxAuthAccessToken->wxComponentAccessToken($data);
            if ($httpWxAuthAccessTokenResult === false) {
                if ($httpWxAuthAccessToken->hasErrors()) {
                    $firstError = '';
                    foreach ($httpWxAuthAccessToken->getFirstErrors() as $message) {
                        $firstError = $message;
                        break;
                    }
                    throw new ServerErrorHttpException(Yii::t('error', Yii::t('error', Yii::t('error', '205058'), ['first_error' => $firstError])), 205058);
                } elseif (!$httpWxAuthAccessToken->hasErrors()) {
                    throw new ServerErrorHttpException('WeChat third-party platform HTTP requests fail for unknown reasons!');
                }
            }
            // 保存 第三方平台 access_token、有效截止时间 到 Redis
            $componentAccessToken = [
                'component_access_token' => $httpWxAuthAccessTokenResult['data']['component_access_token'],
                'expires_at' => $time + $httpWxAuthAccessTokenResult['data']['expires_in'],
            ];
            $redis->set($componentAccessTokenKey, serialize($componentAccessToken));
            file_put_contents(Yii::getAlias('@runtime') . '/frontend-services-WxOpenAuthService-componentAccessToken-' . microtime(true) . '-' . mt_rand()  . '.txt', print_r($componentAccessToken, true), FILE_APPEND | LOCK_EX);
        }
        return true;
    }

</pre>
3、获取第三方平台预授权码的实现中,与获取第三方平台令牌的实现类似。代码如下
<pre class="wp-block-syntaxhighlighter-code">

    /**
     * 获取第三方平台预授权码
     *
     * @param $appId string  第三方平台 appId
     * @return bool
     * @throws ServerErrorHttpException
     * @throws NotFoundHttpException
     */
    public static function getComponentPreAuthCode($appId)
    {
        $time = time();
        $redis = Yii::$app->redis;
        $redisCommandkeyPrefix = Yii::$app->params['redisCommand']['keyPrefix'];
        $componentAccessTokenKey = $redisCommandkeyPrefix . 'component_access_token:' . $appId;
        $componentAccessToken = $redis->get($componentAccessTokenKey);
        if (!$componentAccessToken) {
            throw new NotFoundHttpException(Yii::t('error', 214017), 214017);
        }
        $componentAccessToken = unserialize($componentAccessToken);
        $componentPreAuthCodeKey = $redisCommandkeyPrefix . 'component_pre_auth_code:' . $appId;
        // 获取 Redis 中的 component_pre_auth_code
        $componentPreAuthCode = $redis->get($componentPreAuthCodeKey);

        // 判断 Redis 中的 component_pre_auth_code 是否存在
        if ($componentPreAuthCode) {
            $componentPreAuthCode = unserialize($componentPreAuthCode);
        }
        if (!$componentPreAuthCode || (($componentPreAuthCode['expires_at'] - 900) < $time) ) {
            $data = [
                'component_appid' => $appId,
            ];
            $httpWxAuthAccessToken = new HttpWxAuthAccessToken();
            // http 请求获取 pre_auth_code
            $httpWxAuthAccessTokenResult = $httpWxAuthAccessToken->wxComponentPreAuthCode($data, $componentAccessToken['component_access_token']);
            if ($httpWxAuthAccessTokenResult === false) {
                if ($httpWxAuthAccessToken->hasErrors()) {
                    $firstError = '';
                    foreach ($httpWxAuthAccessToken->getFirstErrors() as $message) {
                        $firstError = $message;
                        break;
                    }
                    throw new ServerErrorHttpException(Yii::t('error', Yii::t('error', Yii::t('error', '217004'), ['first_error' => $firstError])), 217004);
                } elseif (!$httpWxAuthAccessToken->hasErrors()) {
                    throw new ServerErrorHttpException('WeChat third-party platform HTTP requests fail for unknown reasons!');
                }
            }
            // 保存 第三方平台 pre_auth_code、有效截止时间 到 Redis
            $componentPreAuthCode = [
                'pre_auth_code' => $httpWxAuthAccessTokenResult['data']['pre_auth_code'],
                'expires_at' => $time + $httpWxAuthAccessTokenResult['data']['expires_in'],
            ];
            $redis->set($componentPreAuthCodeKey, serialize($componentPreAuthCode));
            file_put_contents(Yii::getAlias('@runtime') . '/frontend-services-WxOpenAuthService-componentPreAuthCode-' . microtime(true) . '-' . mt_rand()  . '.txt', print_r($componentPreAuthCode, true), FILE_APPEND | LOCK_EX);
        }
        return true;
    }

</pre>
4、HTTP 模型代码如下


    /**
     * HTTP请求,微信第三方平台通过 component_verify_ticket 获取第三方平台的 component_access_token
     * @param array $data 数据
     * 格式如下:
     *
     * [
     *     'component_appid' => 'wxd7f67f1792c6e238', // 第三方平台 appId
     *     'component_appsecret' => '9853ba602cae7a31b4dacd7978ad75c6', // 第三方平台 appSecret
     *     'component_verify_ticket' => 'ticket@@@wM91oELf8K9_3g8QCXJ9gkPXs6JN2AZjNjI7JEDhFL9MEWi00eEMIqqhPH338OFnwJ5cpjksZUGWYTQXqjsLMw', // 微信后台推送的 ticket
     *  ]
     *
     * @return array|false
     *
     * 响应格式如下:
     *
     * [
     *     'component_access_token' => '20_qD79ll9kFdMh3--X43qS-Tw8E04cuFEnoAUrbldWodKbFVg11VtlpJrRXVuVMs7fsVyEXbLByWT__P0o9-lCCWw0rsxD3yxFT3skdxsznhsMBrAKxlhOlRvbUWBsZMJ57oTLSnCMlWtdDv8tGMKjAJAYEC', // 第三方平台 access_token
     *     'expires_in' => 7200, // 有效期,单位:秒
     * ]
     *
     * 失败(将错误保存在 [[yii\base\Model::errors]] 属性中)
     * false
     *
     * @throws ServerErrorHttpException 如果响应状态码不等于20x
     */
    public function wxComponentAccessToken($data)
    {
        $response = Yii::$app->wxAuthHttp->createRequest()
            ->setMethod('post')
            ->setFormat('json')
            ->setUrl('cgi-bin/component/api_component_token')
            ->setData($data)
            ->send();
        // 检查响应状态码是否等于20x
        if ($response->isOk) {
            // 检查业务逻辑是否成功
            if (!isset($response->data['errcode'])) {
                $responseData = ['message' => '', 'data' => $response->data];
                return $responseData;
            } else {
                $this->addError('id', $response->data['errmsg']);
                return false;
            }
        } else {
            throw new ServerErrorHttpException(Yii::t('error', Yii::t('error', Yii::t('error', '202227'), ['status_code' => $response->statusCode, 'error_code' => $response->data['errcode'], 'error' => $response->data['errmsg']])), 202227);
        }
    }

    /**
     * HTTP请求,微信第三方平台通过 component_access_token 获取第三方平台的预授权码
     * @param array $data 请求数据
     * 格式如下:
     * [
     *     'component_appid' => 'wxd7f67f1792c6e238', // 第三方平台 appId
     * ]
     * @param string $componentAccessToken  第三方平台的 component_access_token
     * @return array|false
     *
     * 响应格式如下:
     *
     * [
     *     'pre_auth_code' => 'preauthcode@@@IexVwWK9bIkK-0pEd8plLnza0O8oalvXz1JWah5nfaHBJ0CN8Z8Kucu8rX2yA_4l', // 预授权码
     *     'expires_in' => 1800, // 有效期,单位:秒
     * ]
     *
     * 失败(将错误保存在 [[yii\base\Model::errors]] 属性中)
     * false
     * @throws ServerErrorHttpException
     */
    public function wxComponentPreAuthCode($data, $componentAccessToken)
    {
        $response = Yii::$app->wxAuthHttp->createRequest()
            ->setMethod('post')
            ->setFormat('json')
            ->setUrl('cgi-bin/component/api_create_preauthcode?component_access_token=' . $componentAccessToken)
            ->setData($data)
            ->send();
        // 检查响应状态码是否等于20x
        if ($response->isOk) {
            // 检查业务逻辑是否成功
            if (!isset($response->data['errcode'])) {
                $responseData = ['message' => '', 'data' => $response->data];
                return $responseData;
            } else {
                $this->addError('id', $response->data['errmsg']);
                return false;
            }
        } else {
            throw new ServerErrorHttpException(Yii::t('error', Yii::t('error', Yii::t('error', '202228'), ['status_code' => $response->statusCode, 'error_code' => $response->data['errcode'], 'error' => $response->data['errmsg']])), 202228);
        }
    }


5、最终的结果,查看生成的日志文件。http 请求获取 component_access_token 平均间隔时间:1小时50分钟。http 请求获取 http 请求获取 pre_auth_code 平均间隔时间:20分钟。此方案的缺陷在于:一旦 component_verify_ticket 接收失败(如微信推送 component_verify_ticket 的服务器发生故障),则微信的 component_access_token、pre_auth_code 皆会过期,无法获取到最新值。因为仅有此入口为更新触发点。后续计划实现2个定时命令(间隔10分钟运行一次),分别基于 component_verify_ticket 更新 component_access_token、基于 component_access_token 更新 pre_auth_code。避免出现因为 component_verify_ticket 接收失败而无法更新 component_access_token、pre_auth_code 的情况。官方建议。如图1
最终的结果,查看生成的日志文件。http 请求获取 component_access_token 平均间隔时间:1小时50分钟。http 请求获取 http 请求获取 pre_auth_code 平均间隔时间:20分钟。

图1

6、查看 Redis 中的缓存数据。如图2
查看 Redis 中的缓存数据

图2

7、查看生成的日志文件。以确认 http 请求的时间间隔。符合预期。http 请求获取 component_access_token 平均间隔时间:(21 09:39 – 20 18:55) / 8 = 110.5 分钟。http 请求获取 component_access_token 最大间隔时间:(20 22:39 – 20 20:44) = 115 分钟(小于过期时间 120 分钟)。http 请求获取 pre_auth_code 平均间隔时间:(21 09:59 – 20 18:55) / 45 = 20 分钟。http 请求获取 pre_auth_code 最大间隔时间:(20 21:59 – 20 21:34) = 25 分钟(小于过期时间 30 分钟)。


[root@api-64796bf684-4dk5b runtime]# ls -lrt
-rw-r--r-- 1 nginx nginx  231 Jul 20 18:55 frontend-services-WxOpenAuthService-componentAccessToken-1626778505.5976-2090872825.txt
-rw-r--r-- 1 nginx nginx  231 Jul 20 20:44 frontend-services-WxOpenAuthService-componentAccessToken-1626785088.6584-1698188199.txt
-rw-r--r-- 1 nginx nginx  231 Jul 20 22:39 frontend-services-WxOpenAuthService-componentAccessToken-1626791942.0405-1205529613.txt
-rw-r--r-- 1 nginx nginx  231 Jul 21 00:24 frontend-services-WxOpenAuthService-componentAccessToken-1626798260.5317-841190668.txt
-rw-r--r-- 1 nginx nginx  231 Jul 21 02:14 frontend-services-WxOpenAuthService-componentAccessToken-1626804844.4907-2046370607.txt
-rw-r--r-- 1 nginx nginx  231 Jul 21 04:04 frontend-services-WxOpenAuthService-componentAccessToken-1626811446.0864-1972564751.txt
-rw-r--r-- 1 nginx nginx  231 Jul 21 05:54 frontend-services-WxOpenAuthService-componentAccessToken-1626818067.4014-922194254.txt
-rw-r--r-- 1 nginx nginx  231 Jul 21 07:45 frontend-services-WxOpenAuthService-componentAccessToken-1626824703.4927-671650863.txt
-rw-r--r-- 1 nginx nginx  231 Jul 21 09:39 frontend-services-WxOpenAuthService-componentAccessToken-1626831557.828-269483974.txt
[root@api-64796bf684-4dk5b runtime]# 




[root@api-64796bf684-4dk5b runtime]# ls -lrt
-rw-r--r-- 1 nginx nginx  165 Jul 20 18:55 frontend-services-WxOpenAuthService-componentPreAuthCode-1626778505.8489-752113831.txt
-rw-r--r-- 1 nginx nginx  165 Jul 20 19:15 frontend-services-WxOpenAuthService-componentPreAuthCode-1626779710.0295-1883392791.txt
-rw-r--r-- 1 nginx nginx  165 Jul 20 19:35 frontend-services-WxOpenAuthService-componentPreAuthCode-1626780909.2572-2030512685.txt
-rw-r--r-- 1 nginx nginx  165 Jul 20 19:54 frontend-services-WxOpenAuthService-componentPreAuthCode-1626782090.5806-110245625.txt
-rw-r--r-- 1 nginx nginx  165 Jul 20 20:14 frontend-services-WxOpenAuthService-componentPreAuthCode-1626783290.1634-865268997.txt
-rw-r--r-- 1 nginx nginx  165 Jul 20 20:34 frontend-services-WxOpenAuthService-componentPreAuthCode-1626784491.401-904668390.txt
-rw-r--r-- 1 nginx nginx  165 Jul 20 20:54 frontend-services-WxOpenAuthService-componentPreAuthCode-1626785681.1526-312599467.txt
-rw-r--r-- 1 nginx nginx  165 Jul 20 21:14 frontend-services-WxOpenAuthService-componentPreAuthCode-1626786884.6617-148824611.txt
-rw-r--r-- 1 nginx nginx  165 Jul 20 21:34 frontend-services-WxOpenAuthService-componentPreAuthCode-1626788086.7058-993076861.txt
-rw-r--r-- 1 nginx nginx  165 Jul 20 21:59 frontend-services-WxOpenAuthService-componentPreAuthCode-1626789542.8081-1843679886.txt
-rw-r--r-- 1 nginx nginx  165 Jul 20 22:19 frontend-services-WxOpenAuthService-componentPreAuthCode-1626790746.9546-2130813835.txt
-rw-r--r-- 1 nginx nginx  165 Jul 20 22:39 frontend-services-WxOpenAuthService-componentPreAuthCode-1626791942.3167-1090847874.txt
-rw-r--r-- 1 nginx nginx  165 Jul 20 22:54 frontend-services-WxOpenAuthService-componentPreAuthCode-1626792884.6659-1225024664.txt
-rw-r--r-- 1 nginx nginx  165 Jul 20 23:14 frontend-services-WxOpenAuthService-componentPreAuthCode-1626794063.5141-313962662.txt
-rw-r--r-- 1 nginx nginx  165 Jul 20 23:34 frontend-services-WxOpenAuthService-componentPreAuthCode-1626795259.6539-1501709505.txt
-rw-r--r-- 1 nginx nginx  165 Jul 20 23:54 frontend-services-WxOpenAuthService-componentPreAuthCode-1626796457.9117-1972547675.txt
-rw-r--r-- 1 nginx nginx  165 Jul 21 00:14 frontend-services-WxOpenAuthService-componentPreAuthCode-1626797660.4519-582262606.txt
-rw-r--r-- 1 nginx nginx  165 Jul 21 00:34 frontend-services-WxOpenAuthService-componentPreAuthCode-1626798857.7039-272816531.txt
-rw-r--r-- 1 nginx nginx  165 Jul 21 00:54 frontend-services-WxOpenAuthService-componentPreAuthCode-1626800055.7545-1335033710.txt
-rw-r--r-- 1 nginx nginx  165 Jul 21 01:14 frontend-services-WxOpenAuthService-componentPreAuthCode-1626801254.9479-933596508.txt
-rw-r--r-- 1 nginx nginx  165 Jul 21 01:34 frontend-services-WxOpenAuthService-componentPreAuthCode-1626802448.9506-533002721.txt
-rw-r--r-- 1 nginx nginx  165 Jul 21 01:54 frontend-services-WxOpenAuthService-componentPreAuthCode-1626803664.2556-451414973.txt
-rw-r--r-- 1 nginx nginx  165 Jul 21 02:14 frontend-services-WxOpenAuthService-componentPreAuthCode-1626804844.7527-849127051.txt
-rw-r--r-- 1 nginx nginx  165 Jul 21 02:34 frontend-services-WxOpenAuthService-componentPreAuthCode-1626806043.7185-2047662025.txt
-rw-r--r-- 1 nginx nginx  165 Jul 21 02:54 frontend-services-WxOpenAuthService-componentPreAuthCode-1626807243.118-1751995970.txt
-rw-r--r-- 1 nginx nginx  165 Jul 21 03:14 frontend-services-WxOpenAuthService-componentPreAuthCode-1626808449.8901-1639170548.txt
-rw-r--r-- 1 nginx nginx  165 Jul 21 03:34 frontend-services-WxOpenAuthService-componentPreAuthCode-1626809644.1905-1681815156.txt
-rw-r--r-- 1 nginx nginx  165 Jul 21 03:54 frontend-services-WxOpenAuthService-componentPreAuthCode-1626810849.7381-1770515381.txt
-rw-r--r-- 1 nginx nginx  165 Jul 21 04:14 frontend-services-WxOpenAuthService-componentPreAuthCode-1626812045.9617-1614735470.txt
-rw-r--r-- 1 nginx nginx  165 Jul 21 04:34 frontend-services-WxOpenAuthService-componentPreAuthCode-1626813252.8063-1859536354.txt
-rw-r--r-- 1 nginx nginx  165 Jul 21 04:54 frontend-services-WxOpenAuthService-componentPreAuthCode-1626814453.7108-802504726.txt
-rw-r--r-- 1 nginx nginx  165 Jul 21 05:14 frontend-services-WxOpenAuthService-componentPreAuthCode-1626815669.4836-1412803818.txt
-rw-r--r-- 1 nginx nginx  165 Jul 21 05:34 frontend-services-WxOpenAuthService-componentPreAuthCode-1626816865.4676-278503141.txt
-rw-r--r-- 1 nginx nginx  165 Jul 21 05:54 frontend-services-WxOpenAuthService-componentPreAuthCode-1626818067.6856-1726415446.txt
-rw-r--r-- 1 nginx nginx  165 Jul 21 06:14 frontend-services-WxOpenAuthService-componentPreAuthCode-1626819272.89-123856324.txt
-rw-r--r-- 1 nginx nginx  165 Jul 21 06:34 frontend-services-WxOpenAuthService-componentPreAuthCode-1626820477.3397-694428578.txt
-rw-r--r-- 1 nginx nginx  165 Jul 21 06:54 frontend-services-WxOpenAuthService-componentPreAuthCode-1626821679.8346-1999505075.txt
-rw-r--r-- 1 nginx nginx  165 Jul 21 07:15 frontend-services-WxOpenAuthService-componentPreAuthCode-1626822907.5068-670400676.txt
-rw-r--r-- 1 nginx nginx  165 Jul 21 07:35 frontend-services-WxOpenAuthService-componentPreAuthCode-1626824107.4827-1497989531.txt
-rw-r--r-- 1 nginx nginx  165 Jul 21 07:55 frontend-services-WxOpenAuthService-componentPreAuthCode-1626825308.6138-127964288.txt
-rw-r--r-- 1 nginx nginx  165 Jul 21 08:19 frontend-services-WxOpenAuthService-componentPreAuthCode-1626826759.7268-2073402842.txt
-rw-r--r-- 1 nginx nginx  165 Jul 21 08:38 frontend-services-WxOpenAuthService-componentPreAuthCode-1626827916.6763-1465280404.txt
-rw-r--r-- 1 nginx nginx  165 Jul 21 08:59 frontend-services-WxOpenAuthService-componentPreAuthCode-1626829158.7873-2084121660.txt
-rw-r--r-- 1 nginx nginx  165 Jul 21 09:18 frontend-services-WxOpenAuthService-componentPreAuthCode-1626830319.8617-1775614952.txt
-rw-r--r-- 1 nginx nginx  165 Jul 21 09:39 frontend-services-WxOpenAuthService-componentPreAuthCode-1626831558.0899-1560152765.txt
-rw-r--r-- 1 nginx nginx  165 Jul 21 09:59 frontend-services-WxOpenAuthService-componentPreAuthCode-1626832767.0986-1848114078.txt
[root@api-64796bf684-4dk5b runtime]# 


 ]]>
https://www.shuijingwanwq.com/2021/07/20/5093/feed/ 0
xml 数据的解析的重构 https://www.shuijingwanwq.com/2021/07/20/5088/ https://www.shuijingwanwq.com/2021/07/20/5088/#respond Tue, 20 Jul 2021 06:52:36 +0000 https://www.shuijingwanwq.com/?p=5088 浏览量: 110 1、xml 数据打印如下。如图1
xml 数据打印如下

图1

<pre class="wp-block-syntaxhighlighter-code">

<xml>
	<AppId>
		<![CDATA[wxd98c58b273d21bdf]]>
	</AppId>
	<CreateTime>1626662709</CreateTime>
	<InfoType>
		<![CDATA[component_verify_ticket]]>
	</InfoType>
	<ComponentVerifyTicket>
		<![CDATA[ticket@@@bVAZ8WK0CCTWNowBEfvH7SWIRiPhoeNVczaOnAiPN8fzN2tNrxNK_mzJaUd-WFslGAyl6cSR1ryUinlthRQ0SA]]>
	</ComponentVerifyTicket>
</xml>

</pre>
2、现阶段是将 xml 转换为 数组。代码实现如下。libxml_disable_entity_loader 函数已自 PHP 8.0.0 起被废弃。强烈建议不要依赖本函数。


libxml_disable_entity_loader(true);
$values = Json::decode(Json::encode(simplexml_load_string($xml, 'SimpleXMLElement', LIBXML_NOCDATA)), true);


3、转换为数组后,打印结果如下。如图2
转换为数组后,打印结果如下

图2



Array
(
    [AppId] => wxd98c58b273d21bdf
    [CreateTime] => 1626662709
    [InfoType] => component_verify_ticket
    [ComponentVerifyTicket] => ticket@@@bVAZ8WK0CCTWNowBEfvH7SWIRiPhoeNVczaOnAiPN8fzN2tNrxNK_mzJaUd-WFslGAyl6cSR1ryUinlthRQ0SA
)



4、删除函数:libxml_disable_entity_loader。不转换为数组。直接使用对象。LIBXML_NOCDATA 表示 将 CDATA 合并为文本节点。如图3
删除函数:libxml_disable_entity_loader。不转换为数组。直接使用对象。LIBXML_NOCDATA 表示 将 CDATA 合并为文本节点

图3



$values = simplexml_load_string($xml, 'SimpleXMLElement', LIBXML_NOCDATA);
print_r($values);
echo $values->AppId;
exit;




SimpleXMLElement Object
(
    [AppId] => wxd98c58b273d21bdf
    [CreateTime] => 1626662709
    [InfoType] => component_verify_ticket
    [ComponentVerifyTicket] => ticket@@@bVAZ8WK0CCTWNowBEfvH7SWIRiPhoeNVczaOnAiPN8fzN2tNrxNK_mzJaUd-WFslGAyl6cSR1ryUinlthRQ0SA
)
wxd98c58b273d21bdf


]]>
https://www.shuijingwanwq.com/2021/07/20/5088/feed/ 0
微信公众号新增永久图文素材的接口调用,隐藏阅读原文链接的实现 https://www.shuijingwanwq.com/2021/07/12/5050/ https://www.shuijingwanwq.com/2021/07/12/5050/#respond Mon, 12 Jul 2021 07:55:39 +0000 https://www.shuijingwanwq.com/?p=5050 浏览量: 121

1、微信公众号新增永久图文素材的接口调用文档,字段:content_source_url 必须。图文消息的原文地址,即点击“阅读原文”后的URL。如图1

微信公众号新增永久图文素材的接口调用文档,字段:content_source_url 必须。图文消息的原文地址,即点击“阅读原文”后的URL。

图1

2、在微信公众号后台,创作图文消息时候,不勾选原文链接时候,字段:sourceurl0 为空。如图2

在微信公众号后台,创作图文消息时候,不勾选原文链接时候,字段:sourceurl0 为空。

图2

3、在微信公众号后台,创作图文消息时候,勾选原文链接时候,字段:sourceurl0 的值为填写的原文链接。如图3

在微信公众号后台,创作图文消息时候,勾选原文链接时候,字段:sourceurl0 的值为填写的原文链接。

图3

4、最终决定在新增永久图文素材的接口调用上,字段:content_source_url 允许等于空字符串。当等于空字符串后,调用成功。然后再调用接口:根据标签进行群发【订阅号与服务号认证后均可用】。最终发布成功。文章未显示阅读原文链接。符合预期。如图4

最终决定在新增永久图文素材的接口调用上,字段:content_source_url 允许等于空字符串。当等于空字符串后,调用成功。然后再调用接口:根据标签进行群发【订阅号与服务号认证后均可用】。最终发布成功。文章未显示阅读原文链接。符合预期。

图4

5、在新增永久图文素材的接口调用上,字段:content_source_url 不存在,仍然可以调用成功。

]]>
https://www.shuijingwanwq.com/2021/07/12/5050/feed/ 0
微信公众号新增永久图文素材时,报错:errcode,88000;errmsg:without comment privilege hint: [H4ZZ7a0344ha16] rid: 60e80cb8-1544f534-4f195aea https://www.shuijingwanwq.com/2021/07/09/5043/ https://www.shuijingwanwq.com/2021/07/09/5043/#respond Fri, 09 Jul 2021 09:06:40 +0000 https://www.shuijingwanwq.com/?p=5043 浏览量: 173 1、微信公众号新增永久图文素材时,报错:errcode,88000;errmsg:without comment privilege hint: [H4ZZ7a0344ha16] rid: 60e80cb8-1544f534-4f195aea。如图1
微信公众号新增永久图文素材时,报错:errcode,88000;errmsg:without comment privilege hint: [H4ZZ7a0344ha16] rid: 60e80cb8-1544f534-4f195aea。

图1



{
    "errcode": 88000,
    "errmsg": "without comment privilege hint: [H4ZZ7a0344ha16] rid: 60e80cb8-1544f534-4f195aea"
}


2、在另外一个公众号上,却是未报错。对比两个公众号的差异。发现成功的公众号,已开通:互动 – 留言 功能。如图2
在另外一个公众号上,却是未报错。对比两个公众号的差异。发现成功的公众号,已开通:互动 - 留言 功能。

图2

3、在成功的公众号后台新建图文消息时候,有留言功能的开关。如图3
在成功的公众号后台新建图文消息时候,有留言功能的开关。

图3

4、发现报错的公众号,已开通页面中不存在:互动 – 留言 功能。未开通页面中也不存在:互动 – 留言 功能。如图4
发现报错的公众号,已开通页面中不存在:互动 - 留言 功能。未开通页面中也不存在:互动 - 留言 功能。

图4

5、在报错的公众号后台新建图文消息时候,无留言功能的开关。如图5
在报错的公众号后台新建图文消息时候,无留言功能的开关。

图5

6、参考网址:https://developers.weixin.qq.com/community/develop/doc/0008a020380e888090ba4615556000 。2018年之前注册的公众号有留言功能,之后注册的只能通过账号迁移开通留言了。 7、分别查看报错与成功的公众号的认证时间:2018-10-14、2017-07-25。符合 2018年 时间点的结论。  ]]>
https://www.shuijingwanwq.com/2021/07/09/5043/feed/ 0
微信公众号新增永久视频素材的接口调用,上传后不可用 https://www.shuijingwanwq.com/2021/07/09/5034/ https://www.shuijingwanwq.com/2021/07/09/5034/#respond Fri, 09 Jul 2021 06:26:23 +0000 https://www.shuijingwanwq.com/?p=5034 浏览量: 221 1、参考网址:https://developers.weixin.qq.com/doc/offiaccount/Asset_Management/Adding_Permanent_Assets.html 。如图1
参考网址:https://developers.weixin.qq.com/doc/offiaccount/Asset_Management/Adding_Permanent_Assets.html

图1

2、在 Postman 中,请求头:form-data。2 个请求体参数:description,格式为 Text;media,格式为 File。如图2
在 Postman 中,请求头:form-data。2 个请求体参数:description,格式为 Text;media,格式为 File

图2



description={"title":"VIDEO_TITLE","introduction":"INTRODUCTION"}
media=@h264_2000k_mp4.mp4




{
    "media_id": "1gCdtqCQ5Mv0ziRAQov85-VxHX7WpDjRmHnCdmX2RBE",
    "item": []
}


3、当取消请求体参数:description 后,响应失败。如图3
当取消请求体参数:description 后,响应失败。

图3



{
    "errcode": 41005,
    "errmsg": "media data missing hint: [bhDfBa0363d418] rid: 60e6c4a6-64b78b4a-5be3301c"
}


4、进入公众平台官网素材管理模块中,查看视频列表。存在对应的素材:VIDEO_TITLE。但是,在一天之后,仍然未审核通过。连续上传了总计 3 个视频,皆是如此。如图4
进入公众平台官网素材管理模块中,查看视频列表。存在对应的素材:VIDEO_TITLE。但是,在一天之后,仍然未审核通过。连续上传了总计 3 个视频,皆是如此。

图4

5、同样的视频文件,通过官网上传,却是能够在短时间内审核通过。如图5
同样的视频文件,通过官网上传,却是能够在短时间内审核通过。

图5

6、调用接口:获取视频素材列表。响应中,通过接口上传的 3 个视频,不存在字段:vid。如图6
调用接口:获取视频素材列表。响应中,通过接口上传的 3 个视频,不存在字段:vid。

图6

7、在微信开放社区中搜索到相关的问题与回复。网址:https://developers.weixin.qq.com/community/minihome/doc/0000acea168dc82664ba9d86d52000 。你好,目前素材管理接口里,视频素材的上传没有送审,在微信公众平台后台的素材管理列表展示状态会异常,不能用于群发等常规场景。若目前有视频上传和使用需求,建议直接通过微信公众平台后台上传视频。公众号视频上传相关指引可查阅:https://support.qq.com/products/66522/faqs/54079  ]]>
https://www.shuijingwanwq.com/2021/07/09/5034/feed/ 0