PHP生成唯一会员卡号

我们将0-Z(0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ)分别代表数值0-35,如字母Z代表35。这样的话我要得到一个5位的编号,最大信息量就是36的5次方了,36^5 = 60466176,即最大的5位编号相当于10进制的数字:60466176。

本文中为了做演示,我们假定某俱乐部发放一批10位的会员卡号,会员卡号由3位城市编号+5位卡号编码+2位校验码组成。城市编号用区号表示,如755代表深圳,5位卡编号则由36进制的卡编号组成,后面两位校验码则是通过一定的算法生成的,校验码的用处是可以验证卡号的合法性。这样的话,我们生成的10位卡号相当于最大能满足6000多万会员卡号,并且是不重复唯一的卡号。

PHP

我们使用PHP进行进制转换,10进制转36进制。

class Code {
    //密码字典
    private $dic = array(
        0=>‘0‘,    1=>‘1‘, 2=>‘2‘, 3=>‘3‘, 4=>‘4‘, 5=>‘5‘, 6=>‘6‘, 7=>‘7‘, 8=>‘8‘,
        9=>‘9‘, 10=>‘A‘,  11=>‘B‘, 12=>‘C‘, 13=>‘D‘, 14=>‘E‘, 15=>‘F‘,  16=>‘G‘,  17=>‘H‘,
        18=>‘I‘,19=>‘J‘,  20=>‘K‘, 21=>‘L‘,  22=>‘M‘,  23=>‘N‘, 24=>‘O‘, 25=>‘P‘, 26=>‘Q‘,
    27=>‘R‘,28=>‘S‘,  29=>‘T‘,  30=>‘U‘, 31=>‘V‘,  32=>‘W‘,  33=>‘X‘, 34=>‘Y‘, 35=>‘Z‘
    ); 

    public function encodeID($int, $format=8) {
        $dics = $this->dic;
        $dnum = 36; //进制数
        $arr = array ();
        $loop = true;
        while ($loop) {
            $arr[] = $dics[bcmod($int, $dnum)];
            $int = bcdiv($int, $dnum, 0);
            if ($int == ‘0‘) {
                $loop = false;
            }
        }
        if (count($arr) < $format)
            $arr = array_pad($arr, $format, $dics[0]); 

        return implode(‘‘, array_reverse($arr));
    } 

    public function decodeID($ids) {
        $dics = $this->dic;
        $dnum = 36; //进制数
        //键值交换
        $dedic = array_flip($dics);
        //去零
        $id = ltrim($ids, $dics[0]);
        //反转
        $id = strrev($id);
        $v = 0;
        for ($i = 0, $j = strlen($id); $i < $j; $i++) {
            $v = bcadd(bcmul($dedic[$id {
                $i }
            ], bcpow($dnum, $i, 0), 0), $v, 0);
        }
        return $v;
    } 

}
 

我们定义Code类,先定义密码字典,即0-Z分别对应的数值,方法encodeID($int, $format)中参数$int表示数字,$format表示位数长度,比方encodeID(123456789,5)表示将数字123456789转换成5位的36进制编号,而方法decodeID($ids)用于将36进制的编号转换成10进制的编号。

我们可以这样来生成卡号:

$code = new Code();
$card_no = $code->encodeID(888888,5); 

如上,我们就可以得到一个5位的卡编号,它实际代表着卡号是888888(6个8)的会员编号,而实际进行转换后是5位编号:0J1VC。

接着,我们将城市编号和校验码加上,城市编号是已经定义好的,校验码则通过一定的算法取得,本例中,我们使用简单的算法:将前三位城市编号和五位卡编号进行md5加密,然后取md5值的前2位作为校验码,这样就得到了编号后面的两位校验码。

$card_pre = ‘755‘;
$card_vc = substr(md5($card_pre.$card_no),0,2);
$card_vc = strtoupper($card_vc);
echo $card_pre.$card_no.$card_vc; 

实际应用中,可以通过数据库得到10进制的编号,保证编号唯一,再将上述代码组合,最终生成一个10位的不重复的会员卡号。



声明:本文为原创文章,helloweba.com和作者拥有版权,如需转载,请注明来源于helloweba.com并保留原文链接:http://www.helloweba.com/view-blog-259.html

时间: 2024-10-15 16:00:10

PHP生成唯一会员卡号的相关文章

php生成唯一订单号

支持更改长度/** * 生成唯一订单号 * */ function build_order_no(){ return date('Ymd').substr(implode(NULL, array_map('ord', str_split(substr(uniqid(), 7, 13), 1))), 0, 8); }

如何生成唯一订单号(转)

首先,订单号有3个性质:1.唯一性 2.不可推测性 3.效率性 唯一性和不可推测性不用说了,效率性是指不能频繁的去数据库查询以避免重复.况且满足这些条件的同时订单号还要足够的短.我在java下定制的订单号生成方式如下:int r1=(int)(Math.random()*(10));//产生2个0-9的随机数int r2=(int)(Math.random()*(10));long now = System.currentTimeMillis();//一个13位的时间戳String paymen

c# asp.net 生成唯一订单号

c# asp.net 生成唯一订单号 string OrderNo = DateTime.Now.Year.ToString().Substring(2, 2) + DateTime.Now.Month.ToString().PadLeft(2, '0') + DateTime.Now.Day.ToString().PadLeft(2, '0') + DateTime.Now.Hour.ToString().PadLeft(2, '0') + DateTime.Now.Minute.ToStri

C# 生成唯一订单号

根据GUID+DateTime.Now.Ticks生产唯一订单号 1 /// <summary> 2 /// 生成唯一数 3 /// </summary> 4 public class UniqueData 5 { 6 private static object obj = new object(); 7 private static int GuidInt { get { return Guid.NewGuid().GetHashCode(); } } 8 private sta

用SQL存储过程生成唯一单据号

在一些系统中,经理要生成单据号,为了不使多台客户端生成的单据号重复,一般要在服务端生成这种流水号,本文是在数据库中生成流水号,并且可以生成多种类型的单据号(比如销售单据号,盘点单据号,进货单据号等),利用数据库锁的原理,先看一下SQL语句: CREATE PROC [dbo].[getlsh]     @lx VARCHAR(6) ,     @lsh VARCHAR(30) OUTPUT AS     BEGIN  --启动事务处理         [email protected]_poin

mysql使用触发器生成唯一订单号,

需求:订单号唯一,并且期望是时间格式加其他字符串, 实现:采用触发机制,在新增时根据新增id值加1作为订单生成的随机且确定唯一的数,因为id唯一: 遇到问题:新增时不能提前知道id值, 解决:取到当前表中最大值+1即为id: 业务需要研究几个小时终于实现一套可行方案: 代码: 建表 DROP TABLE IF EXISTS `qs_test`; CREATE TABLE `qs_test` ( `id` int(10) UNSIGNED NOT NULL AUTO_INCREMENT, `ord

生成唯一订单号 (支持每秒1000个并发)

#region 订单号生成(支持每秒1000个并发) private static object locker = new object(); private static int sn = 0; public static string GetOrderNO() { lock (locker) { if (sn == 999) sn = 0; else sn++; return DateTime.Now.ToString("yyMMddHHmmssfff") + sn.ToStrin

MySQL使用过程存储生成唯一订单号

数据库表: /* Navicat MySQL Data Transfer Source Server : local Source Server Version : 50640 Source Host : localhost:3306 Source Database : springsecurity Target Server Type : MYSQL Target Server Version : 50640 File Encoding : 65001 Date: 2018-08-25 22:

两个PHP方面的东西,超过2038的时间和唯一订单号算法

2014年10月01日  php开发 1条评论 阅读264次 DateTime::format 被设计成不受外部设置影响(面向对象就应该如此)所以无论你如何改变环境参数 date_default_timezone ,都不会影响输出结果要想改变 DateTime::format 的时区设置,需要向 DateTime::setTimezone 传入一个时区对象 DateTimeZone 1 $d = new DateTime('@2444486400'); 2 $d->setTimezone(new