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