Search in sources :

Example 26 with Payment

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

the class TestInvoicePayment method testPartialRefundsOnPartialPayments.

@Test(groups = "slow")
public void testPartialRefundsOnPartialPayments() throws Exception {
    final AccountData accountData = getAccountData(1);
    final Account account = createAccountWithNonOsgiPaymentMethod(accountData);
    accountChecker.checkAccount(account.getId(), accountData, callContext);
    add_AUTO_PAY_OFF_Tag(account.getId(), ObjectType.ACCOUNT);
    clock.setDay(new LocalDate(2012, 4, 1));
    busHandler.pushExpectedEvents(NextEvent.INVOICE);
    final InvoiceItem externalCharge = new ExternalChargeInvoiceItem(null, account.getId(), null, "Initial external charge", clock.getUTCToday(), BigDecimal.TEN, Currency.USD);
    final InvoiceItem item1 = invoiceUserApi.insertExternalCharges(account.getId(), clock.getUTCToday(), ImmutableList.<InvoiceItem>of(externalCharge), true, callContext).get(0);
    assertListenerStatus();
    // Trigger first partial payment ($4) on first invoice
    final Invoice invoice = invoiceUserApi.getInvoice(item1.getInvoiceId(), callContext);
    Payment payment1 = createPaymentAndCheckForCompletion(account, invoice, new BigDecimal("4.00"), account.getCurrency(), NextEvent.PAYMENT, NextEvent.INVOICE_PAYMENT);
    Invoice invoice1 = invoiceUserApi.getInvoice(item1.getInvoiceId(), callContext);
    assertTrue(invoice1.getBalance().compareTo(new BigDecimal("6.00")) == 0);
    assertTrue(invoice1.getPaidAmount().compareTo(new BigDecimal("4.00")) == 0);
    assertTrue(invoice1.getChargedAmount().compareTo(BigDecimal.TEN) == 0);
    BigDecimal accountBalance = invoiceUserApi.getAccountBalance(account.getId(), callContext);
    assertTrue(accountBalance.compareTo(new BigDecimal("6.00")) == 0);
    // Trigger second partial payment ($6) on first invoice
    Payment payment2 = createPaymentAndCheckForCompletion(account, invoice, new BigDecimal("6.00"), account.getCurrency(), NextEvent.PAYMENT, NextEvent.INVOICE_PAYMENT);
    invoice1 = invoiceUserApi.getInvoice(item1.getInvoiceId(), callContext);
    assertTrue(invoice1.getBalance().compareTo(BigDecimal.ZERO) == 0);
    assertTrue(invoice1.getPaidAmount().compareTo(BigDecimal.TEN) == 0);
    assertTrue(invoice1.getChargedAmount().compareTo(BigDecimal.TEN) == 0);
    accountBalance = invoiceUserApi.getAccountBalance(account.getId(), callContext);
    assertTrue(accountBalance.compareTo(BigDecimal.ZERO) == 0);
    // Refund first payment with item adjustment
    final Map<UUID, BigDecimal> iias = new HashMap<UUID, BigDecimal>();
    iias.put(item1.getId(), new BigDecimal("4.00"));
    payment1 = refundPaymentWithInvoiceItemAdjAndCheckForCompletion(account, payment1, new BigDecimal("4.00"), Currency.USD, iias, NextEvent.PAYMENT, NextEvent.INVOICE_PAYMENT, NextEvent.INVOICE_ADJUSTMENT);
    invoice1 = invoiceUserApi.getInvoice(item1.getInvoiceId(), callContext);
    assertTrue(invoice1.getBalance().compareTo(BigDecimal.ZERO) == 0);
    accountBalance = invoiceUserApi.getAccountBalance(account.getId(), callContext);
    assertTrue(accountBalance.compareTo(BigDecimal.ZERO) == 0);
    // Refund second payment with item adjustment
    iias.put(item1.getId(), new BigDecimal("6.00"));
    payment2 = refundPaymentWithInvoiceItemAdjAndCheckForCompletion(account, payment2, new BigDecimal("6.00"), Currency.USD, iias, NextEvent.PAYMENT, NextEvent.INVOICE_PAYMENT, NextEvent.INVOICE_ADJUSTMENT);
    invoice1 = invoiceUserApi.getInvoice(item1.getInvoiceId(), callContext);
    assertTrue(invoice1.getBalance().compareTo(BigDecimal.ZERO) == 0);
    accountBalance = invoiceUserApi.getAccountBalance(account.getId(), callContext);
    assertTrue(accountBalance.compareTo(BigDecimal.ZERO) == 0);
    Assert.assertEquals(invoice1.getPayments().size(), 4);
    // Verify links for payment 1
    Assert.assertEquals(invoice1.getPayments().get(0).getAmount().compareTo(new BigDecimal("4.00")), 0);
    Assert.assertNull(invoice1.getPayments().get(0).getLinkedInvoicePaymentId());
    Assert.assertEquals(invoice1.getPayments().get(0).getPaymentCookieId(), payment1.getTransactions().get(0).getExternalKey());
    Assert.assertEquals(invoice1.getPayments().get(0).getPaymentId(), payment1.getId());
    Assert.assertEquals(invoice1.getPayments().get(0).getType(), InvoicePaymentType.ATTEMPT);
    Assert.assertTrue(invoice1.getPayments().get(0).isSuccess());
    // Verify links for payment 2
    Assert.assertEquals(invoice1.getPayments().get(1).getAmount().compareTo(new BigDecimal("6.00")), 0);
    Assert.assertNull(invoice1.getPayments().get(1).getLinkedInvoicePaymentId());
    Assert.assertEquals(invoice1.getPayments().get(1).getPaymentCookieId(), payment2.getTransactions().get(0).getExternalKey());
    Assert.assertEquals(invoice1.getPayments().get(1).getPaymentId(), payment2.getId());
    Assert.assertEquals(invoice1.getPayments().get(1).getType(), InvoicePaymentType.ATTEMPT);
    Assert.assertTrue(invoice1.getPayments().get(1).isSuccess());
    // Verify links for refund 1
    Assert.assertEquals(invoice1.getPayments().get(2).getAmount().compareTo(new BigDecimal("-4.00")), 0);
    Assert.assertEquals(invoice1.getPayments().get(2).getLinkedInvoicePaymentId(), invoice1.getPayments().get(0).getId());
    Assert.assertEquals(invoice1.getPayments().get(2).getPaymentCookieId(), payment1.getTransactions().get(1).getExternalKey());
    Assert.assertEquals(invoice1.getPayments().get(2).getPaymentId(), payment1.getId());
    Assert.assertEquals(invoice1.getPayments().get(2).getType(), InvoicePaymentType.REFUND);
    Assert.assertTrue(invoice1.getPayments().get(2).isSuccess());
    // Verify links for refund 2
    Assert.assertEquals(invoice1.getPayments().get(3).getAmount().compareTo(new BigDecimal("-6.00")), 0);
    Assert.assertEquals(invoice1.getPayments().get(3).getLinkedInvoicePaymentId(), invoice1.getPayments().get(1).getId());
    Assert.assertEquals(invoice1.getPayments().get(3).getPaymentCookieId(), payment2.getTransactions().get(1).getExternalKey());
    Assert.assertEquals(invoice1.getPayments().get(3).getPaymentId(), payment2.getId());
    Assert.assertEquals(invoice1.getPayments().get(3).getType(), InvoicePaymentType.REFUND);
    Assert.assertTrue(invoice1.getPayments().get(3).isSuccess());
}
Also used : Account(org.killbill.billing.account.api.Account) Payment(org.killbill.billing.payment.api.Payment) InvoiceItem(org.killbill.billing.invoice.api.InvoiceItem) ExternalChargeInvoiceItem(org.killbill.billing.invoice.model.ExternalChargeInvoiceItem) Invoice(org.killbill.billing.invoice.api.Invoice) AccountData(org.killbill.billing.account.api.AccountData) HashMap(java.util.HashMap) ExternalChargeInvoiceItem(org.killbill.billing.invoice.model.ExternalChargeInvoiceItem) UUID(java.util.UUID) LocalDate(org.joda.time.LocalDate) BigDecimal(java.math.BigDecimal) Test(org.testng.annotations.Test)

Example 27 with Payment

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

the class TestIntegrationWithWrittenOffTag method testWithWrittenOffInvoice.

@Test(groups = "slow")
public void testWithWrittenOffInvoice() throws Exception {
    clock.setTime(new DateTime(2012, 5, 1, 0, 3, 42, 0));
    // Put the account in AUTO_PAY_OFF to make sure payment system does not try to pay initial invoices
    add_AUTO_PAY_OFF_Tag(account.getId(), ObjectType.ACCOUNT);
    // set next invoice to fail and create network
    final DefaultEntitlement bpEntitlement = createBaseEntitlementAndCheckForCompletion(account.getId(), "externalKey", productName, ProductCategory.BASE, term, NextEvent.CREATE, NextEvent.BLOCK, NextEvent.INVOICE);
    assertNotNull(bpEntitlement);
    List<Invoice> invoices = invoiceApi.getInvoicesByAccount(account.getId(), false, callContext);
    assertEquals(invoices.size(), 1);
    busHandler.pushExpectedEvents(NextEvent.PHASE, NextEvent.INVOICE);
    clock.addDays(31);
    assertListenerStatus();
    invoices = invoiceApi.getInvoicesByAccount(account.getId(), false, callContext);
    assertEquals(invoices.size(), 2);
    // Tag non $0 invoice with WRITTEN_OFF and remove AUTO_PAY_OFF => System should still not pay anything
    add_WRITTEN_OFF_Tag(invoices.get(1).getId(), ObjectType.INVOICE);
    remove_AUTO_PAY_OFF_Tag(account.getId(), ObjectType.ACCOUNT);
    assertListenerStatus();
    List<Payment> accountPayments = paymentApi.getAccountPayments(account.getId(), false, false, ImmutableList.<PluginProperty>of(), callContext);
    assertEquals(accountPayments.size(), 0);
}
Also used : Payment(org.killbill.billing.payment.api.Payment) Invoice(org.killbill.billing.invoice.api.Invoice) DefaultEntitlement(org.killbill.billing.entitlement.api.DefaultEntitlement) DateTime(org.joda.time.DateTime) Test(org.testng.annotations.Test)

Example 28 with Payment

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

the class AccountResource method getInvoicePayments.

/*
     * ************************** PAYMENTS ********************************
     */
// STEPH should refactor code since very similar to @Path("/{accountId:" + UUID_PATTERN + "}/" + PAYMENTS)
@TimedResource
@GET
@Path("/{accountId:" + UUID_PATTERN + "}/" + INVOICE_PAYMENTS)
@Produces(APPLICATION_JSON)
@ApiOperation(value = "Retrieve account invoice payments", response = InvoicePaymentJson.class, responseContainer = "List")
@ApiResponses(value = { @ApiResponse(code = 400, message = "Invalid account id supplied"), @ApiResponse(code = 404, message = "Account not found") })
public Response getInvoicePayments(@PathParam("accountId") final String accountIdStr, @QueryParam(QUERY_AUDIT) @DefaultValue("NONE") final AuditMode auditMode, @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, @javax.ws.rs.core.Context final HttpServletRequest request) throws PaymentApiException, AccountApiException {
    final Iterable<PluginProperty> pluginProperties = extractPluginProperties(pluginPropertiesString);
    final UUID accountId = UUID.fromString(accountIdStr);
    final TenantContext tenantContext = context.createContext(request);
    final Account account = accountUserApi.getAccountById(accountId, tenantContext);
    final List<Payment> payments = paymentApi.getAccountPayments(account.getId(), withPluginInfo, withAttempts, pluginProperties, tenantContext);
    final List<InvoicePayment> invoicePayments = invoicePaymentApi.getInvoicePaymentsByAccount(accountId, tenantContext);
    final AccountAuditLogs accountAuditLogs = auditUserApi.getAccountAuditLogs(accountId, auditMode.getLevel(), tenantContext);
    final List<InvoicePaymentJson> result = new ArrayList<InvoicePaymentJson>(payments.size());
    for (final Payment payment : payments) {
        final UUID invoiceId = getInvoiceId(invoicePayments, payment);
        result.add(new InvoicePaymentJson(payment, invoiceId, accountAuditLogs));
    }
    return Response.status(Status.OK).entity(result).build();
}
Also used : Account(org.killbill.billing.account.api.Account) InvoicePayment(org.killbill.billing.invoice.api.InvoicePayment) InvoicePaymentJson(org.killbill.billing.jaxrs.json.InvoicePaymentJson) ArrayList(java.util.ArrayList) TenantContext(org.killbill.billing.util.callcontext.TenantContext) PluginProperty(org.killbill.billing.payment.api.PluginProperty) InvoicePayment(org.killbill.billing.invoice.api.InvoicePayment) Payment(org.killbill.billing.payment.api.Payment) 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 29 with Payment

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

the class TestPaymentProcessor method testClassicFlow.

@Test(groups = "slow")
public void testClassicFlow() throws Exception {
    final String paymentExternalKey = UUID.randomUUID().toString();
    final Iterable<PluginProperty> pluginPropertiesToDriveTransationToPending = ImmutableList.<PluginProperty>of(new PluginProperty(MockPaymentProviderPlugin.PLUGIN_PROPERTY_PAYMENT_PLUGIN_STATUS_OVERRIDE, PaymentPluginStatus.PENDING, false));
    // AUTH pre-3DS
    final String authorizationKey = UUID.randomUUID().toString();
    final Payment authorization = paymentProcessor.createAuthorization(true, null, account, null, null, TEN, CURRENCY, paymentExternalKey, authorizationKey, null, null, SHOULD_LOCK_ACCOUNT, pluginPropertiesToDriveTransationToPending, callContext, internalCallContext);
    verifyPayment(authorization, paymentExternalKey, ZERO, ZERO, ZERO, 1);
    final UUID paymentId = authorization.getId();
    verifyPaymentTransaction(authorization.getTransactions().get(0), authorizationKey, TransactionType.AUTHORIZE, TEN, paymentId);
    paymentBusListener.verify(1, account.getId(), paymentId, TEN, TransactionStatus.PENDING);
    // AUTH post-3DS
    final Payment authorizationPost3DS = paymentProcessor.createAuthorization(true, null, account, null, paymentId, TEN, CURRENCY, paymentExternalKey, authorizationKey, null, null, SHOULD_LOCK_ACCOUNT, PLUGIN_PROPERTIES, callContext, internalCallContext);
    verifyPayment(authorizationPost3DS, paymentExternalKey, TEN, ZERO, ZERO, 1);
    verifyPaymentTransaction(authorizationPost3DS.getTransactions().get(0), authorizationKey, TransactionType.AUTHORIZE, TEN, paymentId);
    paymentBusListener.verify(2, account.getId(), paymentId, TEN, TransactionStatus.SUCCESS);
    // CAPTURE
    final String capture1Key = UUID.randomUUID().toString();
    final Payment partialCapture1 = paymentProcessor.createCapture(true, null, account, paymentId, FIVE, CURRENCY, capture1Key, null, SHOULD_LOCK_ACCOUNT, PLUGIN_PROPERTIES, callContext, internalCallContext);
    verifyPayment(partialCapture1, paymentExternalKey, TEN, FIVE, ZERO, 2);
    verifyPaymentTransaction(partialCapture1.getTransactions().get(1), capture1Key, TransactionType.CAPTURE, FIVE, paymentId);
    paymentBusListener.verify(3, account.getId(), paymentId, FIVE, TransactionStatus.SUCCESS);
    // CAPTURE
    final String capture2Key = UUID.randomUUID().toString();
    final Payment partialCapture2 = paymentProcessor.createCapture(true, null, account, paymentId, FIVE, CURRENCY, capture2Key, null, SHOULD_LOCK_ACCOUNT, PLUGIN_PROPERTIES, callContext, internalCallContext);
    verifyPayment(partialCapture2, paymentExternalKey, TEN, TEN, ZERO, 3);
    verifyPaymentTransaction(partialCapture2.getTransactions().get(2), capture2Key, TransactionType.CAPTURE, FIVE, paymentId);
    paymentBusListener.verify(4, account.getId(), paymentId, FIVE, TransactionStatus.SUCCESS);
    // REFUND
    final String refund1Key = UUID.randomUUID().toString();
    final Payment partialRefund1 = paymentProcessor.createRefund(true, null, account, paymentId, FIVE, CURRENCY, refund1Key, null, SHOULD_LOCK_ACCOUNT, PLUGIN_PROPERTIES, callContext, internalCallContext);
    verifyPayment(partialRefund1, paymentExternalKey, TEN, TEN, FIVE, 4);
    verifyPaymentTransaction(partialRefund1.getTransactions().get(3), refund1Key, TransactionType.REFUND, FIVE, paymentId);
    paymentBusListener.verify(5, account.getId(), paymentId, FIVE, TransactionStatus.SUCCESS);
    // REFUND
    final String refund2Key = UUID.randomUUID().toString();
    final Payment partialRefund2 = paymentProcessor.createRefund(true, null, account, paymentId, FIVE, CURRENCY, refund2Key, null, SHOULD_LOCK_ACCOUNT, PLUGIN_PROPERTIES, callContext, internalCallContext);
    verifyPayment(partialRefund2, paymentExternalKey, TEN, TEN, TEN, 5);
    verifyPaymentTransaction(partialRefund2.getTransactions().get(4), refund2Key, TransactionType.REFUND, FIVE, paymentId);
    paymentBusListener.verify(6, account.getId(), paymentId, FIVE, TransactionStatus.SUCCESS);
}
Also used : PluginProperty(org.killbill.billing.payment.api.PluginProperty) Payment(org.killbill.billing.payment.api.Payment) UUID(java.util.UUID) Test(org.testng.annotations.Test)

Example 30 with Payment

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

the class TestPaymentProcessor method testInvalidTransition.

@Test(groups = "slow")
public void testInvalidTransition() throws Exception {
    final String paymentExternalKey = UUID.randomUUID().toString();
    final Iterable<PluginProperty> pluginPropertiesToDriveTransationToPending = ImmutableList.<PluginProperty>of(new PluginProperty(MockPaymentProviderPlugin.PLUGIN_PROPERTY_PAYMENT_PLUGIN_STATUS_OVERRIDE, PaymentPluginStatus.ERROR, false));
    // AUTH
    final String authorizationKey = UUID.randomUUID().toString();
    final Payment authorization = paymentProcessor.createAuthorization(true, null, account, null, null, TEN, CURRENCY, paymentExternalKey, authorizationKey, null, null, SHOULD_LOCK_ACCOUNT, pluginPropertiesToDriveTransationToPending, callContext, internalCallContext);
    verifyPayment(authorization, paymentExternalKey, ZERO, ZERO, ZERO, 1);
    final UUID paymentId = authorization.getId();
    verifyPaymentTransaction(authorization.getTransactions().get(0), authorizationKey, TransactionType.AUTHORIZE, TEN, paymentId);
    paymentBusListener.verify(0, 1, 0, account.getId(), paymentId, ZERO, TransactionStatus.PAYMENT_FAILURE);
    // REFUND
    final String refundKey = UUID.randomUUID().toString();
    try {
        paymentProcessor.createRefund(true, null, account, paymentId, TEN, CURRENCY, refundKey, null, SHOULD_LOCK_ACCOUNT, PLUGIN_PROPERTIES, callContext, internalCallContext);
        Assert.fail();
    } catch (final PaymentApiException e) {
        Assert.assertEquals(e.getCode(), ErrorCode.PAYMENT_INVALID_OPERATION.getCode());
    }
    final Payment refreshedPayment = paymentProcessor.getPayment(authorization.getId(), false, false, PLUGIN_PROPERTIES, callContext, internalCallContext);
    // Make sure no state has been created (no UNKNOWN transaction for the refund)
    verifyPayment(refreshedPayment, paymentExternalKey, ZERO, ZERO, ZERO, 1);
    paymentBusListener.verify(0, 1, 0, account.getId(), paymentId, ZERO, TransactionStatus.PAYMENT_FAILURE);
}
Also used : PluginProperty(org.killbill.billing.payment.api.PluginProperty) Payment(org.killbill.billing.payment.api.Payment) PaymentApiException(org.killbill.billing.payment.api.PaymentApiException) UUID(java.util.UUID) 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