PHP使用PhpSpreadsheet读取Excel表格

使用composer安装phpspreadsheet库

composer require phpoffice/phpspreadsheet

使用迭代器读取激活的工作表并输出全部单元格内容

<?php
require 'vendor/autoload.php'; // 引入自动加载器
use PhpOffice\PhpSpreadsheet\IOFactory;
 
$spreadsheet = IOFactory::load('path_to_your_file.xlsx'); // 指定 xlsx 文件路径
$worksheet = $spreadsheet->getActiveSheet(); // 获取当前活动工作表
 
// 遍历每一行数据
foreach ($worksheet->getRowIterator() as $row) {
    foreach ($row->getCellIterator() as $cell) {
        echo $cell->getValue(), "\t"; // 输出单元格值(制表符分隔)
    }
    echo "<br>"; // 换行
}
?>

PHP使用PhpSpreadsheet读取Excel表格

PHP 调用file_get_contents或curl等方法获取接口数据返回SSL错误的问题解决方法

找到PHP配置文件,可用以下BASH命令搜索具体位置

find / -name "php.ini"

编辑php.ini文件

vim /usr/local/php/etc/php.ini

修改配置文件

找到;openssl.cafile=

去掉注释(即去掉前面的分号)

在等号后面添加受信任的根证书路径(根证书文件见本文附件)

最终效果如下(根据实际情况自行修改):
#####
openssl.cafile=/usr/local/php5.6/etc/cacert.pem
#####

保存后重启相关服务

根证书下载


PHP 调用file_get_contents或curl等方法获取接口数据返回SSL错误的问题解决方法

PHP 微信支付退款-单文件

<?php
/**
 * 关于微信退款的说明
 * 1.微信退款要求必传证书,需要到https://pay.weixin.qq.com 账户中心->账户设置->API安全->下载证书,证书路径在第119行和122行修改
 * 2.错误码参照 :https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_4
 */
header('Content-type:text/html; Charset=utf-8');
$mchid = '';          //微信支付商户号 PartnerID 通过微信支付商户资料审核后邮件发送
$appid = '';  //微信支付申请对应的公众号的APPID
$apiKey = '';   //https://pay.weixin.qq.com 帐户设置-安全设置-API安全-API密钥-设置API密钥
$orderNo = '';                      //商户订单号(商户订单号与微信订单号二选一,至少填一个)
$wxOrderNo = '';                     //微信订单号(商户订单号与微信订单号二选一,至少填一个)
$totalFee = 0.20;                   //订单金额,单位:元
$refundFee = 0.20;                  //退款金额,单位:元
$refundNo = 'refund_'.uniqid();        //退款订单号(可随机生成)
$wxPay = new WxpayService($mchid,$appid,$apiKey);
$result = $wxPay->doRefund($totalFee, $refundFee, $refundNo, $wxOrderNo,$orderNo);
if($result===true){
    echo 'refund success';exit();
}
echo 'refund fail';

class WxpayService
{
    protected $mchid;
    protected $appid;
    protected $apiKey;
    public $data = null;

    public function __construct($mchid, $appid, $key)
    {
        $this->mchid = $mchid; //https://pay.weixin.qq.com 产品中心-开发配置-商户号
        $this->appid = $appid; //微信支付申请对应的公众号的APPID
        $this->apiKey = $key;   //https://pay.weixin.qq.com 帐户设置-安全设置-API安全-API密钥-设置API密钥
    }

    /**
     * 退款
     * @param float $totalFee 订单金额 单位元
     * @param float $refundFee 退款金额 单位元
     * @param string $refundNo 退款单号
     * @param string $wxOrderNo 微信订单号
     * @param string $orderNo 商户订单号
     * @return string
     */
    public function doRefund($totalFee, $refundFee, $refundNo, $wxOrderNo='',$orderNo='')
    {
        $config = array(
            'mch_id' => $this->mchid,
            'appid' => $this->appid,
            'key' => $this->apiKey,
        );
        $unified = array(
            'appid' => $config['appid'],
            'mch_id' => $config['mch_id'],
            'nonce_str' => self::createNonceStr(),
            'total_fee' => floatval($totalFee) * 100,       //订单金额	 单位 转为分
            'refund_fee' => floatval($refundFee) * 100,       //退款金额 单位 转为分
            'sign_type' => 'MD5',           //签名类型 支持HMAC-SHA256和MD5,默认为MD5
            'transaction_id'=>$wxOrderNo,               //微信订单号
            'out_trade_no'=>$orderNo,        //商户订单号
            'out_refund_no'=>$refundNo,        //商户退款单号
            'refund_desc'=>'商品已售完',     //退款原因(选填)
        );
        $unified['sign'] = self::getSign($unified, $config['key']);
        $responseXml = $this->curlPost('https://api.mch.weixin.qq.com/secapi/pay/refund', self::arrayToXml($unified));
        $unifiedOrder = simplexml_load_string($responseXml, 'SimpleXMLElement', LIBXML_NOCDATA);
        if ($unifiedOrder === false) {
            die('parse xml error');
        }
        print_r($unifiedOrder);
        if ($unifiedOrder->return_code != 'SUCCESS') {
            die($unifiedOrder->return_msg);
        }
        if ($unifiedOrder->result_code != 'SUCCESS') {
            die($unifiedOrder->err_code);
        }
        return true;
    }

    public static function curlGet($url = '', $options = array())
    {
        $ch = curl_init($url);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
        curl_setopt($ch, CURLOPT_TIMEOUT, 30);
        if (!empty($options)) {
            curl_setopt_array($ch, $options);
        }
        //https请求 不验证证书和host
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
        curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
        $data = curl_exec($ch);
        curl_close($ch);
        return $data;
    }

    public function curlPost($url = '', $postData = '', $options = array())
    {
        if (is_array($postData)) {
            $postData = http_build_query($postData);
        }
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
        curl_setopt($ch, CURLOPT_POST, 1);
        curl_setopt($ch, CURLOPT_POSTFIELDS, $postData);
        curl_setopt($ch, CURLOPT_TIMEOUT, 30); //设置cURL允许执行的最长秒数
        if (!empty($options)) {
            curl_setopt_array($ch, $options);
        }
        //https请求 不验证证书和host
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
        curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);

        //第一种方法,cert 与 key 分别属于两个.pem文件
        //默认格式为PEM,可以注释
        curl_setopt($ch,CURLOPT_SSLCERTTYPE,'PEM');
        curl_setopt($ch,CURLOPT_SSLCERT,getcwd().'/apiclient_cert.pem');
        //默认格式为PEM,可以注释
        curl_setopt($ch,CURLOPT_SSLKEYTYPE,'PEM');
        curl_setopt($ch,CURLOPT_SSLKEY,getcwd().'/apiclient_key.pem');
        //第二种方式,两个文件合成一个.pem文件
//        curl_setopt($ch,CURLOPT_SSLCERT,getcwd().'/all.pem');
        $data = curl_exec($ch);
        curl_close($ch);
        return $data;
    }

    public static function createNonceStr($length = 16)
    {
        $chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
        $str = '';
        for ($i = 0; $i < $length; $i++) {
            $str .= substr($chars, mt_rand(0, strlen($chars) - 1), 1);
        }
        return $str;
    }
    public static function arrayToXml($arr)
    {
        $xml = "<xml>";
        foreach ($arr as $key => $val) {
            if (is_numeric($val)) {
                $xml .= "<" . $key . ">" . $val . "</" . $key . ">";
            } else
                $xml .= "<" . $key . "><![CDATA[" . $val . "]]></" . $key . ">";
        }
        $xml .= "</xml>";
        return $xml;
    }

    public static function getSign($params, $key)
    {
        ksort($params, SORT_STRING);
        $unSignParaString = self::formatQueryParaMap($params, false);
        $signStr = strtoupper(md5($unSignParaString . "&key=" . $key));
        return $signStr;
    }
    protected static function formatQueryParaMap($paraMap, $urlEncode = false)
    {
        $buff = "";
        ksort($paraMap);
        foreach ($paraMap as $k => $v) {
            if (null != $v && "null" != $v) {
                if ($urlEncode) {
                    $v = urlencode($v);
                }
                $buff .= $k . "=" . $v . "&";
            }
        }
        $reqPar = '';
        if (strlen($buff) > 0) {
            $reqPar = substr($buff, 0, strlen($buff) - 1);
        }
        return $reqPar;
    }
}
?>

PHP 微信支付退款-单文件

PHP 日志类

<?php


class Libs_Log_Logger {

    const TRANSFER_ERROR    = 'LOG转换失败,非LOG信息';
    const LOG_FILENAME      = 'output.log';

    /**
     * 本函数用于取代系统的error_log错误日志记录函数
     * @param string|array|object|bool|int $log 需要记录的错误信息,可以是格式良好的任意类型
     * @param string $filename 保存日志信息的文件名,默认存储路径为sites/app/storage/log/output.log
     * @param bool $append 是否以追加的形式添加日志信息,默认追加
     */
    public static function outputLog($log, $filename = self::LOG_FILENAME, $append = true) {
        if (!plum_setmod_dir(PLUM_APP_LOG)) {
            return;
        }
        $filename = PLUM_APP_LOG . '/' . $filename;
        $mode = $append ? 'a' : 'w';
        if (!($handler = @fopen($filename, $mode))) {
            //文件流打开失败时触发错误,并退出
            trigger_error('LOG日志文件打开失败', E_USER_WARNING);
            return;
        }
        //获取调用跟踪
        $trace  = debug_backtrace(DEBUG_BACKTRACE_PROVIDE_OBJECT, 1);
        $debug  = self::log_format(array('file' => $trace[0]['file'], 'line' => $trace[0]['line']));

        $info = self::log_format($log);
        //开始写入
        if (($write_byte = fwrite($handler, $debug.$info)) === false) {
            $error_msg = 'LOG日志写入失败';
            //检查磁盘空间
            $free_space = disk_free_space(PLUM_APP_LOG);
            //磁盘空间不足
            if ($free_space && $write_byte > $free_space) {
                $error_msg .= '磁盘空间不足';
            }
            //写入失败时,触发错误并退出
            trigger_error($error_msg, E_USER_WARNING);
            fclose($handler);
            return;
        }
        //关闭文件流
        fclose($handler);
    }

    /**
     * 输出信息到控制台
     */
    public static function outputConsoleLog($log) {
        //非控制台调用直接退出
        if (php_sapi_name() != 'cli') {
            //die('请在控制台下执行脚本');
            return;
        }
        $info = self::log_format($log);
        fwrite(STDOUT, $info);
    }

    /**
     * 返回格式化的LOG日志信息
     * @param $log
     * @return string
     */
    private static function log_format($log) {
        $log_type = 'Unknown';
        if (is_array($log)) {
            //数组进行json序列化
            $log_type   = 'Array';
            $loginfo    = self::json_encode_helper($log);
        } else if (is_object($log)) {
            $log_type   = 'Object';
            $loginfo    = self::json_encode_helper($log);
        } else if (is_string($log)) {
            $log_type   = 'String';
            $loginfo    = $log;
        } else if (is_bool($log)) {
            $log_type   = 'Bool';
            $loginfo    = $log ? 'true' : 'false';
        } else if (is_numeric($log)) {
            $log_type   = 'Number';
            $loginfo    = strval($log);
        } else if (is_null($log)) {
            $log_type   = 'Null';
            $loginfo    = 'null';
        } else {
            $loginfo = strval($log);
        }
        //再一次判断,排查转换出错的情况
        if (!is_string($loginfo)) {
            $errno  = json_last_error();
            switch ($errno) {
                default :
                    $loginfo = self::TRANSFER_ERROR.";错误号:{$errno};错误信息:".json_last_error_msg();
                    break;
            }

        }
        //添加换行符
        $loginfo .= "\n";

        $format = "[".date('Y/m/d H:i:s', time())."] $log_type: $loginfo";

        return $format;
    }
    /*
     * utf8格式转换
     */
    private static function utf8ize( $mixed ) {
        if (is_array($mixed)) {
            foreach ($mixed as $key => $value) {
                $mixed[$key] = self::utf8ize($value);
            }
        } elseif (is_string($mixed)) {
            //$mixed = mb_convert_encoding($mixed, "UTF-8", "UTF-8");
            $mixed  = utf8_encode($mixed);
        } elseif (is_object($mixed)) {
            foreach ($mixed as $key => $value) {
                $mixed->$key = self::utf8ize($value);
            }
        }
        return $mixed;
    }

    private static function json_encode_helper($var) {
        switch (gettype($var)) {
            case 'boolean':
                return $var ? 'true' : 'false'; // Lowercase necessary!

            case 'integer':
            case 'double':
                return $var;

            case 'resource':
            case 'string':
                // Always use Unicode escape sequences (\u0022) over JSON escape
                // sequences (\") to prevent browsers interpreting these as
                // special characters.
                $replace_pairs = array(
                    // ", \ and U+0000 - U+001F must be escaped according to RFC 4627.
                    '\\' => '\u005C',
                    '"' => '\u0022',
                    "\x00" => '\u0000',
                    "\x01" => '\u0001',
                    "\x02" => '\u0002',
                    "\x03" => '\u0003',
                    "\x04" => '\u0004',
                    "\x05" => '\u0005',
                    "\x06" => '\u0006',
                    "\x07" => '\u0007',
                    "\x08" => '\u0008',
                    "\x09" => '\u0009',
                    "\x0a" => '\u000A',
                    "\x0b" => '\u000B',
                    "\x0c" => '\u000C',
                    "\x0d" => '\u000D',
                    "\x0e" => '\u000E',
                    "\x0f" => '\u000F',
                    "\x10" => '\u0010',
                    "\x11" => '\u0011',
                    "\x12" => '\u0012',
                    "\x13" => '\u0013',
                    "\x14" => '\u0014',
                    "\x15" => '\u0015',
                    "\x16" => '\u0016',
                    "\x17" => '\u0017',
                    "\x18" => '\u0018',
                    "\x19" => '\u0019',
                    "\x1a" => '\u001A',
                    "\x1b" => '\u001B',
                    "\x1c" => '\u001C',
                    "\x1d" => '\u001D',
                    "\x1e" => '\u001E',
                    "\x1f" => '\u001F',
                    // Prevent browsers from interpreting these as as special.
                    "'" => '\u0027',
                    '<' => '\u003C',
                    '>' => '\u003E',
                    '&' => '\u0026',
                    // Prevent browsers from interpreting the solidus as special and
                    // non-compliant JSON parsers from interpreting // as a comment.
                    //'/' => '\u002F',
                    // While these are allowed unescaped according to ECMA-262, section
                    // 15.12.2, they cause problems in some JSON parsers.
                    "\xe2\x80\xa8" => '\u2028', // U+2028, Line Separator.
                    "\xe2\x80\xa9" => '\u2029', // U+2029, Paragraph Separator.
                );

                return '"' . strtr($var, $replace_pairs) . '"';

            case 'array':
                // Arrays in JSON can't be associative. If the array is empty or if it
                // has sequential whole number keys starting with 0, it's not associative
                // so we can go ahead and convert it as an array.
                if (empty($var) || array_keys($var) === range(0, sizeof($var) - 1)) {
                    $output = array();
                    foreach ($var as $v) {
                        $output[] = self::json_encode_helper($v);
                    }
                    return '[ ' . implode(', ', $output) . ' ]';
                }
            // Otherwise, fall through to convert the array as an object.

            case 'object':
                $output = array();
                foreach ($var as $k => $v) {
                    $output[] = self::json_encode_helper(strval($k)) . ':' . self::json_encode_helper($v);
                }
                return '{' . implode(', ', $output) . '}';

            default:
                return 'null';
        }
    }
}

PHP 日志类

PHP 微信支付-商家转账到零钱-单文件版

<?php

class App_Helper_WxTransfer
{

    const AUTH_TAG_LENGTH_BYTE = 16;

    /**
     * @notes 商家转账到零钱
     * @param $batch_no //提现订单号
     * @param $left_money //提现金额 单位 元
     * @param $user_openid //用户openID
     * @param $withdraw_name //提现金额大于200,用户真实名字必填
     * @return bool
     * @throws \Exception
     * @author ljj
     * @date 2022/9/27 4:40 下午
     */
    public static function transfer($appid,$mchid,$cert_client,$cert_key,$v3key,$batch_no, $left_money, $user_openid, $withdraw_name = '',$b_name,$b_remark,$t_remark)
    {
        $config = [
            'app_id' => $appid,
            'mch_id' => $mchid, //商户ID
            'cert_client' => getcwd().$cert_client, //cert证书地址//绝对路径
            'cert_key' => getcwd().$cert_key, //key支付证书绝对地址
        ];

        //获取微信支付平台证书序列号(不是API证书序列号)
        $url = 'https://api.mch.weixin.qq.com/v3/certificates';
        $wx_cert = json_decode(self::https_request_without_wechatpay_serial($url, self::token($url, 'GET', array(), $config)),true);
        //设置加密密钥v3 6efd7276408a3334c7fa3e740c3ec964
        $associated_data = $wx_cert['data'][0]['encrypt_certificate']['associated_data'];
        $nonce = $wx_cert['data'][0]['encrypt_certificate']['nonce'];
        $ciphertext = $wx_cert['data'][0]['encrypt_certificate']['ciphertext'];
        $wx_cert_public_key = self::decryptToString($v3key, $associated_data, $nonce, $ciphertext);
        $wx_cert_sn = $wx_cert['data'][0]['serial_no'];
//        Libs_Log_Logger::outputLog($wx_cert,"wx_transfer1");

        //请求URL
        $url = 'https://api.mch.weixin.qq.com/v3/transfer/batches';
        //请求方式
        $http_method = 'POST';
        //请求参数
        $data = [
            'appid' => $config['app_id'], //申请商户号的appid或商户号绑定的appid(企业号corpid即为此appid)
            'out_batch_no' => $batch_no, //商户系统内部的商家批次单号,要求此参数只能由数字、大小写字母组成,在商户系统内部唯一
            'batch_name' => $b_name, //该笔批量转账的名称
            'batch_remark' => $b_remark, //转账说明,UTF8编码,最多允许32个字符
            'total_amount' => $left_money * 100, //转账金额单位为“分”。转账总金额必须与批次内所有明细转账金额之和保持一致,否则无法发起转账操作
            'total_num' => 1, //一个转账批次单最多发起三千笔转账。转账总笔数必须与批次内所有明细之和保持一致,否则无法发起转账操作
            'transfer_detail_list' => [
                [ //发起批量转账的明细列表,最多三千笔
                    'out_detail_no' => $batch_no, //商户系统内部区分转账批次单下不同转账明细单的唯一标识,要求此参数只能由数字、大小写字母组成
                    'transfer_amount' => $left_money * 100, //转账金额单位为分
                    'transfer_remark' => $t_remark, //单条转账备注(微信用户会收到该备注),UTF8编码,最多允许32个字符
                    'openid' => $user_openid, //openid是微信用户在公众号appid下的唯一用户标识(appid不同,则获取到的openid就不同),可用于永久标记一个用户
                ]
            ]
        ];
        $data['transfer_detail_list'][0]['user_name'] = self::getEncrypt($withdraw_name, $wx_cert_public_key);
        $token = self::token($url, $http_method, $data, $config);
        //获取token
        $result = self::https_request($url, json_encode($data), $token, $wx_cert_sn);
        //发送请求
        $result_arr = json_decode($result, true);
        if (!isset($result_arr['create_time'])) {
            //批次受理失败
            Libs_Log_Logger::outputLog($result_arr,"wx_transfer");
        }
        //      成功返回信息  {"batch_id":"1030001036201351072852022101201442513049","create_time":"2022-10-12T22:08:21+08:00","out_batch_no":"20221011004103000000146822"}
        //批次受理成功,更新提现申请单为提现中状态
        //业务修改为提现中
        return json_encode($result_arr);
    }

    /**
     * @notes 签名生成
     * @param $url
     * @param $http_method
     * @param $data
     * @param $config
     * @return string
     * @author ljj
     * @date 2022/9/27 4:14 下午
     */
    public static function token($url, $http_method, $data, $config)
    {
        $timestamp = time();
        //请求时间戳
        $url_parts = parse_url($url);
        //获取请求的绝对URL
        $nonce = $timestamp . rand('10000', '99999');
        //请求随机串
        $body = empty($data) ? '' : json_encode((object)$data);
        //请求报文主体
        $stream_opts = [
            "ssl" => [
                "verify_peer" => false,
                "verify_peer_name" => false,
            ]
        ];
        $apiclient_cert_arr = openssl_x509_parse(file_get_contents($config['cert_client'], false, stream_context_create($stream_opts)));
        $serial_no = $apiclient_cert_arr['serialNumberHex'];
        //Libs_Log_Logger::outputLog($serial_no,"wx_transfer");
        //证书序列号
        $mch_private_key = file_get_contents($config['cert_key'], false, stream_context_create($stream_opts));
        //密钥
        $merchant_id = $config['mch_id'];
        //商户id
        $canonical_url = ($url_parts['path'] . (!empty($url_parts['query']) ? "?${url_parts['query']}" : ""));
        $message = $http_method . "\n" .
            $canonical_url . "\n" .
            $timestamp . "\n" .
            $nonce . "\n" .
            $body . "\n";
        openssl_sign($message, $raw_sign, $mch_private_key, 'sha256WithRSAEncryption');
        $sign = base64_encode($raw_sign);
        //签名
        $schema = 'WECHATPAY2-SHA256-RSA2048';
        $token = sprintf(
            'mchid="%s",nonce_str="%s",timestamp="%d",serial_no="%s",signature="%s"',
            $merchant_id,
            $nonce,
            $timestamp,
            $serial_no,
            $sign
        );
        //微信返回token
        return $schema . ' ' . $token;
    }

    /**
     * @notes 发送请求
     * @param $url
     * @param $data
     * @param $token
     * @return bool|string
     * @author ljj
     * @date 2022/9/27 4:15 下午
     */
    public static function https_request($url, $data, $token, $wechatpay_serial)
    {
        $curl = curl_init();
        curl_setopt($curl, CURLOPT_URL, (string)$url);
        curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, FALSE);
        curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, FALSE);
        if (!empty($data)) {
            curl_setopt($curl, CURLOPT_POST, 1);
            curl_setopt($curl, CURLOPT_POSTFIELDS, $data);
        }
        curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
        //添加请求头
        $headers = [
            'Authorization:' . $token,
            'Accept: application/json',
            'Content-Type: application/json; charset=utf-8',
            'User-Agent:Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Safari/537.36',
            'Wechatpay-Serial:'.$wechatpay_serial,
        ];
        if (!empty($headers)) {
            curl_setopt($curl, CURLOPT_HTTPHEADER, $headers);
        }
        $output = curl_exec($curl);
        curl_close($curl);
        return $output;
    }

    /**
     * @notes 发送请求
     * @param $url
     * @param $data
     * @param $token
     * @return bool|string
     * @author ljj
     * @date 2022/9/27 4:15 下午
     */
    public static function https_request_without_wechatpay_serial($url, $token)
    {
        $curl = curl_init();
        curl_setopt($curl, CURLOPT_URL, (string)$url);
        curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, FALSE);
        curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, FALSE);
        curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
        //添加请求头
        $headers = [
            'Authorization:' . $token,
            'Accept: application/json',
            'Content-Type: application/json; charset=utf-8',
            'User-Agent:Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Safari/537.36',
        ];
        if (!empty($headers)) {
            curl_setopt($curl, CURLOPT_HTTPHEADER, $headers);
        }
        $output = curl_exec($curl);
        curl_close($curl);
        return $output;
    }

    /**
     * @notes 敏感信息加解密
     * @param $str
     * @param $config
     * @return string
     * @throws \Exception
     * @author ljj
     * @date 2022/9/27 3:53 下午
     */
    public static function getEncrypt($str, $public_key)
    {
        //$str是待加密字符串
        $encrypted = '';
        if (openssl_public_encrypt($str, $encrypted, $public_key, OPENSSL_PKCS1_OAEP_PADDING)) {
            //base64编码
            $sign = base64_encode($encrypted);
        } else {
            //Libs_Log_Logger::outputLog($result_arr,"wx_transfer");
            throw new \Exception('encrypt failed');
        }
        return $sign;
    }

    public static function decryptToString($aesKey, $associatedData, $nonceStr, $ciphertext)
    {
        $ciphertext = \base64_decode($ciphertext);
        if (strlen($ciphertext) <= self::AUTH_TAG_LENGTH_BYTE) {
            return false;
        }

        // ext-sodium (default installed on >= PHP 7.2)
        if (function_exists('\sodium_crypto_aead_aes256gcm_is_available') && \sodium_crypto_aead_aes256gcm_is_available()) {
            return \sodium_crypto_aead_aes256gcm_decrypt($ciphertext, $associatedData, $nonceStr, $aesKey);
        }

        // ext-libsodium (need install libsodium-php 1.x via pecl)
        if (function_exists('\Sodium\crypto_aead_aes256gcm_is_available') && \Sodium\crypto_aead_aes256gcm_is_available()) {
            return \Sodium\crypto_aead_aes256gcm_decrypt($ciphertext, $associatedData, $nonceStr, $aesKey);
        }

        // openssl (PHP >= 7.1 support AEAD)
        if (PHP_VERSION_ID >= 70100 && in_array('aes-256-gcm', \openssl_get_cipher_methods())) {
            $ctext = substr($ciphertext, 0, -self::AUTH_TAG_LENGTH_BYTE);
            $authTag = substr($ciphertext, -self::AUTH_TAG_LENGTH_BYTE);

            return \openssl_decrypt($ctext, 'aes-256-gcm', $aesKey, \OPENSSL_RAW_DATA, $nonceStr,
                $authTag, $associatedData);
        }

        throw new \RuntimeException('AEAD_AES_256_GCM需要PHP 7.1以上或者安装libsodium-php');
    }

    /**
     * @notes 商家明细单号查询明细单API
     * @param $withdrawApply
     * @param $config
     * @return mixed
     * @author ljj
     * @date 2022/9/27 5:54 下午
     */
     public static function details($appid,$mchid,$cert_client,$cert_key,$outbatchno,$outdetailno)
     {
         $config = [
             'app_id' => $appid,
             'mch_id' => $mchid, //商户ID
             'cert_client' => getcwd().$cert_client, //cert证书地址//绝对路径
             'cert_key' => getcwd().$cert_key, //key支付证书绝对地址
         ];
         //请求URL
         $url = 'https://api.mch.weixin.qq.com/v3/transfer/batches/out-batch-no/' . $outbatchno . '/details/out-detail-no/' . $outdetailno;
         //请求方式
         $http_method = 'GET';
         //请求参数
         $data = [];
         $token = self::token($url, $http_method, $data, $config);
         //获取token
         $result = self::https_request($url, $data, $token);
         //发送请求
         $result_arr = json_decode($result, true);
         return $result_arr;
     }
}

PHP 微信支付-商家转账到零钱-单文件版

PHP PDF417二维条形码

首先建立PDF417类

<?php

// File name   : PDF417.php
// Author      : Dinesh Rabara

/**
 * @file
 * PDF417 (ISO/IEC 15438:2006) is a 2-dimensional stacked bar code 
 * (requires PHP bcmath extension)
 * @author Dinesh Rabara
 */
// definitions
if (!defined('PDF417DEFS')) {

    /**
     * Indicate that definitions for this class are set
     */
    define('PDF417DEFS', true);

    // -----------------------------------------------------

    /**
     * Row height respect X dimension of single module
     */
    define('ROWHEIGHT', 4);

    /**
     * Horizontal quiet zone in modules
     */
    define('QUIETH', 2);

    /**
     * Vertical quiet zone in modules
     */
    define('QUIETV', 2);
} // end of definitions
// #*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#

/**
 * @class PDF417
 * @author Dinesh Rabara
 */
class PDF417 {

    /**
     * Barcode array to be returned which is readable by Dinesh Rabara.
     * @protected
     */
    protected $barcode_array = array();

    /**
     * Start pattern.
     * @protected
     */
    protected $start_pattern = '11111111010101000';

    /**
     * Stop pattern.
     * @protected
     */
    protected $stop_pattern = '111111101000101001';

    /**
     * Array of text Compaction Sub-Modes (values 0xFB - 0xFF are used for submode changers).
     * @protected
     */
    protected $textsubmodes = array(
        array(0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x20, 0xFD, 0xFE, 0xFF), // Alpha
        array(0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x20, 0xFD, 0xFE, 0xFF), // Lower
        array(0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x26, 0x0d, 0x09, 0x2c, 0x3a, 0x23, 0x2d, 0x2e, 0x24, 0x2f, 0x2b, 0x25, 0x2a, 0x3d, 0x5e, 0xFB, 0x20, 0xFD, 0xFE, 0xFF), // Mixed
        array(0x3b, 0x3c, 0x3e, 0x40, 0x5b, 0x5c, 0x5d, 0x5f, 0x60, 0x7e, 0x21, 0x0d, 0x09, 0x2c, 0x3a, 0x0a, 0x2d, 0x2e, 0x24, 0x2f, 0x22, 0x7c, 0x2a, 0x28, 0x29, 0x3f, 0x7b, 0x7d, 0x27, 0xFF) // Puntuaction
    );

    /**
     * Array of switching codes for Text Compaction Sub-Modes.
     * @protected
     */
    protected $textlatch = array(
        '01' => array(27), '02' => array(28), '03' => array(28, 25), //
        '10' => array(28, 28), '12' => array(28), '13' => array(28, 25), //
        '20' => array(28), '21' => array(27), '23' => array(25), //
        '30' => array(29), '31' => array(29, 27), '32' => array(29, 28) //
    );

    /**
     * Clusters of codewords (0, 3, 6)<br/>
     * Values are hex equivalents of binary representation of bars (1 = bar, 0 = space).<br/>
     * The codewords numbered from 900 to 928 have special meaning, some enable to switch between modes in order to optimise the code:<ul>
     * <li>900 : Switch to "Text" mode</li>
     * <li>901 : Switch to "Byte" mode</li>
     * <li>902 : Switch to "Numeric" mode</li>
     * <li>903 - 912 : Reserved</li>
     * <li>913 : Switch to "Octet" only for the next codeword</li>
     * <li>914 - 920 : Reserved</li>
     * <li>921 : Initialization</li>
     * <li>922 : Terminator codeword for Macro PDF control block</li>
     * <li>923 : Sequence tag to identify the beginning of optional fields in the Macro PDF control block</li>
     * <li>924 : Switch to "Byte" mode (If the total number of byte is multiple of 6)</li>
     * <li>925 : Identifier for a user defined Extended Channel Interpretation (ECI)</li>
     * <li>926 : Identifier for a general purpose ECI format</li>
     * <li>927 : Identifier for an ECI of a character set or code page</li>
     * <li>928 : Macro marker codeword to indicate the beginning of a Macro PDF Control Block</li>
     * </ul>
     * @protected
     */
    protected $clusters = array(
        array(// cluster 0 -----------------------------------------------------------------------
            0x1d5c0, 0x1eaf0, 0x1f57c, 0x1d4e0, 0x1ea78, 0x1f53e, 0x1a8c0, 0x1d470, 0x1a860, 0x15040, //  10
            0x1a830, 0x15020, 0x1adc0, 0x1d6f0, 0x1eb7c, 0x1ace0, 0x1d678, 0x1eb3e, 0x158c0, 0x1ac70, //  20
            0x15860, 0x15dc0, 0x1aef0, 0x1d77c, 0x15ce0, 0x1ae78, 0x1d73e, 0x15c70, 0x1ae3c, 0x15ef0, //  30
            0x1af7c, 0x15e78, 0x1af3e, 0x15f7c, 0x1f5fa, 0x1d2e0, 0x1e978, 0x1f4be, 0x1a4c0, 0x1d270, //  40
            0x1e93c, 0x1a460, 0x1d238, 0x14840, 0x1a430, 0x1d21c, 0x14820, 0x1a418, 0x14810, 0x1a6e0, //  50
            0x1d378, 0x1e9be, 0x14cc0, 0x1a670, 0x1d33c, 0x14c60, 0x1a638, 0x1d31e, 0x14c30, 0x1a61c, //  60
            0x14ee0, 0x1a778, 0x1d3be, 0x14e70, 0x1a73c, 0x14e38, 0x1a71e, 0x14f78, 0x1a7be, 0x14f3c, //  70
            0x14f1e, 0x1a2c0, 0x1d170, 0x1e8bc, 0x1a260, 0x1d138, 0x1e89e, 0x14440, 0x1a230, 0x1d11c, //  80
            0x14420, 0x1a218, 0x14410, 0x14408, 0x146c0, 0x1a370, 0x1d1bc, 0x14660, 0x1a338, 0x1d19e, //  90
            0x14630, 0x1a31c, 0x14618, 0x1460c, 0x14770, 0x1a3bc, 0x14738, 0x1a39e, 0x1471c, 0x147bc, // 100
            0x1a160, 0x1d0b8, 0x1e85e, 0x14240, 0x1a130, 0x1d09c, 0x14220, 0x1a118, 0x1d08e, 0x14210, // 110
            0x1a10c, 0x14208, 0x1a106, 0x14360, 0x1a1b8, 0x1d0de, 0x14330, 0x1a19c, 0x14318, 0x1a18e, // 120
            0x1430c, 0x14306, 0x1a1de, 0x1438e, 0x14140, 0x1a0b0, 0x1d05c, 0x14120, 0x1a098, 0x1d04e, // 130
            0x14110, 0x1a08c, 0x14108, 0x1a086, 0x14104, 0x141b0, 0x14198, 0x1418c, 0x140a0, 0x1d02e, // 140
            0x1a04c, 0x1a046, 0x14082, 0x1cae0, 0x1e578, 0x1f2be, 0x194c0, 0x1ca70, 0x1e53c, 0x19460, // 150
            0x1ca38, 0x1e51e, 0x12840, 0x19430, 0x12820, 0x196e0, 0x1cb78, 0x1e5be, 0x12cc0, 0x19670, // 160
            0x1cb3c, 0x12c60, 0x19638, 0x12c30, 0x12c18, 0x12ee0, 0x19778, 0x1cbbe, 0x12e70, 0x1973c, // 170
            0x12e38, 0x12e1c, 0x12f78, 0x197be, 0x12f3c, 0x12fbe, 0x1dac0, 0x1ed70, 0x1f6bc, 0x1da60, // 180
            0x1ed38, 0x1f69e, 0x1b440, 0x1da30, 0x1ed1c, 0x1b420, 0x1da18, 0x1ed0e, 0x1b410, 0x1da0c, // 190
            0x192c0, 0x1c970, 0x1e4bc, 0x1b6c0, 0x19260, 0x1c938, 0x1e49e, 0x1b660, 0x1db38, 0x1ed9e, // 200
            0x16c40, 0x12420, 0x19218, 0x1c90e, 0x16c20, 0x1b618, 0x16c10, 0x126c0, 0x19370, 0x1c9bc, // 210
            0x16ec0, 0x12660, 0x19338, 0x1c99e, 0x16e60, 0x1b738, 0x1db9e, 0x16e30, 0x12618, 0x16e18, // 220
            0x12770, 0x193bc, 0x16f70, 0x12738, 0x1939e, 0x16f38, 0x1b79e, 0x16f1c, 0x127bc, 0x16fbc, // 230
            0x1279e, 0x16f9e, 0x1d960, 0x1ecb8, 0x1f65e, 0x1b240, 0x1d930, 0x1ec9c, 0x1b220, 0x1d918, // 240
            0x1ec8e, 0x1b210, 0x1d90c, 0x1b208, 0x1b204, 0x19160, 0x1c8b8, 0x1e45e, 0x1b360, 0x19130, // 250
            0x1c89c, 0x16640, 0x12220, 0x1d99c, 0x1c88e, 0x16620, 0x12210, 0x1910c, 0x16610, 0x1b30c, // 260
            0x19106, 0x12204, 0x12360, 0x191b8, 0x1c8de, 0x16760, 0x12330, 0x1919c, 0x16730, 0x1b39c, // 270
            0x1918e, 0x16718, 0x1230c, 0x12306, 0x123b8, 0x191de, 0x167b8, 0x1239c, 0x1679c, 0x1238e, // 280
            0x1678e, 0x167de, 0x1b140, 0x1d8b0, 0x1ec5c, 0x1b120, 0x1d898, 0x1ec4e, 0x1b110, 0x1d88c, // 290
            0x1b108, 0x1d886, 0x1b104, 0x1b102, 0x12140, 0x190b0, 0x1c85c, 0x16340, 0x12120, 0x19098, // 300
            0x1c84e, 0x16320, 0x1b198, 0x1d8ce, 0x16310, 0x12108, 0x19086, 0x16308, 0x1b186, 0x16304, // 310
            0x121b0, 0x190dc, 0x163b0, 0x12198, 0x190ce, 0x16398, 0x1b1ce, 0x1638c, 0x12186, 0x16386, // 320
            0x163dc, 0x163ce, 0x1b0a0, 0x1d858, 0x1ec2e, 0x1b090, 0x1d84c, 0x1b088, 0x1d846, 0x1b084, // 330
            0x1b082, 0x120a0, 0x19058, 0x1c82e, 0x161a0, 0x12090, 0x1904c, 0x16190, 0x1b0cc, 0x19046, // 340
            0x16188, 0x12084, 0x16184, 0x12082, 0x120d8, 0x161d8, 0x161cc, 0x161c6, 0x1d82c, 0x1d826, // 350
            0x1b042, 0x1902c, 0x12048, 0x160c8, 0x160c4, 0x160c2, 0x18ac0, 0x1c570, 0x1e2bc, 0x18a60, // 360
            0x1c538, 0x11440, 0x18a30, 0x1c51c, 0x11420, 0x18a18, 0x11410, 0x11408, 0x116c0, 0x18b70, // 370
            0x1c5bc, 0x11660, 0x18b38, 0x1c59e, 0x11630, 0x18b1c, 0x11618, 0x1160c, 0x11770, 0x18bbc, // 380
            0x11738, 0x18b9e, 0x1171c, 0x117bc, 0x1179e, 0x1cd60, 0x1e6b8, 0x1f35e, 0x19a40, 0x1cd30, // 390
            0x1e69c, 0x19a20, 0x1cd18, 0x1e68e, 0x19a10, 0x1cd0c, 0x19a08, 0x1cd06, 0x18960, 0x1c4b8, // 400
            0x1e25e, 0x19b60, 0x18930, 0x1c49c, 0x13640, 0x11220, 0x1cd9c, 0x1c48e, 0x13620, 0x19b18, // 410
            0x1890c, 0x13610, 0x11208, 0x13608, 0x11360, 0x189b8, 0x1c4de, 0x13760, 0x11330, 0x1cdde, // 420
            0x13730, 0x19b9c, 0x1898e, 0x13718, 0x1130c, 0x1370c, 0x113b8, 0x189de, 0x137b8, 0x1139c, // 430
            0x1379c, 0x1138e, 0x113de, 0x137de, 0x1dd40, 0x1eeb0, 0x1f75c, 0x1dd20, 0x1ee98, 0x1f74e, // 440
            0x1dd10, 0x1ee8c, 0x1dd08, 0x1ee86, 0x1dd04, 0x19940, 0x1ccb0, 0x1e65c, 0x1bb40, 0x19920, // 450
            0x1eedc, 0x1e64e, 0x1bb20, 0x1dd98, 0x1eece, 0x1bb10, 0x19908, 0x1cc86, 0x1bb08, 0x1dd86, // 460
            0x19902, 0x11140, 0x188b0, 0x1c45c, 0x13340, 0x11120, 0x18898, 0x1c44e, 0x17740, 0x13320, // 470
            0x19998, 0x1ccce, 0x17720, 0x1bb98, 0x1ddce, 0x18886, 0x17710, 0x13308, 0x19986, 0x17708, // 480
            0x11102, 0x111b0, 0x188dc, 0x133b0, 0x11198, 0x188ce, 0x177b0, 0x13398, 0x199ce, 0x17798, // 490
            0x1bbce, 0x11186, 0x13386, 0x111dc, 0x133dc, 0x111ce, 0x177dc, 0x133ce, 0x1dca0, 0x1ee58, // 500
            0x1f72e, 0x1dc90, 0x1ee4c, 0x1dc88, 0x1ee46, 0x1dc84, 0x1dc82, 0x198a0, 0x1cc58, 0x1e62e, // 510
            0x1b9a0, 0x19890, 0x1ee6e, 0x1b990, 0x1dccc, 0x1cc46, 0x1b988, 0x19884, 0x1b984, 0x19882, // 520
            0x1b982, 0x110a0, 0x18858, 0x1c42e, 0x131a0, 0x11090, 0x1884c, 0x173a0, 0x13190, 0x198cc, // 530
            0x18846, 0x17390, 0x1b9cc, 0x11084, 0x17388, 0x13184, 0x11082, 0x13182, 0x110d8, 0x1886e, // 540
            0x131d8, 0x110cc, 0x173d8, 0x131cc, 0x110c6, 0x173cc, 0x131c6, 0x110ee, 0x173ee, 0x1dc50, // 550
            0x1ee2c, 0x1dc48, 0x1ee26, 0x1dc44, 0x1dc42, 0x19850, 0x1cc2c, 0x1b8d0, 0x19848, 0x1cc26, // 560
            0x1b8c8, 0x1dc66, 0x1b8c4, 0x19842, 0x1b8c2, 0x11050, 0x1882c, 0x130d0, 0x11048, 0x18826, // 570
            0x171d0, 0x130c8, 0x19866, 0x171c8, 0x1b8e6, 0x11042, 0x171c4, 0x130c2, 0x171c2, 0x130ec, // 580
            0x171ec, 0x171e6, 0x1ee16, 0x1dc22, 0x1cc16, 0x19824, 0x19822, 0x11028, 0x13068, 0x170e8, // 590
            0x11022, 0x13062, 0x18560, 0x10a40, 0x18530, 0x10a20, 0x18518, 0x1c28e, 0x10a10, 0x1850c, // 600
            0x10a08, 0x18506, 0x10b60, 0x185b8, 0x1c2de, 0x10b30, 0x1859c, 0x10b18, 0x1858e, 0x10b0c, // 610
            0x10b06, 0x10bb8, 0x185de, 0x10b9c, 0x10b8e, 0x10bde, 0x18d40, 0x1c6b0, 0x1e35c, 0x18d20, // 620
            0x1c698, 0x18d10, 0x1c68c, 0x18d08, 0x1c686, 0x18d04, 0x10940, 0x184b0, 0x1c25c, 0x11b40, // 630
            0x10920, 0x1c6dc, 0x1c24e, 0x11b20, 0x18d98, 0x1c6ce, 0x11b10, 0x10908, 0x18486, 0x11b08, // 640
            0x18d86, 0x10902, 0x109b0, 0x184dc, 0x11bb0, 0x10998, 0x184ce, 0x11b98, 0x18dce, 0x11b8c, // 650
            0x10986, 0x109dc, 0x11bdc, 0x109ce, 0x11bce, 0x1cea0, 0x1e758, 0x1f3ae, 0x1ce90, 0x1e74c, // 660
            0x1ce88, 0x1e746, 0x1ce84, 0x1ce82, 0x18ca0, 0x1c658, 0x19da0, 0x18c90, 0x1c64c, 0x19d90, // 670
            0x1cecc, 0x1c646, 0x19d88, 0x18c84, 0x19d84, 0x18c82, 0x19d82, 0x108a0, 0x18458, 0x119a0, // 680
            0x10890, 0x1c66e, 0x13ba0, 0x11990, 0x18ccc, 0x18446, 0x13b90, 0x19dcc, 0x10884, 0x13b88, // 690
            0x11984, 0x10882, 0x11982, 0x108d8, 0x1846e, 0x119d8, 0x108cc, 0x13bd8, 0x119cc, 0x108c6, // 700
            0x13bcc, 0x119c6, 0x108ee, 0x119ee, 0x13bee, 0x1ef50, 0x1f7ac, 0x1ef48, 0x1f7a6, 0x1ef44, // 710
            0x1ef42, 0x1ce50, 0x1e72c, 0x1ded0, 0x1ef6c, 0x1e726, 0x1dec8, 0x1ef66, 0x1dec4, 0x1ce42, // 720
            0x1dec2, 0x18c50, 0x1c62c, 0x19cd0, 0x18c48, 0x1c626, 0x1bdd0, 0x19cc8, 0x1ce66, 0x1bdc8, // 730
            0x1dee6, 0x18c42, 0x1bdc4, 0x19cc2, 0x1bdc2, 0x10850, 0x1842c, 0x118d0, 0x10848, 0x18426, // 740
            0x139d0, 0x118c8, 0x18c66, 0x17bd0, 0x139c8, 0x19ce6, 0x10842, 0x17bc8, 0x1bde6, 0x118c2, // 750
            0x17bc4, 0x1086c, 0x118ec, 0x10866, 0x139ec, 0x118e6, 0x17bec, 0x139e6, 0x17be6, 0x1ef28, // 760
            0x1f796, 0x1ef24, 0x1ef22, 0x1ce28, 0x1e716, 0x1de68, 0x1ef36, 0x1de64, 0x1ce22, 0x1de62, // 770
            0x18c28, 0x1c616, 0x19c68, 0x18c24, 0x1bce8, 0x19c64, 0x18c22, 0x1bce4, 0x19c62, 0x1bce2, // 780
            0x10828, 0x18416, 0x11868, 0x18c36, 0x138e8, 0x11864, 0x10822, 0x179e8, 0x138e4, 0x11862, // 790
            0x179e4, 0x138e2, 0x179e2, 0x11876, 0x179f6, 0x1ef12, 0x1de34, 0x1de32, 0x19c34, 0x1bc74, // 800
            0x1bc72, 0x11834, 0x13874, 0x178f4, 0x178f2, 0x10540, 0x10520, 0x18298, 0x10510, 0x10508, // 810
            0x10504, 0x105b0, 0x10598, 0x1058c, 0x10586, 0x105dc, 0x105ce, 0x186a0, 0x18690, 0x1c34c, // 820
            0x18688, 0x1c346, 0x18684, 0x18682, 0x104a0, 0x18258, 0x10da0, 0x186d8, 0x1824c, 0x10d90, // 830
            0x186cc, 0x10d88, 0x186c6, 0x10d84, 0x10482, 0x10d82, 0x104d8, 0x1826e, 0x10dd8, 0x186ee, // 840
            0x10dcc, 0x104c6, 0x10dc6, 0x104ee, 0x10dee, 0x1c750, 0x1c748, 0x1c744, 0x1c742, 0x18650, // 850
            0x18ed0, 0x1c76c, 0x1c326, 0x18ec8, 0x1c766, 0x18ec4, 0x18642, 0x18ec2, 0x10450, 0x10cd0, // 860
            0x10448, 0x18226, 0x11dd0, 0x10cc8, 0x10444, 0x11dc8, 0x10cc4, 0x10442, 0x11dc4, 0x10cc2, // 870
            0x1046c, 0x10cec, 0x10466, 0x11dec, 0x10ce6, 0x11de6, 0x1e7a8, 0x1e7a4, 0x1e7a2, 0x1c728, // 880
            0x1cf68, 0x1e7b6, 0x1cf64, 0x1c722, 0x1cf62, 0x18628, 0x1c316, 0x18e68, 0x1c736, 0x19ee8, // 890
            0x18e64, 0x18622, 0x19ee4, 0x18e62, 0x19ee2, 0x10428, 0x18216, 0x10c68, 0x18636, 0x11ce8, // 900
            0x10c64, 0x10422, 0x13de8, 0x11ce4, 0x10c62, 0x13de4, 0x11ce2, 0x10436, 0x10c76, 0x11cf6, // 910
            0x13df6, 0x1f7d4, 0x1f7d2, 0x1e794, 0x1efb4, 0x1e792, 0x1efb2, 0x1c714, 0x1cf34, 0x1c712, // 920
            0x1df74, 0x1cf32, 0x1df72, 0x18614, 0x18e34, 0x18612, 0x19e74, 0x18e32, 0x1bef4), // 929
        array(// cluster 3 -----------------------------------------------------------------------
            0x1f560, 0x1fab8, 0x1ea40, 0x1f530, 0x1fa9c, 0x1ea20, 0x1f518, 0x1fa8e, 0x1ea10, 0x1f50c, //  10
            0x1ea08, 0x1f506, 0x1ea04, 0x1eb60, 0x1f5b8, 0x1fade, 0x1d640, 0x1eb30, 0x1f59c, 0x1d620, //  20
            0x1eb18, 0x1f58e, 0x1d610, 0x1eb0c, 0x1d608, 0x1eb06, 0x1d604, 0x1d760, 0x1ebb8, 0x1f5de, //  30
            0x1ae40, 0x1d730, 0x1eb9c, 0x1ae20, 0x1d718, 0x1eb8e, 0x1ae10, 0x1d70c, 0x1ae08, 0x1d706, //  40
            0x1ae04, 0x1af60, 0x1d7b8, 0x1ebde, 0x15e40, 0x1af30, 0x1d79c, 0x15e20, 0x1af18, 0x1d78e, //  50
            0x15e10, 0x1af0c, 0x15e08, 0x1af06, 0x15f60, 0x1afb8, 0x1d7de, 0x15f30, 0x1af9c, 0x15f18, //  60
            0x1af8e, 0x15f0c, 0x15fb8, 0x1afde, 0x15f9c, 0x15f8e, 0x1e940, 0x1f4b0, 0x1fa5c, 0x1e920, //  70
            0x1f498, 0x1fa4e, 0x1e910, 0x1f48c, 0x1e908, 0x1f486, 0x1e904, 0x1e902, 0x1d340, 0x1e9b0, //  80
            0x1f4dc, 0x1d320, 0x1e998, 0x1f4ce, 0x1d310, 0x1e98c, 0x1d308, 0x1e986, 0x1d304, 0x1d302, //  90
            0x1a740, 0x1d3b0, 0x1e9dc, 0x1a720, 0x1d398, 0x1e9ce, 0x1a710, 0x1d38c, 0x1a708, 0x1d386, // 100
            0x1a704, 0x1a702, 0x14f40, 0x1a7b0, 0x1d3dc, 0x14f20, 0x1a798, 0x1d3ce, 0x14f10, 0x1a78c, // 110
            0x14f08, 0x1a786, 0x14f04, 0x14fb0, 0x1a7dc, 0x14f98, 0x1a7ce, 0x14f8c, 0x14f86, 0x14fdc, // 120
            0x14fce, 0x1e8a0, 0x1f458, 0x1fa2e, 0x1e890, 0x1f44c, 0x1e888, 0x1f446, 0x1e884, 0x1e882, // 130
            0x1d1a0, 0x1e8d8, 0x1f46e, 0x1d190, 0x1e8cc, 0x1d188, 0x1e8c6, 0x1d184, 0x1d182, 0x1a3a0, // 140
            0x1d1d8, 0x1e8ee, 0x1a390, 0x1d1cc, 0x1a388, 0x1d1c6, 0x1a384, 0x1a382, 0x147a0, 0x1a3d8, // 150
            0x1d1ee, 0x14790, 0x1a3cc, 0x14788, 0x1a3c6, 0x14784, 0x14782, 0x147d8, 0x1a3ee, 0x147cc, // 160
            0x147c6, 0x147ee, 0x1e850, 0x1f42c, 0x1e848, 0x1f426, 0x1e844, 0x1e842, 0x1d0d0, 0x1e86c, // 170
            0x1d0c8, 0x1e866, 0x1d0c4, 0x1d0c2, 0x1a1d0, 0x1d0ec, 0x1a1c8, 0x1d0e6, 0x1a1c4, 0x1a1c2, // 180
            0x143d0, 0x1a1ec, 0x143c8, 0x1a1e6, 0x143c4, 0x143c2, 0x143ec, 0x143e6, 0x1e828, 0x1f416, // 190
            0x1e824, 0x1e822, 0x1d068, 0x1e836, 0x1d064, 0x1d062, 0x1a0e8, 0x1d076, 0x1a0e4, 0x1a0e2, // 200
            0x141e8, 0x1a0f6, 0x141e4, 0x141e2, 0x1e814, 0x1e812, 0x1d034, 0x1d032, 0x1a074, 0x1a072, // 210
            0x1e540, 0x1f2b0, 0x1f95c, 0x1e520, 0x1f298, 0x1f94e, 0x1e510, 0x1f28c, 0x1e508, 0x1f286, // 220
            0x1e504, 0x1e502, 0x1cb40, 0x1e5b0, 0x1f2dc, 0x1cb20, 0x1e598, 0x1f2ce, 0x1cb10, 0x1e58c, // 230
            0x1cb08, 0x1e586, 0x1cb04, 0x1cb02, 0x19740, 0x1cbb0, 0x1e5dc, 0x19720, 0x1cb98, 0x1e5ce, // 240
            0x19710, 0x1cb8c, 0x19708, 0x1cb86, 0x19704, 0x19702, 0x12f40, 0x197b0, 0x1cbdc, 0x12f20, // 250
            0x19798, 0x1cbce, 0x12f10, 0x1978c, 0x12f08, 0x19786, 0x12f04, 0x12fb0, 0x197dc, 0x12f98, // 260
            0x197ce, 0x12f8c, 0x12f86, 0x12fdc, 0x12fce, 0x1f6a0, 0x1fb58, 0x16bf0, 0x1f690, 0x1fb4c, // 270
            0x169f8, 0x1f688, 0x1fb46, 0x168fc, 0x1f684, 0x1f682, 0x1e4a0, 0x1f258, 0x1f92e, 0x1eda0, // 280
            0x1e490, 0x1fb6e, 0x1ed90, 0x1f6cc, 0x1f246, 0x1ed88, 0x1e484, 0x1ed84, 0x1e482, 0x1ed82, // 290
            0x1c9a0, 0x1e4d8, 0x1f26e, 0x1dba0, 0x1c990, 0x1e4cc, 0x1db90, 0x1edcc, 0x1e4c6, 0x1db88, // 300
            0x1c984, 0x1db84, 0x1c982, 0x1db82, 0x193a0, 0x1c9d8, 0x1e4ee, 0x1b7a0, 0x19390, 0x1c9cc, // 310
            0x1b790, 0x1dbcc, 0x1c9c6, 0x1b788, 0x19384, 0x1b784, 0x19382, 0x1b782, 0x127a0, 0x193d8, // 320
            0x1c9ee, 0x16fa0, 0x12790, 0x193cc, 0x16f90, 0x1b7cc, 0x193c6, 0x16f88, 0x12784, 0x16f84, // 330
            0x12782, 0x127d8, 0x193ee, 0x16fd8, 0x127cc, 0x16fcc, 0x127c6, 0x16fc6, 0x127ee, 0x1f650, // 340
            0x1fb2c, 0x165f8, 0x1f648, 0x1fb26, 0x164fc, 0x1f644, 0x1647e, 0x1f642, 0x1e450, 0x1f22c, // 350
            0x1ecd0, 0x1e448, 0x1f226, 0x1ecc8, 0x1f666, 0x1ecc4, 0x1e442, 0x1ecc2, 0x1c8d0, 0x1e46c, // 360
            0x1d9d0, 0x1c8c8, 0x1e466, 0x1d9c8, 0x1ece6, 0x1d9c4, 0x1c8c2, 0x1d9c2, 0x191d0, 0x1c8ec, // 370
            0x1b3d0, 0x191c8, 0x1c8e6, 0x1b3c8, 0x1d9e6, 0x1b3c4, 0x191c2, 0x1b3c2, 0x123d0, 0x191ec, // 380
            0x167d0, 0x123c8, 0x191e6, 0x167c8, 0x1b3e6, 0x167c4, 0x123c2, 0x167c2, 0x123ec, 0x167ec, // 390
            0x123e6, 0x167e6, 0x1f628, 0x1fb16, 0x162fc, 0x1f624, 0x1627e, 0x1f622, 0x1e428, 0x1f216, // 400
            0x1ec68, 0x1f636, 0x1ec64, 0x1e422, 0x1ec62, 0x1c868, 0x1e436, 0x1d8e8, 0x1c864, 0x1d8e4, // 410
            0x1c862, 0x1d8e2, 0x190e8, 0x1c876, 0x1b1e8, 0x1d8f6, 0x1b1e4, 0x190e2, 0x1b1e2, 0x121e8, // 420
            0x190f6, 0x163e8, 0x121e4, 0x163e4, 0x121e2, 0x163e2, 0x121f6, 0x163f6, 0x1f614, 0x1617e, // 430
            0x1f612, 0x1e414, 0x1ec34, 0x1e412, 0x1ec32, 0x1c834, 0x1d874, 0x1c832, 0x1d872, 0x19074, // 440
            0x1b0f4, 0x19072, 0x1b0f2, 0x120f4, 0x161f4, 0x120f2, 0x161f2, 0x1f60a, 0x1e40a, 0x1ec1a, // 450
            0x1c81a, 0x1d83a, 0x1903a, 0x1b07a, 0x1e2a0, 0x1f158, 0x1f8ae, 0x1e290, 0x1f14c, 0x1e288, // 460
            0x1f146, 0x1e284, 0x1e282, 0x1c5a0, 0x1e2d8, 0x1f16e, 0x1c590, 0x1e2cc, 0x1c588, 0x1e2c6, // 470
            0x1c584, 0x1c582, 0x18ba0, 0x1c5d8, 0x1e2ee, 0x18b90, 0x1c5cc, 0x18b88, 0x1c5c6, 0x18b84, // 480
            0x18b82, 0x117a0, 0x18bd8, 0x1c5ee, 0x11790, 0x18bcc, 0x11788, 0x18bc6, 0x11784, 0x11782, // 490
            0x117d8, 0x18bee, 0x117cc, 0x117c6, 0x117ee, 0x1f350, 0x1f9ac, 0x135f8, 0x1f348, 0x1f9a6, // 500
            0x134fc, 0x1f344, 0x1347e, 0x1f342, 0x1e250, 0x1f12c, 0x1e6d0, 0x1e248, 0x1f126, 0x1e6c8, // 510
            0x1f366, 0x1e6c4, 0x1e242, 0x1e6c2, 0x1c4d0, 0x1e26c, 0x1cdd0, 0x1c4c8, 0x1e266, 0x1cdc8, // 520
            0x1e6e6, 0x1cdc4, 0x1c4c2, 0x1cdc2, 0x189d0, 0x1c4ec, 0x19bd0, 0x189c8, 0x1c4e6, 0x19bc8, // 530
            0x1cde6, 0x19bc4, 0x189c2, 0x19bc2, 0x113d0, 0x189ec, 0x137d0, 0x113c8, 0x189e6, 0x137c8, // 540
            0x19be6, 0x137c4, 0x113c2, 0x137c2, 0x113ec, 0x137ec, 0x113e6, 0x137e6, 0x1fba8, 0x175f0, // 550
            0x1bafc, 0x1fba4, 0x174f8, 0x1ba7e, 0x1fba2, 0x1747c, 0x1743e, 0x1f328, 0x1f996, 0x132fc, // 560
            0x1f768, 0x1fbb6, 0x176fc, 0x1327e, 0x1f764, 0x1f322, 0x1767e, 0x1f762, 0x1e228, 0x1f116, // 570
            0x1e668, 0x1e224, 0x1eee8, 0x1f776, 0x1e222, 0x1eee4, 0x1e662, 0x1eee2, 0x1c468, 0x1e236, // 580
            0x1cce8, 0x1c464, 0x1dde8, 0x1cce4, 0x1c462, 0x1dde4, 0x1cce2, 0x1dde2, 0x188e8, 0x1c476, // 590
            0x199e8, 0x188e4, 0x1bbe8, 0x199e4, 0x188e2, 0x1bbe4, 0x199e2, 0x1bbe2, 0x111e8, 0x188f6, // 600
            0x133e8, 0x111e4, 0x177e8, 0x133e4, 0x111e2, 0x177e4, 0x133e2, 0x177e2, 0x111f6, 0x133f6, // 610
            0x1fb94, 0x172f8, 0x1b97e, 0x1fb92, 0x1727c, 0x1723e, 0x1f314, 0x1317e, 0x1f734, 0x1f312, // 620
            0x1737e, 0x1f732, 0x1e214, 0x1e634, 0x1e212, 0x1ee74, 0x1e632, 0x1ee72, 0x1c434, 0x1cc74, // 630
            0x1c432, 0x1dcf4, 0x1cc72, 0x1dcf2, 0x18874, 0x198f4, 0x18872, 0x1b9f4, 0x198f2, 0x1b9f2, // 640
            0x110f4, 0x131f4, 0x110f2, 0x173f4, 0x131f2, 0x173f2, 0x1fb8a, 0x1717c, 0x1713e, 0x1f30a, // 650
            0x1f71a, 0x1e20a, 0x1e61a, 0x1ee3a, 0x1c41a, 0x1cc3a, 0x1dc7a, 0x1883a, 0x1987a, 0x1b8fa, // 660
            0x1107a, 0x130fa, 0x171fa, 0x170be, 0x1e150, 0x1f0ac, 0x1e148, 0x1f0a6, 0x1e144, 0x1e142, // 670
            0x1c2d0, 0x1e16c, 0x1c2c8, 0x1e166, 0x1c2c4, 0x1c2c2, 0x185d0, 0x1c2ec, 0x185c8, 0x1c2e6, // 680
            0x185c4, 0x185c2, 0x10bd0, 0x185ec, 0x10bc8, 0x185e6, 0x10bc4, 0x10bc2, 0x10bec, 0x10be6, // 690
            0x1f1a8, 0x1f8d6, 0x11afc, 0x1f1a4, 0x11a7e, 0x1f1a2, 0x1e128, 0x1f096, 0x1e368, 0x1e124, // 700
            0x1e364, 0x1e122, 0x1e362, 0x1c268, 0x1e136, 0x1c6e8, 0x1c264, 0x1c6e4, 0x1c262, 0x1c6e2, // 710
            0x184e8, 0x1c276, 0x18de8, 0x184e4, 0x18de4, 0x184e2, 0x18de2, 0x109e8, 0x184f6, 0x11be8, // 720
            0x109e4, 0x11be4, 0x109e2, 0x11be2, 0x109f6, 0x11bf6, 0x1f9d4, 0x13af8, 0x19d7e, 0x1f9d2, // 730
            0x13a7c, 0x13a3e, 0x1f194, 0x1197e, 0x1f3b4, 0x1f192, 0x13b7e, 0x1f3b2, 0x1e114, 0x1e334, // 740
            0x1e112, 0x1e774, 0x1e332, 0x1e772, 0x1c234, 0x1c674, 0x1c232, 0x1cef4, 0x1c672, 0x1cef2, // 750
            0x18474, 0x18cf4, 0x18472, 0x19df4, 0x18cf2, 0x19df2, 0x108f4, 0x119f4, 0x108f2, 0x13bf4, // 760
            0x119f2, 0x13bf2, 0x17af0, 0x1bd7c, 0x17a78, 0x1bd3e, 0x17a3c, 0x17a1e, 0x1f9ca, 0x1397c, // 770
            0x1fbda, 0x17b7c, 0x1393e, 0x17b3e, 0x1f18a, 0x1f39a, 0x1f7ba, 0x1e10a, 0x1e31a, 0x1e73a, // 780
            0x1ef7a, 0x1c21a, 0x1c63a, 0x1ce7a, 0x1defa, 0x1843a, 0x18c7a, 0x19cfa, 0x1bdfa, 0x1087a, // 790
            0x118fa, 0x139fa, 0x17978, 0x1bcbe, 0x1793c, 0x1791e, 0x138be, 0x179be, 0x178bc, 0x1789e, // 800
            0x1785e, 0x1e0a8, 0x1e0a4, 0x1e0a2, 0x1c168, 0x1e0b6, 0x1c164, 0x1c162, 0x182e8, 0x1c176, // 810
            0x182e4, 0x182e2, 0x105e8, 0x182f6, 0x105e4, 0x105e2, 0x105f6, 0x1f0d4, 0x10d7e, 0x1f0d2, // 820
            0x1e094, 0x1e1b4, 0x1e092, 0x1e1b2, 0x1c134, 0x1c374, 0x1c132, 0x1c372, 0x18274, 0x186f4, // 830
            0x18272, 0x186f2, 0x104f4, 0x10df4, 0x104f2, 0x10df2, 0x1f8ea, 0x11d7c, 0x11d3e, 0x1f0ca, // 840
            0x1f1da, 0x1e08a, 0x1e19a, 0x1e3ba, 0x1c11a, 0x1c33a, 0x1c77a, 0x1823a, 0x1867a, 0x18efa, // 850
            0x1047a, 0x10cfa, 0x11dfa, 0x13d78, 0x19ebe, 0x13d3c, 0x13d1e, 0x11cbe, 0x13dbe, 0x17d70, // 860
            0x1bebc, 0x17d38, 0x1be9e, 0x17d1c, 0x17d0e, 0x13cbc, 0x17dbc, 0x13c9e, 0x17d9e, 0x17cb8, // 870
            0x1be5e, 0x17c9c, 0x17c8e, 0x13c5e, 0x17cde, 0x17c5c, 0x17c4e, 0x17c2e, 0x1c0b4, 0x1c0b2, // 880
            0x18174, 0x18172, 0x102f4, 0x102f2, 0x1e0da, 0x1c09a, 0x1c1ba, 0x1813a, 0x1837a, 0x1027a, // 890
            0x106fa, 0x10ebe, 0x11ebc, 0x11e9e, 0x13eb8, 0x19f5e, 0x13e9c, 0x13e8e, 0x11e5e, 0x13ede, // 900
            0x17eb0, 0x1bf5c, 0x17e98, 0x1bf4e, 0x17e8c, 0x17e86, 0x13e5c, 0x17edc, 0x13e4e, 0x17ece, // 910
            0x17e58, 0x1bf2e, 0x17e4c, 0x17e46, 0x13e2e, 0x17e6e, 0x17e2c, 0x17e26, 0x10f5e, 0x11f5c, // 920
            0x11f4e, 0x13f58, 0x19fae, 0x13f4c, 0x13f46, 0x11f2e, 0x13f6e, 0x13f2c, 0x13f26), // 929
        array(// cluster 6 -----------------------------------------------------------------------
            0x1abe0, 0x1d5f8, 0x153c0, 0x1a9f0, 0x1d4fc, 0x151e0, 0x1a8f8, 0x1d47e, 0x150f0, 0x1a87c, //  10
            0x15078, 0x1fad0, 0x15be0, 0x1adf8, 0x1fac8, 0x159f0, 0x1acfc, 0x1fac4, 0x158f8, 0x1ac7e, //  20
            0x1fac2, 0x1587c, 0x1f5d0, 0x1faec, 0x15df8, 0x1f5c8, 0x1fae6, 0x15cfc, 0x1f5c4, 0x15c7e, //  30
            0x1f5c2, 0x1ebd0, 0x1f5ec, 0x1ebc8, 0x1f5e6, 0x1ebc4, 0x1ebc2, 0x1d7d0, 0x1ebec, 0x1d7c8, //  40
            0x1ebe6, 0x1d7c4, 0x1d7c2, 0x1afd0, 0x1d7ec, 0x1afc8, 0x1d7e6, 0x1afc4, 0x14bc0, 0x1a5f0, //  50
            0x1d2fc, 0x149e0, 0x1a4f8, 0x1d27e, 0x148f0, 0x1a47c, 0x14878, 0x1a43e, 0x1483c, 0x1fa68, //  60
            0x14df0, 0x1a6fc, 0x1fa64, 0x14cf8, 0x1a67e, 0x1fa62, 0x14c7c, 0x14c3e, 0x1f4e8, 0x1fa76, //  70
            0x14efc, 0x1f4e4, 0x14e7e, 0x1f4e2, 0x1e9e8, 0x1f4f6, 0x1e9e4, 0x1e9e2, 0x1d3e8, 0x1e9f6, //  80
            0x1d3e4, 0x1d3e2, 0x1a7e8, 0x1d3f6, 0x1a7e4, 0x1a7e2, 0x145e0, 0x1a2f8, 0x1d17e, 0x144f0, //  90
            0x1a27c, 0x14478, 0x1a23e, 0x1443c, 0x1441e, 0x1fa34, 0x146f8, 0x1a37e, 0x1fa32, 0x1467c, // 100
            0x1463e, 0x1f474, 0x1477e, 0x1f472, 0x1e8f4, 0x1e8f2, 0x1d1f4, 0x1d1f2, 0x1a3f4, 0x1a3f2, // 110
            0x142f0, 0x1a17c, 0x14278, 0x1a13e, 0x1423c, 0x1421e, 0x1fa1a, 0x1437c, 0x1433e, 0x1f43a, // 120
            0x1e87a, 0x1d0fa, 0x14178, 0x1a0be, 0x1413c, 0x1411e, 0x141be, 0x140bc, 0x1409e, 0x12bc0, // 130
            0x195f0, 0x1cafc, 0x129e0, 0x194f8, 0x1ca7e, 0x128f0, 0x1947c, 0x12878, 0x1943e, 0x1283c, // 140
            0x1f968, 0x12df0, 0x196fc, 0x1f964, 0x12cf8, 0x1967e, 0x1f962, 0x12c7c, 0x12c3e, 0x1f2e8, // 150
            0x1f976, 0x12efc, 0x1f2e4, 0x12e7e, 0x1f2e2, 0x1e5e8, 0x1f2f6, 0x1e5e4, 0x1e5e2, 0x1cbe8, // 160
            0x1e5f6, 0x1cbe4, 0x1cbe2, 0x197e8, 0x1cbf6, 0x197e4, 0x197e2, 0x1b5e0, 0x1daf8, 0x1ed7e, // 170
            0x169c0, 0x1b4f0, 0x1da7c, 0x168e0, 0x1b478, 0x1da3e, 0x16870, 0x1b43c, 0x16838, 0x1b41e, // 180
            0x1681c, 0x125e0, 0x192f8, 0x1c97e, 0x16de0, 0x124f0, 0x1927c, 0x16cf0, 0x1b67c, 0x1923e, // 190
            0x16c78, 0x1243c, 0x16c3c, 0x1241e, 0x16c1e, 0x1f934, 0x126f8, 0x1937e, 0x1fb74, 0x1f932, // 200
            0x16ef8, 0x1267c, 0x1fb72, 0x16e7c, 0x1263e, 0x16e3e, 0x1f274, 0x1277e, 0x1f6f4, 0x1f272, // 210
            0x16f7e, 0x1f6f2, 0x1e4f4, 0x1edf4, 0x1e4f2, 0x1edf2, 0x1c9f4, 0x1dbf4, 0x1c9f2, 0x1dbf2, // 220
            0x193f4, 0x193f2, 0x165c0, 0x1b2f0, 0x1d97c, 0x164e0, 0x1b278, 0x1d93e, 0x16470, 0x1b23c, // 230
            0x16438, 0x1b21e, 0x1641c, 0x1640e, 0x122f0, 0x1917c, 0x166f0, 0x12278, 0x1913e, 0x16678, // 240
            0x1b33e, 0x1663c, 0x1221e, 0x1661e, 0x1f91a, 0x1237c, 0x1fb3a, 0x1677c, 0x1233e, 0x1673e, // 250
            0x1f23a, 0x1f67a, 0x1e47a, 0x1ecfa, 0x1c8fa, 0x1d9fa, 0x191fa, 0x162e0, 0x1b178, 0x1d8be, // 260
            0x16270, 0x1b13c, 0x16238, 0x1b11e, 0x1621c, 0x1620e, 0x12178, 0x190be, 0x16378, 0x1213c, // 270
            0x1633c, 0x1211e, 0x1631e, 0x121be, 0x163be, 0x16170, 0x1b0bc, 0x16138, 0x1b09e, 0x1611c, // 280
            0x1610e, 0x120bc, 0x161bc, 0x1209e, 0x1619e, 0x160b8, 0x1b05e, 0x1609c, 0x1608e, 0x1205e, // 290
            0x160de, 0x1605c, 0x1604e, 0x115e0, 0x18af8, 0x1c57e, 0x114f0, 0x18a7c, 0x11478, 0x18a3e, // 300
            0x1143c, 0x1141e, 0x1f8b4, 0x116f8, 0x18b7e, 0x1f8b2, 0x1167c, 0x1163e, 0x1f174, 0x1177e, // 310
            0x1f172, 0x1e2f4, 0x1e2f2, 0x1c5f4, 0x1c5f2, 0x18bf4, 0x18bf2, 0x135c0, 0x19af0, 0x1cd7c, // 320
            0x134e0, 0x19a78, 0x1cd3e, 0x13470, 0x19a3c, 0x13438, 0x19a1e, 0x1341c, 0x1340e, 0x112f0, // 330
            0x1897c, 0x136f0, 0x11278, 0x1893e, 0x13678, 0x19b3e, 0x1363c, 0x1121e, 0x1361e, 0x1f89a, // 340
            0x1137c, 0x1f9ba, 0x1377c, 0x1133e, 0x1373e, 0x1f13a, 0x1f37a, 0x1e27a, 0x1e6fa, 0x1c4fa, // 350
            0x1cdfa, 0x189fa, 0x1bae0, 0x1dd78, 0x1eebe, 0x174c0, 0x1ba70, 0x1dd3c, 0x17460, 0x1ba38, // 360
            0x1dd1e, 0x17430, 0x1ba1c, 0x17418, 0x1ba0e, 0x1740c, 0x132e0, 0x19978, 0x1ccbe, 0x176e0, // 370
            0x13270, 0x1993c, 0x17670, 0x1bb3c, 0x1991e, 0x17638, 0x1321c, 0x1761c, 0x1320e, 0x1760e, // 380
            0x11178, 0x188be, 0x13378, 0x1113c, 0x17778, 0x1333c, 0x1111e, 0x1773c, 0x1331e, 0x1771e, // 390
            0x111be, 0x133be, 0x177be, 0x172c0, 0x1b970, 0x1dcbc, 0x17260, 0x1b938, 0x1dc9e, 0x17230, // 400
            0x1b91c, 0x17218, 0x1b90e, 0x1720c, 0x17206, 0x13170, 0x198bc, 0x17370, 0x13138, 0x1989e, // 410
            0x17338, 0x1b99e, 0x1731c, 0x1310e, 0x1730e, 0x110bc, 0x131bc, 0x1109e, 0x173bc, 0x1319e, // 420
            0x1739e, 0x17160, 0x1b8b8, 0x1dc5e, 0x17130, 0x1b89c, 0x17118, 0x1b88e, 0x1710c, 0x17106, // 430
            0x130b8, 0x1985e, 0x171b8, 0x1309c, 0x1719c, 0x1308e, 0x1718e, 0x1105e, 0x130de, 0x171de, // 440
            0x170b0, 0x1b85c, 0x17098, 0x1b84e, 0x1708c, 0x17086, 0x1305c, 0x170dc, 0x1304e, 0x170ce, // 450
            0x17058, 0x1b82e, 0x1704c, 0x17046, 0x1302e, 0x1706e, 0x1702c, 0x17026, 0x10af0, 0x1857c, // 460
            0x10a78, 0x1853e, 0x10a3c, 0x10a1e, 0x10b7c, 0x10b3e, 0x1f0ba, 0x1e17a, 0x1c2fa, 0x185fa, // 470
            0x11ae0, 0x18d78, 0x1c6be, 0x11a70, 0x18d3c, 0x11a38, 0x18d1e, 0x11a1c, 0x11a0e, 0x10978, // 480
            0x184be, 0x11b78, 0x1093c, 0x11b3c, 0x1091e, 0x11b1e, 0x109be, 0x11bbe, 0x13ac0, 0x19d70, // 490
            0x1cebc, 0x13a60, 0x19d38, 0x1ce9e, 0x13a30, 0x19d1c, 0x13a18, 0x19d0e, 0x13a0c, 0x13a06, // 500
            0x11970, 0x18cbc, 0x13b70, 0x11938, 0x18c9e, 0x13b38, 0x1191c, 0x13b1c, 0x1190e, 0x13b0e, // 510
            0x108bc, 0x119bc, 0x1089e, 0x13bbc, 0x1199e, 0x13b9e, 0x1bd60, 0x1deb8, 0x1ef5e, 0x17a40, // 520
            0x1bd30, 0x1de9c, 0x17a20, 0x1bd18, 0x1de8e, 0x17a10, 0x1bd0c, 0x17a08, 0x1bd06, 0x17a04, // 530
            0x13960, 0x19cb8, 0x1ce5e, 0x17b60, 0x13930, 0x19c9c, 0x17b30, 0x1bd9c, 0x19c8e, 0x17b18, // 540
            0x1390c, 0x17b0c, 0x13906, 0x17b06, 0x118b8, 0x18c5e, 0x139b8, 0x1189c, 0x17bb8, 0x1399c, // 550
            0x1188e, 0x17b9c, 0x1398e, 0x17b8e, 0x1085e, 0x118de, 0x139de, 0x17bde, 0x17940, 0x1bcb0, // 560
            0x1de5c, 0x17920, 0x1bc98, 0x1de4e, 0x17910, 0x1bc8c, 0x17908, 0x1bc86, 0x17904, 0x17902, // 570
            0x138b0, 0x19c5c, 0x179b0, 0x13898, 0x19c4e, 0x17998, 0x1bcce, 0x1798c, 0x13886, 0x17986, // 580
            0x1185c, 0x138dc, 0x1184e, 0x179dc, 0x138ce, 0x179ce, 0x178a0, 0x1bc58, 0x1de2e, 0x17890, // 590
            0x1bc4c, 0x17888, 0x1bc46, 0x17884, 0x17882, 0x13858, 0x19c2e, 0x178d8, 0x1384c, 0x178cc, // 600
            0x13846, 0x178c6, 0x1182e, 0x1386e, 0x178ee, 0x17850, 0x1bc2c, 0x17848, 0x1bc26, 0x17844, // 610
            0x17842, 0x1382c, 0x1786c, 0x13826, 0x17866, 0x17828, 0x1bc16, 0x17824, 0x17822, 0x13816, // 620
            0x17836, 0x10578, 0x182be, 0x1053c, 0x1051e, 0x105be, 0x10d70, 0x186bc, 0x10d38, 0x1869e, // 630
            0x10d1c, 0x10d0e, 0x104bc, 0x10dbc, 0x1049e, 0x10d9e, 0x11d60, 0x18eb8, 0x1c75e, 0x11d30, // 640
            0x18e9c, 0x11d18, 0x18e8e, 0x11d0c, 0x11d06, 0x10cb8, 0x1865e, 0x11db8, 0x10c9c, 0x11d9c, // 650
            0x10c8e, 0x11d8e, 0x1045e, 0x10cde, 0x11dde, 0x13d40, 0x19eb0, 0x1cf5c, 0x13d20, 0x19e98, // 660
            0x1cf4e, 0x13d10, 0x19e8c, 0x13d08, 0x19e86, 0x13d04, 0x13d02, 0x11cb0, 0x18e5c, 0x13db0, // 670
            0x11c98, 0x18e4e, 0x13d98, 0x19ece, 0x13d8c, 0x11c86, 0x13d86, 0x10c5c, 0x11cdc, 0x10c4e, // 680
            0x13ddc, 0x11cce, 0x13dce, 0x1bea0, 0x1df58, 0x1efae, 0x1be90, 0x1df4c, 0x1be88, 0x1df46, // 690
            0x1be84, 0x1be82, 0x13ca0, 0x19e58, 0x1cf2e, 0x17da0, 0x13c90, 0x19e4c, 0x17d90, 0x1becc, // 700
            0x19e46, 0x17d88, 0x13c84, 0x17d84, 0x13c82, 0x17d82, 0x11c58, 0x18e2e, 0x13cd8, 0x11c4c, // 710
            0x17dd8, 0x13ccc, 0x11c46, 0x17dcc, 0x13cc6, 0x17dc6, 0x10c2e, 0x11c6e, 0x13cee, 0x17dee, // 720
            0x1be50, 0x1df2c, 0x1be48, 0x1df26, 0x1be44, 0x1be42, 0x13c50, 0x19e2c, 0x17cd0, 0x13c48, // 730
            0x19e26, 0x17cc8, 0x1be66, 0x17cc4, 0x13c42, 0x17cc2, 0x11c2c, 0x13c6c, 0x11c26, 0x17cec, // 740
            0x13c66, 0x17ce6, 0x1be28, 0x1df16, 0x1be24, 0x1be22, 0x13c28, 0x19e16, 0x17c68, 0x13c24, // 750
            0x17c64, 0x13c22, 0x17c62, 0x11c16, 0x13c36, 0x17c76, 0x1be14, 0x1be12, 0x13c14, 0x17c34, // 760
            0x13c12, 0x17c32, 0x102bc, 0x1029e, 0x106b8, 0x1835e, 0x1069c, 0x1068e, 0x1025e, 0x106de, // 770
            0x10eb0, 0x1875c, 0x10e98, 0x1874e, 0x10e8c, 0x10e86, 0x1065c, 0x10edc, 0x1064e, 0x10ece, // 780
            0x11ea0, 0x18f58, 0x1c7ae, 0x11e90, 0x18f4c, 0x11e88, 0x18f46, 0x11e84, 0x11e82, 0x10e58, // 790
            0x1872e, 0x11ed8, 0x18f6e, 0x11ecc, 0x10e46, 0x11ec6, 0x1062e, 0x10e6e, 0x11eee, 0x19f50, // 800
            0x1cfac, 0x19f48, 0x1cfa6, 0x19f44, 0x19f42, 0x11e50, 0x18f2c, 0x13ed0, 0x19f6c, 0x18f26, // 810
            0x13ec8, 0x11e44, 0x13ec4, 0x11e42, 0x13ec2, 0x10e2c, 0x11e6c, 0x10e26, 0x13eec, 0x11e66, // 820
            0x13ee6, 0x1dfa8, 0x1efd6, 0x1dfa4, 0x1dfa2, 0x19f28, 0x1cf96, 0x1bf68, 0x19f24, 0x1bf64, // 830
            0x19f22, 0x1bf62, 0x11e28, 0x18f16, 0x13e68, 0x11e24, 0x17ee8, 0x13e64, 0x11e22, 0x17ee4, // 840
            0x13e62, 0x17ee2, 0x10e16, 0x11e36, 0x13e76, 0x17ef6, 0x1df94, 0x1df92, 0x19f14, 0x1bf34, // 850
            0x19f12, 0x1bf32, 0x11e14, 0x13e34, 0x11e12, 0x17e74, 0x13e32, 0x17e72, 0x1df8a, 0x19f0a, // 860
            0x1bf1a, 0x11e0a, 0x13e1a, 0x17e3a, 0x1035c, 0x1034e, 0x10758, 0x183ae, 0x1074c, 0x10746, // 870
            0x1032e, 0x1076e, 0x10f50, 0x187ac, 0x10f48, 0x187a6, 0x10f44, 0x10f42, 0x1072c, 0x10f6c, // 880
            0x10726, 0x10f66, 0x18fa8, 0x1c7d6, 0x18fa4, 0x18fa2, 0x10f28, 0x18796, 0x11f68, 0x18fb6, // 890
            0x11f64, 0x10f22, 0x11f62, 0x10716, 0x10f36, 0x11f76, 0x1cfd4, 0x1cfd2, 0x18f94, 0x19fb4, // 900
            0x18f92, 0x19fb2, 0x10f14, 0x11f34, 0x10f12, 0x13f74, 0x11f32, 0x13f72, 0x1cfca, 0x18f8a, // 910
            0x19f9a, 0x10f0a, 0x11f1a, 0x13f3a, 0x103ac, 0x103a6, 0x107a8, 0x183d6, 0x107a4, 0x107a2, // 920
            0x10396, 0x107b6, 0x187d4, 0x187d2, 0x10794, 0x10fb4, 0x10792, 0x10fb2, 0x1c7ea)         // 929
    ); // end of $clusters array

    /**
     * Array of factors of the Reed-Solomon polynomial equations used for error correction; one sub array for each correction level (0-8).
     * @protected
     */
    protected $rsfactors = array(
        array(// ECL 0 (2 factors) -------------------------------------------------------------------------------
            0x01b, 0x395), //   2
        array(// ECL 1 (4 factors) -------------------------------------------------------------------------------
            0x20a, 0x238, 0x2d3, 0x329), //   4
        array(// ECL 2 (8 factors) -------------------------------------------------------------------------------
            0x0ed, 0x134, 0x1b4, 0x11c, 0x286, 0x28d, 0x1ac, 0x17b), //   8
        array(// ECL 3 (16 factors) ------------------------------------------------------------------------------
            0x112, 0x232, 0x0e8, 0x2f3, 0x257, 0x20c, 0x321, 0x084, 0x127, 0x074, 0x1ba, 0x1ac, 0x127, 0x02a, 0x0b0, 0x041), //  16
        array(// ECL 4 (32 factors) ------------------------------------------------------------------------------
            0x169, 0x23f, 0x39a, 0x20d, 0x0b0, 0x24a, 0x280, 0x141, 0x218, 0x2e6, 0x2a5, 0x2e6, 0x2af, 0x11c, 0x0c1, 0x205, //  16
            0x111, 0x1ee, 0x107, 0x093, 0x251, 0x320, 0x23b, 0x140, 0x323, 0x085, 0x0e7, 0x186, 0x2ad, 0x14a, 0x03f, 0x19a), //  32
        array(// ECL 5 (64 factors) ------------------------------------------------------------------------------
            0x21b, 0x1a6, 0x006, 0x05d, 0x35e, 0x303, 0x1c5, 0x06a, 0x262, 0x11f, 0x06b, 0x1f9, 0x2dd, 0x36d, 0x17d, 0x264, //  16
            0x2d3, 0x1dc, 0x1ce, 0x0ac, 0x1ae, 0x261, 0x35a, 0x336, 0x21f, 0x178, 0x1ff, 0x190, 0x2a0, 0x2fa, 0x11b, 0x0b8, //  32
            0x1b8, 0x023, 0x207, 0x01f, 0x1cc, 0x252, 0x0e1, 0x217, 0x205, 0x160, 0x25d, 0x09e, 0x28b, 0x0c9, 0x1e8, 0x1f6, //  48
            0x288, 0x2dd, 0x2cd, 0x053, 0x194, 0x061, 0x118, 0x303, 0x348, 0x275, 0x004, 0x17d, 0x34b, 0x26f, 0x108, 0x21f), //  64
        array(// ECL 6 (128 factors) -----------------------------------------------------------------------------
            0x209, 0x136, 0x360, 0x223, 0x35a, 0x244, 0x128, 0x17b, 0x035, 0x30b, 0x381, 0x1bc, 0x190, 0x39d, 0x2ed, 0x19f, //  16
            0x336, 0x05d, 0x0d9, 0x0d0, 0x3a0, 0x0f4, 0x247, 0x26c, 0x0f6, 0x094, 0x1bf, 0x277, 0x124, 0x38c, 0x1ea, 0x2c0, //  32
            0x204, 0x102, 0x1c9, 0x38b, 0x252, 0x2d3, 0x2a2, 0x124, 0x110, 0x060, 0x2ac, 0x1b0, 0x2ae, 0x25e, 0x35c, 0x239, //  48
            0x0c1, 0x0db, 0x081, 0x0ba, 0x0ec, 0x11f, 0x0c0, 0x307, 0x116, 0x0ad, 0x028, 0x17b, 0x2c8, 0x1cf, 0x286, 0x308, //  64
            0x0ab, 0x1eb, 0x129, 0x2fb, 0x09c, 0x2dc, 0x05f, 0x10e, 0x1bf, 0x05a, 0x1fb, 0x030, 0x0e4, 0x335, 0x328, 0x382, //  80
            0x310, 0x297, 0x273, 0x17a, 0x17e, 0x106, 0x17c, 0x25a, 0x2f2, 0x150, 0x059, 0x266, 0x057, 0x1b0, 0x29e, 0x268, //  96
            0x09d, 0x176, 0x0f2, 0x2d6, 0x258, 0x10d, 0x177, 0x382, 0x34d, 0x1c6, 0x162, 0x082, 0x32e, 0x24b, 0x324, 0x022, // 112
            0x0d3, 0x14a, 0x21b, 0x129, 0x33b, 0x361, 0x025, 0x205, 0x342, 0x13b, 0x226, 0x056, 0x321, 0x004, 0x06c, 0x21b), // 128
        array(// ECL 7 (256 factors) -----------------------------------------------------------------------------
            0x20c, 0x37e, 0x04b, 0x2fe, 0x372, 0x359, 0x04a, 0x0cc, 0x052, 0x24a, 0x2c4, 0x0fa, 0x389, 0x312, 0x08a, 0x2d0, //  16
            0x35a, 0x0c2, 0x137, 0x391, 0x113, 0x0be, 0x177, 0x352, 0x1b6, 0x2dd, 0x0c2, 0x118, 0x0c9, 0x118, 0x33c, 0x2f5, //  32
            0x2c6, 0x32e, 0x397, 0x059, 0x044, 0x239, 0x00b, 0x0cc, 0x31c, 0x25d, 0x21c, 0x391, 0x321, 0x2bc, 0x31f, 0x089, //  48
            0x1b7, 0x1a2, 0x250, 0x29c, 0x161, 0x35b, 0x172, 0x2b6, 0x145, 0x0f0, 0x0d8, 0x101, 0x11c, 0x225, 0x0d1, 0x374, //  64
            0x13b, 0x046, 0x149, 0x319, 0x1ea, 0x112, 0x36d, 0x0a2, 0x2ed, 0x32c, 0x2ac, 0x1cd, 0x14e, 0x178, 0x351, 0x209, //  80
            0x133, 0x123, 0x323, 0x2c8, 0x013, 0x166, 0x18f, 0x38c, 0x067, 0x1ff, 0x033, 0x008, 0x205, 0x0e1, 0x121, 0x1d6, //  96
            0x27d, 0x2db, 0x042, 0x0ff, 0x395, 0x10d, 0x1cf, 0x33e, 0x2da, 0x1b1, 0x350, 0x249, 0x088, 0x21a, 0x38a, 0x05a, // 112
            0x002, 0x122, 0x2e7, 0x0c7, 0x28f, 0x387, 0x149, 0x031, 0x322, 0x244, 0x163, 0x24c, 0x0bc, 0x1ce, 0x00a, 0x086, // 128
            0x274, 0x140, 0x1df, 0x082, 0x2e3, 0x047, 0x107, 0x13e, 0x176, 0x259, 0x0c0, 0x25d, 0x08e, 0x2a1, 0x2af, 0x0ea, // 144
            0x2d2, 0x180, 0x0b1, 0x2f0, 0x25f, 0x280, 0x1c7, 0x0c1, 0x2b1, 0x2c3, 0x325, 0x281, 0x030, 0x03c, 0x2dc, 0x26d, // 160
            0x37f, 0x220, 0x105, 0x354, 0x28f, 0x135, 0x2b9, 0x2f3, 0x2f4, 0x03c, 0x0e7, 0x305, 0x1b2, 0x1a5, 0x2d6, 0x210, // 176
            0x1f7, 0x076, 0x031, 0x31b, 0x020, 0x090, 0x1f4, 0x0ee, 0x344, 0x18a, 0x118, 0x236, 0x13f, 0x009, 0x287, 0x226, // 192
            0x049, 0x392, 0x156, 0x07e, 0x020, 0x2a9, 0x14b, 0x318, 0x26c, 0x03c, 0x261, 0x1b9, 0x0b4, 0x317, 0x37d, 0x2f2, // 208
            0x25d, 0x17f, 0x0e4, 0x2ed, 0x2f8, 0x0d5, 0x036, 0x129, 0x086, 0x036, 0x342, 0x12b, 0x39a, 0x0bf, 0x38e, 0x214, // 224
            0x261, 0x33d, 0x0bd, 0x014, 0x0a7, 0x01d, 0x368, 0x1c1, 0x053, 0x192, 0x029, 0x290, 0x1f9, 0x243, 0x1e1, 0x0ad, // 240
            0x194, 0x0fb, 0x2b0, 0x05f, 0x1f1, 0x22b, 0x282, 0x21f, 0x133, 0x09f, 0x39c, 0x22e, 0x288, 0x037, 0x1f1, 0x00a), // 256
        array(// ECL 8 (512 factors) -----------------------------------------------------------------------------
            0x160, 0x04d, 0x175, 0x1f8, 0x023, 0x257, 0x1ac, 0x0cf, 0x199, 0x23e, 0x076, 0x1f2, 0x11d, 0x17c, 0x15e, 0x1ec, //  16
            0x0c5, 0x109, 0x398, 0x09b, 0x392, 0x12b, 0x0e5, 0x283, 0x126, 0x367, 0x132, 0x058, 0x057, 0x0c1, 0x160, 0x30d, //  32
            0x34e, 0x04b, 0x147, 0x208, 0x1b3, 0x21f, 0x0cb, 0x29a, 0x0f9, 0x15a, 0x30d, 0x26d, 0x280, 0x10c, 0x31a, 0x216, //  48
            0x21b, 0x30d, 0x198, 0x186, 0x284, 0x066, 0x1dc, 0x1f3, 0x122, 0x278, 0x221, 0x025, 0x35a, 0x394, 0x228, 0x029, //  64
            0x21e, 0x121, 0x07a, 0x110, 0x17f, 0x320, 0x1e5, 0x062, 0x2f0, 0x1d8, 0x2f9, 0x06b, 0x310, 0x35c, 0x292, 0x2e5, //  80
            0x122, 0x0cc, 0x2a9, 0x197, 0x357, 0x055, 0x063, 0x03e, 0x1e2, 0x0b4, 0x014, 0x129, 0x1c3, 0x251, 0x391, 0x08e, //  96
            0x328, 0x2ac, 0x11f, 0x218, 0x231, 0x04c, 0x28d, 0x383, 0x2d9, 0x237, 0x2e8, 0x186, 0x201, 0x0c0, 0x204, 0x102, // 112
            0x0f0, 0x206, 0x31a, 0x18b, 0x300, 0x350, 0x033, 0x262, 0x180, 0x0a8, 0x0be, 0x33a, 0x148, 0x254, 0x312, 0x12f, // 128
            0x23a, 0x17d, 0x19f, 0x281, 0x09c, 0x0ed, 0x097, 0x1ad, 0x213, 0x0cf, 0x2a4, 0x2c6, 0x059, 0x0a8, 0x130, 0x192, // 144
            0x028, 0x2c4, 0x23f, 0x0a2, 0x360, 0x0e5, 0x041, 0x35d, 0x349, 0x200, 0x0a4, 0x1dd, 0x0dd, 0x05c, 0x166, 0x311, // 160
            0x120, 0x165, 0x352, 0x344, 0x33b, 0x2e0, 0x2c3, 0x05e, 0x008, 0x1ee, 0x072, 0x209, 0x002, 0x1f3, 0x353, 0x21f, // 176
            0x098, 0x2d9, 0x303, 0x05f, 0x0f8, 0x169, 0x242, 0x143, 0x358, 0x31d, 0x121, 0x033, 0x2ac, 0x1d2, 0x215, 0x334, // 192
            0x29d, 0x02d, 0x386, 0x1c4, 0x0a7, 0x156, 0x0f4, 0x0ad, 0x023, 0x1cf, 0x28b, 0x033, 0x2bb, 0x24f, 0x1c4, 0x242, // 208
            0x025, 0x07c, 0x12a, 0x14c, 0x228, 0x02b, 0x1ab, 0x077, 0x296, 0x309, 0x1db, 0x352, 0x2fc, 0x16c, 0x242, 0x38f, // 224
            0x11b, 0x2c7, 0x1d8, 0x1a4, 0x0f5, 0x120, 0x252, 0x18a, 0x1ff, 0x147, 0x24d, 0x309, 0x2bb, 0x2b0, 0x02b, 0x198, // 240
            0x34a, 0x17f, 0x2d1, 0x209, 0x230, 0x284, 0x2ca, 0x22f, 0x03e, 0x091, 0x369, 0x297, 0x2c9, 0x09f, 0x2a0, 0x2d9, // 256
            0x270, 0x03b, 0x0c1, 0x1a1, 0x09e, 0x0d1, 0x233, 0x234, 0x157, 0x2b5, 0x06d, 0x260, 0x233, 0x16d, 0x0b5, 0x304, // 272
            0x2a5, 0x136, 0x0f8, 0x161, 0x2c4, 0x19a, 0x243, 0x366, 0x269, 0x349, 0x278, 0x35c, 0x121, 0x218, 0x023, 0x309, // 288
            0x26a, 0x24a, 0x1a8, 0x341, 0x04d, 0x255, 0x15a, 0x10d, 0x2f5, 0x278, 0x2b7, 0x2ef, 0x14b, 0x0f7, 0x0b8, 0x02d, // 304
            0x313, 0x2a8, 0x012, 0x042, 0x197, 0x171, 0x036, 0x1ec, 0x0e4, 0x265, 0x33e, 0x39a, 0x1b5, 0x207, 0x284, 0x389, // 320
            0x315, 0x1a4, 0x131, 0x1b9, 0x0cf, 0x12c, 0x37c, 0x33b, 0x08d, 0x219, 0x17d, 0x296, 0x201, 0x038, 0x0fc, 0x155, // 336
            0x0f2, 0x31d, 0x346, 0x345, 0x2d0, 0x0e0, 0x133, 0x277, 0x03d, 0x057, 0x230, 0x136, 0x2f4, 0x299, 0x18d, 0x328, // 352
            0x353, 0x135, 0x1d9, 0x31b, 0x17a, 0x01f, 0x287, 0x393, 0x1cb, 0x326, 0x24e, 0x2db, 0x1a9, 0x0d8, 0x224, 0x0f9, // 368
            0x141, 0x371, 0x2bb, 0x217, 0x2a1, 0x30e, 0x0d2, 0x32f, 0x389, 0x12f, 0x34b, 0x39a, 0x119, 0x049, 0x1d5, 0x317, // 384
            0x294, 0x0a2, 0x1f2, 0x134, 0x09b, 0x1a6, 0x38b, 0x331, 0x0bb, 0x03e, 0x010, 0x1a9, 0x217, 0x150, 0x11e, 0x1b5, // 400
            0x177, 0x111, 0x262, 0x128, 0x0b7, 0x39b, 0x074, 0x29b, 0x2ef, 0x161, 0x03e, 0x16e, 0x2b3, 0x17b, 0x2af, 0x34a, // 416
            0x025, 0x165, 0x2d0, 0x2e6, 0x14a, 0x005, 0x027, 0x39b, 0x137, 0x1a8, 0x0f2, 0x2ed, 0x141, 0x036, 0x29d, 0x13c, // 432
            0x156, 0x12b, 0x216, 0x069, 0x29b, 0x1e8, 0x280, 0x2a0, 0x240, 0x21c, 0x13c, 0x1e6, 0x2d1, 0x262, 0x02e, 0x290, // 448
            0x1bf, 0x0ab, 0x268, 0x1d0, 0x0be, 0x213, 0x129, 0x141, 0x2fa, 0x2f0, 0x215, 0x0af, 0x086, 0x00e, 0x17d, 0x1b1, // 464
            0x2cd, 0x02d, 0x06f, 0x014, 0x254, 0x11c, 0x2e0, 0x08a, 0x286, 0x19b, 0x36d, 0x29d, 0x08d, 0x397, 0x02d, 0x30c, // 480
            0x197, 0x0a4, 0x14c, 0x383, 0x0a5, 0x2d6, 0x258, 0x145, 0x1f2, 0x28f, 0x165, 0x2f0, 0x300, 0x0df, 0x351, 0x287, // 496
            0x03f, 0x136, 0x35f, 0x0fb, 0x16e, 0x130, 0x11a, 0x2e2, 0x2a3, 0x19a, 0x185, 0x0f4, 0x01f, 0x079, 0x12f, 0x107) // 512
    );

    /**
     * This is the class constructor.
     * Creates a PDF417 object
     * @param $code (string) code to represent using PDF417
     * @param $ecl (int) error correction level (0-8); default -1 = automatic correction level
     * @param $aspectratio (float) the width to height of the symbol (excluding quiet zones)
     * @param $macro (array) information for macro block
     * @public
     */
    public function __construct($code, $ecl = -1, $aspectratio = 2, $macro = array()) {
        $barcode_array = array();
        if ((is_null($code)) OR ($code == '\0') OR ($code == '')) {
            return false;
        }
        // get the input sequence array
        $sequence = $this->getInputSequences($code);
        $codewords = array(); // array of code-words
        foreach ($sequence as $seq) {
            $cw = $this->getCompaction($seq[0], $seq[1], true);
            $codewords = array_merge($codewords, $cw);
        }
        if ($codewords[0] == 900) {
            // Text Alpha is the default mode, so remove the first code
            array_shift($codewords);
        }
        // count number of codewords
        $numcw = count($codewords);
        if ($numcw > 925) {
            // reached maximum data codeword capacity
            return false;
        }
        // build macro control block codewords
        if (!empty($macro)) {
            $macrocw = array();
            // beginning of macro control block
            $macrocw[] = 928;
            // segment index
            $cw = $this->getCompaction(902, sprintf('%05d', $macro['segment_index']), false);
            $macrocw = array_merge($macrocw, $cw);
            // file ID
            $cw = $this->getCompaction(900, $macro['file_id'], false);
            $macrocw = array_merge($macrocw, $cw);
            // optional fields
            $optmodes = array(900, 902, 902, 900, 900, 902, 902);
            $optsize = array(-1, 2, 4, -1, -1, -1, 2);
            foreach ($optmodes as $k => $omode) {
                if (isset($macro['option_' . $k])) {
                    $macrocw[] = 923;
                    $macrocw[] = $k;
                    if ($optsize[$k] == 2) {
                        $macro['option_' . $k] = sprintf('%05d', $macro['option_' . $k]);
                    } elseif ($optsize[$k] == 4) {
                        $macro['option_' . $k] = sprintf('%010d', $macro['option_' . $k]);
                    }
                    $cw = $this->getCompaction($omode, $macro['option_' . $k], false);
                    $macrocw = array_merge($macrocw, $cw);
                }
            }
            if ($macro['segment_index'] == ($macro['segment_total'] - 1)) {
                // end of control block
                $macrocw[] = 922;
            }
            // update total codewords
            $numcw += count($macrocw);
        }
        // set error correction level
        $ecl = $this->getErrorCorrectionLevel($ecl, $numcw);
        // number of codewords for error correction
        $errsize = (2 << $ecl);
        // calculate number of columns (number of codewords per row) and rows
        $nce = ($numcw + $errsize + 1);
        $cols = round((sqrt(4761 + (68 * $aspectratio * ROWHEIGHT * $nce)) - 69) / 34);
        // adjust cols
        if ($cols < 1) {
            $cols = 1;
        } elseif ($cols > 30) {
            $cols = 30;
        }
        $rows = ceil($nce / $cols);
        $size = ($cols * $rows);
        // adjust rows
        if (($rows < 3) OR ($rows > 90)) {
            if ($rows < 3) {
                $rows = 3;
            } elseif ($rows > 90) {
                $rows = 90;
            }
            $cols = ceil($size / $rows);
            $size = ($cols * $rows);
        }
        if ($size > 928) {
            // set dimensions to get maximum capacity
            if (abs($aspectratio - (17 * 29 / 32)) < abs($aspectratio - (17 * 16 / 58))) {
                $cols = 29;
                $rows = 32;
            } else {
                $cols = 16;
                $rows = 58;
            }
            $size = 928;
        }
        // calculate padding
        $pad = ($size - $nce);
        if ($pad > 0) {
            if (($size - $rows) == $nce) {
                --$rows;
                $size -= $rows;
            } else {
                // add pading
                $codewords = array_merge($codewords, array_fill(0, $pad, 900));
            }
        }
        if (!empty($macro)) {
            // add macro section
            $codewords = array_merge($codewords, $macrocw);
        }
        // Symbol Lenght Descriptor (number of data codewords including Symbol Lenght Descriptor and pad codewords)
        $sld = $size - $errsize;
        // add symbol length description
        array_unshift($codewords, $sld);
        // calculate error correction
        $ecw = $this->getErrorCorrection($codewords, $ecl);
        // add error correction codewords
        $codewords = array_merge($codewords, $ecw);
        // add horizontal quiet zones to start and stop patterns
        $pstart = str_repeat('0', QUIETH) . $this->start_pattern;
        $pstop = $this->stop_pattern . str_repeat('0', QUIETH);
        $barcode_array['num_rows'] = ($rows * ROWHEIGHT) + (2 * QUIETV);
        $barcode_array['num_cols'] = (($cols + 2) * 17) + 35 + (2 * QUIETH);
        $barcode_array['bcode'] = array();
        // build rows for vertical quiet zone
        if (QUIETV > 0) {
            $empty_row = array_fill(0, $barcode_array['num_cols'], 0);
            for ($i = 0; $i < QUIETV; ++$i) {
                // add vertical quiet rows
                $barcode_array['bcode'][] = $empty_row;
            }
        }
        $k = 0; // codeword index
        $cid = 0; // initial cluster
        // for each row
        for ($r = 0; $r < $rows; ++$r) {
            // row start code
            $row = $pstart;
            switch ($cid) {
                case 0: {
                        $L = ((30 * intval($r / 3)) + intval(($rows - 1) / 3));
                        break;
                    }
                case 1: {
                        $L = ((30 * intval($r / 3)) + ($ecl * 3) + (($rows - 1) % 3));
                        break;
                    }
                case 2: {
                        $L = ((30 * intval($r / 3)) + ($cols - 1));
                        break;
                    }
            }
            // left row indicator
            $row .= sprintf('%17b', $this->clusters[$cid][$L]);
            // for each column
            for ($c = 0; $c < $cols; ++$c) {
                $row .= sprintf('%17b', $this->clusters[$cid][$codewords[$k]]);
                ++$k;
            }
            switch ($cid) {
                case 0: {
                        $L = ((30 * intval($r / 3)) + ($cols - 1));
                        break;
                    }
                case 1: {
                        $L = ((30 * intval($r / 3)) + intval(($rows - 1) / 3));
                        break;
                    }
                case 2: {
                        $L = ((30 * intval($r / 3)) + ($ecl * 3) + (($rows - 1) % 3));
                        break;
                    }
            }
            // right row indicator
            $row .= sprintf('%17b', $this->clusters[$cid][$L]);
            // row stop code
            $row .= $pstop;
            // convert the string to array
            $arow = preg_split('//', $row, -1, PREG_SPLIT_NO_EMPTY);
            // duplicate row to get the desired height
            for ($h = 0; $h < ROWHEIGHT; ++$h) {
                $barcode_array['bcode'][] = $arow;
            }
            ++$cid;
            if ($cid > 2) {
                $cid = 0;
            }
        }
        if (QUIETV > 0) {
            for ($i = 0; $i < QUIETV; ++$i) {
                // add vertical quiet rows
                $barcode_array['bcode'][] = $empty_row;
            }
        }
        $this->barcode_array = $barcode_array;
    }

    /**
     * Returns a barcode array which is readable by Dinesh Rabara
     * @return array barcode array readable by Dinesh Rabara;
     * @public
     */
    public function getBarcodeArray() {
        return $this->barcode_array;
    }

    /**
     * Returns the error correction level (0-8) to be used
     * @param $ecl (int) error correction level
     * @param $numcw (int) number of data codewords
     * @return int error correction level
     * @protected
     */
    protected function getErrorCorrectionLevel($ecl, $numcw) {
        // get maximum correction level
        $maxecl = 8; // starting error level
        $maxerrsize = (928 - $numcw); // available codewords for error
        while ($maxecl > 0) {
            $errsize = (2 << $ecl);
            if ($maxerrsize >= $errsize) {
                break;
            }
            --$maxecl;
        }
        // check for automatic levels
        if (($ecl < 0) OR ($ecl > 8)) {
            if ($numcw < 41) {
                $ecl = 2;
            } elseif ($numcw < 161) {
                $ecl = 3;
            } elseif ($numcw < 321) {
                $ecl = 4;
            } elseif ($numcw < 864) {
                $ecl = 5;
            } else {
                $ecl = $maxecl;
            }
        }
        if ($ecl > $maxecl) {
            $ecl = $maxecl;
        }
        return $ecl;
    }

    /**
     * Returns the error correction codewords
     * @param $cw (array) array of codewords including Symbol Lenght Descriptor and pad
     * @param $ecl (int) error correction level 0-8
     * @return array of error correction codewords
     * @protected
     */
    protected function getErrorCorrection($cw, $ecl) {
        // get error correction coefficients
        $ecc = $this->rsfactors[$ecl];
        // number of error correction factors
        $eclsize = (2 << $ecl);
        // maximum index for $rsfactors[$ecl]
        $eclmaxid = ($eclsize - 1);
        // initialize array of error correction codewords
        $ecw = array_fill(0, $eclsize, 0);
        // for each data codeword
        foreach ($cw as $k => $d) {
            $t1 = ($d + $ecw[$eclmaxid]) % 929;
            for ($j = $eclmaxid; $j > 0; --$j) {
                $t2 = ($t1 * $ecc[$j]) % 929;
                $t3 = 929 - $t2;
                $ecw[$j] = ($ecw[($j - 1)] + $t3) % 929;
            }
            $t2 = ($t1 * $ecc[0]) % 929;
            $t3 = 929 - $t2;
            $ecw[0] = $t3 % 929;
        }
        foreach ($ecw as $j => $e) {
            if ($e != 0) {
                $ecw[$j] = 929 - $e;
            }
        }
        $ecw = array_reverse($ecw);
        return $ecw;
    }

    /**
     * Create array of sequences from input
     * @param $code (string) code
     * @return bidimensional array containing characters and classification
     * @protected
     */
    protected function getInputSequences($code) {
        $sequence_array = array(); // array to be returned
        $numseq = array();
        // get numeric sequences
        preg_match_all('/([0-9]{13,})/', $code, $numseq, PREG_OFFSET_CAPTURE);
        $numseq[1][] = array('', strlen($code));
        $offset = 0;
        foreach ($numseq[1] as $seq) {
            $seqlen = strlen($seq[0]);
            if ($seq[1] > 0) {
                // extract text sequence before the number sequence
                $prevseq = substr($code, $offset, ($seq[1] - $offset));
                $textseq = array();
                // get text sequences
                preg_match_all('/([\x09\x0a\x0d\x20-\x7e]{5,})/', $prevseq, $textseq, PREG_OFFSET_CAPTURE);
                $textseq[1][] = array('', strlen($prevseq));
                $txtoffset = 0;
                foreach ($textseq[1] as $txtseq) {
                    $txtseqlen = strlen($txtseq[0]);
                    if ($txtseq[1] > 0) {
                        // extract byte sequence before the text sequence
                        $prevtxtseq = substr($prevseq, $txtoffset, ($txtseq[1] - $txtoffset));
                        if (strlen($prevtxtseq) > 0) {
                            // add BYTE sequence
                            if ((strlen($prevtxtseq) == 1) AND ((count($sequence_array) > 0) AND ($sequence_array[(count($sequence_array) - 1)][0] == 900))) {
                                $sequence_array[] = array(913, $prevtxtseq);
                            } elseif ((strlen($prevtxtseq) % 6) == 0) {
                                $sequence_array[] = array(924, $prevtxtseq);
                            } else {
                                $sequence_array[] = array(901, $prevtxtseq);
                            }
                        }
                    }
                    if ($txtseqlen > 0) {
                        // add numeric sequence
                        $sequence_array[] = array(900, $txtseq[0]);
                    }
                    $txtoffset = $txtseq[1] + $txtseqlen;
                }
            }
            if ($seqlen > 0) {
                // add numeric sequence
                $sequence_array[] = array(902, $seq[0]);
            }
            $offset = $seq[1] + $seqlen;
        }
        return $sequence_array;
    }

    /**
     * Compact data by mode.
     * @param $mode (int) compaction mode number
     * @param $code (string) data to compact
     * @param $addmode (boolean) if true add the mode codeword at first position
     * @return array of codewords
     * @protected
     */
    protected function getCompaction($mode, $code, $addmode = true) {
        $cw = array(); // array of codewords to return
        switch ($mode) {
            case 900: { // Text Compaction mode latch
                    $submode = 0; // default Alpha sub-mode
                    $txtarr = array(); // array of characters and sub-mode switching characters
                    $codelen = strlen($code);
                    for ($i = 0; $i < $codelen; ++$i) {
                        $chval = ord($code{$i});
                        if (($k = array_search($chval, $this->textsubmodes[$submode])) !== false) {
                            // we are on the same sub-mode
                            $txtarr[] = $k;
                        } else {
                            // the sub-mode is changed
                            for ($s = 0; $s < 4; ++$s) {
                                // search new sub-mode
                                if (($s != $submode) AND (($k = array_search($chval, $this->textsubmodes[$s])) !== false)) {
                                    // $s is the new submode
                                    if (((($i + 1) == $codelen) OR ((($i + 1) < $codelen) AND (array_search(ord($code{($i + 1)}), $this->textsubmodes[$submode]) !== false))) AND (($s == 3) OR (($s == 0) AND ($submode == 1)))) {
                                        // shift (temporary change only for this char)
                                        if ($s == 3) {
                                            // shift to puntuaction
                                            $txtarr[] = 29;
                                        } else {
                                            // shift from lower to alpha
                                            $txtarr[] = 27;
                                        }
                                    } else {
                                        // latch
                                        $txtarr = array_merge($txtarr, $this->textlatch['' . $submode . $s]);
                                        // set new submode
                                        $submode = $s;
                                    }
                                    // add characted code to array
                                    $txtarr[] = $k;
                                    break;
                                }
                            }
                        }
                    }
                    $txtarrlen = count($txtarr);
                    if (($txtarrlen % 2) != 0) {
                        // add padding
                        $txtarr[] = 29;
                        ++$txtarrlen;
                    }
                    // calculate codewords
                    for ($i = 0; $i < $txtarrlen; $i += 2) {
                        $cw[] = (30 * $txtarr[$i]) + $txtarr[($i + 1)];
                    }
                    break;
                }
            case 901:
            case 924: { // Byte Compaction mode latch
                    while (($codelen = strlen($code)) > 0) {
                        if ($codelen > 6) {
                            $rest = substr($code, 6);
                            $code = substr($code, 0, 6);
                            $sublen = 6;
                        } else {
                            $rest = '';
                            $sublen = strlen($code);
                        }
                        if ($sublen == 6) {
                            $t = bcmul('' . ord($code{0}), '1099511627776');
                            $t = bcadd($t, bcmul('' . ord($code{1}), '4294967296'));
                            $t = bcadd($t, bcmul('' . ord($code{2}), '16777216'));
                            $t = bcadd($t, bcmul('' . ord($code{3}), '65536'));
                            $t = bcadd($t, bcmul('' . ord($code{4}), '256'));
                            $t = bcadd($t, '' . ord($code{5}));
                            do {
                                $d = bcmod($t, '900');
                                $t = bcdiv($t, '900');
                                array_unshift($cw, $d);
                            } while ($t != '0');
                        } else {
                            for ($i = 0; $i < $sublen; ++$i) {
                                $cw[] = ord($code{$i});
                            }
                        }
                        $code = $rest;
                    }
                    break;
                }
            case 902: { // Numeric Compaction mode latch
                    while (($codelen = strlen($code)) > 0) {
                        if ($codelen > 44) {
                            $rest = substr($code, 44);
                            $code = substr($code, 0, 44);
                        } else {
                            $rest = '';
                        }
                        $t = '1' . $code;
                        do {
                            $d = bcmod($t, '900');
                            $t = bcdiv($t, '900');
                            array_unshift($cw, $d);
                        } while ($t != '0');
                        $code = $rest;
                    }
                    break;
                }
            case 913: { // Byte Compaction mode shift
                    $cw[] = ord($code);
                    break;
                }
        }
        if ($addmode) {
            // add the compaction mode codeword at the beginning
            array_unshift($cw, $mode);
        }
        return $cw;
    }

}

// end PDF417 class

//============================================================+
// END OF FILE
//============================================================+

然后引用PDF417类创建SVG格式二维码

<?php
	include_once dirname(__FILE__).'/../utils/PDF417.php';

	function createPDF417SVG($code,$w = 5,$h = 2,$color = 'black'){
        $barcode = new PDF417($code);
        $barcode_array = $barcode->getBarcodeArray();

        $repstr = array("\0" => '', '&' => '&amp;', '<' => '&lt;', '>' => '&gt;');
        $svg = '<' . '?' . 'xml version="1.0" standalone="no"' . '?' . '>' . "\n";
        $svg .= '<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">' . "\n";
        $svg .= '<svg width="' . round(($barcode_array['num_cols'] * $w), 3) . '" height="' . round(($barcode_array['num_rows'] * $h), 3) . '" version="1.1" xmlns="http://www.w3.org/2000/svg">' . "\n";
        $svg .= "\t" . '<desc>' . strtr($barcode_array['code'], $repstr) . '</desc>' . "\n";
        $svg .= "\t" . '<g id="elements" fill="' . $color . '" stroke="none">' . "\n";
        $y = 0;
        for ($r = 0; $r < $barcode_array['num_rows']; ++$r) {
            $x = 0;
            for ($c = 0; $c < $barcode_array['num_cols']; ++$c) {
                if ($barcode_array['bcode'][$r][$c] == 1) {
                    // draw a single barcode cell
                    $svg .= "\t\t" . '<rect x="' . $x . '" y="' . $y . '" width="' . $w . '" height="' . $h . '" />' . "\n";
                }
                $x += $w;
            }
            $y += $h;
        }
        $svg .= "\t" . '</g>' . "\n";
        $svg .= '</svg>' . "\n";
        return $svg;
    }
    
    header('Content-Type:image/svg+xml');
    echo createPDF417SVG($_GET['text'],$_GET['w'],$_GET['h'],$_GET['color']);
?>

然后通过HTML的img标签的src属性直接带参数引用该PHP即可


PHP PDF417二维条形码

PHP UEditor编辑器(支持传统蒙古文排版)

UEditor编辑器本身没有从上到下从左到右的排版方式,借鉴前辈的经验,对编辑器进行改造,改造后支持传统蒙古文自上而下从左向右的排版方式。本编辑器的原始代码来自github上的开源项目,原发布者在官方版本的基础上增加了OSS、QINIU、COS三种存储方式,本人在此基础上追加了传统蒙古文排版功能。(注:里面的蒙古文哈旺体来自蒙科立),下图为演示示例:蒙古文歌词《美丽的草原我的家》

下载源代码(代码为纯编辑器,不含上图中的文章导入及发布功能,不含数据库,需使用者自己开发)


PHP UEditor编辑器(支持传统蒙古文排版)

PHP FTP类

<?php


class App_Helper_FtpHelper
{
    var $connector;
    var $getback;

    //连接FTP
    function connect($ftp_server, $port, $timeout, $uname, $passwd)
    {
        $this->connector = @ftp_connect($ftp_server, $port, $timeout);
        $this->login_result = @ftp_login($this->connector, "$uname", "$passwd");
        if (!$this->connector) {
            echo "FTP connection has failed! \n";
            echo "Attempted to connect to $ftp_server for user $uname \n";
            die;
        } else if (!$this->login_result) {
            echo "Connected to $ftp_server, for user $uname \n";
        }
    }

    function lastmodtime($value)
    {
        $getback = ftp_mdtm($this->connector, $value);
        return $getback;
    }

    //更改当前目录
    function changedir($targetdir)
    {
        $getback = ftp_chdir($this->connector, $targetdir);
        return $getback;
    }

    //获取当前目录
    function getdir()
    {
        $getback = ftp_pwd($this->connector);
        return $getback;
    }

    //获取文件列表
    function get_file_list($directory)
    {
        $getback = ftp_rawlist($this->connector, $directory);
        return $getback;
    }

    //获取文件
    function get_file($file_to_get, $mode, $mode2)
    {
        $realfile = basename($file_to_get);
        $filename = $realfile;
        $checkdir = @$this->changedir($realfile);
        if ($checkdir == TRUE) {
            ftp_cdup($this->connector);
            echo "\n[DIR] $realfile";
        } else {
            echo "..... " . $realfile . "\n";
            $getback = ftp_get($this->connector, $filename, $realfile, $mode);
            if ($mode2) {
                $delstatus = ftp_delete($this->connector, $file_to_get);
                if ($delstatus == TRUE) {
                    echo "File $realfile on f deleted \n";
                }
            }
        }
        return $getback;
    }

    function put_file($remote,$local){
        ftp_put($this->connector,$remote,$local,FTP_BINARY,0);
        return 'https://sc-qdmgyg-com.oss-cn-beijing.aliyuncs.com'.'/sc/'.$remote;
    }

    function mode($pasvmode)
    {
        $result = ftp_pasv($this->connector, $pasvmode);
    }

    //退出
    function ftp_bye()
    {
        ftp_quit($this->connector);
//        return $getback;
    }
}

PHP FTP类

PHP HTTP类

<?php

class Libs_Http_Client {

    private static $boundary = '';

    public static function get($url, $params = array(), $headers = array(), $misc = array(), $cookie='') {
        if (!empty($params)) {
            $url = $url . '?' . http_build_query($params);
        }
        return self::http($url, 'GET', null, $headers, $misc, $cookie);
    }

    public static function post($url, $params, $files = array(), $headers = array(), $misc = array()) {
        if (!$files) {
            if (is_array($params) || is_object($params)) {
                $body = http_build_query($params);
            } else {
                $body = $params;
            }
        } else {
            $body = self::build_http_query_multi($params, $files);
            $headers[] = "Content-Type: multipart/form-data; boundary=" . self::$boundary;
        }
        return self::http($url, 'POST', $body, $headers, $misc);
    }

    public static function postFiles($url, $files, $params = array(), $headers = array(), $misc = array()) {
        if (!is_array($files)) {
            return false;
        }

        foreach ($files as $key => &$val) {
            $val = '@'.$val;
        }
        $body = array_merge($files, $params);
        $headers[] = "Content-Type: multipart/form-data";

        return self::http($url, 'POST', $body, $headers, $misc);
    }

    public static function getFiles($url, $files, $params = array(), $headers = array(), $misc = array()) {
        if (!is_array($files)) {
            return false;
        }

        foreach ($files as $key => &$val) {
            $val = '@'.$val;
        }
        $body = array_merge($files, $params);
        $headers[] = "Content-Type: multipart/form-data";

        return self::http($url, 'GET', $body, $headers, $misc);
    }


    /**
     * Make an HTTP request
     *
     * @return string API results
     * @ignore
     */
    private static function http($url, $method, $postfields = NULL, $headers = array(), $misc = array(), $cookie='') {
        $ci = curl_init();
        /* Curl settings */
        curl_setopt($ci, CURLOPT_USERAGENT, 'Tdot Plum Client v0.1');       //HTTP头部user agent
        curl_setopt($ci, CURLOPT_CONNECTTIMEOUT, 30);                       //连接超时时间,单位秒
        curl_setopt($ci, CURLOPT_TIMEOUT, 30);                              //最大执行时间,单位秒
        curl_setopt($ci, CURLOPT_RETURNTRANSFER, TRUE);                     //避免直接输出返回值
        curl_setopt($ci, CURLOPT_ENCODING, "");                             //可接受编码类型,空串支持所有类型
        curl_setopt($ci, CURLOPT_SSL_VERIFYPEER, false);
        curl_setopt($ci, CURLOPT_SSL_VERIFYHOST, 2);
        //curl_setopt($ci, CURLOPT_HEADERFUNCTION, array($this, 'getHeader'));
        curl_setopt($ci, CURLOPT_HEADER, FALSE);

        switch ($method) {
            case 'POST':
                curl_setopt($ci, CURLOPT_POST, TRUE);
                if (!empty($postfields)) {
                    curl_setopt($ci, CURLOPT_POSTFIELDS, $postfields);
                }
                break;
        }

        foreach ($misc as $key => $val) {
            $key    = strtoupper($key);
            switch ($key) {
                case 'REFERER' :
                    curl_setopt($ci, CURLOPT_REFERER, $val);
                    break;
            }
        }

        curl_setopt($ci, CURLOPT_URL, $url);
        curl_setopt($ci, CURLOPT_HTTPHEADER, $headers);
        if($cookie){
            curl_setopt ($ci, CURLOPT_COOKIE , $cookie );
        }
        curl_setopt($ci, CURLINFO_HEADER_OUT, TRUE);

        $response = curl_exec($ci);
        $httpCode = curl_getinfo($ci, CURLINFO_HTTP_CODE);
        $httpInfo = curl_getinfo($ci);
        curl_close ($ci);
        return $response;
    }

    /**
     * 发送文件时使用
     * @param array $params
     * @param array $files
     * @return string
     */
    private static function build_http_query_multi($params, $files) {
        //if (!$params) return '';

        self::$boundary = $boundary = uniqid('------------------');
        $MPboundary = '--'.$boundary;
        $endMPboundary = $MPboundary. '--';
        $multipartbody = '';

        foreach ($params as $key => $value) {
            $multipartbody .= $MPboundary . "\r\n";
            $multipartbody .= 'content-disposition: form-data; name="' . $key . "\"\r\n\r\n";
            $multipartbody .= $value."\r\n";
        }
        foreach ($files as $key => $value) {
            if (!$value) {continue;}

            if (is_array($value)) {
                $url = $value['url'];
                if (isset($value['name'])) {
                    $filename = $value['name'];
                } else {
                    $parts = explode( '?', basename($value['url']));
                    $filename = $parts[0];
                }
                $field = isset($value['field']) ? $value['field'] : $key;
            } else {
                $url = $value;
                $parts = explode( '?', basename($url));
                $filename = $parts[0];
                $field = $key;
            }
            $content = file_get_contents($url);

            $multipartbody .= $MPboundary . "\r\n";
            $multipartbody .= 'Content-Disposition: form-data; name="' . $field . '"; filename="' . $filename . '"'. "\r\n";
            $multipartbody .= "Content-Type: image/unknown\r\n\r\n";
            $multipartbody .= $content. "\r\n";
        }

        $multipartbody .= $endMPboundary;
        return $multipartbody;
    }
}

PHP HTTP类

PHP微信小程序获取用户手机号

<?php
/*获取access_token,不能用于获取用户信息的token*/
    function getAccessToken()
    {
        $appid = 'AppId';
        $secret = 'AppSecret';

        $url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=".$appid."&secret=".$secret."";

        $ch = curl_init();
        curl_setopt($ch,CURLOPT_URL,$url);
        curl_setopt($ch,CURLOPT_HEADER,0);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1 );
        curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 10);
        $res = curl_exec($ch);
        curl_close($ch);
        return $res;
        exit();
    }
    //图片合法性验证
    function http_request($url, $data = null)
    {
        $curl = curl_init();
        curl_setopt($curl, CURLOPT_URL, $url);
        curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, FALSE);
        curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, FALSE);

        if (!empty($data)) {
            curl_setopt($curl, CURLOPT_POST, TRUE);
            curl_setopt($curl, CURLOPT_POSTFIELDS,$data);
            curl_setopt($curl, CURLOPT_HTTPHEADER, array(
                'Content-Type: application/json'
            ));
        }
        curl_setopt($curl, CURLOPT_RETURNTRANSFER, TRUE);
        $output = curl_exec($curl);
        curl_close($curl);

        return $output;
        exit();

    }
    //  获取手机号
    function getPhoneNumber(){
        $tmp = getAccessToken();
        $tmptoken = json_decode($tmp);
        $token = $tmptoken->access_token;
        $data['code'] = $_GET['code'];//前端获取code

        $url = "https://api.weixin.qq.com/wxa/business/getuserphonenumber?access_token=$token";
        $info = http_request($url,json_encode($data),'json');
        // 一定要注意转json,否则汇报47001错误
        $tmpinfo = json_decode($info);

        $code = $tmpinfo->errcode;
        $phone_info = $tmpinfo->phone_info;
        //手机号
        $phoneNumber = $phone_info->phoneNumber;
        if($code == '0'){
            echo json_encode(['code'=>1,'msg'=>'请求成功','phoneNumber'=>$phoneNumber]);
            die();
        }else{
            echo json_encode(['code'=>2,'msg'=>'请求失败']);
            die();
        }

    }

   	getPhoneNumber();
?>

PHP微信小程序获取用户手机号