or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

analytics.mdcloud-development.mdconfiguration.mdcore-services.mddevelopment-tools.mdecommerce.mdindex.mdlive-streaming.mdlogistics.mdmedia-content.mdmessaging.mdqr-codes.mduser-management.md

logistics.mddocs/

0

# Express & Logistics

1

2

Express delivery integration and logistics management including shipping, tracking, delivery services, and same-city delivery for WeChat MiniApp e-commerce and service applications.

3

4

## Capabilities

5

6

### Express Service Interface

7

8

Core express delivery operations for package shipping and tracking.

9

10

```java { .api }

11

public interface WxMaExpressService {

12

// Delivery Company Management

13

List<WxMaExpressDeliveryCompany> getAllDelivery() throws WxErrorException;

14

WxMaExpressAccount getAccount(String type, String bindAccount) throws WxErrorException;

15

WxMaExpressAccountResult bindAccount(String type, String bizId, String deliveryId, String password) throws WxErrorException;

16

boolean unbindAccount(String type, String bizId, String deliveryId) throws WxErrorException;

17

18

// Order Management

19

WxMaExpressOrderResult addOrder(WxMaExpressOrder order) throws WxErrorException;

20

boolean cancelOrder(String orderId, String openid, String deliveryId, String waybillId) throws WxErrorException;

21

WxMaExpressOrderResult getOrder(String orderId, String openid, String deliveryId, String waybillId) throws WxErrorException;

22

WxMaExpressPathResult getPath(String orderId, String openid, String deliveryId, String waybillId) throws WxErrorException;

23

24

// Shipping Information

25

WxMaExpressQuotaResult getQuota(String deliveryId) throws WxErrorException;

26

WxMaExpressPrinterResult getPrinter() throws WxErrorException;

27

WxMaExpressPrinterResult updatePrinter(String openid, WxMaExpressPrinter printer) throws WxErrorException;

28

}

29

```

30

31

### Immediate Delivery Service Interface

32

33

Same-city instant delivery services for time-sensitive deliveries.

34

35

```java { .api }

36

public interface WxMaImmediateDeliveryService {

37

// Delivery Configuration

38

WxMaImmeDeliveryBindResult bindAccount(String shopAppId, String deliveryId, String shopAppKey) throws WxErrorException;

39

40

// Order Management

41

WxMaImmeDeliveryCreateResult createOrder(WxMaImmeDeliveryOrder order) throws WxErrorException;

42

boolean addOrderTip(String shopOrderId, String deliveryToken, Integer tips) throws WxErrorException;

43

boolean cancelOrder(String shopOrderId, String deliveryToken, Integer reasonCode) throws WxErrorException;

44

WxMaImmeDeliveryOrderResult getOrder(String shopOrderId, String openid) throws WxErrorException;

45

46

// Delivery Management

47

WxMaImmeDeliveryCarrier mockUpdateOrder(String shopOrderId, Integer actionType) throws WxErrorException;

48

boolean receiveOrder(String shopOrderId) throws WxErrorException;

49

50

// Service Information

51

WxMaImmeDeliveryResult getAllImmeDelivery() throws WxErrorException;

52

boolean onAddOrder(String shopOrderId) throws WxErrorException;

53

boolean onOrderStatus(String shopOrderId) throws WxErrorException;

54

}

55

```

56

57

### Express Delivery Return Service

58

59

Return and exchange logistics component for e-commerce order returns.

60

61

```java { .api }

62

public interface WxMaExpressDeliveryReturnService {

63

// Return Order Management

64

WxMaExpressDeliveryReturnResult addReturnOrder(WxMaExpressDeliveryReturnOrder order) throws WxErrorException;

65

boolean cancelReturnOrder(String orderId, String openid, String waybillId) throws WxErrorException;

66

WxMaExpressDeliveryReturnOrderResult getReturnOrder(String orderId, String openid, String waybillId) throws WxErrorException;

67

68

// Return Path Tracking

69

WxMaExpressDeliveryReturnPathResult getReturnPath(String orderId, String openid, String waybillId) throws WxErrorException;

70

}

71

```

72

73

### Same-City Delivery Service

74

75

Local delivery services for same-city fulfillment.

76

77

```java { .api }

78

public interface WxMaIntracityService {

79

// Service Management

80

WxMaIntracityServiceResult queryService(WxMaIntracityServiceQuery query) throws WxErrorException;

81

82

// Order Operations

83

WxMaIntracityOrderResult createOrder(WxMaIntracityOrder order) throws WxErrorException;

84

boolean cancelOrder(String orderId, Integer reasonCode, String reasonDesc) throws WxErrorException;

85

WxMaIntracityOrderDetailResult getOrder(String orderId) throws WxErrorException;

86

87

// Real-time Updates

88

WxMaIntracityRealtimeOrderResult realtimeQuery(String orderId) throws WxErrorException;

89

}

90

```

91

92

### Express Data Models

93

94

Comprehensive data models for express delivery operations.

95

96

```java { .api }

97

public class WxMaExpressOrder implements Serializable {

98

private String orderId; // Order ID

99

private String openid; // User OpenID

100

private String deliveryId; // Delivery company ID

101

private String bizId; // Business ID

102

private String customRemark; // Custom remark

103

private String tagid; // Template ID

104

private WxMaExpressSender sender; // Sender information

105

private WxMaExpressReceiver receiver; // Receiver information

106

private WxMaExpressShop shop; // Shop information

107

private WxMaExpressInsured insured; // Insurance information

108

private WxMaExpressService service; // Service information

109

110

// Getters and setters

111

public String getOrderId();

112

public void setOrderId(String orderId);

113

public String getOpenid();

114

public void setOpenid(String openid);

115

public String getDeliveryId();

116

public void setDeliveryId(String deliveryId);

117

public WxMaExpressSender getSender();

118

public void setSender(WxMaExpressSender sender);

119

public WxMaExpressReceiver getReceiver();

120

public void setReceiver(WxMaExpressReceiver receiver);

121

122

// Utility methods

123

public static WxMaExpressOrder fromJson(String json);

124

public String toJson();

125

}

126

127

public class WxMaExpressSender implements Serializable {

128

private String name; // Sender name

129

private String tel; // Phone number

130

private String mobile; // Mobile number

131

private String company; // Company name

132

private String postCode; // Postal code

133

private String country; // Country

134

private String province; // Province

135

private String city; // City

136

private String area; // District/Area

137

private String address; // Detailed address

138

139

// Getters and setters

140

public String getName();

141

public void setName(String name);

142

public String getTel();

143

public void setTel(String tel);

144

public String getAddress();

145

public void setAddress(String address);

146

public String getCity();

147

public void setCity(String city);

148

public String getProvince();

149

public void setProvince(String province);

150

}

151

152

public class WxMaExpressReceiver implements Serializable {

153

private String name; // Receiver name

154

private String tel; // Phone number

155

private String mobile; // Mobile number

156

private String company; // Company name

157

private String postCode; // Postal code

158

private String country; // Country

159

private String province; // Province

160

private String city; // City

161

private String area; // District/Area

162

private String address; // Detailed address

163

164

// Same structure as WxMaExpressSender

165

// Getters and setters omitted for brevity

166

}

167

168

public class WxMaExpressOrderResult implements Serializable {

169

private Integer resultCode; // Result code

170

private String resultMsg; // Result message

171

private String orderId; // Order ID

172

private String waybillId; // Waybill number

173

private String waybillData; // Waybill data for printing

174

175

// Getters and setters

176

public Integer getResultCode();

177

public void setResultCode(Integer resultCode);

178

public String getWaybillId();

179

public void setWaybillId(String waybillId);

180

181

// Convenience methods

182

public boolean isSuccess();

183

public String getWaybillData();

184

}

185

```

186

187

### Immediate Delivery Models

188

189

Data models for same-city instant delivery operations.

190

191

```java { .api }

192

public class WxMaImmeDeliveryOrder implements Serializable {

193

private String shopOrderId; // Shop order ID

194

private String shopNo; // Shop number

195

private Integer deliverySign; // Delivery signature requirement

196

private String shopOrderStatus; // Shop order status

197

private String deliveryId; // Delivery company ID

198

private String openid; // User OpenID

199

private String subtip; // Delivery note

200

private String tag; // Order tag

201

private WxMaImmeDeliverySender sender; // Sender info

202

private WxMaImmeDeliveryReceiver receiver; // Receiver info

203

private WxMaImmeDeliveryOrder cargo; // Cargo info

204

private WxMaImmeDeliveryOrderInfo orderInfo; // Order details

205

private WxMaImmeDeliveryShop shop; // Shop info

206

207

// Getters and setters

208

public String getShopOrderId();

209

public void setShopOrderId(String shopOrderId);

210

public String getDeliveryId();

211

public void setDeliveryId(String deliveryId);

212

213

// Nested classes for sender, receiver, cargo, etc.

214

public static class WxMaImmeDeliverySender {

215

private String name; // Sender name

216

private String city; // City

217

private String address; // Address

218

private Double lng; // Longitude

219

private Double lat; // Latitude

220

private String phone; // Phone number

221

222

// Getters and setters

223

public String getName();

224

public void setName(String name);

225

public String getPhone();

226

public void setPhone(String phone);

227

public Double getLng();

228

public void setLng(Double lng);

229

public Double getLat();

230

public void setLat(Double lat);

231

}

232

233

public static class WxMaImmeDeliveryReceiver {

234

private String name; // Receiver name

235

private String city; // City

236

private String address; // Address

237

private Double lng; // Longitude

238

private Double lat; // Latitude

239

private String phone; // Phone number

240

241

// Same structure as sender

242

}

243

}

244

245

public class WxMaImmeDeliveryCreateResult implements Serializable {

246

private Integer resultcode; // Result code

247

private String resultmsg; // Result message

248

private String fee; // Delivery fee

249

private String deliverfee; // Actual delivery fee

250

private String couponfee; // Coupon discount

251

private String tips; // Tips

252

private String insurancefee; // Insurance fee

253

private String distance; // Distance

254

private String waybillId; // Waybill ID

255

private String orderId; // Order ID

256

private String deliveryToken; // Delivery token

257

258

// Getters and setters

259

public boolean isSuccess();

260

public String getWaybillId();

261

public String getDeliveryToken();

262

}

263

```

264

265

## Usage Examples

266

267

### Express Delivery Management

268

269

#### Set Up Express Delivery

270

271

```java

272

@Service

273

public class ExpressDeliveryService {

274

275

@Autowired

276

private WxMaService wxMaService;

277

278

public List<DeliveryCompany> getAvailableDeliveryCompanies() {

279

try {

280

List<WxMaExpressDeliveryCompany> companies = wxMaService.getExpressService()

281

.getAllDelivery();

282

283

return companies.stream()

284

.map(this::convertToDeliveryCompany)

285

.collect(Collectors.toList());

286

287

} catch (WxErrorException e) {

288

logger.error("Failed to get delivery companies: {}", e.getMessage());

289

throw new ExpressServiceException("Failed to get delivery companies", e);

290

}

291

}

292

293

public void bindDeliveryAccount(String deliveryCompanyId, String accountId, String password) {

294

try {

295

WxMaExpressAccountResult result = wxMaService.getExpressService()

296

.bindAccount("bind", accountId, deliveryCompanyId, password);

297

298

if (result.getResultCode() == 0) {

299

logger.info("Successfully bound delivery account: {} to company: {}",

300

accountId, deliveryCompanyId);

301

} else {

302

throw new ExpressServiceException("Failed to bind account: " + result.getResultMsg());

303

}

304

305

} catch (WxErrorException e) {

306

logger.error("Delivery account binding failed: {}", e.getMessage());

307

throw new ExpressServiceException("Account binding failed", e);

308

}

309

}

310

}

311

```

312

313

#### Create Express Order

314

315

```java

316

public class ExpressOrderService {

317

318

public String createExpressOrder(ExpressOrderRequest request) {

319

try {

320

// Build express order

321

WxMaExpressOrder order = new WxMaExpressOrder();

322

order.setOrderId(request.getOrderId());

323

order.setOpenid(request.getOpenid());

324

order.setDeliveryId(request.getDeliveryCompanyId());

325

order.setBizId(request.getBizId());

326

order.setCustomRemark(request.getRemark());

327

328

// Set sender information

329

WxMaExpressSender sender = new WxMaExpressSender();

330

sender.setName(request.getSender().getName());

331

sender.setTel(request.getSender().getPhone());

332

sender.setProvince(request.getSender().getProvince());

333

sender.setCity(request.getSender().getCity());

334

sender.setArea(request.getSender().getArea());

335

sender.setAddress(request.getSender().getAddress());

336

sender.setPostCode(request.getSender().getPostCode());

337

order.setSender(sender);

338

339

// Set receiver information

340

WxMaExpressReceiver receiver = new WxMaExpressReceiver();

341

receiver.setName(request.getReceiver().getName());

342

receiver.setTel(request.getReceiver().getPhone());

343

receiver.setProvince(request.getReceiver().getProvince());

344

receiver.setCity(request.getReceiver().getCity());

345

receiver.setArea(request.getReceiver().getArea());

346

receiver.setAddress(request.getReceiver().getAddress());

347

receiver.setPostCode(request.getReceiver().getPostCode());

348

order.setReceiver(receiver);

349

350

// Set cargo information if needed

351

if (request.getCargo() != null) {

352

WxMaExpressCargo cargo = new WxMaExpressCargo();

353

cargo.setCount(request.getCargo().getCount());

354

cargo.setWeight(request.getCargo().getWeight());

355

cargo.setSpaceX(request.getCargo().getLength());

356

cargo.setSpaceY(request.getCargo().getWidth());

357

cargo.setSpaceZ(request.getCargo().getHeight());

358

cargo.setDetailList(request.getCargo().getItems().stream()

359

.map(item -> new WxMaExpressCargoDetail(item.getName(), item.getCount()))

360

.collect(Collectors.toList()));

361

order.setCargo(cargo);

362

}

363

364

// Create order with WeChat

365

WxMaExpressOrderResult result = wxMaService.getExpressService()

366

.addOrder(order);

367

368

if (result.isSuccess()) {

369

String waybillId = result.getWaybillId();

370

logger.info("Express order created: {} -> waybill: {}",

371

request.getOrderId(), waybillId);

372

373

// Store waybill information

374

storeWaybillInfo(request.getOrderId(), waybillId, result.getWaybillData());

375

376

return waybillId;

377

} else {

378

throw new ExpressOrderException("Order creation failed: " + result.getResultMsg());

379

}

380

381

} catch (WxErrorException e) {

382

logger.error("Express order creation failed: {}", e.getMessage());

383

throw new ExpressOrderException("Failed to create express order", e);

384

}

385

}

386

387

public ExpressOrderStatus getOrderStatus(String orderId, String openid,

388

String deliveryId, String waybillId) {

389

try {

390

WxMaExpressOrderResult result = wxMaService.getExpressService()

391

.getOrder(orderId, openid, deliveryId, waybillId);

392

393

return convertToOrderStatus(result);

394

395

} catch (WxErrorException e) {

396

logger.error("Failed to get express order status: {}", e.getMessage());

397

throw new ExpressOrderException("Failed to get order status", e);

398

}

399

}

400

401

public List<ExpressPathInfo> getDeliveryPath(String orderId, String openid,

402

String deliveryId, String waybillId) {

403

try {

404

WxMaExpressPathResult result = wxMaService.getExpressService()

405

.getPath(orderId, openid, deliveryId, waybillId);

406

407

return result.getPathItemList().stream()

408

.map(this::convertToPathInfo)

409

.collect(Collectors.toList());

410

411

} catch (WxErrorException e) {

412

logger.error("Failed to get delivery path: {}", e.getMessage());

413

return Collections.emptyList();

414

}

415

}

416

}

417

```

418

419

### Immediate Delivery Service

420

421

#### Same-City Instant Delivery

422

423

```java

424

@Service

425

public class ImmediateDeliveryService {

426

427

public String createImmediateDelivery(ImmediateDeliveryRequest request) {

428

try {

429

// Build immediate delivery order

430

WxMaImmeDeliveryOrder order = new WxMaImmeDeliveryOrder();

431

order.setShopOrderId(request.getOrderId());

432

order.setDeliveryId(request.getDeliveryCompanyId());

433

order.setOpenid(request.getOpenid());

434

order.setSubtip(request.getDeliveryNote());

435

order.setDeliverySign(request.getRequireSignature() ? 1 : 0);

436

437

// Set sender information

438

WxMaImmeDeliveryOrder.WxMaImmeDeliverySender sender =

439

new WxMaImmeDeliveryOrder.WxMaImmeDeliverySender();

440

sender.setName(request.getSender().getName());

441

sender.setPhone(request.getSender().getPhone());

442

sender.setAddress(request.getSender().getAddress());

443

sender.setLng(request.getSender().getLongitude());

444

sender.setLat(request.getSender().getLatitude());

445

order.setSender(sender);

446

447

// Set receiver information

448

WxMaImmeDeliveryOrder.WxMaImmeDeliveryReceiver receiver =

449

new WxMaImmeDeliveryOrder.WxMaImmeDeliveryReceiver();

450

receiver.setName(request.getReceiver().getName());

451

receiver.setPhone(request.getReceiver().getPhone());

452

receiver.setAddress(request.getReceiver().getAddress());

453

receiver.setLng(request.getReceiver().getLongitude());

454

receiver.setLat(request.getReceiver().getLatitude());

455

order.setReceiver(receiver);

456

457

// Create immediate delivery order

458

WxMaImmeDeliveryCreateResult result = wxMaService.getImmeDeliveryService()

459

.createOrder(order);

460

461

if (result.isSuccess()) {

462

String waybillId = result.getWaybillId();

463

String deliveryToken = result.getDeliveryToken();

464

465

logger.info("Immediate delivery created: {} -> waybill: {}",

466

request.getOrderId(), waybillId);

467

468

// Store delivery information

469

storeDeliveryInfo(request.getOrderId(), waybillId, deliveryToken, result);

470

471

return waybillId;

472

} else {

473

throw new ImmediateDeliveryException(

474

"Immediate delivery creation failed: " + result.getResultmsg());

475

}

476

477

} catch (WxErrorException e) {

478

logger.error("Immediate delivery creation failed: {}", e.getMessage());

479

throw new ImmediateDeliveryException("Failed to create immediate delivery", e);

480

}

481

}

482

483

public void addDeliveryTip(String orderId, String deliveryToken, double tipAmount) {

484

try {

485

int tipAmountCents = (int) (tipAmount * 100); // Convert to cents

486

487

boolean success = wxMaService.getImmeDeliveryService()

488

.addOrderTip(orderId, deliveryToken, tipAmountCents);

489

490

if (success) {

491

logger.info("Added tip of ¥{} to order: {}", tipAmount, orderId);

492

}

493

494

} catch (WxErrorException e) {

495

logger.error("Failed to add delivery tip: {}", e.getMessage());

496

}

497

}

498

499

public void cancelImmediateDelivery(String orderId, String deliveryToken,

500

CancellationReason reason) {

501

try {

502

Integer reasonCode = getCancellationReasonCode(reason);

503

504

boolean success = wxMaService.getImmeDeliveryService()

505

.cancelOrder(orderId, deliveryToken, reasonCode);

506

507

if (success) {

508

logger.info("Cancelled immediate delivery order: {} (reason: {})",

509

orderId, reason);

510

511

// Update order status in database

512

updateOrderStatus(orderId, "cancelled", reason.getDescription());

513

}

514

515

} catch (WxErrorException e) {

516

logger.error("Failed to cancel immediate delivery: {}", e.getMessage());

517

throw new ImmediateDeliveryException("Cancellation failed", e);

518

}

519

}

520

}

521

```

522

523

### Delivery Tracking and Monitoring

524

525

```java

526

@Service

527

public class DeliveryTrackingService {

528

529

@Scheduled(fixedRate = 300000) // Every 5 minutes

530

public void updateDeliveryStatuses() {

531

List<ActiveDelivery> activeDeliveries = deliveryRepository.findActiveDeliveries();

532

533

for (ActiveDelivery delivery : activeDeliveries) {

534

try {

535

updateDeliveryStatus(delivery);

536

Thread.sleep(100); // Rate limiting

537

538

} catch (Exception e) {

539

logger.error("Failed to update delivery status for order {}: {}",

540

delivery.getOrderId(), e.getMessage());

541

}

542

}

543

}

544

545

private void updateDeliveryStatus(ActiveDelivery delivery) {

546

try {

547

if (delivery.getDeliveryType() == DeliveryType.EXPRESS) {

548

updateExpressDeliveryStatus(delivery);

549

} else if (delivery.getDeliveryType() == DeliveryType.IMMEDIATE) {

550

updateImmediateDeliveryStatus(delivery);

551

}

552

553

} catch (WxErrorException e) {

554

logger.error("Delivery status update failed: {}", e.getMessage());

555

}

556

}

557

558

private void updateExpressDeliveryStatus(ActiveDelivery delivery) throws WxErrorException {

559

WxMaExpressPathResult pathResult = wxMaService.getExpressService()

560

.getPath(delivery.getOrderId(), delivery.getOpenid(),

561

delivery.getDeliveryId(), delivery.getWaybillId());

562

563

if (pathResult.isSuccess() && !pathResult.getPathItemList().isEmpty()) {

564

List<WxMaExpressPathItem> pathItems = pathResult.getPathItemList();

565

WxMaExpressPathItem latestStatus = pathItems.get(0); // Latest status first

566

567

// Check if status has changed

568

if (!latestStatus.getActionType().equals(delivery.getLastStatus())) {

569

// Update status in database

570

delivery.setLastStatus(latestStatus.getActionType());

571

delivery.setLastStatusTime(new Date(latestStatus.getActionTime() * 1000));

572

deliveryRepository.save(delivery);

573

574

// Send status notification to user

575

sendStatusNotification(delivery, latestStatus);

576

577

// Check if delivered

578

if (isDeliveredStatus(latestStatus.getActionType())) {

579

handleDeliveryCompleted(delivery);

580

}

581

}

582

}

583

}

584

585

private void updateImmediateDeliveryStatus(ActiveDelivery delivery) throws WxErrorException {

586

WxMaImmeDeliveryOrderResult orderResult = wxMaService.getImmeDeliveryService()

587

.getOrder(delivery.getOrderId(), delivery.getOpenid());

588

589

if (orderResult.isSuccess()) {

590

String currentStatus = orderResult.getOrderStatus();

591

592

if (!currentStatus.equals(delivery.getLastStatus())) {

593

delivery.setLastStatus(currentStatus);

594

delivery.setLastStatusTime(new Date());

595

deliveryRepository.save(delivery);

596

597

// Send notification

598

sendImmediateDeliveryNotification(delivery, currentStatus);

599

600

// Handle completion

601

if ("FINISHED_FINISH".equals(currentStatus)) {

602

handleDeliveryCompleted(delivery);

603

}

604

}

605

}

606

}

607

608

private void sendStatusNotification(ActiveDelivery delivery, WxMaExpressPathItem status) {

609

// Send WeChat subscription message

610

Map<String, WxMaSubscribeData> data = new HashMap<>();

611

data.put("thing1", new WxMaSubscribeData(delivery.getOrderId()));

612

data.put("thing2", new WxMaSubscribeData(status.getActionTypeDesc()));

613

data.put("time3", new WxMaSubscribeData(

614

new SimpleDateFormat("yyyy-MM-dd HH:mm:ss")

615

.format(new Date(status.getActionTime() * 1000))));

616

617

WxMaSubscribeMessage message = new WxMaSubscribeMessage();

618

message.setToUser(delivery.getOpenid());

619

message.setTemplateId("delivery_status_template_id");

620

message.setData(data);

621

622

try {

623

wxMaService.getMsgService().sendSubscribeMsg(message);

624

} catch (WxErrorException e) {

625

logger.error("Failed to send delivery notification: {}", e.getMessage());

626

}

627

}

628

}

629

```

630

631

### Return and Exchange Management

632

633

```java

634

@Service

635

public class ReturnDeliveryService {

636

637

public String createReturnOrder(ReturnOrderRequest request) {

638

try {

639

WxMaExpressDeliveryReturnOrder returnOrder = new WxMaExpressDeliveryReturnOrder();

640

returnOrder.setOrderId(request.getOriginalOrderId());

641

returnOrder.setOpenid(request.getOpenid());

642

returnOrder.setReturnInfo(request.getReturnReason());

643

644

// Set pickup information (customer)

645

WxMaExpressDeliveryReturnSender sender = new WxMaExpressDeliveryReturnSender();

646

sender.setName(request.getCustomer().getName());

647

sender.setTel(request.getCustomer().getPhone());

648

sender.setAddress(request.getCustomer().getAddress());

649

returnOrder.setSender(sender);

650

651

// Set delivery information (merchant)

652

WxMaExpressDeliveryReturnReceiver receiver = new WxMaExpressDeliveryReturnReceiver();

653

receiver.setName(request.getMerchant().getName());

654

receiver.setTel(request.getMerchant().getPhone());

655

receiver.setAddress(request.getMerchant().getAddress());

656

returnOrder.setReceiver(receiver);

657

658

WxMaExpressDeliveryReturnResult result = wxMaService.getExpressDeliveryReturnService()

659

.addReturnOrder(returnOrder);

660

661

if (result.isSuccess()) {

662

String waybillId = result.getWaybillId();

663

logger.info("Return order created: {} -> waybill: {}",

664

request.getOriginalOrderId(), waybillId);

665

666

// Store return order information

667

storeReturnOrderInfo(request, waybillId, result);

668

669

return waybillId;

670

} else {

671

throw new ReturnOrderException("Return order creation failed: " + result.getResultMsg());

672

}

673

674

} catch (WxErrorException e) {

675

logger.error("Return order creation failed: {}", e.getMessage());

676

throw new ReturnOrderException("Failed to create return order", e);

677

}

678

}

679

680

public List<ReturnPathInfo> getReturnPath(String orderId, String openid, String waybillId) {

681

try {

682

WxMaExpressDeliveryReturnPathResult result = wxMaService.getExpressDeliveryReturnService()

683

.getReturnPath(orderId, openid, waybillId);

684

685

return result.getPathItemList().stream()

686

.map(this::convertToReturnPathInfo)

687

.collect(Collectors.toList());

688

689

} catch (WxErrorException e) {

690

logger.error("Failed to get return path: {}", e.getMessage());

691

return Collections.emptyList();

692

}

693

}

694

}

695

```

696

697

### Logistics Analytics

698

699

```java

700

@Service

701

public class LogisticsAnalyticsService {

702

703

public DeliveryPerformanceReport generateDeliveryReport(Date startDate, Date endDate) {

704

List<DeliveryRecord> deliveries = deliveryRepository.findByDateRange(startDate, endDate);

705

706

DeliveryPerformanceReport report = new DeliveryPerformanceReport();

707

report.setTotalDeliveries(deliveries.size());

708

709

// Calculate average delivery time

710

double avgDeliveryHours = deliveries.stream()

711

.filter(d -> d.getDeliveredTime() != null)

712

.mapToLong(d -> d.getDeliveredTime().getTime() - d.getCreatedTime().getTime())

713

.average()

714

.orElse(0) / (1000 * 60 * 60); // Convert to hours

715

716

report.setAverageDeliveryHours(avgDeliveryHours);

717

718

// Success rate

719

long successfulDeliveries = deliveries.stream()

720

.filter(d -> "delivered".equals(d.getStatus()))

721

.count();

722

report.setSuccessRate((double) successfulDeliveries / deliveries.size() * 100);

723

724

// Cost analysis

725

double totalCost = deliveries.stream()

726

.mapToDouble(DeliveryRecord::getCost)

727

.sum();

728

report.setTotalCost(totalCost);

729

report.setAverageCost(totalCost / deliveries.size());

730

731

// Delivery company performance

732

Map<String, CompanyPerformance> companyPerformance = deliveries.stream()

733

.collect(Collectors.groupingBy(DeliveryRecord::getDeliveryCompany))

734

.entrySet().stream()

735

.collect(Collectors.toMap(

736

Map.Entry::getKey,

737

entry -> calculateCompanyPerformance(entry.getValue())

738

));

739

740

report.setCompanyPerformance(companyPerformance);

741

742

return report;

743

}

744

745

private CompanyPerformance calculateCompanyPerformance(List<DeliveryRecord> deliveries) {

746

CompanyPerformance performance = new CompanyPerformance();

747

performance.setTotalOrders(deliveries.size());

748

749

long successful = deliveries.stream()

750

.filter(d -> "delivered".equals(d.getStatus()))

751

.count();

752

performance.setSuccessRate((double) successful / deliveries.size() * 100);

753

754

double avgTime = deliveries.stream()

755

.filter(d -> d.getDeliveredTime() != null)

756

.mapToLong(d -> d.getDeliveredTime().getTime() - d.getCreatedTime().getTime())

757

.average()

758

.orElse(0) / (1000 * 60 * 60);

759

performance.setAverageDeliveryHours(avgTime);

760

761

return performance;

762

}

763

}

764

```

765

766

This logistics module provides comprehensive express delivery, same-city delivery, return logistics, and delivery tracking capabilities for WeChat MiniApp e-commerce and service applications.