Search in sources :

Example 1 with Fee

use of uk.gov.pay.connector.fee.model.Fee in project pay-connector by alphagov.

the class StripeCaptureHandler method capture.

@Override
public CaptureResponse capture(CaptureGatewayRequest request) {
    String transactionId = request.getTransactionId();
    try {
        StripeCharge capturedCharge;
        capturedCharge = captureWithPaymentIntentAPI(request);
        List<Fee> feeList = generateFeeList(request.getCreatedDate(), request, capturedCharge.getFee().orElse(0L));
        Long processingFee = StripeFeeCalculator.getTotalFeeAmount(feeList);
        Long netTransferAmount = request.getAmount() - processingFee;
        transferToConnectAccount(request, netTransferAmount, capturedCharge.getId());
        return new CaptureResponse(transactionId, COMPLETE, feeList);
    } catch (GatewayErrorException e) {
        if (e.getFamily() == CLIENT_ERROR) {
            var stripeErrorResponse = jsonObjectMapper.getObject(e.getResponseFromGateway(), StripeErrorResponse.class);
            String errorCode = stripeErrorResponse.getError().getCode();
            String errorMessage = stripeErrorResponse.getError().getMessage();
            LOGGER.warn("Capture failed for transaction id {}. Failure code from Stripe: {}, failure message from " + "Stripe: {}. External Charge id: {}. Response code from Stripe: {}", transactionId, errorCode, errorMessage, request.getExternalId(), e.getStatus());
            return fromBaseCaptureResponse(new StripeCaptureResponse(transactionId, errorCode, errorMessage), null);
        }
        if (e.getFamily() == SERVER_ERROR) {
            LOGGER.warn("Capture failed for transaction id {}. Reason: {}. Status code from Stripe: {}. Charge External Id: {}", transactionId, e.getMessage(), e.getStatus(), request.getExternalId());
            GatewayError gatewayError = gatewayConnectionError("An internal server error occurred when capturing charge_external_id: " + request.getExternalId());
            return CaptureResponse.fromGatewayError(gatewayError);
        }
        LOGGER.error("Unrecognised response status during capture. charge_external_id={}, status={}, response={}", request.getExternalId(), e.getStatus(), e.getResponseFromGateway());
        throw new RuntimeException("Unrecognised response status during capture.");
    } catch (GatewayException e) {
        return CaptureResponse.fromGatewayError(e.toGatewayError());
    }
}
Also used : GatewayErrorException(uk.gov.pay.connector.gateway.GatewayException.GatewayErrorException) Fee(uk.gov.pay.connector.fee.model.Fee) StripeCaptureResponse(uk.gov.pay.connector.gateway.stripe.response.StripeCaptureResponse) StripeErrorResponse(uk.gov.pay.connector.gateway.stripe.json.StripeErrorResponse) StripeCaptureResponse(uk.gov.pay.connector.gateway.stripe.response.StripeCaptureResponse) CaptureResponse(uk.gov.pay.connector.gateway.CaptureResponse) CaptureResponse.fromBaseCaptureResponse(uk.gov.pay.connector.gateway.CaptureResponse.fromBaseCaptureResponse) StripeCharge(uk.gov.pay.connector.gateway.stripe.json.StripeCharge) GatewayException(uk.gov.pay.connector.gateway.GatewayException) GatewayError(uk.gov.pay.connector.gateway.model.GatewayError)

Example 2 with Fee

use of uk.gov.pay.connector.fee.model.Fee in project pay-connector by alphagov.

the class CollectFeesForFailedPaymentsTaskHandlerTest method shouldPersistFeesAndEmitEvent.

@Test
void shouldPersistFeesAndEmitEvent() throws Exception {
    var paymentTaskData = new PaymentTaskData(chargeExternalId);
    List<Fee> fees = List.of(Fee.of(RADAR, 6L), Fee.of(THREE_D_S, 7L));
    when(stripePaymentProvider.calculateAndTransferFeesForFailedPayments(charge)).thenReturn(fees);
    collectFeesForFailedPaymentsTaskHandler.collectAndPersistFees(paymentTaskData);
    assertThat(charge.getFees(), hasSize(2));
    assertThat(charge.getFees(), containsInAnyOrder(allOf(hasProperty("amountCollected", is(6L)), hasProperty("feeType", is(RADAR)), hasProperty("createdDate", is(clock.instant()))), allOf(hasProperty("amountCollected", is(7L)), hasProperty("feeType", is(THREE_D_S)), hasProperty("createdDate", is(clock.instant())))));
    assertThat(charge.getNetAmount(), is(Optional.of(-13L)));
    verify(eventService).emitAndRecordEvent(feeIncurredEventArgumentCaptor.capture());
    FeeIncurredEventDetails eventDetails = (FeeIncurredEventDetails) feeIncurredEventArgumentCaptor.getValue().getEventDetails();
    assertThat(eventDetails.getFee(), is(13L));
    assertThat(eventDetails.getNetAmount(), is(-13L));
    assertThat(eventDetails.getFeeBreakdown(), is(fees));
}
Also used : FeeIncurredEventDetails(uk.gov.pay.connector.events.eventdetails.charge.FeeIncurredEventDetails) Fee(uk.gov.pay.connector.fee.model.Fee) PaymentTaskData(uk.gov.pay.connector.queue.tasks.model.PaymentTaskData) Test(org.junit.jupiter.api.Test)

Example 3 with Fee

use of uk.gov.pay.connector.fee.model.Fee in project pay-connector by alphagov.

the class CardCaptureServiceIT method shouldPersistFeesForStripeV2Charge.

@Test
public void shouldPersistFeesForStripeV2Charge() {
    long chargeId = nextInt();
    String externalChargeId = RandomIdGenerator.newId();
    databaseTestHelper.addCharge(anAddChargeParams().withChargeId(chargeId).withExternalChargeId(externalChargeId).withPaymentProvider(STRIPE.getName()).withGatewayAccountId(accountId).withAmount(10000).withStatus(ChargeStatus.CAPTURE_READY).build());
    String oldChargeStatus = ChargeStatus.CAPTURE_READY.getValue();
    String transactionId = "transactionId";
    List<Fee> feeList = List.of(Fee.of(RADAR, 10L), Fee.of(THREE_D_S, 20L), Fee.of(TRANSACTION, 480L));
    CaptureResponse captureResponse = new CaptureResponse(transactionId, CaptureResponse.ChargeState.COMPLETE, feeList);
    // Trigger the post gateway capture response programmatically which normally would be invoked by the scheduler.
    testContext.getInstanceFromGuiceContainer(CardCaptureService.class).processGatewayCaptureResponse(externalChargeId, oldChargeStatus, captureResponse);
    List<Map<String, Object>> listOfFees = databaseTestHelper.getFeesByChargeId(chargeId);
    assertThat(listOfFees, hasSize(3));
    assertThat(listOfFees, containsInAnyOrder(allOf(hasEntry("fee_type", (Object) "radar"), hasEntry("amount_collected", 10L)), allOf(hasEntry("fee_type", (Object) "three_ds"), hasEntry("amount_collected", 20L)), allOf(hasEntry("fee_type", (Object) "transaction"), hasEntry("amount_collected", 480L))));
}
Also used : CaptureResponse(uk.gov.pay.connector.gateway.CaptureResponse) Fee(uk.gov.pay.connector.fee.model.Fee) Map(java.util.Map) Test(org.junit.Test)

Example 4 with Fee

use of uk.gov.pay.connector.fee.model.Fee in project pay-connector by alphagov.

the class CollectFeesForFailedPaymentsTaskHandler method collectAndPersistFees.

@Transactional
public void collectAndPersistFees(PaymentTaskData paymentTaskData) throws GatewayException {
    ChargeEntity charge = chargeService.findChargeByExternalId(paymentTaskData.getPaymentExternalId());
    List<Fee> fees = stripePaymentProvider.calculateAndTransferFeesForFailedPayments(charge);
    Instant now = clock.instant();
    fees.stream().map(fee -> new FeeEntity(charge, now, fee)).forEach(charge::addFee);
    emitFeeEvent(charge);
}
Also used : StructuredArguments.kv(net.logstash.logback.argument.StructuredArguments.kv) PaymentTaskData(uk.gov.pay.connector.queue.tasks.model.PaymentTaskData) Logger(org.slf4j.Logger) EventService(uk.gov.pay.connector.events.EventService) LoggerFactory(org.slf4j.LoggerFactory) Instant(java.time.Instant) PaymentEvent(uk.gov.pay.connector.events.model.charge.PaymentEvent) Fee(uk.gov.pay.connector.fee.model.Fee) String.format(java.lang.String.format) Transactional(com.google.inject.persist.Transactional) FeeIncurredEvent(uk.gov.pay.connector.events.model.charge.FeeIncurredEvent) Inject(javax.inject.Inject) LEDGER_EVENT_TYPE(uk.gov.service.payments.logging.LoggingKeys.LEDGER_EVENT_TYPE) List(java.util.List) FeeEntity(uk.gov.pay.connector.charge.model.domain.FeeEntity) StripePaymentProvider(uk.gov.pay.connector.gateway.stripe.StripePaymentProvider) ChargeService(uk.gov.pay.connector.charge.service.ChargeService) EventCreationException(uk.gov.pay.connector.events.exception.EventCreationException) Clock(java.time.Clock) ChargeEntity(uk.gov.pay.connector.charge.model.domain.ChargeEntity) GatewayException(uk.gov.pay.connector.gateway.GatewayException) PAYMENT_EXTERNAL_ID(uk.gov.service.payments.logging.LoggingKeys.PAYMENT_EXTERNAL_ID) ChargeEntity(uk.gov.pay.connector.charge.model.domain.ChargeEntity) Fee(uk.gov.pay.connector.fee.model.Fee) Instant(java.time.Instant) FeeEntity(uk.gov.pay.connector.charge.model.domain.FeeEntity) Transactional(com.google.inject.persist.Transactional)

Example 5 with Fee

use of uk.gov.pay.connector.fee.model.Fee in project pay-connector by alphagov.

the class StripeCaptureHandlerTest method shouldCaptureWithV2RadarAnd3dsFeesAndTransferCorrectAmountToConnectAccount.

@Test
public void shouldCaptureWithV2RadarAnd3dsFeesAndTransferCorrectAmountToConnectAccount() throws Exception {
    mockStripeCaptureAndTransfer();
    // 26Aug2021
    int chargeCreatedDate = 1629936000;
    // 25Aug2021
    int feeV2DateAfterChargeCreatedDate = 1629849600;
    when(stripeGatewayConfig.getFeePercentageV2Date()).thenReturn(Instant.ofEpochSecond(feeV2DateAfterChargeCreatedDate));
    when(stripeGatewayConfig.getFeePercentageV2()).thenReturn(0.50);
    when(stripeGatewayConfig.getRadarFeeInPence()).thenReturn(5);
    when(stripeGatewayConfig.getThreeDsFeeInPence()).thenReturn(10);
    ChargeEntity chargeEntity = aValidChargeEntity().withGatewayAccountEntity(gatewayAccount).withTransactionId(transactionId).withAmount(10000L).withCreatedDate(Instant.ofEpochSecond(chargeCreatedDate)).withGatewayAccountCredentialsEntity(aGatewayAccountCredentialsEntity().withCredentials(Map.of("stripe_account_id", "stripe_account_id")).withPaymentProvider(STRIPE.getName()).build()).withEvents(List.of(aChargeEventEntity().withStatus(AUTHORISATION_3DS_REQUIRED).build(), aChargeEventEntity().withStatus(CREATED).build())).build();
    captureGatewayRequest = CaptureGatewayRequest.valueOf(chargeEntity);
    CaptureResponse captureResponse = stripeCaptureHandler.capture(captureGatewayRequest);
    ArgumentCaptor<StripeTransferOutRequest> transferRequestCaptor = ArgumentCaptor.forClass(StripeTransferOutRequest.class);
    verify(gatewayClient, times(2)).postRequestFor(transferRequestCaptor.capture());
    assertThat(transferRequestCaptor.getValue().getGatewayOrder().getPayload(), containsString("amount=9885"));
    assertTrue(captureResponse.isSuccessful());
    List<Fee> feeList = captureResponse.getFeeList();
    assertThat(feeList.size(), is(3));
    assertThat(captureResponse.getFeeList(), containsInAnyOrder(Fee.of(FeeType.TRANSACTION, 100L), Fee.of(FeeType.RADAR, 5L), Fee.of(FeeType.THREE_D_S, 10L)));
}
Also used : ChargeEntityFixture.aValidChargeEntity(uk.gov.pay.connector.charge.model.domain.ChargeEntityFixture.aValidChargeEntity) ChargeEntity(uk.gov.pay.connector.charge.model.domain.ChargeEntity) CaptureResponse(uk.gov.pay.connector.gateway.CaptureResponse) StripeTransferOutRequest(uk.gov.pay.connector.gateway.stripe.request.StripeTransferOutRequest) Fee(uk.gov.pay.connector.fee.model.Fee) Test(org.junit.Test)

Aggregations

Fee (uk.gov.pay.connector.fee.model.Fee)9 CaptureResponse (uk.gov.pay.connector.gateway.CaptureResponse)7 ChargeEntity (uk.gov.pay.connector.charge.model.domain.ChargeEntity)6 Test (org.junit.Test)5 ChargeEntityFixture.aValidChargeEntity (uk.gov.pay.connector.charge.model.domain.ChargeEntityFixture.aValidChargeEntity)4 StripeTransferOutRequest (uk.gov.pay.connector.gateway.stripe.request.StripeTransferOutRequest)4 Transactional (com.google.inject.persist.Transactional)2 String.format (java.lang.String.format)2 Clock (java.time.Clock)2 List (java.util.List)2 Inject (javax.inject.Inject)2 StructuredArguments.kv (net.logstash.logback.argument.StructuredArguments.kv)2 Logger (org.slf4j.Logger)2 LoggerFactory (org.slf4j.LoggerFactory)2 FeeEntity (uk.gov.pay.connector.charge.model.domain.FeeEntity)2 ChargeService (uk.gov.pay.connector.charge.service.ChargeService)2 EventService (uk.gov.pay.connector.events.EventService)2 EventCreationException (uk.gov.pay.connector.events.exception.EventCreationException)2 FeeIncurredEvent (uk.gov.pay.connector.events.model.charge.FeeIncurredEvent)2 GatewayException (uk.gov.pay.connector.gateway.GatewayException)2