Dependency Inversion With Payment Gateways Stripe/Paypal Using Nodejs
Tags: node, javascript, oop, solid
Published: 2020-10-29 18:38:19

**What We Are Going To Cover Today**
* Idea Of Dependency Inversion
* Problem/Solution With Payment Gateways Stripe/Paypal
* Real Scenario You Can use in your E-commerce Project

# Dependency inversion
* High level Modules should not depend on low level modules Both Should Depend on Abstraction
* Or We Can Say Any higher classes should always depend upon the abstraction of the class rather than the detail.

**From This Definition We Can Say That**
##### We Just want Our Code Depends On The Wrapper We Created  Not The Actual Implementation Of Dependency We're Using

# The Problem We Have
* Change Payment Gateway From Stripe >> Paypal Will Be Very Hard and We Will Change tons Of Code
* Our Code Depends on the Actual Implementation Of The Payment Service and This Going to be Hard to Maintain
* Testing Everything From Scratch Again
* Making any Transaction Going To Be Really Hard to Trace Later

# Solution

![Dependency Inversion With Stripe/Paypal](https://dev-to-uploads.s3.amazonaws.com/i/lcuac4efldr1mxs3jvzt.png)

* Create Intermediate Layer This Layer Going to Be Wrapper Around Payment Gateway Services
* e.g StripeServiceWrapper, PaypalServiceWrapper 
* So We Just Abstract the Payment Gateways Idea Using These Wrappers it's
* Our Code Now Depends On These Wrappers Not The Actual Implementation Of Dependency We're Using

# Let's Start By Some Code Snippets
**Payment Store**
Here We Are Going to Inject The Wrapper And Makes The Transaction With Anyone We Want Easily

```javascript
import PaymentService from "./PaymentService";
class PaymentStore {
  constructor(paymentWrapper) {
    this.paymentWrapper = paymentWrapper;
    this.paymentService = new PaymentService();
  }

  async makeTransaction(chargeData) {
    const charge = await this.paymentWrapper.createCharge(chargeData);
    await this.paymentService.addNewCharge(charge);
    return charge;
  }
}

export default PaymentStore;
```

**Stripe Wrapper**
```javascript
import Stripe from "stripe";
import mockPayment from "./Stripe/mockPayment";
class StripeServiceWrapper {
  constructor() {
    this.stripe = new Stripe(process.env.STRIPE_SECRET_KEY);
  }
  async createCharge() {
    const { amount, currency, description, source } = mockPayment;
    const charge = await this.stripe.charges.create({
      amount,
      currency,
      description,
      source,
    });
    return charge;
  }

  async createCustomer(customerData) {
    const { name, email, source, address, phone } = customerData;
    const customer = await stripe.customers.create({
      address,
      name,
      email,
      phone,
      source,
    });
    return customer;
  }
}

export default StripeServiceWrapper;
```

**Paypal Wrapper** 

```javascript
import paypal from "paypal-rest-sdk";
import "./PayPal/PayPalConfig";

class PayPalServiceWrapper {
  createCharge({ payment_object, paymentId }) {
    return new Promise(function (resolve, reject) {
      paypal.payment.execute(paymentId, payment_object, function (error, payment) {
        if (error) reject(error);
        else {
          const { id, transactions } = payment;
          resolve({ id, amount: parseInt(transactions[0].amount.total) });
        }
      });
    });
  }

  paymentExecutionLink(paymentObject) {
    return new Promise(function (resolve, reject) {
      paypal.payment.create(paymentObject, function (error, payment) {
        if (error) reject(error);
        else resolve(payment);
      });
    });
  }

  getRedirectLink(links) {
    for (let i = 0; i < links.length; i++) {
      if (links[i].rel === "approval_url") return links[i].href;
    }
  }
}

export default PayPalServiceWrapper;
```
##### So Now At Our Controller It's Going to Be Very Easy To Switch From Stripe To Paypal

```javascript
const post = async (req, res) => {
  const store = new PaymentStore(new StripeServiceWrapper());
  await store.makeTransaction();
  return res.status(200).send({SUCCESS_MESSAGE});
};
```

#### You Can Find The Code And How to Start Easy At
https://github.com/eslamelkholy/Payment-Gateway-Stripe-Paypal-Using-Dependency-Inversion

#### References

https://en.wikipedia.org/wiki/Dependency_inversion_principle

https://www.geeksforgeeks.org/dependecy-inversion-principle-solid/

https://www.youtube.com/watch?v=9oHY5TllWaU&list=PLZlA0Gpn_vH_CthENcPCM0Dww6a5XYC7f&index=11&ab_channel=WebDevSimplified

https://dev.to/educative/s-o-l-i-d-principles-of-object-oriented-programming-in-c-2m98#dependency