OkHttp实战:5分钟搞定微信支付/支付宝回调接口的验签与响应
OkHttp实战5分钟搞定微信支付/支付宝回调接口的验签与响应当你的应用接入第三方支付平台时支付成功后的回调处理是确保交易完整性的关键环节。一个健壮的回调处理系统需要高效完成签名验证、数据解析和响应返回而OkHttp作为现代Java生态中最受欢迎的HTTP客户端库能够帮助我们优雅地实现这一流程。1. 支付回调的核心挑战与OkHttp解决方案第三方支付平台如微信支付、支付宝在交易完成后会向商户服务器发送异步通知。这个过程中存在几个技术难点签名验证防止伪造请求数据格式处理微信支付使用XML支付宝使用JSON响应时效性必须在规定时间内返回确认幂等性保证避免重复处理同一笔交易OkHttp的以下特性使其成为处理支付回调的理想选择// OkHttp核心优势示例 OkHttpClient client new OkHttpClient.Builder() .connectTimeout(3, TimeUnit.SECONDS) // 快速响应 .readTimeout(5, TimeUnit.SECONDS) .writeTimeout(5, TimeUnit.SECONDS) .addInterceptor(new SignatureInterceptor()) // 签名拦截器 .build();2. 构建安全的验签机制支付平台的签名算法通常采用RSA或HMAC-SHA256OkHttp可以通过拦截器统一处理签名验证2.1 签名验证拦截器实现public class PaymentSignatureInterceptor implements Interceptor { private static final String SIGN_FIELD sign; private final String apiKey; public PaymentSignatureInterceptor(String apiKey) { this.apiKey apiKey; } Override public Response intercept(Chain chain) throws IOException { Request request chain.request(); Response response chain.proceed(request); // 验证响应签名 String responseBody response.peekBody(Long.MAX_VALUE).string(); MapString, String params parseResponse(responseBody); if (!verifySignature(params, apiKey)) { throw new SecurityException(Invalid signature); } return response.newBuilder() .body(ResponseBody.create(responseBody, response.body().contentType())) .build(); } private boolean verifySignature(MapString, String params, String key) { // 实现具体的验签逻辑 return PaymentSignUtil.verify(params, key); } }2.2 常见支付平台签名对比平台算法签名位置特点微信支付HMAC-SHA256HTTP Header需要二次验签支付宝RSA2POST Body支持多种签名方式PayPalSHA1withRSAAuthorization使用证书链验证3. 处理不同支付平台的数据格式3.1 XML与JSON的自动转换// 微信支付XML处理示例 public String handleWechatNotify(String xmlData) throws IOException { // 使用JAXB或SimpleXML解析 WechatPaymentResult result xmlMapper.readValue(xmlData, WechatPaymentResult.class); // 业务处理... // 返回微信要求的XML响应 return xmlreturn_codeSUCCESS/return_code/xml; } // 支付宝JSON处理示例 public String handleAlipayNotify(String jsonData) { JSONObject json new JSONObject(jsonData); AlipayPaymentResult result json.toJavaObject(AlipayPaymentResult.class); // 业务处理... return success; // 支付宝特定响应 }3.2 统一封装工具类public class PaymentCallbackHandler { private final OkHttpClient httpClient; private final PaymentConfig config; public PaymentCallbackHandler(PaymentConfig config) { this.httpClient new OkHttpClient.Builder() .addInterceptor(new PaymentSignatureInterceptor(config.getApiKey())) .build(); this.config config; } public String processCallback(String rawData, PaymentPlatform platform) { try { PaymentResult result platform.parse(rawData); boolean valid platform.verifySignature(result); if (valid) { // 处理业务逻辑 return platform.getSuccessResponse(); } return platform.getFailureResponse(); } catch (Exception e) { return platform.getErrorResponse(); } } }4. 同步与异步调用的策略选择支付回调处理需要根据业务场景选择合适的调用方式4.1 同步执行execute适用于简单业务逻辑需要立即返回结果的场景测试环境验证public String handleCallbackSync(Request request) throws IOException { try (Response response httpClient.newCall(request).execute()) { if (!response.isSuccessful()) { throw new IOException(Unexpected code response); } return response.body().string(); } }4.2 异步执行enqueue适用于复杂业务处理需要保证快速响应的生产环境高并发场景public void handleCallbackAsync(Request request, Callback callback) { httpClient.newCall(request).enqueue(new Callback() { Override public void onFailure(Call call, IOException e) { callback.onError(e); } Override public void onResponse(Call call, Response response) { try { String result response.body().string(); callback.onSuccess(result); } catch (IOException e) { callback.onError(e); } } }); }5. 实战完整的支付回调处理流程5.1 处理流程图解接收支付平台回调请求解析请求参数并验签检查订单状态防止重复处理执行业务逻辑发货、记账等记录处理日志返回平台指定格式的响应5.2 完整工具类实现Slf4j public class PaymentCallbackUtil { private static final MapPaymentPlatform, PaymentHandler handlers new EnumMap(PaymentPlatform.class); static { handlers.put(PaymentPlatform.WECHAT, new WechatPaymentHandler()); handlers.put(PaymentPlatform.ALIPAY, new AlipayPaymentHandler()); } public static String handlePaymentNotify(String rawData, PaymentPlatform platform) { PaymentHandler handler handlers.get(platform); if (handler null) { throw new IllegalArgumentException(Unsupported platform); } try { // 1. 解析原始数据 PaymentNotification notification handler.parse(rawData); // 2. 验证签名 if (!handler.verify(notification)) { log.warn(Invalid signature for {}, platform); return handler.getFailureResponse(); } // 3. 检查订单状态 if (isOrderProcessed(notification.getOutTradeNo())) { log.info(Order {} already processed, notification.getOutTradeNo()); return handler.getSuccessResponse(); } // 4. 处理业务逻辑 boolean success processBusiness(notification); // 5. 记录处理结果 logPaymentResult(notification, success); return success ? handler.getSuccessResponse() : handler.getFailureResponse(); } catch (Exception e) { log.error(Process payment notify failed, e); return handler.getErrorResponse(); } } private static boolean isOrderProcessed(String outTradeNo) { // 实现订单查重逻辑 return false; } private static boolean processBusiness(PaymentNotification notification) { // 实现业务处理逻辑 return true; } }在实际项目中支付回调处理往往是最容易出问题的环节之一。经过多次迭代我们发现将验签逻辑与业务处理分离同时做好完善的日志记录可以显著提高系统的可靠性。特别是在高并发场景下使用OkHttp的连接池特性能够有效提升处理性能。