2022年3月

不多说,上完整代码!

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    //这里是应有的css文件引用
    <?php require "app/admin/view/layout/header.html" ?>
</head>
<body>
<div class="layui-card-body text-center" style="box-sizing: border-box;">
    <div id="qrcode" class="layui-inline"></div>
    <h2 style="color: red;padding-top:20px">请使用微信扫码支付</h2>
</div>
 //这里是应有的js文件引用
<?php require "app/admin/view/layout/footer.html" ?>

<script>

    layui.use(['form', 'QRCode'], function () {
        var $ = layui.jquery;
        var form = layui.form;
        var QRCode = layui.QRCode;

        new QRCode(document.getElementById("qrcode"), {
            text: '二维码的短地址',
            width: 250,
            height: 250,
            colorDark: '#000000',
            colorLight: '#ffffff',
            correctLevel: QRCode.CorrectLevel.H,
        });


        //1.支付轮询
        $(document).ready(function () {
            setInterval(function () {
                //1.先得到当前iframe层的索引 关闭窗口
                var index = parent.layer.getFrameIndex(window.name);
                $.post("后台url",
                    {out_trade_no: "订单号"},
                    function (res) {
                    if (res.code === 200) {
                        layer.msg(res.msg, {icon: 1, time: 2500, shade: 0.4}, function () {
                            parent.layer.close(index); //2.再执行关闭自身
                            parent.location.reload();
                        });
                    }
                }, 'json');
                return false;
            }, 3000);
        });
    });
</script>
</body>
</html>


说实话,到放弃为止,我还是没有找到这个商户公钥到底在哪里得到。

我下面收集了一个热心网友给我的回复,但我也没有测试,贴出来给大家参考:

# 必填-商户号,服务商模式下为服务商商户号
mch_id='1111111111',
# 必填-商户秘钥 V3 版本生成的 32 位秘钥
mch_secret_key=""
# 商户私钥 字符串或路径 (商户私钥,就是V2的私钥,路径也可以)
mch_secret_cert="apiclient_cert.key"
# 必填-商户公钥证书路径 (商户公钥,就是V2的私钥,路径也可以)
mch_public_cert_path="apiclient_key.pem"
// 就是之前的 那两个 对应一下就行啦
// 没有什么太复杂的  很简单
// 这个证书 要去  https://pay.weixin.qq.com/wiki/doc/apiv3/wechatpay/wechatpay6_0.shtml 下载证书文件生成
// 生成的就是 apiclient_cert + apiclient_key文件


========================== 更新(暂未测试) ==========================

1、官方文档:https://pay.weixin.qq.com/wiki/doc/api/tools/mch_pay.php?chapter=24_7

2、命令行工具:https://github.com/EasyWechat/console

Get payment RSA public key.

$ ./vendor/bin/easywechat payment:rsa_public_key \
    --mch_id=14339221228 \
    --api_key=36YTbDmLgyQ52noqdxgwGiYy \
    --cert_path=/Users/overtrue/www/demo/apiclient_cert.pem \
    --key_path=/Users/overtrue/www/demo/apiclient_key.pem 
    
# Public key of mch_id:14339221228 saved as ./public-14339221228.pem


1、起因如下图

QQ20220328-0.jpg

2、walk老大的贴码

<?php
require_once __DIR__ . '/vendor/autoload.php';

use Workerman\Worker;
use Workerman\Connection\AsyncTcpConnection;

$worker = new Worker('tcp://0.0.0.0:80');
$worker->onConnect = function ($con) {
    $rcon = new AsyncTcpConnection('tcp://内网ip:80');
    $rcon->pipe($con);
    $con->pipe($rcon);
    $rcon->connect();
};

$worker = new Worker('tcp://0.0.0.0:443');
$worker->count = 8;
$worker->onConnect = function ($con) {
    $rcon = new AsyncTcpConnection('tcp://内网ip:443');
    $rcon->pipe($con);
    $con->pipe($rcon);
    $rcon->connect();
};

Worker::runAll();


一、要求

比方说一个试卷,总共 60 题,每道题都由难度、章节、类型 3 个属性
按照难度 简单 20 题 一般 30 题 困难 10 题
按照章节 章节一 10 题 章节二 15 题 章节 3 20 题,章节四 15 题
按照类型 文字题 20 题 图片题 20 题 视频题 20 题
每种维度题目数量是可以自行设置的,保证总题量等于 60 就行
不是每个最细分类(我这里称 sku 把)都有题目或者说有足量的题目,这种情况要考虑到
然后随机从数据库中取出这些题,有没有比较好的算法?

二、实现办法

1、方法一

    $tmp = [];
    for ($i=1;$i<=60;$i++){
        if($i <= 20) $item = ['简单'];
        if($i <= 50 && $i>20) $item = ['一般'];
        if($i <= 60 && $i>50) $item = ['困难'];
        $tmp[] = $item;
    }
    shuffle($tmp);
    foreach ($tmp as $key => &$value){
        if($key < 10) array_push($value,'章节一');
        if($key < 25 && $key>=10) array_push($value,'章节二');
        if($key < 45 && $key>=25) array_push($value,'章节三');
        if($key < 60 && $key>=45) array_push($value,'章节四');
    }
    shuffle($tmp);
    foreach ($tmp as $key => &$value){
        if($key < 20) array_push($value,'文字题');
        if($key < 40 && $key>=20) array_push($value,'图片题');
        if($key < 60 && $key>=40) array_push($value,'视频题');
    }
    $qa = [];
    foreach ($tmp as $v){
        $index = implode('-',$v);
        $qa[$index] = isset($qa[$index]) ? $qa[$index] + 1 : 1;
    }
    dd($qa);

效果
aaa.png

2、方式二


$origin = [
    'level' => [
        ['text' => '简单', 'total' => 20],
        ['text' => '一般', 'total' => 30],
        ['text' => '困难', 'total' => 10]
    ]
];
$data = [];
for ($index = 0; $index < 60; $index++) {
    $item = [];
    foreach ($origin as $type => $values) {
        $total = array_sum(array_column($values, 'total'));
        $random = rand(1, $total);
        foreach ($values as $key => $value) {
            if ($random <= $value['total']) {
                $item[$type] = $value['text'];
                $origin[$type][$key]['total']--;
                break;
            } else {
                $random -= $value['total'];
            }
        }
    }
    $data[] = $item;
}




1.composer安装阿里云OSS SDK

composer require aliyuncs/oss-sdk-php

2.控制器里面引用

use OSS\Core\OssException;

use OSS\OssClient;

use OSS\Core\OssUtil; 

2.上传代码逻辑

//        接收文件数据
    $file = request()->file('img');

// 取出文件名截取后缀

    $name = $file->getOriginalName();
    $suffix = strchr($name,'.');

// 阿里云配置

    $accessKeyId = "LTAI5t88SfZ5yhH4Sgu1u3gt";
    $accessKeySecret = "vbLBZWvzazGZvJpPap20ZyKDoBbdq2";
    // Endpoint以杭州为例,其它Region请按实际情况填写。
    $endpoint = "oss-cn-shanghai.aliyuncs.com";
    // 设置存储空间名称。
    $bucket= "*";
    // 设置文件名称。
    //这里是由sha1加密生成文件名 之后连接上文件后缀
    $object = sha1(date('YmdHis', time()) . uniqid()) . $suffix;
    $url = 'http://test.caotengfei.xyz/'.$object;
    // <yourLocalFile>由本地文件路径加文件名包括后缀组成,例如/users/local/myfile.txt。
    $filePath = $file->getPathname();
    $options = array(
        OssClient::OSS_CHECK_MD5 => true,
        OssClient::OSS_PART_SIZE => 1,
    );

    try{
        $ossClient = new OssClient($accessKeyId, $accessKeySecret, $endpoint);
        //返回uploadId。uploadId是分片上传事件的唯一标识,您可以根据uploadId发起相关的操作,如取消分片上传、查询分片上传等。
        $uploadId = $ossClient->initiateMultipartUpload($bucket, $object);
    } catch(OssException $e) {
        printf(__FUNCTION__ . ": initiateMultipartUpload FAILED\n");
        printf($e->getMessage() . "\n");
        return ;
    }
    print(__FUNCTION__ . ": initiateMultipartUpload OK" . "\n");

    $partSize = 10 * 1024 * 1024;
    $uploadFileSize = filesize($filePath);
    $pieces = $ossClient->generateMultiuploadParts($uploadFileSize, $partSize);
    $responseUploadPart = array();
    $uploadPosition = 0;
    $isCheckMd5 = true;
    foreach ($pieces as $i => $piece) {
        $fromPos = $uploadPosition + (integer)$piece[$ossClient::OSS_SEEK_TO];
        $toPos = (integer)$piece[$ossClient::OSS_LENGTH] + $fromPos - 1;
        $upOptions = array(
            // 上传文件。
            $ossClient::OSS_FILE_UPLOAD => $filePath,
            // 设置分片号。
            $ossClient::OSS_PART_NUM => ($i + 1),
            // 指定分片上传起始位置。
            $ossClient::OSS_SEEK_TO => $fromPos,
            // 指定文件长度。
            $ossClient::OSS_LENGTH => $toPos - $fromPos + 1,
            // 是否开启MD5校验,true为开启。
            $ossClient::OSS_CHECK_MD5 => $isCheckMd5,
        );
        // 开启MD5校验。
        if ($isCheckMd5) {
            $contentMd5 = OssUtil::getMd5SumForFile($filePath, $fromPos, $toPos);
            $upOptions[$ossClient::OSS_CONTENT_MD5] = $contentMd5;
        }
        try {
            // 上传分片。
            $responseUploadPart[] = $ossClient->uploadPart($bucket, $object, $uploadId, $upOptions);
        } catch(OssException $e) {
            printf(__FUNCTION__ . ": initiateMultipartUpload, uploadPart - part#{$i} FAILED\n");
            printf($e->getMessage() . "\n");
            return;
        }
        printf(__FUNCTION__ . ": initiateMultipartUpload, uploadPart - part#{$i} OK\n");
    }
// $uploadParts是由每个分片的ETag和分片号(PartNumber)组成的数组。
        $uploadParts = array();
        foreach ($responseUploadPart as $i => $eTag) {
            $uploadParts[] = array(
                'PartNumber' => ($i + 1),
                'ETag' => $eTag,
            );
        }
    try {
        // 执行completeMultipartUpload操作时,需要提供所有有效的$uploadParts。OSS收到提交的$uploadParts后,会逐一验证每个分片的有效性。当所有的数据分片验证通过后,OSS将把这些分片组合成一个完整的文件。
        $ossClient->completeMultipartUpload($bucket, $object, $uploadId, $uploadParts);
    }  catch(OssException $e) {
        printf(__FUNCTION__ . ": completeMultipartUpload FAILED\n");
        printf($e->getMessage() . "\n");
        return;
    }
        return json(['code'=>200,'msg'=>'成功','url'=>$url]);





真正的好朋友,互损不会翻脸,疏远不会猜疑,出钱不会计较,地位不分高低,成功无需巴结,失败不会离去。奋斗的时候搭把手,迷茫的时候拉一把,开心的时候干一杯,难过的时候抱一下。一起走吧,趁将来未来,趁热情未冷。——致我们真挚的友情

共同之处是:

1、都是遍历数据每个元素;
2、回调的参数都相同都支持元素主键
3、其中回调函数中的this指向的是window对象;

不同的地方是:

map()会分配内存生成并返回新数组。
forEach()可以更改原数组元素值。

使用场景:

froEach()而只是想用数据做一些事情时,并调用回显之用。
map()适用于生成并生成新数组,原数组不变,它的性能要比forEach()要高。

简单粗暴更直接:

   /**
     * 自定义token
     * @param null $userId
     * @param null $roles
     * @param int $timeout
     * @return string
     */
    protected function setToken($userId = null, $roles = null, $timeout = 0) :string
    {
        $year = 1984;
        $time = time();
        return $roles.'.'.md5($time).'.'.$year + $userId.'.'.$time.'.'. $timeout;
    }