1. 生成业务参数签名和请求头签名 方法
// 极兔快递生成请求头签名
func JHeaderDigest(jsonData []byte, privateKey string) string {
// 计算MD5摘要
hash := md5.Sum(append(jsonData, []byte(privateKey)...))
// 进行base64加密
digest := base64.StdEncoding.EncodeToString(hash[:])
return digest
}
// 极兔快递生成业务参数签名
func JDataDigest(customerId string, customerPwd string, privateKey string) string {
// 计算密文
cipherText := md5.Sum([]byte(customerPwd + "jadada236t2"))
cipherTextStr := fmt.Sprintf("%X", cipherText) // 将密文转换为大写的十六进制字符串
// 拼接客户编号、密文和私钥
signatureStr := customerId + cipherTextStr + privateKey
// 计算签名的MD5摘要
signature := md5.Sum([]byte(signatureStr))
// 进行Base64加密
dataDigest := base64.StdEncoding.EncodeToString(signature[:])
return dataDigest
}
2. 生成业务签名以及时间戳
apiAccount := "17**************05"
privateKey := "0258****************01a"
customerId := "J00********99"
customerPwd := "H5*******E6"
// 生成业务参数签名
dataDigest := utils.JDataDigest(customerId, customerPwd, privateKey)
timestamp := time.Now().UnixNano() / int64(time.Millisecond)
3. 书写业务参数 并格式化
bizContentSender := orderReq.BizContentSender{
Name: orderStu.OrderName,
Mobile: orderStu.OrderPhone,
Prov: orderStu.OrderProvice,
CountryCode: "CHN",
City: orderStu.OrderCity,
Area: orderStu.OrderArea,
Address: orderStu.OrderAddress,
}
bizContentReceiver := orderReq.BizContentReceiver{
Name: orderStu.BackName,
Mobile: orderStu.BackPhone,
Prov: orderStu.BackPhone,
CountryCode: "CHN",
City: orderStu.BackCity,
Area: orderStu.BackArea,
Address: orderStu.BackAddress,
}
bizContent := orderReq.BizContent{
CustomerCode: customerId,
Digest: dataDigest,
TxlogisticId: "CESHI202312251445001",
ExpressType: "EZ",
OrderType: "2",
ServiceType: "02",
DeliveryType: "04",
PayType: "PP_PM",
Sender: bizContentSender,
Receiver: bizContentReceiver,
GoodsType: "bm000003",
Weight: "0.25",
}
jsonData, err := json.Marshal(bizContent)
if err != nil {
return errors.New("转为JSON时报错")
}
jsonStr := string(jsonData)
4. 生成请求头签名
digest := utils.JHeaderDigest(jsonData, privateKey)
5. 请求极兔api
postural := "https://uat-openapi.jtexpress.com.cn/webopenplatformapi/api/order/v2/addOrder"
// 构建表单数据
formData := url.Values{}
formData.Add("bizContent", jsonStr)
// 创建POST请求对象
req, err := http.NewRequest("POST", postural, strings.NewReader(formData.Encode()))
if err != nil {
return err
}
// 设置请求头
req.Header.Set("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8")
req.Header.Set("apiAccount", apiAccount)
req.Header.Set("digest", digest)
timerStr := strconv.FormatInt(timestamp, 10)
req.Header.Set("timestamp", timerStr)
// 创建HTTP客户端
client := &http.Client{}
// 发送请求
resp, err := client.Do(req)
if err != nil {
fmt.Println("发送请求时出错:", err)
return err
}
defer resp.Body.Close()
// 读取响应内容
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
fmt.Println("读取响应时出错:", err)
return err
}
// 打印响应内容
fmt.Println(string(body))
完整代码
package order
import (
"encoding/json"
"errors"
"fmt"
"github.com/flipped-aurora/gin-vue-admin/server/global"
"github.com/flipped-aurora/gin-vue-admin/server/model/order"
orderReq "github.com/flipped-aurora/gin-vue-admin/server/model/order/request"
"github.com/flipped-aurora/gin-vue-admin/server/utils"
"io/ioutil"
"net/http"
"net/url"
"strconv"
"strings"
"time"
)
type OrderOuter struct{}
func (OrderStructService *OrderStructService) GetBackExpress(id uint) (err error) {
var orderStu order.OrderStruct
err = global.GVA_DB.Where("id = ?", id).First(&orderStu).Error
if err != nil {
return errors.New("未查询到此订单")
}
if *(orderStu.Status) < 5 {
return errors.New("该订单状态无法申请快递单号")
}
if orderStu.BackName == "" || orderStu.BackPhone == "" || orderStu.BackProvince == "" || orderStu.BackCity == "" || orderStu.BackArea == "" || orderStu.BackAddress == "" {
return errors.New("退回地址信息不完整,无法申请快递单号")
}
apiAccount := "1783**********5932605"
privateKey := "0258d71**********201a"
customerId := "J00*****99"
customerPwd := "H5C****6"
// 生成业务参数签名
dataDigest := utils.JDataDigest(customerId, customerPwd, privateKey)
timestamp := time.Now().UnixNano() / int64(time.Millisecond)
bizContentSender := orderReq.BizContentSender{
Name: orderStu.OrderName,
Mobile: orderStu.OrderPhone,
Prov: orderStu.OrderProvice,
CountryCode: "CHN",
City: orderStu.OrderCity,
Area: orderStu.OrderArea,
Address: orderStu.OrderAddress,
}
bizContentReceiver := orderReq.BizContentReceiver{
Name: orderStu.BackName,
Mobile: orderStu.BackPhone,
Prov: orderStu.BackPhone,
CountryCode: "CHN",
City: orderStu.BackCity,
Area: orderStu.BackArea,
Address: orderStu.BackAddress,
}
bizContent := orderReq.BizContent{
CustomerCode: customerId,
Digest: dataDigest,
TxlogisticId: "CESHI202312251445001",
ExpressType: "EZ",
OrderType: "2",
ServiceType: "02",
DeliveryType: "04",
PayType: "PP_PM",
Sender: bizContentSender,
Receiver: bizContentReceiver,
GoodsType: "bm000003",
Weight: "0.25",
}
jsonData, err := json.Marshal(bizContent)
if err != nil {
return errors.New("转为JSON时报错")
}
jsonStr := string(jsonData)
postural := "https://uat-openapi.jtexpress.com.cn/webopenplatformapi/api/order/v2/addOrder"
digest := utils.JHeaderDigest(jsonData, privateKey)
// 构建表单数据
formData := url.Values{}
formData.Add("bizContent", jsonStr)
// 创建POST请求对象
req, err := http.NewRequest("POST", postural, strings.NewReader(formData.Encode()))
if err != nil {
return err
}
// 设置请求头
req.Header.Set("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8")
req.Header.Set("apiAccount", apiAccount)
req.Header.Set("digest", digest)
timerStr := strconv.FormatInt(timestamp, 10)
req.Header.Set("timestamp", timerStr)
// 创建HTTP客户端
client := &http.Client{}
// 发送请求
resp, err := client.Do(req)
if err != nil {
fmt.Println("发送请求时出错:", err)
return err
}
defer resp.Body.Close()
// 读取响应内容
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
fmt.Println("读取响应时出错:", err)
return err
}
// 打印响应内容
fmt.Println(string(body))
return err
}
OrderReq代码:
package request
type BizContent struct {
CustomerCode string `json:"customerCode"`
Digest string `json:"digest"`
TxlogisticId string `json:"txlogisticId"`
ExpressType string `json:"expressType"`
OrderType string `json:"orderType"`
ServiceType string `json:"serviceType"`
DeliveryType string `json:"deliveryType"`
PayType string `json:"payType"`
Sender BizContentSender `json:"sender"`
Receiver BizContentReceiver `json:"receiver"`
GoodsType string `json:"goodsType"`
Weight string `json:"weight"`
TotalQuantity uint `json:"totalQuantity"`
}
type BizContentSender struct {
Name string `json:"name" `
Mobile string `json:"mobile"`
CountryCode string `json:"countryCode"`
Prov string `json:"prov"`
City string `json:"city"`
Area string `json:"area"`
Address string `json:"address"`
}
type BizContentReceiver struct {
Name string `json:"name"`
Mobile string `json:"mobile"`
CountryCode string `json:"countryCode"`
Prov string `json:"prov"`
City string `json:"city"`
Area string `json:"area"`
Address string `json:"address"`
}
utils完整代码:
package utils
import (
"crypto/md5"
"encoding/base64"
"fmt"
)
// 极兔快递生成请求头签名
func JHeaderDigest(jsonData []byte, privateKey string) string {
// 计算MD5摘要
hash := md5.Sum(append(jsonData, []byte(privateKey)...))
// 进行base64加密
digest := base64.StdEncoding.EncodeToString(hash[:])
return digest
}
// 极兔快递生成业务参数签名
func JDataDigest(customerId string, customerPwd string, privateKey string) string {
// 计算密文
cipherText := md5.Sum([]byte(customerPwd + "jadada236t2"))
cipherTextStr := fmt.Sprintf("%X", cipherText) // 将密文转换为大写的十六进制字符串
// 拼接客户编号、密文和私钥
signatureStr := customerId + cipherTextStr + privateKey
// 计算签名的MD5摘要
signature := md5.Sum([]byte(signatureStr))
// 进行Base64加密
dataDigest := base64.StdEncoding.EncodeToString(signature[:])
return dataDigest
}