提交 79ef27e3 authored 作者: gukai's avatar gukai

Merge branch 'master' of https://gitlab.jxhh.com/stbz/library

* 'master' of https://gitlab.jxhh.com/stbz/library:
  京东
  京东
/go.sum
/.idea
......@@ -5,6 +5,7 @@ go 1.16
require (
github.com/gogf/gf v1.16.6
github.com/kjk/betterguid v0.0.0-20170621091430-c442874ba63a
github.com/nsqio/go-nsq v1.1.0
github.com/olivere/elastic/v7 v7.0.30
)
差异被折叠。
package logs
import (
"context"
"fmt"
"github.com/gogf/gf/errors/gerror"
"github.com/gogf/gf/frame/g"
"github.com/gogf/gf/os/glog"
)
type RequestLogReq struct {
Path string //存储路径
RequestURI string //请求URI
......@@ -20,13 +20,14 @@ type RequestLogReq struct {
ResponseTime int64 //响应时间 毫秒级
}
const FormatErr = "参数【%v】错误【%v】响应时间【%v】"
const FormatSuc = "参数【%v】响应【%v】响应时间【%v】"
//统一请求日志 20211208 gk
func RequestLog(req RequestLogReq){
func RequestLog(req RequestLogReq) {
Info(req.Path, "请求ID:【%v】 服务名称: 【%v】 请求路径:【%v】 请求方法: 【%v】 请求参数: 【%v】 响应参数: 【%v】 响应时间:【%v ms】error:【%v】",
req.RequestID, req.ServerName, req.RequestURI, req.Method, req.Params,req.Response, req.ResponseTime, nil)
Info(req.Path, "请求ID:【%v】 服务名称: 【%v】 请求路径:【%v】 请求方法: 【%v】 请求参数: 【%v】 响应参数: 【%v】 响应时间:【%v ms】error:【%v】",
req.RequestID, req.ServerName, req.RequestURI, req.Method, req.Params, req.Response, req.ResponseTime, nil)
if req.Err != nil {
Error("%+v", gerror.Wrap(req.Err, req.RequestID))
......@@ -35,9 +36,9 @@ func RequestLog(req RequestLogReq){
}
//记录info日志 20211208 gk
func Info(path string,format string, v ...interface{}) {
func Info(path string, format string, v ...interface{}) {
newPath := g.Log().GetPath() + "/" + path
glog.Path(newPath).File( "info-{Ymd}.log").Println(fmt.Sprintf(format, v...))
glog.Path(newPath).File("info-{Ymd}.log").Println(fmt.Sprintf(format, v...))
}
//记录error日志 20211208 gk
......@@ -49,8 +50,16 @@ func Error(format string, v ...interface{}) {
//检查错误 20211208 gk
func CheckErr(err error, extra string) bool {
if err != nil {
Error("%+v",gerror.Wrap(err, extra))
Error("%+v", gerror.Wrap(err, extra))
return true
}
return false
}
\ No newline at end of file
}
func Infof(ctx context.Context, path string, format string, v ...interface{}) {
g.Log().Ctx(ctx).Cat(path).Infof(format, v...)
}
func Errorf(ctx context.Context, format string, v ...interface{}) {
g.Log().Ctx(ctx).Cat("error").Infof(format, v...)
}
## stbz/library
胜天半子内部调用库
## 地址
https://gitlab.jxhh.com/stbz/library
## 限制
golang版本 >= 1.16
## 使用方法
```golang
package main
import (
"github.com/gogf/gf/net/ghttp"
"gitlab.jxhh.com/stbz/library.git/upstream/jingdong"
)
//初始化配置【可在boot使用】
var conf *jingdong.Config
_ = g.Cfg().GetStruct("jd", &conf
jingdong.New(conf)
//订单详情
InfoRes,err:=jingdong.Order.GetOrderInfo(ctx, "236317795961")
g.Dump(InfoRes)
g.Dump(err)
//地址解析
ParseRes, err := jingdong.Address.Parse(ctx, "四川省成都市武侯区天府四街保利星座5栋")
g.Dump(ParseRes)
g.Dump(err)
```
package jingdong
import (
"context"
"github.com/gogf/gf/crypto/gmd5"
"github.com/gogf/gf/encoding/gjson"
"github.com/gogf/gf/frame/g"
"github.com/gogf/gf/os/gtime"
"github.com/gogf/gf/util/gconv"
"gitlab.jxhh.com/stbz/library.git/logs"
"net/url"
"strings"
"time"
)
type Config struct {
ApiUrl string
BasePathUrl string
GetTokenUrl string
RefreshTokenUrl string
AppKey string
AppSecret string
UserName string
PassWord string
Mobile string
Email string
SubmitState string
CompanyName string
}
type CommonRes struct {
Success bool `json:"success"`
ResultCode string `json:"resultCode"`
ResultMessage string `json:"resultMessage"`
}
type client struct {
*Config
AccessToken string
}
var server *client
const CacheKey = "jingdong:token"
const pkgName = "jingdong"
func New(config *Config) {
_ = gconv.Scan(config, &server)
return
}
//post 请求
func (s *client) post(ctx context.Context, method string, params g.MapStrStr) (str string, err error) {
Start := gtime.TimestampMilli()
postValues := url.Values{}
for k, v := range params {
postValues.Add(k, v)
}
postString := postValues.Encode()
Request := g.Client()
Request.SetHeader("Content-Type", "application/x-www-form-urlencoded")
resp, err := Request.Timeout(time.Second*5).Post(method, postString)
defer func() {
_ = resp.Body.Close()
paramStr := gjson.New(params).MustToJsonString()
ctx = context.WithValue(ctx, "Method", "POST")
ctx = context.WithValue(ctx, "URI", method)
if err != nil {
logs.Errorf(ctx, logs.FormatErr, paramStr, err.Error(), gtime.TimestampMilli()-Start)
} else {
logs.Infof(ctx, pkgName, logs.FormatSuc, paramStr, str, gtime.TimestampMilli()-Start)
}
}()
if err != nil {
return
}
str = resp.ReadAllString()
return
}
//getSign 签名
func (s *client) getSign(timeStamp string) string {
var str = s.AppSecret + timeStamp + s.AppKey + s.UserName
return strings.ToUpper(gmd5.MustEncrypt(str + gmd5.MustEncrypt(s.PassWord) + "access_token" + s.AppSecret))
}
// requestApi 请求
func (s *client) requestApi(ctx context.Context, method string, businessParams g.MapStrStr) (str string, err error) {
params, err := s.createPostRequest(ctx, businessParams)
if err != nil {
return
}
urlMethod := s.ApiUrl + method
str, err = s.post(ctx, urlMethod, params)
return
}
func (s *client) createPostRequest(ctx context.Context, businessParams g.MapStrStr) (res g.MapStrStr, err error) {
err = s.getAccessToken(ctx)
if err != nil {
return
}
res = g.MapStrStr{
"token": s.AccessToken,
}
if businessParams != nil {
for k, v := range businessParams {
res[k] = v
}
}
return
}
package jingdong
import (
"context"
"github.com/gogf/gf/encoding/gjson"
"github.com/gogf/gf/util/gconv"
)
type addressJD struct {
}
var Address = addressJD{}
type ParseRes struct {
*CommonRes
Result struct {
NationId string `json:"nationId"` //国家ID
Nation string `json:"nation"` //国家名称
ProvinceId int `json:"provinceId"` //一级地址ID
Province string `json:"province"` //一级地址名称
CityId int `json:"cityId"` //二级地址ID
City string `json:"city"` //二级地址名称
CountyId int `json:"countyId"` //三级地址ID
County string `json:"county"` //三级地址名称
TownId int `json:"townId"` //四级地址ID
Town string `json:"town"` //四级地址名称
} `json:"result"`
}
type GetTownRes struct {
*CommonRes
Result map[string]int `json:"result"`
}
//Parse 地址详情转换京东地址编码
func (addressJD) Parse(ctx context.Context, address string) (res *ParseRes, err error) {
method := "area/getJDAddressFromAddress"
param := map[string]string{
"address": address,
}
result, err := server.requestApi(ctx, method, param)
if err != nil {
return
}
err = gjson.New(result).Scan(&res)
return
}
// CheckArea 验证地址有效性
func (addressJD) CheckArea(ctx context.Context, provinceId, cityId, countyId, townId interface{}) (res *CommonRes, err error) {
method := "area/checkArea"
param := map[string]string{
"provinceId": gconv.String(provinceId),
"cityId": gconv.String(cityId),
"countyId": gconv.String(countyId),
"townId": gconv.String(townId),
}
result, err := server.requestApi(ctx, method, param)
if err != nil {
return
}
err = gjson.New(result).Scan(&res)
return
}
// GetTown 查询四级地址
func (addressJD) GetTown(ctx context.Context, id interface{}) (res *GetTownRes, err error) {
method := "area/getTown"
param := map[string]string{
"id": gconv.String(id),
}
result, err := server.requestApi(ctx, method, param)
if err != nil {
return
}
err = gjson.New(result).Scan(&res)
return
}
package jingdong
import (
"context"
"github.com/gogf/gf/container/garray"
"github.com/gogf/gf/encoding/gjson"
"github.com/gogf/gf/frame/g"
"github.com/gogf/gf/util/gconv"
)
type goodsJD struct {
}
var Goods = goodsJD{}
type CheckSaleRes struct {
*CommonRes
Result []struct {
SkuId int `json:"skuid"` //商品编号
Name string `json:"name"` //商品名称
SaleState int `json:"saleState"` //是否可售 1:是,0:否
IsCanVAT int `json:"isCanVAT"` //是否可开增票,1:支持,0:不支持
Is7ToReturn int `json:"is7ToReturn"` //是否支持7天退货,1:是,0:不支持
} `json:"result"`
}
type CheckOnSaleRes struct {
*CommonRes
Result []struct {
Sku int `json:"sku"` //商品编号
State int `json:"state"` //1:上架,0:下架
} `json:"result"`
}
type GetStockRes struct {
*CommonRes
Result []struct {
SkuID int `json:"skuId"` //商品编号
AreaID string `json:"areaId"` //入参时传入的区域码area。因京东目前是3、4级地址均支持,存在areaId在传入的3级地址后填充4级地址“_0“后返回的情况。
StockStateID int `json:"stockStateId"` //存状态编号。 参考枚举值: 33,39,40,36,34,99
StockStateDesc string `json:"StockStateDesc"` /*库存状态描述。以下为stockStateId不同时,此字段不同的返回值:
33 有货 现货-下单立即发货
39 有货 在途-正在内部配货,预计2~6天到达本仓库
40 有货 可配货-下单后从有货仓库配货
36 预订
34 无货
99 无货开预定*/
} `json:"result"`
}
type CheckAreaLimitRes struct {
*CommonRes
Result []struct {
SkuID int `json:"skuId"` //商品编码
IsAreaRestrict bool `json:"isAreaRestrict"` //true 代表区域受限 false 区域不受限
} `json:"result"`
}
type GetProductsPriceRes struct {
*CommonRes
Result []struct {
SkuID int `json:"skuId"` //商品编码
Price float64 `json:"price"` //京东销售价
JdPrice float64 `json:"jdPrice"` //京东价
MarketPrice float64 `json:"marketPrice"` //京东的前台划线价
} `json:"result"`
}
type GetDetailRes struct {
*CommonRes
Result struct {
SaleUnit string `json:"saleUnit"` //售卖单位
Weight string `json:"weight"` //重量
ProductArea string `json:"productArea"` //产地
WareQD string `json:"wareQD"` //包装清单
ImagePath string `json:"imagePath"` //主图
State int `json:"state"` //状态
Sku int `json:"sku"` //商品编号
BrandName string `json:"brandName"` //品牌名称
Category string `json:"category"` //分类 示例"670;729;4837"
Name string `json:"name"` //商品名称
Introduction string `json:"introduction"` //商品详情页大字段
IsFactoryShip string `json:"isFactoryShip"` //1 厂商直送;0 非厂商直送
IsSelf int `json:"isSelf"` //是否自营
LowestBuy interface{} `json:"LowestBuy"` //商品最低起购量
Wxintroduction string `json:"wxintroduction"` //微信小程序商品详情大字段,仅提供图片地址
} `json:"result"`
}
type GetCategoryRes struct {
*CommonRes //异常代码(3422:获取分类列表信息失败;3423:分类列表不存在;1003:参数值不正确;5001:服务异常,请稍后重试;)
Result struct {
TotalRows int `json:"totalRows"`
PageNo int `json:"pageNo"`
PageSize int `json:"pageSize"`
Categorys []struct {
CatId int `json:"catId"` //分类ID
ParentId int `json:"parentId"` //父分类ID
Name string `json:"name"` //分类名称
CatClass int `json:"catClass"` //0:一级分类;1:二级分类;2:三级分类;
State int `json:"state"`
} `json:"categorys"`
} `json:"result"`
}
type GetSkuImageRes struct {
*CommonRes //异常代码(0010:返回数据为空;1001:参数为空;1003:参数值不正确/sku数量过多,目前最大支持100个商品)
Result map[string][]struct {
Id int `json:"id"` //编号
SkuId int `json:"skuId"` //商品编号
Path string `json:"path"` //图片路径
} `json:"result"`
}
type GetSimilarSkuRes struct {
*CommonRes
Result []struct {
Dim int `json:"dim"` //维度
SaleName string `json:"saleName"` //销售名称
SaleAttrList []struct { //商品销售标签 销售属性下可能只有一个标签,此种场景可以选择显示销售名称和标签,也可以不显示
ImagePath string `json:"imagePath"` //标签图片地址
SaleValue string `json:"saleValue"` //标签名称
SkuIds []int `json:"skuIds"` //当前标签下的同类商品skuId
} `json:"saleAttrList"` //
} `json:"result"`
}
// CheckSale 商品可售验证接口
func (goodsJD) CheckSale(ctx context.Context, req *garray.Array) (res *CheckSaleRes, err error) {
method := "product/check"
param := map[string]string{
"skuIds": req.Join(","),
}
result, err := server.requestApi(ctx, method, param)
if err != nil {
return
}
err = gjson.New(result).Scan(&res)
return
}
// CheckOnSale 查询商品上下架状态
func (goodsJD) CheckOnSale(ctx context.Context, req *garray.Array) (res *CheckOnSaleRes, err error) {
method := "product/skuState"
param := map[string]string{
"sku": req.Join(","),
}
result, err := server.requestApi(ctx, method, param)
if err != nil {
return
}
err = gjson.New(result).Scan(&res)
return
}
//GetStock 查询商品库存
func (goodsJD) GetStock(ctx context.Context, req *garray.Array, area string) (res *GetStockRes, err error) {
method := "stock/getNewStockById"
param := map[string]string{
"skuNums": req.Join(","),
"area": area,
}
result, err := server.requestApi(ctx, method, param)
if err != nil {
return
}
err = gjson.New(result).Scan(&res)
return
}
// CheckAreaLimit 查询商品区域购买限制
func (goodsJD) CheckAreaLimit(ctx context.Context, skuIds *garray.Array, provinceID, cityID, countyID, townID interface{}) (res *CheckAreaLimitRes, err error) {
method := "product/checkAreaLimit"
param := map[string]string{
"skuIds": skuIds.Join(","),
"province": gconv.String(provinceID),
"city": gconv.String(cityID),
"county": gconv.String(countyID),
"town": gconv.String(townID),
}
result, err := server.requestApi(ctx, method, param)
if err != nil {
return
}
err = gjson.New(result).Scan(&res)
return
}
//GetProductsPrice 查询商品价格
func (goodsJD) GetProductsPrice(ctx context.Context, skus *garray.Array) (res *GetProductsPriceRes, err error) {
method := "price/getSellPrice"
param := map[string]string{
"sku": skus.Join(","),
"queryExts": "marketPrice",
}
result, err := server.requestApi(ctx, method, param)
if err != nil {
return
}
err = gjson.New(result).Scan(&res)
return
}
//GetDetail 查询商品详情
func (goodsJD) GetDetail(ctx context.Context, skus *garray.Array) (res *GetDetailRes, err error) {
method := "product/getDetail"
param := map[string]string{
"sku": skus.Join(","),
"queryExts": "spuId,pName,isFactoryShip,isSelf,LowestBuy,wxintroduction",
}
result, err := server.requestApi(ctx, method, param)
if err != nil {
return
}
err = gjson.New(result).Scan(&res)
return
}
//GetCategory 查询分类列表
func (goodsJD) GetCategory(ctx context.Context, pageNo, pageSize interface{}) (res *GetCategoryRes, err error) {
method := "product/getCategorys"
param := g.MapStrStr{
"pageNo": gconv.String(pageNo),
"pageSize": gconv.String(pageSize),
}
result, err := server.requestApi(ctx, method, param)
if err != nil {
return
}
err = gjson.New(result).Scan(&res)
return
}
//GetSkuImage 查询商品图片
func (goodsJD) GetSkuImage(ctx context.Context, skus *garray.Array) (res *GetSkuImageRes, err error) {
method := "product/skuImage"
param := map[string]string{
"sku": skus.Join(","),
}
result, err := server.requestApi(ctx, method, param)
if err != nil {
return
}
err = gjson.New(result).Scan(&res)
return
}
//GetSimilarSku 查询同类商品
func (goodsJD) GetSimilarSku(ctx context.Context, skus *garray.Array) (res *GetSimilarSkuRes, err error) {
method := "product/getSimilarSku"
param := map[string]string{
"sku": skus.Join(","),
}
result, err := server.requestApi(ctx, method, param)
if err != nil {
return
}
err = gjson.New(result).Scan(&res)
return
}
package jingdong
import (
"context"
"github.com/gogf/gf/container/garray"
"github.com/gogf/gf/encoding/gjson"
)
type msgJD struct {
}
var Msg = msgJD{}
type GetPushMessages struct {
*CommonRes
Result []struct {
Id int `json:"id"`
Type int `json:"type"`
Time string `json:"time"`
Result interface{} `json:"result"`
} `json:"result"`
}
type DelPushMessages struct {
*CommonRes
Result bool `json:"result"`
}
//GetPushMessages 获取消息 【每次是能获取100条,旧消息不删除不能获取最新消息】
//1:订单拆分消息{"id":推送id, "result" : {"pOrder" :父订单id} , "type": 1, "time":推送时间}
//2:商品价格变更{"id":推送id, "result":{"skuId" : 商品编号 }, "type": 2, "time":推送时间}
//4:商品上下架变更消息{"id":推送id, "result":{"skuId" : 商品编号 }, "type": 4 "time":推送时间}
//5:订单妥投消息{"id":推送id, "result":{"orderId":"京东订单编号", "state":"1是妥投,2是拒收"}, "type" : 5, "time":推送时间}
//6:商品池内商品添加、删除消息{"id":推送id, "result":{"skuId": 商品编号, "page_num":商品池编号, "state":"1添加,2删除"}, "type" : 6, "time":推送时间}
//10:订单取消消息{"id":推送id, "result":{" orderId": 京东订单编号 }, "type" : 10, "time":推送时间}
//11:发票开票进度消息{"id":推送id, "result":{"markId":"发票提报标识","state":"状态"}, "type" : 11, "time":推送时间}
//state状态:1:代表全部开票;2:代表驳回;3:部分开票;4:发票寄出
//12:配送单生成成功消息{"id":推送id, "result":{" orderId": 京东订单编号 }, "type" : 12, "time":推送时间}
//13:换新订单生成成功消息{"id":推送id, "result":{"afsServiceId": 服务单号, " orderId":换新订单号}, "type" : 13, "time":推送时间}
//14:支付失败消息{"id":推送id, "result":{" orderId": 京东订单编号}, "type" : 14, "time":推送时间}
//15:7天未支付取消消息/未确认取消消息{"id":推送id, "result":{"orderId": 京东订单编号, "cancelType": 取消类型}, "type" : 15, "time":推送时间}
//16:商品介绍及规格参数变更消息{"id":推送id, "result":{"skuId" : 商品编号 } "type" : 16, "time":推送时间}
//17:赠品促销变更消息{"id":推送id, "result":{"skuId" : 商品编号 } "type" : 17, "time":推送时间}
//18:订单等待确认收货消息{"id":推送id, "result":{"orderId":京东订单号} "type" : 18, "time":推送时间}
//23:订单配送退货消息{"id":推送id, "result":{"orderId":京东订单号} "type" : 23, "time":推送时间}
//25:新订单消息{"id":推送id, "result":{"orderId":京东订单号, "pin":"京东账号"} "type" : 25, "time":推送时间(订单创建时间)}
//26:预定订单消息{"id":推送id, "result":{"orderId":京东订单号} "type" : 26, "time":推送时间}
//28:售后服务单进度消息{"id":推送id, "result":{"orderId":京东订单号,"pin":"京东账号","skuId":商品编号,"afsServiceId":"服务单号","state":服务单状态} "type" : 28, "time":推送时间}
//31:订单完成消息{"orderId":123123123,"jdOrderState":19,"completeTime":"2018-09-20 16:21:21","pin":"测试pin"}
//48:商品池添加、删除消息{"id":推送id, "result":"{"poolType": "recommend", "page_num":"商品池编号", "state":"1添加,2删除"}", "type" : 28, "time":推送时间}
//49:折扣率变更消息{"id":推送id, "result":"{"oldRate":0.10,"category":"670-671-718","newRate":0.05,"type":1}" "type" : 28, "time":推送时间}
//50:京东地址变更消息[{ "id": "推送id", "result": { "areaId": "京东地址编码", "areaName": "京东地址名称", "parentId": "父京东ID编码", "areaLevel": “地址等级(行政级别:国家(1)、省(2)、市(3)、县(4)、镇(5))”, "operateType":”操作类型(插入数据为1,更新时为2,删除时为3)}”, "time":"消息推送时间", “type":”消息类型” } ]
//100:商品税率变更消息(目前未涵盖全部商品){"timestampLong": "1499136371666","features": "consumptionVAT:12,outputVAT:11,inputVAT:11","sku_id": "3213213"}
//102:专票资质审核进度消息 {"completeDate":"2019-01-09 00:19:14","pushDate":"2019-01-09 00:19:16","pins":"测试","reason":"财务审批通过","status":2,"unitName":"广州市翎唯营销策划有限公司","submitDate":"2018-09-25 15:56:47","taxpayerId":"914401055697802911","vatId":462260}
func (msgJD) GetPushMessages(ctx context.Context, id *garray.Array) (res *GetPushMessages, err error) {
method := "message/get"
param := map[string]string{
"type": id.Join(","),
}
result, err := server.requestApi(ctx, method, param)
if err != nil {
return
}
err = gjson.New(result).Scan(&res)
return
}
//DeletePushMessage 删除消息
func (msgJD) DeletePushMessage(ctx context.Context, id *garray.Array) (res *DelPushMessages, err error) {
method := "message/del"
param := map[string]string{
"id": id.Join(","),
}
result, err := server.requestApi(ctx, method, param)
if err != nil {
return
}
err = gjson.New(result).Scan(&res)
return
}
package jingdong
import (
"context"
"github.com/gogf/gf/encoding/gjson"
"github.com/gogf/gf/frame/g"
)
type orderJD struct {
}
//Order 订单
var Order = orderJD{}
//GetDeliveryRes 物流轨迹
type GetDeliveryRes struct {
*CommonRes
Result struct {
OrderTrack []struct {
Content string `json:"content"` //操作内容明细
MsgTime string `json:"msgTime"` //操作时间。日期格式为“yyyy-MM-dd hh:mm:ss”
Operator string `json:"operator"` //操作员名称
} `json:"orderTrack"`
WaybillCode []struct {
OrderID string `json:"orderId"` //订单号
ParentID string `json:"parentId"` //父订单号。 此字段为0 未拆单
Carrier string `json:"carrier"` //承运商
DeliveryOrderID string `json:"deliveryOrderId"` //运单号
} `json:"waybillCode"`
JdOrderID int `json:"jdOrderId"`
} `json:"result"`
}
//PriceSnap 商品价格
type PriceSnap struct {
SkuID int `json:"skuId"` //商品编号
Price int `json:"price"` //商品价格 格式:21.30
}
//PlaceOrderReq 下单
type PlaceOrderReq struct {
OrderSn string //订单单号
SkuNums []*SkuNums
Consignee string //收货人姓名,最多20个字符
Phone string //手机号,最多20个字符
Address *PlaceOrderAddress
PriceSnap []*PriceSnap
}
//PlaceOrderAddress 下单地址
type PlaceOrderAddress struct {
Province string //一级地址编码
City string //二级地址编码
County string //三级地址编码
Town string //四级地址编码
Desc string //收货人详细地址,最多100个字符
}
//PlaceOrderRes 下单
type PlaceOrderRes struct {
*CommonRes
Result struct {
JdOrderID int64 `json:"jdOrderId"` //京东订单号
OrderPrice float64 `json:"orderPrice"` //订单总金额
OrderNakedPrice float64 `json:"orderNakedPrice"` //订单未税金额
OrderTaxPrice float64 `json:"orderTaxPrice"` //订单税额
Sku []*OrderSkuItem `json:"sku"`
} `json:"result"`
}
//OrderSkuItem 订单商品
type OrderSkuItem struct {
SkuID int `json:"skuId"` //商品编号
Num int `json:"num"` //商品数量
Price float64 `json:"price"` //商品单价
Name string `json:"name"` //商品名称
NakedPrice float64 `json:"nakedPrice"` //商品未税价
}
//ReflectOrderRes 反查订单
type ReflectOrderRes struct {
*CommonRes
Result string `json:"result"` //第三方订单号(非京东订单号)
}
//GetOrderRes 订单详情
type GetOrderRes struct {
*CommonRes
Result struct {
JdOrderID int64 `json:"jdOrderId"` //京东订单编号
Type int `json:"type"` //订单类型。1是父订单 2是子订单
Freight float64 `json:"freight"` //运费
OrderPrice float64 `json:"orderPrice"` //订单总金额
OrderNakedPrice float64 `json:"orderNakedPrice"` //订单未含税金额
OrderTaxPrice float64 `json:"orderTaxPrice"` //订单税额
Sku []*OrderSkuItem `json:"sku"` //商品列表
OrderState int `json:"orderState"` //订单状态。0为取消订单 1为有效
State int `json:"state"` //物流状态。0 是新建 1是妥投 2是拒收
POrder struct {
JdOrderID int64 `json:"jdOrderId"` //京东订单编号
Freight float64 `json:"freight"` //运费
OrderPrice float64 `json:"orderPrice"` //订单总金额
OrderNakedPrice float64 `json:"orderNakedPrice"` //订单未含税金额
Sku []*OrderSkuItem `json:"sku"` //商品列表
} `json:"pOrder"`
COrder []struct {
POrder string `json:"pOrder"` //父订单号。为0时,此订单为父单。
JdOrderID int `json:"jdOrderId"` //京东订单编号
Freight float64 `json:"freight"` //运费
OrderPrice float64 `json:"orderPrice"` //订单总金额
OrderNakedPrice float64 `json:"orderNakedPrice"` //订单未含税金额
Sku []OrderSkuItem `json:"sku"` //商品列表
} `json:"cOrder"`
} `json:"result"`
}
//GetFreightRes 运费
type GetFreightRes struct {
*CommonRes
Result struct {
Freight float64 `json:"freight"` //总运费
BaseFreight float64 `json:"baseFreight"` //基础运费
RemoteRegionFreight float64 `json:"remoteRegionFreight"` //偏远地区加收运费
} `json:"result"`
}
//SkuNums 商品数量
type SkuNums struct {
SkuID int `json:"skuId"` //商品编号
Num int `json:"num"` //商品数量
}
// GetDelivery 物流信息
func (*orderJD) GetDelivery(ctx context.Context, OrderID string) (res *GetDeliveryRes, err error) {
method := "order/orderTrack"
param := g.MapStrStr{
"jdOrderId": OrderID,
"waybillCode": "1",
}
result, err := server.requestApi(ctx, method, param)
if err != nil {
return
}
err = gjson.New(result).Scan(&res)
return
}
// PlaceOrder 下单
func (orderJD) PlaceOrder(ctx context.Context, req *PlaceOrderReq) (res *PlaceOrderRes, err error) {
method := "order/submitOrder"
var param = g.MapStrStr{
"thirdOrder": req.OrderSn,
"sku": gjson.New(req.SkuNums).MustToJsonString(),
"orderPriceSnap": gjson.New(req.PriceSnap).MustToJsonString(),
"name": req.Consignee,
"mobile": req.Phone,
"province": req.Address.Province,
"city": req.Address.City,
"county": req.Address.County,
"town": req.Address.Town,
"address": req.Address.Desc,
"email": server.Email,
"companyName": server.CompanyName,
"submitState": server.SubmitState,
"invoicePhone": server.Mobile,
"invoiceState": "2",
"invoiceType": "4",
"selectedInvoiceTitle": "5",
"invoiceContent": "1",
"paymentType": "4",
"isUseBalance": "1",
"doOrderPriceMode": "1",
}
result, err := server.requestApi(ctx, method, param)
if err != nil {
return
}
err = gjson.New(result).Scan(&res)
return
}
// ReflectOrder 反查订单
func (orderJD) ReflectOrder(ctx context.Context, thirdOrder string) (res *ReflectOrderRes, err error) {
method := "order/selectJdOrderIdByThirdOrder"
param := g.MapStrStr{
"thirdOrder": thirdOrder,
}
result, err := server.requestApi(ctx, method, param)
if err != nil {
return
}
err = gjson.New(result).Scan(&res)
return
}
// GetOrderInfo 订单详情
func (orderJD) GetOrderInfo(ctx context.Context, OrderID string) (res *GetOrderRes, err error) {
method := "order/selectJdOrder"
param := g.MapStrStr{
"jdOrderId": OrderID,
}
result, err := server.requestApi(ctx, method, param)
if err != nil {
return
}
_ = gjson.New(result).Scan(&res)
return
}
// GetFreight 查询运费
func (orderJD) GetFreight(ctx context.Context, sku []*SkuNums, province, city, county, town string) (res *GetFreightRes, err error) {
method := "order/getFreight"
param := g.MapStrStr{
"sku": gjson.New(sku).MustToJsonString(),
"province": province,
"city": city,
"county": county,
"town": town,
"paymentType": "4",
}
result, err := server.requestApi(ctx, method, param)
if err != nil {
return
}
err = gjson.New(result).Scan(&res)
return
}
// ConfirmReceived 确认收货
func (orderJD) ConfirmReceived(ctx context.Context, OrderID string) (res *CommonRes, err error) {
method := "order/confirmReceived"
param := g.MapStrStr{
"jdOrderId": OrderID,
}
result, err := server.requestApi(ctx, method, param)
if err != nil {
return
}
err = gjson.New(result).Scan(&res)
return
}
差异被折叠。
package jingdong
import (
"context"
"errors"
"github.com/gogf/gf/crypto/gmd5"
"github.com/gogf/gf/encoding/gjson"
"github.com/gogf/gf/frame/g"
"github.com/gogf/gf/os/gtime"
"github.com/gogf/gf/util/gconv"
"github.com/gogf/gf/util/gutil"
)
type getAccessTokenRes struct {
*CommonRes
Result *accessToken `json:"result"`
}
type refreshTokenRes struct {
*CommonRes
Result *accessToken `json:"result"`
}
type accessToken struct {
Uid string `json:"uid"`
AccessToken string `json:"access_token"`
RefreshToken string `json:"refresh_token"`
Time int64 `json:"time"`
ExpiresIn int64 `json:"expires_in"`
RefreshTokenExpires int64 `json:"refresh_token_expires"`
}
//getAccessToken 获取token
func (s *client) getAccessToken(ctx context.Context) (err error) {
var token *accessToken
cache, _ := g.Redis().DoVar("HGETALL", CacheKey)
if !cache.IsEmpty() {
_ = cache.Scan(&token)
if token.Time+token.ExpiresIn*1000 > gtime.TimestampMilli() {
s.AccessToken = token.AccessToken
return
}
return s.refreshToken(ctx, token)
}
timeStamp := gtime.Now().String()
sign := s.getSign(timeStamp)
var params = g.MapStrStr{
"grant_type": "access_token",
"client_id": s.AppKey,
"timestamp": timeStamp,
"username": server.UserName,
"password": gmd5.MustEncrypt(s.PassWord),
"sign": sign,
}
result, err := s.post(ctx, server.GetTokenUrl, params)
if err != nil {
return
}
var jdRes *getAccessTokenRes
_ = gjson.New(result).Scan(&jdRes)
if jdRes == nil {
err = errors.New("authorize failed,empty response")
return
}
if !jdRes.Success {
err = errors.New(jdRes.ResultMessage)
return
}
_, _ = g.Redis().Do("HMSET", append(g.Slice{CacheKey}, gutil.MapToSlice(gconv.Map(jdRes.Result))...)...)
s.AccessToken = jdRes.Result.AccessToken
return
}
//refreshToken 刷新token
func (s *client) refreshToken(ctx context.Context, req *accessToken) (err error) {
if req.RefreshTokenExpires < gtime.Timestamp() {
_, err = g.Redis().DoVar("DEL", CacheKey)
return s.getAccessToken(ctx)
}
var params = g.MapStrStr{
"refresh_token": req.RefreshToken,
"client_id": s.AppKey,
"client_secret": s.AppSecret,
}
result, err := s.post(ctx, s.RefreshTokenUrl, params)
if err != nil {
return
}
var jdRes *refreshTokenRes
err = gjson.New(result).Scan(&jdRes)
if err != nil {
return
}
if jdRes == nil {
return
}
if !jdRes.Success {
err = errors.New(jdRes.ResultMessage)
return
}
_, _ = g.Redis().Do("HMSET", append(g.Slice{CacheKey}, gutil.MapToSlice(gconv.Map(jdRes.Result))...)...)
s.AccessToken = jdRes.Result.AccessToken
return
}
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论