php对接微信公众号扫码登录开发实录(H5微信扫描登录、服务出现故障调试、模版消息设置、扫码轮询交互)

news2025/1/16 0:20:39

微信公众号扫码登录开发实录

  • 前言
  • 一、服务器配置
    • 1.微信公众号配置
    • 2.本地服务器验证程序
  • 二、生成登录二维码
    • 1.生成微信登录二维码
    • 2.封装成便于刷新的函数
  • 三、扫码验证和交互
  • 四、模版消息设置
  • 五、开发中遇见的问题
    • 1.该公众号提供的服务出现故障,请稍后再试?
    • 2.微信第三方平台的token和jssdk的token是否一致?
    • 3.微信公众号消息模版调用的是哪个token?
    • 4.微信公众号可以批量推送消息模版吗
    • 5.php如何配置微信公众号的服务器配置
    • 6.扫描二维码后,php与微信公众号之间的推送和接收代码是怎么样的?
    • 7.扫描后,无法获取file_get_contents("php://input")
    • 8.HTTP_RAW_POST_DATA的使用方法是什么
    • 9.微信首次关注,未触发事件如何处理?

前言

微信公众号扫码登录在安全性、用户体验和数据收集方面优势明显,是目前许多应用程序采用的登录方式之一。

  1. 无需记住账号密码:用户无需输入和记住账号和密码,只需使用微信扫描二维码即可快速登录。

  2. 安全性高:微信采用 OAuth2.0 协议,将用户信息传递给第三方应用程序,而不会向第三方应用程序公开用户的微信账号和密码,有效保护用户隐私和安全。

  3. 用户体验好:扫码登录可以在移动设备上快速完成登录操作,无需输入许多文字,提高用户体验和用户参与度。

  4. 便于推送内容:通过微信公众号扫码登录,第三方应用程序可以获得用户的微信头像、昵称和 openid 等信息,这些信息对于精准推送内容非常有帮助。

  5. 方便分享内容:在扫码登录后,用户可以通过微信分享按钮将文章等内容分享给朋友,实现了“口碑”式传播。

一、服务器配置

1.微信公众号配置

切记,配置好需要点击“启用”。
在这里插入图片描述

2.本地服务器验证程序

// 微信token认证
$signature = $_GET["signature"];
$timestamp = $_GET["timestamp"];
$nonce = $_GET["nonce"];
$echostr = $_GET["echostr"];
// 你在微信公众号后台的设置的Token
$token = "3cab7ce41****ca24";

// 1)将token、timestamp、nonce三个参数进行字典序排序
$tmpArr = array($nonce, $token, $timestamp);
sort($tmpArr, SORT_STRING);

// 2)将三个参数字符串拼接成一个字符串进行sha1加密
$str = implode($tmpArr);
$sign = sha1($str);

// 3)开发者获得加密后的字符串可与signature对比,标识该请求来源于微信
if ($sign == $signature) {
    echo $echostr;
}

二、生成登录二维码

1.生成微信登录二维码

生成微信登录二维码的代码需要使用微信开放平台提供的 API,请参考以下步骤:

  1. 获取 access_token

在使用微信开放平台提供的 API 时,需要先获得一个 access_token。可以通过以下 URL 地址获取:

https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid={APPID}&secret={APPSECRET}

其中 APPID 和 APPSECRET 分别是在微信开放平台创建应用后获取的应用 ID 和应用密钥。将该 URL 地址进行 url encode,然后发送 GET 请求即可获取 access_token。

  1. 获取登录二维码的 ticket

使用上传图片素材接口(media/upload)获取二维码 Ticket ,该接口的请求 URL 地址为:

POST https://api.weixin.qq.com/cgi-bin/media/upload?access_token=ACCESS_TOKEN&type=image
  1. 生成登录二维码

将获取到的 Ticket 通过以下 URL 地址生成登录二维码:

https://mp.weixin.qq.com/cgi-bin/showqrcode?ticket=TICKET

其中 TICKET 是在上一步取到的 Ticket。将以上 URL 地址拼接起来,即可生成二维码,二维码有效期为 5 分钟。需要注意二维码中必须携带正确的参数,以保证登录成功。

2.封装成便于刷新的函数

  • 封装函数
//生成二维码;
    case "makeQrcode";
        require_once "libs/wx/jssdk.php";
        $CONF = require_once "conf/config.php";
        $jssdk = new JSSDK($CONF['wx_appId'], $CONF['wx_AppSecret']);
        $code_img = json_decode($jssdk->getQrcodeTicket(), true);
        $res['ticket'] = $code_img['ticket'];
        $res['scene_id'] = $code_img['uid'];
        $res['url'] = $code_img['url'];
        $res['code'] = 1;
        $res['msg'] = "成功生成登录二维码";
        die(json_encode_lockdata($res));
        break;
  • 生成二维码的同时,将ticket、scene_id、url同步传递到前端。
   public function getQrcodeTicket()
    {
        $qrcode_url = 'https://api.weixin.qq.com/cgi-bin/qrcode/create?access_token=' . $this->getAccessToken();
        $post_data = array();
        $post_data['expire_seconds'] = 120; //有效时间
        $post_data['action_name'] = 'QR_SCENE';
        $post_data['action_info']['scene']['scene_id'] = $this->make_uid(); //传参二维码主键id,微信端可获取
        $json = $this->httpPost($qrcode_url, json_encode($post_data));
        if (!$json['errcode']) {
            $data['url'] = 'https://mp.weixin.qq.com/cgi-bin/showqrcode?ticket=' . urlencode($json['ticket']);
            $data['uid'] = $post_data['action_info']['scene']['scene_id'];
            $data['ticket'] = $json['ticket'];
            return json_encode($data);
        } else {
            die('发生错误:错误代码 ' . $json['errcode'] . ',微信返回错误信息:' . $json['errmsg']);
        }
    }
  • 前端二维码容器
 <div class="photo">
    <img src="" width="180" height="180" id="qrcode">
       <p>关注微信公众号(点击刷新二维码)</p>
  </div>
  • 前端调用
      //请求登录二维码
        getWxQRcode();
        $("#qrcode").click(function () {
            getWxQRcode();
        })
    //获取微信登录二维码
    function getWxQRcode() {
        $.getJSON("?m=Login&a=loginDeal&act=makeQrcode", function (data) {
            $("#qrcode").attr("src", data.url);
            ticket = data.ticket;
            scene_id = data.scene_id;
        });
    }

三、扫码验证和交互

  • 扫码,微信服务器推送信息
//$postStr = file_get_contents("php://input");//php版本>7.0使用
$postStr = $GLOBALS["HTTP_RAW_POST_DATA"];
if (!empty($postStr)) {
    $postObj = simplexml_load_string($postStr, 'SimpleXMLElement', LIBXML_NOCDATA);
    $eventType = strtolower($postObj->Event);
    $scene_id = trim($postObj->EventKey);
    $replyMsg = "微信扫码登录";
    $fromUsername = trim($postObj->ToUserName);
    $toUsername = trim($postObj->FromUserName);
    $replyTime = time();

    /* 业务逻辑
     * 扫码后,将相关数据保存在服务器,以便扫码比对
     * $upload_dir,票据保存目录
     * $ticket,票据名称
     * $scene_id,场景值ID
     * */
    $upload_dir = 'upload/ticket/';
    if (!is_dir($upload_dir)) {
        mkdir($upload_dir, 0755, true);
    }
    $ticket = $postObj->Ticket;
    $data = ['openid' => $toUsername, 'scene_id' => $scene_id];
    $content = json_encode($data);
    $fp = fopen('./upload/ticket/' . $scene_id . "_" . $ticket . ".json", "w");
    fwrite($fp, $content);
    fclose($fp);

    //已关注
    if ($eventType == 'scan') {
        //读取数据库,判断$toUsername是否绑定
        /* 已绑定,执行登陆
         * 是否绑定手机号
         * */
        //文本消息
        // . "-" . $eventType . "-" . $toUsername
        $resultStr = $jssdk->sendText($toUsername, $fromUsername, $replyMsg);// . "-" . $scene_id . "-" . json_encode($postObj)
        echo $resultStr;

        /* 模版消息
         * 必须填填写,否则无推送(模版消息,是return;文本消息是echo)
         * 测试openid:oe2dH62ZgphwmJRGvAVTlCJjWTN4
         * */
        /* $resultStr = $jssdk->sendWXMsg(trim($toUsername), $CONF['sys_name'], 'scan');
         return $resultStr;*/
    }

    //首次关注
    if ($eventType == 'subscribe') {
        //文本消息
        $resultStr = $jssdk->sendtext($toUsername, $fromUsername, '感谢关注' . $CONF['sys_name']);
        echo $resultStr;
        /*$resultStr = $jssdk->sendWXMsg(trim($toUsername), $CONF['sys_name'], 'subscribe');
        return $resultStr;*/
    }
  • 前端轮询
  //验证扫码状态
        function wxLogin() {
            $.getJSON("?m=Login&a=loginDeal&act=wx_login", {ticket: ticket, scene_id: scene_id}, function (res) {
                    //console.log(res);
                    //已绑定用户
                    if (res.code == 1) {
                        layer.msg(res.msg, {icon: 1, time: 2000}, function () {
                            location.reload();
                        });
                    }
                    //未绑定用户
                    if (res.code == 2) {
                        layer.msg(res.msg, {icon: 2, time: 2000}, function () {
                            location.href = '?m=User&a=userBind';
                        });
                    }
                }
            );
        }

        //轮询
        var timer = setInterval(function () {
            wxLogin();
        }, 2000);
  • 后端验证扫码
 //判断二维码是否扫码
    case  "wx_login";
        $ticket = get_param("ticket");
        $scene_id = get_param("scene_id");
        $file = "upload/ticket/" . $scene_id . "_" . $ticket . ".json";
        @$login = file_get_contents($file);
        if ($login) {
            $openid = json_decode($login)->openid;
            $_SESSION['openid'] = $openid;
            //发送登录模版消息
            require_once "libs/wx/jssdk.php";
            $jssdk = new JSSDK($CONF['wx_appId'], $CONF['wx_AppSecret']);
            $resultStr = $jssdk->sendWXMsg(trim($openid), $CONF['sys_name'], 'scan');
            //return $resultStr;

            //验证码自动销毁;
            session_destroy();

            //删除临时文件
            if (file_exists($file)) {
                unlink($file);
            }
            //$res['openid'] = $openid;
            $res['code'] = 1;
            $res['msg'] = "登录成功";
            die(json_encode_lockdata($res));
        } else {
            $res['code'] = 0;
            $res['msg'] = "无法获取票据";
            die(json_encode_lockdata($res));
        }
        break;

四、模版消息设置

在这里插入图片描述

    //发送模版消息
    public function sendWXMsg($openid, $sysTitle, $temp_type)
    {
        $json_template = $this->jsonTemplate($openid, $sysTitle, $temp_type);
        $url = "https://api.weixin.qq.com/cgi-bin/message/template/send?access_token=" . $this->getAccessToken();
        $res = json_decode($this->curl_post($url, urldecode(trim($json_template))), true);
        if ($res['errcode'] == 0) {
            return '发送成功';
        } else {
            return $res['errmsg'];
        }
    }

    /**
     * 模板消息json格式化
     * $openid,用户openid;
     * $template_id,在公众号下配置的模板id
     * $temp_type,消息类型
     */
    private function jsonTemplate($openid, $sysTitle, $temp_type)
    {
        $skipUrl = 'http://xiaoe.***.cn';//点击模板消息会跳转的链接
        switch ($temp_type) {
            case "scan"://扫描登录
                $template_id = "HXdRtFldq88I-z0aIgwv-9_4FXtQFbfYqR83kM1-29s";
                $template = array(
                    "touser" => $openid,
                    "template_id" => trim($template_id),
                    "url" => $skipUrl,
                    "data" => array(
                        "thing4" => array("value" => urlencode($sysTitle)),
                        "time3" => array("value" => urlencode(date("Y-m-d H:i:s"))),
                        "thing10" => array("value" => urlencode("微信扫码登录")),
                    )
                ); //模板消息
                return json_encode($template);
                break;

            case "subscribe"://首次关注
                $template_id = "HXdRtFldq88I-z0aIgwv-9_4FXtQFbfYqR83kM1-29s";
                $template = array(
                    "touser" => $openid,
                    "template_id" => trim($template_id),
                    "url" => $skipUrl,
                    "data" => array(
                        "thing4" => array("value" => urlencode($sysTitle)),
                        "time3" => array("value" => urlencode(date("Y-m-d H:i:s"))),
                        "thing10" => array("value" => urlencode("微信扫码登录(首次关注)")),
                    )
                ); //模板消息
                return json_encode($template);
                break;

            case "order"://产品订购
                $template_id = "RkCMp_dH7F4A3lOO471v9XdAXvmO_7cY21cfCnY6u-3o";
                break;
            default:
                echo "";
        }
    }

五、开发中遇见的问题

1.该公众号提供的服务出现故障,请稍后再试?

如果正在发送消息模板,会出现消息模板格式错误的情况,导致无法正常发送消息。如果模板格式存在问题,微信公众号服务器会返回相应的错误提示,例如“模板格式错误”、“内容过长”等错误信息。

因此,在使用微信公众号发送消息模板时,应确保模板格式正确、内容符合要求。建议按照微信公众号官方文档中提供的模板格式规范进行开发,并在发送前进行模板格式和内容的检查工作,以避免该问题的发生。

  1. $toUsername,使用trim()过滤空格,防止发送信息错误;
  2. 返回值必须要返回一个字符串,否则会导致扫描后公众号提示“该公众号提供的服务出现故障,请稍后再试”。
  $resultStr = $jssdk->sendText($toUsername, $fromUsername, $replyMsg);// . "-" . $scene_id . "-" . json_encode($postObj)
   echo $resultStr;

2.微信第三方平台的token和jssdk的token是否一致?

微信第三方平台的token和jssdk的token是不同的。
微信第三方平台的token是用于与微信服务器进行交互的身份标识,用于验证第三方平台身份和加解密票据等。 而jssdk的token是用于调用微信JS-SDK时进行验证的票据,通过对微信公众号进行认证后可以获取。它主要用于获取用户信息、分享接口、支付接口等功能的调用。
虽然两者都是token,但由于用途不同,因此它们的生成方式及验证流程也不一样。

3.微信公众号消息模版调用的是哪个token?

微信公众号消息模板调用的是微信公众号的access_token。
access_token是获取微信公众号 API 调用凭证(Token)的接口,每个公众号都有独立的access_token。在调用公众号接口时,需要携带access_token参数,以验证公众号身份。
调用公众号模板消息接口时,需要先获取到access_token后才能进行调用。access_token的获取方式有两种:一种是通过公众号网页授权获取,另一种是通过公众号开发者中心的API token获取。具体获取方式可以参考微信公众号开发文档。

4.微信公众号可以批量推送消息模版吗

微信公众号支持批量发送消息模板。具体实现方式是,开发者可以使用微信公众平台接口向指定OpenID群发模板消息,每次调用最多可以发送给10000个用户。调用接口前需要先获取到公众号的access_token。

调用接口的方法如下:

  1. 构造请求数据包,包括模板内容和接收用户的openid列表。
  2. 将数据包格式化为json字符串。
  3. 调用模板消息发送接口,将消息发送给微信服务器。
  4. 微信服务器接收到消息后,将模板消息发送给指定OpenID的用户。

需要注意的是,微信规定模板消息的发送频率不能超过每个用户每天1条,且对于相同模板消息,30天内只能发送一次,否则将会被认为是垃圾邮件,会对公众号造成不利影响。

5.php如何配置微信公众号的服务器配置

在PHP中,配置微信公众号的服务器配置需要做以下几件事情:

  1. 在公众号后台配置服务器地址和Token,务必保证服务器地址与Token填写无误;
  2. 在自己的服务器端编写代码,对微信服务器发送的请求进行验证和处理;
  3. 返回特定格式的消息给微信服务器,告诉微信服务器处理结果。

下面是具体操作步骤:

  1. 在公众号后台配置服务器地址和Token

在公众号后台->开发->基本配置页面填写服务器配置项,将服务器地址与Token填写正确,其中Token是自定义的密钥,可自行设置。

  1. 编写代码对微信服务器发送的请求进行验证和处理

在自己的服务器端,为事件接口URL配置一个处理请求的入口,并根据微信服务器发送的请求做出相应的响应。具体实现步骤如下:

  • 验证请求是否合法,验证请求签名是否正确;
  • 通过文件方式或者Redis等缓存技术,存储access_token等参数,保证服务器可以快速响应;
  • 处理各种事件、消息等请求,并在消息处理后,按照微信服务器要求,返回特定格式的消息给微信服务器;
  1. 返回特定格式的消息给微信服务器

处理完请求后,需要将结果按照微信服务器要求,返回特定格式的消息给微信服务器,告诉微信服务器处理结果,否则会导致请求失败。

在向微信服务器发送消息时,需要将响应消息格式化为XML字符串,并按照微信服务器要求,包装成特定的格式。

以上是关于如何在PHP中配置微信公众号的服务器配置的简单介绍,细节和具体代码实现请参考微信公众号官方文档。

6.扫描二维码后,php与微信公众号之间的推送和接收代码是怎么样的?

在 PHP 中,实现扫描二维码后与微信公众号之间的推送和接收可以分为以下几个步骤:

  1. 配置开发者中心服务器地址和 Token。

需要在微信开发者中心中开启接口配置,填写服务器 URL 和 Token 信息,这些信息将在后续的接口验证中用到。

  1. 接收和验证微信发送的请求。

当有用户通过扫描二维码进入公众号时,微信会把用户的请求发送到配置的服务器地址中,开发者需要编写代码,接受并验证微信服务器发送的请求的合法性。

  1. 处理用户请求。

当开发者成功接收并验证了微信发送的请求的合法性后,需要根据业务逻辑对请求进行处理,可以根据不同的场景,进行相关操作,比如数据库操作、数据查询等。

  1. 回复用户消息。

根据处理结果,开发者需要对微信返回特定结构的消息,告诉微信服务器处理结果并让公众号给用户发送相应的消息,返回的消息格式也需要遵守微信的规范,即按照微信服务器要求组织消息内容,将响应消息内容格式化成XML字符串。

下面是一个简单的接收和处理微信二维码扫描事件的 PHP 代码示例:

// 验证请求签名
$signature = $_GET["signature"];
$timestamp = $_GET["timestamp"];
$nonce = $_GET["nonce"];
$token = "your_token";
$tmpArr = array($token, $timestamp, $nonce);
sort($tmpArr, SORT_STRING);
$tmpStr = implode($tmpArr);
$tmpStr = sha1($tmpStr);
if ($signature != $tmpStr) {
  die("signature error");
}

// 处理请求
$postStr = file_get_contents("php://input");
if (!empty($postStr)) {
  $postObj = simplexml_load_string($postStr, 'SimpleXMLElement', LIBXML_NOCDATA);
  $eventType = $postObj->Event;
  if ($eventType == 'SCAN') {
    // 处理扫描事件
    // 通过扫描事件里的场景值scene_id做进一步的业务逻辑
    $sceneId = $postObj->EventKey;

    // 回复消息,告知用户已经处理了请求
    $replyMsg = "您的扫描请求已经处理成功";
    $fromUsername = $postObj->ToUserName;
    $toUsername = $postObj->FromUserName;
    $replyTime = time();
    $textTpl = "<xml>
      <ToUserName><![CDATA[%s]]></ToUserName>
      <FromUserName><![CDATA[%s]]></FromUserName>
      <CreateTime>%s</CreateTime>
      <MsgType><![CDATA[%s]]></MsgType>
      <Content><![CDATA[%s]]></Content>
      <FuncFlag>0</FuncFlag>
    </xml>";
    $msgType = "text";
    $resultStr = sprintf($textTpl, $toUsername, $fromUsername, $replyTime, $msgType, $replyMsg);
    echo $resultStr;
  }
}

7.扫描后,无法获取file_get_contents(“php://input”)

如果在扫描二维码后使用 file_get_contents("php://input") 无法获取POST过来的数据,一般有以下几种可能原因:

  1. 服务器未开启 always_populate_raw_post_data 选项

PHP.ini 中配置项 always_populate_raw_post_data 表示是否在初始化时自动填充 $HTTP_RAW_POST_DATA 变量,而 $HTTP_RAW_POST_DATA 变量包含了 POST 过来的原始数据。该选项默认为 0(即关闭状态),如果需要通过 file_get_contents("php://input") 获取 POST 数据,则需要将其设置为 always_populate_raw_post_data = -1,然后重新启动服务器。

  1. 请求参数被禁用

在 PHP 中,有一些安全选项可以禁用 $_REQUEST$_GET$_POST 等全局变量,可以检查 PHP.ini 中的以下选项是否置为 off

variables_order
disable_functions
disable_classes
  1. 其他原因

如果上述原因都检查过了还是无法获取 POST 数据,可以尝试换一个新的 PHP 版本,也可以考虑使用其他的方法获取 POST 数据,比如使用 php://stdinHTTP_RAW_POST_DATAstream_get_contents() 等。

需要注意的是,在微信开发中,如果使用了微信官方提供的 SDK 来接收和处理微信的 POST 请求,一般不需要使用 file_get_contents("php://input") 来获取 POST 数据,可以直接通过 SDK 提供的方法来处理请求。

8.HTTP_RAW_POST_DATA的使用方法是什么

在不开启 always_populate_raw_post_data 或者 auto_globals_jit 配置时,$_POST$_FILES 超全局变量中不会保存 POST 过来的原始数据,此时可以使用 $HTTP_RAW_POST_DATA 变量来获取原始 POST 数据。

$HTTP_RAW_POST_DATA 是一个全局变量,它包含了 POST 数据的原始内容。要使用它来获取 POST 数据,可以按照以下步骤操作:

  1. 设置 always_populate_raw_post_data=-1

在 PHP.ini 中设置 always_populate_raw_post_data=-1,然后重新启动服务器,确保 $HTTP_RAW_POST_DATA 变量可以正常获取。

  1. 使用 $HTTP_RAW_POST_DATA
if (isset($HTTP_RAW_POST_DATA)) {
    $postRequestData = $HTTP_RAW_POST_DATA;
} else {
    $postRequestData = file_get_contents("php://input");
}

在上述代码中,首先检查 $HTTP_RAW_POST_DATA 是否存在,如果存在,则将 POST 数据的原始内容赋值给 $postRequestData 变量,否则,使用 file_get_contents("php://input") 函数从标准输入流中读取原始数据。

需要注意的是,$HTTP_RAW_POST_DATA 变量在 PHP 版本 5.6.0 之后被废弃,并且在 PHP 版本 7.2.0 中被移除,建议使用 php://stdinphp://input 来获取 POST 数据。
在这里插入图片描述

9.微信首次关注,未触发事件如何处理?

如果用户在未关注公众号的情况下,通过扫描带场景值二维码(或其他途径)进行关注,那么并不会收到关注事件,微信服务器只会默认推送一次文本类型的消息,公众号开发者需要对这种情况进行特殊处理。

具体而言,对于首次关注时未触发关注事件,可以使用替代方案来实现处理,例如在公众号的自动回复中,设置一条欢迎语并放置在第一位,让用户在关注后第一时间接收到并引导用户进行相关操作。

同时,在处理此类情况时,需要注意以下几点:

  1. 判断用户是否关注过公众号

可以通过在公众号中记录用户的关注状态,来判断用户是否关注过公众号。如果用户已经关注过公众号,则可以正常地处理关注事件。

  1. 限制重复关注

为避免用户重复关注公众号,可以在处理关注事件时,判断用户的关注状态,只有在用户之前没有关注过公众号的情况下,才进行相应的业务操作。

  1. 考虑用户体验

处理首次关注时未触发事件的情况,需要考虑到用户的使用体验。在向用户发送欢迎语时,应该具有一定的个性化,并引导用户完成与公众号的互动操作,例如进行菜单的点击、发送关键词等。

需要注意的是,由于微信公众号平台不断升级优化,某些问题可能在后续的版本中得到解决。因此,在出现问题时,开发者可以参考微信公众平台文档中的最新说明,在此基础上进行相应的处理操作。


@漏刻有时

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/678955.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

区分 scanf和printf、fscanf和fprintf、sscanf和sprintf函数

文章目录 前言scanf和printffscanf和fprintfsscanf和sprintf总结 前言 C语言中&#xff0c;许多函数的函数名过于相似&#xff0c;使用者要是不能很好地区分这些函数&#xff0c;就会造成误用&#xff0c;最终导致代码的结果大相径庭。对于scanf和printf函数、fscanf和fprintf…

Xcode 15 beta 2 (15A5161b) 发布下载 - Apple 平台 IDE (visonOS 1 beta 已发布)

Xcode 15 beta 2 (15A5161b) 发布下载 - Apple 平台 IDE (visonOS 1 beta 已发布) IDE for iOS/iPadOS/macOS/watchOS/tvOS/visonOS 此版本已加入 visonOS 支持。 请访问原文链接&#xff1a;https://sysin.org/blog/apple-xcode-15/&#xff0c;查看最新版。原创作品&#…

UWB测距方案|3C门店展示防丢报警方案,优化防盗设计提升购机体验

目前市场上最常见的3C产品&#xff08;如手机&#xff0c;平板电脑&#xff0c;电脑等&#xff09;展示防盗是采用有线防盗技术&#xff0c;即底座&#xff0c;防盗线以及警报触头组成。以线下手机营业厅为例&#xff0c;防盗线的长度直接限制了体验者的活动范围&#xff0c;没…

【VC 7/8】vCenter Server 更新(小版本升级)Ⅲ—— VC更新命令行工具 software-packages 更新命令说明

目录 3. software-packages 更新命令说明&#xff08;1&#xff09;查看 VCSA 中所有已安装的修补程序列表ⅰ 查看 VCSA 中已安装的修补程序和软件包的完整列表ⅱ 要按时间顺序查看已应用到 VCSA的所有修补程序ⅲ 要查看特定修补程序的详细信息 &#xff08;2&#xff09;将修补…

Centos7系统安装Docker

目录 1.Docker安装 1.安装Docker 2.启动Docker 2.Docker相关服务及配置镜像加速器 1.Docker安装 1.安装Docker 输入命令curl -fsSL https://get.docker.com | bash -s docker --mirror Aliyun进行安装 安装结束后&#xff0c;输入docker -v查看安装的docker版本 2.启动D…

【文献分享】基于边界点优化和多步路径规划的机器人自主探索

论文题目&#xff1a;Autonomous Robotic Exploration Based on Frontier Point Optimization and Multistep Path Planning 中文题目&#xff1a;基于边界点优化和多步路径规划的机器人自主探索 作者&#xff1a;Baofu Fang &#xff1b;Jianfeng Ding ; Zaijun Wang 作者机…

Elasticsearch:redact processor - 编辑处理器

警告&#xff1a;此功能处于技术预览阶段&#xff0c;可能会在未来版本中更改或删除。 Elastic 将尽最大努力解决任何问题&#xff0c;但技术预览版中的功能不受官方 GA 功能的支持 SLA 的约束。 Redact 处理器使用 Grok 规则引擎来模糊输入文档中与给定 Grok 模式匹配的文本。…

VMware虚拟机在Mac上安装

文章目录 下载链接2 下载CentOS操作系统 下载链接 点击下载官网VMware有30天免费试用&#xff0c;我们点击试用&#xff0c;如果后期需要再购买就可以了 也可以选择player版&#xff0c;免费注册然后下载&#xff0c;不用钱 注册好后会给你生成一个许可证密钥 2 下载CentOS操…

VSCode gdb 调试 qemu u-boot 的方法

前言 最近使用 VS Code GDB 调试 qemu&#xff0c;有了一点收获&#xff0c;u-boot 编译后生成了一个 elf 文件&#xff1a;u-boot&#xff0c;是否也可以调试一下&#xff1f; 为何需要 VS Code GDB 调试&#xff0c;直接 gdb 调试不就可以了吗&#xff1f;答案就是&#xff…

区块链技术的应用与前景展望

第一章&#xff1a;引言 在当今数字化时代&#xff0c;区块链技术作为一项前沿技术正迅速崭露头角&#xff0c;并在各个行业展现出巨大的潜力。区块链技术不仅仅是比特币和其他数字货币的基石&#xff0c;更是一种分布式、去中心化的记账和验证技术。本文将探讨区块链技术的应…

Matlab评价模型-TOPSIS法(优劣解距离法)

评价模型-TOPSIS法(优劣解距离法) 1.1 概念 TOPSIS 法是一种常用的组内综合评价方法&#xff0c;能充分利用原始数据的信息&#xff0c;其结果能精确地反映各评价方案之间的差距。基本过程为基于归一化后的原始数据矩阵&#xff0c;采用余弦法找出有限方案中的最优方案和最劣…

C++14部分新特性

文章目录 1、lambda表达式2、constexpr关键字3、函数返回类型推导4、变量模版5、二进制字面值6、数字分位符7、通过类型寻址多元组8、make_unique 1、lambda表达式 C14提供了在lambda式的形参声明中使用auto的能力 泛型 lambda&#xff1a;C14 中的 lambda 表达式可以使用模板…

可维护的代码,高复用性之路:函数式编程带你飞

文章目录 I. 前言介绍函数式编程引言&#xff1a;为什么需要函数式编程 II. 函数式编程基础声明式编程和命令式编程比较纯函数&#xff1a;概念&#xff0c;优点和局限性不可变数据&#xff1a;概念&#xff0c;优点和局限性 III. 函数式编程优点易于理解和调试代码可以提高代码…

Matlab数学建模-典型相关分析

统计分析-典型相关分析 概念 典型相关分析是研究两个多变量&#xff08;向量&#xff09;之间之间的线性相关关系&#xff0c;能够揭示出两组变量之间的内在联系。 CCA(典型相关分析) 在一元统计分析中&#xff0c;用相关系数来衡量两个随机变量的线性相关关系&#xff0c;…

C++ 第三弹继承和多态-类和对象

目录 1.继承 1.1什么是继承&#xff1f; 1.2语法格式 1.3继承权限 1.4继承概念语法格式 1.5赋值兼容规则 1.6继承体系中的作用域 1.7在继承体系中的构造和析构 1.8静态成员继承 1.9友元的继承 1.10不同继承方式下子类的对象模型 1.11继承和组合 2.多态 2.1什么是…

分销架构总结

概述 对于过往分销系统的经验总结。视角上会不区分实物及虚拟服务的分销。 分销定义&#xff1a;将产品从生产者转移到消费者。 分销职责&#xff1a;获客&#xff0c;服务(售前&#xff0c;售中&#xff0c;售后)。核心是通过不同分销渠道将产品能卖出去。 在整体分销网络…

jjy-share-v1.0 一键分享到微博、QQ空间、QQ好友、微信,一键分享,一键分享代码,一键分享插件,一键分享代码插件

项目地址&#xff1a; jjy-share-v1.0: 一键分享到微博、QQ空间、QQ好友、微信作者&#xff1a; 极纪元-橙作者博客&#xff1a;https://cplvfx.blog.csdn.net/码云Gitee&#xff1a;https://gitee.com/cplvfx/时间&#xff1a;2023年6月21日 介绍 一键分享到微博、QQ空间、…

Qt下使用QPainter实现界面上饼状图、圆环图的绘制

文章目录 前言一、示例讲解二、圆环图绘制步骤三、设置圆环图数据四、示例完整代码五、下载链接总结 前言 前面的文章有讲述使用Qt下的Charts 模块来进行饼图的绘制&#xff1a;QChart实现ui界面上指定位置饼状图、圆环图的绘制&#xff0c;但是使用过程中并不能很好的实现自己…

Embedding 嵌入知识入门

原文首发于博客文章Embedding 嵌入知识入门 文本嵌入是什么 向量是一个有方向和长度的量&#xff0c;可以用数学中的坐标来表示。例如&#xff0c;可以用二维坐标系中的向量表示一个平面上的点&#xff0c;也可以用三维坐标系中的向量表示一个空间中的点。在机器学习中&#x…

强化学习从基础到进阶-案例与实践[4.1]:深度Q网络-DQN项目实战CartPole-v0

【强化学习原理项目专栏】必看系列&#xff1a;单智能体、多智能体算法原理项目实战、相关技巧&#xff08;调参、画图等、趣味项目实现、学术应用项目实现 专栏详细介绍&#xff1a;【强化学习原理项目专栏】必看系列&#xff1a;单智能体、多智能体算法原理项目实战、相关技巧…