Stripe is a software that allows individuals and businesses to make and receive payments over the Internet. It offers an API in many programming languages to allow people creating Customers, Products and Plans and charge for them. Also, Stripe give us a checkout to make easier the payments.
- Customer => User
- Product => Product
- Plans => Product attribute
Set your Private and Public Stripe Key on the application.properties under src/main/resources (stripe.privateKey/publicKey)
The following explanations of implementations with Stripe in the back do not include the complete code, only the key lines. For more information, see the Stripe API or the full code available in this repository,
Stripe Customers API Whenever someone registers, Customer (Stripe) and User (Licensoft) are created. Both are linked by stripeCustomerId attribute in User.
...
Customer customer = Customer.create(customerParameter);
userServ.save(new User(customer.getId(),user, pass1, "ROLE_USER"));
Stripe Products API Stripe offers many options to create a Product. Licensoft has 2 types of products: Good (Stripe) | Lifetime (Licensoft) & Service (Stripe) | Subscription (Licensoft).
...
params.put("type", "good");` OR `params.put("type", "service");
Creating the Product in stripe:
productStripe = com.stripe.model.Product.create(params);
Stripe Plans API Each Subscription Product can have many different Plans (with different prices and intervals). When a Plan is created, it is linked with the Product (Licensoft) by the plans Map attribute.
...
params.put("interval", "month");
params.put("product", productId);
params.put("amount", (int)(price*100));
Plan plan1M = Plan.create(params);
product.getPlans().put("M",plan1M.getId());
Stripe Subscription API User can choose which product plan to subscribe. Prerequisite: Customer (Stripe) must have a payment source attached previously.
...
params.put("customer", user.getCustomerStripeId());
Subscription subscription = Subscription.create(params);
This process is divided into 4 parts:
- Transforming card data info to a Stripe token.
- Creation of a PaymentMethod with the token created in the Frontend and passed to the backend, and the data of the transaction (amount, user info, options...).
- Creation of a PaymentIntent and attach the recent PaymentMethod created to it.
- Confirm the PaymentIntent, and check if they payment was succeded, failed or needs extra actions (3DSecure, confirmation SMS). Purchasing a Lifetime Product consists in ordering it. Stripe Order API It's not necessary to have a payment source attached into it, because Stripe Elements (frontend) will collect the card information to do the Order.
1st part:
Frontend card info recopilation
2nd part:
Map<String, Object> card = new HashMap<>();
card.put("token", tokenId);
Map<String, Object> paramsPM = new HashMap<>();
paramsPM.put("type", "card");
paramsPM.put("card", card);
PaymentMethod paymentMethod = this.stripeServ.createPaymentMethod(paramsPM);
3rd part:
Map<String, Object> params = new HashMap<>();
params.put("amount", product.getPlansPrices().get("L").intValue()*100);
params.put("payment_method", paymentMethod.getId());
params.put("currency", "eur");
params.put("description", "Product bought: " + product.getName());
List<Object> payment_method_types = new ArrayList<>();
payment_method_types.add("card");
params.put("payment_method_types", payment_method_types);
params.put("customer",u.getCustomerStripeId());
params.put("receipt_email",u.getEmail());
PaymentIntent paymentIntent = this.stripeServ.createPaymentIntent(params);
4th part:
...
PaymentIntent piReturned = this.stripeServ.confirmPaymentIntent(paymentIntent, params);
String status = piReturned.getStatus();
...
if(status.equals("succeeded")) {
...
}else if(status.equals("requires_payment_method")) {
...
}else if(status.equals("requires_action")) {
...
}else {
return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR);
}
As Purchasing a Product, attaching a card to a Customer (Stripe) is divided in the same two parts. 1st part: Frontend Get card info 2nd part:
Customer c = Customer.retrieve(user.getCustomerStripeId());
...
source.put("source", tokenId); //Token caught from the front
c.getSources().create(source);
Frontend will automatically request to the backend the public stripe key when needed.
All the Stripe implementations in Angular consists of Stripe Elements.
With Stripe Elements we can easily get card info and transform it to a token to pass it to the backend.
... (previous actions)
var handler = (<any>window).StripeCheckout.configure({
key: '***',
currency:'eur',
token: (token: any) =>{
if(token!=null){
... send token to the back...
}
}
});`
After setting up StripeElements in Angular and making the html form, logic in typescript follows this main steps:
const elements = stripe.elements();
const card = elements.create('card');
card.mount('#card-element');
...
const paymentForm = document.getElementById('payment-form');
paymentForm.addEventListener('submit', event => {
//Send info to the back
this.userProfileServ.addCardStripeElements(result.token.id).subscribe(...)...
}