Source:
<code>public Pagination<Payment> searchPayments(final String searchKey, final Long offset, final Long limit, final String pluginName, final boolean withPluginInfo, final boolean withAttempts, final Iterable<PluginProperty> properties, final TenantContext tenantContext, final InternalTenantContext internalTenantContext) throws PaymentApiException { final PaymentPluginApi pluginApi = getPaymentPluginApi(pluginName); final Pagination<PaymentTransactionInfoPlugin> paymentTransactionInfoPlugins; try { <START> paymentTransactionInfoPlugins = pluginApi.searchPayments(searchKey, offset, limit, properties, tenantContext); <END> } catch (final PaymentPluginApiException e) { throw new PaymentApiException(e, ErrorCode.PAYMENT_PLUGIN_SEARCH_PAYMENTS, pluginName, searchKey); } final Multimap<UUID, PaymentTransactionInfoPlugin> payments = HashMultimap.<UUID, PaymentTransactionInfoPlugin>create(); for (final PaymentTransactionInfoPlugin paymentTransactionInfoPlugin : paymentTransactionInfoPlugins) { payments.put(paymentTransactionInfoPlugin.getKbPaymentId(), paymentTransactionInfoPlugin); } final Collection<Payment> results = new LinkedList<Payment>(); for (final UUID paymentId : payments.keys()) { final Payment result = toPayment(paymentId, withPluginInfo ? payments.get(paymentId) : ImmutableList.<PaymentTransactionInfoPlugin>of(), withAttempts, internalTenantContext); if (result != null) { results.add(result); } } return new DefaultPagination<Payment>(paymentTransactionInfoPlugins, limit, results.iterator()); }</code><technical_language>I offset limit miss-leading method name searchPayments. client restrict result payments size, plugin transaction level. case that, client sends a limit of 100, get 1 payment in page 100 transactions embedded. a payment cross 2 consequent pages. considering plugins returning a more proper list instead of PaymentTransactionInfoPlugins? class PluginPayment { private UUID kbPaymentId; private Collection<PaymentTransactionInfoPlugin> transactions } a thought, happy changed in this PR</technical_language>

Target:
public Pagination<Payment> searchPayments(final String searchKey, final Long offset, final Long limit, final String pluginName, final boolean withPluginInfo, final boolean withAttempts, final Iterable<PluginProperty> properties, final TenantContext tenantContext, final InternalTenantContext internalTenantContext) throws PaymentApiException { final PaymentPluginApi pluginApi = getPaymentPluginApi(pluginName); final Pagination<PaymentTransactionInfoPlugin> paymentTransactionInfoPlugins; try { paymentTransactionInfoPlugins = pluginApi.searchPayments(searchKey, offset, limit, properties, tenantContext); } catch (final PaymentPluginApiException e) { throw new PaymentApiException(e, ErrorCode.PAYMENT_PLUGIN_SEARCH_PAYMENTS, pluginName, searchKey); } final Multimap<UUID, PaymentTransactionInfoPlugin> payments = HashMultimap.<UUID, PaymentTransactionInfoPlugin>create(); for (final PaymentTransactionInfoPlugin paymentTransactionInfoPlugin : paymentTransactionInfoPlugins) { if (paymentTransactionInfoPlugin.getKbPaymentId() == null) { log.debug("Plugin returned a payment without a kbPaymentId for searchKey {}", pluginName, searchKey); } else { payments.put(paymentTransactionInfoPlugin.getKbPaymentId(), paymentTransactionInfoPlugin); } } final Collection<Payment> results = new LinkedList<Payment>(); for (final UUID paymentId : payments.keys()) { final Payment result = toPayment(paymentId, withPluginInfo ? payments.get(paymentId) : ImmutableList.<PaymentTransactionInfoPlugin>of(), withAttempts, internalTenantContext); if (result != null) { results.add(result); } } return new DefaultPagination<Payment>(paymentTransactionInfoPlugins, limit, results.iterator()); }