// If the gateway sends back Shipping Information, we will save that to the first shippable fulfillment group.
populateShippingInfo(responseDTO, order);
// ALWAYS create a new order payment for the payment that comes in. Invalid payments should be cleaned up by
// invoking {@link #markPaymentAsInvalid}.
OrderPayment payment = orderPaymentService.create();
payment.setType(responseDTO.getPaymentType());
payment.setPaymentGatewayType(responseDTO.getPaymentGatewayType());
payment.setAmount(responseDTO.getAmount());
// If this gateway does not support multiple payments then mark all of the existing payments
// as invalid before adding the new one
List<OrderPayment> paymentsToInvalidate = new ArrayList<OrderPayment>();
Address tempBillingAddress = null;
if (!config.handlesMultiplePayments()) {
PaymentGatewayType gateway = config.getGatewayType();
for (OrderPayment p : order.getPayments()) {
// A Payment on the order will be invalidated if:
// - It's a temporary order payment: There may be a temporary Order Payment on the Order (e.g. to save the billing address)
// - The payment being added is a Final Payment and there already exists a Final Payment
// - The payment being added has the same gateway type of an existing one.
if (PaymentGatewayType.TEMPORARY.equals(p.getGatewayType()) ||
(p.isFinalPayment() && payment.isFinalPayment()) ||
(p.getGatewayType() != null && p.getGatewayType().equals(gateway))) {
paymentsToInvalidate.add(p);
if (PaymentType.CREDIT_CARD.equals(p.getType()) &&
PaymentGatewayType.TEMPORARY.equals(p.getGatewayType()) ) {
tempBillingAddress = p.getBillingAddress();
}
}
}
}
for (OrderPayment invalid : paymentsToInvalidate) {
order.getPayments().remove(invalid);
markPaymentAsInvalid(invalid.getId());
}
// The billing address that will be saved on the order will be parsed off the
// Response DTO sent back from the Gateway as it may have Address Verification or Standardization.
// If you do not wish to use the Billing Address coming back from the Gateway, you can override the
// populateBillingInfo() method or set the useBillingAddressFromGateway property.
populateBillingInfo(responseDTO, payment, tempBillingAddress);
// Create the transaction for the payment
PaymentTransaction transaction = orderPaymentService.createTransaction();
transaction.setAmount(responseDTO.getAmount());
transaction.setRawResponse(responseDTO.getRawResponse());
transaction.setSuccess(responseDTO.isSuccessful());
transaction.setType(responseDTO.getPaymentTransactionType());
for (Entry<String, String> entry : responseDTO.getResponseMap().entrySet()) {
transaction.getAdditionalFields().put(entry.getKey(), entry.getValue());
}
//Set the Credit Card Info on the Additional Fields Map
if (PaymentType.CREDIT_CARD.equals(responseDTO.getPaymentType()) &&
responseDTO.getCreditCard().creditCardPopulated()) {
transaction.getAdditionalFields().put(PaymentAdditionalFieldType.NAME_ON_CARD.getType(),
responseDTO.getCreditCard().getCreditCardHolderName());
transaction.getAdditionalFields().put(PaymentAdditionalFieldType.CARD_TYPE.getType(),
responseDTO.getCreditCard().getCreditCardType());
transaction.getAdditionalFields().put(PaymentAdditionalFieldType.EXP_DATE.getType(),
responseDTO.getCreditCard().getCreditCardExpDate());
transaction.getAdditionalFields().put(PaymentAdditionalFieldType.LAST_FOUR.getType(),
responseDTO.getCreditCard().getCreditCardLastFour());
}
//TODO: validate that this particular type of transaction can be added to the payment (there might already
// be an AUTHORIZE transaction, for instance)
//Persist the order payment as well as its transaction
payment.setOrder(order);
transaction.setOrderPayment(payment);
payment.addTransaction(transaction);
payment = orderPaymentService.save(payment);
if (transaction.getSuccess()) {
orderService.addPaymentToOrder(order, payment, null);
} else {
// We will have to mark the entire payment as invalid and boot the user to re-enter their
// billing info and payment information as there may be an error either with the billing address/or credit card
handleUnsuccessfulTransaction(payment);
}
return payment.getId();
}