diff --git a/jaxrs/src/main/java/org/killbill/billing/jaxrs/resources/InvoicePaymentResource.java b/jaxrs/src/main/java/org/killbill/billing/jaxrs/resources/InvoicePaymentResource.java
index 54aa634..24b456d 100644
--- a/jaxrs/src/main/java/org/killbill/billing/jaxrs/resources/InvoicePaymentResource.java
+++ b/jaxrs/src/main/java/org/killbill/billing/jaxrs/resources/InvoicePaymentResource.java
@@ -164,9 +164,10 @@ public class InvoicePaymentResource extends JaxRsResourceBase {
@javax.ws.rs.core.Context final HttpServletRequest request) throws PaymentApiException, AccountApiException {
verifyNonNullOrEmpty(json, "InvoicePaymentTransactionJson body should be specified");
- final CallContext callContext = context.createCallContextNoAccountId(createdBy, reason, comment, request);
- final Payment payment = paymentApi.getPayment(paymentId, false, false, ImmutableList.<PluginProperty>of(), callContext);
- final Account account = accountUserApi.getAccountById(payment.getAccountId(), callContext);
+ final CallContext callContextNoAccountId = context.createCallContextNoAccountId(createdBy, reason, comment, request);
+ final Payment payment = paymentApi.getPayment(paymentId, false, false, ImmutableList.<PluginProperty>of(), callContextNoAccountId);
+ final Account account = accountUserApi.getAccountById(payment.getAccountId(), callContextNoAccountId);
+ final CallContext callContext = context.createCallContextWithAccountId(account.getId(), createdBy, reason, comment, request);
final Iterable<PluginProperty> pluginProperties;
final String transactionExternalKey = json.getTransactionExternalKey() != null ? json.getTransactionExternalKey() : UUIDs.randomUUID().toString();
@@ -187,37 +188,40 @@ public class InvoicePaymentResource extends JaxRsResourceBase {
pluginProperties = extractPluginProperties(pluginPropertiesString);
}
- final InvoicePayment result;
+ final UUID paymentIdToRedirectTo;
if (externalPayment) {
- result = invoicePaymentApi.createCreditForInvoicePayment(isAdjusted,
- adjustments,
- account,
- paymentId,
- paymentMethodId,
- null,
- json.getAmount(),
- account.getCurrency(),
- json.getEffectiveDate(),
- paymentExternalKey,
- transactionExternalKey,
- pluginProperties,
- createInvoicePaymentControlPluginApiPaymentOptions(true),
- callContext);
+ final InvoicePayment result = invoicePaymentApi.createCreditForInvoicePayment(isAdjusted,
+ adjustments,
+ account,
+ paymentId,
+ paymentMethodId,
+ null,
+ json.getAmount(),
+ account.getCurrency(),
+ json.getEffectiveDate(),
+ paymentExternalKey,
+ transactionExternalKey,
+ pluginProperties,
+ createInvoicePaymentControlPluginApiPaymentOptions(true),
+ callContext);
+ // /!\ Note! The invoicePayment#paymentId points to the original payment (PURCHASE) here, NOT the new one (CREDIT)
+ paymentIdToRedirectTo = paymentApi.getPaymentByTransactionExternalKey(transactionExternalKey, false, false, ImmutableList.<PluginProperty>of(), callContext).getId();
} else {
- result = invoicePaymentApi.createRefundForInvoicePayment(isAdjusted,
- adjustments,
- account,
- payment.getId(),
- json.getAmount(),
- account.getCurrency(),
- json.getEffectiveDate(),
- transactionExternalKey,
- pluginProperties,
- createInvoicePaymentControlPluginApiPaymentOptions(false),
- callContext);
+ final InvoicePayment result = invoicePaymentApi.createRefundForInvoicePayment(isAdjusted,
+ adjustments,
+ account,
+ payment.getId(),
+ json.getAmount(),
+ account.getCurrency(),
+ json.getEffectiveDate(),
+ transactionExternalKey,
+ pluginProperties,
+ createInvoicePaymentControlPluginApiPaymentOptions(false),
+ callContext);
+ paymentIdToRedirectTo = result.getPaymentId();
}
- return uriBuilder.buildResponse(uriInfo, InvoicePaymentResource.class, "getInvoicePayment", result.getId(), request);
+ return uriBuilder.buildResponse(uriInfo, InvoicePaymentResource.class, "getInvoicePayment", paymentIdToRedirectTo, request);
}
@TimedResource
diff --git a/jaxrs/src/main/java/org/killbill/billing/jaxrs/resources/TransactionResource.java b/jaxrs/src/main/java/org/killbill/billing/jaxrs/resources/TransactionResource.java
index 99bdd75..bceabc9 100644
--- a/jaxrs/src/main/java/org/killbill/billing/jaxrs/resources/TransactionResource.java
+++ b/jaxrs/src/main/java/org/killbill/billing/jaxrs/resources/TransactionResource.java
@@ -73,6 +73,7 @@ import org.killbill.commons.metrics.TimedResource;
import com.google.common.collect.ImmutableList;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
+import io.swagger.annotations.ApiParam;
import io.swagger.annotations.ApiResponse;
import io.swagger.annotations.ApiResponses;
@@ -117,6 +118,25 @@ public class TransactionResource extends JaxRsResourceBase {
return Response.status(Response.Status.OK).entity(result).build();
}
+ @TimedResource(name = "getPaymentByTransactionExternalKey")
+ @GET
+ @Produces(APPLICATION_JSON)
+ @ApiOperation(value = "Retrieve a payment by transaction external key", response = PaymentJson.class)
+ @ApiResponses(value = {@ApiResponse(code = 404, message = "Payment not found")})
+ public Response getPaymentByTransactionExternalKey(@ApiParam(required = true) @QueryParam(QUERY_TRANSACTION_EXTERNAL_KEY) final String paymentTransactionExternalKey,
+ @QueryParam(QUERY_WITH_PLUGIN_INFO) @DefaultValue("false") final Boolean withPluginInfo,
+ @QueryParam(QUERY_WITH_ATTEMPTS) @DefaultValue("false") final Boolean withAttempts,
+ @QueryParam(QUERY_PLUGIN_PROPERTY) final List<String> pluginPropertiesString,
+ @QueryParam(QUERY_AUDIT) @DefaultValue("NONE") final AuditMode auditMode,
+ @javax.ws.rs.core.Context final HttpServletRequest request) throws PaymentApiException {
+ final Iterable<PluginProperty> pluginProperties = extractPluginProperties(pluginPropertiesString);
+ final TenantContext tenantContext = context.createTenantContextNoAccountId(request);
+ final Payment payment = paymentApi.getPaymentByTransactionExternalKey(paymentTransactionExternalKey, withPluginInfo, withAttempts, pluginProperties, tenantContext);
+ final AccountAuditLogs accountAuditLogs = auditUserApi.getAccountAuditLogs(payment.getAccountId(), auditMode.getLevel(), tenantContext);
+ final PaymentJson result = new PaymentJson(payment, accountAuditLogs);
+ return Response.status(Response.Status.OK).entity(result).build();
+ }
+
@TimedResource
@POST
@Path("/{transactionId:" + UUID_PATTERN + "}/")
diff --git a/payment/src/main/java/org/killbill/billing/payment/api/DefaultPaymentApi.java b/payment/src/main/java/org/killbill/billing/payment/api/DefaultPaymentApi.java
index cf9d900..1418ef1 100644
--- a/payment/src/main/java/org/killbill/billing/payment/api/DefaultPaymentApi.java
+++ b/payment/src/main/java/org/killbill/billing/payment/api/DefaultPaymentApi.java
@@ -1085,6 +1085,15 @@ public class DefaultPaymentApi extends DefaultApiBase implements PaymentApi {
return payment;
}
+ @Override
+ public Payment getPaymentByTransactionExternalKey(final String transactionExternalKey, final boolean withPluginInfo, final boolean withAttempts, final Iterable<PluginProperty> properties, final TenantContext context) throws PaymentApiException {
+ final Payment payment = paymentProcessor.getPaymentByTransactionExternalKey(transactionExternalKey, withPluginInfo, withAttempts, properties, context, internalCallContextFactory.createInternalTenantContextWithoutAccountRecordId(context));
+ if (payment == null) {
+ throw new PaymentApiException(ErrorCode.PAYMENT_NO_SUCH_PAYMENT, transactionExternalKey);
+ }
+ return payment;
+ }
+
private PaymentTransaction findPaymentTransaction(final Payment payment, @Nullable final String paymentTransactionExternalKey) {
// By design, the payment transactions are already correctly sorted (by effective date asc)
if (paymentTransactionExternalKey == null) {
diff --git a/payment/src/main/java/org/killbill/billing/payment/core/PaymentProcessor.java b/payment/src/main/java/org/killbill/billing/payment/core/PaymentProcessor.java
index ecaa6d8..e3bfbfa 100644
--- a/payment/src/main/java/org/killbill/billing/payment/core/PaymentProcessor.java
+++ b/payment/src/main/java/org/killbill/billing/payment/core/PaymentProcessor.java
@@ -435,12 +435,22 @@ public class PaymentProcessor extends ProcessorBase {
public Payment getPaymentByTransactionId(final UUID transactionId, final boolean withPluginInfo, final boolean withAttempts, final Iterable<PluginProperty> properties, final TenantContext tenantContext, final InternalTenantContext internalTenantContext) throws PaymentApiException {
final PaymentTransactionModelDao paymentTransactionDao = paymentDao.getPaymentTransaction(transactionId, internalTenantContext);
if (null != paymentTransactionDao) {
- PaymentModelDao paymentModelDao = paymentDao.getPayment(paymentTransactionDao.getPaymentId(), internalTenantContext);
+ final PaymentModelDao paymentModelDao = paymentDao.getPayment(paymentTransactionDao.getPaymentId(), internalTenantContext);
return toPayment(paymentModelDao, withPluginInfo, withAttempts, properties, tenantContext, internalTenantContext);
}
return null;
}
+ public Payment getPaymentByTransactionExternalKey(final String transactionExternalKey, final boolean withPluginInfo, final boolean withAttempts, final Iterable<PluginProperty> properties, final TenantContext tenantContext, final InternalTenantContext internalTenantContext) throws PaymentApiException {
+ final List<PaymentTransactionModelDao> paymentTransactionDao = paymentDao.getPaymentTransactionsByExternalKey(transactionExternalKey, internalTenantContext);
+ if (paymentTransactionDao.isEmpty()) {
+ return null;
+ }
+ // All transactions must be on the same payment (see sanity in buildPaymentStateContext)
+ final PaymentModelDao paymentModelDao = paymentDao.getPayment(paymentTransactionDao.get(0).getPaymentId(), internalTenantContext);
+ return toPayment(paymentModelDao, withPluginInfo, withAttempts, properties, tenantContext, internalTenantContext);
+ }
+
private Payment performOperation(final boolean isApiPayment,
@Nullable final UUID attemptId,
final TransactionType transactionType,