/** * 生成商家交易單號 * <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)國際許可協議進行許可,轉載請註明做者及出處。 |