Nginx重定向[Rewrite]配置

nginx rewrite 各参数意义

$arg_PARAMETER #这个变量包含GET请求中,如果有变量PARAMETER时的值。

$args #这个变量等于请求行中(GET请求)的参数,例如foo=123&bar=blahblah;

$binary_remote_addr #二进制的客户地址。

$body_bytes_sent #响应时送出的body字节数数量。即使连接中断,这个数据也是精确的。

$content_length #请求头中的Content-length字段。

$content_type #请求头中的Content-Type字段。

$cookie_COOKIE #cookie COOKIE变量的值

$document_root #当前请求在root指令中指定的值。

$document_uri #与$uri相同。

$host #请求主机头字段,否则为服务器名称。

$hostname #Set to the machine’s hostname as returned by gethostname

$http_HEADER

$is_args #如果有$args参数,这个变量等于”?”,否则等于””,空值。

$http_user_agent #客户端agent信息

$http_cookie #客户端cookie信息

$limit_rate #这个变量可以限制连接速率。

$query_string #与$args相同。

$request_body_file #客户端请求主体信息的临时文件名。

$request_method #客户端请求的动作,通常为GET或POST。

$remote_addr #客户端的IP地址。

$remote_port #客户端的端口。

$remote_user #已经经过Auth Basic Module验证的用户名。

$request_completion #如果请求结束,设置为OK. 当请求未结束或如果该请求不是请求链串的最后一个时,为空(Empty)。

$request_method #GET或POST

$request_filename #当前请求的文件路径,由root或alias指令与URI请求生成。

$request_uri #包含请求参数的原始URI,不包含主机名,如:”/foo/bar.php?arg=baz”。不能修改。

$scheme #HTTP方法(如http,https)。

$server_protocol #请求使用的协议,通常是HTTP/1.0或HTTP/1.1。

$server_addr #服务器地址,在完成一次系统调用后可以确定这个值。

$server_name #服务器名称。

$server_port #请求到达服务器的端口号。

$uri #不带请求参数的当前URI,$uri不包含主机名,如”/foo/bar.html”。该值有可能和$request_uri 不一致。$request_uri是浏览器发过来的值。该值是rewrite后的值。例如做了internal redirects后。

今 天在给某网站写rewrite重定向规则时,碰到了这个关于重定向的参数处理问题。默认的情况下,Nginx在进行rewrite后都会自动添加上旧地址 中的参数部分,而这对于重定向到的新地址来说可能是多余。虽然这也不会对重定向的结果造成多少影响,但当你注意到新地址中包含有多余的“?xxx=xxx”时,心里总还是会觉得不爽。那么该如何来处理这部分的内容呢?看了下面两个简单的例子你就会明白了。

例如:
http://example.com/test.php?para=xxx 重定向到 http://example.com/new
若按照默认的写法:rewrite ^/test.php(.*) /new permanent;
重定向后的结果是:http://example.com/new?para=xxx
如果改写成:rewrite ^/test.php(.*) /new? permanent;
那结果就是:http://example.com/new

所以,关键点就在于“?”这个尾缀。假如又想保留某个特定的参数,那又该如何呢?可以利用Nginx本身就带有的$arg_PARAMETER参数来实现。

例如:
http://example.com/test.php?para=xxx&p=xx 重写向到 http://example.com/new?p=xx
可以写成:rewrite ^/test.php /new?p=$arg_p? permanent;

只求结果的朋友可以直接忽略前面的内容,看这里:

rewrite  ^/test.php  /new  permanent;       //重写向带参数的地址

    rewrite  ^/test.php  /new?  permanent;      //重定向后不带参数

    rewrite  ^/test.php   /new?id=$arg_id?  permanent;    //重定向后带指定的参数

permanent是永久重定向参数,根据需要去掉也可以,不过最好是带有。
参考301重定向与302重定向的区别

首先Apache的Rewite规则差别不是很大,但是Nginx的Rewrite规则比Apache的简单灵活多了
Nginx可以用if进行条件匹配,语法规则类似C

if ($http_user_agent ~ MSIE) {
rewrite ^(.*)$ /msie/$1 break;
}

Rewrite的Flags

Flags can be any of the following:
* last - completes processing of rewrite directives, after which searches for corresponding URI and location
* break - completes processing of rewrite directives
*redirect - returns temporary redirect with code 302; it is used if the substituting line begins with http://
* permanent - returns permanent redirect with code 301

last – 完成重写指令后,搜索相应的URI和位置。相当于Apache里的[L]标记,表示完成rewrite,不再匹配后面的规则。
break – 中止Rewirte,不在继续匹配。
redirect – 返回临时重定向的HTTP状态302。
permanent – 返回永久重定向的HTTP状态301。

ZEND Framework的重定向规则:
案例一:
全部重定向到 /index.php

rewrite ^/(.*) /index.php?$1&;

案例二:
如果文件或目录不存在则重定向到index.php

if (!-e $request_filename) {
rewrite ^/(.*) /index.php?$1&;
}

WordPress的重定向规则:
案例一:
http://www.wemvc.com/12 重定向到 http://www.wemvc.com/index.php?p=12

if (!-e $request_filename) {
rewrite ^/(.+)$ /index.php?p=$1 last;
}

案例二:
与zendframework配置很像

if (!-e $request_filename) {
rewrite ^/(.*) /index.php?$1&;
}

以下为Discuz完整的Rewrite for Nginx规则

if (!-f $request_filename) {
rewrite ^/archiver/((fid|tid)-[w-]+.html)$ /archiver/index.php?$1 last;
rewrite ^/forum-([0-9]+)-([0-9]+).html$ /forumdisplay.php?fid=$1&page=$2 last;
rewrite ^/thread-([0-9]+)-([0-9]+)-([0-9]+).html$ /viewthread.php?tid=$1&extra=page=$3&page=$2 last;
rewrite ^/space-(username|uid)-(.+).html$ /space.php?$1=$2 last;rewrite ^/tag-(.+).html$ /tag.php?name=$1 last;
}

文件及目录匹配,其中:
-f和!-f用来判断是否存在文件
-d和!-d用来判断是否存在目录
-e和!-e用来判断是否存在文件或目录
-x和!-x用来判断文件是否可执行

正则表达式全部符号解释
~ 为区分大小写匹配
~* 为不区分大小写匹配
!~和!~* 分别为区分大小写不匹配及不区分大小写不匹配
(pattern) 匹配 pattern 并获取这一匹配。所获取的匹配可以从产生的 Matches 集合得到,在VBScript. 中使用 SubMatches 集合,在JScript. 中则使用 $0…$9 属性。要匹配圆括号字符,请使用 ‘(’ 或 ‘)’。
^ 匹配输入字符串的开始位置。
$ 匹配输入字符串的结束位置。

$(function () {
$('pre.prettyprint code').each(function () {
var lines = $(this).text().split('n').length;
var $numbering = $('

    ').addClass('pre-numbering').hide();
    $(this).addClass('has-numbering').parent().append($numbering);
    for (i = 1; i <= lines; i++) {
    $numbering.append($('
  • ').text(i));
    };
    $numbering.fadeIn(1700);
    });
    });

此文章通过 python 爬虫创建,原文是自己的csdn 地址: Nginx重定向[Rewrite]配置

php 版本 微信支付 APP 服务端开发

我们通过 微信支付的文档知道 第一步 服务端需要调用统一下单接口生成预付单,其中主要的参数就是 prepay_id 这样 app 通过 prepay_id 就可以发起支付请求了。
我们可以参考 微信支付的 官方SDK(就是个坑)
统一下单接口就是 调用函数

WxPayApi::unifiedOrder($input);

其中的一个参数 设置为:

$input->SetTrade_type("APP");

没有服务端demo 可以参考 JSAPI的修改上面的参数就可以了
统一下单接口定义在 WxPay.Api.php中其中有代码

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

即向微信接口发送所需要的数据 ,这里面就会出现坑爹的地方。

记得以前版本的 sdk 单词CURLOPT 少些个T
这次是需要把代码

curl_setopt($ch,CURLOPT_SSL_VERIFYPEER,TRUE);

改为

curl_setopt($ch,CURLOPT_SSL_VERIFYPEER,FALSE);

在 WxPay.Data.php中有函数 FromXml($xml)
其中有代码
libxml_disable_entity_loader(true);
这个函数可能引起很大的问题
他的初衷本来是为安全考虑,禁止引用外部xml 网上的一个bug 解释是:

The function 'libxml_disable_entity_loader' is not thread safe so, if a thread configure it to 'true' all the others threads are true too. And it should be at 'false' by default when a new request come. That is why the problem disappears when we restart php-fpm daemon.
If you write this at the beginning of app.php we can see that all is working again:
<?php// app.php
libxml_disable_entity_loader(false);


The problem is caused by some third-party bundle or library, because it must be changing to true and is not restoring to false again.

一些PHP框架使用了这个函数 就会出现问题,我使用magento框架 测试微信支付,添加了这个函数 结果这个服务器上的其它web测试环境都不能够正常访问了。应该就是破坏了整个服务器的load xml 逻辑。
重启服务器后正常,所以我干脆就注释掉了这个函数。
再之后就是得到 prepay_id 后 依照客户端需要的参数给相应参数
但是给客户端的时候需要二次加密
就是在走一遍 加密流程
大致 函数是:

if($order['result_code'] == 'SUCCESS' && $order['return_code'] == 'SUCCESS'){
            $data['appid'] = $order['appid'];
            $data['noncestr'] = WxPayApi::getNonceStr();
            $data['package'] = 'Sign=WXPay';
            $data['partnerid'] = WxPayConfig::MCHID;
            $data['prepayid'] = $order['prepay_id'];
            $data['timestamp'] = time();
            $s = $this->MakeSign($data);
            $data['sign'] = $s;
            $resJson = json_encode($data);
            echo $resJson;

这样客户端就能够正常像微信发送支付请求了。
最后 就是 写好 服务端的 notify函数
根据业务流程 和 notify demo 修改即可

 

此文章通过 python 爬虫创建,原文是自己的csdn 地址: php 版本 微信支付 APP 服务端开发

 

Magento 手机支付 (支付宝无线支付)

 现在magento 支付宝插件在网上还是很多的。但是支付宝无线支付貌似还不多。这里我只是根据官方文档和其它

支付方式编写出无线支付的雏形,可用但是不完善,先记录在这里。(当然文章是点到为止,只给我这种菜鸟看看,大神无视我吧。)

---------------------------------------------------我就是分割线怎么了---------------------------------------------------   

首先肯定是要熟悉支付宝官方给出的文档

手机网页即时到账接口 和 手机网页支付接入与使用规则 以及 demo 代码

之后开始梳理流程:

(一下是在默认情况下,不要纠结个别变量的不同)

1. 在magento中我们点击结账,如果支付方式选择的是第三方支付方式会跳转到相应支付方式Paymentcontroller里的redirectAction

    在模块的system.xml 中加入你自己的后台配置代码

2. 在这里magento最主要的是 记录$order以及createBlock 输出html

$this->getResponse()
            ->setBody($this->getLayout()
                ->createBlock('alipaymobile/redirect')
                ->setOrder($order)
                ->toHtml());

3. 在输出的页面 例如是支付宝或者快钱等支付方式通常是隐藏的form表单包含要提交的信息,以及自动提交的js  

    但是支付宝无线支付有些不同,从官方文档中得知 我们首先需要 获得授权即调用接口手机网页即时到账授权接口

    然后才是 调用接口手机网页即时到账交易接口

    那么我的解决思路是在 Block/Redirect.php 中先去掉用授权接口然后是代码自动调用即时到帐接口完成结账。

    这时候看到的网页是要跳转两次的。

4. 首先调用授权接口 隐藏的form表单提交的 url地址应当是 里一个例如AlipayapiController

    并且主要代码都是在这个controller中实现的

   

//建立请求
        $alipaySubmit = new AlipaySubmit($alipay_config);
        $html_text = $alipaySubmit->buildRequestHttp($para_token);

//获取request_token
        $request_token = $para_html_text['request_token'];

//建立请求
        $alipaySubmit = new AlipaySubmit($alipay_config);
        $html_text = $alipaySubmit->buildRequestForm($parameter, 'get', '确认');

   注意:按这种方法其中出现的一个重要问题是会获取不到 notifyUrl 和 SuccessUrl, (除非你直接写的绝对路径,而不是从model中获取的)

               是因为 在model中 getSuccessURL 和 getNotifyURL 都是使用protected声明的。 最简单的解决办法是改成public

               以我之愚见好像没必要声明成protected

5. 处理success代码 和 notify代码即可。

这完成了结账流程没错,但是只是90%吧,因为还有重要的前端处理流程。

即PC端 是不需要显示这个支付方式的 一种解决办法是

在template/checkout/onpage/payment/methods.phtml 中找到代码

foreach ($methods as $_method):
        $_code = $_method->getCode();

在后面加上

if($_code == "alipaymobile_payment"){
            continue;
        }

即可,当然这里的 alipaymobile_payment  要自己根据实际情况来定了。

另一个需要修改的地方是我的订单包括历史订单页面(我这里实在之前开发了继续支付功能)

当你在手机选择了 支付宝无线支付 但是没有做付款操作,转而用电脑继续,那么此时在订单付款按钮处就

不应该选择支付宝无线支付了。可以使用

$paymentsAllMethods = Mage::getSingleton('payment/config')->getActiveMethods();

过滤出可用的支付方式即可。

至此 就基本完成了。大家凑合看吧,其实有了官方文档,加上对magento有些了解花点时间就可以写出来的

我只不过写下我自己的解决办法。 不喜勿喷!欢迎指正!

懒得开发的可以联系我

但我不会去帮你定制。(哎呀,我的服务竟然这么差!)

---------------------------------------------------我就是分割线怎么了---------------------------------------------------

这是发在CSDN的第一篇文章,所以必须是原创的! 

最开始在新浪上写博客,后来到百度空间,我只想说百度空间让我几乎没有了写博客的欲望。

总之现在又想乱写点东西了,给自己看也好。

PS: 会陆续把我印象笔记里的东西拿过来。

此文章通过 python 爬虫创建,原文是自己的csdn 地址: Magento 手机支付 (支付宝无线支付)