Search code examples
adyen

Web Drop-in integration "advanced use case" redirect result


I'm trying to understand if it's possible to retrieve the redirectResult when the user is redirected to our redirectUrl to invoke the /payment/details API endpoint to speed up delivering virtual goods instead of waiting for the web hook (I'm aware it will not work for "async" payment methods).

Looking at https://docs.adyen.com/online-payments/web-drop-in/advanced-use-cases/redirect-result it should be possible, however, the returnUrl in CreateCheckoutSessionResponse returned from com.adyen.service.Checkout#sessions (adyen-java-api-library 17.2.0 - checkout api version v68) does not contain the aforementioned redirectResult param so the configuration we pass into the drop-in template is missing this data and does not seem to be available in the onPaymentCompleted callback either (only resultCode and sessionData).

@Override
public RedirectResponse handleRedirectToPartner(PaymentContext paymentContext) throws PartnerIntegrationException {
    final Payment payment = paymentContext.getPayment();

    final Amount amount = new Amount();
    amount.setCurrency(payment.getCurrency().toUpperCase());
    amount.setValue((long) payment.getPriceInCents());

    final CreateCheckoutSessionRequest checkoutSessionRequest = new CreateCheckoutSessionRequest();
    ...
    checkoutSessionRequest.setChannel(CreateCheckoutSessionRequest.ChannelEnum.WEB);
    checkoutSessionRequest.setReturnUrl(getReturnUrl());

    try {
        CreateCheckoutSessionResponse checkoutSessionResponse = checkout().sessions(checkoutSessionRequest);
        JSONObject params = new JSONObject();
        params.put("environment", testMode ? "test" : "live");
        params.put("clientKey", adyenClientKey);
        JSONObject session = new JSONObject();
        session.put("id", checkoutSessionResponse.getId());
        session.put("sessionData", checkoutSessionResponse.getSessionData());
        params.put("session", session);
        params.put("urlKo", getFailureUrl());
        params.put("urlOk", checkoutSessionResponse.getReturnUrl());
        params.put("urlPending", getUrlPending(checkoutSessionResponse.getReturnUrl()));

        return new RedirectResponse(RedirectResponse.Type.REDIRECT_CUSTOM_HTML_ADYEN, null, params);
    } catch (ApiException | IOException e) {
        throw new PartnerIntegrationException("Failed creating Adyen session", e);
    }
}

protected Checkout checkout() {
    return new Checkout(new Client(adyenApiKey, testMode ? Environment.TEST : Environment.LIVE,
            testMode ? null : liveEndpointUrlPrefix));
}

(async () => {
    let configuration = ${partnerJsonParameters?string};
    configuration.onPaymentCompleted = function(result, component) {
        console.info(result);
        if (result.sessionData) {
            console.info(result.sessionData);
        }
        if (result.resultCode) {
            console.info(result.resultCode);
        }
        handleServerResponse(result, configuration);
    };
    configuration.onError = function(error, component) {
        console.error(error, component);
        handleServerResponse(result, configuration);
    };
    let checkout = await AdyenCheckout(configuration);
    checkout.create('dropin').mount('#dropin-container');
})();

Solution

  • The sessions request does not perform the payment, but only initiates the payment session with all required parameters and configuration.

    The Web drop-in takes care of 'talking' to the Adyen backend and eventually, the payment outcome can be obtained in the frontend using the onPaymentCompleted handler.

      onPaymentCompleted: (result, component) => {
            console.info("onPaymentCompleted: " + result.resultCode);
            ...
          }
    

    See Use the result code

    On the server-side it is possible to get the payment result with a /payments/details call in addition to /sessions if needed.

     // get redirectResult appended to the returnUrl 
     String redirectResult = request.getParameter("redirectResult");
    
     var paymentDetails = new PaymentsDetailsRequest();
     paymentDetails.setDetails(Collections.singletonMap("redirectResult", redirectResult));
    
     // use paymentDetails() method
     var paymentsDetailsResponse = checkout.paymentsDetails(paymentDetails);
    
     String resultCode = paymentsDetailsResponse.getResultCode();
    

    Note that a synchronous result is not always available, hence relying on the webhook is best.