3
votes

I am using Stripe as a payment processor in an application and have a few questions concerning getting an error response when using the Java library as opposed to receiving the errors over HTTP as is documented in the description of errors codes on the official Stripe documentation

The method I am using to charge credit cards based on a customer object that has previously been created with stripe is:

public void charge(BigDecimal amount) throws AuthenticationException, InvalidRequestException, APIConnectionException, CardException, APIException {
    //Convert amount to cents
    NumberFormat usdCostFormat = NumberFormat.getCurrencyInstance(Locale.US);
    usdCostFormat.setMinimumFractionDigits(1);
    usdCostFormat.setMaximumFractionDigits(2);
    double chargeAmountDollars = Double.valueOf(usdCostFormat.format(amount.doubleValue()));
    int chargeAmountCents = (int) chargeAmountDollars * 100;
    Map<String, Object> chargeParams = new HashMap<String, Object>();
    chargeParams.put("amount", chargeAmountCents);
    chargeParams.put("currency", "usd");
    chargeParams.put("customer", subscription.getCustomerId());
    Charge charge = Charge.create(chargeParams);
    //Should I be inspecting the returned charge object and throwing my own errors here?
}

The method throws a variety of exceptions. The CardException seems like it might give me details about errors with the payment, but it is actually meant to be used to detect things like declines and invalid card params? Will these exceptions tell me things such as "the credit card was declined" or "the cvc code was incorrect" or should I be examining the return Charge object to get that data?

An example of a method calling the charge method might be something like:

BigDecimal discount = cost.multiply(BigDecimal.valueOf(discountPercentage).setScale(2, RoundingMode.HALF_EVEN));
cost = cost.subtract(discount);

if(cost.compareTo(BigDecimal.ZERO) > 0) {
    //Charge the credit card.
    try {
        paymentManager.charge(cost);
                    //Everything went ok, return success to user.
    } catch (AuthenticationException e) {
        //Authentication with API failed. Log error.
    } catch (InvalidRequestException e) {
        //Invalid parameters, log error.
    } catch (APIConnectionException e) {
        //Network communication failure. Try again.
    } catch (CardException e) {
        String errorCode = e.getCode();
        String errorMsg = e.getParam();
        if(errorCode.equals("incorrect_number")) {
            //Tell the user the cc number is incorrect.
        } else if(errorCode.equals("invalid_cvc")) {
            //Tell the user the cvc is wrong.
        }
        //This is a sample, production will check all possible errors.
    } catch (APIException e) {
        //Something went wrong on Stripes end.
    }
}

Secondly, should I be concerned about payments originating from outside the USA or does Stripe handle all of that for me? Do I need to detect the currency based on the locale of the user and set the proper currency code, or will Stripe convert all payments to USD since that is the currency that monies is deposited into my account?

Update: According to an email I received from Stripe's support team, the issuing banks of non-US cards will automatically perform all currency conversions from local to USD. I don't have to adjust the currency code based on the origin of the card being charged.

1

1 Answers

4
votes

It seems like CardException will give you both card-related (invalid CVC) AND payment-related (declined) errors.

From the docs, here how to use the Charge.create() method:

Returns a charge object if the charge succeeded. An error will be returned if something goes wrong. A common source of error is an invalid or expired card, or a valid card with insufficient available balance.

From the Stripe Java documentation:

Card Errors
Type: card_error

Code                  Details
incorrect_number      The card number is incorrect
invalid_number        The card number is not a valid credit card number
invalid_expiry_month  The card's expiration month is invalid
invalid_expiry_year   The card's expiration year is invalid
invalid_cvc           The card's security code is invalid
expired_card          The card has expired
incorrect_cvc         The card's security code is incorrect
card_declined         The card was declined.
missing               There is no card on a customer that is being charged.
processing_error      An error occurred while processing the card.

As for currency, there is a currency value that is passed in the Map to the Charge.create() method which seems to indicate the currency you want the charge made in. I'm not sure how that relates to settlement though.