Comprehensive Java SDK for WeChat MiniApp development with complete platform integration
—
Express delivery integration and logistics management including shipping, tracking, delivery services, and same-city delivery for WeChat MiniApp e-commerce and service applications.
Core express delivery operations for package shipping and tracking.
public interface WxMaExpressService {
// Delivery Company Management
List<WxMaExpressDeliveryCompany> getAllDelivery() throws WxErrorException;
WxMaExpressAccount getAccount(String type, String bindAccount) throws WxErrorException;
WxMaExpressAccountResult bindAccount(String type, String bizId, String deliveryId, String password) throws WxErrorException;
boolean unbindAccount(String type, String bizId, String deliveryId) throws WxErrorException;
// Order Management
WxMaExpressOrderResult addOrder(WxMaExpressOrder order) throws WxErrorException;
boolean cancelOrder(String orderId, String openid, String deliveryId, String waybillId) throws WxErrorException;
WxMaExpressOrderResult getOrder(String orderId, String openid, String deliveryId, String waybillId) throws WxErrorException;
WxMaExpressPathResult getPath(String orderId, String openid, String deliveryId, String waybillId) throws WxErrorException;
// Shipping Information
WxMaExpressQuotaResult getQuota(String deliveryId) throws WxErrorException;
WxMaExpressPrinterResult getPrinter() throws WxErrorException;
WxMaExpressPrinterResult updatePrinter(String openid, WxMaExpressPrinter printer) throws WxErrorException;
}Same-city instant delivery services for time-sensitive deliveries.
public interface WxMaImmediateDeliveryService {
// Delivery Configuration
WxMaImmeDeliveryBindResult bindAccount(String shopAppId, String deliveryId, String shopAppKey) throws WxErrorException;
// Order Management
WxMaImmeDeliveryCreateResult createOrder(WxMaImmeDeliveryOrder order) throws WxErrorException;
boolean addOrderTip(String shopOrderId, String deliveryToken, Integer tips) throws WxErrorException;
boolean cancelOrder(String shopOrderId, String deliveryToken, Integer reasonCode) throws WxErrorException;
WxMaImmeDeliveryOrderResult getOrder(String shopOrderId, String openid) throws WxErrorException;
// Delivery Management
WxMaImmeDeliveryCarrier mockUpdateOrder(String shopOrderId, Integer actionType) throws WxErrorException;
boolean receiveOrder(String shopOrderId) throws WxErrorException;
// Service Information
WxMaImmeDeliveryResult getAllImmeDelivery() throws WxErrorException;
boolean onAddOrder(String shopOrderId) throws WxErrorException;
boolean onOrderStatus(String shopOrderId) throws WxErrorException;
}Return and exchange logistics component for e-commerce order returns.
public interface WxMaExpressDeliveryReturnService {
// Return Order Management
WxMaExpressDeliveryReturnResult addReturnOrder(WxMaExpressDeliveryReturnOrder order) throws WxErrorException;
boolean cancelReturnOrder(String orderId, String openid, String waybillId) throws WxErrorException;
WxMaExpressDeliveryReturnOrderResult getReturnOrder(String orderId, String openid, String waybillId) throws WxErrorException;
// Return Path Tracking
WxMaExpressDeliveryReturnPathResult getReturnPath(String orderId, String openid, String waybillId) throws WxErrorException;
}Local delivery services for same-city fulfillment.
public interface WxMaIntracityService {
// Service Management
WxMaIntracityServiceResult queryService(WxMaIntracityServiceQuery query) throws WxErrorException;
// Order Operations
WxMaIntracityOrderResult createOrder(WxMaIntracityOrder order) throws WxErrorException;
boolean cancelOrder(String orderId, Integer reasonCode, String reasonDesc) throws WxErrorException;
WxMaIntracityOrderDetailResult getOrder(String orderId) throws WxErrorException;
// Real-time Updates
WxMaIntracityRealtimeOrderResult realtimeQuery(String orderId) throws WxErrorException;
}Comprehensive data models for express delivery operations.
public class WxMaExpressOrder implements Serializable {
private String orderId; // Order ID
private String openid; // User OpenID
private String deliveryId; // Delivery company ID
private String bizId; // Business ID
private String customRemark; // Custom remark
private String tagid; // Template ID
private WxMaExpressSender sender; // Sender information
private WxMaExpressReceiver receiver; // Receiver information
private WxMaExpressShop shop; // Shop information
private WxMaExpressInsured insured; // Insurance information
private WxMaExpressService service; // Service information
// Getters and setters
public String getOrderId();
public void setOrderId(String orderId);
public String getOpenid();
public void setOpenid(String openid);
public String getDeliveryId();
public void setDeliveryId(String deliveryId);
public WxMaExpressSender getSender();
public void setSender(WxMaExpressSender sender);
public WxMaExpressReceiver getReceiver();
public void setReceiver(WxMaExpressReceiver receiver);
// Utility methods
public static WxMaExpressOrder fromJson(String json);
public String toJson();
}
public class WxMaExpressSender implements Serializable {
private String name; // Sender name
private String tel; // Phone number
private String mobile; // Mobile number
private String company; // Company name
private String postCode; // Postal code
private String country; // Country
private String province; // Province
private String city; // City
private String area; // District/Area
private String address; // Detailed address
// Getters and setters
public String getName();
public void setName(String name);
public String getTel();
public void setTel(String tel);
public String getAddress();
public void setAddress(String address);
public String getCity();
public void setCity(String city);
public String getProvince();
public void setProvince(String province);
}
public class WxMaExpressReceiver implements Serializable {
private String name; // Receiver name
private String tel; // Phone number
private String mobile; // Mobile number
private String company; // Company name
private String postCode; // Postal code
private String country; // Country
private String province; // Province
private String city; // City
private String area; // District/Area
private String address; // Detailed address
// Same structure as WxMaExpressSender
// Getters and setters omitted for brevity
}
public class WxMaExpressOrderResult implements Serializable {
private Integer resultCode; // Result code
private String resultMsg; // Result message
private String orderId; // Order ID
private String waybillId; // Waybill number
private String waybillData; // Waybill data for printing
// Getters and setters
public Integer getResultCode();
public void setResultCode(Integer resultCode);
public String getWaybillId();
public void setWaybillId(String waybillId);
// Convenience methods
public boolean isSuccess();
public String getWaybillData();
}Data models for same-city instant delivery operations.
public class WxMaImmeDeliveryOrder implements Serializable {
private String shopOrderId; // Shop order ID
private String shopNo; // Shop number
private Integer deliverySign; // Delivery signature requirement
private String shopOrderStatus; // Shop order status
private String deliveryId; // Delivery company ID
private String openid; // User OpenID
private String subtip; // Delivery note
private String tag; // Order tag
private WxMaImmeDeliverySender sender; // Sender info
private WxMaImmeDeliveryReceiver receiver; // Receiver info
private WxMaImmeDeliveryOrder cargo; // Cargo info
private WxMaImmeDeliveryOrderInfo orderInfo; // Order details
private WxMaImmeDeliveryShop shop; // Shop info
// Getters and setters
public String getShopOrderId();
public void setShopOrderId(String shopOrderId);
public String getDeliveryId();
public void setDeliveryId(String deliveryId);
// Nested classes for sender, receiver, cargo, etc.
public static class WxMaImmeDeliverySender {
private String name; // Sender name
private String city; // City
private String address; // Address
private Double lng; // Longitude
private Double lat; // Latitude
private String phone; // Phone number
// Getters and setters
public String getName();
public void setName(String name);
public String getPhone();
public void setPhone(String phone);
public Double getLng();
public void setLng(Double lng);
public Double getLat();
public void setLat(Double lat);
}
public static class WxMaImmeDeliveryReceiver {
private String name; // Receiver name
private String city; // City
private String address; // Address
private Double lng; // Longitude
private Double lat; // Latitude
private String phone; // Phone number
// Same structure as sender
}
}
public class WxMaImmeDeliveryCreateResult implements Serializable {
private Integer resultcode; // Result code
private String resultmsg; // Result message
private String fee; // Delivery fee
private String deliverfee; // Actual delivery fee
private String couponfee; // Coupon discount
private String tips; // Tips
private String insurancefee; // Insurance fee
private String distance; // Distance
private String waybillId; // Waybill ID
private String orderId; // Order ID
private String deliveryToken; // Delivery token
// Getters and setters
public boolean isSuccess();
public String getWaybillId();
public String getDeliveryToken();
}@Service
public class ExpressDeliveryService {
@Autowired
private WxMaService wxMaService;
public List<DeliveryCompany> getAvailableDeliveryCompanies() {
try {
List<WxMaExpressDeliveryCompany> companies = wxMaService.getExpressService()
.getAllDelivery();
return companies.stream()
.map(this::convertToDeliveryCompany)
.collect(Collectors.toList());
} catch (WxErrorException e) {
logger.error("Failed to get delivery companies: {}", e.getMessage());
throw new ExpressServiceException("Failed to get delivery companies", e);
}
}
public void bindDeliveryAccount(String deliveryCompanyId, String accountId, String password) {
try {
WxMaExpressAccountResult result = wxMaService.getExpressService()
.bindAccount("bind", accountId, deliveryCompanyId, password);
if (result.getResultCode() == 0) {
logger.info("Successfully bound delivery account: {} to company: {}",
accountId, deliveryCompanyId);
} else {
throw new ExpressServiceException("Failed to bind account: " + result.getResultMsg());
}
} catch (WxErrorException e) {
logger.error("Delivery account binding failed: {}", e.getMessage());
throw new ExpressServiceException("Account binding failed", e);
}
}
}public class ExpressOrderService {
public String createExpressOrder(ExpressOrderRequest request) {
try {
// Build express order
WxMaExpressOrder order = new WxMaExpressOrder();
order.setOrderId(request.getOrderId());
order.setOpenid(request.getOpenid());
order.setDeliveryId(request.getDeliveryCompanyId());
order.setBizId(request.getBizId());
order.setCustomRemark(request.getRemark());
// Set sender information
WxMaExpressSender sender = new WxMaExpressSender();
sender.setName(request.getSender().getName());
sender.setTel(request.getSender().getPhone());
sender.setProvince(request.getSender().getProvince());
sender.setCity(request.getSender().getCity());
sender.setArea(request.getSender().getArea());
sender.setAddress(request.getSender().getAddress());
sender.setPostCode(request.getSender().getPostCode());
order.setSender(sender);
// Set receiver information
WxMaExpressReceiver receiver = new WxMaExpressReceiver();
receiver.setName(request.getReceiver().getName());
receiver.setTel(request.getReceiver().getPhone());
receiver.setProvince(request.getReceiver().getProvince());
receiver.setCity(request.getReceiver().getCity());
receiver.setArea(request.getReceiver().getArea());
receiver.setAddress(request.getReceiver().getAddress());
receiver.setPostCode(request.getReceiver().getPostCode());
order.setReceiver(receiver);
// Set cargo information if needed
if (request.getCargo() != null) {
WxMaExpressCargo cargo = new WxMaExpressCargo();
cargo.setCount(request.getCargo().getCount());
cargo.setWeight(request.getCargo().getWeight());
cargo.setSpaceX(request.getCargo().getLength());
cargo.setSpaceY(request.getCargo().getWidth());
cargo.setSpaceZ(request.getCargo().getHeight());
cargo.setDetailList(request.getCargo().getItems().stream()
.map(item -> new WxMaExpressCargoDetail(item.getName(), item.getCount()))
.collect(Collectors.toList()));
order.setCargo(cargo);
}
// Create order with WeChat
WxMaExpressOrderResult result = wxMaService.getExpressService()
.addOrder(order);
if (result.isSuccess()) {
String waybillId = result.getWaybillId();
logger.info("Express order created: {} -> waybill: {}",
request.getOrderId(), waybillId);
// Store waybill information
storeWaybillInfo(request.getOrderId(), waybillId, result.getWaybillData());
return waybillId;
} else {
throw new ExpressOrderException("Order creation failed: " + result.getResultMsg());
}
} catch (WxErrorException e) {
logger.error("Express order creation failed: {}", e.getMessage());
throw new ExpressOrderException("Failed to create express order", e);
}
}
public ExpressOrderStatus getOrderStatus(String orderId, String openid,
String deliveryId, String waybillId) {
try {
WxMaExpressOrderResult result = wxMaService.getExpressService()
.getOrder(orderId, openid, deliveryId, waybillId);
return convertToOrderStatus(result);
} catch (WxErrorException e) {
logger.error("Failed to get express order status: {}", e.getMessage());
throw new ExpressOrderException("Failed to get order status", e);
}
}
public List<ExpressPathInfo> getDeliveryPath(String orderId, String openid,
String deliveryId, String waybillId) {
try {
WxMaExpressPathResult result = wxMaService.getExpressService()
.getPath(orderId, openid, deliveryId, waybillId);
return result.getPathItemList().stream()
.map(this::convertToPathInfo)
.collect(Collectors.toList());
} catch (WxErrorException e) {
logger.error("Failed to get delivery path: {}", e.getMessage());
return Collections.emptyList();
}
}
}@Service
public class ImmediateDeliveryService {
public String createImmediateDelivery(ImmediateDeliveryRequest request) {
try {
// Build immediate delivery order
WxMaImmeDeliveryOrder order = new WxMaImmeDeliveryOrder();
order.setShopOrderId(request.getOrderId());
order.setDeliveryId(request.getDeliveryCompanyId());
order.setOpenid(request.getOpenid());
order.setSubtip(request.getDeliveryNote());
order.setDeliverySign(request.getRequireSignature() ? 1 : 0);
// Set sender information
WxMaImmeDeliveryOrder.WxMaImmeDeliverySender sender =
new WxMaImmeDeliveryOrder.WxMaImmeDeliverySender();
sender.setName(request.getSender().getName());
sender.setPhone(request.getSender().getPhone());
sender.setAddress(request.getSender().getAddress());
sender.setLng(request.getSender().getLongitude());
sender.setLat(request.getSender().getLatitude());
order.setSender(sender);
// Set receiver information
WxMaImmeDeliveryOrder.WxMaImmeDeliveryReceiver receiver =
new WxMaImmeDeliveryOrder.WxMaImmeDeliveryReceiver();
receiver.setName(request.getReceiver().getName());
receiver.setPhone(request.getReceiver().getPhone());
receiver.setAddress(request.getReceiver().getAddress());
receiver.setLng(request.getReceiver().getLongitude());
receiver.setLat(request.getReceiver().getLatitude());
order.setReceiver(receiver);
// Create immediate delivery order
WxMaImmeDeliveryCreateResult result = wxMaService.getImmeDeliveryService()
.createOrder(order);
if (result.isSuccess()) {
String waybillId = result.getWaybillId();
String deliveryToken = result.getDeliveryToken();
logger.info("Immediate delivery created: {} -> waybill: {}",
request.getOrderId(), waybillId);
// Store delivery information
storeDeliveryInfo(request.getOrderId(), waybillId, deliveryToken, result);
return waybillId;
} else {
throw new ImmediateDeliveryException(
"Immediate delivery creation failed: " + result.getResultmsg());
}
} catch (WxErrorException e) {
logger.error("Immediate delivery creation failed: {}", e.getMessage());
throw new ImmediateDeliveryException("Failed to create immediate delivery", e);
}
}
public void addDeliveryTip(String orderId, String deliveryToken, double tipAmount) {
try {
int tipAmountCents = (int) (tipAmount * 100); // Convert to cents
boolean success = wxMaService.getImmeDeliveryService()
.addOrderTip(orderId, deliveryToken, tipAmountCents);
if (success) {
logger.info("Added tip of ¥{} to order: {}", tipAmount, orderId);
}
} catch (WxErrorException e) {
logger.error("Failed to add delivery tip: {}", e.getMessage());
}
}
public void cancelImmediateDelivery(String orderId, String deliveryToken,
CancellationReason reason) {
try {
Integer reasonCode = getCancellationReasonCode(reason);
boolean success = wxMaService.getImmeDeliveryService()
.cancelOrder(orderId, deliveryToken, reasonCode);
if (success) {
logger.info("Cancelled immediate delivery order: {} (reason: {})",
orderId, reason);
// Update order status in database
updateOrderStatus(orderId, "cancelled", reason.getDescription());
}
} catch (WxErrorException e) {
logger.error("Failed to cancel immediate delivery: {}", e.getMessage());
throw new ImmediateDeliveryException("Cancellation failed", e);
}
}
}@Service
public class DeliveryTrackingService {
@Scheduled(fixedRate = 300000) // Every 5 minutes
public void updateDeliveryStatuses() {
List<ActiveDelivery> activeDeliveries = deliveryRepository.findActiveDeliveries();
for (ActiveDelivery delivery : activeDeliveries) {
try {
updateDeliveryStatus(delivery);
Thread.sleep(100); // Rate limiting
} catch (Exception e) {
logger.error("Failed to update delivery status for order {}: {}",
delivery.getOrderId(), e.getMessage());
}
}
}
private void updateDeliveryStatus(ActiveDelivery delivery) {
try {
if (delivery.getDeliveryType() == DeliveryType.EXPRESS) {
updateExpressDeliveryStatus(delivery);
} else if (delivery.getDeliveryType() == DeliveryType.IMMEDIATE) {
updateImmediateDeliveryStatus(delivery);
}
} catch (WxErrorException e) {
logger.error("Delivery status update failed: {}", e.getMessage());
}
}
private void updateExpressDeliveryStatus(ActiveDelivery delivery) throws WxErrorException {
WxMaExpressPathResult pathResult = wxMaService.getExpressService()
.getPath(delivery.getOrderId(), delivery.getOpenid(),
delivery.getDeliveryId(), delivery.getWaybillId());
if (pathResult.isSuccess() && !pathResult.getPathItemList().isEmpty()) {
List<WxMaExpressPathItem> pathItems = pathResult.getPathItemList();
WxMaExpressPathItem latestStatus = pathItems.get(0); // Latest status first
// Check if status has changed
if (!latestStatus.getActionType().equals(delivery.getLastStatus())) {
// Update status in database
delivery.setLastStatus(latestStatus.getActionType());
delivery.setLastStatusTime(new Date(latestStatus.getActionTime() * 1000));
deliveryRepository.save(delivery);
// Send status notification to user
sendStatusNotification(delivery, latestStatus);
// Check if delivered
if (isDeliveredStatus(latestStatus.getActionType())) {
handleDeliveryCompleted(delivery);
}
}
}
}
private void updateImmediateDeliveryStatus(ActiveDelivery delivery) throws WxErrorException {
WxMaImmeDeliveryOrderResult orderResult = wxMaService.getImmeDeliveryService()
.getOrder(delivery.getOrderId(), delivery.getOpenid());
if (orderResult.isSuccess()) {
String currentStatus = orderResult.getOrderStatus();
if (!currentStatus.equals(delivery.getLastStatus())) {
delivery.setLastStatus(currentStatus);
delivery.setLastStatusTime(new Date());
deliveryRepository.save(delivery);
// Send notification
sendImmediateDeliveryNotification(delivery, currentStatus);
// Handle completion
if ("FINISHED_FINISH".equals(currentStatus)) {
handleDeliveryCompleted(delivery);
}
}
}
}
private void sendStatusNotification(ActiveDelivery delivery, WxMaExpressPathItem status) {
// Send WeChat subscription message
Map<String, WxMaSubscribeData> data = new HashMap<>();
data.put("thing1", new WxMaSubscribeData(delivery.getOrderId()));
data.put("thing2", new WxMaSubscribeData(status.getActionTypeDesc()));
data.put("time3", new WxMaSubscribeData(
new SimpleDateFormat("yyyy-MM-dd HH:mm:ss")
.format(new Date(status.getActionTime() * 1000))));
WxMaSubscribeMessage message = new WxMaSubscribeMessage();
message.setToUser(delivery.getOpenid());
message.setTemplateId("delivery_status_template_id");
message.setData(data);
try {
wxMaService.getMsgService().sendSubscribeMsg(message);
} catch (WxErrorException e) {
logger.error("Failed to send delivery notification: {}", e.getMessage());
}
}
}@Service
public class ReturnDeliveryService {
public String createReturnOrder(ReturnOrderRequest request) {
try {
WxMaExpressDeliveryReturnOrder returnOrder = new WxMaExpressDeliveryReturnOrder();
returnOrder.setOrderId(request.getOriginalOrderId());
returnOrder.setOpenid(request.getOpenid());
returnOrder.setReturnInfo(request.getReturnReason());
// Set pickup information (customer)
WxMaExpressDeliveryReturnSender sender = new WxMaExpressDeliveryReturnSender();
sender.setName(request.getCustomer().getName());
sender.setTel(request.getCustomer().getPhone());
sender.setAddress(request.getCustomer().getAddress());
returnOrder.setSender(sender);
// Set delivery information (merchant)
WxMaExpressDeliveryReturnReceiver receiver = new WxMaExpressDeliveryReturnReceiver();
receiver.setName(request.getMerchant().getName());
receiver.setTel(request.getMerchant().getPhone());
receiver.setAddress(request.getMerchant().getAddress());
returnOrder.setReceiver(receiver);
WxMaExpressDeliveryReturnResult result = wxMaService.getExpressDeliveryReturnService()
.addReturnOrder(returnOrder);
if (result.isSuccess()) {
String waybillId = result.getWaybillId();
logger.info("Return order created: {} -> waybill: {}",
request.getOriginalOrderId(), waybillId);
// Store return order information
storeReturnOrderInfo(request, waybillId, result);
return waybillId;
} else {
throw new ReturnOrderException("Return order creation failed: " + result.getResultMsg());
}
} catch (WxErrorException e) {
logger.error("Return order creation failed: {}", e.getMessage());
throw new ReturnOrderException("Failed to create return order", e);
}
}
public List<ReturnPathInfo> getReturnPath(String orderId, String openid, String waybillId) {
try {
WxMaExpressDeliveryReturnPathResult result = wxMaService.getExpressDeliveryReturnService()
.getReturnPath(orderId, openid, waybillId);
return result.getPathItemList().stream()
.map(this::convertToReturnPathInfo)
.collect(Collectors.toList());
} catch (WxErrorException e) {
logger.error("Failed to get return path: {}", e.getMessage());
return Collections.emptyList();
}
}
}@Service
public class LogisticsAnalyticsService {
public DeliveryPerformanceReport generateDeliveryReport(Date startDate, Date endDate) {
List<DeliveryRecord> deliveries = deliveryRepository.findByDateRange(startDate, endDate);
DeliveryPerformanceReport report = new DeliveryPerformanceReport();
report.setTotalDeliveries(deliveries.size());
// Calculate average delivery time
double avgDeliveryHours = deliveries.stream()
.filter(d -> d.getDeliveredTime() != null)
.mapToLong(d -> d.getDeliveredTime().getTime() - d.getCreatedTime().getTime())
.average()
.orElse(0) / (1000 * 60 * 60); // Convert to hours
report.setAverageDeliveryHours(avgDeliveryHours);
// Success rate
long successfulDeliveries = deliveries.stream()
.filter(d -> "delivered".equals(d.getStatus()))
.count();
report.setSuccessRate((double) successfulDeliveries / deliveries.size() * 100);
// Cost analysis
double totalCost = deliveries.stream()
.mapToDouble(DeliveryRecord::getCost)
.sum();
report.setTotalCost(totalCost);
report.setAverageCost(totalCost / deliveries.size());
// Delivery company performance
Map<String, CompanyPerformance> companyPerformance = deliveries.stream()
.collect(Collectors.groupingBy(DeliveryRecord::getDeliveryCompany))
.entrySet().stream()
.collect(Collectors.toMap(
Map.Entry::getKey,
entry -> calculateCompanyPerformance(entry.getValue())
));
report.setCompanyPerformance(companyPerformance);
return report;
}
private CompanyPerformance calculateCompanyPerformance(List<DeliveryRecord> deliveries) {
CompanyPerformance performance = new CompanyPerformance();
performance.setTotalOrders(deliveries.size());
long successful = deliveries.stream()
.filter(d -> "delivered".equals(d.getStatus()))
.count();
performance.setSuccessRate((double) successful / deliveries.size() * 100);
double avgTime = deliveries.stream()
.filter(d -> d.getDeliveredTime() != null)
.mapToLong(d -> d.getDeliveredTime().getTime() - d.getCreatedTime().getTime())
.average()
.orElse(0) / (1000 * 60 * 60);
performance.setAverageDeliveryHours(avgTime);
return performance;
}
}This logistics module provides comprehensive express delivery, same-city delivery, return logistics, and delivery tracking capabilities for WeChat MiniApp e-commerce and service applications.
Install with Tessl CLI
npx tessl i tessl/maven-com-github-binarywang--weixin-java-miniapp