php根据浏览器调用支付_Android通过外部浏览器调用微信H5支付,Android+PHP详解

看了好多关于讲解微信H5支付开发的文章,大多数都是通过微信内部浏览器来调用支付接口(其实就是公众号支付),可能是因为H5支付接口刚开放不久吧。

微信官方体验链接:http://wxpay.wxutil.com/mch/pay/h5.v2.php,请在微信外浏览器打开。

看了上面的体验链接,如果感兴趣,可以接着往下看,希望对你有所帮助。

一、Android端

Android端代码相对来说比较简单一些,我这边直接调用系统浏览器打开H5支付页面Intent intent = new Intent();

intent.setAction("android.intent.action.VIEW");

Uri content_url = Uri.parse(url); //url里面包含了后端需要用到的参数,例如金额,用户ID

intent.setData(content_url);

startActivity(intent);

刚开始考虑过使用webview来加载支付页面,但是调试接口的时候发现一直报如下错误:

AAffA0nNPuCLAAAAAElFTkSuQmCC

微信官方报错示例图

根据微信官方的报错示例可以看出,应该是webview中没有设置referer导致的。于是,我按照说明加上了referer,然鹅,并没有什么卵用,依然报错。我只好放弃使用webview改用系统浏览器。使用系统浏览器的弊端还是挺明显的,客户端和后台传值不好处理(正在看文章的你,如果用webview调用成功了,还请赐教)

二、PHP端

1.获取从Android端传过来的参数

目前我只想到一种方法,就是通过url携带参数给服务端传值,OK,获取方式如下://当前页面的URL地址为:http://www.XXXXX.com/wechatpay/h5Pay.php?money=100&uid=337828932$string = $_SERVER['QUERY_STRING'];//通过$_SERVER['QUERY_STRING']函数获取url地址?后面的值$androidData = convertUrlQuery($string);//将字符串$string转化为数组$money = $androidData['money '];//获取money值 100$uid = $androidData['uid'];//获取用户ID 337828932

上面用到的convertUrlQuery函数代码//将字符串参数变为数组function convertUrlQuery($query){

$queryParts = explode('&', $query);

$params = array();    foreach ($queryParts as $param) {

$item = explode('=', $param);

$params[$item[0]] = $item[1];

}    return $params;

}

2.调用微信统一下单API2.1 具体参数名称以及各参数的用途请查看微信官方文档 统一下单API//配置需要传递给微信的参数

$input = new WxPayUnifiedOrder();

$input->SetBody("xxxx-商品购买");

$input->SetAttach("xxxx");

$input->SetDevice_info("WEB");

$input->SetOut_trade_no(WxPayConfig::MCHID . date("YmdHis").$uid);//把UID加在末尾主要用于识别用户,给对应的用户充值余额

$input->SetTotal_fee($money);

$input->SetTime_start(date("YmdHis"));

$input->SetTime_expire(date("YmdHis", time() + 600));

$input->SetGoods_tag("t");

$input->SetNotify_url("http://www.xxxxx.com/wechatpay/notify.php");//用于接收微信下发的支付结果通知

$input->SetTrade_type("MWEB");

$input->SetOpenid($openId);

$input->SetScene_info("{\"h5_info\": \"h5_info\"{\"type\": \"Wap\",\"wap_url\": \"http://www.xxxxx.com/shop\",\"wap_name\": \"xxx\"}}");2.2 接下来通过$order = WxPayApi::unifiedOrder($input);获取微信返回的参数,unifiedOrder函数具体实现如下/**

*

* 统一下单,WxPayUnifiedOrder中out_trade_no、body、total_fee、trade_type必填

* appid、mchid、spbill_create_ip、nonce_str不需要填入

* @param WxPayUnifiedOrder $inputObj

* @param int $timeOut

* @throws WxPayException

* @return 成功时返回,其他抛异常

*/

public static function unifiedOrder($inputObj, $timeOut = 6)

{

$url = "https://api.mch.weixin.qq.com/pay/unifiedorder";        //检测必填参数

if(!$inputObj->IsOut_trade_noSet()) {            throw new WxPayException("缺少统一支付接口必填参数out_trade_no!");

}else if(!$inputObj->IsBodySet()){            throw new WxPayException("缺少统一支付接口必填参数body!");

}else if(!$inputObj->IsTotal_feeSet()) {            throw new WxPayException("缺少统一支付接口必填参数total_fee!");

}else if(!$inputObj->IsTrade_typeSet()) {            throw new WxPayException("缺少统一支付接口必填参数trade_type!");

}

//异步通知url未设置,则使用配置文件中的url

if(!$inputObj->IsNotify_urlSet()){

$inputObj->SetNotify_url(WxPayConfig::NOTIFY_URL);//异步通知url

}

$inputObj->SetAppid(WxPayConfig::APPID);//公众账号ID

$inputObj->SetMch_id(WxPayConfig::MCHID);//商户号

$inputObj->SetSpbill_create_ip(self::getIp());//终端ip

//$inputObj->SetSpbill_create_ip("1.1.1.1");

$inputObj->SetNonce_str(self::getNonceStr());//随机字符串

//签名

$inputObj->SetSign();

$xml = $inputObj->ToXml();

$startTimeStamp = self::getMillisecond();//请求开始时间

$response = self::postXmlCurl($xml, $url, false, $timeOut);

$result = WxPayResults::Init($response);        self::reportCostTime($url, $startTimeStamp, $result);//上报请求花费时间

return $result;

}2.3 上面代码中需要注意的有以下3点获取客服端的真实IP地址使用REMOTE_ADDR只能获取访问者本地连接中设置的IP。经本人粗略测试,使用UC浏览的时候将无法直接获取真实IP,这是如果把这个IP传过去,微信将会返回 网络环境未能通过安全验证,请稍后再试 的错误

这时可以使用以下方式获取用户真实IP//获取用户真实IP

public static function getIp(){

$ip = '';        if(isset($_SERVER['HTTP_X_FORWARDED_FOR'])){

$ip = $_SERVER['HTTP_X_FORWARDED_FOR'];

}elseif(isset($_SERVER['HTTP_CLIENT_IP'])){

$ip = $_SERVER['HTTP_CLIENT_IP'];

}else{

$ip = $_SERVER['REMOTE_ADDR'];

}

$ip_arr = explode(',', $ip);        return $ip_arr[0];

}把参数转换成XML格式在这JSON横行的年代,还使用XML格式传递数据,也许这是微信的高端操作,也许是他们以前的框架就是那样,这我们就不管了。直接上代码/**

* 输出xml字符

* @throws WxPayException

**/

public function ToXml()

{        if(!is_array($this->values)

|| count($this->values) <= 0)

{            throw new WxPayException("数组数据异常!");

}

$xml = "";        foreach ($this->values as $key=>$val)

{            if (is_numeric($val)){

$xml.="".$val."".$key.">";

}else{

$xml.="".$key.">";

}

}

$xml.="";        return $xml;

}签名方法

签名生成的通用步骤如下:

第一步,设所有发送或者接收到的数据为集合M,将集合M内非空参数值的参数按照参数名ASCII码从小到大排序(字典序),使用URL键值对的格式(即key1=value1&key2=value2…)拼接成字符串stringA。

特别注意以下重要规则:参数名ASCII码从小到大排序(字典序);

如果参数的值为空不参与签名;

参数名区分大小写;

验证调用返回或微信主动通知签名时,传送的sign参数不参与签名,将生成的签名与该sign值作校验。

微信接口可能增加字段,验证签名时必须支持增加的扩展字段

第二步,在stringA最后拼接上key得到stringSignTemp字符串,并对stringSignTemp进行MD5运算,再将得到的字符串所有字符转换为大写,得到sign值signValue。

key设置路径:微信商户平台(pay.weixin.qq.com)-->账户设置-->API安全-->密钥设置/**

* 生成签名

* @return 签名

*/

public function MakeSign()

{        //签名步骤一:按字典序排序参数

ksort($this->values);

$string = $this->ToUrlParams();        //签名步骤二:在string后加入KEY

$string = $string . "&key=".WxPayConfig::KEY;        //签名步骤三:MD5加密

$string = md5($string);        //签名步骤四:所有字符转为大写

$result = strtoupper($string);        return $result;

}    /**

* 格式化参数  --格式化成url参数

*/

public function ToUrlParams()

{

$buff = "";        foreach ($this->values as $k => $v)

{            if($k != "sign" && $v != "" && !is_array($v)){

$buff .= $k . "=" . $v . "&";

}

}

$buff = trim($buff, "&");        return $buff;

}2.4 通过返回的mweb_url参数调起微信APPif ($order['mweb_url']) {

$orderId = $input->GetOut_trade_no();

$payUrl = $order['mweb_url']."&redirect_url=http%3A%2F%2Fwww.xxxx.com%2Fwechatpay%2Forderquery.php%3Ftransaction_id%3D".$orderId;

Log::DEBUG($payUrl);        //通过JS打开链接,调起微信APP支付

echo "";

}这里详细解释一下payUrl中redirect_url参数的含义

正常流程用户支付完成后会返回至发起支付的页面,如需返回至指定页面,则可以在MWEB_URL后拼接上redirect_url参数,来指定回调页面。

如,您希望用户支付完成后跳转至https://www.wechatpay.com.cn,则可以做如下处理:

假设您通过统一下单接口获到的MWEB_URL= https://wx.tenpay.com/cgi-bin/mmpayweb-bin/checkmweb?prepay_id=wx20161110163838f231619da20804912345&package=1037687096

则拼接后的地址为MWEB_URL= https://wx.tenpay.com/cgi-bin/mmpayweb-bin/checkmweb?prepay_id=wx20161110163838f231619da20804912345&package=1037687096&redirect_url=https%3A%2F%2Fwww.wechatpay.com.cn

注意:

1.需对redirect_url进行urlencode处理

2.由于设置redirect_url后,回跳指定页面的操作可能发生在:1,微信支付中间页调起微信收银台后超过5秒 2,用户点击“取消支付“或支付完成后点“完成”按钮。因此无法保证页面回跳时,支付流程已结束,所以商户设置的redirect_url地址不能自动执行查单操作,应让用户去点击按钮触发查单操作,而我后面拼接的$orderId就是用于查单操作的参数。回跳页面展示效果可参考下图

AAffA0nNPuCLAAAAAElFTkSuQmCC

回调页面示例图.png

3.处理微信支付结果通知支付完成后,微信会把相关支付结果和用户信息发送给商户,商户需要接收处理,并返回应答。

对后台通知交互时,如果微信收到商户的应答不是成功或超时,微信认为通知失败,微信会通过一定的策略定期重新发起通知,尽可能提高通知的成功率,但微信不保证通知最终能成功。 (通知频率为15/15/30/180/1800/1800/1800/1800/3600,单位:秒)

注意:同样的通知可能会多次发送给商户系统。商户系统必须能够正确处理重复的通知。

推荐的做法是,当收到通知进行处理时,首先检查对应业务数据的状态,判断该通知是否已经处理过,如果没有处理过再进行处理,如果处理过直接返回结果成功。在对业务数据进行状态检查和处理之前,要采用数据锁进行并发控制,以避免函数重入造成的数据混乱。

特别提醒:商户系统对于支付结果通知的内容一定要做签名验证,并校验返回的订单金额是否与商户侧的订单金额一致,防止数据泄漏导致出现“假通知”,造成资金损失。

支付回调基础类/**

*

* 回调基础类

* @author widyhu

*

*/class WxPayNotify extends WxPayNotifyReply{    /**

*

* 回调入口

* @param bool $needSign  是否需要签名输出

*/

final public function Handle($needSign = true)

{

$msg = "OK";        //当返回false的时候,表示notify中调用NotifyCallBack回调失败获取签名校验失败,此时直接回复失败

$result = WxpayApi::notify(array($this, 'NotifyCallBack'), $msg);        if($result == false){            $this->SetReturn_code("FAIL");            $this->SetReturn_msg($msg);            $this->ReplyNotify(false);            return;

} else {            //该分支在成功回调到NotifyCallBack方法,处理完成之后流程

$this->SetReturn_code("SUCCESS");            $this->SetReturn_msg("OK");

}        $this->ReplyNotify($needSign);

}

/**

*

* 回调方法入口,子类可重写该方法

* 注意:

* 1、微信回调超时时间为2s,建议用户使用异步处理流程,确认成功之后立刻回复微信服务器

* 2、微信服务器在调用失败或者接到回包为非确认包的时候,会发起重试,需确保你的回调是可以重入

* @param array $data 回调解释出的参数

* @param string $msg 如果回调处理失败,可以将错误信息输出到该方法

* @return true回调出来完成不需要继续回调,false回调处理未完成需要继续回调

*/

public function NotifyProcess($data, &$msg)

{        //TODO 用户基础该类之后需要重写该方法,成功的时候返回true,失败返回false

return true;

}

/**

*

* notify回调方法,该方法中需要赋值需要输出的参数,不可重写

* @param array $data

* @return true回调出来完成不需要继续回调,false回调处理未完成需要继续回调

*/

final public function NotifyCallBack($data)

{

$msg = "OK";

$result = $this->NotifyProcess($data, $msg);

if($result == true){            $this->SetReturn_code("SUCCESS");            $this->SetReturn_msg("OK");

} else {            $this->SetReturn_code("FAIL");            $this->SetReturn_msg($msg);

}        return $result;

}

/**

*

* 回复通知

* @param bool $needSign 是否需要签名输出

*/

final private function ReplyNotify($needSign = true)

{        //如果需要签名

if($needSign == true &&

$this->GetReturn_code($return_code) == "SUCCESS")

{            $this->SetSign();

}

WxpayApi::replyNotify($this->ToXml());

}

}需要注意的是,如果用户只是打开付款界面,而没有执行付款操作的话,是不会触发通知的。

当我们接收到的参数中同时含有return_code,result_code,trade_state并且每个返回值都为SUCCESS的时候,代表用户付款成功if(array_key_exists("return_code", $result)

&& array_key_exists("result_code", $result)

&&array_key_exists("trade_state", $resultData)

&& $resultData["trade_state"] == "SUCCESS"

&& $result["return_code"] == "SUCCESS"

&& $result["result_code"] == "SUCCESS")

{            //这里执行给用户充值余额的操作

}

4.redirect_url回调页面处理

如果在第2.4步骤中MWEB_URL后拼接上了redirect_url参数,用户支付完成后将返回到这个页面。

当用户点击界面的已完成按钮,将触发查单操作

微信查单操作API

查单操作相关代码如下//查询订单

public function Queryorder($transaction_id)

{

$input = new WxPayOrderQuery();

$input->SetTransaction_id($transaction_id);

$result = WxPayApi::orderQuery($input);

Log::DEBUG("query:" . json_encode($result));        if(array_key_exists("return_code", $result)

&& array_key_exists("result_code", $result)

&& $result["return_code"] == "SUCCESS"

&& $result["result_code"] == "SUCCESS")

{            return $result;

}        return false;

}

界面布局以及相关的逻辑处理:if(isset($_REQUEST["out_trade_no"]) && $_REQUEST["out_trade_no"] != ""){

$out_trade_no = $_REQUEST["out_trade_no"];

$input = new WxPayOrderQuery();

$input->SetOut_trade_no($out_trade_no);

Log::DEBUG("out_trade_no".$out_trade_no);//  printf_info(WxPayApi::orderQuery($input));

$result=WxPayApi::orderQuery($input);    if(array_key_exists("return_code", $result)

&& array_key_exists("result_code", $result)

&& array_key_exists("trade_state", $result)

&& $result["trade_state"] == "SUCCESS"

&& $result["return_code"] == "SUCCESS"

&& $result["result_code"] == "SUCCESS"){

$successUrl="success.html";        echo "";

}else{

$failUrl="fail.html";        echo "";

}    exit();

}?>

window.=function () {        var Request=new UrlSearch(); //实例化

document.getElementById("out_trade_no").value=Request.transaction_id;

document.getElementById("transaction_id").style.height = 0;

document.getElementById("out_trade_no").style.height = 0;

document.getElementById("btn").style.height = 0;

$.DialogByZ.Confirm({Title: "", Content: "请确认微信支付是否已完成",FunL:confirmL,FunR:Immediate})

}    ///

function confirmL(){

$.DialogByZ.Close();

document.getElementById('btn').click();

}    function Immediate(){        //location.href="http://sc.chinaz.com/jiaoben/"

window.location.href="nonglegou://data/?state=fail";

}    function UrlSearch()

{        var name,value;        var str=location.href; //取得整个地址栏

var num=str.indexOf("?")

str=str.substr(num+1); //取得所有参数   stringvar.substr(start [, length ]

var arr=str.split("&"); //各个参数放到数组里

for(var i=0;i < arr.length;i++){

num=arr[i].indexOf("=");            if(num>0){

name=arr[i].substring(0,num);

value=arr[i].substr(num+1);

this[name]=value;

}

}

}

三、总结

微信H5支付的整个流程,大概就是这样子,以下是流程图

AAffA0nNPuCLAAAAAElFTkSuQmCC

接口流程图用户在商户侧完成下单,使用微信支付进行支付

由商户后台向微信支付发起下单请求(调用统一下单接口)注:交易类型trade_type=MWEB

统一下单接口返回支付相关参数给商户后台,如支付跳转url(参数名“mweb_url”),商户通过mweb_url调起微信支付中间页

中间页进行H5权限的校验,安全性检查(此处常见错误请见下文)

如支付成功,商户后台会接收到微信侧的异步通知

用户在微信支付收银台完成支付或取消支付,返回商户页面(默认为返回支付发起页面)

商户在展示页面,引导用户主动发起支付结果的查询

商户后台判断是否接到收微信侧的支付结果通知,如没有,后台调用我们的订单查询接口确认订单状态

展示最终的订单支付结果给用户

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

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

相关文章

秒杀系统架构分析与实战

0 系列目录 秒杀系统架构 秒杀系统架构分析与实战1 秒杀业务分析 正常电子商务流程 &#xff08;1&#xff09;查询商品&#xff1b;&#xff08;2&#xff09;创建订单&#xff1b;&#xff08;3&#xff09;扣减库存&#xff1b;&#xff08;4&#xff09;更新订单&#xff1…

如何提高安卓代码的质量和语法

本文讲的是如何提高安卓代码的质量和语法&#xff0c;在这篇文章中&#xff0c;我会介绍几种不同的方式&#xff0c;让你通过自动化工具提高你的Android代码质量&#xff0c;包括 Checkstyle&#xff0c; Findbugs&#xff0c;PMD&#xff0c; 当然&#xff0c;还有我们最熟悉的…

grep 命令的 12 个实例

2019独角兽企业重金招聘Python工程师标准>>> 你是否遇到过需要在文件中查找一个特定的字符串或者样式&#xff0c;但是不知道从哪儿开始&#xff1f;那么,就请grep来帮你吧。 grep是每个Linux发行版都预装的一个强有力的文件模式搜索工具。无论何种原因&#xff0c;…

Linux : shell基础(慕课网Linux达人养成计划课程笔记)

Shell概述 shell是Linux中的命令行解释器&#xff0c;为用户提供了一个向Linux内核发送请求一边运行程序的界面系统级程序&#xff0c;用户可以用shell来启动、挂起、停止甚至编写一些程序。shell还是一个功能相当强大的编程语言&#xff0c;易编写&#xff0c;易调试&#xff…

php图型分析插件,IMAGE缩略图插件

应用信息 名称: IMAGE缩略图插件 售价: (免费) 应用ID: IMAGE 最低要求: Z-BlogPHP 1.5.1 Zero Build 151740版 本: 2 发布日期: 2014-08-27PHP最低版本要求: 5.3 更新日期: 2018-05-21立即购买 加入购物车作者信息 开发者ID: 十五楼的鸟儿 本站用户组: 管理员 联系邮箱: adm…

2017.9.5 postgresql加密函数的使用

需要安装的插件的名字&#xff1a;pgcrypto官网地址&#xff1a;https://www.postgresql.org/docs/9.4/static/pgcrypto.htmlstackoverflow:https://stackoverflow.com/questions/8000740/how-do-i-install-pgcrypto-in-postgresql-9-1-on-windows/46046367#46046367https://st…

php 序列化方法,PHP序列化操作方法分析

本文实例讲述了PHP序列化操作方法。分享给大家供大家参考&#xff0c;具体如下&#xff1a;序列化就是将变量数据转换为字符串(跟类型转换机制不同)&#xff0c;一般应用于存储数据(文件)&#xff0c;然后在别的情形下恢复(反序列化)序列化&#xff1a;$val serialize($var);f…

Redis入门到精通-Redis数据类型

2019独角兽企业重金招聘Python工程师标准>>> 登录Redis数据库 [rootlocalhost bin]# /usr/local/redis/bin/redis-cli String类型 ​ String 数据结构是简单的key-value类型&#xff0c;value其实不仅是String&#xff0c;也可以是数字&#xff0c;是包含很多种类型…

装机之 BIOS、EFI与UEFI详解

在我们的电脑中&#xff0c;都有一块黑色的小芯片。但是请千万不要小看它&#xff0c;如果它损坏或者数据错误乱套的话&#xff0c;恭喜&#xff0c;如果不会“救回”这个小芯片&#xff0c;那么这台电脑可以挂闲鱼卖零件了…… 这个小芯片是什么呢&#xff1f;对&#xff0c;…

php 模板 php + mysql + myodbc,连接MySQL数据库在ASP中,就用MyODBC

我们大家都知道ASP与MySQL连接现在应用最为广泛的两种办法是&#xff0c;一是使用组件&#xff0c;经常使用的是MySQL(和PHP搭配之最佳组合)X&#xff0c;可惜价格很贵。另一个就是用MyODBC来连接MySQL数据库&#xff0c;下面我们就来看看第二种方式。 试验的平台&#xff1a; …

Android Gradle和Gradle插件区别

2019独角兽企业重金招聘Python工程师标准>>> 一、引言 1、什么是Gradle?什么是Gradle插件? build.gradle中依赖的classpath com.android.tools.build:gradle:2.1.2和gradle-wrapper.properties中的distributionUrlhttps\://services.gradle.org/distributions/gra…

装机之MBR和GPT

MBR分区 MBR的意思是“主引导记录”&#xff0c;是IBM公司早年间提出的。它是存在于磁盘驱动器开始部分的一个特殊的启动扇区。这个扇区包含了已安装的操作系统系统信息&#xff0c;并用一小段代码来启动系统。如果你安装了Windows&#xff0c;其启动信息就放在这一段代码中—…

实验报告3

中国人民公安大学 Chinese people’ public security university 网络对抗技术 实验报告 实验三 密码破解技术 学生姓名 陆圣宇 年级 2014 区队 三 指导教师 高见 信息技术与网络安全学院 2016年11月7日 实验任务总纲 2016—2017 学年 第 一 学期 一、实验目的 1&am…

装机之windows10和ubuntu双系统

制作系统U盘 下载Ubuntu16.04 我们首先去Ubuntu的官网下载一个Ubuntu16.04的iso镜像文件。当然里面也有优麒麟&#xff0c;其实就是把Ubuntu16.04汉化了一下&#xff0c;个人推荐安装Ubuntu16.04 体验上可能好一些。 利用软碟通制作 不会的可以查看此教程https://blog.csdn…

matlab var std,Matlab var std cov 函数解析

在Matlab中使用var求样本方差&#xff0c;使用std求标准差&#xff01;首先来了解一下方差公式&#xff1a;p [-0.92 0.73 -0.47 0.74 0.29; -0.08 0.86 -0.67 -0.52 0.93]p -0.9200 0.7300 -0.4700 0.7400 0.2900-0.0800 0.8600 -0.6700 -0.5200 0.9300…

Java中什么是匿名对象,空参构造方法输出创建了几个匿名对象,属性声明成static...

package com.swift; //使用无参构造方法自动生成对象&#xff0c;序号不断自增 public class Person {private static int count; //如果在定义类时&#xff0c;使用的是静态的属性&#xff0c;则得到的结果是不同的。count生命周期长&#xff0c;与类相同public int id;public…

装机之制作系统U盘

工具&#xff1a;UltraISO&#xff08;软碟通&#xff09;&#xff0c;iso镜像 在制作系统U盘的时候我们需要去下一个软件——UltraISO&#xff08;软碟通&#xff09;&#xff0c;这个自己去百度搜索一下应该就能出来的。下载安装完以后&#xff0c;我们打开软碟通的界面打开…

李飞飞:为什么计算机视觉对机器人如此重要?

根据Guide2Research的排名&#xff0c;IROS是计算机视觉领域排名第四的学术会议&#xff0c;前三名分别为CVPR、ICCV、ECCV。计算机视觉在机器人的发展史中起着非常重要的作用&#xff0c;与之相关的“感知”也正是历年IROS大会上的重要内容&#xff0c;随着机器人研究的发展和…

linux 命令 which whereis locate find

0、概述 * which&#xff1a;在PATH变量指定的路径中&#xff0c;搜索与指定名字匹配的系统命令的位置&#xff0c;并且返回第一个搜索结果。 * whereis&#xff1a;搜索与指定名字匹配的二进制文件、源文件和帮助手册文件所在的路径。二进制文件&#xff08;参数-b&…

python 转 exe -- py2exe库实录

本文基于windows 7 python 3.4 把python程序打包成exe&#xff0c;比较好用的库是py2exe 其操作步骤是: --> 编写python程序 --> 再额外编写一个导入了py2exe的python脚本(不妨如&#xff1a;setup.py)存在同一目录下 --> 运行这个脚本&#xff0c;打包生成的exe文件…