This commit is contained in:
richboo111
2023-03-17 14:16:48 +08:00
parent 33244441f3
commit bf5efa6faa
4 changed files with 982 additions and 0 deletions

View File

@@ -1 +1,283 @@
package xpyunapi
const (
//http返回成功状态码
HttpStatusSuccessCode = 200
//响应状态码
REQUEST_HEADER_ERROR = -1 // 请求头错误
REQUEST_PARAM_INVALID = -2 //参数不合法
REQUEST_SIGN_FAILED = -3 //参数签名失败
REQUEST_USER_NOT_REGISTER = -4 //用户未注册
SN_USER_NOT_MATCH = 1001 //打印机编号和用户不匹配
PRINTER_NOT_REGISTER = 1002 //打印机未注册
PRINTER_OFFLINE = 1003 //打印机不在线
ADD_ORDER_FAILED = 1004 //添加订单失败
ORDER_NOT_FOUND = 1005 //未找到订单信息
ORDER_DATE_INVALID = 1006 //订单日期格式或大小不正确
PRINT_CONTENT_MORE_THAN_12K_BYTES = 1007 //打印内容不能超过12K
PRINTER_RECORD_LOCK_FAIL = 1008 //用户修改打印机记录失败
SN_OR_NAME_EMPTY = 1009 // 用户添加打印机时,打印机编号或名称不能为空
PRINTER_NUMBER_INVALID = 1010 //打印机设备编号无效
PRINTER_EXIST = 1011 //打印机已存在,若当前开放平台无法查询到打印机信息,请联系售后技术支持人员核实
PRINTER_EXCEPTION = 1012 //添加打印设备失败,请稍后再试或联系售后技术支持人员
ORDER_IDEMPOTENT = 1013 //打印订单时触发幂等性
ORDER_IDEMPOTENT_LIMITLEN = 1014 //幂等因子过长
LOGO_FORMAT_ERROR = 1016 //LOGO文件格式错误
LOGO_SIZE_LARGE = 1017 //LOGO文件超出规定范围
LOGO_UPLOAD_TIMES = 1018 //LOGO上传次数超限制
LOGO_DELETE_NO_EXIST = 1020 // LOGO删除失败
LABEL_MODE_ERROR = 1021 //LOGO上传模式错误
)
var XpuErrMsg2 = map[string]string{
"REQUEST_HEADER_ERROR": "请求头错误",
"REQUEST_PARAM_INVALID": "参数不合法",
"REQUEST_SIGN_FAILED": "参数签名失败",
"REQUEST_USER_NOT_REGISTER": "用户未注册",
"SN_USER_NOT_MATCH": "打印机编号和用户不匹配",
"PRINTER_NOT_REGISTER": "打印机未注册",
"PRINTER_OFFLINE": "打印机不在线",
"ADD_ORDER_FAILED": "添加订单失败",
"ORDER_NOT_FOUND": "未找到订单信息",
"ORDER_DATE_INVALID": "订单日期格式或大小不正确",
"PRINT_CONTENT_MORE_THAN_12K_BYTES": "打印内容不能超过12K",
"PRINTER_RECORD_LOCK_FAIL": "用户修改打印机记录失败",
"SN_OR_NAME_EMPTY": "用户添加打印机时,打印机编号或名称不能为空",
"PRINTER_NUMBER_INVALID": "打印机设备编号无效",
"PRINTER_EXIST": "打印机已存在",
"PRINTER_EXCEPTION": "添加打印设备失败",
"ORDER_IDEMPOTENT": "打印订单时触发幂等性",
"ORDER_IDEMPOTENT_LIMITLEN": "幂等因子过长",
"LOGO_FORMAT_ERROR": "LOGO文件格式错误",
"LOGO_SIZE_LARGE": "LOGO文件超出规定范围",
"LOGO_UPLOAD_TIMES": "LOGO上传次数超限制",
"LOGO_DELETE_NO_EXIST": "LOGO删除失败",
"LABEL_MODE_ERROR": "LOGO上传模式错误",
}
var XpuErrMsg = map[string]string{
"1001": "打印机编号和用户不匹配",
"1002": "打印机未注册,尚未添加至云平台",
"1003": "打印机不在线",
"1004": "添加订单失败",
"1005": "未找到订单信息",
"1006": "订单日期格式或大小不正确",
"1007": "打印内容不能超过12K",
"1008": "用户修改打印机记录失败",
"1009": "用户添加打印机时,打印机编号或名称不能为空",
"1010": "打印机设备编号无效",
"1011": "打印机已存在",
"1012": "添加打印设备失败",
"1013": "打印订单时触发幂等性",
"1014": "幂等因子过长",
"1016": "LOGO文件格式错误",
"1017": "LOGO文件超出规定范围",
"1018": "LOGO上传次数超限制",
"1020": "LOGO删除失败",
"1021": "LOGO上传模式错误",
}
const (
//声音类型 v10版本
VoiceTypeV10PersonBig = 0 //真人语音 大
VoiceTypeV10PersonMedium = 1 //真人语音 中
VoiceTypeV10PersonSmall = 2 //真人语音 小
VoiceTypeV10DiDi = 3 //滴滴声
VoiceTypeV10Mute = 4 //静音
//声音类型 其他固件版本
VoiceTypeOtherPerson = 0 //真人语音
VoiceTypeOtherDiDi = 3 //滴滴声
VoiceTypeOtherMute = 4 //静音
//声音大小打印机固件版本为非V10.xx的机器支持此参数
VolumeLevelBig = 0 //大
VolumeLevelMedium = 1 //中
VolumeLevelSmall = 2 //小
VolumeLevelClose = 3 //关闭
//切刀控制开关,默认为0,仅用于支持切刀的芯烨云打印机
CutterOpen = 0 //开启云端默认设置控制切刀
CutterClose = 1 //关闭云端切刀
//声音播放模式:0-取消订单模式,1-静音模式,2-来单播放模式(默认),3-播报退单语音4-播报美团来单语音5-播报饿了么来单语音
VoiceCancelOrder = 0 //取消订单模式
VoiceMute = 1 //静音模式
VoicePlayOrder = 2 //来单播放模式
VoiceUserChargeback = 3 //用户申请退单模式
VoiceMT = 4 //播报美团来单语音
VoiceELM = 5 //播报饿了么来单语音
//打印模式 默认0
ModeCheckYes = 1 //不检查打印机是否在线,直接生成打印订单,并返回打印订单号。如果打印机不在线,订单将缓存在打印队列中,打印机正常在线时会自动打印
ModeCheckNo = 0 //或不指定则会检查打印机是否在线,如果不在线 则不生成打印订单,直接返回设备不在线状态码;如果在线则生成打印订单,并返回打印订单号
//默认订单过期时间
ExpiresInDefault = 86399 //秒
//支付方式41-55
PayTypeZFB = 41 //支付宝
PayTypeWX = 42 //微信
PayTypeYunZF = 43 //云支付
PayTypeYLCard = 44 //银联刷卡
PayTypeYLPay = 45 //银联支付
PayTypeMemberCardPay = 46 //会员卡消费
PayTypeMemberCardCharge = 47 //会员卡充值
PayTypeYiZF = 48 //翼支付
PayTypePaymentSuccess = 49 //成功收款
PayTypeJLZF = 50 //嘉联支付
PayTypeYQB = 51 //壹钱包
PayTypeJDZF = 52 //京东支付
PayTypeKQZF = 53 //快钱支付
PayTypeWZF = 54 //威支付
PayTypeXQZF = 55 //享钱支付
//支付与否
PayModeDrawback = 59 //退款
PayModeReceipt = 60 //到账
PayModeConsume = 61 //消费
//打印机状态
PrinterStateOffline = 0 //离线
PrinterStateOnlineNormal = 1 //在线正常
PrinterStateOnlineUnusual = 2 //在线异常
PrinterStateError = -1 //获取状态出错
)
var (
//打印机状态说明
PrinterStatus = map[float64]string{
PrinterStateOffline: "离线",
PrinterStateOnlineNormal: "在线正常",
PrinterStateOnlineUnusual: "在线异常",
PrinterStateError: "获取状态出错",
}
)
//请求参数
type RestRequest struct {
User string `json:"user"` //开发者ID(芯烨云后台登录账号)
UserKey string `json:"-"` //芯烨云后台开发者密钥
Timestamp int64 `json:"timestamp"` //当前UNIX时间戳10位精确到秒
Sign string `json:"sign"` //对参数 user + UKEY + timestamp 拼接后(+号表示连接符进行SHA1加密得到签名值为40位小写字符串
Debug int `json:"debug"` //debug=1返回非json格式的数据。仅测试时候使用
}
//响应参数
type XPYunResp struct {
HttpStatusCode int `json:"httpStatusCode"`
Content *XPYunRespContent `json:"content"`
}
type XPYunRespContent struct {
Code int `json:"code"`
Msg string `json:"msg"`
Data interface{} `json:"data,omitempty"`
ServerExecutedTime int `json:"serverExecutedTime"`
}
type AddPrinterRequestItem struct {
Sn string `json:"sn"` //打印机编号
Name string `json:"name,omitempty"` //打印机名称
}
// 添加打印机到开发者账户(可批量)
type AddPrinterRequest struct {
RestRequest `json:",inline"`
Items []*AddPrinterRequestItem `json:"items"`
}
//设置打印机语音类型
type SetVoiceTypeRequest struct {
RestRequest `json:",inline"`
Sn string `json:"sn"` //打印机编号
VoiceType int `json:"voiceType"` //声音类型打印机固件版本为V10.xx的机器取值 0真人语音 1真人语音 2真人语音 3 嘀嘀声 4 静音;其它固件版本的机器取值0真人语音 3 嘀嘀声 4 静音
VolumeLevel int `json:"volumeLevel"` //声音大小0大 1中 2小 3关闭,说明打印机固件版本为非V10.xx的机器支持此参数
}
//打印小票订单
type PrintRequest struct {
RestRequest `json:",inline"`
Sn string `json:"sn"` //打印机编号
Content string `json:"content"` //打印内容,不能超过12k字节
//非必填
Copies int `json:"copies,omitempty"` //打印份数,默认为1,取值[1-65535]
Cutter int `json:"cutter,omitempty"` //是否支持切刀自定义控制 0采用默认切刀 1采用自定义控制切刀
Voice int `json:"voice,omitempty"` //声音播放模式,0-取消订单模式,1-静音模式,2-来单播放模式(默认),3-播报退单语音4-播报美团来单语音5-播报饿了么来单语音
Mode int `json:"mode,omitempty"` //打印模式默认为0
ExpiresIn int `json:"expiresIn,omitempty"` //订单有效期 单位:秒 取值范围为0<订单失效时间<24*60*60,使用该参数时需要将参数mode 设置为1
BackurlFlag int `json:"backurlFlag,omitempty"` //回调地址对应标识,必须先在管理后台设置,否则无效
PayType int `json:"payType,omitempty"` //41~55 支付宝 41、微信 42、云支付 43、银联刷卡 44、银联支付 45、会员卡消费 46、会员卡充值 47、翼支付 48、成功收款 49、嘉联支付 50、壹钱包 51、京东支付 52、快钱支付 53、威支付 54、享钱支付 55
PayMode int `json:"payMode,omitempty"` //59~61 退款 59 到账 60 消费 61
Money float64 `json:"money,omitempty"` //支付金额 允许保留2位小数
}
//打印标签订单
type PrintLabelRequest struct {
RestRequest `json:",inline"`
Sn string `json:"sn"` //打印机编号
Content string `json:"content"` //打印内容,不能超过12k字节
//非必填
Copies int `json:"copies,omitempty"` //打印份数,默认为1,取值[1-65535]
Voice int `json:"voice,omitempty"` //声音播放模式,0-取消订单模式,1-静音模式,2-来单播放模式(默认),3-播报退单语音4-播报美团来单语音5-播报饿了么来单语音
Mode int `json:"mode,omitempty"` //打印模式默认为0
ExpiresIn int `json:"expiresIn,omitempty"` //订单有效期 单位:秒 取值范围为0<订单失效时间<24*60*60,使用该参数时需要将参数mode 设置为1
BackurlFlag int `json:"backurlFlag,omitempty"` //回调地址对应标识,必须先在管理后台设置,否则无效
PayType int `json:"payType,omitempty"` //41~55 支付宝 41、微信 42、云支付 43、银联刷卡 44、银联支付 45、会员卡消费 46、会员卡充值 47、翼支付 48、成功收款 49、嘉联支付 50、壹钱包 51、京东支付 52、快钱支付 53、威支付 54、享钱支付 55
PayMode int `json:"payMode,omitempty"` //59~61 退款 59 到账 60 消费 61
Money float64 `json:"money,omitempty"` //支付金额 允许保留2位小数
}
//删除打印机
type DelPrinterRequest struct {
RestRequest `json:",inline"`
SnList []string `json:"snlist"` //打印机编号集合
}
//修改打印机信息
type UpdPrinterRequest struct {
RestRequest `json:",inline"`
Sn string `json:"sn"` //打印机编号
Name string `json:"name,omitempty"` //打印机名称
//非必填
CardNo string `json:"cardno"` //打印机流量卡号码
}
//清空待打印队列
type EmpPrinterQueueRequest struct {
RestRequest `json:",inline"`
Sn string `json:"sn"` //打印机编号
}
// 查询订单状态
type QueryOrderStateRequest struct {
RestRequest `json:",inline"`
OrderId string `json:"orderId"` //订单编号,由“打印订单”接口返回
}
//查询指定打印机某天的订单统计数
type QueryOrderStatisRequest struct {
RestRequest `json:",inline"`
Sn string `json:"sn"` //打印机编号
Date string `json:"date"` //查询日期格式YY-MM-DD2016-09-20
}
//获取指定打印机状态
type QueryPrinterStatusRequest struct {
RestRequest `json:",inline"`
Sn string `json:"sn"` //打印机编号
}
//批量查询打印机状态
type QueryPrintersStatusRequest struct {
RestRequest `json:",inline"`
SnList []string `json:"snlist"` //打印机编号集合,一次最多20台
}
//金额播报 仅用于支持金额播报的芯烨云打印机
type PlayVoiceRequest struct {
RestRequest `json:",inline"`
Sn string `json:"sn"` //打印机编号
//非必填
PayType int `json:"payType"` //支付方式41~55
PayMode int `json:"payMode"` //支付与否59~61退款 59 到账 60 消费 61
Money float64 `json:"money"` //支付金额,允许保留2位小数
}

View File

@@ -1 +1,219 @@
package xpyunapi
//
import (
"encoding/json"
"fmt"
"testing"
)
//
const (
UserName = "feng.shi@rosy.net.cn" //开发者ID
UserKey = "20a24d4332954993b05876e7b3db2a96" //开发者密钥
TestPrinterSN = "029JC1ZZD853B4B" //测试打印机SN
)
//
var api = New(UserName, UserKey)
//
//测试格式化商品列表
func TestFormatPrintOrderItem(t *testing.T) {
str := FormatPrintOrderItem("测试商品名字", 100, 8.78)
fmt.Println(str)
request := &PrintRequest{
RestRequest: api.GenerateRestRequest(),
Sn: TestPrinterSN,
Content: str,
Copies: 1,
Voice: VoicePlayOrder,
Mode: ModeCheckYes,
}
orderID, err := api.Print(request)
fmt.Printf("orderID=====%s", orderID)
fmt.Printf("err=====%v", err)
}
func TestPrint(t *testing.T) {
printContent := ""
printContent = printContent + "<IMG></IMG><BR><C>" + "<B>京西菜市</B>" + "<BR></C>"
printContent += StrRepeat("-", 32)
printContent += "<BR><L>下单时间2023-03-16 15:30:28"
printContent += "<BR><L>预计送达2023-03-16 16:30:28"
printContent += "<BR><L>" + "客户姓名:杨玺" + "<BR>" + "客户电话17235643746"
printContent += "<BR><HB>订单编号7764828754021845</HB>" + "<BR>"
printContent += "<IMG></IMG><BR><C>" + "<B>京西菜市#23</B>" + "<BR></C>"
printContent += "<C><BARCODE t=CODE128 w=2 h=100 p=2>5842160392535156</BARCODE>"
printContent += "<C>" + "<QRCODE s=6 e=L l=center>https://www.xpyun.net</QRCODE>" + "</C>"
printContent += StrRepeat("-", 32)
printContent += "<HB>客户地址四川省成都市武侯区双流县金华镇门口大院5栋1单元1104号</HB><BR>"
printContent += StrRepeat("-", 32)
printContent += "<BR>客户备注:缺货时电话与我沟通 收货人隐私号17882904902——5355手机号 181****6752" + "<BR>"
printContent += StrRepeat("-", 32)
printContent = printContent + "<BR>商品列表" + StrRepeat(" ", 6) + "<BR>"
printContent += "商品名" + StrRepeat(" ", 2) + "数量" + StrRepeat(" ", 3) + "单价" + StrRepeat(" ", 5) + "小计" + "<BR>"
printContent += StrRepeat("-", 32)
printContent += FormatPrintOrderItem("[优]猪肉馅约250g/份", 1, 999)
printContent += FormatPrintOrderItem("鲜鸡蛋约250g/份", 1, 7.8)
printContent += FormatPrintOrderItem("豌豆米-手工剥豆约100g/份", 1, 4)
printContent += FormatPrintOrderItem("娃娃菜200g/个", 5, 2)
printContent += "<L>" + "共4种9件商品" + "<BR></L>"
printContent += "<L>" + "实付金额: " + "327.83" + "元" + "<BR></L>"
printContent = printContent + "<BR><BR>"
printContent += StrRepeat("-", 14) + "#23完" + StrRepeat("-", 14)
printContent += "<BR>"
request := PrintRequest{
RestRequest: api.GenerateRestRequest(),
Sn: TestPrinterSN,
Content: printContent,
Copies: 1,
Voice: 2,
Mode: 1,
}
result, err := api.Print(&request)
//序列化
reslutJson, _ := json.Marshal(result)
var msg = fmt.Sprintf("response result: %+v", string(reslutJson))
fmt.Println(msg)
fmt.Println(err)
}
////批量添加打印机
//func TestAddPrinters(t *testing.T) {
// request := &AddPrinterRequest{
// Items: []*AddPrinterRequestItem{{
// Sn: TestPrinterSN,
// Name: "京西测试打印机0315",
// }},
// RestRequest: api.GenerateRestRequest(),
// }
// err := api.AddPrinters(request)
// fmt.Println(err)
//}
//
////设置打印机语音类型
//func TestSetVoiceType(t *testing.T) {
// request := &SetVoiceTypeRequest{
// RestRequest: api.GenerateRestRequest(),
// Sn: TestPrinterSN,
// VoiceType: VoiceTypeV10PersonSmall,
// VolumeLevel: VolumeLevelSmall,
// }
// err := api.SetVoiceType(request)
// fmt.Println(err)
//}
//
////打印小票订单
//func TestPrint(t *testing.T) {
// request := &PrintRequest{
// RestRequest: api.GenerateRestRequest(),
// Sn: TestPrinterSN,
// Content: "-----测试打印小票订单---------" +
// "kljhsjkfhwiohguoiq" +
// "ojkahfohsajkohaowjgokaw",
// Copies: 1,
// Voice: VoicePlayOrder,
// Mode: ModeCheckYes,
// }
// orderID, err := api.Print(request)
// fmt.Println(orderID)
// fmt.Println(err)
//}
//
////删除打印机
//func TestDelPrinter(t *testing.T) {
// request := &DelPrinterRequest{
// RestRequest: api.GenerateRestRequest(),
// SnList: []string{
// TestPrinterSN,
// },
// }
// err := api.DelPrinters(request)
// fmt.Println(err)
//}
//
////修改打印机信息
//func TestUpdPrinter(t *testing.T) {
// request := &UpdPrinterRequest{
// RestRequest: api.GenerateRestRequest(),
// Sn: "234124",
// Name: "京西测试打印机3151",
// }
// err := api.UpdatePrinter(request)
// fmt.Println(err)
//}
//
////清空待打印队列
//func TestEmptyPrinterQueue(t *testing.T) {
// request := &EmpPrinterQueueRequest{
// RestRequest: api.GenerateRestRequest(),
// Sn: TestPrinterSN,
// }
// err := api.EmptyPrinterQueue(request)
// fmt.Println(err)
//}
//
////查询订单状态
//func TestQueryOrderState(t *testing.T) {
// request := &QueryOrderStateRequest{
// RestRequest: api.GenerateRestRequest(),
// OrderId: "dfhsehsteh",
// }
// state, err := api.QueryOrderState(request)
// fmt.Println(state)
// fmt.Println(err)
//}
//
////查询指定某天的订单统计数
//func TestQueryOrderStatis(t *testing.T) {
// request := &QueryOrderStatisRequest{
// RestRequest: api.GenerateRestRequest(),
// Sn: "72624647",
// Date: "2023-03-15",
// }
// printed, waiting, err := api.QueryOrderStatis(request)
// fmt.Println(printed)
// fmt.Println(waiting)
// fmt.Println(err)
//}
//
////查询指定打印机状态
//func TestQueryPrinterStatus(t *testing.T) {
// request := &QueryPrinterStatusRequest{
// RestRequest: api.GenerateRestRequest(),
// Sn: "7273737",
// }
// status, err := api.QueryPrinterStatus(request)
// fmt.Println(status)
// fmt.Println(err)
//}
//
////批量查询打印机状态
//func TestBatchQueryPrinterStatus(t *testing.T) {
// request := &QueryPrintersStatusRequest{
// RestRequest: api.GenerateRestRequest(),
// SnList: []string{
// TestPrinterSN,
// "262623738",
// },
// }
// status, err := api.QueryPrintersStatus(request)
// fmt.Println(status)
// fmt.Println(err)
//}
//
////金额播报
//func TestPlayVoice(t *testing.T) {
// request := &PlayVoiceRequest{
// RestRequest: api.GenerateRestRequest(),
// Sn: TestPrinterSN,
// PayType: PayTypeZFB,
// PayMode: PayModeReceipt,
// Money: 25.8,
// }
// err := api.PlayVoice(request)
// fmt.Println(err)
//}

View File

@@ -1 +1,171 @@
package xpyunapi
import (
"bytes"
"crypto/sha1"
"encoding/json"
"fmt"
"git.rosy.net.cn/baseapi/utils"
"golang.org/x/text/encoding/simplifiedchinese"
"golang.org/x/text/transform"
"io/ioutil"
"net/http"
"strconv"
"strings"
"time"
)
/**
* 发送http的json请求
*
* @param url 请求url
* @param jsonStr 发送的json字符串
*
*/
func HttpPostJson(url string, data interface{}) *XPYunResp {
b, err := json.Marshal(&data)
if err != nil {
var msg = fmt.Sprintf("json serialize err:%+v", err)
fmt.Println(msg)
result := XPYunResp{
HttpStatusCode: 500,
}
return &result
}
//var reqMsg = fmt.Sprintf("response result:%+v", string(b))
//fmt.Println(reqMsg)
resp, err := http.Post(url, "application/json", bytes.NewBuffer(b))
if err != nil {
fmt.Println(err)
}
defer resp.Body.Close()
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
var msg = fmt.Sprintf("post json error:%+v", err)
fmt.Println(msg)
}
result := XPYunResp{
HttpStatusCode: resp.StatusCode,
}
var content XPYunRespContent
err = json.Unmarshal(body, &content)
if err == nil {
result.Content = &content
} else {
var msg = fmt.Sprintf("unmarshal body failed, error:%+v", err)
fmt.Println(msg)
}
return &result
}
/**
* 哈稀签名
* @param signSource - 源字符串
* @return
*/
func Sign(signSource string) string {
h := sha1.New()
h.Write([]byte(signSource))
result := fmt.Sprintf("%x", h.Sum(nil))
return result
}
//获得毫秒数
func GetMillisecond() int64 {
return time.Now().UnixNano() / 1e6
}
/**
* 获得字符串重复
* @param str - 要进行重复的字符串
* @param repeatTimes - 重复次数
*/
func StrRepeat(str string, repeatTimes int) string {
return strings.Repeat(str, repeatTimes)
}
func CalcGbkLenForPrint(data string) int {
gbk, err := Utf8ToGbk(data)
if err != nil {
return 0
}
return len(gbk)
}
func CalcAsciiLenForPrint(data string) int {
return len(data)
}
func Utf8ToGbk(s string) (string, error) {
reader := transform.NewReader(bytes.NewReader([]byte(s)), simplifiedchinese.GBK.NewEncoder())
d, e := ioutil.ReadAll(reader)
if e != nil {
return "", e
}
return string(d), nil
}
//解析返回数据结构体
func GetXpuResponse(data interface{}) *XPYunRespContent {
retVal := &XPYunRespContent{}
resultJson, _ := json.Marshal(data)
decoder := json.NewDecoder(bytes.NewBufferString(string(resultJson)))
if err := decoder.Decode(&retVal); err != nil {
return nil
}
return retVal
}
const ROW_MAX_CHAR_LEN = 32
const MAX_NAME_CHAR_LEN = 20
const NEX_ROW_CHAR_LEN = 8
const LAST_ROW_MAX_NAME_CHAR_LEN = 16
const MAX_QUANTITY_CHAR_LEN = 6
const MAX_PRICE_CHAR_LEN = 6
const LAST_ROW_MAX_NAME_CHAR_LEN80 = 24 //26
const ROW_MAX_CHAR_LEN80 = 48
const MAX_NAME_CHAR_LEN80 = 27
const MAX_QUANTITY_CHAR_LEN80 = 7
//var orderNameEmpty = StrRepeat(" ", MAX_NAME_CHAR_LEN)
var orderNameEmpty = StrRepeat(" ", NEX_ROW_CHAR_LEN)
//test函数
func FormatPrintOrderItem(foodName string, quantity int, price float64) string {
//foodNameLen := CalcGbkLenForPrint(foodName)
quantityStr := strconv.Itoa(quantity)
quantityLen := CalcAsciiLenForPrint(quantityStr)
priceStr := fmt.Sprintf("%.2f", price)
priceLen := CalcAsciiLenForPrint(priceStr)
subtotalStr := fmt.Sprintf("%.2f", utils.Int2Float64(quantity)*price)
//subtotalLen := CalcAsciiLenForPrint(subtotalStr)
result := foodName + "<BR>"
//mod := foodNameLen % ROW_MAX_CHAR_LEN
//if mod <= LAST_ROW_MAX_NAME_CHAR_LEN {
// // 保证各个列的宽度固定,不足部分,利用空格填充
// result = result + StrRepeat(" ", MAX_NAME_CHAR_LEN-mod)
//
//} else {
// // 另起新行
// result = result + "<BR>"
// result = result + orderNameEmpty
//}
result += orderNameEmpty + "x" + quantityStr + StrRepeat(" ", MAX_QUANTITY_CHAR_LEN-quantityLen)
result += "¥" + priceStr + StrRepeat(" ", MAX_QUANTITY_CHAR_LEN+1-priceLen)
result += "¥" + subtotalStr
result += "<BR>"
return result
}

View File

@@ -1 +1,313 @@
package xpyunapi
import (
"errors"
"fmt"
"git.rosy.net.cn/baseapi/platformapi"
"net/http"
"strconv"
"strings"
"sync"
)
const (
baseURL = "https://open.xpyun.net/api/openapi/xprinter/"
signKey = "sign"
timestampKey = "timestamp"
debugTest = 1 //debug=1返回非json格式的数据仅测试时候使用
)
const (
ResponseCodeSuccess = 0 //成功
ResponseMsgSuccess = "ok"
)
var (
exceedLimitCodes = map[string]int{}
canRetryCodes = map[string]int{}
)
type API struct {
locker sync.RWMutex
accessToken string
userName string
userKey string
client *http.Client
config *platformapi.APIConfig
}
//初始化
func New(userName, userKey string, config ...*platformapi.APIConfig) *API {
curConfig := platformapi.DefAPIConfig
if len(config) > 0 {
curConfig = *config[0]
}
return &API{
userName: userName,
userKey: userKey,
client: &http.Client{Timeout: curConfig.ClientTimeout},
config: &curConfig,
}
}
//生成签名
func (a *API) GenerateSign() string {
return Sign(a.userName + a.userKey + strconv.FormatInt(GetMillisecond(), 10))
}
//生成 RestRequest
func (a *API) GenerateRestRequest() RestRequest {
return RestRequest{
User: a.userName,
UserKey: a.userKey,
Timestamp: GetMillisecond(),
Sign: a.GenerateSign(),
}
}
func xpyunPostJson(url string, request interface{}) *XPYunResp {
result := HttpPostJson(url, request)
return result
}
// 1.添加打印机到开发者账户(可批量)
func (a *API) AddPrinters(sn, printerName string) error {
url := baseURL + "addPrinters"
request := &AddPrinterRequest{
RestRequest: a.GenerateRestRequest(),
Items: []*AddPrinterRequestItem{{
Sn: sn,
Name: printerName,
}},
}
resp := xpyunPostJson(url, request)
if resp.HttpStatusCode != HttpStatusSuccessCode {
return errors.New("HTTP请求错误请检查重试")
}
if resp.Content.Code != ResponseCodeSuccess {
return fmt.Errorf("%v", XpuErrMsg2[resp.Content.Msg])
}
retVal, _ := resp.Content.Data.(map[string]interface{})
failMsg := ""
if len(retVal["failMsg"].([]interface{})) > 0 {
for _, v := range retVal["failMsg"].([]interface{}) {
t := strings.Split(v.(string), ":")
failMsg += t[0] + XpuErrMsg[t[1]]
}
return fmt.Errorf("添加打印机错误:%v", failMsg)
}
return nil
}
//2.设置打印机语音类型
func (a *API) SetVoiceType(sn string, soundSize int) error {
url := baseURL + "setVoiceType"
request := &SetVoiceTypeRequest{
RestRequest: a.GenerateRestRequest(),
Sn: sn,
VoiceType: VoiceTypeOtherPerson,
VolumeLevel: soundSize,
}
resp := xpyunPostJson(url, request)
if resp.HttpStatusCode != HttpStatusSuccessCode {
return errors.New("HTTP请求错误请检查重试")
}
if resp.Content.Code != ResponseCodeSuccess {
return fmt.Errorf("%v", XpuErrMsg2[resp.Content.Msg])
}
retVal, _ := resp.Content.Data.(map[string]interface{})
failMsg := ""
if retVal != nil && len(retVal["failMsg"].([]interface{})) > 0 {
for _, v := range retVal["failMsg"].([]interface{}) {
t := strings.Split(v.(string), ":")
failMsg += t[0] + XpuErrMsg[t[1]]
}
return fmt.Errorf("设置打印机运营类型错误:%v", failMsg)
}
return nil
}
//3.打印小票订单
func (a *API) Print(request *PrintRequest) (string, error) {
url := baseURL + "print"
request.RestRequest = a.GenerateRestRequest()
resp := xpyunPostJson(url, request)
if resp.HttpStatusCode != HttpStatusSuccessCode {
return "0", errors.New("HTTP请求错误请检查重试")
}
if resp.Content.Code != ResponseCodeSuccess {
return "0", fmt.Errorf("%v", XpuErrMsg2[resp.Content.Msg])
}
retVal, _ := resp.Content.Data.(string)
if len(retVal) > 0 {
return retVal, nil
} else {
return "0", nil
}
}
// 5.批量删除打印机
func (a *API) DelPrinters(snList []string) error {
url := baseURL + "delPrinters"
request := &DelPrinterRequest{
RestRequest: a.GenerateRestRequest(),
SnList: snList,
}
resp := xpyunPostJson(url, request)
if resp.HttpStatusCode != HttpStatusSuccessCode {
return errors.New("HTTP请求错误请检查重试")
}
if resp.Content.Code != ResponseCodeSuccess {
return fmt.Errorf("%v", XpuErrMsg2[resp.Content.Msg])
}
retVal, _ := resp.Content.Data.(map[string]interface{})
failMsg := ""
if retVal != nil && len(retVal["failMsg"].([]interface{})) > 0 {
for _, v := range retVal["failMsg"].([]interface{}) {
t := strings.Split(v.(string), ":")
failMsg += t[0] + XpuErrMsg[t[1]]
}
return fmt.Errorf("删除打印机错误:%v", failMsg)
}
return nil
}
//6.修改打印机信息
func (a *API) UpdatePrinter(request *UpdPrinterRequest) error {
url := baseURL + "updPrinter"
request.RestRequest = a.GenerateRestRequest()
resp := xpyunPostJson(url, request)
if resp.HttpStatusCode != HttpStatusSuccessCode {
return errors.New("HTTP请求错误请检查重试")
}
if resp.Content.Code != ResponseCodeSuccess {
return fmt.Errorf("%v", XpuErrMsg2[resp.Content.Msg])
}
retVal, _ := resp.Content.Data.(map[string]interface{})
failMsg := ""
if retVal != nil && len(retVal["failMsg"].([]interface{})) > 0 {
for _, v := range retVal["failMsg"].([]interface{}) {
t := strings.Split(v.(string), ":")
failMsg += t[0] + XpuErrMsg[t[1]]
}
return fmt.Errorf("修改打印机信息错误:%v", failMsg)
}
return nil
}
//7.清空待打印队列
func (a *API) EmptyPrinterQueue(sn string) error {
url := baseURL + "delPrinterQueue"
request := &EmpPrinterQueueRequest{
RestRequest: a.GenerateRestRequest(),
Sn: sn,
}
resp := xpyunPostJson(url, request)
if resp.HttpStatusCode != HttpStatusSuccessCode {
return errors.New("HTTP请求错误请检查重试")
}
if resp.Content.Code != ResponseCodeSuccess {
return fmt.Errorf("%v", XpuErrMsg[resp.Content.Msg])
}
retVal, _ := resp.Content.Data.(map[string]interface{})
failMsg := ""
if retVal != nil && len(retVal["failMsg"].([]interface{})) > 0 {
for _, v := range retVal["failMsg"].([]interface{}) {
t := strings.Split(v.(string), ":")
failMsg += t[0] + XpuErrMsg[t[1]]
}
return fmt.Errorf("清空待打印机队列错误:%v", failMsg)
}
return nil
}
//8.查询订单状态
func (a *API) QueryOrderState(request *QueryOrderStateRequest) (bool, error) {
url := baseURL + "queryOrderState"
request.RestRequest = a.GenerateRestRequest()
resp := xpyunPostJson(url, request)
if resp.HttpStatusCode != HttpStatusSuccessCode {
return false, errors.New("HTTP请求错误请检查重试")
}
if resp.Content.Code != ResponseCodeSuccess {
return false, fmt.Errorf("%v", XpuErrMsg2[resp.Content.Msg])
}
return resp.Content.Data.(bool), nil
}
//9.查询打印机某天的订单统计数
func (a *API) QueryOrderStatis(request *QueryOrderStatisRequest) (printed, waiting float64, err error) {
url := baseURL + "queryOrderStatis"
request.RestRequest = a.GenerateRestRequest()
resp := xpyunPostJson(url, request)
if resp.HttpStatusCode != HttpStatusSuccessCode {
return 0, 0, errors.New("HTTP请求错误请检查重试")
}
if resp.Content.Code != ResponseCodeSuccess {
return 0, 0, fmt.Errorf("%v", XpuErrMsg2[resp.Content.Msg])
}
retVal, _ := resp.Content.Data.(map[string]interface{})
if retVal != nil {
printed = retVal["printed"].(float64)
waiting = retVal["waiting"].(float64)
return printed, waiting, nil
}
return 0, 0, nil
}
//10.获取指定打印机状态
//* 0、离线 1、在线正常 2、在线不正常
// * 备注异常一般是无纸离线的判断是打印机与服务器失去联系超过30秒
func (a *API) QueryPrinterStatus(sn string) (interface{}, error) {
url := baseURL + "queryPrinterStatus"
request := &QueryPrinterStatusRequest{
RestRequest: a.GenerateRestRequest(),
Sn: sn,
}
resp := xpyunPostJson(url, request)
if resp.HttpStatusCode != HttpStatusSuccessCode {
return PrinterStateError, errors.New("HTTP请求错误请检查重试")
}
if resp.Content.Code != ResponseCodeSuccess {
return PrinterStateError, fmt.Errorf("%v", XpuErrMsg2[resp.Content.Msg])
}
if resp.Content.Data != nil && resp.Content.Data.(float64) >= 0 {
return resp.Content.Data, nil
}
return PrinterStateError, nil
}
//11.批量获取指定打印机状态
func (a *API) QueryPrintersStatus(request *QueryPrintersStatusRequest) ([]float64, error) {
url := baseURL + "queryPrintersStatus"
request.RestRequest = a.GenerateRestRequest()
resp := xpyunPostJson(url, request)
if resp.HttpStatusCode != HttpStatusSuccessCode {
return nil, errors.New("HTTP请求错误请检查重试")
}
if resp.Content.Code != ResponseCodeSuccess {
return nil, fmt.Errorf("%v", XpuErrMsg2[resp.Content.Msg])
}
retVal := []float64{}
if resp.Content.Data != nil && resp.Content.Data.(float64) >= 0 {
for _, v := range resp.Content.Data.([]interface{}) {
retVal = append(retVal, v.(float64))
}
}
return nil, nil
}
//12.金额播报
func (a *API) PlayVoice(request *PlayVoiceRequest) error {
url := baseURL + "playVoice"
request.RestRequest = a.GenerateRestRequest()
resp := xpyunPostJson(url, request)
if resp.HttpStatusCode != HttpStatusSuccessCode {
return errors.New("HTTP请求错误请检查重试")
}
if resp.Content.Code != ResponseCodeSuccess {
return fmt.Errorf("%v", XpuErrMsg2[resp.Content.Msg])
}
return nil
}