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

configuration.mddocs/

0

# Configuration

1

2

Comprehensive configuration management supporting memory-based and Redis-based storage with multi-app support, access token management, and production-ready deployment options for WeChat MiniApp applications.

3

4

## Capabilities

5

6

### Configuration Interface

7

8

Core configuration interface providing access to all WeChat MiniApp settings and credentials.

9

10

```java { .api }

11

public interface WxMaConfig {

12

// Basic Configuration

13

String getAppid();

14

void setAppid(String appid);

15

String getSecret();

16

void setSecret(String secret);

17

String getToken();

18

void setToken(String token);

19

String getAesKey();

20

void setAesKey(String aesKey);

21

String getOriginalId();

22

void setOriginalId(String originalId);

23

String getCloudEnv();

24

void setCloudEnv(String cloudEnv);

25

26

// Access Token Management

27

String getAccessToken();

28

Lock getAccessTokenLock();

29

boolean isAccessTokenExpired();

30

void expireAccessToken();

31

void updateAccessToken(WxAccessToken accessToken);

32

void updateAccessToken(String accessToken, int expiresInSeconds);

33

34

// Stable Access Token Support

35

boolean isStableAccessToken();

36

void useStableAccessToken(boolean use);

37

38

// JSAPI Ticket Management

39

String getJsapiTicket();

40

Lock getJsapiTicketLock();

41

boolean isJsapiTicketExpired();

42

void expireJsapiTicket();

43

void updateJsapiTicket(String jsapiTicket, int expiresInSeconds);

44

45

// Card API Ticket Management

46

String getCardApiTicket();

47

Lock getCardApiTicketLock();

48

boolean isCardApiTicketExpired();

49

void expireCardApiTicket();

50

void updateCardApiTicket(String cardApiTicket, int expiresInSeconds);

51

52

// HTTP Configuration

53

String getHttpProxyHost();

54

void setHttpProxyHost(String httpProxyHost);

55

int getHttpProxyPort();

56

void setHttpProxyPort(int httpProxyPort);

57

String getHttpProxyUsername();

58

void setHttpProxyUsername(String httpProxyUsername);

59

String getHttpProxyPassword();

60

void setHttpProxyPassword(String httpProxyPassword);

61

62

// HTTP Client Configuration

63

int getRetrySleepMillis();

64

void setRetrySleepMillis(int retrySleepMillis);

65

int getMaxRetryTimes();

66

void setMaxRetryTimes(int maxRetryTimes);

67

ApacheHttpClientBuilder getApacheHttpClientBuilder();

68

void setApacheHttpClientBuilder(ApacheHttpClientBuilder apacheHttpClientBuilder);

69

70

// API Signature (for server-side API)

71

String getApiSignatureRsaPrivateKey();

72

void setApiSignatureRsaPrivateKey(String apiSignatureRsaPrivateKey);

73

String getApiSignatureAesKey();

74

void setApiSignatureAesKey(String apiSignatureAesKey);

75

String getApiSignatureRsaPrivateKeySn();

76

void setApiSignatureRsaPrivateKeySn(String apiSignatureRsaPrivateKeySn);

77

String getApiSignatureAesKeySn();

78

void setApiSignatureAesKeySn(String apiSignatureAesKeySn);

79

80

// Third-party Platform Support

81

String getWechatMpAppid();

82

void setWechatMpAppid(String wechatMpAppid);

83

}

84

```

85

86

### Default Configuration Implementation

87

88

Memory-based configuration implementation suitable for single-instance deployments.

89

90

```java { .api }

91

public class WxMaDefaultConfigImpl implements WxMaConfig, Serializable {

92

// Configuration Storage

93

private String appid; // Mini program App ID

94

private String secret; // Mini program App Secret

95

private String token; // Message encryption token

96

private String aesKey; // Message encryption AES key

97

private String originalId; // Original ID

98

private String cloudEnv; // Cloud environment ID

99

100

// Access Token Management

101

private volatile String accessToken; // Current access token

102

private volatile long accessTokenExpiresTime; // Expiration timestamp

103

private final Lock accessTokenLock = new ReentrantLock();

104

private boolean stableAccessToken = false; // Use stable access token interface

105

106

// Token Update Callbacks

107

private Consumer<WxAccessTokenEntity> updateAccessTokenBefore;

108

private boolean enableUpdateAccessTokenBefore = false;

109

110

// JSAPI Ticket Management

111

private volatile String jsapiTicket; // JSAPI ticket

112

private volatile long jsapiTicketExpiresTime; // JSAPI ticket expiration

113

private final Lock jsapiTicketLock = new ReentrantLock();

114

115

// Card API Ticket Management

116

private volatile String cardApiTicket; // Card API ticket

117

private volatile long cardApiTicketExpiresTime; // Card API ticket expiration

118

private final Lock cardApiTicketLock = new ReentrantLock();

119

120

// HTTP Configuration

121

private String httpProxyHost; // HTTP proxy host

122

private int httpProxyPort = 0; // HTTP proxy port

123

private String httpProxyUsername; // HTTP proxy username

124

private String httpProxyPassword; // HTTP proxy password

125

private int retrySleepMillis = 1000; // Retry delay in milliseconds

126

private int maxRetryTimes = 5; // Maximum retry attempts

127

128

// HTTP Client Builder

129

private ApacheHttpClientBuilder apacheHttpClientBuilder;

130

131

// API Signature Configuration

132

private String apiSignatureRsaPrivateKey; // RSA private key for API signature

133

private String apiSignatureAesKey; // AES key for API signature

134

private String apiSignatureRsaPrivateKeySn; // RSA key serial number

135

private String apiSignatureAesKeySn; // AES key serial number

136

137

// Third-party Platform

138

private String wechatMpAppid; // Component app ID for third-party platforms

139

140

// Constructors

141

public WxMaDefaultConfigImpl();

142

143

// Token Management Methods

144

@Override

145

public boolean isAccessTokenExpired();

146

@Override

147

public void updateAccessToken(String accessToken, int expiresInSeconds);

148

@Override

149

public void updateAccessToken(WxAccessToken accessToken);

150

151

// Callback Configuration

152

public void setUpdateAccessTokenBefore(Consumer<WxAccessTokenEntity> updateAccessTokenBefore);

153

public void enableUpdateAccessTokenBefore(boolean enable);

154

155

// All getters and setters...

156

}

157

```

158

159

### Redis Configuration Implementations

160

161

Production-ready Redis-based configuration implementations for distributed deployments.

162

163

```java { .api }

164

// Basic Redis Configuration

165

public class WxMaRedisConfigImpl extends AbstractWxMaRedisConfig {

166

private final RedisTemplate<String, String> redisTemplate;

167

168

public WxMaRedisConfigImpl(RedisTemplate<String, String> redisTemplate);

169

public WxMaRedisConfigImpl(RedisTemplate<String, String> redisTemplate, String keyPrefix);

170

171

// Redis operations using RedisTemplate

172

@Override

173

public String getConfigValue(String key, String defaultValue);

174

@Override

175

public void setConfigValue(String key, String value);

176

@Override

177

public void expireConfigValue(String key, int seconds);

178

}

179

180

// Redisson Configuration

181

public class WxMaRedissonConfigImpl extends AbstractWxMaRedisConfig {

182

private final RedissonClient redissonClient;

183

184

public WxMaRedissonConfigImpl(RedissonClient redissonClient);

185

public WxMaRedissonConfigImpl(RedissonClient redissonClient, String keyPrefix);

186

187

// Redisson operations with distributed locks

188

@Override

189

public Lock getConfigLock(String key);

190

@Override

191

public String getConfigValue(String key, String defaultValue);

192

@Override

193

public void setConfigValue(String key, String value);

194

}

195

196

// Enhanced Redis Configuration

197

public class WxMaRedisBetterConfigImpl extends AbstractWxMaRedisConfig {

198

private final RedisTemplate<String, String> redisTemplate;

199

private final StringRedisTemplate stringRedisTemplate;

200

201

public WxMaRedisBetterConfigImpl(RedisTemplate<String, String> redisTemplate,

202

StringRedisTemplate stringRedisTemplate);

203

204

// Enhanced Redis operations with better performance

205

@Override

206

public void updateAccessToken(String accessToken, int expiresInSeconds);

207

@Override

208

public boolean isAccessTokenExpired();

209

}

210

211

// Redis Connection Configuration

212

public class WxMaRedisConnectionConfigImpl extends AbstractWxMaRedisConfig {

213

private final RedisConnectionFactory connectionFactory;

214

215

public WxMaRedisConnectionConfigImpl(RedisConnectionFactory connectionFactory);

216

public WxMaRedisConnectionConfigImpl(RedisConnectionFactory connectionFactory, String keyPrefix);

217

218

// Direct Redis connection operations

219

}

220

```

221

222

### Abstract Redis Configuration

223

224

Base class providing common Redis configuration functionality.

225

226

```java { .api }

227

public abstract class AbstractWxMaRedisConfig implements WxMaConfig {

228

protected String keyPrefix = "wx:ma:"; // Redis key prefix

229

230

// Configuration Keys

231

protected static final String ACCESS_TOKEN_KEY = "access_token";

232

protected static final String JSAPI_TICKET_KEY = "jsapi_ticket";

233

protected static final String CARD_API_TICKET_KEY = "card_api_ticket";

234

235

// Lock Keys

236

protected static final String ACCESS_TOKEN_LOCK_KEY = "access_token:lock";

237

protected static final String JSAPI_TICKET_LOCK_KEY = "jsapi_ticket:lock";

238

protected static final String CARD_API_TICKET_LOCK_KEY = "card_api_ticket:lock";

239

240

// Abstract methods to be implemented by subclasses

241

protected abstract String getValue(String key);

242

protected abstract void setValue(String key, String value, int expireSeconds);

243

protected abstract void expire(String key, int seconds);

244

protected abstract Long getExpire(String key);

245

protected abstract Lock getLock(String key);

246

247

// Common Redis operations

248

protected String buildKey(String key) {

249

return keyPrefix + getAppid() + ":" + key;

250

}

251

252

// Token management using Redis

253

@Override

254

public String getAccessToken() {

255

return getValue(buildKey(ACCESS_TOKEN_KEY));

256

}

257

258

@Override

259

public boolean isAccessTokenExpired() {

260

Long expire = getExpire(buildKey(ACCESS_TOKEN_KEY));

261

return expire == null || expire < 200; // 200 second buffer

262

}

263

264

@Override

265

public void updateAccessToken(String accessToken, int expiresInSeconds) {

266

setValue(buildKey(ACCESS_TOKEN_KEY), accessToken, expiresInSeconds - 200);

267

}

268

269

@Override

270

public Lock getAccessTokenLock() {

271

return getLock(buildKey(ACCESS_TOKEN_LOCK_KEY));

272

}

273

}

274

```

275

276

## Usage Examples

277

278

### Basic Configuration Setup

279

280

#### Memory-based Configuration (Development)

281

282

```java

283

@Configuration

284

public class WeChatMiniAppConfig {

285

286

@Value("${wechat.miniapp.appid}")

287

private String appid;

288

289

@Value("${wechat.miniapp.secret}")

290

private String secret;

291

292

@Value("${wechat.miniapp.token:}")

293

private String token;

294

295

@Value("${wechat.miniapp.aes-key:}")

296

private String aesKey;

297

298

@Bean

299

public WxMaConfig wxMaConfig() {

300

WxMaDefaultConfigImpl config = new WxMaDefaultConfigImpl();

301

config.setAppid(appid);

302

config.setSecret(secret);

303

config.setToken(token);

304

config.setAesKey(aesKey);

305

306

// HTTP configuration

307

config.setRetrySleepMillis(1000);

308

config.setMaxRetryTimes(3);

309

310

// Enable stable access token (recommended for production)

311

config.useStableAccessToken(true);

312

313

return config;

314

}

315

316

@Bean

317

public WxMaService wxMaService(WxMaConfig wxMaConfig) {

318

WxMaServiceImpl service = new WxMaServiceImpl();

319

service.setWxMaConfig(wxMaConfig);

320

return service;

321

}

322

}

323

```

324

325

#### Redis-based Configuration (Production)

326

327

```java

328

@Configuration

329

@ConditionalOnProperty(name = "wechat.redis.enabled", havingValue = "true")

330

public class WeChatRedisConfig {

331

332

@Autowired

333

private RedisTemplate<String, String> redisTemplate;

334

335

@Bean

336

public WxMaConfig wxMaRedisConfig() {

337

WxMaRedisConfigImpl config = new WxMaRedisConfigImpl(redisTemplate, "wechat:ma:");

338

config.setAppid("your-appid");

339

config.setSecret("your-secret");

340

config.setToken("your-token");

341

config.setAesKey("your-aes-key");

342

343

// Configure HTTP settings

344

config.setHttpProxyHost("proxy.company.com");

345

config.setHttpProxyPort(8080);

346

config.setHttpProxyUsername("proxy-user");

347

config.setHttpProxyPassword("proxy-pass");

348

349

// Configure retry settings

350

config.setRetrySleepMillis(2000);

351

config.setMaxRetryTimes(5);

352

353

return config;

354

}

355

}

356

```

357

358

### Multi-App Configuration

359

360

#### Multiple Mini Programs Support

361

362

```java

363

@Configuration

364

public class MultiAppWeChatConfig {

365

366

@Bean

367

public WxMaService multiAppWxMaService() {

368

WxMaServiceImpl service = new WxMaServiceImpl();

369

370

// Configure multiple apps

371

Map<String, WxMaConfig> configs = new HashMap<>();

372

373

// App 1 - Main app

374

WxMaDefaultConfigImpl config1 = new WxMaDefaultConfigImpl();

375

config1.setAppid("app1-appid");

376

config1.setSecret("app1-secret");

377

config1.setToken("app1-token");

378

configs.put("main", config1);

379

380

// App 2 - Secondary app

381

WxMaDefaultConfigImpl config2 = new WxMaDefaultConfigImpl();

382

config2.setAppid("app2-appid");

383

config2.setSecret("app2-secret");

384

config2.setToken("app2-token");

385

configs.put("secondary", config2);

386

387

// App 3 - Test environment

388

WxMaDefaultConfigImpl config3 = new WxMaDefaultConfigImpl();

389

config3.setAppid("test-appid");

390

config3.setSecret("test-secret");

391

config3.setToken("test-token");

392

configs.put("test", config3);

393

394

service.setMultiConfigs(configs, "main"); // "main" as default

395

396

return service;

397

}

398

}

399

400

@Service

401

public class MultiAppService {

402

403

@Autowired

404

private WxMaService wxMaService;

405

406

public void handleMainAppRequest(String jsCode) {

407

// Use main app (default)

408

WxMaJscode2SessionResult session = wxMaService.getUserService()

409

.getSessionInfo(jsCode);

410

// Process main app request...

411

}

412

413

public void handleSecondaryAppRequest(String jsCode) {

414

// Switch to secondary app

415

wxMaService.switchoverTo("secondary");

416

try {

417

WxMaJscode2SessionResult session = wxMaService.getUserService()

418

.getSessionInfo(jsCode);

419

// Process secondary app request...

420

} finally {

421

// Switch back to default

422

wxMaService.switchoverTo("main");

423

}

424

}

425

426

public void handleTestRequest(String jsCode) {

427

// Use test environment

428

wxMaService.switchoverTo("test");

429

try {

430

WxMaJscode2SessionResult session = wxMaService.getUserService()

431

.getSessionInfo(jsCode);

432

// Process test request...

433

} finally {

434

wxMaService.switchoverTo("main");

435

}

436

}

437

}

438

```

439

440

### Advanced Configuration

441

442

#### Custom HTTP Client Configuration

443

444

```java

445

@Configuration

446

public class CustomHttpClientConfig {

447

448

@Bean

449

public WxMaConfig customHttpConfig() {

450

WxMaDefaultConfigImpl config = new WxMaDefaultConfigImpl();

451

config.setAppid("your-appid");

452

config.setSecret("your-secret");

453

454

// Custom Apache HttpClient configuration

455

ApacheHttpClientBuilder httpClientBuilder = ApacheHttpClientBuilder.create()

456

.setConnectionTimeout(10000) // 10 seconds connection timeout

457

.setSocketTimeout(30000) // 30 seconds socket timeout

458

.setConnectionRequestTimeout(5000) // 5 seconds connection request timeout

459

.setMaxTotalConnections(200) // Max total connections

460

.setMaxConnectionsPerRoute(50) // Max connections per route

461

.setRetryCount(3); // Retry count

462

463

// Custom connection pool configuration

464

httpClientBuilder.setConnectionTimeToLive(300, TimeUnit.SECONDS);

465

httpClientBuilder.setConnectionKeepAlive(true);

466

467

config.setApacheHttpClientBuilder(httpClientBuilder);

468

469

// Configure retry behavior

470

config.setRetrySleepMillis(1500);

471

config.setMaxRetryTimes(3);

472

473

return config;

474

}

475

}

476

```

477

478

#### Access Token Callback Configuration

479

480

```java

481

@Component

482

public class TokenManagementService {

483

484

@Bean

485

public WxMaConfig tokenCallbackConfig() {

486

WxMaDefaultConfigImpl config = new WxMaDefaultConfigImpl();

487

config.setAppid("your-appid");

488

config.setSecret("your-secret");

489

490

// Enable token update callbacks

491

config.enableUpdateAccessTokenBefore(true);

492

493

// Set token update callback

494

config.setUpdateAccessTokenBefore(tokenEntity -> {

495

logger.info("Access token about to be updated: {} -> {}",

496

tokenEntity.getOldToken(), tokenEntity.getNewToken());

497

498

// Store token update in audit log

499

auditService.logTokenUpdate(tokenEntity);

500

501

// Update token in external cache if needed

502

externalCacheService.updateToken(tokenEntity.getNewToken());

503

504

// Notify monitoring system

505

monitoringService.notifyTokenUpdate(tokenEntity);

506

});

507

508

return config;

509

}

510

511

@Autowired

512

private AuditService auditService;

513

514

@Autowired

515

private ExternalCacheService externalCacheService;

516

517

@Autowired

518

private MonitoringService monitoringService;

519

}

520

```

521

522

### Production Configuration Examples

523

524

#### Redis Cluster Configuration

525

526

```java

527

@Configuration

528

@Profile("production")

529

public class ProductionRedisConfig {

530

531

@Bean

532

public LettuceConnectionFactory redisConnectionFactory() {

533

RedisClusterConfiguration clusterConfig = new RedisClusterConfiguration(

534

Arrays.asList(

535

"redis-cluster-node1:7000",

536

"redis-cluster-node2:7000",

537

"redis-cluster-node3:7000"

538

)

539

);

540

clusterConfig.setPassword("redis-password");

541

542

LettuceClientConfiguration clientConfig = LettuceClientConfiguration.builder()

543

.commandTimeout(Duration.ofSeconds(2))

544

.shutdownTimeout(Duration.ZERO)

545

.build();

546

547

return new LettuceConnectionFactory(clusterConfig, clientConfig);

548

}

549

550

@Bean

551

public WxMaConfig productionWxMaConfig(RedisConnectionFactory connectionFactory) {

552

WxMaRedisConnectionConfigImpl config = new WxMaRedisConnectionConfigImpl(

553

connectionFactory, "prod:wechat:ma:"

554

);

555

556

config.setAppid("prod-appid");

557

config.setSecret("prod-secret");

558

config.setToken("prod-token");

559

config.setAesKey("prod-aes-key");

560

561

// Production settings

562

config.useStableAccessToken(true);

563

config.setRetrySleepMillis(2000);

564

config.setMaxRetryTimes(5);

565

566

// Configure for high availability

567

config.setHttpProxyHost(null); // No proxy in production

568

config.setMaxRetryTimes(10); // More retries for reliability

569

570

return config;

571

}

572

}

573

```

574

575

#### Environment-specific Configuration

576

577

```java

578

@Configuration

579

public class EnvironmentAwareConfig {

580

581

@Value("${spring.profiles.active:dev}")

582

private String activeProfile;

583

584

@Bean

585

@ConditionalOnProperty(name = "spring.profiles.active", havingValue = "dev")

586

public WxMaConfig devConfig() {

587

WxMaDefaultConfigImpl config = new WxMaDefaultConfigImpl();

588

config.setAppid("dev-appid");

589

config.setSecret("dev-secret");

590

config.setRetrySleepMillis(500); // Faster retries in dev

591

config.setMaxRetryTimes(2); // Fewer retries in dev

592

593

return config;

594

}

595

596

@Bean

597

@ConditionalOnProperty(name = "spring.profiles.active", havingValue = "staging")

598

public WxMaConfig stagingConfig(RedisTemplate<String, String> redisTemplate) {

599

WxMaRedisConfigImpl config = new WxMaRedisConfigImpl(

600

redisTemplate, "staging:wechat:ma:"

601

);

602

config.setAppid("staging-appid");

603

config.setSecret("staging-secret");

604

config.useStableAccessToken(true);

605

606

return config;

607

}

608

609

@Bean

610

@ConditionalOnProperty(name = "spring.profiles.active", havingValue = "prod")

611

public WxMaConfig productionConfig(RedissonClient redissonClient) {

612

WxMaRedissonConfigImpl config = new WxMaRedissonConfigImpl(

613

redissonClient, "prod:wechat:ma:"

614

);

615

config.setAppid("prod-appid");

616

config.setSecret("prod-secret");

617

config.useStableAccessToken(true);

618

config.setRetrySleepMillis(3000);

619

config.setMaxRetryTimes(8);

620

621

return config;

622

}

623

}

624

```

625

626

### Configuration Monitoring and Health Checks

627

628

```java

629

@Component

630

public class WeChatConfigHealthIndicator implements HealthIndicator {

631

632

@Autowired

633

private WxMaService wxMaService;

634

635

@Override

636

public Health health() {

637

try {

638

WxMaConfig config = wxMaService.getWxMaConfig();

639

640

// Check basic configuration

641

if (config.getAppid() == null || config.getSecret() == null) {

642

return Health.down()

643

.withDetail("error", "Missing required configuration")

644

.build();

645

}

646

647

// Check access token

648

String accessToken = config.getAccessToken();

649

boolean tokenExpired = config.isAccessTokenExpired();

650

651

Health.Builder builder = Health.up()

652

.withDetail("appid", config.getAppid())

653

.withDetail("hasAccessToken", accessToken != null)

654

.withDetail("tokenExpired", tokenExpired)

655

.withDetail("configType", config.getClass().getSimpleName());

656

657

// Check Redis connection if using Redis config

658

if (config instanceof AbstractWxMaRedisConfig) {

659

builder.withDetail("storageType", "Redis");

660

} else {

661

builder.withDetail("storageType", "Memory");

662

}

663

664

return builder.build();

665

666

} catch (Exception e) {

667

return Health.down()

668

.withDetail("error", e.getMessage())

669

.build();

670

}

671

}

672

}

673

674

@Component

675

public class ConfigurationMetrics {

676

677

@Autowired

678

private WxMaService wxMaService;

679

680

@Autowired

681

private MeterRegistry meterRegistry;

682

683

@PostConstruct

684

public void initMetrics() {

685

// Track access token age

686

Gauge.builder("wechat.access_token.age.seconds")

687

.description("Age of current access token in seconds")

688

.register(meterRegistry, this, metrics -> {

689

try {

690

WxMaConfig config = wxMaService.getWxMaConfig();

691

// Calculate token age based on expiration

692

return config.isAccessTokenExpired() ? -1 :

693

calculateTokenAge(config.getAccessToken());

694

} catch (Exception e) {

695

return -1;

696

}

697

});

698

}

699

700

@EventListener

701

public void onAccessTokenUpdate(AccessTokenUpdateEvent event) {

702

meterRegistry.counter("wechat.access_token.updates.total")

703

.increment();

704

}

705

706

@Scheduled(fixedRate = 60000) // Every minute

707

public void recordConfigMetrics() {

708

try {

709

WxMaConfig config = wxMaService.getWxMaConfig();

710

711

// Record token expiration status

712

meterRegistry.gauge("wechat.access_token.expired",

713

config.isAccessTokenExpired() ? 1 : 0);

714

715

// Record JSAPI ticket status

716

meterRegistry.gauge("wechat.jsapi_ticket.expired",

717

config.isJsapiTicketExpired() ? 1 : 0);

718

719

} catch (Exception e) {

720

logger.error("Failed to record config metrics: {}", e.getMessage());

721

}

722

}

723

}

724

```

725

726

### Configuration Security Best Practices

727

728

```java

729

@Configuration

730

public class SecureConfigurationExample {

731

732

// Use environment variables for sensitive data

733

@Value("${WECHAT_APPID}")

734

private String appid;

735

736

@Value("${WECHAT_SECRET}")

737

private String secret;

738

739

@Value("${WECHAT_AES_KEY}")

740

private String aesKey;

741

742

@Bean

743

public WxMaConfig secureConfig() {

744

WxMaDefaultConfigImpl config = new WxMaDefaultConfigImpl();

745

config.setAppid(appid);

746

config.setSecret(secret);

747

config.setAesKey(aesKey);

748

749

// Configure API signature for enhanced security

750

config.setApiSignatureRsaPrivateKey(loadRsaPrivateKey());

751

config.setApiSignatureAesKey(loadApiAesKey());

752

753

return config;

754

}

755

756

private String loadRsaPrivateKey() {

757

try {

758

// Load from secure key management system

759

return keyManagementService.getPrivateKey("wechat-rsa");

760

} catch (Exception e) {

761

logger.error("Failed to load RSA private key: {}", e.getMessage());

762

throw new ConfigurationException("Security key loading failed", e);

763

}

764

}

765

766

private String loadApiAesKey() {

767

try {

768

return keyManagementService.getAesKey("wechat-api");

769

} catch (Exception e) {

770

logger.error("Failed to load API AES key: {}", e.getMessage());

771

throw new ConfigurationException("Security key loading failed", e);

772

}

773

}

774

775

@Autowired

776

private KeyManagementService keyManagementService;

777

}

778

```

779

780

This configuration module provides comprehensive setup options for WeChat MiniApp applications, supporting both development and production environments with proper security, monitoring, and scalability considerations.