185 行
6.2 KiB
PHP
185 行
6.2 KiB
PHP
<?php
|
|
|
|
namespace app\common\library;
|
|
|
|
/**
|
|
* 芯烨云 (Xprinter / xingye) 小票打印机服务类
|
|
*/
|
|
class PrinterService
|
|
{
|
|
protected $user;
|
|
protected $ukey;
|
|
protected $sn;
|
|
protected $url = "https://open.xprinter.com/Api/Open/";
|
|
|
|
public function __construct()
|
|
{
|
|
$config = [];
|
|
if (function_exists("config")) {
|
|
$config = config("printer");
|
|
}
|
|
if (empty($config)) {
|
|
$configFile = __DIR__ . "/../../extra/printer.php";
|
|
if (file_exists($configFile)) {
|
|
$config = include $configFile;
|
|
}
|
|
}
|
|
|
|
$this->user = isset($config["client_id"]) ? trim($config["client_id"]) : "";
|
|
$this->ukey = isset($config["client_secret"]) ? trim($config["client_secret"]) : "";
|
|
$this->sn = isset($config["sn"]) ? trim($config["sn"]) : "";
|
|
}
|
|
|
|
/**
|
|
* 查询芯烨云打印机状态
|
|
*/
|
|
public function queryStatus()
|
|
{
|
|
$stime = time();
|
|
$sig = sha1($this->user . $this->ukey . $stime);
|
|
|
|
$params = [
|
|
"user" => $this->user,
|
|
"stime" => $stime,
|
|
"sig" => $sig,
|
|
"apiname" => "Open_queryPrinterStatus",
|
|
"sn" => $this->sn
|
|
];
|
|
|
|
return $this->sendRequest($params);
|
|
}
|
|
|
|
/**
|
|
* 打印订单小票
|
|
*/
|
|
public function printOrder($orderData = [], $times = 1)
|
|
{
|
|
$stime = time();
|
|
$sig = sha1($this->user . $this->ukey . $stime);
|
|
|
|
$content = $this->buildReceiptContent($orderData);
|
|
|
|
$params = [
|
|
"user" => $this->user,
|
|
"stime" => $stime,
|
|
"sig" => $sig,
|
|
"apiname" => "Open_printMsg",
|
|
"sn" => $this->sn,
|
|
"content" => $content,
|
|
"times" => $times
|
|
];
|
|
|
|
return $this->sendRequest($params);
|
|
}
|
|
|
|
/**
|
|
* 拼接排版小票格式
|
|
*/
|
|
public function buildReceiptContent($order = [])
|
|
{
|
|
$title = $this->cleanText(isset($order["shop_name"]) ? $order["shop_name"] : "小众厨房设备商城");
|
|
$orderSn = $this->cleanText(isset($order["order_sn"]) ? $order["order_sn"] : "TEST" . date("YmdHis"));
|
|
$createTime = isset($order["createtime"]) ? date("Y-m-d H:i:s", $order["createtime"]) : date("Y-m-d H:i:s");
|
|
$consignee = $this->cleanText(isset($order["consignee"]) ? $order["consignee"] : "测试用户");
|
|
$phone = $this->cleanText(isset($order["phone"]) ? $order["phone"] : "138****8888");
|
|
$address = $this->cleanText(isset($order["address"]) ? $order["address"] : "贵州省修文县城内");
|
|
$totalAmount = $this->cleanText(isset($order["total_fee"]) ? $order["total_fee"] : "0.01");
|
|
|
|
$info = "<CB>{$title}</CB><BR>";
|
|
$info .= "<CB>-- 订单小票 --</CB><BR>";
|
|
$info .= "--------------------------------<BR>";
|
|
$info .= "订单编号:" . $orderSn . "<BR>";
|
|
$info .= "下单时间:" . $createTime . "<BR>";
|
|
$info .= "--------------------------------<BR>";
|
|
$info .= "商品名称 数量 单价<BR>";
|
|
|
|
if (!empty($order["items"]) && is_array($order["items"])) {
|
|
foreach ($order["items"] as $item) {
|
|
$name = $this->cleanText(isset($item["name"]) ? $item["name"] : "商品");
|
|
$num = $this->cleanText(isset($item["num"]) ? $item["num"] : 1);
|
|
$price = $this->cleanText(isset($item["price"]) ? $item["price"] : "0.00");
|
|
$info .= $name . " " . $num . " ¥" . $price . "<BR>";
|
|
}
|
|
} else {
|
|
$info .= "测试商品-厨房专用设备 1 ¥" . $totalAmount . "<BR>";
|
|
}
|
|
|
|
$info .= "--------------------------------<BR>";
|
|
$info .= "合计金额:¥" . $totalAmount . " 元<BR>";
|
|
$info .= "客户姓名:" . $consignee . "<BR>";
|
|
$info .= "联系电话:" . $phone . "<BR>";
|
|
$info .= "送货地址:" . $address . "<BR>";
|
|
$info .= "--------------------------------<BR>";
|
|
$info .= "<CB>谢谢惠顾,欢迎再次光临!</CB><BR><BR>";
|
|
|
|
return $info;
|
|
}
|
|
|
|
/**
|
|
* 发送 cURL 请求给芯烨云 API 网关
|
|
*/
|
|
protected function sendRequest($data)
|
|
{
|
|
if (!$this->user || !$this->ukey || !$this->sn) {
|
|
return [
|
|
'accepted' => false,
|
|
'response' => '',
|
|
'error' => '打印机配置不完整',
|
|
'uncertain' => false,
|
|
];
|
|
}
|
|
|
|
$ch = curl_init();
|
|
curl_setopt($ch, CURLOPT_URL, $this->url);
|
|
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
|
|
curl_setopt($ch, CURLOPT_POST, 1);
|
|
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($data));
|
|
curl_setopt($ch, CURLOPT_HTTPHEADER, ["Cookie: _gp_pc=1"]);
|
|
curl_setopt($ch, CURLOPT_TIMEOUT, 10);
|
|
$result = curl_exec($ch);
|
|
$error = curl_error($ch);
|
|
$errno = curl_errno($ch);
|
|
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
|
|
curl_close($ch);
|
|
|
|
if ($error) {
|
|
return [
|
|
'accepted' => false,
|
|
'response' => '',
|
|
'error' => '云打印请求失败: ' . $error,
|
|
// 网络层无法确认服务端是否已经受理,禁止自动重试以避免重复小票。
|
|
'uncertain' => true,
|
|
];
|
|
}
|
|
|
|
$response = trim((string)$result);
|
|
$accepted = $httpCode >= 200 && $httpCode < 300 && $this->isAcceptedResponse($response);
|
|
|
|
return [
|
|
'accepted' => $accepted,
|
|
'response' => mb_substr($response, 0, 1000, 'UTF-8'),
|
|
'error' => $accepted ? '' : '云打印未受理,HTTP ' . $httpCode,
|
|
'uncertain' => false,
|
|
];
|
|
}
|
|
|
|
protected function isAcceptedResponse($response)
|
|
{
|
|
if (strtoupper($response) === 'OK') {
|
|
return true;
|
|
}
|
|
|
|
$data = json_decode($response, true);
|
|
return is_array($data) && (
|
|
(isset($data['ret']) && (int)$data['ret'] === 0) ||
|
|
(isset($data['code']) && (int)$data['code'] === 0)
|
|
);
|
|
}
|
|
|
|
protected function cleanText($value)
|
|
{
|
|
$value = strip_tags((string)$value);
|
|
return preg_replace('/[\r\n\t]+/', ' ', $value);
|
|
}
|
|
}
|