Beispiel #1
0
  @Test(groups = "slow")
  public void testCreateSuccessPurchaseWithPaymentControl()
      throws PaymentApiException, InvoiceApiException, EventBusException {

    final BigDecimal requestedAmount = BigDecimal.TEN;
    final UUID subscriptionId = UUID.randomUUID();
    final UUID bundleId = UUID.randomUUID();
    final LocalDate now = clock.getUTCToday();

    final Invoice invoice = testHelper.createTestInvoice(account, now, Currency.USD);

    final String paymentExternalKey = invoice.getId().toString();
    final String transactionExternalKey = "wouf wouf";

    invoice.addInvoiceItem(
        new MockRecurringInvoiceItem(
            invoice.getId(),
            account.getId(),
            subscriptionId,
            bundleId,
            "test plan",
            "test phase",
            null,
            now,
            now.plusMonths(1),
            requestedAmount,
            new BigDecimal("1.0"),
            Currency.USD));

    final Payment payment =
        paymentApi.createPurchaseWithPaymentControl(
            account,
            account.getPaymentMethodId(),
            null,
            requestedAmount,
            Currency.USD,
            paymentExternalKey,
            transactionExternalKey,
            createPropertiesForInvoice(invoice),
            INVOICE_PAYMENT,
            callContext);
    assertEquals(payment.getTransactions().size(), 1);
    assertEquals(
        payment.getTransactions().get(0).getTransactionStatus(), TransactionStatus.SUCCESS);
    assertEquals(payment.getTransactions().get(0).getTransactionType(), TransactionType.PURCHASE);

    final List<PaymentAttemptModelDao> attempts =
        paymentDao.getPaymentAttempts(paymentExternalKey, internalCallContext);
    assertEquals(attempts.size(), 1);

    final PaymentAttemptModelDao attempt = attempts.get(0);
    assertEquals(attempt.getStateName(), "SUCCESS");

    // Ok now the fun part starts... we modify the attempt state to be 'INIT' and wait the the
    // Janitor to do its job.
    paymentDao.updatePaymentAttempt(
        attempt.getId(), attempt.getTransactionId(), "INIT", internalCallContext);
    final PaymentAttemptModelDao attempt2 =
        paymentDao.getPaymentAttempt(attempt.getId(), internalCallContext);
    assertEquals(attempt2.getStateName(), "INIT");

    clock.addDays(1);
    try {
      Thread.sleep(1500);
    } catch (InterruptedException e) {
    }

    final PaymentAttemptModelDao attempt3 =
        paymentDao.getPaymentAttempt(attempt.getId(), internalCallContext);
    assertEquals(attempt3.getStateName(), "SUCCESS");
  }
Beispiel #2
0
  @Test(groups = "slow")
  public void testCreateSuccessRefundPaymentControlWithItemAdjustments()
      throws PaymentApiException, InvoiceApiException, EventBusException {

    final BigDecimal requestedAmount = BigDecimal.TEN;
    final UUID subscriptionId = UUID.randomUUID();
    final UUID bundleId = UUID.randomUUID();
    final LocalDate now = clock.getUTCToday();

    final Invoice invoice = testHelper.createTestInvoice(account, now, Currency.USD);

    final String paymentExternalKey = invoice.getId().toString();
    final String transactionExternalKey = "craboom";
    final String transactionExternalKey2 = "qwerty";

    final InvoiceItem invoiceItem =
        new MockRecurringInvoiceItem(
            invoice.getId(),
            account.getId(),
            subscriptionId,
            bundleId,
            "test plan",
            "test phase",
            null,
            now,
            now.plusMonths(1),
            requestedAmount,
            new BigDecimal("1.0"),
            Currency.USD);
    invoice.addInvoiceItem(invoiceItem);

    final Payment payment =
        paymentApi.createPurchaseWithPaymentControl(
            account,
            account.getPaymentMethodId(),
            null,
            requestedAmount,
            Currency.USD,
            paymentExternalKey,
            transactionExternalKey,
            createPropertiesForInvoice(invoice),
            INVOICE_PAYMENT,
            callContext);

    final List<PluginProperty> refundProperties = new ArrayList<PluginProperty>();
    final HashMap<UUID, BigDecimal> uuidBigDecimalHashMap = new HashMap<UUID, BigDecimal>();
    uuidBigDecimalHashMap.put(invoiceItem.getId(), new BigDecimal("1.0"));
    final PluginProperty refundIdsProp =
        new PluginProperty(
            InvoicePaymentRoutingPluginApi.PROP_IPCD_REFUND_IDS_WITH_AMOUNT_KEY,
            uuidBigDecimalHashMap,
            false);
    refundProperties.add(refundIdsProp);

    final Payment payment2 =
        paymentApi.createRefundWithPaymentControl(
            account,
            payment.getId(),
            null,
            Currency.USD,
            transactionExternalKey2,
            refundProperties,
            INVOICE_PAYMENT,
            callContext);

    assertEquals(payment2.getTransactions().size(), 2);
    PaymentTransaction refundTransaction = payment2.getTransactions().get(1);
    assertEquals(refundTransaction.getTransactionType(), TransactionType.REFUND);

    final List<PaymentAttemptModelDao> attempts =
        paymentDao.getPaymentAttempts(paymentExternalKey, internalCallContext);
    assertEquals(attempts.size(), 2);

    final PaymentAttemptModelDao refundAttempt = attempts.get(1);
    assertEquals(refundAttempt.getTransactionType(), TransactionType.REFUND);

    // Ok now the fun part starts... we modify the attempt state to be 'INIT' and wait the the
    // Janitor to do its job.
    paymentDao.updatePaymentAttempt(
        refundAttempt.getId(), refundAttempt.getTransactionId(), "INIT", internalCallContext);
    final PaymentAttemptModelDao attempt2 =
        paymentDao.getPaymentAttempt(refundAttempt.getId(), internalCallContext);
    assertEquals(attempt2.getStateName(), "INIT");

    clock.addDays(1);
    try {
      Thread.sleep(1500);
    } catch (InterruptedException e) {
    }

    final PaymentAttemptModelDao attempt3 =
        paymentDao.getPaymentAttempt(refundAttempt.getId(), internalCallContext);
    assertEquals(attempt3.getStateName(), "SUCCESS");
  }
  @Override
  public void leavingState(final State state) throws OperationException {
    final DateTime utcNow = pluginControlPaymentAutomatonRunner.getClock().getUTCNow();

    // Retrieve the associated payment transaction, if any
    PaymentTransactionModelDao paymentTransactionModelDaoCandidate = null;
    if (stateContext.getTransactionId() != null) {
      paymentTransactionModelDaoCandidate =
          paymentDao.getPaymentTransaction(
              stateContext.getTransactionId(), stateContext.getInternalCallContext());
      Preconditions.checkNotNull(
          paymentTransactionModelDaoCandidate,
          "paymentTransaction cannot be null for id " + stateContext.getTransactionId());
    } else if (stateContext.getPaymentTransactionExternalKey() != null) {
      final List<PaymentTransactionModelDao> paymentTransactionModelDaos =
          paymentDao.getPaymentTransactionsByExternalKey(
              stateContext.getPaymentTransactionExternalKey(),
              stateContext.getInternalCallContext());
      if (!paymentTransactionModelDaos.isEmpty()) {
        paymentTransactionModelDaoCandidate =
            paymentTransactionModelDaos.get(paymentTransactionModelDaos.size() - 1);
      }
    }
    final PaymentTransactionModelDao paymentTransactionModelDao =
        paymentTransactionModelDaoCandidate != null
                && TRANSIENT_TRANSACTION_STATUSES.contains(
                    paymentTransactionModelDaoCandidate.getTransactionStatus())
            ? paymentTransactionModelDaoCandidate
            : null;

    if (stateContext.getPaymentId() != null && stateContext.getPaymentExternalKey() == null) {
      final PaymentModelDao payment =
          paymentDao.getPayment(stateContext.getPaymentId(), stateContext.getInternalCallContext());
      Preconditions.checkNotNull(
          payment, "payment cannot be null for id " + stateContext.getPaymentId());
      stateContext.setPaymentExternalKey(payment.getExternalKey());
      stateContext.setPaymentMethodId(payment.getPaymentMethodId());
    } else if (stateContext.getPaymentExternalKey() == null) {
      stateContext.setPaymentExternalKey(UUIDs.randomUUID().toString());
    }

    if (paymentTransactionModelDao != null) {
      stateContext.setPaymentTransactionExternalKey(
          paymentTransactionModelDao.getTransactionExternalKey());
    } else if (stateContext.getPaymentTransactionExternalKey() == null) {
      stateContext.setPaymentTransactionExternalKey(UUIDs.randomUUID().toString());
    }

    if (stateContext.getPaymentMethodId() == null) {
      // Similar logic in PaymentAutomatonRunner
      stateContext.setPaymentMethodId(stateContext.getAccount().getPaymentMethodId());
    }

    if (state.getName().equals(initialState.getName())
        || state.getName().equals(retriedState.getName())) {
      try {
        final PaymentAttemptModelDao attempt;
        if (paymentTransactionModelDao != null
            && paymentTransactionModelDao.getAttemptId() != null) {
          attempt =
              pluginControlPaymentAutomatonRunner
                  .getPaymentDao()
                  .getPaymentAttempt(
                      paymentTransactionModelDao.getAttemptId(),
                      stateContext.getInternalCallContext());
          Preconditions.checkNotNull(
              attempt,
              "attempt cannot be null for id " + paymentTransactionModelDao.getAttemptId());
        } else {
          //
          // We don't serialize any properties at this stage to avoid serializing sensitive
          // information.
          // However, if after going through the control plugins, the attempt end up in RETRIED
          // state,
          // the properties will be serialized in the enteringState callback (any plugin that sets a
          // retried date is responsible to correctly remove sensitive information such as CVV, ...)
          //
          final byte[] serializedProperties =
              PluginPropertySerializer.serialize(ImmutableList.<PluginProperty>of());

          attempt =
              new PaymentAttemptModelDao(
                  stateContext.getAccount().getId(),
                  stateContext.getPaymentMethodId(),
                  utcNow,
                  utcNow,
                  stateContext.getPaymentExternalKey(),
                  stateContext.getTransactionId(),
                  stateContext.getPaymentTransactionExternalKey(),
                  transactionType,
                  initialState.getName(),
                  stateContext.getAmount(),
                  stateContext.getCurrency(),
                  stateContext.getPaymentControlPluginNames(),
                  serializedProperties);
          pluginControlPaymentAutomatonRunner
              .getPaymentDao()
              .insertPaymentAttemptWithProperties(attempt, stateContext.getInternalCallContext());
        }

        stateContext.setAttemptId(attempt.getId());
      } catch (final PluginPropertySerializerException e) {
        throw new OperationException(e);
      }
    }
  }