commit
930cafc1e2
@ -0,0 +1,9 @@
|
||||
package address
|
||||
|
||||
type Address struct {
|
||||
ProvinceId uint `json:"provinceId"`
|
||||
CityId uint `json:"cityId"`
|
||||
CountyId uint `json:"countyId"`
|
||||
TownId uint `json:"townId"`
|
||||
FullAddress string `json:"fullAddress"`
|
||||
}
|
@ -0,0 +1,16 @@
|
||||
package jdsdk
|
||||
|
||||
import (
|
||||
"git.oa00.com/go/jdsdk/mq"
|
||||
"git.oa00.com/go/jdsdk/order"
|
||||
"git.oa00.com/go/jdsdk/sku"
|
||||
)
|
||||
|
||||
var Api = &api{}
|
||||
|
||||
type api struct {
|
||||
Sku sku.Sku
|
||||
Order order.Order
|
||||
Mq mq.Mq
|
||||
AfterSale order.AfterSale
|
||||
}
|
@ -0,0 +1,38 @@
|
||||
package config
|
||||
|
||||
var SdkConfig = Config{}
|
||||
|
||||
// ConfigInit @Title 初始化配置
|
||||
func ConfigInit(config Config) {
|
||||
SdkConfig = config
|
||||
}
|
||||
|
||||
type Config struct {
|
||||
Url string // api地址
|
||||
TokenUrl string // api
|
||||
MqUrl string // mq地址
|
||||
AppKey string // appKey
|
||||
AppSecret string // appSecret
|
||||
AccessToken string // accessToken
|
||||
RefreshToken string // refreshToken
|
||||
ChannelId uint // channelId
|
||||
CustomerId uint // customerId
|
||||
OpName string // 账号
|
||||
Pin string // 下单账号
|
||||
AccountId uint // 账号id
|
||||
AccessKey string // accessKey
|
||||
SecretKey string // secretKey
|
||||
RefreshTokenCallback func(token *Bearer)
|
||||
}
|
||||
|
||||
type Bearer struct {
|
||||
AccessToken string `json:"access_token"`
|
||||
ExpiresIn uint `json:"expires_in"`
|
||||
RefreshToken string `json:"refresh_token"`
|
||||
Scope string `json:"scope"`
|
||||
UID string `json:"uid"`
|
||||
Time int64 `json:"time"`
|
||||
TokenType string `json:"token_type"`
|
||||
Code uint `json:"code"`
|
||||
Xid string `json:"xid"`
|
||||
}
|
@ -0,0 +1,5 @@
|
||||
module git.oa00.com/go/jdsdk
|
||||
|
||||
go 1.17
|
||||
|
||||
require github.com/mitchellh/mapstructure v1.5.0
|
@ -0,0 +1,2 @@
|
||||
github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY=
|
||||
github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
|
@ -0,0 +1,283 @@
|
||||
package mq
|
||||
|
||||
import (
|
||||
"git.oa00.com/go/jdsdk/request"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
const (
|
||||
skuChange = "sku_change"
|
||||
skuPriceChange = "sku_price_change"
|
||||
orderCreate = "order_create"
|
||||
orderPay = "order_pay"
|
||||
orderStockOut = "order_stockout"
|
||||
orderDelivered = "order_delivered"
|
||||
orderFinish = "order_finish"
|
||||
orderCancel = "order_cancel"
|
||||
orderRefund = "order_refund"
|
||||
afsCreate = "afs_create"
|
||||
afsStepResult = "afs_step_result"
|
||||
balanceEarlyWarning = "order_balance_not_enough"
|
||||
|
||||
AckSuccess = "SUCCESS"
|
||||
AckFailed = "CONSUME_FAILED"
|
||||
AckRESEND = "RESEND"
|
||||
AckDISCARD = "DISCARD"
|
||||
|
||||
SkuTypeDelete = 0 // 删除
|
||||
SkuTypeAdd = 1 // 新增
|
||||
SkuTypeEdit = 2 // 修改
|
||||
SkuTypeRecovery = 3 // 删除恢复
|
||||
|
||||
OrderModelNormal = 1 // 正常订单
|
||||
OrderModelAfter = 2 // 售后订单
|
||||
|
||||
OrderCancelStatusSuccess = 1 // 取消成功
|
||||
OrderCancelStatusFail = 2 // 取消失败
|
||||
OrderCancelStatusApply = 3 // 申请取消
|
||||
OrderCancelStatusReject = 4 // 申请拒收
|
||||
)
|
||||
|
||||
type Mq struct {
|
||||
}
|
||||
|
||||
type MessageSku struct {
|
||||
Type int `json:"type"` // 0=删除 1=新增 2=修改 3=删除
|
||||
SkuId uint64 `json:"skuId"`
|
||||
Timestamp int64 `json:"timestamp"`
|
||||
}
|
||||
|
||||
// SkuChange @Title sku变动
|
||||
func (m *Mq) SkuChange(handler func(message request.Message)) {
|
||||
run(skuChange, handler)
|
||||
}
|
||||
|
||||
// SkuPriceChange @Title sku价格变动
|
||||
func (m *Mq) SkuPriceChange(handler func(message request.Message)) {
|
||||
run(skuPriceChange, handler)
|
||||
}
|
||||
|
||||
type OrderCreate struct {
|
||||
OrderId uint64 `json:"orderId"` // 订单号
|
||||
DParentOrderId uint64 `json:"dParentOrderId"` // 父订单号
|
||||
AutoCancelSeconds string `json:"autoCancelSeconds"` // 订单自动取消时间 秒数
|
||||
Yn uint `json:"yn"` // 是否有效 1=有效 0=无效
|
||||
CreateTime string `json:"createTime"` // 订单创建时间 Y/m/d H:i
|
||||
TotalFee float64 `json:"totalFee"` // 总金额 包含运费
|
||||
FreightFee string `json:"freightFee"` // 运费
|
||||
Timestamp int64 `json:"timestamp"` // 请求时间
|
||||
SkuList []OrderSkuItem `json:"skuList"` // sku列表
|
||||
ChannelOrderId string `json:"channelOrderId"` // 渠道订单号
|
||||
RootOrderId uint64 `json:"rootOrderId"` // 顶级订单号
|
||||
OrderModel int `json:"orderModel"` // 订单模式 1=正常订单 2=售后订单
|
||||
DiscountFee float64 `json:"discountFee"` // 优惠金额
|
||||
AfsOrderInfo OrderAfsItem `json:"afsOrderInfo"` // 售后单信息
|
||||
}
|
||||
type OrderAfsItem struct {
|
||||
OrderId uint64 `json:"orderId"` // 售后订单号
|
||||
ParentOrderId uint64 `json:"parentOrderId"` // 售后父订单号
|
||||
ServiceId uint64 `json:"serviceId"` // 售后单号
|
||||
}
|
||||
type OrderSkuItem struct {
|
||||
SkuId uint64 `json:"skuId"` // skuId
|
||||
SkuName string `json:"skuName"` // 商品名称
|
||||
Quantity int `json:"quantity"` // 数量
|
||||
Price float64 `json:"price"` // 单价
|
||||
SkuType int `json:"skuType"` // 商品类型 1=主品 2=赠品
|
||||
MainSkuId uint64 `json:"mainSkuId"` // 赠品对应主品skuId
|
||||
}
|
||||
|
||||
// OrderCreate @Title 订单创建
|
||||
func (m *Mq) OrderCreate(handler func(message request.Message)) {
|
||||
run(orderCreate, handler)
|
||||
}
|
||||
|
||||
type OrderPay struct {
|
||||
OrderId uint64 `json:"orderId"` // 订单号
|
||||
PayTime string `json:"payTime"` // 支付时间
|
||||
RealPayFee float64 `json:"realPayFee"` // 实际支付金额
|
||||
Timestamp int64 `json:"timestamp"` // 时间戳
|
||||
ChannelOrderId string `json:"channelOrderId"` // 渠道单号
|
||||
DParentOrderId uint64 `json:"dParentOrderId"` // 父订单号
|
||||
RootOrderId uint64 `json:"rootOrderId"` // 顶级订单号
|
||||
}
|
||||
|
||||
// OrderPay @Title 订单支付
|
||||
func (m *Mq) OrderPay(handler func(message request.Message)) {
|
||||
run(orderPay, handler)
|
||||
}
|
||||
|
||||
type OrderStockOut struct {
|
||||
OrderId uint64 `json:"orderId"` // 订单号
|
||||
Packages []Package `json:"packages"` // 包裹
|
||||
Timestamp int64 `json:"timestamp"` // 时间戳
|
||||
ChannelOrderId string `json:"channelOrderId"` // 渠道单号
|
||||
DParentOrderId uint64 `json:"dParentOrderId"` // 父订单号
|
||||
RootOrderId uint64 `json:"rootOrderId"` // 顶级订单号
|
||||
}
|
||||
|
||||
type Package struct {
|
||||
OutboundTime string `json:"outboundTime"` // 出库时间
|
||||
LogisticsCode string `json:"logisticsCode"` // 物流编码
|
||||
LogisticsName string `json:"logisticsName"` // 物流名称
|
||||
WaybillCode string `json:"waybillCode"` // 运单号
|
||||
OutLogisticsCode string `json:"outLogisticsCode"` // 物流外部编码
|
||||
SkuList []PackageSku `json:"skuList"` // sku列表
|
||||
}
|
||||
|
||||
type PackageSku struct {
|
||||
SkuId string `json:"skuId"` // skuId
|
||||
SkuName string `json:"skuName"` // 名称
|
||||
Quantity uint `json:"quantity"` // 数量
|
||||
}
|
||||
|
||||
// GetSkuIdUint64 @Title 获取uint64
|
||||
func (p *PackageSku) GetSkuIdUint64() uint64 {
|
||||
skuId, _ := strconv.ParseUint(p.SkuId, 10, 64)
|
||||
return skuId
|
||||
}
|
||||
|
||||
// OrderStockOut @Title 订单出库
|
||||
func (m *Mq) OrderStockOut(handler func(message request.Message)) {
|
||||
run(orderStockOut, handler)
|
||||
}
|
||||
|
||||
type OrderDelivered struct {
|
||||
OrderId uint64 `json:"orderId"` // 订单号
|
||||
OpeTime string `json:"opeTime"` // 妥投时间 Y/m/d H:i
|
||||
Timestamp int64 `json:"timestamp"` // 时间戳
|
||||
ChannelOrderId string `json:"channelOrderId"` // 渠道单号
|
||||
DParentOrderId uint64 `json:"dParentOrderId"` // 父订单号
|
||||
RootOrderId uint64 `json:"rootOrderId"` // 顶级订单号
|
||||
}
|
||||
|
||||
// OrderDelivered @Title 订单妥投
|
||||
func (m *Mq) OrderDelivered(handler func(message request.Message)) {
|
||||
run(orderDelivered, handler)
|
||||
}
|
||||
|
||||
type OrderFinish struct {
|
||||
OrderId uint64 `json:"orderId"` // 订单号
|
||||
FinishedTime string `json:"finishedTime"` // 完成时间 Y/m/d H:i
|
||||
Timestamp int64 `json:"timestamp"` // 时间戳
|
||||
ChannelOrderId string `json:"channelOrderId"` // 渠道单号
|
||||
DParentOrderId uint64 `json:"dParentOrderId"` // 父订单号
|
||||
RootOrderId uint64 `json:"rootOrderId"` // 顶级订单号
|
||||
}
|
||||
|
||||
// OrderFinish @Title 订单完成
|
||||
func (m *Mq) OrderFinish(handler func(message request.Message)) {
|
||||
run(orderFinish, handler)
|
||||
}
|
||||
|
||||
type OrderCancel struct {
|
||||
OrderId uint64 `json:"orderId"` // 订单号
|
||||
CreateTime string `json:"createTime"` // 取消成功时间 Y/m/d H:i
|
||||
CancelStatus uint `json:"cancelStatus"` // 取消状态 1=取消成功 2=取消失败 3=申请取消 4=申请拒收
|
||||
ExtendInfo string `json:"extendInfo"` // 拓展字段
|
||||
Timestamp int64 `json:"timestamp"` // 时间戳
|
||||
ChannelOrderId string `json:"channelOrderId"` // 渠道单号
|
||||
DParentOrderId uint64 `json:"dParentOrderId"` // 父订单号
|
||||
RootOrderId uint64 `json:"rootOrderId"` // 顶级订单号
|
||||
RootOrderStatus uint `json:"rootOrderStatus"` // 订单取消前的状态 0=已代扣 1=未代扣
|
||||
}
|
||||
|
||||
// OrderCancel @Title 订单取消
|
||||
func (m *Mq) OrderCancel(handler func(message request.Message)) {
|
||||
run(orderCancel, handler)
|
||||
}
|
||||
|
||||
type OrderRefund struct {
|
||||
OrderId uint64 `json:"orderId"` // 订单号
|
||||
RefundTime string `json:"refundTime"` // 退款时间 无效
|
||||
ServiceNumber string `json:"service_number"` // 京东服务单号
|
||||
SkuList []PackageSku `json:"skuList"` // sku列表
|
||||
RefundType uint `json:"refundType"` // 退款类型 1=售后退款 2=取消退款 3=多支付退款 4=余额提现 5=整单二次退款
|
||||
RefundFee float64 `json:"refundFee"` // 退款金额
|
||||
RefundId string `json:"refundId"` // 退款编码
|
||||
Timestamp int64 `json:"timestamp"` // 时间戳
|
||||
ChannelOrderId string `json:"channelOrderId"` // 渠道单号
|
||||
DParentOrderId uint64 `json:"dParentOrderId"` // 父订单号
|
||||
RootOrderId uint64 `json:"rootOrderId"` // 顶级订单号
|
||||
}
|
||||
|
||||
// OrderRefund @Title 退款成功
|
||||
func (m *Mq) OrderRefund(handler func(message request.Message)) {
|
||||
run(orderRefund, handler)
|
||||
}
|
||||
|
||||
type AfsCreate struct {
|
||||
OrderId uint64 `json:"orderId"` // 订单号
|
||||
AfsApplyTime int64 `json:"afsApplyTime"` // 售后申请时间 Y/m/d H:i
|
||||
ChannelAfsApplyId string `json:"channelAfsApplyId"` // 渠道售后单号
|
||||
AfsServiceId uint64 `json:"afsServiceId"` // 京东收好单号
|
||||
SkuId uint64 `json:"skuId"` // skuId
|
||||
SkuName string `json:"skuName"` // 商品名称
|
||||
AfsType uint `json:"afsType"` // 售后类型 10=退货 20=换货
|
||||
AfsApplyId uint64 `json:"afsApplyId"` // 售后申请单号
|
||||
Timestamp int64 `json:"timestamp"` // 时间戳
|
||||
ChannelOrderId string `json:"channelOrderId"` // 渠道单号
|
||||
}
|
||||
|
||||
// AfsCreate @Title 售后创建
|
||||
func (m *Mq) AfsCreate(handler func(message request.Message)) {
|
||||
run(afsCreate, handler)
|
||||
}
|
||||
|
||||
type AfsStepResult struct {
|
||||
OrderId uint64 `json:"orderId"` // 订单号
|
||||
AfsServiceId uint64 `json:"afsServiceId"` // 京东售后单号
|
||||
AfsResultType string `json:"afsResultType"` // 京东售后单号
|
||||
// 售后状态 APPLY=创建售后 AUDIT_FAIL=审核驳回 CANCEL=审核取消 COMPENSATE_BALANCE=直赔余额 OA_COMPENSATION=直赔商品 PICKWARE_SEND=客户发货
|
||||
// POP_REISSUE=POP补发商品 REFUND_NO_RETURN=退款不退货 OA_COMPENSATION_NEWORDER=直赔商品生成新订单
|
||||
// AFS_RECV_PRODUCT=收到商品 OA_REWORK=返修换新 RETURN=原反 RETURN_CANCEL=原反取消 FORCECOMPLETE=强制关单
|
||||
// OA_REWORK_NEWORDER=换修换新生成新订单 POP_UNDERLINENEWORDER=pop线下换新 REFUND_APPLY=退款申请 CUSTOMER_CONFIRM=待用户确认
|
||||
// REFUND=退款 CUSTOMER_COMPLETE=用户已解决
|
||||
SkuId uint64 `json:"skuId"` // skuId
|
||||
SkuName string `json:"skuName"` // 商品名称
|
||||
AfsType uint `json:"afsType"` // 售后类型 10=退货 20=换货
|
||||
StepType string `json:"stepType"` // 处理环节 APPLY=申请 AUDIT=审核 RECEIVED=收货 PROCESS=处理 CONFIRM=确认 COMPLETE=用户已解决
|
||||
OperationDate string `json:"operationDate"` // 操作时间 Y-m-d H:i:s
|
||||
Timestamp int64 `json:"timestamp"` // 时间戳
|
||||
}
|
||||
|
||||
// AfsStepResult @Title 售后处理
|
||||
func (m *Mq) AfsStepResult(handler func(message request.Message)) {
|
||||
run(afsStepResult, handler)
|
||||
}
|
||||
|
||||
type BalanceEarlyWarning struct {
|
||||
CustomerNum string `json:"customerNum"` // 钱包号
|
||||
Msg string `json:"msg"` // 不足提示
|
||||
}
|
||||
|
||||
// BalanceEarlyWarning @Title 余额预警
|
||||
func (m *Mq) BalanceEarlyWarning(handler func(message request.Message)) {
|
||||
run(balanceEarlyWarning, handler)
|
||||
}
|
||||
|
||||
type ack struct {
|
||||
action string
|
||||
}
|
||||
|
||||
func (a *ack) Ack() {
|
||||
}
|
||||
|
||||
// @Title 调用请求
|
||||
func run(action string, handler func(message request.Message)) {
|
||||
defer func() {
|
||||
if err := recover(); err != nil {
|
||||
run(action, handler)
|
||||
}
|
||||
}()
|
||||
for true {
|
||||
mq, err := request.ExecMq(action)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
if len(mq.Messages) == 0 {
|
||||
continue
|
||||
}
|
||||
handler(mq)
|
||||
}
|
||||
}
|
@ -0,0 +1,324 @@
|
||||
package request
|
||||
|
||||
import (
|
||||
"crypto/hmac"
|
||||
"crypto/md5"
|
||||
"crypto/sha1"
|
||||
"encoding/base64"
|
||||
"encoding/hex"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"git.oa00.com/go/jdsdk/config"
|
||||
"github.com/mitchellh/mapstructure"
|
||||
"log"
|
||||
"net/url"
|
||||
"reflect"
|
||||
"sort"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
type ctpProtocol struct {
|
||||
AppKey string `json:"appKey"`
|
||||
ChannelId uint `json:"channelId"`
|
||||
CustomerId uint `json:"customerId"`
|
||||
OpName string `json:"opName"`
|
||||
TraceId string `json:"traceId"`
|
||||
}
|
||||
|
||||
type resp struct {
|
||||
Code string `json:"code"`
|
||||
Result struct {
|
||||
ErrMsg string `json:"errMsg"`
|
||||
Data interface{} `json:"data"`
|
||||
StockStateList interface{} `json:"StockStateList"`
|
||||
Success bool `json:"success"`
|
||||
ErrCode int `json:"errCode"`
|
||||
} `json:"result"`
|
||||
}
|
||||
|
||||
type RespErr struct {
|
||||
ErrorResponse struct {
|
||||
Code string `json:"code"`
|
||||
ZhDesc string `json:"zh_desc"`
|
||||
EnDesc string `json:"en_desc"`
|
||||
} `json:"error_response"`
|
||||
}
|
||||
|
||||
// @Title 调用接口
|
||||
func exec(action string, data string, result interface{}) error {
|
||||
t := time.Now().Format("2006-01-02 15:04:05")
|
||||
params := url.Values{
|
||||
"app_key": {config.SdkConfig.AppKey},
|
||||
"method": {action},
|
||||
"access_token": {config.SdkConfig.AccessToken},
|
||||
"v": {"2.0"},
|
||||
"format": {"json"},
|
||||
"timestamp": {t},
|
||||
"360buy_param_json": {data},
|
||||
}
|
||||
params.Add("sign", Sign(params))
|
||||
bytes, err := request("GET", fmt.Sprintf("%s?%s", config.SdkConfig.Url, params.Encode()), "")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
log.Println(string(bytes))
|
||||
respErr := RespErr{}
|
||||
json.Unmarshal(bytes, &respErr)
|
||||
if respErr.ErrorResponse.Code != "" {
|
||||
if respErr.ErrorResponse.Code == "19" && config.SdkConfig.RefreshTokenCallback != nil {
|
||||
token, err := RefreshToken()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
config.SdkConfig.RefreshTokenCallback(token)
|
||||
}
|
||||
return errors.New(respErr.ErrorResponse.ZhDesc)
|
||||
}
|
||||
mResp := map[string]resp{}
|
||||
json.Unmarshal(bytes, &mResp)
|
||||
for _, val := range mResp {
|
||||
if val.Result.ErrCode != 200 {
|
||||
return errors.New(val.Result.ErrMsg)
|
||||
}
|
||||
if val.Result.Data != nil {
|
||||
err = mapstructure.Decode(val.Result.Data, &result)
|
||||
}
|
||||
if val.Result.StockStateList != nil {
|
||||
err = mapstructure.Decode(val.Result.StockStateList, &result)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
return errors.New("接口请求错误")
|
||||
}
|
||||
|
||||
// ExecProtocol @Title 调用接口
|
||||
func ExecProtocol(action string, data interface{}, result interface{}) error {
|
||||
requestData := map[string]interface{}{
|
||||
"protocol": ctpProtocol{
|
||||
AppKey: config.SdkConfig.AppKey,
|
||||
ChannelId: config.SdkConfig.ChannelId,
|
||||
CustomerId: config.SdkConfig.CustomerId,
|
||||
OpName: config.SdkConfig.OpName,
|
||||
TraceId: "",
|
||||
},
|
||||
getStructName(data): data,
|
||||
}
|
||||
jsonData, _ := json.Marshal(&requestData)
|
||||
return exec(action, string(jsonData), result)
|
||||
}
|
||||
|
||||
// ExecCtlProtocol @Title 调用接口
|
||||
func ExecCtlProtocol(action string, data interface{}, result interface{}) error {
|
||||
requestData := map[string]interface{}{
|
||||
"ctpProtocol": ctpProtocol{
|
||||
AppKey: config.SdkConfig.AppKey,
|
||||
ChannelId: config.SdkConfig.ChannelId,
|
||||
CustomerId: config.SdkConfig.CustomerId,
|
||||
OpName: config.SdkConfig.OpName,
|
||||
TraceId: "",
|
||||
},
|
||||
getStructName(data): data,
|
||||
}
|
||||
jsonData, _ := json.Marshal(&requestData)
|
||||
return exec(action, string(jsonData), result)
|
||||
}
|
||||
|
||||
// ExecParam @Title 调用接口
|
||||
func ExecParam(action string, data map[string]interface{}, result interface{}) error {
|
||||
requestData := map[string]interface{}{
|
||||
"appKey": config.SdkConfig.AppKey,
|
||||
"channelId": config.SdkConfig.ChannelId,
|
||||
"customerId": config.SdkConfig.CustomerId,
|
||||
"traceId": "",
|
||||
"pin": config.SdkConfig.Pin,
|
||||
"clientIp": "127.0.0.1",
|
||||
}
|
||||
for key, item := range data {
|
||||
requestData[key] = item
|
||||
}
|
||||
jsonData, _ := json.Marshal(&requestData)
|
||||
return exec(action, string(jsonData), result)
|
||||
}
|
||||
|
||||
type mqResult struct {
|
||||
RequestId string `json:"requestId"`
|
||||
Result Message `json:"result"`
|
||||
Error resError `json:"error"`
|
||||
}
|
||||
|
||||
type Message struct {
|
||||
TopicName string `json:"topicName"`
|
||||
AckIndex string `json:"ackIndex"`
|
||||
Messages []MessageItem `json:"messages"`
|
||||
Action string `json:"action"`
|
||||
}
|
||||
|
||||
type MessageItem struct {
|
||||
MessageId string `json:"messageId"`
|
||||
MessageBody string `json:"messageBody"`
|
||||
}
|
||||
|
||||
type resError struct {
|
||||
Code int `json:"code"`
|
||||
Message string `json:"message"`
|
||||
Status string `json:"status"`
|
||||
}
|
||||
|
||||
const (
|
||||
AckActionSuccess = "SUCCESS" // 消费成功
|
||||
AckActionFailed = "CONSUME_FAILED" // 消费失败,服务端会进行重新推送
|
||||
AckActionResend = "RESEND" // 立即重发
|
||||
AckActionDiscard = "DISCARD" // 丢弃消息,服务端不会进行重试
|
||||
)
|
||||
|
||||
// Success @Title 消费成功
|
||||
func (m *Message) Success() error {
|
||||
return m.ack(AckActionSuccess)
|
||||
}
|
||||
|
||||
// Failed @Title 消费失败,服务端会进行重新推送
|
||||
func (m *Message) Failed() error {
|
||||
return m.ack(AckActionFailed)
|
||||
}
|
||||
|
||||
// Resend @Title 立即重发
|
||||
func (m *Message) Resend() error {
|
||||
return m.ack(AckActionResend)
|
||||
}
|
||||
|
||||
// Discard @Title 丢弃消息,服务端不会进行重试
|
||||
func (m *Message) Discard() error {
|
||||
return m.ack(AckActionDiscard)
|
||||
}
|
||||
|
||||
// Ack @Title 确认消息
|
||||
func (m *Message) ack(ackAction string) error {
|
||||
dateTime := time.Now().UTC().Format("2006-01-02T15:04:05Z")
|
||||
data := map[string]string{
|
||||
"topic": m.TopicName,
|
||||
"consumerGroupId": fmt.Sprintf("open_message_%d", config.SdkConfig.AccountId),
|
||||
"ackAction": ackAction,
|
||||
"ackIndex": m.AckIndex,
|
||||
"accessKey": config.SdkConfig.AccessKey,
|
||||
"dateTime": dateTime,
|
||||
}
|
||||
sign := MqSign(data)
|
||||
jsonData, _ := json.Marshal(&data)
|
||||
bytes, err := request(post, config.SdkConfig.MqUrl+"/ack", string(jsonData), map[string]string{
|
||||
"accessKey": config.SdkConfig.AccessKey,
|
||||
"dateTime": dateTime,
|
||||
"signature": sign,
|
||||
"Content-Type": "application/json",
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
res := mqResult{}
|
||||
if err := json.Unmarshal(bytes, &res); err != nil {
|
||||
return err
|
||||
}
|
||||
if res.Error.Code > 0 {
|
||||
return errors.New(res.Error.Message)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// ExecMq @Title 调用mq
|
||||
func ExecMq(action string) (Message, error) {
|
||||
data := map[string]string{
|
||||
"topic": fmt.Sprintf("open_message_ct_%s_%s", action, config.SdkConfig.AppKey),
|
||||
"consumerGroupId": fmt.Sprintf("open_message_%d", config.SdkConfig.AccountId),
|
||||
}
|
||||
value := url.Values{}
|
||||
for k, v := range data {
|
||||
value.Set(k, v)
|
||||
}
|
||||
dateTime := time.Now().UTC().Format("2006-01-02T15:04:05Z")
|
||||
data["accessKey"] = config.SdkConfig.AccessKey
|
||||
data["dateTime"] = dateTime
|
||||
|
||||
sign := MqSign(data)
|
||||
bytes, err := request(get, config.SdkConfig.MqUrl+"/messages?"+value.Encode(), "", map[string]string{
|
||||
"accessKey": config.SdkConfig.AccessKey,
|
||||
"dateTime": dateTime,
|
||||
"signature": sign,
|
||||
})
|
||||
if err != nil {
|
||||
return Message{}, err
|
||||
}
|
||||
res := mqResult{}
|
||||
if err := json.Unmarshal(bytes, &res); err != nil {
|
||||
return Message{}, err
|
||||
}
|
||||
res.Result.Action = action
|
||||
if res.Error.Code > 0 {
|
||||
return res.Result, errors.New(res.Error.Message)
|
||||
}
|
||||
return res.Result, err
|
||||
}
|
||||
|
||||
func map2str(data map[string]string, sep string) string {
|
||||
var temp []string
|
||||
for key, _ := range data {
|
||||
temp = append(temp, key)
|
||||
}
|
||||
sort.Strings(temp)
|
||||
var tt []string
|
||||
for _, v := range temp {
|
||||
tt = append(tt, fmt.Sprintf("%s=%s", v, data[v]))
|
||||
}
|
||||
return strings.Join(tt, sep)
|
||||
}
|
||||
|
||||
// MqSign @Title mq签名
|
||||
func MqSign(data map[string]string) string {
|
||||
h := hmac.New(sha1.New, []byte(config.SdkConfig.SecretKey))
|
||||
str := map2str(data, "&")
|
||||
h.Write([]byte(str))
|
||||
return base64.StdEncoding.EncodeToString(h.Sum(nil))
|
||||
}
|
||||
|
||||
// RefreshToken @Title 刷新token
|
||||
func RefreshToken() (*config.Bearer, error) {
|
||||
value := url.Values{}
|
||||
value.Set("app_key", config.SdkConfig.AppKey)
|
||||
value.Set("app_secret", config.SdkConfig.AppSecret)
|
||||
value.Set("refresh_token", config.SdkConfig.RefreshToken)
|
||||
value.Set("grant_type", "refresh_token")
|
||||
data, err := request(get, fmt.Sprintf("%s?%s", config.SdkConfig.TokenUrl, value.Encode()), "")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var b config.Bearer
|
||||
if err = json.Unmarshal(data, &b); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &b, nil
|
||||
}
|
||||
|
||||
// Sign @Title 签名
|
||||
func Sign(params url.Values) string {
|
||||
h := md5.New()
|
||||
var order []string
|
||||
for key, _ := range params {
|
||||
order = append(order, key)
|
||||
}
|
||||
sort.Strings(order)
|
||||
h.Write([]byte(config.SdkConfig.AppSecret))
|
||||
for _, value := range order {
|
||||
h.Write([]byte(fmt.Sprintf("%s%s", value, params.Get(value))))
|
||||
}
|
||||
h.Write([]byte(config.SdkConfig.AppSecret))
|
||||
return strings.ToUpper(hex.EncodeToString(h.Sum(nil)))
|
||||
}
|
||||
|
||||
// 字符串首字母小写
|
||||
func getStructName(obj interface{}) string {
|
||||
s := reflect.TypeOf(obj).Name()
|
||||
if s == "" {
|
||||
return ""
|
||||
}
|
||||
return strings.ToLower(s[:1]) + s[1:]
|
||||
}
|
@ -0,0 +1,37 @@
|
||||
package request
|
||||
|
||||
import (
|
||||
"io"
|
||||
"net/http"
|
||||
"strings"
|
||||
)
|
||||
|
||||
const (
|
||||
post = "POST"
|
||||
get = "GET"
|
||||
)
|
||||
|
||||
var client = &http.Client{}
|
||||
|
||||
// @Title 请求
|
||||
func request(method, url, data string, headers ...map[string]string) ([]byte, error) {
|
||||
reqest, err := http.NewRequest(method, url, strings.NewReader(data))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(headers) > 0 {
|
||||
for key, value := range headers[0] {
|
||||
reqest.Header.Add(key, value)
|
||||
}
|
||||
}
|
||||
response, err := client.Do(reqest)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer response.Body.Close()
|
||||
result, err := io.ReadAll(response.Body)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return result, nil
|
||||
}
|
Loading…
Reference in new issue