php 连接rabbitmq

作者: 分类: php 时间: 2022-06-27 评论: 暂无评论

composer require php-amqplib/php-amqplib 3.1.2

<?php


namespace app\ospay\model;

use app\common\library\helper;
use PhpAmqpLib\Channel\AMQPChannel;
use PhpAmqpLib\Connection\AMQPSocketConnection;
use PhpAmqpLib\Message\AMQPMessage;
use PhpAmqpLib\Wire\AMQPAbstractCollection;
use PhpAmqpLib\Wire\AMQPTable;
use think\facade\Db;
use think\Model;
use app\ospay\serve\LvServe;

/**
 * 支付系统
 * Class OsPay
 * @package app\ospay\model
 */
class OsQueen extends Model
{
    public static $QUEEN_KEY = 'OS_PAY_NOTIFY_LIST';

    public static $CON;


    public static function getQueenCon()
    {
        // 创建链接
        $connection = new AMQPSocketConnection(
            config('rabbitmq.host'), config('rabbitmq.port'),
            config('rabbitmq.login'), config('rabbitmq.password'),
            config('rabbitmq.vhost'), false,
            'AMQPLAIN', null, 'en_US',
            3, false, 3, 60
        );
        return $connection;
    }
    public static function getChan(AMQPSocketConnection $connection)
    {
        $arg = new AMQPTable();
        $arg->set('x-max-length', 100*10000); //缓冲队列 最长100万
        $arg->set('x-max-length-bytes', 512 * 1000 * 1000);  //单位字节(byte) 512M
        $channel = $connection->channel();
        $channel->queue_declare(OsQueen::$QUEEN_KEY, false, true, false, false, false, $arg);
        return $channel;
    }

    /**
     * 添加到队列
     *
     */
    public static function sendQueen(AMQPChannel $channel,$data)
    {
        $msg = new AMQPMessage($data, ['delivery_mode' => AMQPMessage::DELIVERY_MODE_PERSISTENT]);
        $channel->basic_publish($msg, '', self::$QUEEN_KEY);

    }


    /**
     * 消费者
     * @throws \ErrorException
     */
    public static function consume(string $tag)
    {
        echo $tag;
        // 创建链接
        $con=OsQueen::getQueenCon();
        $chan=OsQueen::getChan($con);
        $func = function (AMQPMessage $msg) {
            OsQueen::notifyOrder($msg->getBody());
            $msg->ack();
        };
        $chan->basic_qos(null, 1, null);
        $chan->basic_consume(self::$QUEEN_KEY, $tag, false, false, false, false, $func);
        while($chan->is_open()) {
            $chan->wait();
        }
    }

    public static function notifyOrder($queen_id)
    {
        $order = OsQueen::find($queen_id);
        $config=OsShopAttach::where('shop_id',$order['shop_id'])->cache(600)->find();
        if(!empty($order)&&$order['notify_status']==0){
            $data = [
                'code' => $order['code'],
                'shop_id' => $order['shop_id'],
                'out_trade_no' => $order['out_trade_no'],
                'order_no' => $order['order_no'],
                'total_fee' => $order['total_fee'],
            ];

            $data['sign'] = LvServe::sign($data,$config['md5_key']);
            $data['attach'] = $order['attach'];
            $data['msg'] = $order['msg'];

            $w[] = [
                'id', '=', $order['id']
            ];
            try {
                $resp = LvServe::curl($order['notify_url'], $data, 6);
                $up = [];
                $up['notify_status'] = strtoupper($resp) == 'SUCCESS' ? 1 : 0;
                $up['update_at'] = time();
                $up['notify_num']=Db::raw('notify_num+1');
                OsQueen::where($w)->update($up);
            } catch (\Exception $e) {
                log_write(helper::jsonEncode($e->getMessage()), 'error');
                $up['notify_status'] =  0;
                $up['update_at'] = time();
                OsQueen::where($w)->update($up);
                return;
            }
        }
    }

}

公钥和私钥

作者: 分类: php 时间: 2022-06-24 评论: 暂无评论

1.加密方式分为对称加密和非对称加密,对称加密只使用一个秘钥,加密和解密都使用该秘钥;非对称加密则使用一对秘钥,使用公钥加密,私钥解密。

** 2.公钥和私钥成对出现

公开的密钥叫公钥,只有自己知道的叫私钥
用公钥加密的数据只有对应的私钥可以解密
用私钥加密的数据只有对应的公钥可以解密
如果可以用公钥解密,则必然是对应的私钥加的密
如果可以用私钥解密,则必然是对应的公钥加的密** 

3.发送方(A)使用接收方(B)的公钥对数据加密,使用自己的私钥对加密数据进行签名。然后组装加密数据和签名,发送给接收方(B)
接收方(B)接收到A的数据后。先使用发送方(A)的公钥数据加密数据进行验签,签名无问题后。再使用自己的私钥对数据进行解密。

公钥私钥.png

编码格式
同样的X.509证书,可能有不同的编码格式,目前有以下两种编码格式.

PEM - Privacy Enhanced Mail,打开看文本格式,以"-----BEGIN..."开头, "-----END..."结尾,内容是BASE64编码.
查看PEM格式证书的信息:openssl x509 -in certificate.pem -text -noout
Apache和*NIX服务器偏向于使用这种编码格式.

DER - Distinguished Encoding Rules,打开看是二进制格式,不可读.
查看DER格式证书的信息:openssl x509 -in certificate.der -inform der -text -noout
Java和Windows服务器偏向于使用这种编码格式.

相关的文件扩展名
这是比较误导人的地方,虽然我们已经知道有PEM和DER这两种编码格式,但文件扩展名并不一定就叫"PEM"或者"DER",常见的扩展名除了PEM和DER还有以下这些,它们除了编码格式可能不同之外,内容也有差别,但大多数都能相互转换编码格式.

CRT - CRT应该是certificate的三个字母,其实还是证书的意思,常见于*NIX系统,有可能是PEM编码,也有可能是DER编码,大多数应该是PEM编码,相信你已经知道怎么辨别.

CER - 还是certificate,还是证书,常见于Windows系统,同样的,可能是PEM编码,也可能是DER编码,大多数应该是DER编码.

KEY - 通常用来存放一个公钥或者私钥,并非X.509证书,编码同样的,可能是PEM,也可能是DER.
查看KEY的办法:openssl rsa -in mykey.key -text -noout
如果是DER格式的话,同理应该这样了:openssl rsa -in mykey.key -text -noout -inform der

CSR - Certificate Signing Request,即证书签名请求,这个并不是证书,而是向权威证书颁发机构获得签名证书的申请,其核心内容是一个公钥(当然还附带了一些别的信息),在生成这个申请的时候,同时也会生成一个私钥,私钥要自己保管好.做过iOS APP的朋友都应该知道是怎么向苹果申请开发者证书的吧.
查看的办法:openssl req -noout -text -in my.csr (如果是DER格式的话照旧加上-inform der,这里不写了)

PFX/P12 - predecessor of PKCS#12,对*nix服务器来说,一般CRT和KEY是分开存放在不同文件中的,但Windows的IIS则将它们存在一个PFX文件中,(因此这个文件包含了证书及私钥)这样会不会不安全?应该不会,PFX通常会有一个"提取密码",你想把里面的东西读取出来的话,它就要求你提供提取密码,PFX使用的时DER编码,如何把PFX转换为PEM编码?
openssl pkcs12 -in for-iis.pfx -out for-iis.pem -nodes
这个时候会提示你输入提取代码. for-iis.pem就是可读的文本.
生成pfx的命令类似这样:openssl pkcs12 -export -in certificate.crt -inkey privateKey.key -out certificate.pfx -certfile CACert.crt

其中CACert.crt是CA(权威证书颁发机构)的根证书,有的话也通过-certfile参数一起带进去.这么看来,PFX其实是个证书密钥库.

最后加上自己的理解:

PEM和DER是不同的编码方式,PEM在linux上常用,DER在window上常用,可以相互转换。

在linux上常用crt和key俩文件,在window常用PFX,PFX里边包含证书和私钥,可以用来生成,也可以通过证书和私钥合成PFX,都是可以的。

依赖注入

作者: 分类: php 时间: 2022-06-20 评论: 暂无评论

基本概念
我们可以用一个简单的例子来说明依赖注入的概念

下面的代码中有一个 Database 的类,它需要一个适配器来与数据库交互。我们在构造函数里实例化了适配器,从而产生了耦合。这会使测试变得很困难,而且 Database 类和适配器耦合的很紧密。

<?php
namespace Database;

class Database
{
    protected $adapter;

    public function __construct()
    {
        $this->adapter = new MySqlAdapter;
    }
}

class MysqlAdapter {}

这段代码可以用依赖注入重构,从而解耦

<?php
namespace Database;

class Database
{
    protected $adapter;

    public function __construct(MySqlAdapter $adapter)
    {
        $this->adapter = $adapter;
    }
}

class MysqlAdapter {}

现在,我们以参数的形式向 Database 类传递其依赖的对象,而不是让它自己产生所依赖的对象。我们甚至可以创建一个方法(method),让这个方法可以接受依赖对象作为参数并在内部设置依赖关系,或者,如果 $adapter 属性本身是 public 的,我们可以直接给它赋值。

复杂的问题
如果你曾经了解过依赖注入,那么你可能见过 “控制反转”(Inversion of Control) 或者 “依赖反转准则”(Dependency Inversion Principle)这种说法。这些是依赖注入能解决的更复杂的问题。

控制反转
顾名思义,一个系统通过组织控制和对象的完全分离来实现”控制反转”。对于依赖注入,这就意味着通过在系统的其他地方控制和实例化依赖对象,从而实现了解耦。

一些 PHP 框架很早以前就已经实现控制反转了,但是问题是,应该反转哪部分以及到什么程度?比如, MVC 框架通常会提供超类或者基本的控制器类以便其他控制器可以通过继承来获得相应的依赖。这就是控制反转的例子,但是这种方法是直接移除了依赖而不是减轻了依赖。

依赖注入允许我们通过按需注入的方式更加优雅地解决这个问题,完全不需要任何耦合。

依赖反转准则
依赖反转准则是面向对象设计准则 S.O.L.I.D 中的 “D” ,倡导 “依赖于抽象而不是具体”。简单来说就是依赖应该是接口/约定或者抽象类,而不是具体的实现。我们能很容易重构前面的例子,使之遵循这个准则

<?php
namespace Database;

class Database
{
    protected $adapter;

    public function __construct(AdapterInterface $adapter)
    {
        $this->adapter = $adapter;
    }
}

interface AdapterInterface {}

class MysqlAdapter implements AdapterInterface {}

php项目优化秘籍

作者: 分类: php 时间: 2022-06-16 评论: 暂无评论

1.opchache 性能加强20%
2.水平分表,减少一半字段,对select count(money) 加强15%,对select * 加强在50%
3.PB级数据,列存sql(比如 select count(money)),建议上polardb。记得忽略索引(where 1=1 或 use index())。1000万条数据,mysql需要40s,列存数据3秒