
{{wikiTitle}}
小票打印
目录:
一、功能概述
本模块实现基于易联云API的订单小票打印功能,支持手动触发打印与支付成功自动打印两种模式,包含完整的权限校验、打印状态检测、订单数据组装、第三方服务调用能力。
二、核心流程
start
:触发打印请求;
if (权限校验通过?) then (是)
else (否)
:返回403无权限;
stop
endif
if (打印总开关开启?) then (是)
else (否)
:抛出"未开启打印"异常;
stop
endif
if (自动打印模式?) then (是)
if (自动打印配置开启?) then (是)
else (否)
:跳过打印;
stop
endif
endif
:校验订单状态;
if (订单存在且已支付?) then (是)
else (否)
:抛出订单异常;
stop
endif
:构造打印数据;
:调用易联云API;
if (调用成功?) then (是)
:记录成功日志;
else (否)
:记录错误日志;
endif
stop
三、核心代码结构详解
1.判断打印模式
public void YlyPrint(String orderId,boolean isAuto) {...}
isAuto 是否自动打印参数,手动触发传入false,支付成功传入true。
2.打印数据构造器
List<YlyPrintRequestGoods> goods = orderItems.stream()
.map(item -> new YlyPrintRequestGoods(...)).collect(...);
3.第三方服务调用
ylyUtil.ylyPrint(ylyPrintRequest); // 实际调用易联云SDK
4.YlyUtil工具类核心说明
YlyUtil作为易联云打印服务核心工具类,承担以下职责:
打印机初始化及Token管理
打印指令生成与协议封装
语音/音量等设备控制
打印状态配置读取
1.核心方法说明
// 初始化打印机连接
public void instant() {
// 从配置中心加载参数
client_id = systemConfigService.getValueByKey(YlyConstants.YLY_PRINT_APP_ID);
...
// 获取/刷新AccessToken
if (redisUtil.exists(YlyConstants.YLY_REDIS_TOKEN)) {
// 从Redis读取缓存Token
} else {
// 调用易联云API获取新Token
}
// 添加打印机设备
RequestMethod.getInstance().addPrinter(...);
}
// 执行小票打印
public void ylyPrint(YlyPrintRequest request) throws Exception {
// 构建打印内容模板
String printSb = "<FH><FB><center>...</center></FB></FH>";
// URL编码后发送打印指令
RequestMethod.getInstance().printIndex(..., URLEncoder.encode(printSb, "utf-8"), ...);
}
// 校验自动打印配置
public boolean checkYlyPrintAfterPaySuccess() {
return "1".equals(systemConfigService.getValueByKey(YlyConstants.YLY_PRINT_AUTO_STATUS));
}
2.打印模板定制策略
模板结构分析
<!-- 模板示例 -->
<FH><FB><center>{商户名称}</center></FB></FH>
********************************
<FH>
订单编号:{订单号}
日期:{支付时间}
...
</FH>
********************************
<FH>
商品名称 单价 数量 金额
{商品列表}
</FH>
********************************
<FH>
<LR>合计:¥{总金额}元,优惠:¥{优惠金额}元</LR>
...
</FH>
定制修改步骤
1.修改模板内容
调整ylyPrint()方法中的HTML模板字符串,支持以下控制指令:
<!-- 排版指令 -->
<FB> <!-- 加粗 -->
<FH> <!-- 恢复默认 -->
<center> <!-- 居中 -->
<LR>左列:右列</LR> <!-- 分列显示 -->
2.增加自定义字段
// 在YlyPrintRequest中新增字段
private String memberLevel;
// 模板中插入新字段
printSb.append("会员等级:" + request.getMemberLevel() + "\n");
3.使用模板引擎(推荐)
引入Freemarker模板引擎:
Configuration cfg = new Configuration(Configuration.VERSION_2_3_30);
cfg.setClassForTemplateLoading(this.getClass(), "/templates");
Template temp = cfg.getTemplate("yly.ftl");
String html = FreeMarkerTemplateUtils.processTemplateIntoString(temp, dataModel);
四、二开策略指南
1. 更换打印服务商(如飞鹅云)
实施步骤:
1.实现新服务商接口:
public interface PrinterAdapter {
void initPrinter() throws PrinterException;
void printReceipt(ReceiptData data) throws PrinterException;
}
@Component("feiyunAdapter")
public class FeiyunAdapter implements PrinterAdapter {
// 实现飞鹅云SDK调用
}
2.修改服务层调用点:
@Autowired @Qualifier("feiyunAdapter")
private PrinterAdapter printerAdapter;
public void YlyPrint(...) {
printerAdapter.printReceipt(convertData(ylyPrintRequest));
}
2. 增加打印队列
优化方案:
// 在YlyPrintServiceImpl中注入RabbitTemplate
@Autowired
private RabbitTemplate rabbitTemplate;
// 修改打印方法
@Async
public void YlyPrint(String orderId, boolean isAuto) {
// 验证逻辑...
rabbitTemplate.convertAndSend("print.task.queue", printRequest);
}
// 定义队列消费者
@RabbitListener(queues = "print.task.queue")
public void handlePrintTask(PrintRequest request) {
try {
ylyUtil.ylyPrint(request);
} catch (Exception e) {
redisUtil.lPush("print:retry:queue", request);
}
}
3. 扩展打印内容
场景示例:增加会员积分显示
扩展数据对象:
public class YlyPrintRequest {
// 新增字段
private Integer usePoints;
private String pointsRule;
}
修改模板构造:
printSb.append("<FH>使用积分:" + request.getUsePoints() + "(" + request.getPointsRule() + ")</FH>\n");
在订单处理层填充数据:
ylyPrintRequest.setUsePoints(order.getUseIntegral());
ylyPrintRequest.setPointsRule("100积分抵1元");
五、注意事项
编码规范:
打印内容必须使用URLEncoder.encode(printSb, “utf-8”)进行编码
AccessToken缓存时间需小于易联云有效期(35天)




评论({{cateWiki.comment_num}})
{{commentWhere.order ? '评论从旧到新':'评论从新到旧'}}
{{cateWiki.page_view_num}}人看过该文档


评论(0)
{{commentWhere.order ? '评论从旧到新':'评论从新到旧'}}
278人看过该文档




{{item.user ? item.user.nickname : ''}}
(自评)
{{item.content}}
{{item.create_time}}
删除




搜索结果
为您找到{{wikiCount}}条结果
{{item.page_view_num}}
{{item.like ? item.like.like_num : 0}}
{{item.comment ? item.comment.comment_num : 0}}
位置:
{{path.name}}
{{(i+1) == item.catalogue.path_data.length ? '':'/'}}


