private void updateDefaultPaymentMethodIfNeeded(final String pluginName, final Account account, @Nullable final UUID defaultPluginPaymentMethodId, final InternalCallContext context) throws PaymentApiException, AccountApiException { // If the plugin does not have a default payment gateway, we keep the current default payment method in KB account as it is. if (defaultPluginPaymentMethodId == null) { return; } // Some gateways have the concept of default payment methods. Kill Bill has also its own default payment method // and is authoritative on this matter. However, if the default payment method is associated with a given plugin, // and if the default payment method in that plugin has changed, we will reflect this change in Kill Bill as well. boolean shouldUpdateDefaultPaymentMethod = true; if (account.getPaymentMethodId() != null) { final PaymentMethodModelDao currentDefaultPaymentMethod = paymentDao.getPaymentMethod(account.getPaymentMethodId(), context); shouldUpdateDefaultPaymentMethod = pluginName.equals(currentDefaultPaymentMethod.getPluginName()); } if (shouldUpdateDefaultPaymentMethod) { accountInternalApi.updatePaymentMethod(account.getId(), defaultPluginPaymentMethodId, context); } } }
public void addTestPaymentMethod(final Account account, final PaymentMethodPlugin paymentMethodInfo) throws Exception { final UUID paymentMethodId = paymentApi.addPaymentMethod(MockPaymentProviderPlugin.PLUGIN_NAME, account, true, paymentMethodInfo, context); Mockito.when(account.getPaymentMethodId()).thenReturn(paymentMethodId); } }
protected PaymentPluginApi getPaymentProviderPlugin(final Account account, final InternalTenantContext context) throws PaymentApiException { final UUID paymentMethodId = account.getPaymentMethodId(); if (paymentMethodId == null) { throw new PaymentApiException(ErrorCode.PAYMENT_NO_DEFAULT_PAYMENT_METHOD, account.getId()); } return getPaymentProviderPlugin(paymentMethodId, context); }
@DELETE @Path("/{accountId:" + UUID_PATTERN + "}/" + TAGS) @Consumes(APPLICATION_JSON) @Produces(APPLICATION_JSON) public Response deleteTags(@PathParam(ID_PARAM_NAME) final String id, @QueryParam(QUERY_TAGS) final String tagList, @HeaderParam(HDR_CREATED_BY) final String createdBy, @HeaderParam(HDR_REASON) final String reason, @HeaderParam(HDR_COMMENT) final String comment, @javax.ws.rs.core.Context final HttpServletRequest request) throws TagApiException, AccountApiException { final CallContext callContext = context.createContext(createdBy, reason, comment, request); // Look if there is an AUTO_PAY_OFF for that account and check if the account has a default paymentMethod // If not we can't remove the AUTO_PAY_OFF tag final Collection<UUID> tagDefinitionUUIDs = getTagDefinitionUUIDs(tagList); boolean isTagAutoPayOff = false; for (final UUID cur : tagDefinitionUUIDs) { if (cur.equals(ControlTagType.AUTO_PAY_OFF.getId())) { isTagAutoPayOff = true; break; } } final UUID accountId = UUID.fromString(id); if (isTagAutoPayOff) { final Account account = accountUserApi.getAccountById(accountId, callContext); if (account.getPaymentMethodId() == null) { throw new TagApiException(ErrorCode.TAG_CANNOT_BE_REMOVED, ControlTagType.AUTO_PAY_OFF, " the account does not have a default payment method"); } } return super.deleteTags(UUID.fromString(id), tagList, callContext); }
@POST @Path("/{accountId:" + UUID_PATTERN + "}/" + PAYMENT_METHODS) @Consumes(APPLICATION_JSON) @Produces(APPLICATION_JSON) public Response createPaymentMethod(final PaymentMethodJson json, @PathParam("accountId") final String accountId, @QueryParam(QUERY_PAYMENT_METHOD_IS_DEFAULT) @DefaultValue("false") final Boolean isDefault, @QueryParam(QUERY_PAY_ALL_UNPAID_INVOICES) @DefaultValue("false") final Boolean payAllUnpaidInvoices, @HeaderParam(HDR_CREATED_BY) final String createdBy, @HeaderParam(HDR_REASON) final String reason, @HeaderParam(HDR_COMMENT) final String comment, @javax.ws.rs.core.Context final UriInfo uriInfo, @javax.ws.rs.core.Context final HttpServletRequest request) throws AccountApiException, PaymentApiException { final CallContext callContext = context.createContext(createdBy, reason, comment, request); final PaymentMethod data = json.toPaymentMethod(accountId); final Account account = accountUserApi.getAccountById(data.getAccountId(), callContext); final boolean hasDefaultPaymentMethod = account.getPaymentMethodId() != null || isDefault; final Collection<Invoice> unpaidInvoices = payAllUnpaidInvoices ? invoiceApi.getUnpaidInvoicesByAccountId(account.getId(), clock.getUTCToday(), callContext) : Collections.<Invoice>emptyList(); if (payAllUnpaidInvoices && unpaidInvoices.size() > 0 && !hasDefaultPaymentMethod) { return Response.status(Status.BAD_REQUEST).build(); } final UUID paymentMethodId = paymentApi.addPaymentMethod(data.getPluginName(), account, isDefault, data.getPluginDetail(), callContext); if (payAllUnpaidInvoices && unpaidInvoices.size() > 0) { for (final Invoice invoice : unpaidInvoices) { paymentApi.createPayment(account, invoice.getId(), invoice.getBalance(), callContext); } } return uriBuilder.buildResponse(PaymentMethodResource.class, "getPaymentMethod", paymentMethodId, uriInfo.getBaseUri().toString()); }
assertEquals(initDefaultMethod.getId(), account.getPaymentMethodId()); Mockito.when(account.getPaymentMethodId()).thenReturn(newPaymentMethodId); assertEquals(newPaymentMethodId, account.getPaymentMethodId());
@Test(groups = "slow") public void testRefreshWithNewPaymentMethod() throws Exception { final Account account = testHelper.createTestAccount("foo@bar.com", true); Assert.assertEquals(getPluginApi().getPaymentMethods(account.getId(), true, callContext).size(), 1); final UUID existingPMId = account.getPaymentMethodId(); // Add new payment in plugin directly final UUID newPmId = UUID.randomUUID(); getPluginApi().addPaymentMethod(account.getId(), newPmId, new DefaultNoOpPaymentMethodPlugin(UUID.randomUUID().toString(), false, ImmutableList.<PaymentMethodKVInfo>of()), false, callContext); // Verify that the refresh does indeed show 2 PMs final List<PaymentMethod> methods = paymentMethodProcessor.refreshPaymentMethods(MockPaymentProviderPlugin.PLUGIN_NAME, account, internalCallContext); Assert.assertEquals(methods.size(), 2); checkPaymentMethodExistsWithStatus(methods, existingPMId, true); checkPaymentMethodExistsWithStatus(methods, newPmId, true); }
private Payment processRetryPaymentWithAccountLocked(final PaymentPluginApi plugin, final Account account, final Invoice invoice, final PaymentModelDao payment, final BigDecimal requestedAmount, final InternalCallContext context) throws PaymentApiException { final PaymentAttemptModelDao attempt = new PaymentAttemptModelDao(account.getId(), invoice.getId(), payment.getId(), account.getPaymentMethodId(), clock.getUTCNow(), requestedAmount, invoice.getCurrency()); paymentDao.updatePaymentWithNewAttempt(payment.getId(), attempt, context); return processPaymentWithAccountLocked(plugin, account, invoice, payment, attempt, false, context); }
public static PaymentMethodJson toPaymentMethodJson(final Account account, final PaymentMethod in, @Nullable final AccountAuditLogs accountAuditLogs) { final boolean isDefault = account.getPaymentMethodId() != null && account.getPaymentMethodId().equals(in.getId()); final PaymentMethodPlugin pluginDetail = in.getPluginDetail(); PaymentMethodPluginDetailJson pluginDetailJson = null;
@Test(groups = "slow") public void testRefreshWithDeletedPaymentMethod() throws Exception { final Account account = testHelper.createTestAccount("super@bar.com", true); Assert.assertEquals(getPluginApi().getPaymentMethods(account.getId(), true, callContext).size(), 1); final UUID firstPmId = account.getPaymentMethodId(); final UUID secondPmId = paymentApi.addPaymentMethod(MockPaymentProviderPlugin.PLUGIN_NAME, account, true, new DefaultNoOpPaymentMethodPlugin(UUID.randomUUID().toString(), false, null), callContext); Assert.assertEquals(getPluginApi().getPaymentMethods(account.getId(), true, callContext).size(), 2); Assert.assertEquals(paymentApi.getPaymentMethods(account, false, callContext).size(), 2); // Remove second PM from plugin getPluginApi().deletePaymentMethod(account.getId(), secondPmId, callContext); Assert.assertEquals(getPluginApi().getPaymentMethods(account.getId(), true, callContext).size(), 1); Assert.assertEquals(paymentApi.getPaymentMethods(account, false, callContext).size(), 2); // Verify that the refresh sees that PM as being deleted now final List<PaymentMethod> methods = paymentMethodProcessor.refreshPaymentMethods(MockPaymentProviderPlugin.PLUGIN_NAME, account, internalCallContext); Assert.assertEquals(methods.size(), 1); checkPaymentMethodExistsWithStatus(methods, firstPmId, true); PaymentMethodModelDao deletedPMModel = paymentDao.getPaymentMethodIncludedDeleted(secondPmId, internalCallContext); Assert.assertNotNull(deletedPMModel); Assert.assertFalse(deletedPMModel.isActive()); }
public AccountJson(final Account account, final BigDecimal accountBalance, final BigDecimal accountCBA, @Nullable final AccountAuditLogs accountAuditLogs) { super(toAuditLogJson(accountAuditLogs == null ? null : accountAuditLogs.getAuditLogsForAccount())); this.accountCBA = accountCBA; this.accountBalance = accountBalance; this.accountId = account.getId().toString(); this.externalKey = account.getExternalKey(); this.name = account.getName(); this.firstNameLength = account.getFirstNameLength(); this.email = account.getEmail(); this.billCycleDayLocal = account.getBillCycleDayLocal(); this.currency = account.getCurrency() != null ? account.getCurrency().toString() : null; this.paymentMethodId = account.getPaymentMethodId() != null ? account.getPaymentMethodId().toString() : null; this.timeZone = account.getTimeZone().toString(); this.address1 = account.getAddress1(); this.address2 = account.getAddress2(); this.postalCode = account.getPostalCode(); this.company = account.getCompanyName(); this.city = account.getCity(); this.state = account.getStateOrProvince(); this.country = account.getCountry(); this.locale = account.getLocale(); this.phone = account.getPhone(); this.isMigrated = account.isMigrated(); this.isNotifiedForInvoices = account.isNotifiedForInvoices(); }
private Payment setTerminalStateOnRetryWithAccountLocked(final Account account, final Invoice invoice, final PaymentModelDao payment, final BigDecimal requestedAmount, final String terminalStateReason, final InternalCallContext context) { final PaymentStatus paymentStatus; switch (payment.getPaymentStatus()) { case PAYMENT_FAILURE: paymentStatus = PaymentStatus.PAYMENT_FAILURE_ABORTED; break; case PLUGIN_FAILURE: case UNKNOWN: paymentStatus = PaymentStatus.PLUGIN_FAILURE_ABORTED; break; case AUTO_PAY_OFF: default: throw new IllegalStateException("Unexpected payment status for retry " + payment.getPaymentStatus()); } final PaymentAttemptModelDao attempt = new PaymentAttemptModelDao(account.getId(), invoice.getId(), payment.getId(), account.getPaymentMethodId(), clock.getUTCNow(), requestedAmount, invoice.getCurrency()); paymentDao.updatePaymentWithNewAttempt(payment.getId(), attempt, context); paymentDao.updatePaymentAndAttemptOnCompletion(payment.getId(), paymentStatus, requestedAmount, account.getCurrency(), attempt.getId(), null, terminalStateReason, context); final List<PaymentAttemptModelDao> allAttempts = paymentDao.getAttemptsForPayment(payment.getId(), context); return new DefaultPayment(payment, null, allAttempts, Collections.<RefundModelDao>emptyList()); }
if (paymentMethodId.equals(account.getPaymentMethodId())) { if (!deleteDefaultPaymentMethodWithAutoPayOff) { throw new PaymentApiException(ErrorCode.PAYMENT_DEL_DEFAULT_PAYMENT_METHOD, account.getId());
Assert.assertEquals(accountJson.getExternalKey(), account.getExternalKey()); Assert.assertEquals(accountJson.getName(), account.getName()); Assert.assertEquals(accountJson.getPaymentMethodId(), account.getPaymentMethodId().toString()); Assert.assertEquals(accountJson.getPhone(), account.getPhone()); Assert.assertEquals(accountJson.isMigrated(), account.isMigrated());
if (paymentMethod.getId().equals(account.getPaymentMethodId()) && paymentMethod.getPluginDetail() != null) { paymentMethodType = PaymentMethodUtils.getPaymentMethodType(paymentMethod.getPluginDetail()); creditCardType = PaymentMethodUtils.getCardType(paymentMethod.getPluginDetail());
} else { plugin = getPaymentProviderPlugin(account, context); paymentMethodId = account.getPaymentMethodId();