killbill-memoizeit

Intermediary steps towards fixing the jaxrs API to fit the new

6/28/2014 11:48:42 PM

Changes

jaxrs/src/main/java/org/killbill/billing/jaxrs/json/PaymentJson.java 353(+0 -353)

profiles/killbill/src/test/java/org/killbill/billing/jaxrs/TestDirectPayment.java 151(+0 -151)

Details

diff --git a/jaxrs/src/main/java/org/killbill/billing/jaxrs/json/AccountTimelineJson.java b/jaxrs/src/main/java/org/killbill/billing/jaxrs/json/AccountTimelineJson.java
index c6adaab..ad869dc 100644
--- a/jaxrs/src/main/java/org/killbill/billing/jaxrs/json/AccountTimelineJson.java
+++ b/jaxrs/src/main/java/org/killbill/billing/jaxrs/json/AccountTimelineJson.java
@@ -22,7 +22,6 @@ import java.util.ArrayList;
 import java.util.HashSet;
 import java.util.LinkedList;
 import java.util.List;
-import java.util.Map;
 import java.util.Set;
 import java.util.UUID;
 
@@ -32,38 +31,38 @@ import org.killbill.billing.invoice.api.Invoice;
 import org.killbill.billing.invoice.api.InvoiceItem;
 import org.killbill.billing.invoice.api.InvoiceItemType;
 import org.killbill.billing.invoice.api.InvoicePayment;
+import org.killbill.billing.jaxrs.resources.JaxRsResourceBase;
 import org.killbill.billing.payment.api.DirectPayment;
-import org.killbill.billing.payment.api.DirectPaymentTransaction;
 import org.killbill.billing.util.audit.AccountAuditLogs;
 import org.killbill.billing.util.audit.AuditLog;
 
 import com.fasterxml.jackson.annotation.JsonCreator;
 import com.fasterxml.jackson.annotation.JsonProperty;
-import com.google.common.collect.Multimap;
 
 public class AccountTimelineJson {
 
     private final AccountJson account;
     private final List<BundleJson> bundles;
     private final List<InvoiceJson> invoices;
-    private final List<PaymentJson> payments;
+    private final List<InvoicePaymentJson> payments;
 
     @JsonCreator
     public AccountTimelineJson(@JsonProperty("account") final AccountJson account,
                                @JsonProperty("bundles") final List<BundleJson> bundles,
                                @JsonProperty("invoices") final List<InvoiceJson> invoices,
-                               @JsonProperty("payments") final List<PaymentJson> payments) {
+                               @JsonProperty("payments") final List<InvoicePaymentJson> payments) {
         this.account = account;
         this.bundles = bundles;
         this.invoices = invoices;
         this.payments = payments;
     }
 
-
-    public AccountTimelineJson(final Account account, final List<Invoice> invoices, final List<DirectPayment> payments,
-                               final Map<UUID, UUID> invoiceIdByPayment, final List<SubscriptionBundle> bundles,
-                                final Multimap<UUID, DirectPaymentTransaction> refundsByPayment,
-                               final Multimap<UUID, DirectPaymentTransaction> chargebacksByPayment, final AccountAuditLogs accountAuditLogs) {
+    public AccountTimelineJson(final Account account,
+                               final List<Invoice> invoices,
+                               final List<DirectPayment> payments,
+                               final List<InvoicePayment> invoicePayments,
+                               final List<SubscriptionBundle> bundles,
+                               final AccountAuditLogs accountAuditLogs) {
         this.account = new AccountJson(account, null, null, accountAuditLogs);
         this.bundles = new LinkedList<BundleJson>();
         for (final SubscriptionBundle bundle : bundles) {
@@ -91,28 +90,10 @@ public class AccountTimelineJson {
                                               auditLogs));
         }
 
-        this.payments = new LinkedList<PaymentJson>();
+        this.payments = new LinkedList<InvoicePaymentJson>();
         for (final DirectPayment payment : payments) {
-            final List<RefundJson> refunds = new ArrayList<RefundJson>();
-            for (final DirectPaymentTransaction refund : refundsByPayment.get(payment.getId())) {
-                // STEPH add adjusted invoice items? and also audit_logs
-                final List<AuditLog> auditLogs = accountAuditLogs.getAuditLogsForPaymentTransaction(refund.getId());
-                refunds.add(new RefundJson(refund, null, auditLogs));
-            }
-
-            final List<ChargebackJson> chargebacks = new ArrayList<ChargebackJson>();
-            for (final DirectPaymentTransaction chargeback : chargebacksByPayment.get(payment.getId())) {
-                final List<AuditLog> auditLogs = accountAuditLogs.getAuditLogsForPaymentTransaction(chargeback.getId());
-                chargebacks.add(new ChargebackJson(payment.getAccountId(), chargeback, auditLogs));
-            }
-
-            final List<AuditLog> auditLogs = accountAuditLogs.getAuditLogsForPayment(payment.getId());
-            final UUID invoiceId = invoiceIdByPayment.get(payment.getId());
-            this.payments.add(new PaymentJson(payment,
-                                              getBundleExternalKey(invoiceId, invoices, bundles),
-                                              refunds,
-                                              chargebacks,
-                                              auditLogs));
+            final UUID invoiceId = JaxRsResourceBase.getInvoiceId(invoicePayments, payment);
+            this.payments.add(new InvoicePaymentJson(payment, invoiceId, accountAuditLogs));
         }
     }
 
@@ -128,7 +109,7 @@ public class AccountTimelineJson {
         return invoices;
     }
 
-    public List<PaymentJson> getPayments() {
+    public List<InvoicePaymentJson> getPayments() {
         return payments;
     }
 
diff --git a/jaxrs/src/main/java/org/killbill/billing/jaxrs/json/BundleTimelineJson.java b/jaxrs/src/main/java/org/killbill/billing/jaxrs/json/BundleTimelineJson.java
index ff0d8af..942daee 100644
--- a/jaxrs/src/main/java/org/killbill/billing/jaxrs/json/BundleTimelineJson.java
+++ b/jaxrs/src/main/java/org/killbill/billing/jaxrs/json/BundleTimelineJson.java
@@ -27,7 +27,7 @@ public class BundleTimelineJson {
 
     private final BundleJson bundle;
 
-    private final List<PaymentJson> payments;
+    private final List<InvoicePaymentJson> payments;
 
     private final List<InvoiceJson> invoices;
 
@@ -37,7 +37,7 @@ public class BundleTimelineJson {
     @JsonCreator
     public BundleTimelineJson(@JsonProperty("viewId") final String viewId,
                               @JsonProperty("bundle") final BundleJson bundle,
-                              @JsonProperty("payments") final List<PaymentJson> payments,
+                              @JsonProperty("payments") final List<InvoicePaymentJson> payments,
                               @JsonProperty("invoices") final List<InvoiceJson> invoices,
                               @JsonProperty("reasonForChange") final String reason) {
         this.viewId = viewId;
@@ -55,7 +55,7 @@ public class BundleTimelineJson {
         return bundle;
     }
 
-    public List<PaymentJson> getPayments() {
+    public List<InvoicePaymentJson> getPayments() {
         return payments;
     }
 
diff --git a/jaxrs/src/main/java/org/killbill/billing/jaxrs/json/DirectPaymentJson.java b/jaxrs/src/main/java/org/killbill/billing/jaxrs/json/DirectPaymentJson.java
index 53ce7a9..47a0888 100644
--- a/jaxrs/src/main/java/org/killbill/billing/jaxrs/json/DirectPaymentJson.java
+++ b/jaxrs/src/main/java/org/killbill/billing/jaxrs/json/DirectPaymentJson.java
@@ -35,36 +35,42 @@ import com.google.common.collect.Iterables;
 public class DirectPaymentJson extends JsonBase {
 
     private final String accountId;
-    private final String directPaymentId;
+    private final String paymentId;
     private final String paymentNumber;
-    private final String directPaymentExternalKey;
+    private final String paymentExternalKey;
     private final BigDecimal authAmount;
     private final BigDecimal capturedAmount;
+    private final BigDecimal purchasedAmount;
     private final BigDecimal refundedAmount;
+    private final BigDecimal creditedAmount;
     private final String currency;
     private final String paymentMethodId;
     private final List<DirectTransactionJson> transactions;
 
     @JsonCreator
     public DirectPaymentJson(@JsonProperty("accountId") final String accountId,
-                             @JsonProperty("directPaymentId") final String directPaymentId,
+                             @JsonProperty("paymentId") final String paymentId,
                              @JsonProperty("paymentNumber") final String paymentNumber,
-                             @JsonProperty("directPaymentExternalKey") final String directPaymentExternalKey,
+                             @JsonProperty("paymentExternalKey") final String paymentExternalKey,
                              @JsonProperty("authAmount") final BigDecimal authAmount,
                              @JsonProperty("capturedAmount") final BigDecimal capturedAmount,
+                             @JsonProperty("purchasedAmount") final BigDecimal purchasedAmount,
                              @JsonProperty("refundedAmount") final BigDecimal refundedAmount,
+                             @JsonProperty("creditedAmount") final BigDecimal creditedAmount,
                              @JsonProperty("currency") final String currency,
                              @JsonProperty("paymentMethodId") final String paymentMethodId,
                              @JsonProperty("transactions") final List<DirectTransactionJson> transactions,
                              @JsonProperty("auditLogs") @Nullable final List<AuditLogJson> auditLogs) {
         super(auditLogs);
         this.accountId = accountId;
-        this.directPaymentId = directPaymentId;
+        this.paymentId = paymentId;
         this.paymentNumber = paymentNumber;
-        this.directPaymentExternalKey = directPaymentExternalKey;
+        this.paymentExternalKey = paymentExternalKey;
         this.authAmount = authAmount;
         this.capturedAmount = capturedAmount;
+        this.purchasedAmount = purchasedAmount;
         this.refundedAmount = refundedAmount;
+        this.creditedAmount = creditedAmount;
         this.currency = currency;
         this.paymentMethodId = paymentMethodId;
         this.transactions = transactions;
@@ -77,7 +83,9 @@ public class DirectPaymentJson extends JsonBase {
              dp.getExternalKey(),
              dp.getAuthAmount(),
              dp.getCapturedAmount(),
+             dp.getPurchasedAmount(),
              dp.getRefundedAmount(),
+             dp.getCreditedAmount(),
              dp.getCurrency() != null ? dp.getCurrency().toString() : null,
              dp.getPaymentMethodId() != null ? dp.getPaymentMethodId().toString() : null,
              getTransactions(dp.getTransactions(), dp.getExternalKey(), accountAuditLogs),
@@ -90,7 +98,7 @@ public class DirectPaymentJson extends JsonBase {
                                                             @Override
                                                             public DirectTransactionJson apply(final DirectPaymentTransaction directPaymentTransaction) {
                                                                 final List<AuditLog> auditLogsForDirectPaymentTransaction = accountAuditLogs == null ? null : accountAuditLogs.getAuditLogsForPaymentTransaction(directPaymentTransaction.getId());
-                                                                return new DirectTransactionJson(directPaymentTransaction, directPaymentExternalKey, auditLogsForDirectPaymentTransaction);
+                                                                return new DirectTransactionJson(directPaymentTransaction, auditLogsForDirectPaymentTransaction);
                                                             }
                                                         }
                                                        ));
@@ -100,16 +108,16 @@ public class DirectPaymentJson extends JsonBase {
         return accountId;
     }
 
-    public String getDirectPaymentId() {
-        return directPaymentId;
+    public String getPaymentId() {
+        return paymentId;
     }
 
     public String getPaymentNumber() {
         return paymentNumber;
     }
 
-    public String getDirectPaymentExternalKey() {
-        return directPaymentExternalKey;
+    public String getPaymentExternalKey() {
+        return paymentExternalKey;
     }
 
     public BigDecimal getAuthAmount() {
@@ -124,6 +132,14 @@ public class DirectPaymentJson extends JsonBase {
         return refundedAmount;
     }
 
+    public BigDecimal getPurchasedAmount() {
+        return purchasedAmount;
+    }
+
+    public BigDecimal getCreditedAmount() {
+        return creditedAmount;
+    }
+
     public String getCurrency() {
         return currency;
     }
@@ -140,12 +156,14 @@ public class DirectPaymentJson extends JsonBase {
     public String toString() {
         final StringBuilder sb = new StringBuilder("DirectPaymentJson{");
         sb.append("accountId='").append(accountId).append('\'');
-        sb.append(", directPaymentId='").append(directPaymentId).append('\'');
+        sb.append(", paymentId='").append(paymentId).append('\'');
         sb.append(", paymentNumber='").append(paymentNumber).append('\'');
-        sb.append(", directPaymentExternalKey='").append(directPaymentExternalKey).append('\'');
+        sb.append(", paymentExternalKey='").append(paymentExternalKey).append('\'');
         sb.append(", authAmount=").append(authAmount);
         sb.append(", capturedAmount=").append(capturedAmount);
+        sb.append(", purchasedAmount=").append(purchasedAmount);
         sb.append(", refundedAmount=").append(refundedAmount);
+        sb.append(", creditedAmount=").append(creditedAmount);
         sb.append(", currency='").append(currency).append('\'');
         sb.append(", paymentMethodId='").append(paymentMethodId).append('\'');
         sb.append(", transactions=").append(transactions);
@@ -173,13 +191,19 @@ public class DirectPaymentJson extends JsonBase {
         if (capturedAmount != null ? capturedAmount.compareTo(that.capturedAmount) != 0 : that.capturedAmount != null) {
             return false;
         }
+        if (creditedAmount != null ? creditedAmount.compareTo(that.creditedAmount) != 0 : that.creditedAmount != null) {
+            return false;
+        }
+        if (purchasedAmount != null ? purchasedAmount.compareTo(that.purchasedAmount) != 0 : that.purchasedAmount != null) {
+            return false;
+        }
         if (currency != null ? !currency.equals(that.currency) : that.currency != null) {
             return false;
         }
-        if (directPaymentExternalKey != null ? !directPaymentExternalKey.equals(that.directPaymentExternalKey) : that.directPaymentExternalKey != null) {
+        if (paymentExternalKey != null ? !paymentExternalKey.equals(that.paymentExternalKey) : that.paymentExternalKey != null) {
             return false;
         }
-        if (directPaymentId != null ? !directPaymentId.equals(that.directPaymentId) : that.directPaymentId != null) {
+        if (paymentId != null ? !paymentId.equals(that.paymentId) : that.paymentId != null) {
             return false;
         }
         if (paymentMethodId != null ? !paymentMethodId.equals(that.paymentMethodId) : that.paymentMethodId != null) {
@@ -201,11 +225,13 @@ public class DirectPaymentJson extends JsonBase {
     @Override
     public int hashCode() {
         int result = accountId != null ? accountId.hashCode() : 0;
-        result = 31 * result + (directPaymentId != null ? directPaymentId.hashCode() : 0);
+        result = 31 * result + (paymentId != null ? paymentId.hashCode() : 0);
         result = 31 * result + (paymentNumber != null ? paymentNumber.hashCode() : 0);
-        result = 31 * result + (directPaymentExternalKey != null ? directPaymentExternalKey.hashCode() : 0);
+        result = 31 * result + (paymentExternalKey != null ? paymentExternalKey.hashCode() : 0);
         result = 31 * result + (authAmount != null ? authAmount.hashCode() : 0);
         result = 31 * result + (capturedAmount != null ? capturedAmount.hashCode() : 0);
+        result = 31 * result + (creditedAmount != null ? creditedAmount.hashCode() : 0);
+        result = 31 * result + (purchasedAmount != null ? purchasedAmount.hashCode() : 0);
         result = 31 * result + (refundedAmount != null ? refundedAmount.hashCode() : 0);
         result = 31 * result + (currency != null ? currency.hashCode() : 0);
         result = 31 * result + (paymentMethodId != null ? paymentMethodId.hashCode() : 0);
diff --git a/jaxrs/src/main/java/org/killbill/billing/jaxrs/json/DirectTransactionJson.java b/jaxrs/src/main/java/org/killbill/billing/jaxrs/json/DirectTransactionJson.java
index 7204ef3..18c5ff3 100644
--- a/jaxrs/src/main/java/org/killbill/billing/jaxrs/json/DirectTransactionJson.java
+++ b/jaxrs/src/main/java/org/killbill/billing/jaxrs/json/DirectTransactionJson.java
@@ -30,10 +30,9 @@ import com.fasterxml.jackson.annotation.JsonProperty;
 
 public class DirectTransactionJson extends JsonBase {
 
-    private final String directTransactionId;
-    private final String directTransactionExternalKey;
-    private final String directPaymentId;
-    private final String directPaymentExternalKey;
+    private final String transactionId;
+    private final String transactionExternalKey;
+    private final String paymentId;
     private final String transactionType;
     private final DateTime effectiveDate;
     private final String status;
@@ -47,10 +46,9 @@ public class DirectTransactionJson extends JsonBase {
     private final List<PluginPropertyJson> properties;
 
     @JsonCreator
-    public DirectTransactionJson(@JsonProperty("directTransactionId") final String directTransactionId,
-                                 @JsonProperty("directTransactionExternalKey") final String directTransactionExternalKey,
-                                 @JsonProperty("directPaymentId") final String directPaymentId,
-                                 @JsonProperty("directPaymentExternalKey") final String directPaymentExternalKey,
+    public DirectTransactionJson(@JsonProperty("transactionId") final String transactionId,
+                                 @JsonProperty("transactionExternalKey") final String transactionExternalKey,
+                                 @JsonProperty("paymentId") final String directPaymentId,
                                  @JsonProperty("transactionType") final String transactionType,
                                  @JsonProperty("amount") final BigDecimal amount,
                                  @JsonProperty("currency") final String currency,
@@ -63,10 +61,9 @@ public class DirectTransactionJson extends JsonBase {
                                  @JsonProperty("properties") final List<PluginPropertyJson> properties,
                                  @JsonProperty("auditLogs") @Nullable final List<AuditLogJson> auditLogs) {
         super(auditLogs);
-        this.directTransactionId = directTransactionId;
-        this.directTransactionExternalKey = directTransactionExternalKey;
-        this.directPaymentId = directPaymentId;
-        this.directPaymentExternalKey = directPaymentExternalKey;
+        this.transactionId = transactionId;
+        this.transactionExternalKey = transactionExternalKey;
+        this.paymentId = directPaymentId;
         this.transactionType = transactionType;
         this.effectiveDate = effectiveDate;
         this.status = status;
@@ -79,11 +76,10 @@ public class DirectTransactionJson extends JsonBase {
         this.properties = properties;
     }
 
-    public DirectTransactionJson(final DirectPaymentTransaction dpt, final String directPaymentExternalKey, @Nullable final List<AuditLog> directTransactionLogs) {
+    public DirectTransactionJson(final DirectPaymentTransaction dpt, @Nullable final List<AuditLog> directTransactionLogs) {
         this(dpt.getId().toString(),
              dpt.getExternalKey(),
              dpt.getDirectPaymentId().toString(),
-             directPaymentExternalKey,
              dpt.getTransactionType().toString(),
              dpt.getAmount(),
              dpt.getCurrency() != null ? dpt.getCurrency().toString() : null,
@@ -97,20 +93,16 @@ public class DirectTransactionJson extends JsonBase {
              toAuditLogJson(directTransactionLogs));
     }
 
-    public String getDirectTransactionId() {
-        return directTransactionId;
+    public String getTransactionId() {
+        return transactionId;
     }
 
-    public String getDirectTransactionExternalKey() {
-        return directTransactionExternalKey;
+    public String getPaymentId() {
+        return paymentId;
     }
 
-    public String getDirectPaymentId() {
-        return directPaymentId;
-    }
-
-    public String getDirectPaymentExternalKey() {
-        return directPaymentExternalKey;
+    public String getTransactionExternalKey() {
+        return transactionExternalKey;
     }
 
     public String getTransactionType() {
@@ -156,10 +148,9 @@ public class DirectTransactionJson extends JsonBase {
     @Override
     public String toString() {
         final StringBuilder sb = new StringBuilder("DirectTransactionJson{");
-        sb.append("directTransactionId='").append(directTransactionId).append('\'');
-        sb.append(", directTransactionExternalKey='").append(directTransactionExternalKey).append('\'');
-        sb.append(", directPaymentId='").append(directPaymentId).append('\'');
-        sb.append(", directPaymentExternalKey='").append(directPaymentExternalKey).append('\'');
+        sb.append("transactionId='").append(transactionId).append('\'');
+        sb.append(", paymentId='").append(paymentId).append('\'');
+        sb.append(", transactionExternalKey='").append(transactionExternalKey).append('\'');
         sb.append(", transactionType='").append(transactionType).append('\'');
         sb.append(", effectiveDate=").append(effectiveDate);
         sb.append(", status='").append(status).append('\'');
@@ -191,16 +182,13 @@ public class DirectTransactionJson extends JsonBase {
         if (currency != null ? !currency.equals(that.currency) : that.currency != null) {
             return false;
         }
-        if (directPaymentExternalKey != null ? !directPaymentExternalKey.equals(that.directPaymentExternalKey) : that.directPaymentExternalKey != null) {
-            return false;
-        }
-        if (directPaymentId != null ? !directPaymentId.equals(that.directPaymentId) : that.directPaymentId != null) {
+        if (transactionExternalKey != null ? !transactionExternalKey.equals(that.transactionExternalKey) : that.transactionExternalKey != null) {
             return false;
         }
-        if (directTransactionExternalKey != null ? !directTransactionExternalKey.equals(that.directTransactionExternalKey) : that.directTransactionExternalKey != null) {
+        if (paymentId != null ? !paymentId.equals(that.paymentId) : that.paymentId != null) {
             return false;
         }
-        if (directTransactionId != null ? !directTransactionId.equals(that.directTransactionId) : that.directTransactionId != null) {
+        if (transactionId != null ? !transactionId.equals(that.transactionId) : that.transactionId != null) {
             return false;
         }
         if (effectiveDate != null ? effectiveDate.compareTo(that.effectiveDate) != 0 : that.effectiveDate != null) {
@@ -233,10 +221,9 @@ public class DirectTransactionJson extends JsonBase {
 
     @Override
     public int hashCode() {
-        int result = directTransactionId != null ? directTransactionId.hashCode() : 0;
-        result = 31 * result + (directTransactionExternalKey != null ? directTransactionExternalKey.hashCode() : 0);
-        result = 31 * result + (directPaymentId != null ? directPaymentId.hashCode() : 0);
-        result = 31 * result + (directPaymentExternalKey != null ? directPaymentExternalKey.hashCode() : 0);
+        int result = transactionId != null ? transactionId.hashCode() : 0;
+        result = 31 * result + (paymentId != null ? paymentId.hashCode() : 0);
+        result = 31 * result + (transactionExternalKey != null ? transactionExternalKey.hashCode() : 0);
         result = 31 * result + (transactionType != null ? transactionType.hashCode() : 0);
         result = 31 * result + (effectiveDate != null ? effectiveDate.hashCode() : 0);
         result = 31 * result + (status != null ? status.hashCode() : 0);
diff --git a/jaxrs/src/main/java/org/killbill/billing/jaxrs/json/InvoicePaymentJson.java b/jaxrs/src/main/java/org/killbill/billing/jaxrs/json/InvoicePaymentJson.java
new file mode 100644
index 0000000..004b453
--- /dev/null
+++ b/jaxrs/src/main/java/org/killbill/billing/jaxrs/json/InvoicePaymentJson.java
@@ -0,0 +1,93 @@
+/*
+ * Copyright 2010-2013 Ning, Inc.
+ * Copyright 2014 Groupon, Inc
+ * Copyright 2014 The Billing Project, LLC
+ *
+ * The Billing Project 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.json;
+
+import java.math.BigDecimal;
+import java.util.List;
+import java.util.UUID;
+
+import javax.annotation.Nullable;
+
+import org.killbill.billing.payment.api.DirectPayment;
+import org.killbill.billing.util.audit.AccountAuditLogs;
+
+import com.fasterxml.jackson.annotation.JsonCreator;
+import com.fasterxml.jackson.annotation.JsonProperty;
+
+public class InvoicePaymentJson extends DirectPaymentJson {
+
+    private final String targetInvoiceId;
+
+    @JsonCreator
+    public InvoicePaymentJson(@JsonProperty("targetInvoiceId") final String targetInvoiceId,
+                              @JsonProperty("accountId") final String accountId,
+                              @JsonProperty("paymentId") final String paymentId,
+                              @JsonProperty("paymentNumber") final String paymentNumber,
+                              @JsonProperty("paymentExternalKey") final String paymentExternalKey,
+                              @JsonProperty("authAmount") final BigDecimal authAmount,
+                              @JsonProperty("capturedAmount") final BigDecimal capturedAmount,
+                              @JsonProperty("purchasedAmount") final BigDecimal purchasedAmount,
+                              @JsonProperty("refundedAmount") final BigDecimal refundedAmount,
+                              @JsonProperty("creditedAmount") final BigDecimal creditedAmount,
+                              @JsonProperty("currency") final String currency,
+                              @JsonProperty("paymentMethodId") final String paymentMethodId,
+                              @JsonProperty("transactions") final List<DirectTransactionJson> transactions,
+                              @JsonProperty("auditLogs") @Nullable final List<AuditLogJson> auditLogs) {
+        super(accountId, paymentId, paymentNumber, paymentExternalKey, authAmount, capturedAmount, purchasedAmount, refundedAmount, creditedAmount, currency, paymentMethodId, transactions, auditLogs);
+        this.targetInvoiceId = targetInvoiceId;
+    }
+
+    public InvoicePaymentJson(final DirectPayment dp, @Nullable final UUID invoiceId, @Nullable final AccountAuditLogs accountAuditLogs) {
+        super(dp, accountAuditLogs);
+        this.targetInvoiceId = invoiceId != null ? invoiceId.toString() : null;
+    }
+
+
+        public String getTargetInvoiceId() {
+        return targetInvoiceId;
+    }
+
+    @Override
+    public boolean equals(final Object o) {
+        if (this == o) {
+            return true;
+        }
+        if (!(o instanceof InvoicePaymentJson)) {
+            return false;
+        }
+        if (!super.equals(o)) {
+            return false;
+        }
+
+        final InvoicePaymentJson that = (InvoicePaymentJson) o;
+
+        if (targetInvoiceId != null ? !targetInvoiceId.equals(that.targetInvoiceId) : that.targetInvoiceId != null) {
+            return false;
+        }
+
+        return true;
+    }
+
+    @Override
+    public int hashCode() {
+        int result = super.hashCode();
+        result = 31 * result + (targetInvoiceId != null ? targetInvoiceId.hashCode() : 0);
+        return result;
+    }
+}
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 e025dc0..732323e 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
@@ -23,13 +23,10 @@ import java.net.URI;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Collections;
-import java.util.HashMap;
 import java.util.LinkedList;
 import java.util.List;
-import java.util.Map;
 import java.util.UUID;
 
-import javax.annotation.Nullable;
 import javax.servlet.http.HttpServletRequest;
 import javax.ws.rs.Consumes;
 import javax.ws.rs.DELETE;
@@ -73,8 +70,8 @@ import org.killbill.billing.jaxrs.json.DirectPaymentJson;
 import org.killbill.billing.jaxrs.json.DirectTransactionJson;
 import org.killbill.billing.jaxrs.json.InvoiceEmailJson;
 import org.killbill.billing.jaxrs.json.InvoiceJson;
+import org.killbill.billing.jaxrs.json.InvoicePaymentJson;
 import org.killbill.billing.jaxrs.json.OverdueStateJson;
-import org.killbill.billing.jaxrs.json.PaymentJson;
 import org.killbill.billing.jaxrs.json.PaymentMethodJson;
 import org.killbill.billing.jaxrs.json.RefundJson;
 import org.killbill.billing.jaxrs.util.Context;
@@ -355,12 +352,7 @@ public class AccountResource extends JaxRsResourceBase {
         final AccountAuditLogs accountAuditLogs = auditUserApi.getAccountAuditLogs(accountId, auditMode.getLevel(), tenantContext);
 
         final List<InvoicePayment> invoicePayments = invoicePaymentApi.getInvoicePaymentsByAccount(accountId, tenantContext);
-        final Map<UUID, UUID> invoicesIdByPayment = new HashMap<UUID, UUID>();
-        for (InvoicePayment cur : invoicePayments) {
-            invoicesIdByPayment.put(cur.getPaymentId(), cur.getInvoiceId());
-        }
-        final AccountTimelineJson json = new AccountTimelineJson(account, invoices, payments, invoicesIdByPayment, bundles,
-                                                                 refundsByPayment, chargebacksByPayment,
+        final AccountTimelineJson json = new AccountTimelineJson(account, invoices, payments, invoicePayments, bundles,
                                                                  accountAuditLogs);
         return Response.status(Status.OK).entity(json).build();
     }
@@ -460,15 +452,19 @@ public class AccountResource extends JaxRsResourceBase {
      */
 
     @GET
-    @Path("/{accountId:" + UUID_PATTERN + "}/" + PAYMENTS)
+    @Path("/{accountId:" + UUID_PATTERN + "}/" + INVOICE_PAYMENTS)
     @Produces(APPLICATION_JSON)
-    public Response getPayments(@PathParam("accountId") final String accountId,
-                                @QueryParam(QUERY_WITH_PLUGIN_INFO) @DefaultValue("false") final Boolean withPluginInfo,
-                                @javax.ws.rs.core.Context final HttpServletRequest request) throws PaymentApiException {
-        final List<DirectPayment> payments = paymentApi.getAccountPayments(UUID.fromString(accountId), withPluginInfo, ImmutableList.<PluginProperty>of(), context.createContext(request));
-        final List<PaymentJson> result = new ArrayList<PaymentJson>(payments.size());
+    public Response getInvoicePayments(@PathParam("accountId") final String accountIdStr,
+                                       @QueryParam(QUERY_WITH_PLUGIN_INFO) @DefaultValue("false") final Boolean withPluginInfo,
+                                       @javax.ws.rs.core.Context final HttpServletRequest request) throws PaymentApiException {
+        final TenantContext tenantContext = context.createContext(request);
+        final UUID accountId = UUID.fromString(accountIdStr);
+        final List<DirectPayment> payments = paymentApi.getAccountPayments(accountId, withPluginInfo, ImmutableList.<PluginProperty>of(), tenantContext);
+        final List<InvoicePayment> invoicePayments = invoicePaymentApi.getInvoicePaymentsByAccount(accountId, tenantContext);
+        final List<InvoicePaymentJson> result = new ArrayList<InvoicePaymentJson>(payments.size());
         for (final DirectPayment payment : payments) {
-            result.add(new PaymentJson(payment, null));
+            final UUID invoiceId = getInvoiceId(invoicePayments, payment);
+            result.add(new InvoicePaymentJson(payment, invoiceId, null));
         }
         return Response.status(Status.OK).entity(result).build();
     }
@@ -476,7 +472,7 @@ public class AccountResource extends JaxRsResourceBase {
     @POST
     @Produces(APPLICATION_JSON)
     @Consumes(APPLICATION_JSON)
-    @Path("/{accountId:" + UUID_PATTERN + "}/" + PAYMENTS)
+    @Path("/{accountId:" + UUID_PATTERN + "}/" + INVOICE_PAYMENTS)
     public Response payAllInvoices(@PathParam("accountId") final String accountId,
                                    @QueryParam(QUERY_PAYMENT_EXTERNAL) @DefaultValue("false") final Boolean externalPayment,
                                    @QueryParam(QUERY_PAYMENT_AMOUNT) final BigDecimal paymentAmount,
@@ -520,7 +516,6 @@ public class AccountResource extends JaxRsResourceBase {
         return Response.status(Status.OK).build();
     }
 
-
     @POST
     @Path("/{accountId:" + UUID_PATTERN + "}/" + PAYMENT_METHODS)
     @Consumes(APPLICATION_JSON)
@@ -609,15 +604,15 @@ public class AccountResource extends JaxRsResourceBase {
     }
 
     /*
-     * ************************* DIRECT PAYMENTS *****************************
+     * ************************* PAYMENTS *****************************
      */
     @GET
-    @Path("/{accountId:" + UUID_PATTERN + "}/" + DIRECT_PAYMENTS)
+    @Path("/{accountId:" + UUID_PATTERN + "}/" + PAYMENTS)
     @Produces(APPLICATION_JSON)
-    public Response getDirectPaymentsForAccount(@PathParam("accountId") final String accountIdStr,
-                                                @QueryParam(QUERY_AUDIT) @DefaultValue("NONE") final AuditMode auditMode,
-                                                @QueryParam(QUERY_WITH_PLUGIN_INFO) @DefaultValue("false") final Boolean withPluginInfo,
-                                                @javax.ws.rs.core.Context final HttpServletRequest request) throws PaymentApiException {
+    public Response getPayments(@PathParam("accountId") final String accountIdStr,
+                                @QueryParam(QUERY_AUDIT) @DefaultValue("NONE") final AuditMode auditMode,
+                                @QueryParam(QUERY_WITH_PLUGIN_INFO) @DefaultValue("false") final Boolean withPluginInfo,
+                                @javax.ws.rs.core.Context final HttpServletRequest request) throws PaymentApiException {
         final UUID accountId = UUID.fromString(accountIdStr);
         final TenantContext tenantContext = context.createContext(request);
         final List<DirectPayment> payments = paymentApi.getAccountPayments(accountId, withPluginInfo, ImmutableList.<PluginProperty>of(), tenantContext);
@@ -632,7 +627,7 @@ public class AccountResource extends JaxRsResourceBase {
     }
 
     @POST
-    @Path("/{accountId:" + UUID_PATTERN + "}/" + DIRECT_PAYMENTS)
+    @Path("/{accountId:" + UUID_PATTERN + "}/" + PAYMENTS)
     @Consumes(APPLICATION_JSON)
     @Produces(APPLICATION_JSON)
     public Response processDirectPayment(final DirectTransactionJson json,
@@ -650,25 +645,25 @@ public class AccountResource extends JaxRsResourceBase {
         final Account account = accountUserApi.getAccountById(accountId, callContext);
         final UUID paymentMethodId = paymentMethodIdStr == null ? account.getPaymentMethodId() : UUID.fromString(paymentMethodIdStr);
         final Currency currency = json.getCurrency() == null ? account.getCurrency() : Currency.valueOf(json.getCurrency());
-        final UUID directPaymentId = json.getDirectPaymentId() == null ? null : UUID.fromString(json.getDirectPaymentId());
+        final UUID directPaymentId = json.getPaymentId() == null ? null : UUID.fromString(json.getPaymentId());
 
         final TransactionType transactionType = TransactionType.valueOf(json.getTransactionType());
         final DirectPayment result;
         switch (transactionType) {
             case AUTHORIZE:
                 result = paymentApi.createAuthorization(account, paymentMethodId, directPaymentId, json.getAmount(), currency,
-                                                              json.getDirectPaymentExternalKey(), json.getDirectTransactionExternalKey(),
-                                                              pluginProperties, callContext);
+                                                        json.getTransactionExternalKey(), json.getTransactionExternalKey(),
+                                                        pluginProperties, callContext);
                 break;
             case PURCHASE:
                 result = paymentApi.createPurchase(account, paymentMethodId, directPaymentId, json.getAmount(), currency,
-                                                         json.getDirectPaymentExternalKey(), json.getDirectTransactionExternalKey(),
-                                                         pluginProperties, callContext);
+                                                   json.getTransactionExternalKey(), json.getTransactionExternalKey(),
+                                                   pluginProperties, callContext);
                 break;
             case CREDIT:
                 result = paymentApi.createCredit(account, paymentMethodId, directPaymentId, json.getAmount(), currency,
-                                                       json.getDirectPaymentExternalKey(), json.getDirectTransactionExternalKey(),
-                                                       pluginProperties, callContext);
+                                                 json.getTransactionExternalKey(), json.getTransactionExternalKey(),
+                                                 pluginProperties, callContext);
                 break;
             default:
                 return Response.status(Status.PRECONDITION_FAILED).entity("TransactionType " + transactionType + " is not allowed for an account").build();
@@ -718,7 +713,8 @@ public class AccountResource extends JaxRsResourceBase {
                 return new RefundJson(input, null, null);
             }
         });
-        return Response.status(Status.OK).entity(result).build();
+        final List<RefundJson> realResult = ImmutableList.copyOf(result);
+        return Response.status(Status.OK).entity(realResult).build();
     }
 
     /*
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
index 707efe1..cbae67b 100644
--- a/jaxrs/src/main/java/org/killbill/billing/jaxrs/resources/DirectPaymentResource.java
+++ b/jaxrs/src/main/java/org/killbill/billing/jaxrs/resources/DirectPaymentResource.java
@@ -67,7 +67,7 @@ import com.google.common.collect.ImmutableMap;
 
 import static javax.ws.rs.core.MediaType.APPLICATION_JSON;
 
-@Path(JaxrsResource.DIRECT_PAYMENTS_PATH)
+@Path(JaxrsResource.PAYMENTS_PATH)
 public class DirectPaymentResource extends JaxRsResourceBase {
 
     @Inject
@@ -204,7 +204,7 @@ public class DirectPaymentResource extends JaxRsResourceBase {
         final Currency currency = json.getCurrency() == null ? account.getCurrency() : Currency.valueOf(json.getCurrency());
 
         final DirectPayment payment = paymentApi.createCapture(account, directPaymentId, json.getAmount(), currency,
-                                                                     json.getDirectTransactionExternalKey(), pluginProperties, callContext);
+                                                                     json.getTransactionExternalKey(), pluginProperties, callContext);
         return uriBuilder.buildResponse(uriInfo, DirectPaymentResource.class, "getDirectPayment", payment.getId());
     }
 
@@ -229,7 +229,7 @@ public class DirectPaymentResource extends JaxRsResourceBase {
         final Currency currency = json.getCurrency() == null ? account.getCurrency() : Currency.valueOf(json.getCurrency());
 
         final DirectPayment payment = paymentApi.createRefund(account, directPaymentId, json.getAmount(), currency,
-                                                              json.getDirectTransactionExternalKey(), pluginProperties, callContext);
+                                                              json.getTransactionExternalKey(), pluginProperties, callContext);
         return uriBuilder.buildResponse(uriInfo, DirectPaymentResource.class, "getDirectPayment", payment.getId());
     }
 
@@ -252,7 +252,7 @@ public class DirectPaymentResource extends JaxRsResourceBase {
 
         final Account account = accountUserApi.getAccountById(initialPayment.getAccountId(), callContext);
 
-        final DirectPayment payment = paymentApi.createVoid(account, directPaymentId, json.getDirectTransactionExternalKey(), pluginProperties, callContext);
+        final DirectPayment payment = paymentApi.createVoid(account, directPaymentId, json.getTransactionExternalKey(), pluginProperties, callContext);
         return uriBuilder.buildResponse(uriInfo, DirectPaymentResource.class, "getDirectPayment", payment.getId());
     }
 
diff --git a/jaxrs/src/main/java/org/killbill/billing/jaxrs/resources/InvoicePaymentResource.java b/jaxrs/src/main/java/org/killbill/billing/jaxrs/resources/InvoicePaymentResource.java
index d538f32..1d6718d 100644
--- a/jaxrs/src/main/java/org/killbill/billing/jaxrs/resources/InvoicePaymentResource.java
+++ b/jaxrs/src/main/java/org/killbill/billing/jaxrs/resources/InvoicePaymentResource.java
@@ -19,7 +19,6 @@
 package org.killbill.billing.jaxrs.resources;
 
 import java.math.BigDecimal;
-import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
@@ -32,56 +31,45 @@ import javax.ws.rs.DefaultValue;
 import javax.ws.rs.GET;
 import javax.ws.rs.HeaderParam;
 import javax.ws.rs.POST;
-import javax.ws.rs.PUT;
 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.Response.Status;
 import javax.ws.rs.core.UriInfo;
 
 import org.killbill.billing.ObjectType;
 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.catalog.api.Currency;
-import org.killbill.billing.invoice.api.InvoiceApiException;
-import org.killbill.billing.invoice.api.InvoicePayment;
-import org.killbill.billing.invoice.api.InvoicePaymentApi;
-import org.killbill.billing.jaxrs.json.ChargebackJson;
 import org.killbill.billing.jaxrs.json.CustomFieldJson;
+import org.killbill.billing.jaxrs.json.DirectPaymentJson;
 import org.killbill.billing.jaxrs.json.InvoiceItemJson;
-import org.killbill.billing.jaxrs.json.PaymentJson;
+import org.killbill.billing.jaxrs.json.InvoicePaymentJson;
 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.DirectPayment;
 import org.killbill.billing.payment.api.DirectPaymentApi;
-import org.killbill.billing.payment.api.DirectPaymentTransaction;
 import org.killbill.billing.payment.api.PaymentApiException;
 import org.killbill.billing.payment.api.PluginProperty;
-import org.killbill.billing.payment.api.TransactionType;
 import org.killbill.billing.util.api.AuditUserApi;
 import org.killbill.billing.util.api.CustomFieldApiException;
 import org.killbill.billing.util.api.CustomFieldUserApi;
 import org.killbill.billing.util.api.TagApiException;
 import org.killbill.billing.util.api.TagDefinitionApiException;
 import org.killbill.billing.util.api.TagUserApi;
+import org.killbill.billing.util.audit.AccountAuditLogs;
 import org.killbill.billing.util.callcontext.CallContext;
 import org.killbill.billing.util.callcontext.TenantContext;
 import org.killbill.clock.Clock;
 
-import com.google.common.base.Function;
-import com.google.common.base.Predicate;
-import com.google.common.collect.Collections2;
 import com.google.common.collect.ImmutableList;
-import com.google.common.collect.Iterables;
 import com.google.inject.Inject;
 
 import static javax.ws.rs.core.MediaType.APPLICATION_JSON;
 
-@Path(JaxrsResource.PAYMENTS_PATH)
+@Path(JaxrsResource.INVOICE_PAYMENTS_PATH)
 public class InvoicePaymentResource extends JaxRsResourceBase {
 
     private static final String ID_PARAM_NAME = "paymentId";
@@ -100,6 +88,26 @@ public class InvoicePaymentResource extends JaxRsResourceBase {
     }
 
 
+    @GET
+    @Path("/{paymentId:" + UUID_PATTERN + "}/")
+    @Produces(APPLICATION_JSON)
+    public Response getInvoicePayment(@PathParam("paymentId") final String directPaymentIdStr,
+                                     @QueryParam(QUERY_WITH_PLUGIN_INFO) @DefaultValue("false") final Boolean withPluginInfo,
+                                     @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 directPaymentIdId = UUID.fromString(directPaymentIdStr);
+        final TenantContext tenantContext = context.createContext(request);
+        final DirectPayment directPayment = paymentApi.getPayment(directPaymentIdId, withPluginInfo, pluginProperties, tenantContext);
+        final AccountAuditLogs accountAuditLogs = auditUserApi.getAccountAuditLogs(directPayment.getAccountId(), auditMode.getLevel(), tenantContext);
+        final DirectPaymentJson paymentJson = new DirectPaymentJson(directPayment, accountAuditLogs);
+        // STEPH (API is broken need to also have the invoiceId)
+        //final InvoicePaymentJson result = new InvoicePaymentJson(directPayment, accountAuditLogs)
+        return Response.status(Response.Status.OK).entity(paymentJson).build();
+    }
+
+
     @POST
     @Path("/{paymentId:" + UUID_PATTERN + "}/" + REFUNDS)
     @Consumes(APPLICATION_JSON)
@@ -128,17 +136,21 @@ public class InvoicePaymentResource extends JaxRsResourceBase {
                     adjustments.put(UUID.fromString(item.getInvoiceItemId()), item.getAmount());
                 }
                 pluginProperties = extractPluginProperties(pluginPropertiesString,
-                                                           new PluginProperty("IPCD_REF_IDS_AMOUNTS", true, false),
-                                                           new PluginProperty("IPCD_REFUND_WITH_ADJUSTMENTS", adjustments, false));
+                                                           new PluginProperty("IPCD_REFUND_WITH_ADJUSTMENTS", "true", false),
+                                                           new PluginProperty("IPCD_REFUND_IDS_AMOUNTS", adjustments, false));
             } else {
                 pluginProperties = extractPluginProperties(pluginPropertiesString,
-                                                           new PluginProperty("IPCD_REF_IDS_AMOUNTS", true, false));
+                                                           new PluginProperty("IPCD_REFUND_WITH_ADJUSTMENTS", "true", false));
             }
         } else {
             pluginProperties = extractPluginProperties(pluginPropertiesString);
         }
-        final DirectPayment result = paymentApi.createRefundWithPaymentControl(account, payment.getId(), null, account.getCurrency(), transactionExternalKey,
+
+
+        final DirectPayment result = paymentApi.createRefundWithPaymentControl(account, payment.getId(), json.getAmount(), account.getCurrency(), transactionExternalKey,
                                                                                pluginProperties, createInvoicePaymentControlPluginApiPaymentOptions(false), callContext);
+
+        // STEPH should be changed to return InvoicePayment instead
         return uriBuilder.buildResponse(DirectPaymentResource.class, "getDirectPayment", result.getId(), uriInfo.getBaseUri().toString());
     }
 
diff --git a/jaxrs/src/main/java/org/killbill/billing/jaxrs/resources/InvoiceResource.java b/jaxrs/src/main/java/org/killbill/billing/jaxrs/resources/InvoiceResource.java
index a89d229..98e7b0c 100644
--- a/jaxrs/src/main/java/org/killbill/billing/jaxrs/resources/InvoiceResource.java
+++ b/jaxrs/src/main/java/org/killbill/billing/jaxrs/resources/InvoiceResource.java
@@ -62,7 +62,7 @@ import org.killbill.billing.invoice.api.InvoiceUserApi;
 import org.killbill.billing.jaxrs.json.CustomFieldJson;
 import org.killbill.billing.jaxrs.json.InvoiceItemJson;
 import org.killbill.billing.jaxrs.json.InvoiceJson;
-import org.killbill.billing.jaxrs.json.PaymentJson;
+import org.killbill.billing.jaxrs.json.InvoicePaymentJson;
 import org.killbill.billing.jaxrs.util.Context;
 import org.killbill.billing.jaxrs.util.JaxrsUriBuilder;
 import org.killbill.billing.payment.api.DirectPayment;
@@ -76,7 +76,6 @@ import org.killbill.billing.util.api.TagApiException;
 import org.killbill.billing.util.api.TagDefinitionApiException;
 import org.killbill.billing.util.api.TagUserApi;
 import org.killbill.billing.util.audit.AccountAuditLogs;
-import org.killbill.billing.util.audit.AccountAuditLogsForObjectType;
 import org.killbill.billing.util.callcontext.CallContext;
 import org.killbill.billing.util.callcontext.TenantContext;
 import org.killbill.billing.util.entity.Pagination;
@@ -386,20 +385,13 @@ public class InvoiceResource extends JaxRsResourceBase {
             final DirectPayment payment = paymentApi.getPayment(cur.getId(), withPluginInfo, ImmutableList.<PluginProperty>of(), tenantContext);
             payments.add(payment);
         }
-        final List<PaymentJson> result = new ArrayList<PaymentJson>(payments.size());
+        final List<InvoicePaymentJson> result = new ArrayList<InvoicePaymentJson>(payments.size());
         if (payments.isEmpty()) {
             return Response.status(Status.OK).entity(result).build();
         }
-
-        final AccountAuditLogsForObjectType auditLogsForPayments = auditUserApi.getAccountAuditLogs(payments.get(0).getAccountId(),
-                                                                                                    ObjectType.PAYMENT,
-                                                                                                    auditMode.getLevel(),
-                                                                                                    tenantContext);
-
         for (final DirectPayment cur : payments) {
-            result.add(new PaymentJson(cur, auditLogsForPayments.getAuditLogs(cur.getId())));
+            result.add(new InvoicePaymentJson(cur, invoice.getId(), null));
         }
-
         return Response.status(Status.OK).entity(result).build();
     }
 
@@ -407,7 +399,7 @@ public class InvoiceResource extends JaxRsResourceBase {
     @Produces(APPLICATION_JSON)
     @Consumes(APPLICATION_JSON)
     @Path("/{invoiceId:" + UUID_PATTERN + "}/" + PAYMENTS)
-    public Response createInstantPayment(final PaymentJson payment,
+    public Response createInstantPayment(final InvoicePaymentJson payment,
                                          @QueryParam(QUERY_PAYMENT_EXTERNAL) @DefaultValue("false") final Boolean externalPayment,
                                          @QueryParam(QUERY_PLUGIN_PROPERTY) final List<String> pluginPropertiesString,
                                          @HeaderParam(HDR_CREATED_BY) final String createdBy,
@@ -419,9 +411,10 @@ public class InvoiceResource extends JaxRsResourceBase {
         final CallContext callContext = context.createContext(createdBy, reason, comment, request);
 
         final Account account = accountUserApi.getAccountById(UUID.fromString(payment.getAccountId()), callContext);
-        final UUID invoiceId = UUID.fromString(payment.getInvoiceId());
-        createPurchaseForInvoice(account, invoiceId, payment.getPurchaseAmount(), externalPayment, callContext);
-        return uriBuilder.buildResponse(uriInfo, InvoiceResource.class, "getPayments", payment.getInvoiceId());
+        final UUID invoiceId = UUID.fromString(payment.getTargetInvoiceId());
+        final DirectPayment result = createPurchaseForInvoice(account, invoiceId, payment.getPurchasedAmount(), externalPayment, callContext);
+        // STEPH should that live in InvoicePayment instead?
+        return uriBuilder.buildResponse(uriInfo, DirectPaymentResource.class, "getDirectPayment", result.getId());
     }
 
     @POST
diff --git a/jaxrs/src/main/java/org/killbill/billing/jaxrs/resources/JaxrsResource.java b/jaxrs/src/main/java/org/killbill/billing/jaxrs/resources/JaxrsResource.java
index 0243355..1188e54 100644
--- a/jaxrs/src/main/java/org/killbill/billing/jaxrs/resources/JaxrsResource.java
+++ b/jaxrs/src/main/java/org/killbill/billing/jaxrs/resources/JaxrsResource.java
@@ -93,6 +93,8 @@ public interface JaxrsResource {
     public static final String QUERY_WITH_PLUGIN_INFO = "withPluginInfo";
     public static final String QUERY_PAYMENT_METHOD_IS_DEFAULT = "isDefault";
 
+    public static final String QUERY_PAYMENT_METHOD_PLUGIN_INFO = "pluginInfo"; // STEPH check on that one, why was that missing?
+
     public static final String QUERY_PAY_ALL_UNPAID_INVOICES = "payAllUnpaidInvoices";
     public static final String QUERY_PAY_INVOICE = "payInvoice";
 
@@ -139,17 +141,13 @@ public interface JaxrsResource {
     public static final String CHARGES = "charges";
     public static final String CHARGES_PATH = PREFIX + "/" + INVOICES + "/" + CHARGES;
 
-    public static final String PAYMENTS = "invoicePayments";
+    public static final String PAYMENTS = "payments";
     public static final String PAYMENTS_PATH = PREFIX + "/" + PAYMENTS;
 
-    public static final String DIRECT_PAYMENTS = "directPayments";
-    public static final String DIRECT_PAYMENTS_PATH = PREFIX + "/" + DIRECT_PAYMENTS;
-
     public static final String PAYMENT_GATEWAYS = "paymentGateways";
     public static final String PAYMENT_GATEWAYS_PATH = PREFIX + "/" + PAYMENT_GATEWAYS;
 
     public static final String REFUNDS = "refunds";
-    public static final String REFUNDS_PATH = PREFIX + "/" + "refunds";
 
     public static final String PAYMENT_METHODS = "paymentMethods";
     public static final String PAYMENT_METHODS_PATH = PREFIX + "/" + PAYMENT_METHODS;
@@ -158,6 +156,9 @@ public interface JaxrsResource {
     public static final String CREDITS = "credits";
     public static final String CREDITS_PATH = PREFIX + "/" + CREDITS;
 
+    public static final String INVOICE_PAYMENTS = "invoicePayments";
+    public static final String INVOICE_PAYMENTS_PATH = PREFIX + "/" + INVOICE_PAYMENTS;
+
     public static final String CHARGEBACKS = "chargebacks";
     public static final String CHARGEBACKS_PATH = PREFIX + "/" + CHARGEBACKS;
 
diff --git a/jaxrs/src/main/java/org/killbill/billing/jaxrs/resources/JaxRsResourceBase.java b/jaxrs/src/main/java/org/killbill/billing/jaxrs/resources/JaxRsResourceBase.java
index cc2afcc..0648bc6 100644
--- a/jaxrs/src/main/java/org/killbill/billing/jaxrs/resources/JaxRsResourceBase.java
+++ b/jaxrs/src/main/java/org/killbill/billing/jaxrs/resources/JaxRsResourceBase.java
@@ -50,6 +50,8 @@ 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.invoice.api.Invoice;
+import org.killbill.billing.invoice.api.InvoicePayment;
+import org.killbill.billing.invoice.api.InvoicePaymentType;
 import org.killbill.billing.jaxrs.json.CustomFieldJson;
 import org.killbill.billing.jaxrs.json.JsonBase;
 import org.killbill.billing.jaxrs.json.TagJson;
@@ -344,7 +346,7 @@ public abstract class JaxRsResourceBase implements JaxrsResource {
         return properties;
     }
 
-    protected void createPurchaseForInvoice(final Account account, final UUID invoiceId, final BigDecimal amountToPay, final Boolean externalPayment, final CallContext callContext) throws PaymentApiException {
+    protected DirectPayment createPurchaseForInvoice(final Account account, final UUID invoiceId, final BigDecimal amountToPay, final Boolean externalPayment, final CallContext callContext) throws PaymentApiException {
 
         final List<PluginProperty> properties = new ArrayList<PluginProperty>();
         final String paymentExternalKey = UUID.randomUUID().toString();
@@ -353,7 +355,7 @@ public abstract class JaxRsResourceBase implements JaxrsResource {
                                                                   invoiceId.toString(), false);
         properties.add(invoiceProperty);
 
-        paymentApi.createPurchaseWithPaymentControl(account, account.getPaymentMethodId(), null, amountToPay, account.getCurrency(), paymentExternalKey, transactionExternalKey,
+        return paymentApi.createPurchaseWithPaymentControl(account, account.getPaymentMethodId(), null, amountToPay, account.getCurrency(), paymentExternalKey, transactionExternalKey,
                                                     properties, createInvoicePaymentControlPluginApiPaymentOptions(externalPayment), callContext);
     }
 
@@ -372,7 +374,7 @@ public abstract class JaxRsResourceBase implements JaxrsResource {
         };
     }
 
-    protected Iterable<DirectPaymentTransaction> getDirectPaymentTransactions(final List<DirectPayment> payments, final TransactionType transactionType) {
+    public static Iterable<DirectPaymentTransaction> getDirectPaymentTransactions(final List<DirectPayment> payments, final TransactionType transactionType) {
         return Iterables.concat(Iterables.transform(payments, new Function<DirectPayment, Iterable<DirectPaymentTransaction>>() {
             @Override
             public Iterable<DirectPaymentTransaction> apply(final DirectPayment input) {
@@ -385,4 +387,15 @@ public abstract class JaxRsResourceBase implements JaxrsResource {
             }
         }));
     }
+
+    public static UUID getInvoiceId(final List<InvoicePayment> invoicePayments, final DirectPayment payment) {
+        final InvoicePayment invoicePayment = Iterables.tryFind(invoicePayments, new Predicate<InvoicePayment>() {
+            @Override
+            public boolean apply(final InvoicePayment input) {
+                return input.getPaymentId().equals(payment.getId()) && input.getType() == InvoicePaymentType.ATTEMPT;
+            }
+        }).orNull();
+        return invoicePayment != null ? invoicePayment.getInvoiceId() : null;
+    }
+
 }
diff --git a/jaxrs/src/test/java/org/killbill/billing/jaxrs/json/TestBundleTimelineJson.java b/jaxrs/src/test/java/org/killbill/billing/jaxrs/json/TestBundleTimelineJson.java
index 5250ee6..a225588 100644
--- a/jaxrs/src/test/java/org/killbill/billing/jaxrs/json/TestBundleTimelineJson.java
+++ b/jaxrs/src/test/java/org/killbill/billing/jaxrs/json/TestBundleTimelineJson.java
@@ -28,7 +28,6 @@ import org.killbill.billing.catalog.api.Currency;
 import org.killbill.billing.jaxrs.JaxrsTestSuiteNoDB;
 
 import com.google.common.collect.ImmutableList;
-import com.sun.org.apache.xpath.internal.operations.Bool;
 
 public class TestBundleTimelineJson extends JaxrsTestSuiteNoDB {
 
@@ -39,12 +38,12 @@ public class TestBundleTimelineJson extends JaxrsTestSuiteNoDB {
 
         final BundleJson bundleJson = createBundleWithSubscriptions();
         final InvoiceJson invoiceJson = createInvoice();
-        final PaymentJson paymentJson = createPayment(UUID.fromString(invoiceJson.getAccountId()),
+        final InvoicePaymentJson paymentJson = createPayment(UUID.fromString(invoiceJson.getAccountId()),
                                                                   UUID.fromString(invoiceJson.getInvoiceId()));
 
         final BundleTimelineJson bundleTimelineJson = new BundleTimelineJson(viewId,
                                                                              bundleJson,
-                                                                             ImmutableList.<PaymentJson>of(paymentJson),
+                                                                             ImmutableList.<InvoicePaymentJson>of(paymentJson),
                                                                              ImmutableList.<InvoiceJson>of(invoiceJson),
                                                                              reason);
 
@@ -82,24 +81,20 @@ public class TestBundleTimelineJson extends JaxrsTestSuiteNoDB {
                                      targetDate, invoiceNumber, balance, accountId.toString(), null, null, null, null);
     }
 
-    private PaymentJson createPayment(final UUID accountId, final UUID invoiceId) {
+    private InvoicePaymentJson createPayment(final UUID accountId, final UUID invoiceId) {
         final UUID paymentId = UUID.randomUUID();
         final Integer paymentNumber = 17;
-        final UUID paymentMethodId = UUID.randomUUID();
+        final String paymentExternalKey = UUID.randomUUID().toString();
         final BigDecimal authAmount = BigDecimal.TEN;
         final BigDecimal captureAmount = BigDecimal.ZERO;
         final BigDecimal purchasedAMount = BigDecimal.ZERO;
         final BigDecimal creditAmount = BigDecimal.ZERO;
         final BigDecimal refundAmount = BigDecimal.ZERO;
-        final DateTime paymentRequestedDate = clock.getUTCNow();
-        final DateTime paymentEffectiveDate = clock.getUTCNow();
-        final Integer retryCount = Integer.MAX_VALUE;
         final String currency = "USD";
-        final String status = UUID.randomUUID().toString();
-        final String gatewayErrorCode = "OK";
-        final String gatewayErrorMsg = "Excellent...";
-        return new PaymentJson(authAmount, captureAmount, purchasedAMount, creditAmount, refundAmount, Boolean.FALSE, accountId.toString(), invoiceId.toString(), paymentId.toString(), paymentNumber.toString(),
-                                     paymentMethodId.toString(), paymentRequestedDate, paymentEffectiveDate, retryCount, currency, status,
-                                     gatewayErrorCode, gatewayErrorMsg, null, null, null, null);
+
+        return new InvoicePaymentJson(invoiceId.toString(), accountId.toString(), paymentId.toString(), paymentNumber.toString(),
+                                      paymentExternalKey, authAmount, captureAmount, purchasedAMount, refundAmount, creditAmount, currency,
+                                      UUID.randomUUID().toString(),
+                                      null, null);
     }
 }
diff --git a/payment/src/main/java/org/killbill/billing/payment/control/InvoicePaymentControlPluginApi.java b/payment/src/main/java/org/killbill/billing/payment/control/InvoicePaymentControlPluginApi.java
index 76784c3..73357a6 100644
--- a/payment/src/main/java/org/killbill/billing/payment/control/InvoicePaymentControlPluginApi.java
+++ b/payment/src/main/java/org/killbill/billing/payment/control/InvoicePaymentControlPluginApi.java
@@ -79,7 +79,7 @@ public final class InvoicePaymentControlPluginApi implements PaymentControlPlugi
     /* Don't change value String for properties as they are referenced from jaxrs without the constants which are not accessible */
     public final static String PLUGIN_NAME = "__INVOICE_PAYMENT_CONTROL_PLUGIN__";
     public static final String PROP_IPCD_INVOICE_ID = "IPCD_INVOICE_ID";
-    public static final String PROP_IPCD_REFUND_IDS_WITH_AMOUNT_KEY = "IPCD_REF_IDS_AMOUNTS";
+    public static final String PROP_IPCD_REFUND_IDS_WITH_AMOUNT_KEY = "IPCD_REFUND_IDS_AMOUNTS";
     public static final String PROP_IPCD_REFUND_WITH_ADJUSTMENTS = "IPCD_REFUND_WITH_ADJUSTMENTS";
 
     private final PaymentConfig paymentConfig;
diff --git a/profiles/killbill/src/test/java/org/killbill/billing/jaxrs/TestAccount.java b/profiles/killbill/src/test/java/org/killbill/billing/jaxrs/TestAccount.java
index 982f688..2438903 100644
--- a/profiles/killbill/src/test/java/org/killbill/billing/jaxrs/TestAccount.java
+++ b/profiles/killbill/src/test/java/org/killbill/billing/jaxrs/TestAccount.java
@@ -32,11 +32,15 @@ import org.killbill.billing.client.model.Account;
 import org.killbill.billing.client.model.Accounts;
 import org.killbill.billing.client.model.AuditLog;
 import org.killbill.billing.client.model.CustomField;
+import org.killbill.billing.client.model.InvoicePayments;
 import org.killbill.billing.client.model.Payment;
 import org.killbill.billing.client.model.PaymentMethod;
 import org.killbill.billing.client.model.PaymentMethodPluginDetail;
+import org.killbill.billing.client.model.Payments;
 import org.killbill.billing.client.model.Refund;
+import org.killbill.billing.client.model.Refunds;
 import org.killbill.billing.client.model.Tag;
+import org.killbill.billing.invoice.api.InvoicePayment;
 import org.killbill.billing.util.api.AuditLevel;
 import org.testng.Assert;
 import org.testng.annotations.Test;
@@ -180,11 +184,11 @@ public class TestAccount extends TestJaxrsBase {
         final Account accountJson = createAccountWithPMBundleAndSubscriptionAndWaitForFirstInvoice();
 
         // Verify payments
-        final List<Payment> objFromJson = killBillClient.getPaymentsForAccount(accountJson.getAccountId());
+        final InvoicePayments objFromJson = killBillClient.getPaymentsForAccount(accountJson.getAccountId());
         Assert.assertEquals(objFromJson.size(), 1);
 
         // Verify refunds
-        final List<Refund> objRefundFromJson = killBillClient.getRefundsForAccount(accountJson.getAccountId());
+        final Refunds objRefundFromJson = killBillClient.getRefundsForAccount(accountJson.getAccountId());
         Assert.assertEquals(objRefundFromJson.size(), 0);
     }
 
diff --git a/profiles/killbill/src/test/java/org/killbill/billing/jaxrs/TestAccountTimeline.java b/profiles/killbill/src/test/java/org/killbill/billing/jaxrs/TestAccountTimeline.java
index 70c44ea..0ab8c47 100644
--- a/profiles/killbill/src/test/java/org/killbill/billing/jaxrs/TestAccountTimeline.java
+++ b/profiles/killbill/src/test/java/org/killbill/billing/jaxrs/TestAccountTimeline.java
@@ -33,13 +33,24 @@ import org.killbill.billing.client.model.Chargeback;
 import org.killbill.billing.client.model.Credit;
 import org.killbill.billing.client.model.EventSubscription;
 import org.killbill.billing.client.model.Invoice;
+import org.killbill.billing.client.model.InvoicePayment;
 import org.killbill.billing.client.model.Payment;
 import org.killbill.billing.client.model.Refund;
+import org.killbill.billing.client.model.Transaction;
+import org.killbill.billing.jaxrs.resources.JaxRsResourceBase;
+import org.killbill.billing.payment.api.DirectPayment;
+import org.killbill.billing.payment.api.DirectPaymentTransaction;
+import org.killbill.billing.payment.api.TransactionType;
 import org.killbill.billing.util.api.AuditLevel;
 import org.killbill.billing.util.audit.ChangeType;
 import org.testng.Assert;
 import org.testng.annotations.Test;
 
+import com.google.common.base.Function;
+import com.google.common.base.Predicate;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Iterables;
+
 public class TestAccountTimeline extends TestJaxrsBase {
 
     private static final String PAYMENT_REQUEST_PROCESSOR = "PaymentRequestProcessor";
@@ -87,7 +98,7 @@ public class TestAccountTimeline extends TestJaxrsBase {
         final Refund refund = new Refund();
         refund.setPaymentId(postedPayment.getPaymentId());
         refund.setAmount(refundAmount);
-        killBillClient.createRefund(refund, createdBy, reason, comment);
+        killBillClient.createInvoicePaymentRefund(refund, createdBy, reason, comment);
 
         // Add chargeback
         final BigDecimal chargebackAmount = BigDecimal.ONE;
@@ -114,26 +125,33 @@ public class TestAccountTimeline extends TestJaxrsBase {
         for (final AuditLevel auditLevel : AuditLevel.values()) {
             final AccountTimeline timeline = killBillClient.getAccountTimeline(accountId, auditLevel);
 
-            // Verify payments
             Assert.assertEquals(timeline.getPayments().size(), 1);
-            final Payment paymentJson = timeline.getPayments().get(0);
+            final InvoicePayment payment =  timeline.getPayments().get(0);
+
+            // Verify payments
+            final List<Transaction> purchaseTransactions  = getDirectPaymentTransactions(timeline.getPayments(), TransactionType.PURCHASE.toString());
+            Assert.assertEquals(purchaseTransactions.size(), 1);
+            final Transaction purchaseTransaction = purchaseTransactions.get(0);
 
             // Verify refunds
-            Assert.assertEquals(paymentJson.getRefunds().size(), 1);
-            final Refund refundJson = paymentJson.getRefunds().get(0);
-            Assert.assertEquals(refundJson.getPaymentId(), paymentJson.getPaymentId());
-            Assert.assertEquals(refundJson.getAmount().compareTo(refundAmount), 0);
+            final List<Transaction> refundTransactions  = getDirectPaymentTransactions(timeline.getPayments(), TransactionType.REFUND.toString());
+            Assert.assertEquals(refundTransactions.size(), 1);
+            final Transaction refundTransaction = refundTransactions.get(0);
+            Assert.assertEquals(refundTransaction.getPaymentId(), payment.getPaymentId());
+            Assert.assertEquals(refundTransaction.getAmount().compareTo(refundAmount), 0);
 
             // Verify chargebacks
-            Assert.assertEquals(paymentJson.getChargebacks().size(), 1);
-            final Chargeback chargebackJson = paymentJson.getChargebacks().get(0);
-            Assert.assertEquals(chargebackJson.getPaymentId(), paymentJson.getPaymentId());
-            Assert.assertEquals(chargebackJson.getAmount().compareTo(chargebackAmount), 0);
+            final List<Transaction> chargebackTransactions  = getDirectPaymentTransactions(timeline.getPayments(), TransactionType.CHARGEBACK.toString());
+            Assert.assertEquals(chargebackTransactions.size(), 1);
+            final Transaction chargebackTransaction = chargebackTransactions.get(0);
+            Assert.assertEquals(chargebackTransaction.getPaymentId(), payment.getPaymentId());
+            Assert.assertEquals(chargebackTransaction.getAmount().compareTo(chargebackAmount), 0);
 
             // Verify audits
-            final List<AuditLog> paymentAuditLogs = paymentJson.getAuditLogs();
-            final List<AuditLog> refundAuditLogs = refundJson.getAuditLogs();
-            final List<AuditLog> chargebackAuditLogs = chargebackJson.getAuditLogs();
+            final List<AuditLog> paymentAuditLogs = purchaseTransaction.getAuditLogs();
+            final List<AuditLog> refundAuditLogs = refundTransaction.getAuditLogs();
+            final List<AuditLog> chargebackAuditLogs = chargebackTransaction.getAuditLogs();
+
             if (AuditLevel.NONE.equals(auditLevel)) {
                 // Audits for payments
                 Assert.assertEquals(paymentAuditLogs.size(), 0);
diff --git a/profiles/killbill/src/test/java/org/killbill/billing/jaxrs/TestChargeback.java b/profiles/killbill/src/test/java/org/killbill/billing/jaxrs/TestChargeback.java
index 8c9a4d3..78490d6 100644
--- a/profiles/killbill/src/test/java/org/killbill/billing/jaxrs/TestChargeback.java
+++ b/profiles/killbill/src/test/java/org/killbill/billing/jaxrs/TestChargeback.java
@@ -181,7 +181,7 @@ public class TestChargeback extends TestJaxrsBase {
     }
 
     private Payment getPayment(final Invoice invoice) throws KillBillClientException {
-        final List<Payment> payments = killBillClient.getPaymentsForInvoice(invoice.getInvoiceId());
+        final List<Payment> payments = null; //killBillClient.getPaymentsForInvoice(invoice.getInvoiceId());
         assertNotNull(payments);
         assertEquals(payments.size(), 1);
         return payments.get(0);
diff --git a/profiles/killbill/src/test/java/org/killbill/billing/jaxrs/TestExceptions.java b/profiles/killbill/src/test/java/org/killbill/billing/jaxrs/TestExceptions.java
index 3105271..cede276 100644
--- a/profiles/killbill/src/test/java/org/killbill/billing/jaxrs/TestExceptions.java
+++ b/profiles/killbill/src/test/java/org/killbill/billing/jaxrs/TestExceptions.java
@@ -21,6 +21,7 @@ package org.killbill.billing.jaxrs;
 import java.math.BigDecimal;
 import java.util.List;
 
+import org.killbill.billing.client.model.InvoicePayment;
 import org.testng.Assert;
 import org.testng.annotations.Test;
 
@@ -38,7 +39,7 @@ public class TestExceptions extends TestJaxrsBase {
     @Test(groups = "slow")
     public void testExceptionMapping() throws Exception {
         final Account account = createAccountWithPMBundleAndSubscriptionAndWaitForFirstInvoice();
-        final List<Payment> payments = killBillClient.getPaymentsForAccount(account.getAccountId());
+        final List<InvoicePayment> payments = killBillClient.getPaymentsForAccount(account.getAccountId());
         final Chargeback input = new Chargeback();
         input.setAmount(BigDecimal.TEN.negate());
         input.setPaymentId(payments.get(0).getPaymentId());
diff --git a/profiles/killbill/src/test/java/org/killbill/billing/jaxrs/TestInvoice.java b/profiles/killbill/src/test/java/org/killbill/billing/jaxrs/TestInvoice.java
index 041463c..f128262 100644
--- a/profiles/killbill/src/test/java/org/killbill/billing/jaxrs/TestInvoice.java
+++ b/profiles/killbill/src/test/java/org/killbill/billing/jaxrs/TestInvoice.java
@@ -29,6 +29,8 @@ import org.killbill.billing.client.model.Account;
 import org.killbill.billing.client.model.AuditLog;
 import org.killbill.billing.client.model.Invoice;
 import org.killbill.billing.client.model.InvoiceItem;
+import org.killbill.billing.client.model.InvoicePayment;
+import org.killbill.billing.client.model.InvoicePayments;
 import org.killbill.billing.client.model.Invoices;
 import org.killbill.billing.client.model.Payment;
 import org.killbill.billing.client.model.PaymentMethod;
@@ -51,7 +53,7 @@ public class TestInvoice extends TestJaxrsBase {
 
         final Account accountJson = createAccountWithPMBundleAndSubscriptionAndWaitForFirstInvoice();
 
-        final List<Invoice> invoices = null; // STEPH killBillClient.getInvoicesForAccount(accountJson.getAccountId(), true, AuditLevel.FULL);
+        final List<Invoice> invoices = killBillClient.getInvoicesForAccount(accountJson.getAccountId(), true, false, AuditLevel.FULL);
         assertEquals(invoices.size(), 2);
         for (final Invoice invoiceJson : invoices) {
             Assert.assertEquals(invoiceJson.getAuditLogs().size(), 1);
@@ -102,13 +104,12 @@ public class TestInvoice extends TestJaxrsBase {
         assertEquals(invoices.size(), 2);
 
         for (final Invoice cur : invoices) {
-            final List<Payment> objFromJson = killBillClient.getPaymentsForInvoice(cur.getInvoiceId());
-
+            final InvoicePayments objFromJson = killBillClient.getInvoicePayment(cur.getInvoiceId());
             if (cur.getAmount().compareTo(BigDecimal.ZERO) == 0) {
                 assertEquals(objFromJson.size(), 0);
             } else {
                 assertEquals(objFromJson.size(), 1);
-                assertEquals(cur.getAmount().compareTo(objFromJson.get(0).getAmount()), 0);
+                assertEquals(cur.getAmount().compareTo(objFromJson.get(0).getPurchasedAmount()), 0);
             }
         }
     }
@@ -153,14 +154,14 @@ public class TestInvoice extends TestJaxrsBase {
                 continue;
             }
 
-            // CREATE INSTA PAYMENT
-            final Payment payment = new Payment();
-            payment.setAccountId(accountJson.getAccountId());
-            payment.setInvoiceId(cur.getInvoiceId());
-            payment.setAmount(cur.getBalance());
-            final List<Payment> objFromJson = killBillClient.createPayment(payment, false, createdBy, reason, comment);
+            // CREATE PAYMENT
+            final InvoicePayment invoicePayment = new InvoicePayment();
+            invoicePayment.setPurchasedAmount(cur.getBalance());
+            invoicePayment.setAccountId(accountJson.getAccountId());
+            invoicePayment.setTargetInvoiceId(cur.getInvoiceId());
+            final InvoicePayments objFromJson = null; // STEPH killBillClient.createInvoicePayment(invoicePayment, true, createdBy, reason, comment);
             assertEquals(objFromJson.size(), 1);
-            assertEquals(cur.getBalance().compareTo(objFromJson.get(0).getAmount()), 0);
+            assertEquals(cur.getBalance().compareTo(objFromJson.get(0).getPurchasedAmount()), 0);
         }
     }
 
@@ -168,8 +169,8 @@ public class TestInvoice extends TestJaxrsBase {
     public void testExternalPayment() throws Exception {
         final Account accountJson = createAccountNoPMBundleAndSubscriptionAndWaitForFirstInvoice();
 
-        // Verify we didn't get any payment
-        final List<Payment> noPaymentsFromJson = killBillClient.getPaymentsForAccount(accountJson.getAccountId());
+        // Verify we didn't get any invoicePayment
+        final List<InvoicePayment> noPaymentsFromJson = killBillClient.getPaymentsForAccount(accountJson.getAccountId());
         assertEquals(noPaymentsFromJson.size(), 1);
         final UUID initialPaymentId = noPaymentsFromJson.get(0).getPaymentId();
 
@@ -179,16 +180,15 @@ public class TestInvoice extends TestJaxrsBase {
         assertEquals(invoices.size(), 2);
         final UUID invoiceId = invoices.get(1).getInvoiceId();
 
-        // Post an external payment
-        final BigDecimal paidAmount = BigDecimal.TEN;
-        final Payment payment = new Payment();
-        payment.setAmount(BigDecimal.TEN);
-        payment.setAccountId(accountJson.getAccountId());
-        payment.setInvoiceId(invoiceId);
-        killBillClient.createPayment(payment, true, createdBy, reason, comment);
+        // Post an external invoicePayment
+        final InvoicePayment invoicePayment = new InvoicePayment();
+        invoicePayment.setPurchasedAmount(BigDecimal.TEN);
+        invoicePayment.setAccountId(accountJson.getAccountId());
+        invoicePayment.setTargetInvoiceId(invoiceId);
+        killBillClient.createInvoicePayment(invoicePayment, true, createdBy, reason, comment);
 
-        // Verify we indeed got the payment
-        final List<Payment> paymentsFromJson = killBillClient.getPaymentsForAccount(accountJson.getAccountId());
+        // Verify we indeed got the invoicePayment
+        final List<InvoicePayment> paymentsFromJson = killBillClient.getPaymentsForAccount(accountJson.getAccountId());
         assertEquals(paymentsFromJson.size(), 2);
         Payment secondPayment = null;
         for (final Payment cur : paymentsFromJson) {
@@ -199,7 +199,6 @@ public class TestInvoice extends TestJaxrsBase {
         }
         assertNotNull(secondPayment);
 
-        assertEquals(secondPayment.getPaidAmount().compareTo(paidAmount), 0);
 
         // Check the PaymentMethod from paymentMethodId returned in the Payment object
         final UUID paymentMethodId = secondPayment.getPaymentMethodId();
diff --git a/profiles/killbill/src/test/java/org/killbill/billing/jaxrs/TestInvoicePayment.java b/profiles/killbill/src/test/java/org/killbill/billing/jaxrs/TestInvoicePayment.java
new file mode 100644
index 0000000..6cb3db0
--- /dev/null
+++ b/profiles/killbill/src/test/java/org/killbill/billing/jaxrs/TestInvoicePayment.java
@@ -0,0 +1,271 @@
+/*
+ * Copyright 2010-2013 Ning, Inc.
+ * Copyright 2014 Groupon, Inc
+ * Copyright 2014 The Billing Project, LLC
+ *
+ * The Billing Project 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 java.math.RoundingMode;
+import java.util.List;
+import java.util.UUID;
+
+import org.killbill.billing.client.KillBillClientException;
+import org.killbill.billing.client.model.Account;
+import org.killbill.billing.client.model.Invoice;
+import org.killbill.billing.client.model.InvoiceItem;
+import org.killbill.billing.client.model.InvoicePayment;
+import org.killbill.billing.client.model.InvoicePayments;
+import org.killbill.billing.client.model.Payment;
+import org.killbill.billing.client.model.PaymentMethod;
+import org.killbill.billing.client.model.Payments;
+import org.killbill.billing.client.model.Refund;
+import org.killbill.billing.client.model.Transaction;
+import org.killbill.billing.payment.api.TransactionType;
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+import com.google.common.collect.ImmutableList;
+
+public class TestInvoicePayment extends TestJaxrsBase {
+
+    @Test(groups = "slow")
+    public void testRetrievePayment() throws Exception {
+        final InvoicePayment paymentJson = setupScenarioWithPayment();
+        final Payment retrievedPaymentJson = killBillClient.getPayment(paymentJson.getPaymentId(), false);
+        Assert.assertTrue(retrievedPaymentJson.equals((Payment) paymentJson));
+    }
+
+    @Test(groups = "slow", description = "Can create a full refund with no adjustment")
+    public void testFullRefundWithNoAdjustment() throws Exception {
+        final InvoicePayment invoicePaymentJson = setupScenarioWithPayment();
+
+        // Issue a refund for the full amount
+        final BigDecimal refundAmount = invoicePaymentJson.getPurchasedAmount();
+        final BigDecimal expectedInvoiceBalance = refundAmount;
+
+        // Post and verify the refund
+        final Refund refund = new Refund();
+        refund.setPaymentId(invoicePaymentJson.getPaymentId());
+        refund.setAmount(refundAmount);
+        final Payment paymentAfterRefundJson = killBillClient.createInvoicePaymentRefund(refund, createdBy, reason, comment);
+        verifyRefund(invoicePaymentJson, paymentAfterRefundJson, refundAmount);
+
+        // Verify the invoice balance
+        verifyInvoice(invoicePaymentJson, expectedInvoiceBalance);
+    }
+
+    @Test(groups = "slow", description = "Can create a partial refund with no adjustment")
+    public void testPartialRefundWithNoAdjustment() throws Exception {
+        final InvoicePayment paymentJson = setupScenarioWithPayment();
+
+        // Issue a refund for a fraction of the amount
+        final BigDecimal refundAmount = getFractionOfAmount(paymentJson.getPurchasedAmount());
+        final BigDecimal expectedInvoiceBalance = refundAmount;
+
+        // Post and verify the refund
+        final Refund refund = new Refund();
+        refund.setPaymentId(paymentJson.getPaymentId());
+        refund.setAmount(refundAmount);
+        final Payment paymentAfterRefundJson = killBillClient.createInvoicePaymentRefund(refund, createdBy, reason, comment);
+        verifyRefund(paymentJson, paymentAfterRefundJson, refundAmount);
+
+        // Verify the invoice balance
+        verifyInvoice(paymentJson, expectedInvoiceBalance);
+    }
+
+    @Test(groups = "slow", description = "Can create a full refund with invoice adjustment")
+    public void testFullRefundWithInvoiceAdjustment() throws Exception {
+        final InvoicePayment paymentJson = setupScenarioWithPayment();
+
+        // Issue a refund for the full amount
+        final BigDecimal refundAmount = paymentJson.getPurchasedAmount();
+        final BigDecimal expectedInvoiceBalance = BigDecimal.ZERO;
+
+        // Post and verify the refund
+        final Refund refund = new Refund();
+        refund.setPaymentId(paymentJson.getPaymentId());
+        refund.setAmount(refundAmount);
+        refund.setAdjusted(true);
+        final Payment paymentAfterRefundJson = killBillClient.createInvoicePaymentRefund(refund, createdBy, reason, comment);
+        verifyRefund(paymentJson, paymentAfterRefundJson, refundAmount);
+
+        // Verify the invoice balance
+        verifyInvoice(paymentJson, expectedInvoiceBalance);
+    }
+
+    @Test(groups = "slow", description = "Can create a partial refund with invoice adjustment")
+    public void testPartialRefundWithInvoiceAdjustment() throws Exception {
+        final InvoicePayment paymentJson = setupScenarioWithPayment();
+
+        // Issue a refund for a fraction of the amount
+        final BigDecimal refundAmount = getFractionOfAmount(paymentJson.getPurchasedAmount());
+        final BigDecimal expectedInvoiceBalance = BigDecimal.ZERO;
+
+        // Post and verify the refund
+        final Refund refund = new Refund();
+        refund.setPaymentId(paymentJson.getPaymentId());
+        refund.setAmount(refundAmount);
+        refund.setAdjusted(true);
+        final Payment paymentAfterRefundJson = killBillClient.createInvoicePaymentRefund(refund, createdBy, reason, comment);
+        verifyRefund(paymentJson, paymentAfterRefundJson, refundAmount);
+
+        // Verify the invoice balance
+        verifyInvoice(paymentJson, expectedInvoiceBalance);
+    }
+
+    @Test(groups = "slow", description = "Can create a full refund with invoice item adjustment")
+    public void testRefundWithFullInvoiceItemAdjustment() throws Exception {
+        final InvoicePayment paymentJson = setupScenarioWithPayment();
+
+        // Get the individual items for the invoice
+        final Invoice invoice = killBillClient.getInvoice(paymentJson.getTargetInvoiceId(), true);
+        final InvoiceItem itemToAdjust = invoice.getItems().get(0);
+
+        // Issue a refund for the full amount
+        final BigDecimal refundAmount = itemToAdjust.getAmount();
+        final BigDecimal expectedInvoiceBalance = BigDecimal.ZERO;
+
+        // Post and verify the refund
+        final Refund refund = new Refund();
+        refund.setPaymentId(paymentJson.getPaymentId());
+        refund.setAmount(refundAmount);
+        refund.setAdjusted(true);
+        final InvoiceItem adjustment = new InvoiceItem();
+        adjustment.setInvoiceItemId(itemToAdjust.getInvoiceItemId());
+        /* null amount means full adjustment for that item */
+        refund.setAdjustments(ImmutableList.<InvoiceItem>of(adjustment));
+        final Payment paymentAfterRefundJson = killBillClient.createInvoicePaymentRefund(refund, createdBy, reason, comment);
+        verifyRefund(paymentJson, paymentAfterRefundJson, refundAmount);
+
+        // Verify the invoice balance
+        verifyInvoice(paymentJson, expectedInvoiceBalance);
+    }
+
+    @Test(groups = "slow", description = "Can create a partial refund with invoice item adjustment")
+    public void testPartialRefundWithInvoiceItemAdjustment() throws Exception {
+        final InvoicePayment paymentJson = setupScenarioWithPayment();
+
+        // Get the individual items for the invoice
+        final Invoice invoice = killBillClient.getInvoice(paymentJson.getTargetInvoiceId(), true);
+        final InvoiceItem itemToAdjust = invoice.getItems().get(0);
+
+        // Issue a refund for a fraction of the amount
+        final BigDecimal refundAmount = getFractionOfAmount(itemToAdjust.getAmount());
+        final BigDecimal expectedInvoiceBalance = BigDecimal.ZERO;
+
+        // Post and verify the refund
+        final Refund refund = new Refund();
+        refund.setPaymentId(paymentJson.getPaymentId());
+        refund.setAdjusted(true);
+        final InvoiceItem adjustment = new InvoiceItem();
+        adjustment.setInvoiceItemId(itemToAdjust.getInvoiceItemId());
+        adjustment.setAmount(refundAmount);
+        refund.setAdjustments(ImmutableList.<InvoiceItem>of(adjustment));
+        final Payment paymentAfterRefundJson = killBillClient.createInvoicePaymentRefund(refund, createdBy, reason, comment);
+        verifyRefund(paymentJson, paymentAfterRefundJson, refundAmount);
+
+        // Verify the invoice balance
+        verifyInvoice(paymentJson, expectedInvoiceBalance);
+    }
+
+    @Test(groups = "slow", description = "Can paginate through all payments and refunds")
+    public void testPaymentsAndRefundsPagination() throws Exception {
+        InvoicePayment lastPayment = setupScenarioWithPayment();
+
+        for (int i = 0; i < 5; i++) {
+            final Refund refund = new Refund();
+            refund.setPaymentId(lastPayment.getPaymentId());
+            refund.setAmount(lastPayment.getPurchasedAmount());
+            killBillClient.createInvoicePaymentRefund(refund, createdBy, reason, comment);
+
+            final InvoicePayment invoicePayment = new InvoicePayment();
+            invoicePayment.setPurchasedAmount(lastPayment.getPurchasedAmount());
+            invoicePayment.setAccountId(lastPayment.getAccountId());
+            invoicePayment.setTargetInvoiceId(lastPayment.getTargetInvoiceId());
+            final InvoicePayment payment = killBillClient.createInvoicePayment(invoicePayment, true, createdBy, reason, comment);
+            lastPayment = payment;
+        }
+
+        final InvoicePayments allPayments = killBillClient.getInvoicePaymentsForAccount(lastPayment.getAccountId());
+        Assert.assertEquals(allPayments.size(), 6);
+
+        final List<Transaction> objRefundFromJson = getDirectPaymentTransactions(allPayments, TransactionType.REFUND.toString());
+        Assert.assertEquals(objRefundFromJson.size(), 5);
+
+        Payments paymentsPage = killBillClient.getPayments(0L, 1L);
+        for (int i = 0; i < 6; i++) {
+            Assert.assertNotNull(paymentsPage);
+            Assert.assertEquals(paymentsPage.size(), 1);
+            Assert.assertEquals(paymentsPage.get(0), allPayments.get(i));
+            paymentsPage = paymentsPage.getNext();
+        }
+        Assert.assertNull(paymentsPage);
+    }
+
+    private BigDecimal getFractionOfAmount(final BigDecimal amount) {
+        return amount.divide(BigDecimal.TEN).setScale(2, BigDecimal.ROUND_HALF_UP);
+    }
+
+    private InvoicePayment setupScenarioWithPayment() throws Exception {
+        final Account accountJson = createAccountWithPMBundleAndSubscriptionAndWaitForFirstInvoice();
+
+        final List<InvoicePayment> paymentsForAccount = killBillClient.getPaymentsForAccount(accountJson.getAccountId());
+        Assert.assertEquals(paymentsForAccount.size(), 1);
+
+        final InvoicePayment paymentJson = paymentsForAccount.get(0);
+
+        // Check the PaymentMethod from paymentMethodId returned in the Payment object
+        final UUID paymentMethodId = paymentJson.getPaymentMethodId();
+        final PaymentMethod paymentMethodJson = killBillClient.getPaymentMethod(paymentMethodId, true);
+        Assert.assertEquals(paymentMethodJson.getPaymentMethodId(), paymentMethodId);
+        Assert.assertEquals(paymentMethodJson.getAccountId(), accountJson.getAccountId());
+
+        // Verify the refunds
+        final List<Transaction> objRefundFromJson = getDirectPaymentTransactions(paymentsForAccount, TransactionType.REFUND.toString());
+        Assert.assertEquals(objRefundFromJson.size(), 0);
+        return paymentJson;
+    }
+
+    private void verifyRefund(final InvoicePayment paymentJson, final Payment paymentAfterRefund, final BigDecimal refundAmount) throws KillBillClientException {
+
+        final List<Transaction> transactions = getDirectPaymentTransactions(ImmutableList.of(paymentAfterRefund), TransactionType.REFUND.toString());
+        Assert.assertEquals(transactions.size(), 1);
+
+        final Transaction refund = transactions.get(0);
+        Assert.assertEquals(refund.getPaymentId(), paymentJson.getPaymentId());
+        Assert.assertEquals(refund.getAmount().setScale(2, RoundingMode.HALF_UP), refundAmount.setScale(2, RoundingMode.HALF_UP));
+        Assert.assertEquals(refund.getCurrency(), DEFAULT_CURRENCY);
+        Assert.assertEquals(refund.getStatus(), "SUCCESS");
+        Assert.assertEquals(refund.getEffectiveDate().getYear(), clock.getUTCNow().getYear());
+        Assert.assertEquals(refund.getEffectiveDate().getMonthOfYear(), clock.getUTCNow().getMonthOfYear());
+        Assert.assertEquals(refund.getEffectiveDate().getDayOfMonth(), clock.getUTCNow().getDayOfMonth());
+
+        // Verify the refund via the payment API
+        final Payment retrievedPaymentJson = killBillClient.getPayment(paymentJson.getPaymentId(), true);
+        Assert.assertEquals(retrievedPaymentJson.getPaymentId(), paymentJson.getPaymentId());
+        Assert.assertEquals(retrievedPaymentJson.getPurchasedAmount().setScale(2, RoundingMode.HALF_UP), paymentJson.getPurchasedAmount().setScale(2, RoundingMode.HALF_UP));
+        Assert.assertEquals(retrievedPaymentJson.getAccountId(), paymentJson.getAccountId());
+        Assert.assertEquals(retrievedPaymentJson.getCurrency(), paymentJson.getCurrency());
+        Assert.assertEquals(retrievedPaymentJson.getPaymentMethodId(), paymentJson.getPaymentMethodId());
+    }
+
+    private void verifyInvoice(final InvoicePayment paymentJson, final BigDecimal expectedInvoiceBalance) throws KillBillClientException {
+        final Invoice invoiceJson = killBillClient.getInvoice(paymentJson.getTargetInvoiceId());
+        Assert.assertEquals(invoiceJson.getBalance().setScale(2, BigDecimal.ROUND_HALF_UP),
+                            expectedInvoiceBalance.setScale(2, BigDecimal.ROUND_HALF_UP));
+    }
+}
diff --git a/profiles/killbill/src/test/java/org/killbill/billing/jaxrs/TestJaxrsBase.java b/profiles/killbill/src/test/java/org/killbill/billing/jaxrs/TestJaxrsBase.java
index d9f174b..53a52b6 100644
--- a/profiles/killbill/src/test/java/org/killbill/billing/jaxrs/TestJaxrsBase.java
+++ b/profiles/killbill/src/test/java/org/killbill/billing/jaxrs/TestJaxrsBase.java
@@ -20,6 +20,7 @@ package org.killbill.billing.jaxrs;
 
 import java.util.EventListener;
 import java.util.Iterator;
+import java.util.List;
 import java.util.Map;
 
 import javax.inject.Inject;
@@ -33,7 +34,10 @@ import org.killbill.billing.GuicyKillbillTestWithEmbeddedDBModule;
 import org.killbill.billing.api.TestApiListener;
 import org.killbill.billing.client.KillBillClient;
 import org.killbill.billing.client.KillBillHttpClient;
+import org.killbill.billing.client.model.InvoicePayment;
+import org.killbill.billing.client.model.Payment;
 import org.killbill.billing.client.model.Tenant;
+import org.killbill.billing.client.model.Transaction;
 import org.killbill.billing.invoice.api.InvoiceNotifier;
 import org.killbill.billing.invoice.glue.DefaultInvoiceModule;
 import org.killbill.billing.invoice.notification.NullInvoiceNotifier;
@@ -58,8 +62,11 @@ import org.testng.annotations.BeforeClass;
 import org.testng.annotations.BeforeMethod;
 import org.testng.annotations.BeforeSuite;
 
+import com.google.common.base.Function;
+import com.google.common.base.Predicate;
 import com.google.common.collect.ImmutableList;
 import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.Iterables;
 import com.google.inject.Module;
 import com.google.inject.util.Modules;
 
@@ -249,4 +256,19 @@ public class TestJaxrsBase extends KillbillClient {
         } catch (final Exception ignored) {
         }
     }
+
+    protected static <T extends Payment>  List<Transaction> getDirectPaymentTransactions(final List<T> payments, final String transactionType) {
+        return ImmutableList.copyOf(Iterables.concat(Iterables.transform(payments, new Function<T, Iterable<Transaction>>() {
+            @Override
+            public Iterable<Transaction> apply(final T input) {
+                return Iterables.filter(input.getTransactions(), new Predicate<Transaction>() {
+                    @Override
+                    public boolean apply(final Transaction input) {
+                        return input.getTransactionType().equals(transactionType);
+                    }
+                });
+            }
+        })));
+    }
+
 }
diff --git a/profiles/killbill/src/test/java/org/killbill/billing/jaxrs/TestOverdue.java b/profiles/killbill/src/test/java/org/killbill/billing/jaxrs/TestOverdue.java
index 958eec8..d9d9898 100644
--- a/profiles/killbill/src/test/java/org/killbill/billing/jaxrs/TestOverdue.java
+++ b/profiles/killbill/src/test/java/org/killbill/billing/jaxrs/TestOverdue.java
@@ -24,6 +24,7 @@ import java.util.List;
 
 import org.killbill.billing.client.model.Account;
 import org.killbill.billing.client.model.Invoice;
+import org.killbill.billing.client.model.InvoicePayment;
 import org.killbill.billing.client.model.Invoices;
 import org.killbill.billing.client.model.Payment;
 import org.testng.Assert;
@@ -72,11 +73,12 @@ public class TestOverdue extends TestJaxrsBase {
         }).reverse().sortedCopy(invoicesForAccount);
         for (final Invoice invoice : mostRecentInvoiceFirst) {
             if (invoice.getBalance().compareTo(BigDecimal.ZERO) > 0) {
-                final Payment payment = new Payment();
-                payment.setAccountId(accountJson.getAccountId());
-                payment.setInvoiceId(invoice.getInvoiceId());
-                payment.setAmount(invoice.getBalance());
-                killBillClient.createPayment(payment, true, createdBy, reason, comment);
+
+                final InvoicePayment invoicePayment = new InvoicePayment();
+                invoicePayment.setPurchasedAmount(invoice.getAmount());
+                invoicePayment.setAccountId(accountJson.getAccountId());
+                invoicePayment.setTargetInvoiceId(invoice.getInvoiceId());
+                killBillClient.createInvoicePayment(invoicePayment, true, createdBy, reason, comment);
             }
         }
 
diff --git a/profiles/killbill/src/test/java/org/killbill/billing/jaxrs/TestPayment.java b/profiles/killbill/src/test/java/org/killbill/billing/jaxrs/TestPayment.java
index bb38545..6ce2786 100644
--- a/profiles/killbill/src/test/java/org/killbill/billing/jaxrs/TestPayment.java
+++ b/profiles/killbill/src/test/java/org/killbill/billing/jaxrs/TestPayment.java
@@ -1,5 +1,4 @@
 /*
- * Copyright 2010-2013 Ning, Inc.
  * Copyright 2014 Groupon, Inc
  * Copyright 2014 The Billing Project, LLC
  *
@@ -19,275 +18,135 @@
 package org.killbill.billing.jaxrs;
 
 import java.math.BigDecimal;
-import java.math.RoundingMode;
-import java.util.List;
 import java.util.UUID;
 
+import javax.annotation.Nullable;
+
 import org.killbill.billing.client.KillBillClientException;
 import org.killbill.billing.client.model.Account;
-import org.killbill.billing.client.model.Invoice;
-import org.killbill.billing.client.model.InvoiceItem;
+import org.killbill.billing.client.model.InvoicePayments;
 import org.killbill.billing.client.model.Payment;
 import org.killbill.billing.client.model.PaymentMethod;
+import org.killbill.billing.client.model.PaymentMethodPluginDetail;
 import org.killbill.billing.client.model.Payments;
-import org.killbill.billing.client.model.Refund;
-import org.killbill.billing.client.model.Refunds;
-import org.killbill.billing.payment.api.RefundStatus;
+import org.killbill.billing.client.model.Transaction;
 import org.testng.Assert;
 import org.testng.annotations.Test;
 
-import com.google.common.collect.ImmutableList;
+import com.google.common.base.Objects;
 
 public class TestPayment extends TestJaxrsBase {
 
     @Test(groups = "slow")
-    public void testRetrievePayment() throws Exception {
-        final Payment paymentJson = setupScenarioWithPayment();
-
-        final Payment retrievedPaymentJson = killBillClient.getPayment(paymentJson.getPaymentId(), false);
-        Assert.assertEquals(retrievedPaymentJson, paymentJson);
-    }
-
-    @Test(groups = "slow", description = "Can create a full refund with no adjustment")
-    public void testFullRefundWithNoAdjustment() throws Exception {
-        final Payment paymentJson = setupScenarioWithPayment();
-
-        // Issue a refund for the full amount
-        final BigDecimal refundAmount = paymentJson.getAmount();
-        final BigDecimal expectedInvoiceBalance = refundAmount;
-
-        // Post and verify the refund
-        final Refund refund = new Refund();
-        refund.setPaymentId(paymentJson.getPaymentId());
-        refund.setAmount(refundAmount);
-        final Refund refundJsonCheck = killBillClient.createRefund(refund, createdBy, reason, comment);
-        verifyRefund(paymentJson, refundJsonCheck, refundAmount);
-
-        // Verify the invoice balance
-        verifyInvoice(paymentJson, expectedInvoiceBalance);
-    }
-
-    @Test(groups = "slow", description = "Can create a partial refund with no adjustment")
-    public void testPartialRefundWithNoAdjustment() throws Exception {
-        final Payment paymentJson = setupScenarioWithPayment();
-
-        // Issue a refund for a fraction of the amount
-        final BigDecimal refundAmount = getFractionOfAmount(paymentJson.getAmount());
-        final BigDecimal expectedInvoiceBalance = refundAmount;
-
-        // Post and verify the refund
-        final Refund refund = new Refund();
-        refund.setPaymentId(paymentJson.getPaymentId());
-        refund.setAmount(refundAmount);
-        final Refund refundJsonCheck = killBillClient.createRefund(refund, createdBy, reason, comment);
-        verifyRefund(paymentJson, refundJsonCheck, refundAmount);
-
-        // Verify the invoice balance
-        verifyInvoice(paymentJson, expectedInvoiceBalance);
-    }
+    public void testCreateRetrievePayment() throws Exception {
+        final Account account = createAccountWithDefaultPaymentMethod();
+        testCreateRetrievePayment(account, null, UUID.randomUUID().toString(), 1);
 
-    @Test(groups = "slow", description = "Can create a full refund with invoice adjustment")
-    public void testFullRefundWithInvoiceAdjustment() throws Exception {
-        final Payment paymentJson = setupScenarioWithPayment();
-
-        // Issue a refund for the full amount
-        final BigDecimal refundAmount = paymentJson.getAmount();
-        final BigDecimal expectedInvoiceBalance = BigDecimal.ZERO;
-
-        // Post and verify the refund
-        final Refund refund = new Refund();
-        refund.setPaymentId(paymentJson.getPaymentId());
-        refund.setAmount(refundAmount);
-        refund.setAdjusted(true);
-        final Refund refundJsonCheck = killBillClient.createRefund(refund, createdBy, reason, comment);
-        verifyRefund(paymentJson, refundJsonCheck, refundAmount);
-
-        // Verify the invoice balance
-        verifyInvoice(paymentJson, expectedInvoiceBalance);
+        final PaymentMethod paymentMethodJson = new PaymentMethod(null, account.getAccountId(), false, PLUGIN_NAME, new PaymentMethodPluginDetail());
+        final PaymentMethod nonDefaultPaymentMethod = killBillClient.createPaymentMethod(paymentMethodJson, createdBy, reason, comment);
+        testCreateRetrievePayment(account, nonDefaultPaymentMethod.getPaymentMethodId(), UUID.randomUUID().toString(), 2);
     }
 
-    @Test(groups = "slow", description = "Can create a partial refund with invoice adjustment")
-    public void testPartialRefundWithInvoiceAdjustment() throws Exception {
-        final Payment paymentJson = setupScenarioWithPayment();
-
-        // Issue a refund for a fraction of the amount
-        final BigDecimal refundAmount = getFractionOfAmount(paymentJson.getAmount());
-        final BigDecimal expectedInvoiceBalance = BigDecimal.ZERO;
-
-        // Post and verify the refund
-        final Refund refund = new Refund();
-        refund.setPaymentId(paymentJson.getPaymentId());
-        refund.setAmount(refundAmount);
-        refund.setAdjusted(true);
-        final Refund refundJsonCheck = killBillClient.createRefund(refund, createdBy, reason, comment);
-        verifyRefund(paymentJson, refundJsonCheck, refundAmount);
-
-        // Verify the invoice balance
-        verifyInvoice(paymentJson, expectedInvoiceBalance);
+    public void testCreateRetrievePayment(final Account account, @Nullable final UUID paymentMethodId,
+                                          final String PaymentExternalKey, final int PaymentNb) throws Exception {
+        // Authorization
+        final String authTransactionExternalKey = UUID.randomUUID().toString();
+        final Transaction authTransaction = new Transaction();
+        authTransaction.setAmount(BigDecimal.TEN);
+        authTransaction.setCurrency(account.getCurrency());
+        authTransaction.setPaymentExternalKey(PaymentExternalKey);
+        authTransaction.setTransactionExternalKey(authTransactionExternalKey);
+        authTransaction.setTransactionType("AUTHORIZE");
+        final Payment authPayment = killBillClient.createPayment(account.getAccountId(), paymentMethodId, authTransaction, createdBy, reason, comment);
+        verifyPayment(account, paymentMethodId, authPayment, PaymentExternalKey, authTransactionExternalKey,
+                            BigDecimal.TEN, BigDecimal.ZERO, BigDecimal.ZERO, 1, PaymentNb);
+
+        // Capture 1
+        final String capture1TransactionExternalKey = UUID.randomUUID().toString();
+        final Transaction captureTransaction = new Transaction();
+        captureTransaction.setPaymentId(authPayment.getPaymentId());
+        captureTransaction.setAmount(BigDecimal.ONE);
+        captureTransaction.setCurrency(account.getCurrency());
+        captureTransaction.setPaymentExternalKey(PaymentExternalKey);
+        captureTransaction.setTransactionExternalKey(capture1TransactionExternalKey);
+        final Payment capturedPayment1 = killBillClient.captureAuthorization(captureTransaction, createdBy, reason, comment);
+        verifyPayment(account, paymentMethodId, capturedPayment1, PaymentExternalKey, authTransactionExternalKey,
+                            BigDecimal.TEN, BigDecimal.ONE, BigDecimal.ZERO, 2, PaymentNb);
+        verifyPaymentTransaction(authPayment.getPaymentId(), capturedPayment1.getTransactions().get(1),
+                                       PaymentExternalKey, capture1TransactionExternalKey,
+                                       account, captureTransaction.getAmount(), "CAPTURE");
+
+        // Capture 2
+        final String capture2TransactionExternalKey = UUID.randomUUID().toString();
+        captureTransaction.setTransactionExternalKey(capture2TransactionExternalKey);
+        final Payment capturedPayment2 = killBillClient.captureAuthorization(captureTransaction, createdBy, reason, comment);
+        verifyPayment(account, paymentMethodId, capturedPayment2, PaymentExternalKey, authTransactionExternalKey,
+                            BigDecimal.TEN, new BigDecimal("2"), BigDecimal.ZERO, 3, PaymentNb);
+        verifyPaymentTransaction(authPayment.getPaymentId(), capturedPayment2.getTransactions().get(2),
+                                       PaymentExternalKey, capture2TransactionExternalKey,
+                                       account, captureTransaction.getAmount(), "CAPTURE");
+
+        // Refund
+        final String refundTransactionExternalKey = UUID.randomUUID().toString();
+        final Transaction refundTransaction = new Transaction();
+        refundTransaction.setPaymentId(authPayment.getPaymentId());
+        refundTransaction.setAmount(new BigDecimal("2"));
+        refundTransaction.setCurrency(account.getCurrency());
+        refundTransaction.setPaymentExternalKey(PaymentExternalKey);
+        refundTransaction.setTransactionExternalKey(refundTransactionExternalKey);
+        final Payment refundPayment = killBillClient.refundPayment(refundTransaction, createdBy, reason, comment);
+        verifyPayment(account, paymentMethodId, refundPayment, PaymentExternalKey, authTransactionExternalKey,
+                            BigDecimal.TEN, new BigDecimal("2"), new BigDecimal("2"), 4, PaymentNb);
+        verifyPaymentTransaction(authPayment.getPaymentId(), refundPayment.getTransactions().get(3),
+                                       PaymentExternalKey, refundTransactionExternalKey,
+                                       account, refundTransaction.getAmount(), "REFUND");
     }
 
-    @Test(groups = "slow", description = "Can create a full refund with invoice item adjustment")
-    public void testRefundWithFullInvoiceItemAdjustment() throws Exception {
-        final Payment paymentJson = setupScenarioWithPayment();
-
-        // Get the individual items for the invoice
-        final Invoice invoice = killBillClient.getInvoice(paymentJson.getInvoiceId(), true);
-        final InvoiceItem itemToAdjust = invoice.getItems().get(0);
-
-        // Issue a refund for the full amount
-        final BigDecimal refundAmount = itemToAdjust.getAmount();
-        final BigDecimal expectedInvoiceBalance = BigDecimal.ZERO;
-
-        // Post and verify the refund
-        final Refund refund = new Refund();
-        refund.setPaymentId(paymentJson.getPaymentId());
-        refund.setAmount(refundAmount);
-        refund.setAdjusted(true);
-        final InvoiceItem adjustment = new InvoiceItem();
-        adjustment.setInvoiceItemId(itemToAdjust.getInvoiceItemId());
-        /* null amount means full adjustment for that item */
-        refund.setAdjustments(ImmutableList.<InvoiceItem>of(adjustment));
-        final Refund refundJsonCheck = killBillClient.createRefund(refund, createdBy, reason, comment);
-        verifyRefund(paymentJson, refundJsonCheck, refundAmount);
-
-        // Verify the invoice balance
-        verifyInvoice(paymentJson, expectedInvoiceBalance);
-    }
-
-    @Test(groups = "slow", description = "Can create a partial refund with invoice item adjustment")
-    public void testPartialRefundWithInvoiceItemAdjustment() throws Exception {
-        final Payment paymentJson = setupScenarioWithPayment();
-
-        // Get the individual items for the invoice
-        final Invoice invoice = killBillClient.getInvoice(paymentJson.getInvoiceId(), true);
-        final InvoiceItem itemToAdjust = invoice.getItems().get(0);
-
-        // Issue a refund for a fraction of the amount
-        final BigDecimal refundAmount = getFractionOfAmount(itemToAdjust.getAmount());
-        final BigDecimal expectedInvoiceBalance = BigDecimal.ZERO;
-
-        // Post and verify the refund
-        final Refund refund = new Refund();
-        refund.setPaymentId(paymentJson.getPaymentId());
-        refund.setAdjusted(true);
-        final InvoiceItem adjustment = new InvoiceItem();
-        adjustment.setInvoiceItemId(itemToAdjust.getInvoiceItemId());
-        adjustment.setAmount(refundAmount);
-        refund.setAdjustments(ImmutableList.<InvoiceItem>of(adjustment));
-        final Refund refundJsonCheck = killBillClient.createRefund(refund, createdBy, reason, comment);
-        verifyRefund(paymentJson, refundJsonCheck, refundAmount);
-
-        // Verify the invoice balance
-        verifyInvoice(paymentJson, expectedInvoiceBalance);
+    private void verifyPayment(final Account account, @Nullable final UUID paymentMethodId, final Payment Payment,
+                                     final String PaymentExternalKey, final String authTransactionExternalKey,
+                                     final BigDecimal authAmount, final BigDecimal capturedAmount,
+                                     final BigDecimal refundedAmount, final int nbTransactions, final int PaymentNb) throws KillBillClientException {
+        Assert.assertEquals(Payment.getAccountId(), account.getAccountId());
+        Assert.assertEquals(Payment.getPaymentMethodId(), Objects.firstNonNull(paymentMethodId, account.getPaymentMethodId()));
+        Assert.assertNotNull(Payment.getPaymentId());
+        Assert.assertNotNull(Payment.getPaymentNumber());
+        Assert.assertEquals(Payment.getPaymentExternalKey(), PaymentExternalKey);
+        Assert.assertEquals(Payment.getAuthAmount().compareTo(authAmount), 0);
+        Assert.assertEquals(Payment.getCapturedAmount().compareTo(capturedAmount), 0);
+        Assert.assertEquals(Payment.getRefundedAmount().compareTo(refundedAmount), 0);
+        Assert.assertEquals(Payment.getCurrency(), account.getCurrency());
+        Assert.assertEquals(Payment.getTransactions().size(), nbTransactions);
+
+        verifyPaymentTransaction(Payment.getPaymentId(), Payment.getTransactions().get(0),
+                                       PaymentExternalKey, authTransactionExternalKey, account, authAmount, "AUTHORIZE");
+
+        final Payments Payments = killBillClient.getPayments();
+        Assert.assertEquals(Payments.size(), PaymentNb);
+        Assert.assertEquals(Payments.get(PaymentNb - 1), Payment);
+
+        final Payment retrievedPayment = killBillClient.getPayment(Payment.getPaymentId());
+        Assert.assertEquals(retrievedPayment, Payment);
+
+        final InvoicePayments PaymentsForAccount = killBillClient.getPaymentsForAccount(account.getAccountId());
+        Assert.assertEquals(PaymentsForAccount.size(), PaymentNb);
+        Assert.assertEquals(PaymentsForAccount.get(PaymentNb - 1), Payment);
     }
 
-    @Test(groups = "slow", description = "Can paginate through all payments and refunds")
-    public void testPaymentsAndRefundsPagination() throws Exception {
-        Payment lastPayment = setupScenarioWithPayment();
-
-        for (int i = 0; i < 5; i++) {
-            final Refund refund = new Refund();
-            refund.setPaymentId(lastPayment.getPaymentId());
-            refund.setAmount(lastPayment.getAmount());
-            killBillClient.createRefund(refund, createdBy, reason, comment);
-
-            final Payment payment = new Payment();
-            payment.setAccountId(lastPayment.getAccountId());
-            payment.setInvoiceId(lastPayment.getInvoiceId());
-            payment.setAmount(lastPayment.getAmount());
-            final List<Payment> payments = killBillClient.createPayment(payment, false, createdBy, reason, comment);
-
-            lastPayment = payments.get(payments.size() - 1);
+    private void verifyPaymentTransaction(final UUID PaymentId, final Transaction Transaction,
+                                                final String PaymentExternalKey, final String TransactionExternalKey,
+                                                final Account account, @Nullable final BigDecimal amount, final String transactionType) {
+        Assert.assertEquals(Transaction.getPaymentId(), PaymentId);
+        Assert.assertNotNull(Transaction.getTransactionId());
+        Assert.assertEquals(Transaction.getTransactionType(), transactionType);
+        Assert.assertEquals(Transaction.getStatus(), "SUCCESS");
+        if (amount == null) {
+            Assert.assertNull(Transaction.getAmount());
+            Assert.assertNull(Transaction.getCurrency());
+        } else {
+            Assert.assertEquals(Transaction.getAmount().compareTo(amount), 0);
+            Assert.assertEquals(Transaction.getCurrency(), account.getCurrency());
         }
-
-        final Payments allPayments = killBillClient.getPayments();
-        Assert.assertEquals(allPayments.size(), 6);
-
-        final Refunds allRefunds = killBillClient.getRefunds();
-        Assert.assertEquals(allRefunds.size(), 5);
-
-        Payments paymentsPage = killBillClient.getPayments(0L, 1L);
-        for (int i = 0; i < 6; i++) {
-            Assert.assertNotNull(paymentsPage);
-            Assert.assertEquals(paymentsPage.size(), 1);
-            Assert.assertEquals(paymentsPage.get(0), allPayments.get(i));
-            paymentsPage = paymentsPage.getNext();
-        }
-        Assert.assertNull(paymentsPage);
-
-        Refunds refundsPage = killBillClient.getRefunds(0L, 1L);
-        for (int i = 0; i < 5; i++) {
-            Assert.assertNotNull(refundsPage);
-            Assert.assertEquals(refundsPage.size(), 1);
-            Assert.assertEquals(refundsPage.get(0), allRefunds.get(i));
-            refundsPage = refundsPage.getNext();
-        }
-        Assert.assertNull(refundsPage);
-    }
-
-    private BigDecimal getFractionOfAmount(final BigDecimal amount) {
-        return amount.divide(BigDecimal.TEN).setScale(2, BigDecimal.ROUND_HALF_UP);
-    }
-
-    private Payment setupScenarioWithPayment() throws Exception {
-        final Account accountJson = createAccountWithPMBundleAndSubscriptionAndWaitForFirstInvoice();
-
-        final List<Payment> firstPaymentForAccount = killBillClient.getPaymentsForAccount(accountJson.getAccountId());
-        Assert.assertEquals(firstPaymentForAccount.size(), 1);
-
-        final Payment paymentJson = firstPaymentForAccount.get(0);
-
-        // Check the PaymentMethod from paymentMethodId returned in the Payment object
-        final UUID paymentMethodId = paymentJson.getPaymentMethodId();
-        final PaymentMethod paymentMethodJson = killBillClient.getPaymentMethod(paymentMethodId, true);
-        Assert.assertEquals(paymentMethodJson.getPaymentMethodId(), paymentMethodId);
-        Assert.assertEquals(paymentMethodJson.getAccountId(), accountJson.getAccountId());
-
-        // Verify the refunds
-        final List<Refund> objRefundFromJson = killBillClient.getRefundsForPayment(paymentJson.getPaymentId());
-        Assert.assertEquals(objRefundFromJson.size(), 0);
-        return paymentJson;
-    }
-
-    private void verifyRefund(final Payment paymentJson, final Refund refundJsonCheck, final BigDecimal refundAmount) throws KillBillClientException {
-        Assert.assertEquals(refundJsonCheck.getPaymentId(), paymentJson.getPaymentId());
-        Assert.assertEquals(refundJsonCheck.getAmount().setScale(2, RoundingMode.HALF_UP), refundAmount.setScale(2, RoundingMode.HALF_UP));
-        Assert.assertEquals(refundJsonCheck.getCurrency(), DEFAULT_CURRENCY);
-        Assert.assertEquals(refundJsonCheck.getStatus(), RefundStatus.COMPLETED.toString());
-        Assert.assertEquals(refundJsonCheck.getEffectiveDate().getYear(), clock.getUTCNow().getYear());
-        Assert.assertEquals(refundJsonCheck.getEffectiveDate().getMonthOfYear(), clock.getUTCNow().getMonthOfYear());
-        Assert.assertEquals(refundJsonCheck.getEffectiveDate().getDayOfMonth(), clock.getUTCNow().getDayOfMonth());
-        Assert.assertEquals(refundJsonCheck.getRequestedDate().getYear(), clock.getUTCNow().getYear());
-        Assert.assertEquals(refundJsonCheck.getRequestedDate().getMonthOfYear(), clock.getUTCNow().getMonthOfYear());
-        Assert.assertEquals(refundJsonCheck.getRequestedDate().getDayOfMonth(), clock.getUTCNow().getDayOfMonth());
-
-        // Verify the refunds
-        final List<Refund> retrievedRefunds = killBillClient.getRefundsForPayment(paymentJson.getPaymentId());
-        Assert.assertEquals(retrievedRefunds.size(), 1);
-
-        // Verify the refund via the payment API
-        final Payment retrievedPaymentJson = killBillClient.getPayment(paymentJson.getPaymentId(), true);
-        Assert.assertEquals(retrievedPaymentJson.getPaymentId(), paymentJson.getPaymentId());
-        Assert.assertEquals(retrievedPaymentJson.getPaidAmount().setScale(2, RoundingMode.HALF_UP), paymentJson.getPaidAmount().add(refundAmount.negate()).setScale(2, RoundingMode.HALF_UP));
-        Assert.assertEquals(retrievedPaymentJson.getAmount().setScale(2, RoundingMode.HALF_UP), paymentJson.getAmount().setScale(2, RoundingMode.HALF_UP));
-        Assert.assertEquals(retrievedPaymentJson.getAccountId(), paymentJson.getAccountId());
-        Assert.assertEquals(retrievedPaymentJson.getInvoiceId(), paymentJson.getInvoiceId());
-        Assert.assertEquals(retrievedPaymentJson.getRequestedDate(), paymentJson.getRequestedDate());
-        Assert.assertEquals(retrievedPaymentJson.getEffectiveDate(), paymentJson.getEffectiveDate());
-        Assert.assertEquals(retrievedPaymentJson.getRetryCount(), paymentJson.getRetryCount());
-        Assert.assertEquals(retrievedPaymentJson.getCurrency(), paymentJson.getCurrency());
-        Assert.assertEquals(retrievedPaymentJson.getStatus(), paymentJson.getStatus());
-        Assert.assertEquals(retrievedPaymentJson.getGatewayErrorCode(), paymentJson.getGatewayErrorCode());
-        Assert.assertEquals(retrievedPaymentJson.getGatewayErrorMsg(), paymentJson.getGatewayErrorMsg());
-        Assert.assertEquals(retrievedPaymentJson.getPaymentMethodId(), paymentJson.getPaymentMethodId());
-        Assert.assertEquals(retrievedPaymentJson.getChargebacks().size(), 0);
-        Assert.assertEquals(retrievedPaymentJson.getRefunds().size(), 1);
-        Assert.assertEquals(retrievedPaymentJson.getRefunds().get(0), refundJsonCheck);
-    }
-
-    private void verifyInvoice(final Payment paymentJson, final BigDecimal expectedInvoiceBalance) throws KillBillClientException {
-        final Invoice invoiceJson = killBillClient.getInvoice(paymentJson.getInvoiceId());
-        Assert.assertEquals(invoiceJson.getBalance().setScale(2, BigDecimal.ROUND_HALF_UP),
-                            expectedInvoiceBalance.setScale(2, BigDecimal.ROUND_HALF_UP));
+        Assert.assertEquals(Transaction.getTransactionExternalKey(), TransactionExternalKey);
+        Assert.assertEquals(Transaction.getPaymentExternalKey(), PaymentExternalKey);
     }
 }