killbill-memoizeit

Details

diff --git a/jaxrs/src/main/java/org/killbill/billing/jaxrs/resources/AccountResource.java b/jaxrs/src/main/java/org/killbill/billing/jaxrs/resources/AccountResource.java
index e4c0274..46ddf20 100644
--- a/jaxrs/src/main/java/org/killbill/billing/jaxrs/resources/AccountResource.java
+++ b/jaxrs/src/main/java/org/killbill/billing/jaxrs/resources/AccountResource.java
@@ -606,7 +606,7 @@ public class AccountResource extends JaxRsResourceBase {
     @Produces(APPLICATION_JSON)
     public Response getDirectPaymentsForAccount(@PathParam("accountId") final String accountIdStr,
                                                 @QueryParam(QUERY_PAYMENT_METHOD_PLUGIN_INFO) @DefaultValue("false") final Boolean withPluginInfo,
-                                             @javax.ws.rs.core.Context final HttpServletRequest request) throws PaymentApiException {
+                                                @javax.ws.rs.core.Context final HttpServletRequest request) throws PaymentApiException {
 
         final UUID accountId = UUID.fromString(accountIdStr);
         final List<DirectPayment> payments =  directPaymentApi.getAccountPayments(accountId, withPluginInfo, context.createContext(request));
@@ -620,7 +620,7 @@ public class AccountResource extends JaxRsResourceBase {
         return Response.status(Response.Status.OK).entity(result).build();
     }
 
-        @POST
+    @POST
     @Path("/{accountId:" + UUID_PATTERN + "}/" + DIRECT_PAYMENTS)
     @Consumes(APPLICATION_JSON)
     @Produces(APPLICATION_JSON)
@@ -642,28 +642,13 @@ public class AccountResource extends JaxRsResourceBase {
             case AUTHORIZE:
                 result = directPaymentApi.createAuthorization(account, json.getAmount(), json.getExternalKey(), callContext);
                 break;
-
-            case CAPTURE:
-                result = directPaymentApi.createCapture(account, UUID.fromString(json.getDirectPaymentId()), json.getAmount(), callContext);
-                break;
-
-            case CREDIT:
-                result = directPaymentApi.createCredit(account, UUID.fromString(json.getDirectPaymentId()), callContext);
-                break;
-
             case PURCHASE:
                 result = directPaymentApi.createPurchase(account, json.getAmount(), json.getExternalKey(), callContext);
                 break;
-
-            case VOID:
-                result = directPaymentApi.createVoid(account, UUID.fromString(json.getDirectPaymentId()), callContext);
-                break;
-
             default:
-                return Response.status(Status.PRECONDITION_FAILED).entity("Unknown transactionType " + transactionType).build();
+                return Response.status(Status.PRECONDITION_FAILED).entity("TransactionType " + transactionType + " is not allowed for an account").build();
         }
-            // STEPH_DP needs to return 201 with Location
-        return Response.status(Response.Status.OK).entity(new DirectPaymentJson(result, null, null)).build();
+        return uriBuilder.buildResponse(DirectPaymentResource.class, "getDirectPayment", result.getId(), uriInfo.getBaseUri().toString());
     }
 
     /*
diff --git a/jaxrs/src/main/java/org/killbill/billing/jaxrs/resources/DirectPaymentResource.java b/jaxrs/src/main/java/org/killbill/billing/jaxrs/resources/DirectPaymentResource.java
new file mode 100644
index 0000000..d463886
--- /dev/null
+++ b/jaxrs/src/main/java/org/killbill/billing/jaxrs/resources/DirectPaymentResource.java
@@ -0,0 +1,131 @@
+/*
+ * Copyright 2014 Groupon, Inc
+ *
+ * Groupon licenses this file to you under the Apache License, version 2.0
+ * (the "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at:
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.killbill.billing.jaxrs.resources;
+
+import java.util.UUID;
+
+import javax.inject.Inject;
+import javax.servlet.http.HttpServletRequest;
+import javax.ws.rs.Consumes;
+import javax.ws.rs.DELETE;
+import javax.ws.rs.DefaultValue;
+import javax.ws.rs.GET;
+import javax.ws.rs.HeaderParam;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.Produces;
+import javax.ws.rs.QueryParam;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.UriInfo;
+
+import org.killbill.billing.account.api.Account;
+import org.killbill.billing.account.api.AccountApiException;
+import org.killbill.billing.account.api.AccountUserApi;
+import org.killbill.billing.jaxrs.json.DirectPaymentJson;
+import org.killbill.billing.jaxrs.json.PaymentJson;
+import org.killbill.billing.jaxrs.util.Context;
+import org.killbill.billing.jaxrs.util.JaxrsUriBuilder;
+import org.killbill.billing.payment.api.DirectPayment;
+import org.killbill.billing.payment.api.DirectPaymentApi;
+import org.killbill.billing.payment.api.PaymentApiException;
+import org.killbill.billing.util.api.AuditUserApi;
+import org.killbill.billing.util.api.CustomFieldUserApi;
+import org.killbill.billing.util.api.TagUserApi;
+import org.killbill.billing.util.callcontext.CallContext;
+import org.killbill.billing.util.callcontext.TenantContext;
+import org.killbill.clock.Clock;
+
+import static javax.ws.rs.core.MediaType.APPLICATION_JSON;
+
+@Path(JaxrsResource.DIRECT_PAYMENTS_PATH)
+public class DirectPaymentResource extends JaxRsResourceBase {
+
+    private final DirectPaymentApi directPaymentApi;
+
+    @Inject
+    public DirectPaymentResource(final JaxrsUriBuilder uriBuilder,
+                                 final TagUserApi tagUserApi,
+                                 final CustomFieldUserApi customFieldUserApi,
+                                 final AuditUserApi auditUserApi,
+                                 final AccountUserApi accountUserApi,
+                                 final DirectPaymentApi directPaymentApi,
+                                 final Clock clock,
+                                 final Context context) {
+        super(uriBuilder, tagUserApi, customFieldUserApi, auditUserApi, accountUserApi, clock, context);
+        this.directPaymentApi = directPaymentApi;
+    }
+
+    @GET
+    @Path("/{directPaymentId:" + UUID_PATTERN + "}/")
+    @Produces(APPLICATION_JSON)
+    public Response getDirectPayment(@PathParam("directPaymentId") final String directPaymentIdStr,
+                                     @QueryParam(QUERY_PAYMENT_METHOD_PLUGIN_INFO) @DefaultValue("false") final Boolean withPluginInfo,
+                                     @javax.ws.rs.core.Context final HttpServletRequest request) throws PaymentApiException {
+
+        final UUID directPaymentIdId = UUID.fromString(directPaymentIdStr);
+        final DirectPayment payment =  directPaymentApi.getPayment(directPaymentIdId, withPluginInfo, context.createContext(request));
+        final DirectPaymentJson result = new DirectPaymentJson(payment, null, null);
+        return Response.status(Response.Status.OK).entity(result).build();
+    }
+
+    @POST
+    @Path("/{directPaymentId:" + UUID_PATTERN + "}/")
+    @Consumes(APPLICATION_JSON)
+    @Produces(APPLICATION_JSON)
+    public Response captureAuthorization(final PaymentJson json,
+                                         @PathParam("directPaymentId") final String directPaymentIdStr,
+                                         @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 {
+
+
+        // STEPH_DP error code if no such payment
+        final CallContext callContext = context.createContext(createdBy, reason, comment, request);
+        final UUID directPaymentId = UUID.fromString(directPaymentIdStr);
+        final DirectPayment initialPayment = directPaymentApi.getPayment(directPaymentId, false, callContext);
+
+        final Account account = accountUserApi.getAccountById(initialPayment.getAccountId(), callContext);
+
+        final DirectPayment payment = directPaymentApi.createCapture(account, directPaymentId, json.getAmount(), callContext);
+        return uriBuilder.buildResponse(uriInfo, DirectPaymentResource.class, "getDirectPayment", payment.getId());
+    }
+
+
+    @DELETE
+    @Path("/{directPaymentId:" + UUID_PATTERN + "}/")
+    @Consumes(APPLICATION_JSON)
+    @Produces(APPLICATION_JSON)
+    public Response voidPayment(@PathParam("directPaymentId") final String directPaymentIdStr,
+                                @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 {
+        final CallContext callContext = context.createContext(createdBy, reason, comment, request);
+        final UUID directPaymentId = UUID.fromString(directPaymentIdStr);
+        final DirectPayment initialPayment = directPaymentApi.getPayment(directPaymentId, false, callContext);
+
+        final Account account = accountUserApi.getAccountById(initialPayment.getAccountId(), callContext);
+
+        final DirectPayment payment = directPaymentApi.createVoid(account, directPaymentId,callContext);
+        return uriBuilder.buildResponse(uriInfo, DirectPaymentResource.class, "getDirectPayment", payment.getId());
+    }
+
+}
diff --git a/jaxrs/src/main/java/org/killbill/billing/jaxrs/resources/PaymentResource.java b/jaxrs/src/main/java/org/killbill/billing/jaxrs/resources/PaymentResource.java
index e9198e7..9925e0f 100644
--- a/jaxrs/src/main/java/org/killbill/billing/jaxrs/resources/PaymentResource.java
+++ b/jaxrs/src/main/java/org/killbill/billing/jaxrs/resources/PaymentResource.java
@@ -56,6 +56,7 @@ import org.killbill.billing.jaxrs.json.PaymentJson;
 import org.killbill.billing.jaxrs.json.RefundJson;
 import org.killbill.billing.jaxrs.util.Context;
 import org.killbill.billing.jaxrs.util.JaxrsUriBuilder;
+import org.killbill.billing.payment.api.DirectPaymentApi;
 import org.killbill.billing.payment.api.Payment;
 import org.killbill.billing.payment.api.PaymentApi;
 import org.killbill.billing.payment.api.PaymentApiException;
@@ -93,6 +94,7 @@ public class PaymentResource extends JaxRsResourceBase {
     public PaymentResource(final AccountUserApi accountUserApi,
                            final PaymentApi paymentApi,
                            final InvoicePaymentApi invoicePaymentApi,
+                           final DirectPaymentApi directPaymentApi,
                            final JaxrsUriBuilder uriBuilder,
                            final TagUserApi tagUserApi,
                            final CustomFieldUserApi customFieldUserApi,
@@ -170,7 +172,8 @@ public class PaymentResource extends JaxRsResourceBase {
                                                         return new PaymentJson(payment, accountsAuditLogs.get().get(payment.getAccountId()).getAuditLogsForPayment(payment.getId()));
                                                     }
                                                 },
-                                                nextPageUri);
+                                                nextPageUri
+                                               );
     }
 
     @GET
@@ -208,7 +211,8 @@ public class PaymentResource extends JaxRsResourceBase {
                                                         return new PaymentJson(payment, accountsAuditLogs.get().get(payment.getAccountId()).getAuditLogsForPayment(payment.getId()));
                                                     }
                                                 },
-                                                nextPageUri);
+                                                nextPageUri
+                                               );
     }
 
     @PUT
@@ -270,47 +274,6 @@ public class PaymentResource extends JaxRsResourceBase {
     }
 
     @POST
-    @Path("/" + AUTHORIZATION)
-    @Consumes(APPLICATION_JSON)
-    @Produces(APPLICATION_JSON)
-    public Response authorizePayment(final PaymentJson json,
-                                     @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 {
-        throw new UnsupportedOperationException();
-    }
-
-    @POST
-    @Path("/{paymentId:" + UUID_PATTERN + "}/" + CAPTURE)
-    @Consumes(APPLICATION_JSON)
-    @Produces(APPLICATION_JSON)
-    public Response captureAuthorization(final PaymentJson json,
-                                         @PathParam("paymentId") final String paymentId,
-                                         @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 {
-        throw new UnsupportedOperationException();
-    }
-
-
-    @DELETE
-    @Path("/{paymentId:" + UUID_PATTERN + "}/")
-    @Consumes(APPLICATION_JSON)
-    @Produces(APPLICATION_JSON)
-    public Response voidPayment(@PathParam("paymentId") final String paymentId,
-                                @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 {
-        throw new UnsupportedOperationException();
-    }
-
-    @POST
     @Path("/{paymentId:" + UUID_PATTERN + "}/" + REFUNDS)
     @Consumes(APPLICATION_JSON)
     @Produces(APPLICATION_JSON)
diff --git a/payment/src/main/java/org/killbill/billing/payment/api/svcs/DefaultDirectPaymentApi.java b/payment/src/main/java/org/killbill/billing/payment/api/svcs/DefaultDirectPaymentApi.java
index b8438b6..9916fe4 100644
--- a/payment/src/main/java/org/killbill/billing/payment/api/svcs/DefaultDirectPaymentApi.java
+++ b/payment/src/main/java/org/killbill/billing/payment/api/svcs/DefaultDirectPaymentApi.java
@@ -22,14 +22,18 @@ import java.util.UUID;
 
 import javax.inject.Inject;
 
+import org.killbill.billing.ObjectType;
 import org.killbill.billing.account.api.Account;
 import org.killbill.billing.payment.api.DirectPayment;
 import org.killbill.billing.payment.api.DirectPaymentApi;
 import org.killbill.billing.payment.api.PaymentApiException;
 import org.killbill.billing.payment.core.DirectPaymentProcessor;
+import org.killbill.billing.util.cache.CacheController;
+import org.killbill.billing.util.cache.CacheControllerDispatcher;
 import org.killbill.billing.util.callcontext.CallContext;
 import org.killbill.billing.util.callcontext.InternalCallContextFactory;
 import org.killbill.billing.util.callcontext.TenantContext;
+import org.killbill.billing.util.dao.NonEntityDao;
 import org.killbill.clock.Clock;
 
 public class DefaultDirectPaymentApi implements DirectPaymentApi {
diff --git a/payment/src/main/java/org/killbill/billing/payment/core/DirectPaymentProcessor.java b/payment/src/main/java/org/killbill/billing/payment/core/DirectPaymentProcessor.java
index a27eb32..995635b 100644
--- a/payment/src/main/java/org/killbill/billing/payment/core/DirectPaymentProcessor.java
+++ b/payment/src/main/java/org/killbill/billing/payment/core/DirectPaymentProcessor.java
@@ -53,6 +53,7 @@ import org.killbill.billing.payment.plugin.api.PaymentPluginApi;
 import org.killbill.billing.payment.plugin.api.PaymentPluginApiException;
 import org.killbill.billing.payment.plugin.api.PaymentPluginStatus;
 import org.killbill.billing.tag.TagInternalApi;
+import org.killbill.billing.util.callcontext.InternalCallContextFactory;
 import org.killbill.billing.util.config.PaymentConfig;
 import org.killbill.billing.util.dao.NonEntityDao;
 import org.killbill.bus.api.PersistentBus;
@@ -78,6 +79,7 @@ public class DirectPaymentProcessor extends ProcessorBase {
 
     private final PluginDispatcher<Payment> paymentPluginDispatcher;
     private final PluginDispatcher<Void> voidPluginDispatcher;
+    private final InternalCallContextFactory internalCallContextFactory;
 
     private static final Logger log = LoggerFactory.getLogger(DirectPaymentProcessor.class);
 
@@ -89,12 +91,14 @@ public class DirectPaymentProcessor extends ProcessorBase {
                                   final PaymentDao paymentDao,
                                   final NonEntityDao nonEntityDao,
                                   final PersistentBus eventBus,
+                                  final InternalCallContextFactory internalCallContextFactory,
                                   final Clock clock,
                                   final GlobalLocker locker,
                                   final PaymentConfig paymentConfig,
                                   @Named(PLUGIN_EXECUTOR_NAMED) final ExecutorService executor) {
         super(pluginRegistry, accountUserApi, eventBus, paymentDao, nonEntityDao, tagUserApi, locker, executor, invoiceApi);
         this.clock = clock;
+        this.internalCallContextFactory = internalCallContextFactory;
         this.paymentConfig = paymentConfig;
         final long paymentPluginTimeoutSec = TimeUnit.SECONDS.convert(paymentConfig.getPaymentPluginTimeout().getPeriod(), paymentConfig.getPaymentPluginTimeout().getUnit());
         this.paymentPluginDispatcher = new PluginDispatcher<Payment>(paymentPluginTimeoutSec, executor);
@@ -189,43 +193,54 @@ public class DirectPaymentProcessor extends ProcessorBase {
 
         final Iterable<DirectPayment> payments = Iterables.transform(paymentsModelDao, new Function<DirectPaymentModelDao, DirectPayment>() {
 
-            final Ordering<DirectPaymentTransaction> perPaymentTransactionOrdering = Ordering.<DirectPaymentTransaction>from(new Comparator<DirectPaymentTransaction>() {
-                @Override
-                public int compare(final DirectPaymentTransaction o1, final DirectPaymentTransaction o2) {
-                    return o1.getEffectiveDate().compareTo(o2.getEffectiveDate());
-                }
-            });
-
             @Override
             public DirectPayment apply(final DirectPaymentModelDao curDirectPaymentModelDao) {
-
-                final Iterable<DirectPaymentTransactionModelDao> filteredTransactions = Iterables.filter(transactionsModelDao, new Predicate<DirectPaymentTransactionModelDao>() {
-                    @Override
-                    public boolean apply(final DirectPaymentTransactionModelDao curDirectPaymentTransactionModelDao) {
-                        return curDirectPaymentTransactionModelDao.getDirectPaymentId().equals(curDirectPaymentModelDao.getId());
-                    }
-                });
-
-                final Iterable<DirectPaymentTransaction> transactions = Iterables.transform(filteredTransactions, new Function<DirectPaymentTransactionModelDao, DirectPaymentTransaction>() {
-                    @Override
-                    public DirectPaymentTransaction apply(final DirectPaymentTransactionModelDao input) {
-                        return new DefaultDirectPaymentTransaction(input.getId(), input.getCreatedDate(), input.getUpdatedDate(), input.getDirectPaymentId(),
-                                                                   input.getTransactionType(), input.getEffectiveDate(), 0, input.getPaymentStatus(), input.getAmount(), input.getCurrency(),
-                                                                   // STEPH_DP fill in details plugin info if required
-                                                                   input.getGatewayErrorCode(), input.getGatewayErrorMsg(), null);
-                    }
-                });
-
-                final List<DirectPaymentTransaction> sortedTransactions = perPaymentTransactionOrdering.immutableSortedCopy(transactions);
-                return new DefaultDirectPayment(curDirectPaymentModelDao.getId(), curDirectPaymentModelDao.getCreatedDate(), curDirectPaymentModelDao.getUpdatedDate(), curDirectPaymentModelDao.getAccountId(),
-                                                curDirectPaymentModelDao.getPaymentMethodId(), curDirectPaymentModelDao.getPaymentNumber(), curDirectPaymentModelDao.getExternalKey(), sortedTransactions);
+                return toDirectPayment(curDirectPaymentModelDao, transactionsModelDao);
             }
+
         });
         return ImmutableList.copyOf(payments);
     }
 
     public DirectPayment getPayment(final UUID directPaymentId, final boolean withPluginInfo, final InternalTenantContext tenantContext) throws PaymentApiException {
-        return null;
+        final DirectPaymentModelDao paymentModelDao = paymentDao.getDirectPayment(directPaymentId, tenantContext);
+
+        final InternalTenantContext tenantContextWithAccountRecordId =  internalCallContextFactory.createInternalTenantContext(paymentModelDao.getAccountId(), tenantContext);
+        final List<DirectPaymentTransactionModelDao> transactionsForAccount =  paymentDao.getDirectTransactionsForAccount(paymentModelDao.getAccountId(), tenantContextWithAccountRecordId);
+
+        return toDirectPayment(paymentModelDao, transactionsForAccount);
+    }
+
+    private DirectPayment toDirectPayment(final DirectPaymentModelDao curDirectPaymentModelDao, final List<DirectPaymentTransactionModelDao> transactionsModelDao) {
+
+        final Ordering<DirectPaymentTransaction> perPaymentTransactionOrdering = Ordering.<DirectPaymentTransaction>from(new Comparator<DirectPaymentTransaction>() {
+            @Override
+            public int compare(final DirectPaymentTransaction o1, final DirectPaymentTransaction o2) {
+                return o1.getEffectiveDate().compareTo(o2.getEffectiveDate());
+            }
+        });
+
+        final Iterable<DirectPaymentTransactionModelDao> filteredTransactions = Iterables.filter(transactionsModelDao, new Predicate<DirectPaymentTransactionModelDao>() {
+            @Override
+            public boolean apply(final DirectPaymentTransactionModelDao curDirectPaymentTransactionModelDao) {
+                return curDirectPaymentTransactionModelDao.getDirectPaymentId().equals(curDirectPaymentModelDao.getId());
+            }
+        });
+
+        final Iterable<DirectPaymentTransaction> transactions = Iterables.transform(filteredTransactions, new Function<DirectPaymentTransactionModelDao, DirectPaymentTransaction>() {
+            @Override
+            public DirectPaymentTransaction apply(final DirectPaymentTransactionModelDao input) {
+                return new DefaultDirectPaymentTransaction(input.getId(), input.getCreatedDate(), input.getUpdatedDate(), input.getDirectPaymentId(),
+                                                           input.getTransactionType(), input.getEffectiveDate(), 0, input.getPaymentStatus(), input.getAmount(), input.getCurrency(),
+                                                           // STEPH_DP fill in details plugin info if required
+                                                           input.getGatewayErrorCode(), input.getGatewayErrorMsg(), null);
+            }
+        });
+
+        final List<DirectPaymentTransaction> sortedTransactions = perPaymentTransactionOrdering.immutableSortedCopy(transactions);
+        return new DefaultDirectPayment(curDirectPaymentModelDao.getId(), curDirectPaymentModelDao.getCreatedDate(), curDirectPaymentModelDao.getUpdatedDate(), curDirectPaymentModelDao.getAccountId(),
+                                        curDirectPaymentModelDao.getPaymentMethodId(), curDirectPaymentModelDao.getPaymentNumber(), curDirectPaymentModelDao.getExternalKey(), sortedTransactions);
     }
 
+
 }

pom.xml 2(+1 -1)

diff --git a/pom.xml b/pom.xml
index 403a4f3..a77684c 100644
--- a/pom.xml
+++ b/pom.xml
@@ -19,7 +19,7 @@
     <parent>
         <artifactId>killbill-oss-parent</artifactId>
         <groupId>org.kill-bill.billing</groupId>
-        <version>0.6.34</version>
+        <version>0.6.35-SNAPSHOT</version>
     </parent>
     <artifactId>killbill</artifactId>
     <version>0.11.2-SNAPSHOT</version>
diff --git a/server/src/test/java/org/killbill/billing/jaxrs/TestDirectPayment.java b/server/src/test/java/org/killbill/billing/jaxrs/TestDirectPayment.java
new file mode 100644
index 0000000..dab5185
--- /dev/null
+++ b/server/src/test/java/org/killbill/billing/jaxrs/TestDirectPayment.java
@@ -0,0 +1,61 @@
+/*
+ * Copyright 2014 Groupon, Inc
+ *
+ * Groupon licenses this file to you under the Apache License, version 2.0
+ * (the "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at:
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.killbill.billing.jaxrs;
+
+import java.math.BigDecimal;
+
+import org.killbill.billing.client.model.Account;
+import org.killbill.billing.client.model.DirectPayment;
+import org.killbill.billing.client.model.DirectTransaction;
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+import static org.testng.Assert.assertEquals;
+
+public class TestDirectPayment extends TestJaxrsBase {
+
+    @Test(groups = "slow")
+    public void testRetrievePayment() throws Exception {
+
+        final Account account = createAccountWithDefaultPaymentMethod();
+
+        final DirectTransaction transaction = new DirectTransaction();
+        transaction.setAmount(BigDecimal.TEN);
+        transaction.setCurrency(account.getCurrency());
+        transaction.setExternalKey("foo");
+        transaction.setTransactionType("AUTHORIZE");
+
+        final DirectPayment retrievedPaymentJson = killBillClient.createDirectPayment(account.getAccountId(), transaction, createdBy, reason, comment);
+
+        assertEquals(retrievedPaymentJson.getAccountId(), account.getAccountId());
+        Assert.assertNotNull(retrievedPaymentJson.getDirectPaymentId());
+        Assert.assertNotNull(retrievedPaymentJson.getPaymentNumber());
+        assertEquals(retrievedPaymentJson.getAuthAmount().compareTo(BigDecimal.TEN), 0);
+        assertEquals(retrievedPaymentJson.getCapturedAmount().compareTo(BigDecimal.ZERO), 0);
+        assertEquals(retrievedPaymentJson.getRefundedAmount().compareTo(BigDecimal.ZERO), 0);
+        assertEquals(retrievedPaymentJson.getCurrency(), account.getCurrency());
+        assertEquals(retrievedPaymentJson.getPaymentMethodId(), account.getPaymentMethodId());
+        assertEquals(retrievedPaymentJson.getTransactions().size(), 1);
+
+        assertEquals(retrievedPaymentJson.getTransactions().get(0).getDirectPaymentId(), retrievedPaymentJson.getDirectPaymentId());
+        Assert.assertNotNull(retrievedPaymentJson.getTransactions().get(0).getDirectTransactionId());
+        assertEquals(retrievedPaymentJson.getTransactions().get(0).getTransactionType(), "AUTHORIZE");
+        assertEquals(retrievedPaymentJson.getTransactions().get(0).getStatus(), "SUCCESS");
+        assertEquals(retrievedPaymentJson.getTransactions().get(0).getAmount().compareTo(BigDecimal.TEN), 0);
+        assertEquals(retrievedPaymentJson.getTransactions().get(0).getExternalKey(), "foo");
+    }
+}