圆通对接文档

Posted liushuchen

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了圆通对接文档相关的知识,希望对你有一定的参考价值。

package com.eureka.provider;

import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;

import cn.hutool.core.codec.Base64;
import cn.hutool.core.lang.Console;
import cn.hutool.core.lang.UUID;
import cn.hutool.core.util.XmlUtil;
import cn.hutool.crypto.SecureUtil;
import cn.hutool.http.HttpRequest;
import cn.hutool.json.JSONUtil;

@SpringBootTest
public class ProviderApplicationTests {

@Test
void contextLoads() {
}

public static void main(String[] args) {
orderCreate();
// waybillDeclare();
}

public static void waybillDeclare() {
String CHANNEL_CODE = "CN037102";
String CLIENT_KEY = "YT00160001";
String AESKEY = "w4tb3o5aTT9npey7ZGC9TvCdMKA8DiQtDGo145eE77n";
String URL = "http://customs.yto.net.cn/api/waybill/declare/test/1210/message";
// 1. 封装运单报文:跟实际运单情况填写
HashMap<String, Object> waybillMessage = new HashMap<String, Object>();
waybillMessage.put("appType", null);
waybillMessage.put("logisticsCode", null);
waybillMessage.put("logisticsName", null);
waybillMessage.put("logisticsNo", null);
waybillMessage.put("billNo", null);
waybillMessage.put("orderNo", null);
waybillMessage.put("freight", null);
waybillMessage.put("insuredFee", null);
waybillMessage.put("currency", null);
waybillMessage.put("weight", null);
waybillMessage.put("packNo", 1);
waybillMessage.put("goodsInfo", null);
waybillMessage.put("consignee", null);
waybillMessage.put("consigneeAddress", null);
waybillMessage.put("consigneeTelephone", null);
waybillMessage.put("note", null);
HashMap<String, Object> extra = new HashMap<String, Object>();
extra.put("voyageNo", null);
extra.put("ieType", null);
extra.put("tradeMode", null);
extra.put("netWeight", null);
extra.put("shipper", null);
extra.put("shipperAddress", null);
extra.put("shipperTelephone", null);
extra.put("shipperCountry", null);
extra.put("consigneeCountry", null);
extra.put("buyerIdType", 1);
extra.put("buyerIdNumber", null);
extra.put("trasfNo", null);
extra.put("ebpCode", null);
extra.put("ebpName", null);
extra.put("currencyCiq", 156);
extra.put("note", null);
waybillMessage.put("extra", extra);
// 3.封装请求参数
String encrypt = AesUtils.encrypt(JSONUtil.toJsonStr(waybillMessage), AESKEY);
// 生成随机数
String nonce = UUID.randomUUID().toString().toUpperCase();
Date date = new Date();
// 获取签名信息
String[] array = new String[] { CLIENT_KEY, CHANNEL_CODE, String.valueOf(date.getTime()), nonce, encrypt };
StringBuilder sb = new StringBuilder();
// 字符串排序
Arrays.sort(array);
for (int i = 0; i < 5; i++) {
sb.append(array[i]);
}
HashMap<String, Object> message = new HashMap<String, Object>();
message.put("clientKey", CLIENT_KEY);
message.put("ChannelCode", CHANNEL_CODE);
message.put("timestamp", date);
message.put("nonce", nonce);
message.put("data", encrypt);
message.put("signature", SecureUtil.sha1(sb.toString()));
String jsonStr = JSONUtil.toJsonStr(message);
String body = HttpRequest.post(URL).contentType("application/json").body(jsonStr, "application/json")
.timeout(20000)// 超时,毫秒
.execute().body();
Console.log("接口返回数据:{}", body);
}

public static void orderCreate() {
Map<String, Object> data = new HashMap<String, Object>();
data.put("clientID", "K21000119");
data.put("logisticProviderID", "YTO");
data.put("customerId", "K21000119");
data.put("txLogisticID", "WP151831179108113");
data.put("tradeNo", "1");
data.put("totalServiceFee", "1");
data.put("codSplitFee", "1");
data.put("orderType", "1");
data.put("serviceType", "1");
data.put("flag", "1");
Map<String, Object> sender = new HashMap<String, Object>();
sender.put("name", "发件人姓名");
sender.put("phone", "021-12345678");
sender.put("prov", "上海");
sender.put("city", "上海市,青浦区");
sender.put("address", "华徐公路3029弄28号");
data.put("sender", sender);
Map<String, Object> receiver = new HashMap<String, Object>();
receiver.put("name", "收件人姓名");
receiver.put("phone", "18089666766");
receiver.put("prov", "上海");
receiver.put("city", "上海市,青浦区");
sender.put("address", "华徐公路3029弄28号");
data.put("receiver", receiver);
data.put("sendStartTime", "2015-12-12 12:12:12");
data.put("sendEndTime", "2015-12-12 12:12:12");
data.put("goodsValue", "1");
List<Map<String, Object>> items = new ArrayList<Map<String, Object>>();
Map<String, Object> itemDt = new HashMap<String, Object>();
itemDt.put("itemName", "商品");
itemDt.put("number", "1");
itemDt.put("itemValue", "2");
Map<String, Object> item = new HashMap<String, Object>();
item.put("item", itemDt);
items.add(item);
data.put("items", items);
data.put("insuranceValue", 1);
data.put("special", 1);
data.put("remark", 1);

String logistics_interface = XmlUtil.mapToXmlStr(data, "RequestOrder")
.replace("<?xml version="1.0" encoding="UTF-8" standalone="no"?>", "");
Console.log("要发送的xml内容: [{}]", logistics_interface);
String partnerId = "123456";
String url = "http://opentestapi.yto.net.cn/service/e_order_create/v1/BAHrhW";

try {
Map<String, Object> paramMap = new HashMap<String, Object>();
paramMap.put("logistics_interface", URLEncoder.encode(logistics_interface, "utf-8"));
paramMap.put("data_digest",
URLEncoder.encode(Base64.encode(SecureUtil.md5(logistics_interface + partnerId)), "utf-8"));
paramMap.put("clientId", URLEncoder.encode("K21000119", "utf-8"));
paramMap.put("type", URLEncoder.encode("offline", "utf-8"));
System.out.println(paramMap);
String body = HttpRequest.post(url)//
.form(paramMap)// 表单内容
.timeout(20000)// 超时,毫秒
.execute().body();
Map<String, Object> xmlToMap = XmlUtil.xmlToMap(body);
Console.log("接口返回数据:{}", xmlToMap);
} catch (UnsupportedEncodingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}

}

 

 

 

 

 

 

 

 

package com.eureka.provider;

import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.Arrays;

import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;

import org.apache.commons.lang.CharEncoding;
import org.apache.commons.lang.RandomStringUtils;
import org.springframework.util.Base64Utils;

/**
* 前后端数据传输加密工具类
*
* @author monkey
*
*/
public class AesUtils {
private static final Charset CHARSET = Charset.forName(CharEncoding.UTF_8);

/**
* 加密
*
* @param content 加密的字符串
* @param encryptKey key值
* @return
* @throws Exception
*/
public static String encrypt(String text, String aesKey) {
ByteGroup byteCollector = new ByteGroup();
byte[] randomStrBytes = RandomStringUtils.randomAlphanumeric(16).getBytes(CHARSET);
byte[] textBytes = text.getBytes(CHARSET);
byte[] networkBytesOrder = getNetworkBytesOrder(textBytes.length);
// randomStr + networkBytesOrder + text
byteCollector.addBytes(randomStrBytes);
byteCollector.addBytes(networkBytesOrder);
byteCollector.addBytes(textBytes);
// ... + pad: 使用自定义的填充方式对明文进行补位填充
byte[] padBytes = encode(byteCollector.size());
byteCollector.addBytes(padBytes);
// 获得最终的字节流, 未加密
byte[] unencrypted = byteCollector.toBytes();
return aesCbc(unencrypted,Base64Utils.decodeFromString(aesKey + "="));
}

private static String aesCbc(byte[] unencrypted, byte[] aesKey) {
try {
// 设置加密模式为AES的CBC模式
Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding");
SecretKeySpec keySpec = new SecretKeySpec(aesKey, "AES");
IvParameterSpec iv = new IvParameterSpec(aesKey, 0, 16);
cipher.init(Cipher.ENCRYPT_MODE, keySpec, iv);
// 加密
byte[] encrypted = cipher.doFinal(unencrypted);
// 使用BASE64对加密后的字符串进行编码
return Base64Utils.encodeToString(encrypted);
} catch (Exception e) {
return "";
}
}

// 生成4个字节的网络字节序
static byte[] getNetworkBytesOrder(int sourceNumber) {
byte[] orderBytes = new byte[4];
orderBytes[3] = (byte) (sourceNumber & 0xFF);
orderBytes[2] = (byte) (sourceNumber >> 8 & 0xFF);
orderBytes[1] = (byte) (sourceNumber >> 16 & 0xFF);
orderBytes[0] = (byte) (sourceNumber >> 24 & 0xFF);
return orderBytes;
}

// 还原4个字节的网络字节序
private static int recoverNetworkBytesOrder(byte[] orderBytes) {
int sourceNumber = 0;
for (int i = 0; i < 4; i++) {
sourceNumber <<= 8;
sourceNumber |= orderBytes[i] & 0xff;
}
return sourceNumber;
}

/**
* 解密
*
* @param encryptStr 解密的字符串
* @param decryptKey 解密的key值
* @return
* @throws Exception
*/
public static String decrypt(String encryptedMsg, String aesKey) {
try {
if (aesKey.length() != 43) {
return "";
}
byte[] decodeFromString = Base64Utils.decodeFromString(aesKey + "=");
byte[] original;
try {
// 设置解密模式为AES的CBC模式
Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding");
SecretKeySpec keySpec = new SecretKeySpec(decodeFromString, "AES");
IvParameterSpec iv = new IvParameterSpec(Arrays.copyOfRange(decodeFromString, 0, 16));
cipher.init(Cipher.DECRYPT_MODE, keySpec, iv);
// 使用BASE64对密文进行解码
byte[] encrypted = Base64Utils.decodeFromString(encryptedMsg);
// 解密
original = cipher.doFinal(encrypted);
} catch (Exception e) {
return "";
}
String xmlContent;
try {
// 去除补位字符
byte[] bytes = decode(original);
// 分离16位随机字符串,网络字节序
byte[] networkOrder = Arrays.copyOfRange(bytes, 16, 20);
int xmlLength = recoverNetworkBytesOrder(networkOrder);
xmlContent = new String(Arrays.copyOfRange(bytes, 20, 20 + xmlLength), CHARSET);
} catch (Exception e) {
return "";
}

return xmlContent;
} catch (Exception e) {
return "";
}
}

private static final int ZERO = 0;
private static final int BLOCK_SIZE = 32;

/**
* 获得对明文进行补位填充的字节.
*
* @param count 需要进行填充补位操作的明文字节个数
* @return 补齐用的字节数组
*/
static byte[] encode(int count) {
// 计算需要填充的位数
int amountToPad = BLOCK_SIZE - (count % BLOCK_SIZE);
if (amountToPad == 0) {
amountToPad = BLOCK_SIZE;
}
// 获得补位所用的字符
char padChr = chr(amountToPad);
String tmp = new String();
for (int index = 0; index < amountToPad; index++) {
tmp += padChr;
}
return tmp.getBytes(CHARSET);
}

/**
* 删除解密后明文的补位字符
*
* @param decrypted 解密后的明文
* @return 删除补位字符后的明文
*/
static byte[] decode(byte[] decrypted) {
int pad = (int) decrypted[decrypted.length - 1];
if (pad < 1 || pad > BLOCK_SIZE) {
pad = 0;
}
return Arrays.copyOfRange(decrypted, ZERO, decrypted.length - pad);
}

/**
* 将数字转化成ASCII码对应的字符,用于对明文进行补码
*
* @param a 需要转化的数字
* @return 转化得到的字符
*/
static char chr(int a) {
byte target = (byte) (a & 0xFF);
return (char) target;
}
}
class ByteGroup {
ArrayList<Byte> byteContainer = new ArrayList<Byte>();

byte[] toBytes() {
byte[] bytes = new byte[byteContainer.size()];
for (int i = 0; i < byteContainer.size(); i++) {
bytes[i] = byteContainer.get(i);
}
return bytes;
}

ByteGroup addBytes(byte[] bytes) {
for (byte b : bytes) {
byteContainer.add(b);
}
return this;
}

int size() {
return byteContainer.size();
}
}

以上是关于圆通对接文档的主要内容,如果未能解决你的问题,请参考以下文章

免费圆通电子面单接口对接

圆通电子面单接口对接及调试

关于菜鸟的圆通电子面单打印

测试在公司和哪些人员来对接,需要看哪些文档,需要写哪些东西

PHP调用API,有对接文档,有KEY,我是新手,不知道怎么写,请高手赐教!

测试在公司和哪些人员来对接,需要看哪些文档,需要写哪些东西。