*/
class FeiEYunService extends Service
{
const IP = 'https://api.feieyun.cn'; //接口IP或域名
const PORT = 80; // 接口IP端口
const PATH = '/Api/Open/'; //接口路径
protected $user;
protected $uKey;
protected $sn;
protected $printNum;
/**
* @param FeiE $config
*/
public function initConfig(FeiE $config)
{
$this->user = $config->user;
$this->uKey = $config->ukey;
$this->sn = $config->sn;
$this->printNum = $config->print_num;
parent::init();
}
/**
* @param $content
* @param int $times
* @param FeiE|array $config
*/
public function print($content, $config = [])
{
if (!empty($config)) {
$this->initConfig($config);
}
// 格式化内容
$content = $this->formattedContent($content);
$time = time(); // 请求时间
$msgInfo = [
'user' => $this->user,
'stime' => $time,
'sig' => $this->signature($time),
'apiname' => 'Open_printMsg',
'sn' => $this->sn,
'content' => $content,
'times' => $this->printNum // 打印次数
];
$curl = new Curl();
$result = $curl->setHeaders([
'Content-Type' => 'application/x-www-form-urlencoded',
])->setPostParams($msgInfo)->post(self::IP . self::PATH);
$result = Json::decode($result);
if ($result['ret'] != 0) {
throw new UnprocessableEntityHttpException($result['msg']);
}
return $result['data'];
}
/**
* @param $data
* @return string
* @throws \yii\base\InvalidConfigException
*/
protected function formattedContent($data)
{
if (!is_array($data)) {
return $data;
}
$content = "****** {$data['title']} ******" . "
";
$content .= str_repeat('.', 32) . "
";
$content .= "---{$data['payType']}---" . "
";
// $content .= "{$data['merchantTitle']}";
$content .= "打印时间:" . Yii::$app->formatter->asDatetime(time()) . "
";
$content .= "下单时间:" . $data['orderTime'] . "
";
$content .= str_repeat('*', 13) . " 商品 " . str_repeat("*", 13) . "
";
$content .= $this->composing($data['products']);
$content .= "商品总价:¥{$data['productOriginalMoney']}
";
foreach ($data['marketingDetails'] as $marketingDetail) {
$content .= "{$marketingDetail['marketing_name']}:-¥{$marketingDetail['discount_money']}
";
}
$data['pointMoney'] > 0 && $content .= "积分抵扣:-¥{$data['pointMoney']}
";
$data['taxMoney'] > 0 && $content .= "发票税额:-¥{$data['taxMoney']}
";
$content .= "配送费:¥{$data['shippingMoney']}
";
$content .= "应付金额:¥{$data['payMoney']}
";
$content .= str_repeat('.', 32) . "
";
$content .= "昵称: " . $data['nickname'] . "
";
isset($data['receiverName']) && $content .= "客户: " . $data['receiverName'] . "
";
isset($data['receiverMobile']) && $content .= "电话: " . StringHelper::hideStr($data['receiverMobile'],
3) . "
";
isset($data['receiverAddress']) && $content .= "地址: " . $data['receiverRegionName'] . $data['receiverAddress'] . "
";
isset($data['buyerMessage']) && $content .= "备注: " . !empty($data['buyerMessage']) ? $data['buyerMessage'] : '无' . "
";
if (!empty($data['qr'])) {
$content .= str_repeat('.', 32) . "
";
$content .= "二维码" . "
";
$content .= "{$data['qr']}" . "
";
} else {
$content .= str_repeat('.', 32) . "
";
$content .= "二维码" . "
";
$content .= "{$data['orderSn']}" . "
";
}
$content .= str_repeat('.', 32) . "
";
$content .= "订单号" . "
";
$content .= $this->barCode($data['orderSn']) . "
";
$content .= "****** 完 ******" . "
";
return $content;
}
/**
*
* @param $products
* @param int $A 名称
* @param int $B 单价
* @param int $C 数量
* @param int $D 金额
* @return string
*/
protected function composing($products, $A = 14, $B = 6, $C = 3, $D = 6)
{
$orderInfo = '商品名称 数量 金额
';
$orderInfo .= '--------------------------------
';
foreach ($products as $k5 => $v5) {
$name = $v5['title'];
// $price = $v5['price'];
$price = '';
$num = $v5['num'];
$prices = $v5['price'];
$kw3 = '';
$kw1 = '';
$kw2 = '';
$kw4 = '';
$str = $name;
$blankNum = $A;//名称控制为14个字节
$lan = mb_strlen($str, 'utf-8');
$m = 0;
$j = 1;
$blankNum++;
$result = array();
if (strlen($price) < $B) {
$k1 = $B - strlen($price);
for ($q = 0; $q < $k1; $q++) {
$kw1 .= ' ';
}
$price = $price . $kw1;
}
if (strlen($num) < $C) {
$k2 = $C - strlen($num);
for ($q = 0; $q < $k2; $q++) {
$kw2 .= ' ';
}
$num = $num . $kw2;
}
if (strlen($prices) < $D) {
$k3 = $D - strlen($prices);
for ($q = 0; $q < $k3; $q++) {
$kw4 .= ' ';
}
$prices = $prices . $kw4;
}
for ($i = 0; $i < $lan; $i++) {
$new = mb_substr($str, $m, $j, 'utf-8');
$j++;
if (mb_strwidth($new, 'utf-8') < $blankNum) {
if ($m + $j > $lan) {
$m = $m + $j;
$tail = $new;
$lenght = iconv("UTF-8", "GBK//IGNORE", $new);
$k = $A - strlen($lenght);
for ($q = 0; $q < $k; $q++) {
$kw3 .= ' ';
}
if ($m == $j) {
$tail .= $kw3 . ' ' . $price . ' ' . $num . ' ' . $prices;
} else {
$tail .= $kw3 . '
';
}
break;
} else {
$next_new = mb_substr($str, $m, $j, 'utf-8');
if (mb_strwidth($next_new, 'utf-8') < $blankNum) {
continue;
} else {
$m = $i + 1;
$result[] = $new;
$j = 1;
}
}
}
}
$head = '';
foreach ($result as $key => $value) {
if ($key < 1) {
$v_lenght = iconv("UTF-8", "GBK//IGNORE", $value);
$v_lenght = strlen($v_lenght);
if ($v_lenght == 13) {
$value = $value . " ";
}
$head .= $value . ' ' . $price . ' ' . $num . ' ' . $prices;
} else {
$head .= $value . '
';
}
}
$orderInfo .= $head . $tail;
}
$orderInfo .= '--------------------------------
';
return $orderInfo;
}
/**
* 飞鹅技术支持-2020-03-25
* #########################################################################################################
* 一,纯数字条件下:
* 58mm打印机最大支持28位纯数字,80mm打印机最大支持46位纯数字,超出无效
*
* 26-28位数字条形码,在数字中不可以出现2个及以上连续的0存在
* 23-25位数字条形码,在数字中不可以出现3个及以上连续的0存在
* 21-22位数字条形码,在数字中不可以出现4个及以上连续的0存在
* 19-20位数字条形码,在数字中不可以出现6个及以上连续的0存在
* 17-18位数字条形码,在数字中不可以出现8个及以上连续的0存在
* 15-16位数字条形码,在数字中不可以出现10个及以上连续的0存在
* 少于或等于14位数字的条形码,0的数量没有影响
* #########################################################################################################
* 二,非纯数字混合条件下:
* 58mm打印机最大支持14位字符,80mm打印机最大支持23位字符,超出无效
*
* 支持数字,大小写字母,特殊字符例如: !@#$%^&*()-=+_
* #########################################################################################################
*/
protected function barCode($strnum)
{
$chr = '';
$codeB = ["\x30", "\x31", "\x32", "\x33", "\x34", "\x35", "\x36", "\x37", "\x38", "\x39"];//匹配字符集B
$codeC = [
"\x00",
"\x01",
"\x02",
"\x03",
"\x04",
"\x05",
"\x06",
"\x07",
"\x08",
"\x09",
"\x0A",
"\x0B",
"\x0C",
"\x0D",
"\x0E",
"\x0F",
"\x10",
"\x11",
"\x12",
"\x13",
"\x14",
"\x15",
"\x16",
"\x17",
"\x18",
"\x19",
"\x1A",
"\x1B",
"\x1C",
"\x1D",
"\x1E",
"\x1F",
"\x20",
"\x21",
"\x22",
"\x23",
"\x24",
"\x25",
"\x26",
"\x27",
"\x28",
"\x29",
"\x2A",
"\x2B",
"\x2C",
"\x2D",
"\x2E",
"\x2F",
"\x30",
"\x31",
"\x32",
"\x33",
"\x34",
"\x35",
"\x36",
"\x37",
"\x38",
"\x39",
"\x3A",
"\x3B",
"\x3C",
"\x3D",
"\x3E",
"\x3F",
"\x40",
"\x41",
"\x42",
"\x43",
"\x44",
"\x45",
"\x46",
"\x47",
"\x48",
"\x49",
"\x4A",
"\x4B",
"\x4C",
"\x4D",
"\x4E",
"\x4F",
"\x50",
"\x51",
"\x52",
"\x53",
"\x54",
"\x55",
"\x56",
"\x57",
"\x58",
"\x59",
"\x5A",
"\x5B",
"\x5C",
"\x5D",
"\x5E",
"\x5F",
"\x60",
"\x61",
"\x62",
"\x63"
];//匹配字符集C
$length = strlen($strnum);
$b = [];
$b[0] = "\x1b";
$b[1] = "\x64";
$b[2] = "\x02";
$b[3] = "\x1d";
$b[4] = "\x48";
$b[5] = "\x32";//条形码显示控制,\x32上图下字,\x31上字下图,\x30只显示条形码
$b[6] = "\x1d";
$b[7] = "\x68";
$b[8] = "\x50";// \x30 设置条形码高度,7F是最大的高度
$b[9] = "\x1d";
$b[10] = "\x77";
$b[11] = "\x02";// \x01 设置条形码宽度,1-6
$b[12] = "\x1d";
$b[13] = "\x6b";
$b[14] = "\x49";//选择条形码类型code128,code39,codabar等等
$b[15] = chr($length + 2);
$b[16] = "\x7b";
$b[17] = "\x42";//选择字符集
if ($length > 14 && is_numeric($strnum)) {//大于14个字符,且为纯数字的进来这个区间
$b[17] = "\x43";
$j = 0;
$key = 18;
$ss = $length / 2;//初始化数组长度
if ($length % 2 == 1) {//判断条形码为单数
$ss = $ss - 0.5;
}
for ($i = 0; $i < $ss; $i++) {
$temp = substr($strnum, $j, 2);
$iindex = intval($temp);
$j = $j + 2;
if ($iindex == 0) {
$chr = '';
if ($b[$key + $i - 1] == '0' && $b[$key + $i - 2] == '0') {//判断前面的为字符集B,此时不需要转换字符集
$b[$key + $i] = $codeB[0];
$b[$key + $i + 1] = $codeB[0];
$key += 1;
} else {
if ($b[$key + $i - 1] == 'C' && $b[$key + $i - 2] == '{') {//判断前面的为字符集C时转换字符集B
$b[$key + $i - 2] = "\x7b";
$b[$key + $i - 1] = "\x42";
$b[$key + $i] = $codeB[0];
$b[$key + $i + 1] = $codeB[0];
$key += 1;
} else {
$b[$key + $i] = "\x7b";
$b[$key + $i + 1] = "\x42";
$b[$key + $i + 2] = $codeB[0];
$b[$key + $i + 3] = $codeB[0];
$key += 3;
}
}
} else {
if ($b[$key + $i - 1] == '0' && $b[$key + $i - 2] == '0' && $chr != 'chr') {//判断前面的为字符集B,此时要转换字符集C
$b[$key + $i] = "\x7b";
$b[$key + $i + 1] = "\x43";
$b[$key + $i + 2] = $codeC[$iindex];
$key += 2;
} else {
$chr = '';
$b[$key + $i] = $codeC[$iindex];
if ($iindex == 48) {
$chr = 'chr';
}//判断chr(48)等于0的情况
}
}
}
@$lastkey = end(array_keys($b));//取得数组的最后一个元素的键
if ($length % 2 > 0) {
$lastnum = substr($strnum, -1);//取得字符串的最后一个数字
if ($b[$lastkey] == '0' && $b[$lastkey - 1] == '0') {//判断前面的为字符集B,此时不需要转换字符集
$b[$lastkey + 1] = $codeB[$lastnum];
} else {
$b[$lastkey + 1] = "\x7b";
$b[$lastkey + 2] = "\x42";
$b[$lastkey + 3] = $codeB[$lastnum];
}
}
@$b[15] = chr(end(array_keys($b)) - 15);//得出条形码长度
$str = implode("", $b);
} else {//1-14个字符的纯数字和非纯数字的条形码进来这个区间,支持数字,大小写字母,特殊字符例如: !@#$%^&*()-=+_
$str = "\x1b\x64\x02\x1d\x48\x32\x1d\x68\x50\x1d\x77\x02\x1d\x6b\x49" . chr($length + 2) . "\x7b\x42" . $strnum;
}
return $str;
}
/**
* @param $time
* @return string
*/
protected function signature($time)
{
// 公共参数,请求公钥
return sha1($this->user . $this->uKey . $time);
}
}