• 代码收藏系列--php--生成简短唯一订单号(转载)


    代码收藏系列--php--生成简短唯一订单号

    复制代码
    /**
     * 生成商家交易单号
     * <br />特点:不重复
     * <br />示例:
     * <br />普通付款:array('shop_id'=>1,'product_id'=>array(1,2,3), 'user_id'=>1, 'ip'=>'127.0.0.1', 'amount'=>0.01, 'timestamp'=>'2017-06-22 18:02:33', 'sign_key'=>'signkey!@#123_') 结果为: ib1bd7s9bc50c787114b195e7
     * <br />合并付款:generate_trade_no(array('shop_id'=>1,'product_id'=>array(1,2,3), 'user_id'=>1, 'ip'=>'127.0.0.1', 'amount'=>0.01, 'timestamp'=>'2017-06-22 18:02:33', 'sign_key'=>'signkey!@#123_')) 结果为:ib1bd7rs5c50c787114b195e7
     * @param array $data 
     * @return string 返回30或25位位字符串,格式为: 时间{年月日时分秒,14位}+md5{16位}=30位, 例如: 20170622180940c50c787114b195e7 或 ib1bd7s9bc50c787114b195e7
     */
    function generate_trade_no(array $data, $ziptime = true) {
        ksort($data); // 根据数组的键值对数组重新排序    
        $hashtext = md5(json_encode($data)); // 把数组格式化为JSON字符串并生成MD5签名
        $time = date('YmdHis');
        if ($ziptime) {
            $time = base_convert($time, 10, 32); // 使用32进制将14位时间戳压缩到9位32进制值
        }
        $trade_no = $time . substr($hashtext, 8, 16); // 把MD5签名截取16位, 并在签名加上14位或9位日期时间戳, 组成30位或25位字符串
        return $trade_no;
    }
    
    /**
     * php生成32进制8位字符,减轻数据库唯一字段
     * <br />背景:
     * <br />一般在数据库里唯一字段我们用AUTO_ID或者CRC32或者MD5
     * <br />AUTO_ID    10进制根据数据列长度,一般是初学者用,应为在高级应用里不灵活
     * <br />CRC32 16进制8位,很直观,但是重复几率要比 MD5高,
     * <br />MD5   16进制32位,不直观,太占数据库唯一字段,数据选择压力大。
     * <br />最近2天一直在研究如何PHP做一个既有MD5的唯一能力又减少位数用在数据库开发里
     * <br />想到压缩MD5为32进制8位,下面是函数,希望大家测试或者给点意见,或者有更灵活的方法
     * <br />see: http://www.myexception.cn/database/832012.html
     * <br />示例:only('a') 结果是: H1N29LQ1
     * @param string $instr
     * @return string 返回8位字符串
     */
    function only($instr) {
        $instr = md5($instr, true);
        $dict = '0123456789ABCDEFGHIJKLMNOPQRSTUV';
        $outstr = '';
        for ($i = 0; $i < 8; $i++) {
            $ord = ord($instr[$i]);
            $outstr .= $dict[( $ord ^ ord($instr[$i + 8]) ) - $ord & 0x1F];
        }
        return $outstr;
    }
    
    /**
     * 把12位时间数值压缩成8-9位字母+数字组合字符串
     * <br />重点是加上用户编号后将永不重复!
     * <br />用途:订单号、交易号、唯一号
     * <br />如:
     * <br />timeserialize(date('y-m-d-H-i-s')), 结果是:RGXO3128
     * <br />timeserialize('17-12-31-23-59-59'), 结果是:RM31X5959
     * <br />timeserialize('50-12-31-23-59-59'), 结果是:2M31X5959
     * <br />timeserialize('0-0-0-0-0-0'), 结果是:AAAAAA
     * <br />timeserialize('99-99-99-99-99-99'), 结果是:99999999999999
     * @return string 返回8-9位字母+数字组合字符串
     * @since VER:1.0; DATE:2016-1-21; AUTHOR:SoChishun; EMAIL:14507247@qq.com; DESC:Added.
     */
    function timeserialize($time = '') {
        if (!$time) {
            $time = date('y-m-d-H-i-s');
        }
        echo '<div>', $time, '</div>';
        $atime = explode('-', $time);
        $outstr = '';
        // ASCII表:48(0)-57(9), 65(A)-90(Z), 97(a)-122(z)
        // 有效压缩范围:0-25, 48-57
        foreach ($atime as $stime) {
            $itime = $stime * 1;
            echo $itime, ',';
            // 如果数值小于26,则转换成ASCII表的字母,这样可以把两位的数值变成一位字母
            if ($itime < 26) {
                // 65(A)-90(Z)
                $outstr .= chr(65 + $itime);
                continue;
            }
            // 48(0)-57(9)
            // 如果数值在48-57之间,则转换成ASCII表的数字,把两位数转变为1数字
            if ($itime >= 48 && $itime <= 57) {
                $outstr .= chr($stime);
                continue;
            }
            $outstr .= $stime;
        }
        return $outstr;
    }
    复制代码

    版权声明:本文采用署名-非商业性使用-相同方式共享(CC BY-NC-SA 3.0 CN)国际许可协议进行许可,转载请注明作者及出处。
    本文标题:代码收藏系列--php技巧--生成简短唯一订单号
    本文链接:http://www.cnblogs.com/sochishun/p/7070365.html
    本文作者:SoChishun (邮箱:14507247#qq.com | 博客:http://www.cnblogs.com/sochishun/)
    发表日期:2017年6月23日

  • 相关阅读:
    2019 Multi-University Training Contest 1
    2019江西省省赛
    2019牛客暑期多校训练营 第二场
    母函数
    树形DP
    蓝桥杯-标题:打印图形
    蓝桥杯-标题:史丰收速算
    蓝桥杯-标题:切面条
    蓝桥杯-标题:李白打酒
    蓝桥杯-标题:啤酒和饮料
  • 原文地址:https://www.cnblogs.com/hao987/p/8593805.html
Copyright © 2020-2023  润新知