@Override
  @Transactional("blTransactionManager")
  public PaymentInfo addPaymentToOrder(
      Order order, PaymentInfo payment, Referenced securePaymentInfo) {
    payment.setOrder(order);
    order.getPaymentInfos().add(payment);
    order = persist(order);
    int paymentIndex = order.getPaymentInfos().size() - 1;

    if (securePaymentInfo != null) {
      securePaymentInfoService.save(securePaymentInfo);
    }

    return order.getPaymentInfos().get(paymentIndex);
  }
 @Override
 @Transactional("blTransactionManager")
 public void removePaymentFromOrder(Order order, PaymentInfo paymentInfo) {
   PaymentInfo paymentInfoToRemove = null;
   for (PaymentInfo info : order.getPaymentInfos()) {
     if (info.equals(paymentInfo)) {
       paymentInfoToRemove = info;
     }
   }
   if (paymentInfoToRemove != null) {
     try {
       securePaymentInfoService.findAndRemoveSecurePaymentInfo(
           paymentInfoToRemove.getReferenceNumber(), paymentInfo.getType());
     } catch (WorkflowException e) {
       // do nothing--this is an acceptable condition
       LOG.debug("No secure payment is associated with the PaymentInfo", e);
     }
     order.getPaymentInfos().remove(paymentInfoToRemove);
     paymentInfo = paymentInfoDao.readPaymentInfoById(paymentInfoToRemove.getId());
     paymentInfoDao.delete(paymentInfo);
   }
 }
 @Override
 @Transactional("blTransactionManager")
 public void removePaymentsFromOrder(Order order, PaymentInfoType paymentInfoType) {
   List<PaymentInfo> infos = new ArrayList<PaymentInfo>();
   for (PaymentInfo paymentInfo : order.getPaymentInfos()) {
     if (paymentInfoType == null || paymentInfoType.equals(paymentInfo.getType())) {
       infos.add(paymentInfo);
     }
   }
   order.getPaymentInfos().removeAll(infos);
   for (PaymentInfo paymentInfo : infos) {
     try {
       securePaymentInfoService.findAndRemoveSecurePaymentInfo(
           paymentInfo.getReferenceNumber(), paymentInfo.getType());
     } catch (WorkflowException e) {
       // do nothing--this is an acceptable condition
       LOG.debug("No secure payment is associated with the PaymentInfo", e);
     }
     order.getPaymentInfos().remove(paymentInfo);
     paymentInfo = paymentInfoDao.readPaymentInfoById(paymentInfo.getId());
     paymentInfoDao.delete(paymentInfo);
   }
 }
  @Test(groups = {"testSuccessfulCyberSourceCCModulePayment"})
  @Rollback(false)
  public void testSuccessfulCyberSourceCCModulePayment() throws Exception {
    if (serviceManager.getMerchantId().equals("?")) {
      return;
    }

    /*
     * authorize
     */
    CyberSourceCreditCardModule module = new CyberSourceCreditCardModule();
    module.setServiceManager(serviceManager);

    Money amount = new Money(81.46);
    PaymentInfo paymentInfo = new PaymentInfoImpl();
    paymentInfo.setAmount(amount);
    Address address = new AddressImpl();
    address.setAddressLine1("1295 Charleston Road");
    address.setCity("Mountain View");
    address.setCountry(
        new CountryImpl() {
          @Override
          public String getAbbreviation() {
            return "US";
          }
        });
    address.setFirstName("John");
    address.setLastName("Doe");
    address.setPostalCode("94043");
    address.setState(
        new StateImpl() {
          @Override
          public String getAbbreviation() {
            return "CA";
          }
        });
    paymentInfo.setAddress(address);
    paymentInfo.setCustomerIpAddress("10.7.111.111");
    Order order = new OrderImpl();
    order.setEmailAddress("*****@*****.**");
    paymentInfo.setOrder(order);
    Referenced referenced = createCreditCardPaymentInfo("4111111111111111", 12, 2020, null);
    PaymentContext context =
        new PaymentContextImpl(amount, amount, paymentInfo, referenced, "test");

    PaymentResponseItem responseItem = module.authorize(context);
    assert (responseItem.getAmountPaid().equals(amount));

    /*
     * debit
     */
    paymentInfo
        .getAdditionalFields()
        .put("requestId", responseItem.getAdditionalFields().get("requestId"));
    paymentInfo
        .getAdditionalFields()
        .put("requestToken", responseItem.getAdditionalFields().get("requestToken"));

    PaymentResponseItem responseItem2 = module.debit(context);
    assert (responseItem2.getAmountPaid().equals(amount));

    /*
     * authorize and debit
     */
    PaymentResponseItem responseItem3 = module.authorizeAndDebit(context);
    assert (responseItem3.getAmountPaid().equals(amount));

    /*
     * credit
     */
    paymentInfo
        .getAdditionalFields()
        .put("requestId", responseItem3.getAdditionalFields().get("requestId"));
    paymentInfo
        .getAdditionalFields()
        .put("requestToken", responseItem3.getAdditionalFields().get("requestToken"));

    PaymentResponseItem responseItem4 = module.credit(context);
    assert (responseItem4.getAmountPaid().equals(amount));

    /*
     * void
     */
    // TODO void does not seem to work in the CyberSource test environment
    /*PaymentResponseItem responseItem5 = module.authorizeAndDebit(context);
    paymentInfo.getAdditionalFields().put("requestId", responseItem5.getAdditionalFields().get("requestId"));
    paymentInfo.getAdditionalFields().put("requestToken", responseItem5.getAdditionalFields().get("requestToken"));

    PaymentResponseItem responseItem6 = module.voidPayment(context);
    assert(responseItem6.getTransactionSuccess());
    assert(responseItem6.getAmountPaid().equals(amount));*/

    /*
     * auth reverse
     */
    PaymentResponseItem responseItem5 = module.authorize(context);

    paymentInfo
        .getAdditionalFields()
        .put("requestId", responseItem5.getAdditionalFields().get("requestId"));
    paymentInfo
        .getAdditionalFields()
        .put("requestToken", responseItem5.getAdditionalFields().get("requestToken"));

    PaymentResponseItem responseItem6 = module.reverseAuthorize(context);
    assert (responseItem6.getAmountPaid().equals(amount));
  }