//
// PROCESS STATUS UPDATES
//
logger.info("Process status updates... type={}, id={}", event.getType(), event.getId());
if ("payment_intent.succeeded".equals(event.getType())
|| "payment_intent.payment_failed".equals(event.getType())
|| "payment_intent.canceled".equals(event.getType())
) {
// This is currently processing only the payment_intent status changes. It will be followed
// by a charge status change (payment_intent.succeeded then charge.succeeded). The payment_intent
// typically reflects the payment at the convenience store, while th charge is the actual
// charge.
logger.info("Payment intent succeeded...");
final PaymentIntent intent;
final var deserializer = event.getDataObjectDeserializer();
if (deserializer.getObject().isPresent()) {
// Attempt to get the object the normal way
intent = (PaymentIntent) deserializer.getObject().get();
} else {
// API version mismatch — parse raw JSON directly
try {
intent = PaymentIntent.GSON.fromJson(
deserializer.getRawJson(), PaymentIntent.class);
} catch (Exception parseEx) {
logger.error("Webhook: failed to deserialize PaymentIntent from raw JSON", parseEx);
return new PluginGatewayNotification(event.getId());
}
}
logger.info("... intent={}...", intent);
if (intent != null) {
logger.info("Intent not null... status={}, id={}", intent.getStatus(), intent.getId());
try {
// Look up the KB transaction by Stripe PI ID and update it
final StripeResponsesRecord record = dao.getResponseByStripeId(intent.getId(), context.getTenantId());
if (record != null) {
Charge lastCharge = null;
if (intent.getLatestCharge() != null) {
try {
lastCharge = Charge.retrieve(intent.getLatestCharge(), buildRequestOptions(context));
} catch (Exception e) {
logger.warn("Could not retrieve charge for PI {}", intent.getId(), e);
}
}
//
// UPDATE DB
//
final UUID kbTransactionId = UUID.fromString(record.getKbPaymentTransactionId());
StripeResponsesRecord updatedRecord = dao.updateResponse(kbTransactionId, intent, lastCharge, context.getTenantId());
logger.info("Webhook: updated response for PI {} → {}", intent.getId(), intent.getStatus());
notifyStateChange(updatedRecord, intent, properties, context);
} else {
logger.warn("Webhook: no response record found for PI {}", intent.getId());
}
} catch (final SQLException e) {
logger.error("Webhook: DB error updating response for PI {}", intent.getId(), e);
}
return new PluginGatewayNotification(event.getId());
}
}
} catch (final SignatureVerificationException e) {
logger.warn("STRIPE WEBHOOK IGNORED: Invalid Stripe webhook signature", e);
} catch (final Exception e) {
logger.error("STRIPE WEBHOOK ERROR: Failed to process Stripe webhook", e);
}