分类 PHP 下的文章

fiber-ext.jpg

根据上图,可以看出来Fiber的大体执行流程,如下:

1、fiber 大概就是实现了一种主执行流程和fiber执行流程的手动切换。
2、fiber->start() 从main流程切换到fiber流程执行。
3、Fiber::suspend() 从fiber切换到main流程。
4、接下来main流程可以执行一些操作,或者顶一个事件循环监听socket的数据情况
5、当有数据写入事件后,调用Fiber->resume 切换到fiber中去执行比如从socket读取数据这样的操作。
6、fiber的流程代码执行完毕以后,也就自动切换到主流程,如果事件循环也结束了,那么就主流程继续向下执行。

转自:https://www.simapple.com/459.html

方案一

Casbin的核心-表.png

Casbin的核心.png

方案二

111.JPG
原理

222.JPG
规则

333.JPG
数据ER

444.PNG
管理UI

555.JPG
数据表实例

特别声明:其中方案二为某大佬线上生产环境系统设计,如果侵犯到此权限请通知我删除,同时采纳者一同承担相应责任。

POST

<?php
/**
 * curl POST请求
 * @param string $url 请求地址
 * @param array $data 请求数据
 * @param bool $json 请求格式[urlencoded|json]
 * @return bool|string
 */
function curlPost(string $url, array $data, bool $json = true)
{

    if ($json) {
        $str_data = json_encode($data, JSON_UNESCAPED_UNICODE);
        $header = ['Content-Type: application/json'];
    } else {
        // 默认选项
        $str_data = http_build_query($data);
        $header = ['Content-Type: application/x-www-form-urlencoded'];
    }
    $ch = curl_init($url);
    curl_setopt_array($ch, [
        CURLOPT_RETURNTRANSFER => true,
        CURLOPT_POST => true,
        CURLOPT_POSTFIELDS => $str_data,
        CURLOPT_HTTPHEADER => $header,
        CURLOPT_SSL_VERIFYHOST => false,
        CURLOPT_SSL_VERIFYPEER => false,
    ]);
    $output = curl_exec($ch);
    curl_close($ch);
    return $output;
}

GET

<?php
/**
 * curl GET请求
 */
function curlGet($url){
    $ch = curl_init($url);
    curl_setopt_array($ch,[
        CURLOPT_RETURNTRANSFER => true,
    ]);
    $output = curl_exec($ch);
    curl_close($ch);
    return $output;
}

什么是笛卡尔积

笛卡尔乘积是指在数学中,两个集合 X 和 Y 的笛卡尔积(Cartesian product),又称直积,表示为 X×Y,第一个对象是 X 的成员而第二个对象是 Y 的所有可能有序对的其中一个成员。
假设集合 A={a, b},集合 B={0, 1, 2},则两个集合的笛卡尔积为 {(a, 0), (a, 1), (a, 2), (b, 0), (b, 1), (b, 2)}。

商品 SKU 计算

public function test()
{
    $arr = array(array(1,3,4,5),array(3,5,7,9),array(76,6,1,0));

    $cartesian_product = $this->cartesian($arr, []);
    print_r($cartesian_product);
}

/**
 ** 实现二维数组的笛卡尔积组合
 ** $arr 要进行笛卡尔积的二维数组
 ** $str 最终实现的笛卡尔积组合,可不写
 ** @return array
 **/
protected function cartesian($arr,$str = [])
   {
    //去除第一个元素
    $first = array_shift($arr);
    //判断是否是第一次进行拼接
    if(count($str) > 1) {
        foreach ($str as $k => $val) {
            foreach ($first as $key => $value) {
                //最终实现的格式 1,3,76
                //可根据具体需求进行变更
                $str2[] = $val.','.$value;
            }
        }
    }else{
        foreach ($first as $key => $value) {
            //最终实现的格式 1,3,76
            //可根据具体需求进行变更
            $str2[] = $value;
        }
    }
    //递归进行拼接
    if(count($arr) > 0){
        $str2 =$this->cartesian($arr,$str2);
    }
    //返回最终笛卡尔积
    return $str2;
}

运行结果

Array
(
    [0] => 1,3,76
    [1] => 1,3,6
    [2] => 1,3,1
    [3] => 1,3,0
    [4] => 1,5,76
    [5] => 1,5,6
    [6] => 1,5,1
    [7] => 1,5,0
    [8] => 1,7,76
    [9] => 1,7,6
    [10] => 1,7,1
    [11] => 1,7,0
    [12] => 1,9,76
    [13] => 1,9,6
    [14] => 1,9,1
    [15] => 1,9,0
    [16] => 3,3,76
    [17] => 3,3,6
    [18] => 3,3,1
    [19] => 3,3,0
    [20] => 3,5,76
    [21] => 3,5,6
    [22] => 3,5,1
    [23] => 3,5,0
    [24] => 3,7,76
    [25] => 3,7,6
    [26] => 3,7,1
    [27] => 3,7,0
    [28] => 3,9,76
    [29] => 3,9,6
    [30] => 3,9,1
    [31] => 3,9,0
    [32] => 4,3,76
    [33] => 4,3,6
    [34] => 4,3,1
    [35] => 4,3,0
    [36] => 4,5,76
    [37] => 4,5,6
    [38] => 4,5,1
    [39] => 4,5,0
    [40] => 4,7,76
    [41] => 4,7,6
    [42] => 4,7,1
    [43] => 4,7,0
    [44] => 4,9,76
    [45] => 4,9,6
    [46] => 4,9,1
    [47] => 4,9,0
    [48] => 5,3,76
    [49] => 5,3,6
    [50] => 5,3,1
    [51] => 5,3,0
    [52] => 5,5,76
    [53] => 5,5,6
    [54] => 5,5,1
    [55] => 5,5,0
    [56] => 5,7,76
    [57] => 5,7,6
    [58] => 5,7,1
    [59] => 5,7,0
    [60] => 5,9,76
    [61] => 5,9,6
    [62] => 5,9,1
    [63] => 5,9,0
)


直接上代码

<?php
namespace app\controller;

use support\Request;
use support\Response;
use Yansongda\Pay\Pay;

class Payment
{
    protected $config = [
        'alipay' => [
            'default' => [
                // 必填-支付宝分配的 app_id
                'app_id' => 'wx4926de289f70b113',
                // 必填-应用私钥 字符串或路径
                'app_secret_cert' => 'MIIEvLoLc1s/VdBHku+JEd0YmEY+p4sjmcRnlu4AlzLxkWUTTg==',
                // 必填-应用公钥证书 路径
                'app_public_cert_path' => '/Users/yansongda/pay/cert/appCertPublicKey_2016082000295641.crt',
                // 必填-支付宝公钥证书 路径
                'alipay_public_cert_path' => '/Users/yansongda/pay/cert/alipayCertPublicKey_RSA2.crt',
                // 必填-支付宝根证书 路径
                'alipay_root_cert_path' => '/Users/yansongda/pay/cert/alipayRootCert.crt',
                'return_url' => 'https://yansongda.cn/alipay/return',
                'notify_url' => 'https://yansongda.cn/alipay/notify',
                // 选填-第三方应用授权token
                'app_auth_token' => '',
                // 选填-服务商模式下的服务商 id,当 mode 为 Pay::MODE_SERVICE 时使用该参数
                'service_provider_id' => '',
                // 选填-默认为正常模式。可选为: MODE_NORMAL, MODE_SANDBOX, MODE_SERVICE
                'mode' => Pay::MODE_NORMAL,
            ]
        ],
        'wechat' => [
            'default' => [
                // 必填-商户号,服务商模式下为服务商商户号
                'mch_id' => '123xxxx02',
                // 必填-商户秘钥
                'mch_secret_key' => 'xxxxx',  //api安全中心里的V3密码32位的那个
                // 必填-商户私钥 字符串或路径
                'mch_secret_cert' => '/xxxxx/apiclient_key.pem',  //api安全中心里下载的的密钥,绝对路径
                // 必填-商户公钥证书路径
                'mch_public_cert_path' => '/xxxx/apiclient_cert.pem', //api安全中心里下载的公钥,绝对路径
                // 必填
                'notify_url' => 'https://www.xxx.com/member/wx_native_notify', //支付回调地址必须https
                // 选填-公众号 的 app_id
                'mp_app_id' => 'wx4926de289f70b113',
                // 选填-小程序 的 app_id
                'mini_app_id' => '',
                // 选填-app 的 app_id
                'app_id' => '',
                // 选填-合单 app_id
                'combine_app_id' => '',
                // 选填-合单商户号
                'combine_mch_id' => '',
                // 选填-服务商模式下,子公众号 的 app_id
                'sub_mp_app_id' => '',
                // 选填-服务商模式下,子 app 的 app_id
                'sub_app_id' => '',
                // 选填-服务商模式下,子小程序 的 app_id
                'sub_mini_app_id' => '',
                // 选填-服务商模式下,子商户id
                'sub_mch_id' => '',
                // 选填-微信公钥证书路径, optional,强烈建议 php-fpm 模式下配置此参数
                'wechat_public_cert_path' => [
                    '4248DC46520F9EAC26C7FET4464ADBE5ADDA3A' => '/xxxx/wechatpay_public.pem', //通过算法生成的,具体生成方式往下面看。
                ],
                // 选填-默认为正常模式。可选为: MODE_NORMAL, MODE_SERVICE
                'mode' => Pay::MODE_NORMAL,
            ]
        ],
        'logger' => [
            'enable' => false,
            'file' => './logs/alipay.log',
            'level' => 'info', // 建议生产环境等级调整为 info,开发环境为 debug
            'type' => 'single', // optional, 可选 daily.
            'max_file' => 30, // optional, 当 type 为 daily 时有效,默认 30 天
        ],
        'http' => [ // optional
            'timeout' => 5.0,
            'connect_timeout' => 5.0,
            // 更多配置项请参考 [Guzzle](https://guzzle-cn.readthedocs.io/zh_CN/latest/request-options.html)
        ],
    ];

    //二维码生成展示页
    public function index(Request $request)
    {
        Pay::config($this->config);

        $order = [
            'out_trade_no' => time().'',
            'description' => 'subject-测试',
            'amount' => [
                'total' => 1,
            ],
        ];

        $result = Pay::wechat()->scan($order);
        // 二维码内容: $qr = $result->code_url;
        //var_export($result->code_url);

        return view('payment/index', ['code_url' => $result->code_url]);
    }

    //支付成功回调
    public function verify(Request $request)
    {
        Pay::config($this->config);

        // 是的,你没有看错,就是这么简单!
        $result = Pay::wechat()->callback($request->post());
        file_put_contents(__DIR__ . '/notify_result_ysd.txt',
            date('Y-m-d H:i:s') . ':' . var_export($result, true));
        

        //这里很关键,需要注意。
        return new Response(200, [], json_encode(['code' => 'SUCCESS', 'message' => '成功']));
    }
}

微信支付平台证书下载:

http://www.liziyu.com/archives/309/

话不多说直接上代码:

// app\member\controller\pay.php

<?php

namespace app\controller;

use EasyWeChat\Kernel\Exceptions\Exception;
use EasyWeChat\Kernel\Exceptions\InvalidArgumentException;
use support\Request;
use EasyWeChat\Pay\Application;
use Symfony\Component\HttpFoundation\HeaderBag;
use Symfony\Component\HttpFoundation\Request as SymfonyRequest;

class Index
{
    private $config = [
        'mch_id' => 'xxxx', //根据自已实际的填写
        // 商户证书
        'private_key' => '/xxx/apiclient_key.pem',//根据自已实际的填写,绝对路径
        'certificate' => '/xxx/apiclient_cert.pem', //根据自已实际的填写,绝对路径
        // v3 API 秘钥
        'secret_key' => 'xxxx', //根据自已实际的填写
        // v2 API 秘钥
        'v2_secret_key' => 'xxx', //根据自已实际的填写
        'platform_certs' => [
            '/xxx/wechatpay_public.pem', //根据自已实际的填写,获取办法见下面。
        ],
        'http' => [
            'throw' => true, // 状态码非 200、300 时是否抛出异常,默认为开启
            'timeout' => 5.0,
            // 'base_uri' => 'https://api.mch.weixin.qq.com/', // 如果你在国外想要覆盖默认的 url 的时候才使用,根据不同的模块配置不同的 uri
        ],
    ];

    //二维码生成展示页
    public function index(Request $request)
    {
        try {
            $app = new Application($this->config);
            $response = $app->getClient()->post('/v3/pay/transactions/native', [
                'json' => [
                    'mchid' => (string)$app->getMerchant()->getMerchantId(),
                    'out_trade_no' => 'SN_'.time(),
                    'appid' => 'xxxx', //根据自已实际的填写
                    'description' => '测试内容',
                    'notify_url' => 'https://www.xxxx.com/member/wx_native_notify', //注意是ssl协议
                    'amount' => [
                        'total' => 2,
                        'currency' => 'CNY',
                    ]
                ]
            ]);
        } catch (InvalidArgumentException $e) {
            //
        }
        return view('index/index', ['code_url' => $response->toArray()]);
    }


    //回调
    public function verify(Request $request)
    {
        try {
           //下面四行很关键
            $symfony_request = new SymfonyRequest($request->get(), $request->post(), [], $request->cookie(), [], [], $request->rawBody());
            $symfony_request->headers = new HeaderBag($request->header());
            $app = new Application($this->config);
            $app->setRequestFromSymfonyRequest($symfony_request);

            // $app 为你实例化的支付对象,此处省略实例化步骤
            $server = $app->getServer();
            
            // 处理支付结果事件
            $server->handlePaid(function ($message) {
                // $message 为微信推送的通知结果,详看微信官方文档
                file_put_contents(__DIR__ . '/notify_result.txt',
                    date('Y-m-d H:i:s') . ':' . var_export($message, true));
                
                // 微信支付订单号 $message['transaction_id']
                // 商户订单号 $message['out_trade_no']
                // 商户号 $message['mchid']
                // 具体看微信官方文档...
                // 进行业务处理,如存数据库等...

            });
            //这一步特别要注意,必须这么写。
            return $server->serve()->getBody()->getContents();

        } catch (Exception $e) {
            echo $e->getMessage();
        }
    }

}

“平台证书”申请办法:http://www.liziyu.com/archives/309/