killbill-aplcache

Changes

api/src/main/java/com/ning/billing/payment/api/CreditCardPaymentMethodInfo.java 207(+0 -207)

api/src/main/java/com/ning/billing/payment/api/PaymentMethodInfo.java 139(+0 -139)

api/src/main/java/com/ning/billing/payment/api/PaypalPaymentMethodInfo.java 88(+0 -88)

Details

diff --git a/api/src/main/java/com/ning/billing/ErrorCode.java b/api/src/main/java/com/ning/billing/ErrorCode.java
index 66ac58b..1ff2610 100644
--- a/api/src/main/java/com/ning/billing/ErrorCode.java
+++ b/api/src/main/java/com/ning/billing/ErrorCode.java
@@ -208,25 +208,30 @@ public enum ErrorCode {
      * Range 7000 : Payment
      */
     
-    PAYMENT_NO_SUCH_PAYMENT_METHOD(7001, "Payment method for account %s, and paymentId %s does not exist"),
-    PAYMENT_NO_PAYMENT_METHODS(7002, "Payment methods for account %s don't exist"),
-    PAYMENT_UPD_GATEWAY_FAILED(7003, "Failed to update payment gateway for account %s : %s"),
-    PAYMENT_GET_PAYMENT_PROVIDER(7004, "Failed to retrieve payment provider for account %s : %s"),    
+    PAYMENT_NO_SUCH_PAYMENT_METHOD(7000, "Payment method for account %s, and paymentId %s does not exist"),
+    PAYMENT_NO_PAYMENT_METHODS(7001, "Payment methods for account %s don't exist"),
+    PAYMENT_UPD_GATEWAY_FAILED(7002, "Failed to update payment gateway for account %s : %s"),
+    PAYMENT_GET_PAYMENT_PROVIDER(7003, "Failed to retrieve payment provider for account %s : %s"),    
+    PAYMENT_GET_PAYMENT_METHODS(7004, "Failed to retrieve payment method for account %s : %s"),        
     PAYMENT_ADD_PAYMENT_METHOD(7005, "Failed to add payment method for account %s : %s"),        
-    PAYMENT_DEL_PAYMENT_METHOD(7006, "Failed to delete payment method for account %s : %s"),        
-    PAYMENT_UPD_PAYMENT_METHOD(7007, "Failed to update payment method for account %s : %s"),            
-    PAYMENT_CREATE_PAYMENT(7008, "Failed to create payment for account %s : %s"),                
-    PAYMENT_CREATE_PAYMENT_FOR_ATTEMPT(7009, "Failed to create payment for account %s and attempt %s : %s"),                    
-    PAYMENT_CREATE_PAYMENT_FOR_ATTEMPT_WITH_NON_POSITIVE_INV(7010, "Got payment attempt with negative or null invoice for account %s"),                        
-    PAYMENT_CREATE_PAYMENT_FOR_ATTEMPT_BAD(7011, "Failed to create payment for attempts %s "),                    
-    PAYMENT_CREATE_PAYMENT_PROVIDER_ACCOUNT(7012, "Failed to create payment provider account for account %s : %s"),                
-    PAYMENT_UPD_PAYMENT_PROVIDER_ACCOUNT(7013, "Failed to update payment provider account for account %s : %s"),
-    PAYMENT_GET_PAYMENT_PROVIDER_ACCOUNT(7014, "Failed to retrieve payment provider account for account %s : %s"),                        
-    PAYMENT_CREATE_REFUND(7014, "Failed to create refund for account %s : %s"),                
-    PAYMENT_NULL_INVOICE(7015, "Invoice %s has a balance <= 0 "),      
-    PAYMENT_AMOUNT_DENIED(7016, "Payment amount requested for invoice %s is greater than invoice balance [%f/%f]"),         
-    PAYMENT_INTERNAL_ERROR(7017, "Internal payment error : %s"),
-    PAYMENT_PLUGIN_TIMEOUT(7018, "Plugin timeout for account %s and invoice %s"),    
+    PAYMENT_REFRESH_PAYMENT_METHOD(7006, "Failed to resfresh payment methods for account %s : %s"),            
+    PAYMENT_DEL_PAYMENT_METHOD(7007, "Failed to delete payment method for account %s : %s"),        
+    PAYMENT_UPD_PAYMENT_METHOD(7008, "Failed to update payment method for account %s : %s"),            
+    PAYMENT_CREATE_PAYMENT(7009, "Failed to create payment for account %s : %s"),                
+    PAYMENT_CREATE_PAYMENT_FOR_ATTEMPT(70010, "Failed to create payment for account %s and attempt %s : %s"),                    
+    PAYMENT_CREATE_PAYMENT_FOR_ATTEMPT_WITH_NON_POSITIVE_INV(7011, "Got payment attempt with negative or null invoice for account %s"),                        
+    PAYMENT_CREATE_PAYMENT_FOR_ATTEMPT_BAD(7012, "Failed to create payment for attempts %s "),                    
+    PAYMENT_CREATE_PAYMENT_PROVIDER_ACCOUNT(7013, "Failed to create payment provider account for account %s : %s"),                
+    PAYMENT_UPD_PAYMENT_PROVIDER_ACCOUNT(7014, "Failed to update payment provider account for account %s : %s"),
+    PAYMENT_GET_PAYMENT_PROVIDER_ACCOUNT(7015, "Failed to retrieve payment provider account for account %s : %s"),                        
+    PAYMENT_CREATE_REFUND(7016, "Failed to create refund for account %s : %s"),                
+    PAYMENT_NULL_INVOICE(7017, "Invoice %s has a balance <= 0 "),      
+    PAYMENT_AMOUNT_DENIED(7018, "Payment amount requested for invoice %s is greater than invoice balance [%f/%f]"),         
+    PAYMENT_INTERNAL_ERROR(7019, "Internal payment error : %s"),
+    
+    PAYMENT_PLUGIN_TIMEOUT(7100, "Plugin timeout for account %s and invoice %s"),    
+    PAYMENT_PLUGIN_ACCOUNT_INIT(7101, "Account initialization for account %s and plugin % s failed: %s"),        
+    
     /*
     *
     * Range 9000: Miscellaneous
diff --git a/api/src/main/java/com/ning/billing/payment/api/PaymentApi.java b/api/src/main/java/com/ning/billing/payment/api/PaymentApi.java
index 2e2db33..d2661f3 100644
--- a/api/src/main/java/com/ning/billing/payment/api/PaymentApi.java
+++ b/api/src/main/java/com/ning/billing/payment/api/PaymentApi.java
@@ -17,6 +17,7 @@ package com.ning.billing.payment.api;
 
 import java.math.BigDecimal;
 import java.util.List;
+import java.util.Set;
 import java.util.UUID;
 
 import com.ning.billing.account.api.Account;
@@ -25,39 +26,7 @@ import com.ning.billing.payment.plugin.api.PaymentProviderAccount;
 import com.ning.billing.util.callcontext.CallContext;
 
 public interface PaymentApi {
-
-
-    /*
-     * Those PaymentInfo/Gateway APIs are broken but unfortunately are needed until we move to /1.0 killbill APIs
-     */
-    public void updatePaymentGateway(final String accountKey, final CallContext context)
-        throws PaymentApiException;
-
-    public PaymentMethodInfo getPaymentMethod(final String accountKey, final String paymentMethodId)
-        throws PaymentApiException;
-
-    public List<PaymentMethodInfo> getPaymentMethods(final String accountKey)
-        throws PaymentApiException;
-
-    public String addPaymentMethod(final String accountKey, final PaymentMethodInfo paymentMethod, final CallContext context)
-        throws PaymentApiException;
-
-    public PaymentMethodInfo updatePaymentMethod(final String accountKey, final PaymentMethodInfo paymentMethodInfo, final CallContext context)
-        throws PaymentApiException;
-
-    public void deletePaymentMethod(final String accountKey, final String paymentMethodId, final CallContext context)
-        throws PaymentApiException;
-
-    
-    public PaymentProviderAccount getPaymentProviderAccount(String accountKey)
-    throws PaymentApiException;
-    
-    public String createPaymentProviderAccount(final Account account, final CallContext context)
-    throws PaymentApiException;
-
-    public void updatePaymentProviderAccountContact(String accountKey, CallContext context)
-    throws PaymentApiException;
-    
+  
     public Payment createPayment(final String accountKey, final UUID invoiceId, final BigDecimal amount, final CallContext context)
     throws PaymentApiException;
 
@@ -72,5 +41,36 @@ public interface PaymentApi {
 
    public List<Payment> getAccountPayments(final UUID accountId)
     throws PaymentApiException;
-
+   
+   
+   /*
+    * Payment method Apis
+    */
+   public Set<String> getAvailablePlugins();
+   
+   public String initializeAccountPlugin(final String pluginName, final Account account)
+   throws PaymentApiException;
+   
+   public UUID addPaymentMethod(final String pluginName, final Account account, boolean setDefault, final PaymentMethodPlugin paymentMethodInfo, final CallContext context)
+   throws PaymentApiException;
+   
+   public List<PaymentMethod> refreshPaymentMethods(final String pluginName, final Account account, final PaymentMethodPlugin paymentMethodInfo, final CallContext context)
+    throws PaymentApiException;
+   
+   public List<PaymentMethod> getPaymentMethods(final Account account, final boolean withPluginDetail)
+    throws PaymentApiException;
+   
+   public PaymentMethod getPaymentMethod(final Account account, final UUID paymentMethodId, final boolean withPluginDetail)
+   throws PaymentApiException;
+   
+   public void updatePaymentMethod(final Account account, final UUID paymentMethodId, final PaymentMethodPlugin paymentMetghodInfo)
+   throws PaymentApiException;
+   
+   public void deletedPaymentMethod(final Account account, final UUID paymentMethodId, final CallContext context)
+   throws PaymentApiException;
+   
+   public void setDefaultPaymentMethod(final Account account, final UUID paymentMethodId, final CallContext context)
+   throws PaymentApiException;
+   
+  
 }
diff --git a/api/src/main/java/com/ning/billing/payment/api/PaymentMethod.java b/api/src/main/java/com/ning/billing/payment/api/PaymentMethod.java
index b6acf5f..94299e7 100644
--- a/api/src/main/java/com/ning/billing/payment/api/PaymentMethod.java
+++ b/api/src/main/java/com/ning/billing/payment/api/PaymentMethod.java
@@ -27,4 +27,6 @@ public interface PaymentMethod {
     public Boolean isActive();
     
     public String getPluginName();
+    
+    public PaymentMethodPlugin getPluginDetail();
 }
diff --git a/api/src/main/java/com/ning/billing/payment/api/PaymentMethodPlugin.java b/api/src/main/java/com/ning/billing/payment/api/PaymentMethodPlugin.java
new file mode 100644
index 0000000..f829232
--- /dev/null
+++ b/api/src/main/java/com/ning/billing/payment/api/PaymentMethodPlugin.java
@@ -0,0 +1,54 @@
+/* 
+ * Copyright 2010-2011 Ning, Inc.
+ *
+ * Ning 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 com.ning.billing.payment.api;
+
+import java.util.List;
+
+public interface PaymentMethodPlugin {
+    
+    public String getExternalPaymentMethodId();
+    
+    public boolean isDefaultPaymentMethod();
+    
+    public List<PaymentMethodKVInfo> getProperties(); 
+    
+    public String getValueString(String key);
+    
+    public class PaymentMethodKVInfo {
+        private final String key;
+        private final Object value;
+        private final Boolean isUpdatable;
+        
+        public PaymentMethodKVInfo(String key, Object value, Boolean isUpdatable) {
+            super();
+            this.key = key;
+            this.value = value;
+            this.isUpdatable = isUpdatable;
+        }
+
+        public String getKey() {
+            return key;
+        }
+
+        public Object getValue() {
+            return value;
+        }
+
+        public Boolean getIsUpdatable() {
+            return isUpdatable;
+        }
+    }
+}
diff --git a/api/src/main/java/com/ning/billing/payment/provider/PaymentProviderPluginRegistry.java b/api/src/main/java/com/ning/billing/payment/provider/PaymentProviderPluginRegistry.java
index bd76f30..321a421 100644
--- a/api/src/main/java/com/ning/billing/payment/provider/PaymentProviderPluginRegistry.java
+++ b/api/src/main/java/com/ning/billing/payment/provider/PaymentProviderPluginRegistry.java
@@ -15,11 +15,15 @@
  */
 package com.ning.billing.payment.provider;
 
-import com.ning.billing.payment.plugin.api.PaymentProviderPlugin;
+import java.util.Set;
+
+import com.ning.billing.payment.plugin.api.PaymentPluginApi;
 
 public interface PaymentProviderPluginRegistry {
 
-    public void register(final PaymentProviderPlugin plugin, final String name);
+    public void register(final PaymentPluginApi plugin, final String name);
 
-    public PaymentProviderPlugin getPlugin(final String name);
+    public PaymentPluginApi getPlugin(final String name);
+    
+    public Set<String> getRegisteredPluginNames();
 }
diff --git a/payment/src/main/java/com/ning/billing/payment/api/DefaultPaymentApi.java b/payment/src/main/java/com/ning/billing/payment/api/DefaultPaymentApi.java
index 2d61934..69c5cbf 100644
--- a/payment/src/main/java/com/ning/billing/payment/api/DefaultPaymentApi.java
+++ b/payment/src/main/java/com/ning/billing/payment/api/DefaultPaymentApi.java
@@ -18,6 +18,7 @@ package com.ning.billing.payment.api;
 
 import java.math.BigDecimal;
 import java.util.List;
+import java.util.Set;
 import java.util.UUID;
 
 import com.google.inject.Inject;
@@ -49,92 +50,99 @@ public class DefaultPaymentApi implements PaymentApi {
     }
      
  
+ 
+   
     @Override
-    public PaymentMethodInfo getPaymentMethod(String accountKey, String paymentMethodId) 
-        throws PaymentApiException {
-        return methodProcessor.getPaymentMethod(accountKey, paymentMethodId);
+    public Payment createPayment(final String accountKey, final UUID invoiceId, final BigDecimal amount, final CallContext context) 
+    throws PaymentApiException {
+        return paymentProcessor.createPayment(accountKey, invoiceId, amount, context, true);
+     }
+    
+    @Override
+    public Payment createPayment(Account account, UUID invoiceId,
+            final BigDecimal amount, CallContext context) throws PaymentApiException {
+        return paymentProcessor.createPayment(account, invoiceId, amount, context, true);        
     }
 
+    
     @Override
-    public List<PaymentMethodInfo> getPaymentMethods(String accountKey)
-    throws PaymentApiException {
-        return methodProcessor.getPaymentMethods(accountKey);
+    public List<Payment> getInvoicePayments(UUID invoiceId) {
+        return paymentProcessor.getInvoicePayments(invoiceId);
     }
 
     @Override
-    public void updatePaymentGateway(final String accountKey, final CallContext context) 
-    throws PaymentApiException {
-        methodProcessor.updatePaymentGateway(accountKey, context);
+    public List<Payment> getAccountPayments(UUID accountId)
+            throws PaymentApiException {
+        return paymentProcessor.getAccountPayments(accountId);
     }
-
+    
 
     @Override
-    public String addPaymentMethod(final String accountKey, final PaymentMethodInfo paymentMethod, final CallContext context) 
-    throws PaymentApiException {
-        return methodProcessor.addPaymentMethod(accountKey, paymentMethod, context);
+    public Refund createRefund(Account account, UUID paymentId, CallContext context)
+        throws PaymentApiException {
+        return refundProcessor.createRefund(account, paymentId, context);
     }
 
+    
+  
+
 
     @Override
-    public void deletePaymentMethod(final String accountKey, final String paymentMethodId, final CallContext context) 
-    throws PaymentApiException {
-        methodProcessor.deletePaymentMethod(accountKey, paymentMethodId, context);
+    public Set<String> getAvailablePlugins() {
+        return methodProcessor.getAvailablePlugins();
     }
 
-    @Override
-    public PaymentMethodInfo updatePaymentMethod(final String accountKey, final PaymentMethodInfo paymentMethodInfo, final CallContext context) 
-    throws PaymentApiException {
 
-        return methodProcessor.updatePaymentMethod(accountKey, paymentMethodInfo, context);
-     }
-   
     @Override
-    public Payment createPayment(final String accountKey, final UUID invoiceId, final BigDecimal amount, final CallContext context) 
-    throws PaymentApiException {
-        return paymentProcessor.createPayment(accountKey, invoiceId, amount, context, true);
-     }
-    
-    @Override
-    public Payment createPayment(Account account, UUID invoiceId,
-            final BigDecimal amount, CallContext context) throws PaymentApiException {
-        return paymentProcessor.createPayment(account, invoiceId, amount, context, true);        
+    public String initializeAccountPlugin(String pluginName, Account account)
+        throws PaymentApiException {
+        return methodProcessor.initializeAccountPlugin(pluginName, account);
     }
 
-    
+
     @Override
-    public List<Payment> getInvoicePayments(UUID invoiceId) {
-        return paymentProcessor.getInvoicePayments(invoiceId);
+    public UUID addPaymentMethod(String pluginName, Account account,
+            boolean setDefault, final PaymentMethodPlugin paymentMethodInfo, final CallContext context) 
+        throws PaymentApiException {
+        return methodProcessor.addPaymentMethod(pluginName, account, setDefault, paymentMethodInfo, context);
     }
 
+ 
     @Override
-    public List<Payment> getAccountPayments(UUID accountId)
+    public List<PaymentMethod> refreshPaymentMethods(String pluginName,
+            Account account, PaymentMethodPlugin paymentMethodInfo, final CallContext context) 
             throws PaymentApiException {
-        return paymentProcessor.getAccountPayments(accountId);
+        return methodProcessor.refreshPaymentMethods(pluginName, account, context);
     }
 
     @Override
-    public String createPaymentProviderAccount(Account account, CallContext context) 
+    public List<PaymentMethod> getPaymentMethods(Account account, boolean withPluginDetail) 
     throws PaymentApiException {
-        return accountProcessor.createPaymentProviderAccount(account, context);
+        return methodProcessor.getPaymentMethods(account, withPluginDetail);
     }
 
     @Override
-    public void updatePaymentProviderAccountContact(String externalKey, CallContext context) 
+    public PaymentMethod getPaymentMethod(final Account account, UUID paymentMethod, boolean withPluginDetail)
         throws PaymentApiException {
-        accountProcessor.updatePaymentProviderAccountContact(externalKey, context);
+        return methodProcessor.getPaymentMethod(account, paymentMethod, withPluginDetail);
     }
 
-
     @Override
-    public Refund createRefund(Account account, UUID paymentId, CallContext context)
+    public void updatePaymentMethod(final Account account, UUID paymentMethodId, PaymentMethodPlugin paymentMethodInfo)
         throws PaymentApiException {
-        return refundProcessor.createRefund(account, paymentId, context);
+        methodProcessor.updatePaymentMethod(account, paymentMethodId, paymentMethodInfo);
     }
 
+    @Override
+    public void deletedPaymentMethod(final Account account, UUID paymentMethodId, final CallContext context) 
+        throws PaymentApiException {
+        methodProcessor.deletedPaymentMethod(account, paymentMethodId);
+    }
 
     @Override
-    public PaymentProviderAccount getPaymentProviderAccount(String accountKey)
-            throws PaymentApiException {
-        return accountProcessor.getPaymentProviderAccount(accountKey);
+    public void setDefaultPaymentMethod(Account account, UUID paymentMethodId, final CallContext context)
+        throws PaymentApiException {
+        methodProcessor.setDefaultPaymentMethod(account, paymentMethodId);
     }
+
 }
diff --git a/payment/src/main/java/com/ning/billing/payment/api/DefaultPaymentMethod.java b/payment/src/main/java/com/ning/billing/payment/api/DefaultPaymentMethod.java
index 67d8941..1ae4204 100644
--- a/payment/src/main/java/com/ning/billing/payment/api/DefaultPaymentMethod.java
+++ b/payment/src/main/java/com/ning/billing/payment/api/DefaultPaymentMethod.java
@@ -26,20 +26,36 @@ public class DefaultPaymentMethod extends EntityBase  implements PaymentMethod {
     private final UUID accountId;    
     private final Boolean isActive;
     private final String pluginName;
+    private final PaymentMethodPlugin pluginDetail;
     
-    
-    public DefaultPaymentMethod(UUID paymentMethodId, UUID accountId,
-            Boolean isActive, String pluginName) {
+    public DefaultPaymentMethod(UUID paymentMethodId, UUID accountId, Boolean isActive, String pluginName) {
         super(paymentMethodId);
         this.accountId = accountId;
         this.isActive = isActive;
         this.pluginName = pluginName;
+        this.pluginDetail = null;
     }
     
+    public DefaultPaymentMethod(UUID paymentMethodId, UUID accountId, Boolean isActive, String pluginName, PaymentMethodPlugin pluginDetail) {
+        super(paymentMethodId);
+        this.accountId = accountId;
+        this.isActive = isActive;
+        this.pluginName = pluginName;
+        this.pluginDetail = pluginDetail;
+    }
+
+    public DefaultPaymentMethod(UUID accountId, String pluginName, PaymentMethodPlugin pluginDetail) {
+        this(UUID.randomUUID(), accountId, true, pluginName, pluginDetail);
+    }
+
     public DefaultPaymentMethod(PaymentMethodModelDao input) {
         this(input.getId(), input.getAccountId(), input.isActive(), input.getPluginName());
     }
 
+    public DefaultPaymentMethod(PaymentMethodModelDao input, PaymentMethodPlugin pluginDetail) {
+        this(input.getId(), input.getAccountId(), input.isActive(), input.getPluginName(), pluginDetail);
+    }
+
 
     @Override
     public UUID getAccountId() {
@@ -55,4 +71,9 @@ public class DefaultPaymentMethod extends EntityBase  implements PaymentMethod {
     public String getPluginName() {
         return pluginName;
     }
+
+    @Override
+    public PaymentMethodPlugin getPluginDetail() {
+        return pluginDetail;
+    }
 }
diff --git a/payment/src/main/java/com/ning/billing/payment/bus/TagHandler.java b/payment/src/main/java/com/ning/billing/payment/bus/TagHandler.java
new file mode 100644
index 0000000..da66d06
--- /dev/null
+++ b/payment/src/main/java/com/ning/billing/payment/bus/TagHandler.java
@@ -0,0 +1,20 @@
+/* 
+ * Copyright 2010-2011 Ning, Inc.
+ *
+ * Ning 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 com.ning.billing.payment.bus;
+
+public class TagHandler {
+
+}
diff --git a/payment/src/main/java/com/ning/billing/payment/core/AccountProcessor.java b/payment/src/main/java/com/ning/billing/payment/core/AccountProcessor.java
index 9578eed..009d109 100644
--- a/payment/src/main/java/com/ning/billing/payment/core/AccountProcessor.java
+++ b/payment/src/main/java/com/ning/billing/payment/core/AccountProcessor.java
@@ -28,7 +28,7 @@ import com.ning.billing.account.api.AccountUserApi;
 import com.ning.billing.payment.api.PaymentApiException;
 import com.ning.billing.payment.plugin.api.PaymentPluginApiException;
 import com.ning.billing.payment.plugin.api.PaymentProviderAccount;
-import com.ning.billing.payment.plugin.api.PaymentProviderPlugin;
+import com.ning.billing.payment.plugin.api.PaymentPluginApi;
 import com.ning.billing.payment.provider.PaymentProviderPluginRegistry;
 import com.ning.billing.util.bus.Bus;
 import com.ning.billing.util.callcontext.CallContext;
@@ -49,7 +49,7 @@ public class AccountProcessor extends ProcessorBase {
     public String createPaymentProviderAccount(Account account, CallContext context) 
     throws PaymentApiException {
         try {
-            final PaymentProviderPlugin plugin = getPaymentProviderPlugin((Account)null);
+            final PaymentPluginApi plugin = getPaymentProviderPlugin((Account)null);
             return plugin.createPaymentProviderAccount(account);
         } catch (PaymentPluginApiException e) {
             throw new PaymentApiException(ErrorCode.PAYMENT_CREATE_PAYMENT_PROVIDER_ACCOUNT, account.getId(), e.getMessage());
@@ -62,7 +62,7 @@ public class AccountProcessor extends ProcessorBase {
         Account account = null;
         try {
             account = accountUserApi.getAccountByKey(externalKey);
-            final PaymentProviderPlugin plugin = getPaymentProviderPlugin(account);
+            final PaymentPluginApi plugin = getPaymentProviderPlugin(account);
             plugin.updatePaymentProviderAccountExistingContact(account);
         } catch (AccountApiException e) {
             throw new PaymentApiException(e);
@@ -76,7 +76,7 @@ public class AccountProcessor extends ProcessorBase {
         Account account = null;
         try {
             account = accountUserApi.getAccountByKey(externalKey);
-            final PaymentProviderPlugin plugin = getPaymentProviderPlugin(account);
+            final PaymentPluginApi plugin = getPaymentProviderPlugin(account);
             return plugin.getPaymentProviderAccount(externalKey);
         } catch (AccountApiException e) {
             throw new PaymentApiException(e);
diff --git a/payment/src/main/java/com/ning/billing/payment/core/PaymentMethodProcessor.java b/payment/src/main/java/com/ning/billing/payment/core/PaymentMethodProcessor.java
index a10e226..090bc09 100644
--- a/payment/src/main/java/com/ning/billing/payment/core/PaymentMethodProcessor.java
+++ b/payment/src/main/java/com/ning/billing/payment/core/PaymentMethodProcessor.java
@@ -17,18 +17,28 @@ package com.ning.billing.payment.core;
 
 import static com.ning.billing.payment.glue.PaymentModule.PLUGIN_EXECUTOR_NAMED;
 
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.LinkedList;
 import java.util.List;
+import java.util.Set;
+import java.util.UUID;
 import java.util.concurrent.ExecutorService;
 
-import javax.inject.Inject;
 
+import com.google.inject.Inject;
 import com.google.inject.name.Named;
 import com.ning.billing.ErrorCode;
+import com.ning.billing.account.api.Account;
 import com.ning.billing.account.api.AccountUserApi;
+import com.ning.billing.payment.api.DefaultPaymentMethod;
 import com.ning.billing.payment.api.PaymentApiException;
-import com.ning.billing.payment.api.PaymentMethodInfo;
+import com.ning.billing.payment.api.PaymentMethod;
+import com.ning.billing.payment.api.PaymentMethodPlugin;
+import com.ning.billing.payment.dao.PaymentDao;
+import com.ning.billing.payment.dao.PaymentMethodModelDao;
 import com.ning.billing.payment.plugin.api.PaymentPluginApiException;
-import com.ning.billing.payment.plugin.api.PaymentProviderPlugin;
+import com.ning.billing.payment.plugin.api.PaymentPluginApi;
 import com.ning.billing.payment.provider.PaymentProviderPluginRegistry;
 import com.ning.billing.util.bus.Bus;
 import com.ning.billing.util.callcontext.CallContext;
@@ -36,113 +46,201 @@ import com.ning.billing.util.globallocker.GlobalLocker;
 
 public class PaymentMethodProcessor extends ProcessorBase {
 
+    private final PaymentDao paymentDao;
+    
     @Inject
     public PaymentMethodProcessor(final PaymentProviderPluginRegistry pluginRegistry,
             final AccountUserApi accountUserApi,
             final Bus eventBus,
+            final PaymentDao paymentDao,
             final GlobalLocker locker,
             @Named(PLUGIN_EXECUTOR_NAMED)  final ExecutorService executor) {
         super(pluginRegistry, accountUserApi, eventBus, locker, executor);
+        this.paymentDao = paymentDao;
     }
     
-    //@Override
-    public PaymentMethodInfo getPaymentMethod(String accountKey, String paymentMethodId) 
-        throws PaymentApiException {
-            try {
-                final PaymentProviderPlugin plugin = getPaymentProviderPlugin(accountKey);
-                return plugin.getPaymentMethodInfo(paymentMethodId);
-            } catch (PaymentPluginApiException e) {
-                throw new PaymentApiException(e, ErrorCode.PAYMENT_NO_SUCH_PAYMENT_METHOD, accountKey, paymentMethodId);            
-            }
+    public Set<String> getAvailablePlugins() {
+        return pluginRegistry.getRegisteredPluginNames();
+    }
+
 
+    public String initializeAccountPlugin(String pluginName, Account account) throws PaymentApiException {
+        PaymentPluginApi pluginApi = null;
+        try {
+            pluginApi = getPaymentProviderPlugin(account.getExternalKey());
+            return pluginApi.createPaymentProviderAccount(account);
+        } catch (PaymentPluginApiException e) {
+            throw new PaymentApiException(ErrorCode.PAYMENT_PLUGIN_ACCOUNT_INIT,
+                    account.getId(), pluginApi != null ? pluginApi.getName() : null, e.getErrorMessage());
         }
+    }
+
 
-    //@Override
-    public List<PaymentMethodInfo> getPaymentMethods(String accountKey)
+    public UUID addPaymentMethod(String pluginName, Account account,
+            boolean setDefault, final PaymentMethodPlugin paymentMethodProps, CallContext context) 
     throws PaymentApiException {
+        
+        PaymentMethod pm = null;
+        PaymentPluginApi pluginApi = null;
         try {
-            final PaymentProviderPlugin plugin = getPaymentProviderPlugin(accountKey);
-            return plugin.getPaymentMethods(accountKey);
+            pluginApi = getPaymentProviderPlugin(account.getExternalKey());
+            pm = new DefaultPaymentMethod(account.getId(), pluginName, paymentMethodProps);
+            String externalId = pluginApi.addPaymentMethod(account.getExternalKey(), paymentMethodProps, setDefault);
+            PaymentMethodModelDao pmModel = new PaymentMethodModelDao(pm.getId(), pm.getAccountId(), pm.getPluginName(), pm.isActive(), externalId);
+            paymentDao.insertPaymentMethod(pmModel, context);
+            
+            // STEPH setDefault
         } catch (PaymentPluginApiException e) {
-            throw new PaymentApiException(e, ErrorCode.PAYMENT_NO_PAYMENT_METHODS, accountKey);
+            // STEPH all errors should also take a pluginName
+            throw new PaymentApiException(ErrorCode.PAYMENT_ADD_PAYMENT_METHOD, account.getId(), e.getErrorMessage());
         }
+        return pm.getId();
     }
 
-    //@Override
-    public void updatePaymentGateway(final String accountKey, final CallContext context) 
-    throws PaymentApiException {
 
-        new WithAccountLock<Void>().processAccountWithLock(locker, accountKey, new WithAccountLockCallback<Void>() {
-            @Override
-            public Void doOperation() throws PaymentApiException {
-
-                try {
-                    final PaymentProviderPlugin plugin = getPaymentProviderPlugin(accountKey);
-                    plugin.updatePaymentGateway(accountKey);
-                    return null;
-                } catch (PaymentPluginApiException e) {
-                    throw new PaymentApiException(e, ErrorCode.PAYMENT_UPD_GATEWAY_FAILED, accountKey, e.getMessage());
-                }
+    public List<PaymentMethod> refreshPaymentMethods(String pluginName,
+            Account account, final CallContext context)
+            throws PaymentApiException {
+
+        List<PaymentMethod> result = new LinkedList<PaymentMethod>();
+        PaymentPluginApi pluginApi = null;
+        try {
+            pluginApi = getPaymentProviderPlugin(account.getExternalKey());
+            
+            List<PaymentMethodPlugin> pluginPms = pluginApi.getPaymentMethodDetails(account.getExternalKey());
+            for (PaymentMethodPlugin cur : pluginPms) {
+                PaymentMethod input = new DefaultPaymentMethod(account.getId(), pluginName, cur);
+                PaymentMethodModelDao pmModel = new PaymentMethodModelDao(input.getId(), input.getAccountId(), input.getPluginName(), input.isActive(), input.getPluginDetail().getExternalPaymentMethodId());
+                // STEPH we should insert iwithin one batch
+                paymentDao.insertPaymentMethod(pmModel, context);
+                result.add(input);
             }
-        });
+        } catch (PaymentPluginApiException e) {
+            // STEPH all errors should also take a pluginName
+            throw new PaymentApiException(ErrorCode.PAYMENT_REFRESH_PAYMENT_METHOD, account.getId(), e.getErrorMessage());
+        }
+        return result;
+
+    }
+
+    public List<PaymentMethod> getPaymentMethods(Account account, boolean withPluginDetail) throws PaymentApiException {
+
+        List<PaymentMethodModelDao> paymentMethodModels = paymentDao.getPaymentMethods(account.getId());
+        if (paymentMethodModels.size() == 0) {
+            return Collections.emptyList();
+        }
+        return getPaymentMethodInternal(paymentMethodModels, account.getId(), account.getExternalKey(), withPluginDetail);
+    }
+
+    public PaymentMethod getPaymentMethod(Account account, UUID paymentMethodId, boolean withPluginDetail) 
+    throws PaymentApiException {
+        PaymentMethodModelDao paymentMethodModel = paymentDao.getPaymentMethod(paymentMethodId);
+        if (paymentMethodModel == null) {
+            return null;
+        }
+        List<PaymentMethod> result =  getPaymentMethodInternal(Collections.singletonList(paymentMethodModel), account.getId(), account.getExternalKey(), withPluginDetail);
+        return (result.size() == 0) ? null : result.get(0); 
     }
 
 
-    //@Override
-    public String addPaymentMethod(final String accountKey, final PaymentMethodInfo paymentMethod, final CallContext context) 
+    private List<PaymentMethod> getPaymentMethodInternal(List<PaymentMethodModelDao> paymentMethodModels, UUID accountId, String accountKey, boolean withPluginDetail)
     throws PaymentApiException {
-        
-        return new WithAccountLock<String>().processAccountWithLock(locker, accountKey, new WithAccountLockCallback<String>() {
 
-            @Override
-            public String doOperation() throws PaymentApiException {
 
-                try {
-                final PaymentProviderPlugin plugin = getPaymentProviderPlugin(accountKey);
-                return plugin.addPaymentMethod(accountKey, paymentMethod);
-                } catch (PaymentPluginApiException e) {
-                    throw new PaymentApiException(e, ErrorCode.PAYMENT_ADD_PAYMENT_METHOD, accountKey, e.getMessage());
-                }
+        List<PaymentMethod> result = new ArrayList<PaymentMethod>(paymentMethodModels.size());
+
+        PaymentPluginApi pluginApi = null;
+        try {
+            List<PaymentMethodPlugin> pluginDetails = null;
+
+            if (withPluginDetail) {
+                pluginApi = getPaymentProviderPlugin(accountKey);
+                pluginDetails = pluginApi.getPaymentMethodDetails(accountKey); 
+            }
+            
+            for (PaymentMethodModelDao cur : paymentMethodModels) {
+                PaymentMethod pm = new DefaultPaymentMethod(cur, getPaymentMethodDetail(pluginDetails, cur.getExternalId()));
+                result.add(pm);
             }
-        });
+        } catch (PaymentPluginApiException e) {
+            throw new PaymentApiException(ErrorCode.PAYMENT_GET_PAYMENT_METHODS, accountId, e.getErrorMessage());
+        }
+        return result;
     }
+    
+    
+    private PaymentMethodPlugin getPaymentMethodDetail(List<PaymentMethodPlugin> pluginDetails, String externalId) {
+        
+        if (pluginDetails == null) {
+            return null;
+        }
+        for (PaymentMethodPlugin cur : pluginDetails) {
+            if (cur.getExternalPaymentMethodId().equals(externalId)) {
+                return cur;
+            }
+        }
+        return null;
+    }
+
 
 
-    //@Override
-    public void deletePaymentMethod(final String accountKey, final String paymentMethodId, final CallContext context) 
+
+    public void updatePaymentMethod(Account account, UUID paymentMethodId,
+            PaymentMethodPlugin paymentMethodProps) 
     throws PaymentApiException {
         
-        new WithAccountLock<Void>().processAccountWithLock(locker, accountKey, new WithAccountLockCallback<Void>() {
-
-            @Override
-            public Void doOperation() throws PaymentApiException {
-                
-                try {
-                final PaymentProviderPlugin plugin = getPaymentProviderPlugin(accountKey);
-                plugin.deletePaymentMethod(accountKey, paymentMethodId);
-                return null;
-                } catch (PaymentPluginApiException e) {
-                    throw new PaymentApiException(e, ErrorCode.PAYMENT_DEL_PAYMENT_METHOD, accountKey, e.getMessage());
-                }
-            }
-        });
+        PaymentMethodModelDao paymentMethodModel = paymentDao.getPaymentMethod(paymentMethodId);
+        if (paymentMethodModel == null) {
+            throw new PaymentApiException(ErrorCode.PAYMENT_NO_SUCH_PAYMENT_METHOD, account.getId(), paymentMethodId);
+        }
+
+        PaymentPluginApi pluginApi = null;
+        try {
+            pluginApi = getPaymentProviderPlugin(account.getExternalKey());
+            
+            pluginApi.updatePaymentMethod(account.getExternalKey(), paymentMethodModel.getExternalId(), paymentMethodProps);
+        } catch (PaymentPluginApiException e) {
+            throw new PaymentApiException(ErrorCode.PAYMENT_UPD_PAYMENT_METHOD, account.getId(), e.getErrorMessage());
+        }
     }
 
-    //@Override
-    public PaymentMethodInfo updatePaymentMethod(final String accountKey, final PaymentMethodInfo paymentMethodInfo, final CallContext context) 
+
+    public void deletedPaymentMethod(Account account, UUID paymentMethodId) 
     throws PaymentApiException {
 
-        return new WithAccountLock<PaymentMethodInfo>().processAccountWithLock(locker, accountKey, new WithAccountLockCallback<PaymentMethodInfo>() {
+        PaymentMethodModelDao paymentMethodModel = paymentDao.getPaymentMethod(paymentMethodId);
+        if (paymentMethodModel == null) {
+            throw new PaymentApiException(ErrorCode.PAYMENT_NO_SUCH_PAYMENT_METHOD, account.getId(), paymentMethodId);
+        }
 
-            @Override
-            public PaymentMethodInfo doOperation() throws PaymentApiException {
-                try {
-                    final PaymentProviderPlugin plugin = getPaymentProviderPlugin(accountKey);
-                    return plugin.updatePaymentMethod(accountKey, paymentMethodInfo);
-                }  catch (PaymentPluginApiException e) {
-                    throw new PaymentApiException(e, ErrorCode.PAYMENT_UPD_PAYMENT_METHOD, accountKey, e.getMessage());
-                }
-            }
-        });
+        PaymentPluginApi pluginApi = null;
+        try {
+            pluginApi = getPaymentProviderPlugin(account.getExternalKey());
+
+            pluginApi.deletePaymentMethod(account.getExternalKey(), paymentMethodModel.getExternalId());
+        } catch (PaymentPluginApiException e) {
+            throw new PaymentApiException(ErrorCode.PAYMENT_DEL_PAYMENT_METHOD, account.getId(), e.getErrorMessage());
+        }
+        
     }
+
+    public void setDefaultPaymentMethod(Account account, UUID paymentMethodId) 
+    throws PaymentApiException {
+        
+        PaymentMethodModelDao paymentMethodModel = paymentDao.getPaymentMethod(paymentMethodId);
+        if (paymentMethodModel == null) {
+            throw new PaymentApiException(ErrorCode.PAYMENT_NO_SUCH_PAYMENT_METHOD, account.getId(), paymentMethodId);
+        }
+
+        PaymentPluginApi pluginApi = null;
+        try {
+            pluginApi = getPaymentProviderPlugin(account.getExternalKey());
+            
+            pluginApi.setDefaultPaymentMethod(account.getExternalKey(), paymentMethodModel.getExternalId());
+            
+        } catch (PaymentPluginApiException e) {
+            throw new PaymentApiException(ErrorCode.PAYMENT_UPD_PAYMENT_METHOD, account.getId(), e.getErrorMessage());
+        }
+    }
+    
 }
diff --git a/payment/src/main/java/com/ning/billing/payment/core/PaymentProcessor.java b/payment/src/main/java/com/ning/billing/payment/core/PaymentProcessor.java
index 73151f8..a2d2bd1 100644
--- a/payment/src/main/java/com/ning/billing/payment/core/PaymentProcessor.java
+++ b/payment/src/main/java/com/ning/billing/payment/core/PaymentProcessor.java
@@ -51,7 +51,7 @@ import com.ning.billing.payment.dao.PaymentModelDao;
 import com.ning.billing.payment.dispatcher.PluginDispatcher;
 import com.ning.billing.payment.plugin.api.PaymentInfoPlugin;
 import com.ning.billing.payment.plugin.api.PaymentPluginApiException;
-import com.ning.billing.payment.plugin.api.PaymentProviderPlugin;
+import com.ning.billing.payment.plugin.api.PaymentPluginApi;
 import com.ning.billing.payment.provider.PaymentProviderPluginRegistry;
 import com.ning.billing.payment.retry.FailedPaymentRetryService.FailedPaymentRetryServiceScheduler;
 import com.ning.billing.payment.retry.PluginFailureRetryService.PluginFailureRetryServiceScheduler;
@@ -134,7 +134,7 @@ public class PaymentProcessor extends ProcessorBase {
     public Payment createPayment(final Account account, final UUID invoiceId, final BigDecimal inputAmount , final CallContext context,  final boolean isInstantPayment)
     throws PaymentApiException {
 
-        final PaymentProviderPlugin plugin = getPaymentProviderPlugin(account);
+        final PaymentPluginApi plugin = getPaymentProviderPlugin(account);
 
         try {
             return paymentPluginDispatcher.dispatchWithAccountLock(new CallableWithAccountLock<Payment>(locker,
@@ -158,9 +158,10 @@ public class PaymentProcessor extends ProcessorBase {
             if (isInstantPayment) {
                 throw new PaymentApiException(ErrorCode.PAYMENT_PLUGIN_TIMEOUT, account.getId(), invoiceId);
             } else {
+                log.warn(String.format("Payment from Account %s, Invoice %s timedout", account.getId(), invoiceId));
                 // If we don't crash, plugin thread will complete (and set the correct status)
                 // If we crash before plugin thread completes, we may end up with a UNKNOWN Payment
-                // We would like to return an error so the Bus can retry but limited bu Guava bug
+                // We would like to return an error so the Bus can retry but we are limited bu Guava bug
                 return null;
             }
         }
@@ -203,7 +204,7 @@ public class PaymentProcessor extends ProcessorBase {
             }
 
             final Account account = accountUserApi.getAccountById(payment.getAccountId());
-            final PaymentProviderPlugin plugin = getPaymentProviderPlugin(account);
+            final PaymentPluginApi plugin = getPaymentProviderPlugin(account);
             final CallContext context = factory.createCallContext("PaymentRetry", CallOrigin.INTERNAL, UserType.SYSTEM);
             
             voidPluginDispatcher.dispatchWithAccountLock(new CallableWithAccountLock<Void>(locker,
@@ -245,11 +246,12 @@ public class PaymentProcessor extends ProcessorBase {
         } catch (PaymentApiException e) {
             log.info(String.format("Failed to retry payment for paymentId %s", paymentId));
         } catch (TimeoutException e) {
+            log.warn(String.format("Retry for payment %s timedout", paymentId));
             // STEPH we should throw some exception so NotificationQ does not clear status and retries us
         }
     }
 
-    private Payment processNewPaymentWithAccountLocked(PaymentProviderPlugin plugin, Account account, Invoice invoice,
+    private Payment processNewPaymentWithAccountLocked(PaymentPluginApi plugin, Account account, Invoice invoice,
             BigDecimal requestedAmount, boolean isInstantPayment, CallContext context) throws PaymentApiException {
         
         final boolean scheduleRetryForPayment = !isInstantPayment;
@@ -260,7 +262,7 @@ public class PaymentProcessor extends ProcessorBase {
         return processPaymentWithAccountLocked(plugin, account, invoice, savedPayment, attempt, isInstantPayment, context);
     }
     
-    private Payment processRetryPaymentWithAccountLocked(PaymentProviderPlugin plugin, Account account, Invoice invoice, PaymentModelDao payment,
+    private Payment processRetryPaymentWithAccountLocked(PaymentPluginApi plugin, Account account, Invoice invoice, PaymentModelDao payment,
             BigDecimal requestedAmount, CallContext context) throws PaymentApiException {
         final boolean scheduleRetryForPayment = true;
         PaymentAttemptModelDao attempt = new PaymentAttemptModelDao(account.getId(), invoice.getId(), payment.getId(), clock.getUTCNow(), requestedAmount);
@@ -269,7 +271,7 @@ public class PaymentProcessor extends ProcessorBase {
     }
 
     
-    private Payment processPaymentWithAccountLocked(PaymentProviderPlugin plugin, Account account, Invoice invoice,
+    private Payment processPaymentWithAccountLocked(PaymentPluginApi plugin, Account account, Invoice invoice,
             PaymentModelDao paymentInput, PaymentAttemptModelDao attemptInput, boolean isInstantPayment, CallContext context) throws PaymentApiException {
         
         BusEvent event = null;
@@ -291,7 +293,6 @@ public class PaymentProcessor extends ProcessorBase {
                 lastAttempt = allAttempts.get(allAttempts.size() - 1);
                 payment = paymentDao.getPayment(paymentInput.getId());
                 
-                // STEPH should we notify in failure case scenario as well?
                 invoicePaymentApi.notifyOfPaymentAttempt(invoice.getId(),
                         paymentStatus == PaymentStatus.SUCCESS ? payment.getAmount() : null,
                         paymentStatus == PaymentStatus.SUCCESS ? payment.getCurrency() : null,
diff --git a/payment/src/main/java/com/ning/billing/payment/core/ProcessorBase.java b/payment/src/main/java/com/ning/billing/payment/core/ProcessorBase.java
index 080dc60..bbcd3b7 100644
--- a/payment/src/main/java/com/ning/billing/payment/core/ProcessorBase.java
+++ b/payment/src/main/java/com/ning/billing/payment/core/ProcessorBase.java
@@ -28,7 +28,7 @@ import com.ning.billing.account.api.Account;
 import com.ning.billing.account.api.AccountApiException;
 import com.ning.billing.account.api.AccountUserApi;
 import com.ning.billing.payment.api.PaymentApiException;
-import com.ning.billing.payment.plugin.api.PaymentProviderPlugin;
+import com.ning.billing.payment.plugin.api.PaymentPluginApi;
 import com.ning.billing.payment.provider.PaymentProviderPluginRegistry;
 import com.ning.billing.util.bus.Bus;
 import com.ning.billing.util.bus.BusEvent;
@@ -63,7 +63,7 @@ public abstract class ProcessorBase {
     }
     
     
-    protected PaymentProviderPlugin getPaymentProviderPlugin(String accountKey) {
+    protected PaymentPluginApi getPaymentProviderPlugin(String accountKey) {
 
         String paymentProviderName = null;
         if (accountKey != null) {
@@ -78,7 +78,7 @@ public abstract class ProcessorBase {
         return pluginRegistry.getPlugin(paymentProviderName);
     }
     
-    protected PaymentProviderPlugin getPaymentProviderPlugin(Account account) {
+    protected PaymentPluginApi getPaymentProviderPlugin(Account account) {
         String paymentProviderName = null;
 
         if (account != null) {
diff --git a/payment/src/main/java/com/ning/billing/payment/dao/PaymentDao.java b/payment/src/main/java/com/ning/billing/payment/dao/PaymentDao.java
index efbb252..e01a905 100644
--- a/payment/src/main/java/com/ning/billing/payment/dao/PaymentDao.java
+++ b/payment/src/main/java/com/ning/billing/payment/dao/PaymentDao.java
@@ -44,8 +44,6 @@ public interface PaymentDao {
     public PaymentModelDao getPayment(final UUID paymentId);    
 
     public List<PaymentAttemptModelDao> getAttemptsForPayment(final UUID paymentId);
-
-
     
     public PaymentMethodModelDao insertPaymentMethod(final PaymentMethodModelDao paymentMethod, final CallContext context);
     
diff --git a/payment/src/main/java/com/ning/billing/payment/dao/PaymentMethodHistoryBinder.java b/payment/src/main/java/com/ning/billing/payment/dao/PaymentMethodHistoryBinder.java
index 47376d4..988964e 100644
--- a/payment/src/main/java/com/ning/billing/payment/dao/PaymentMethodHistoryBinder.java
+++ b/payment/src/main/java/com/ning/billing/payment/dao/PaymentMethodHistoryBinder.java
@@ -45,7 +45,8 @@ public @interface PaymentMethodHistoryBinder {
                     q.bind("id", paymentMethod.getId().toString());
                     q.bind("isActive", paymentMethod.isActive());                    
                     q.bind("accountId", paymentMethod.getAccountId().toString());            
-                    q.bind("pluginName", paymentMethod.getPluginName());            
+                    q.bind("pluginName", paymentMethod.getPluginName()); 
+                    q.bind("externalId", paymentMethod.getExternalId());
                 }
             };
         }
diff --git a/payment/src/main/java/com/ning/billing/payment/dao/PaymentMethodModelDao.java b/payment/src/main/java/com/ning/billing/payment/dao/PaymentMethodModelDao.java
index 0e59500..b3dadd5 100644
--- a/payment/src/main/java/com/ning/billing/payment/dao/PaymentMethodModelDao.java
+++ b/payment/src/main/java/com/ning/billing/payment/dao/PaymentMethodModelDao.java
@@ -24,13 +24,15 @@ public class PaymentMethodModelDao extends EntityBase {
     private final UUID accountId;
     private final String pluginName;
     private final Boolean isActive;
+    private final String externalId;
     
-    public PaymentMethodModelDao(UUID id, UUID accountId, String pluginName,
-            Boolean isActive) {
+    public PaymentMethodModelDao(final UUID id, final UUID accountId, final String pluginName,
+            final Boolean isActive, final String externalId) {
         super(id);
         this.accountId = accountId;
         this.pluginName = pluginName;
         this.isActive = isActive;
+        this.externalId = externalId;
     }
 
     public UUID getAccountId() {
@@ -44,4 +46,8 @@ public class PaymentMethodModelDao extends EntityBase {
     public Boolean isActive() {
         return isActive;
     }
+
+    public String getExternalId() {
+        return externalId;
+    }
 }
diff --git a/payment/src/main/java/com/ning/billing/payment/dao/PaymentMethodSqlDao.java b/payment/src/main/java/com/ning/billing/payment/dao/PaymentMethodSqlDao.java
index 633bc32..4912901 100644
--- a/payment/src/main/java/com/ning/billing/payment/dao/PaymentMethodSqlDao.java
+++ b/payment/src/main/java/com/ning/billing/payment/dao/PaymentMethodSqlDao.java
@@ -72,6 +72,7 @@ public interface PaymentMethodSqlDao extends Transactional<PaymentMethodSqlDao>,
             stmt.bind("accountId", method.getAccountId().toString());            
             stmt.bind("pluginName", method.getPluginName());            
             stmt.bind("isActive", method.isActive());            
+            stmt.bind("externalId", method.getExternalId());              
         }
     }
     
@@ -84,7 +85,8 @@ public interface PaymentMethodSqlDao extends Transactional<PaymentMethodSqlDao>,
             UUID accountId = getUUID(rs, "account_id");
             String pluginName = rs.getString("plugin_name");
             Boolean isActive = rs.getBoolean("is_active");
-            return new PaymentMethodModelDao(id, accountId, pluginName, isActive);
+            String externalId = rs.getString("external_id");
+            return new PaymentMethodModelDao(id, accountId, pluginName, isActive, externalId);
         }
     }
 }
diff --git a/payment/src/main/java/com/ning/billing/payment/glue/DefaultPaymentService.java b/payment/src/main/java/com/ning/billing/payment/glue/DefaultPaymentService.java
index f6ef52d..1a774df 100644
--- a/payment/src/main/java/com/ning/billing/payment/glue/DefaultPaymentService.java
+++ b/payment/src/main/java/com/ning/billing/payment/glue/DefaultPaymentService.java
@@ -22,9 +22,9 @@ import org.slf4j.LoggerFactory;
 import com.google.inject.Inject;
 import com.ning.billing.lifecycle.LifecycleHandlerType;
 import com.ning.billing.lifecycle.LifecycleHandlerType.LifecycleLevel;
-import com.ning.billing.payment.InvoiceHandler;
 import com.ning.billing.payment.api.PaymentApi;
 import com.ning.billing.payment.api.PaymentService;
+import com.ning.billing.payment.bus.InvoiceHandler;
 import com.ning.billing.payment.retry.FailedPaymentRetryService;
 import com.ning.billing.payment.retry.PluginFailureRetryService;
 import com.ning.billing.util.bus.Bus;
diff --git a/payment/src/main/java/com/ning/billing/payment/glue/PaymentModule.java b/payment/src/main/java/com/ning/billing/payment/glue/PaymentModule.java
index c559720..d17731f 100644
--- a/payment/src/main/java/com/ning/billing/payment/glue/PaymentModule.java
+++ b/payment/src/main/java/com/ning/billing/payment/glue/PaymentModule.java
@@ -26,10 +26,10 @@ import org.skife.config.ConfigurationObjectFactory;
 import com.google.inject.AbstractModule;
 import com.google.inject.name.Names;
 import com.ning.billing.config.PaymentConfig;
-import com.ning.billing.payment.InvoiceHandler;
 import com.ning.billing.payment.api.DefaultPaymentApi;
 import com.ning.billing.payment.api.PaymentApi;
 import com.ning.billing.payment.api.PaymentService;
+import com.ning.billing.payment.bus.InvoiceHandler;
 import com.ning.billing.payment.core.AccountProcessor;
 import com.ning.billing.payment.core.PaymentMethodProcessor;
 import com.ning.billing.payment.core.PaymentProcessor;
diff --git a/payment/src/main/java/com/ning/billing/payment/provider/DefaultPaymentProviderPluginRegistry.java b/payment/src/main/java/com/ning/billing/payment/provider/DefaultPaymentProviderPluginRegistry.java
index d10e4d3..3c7f9f0 100644
--- a/payment/src/main/java/com/ning/billing/payment/provider/DefaultPaymentProviderPluginRegistry.java
+++ b/payment/src/main/java/com/ning/billing/payment/provider/DefaultPaymentProviderPluginRegistry.java
@@ -17,30 +17,33 @@
 package com.ning.billing.payment.provider;
 
 import java.util.Map;
+import java.util.Set;
 import java.util.concurrent.ConcurrentHashMap;
 
 import org.apache.commons.lang.StringUtils;
 
 import com.google.inject.Inject;
 import com.ning.billing.config.PaymentConfig;
-import com.ning.billing.payment.plugin.api.PaymentProviderPlugin;
+import com.ning.billing.payment.plugin.api.PaymentPluginApi;
 
 
 public class DefaultPaymentProviderPluginRegistry implements PaymentProviderPluginRegistry {
     private final String defaultPlugin;
-    private final Map<String, PaymentProviderPlugin> pluginsByName = new ConcurrentHashMap<String, PaymentProviderPlugin>();
+    private final Map<String, PaymentPluginApi> pluginsByName = new ConcurrentHashMap<String, PaymentPluginApi>();
 
     @Inject
     public DefaultPaymentProviderPluginRegistry(PaymentConfig config) {
         this.defaultPlugin = config.getDefaultPaymentProvider();
     }
 
-    public void register(PaymentProviderPlugin plugin, String name) {
+    @Override
+    public void register(PaymentPluginApi plugin, String name) {
         pluginsByName.put(name.toLowerCase(), plugin);
     }
 
-    public PaymentProviderPlugin getPlugin(String name) {
-        PaymentProviderPlugin plugin = pluginsByName.get(StringUtils.defaultIfEmpty(name, defaultPlugin).toLowerCase());
+    @Override
+    public PaymentPluginApi getPlugin(String name) {
+        PaymentPluginApi plugin = pluginsByName.get(StringUtils.defaultIfEmpty(name, defaultPlugin).toLowerCase());
 
         if (plugin == null) {
             throw new IllegalArgumentException("No payment provider plugin is configured for " + name);
@@ -48,4 +51,9 @@ public class DefaultPaymentProviderPluginRegistry implements PaymentProviderPlug
 
         return plugin;
     }
+    
+    @Override
+    public Set<String> getRegisteredPluginNames() {
+        return pluginsByName.keySet();
+    }
 }
diff --git a/payment/src/main/java/com/ning/billing/payment/provider/NoOpPaymentProviderPlugin.java b/payment/src/main/java/com/ning/billing/payment/provider/NoOpPaymentProviderPlugin.java
index dcc24a8..b9605c2 100644
--- a/payment/src/main/java/com/ning/billing/payment/provider/NoOpPaymentProviderPlugin.java
+++ b/payment/src/main/java/com/ning/billing/payment/provider/NoOpPaymentProviderPlugin.java
@@ -24,15 +24,13 @@ import org.joda.time.DateTime;
 import org.joda.time.DateTimeZone;
 
 import com.ning.billing.account.api.Account;
-import com.ning.billing.invoice.api.Invoice;
-import com.ning.billing.payment.api.Payment;
-import com.ning.billing.payment.api.PaymentMethodInfo;
+import com.ning.billing.payment.api.PaymentMethodPlugin;
 import com.ning.billing.payment.plugin.api.PaymentInfoPlugin;
 import com.ning.billing.payment.plugin.api.PaymentPluginApiException;
 import com.ning.billing.payment.plugin.api.PaymentProviderAccount;
-import com.ning.billing.payment.plugin.api.PaymentProviderPlugin;
+import com.ning.billing.payment.plugin.api.PaymentPluginApi;
 
-public class NoOpPaymentProviderPlugin implements PaymentProviderPlugin {
+public class NoOpPaymentProviderPlugin implements PaymentPluginApi {
 
     private boolean makeAllInvoicesFail;
 
@@ -103,52 +101,62 @@ public class NoOpPaymentProviderPlugin implements PaymentProviderPlugin {
             throws PaymentPluginApiException {
     }
 
+
     @Override
-    public PaymentMethodInfo getPaymentMethodInfo(String paymentMethodId)
-            throws PaymentPluginApiException {
-        return null;
+    public void deletePaymentMethod(String accountKey, String paymentMethodId)
+    throws PaymentPluginApiException {
     }
 
     @Override
-    public List<PaymentMethodInfo> getPaymentMethods(String accountKey)
+    public void updatePaymentProviderAccountExistingContact(Account account)
             throws PaymentPluginApiException {
-        return null;
+
     }
 
     @Override
-    public String addPaymentMethod(String accountKey,
-            PaymentMethodInfo paymentMethod) throws PaymentPluginApiException {
-        return null;
+    public void updatePaymentProviderAccountWithNewContact(Account account)
+            throws PaymentPluginApiException {
+
     }
 
     @Override
-    public PaymentMethodInfo updatePaymentMethod(String accountKey,
-            PaymentMethodInfo paymentMethodInfo)
+    public List<PaymentInfoPlugin> processRefund(Account account)
             throws PaymentPluginApiException {
         return null;
     }
 
     @Override
-    public void deletePaymentMethod(String accountKey, String paymentMethodId)
-    throws PaymentPluginApiException {
+    public String getName() {
+        return null;
     }
 
     @Override
-    public void updatePaymentProviderAccountExistingContact(Account account)
+    public List<PaymentMethodPlugin> getPaymentMethodDetails(String accountKey)
             throws PaymentPluginApiException {
-
+        return null;
     }
 
     @Override
-    public void updatePaymentProviderAccountWithNewContact(Account account)
+    public PaymentMethodPlugin getPaymentMethodDetail(String accountKey, String externalPaymentId)
             throws PaymentPluginApiException {
-
+        return null;
     }
 
     @Override
-    public List<PaymentInfoPlugin> processRefund(Account account)
+    public String addPaymentMethod(String accountKey,
+            PaymentMethodPlugin paymentMethodProps, boolean setDefault)
             throws PaymentPluginApiException {
         return null;
     }
 
+    @Override
+    public void updatePaymentMethod(String accountKey,
+            String externalPaymentId, PaymentMethodPlugin paymentMethodProps)
+            throws PaymentPluginApiException {
+    }
+
+    @Override
+    public void setDefaultPaymentMethod(String accountKey,
+            String externalPaymentId) throws PaymentPluginApiException {
+    }
 }
diff --git a/payment/src/main/resources/com/ning/billing/payment/dao/PaymentMethodSqlDao.sql.stg b/payment/src/main/resources/com/ning/billing/payment/dao/PaymentMethodSqlDao.sql.stg
index 2498d1c..27640a6 100644
--- a/payment/src/main/resources/com/ning/billing/payment/dao/PaymentMethodSqlDao.sql.stg
+++ b/payment/src/main/resources/com/ning/billing/payment/dao/PaymentMethodSqlDao.sql.stg
@@ -5,6 +5,7 @@ paymentMethodFields(prefix) ::= <<
     <prefix>account_id,
     <prefix>plugin_name,
     <prefix>is_active,  
+    <prefix>external_id,
     <prefix>created_by,
     <prefix>created_date,
     <prefix>updated_by,
@@ -13,7 +14,7 @@ paymentMethodFields(prefix) ::= <<
 
 insertPaymentMethod() ::= <<
     INSERT INTO payment_methods (<paymentMethodFields()>)
-    VALUES (:id, :accountId, :pluginName , :isActive ,:userName, :createdDate, :userName, :createdDate);
+    VALUES (:id, :accountId, :pluginName , :isActive, :externalId, :userName, :createdDate, :userName, :createdDate);
 >>
 
 markPaymentMethodAsDeleted() ::= <<
@@ -45,7 +46,8 @@ historyFields(prefix) ::= <<
     <prefix>id,
     <prefix>account_id,
     <prefix>plugin_name,
-    <prefix>is_active,  
+    <prefix>is_active,
+    <prefix>external_id,  
     <prefix>created_by,
     <prefix>created_date,
     <prefix>updated_by,
@@ -54,7 +56,7 @@ historyFields(prefix) ::= <<
 
 insertHistoryFromTransaction() ::= <<
     INSERT INTO payment_method_history (<historyFields()>)
-    VALUES (:recordId, :id, :accountId, :pluginName , :isActive ,:userName, :createdDate, :userName, :createdDate);
+    VALUES (:recordId, :id, :accountId, :pluginName , :isActive, :externalId ,:userName, :createdDate, :userName, :createdDate);
 >>
 
 getHistoryRecordId() ::= <<
diff --git a/payment/src/main/resources/com/ning/billing/payment/ddl.sql b/payment/src/main/resources/com/ning/billing/payment/ddl.sql
index 3ee5a80..ba4ff80 100644
--- a/payment/src/main/resources/com/ning/billing/payment/ddl.sql
+++ b/payment/src/main/resources/com/ning/billing/payment/ddl.sql
@@ -80,7 +80,8 @@ CREATE TABLE payment_methods (
     id char(36) NOT NULL,
     account_id char(36) COLLATE utf8_bin NOT NULL,
     plugin_name varchar(20) DEFAULT NULL,
-    is_active bool DEFAULT true,   
+    is_active bool DEFAULT true, 
+    external_id varchar(64), 
     created_by varchar(50) NOT NULL,
     created_date datetime NOT NULL,
     updated_by varchar(50) NOT NULL,
@@ -97,7 +98,8 @@ CREATE TABLE payment_method_history (
     id char(36) NOT NULL,
     account_id char(36) COLLATE utf8_bin NOT NULL,
     plugin_name varchar(20) DEFAULT NULL, 
-    is_active bool DEFAULT true,              
+    is_active bool DEFAULT true, 
+    external_id varchar(64),                  
     created_by varchar(50) NOT NULL,
     created_date datetime NOT NULL,
     updated_by varchar(50) NOT NULL,
diff --git a/payment/src/test/java/com/ning/billing/payment/api/DefaultPaymentMethodPlugin.java b/payment/src/test/java/com/ning/billing/payment/api/DefaultPaymentMethodPlugin.java
new file mode 100644
index 0000000..0250c10
--- /dev/null
+++ b/payment/src/test/java/com/ning/billing/payment/api/DefaultPaymentMethodPlugin.java
@@ -0,0 +1,80 @@
+/* 
+ * Copyright 2010-2011 Ning, Inc.
+ *
+ * Ning 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 com.ning.billing.payment.api;
+
+import java.util.List;
+import java.util.UUID;
+
+public class DefaultPaymentMethodPlugin implements PaymentMethodPlugin {
+
+    private String externalId;
+    private boolean isDefault;
+    private List<PaymentMethodKVInfo> props;
+    
+    public DefaultPaymentMethodPlugin(PaymentMethodPlugin src) {
+        this.externalId = UUID.randomUUID().toString();
+        this.isDefault = src.isDefaultPaymentMethod();
+        this.props = src.getProperties();
+    }
+    
+    public DefaultPaymentMethodPlugin(String externalId, boolean isDefault,
+            List<PaymentMethodKVInfo> props) {
+        super();
+        this.externalId = externalId;
+        this.isDefault = isDefault;
+        this.props = props;
+    }
+
+    @Override
+    public String getExternalPaymentMethodId() {
+        return externalId;
+    }
+
+    @Override
+    public boolean isDefaultPaymentMethod() {
+        return isDefault;
+    }
+
+    @Override
+    public List<PaymentMethodKVInfo> getProperties() {
+        return props;
+    }
+
+    public void setExternalId(String externalId) {
+        this.externalId = externalId;
+    }
+
+    public void setDefault(boolean isDefault) {
+        this.isDefault = isDefault;
+    }
+
+    public void setProps(List<PaymentMethodKVInfo> props) {
+        this.props = props;
+    }
+
+    @Override
+    public String getValueString(String key) {
+        if (props == null) {
+            return null;
+        }
+        for (PaymentMethodKVInfo cur : props) {
+            if (cur.getKey().equals(key)) {
+                return cur.getValue().toString();
+            }
+        }
+        return null;
+    }
+}
diff --git a/payment/src/test/java/com/ning/billing/payment/api/TestPaymentApi.java b/payment/src/test/java/com/ning/billing/payment/api/TestPaymentApi.java
index 9b963c0..aecdc23 100644
--- a/payment/src/test/java/com/ning/billing/payment/api/TestPaymentApi.java
+++ b/payment/src/test/java/com/ning/billing/payment/api/TestPaymentApi.java
@@ -180,43 +180,5 @@ public class TestPaymentApi {
         }
     }
 
-    private PaymentProviderAccount setupAccountWithPaypalPaymentMethod() throws Exception  {
-        final Account account = testHelper.createTestPayPalAccount();
-        paymentApi.createPaymentProviderAccount(account, context);
-
-        String accountKey = account.getExternalKey();
-        return paymentApi.getPaymentProviderAccount(accountKey);
-    }
-
-    @Test(enabled=true)
-    public void testCreatePaypalPaymentMethod() throws Exception  {
-        PaymentProviderAccount account = setupAccountWithPaypalPaymentMethod();
-        assertNotNull(account);
-        paymentApi.getPaymentMethods(account.getAccountKey());
-    }
-
-    @Test(enabled=true)
-    public void testUpdatePaymentProviderAccountContact() throws Exception {
-        final Account account = testHelper.createTestPayPalAccount();
-        paymentApi.createPaymentProviderAccount(account, context);
-
-        Account updatedAccount = BrainDeadProxyFactory.createBrainDeadProxyFor(Account.class);
-        ZombieControl zombieAccount = (ZombieControl) updatedAccount;
-        zombieAccount.addResult("getId", account.getId());
-        zombieAccount.addResult("getName", "Tester " + RandomStringUtils.randomAlphanumeric(10));
-        zombieAccount.addResult("getFirstNameLength", 6);
-        zombieAccount.addResult("getExternalKey", account.getExternalKey());
-        zombieAccount.addResult("getPhone", "888-888-" + RandomStringUtils.randomNumeric(4));
-        zombieAccount.addResult("getEmail", account.getEmail());
-        zombieAccount.addResult("getCurrency", account.getCurrency());
-        zombieAccount.addResult("getBillCycleDay", account.getBillCycleDay());
-
-        paymentApi.updatePaymentProviderAccountContact(updatedAccount.getExternalKey(), context);
-    }
-
-    @Test(enabled=true)
-    public void testCannotDeleteDefaultPaymentMethod() throws Exception  {
-        PaymentProviderAccount account = setupAccountWithPaypalPaymentMethod();
-        paymentApi.deletePaymentMethod(account.getAccountKey(), account.getDefaultPaymentMethodId(), context);
-    }
+    
 }
diff --git a/payment/src/test/java/com/ning/billing/payment/dao/TestPaymentDao.java b/payment/src/test/java/com/ning/billing/payment/dao/TestPaymentDao.java
index 99816db..00390e0 100644
--- a/payment/src/test/java/com/ning/billing/payment/dao/TestPaymentDao.java
+++ b/payment/src/test/java/com/ning/billing/payment/dao/TestPaymentDao.java
@@ -241,8 +241,9 @@ public class TestPaymentDao {
         UUID accountId = UUID.randomUUID();
         String pluginName = "nobody";
         Boolean isActive = Boolean.TRUE;
+        String externalPaymentId = UUID.randomUUID().toString();
         
-        PaymentMethodModelDao method = new PaymentMethodModelDao(paymentMethodId, accountId, pluginName, isActive);
+        PaymentMethodModelDao method = new PaymentMethodModelDao(paymentMethodId, accountId, pluginName, isActive, externalPaymentId);
         
         PaymentMethodModelDao savedMethod = paymentDao.insertPaymentMethod(method, context);
         assertEquals(savedMethod.getId(), paymentMethodId);
@@ -257,6 +258,7 @@ public class TestPaymentDao {
         assertEquals(savedMethod.getAccountId(), accountId);        
         assertEquals(savedMethod.getPluginName(), pluginName);
         assertEquals(savedMethod.isActive(), isActive);
+        assertEquals(savedMethod.getExternalId(), externalPaymentId);
         
     }
 }
diff --git a/payment/src/test/java/com/ning/billing/payment/provider/MockPaymentProviderPlugin.java b/payment/src/test/java/com/ning/billing/payment/provider/MockPaymentProviderPlugin.java
index e83e370..c7247ab 100644
--- a/payment/src/test/java/com/ning/billing/payment/provider/MockPaymentProviderPlugin.java
+++ b/payment/src/test/java/com/ning/billing/payment/provider/MockPaymentProviderPlugin.java
@@ -17,9 +17,7 @@
 package com.ning.billing.payment.provider;
 
 import java.math.BigDecimal;
-import java.math.RoundingMode;
-import java.util.ArrayList;
-import java.util.Collection;
+import java.util.LinkedList;
 import java.util.List;
 import java.util.Map;
 import java.util.UUID;
@@ -28,33 +26,28 @@ import java.util.concurrent.atomic.AtomicBoolean;
 
 import org.apache.commons.lang.RandomStringUtils;
 
-import com.google.common.base.Predicate;
-import com.google.common.collect.Collections2;
 import com.google.inject.Inject;
 import com.ning.billing.account.api.Account;
-import com.ning.billing.invoice.api.Invoice;
-import com.ning.billing.payment.api.CreditCardPaymentMethodInfo;
-import com.ning.billing.payment.api.DefaultPaymentInfoEvent;
-import com.ning.billing.payment.api.Payment;
-import com.ning.billing.payment.api.PaymentInfoEvent;
-import com.ning.billing.payment.api.PaymentMethodInfo;
-import com.ning.billing.payment.api.PaypalPaymentMethodInfo;
+import com.ning.billing.payment.api.DefaultPaymentMethodPlugin;
+import com.ning.billing.payment.api.PaymentMethodPlugin;
 import com.ning.billing.payment.plugin.api.MockPaymentInfoPlugin;
 import com.ning.billing.payment.plugin.api.PaymentInfoPlugin;
 import com.ning.billing.payment.plugin.api.PaymentPluginApiException;
 import com.ning.billing.payment.plugin.api.PaymentProviderAccount;
-import com.ning.billing.payment.plugin.api.PaymentProviderPlugin;
+import com.ning.billing.payment.plugin.api.PaymentPluginApi;
 import com.ning.billing.payment.plugin.api.PaymentInfoPlugin.PaymentPluginStatus;
 import com.ning.billing.util.clock.Clock;
 
-public class MockPaymentProviderPlugin implements PaymentProviderPlugin {
+public class MockPaymentProviderPlugin implements PaymentPluginApi {
     
     private final AtomicBoolean makeNextInvoiceFailWithError = new AtomicBoolean(false);
     private final AtomicBoolean makeNextInvoiceFailWithException = new AtomicBoolean(false);
     private final AtomicBoolean makeAllInvoicesFailWithException = new AtomicBoolean(false);
     private final Map<UUID, PaymentInfoPlugin> payments = new ConcurrentHashMap<UUID, PaymentInfoPlugin>();
+
+    private final Map<String, List<PaymentMethodPlugin>> paymentMethods = new ConcurrentHashMap<String, List<PaymentMethodPlugin>>();
+
     private final Map<String, PaymentProviderAccount> accounts = new ConcurrentHashMap<String, PaymentProviderAccount>();
-    private final Map<String, PaymentMethodInfo> paymentMethods = new ConcurrentHashMap<String, PaymentMethodInfo>();
     private final Clock clock;
 
     @Inject
@@ -133,52 +126,20 @@ public class MockPaymentProviderPlugin implements PaymentProviderPlugin {
     }
 
     @Override
-    public String addPaymentMethod(String accountKey, PaymentMethodInfo paymentMethod)  throws PaymentPluginApiException {
-        if (paymentMethod != null) {
-            PaymentProviderAccount account = accounts.get(accountKey);
-
-            if (account != null && account.getId() != null) {
-                String existingDefaultMethod = account.getDefaultPaymentMethodId();
-
-                String paymentMethodId = "5556-66-77-rr";
-                boolean shouldBeDefault = Boolean.TRUE.equals(paymentMethod.getDefaultMethod()) || existingDefaultMethod == null;
-                PaymentMethodInfo realPaymentMethod = null;
-
-                if (paymentMethod instanceof PaypalPaymentMethodInfo) {
-                    PaypalPaymentMethodInfo paypalPaymentMethod = (PaypalPaymentMethodInfo)paymentMethod;
-
-                    realPaymentMethod = new PaypalPaymentMethodInfo.Builder(paypalPaymentMethod)
-                    .setId(paymentMethodId)
-                    .setAccountId(accountKey)
-                    .setDefaultMethod(shouldBeDefault)
-                    .setBaid(paypalPaymentMethod.getBaid())
-                    .setEmail(paypalPaymentMethod.getEmail())
-                    .build();
-                }
-                else if (paymentMethod instanceof CreditCardPaymentMethodInfo) {
-                    CreditCardPaymentMethodInfo ccPaymentMethod = (CreditCardPaymentMethodInfo)paymentMethod;
-                    realPaymentMethod = new CreditCardPaymentMethodInfo.Builder(ccPaymentMethod).setId(paymentMethodId).build();
-                }
-                if (realPaymentMethod == null) {
-                    throw new PaymentPluginApiException("", "Payment method " + paymentMethod.getType() + " not supported by the plugin");                    
-                }
-                else {
-                    if (shouldBeDefault) {
-                        setDefaultPaymentMethodOnAccount(account, paymentMethodId);
-                    }
-                    paymentMethods.put(paymentMethodId, realPaymentMethod);
-                    return paymentMethodId;
-                }
-            }
-            else {
-                throw new PaymentPluginApiException("", "Could not retrieve account for accountKey " + accountKey);                    
-            }
-        }
-        else {
-            throw new PaymentPluginApiException("", "Could not create add payment method " + paymentMethod + " for " + accountKey);
+    public String addPaymentMethod(String accountKey, PaymentMethodPlugin paymentMethodProps, boolean setDefault)  throws PaymentPluginApiException {
+        PaymentMethodPlugin realWithID = new DefaultPaymentMethodPlugin(paymentMethodProps);
+        List<PaymentMethodPlugin> pms = paymentMethods.get(accountKey);
+        if (pms == null) {
+            pms = new LinkedList<PaymentMethodPlugin>();
+            paymentMethods.put(accountKey, pms);
         }
+        pms.add(realWithID);
+        
+        
+        return realWithID.getExternalPaymentMethodId();
     }
 
+    /*
     public void setDefaultPaymentMethodOnAccount(PaymentProviderAccount account, String paymentMethodId) {
         if (paymentMethodId != null && account != null) {
             accounts.put(account.getAccountKey(),
@@ -204,83 +165,102 @@ public class MockPaymentProviderPlugin implements PaymentProviderPlugin {
             }
         }
     }
+    *
+    *
+    */
 
     @Override
-    public PaymentMethodInfo updatePaymentMethod(String accountKey, PaymentMethodInfo paymentMethod)  throws PaymentPluginApiException {
-        if (paymentMethod != null) {
-            PaymentMethodInfo realPaymentMethod = null;
-
-            if (paymentMethod instanceof PaypalPaymentMethodInfo) {
-                PaypalPaymentMethodInfo paypalPaymentMethod = (PaypalPaymentMethodInfo)paymentMethod;
-                realPaymentMethod = new PaypalPaymentMethodInfo.Builder(paypalPaymentMethod).build();
-            }
-            else if (paymentMethod instanceof CreditCardPaymentMethodInfo) {
-                CreditCardPaymentMethodInfo ccPaymentMethod = (CreditCardPaymentMethodInfo)paymentMethod;
-                realPaymentMethod = new CreditCardPaymentMethodInfo.Builder(ccPaymentMethod).build();
-            }
-            if (realPaymentMethod == null) {
-                throw new PaymentPluginApiException("", "Payment method " + paymentMethod.getType() + " not supported by the plugin");
-            }
-            else {
-                paymentMethods.put(paymentMethod.getId(), paymentMethod);
-                return realPaymentMethod;
-            }
-        }
-        else {
-            throw new PaymentPluginApiException("", "Could not create add payment method " + paymentMethod + " for " + accountKey);            
+    public void updatePaymentMethod(String accountKey, String externalPaymentId, PaymentMethodPlugin paymentMethodProps)
+        throws PaymentPluginApiException {
+        DefaultPaymentMethodPlugin e = getPaymentMethod(accountKey, externalPaymentId);
+        if (e != null) {
+            e.setProps(paymentMethodProps.getProperties());
         }
     }
 
     @Override
     public void deletePaymentMethod(String accountKey, String paymentMethodId)  throws PaymentPluginApiException {
-        PaymentMethodInfo paymentMethodInfo = paymentMethods.get(paymentMethodId);
-        if (paymentMethodInfo != null) {
-            if (Boolean.FALSE.equals(paymentMethodInfo.getDefaultMethod()) || paymentMethodInfo.getDefaultMethod() == null) {
-                if (paymentMethods.remove(paymentMethodId) == null) {
-                    throw new PaymentPluginApiException("", "Did not get any result back");
+
+        PaymentMethodPlugin toBeDeleted = null;
+        List<PaymentMethodPlugin> pms = paymentMethods.get(accountKey);
+        if (pms != null) {
+
+            for (PaymentMethodPlugin cur : pms) {
+                if (cur.getExternalPaymentMethodId().equals(paymentMethodId)) {
+                    toBeDeleted = cur;
+                    break;
                 }
-        } else {
-                throw new PaymentPluginApiException("", "Cannot delete default payment method");                
             }
         }
-        return;
+        if (toBeDeleted != null) {
+            pms.remove(toBeDeleted);
+        }
     }
 
     @Override
-    public PaymentMethodInfo getPaymentMethodInfo(String paymentMethodId)  throws PaymentPluginApiException {
-        if (paymentMethodId == null) {
-            throw new PaymentPluginApiException("", "Could not retrieve payment method for paymentMethodId " + paymentMethodId);
-        }
-        return paymentMethods.get(paymentMethodId);
+    public List<PaymentMethodPlugin> getPaymentMethodDetails(String accountKey)
+            throws PaymentPluginApiException {
+        return paymentMethods.get(accountKey);
     }
 
     @Override
-    public List<PaymentMethodInfo> getPaymentMethods(final String accountKey) throws PaymentPluginApiException {
-
-        Collection<PaymentMethodInfo> filteredPaymentMethods = Collections2.filter(paymentMethods.values(), new Predicate<PaymentMethodInfo>() {
-            @Override
-            public boolean apply(PaymentMethodInfo input) {
-                return accountKey.equals(input.getAccountId());
+    public PaymentMethodPlugin getPaymentMethodDetail(String accountKey, String externalPaymentId) 
+    throws PaymentPluginApiException {
+        return getPaymentMethodDetail(accountKey, externalPaymentId);
+    }
+    
+    private DefaultPaymentMethodPlugin getPaymentMethod(String accountKey, String externalPaymentId) {
+        List<PaymentMethodPlugin> pms = paymentMethods.get(accountKey);
+        if (pms == null) {
+            return null;
+        }
+        for (PaymentMethodPlugin cur : pms) {
+            if (cur.getExternalPaymentMethodId().equals(externalPaymentId)) {
+                return (DefaultPaymentMethodPlugin) cur;
             }
-        });
-        List<PaymentMethodInfo> result = new ArrayList<PaymentMethodInfo>(filteredPaymentMethods);
-        return result;
+        }
+        return null;
     }
+    
+    @Override
+    public void setDefaultPaymentMethod(String accountKey,
+            String externalPaymentId) throws PaymentPluginApiException {
+    }
+
+
+
+
 
     @Override
-    public void updatePaymentGateway(String accountKey)  throws PaymentPluginApiException {
+    public String getName() {
+        return null;
     }
 
+
+    @Override
+    public List<PaymentInfoPlugin> processRefund(Account account)
+            throws PaymentPluginApiException {
+        return null;
+    }
+
+
+
+
+
     @Override
-    public void updatePaymentProviderAccountExistingContact(Account account)  throws PaymentPluginApiException {
+    public void updatePaymentGateway(String accountKey)
+            throws PaymentPluginApiException {
     }
 
+
     @Override
-    public void updatePaymentProviderAccountWithNewContact(Account account)  throws PaymentPluginApiException {
+    public void updatePaymentProviderAccountExistingContact(Account account)
+            throws PaymentPluginApiException {
     }
 
+
     @Override
-    public List<PaymentInfoPlugin> processRefund(Account account)  throws PaymentPluginApiException {
-        return null;
+    public void updatePaymentProviderAccountWithNewContact(Account account)
+            throws PaymentPluginApiException {
     }
 }