Search in sources :

Example 36 with Payment

use of org.killbill.billing.payment.api.Payment in project killbill by killbill.

the class TransactionResource method notifyStateChanged.

@TimedResource
@POST
@Path("/{transactionId:" + UUID_PATTERN + "}/")
@Consumes(APPLICATION_JSON)
@Produces(APPLICATION_JSON)
@ApiOperation(value = "Mark a pending payment transaction as succeeded or failed")
@ApiResponses(value = { @ApiResponse(code = 400, message = "Invalid paymentId supplied"), @ApiResponse(code = 404, message = "Account or Payment not found") })
public Response notifyStateChanged(final PaymentTransactionJson json, @PathParam("transactionId") final String transactionIdStr, @HeaderParam(HDR_CREATED_BY) final String createdBy, @HeaderParam(HDR_REASON) final String reason, @HeaderParam(HDR_COMMENT) final String comment, @javax.ws.rs.core.Context final UriInfo uriInfo, @javax.ws.rs.core.Context final HttpServletRequest request) throws PaymentApiException, AccountApiException {
    verifyNonNullOrEmpty(json, "PaymentTransactionJson body should be specified");
    verifyNonNullOrEmpty(json.getPaymentId(), "PaymentTransactionJson paymentId needs to be set", json.getStatus(), "PaymentTransactionJson status needs to be set");
    final CallContext callContext = context.createContext(createdBy, reason, comment, request);
    final UUID paymentId = UUID.fromString(json.getPaymentId());
    final Payment payment = paymentApi.getPayment(paymentId, false, false, ImmutableList.<PluginProperty>of(), callContext);
    final Account account = accountUserApi.getAccountById(payment.getAccountId(), callContext);
    final boolean success = TransactionStatus.SUCCESS.name().equals(json.getStatus());
    final Payment result = paymentApi.notifyPendingTransactionOfStateChanged(account, UUID.fromString(transactionIdStr), success, callContext);
    return uriBuilder.buildResponse(uriInfo, PaymentResource.class, "getPayment", result.getId(), request);
}
Also used : Account(org.killbill.billing.account.api.Account) Payment(org.killbill.billing.payment.api.Payment) UUID(java.util.UUID) CallContext(org.killbill.billing.util.callcontext.CallContext) Path(javax.ws.rs.Path) TimedResource(org.killbill.commons.metrics.TimedResource) POST(javax.ws.rs.POST) Consumes(javax.ws.rs.Consumes) Produces(javax.ws.rs.Produces) ApiOperation(io.swagger.annotations.ApiOperation) ApiResponses(io.swagger.annotations.ApiResponses)

Example 37 with Payment

use of org.killbill.billing.payment.api.Payment in project killbill by killbill.

the class TransactionResource method getPaymentByTransactionId.

@TimedResource(name = "getPaymentByTransactionId")
@GET
@Path("/{transactionId:" + UUID_PATTERN + "}/")
@Produces(APPLICATION_JSON)
@ApiOperation(value = "Retrieve a payment by transaction id", response = PaymentJson.class)
@ApiResponses(value = { @ApiResponse(code = 404, message = "Payment not found") })
public Response getPaymentByTransactionId(@PathParam("transactionId") final String transactionIdStr, @QueryParam(QUERY_WITH_PLUGIN_INFO) @DefaultValue("false") final Boolean withPluginInfo, @QueryParam(QUERY_WITH_ATTEMPTS) @DefaultValue("false") final Boolean withAttempts, @QueryParam(QUERY_PLUGIN_PROPERTY) final List<String> pluginPropertiesString, @QueryParam(QUERY_AUDIT) @DefaultValue("NONE") final AuditMode auditMode, @javax.ws.rs.core.Context final HttpServletRequest request) throws PaymentApiException {
    final Iterable<PluginProperty> pluginProperties = extractPluginProperties(pluginPropertiesString);
    final UUID transactionIdId = UUID.fromString(transactionIdStr);
    final TenantContext tenantContext = context.createContext(request);
    final Payment payment = paymentApi.getPaymentByTransactionId(transactionIdId, withPluginInfo, withAttempts, pluginProperties, tenantContext);
    final AccountAuditLogs accountAuditLogs = auditUserApi.getAccountAuditLogs(payment.getAccountId(), auditMode.getLevel(), tenantContext);
    final PaymentJson result = new PaymentJson(payment, accountAuditLogs);
    return Response.status(Response.Status.OK).entity(result).build();
}
Also used : PluginProperty(org.killbill.billing.payment.api.PluginProperty) Payment(org.killbill.billing.payment.api.Payment) TenantContext(org.killbill.billing.util.callcontext.TenantContext) PaymentJson(org.killbill.billing.jaxrs.json.PaymentJson) UUID(java.util.UUID) AccountAuditLogs(org.killbill.billing.util.audit.AccountAuditLogs) Path(javax.ws.rs.Path) TimedResource(org.killbill.commons.metrics.TimedResource) Produces(javax.ws.rs.Produces) GET(javax.ws.rs.GET) ApiOperation(io.swagger.annotations.ApiOperation) ApiResponses(io.swagger.annotations.ApiResponses)

Example 38 with Payment

use of org.killbill.billing.payment.api.Payment in project killbill by killbill.

the class TestOverdueIntegration method testShouldBeInOverdueAfterRefundWithoutAdjustment.

@Test(groups = "slow", description = "Test overdue after refund with no adjustment")
public void testShouldBeInOverdueAfterRefundWithoutAdjustment() throws Exception {
    // 2012-05-01T00:03:42.000Z
    clock.setTime(new DateTime(2012, 5, 1, 0, 3, 42, 0));
    setupAccount();
    // Create subscription and don't fail payments
    final DefaultEntitlement baseEntitlement = createBaseEntitlementAndCheckForCompletion(account.getId(), "externalKey", productName, ProductCategory.BASE, term, NextEvent.CREATE, NextEvent.BLOCK, NextEvent.INVOICE);
    bundle = subscriptionApi.getSubscriptionBundle(baseEntitlement.getBundleId(), callContext);
    invoiceChecker.checkInvoice(account.getId(), 1, callContext, new ExpectedInvoiceItemCheck(new LocalDate(2012, 5, 1), null, InvoiceItemType.FIXED, new BigDecimal("0")));
    invoiceChecker.checkChargedThroughDate(baseEntitlement.getId(), new LocalDate(2012, 5, 1), callContext);
    // 2012-05-31 => DAY 30 have to get out of trial before first payment
    addDaysAndCheckForCompletion(30, NextEvent.PHASE, NextEvent.INVOICE, NextEvent.PAYMENT, NextEvent.INVOICE_PAYMENT);
    invoiceChecker.checkInvoice(account.getId(), 2, callContext, new ExpectedInvoiceItemCheck(new LocalDate(2012, 5, 31), new LocalDate(2012, 6, 30), InvoiceItemType.RECURRING, new BigDecimal("249.95")));
    invoiceChecker.checkChargedThroughDate(baseEntitlement.getId(), new LocalDate(2012, 6, 30), callContext);
    // Should still be in clear state
    checkODState(OverdueWrapper.CLEAR_STATE_NAME);
    // 2012-06-15 => DAY 45 - 15 days after invoice
    addDaysAndCheckForCompletion(15);
    // Should still be in clear state
    checkODState(OverdueWrapper.CLEAR_STATE_NAME);
    // 2012-07-05 => DAY 65 - 35 days after invoice
    addDaysAndCheckForCompletion(20, NextEvent.INVOICE, NextEvent.PAYMENT, NextEvent.INVOICE_PAYMENT);
    invoiceChecker.checkInvoice(account.getId(), 3, callContext, new ExpectedInvoiceItemCheck(new LocalDate(2012, 6, 30), new LocalDate(2012, 7, 31), InvoiceItemType.RECURRING, new BigDecimal("249.95")));
    invoiceChecker.checkChargedThroughDate(baseEntitlement.getId(), new LocalDate(2012, 7, 31), callContext);
    // Should still be in clear state
    checkODState(OverdueWrapper.CLEAR_STATE_NAME);
    // Now, refund the second (first non-zero dollar) invoice
    final Payment payment = paymentApi.getPayment(invoiceUserApi.getInvoicesByAccount(account.getId(), false, callContext).get(1).getPayments().get(0).getPaymentId(), false, false, PLUGIN_PROPERTIES, callContext);
    refundPaymentAndCheckForCompletion(account, payment, NextEvent.PAYMENT, NextEvent.INVOICE_PAYMENT, NextEvent.BLOCK);
    // We should now be in OD1
    checkODState("OD1");
    checkChangePlanWithOverdueState(baseEntitlement, true, true);
}
Also used : InvoicePayment(org.killbill.billing.invoice.api.InvoicePayment) Payment(org.killbill.billing.payment.api.Payment) DefaultEntitlement(org.killbill.billing.entitlement.api.DefaultEntitlement) ExpectedInvoiceItemCheck(org.killbill.billing.beatrix.util.InvoiceChecker.ExpectedInvoiceItemCheck) LocalDate(org.joda.time.LocalDate) DateTime(org.joda.time.DateTime) BigDecimal(java.math.BigDecimal) Test(org.testng.annotations.Test)

Example 39 with Payment

use of org.killbill.billing.payment.api.Payment in project killbill by killbill.

the class TestJanitor method testPendingEntriesThatDontMove.

// The test will check that when a PENDING entry stays PENDING, we go through all our retries and eventually give up (no infinite loop of retries)
@Test(groups = "slow")
public void testPendingEntriesThatDontMove() throws Exception {
    final BigDecimal requestedAmount = BigDecimal.TEN;
    final String paymentExternalKey = "haha";
    final String transactionExternalKey = "hoho!";
    testListener.pushExpectedEvent(NextEvent.PAYMENT);
    final Payment payment = paymentApi.createAuthorization(account, account.getPaymentMethodId(), null, requestedAmount, account.getCurrency(), paymentExternalKey, transactionExternalKey, ImmutableList.<PluginProperty>of(), callContext);
    testListener.assertListenerStatus();
    // Artificially move the transaction status to PENDING AND update state on the plugin as well
    final List<PaymentTransactionInfoPlugin> paymentTransactions = mockPaymentProviderPlugin.getPaymentInfo(account.getId(), payment.getId(), ImmutableList.<PluginProperty>of(), callContext);
    final PaymentTransactionInfoPlugin oTx = paymentTransactions.remove(0);
    final PaymentTransactionInfoPlugin updatePaymentTransaction = new DefaultNoOpPaymentInfoPlugin(oTx.getKbPaymentId(), oTx.getKbTransactionPaymentId(), oTx.getTransactionType(), oTx.getAmount(), oTx.getCurrency(), oTx.getCreatedDate(), oTx.getCreatedDate(), PaymentPluginStatus.PENDING, null, null);
    paymentTransactions.add(updatePaymentTransaction);
    mockPaymentProviderPlugin.updatePaymentTransactions(payment.getId(), paymentTransactions);
    final String paymentStateName = paymentSMHelper.getPendingStateForTransaction(TransactionType.AUTHORIZE).toString();
    testListener.pushExpectedEvent(NextEvent.PAYMENT);
    paymentDao.updatePaymentAndTransactionOnCompletion(account.getId(), null, payment.getId(), TransactionType.AUTHORIZE, paymentStateName, paymentStateName, payment.getTransactions().get(0).getId(), TransactionStatus.PENDING, requestedAmount, account.getCurrency(), "loup", "chat", internalCallContext);
    testListener.assertListenerStatus();
    // 15s,1m,3m,1h,1d,1d,1d,1d,1d
    for (final TimeSpan cur : paymentConfig.getIncompleteTransactionsRetries(internalCallContext)) {
        // Verify there is a notification to retry updating the value
        assertEquals(getPendingNotificationCnt(internalCallContext), 1);
        clock.addDeltaFromReality(cur.getMillis() + 1);
        assertNotificationsCompleted(internalCallContext, 5);
        // We add a sleep here to make sure the notification gets processed. Note that calling assertNotificationsCompleted alone would not work
        // because there is a point in time where the notification queue is empty (showing notification was processed), but the processing of the notification
        // will itself enter a new notification, and so the synchronization is difficult without writing *too much code*.
        Thread.sleep(1000);
        assertNotificationsCompleted(internalCallContext, 5);
        final Payment updatedPayment = paymentApi.getPayment(payment.getId(), false, false, ImmutableList.<PluginProperty>of(), callContext);
        Assert.assertEquals(updatedPayment.getTransactions().get(0).getTransactionStatus(), TransactionStatus.PENDING);
    }
    await().atMost(TIMEOUT, TimeUnit.SECONDS).until(new Callable<Boolean>() {

        @Override
        public Boolean call() throws Exception {
            return getPendingNotificationCnt(internalCallContext) == 0;
        }
    });
}
Also used : TimeSpan(org.skife.config.TimeSpan) Payment(org.killbill.billing.payment.api.Payment) DefaultNoOpPaymentInfoPlugin(org.killbill.billing.payment.provider.DefaultNoOpPaymentInfoPlugin) PaymentTransactionInfoPlugin(org.killbill.billing.payment.plugin.api.PaymentTransactionInfoPlugin) BigDecimal(java.math.BigDecimal) InvoiceApiException(org.killbill.billing.invoice.api.InvoiceApiException) PaymentApiException(org.killbill.billing.payment.api.PaymentApiException) EventBusException(org.killbill.bus.api.PersistentBus.EventBusException) Test(org.testng.annotations.Test)

Example 40 with Payment

use of org.killbill.billing.payment.api.Payment in project killbill by killbill.

the class TestJanitor method testPendingEntries.

@Test(groups = "slow")
public void testPendingEntries() throws PaymentApiException, EventBusException, NoSuchNotificationQueue {
    final BigDecimal requestedAmount = BigDecimal.TEN;
    final String paymentExternalKey = "jhj44";
    final String transactionExternalKey = "4jhjj2";
    testListener.pushExpectedEvent(NextEvent.PAYMENT);
    final Payment payment = paymentApi.createAuthorization(account, account.getPaymentMethodId(), null, requestedAmount, account.getCurrency(), paymentExternalKey, transactionExternalKey, ImmutableList.<PluginProperty>of(), callContext);
    testListener.assertListenerStatus();
    // Artificially move the transaction status to PENDING
    final String paymentStateName = paymentSMHelper.getPendingStateForTransaction(TransactionType.AUTHORIZE).toString();
    testListener.pushExpectedEvent(NextEvent.PAYMENT);
    paymentDao.updatePaymentAndTransactionOnCompletion(account.getId(), null, payment.getId(), TransactionType.AUTHORIZE, paymentStateName, paymentStateName, payment.getTransactions().get(0).getId(), TransactionStatus.PENDING, requestedAmount, account.getCurrency(), "loup", "chat", internalCallContext);
    testListener.assertListenerStatus();
    // Move clock for notification to be processed
    testListener.pushExpectedEvent(NextEvent.PAYMENT);
    clock.addDeltaFromReality(5 * 60 * 1000);
    assertNotificationsCompleted(internalCallContext, 5);
    testListener.assertListenerStatus();
    final Payment updatedPayment = paymentApi.getPayment(payment.getId(), false, false, ImmutableList.<PluginProperty>of(), callContext);
    Assert.assertEquals(updatedPayment.getTransactions().get(0).getTransactionStatus(), TransactionStatus.SUCCESS);
}
Also used : Payment(org.killbill.billing.payment.api.Payment) BigDecimal(java.math.BigDecimal) Test(org.testng.annotations.Test)

Aggregations

Payment (org.killbill.billing.payment.api.Payment)75 Test (org.testng.annotations.Test)42 Account (org.killbill.billing.account.api.Account)40 UUID (java.util.UUID)39 BigDecimal (java.math.BigDecimal)32 PluginProperty (org.killbill.billing.payment.api.PluginProperty)30 Invoice (org.killbill.billing.invoice.api.Invoice)27 LocalDate (org.joda.time.LocalDate)24 ApiOperation (io.swagger.annotations.ApiOperation)20 ApiResponses (io.swagger.annotations.ApiResponses)20 Produces (javax.ws.rs.Produces)20 Path (javax.ws.rs.Path)19 TimedResource (org.killbill.commons.metrics.TimedResource)19 DefaultEntitlement (org.killbill.billing.entitlement.api.DefaultEntitlement)17 InvoicePayment (org.killbill.billing.invoice.api.InvoicePayment)15 CallContext (org.killbill.billing.util.callcontext.CallContext)15 AccountData (org.killbill.billing.account.api.AccountData)14 GET (javax.ws.rs.GET)13 DateTime (org.joda.time.DateTime)13 PaymentApiException (org.killbill.billing.payment.api.PaymentApiException)13