cxgj/models/UniqueOrderNo.php
2023-11-27 09:45:13 +08:00

177 lines
5.3 KiB
PHP
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?php
/**
* @author Any
* @description KISS
* @date 2021年6月9日
* @version 1.0.0
*
* _____LOG_____
*
*/
namespace app\models;
use app\components\FlashStorage;
class UniqueOrderNo
{
const ORDER_TYPE_DEFAULT = '000';
const ORDER_TYPE_CASH_USER_WALLET = '010';
const ORDER_TYPE_TRANSFER = '020';
const ORDER_TYPE_PAYMENT_ORDER_UNION = '030';
const ORDER_TYPE_PAYMENT_ORDER = '031';
const ORDER_TYPE_MANUAL_RECHARGE_ORDER = '108';
const ORDER_TYPE_MANUAL_RECHARGE_INTEGRAL_ORDER = '208';
const ORDER_TYPE_INTEGRAL_MALL_ORDER = '300';
const ORDER_TYPE_BINDING_CARD_ORDER = '701'; //此值在商户侧唯一用于【4.7分账接收方进件查询】查询申请单的信息
const ORDER_TYPE_PS_MER_ORDER = '702'; //商户分账单号
const ORDER_TYPE_BOOK_BOX = '801'; //预定包厢
const ORDER_TYPE_AUTO_RECHARGE_ORDER = '109'; //充值订单
const ORDER_TYPE_GOODS = '802'; //商品订单
/**
* 根据订单号获取订单类型Key
* @param string $order_no 订单号
*/
public static function getOrderTypeByOrderNo($order_no)
{
if (empty($order_no) || strlen($order_no) < 19)
return 0;
$order_type = substr($order_no, 14, 3);
switch ($order_type) {
case "010":
return 1;
break;
case "020":
return 2;
case "108":
return 10;
case "109":
return 11;
break;
case "208":
return 12;
case "300":
return 13;
case "601":
return 16;
case "602":
return 21;
case "603":
return 22;
case "604":
return 18;
case "701":
return 17;
case "801":
return 33;
case "802":
return 19;
break;
//@TODO 其他
default:
return 0;
}
}
public static function orderTypeLabels()
{
return [
'1' => '钱包提现',
'2' => '平台转账',
'10' => '余额充值',
'11' => '余额充值',
'12' => '积分充值',
'13' => '积分兑换',
'16' => '球杆检测',
'21' => '球杆检测',
'22' => '球杆检测',
'33' => '预定包厢',
'19' => '商品下单',
'99' => '店长入账记录',
];
}
public static function getOrderType($type)
{
$labels = self::orderTypeLabels();
return isset($labels[$type]) ? $labels[$type] : "未知";
}
/**
* 生成唯一订单号YYYYMMDDHHIISS+订单类型+随机数+校验码2位
* @param string $order_type 订单类型,识别码三位数字
* @param Model $class Model
* @param integer $len 订单号长度最小值为20
* retrun string|null
* throw Exception
*/
public static function generate($order_type, $class = null, $len = 24, $retry = 1, $retry_max = 3, $unique_field = 'order_no')
{
$cache_key = "u_o_n_g_{$order_type}";
$cache_val = FlashStorage::getCache($cache_key);
if ($cache_val !== false) {
sleep(1);
$retry += 1;
return $retry <= $retry_max ? self::generate($order_type, $class, $len, $retry, $retry_max, $unique_field) : null;
}
FlashStorage::setCache($cache_key, $cache_key);
$order_no = null;
if ($class == null) {
$order_no = self::_generate($order_type, $len);
FlashStorage::deleteCache($cache_key);
return $order_no;
}
if (!class_exists($class)) {
throw new \Exception("{$class}不存在");
}
while (true) {
$order_no = self::_generate($order_type, $len);
$exists = $class::find()->where([$unique_field => $order_no])->exists();
if (!$exists) {
FlashStorage::deleteCache($cache_key);
break;
}
}
return $order_no;
}
public static function _generate($order_type, $len = 32)
{
$order_no_main = date('YmdHis', time()) . $order_type;
$rand_str_len = $len - strlen($order_no_main) - 2;
$rand_str = "";
if ($rand_str_len > 0) {
$rand_min = pow(10, $rand_str_len - 1);
$rand_max = pow(10, $rand_str_len) - 1;
$rand_str = mt_rand($rand_min, $rand_max);
}
$order_no_main .= $rand_str;
$order_no_mian_len = strlen($order_no_main);
$order_no_main_sum = 0;
for ($i = 0; $i < $order_no_mian_len; $i++) {
$order_no_main_sum += (int)(substr($order_no_main, $i, 1));
}
$order_no = $order_no_main . str_pad((100 - $order_no_main_sum % 100) % 100, 2, '0', STR_PAD_LEFT);
//并发情况生成唯一订单号
$cache_key = "u_o_n_g_{$order_type}_{$order_no}";
$cache_val = FlashStorage::getCache($cache_key);
if ($cache_val !== false) {
usleep(500);
return self::_generate($order_type, $len);
}
FlashStorage::setCache($cache_key, $cache_key, 60);
return $order_no;
}
}