From 32e4ef5e547cc96b72fb82c728566f72d1d38e83 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=82=B9=E5=AE=97=E6=A5=A0?= Date: Thu, 24 Nov 2022 13:47:14 +0800 Subject: [PATCH] 1 --- platformapi/mtwmapi/mtwmapi.go | 9 +- platformapi/recharge_phone_bill/recharge.go | 116 ++++++++++++++++++ .../recharge_phone_bill/recharge_api.go | 90 ++++++++++++++ .../tiktok_shop/tiktok_api/afs_test.go | 2 +- .../tiktok_shop/tiktok_api/api_test.go | 18 --- 5 files changed, 208 insertions(+), 27 deletions(-) create mode 100644 platformapi/recharge_phone_bill/recharge.go create mode 100644 platformapi/recharge_phone_bill/recharge_api.go diff --git a/platformapi/mtwmapi/mtwmapi.go b/platformapi/mtwmapi/mtwmapi.go index 2f84d74d..aff63f69 100644 --- a/platformapi/mtwmapi/mtwmapi.go +++ b/platformapi/mtwmapi/mtwmapi.go @@ -4,6 +4,7 @@ import ( "bytes" "crypto/md5" "fmt" + "git.rosy.net.cn/baseapi/utils" "mime/multipart" "net/http" "net/url" @@ -12,7 +13,6 @@ import ( "time" "git.rosy.net.cn/baseapi/platformapi" - "git.rosy.net.cn/baseapi/utils" ) const ( @@ -144,7 +144,6 @@ func (a *API) AccessAPI2(cmd string, isGet bool, bizParams map[string]interface{ } signURL := a.genURL(cmd) + "?" params[signKey] = a.signParams(signURL, params) - //globals.SugarLogger.Debugf("params[signKey]=============%s", params[signKey]) err = platformapi.AccessPlatformAPIWithRetry(a.client, func() *http.Request { var request *http.Request @@ -154,7 +153,6 @@ func (a *API) AccessAPI2(cmd string, isGet bool, bizParams map[string]interface{ request, _ = http.NewRequest(http.MethodGet, fullURL, nil) } else { fullURL := a.genURL(cmd) - // baseapi.SugarLogger.Debug(utils.Map2URLValues(params).Encode()) if imgData == nil { request, _ = http.NewRequest(http.MethodPost, fullURL, strings.NewReader(utils.Map2URLValues(params).Encode())) request.Header.Set("Content-Type", "application/x-www-form-urlencoded") @@ -167,11 +165,9 @@ func (a *API) AccessAPI2(cmd string, isGet bool, bizParams map[string]interface{ fw.Write(imgData.([]byte)) } for k, v := range params { - // baseapi.SugarLogger.Debug(k, " ", v) w.WriteField(k, url.QueryEscape(fmt.Sprint(v))) } w.Close() - // b.WriteString(utils.Map2URLValues(params).Encode()) request, _ = http.NewRequest(http.MethodPost, fullURL, &b) request.Header.Set("Content-Type", w.FormDataContentType()) } @@ -225,17 +221,14 @@ func (a *API) AccessAPI3(cmd string, isGet bool, bizParams map[string]interface{ params = utils.MergeMaps(params, bizParams) signURL := a.genURL(cmd) + "?" params[signKey] = a.signParams(signURL, params) - //globals.SugarLogger.Debugf("params[signKey]=============%s", params[signKey]) err = platformapi.AccessPlatformAPIWithRetry(a.client, func() *http.Request { var request *http.Request if isGet { fullURL := utils.GenerateGetURL(apiURL, cmd, params) - // baseapi.SugarLogger.Debug(fullURL) request, _ = http.NewRequest(http.MethodGet, fullURL, nil) } else { fullURL := a.genURL(cmd) - // baseapi.SugarLogger.Debug(utils.Map2URLValues(params).Encode()) request, _ = http.NewRequest(http.MethodPost, fullURL, strings.NewReader(utils.Map2URLValues(params).Encode())) request.Header.Set("Content-Type", "application/x-www-form-urlencoded") request.Header.Set("charset", "UTF-8") diff --git a/platformapi/recharge_phone_bill/recharge.go b/platformapi/recharge_phone_bill/recharge.go new file mode 100644 index 00000000..5dea96ff --- /dev/null +++ b/platformapi/recharge_phone_bill/recharge.go @@ -0,0 +1,116 @@ +package recharge_phone_bill + +import ( + "encoding/json" + "errors" + "git.rosy.net.cn/baseapi/utils" + "net/http" +) + +// 充值类型 +const ( + ChargeTypeDefault = 0 //快充(默认) + ChargeTypeAuto = 1 // 自动慢充 + ChargeTypeManual = 2 // 手动慢充 +) + +// 产品编码 +const ( + FlowCodeY10Y100 = "Y10Y100" // Y10Y100 全国 全省 中国移动 100 + FlowCodeY10Y200 = "Y10Y200" // Y10Y200 全国 全省 中国移动 200 + + FlowCodeD10Y50 = "D10Y50" // D10Y50 全国 全省 中国电信 50 + FlowCodeD10Y100 = "D10Y100" // D10Y100 全国 全省 中国电信 100 + FlowCodeD10Y200 = "D10Y200" // D10Y200 全国 全省 中国电信 200 + + FlowCodeL10Y50 = "L10Y50" // L10Y50 全国 全省 中国联通 50 + FlowCodeL10Y100 = "L10Y100" // L10Y100 全国 全省 中国联通 100 + FlowCodeL10Y200 = "L10Y200" // L10Y200 全国 全省 中国联通 200 +) + +const ( + BaseUrl = "http://39.108.16.170/index.php/" // 基础访问路由 + CreateOrder = "Api/Order/flow" // 话费充值 + QueryOrder = "Api/Order/order_search" // 订单查询 + QueryAccountBill = "Api/Order/balance_search" // 余额查询 +) + +type RechargePhoneBillBase struct { + FlowCode string `json:"flowCode"` // 产品编码 + Mobile string `json:"mobile"` // 手机号码 + OrderNumber string `json:"orderNumber"` // 商户订单号 + CallbackURL string `json:"callbackURL"` // 回调地址,不传不回调 + ChargeType string `json:"chargeType"` // 充值类型 0 快充(默认) 1 自动慢充 2 手动慢充 +} + +var FlowCode = map[string]bool{FlowCodeY10Y100: true, FlowCodeY10Y200: true, FlowCodeD10Y50: true, FlowCodeD10Y100: true, FlowCodeD10Y200: true, FlowCodeL10Y50: true, FlowCodeL10Y100: true, FlowCodeL10Y200: true} + +// RechargePhoneBill 话费充值接口 +func (a *API) RechargePhoneBill(params *RechargePhoneBillBase) (string, error) { + if !FlowCode[params.FlowCode] { + return "", errors.New("不存在的充值类型") + } + + data, err := a.AccessAPI(BaseUrl, CreateOrder, http.MethodPost, utils.Struct2MapByJson(params)) + if err != nil { + return "", err + } + if data["code"].(string) != "2000" { + return "", errors.New(data["msg"].(string)) + } + return data["order_number"].(string), nil +} + +type QueryOrderDetailRes struct { + Code string `json:"code"` + Msg string `json:"msg"` + Data []QueryOrderDetailResList `json:"data"` +} + +type QueryOrderDetailResList struct { + OrderNumber string `json:"order_number"` // 平台订单号 + UserOrdernum string `json:"user_ordernum"` // 商户订单号 + OrderStatus string `json:"order_status"` // 状态:0:未提交,1:充值中,2:已充值,-1:失败 + Mobile string `json:"mobile"` // 手机号码 + Ctime string `json:"ctime"` // 时间戳 + Voucher string `json:"voucher"` // 透传流水号 +} + +// QueryOrderDetail 查询充值订单详情 +func (a *API) QueryOrderDetail(orderNumber, userOrderNum string) ([]QueryOrderDetailResList, error) { + params := make(map[string]interface{}, 0) + if orderNumber == "" && userOrderNum == "" { + return nil, errors.New("订单号不能为空") + } + if orderNumber != "" { + params["order_number"] = orderNumber + } else { + params["user_ordernum"] = userOrderNum + } + data, err := a.AccessAPI(BaseUrl, QueryOrder, http.MethodPost, params) + if err != nil { + return nil, err + } + if data["code"].(string) != "2000" { + return nil, errors.New(data["msg"].(string)) + } + + var result []QueryOrderDetailResList + if err := json.Unmarshal([]byte(utils.Interface2String(data["data"])), &result); err != nil { + return nil, err + } + + return result, nil +} + +// QueryAccountBill 余额查询 +func (a *API) QueryAccountBill() (string, error) { + data, err := a.AccessAPI(BaseUrl, QueryAccountBill, http.MethodPost, nil) + if err != nil { + return "", err + } + if data["code"].(string) != "2000" { + return "", errors.New(data["msg"].(string)) + } + return data["balance"].(string), nil +} diff --git a/platformapi/recharge_phone_bill/recharge_api.go b/platformapi/recharge_phone_bill/recharge_api.go new file mode 100644 index 00000000..bbf63072 --- /dev/null +++ b/platformapi/recharge_phone_bill/recharge_api.go @@ -0,0 +1,90 @@ +package recharge_phone_bill + +import ( + "crypto/md5" + "encoding/json" + "fmt" + "git.rosy.net.cn/baseapi/platformapi" + "git.rosy.net.cn/baseapi/utils" + "net/http" + "strings" + "sync" +) + +type API struct { + account string + password string + secret string + locker sync.RWMutex + client *http.Client + config *platformapi.APIConfig +} + +func New(password, account, secret string, config ...*platformapi.APIConfig) *API { + curConfig := platformapi.DefAPIConfig + if len(config) > 0 { + curConfig = *config[0] + } + return &API{ + account: account, + password: password, + secret: secret, + locker: sync.RWMutex{}, + client: &http.Client{Timeout: curConfig.ClientTimeout}, + config: &curConfig, + } +} + +// 大写( md5( md5(密码)+手机号码+产品编码+商户订单号+秘钥 ) ) 话费充值签名接口 +func (a *API) signParam(params map[string]interface{}) (sig string) { + paramsSign := "" + if params["mobile"] != "" && params["flowCode"] != "" && params["orderNumber"] != "" { + paramsSign = params["mobile"].(string) + params["flowCode"].(string) + params["orderNumber"].(string) + } + md5Password := fmt.Sprintf("%X", fmt.Sprintf("%X", md5.Sum([]byte(a.password)))+paramsSign+a.secret) + return md5Password +} + +func (a *API) AccessAPI(baseUrl, actionApi, method string, bizParams map[string]interface{}) (retVal map[string]interface{}, err error) { + bizParams["account"] = a.account + bizParams["sign"] = a.signParam(bizParams) + // 序列化 + data, err := json.Marshal(bizParams) + if err != nil { + return nil, err + } + + // 全路径请求参数 + fullURL := utils.GenerateGetURL(baseUrl, actionApi, nil) + + // 发送请求 + sendUrl := func() *http.Request { + var request *http.Request + if http.MethodPost == method { + request, _ = http.NewRequest(http.MethodPost, fullURL, strings.NewReader(string(data))) + } else { + request, _ = http.NewRequest(http.MethodGet, utils.GenerateGetURL(baseUrl, actionApi, bizParams), nil) + } + request.Header.Set("Content-Type", "application/json") + return request + } + + // 数据解析 + dataMarshal := func(response *http.Response, bodyStr string, jsonResult1 map[string]interface{}) (errLevel string, err error) { + if jsonResult1 == nil { + return platformapi.ErrLevelRecoverableErr, fmt.Errorf("mapData is nil") + } + if err != nil { + return "", err + } + if utils.MustInterface2Int64(jsonResult1["code"]) != 2000 { + errLevel = platformapi.ErrLevelGeneralFail + err = utils.NewErrorCode(jsonResult1["msg"].(string), utils.Int64ToStr(utils.MustInterface2Int64(jsonResult1["code"]))) + } + retVal = jsonResult1 + return errLevel, err + } + + err = platformapi.AccessPlatformAPIWithRetry(a.client, sendUrl, a.config, dataMarshal) + return retVal, err +} diff --git a/platformapi/tiktok_shop/tiktok_api/afs_test.go b/platformapi/tiktok_shop/tiktok_api/afs_test.go index 05d9d540..6960a0c1 100644 --- a/platformapi/tiktok_shop/tiktok_api/afs_test.go +++ b/platformapi/tiktok_shop/tiktok_api/afs_test.go @@ -8,7 +8,7 @@ import ( "time" ) -var token = `{"access_token":"88a8dd73-b276-4eb6-830e-007b2cf18208","expires_in":1669018480,"scope":"SCOPE","shop_id":57939570,"shop_name":"京西菜市速食","refresh_token":"4fefd9c8-ae3b-41c3-98f0-427585370f61","authority_id":""}` +var token = `{"access_token":"8e3cb15d-1aaa-45da-9bd4-0fd67df135e5","expires_in":1669624306,"scope":"SCOPE","shop_id":57939570,"shop_name":"京西菜市速食","refresh_token":"1e1e3361-0d2a-459d-a8c7-da49c6025a9b","authority_id":""}` var a = New("7136048270014416392", "c397aa9f-3927-47c4-8cfe-4d84e02602e0", token) // 查询售后单详情 diff --git a/platformapi/tiktok_shop/tiktok_api/api_test.go b/platformapi/tiktok_shop/tiktok_api/api_test.go index ce4be66d..8f558da9 100644 --- a/platformapi/tiktok_shop/tiktok_api/api_test.go +++ b/platformapi/tiktok_shop/tiktok_api/api_test.go @@ -2,7 +2,6 @@ package tiktok_api import ( "fmt" - order_getSettleBillDetailV3_request "git.rosy.net.cn/baseapi/platformapi/tiktok_shop/sdk-golang/api/order_getSettleBillDetailV3/request" order_logisticsAdd_request "git.rosy.net.cn/baseapi/platformapi/tiktok_shop/sdk-golang/api/order_logisticsAdd/request" "git.rosy.net.cn/baseapi/utils" "git.rosy.net.cn/jx-callback/globals" @@ -69,23 +68,6 @@ func TestReturnGoodsToWareHouseSuccess(t *testing.T) { a.ReturnGoodsToWareHouseSuccess("7154200345302827303") } -// 获取订单结算信息 -func TestGetSettleBillDetailV3(t *testing.T) { - token := `{"access_token":"60f530b2-9ab6-4723-b487-c094918f0d21","expires_in":1666257163,"scope":"SCOPE","shop_id":"","shop_name":"小时达开放平台对接专用店","refresh_token":"1220666a-5e88-458c-a8c0-06d949fbbd3f","authority_id":""}` - a := New("7136048270014416392", "c397aa9f-3927-47c4-8cfe-4d84e02602e0", token) - a.GetSettleBillDetailV3(&order_getSettleBillDetailV3_request.OrderAddressModifyParam{ - Size: 100, - StartTime: "2022-10-07 00:00:00", - EndTime: "2022-10-14 00:00:00", - //OrderId: "4980573848886616007", - ProductId: "", - PayType: "", - FlowType: "", - TimeType: "1", - StartIndex: "", - }) -} - // 多订单同一个物流包裹 func TestLogisticsAddSinglePack(t *testing.T) { a.LogisticsAddSinglePack()