马来西亚支付网关对接Spring Boot教程

Categories:

# 马来西亚支付网关对接Spring Boot教程

1. 准备工作

在开始对接马来西亚支付网关之前,您需要:

1. 选择支付网关提供商:
– Boost
– GrabPay
– Touch ‘n Go eWallet
– Maybank2u
– CIMB Clicks
– FPX (Financial Process Exchange)

2. 注册商户账户:向所选支付服务提供商申请商户账户

3. 获取API凭证:
– Merchant ID
– API Key/Secret
– 回调URL配置权限

2. Spring Boot项目设置

添加依赖项

“`xml


org.springframework.boot
spring-boot-starter-web



org.apache.httpcomponents
httpclient
4.5.13



com.fasterxml.jackson.core
jackson-databind



org.projectlombok
lomboktrue<|vq_1020|>`


Pay with BOOST

“`

马来西亚支付网关对接Spring Boot教程(续)

7. 安全最佳实践

7.1 HTTPS强制配置

@Configuration
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http.requiresChannel()
.requestMatchers(r -> r.getHeader("X-Forwarded-Proto") != null)
.requiresSecure();
}
}

7.2 API请求签名验证(以Boost为例)

public class SignatureUtils {

public static String generateBoostSignature(String secretKey, Map<String, String> params)
throws NoSuchAlgorithmException, InvalidKeyException {

StringBuilder sb = new StringBuilder();
params.entrySet().stream()
.sorted(Map.Entry.comparingByKey())
.forEach(entry -> sb.append(entry.getKey()).append("=").append(entry.getValue()).append("&"));

String payload = sb.substring(0, sb.length() - 1);

Mac sha256_HMAC = Mac.getInstance("HmacSHA256");
SecretKeySpec secret_key = new SecretKeySpec(secretKey.getBytes(), "HmacSHA256");
sha256_HMAC.init(secret_key);

byte[] hashBytes = sha256_HMAC.doFinal(payload.getBytes());
return Base64.getEncoder().encodeToString(hashBytes);
}
}

8. 多支付网关集成策略

8.1 Payment Gateway Factory模式实现

public interface PaymentGateway {
PaymentResponse createPayment(PaymentRequest request);
}

@Service
public class PaymentGatewayFactory {

private final BoostPaymentService boost;
private final FpxPaymentService fpx;

// ...其他支付服务注入

public PaymentGateway getGateway(String gatewayType) {
switch (gatewayType.toUpperCase()) {
case "BOOST": return boost;
case "FPX": return fpx;
// ...其他case分支

default: throw new IllegalArgumentException("Unsupported payment gateway");
}
}
}

// Controller中使用示例:
@PostMapping("/pay")
public ResponseEntity<?> processPayment(@RequestBody UnifiedPaymentRequest request) {
PaymentGateway gateway = factory.getGateway(request.gatewayType());
return ResponseEntity.ok(gateway.createPayment(request));
}

9. 测试与调试

沙箱环境配置

各平台通常提供沙盒环境:

Provider Sandbox URL Credentials获取方式
Boost https://sandbox.api.myboost.com.my Developer Portal申请
GrabPay https://partner-gsb.sandbox.grab.com Grab商户后台下载

建议使用Mock服务进行本地测试:

@Profile("test")  
@RestController
@RequestMapping("/mock/payment")
class MockBoostController {

@PostMapping("/create")
public ResponseEntity<Map<String,String>> mockCreate(@RequestBody Map req){
return ok(Map.of(
"payment_url", "/mock/checkout?token=mock_" + UUID.randomUUID(),
"status", "PENDING"
));
}
}

10. 生产环境注意事项

1. 交易记录持久化:

CREATE TABLE transactions (
id BIGINT PRIMARY KEY AUTO_INCREMENT,
order_id VARCHAR(50) UNIQUE NOT NULL,
amount DECIMAL(12,2),
gw_type ENUM('BOOST','GRAB','FPX'),
gw_transaction_id VARCHAR(100),
callback_data JSON,
timestamp DATETIME DEFAULT CURRENT_TIMESTAMP
);

2. 定时对账任务:

@Component    
class ReconciliationTask {

private final TransactionRepo repo;

@Scheduled(cron="0 */4 * * * ?") //每4小时执行一次
void reconcileWithGateways(){
repo.findPendingTransactions().forEach(txn -> {
boolean settled = checkGwStatus(txn);
if (settled){
txn.markAsCompleted();
repo.save(txn);
}
});
}
}

3. 性能监控指标(使用Micrometer):

management.endpoints.web.exposure:
include: prometheus

payment.metrics:
success.counter: payment_success_total{type=~"[a-z]+"}
failure.timer: payment_processing_seconds_failed{exception=~".*"}

如需更详细的特定支付网关实现或遇到集成问题,可以提供以下信息以便进一步协助:

  • Target provider name (e.g., TNG eWallet specific requirements?)
  • Received error messages from their API sandbox