Giter Club home page Giter Club logo

ecommerce's Introduction

Fully functional ECOMMERCE API USING GIN FRAMEWORK AND MONGODB

drawing

-----Initial Release v2.30 ⚠️Not tested the efficiency

project structure

  • Ecommerce 📁
    • controllers 📁
      • controllers.go📝
    • database📁
      • database.go📝
    • middleware📁
      • middleware.go📝
    • models📁
      • models.go📝
    • routes📁
      • routes.go📝
    • tokens📁
      • tokengen.go📝
    • go.sum 📝
    • main.go📝

clone this repo and change into the directory ecommerce-main*** make sure go is installed in your system Run

# Start the mongodb container for local development
docker-compose up -d
go run main.go

Using Mongodb for small scale ecommerce industry is not a good idea instead use redis or mysql

API FUNCTIONALITY CURRENTLY ADDED?

  • Signup 🔒
  • Login 🔒
  • Product listing General View 👀
  • Adding the products to DB
  • Sorting the products from DB using regex 👀
  • Adding the products to cart 🛒
  • Removing the Product from cart🛒
  • Viewing the items in cart with total price🛒💰
  • Adding the Home Address 🏠
  • Adding the Work Address 🏢
  • Editing the Address ✂️
  • Deleting the Adress 🗑️
  • Checkout the Items from Cart
  • Buy Now products💰

future implementations?

  • Pagination 1>>2>>3
  • Admin Part
  • OAuth 2
  • etc***

Code At glance in Database(database.go)

first we need to define the database , make sure the mongodb installed in your system. The important thing we have to remember is we need to create a database with two collections , Two collections that for storing the user informations and the other for storing the product informations.We must have to configure the url and port of mongodb configured in your system

// code example of url and port in databasetup.go
mongo.NewClient(options.Client().ApplyURI("mongodb://localhost:27017")) --port and url
// code example of defining collection name
var collection *mongo.Collection = client.Database("Ecommerce").Collection(CollectionName)

like to know more about configurations visit: https://www.mongodb.com/blog/post/quick-start-golang-mongodb-starting-and-setup

Code At glance in models.go

This part defines us how should our database looks like, I think its not about programming skills, but if you have creativity and basic syntax ideas and have some ability to defines struct from creativity 90% of work completed.Before Jumping into other codes we should have a rough idea about our plan so its better to lookup into models .

  • We have to define a product first , having a unique id , name and price
type Product struct {
  Product_ID   primitive.ObjectID `bson:"_id"`
  Product_Name *string            `json:"product_name"`
  Price        *uint64            `json:"price"`
  Rating       *uint8             `json:"rating"`
  Image        *string            `json:"image"`
}
  • We have to define an slice of array products where a user can store individual products
type ProductUser struct {
  Product_ID   primitive.ObjectID `bson:"_id"`
  Product_Name *string            `json:"product_name" bson:"product_name"`
  Price        int                `json:"price"  bson:"price"`
  Rating       *uint              `json:"rating" bson:"rating"`
  Image        *string            `json:"image"  bson:"image"`
}
  • The next struct we have to define the Address
type Address struct {
  Address_id primitive.ObjectID `bson:"_id"`
  House      *string            `json:"house_name" bson:"house_name"`
  Street     *string            `json:"street_name" bson:"street_name"`
  City       *string            `json:"city_name" bson:"city_name"`
  Pincode    *string            `json:"pin_code" bson:"pin_code"`
}
  • If the user has ordered something the struct look like the one in below, having an embedded struct inside a struct , here we define the ProductUser as a slice(A person can buy more than one product right?) and a payement struct to define Cash on delivery or digital payement
type Order struct {
  Order_ID       primitive.ObjectID `bson:"_id"`
  Order_Cart     []ProductUser      `json:"order_list"  bson:"order_list"`
  Orderered_At   time.Time          `json:"ordered_on"  bson:"ordered_on"`
  Price          int                `json:"total_price" bson:"total_price"`
  Discount       *int               `json:"discount"    bson:"discount"`
  Payment_Method Payment            `json:"payment_method" bson:"payment_method"`
}

The Payement struct is something look like this

type Payment struct {
  Digital bool `json:"digital" bson:"digital"`
  COD     bool `json:"cod"     bson:"cod"`
}

we can define those structs as the simple fields or blocks (genrally known as documents and subdocuments in mongodb)in the user databse or the user struct

  • Finally in the user struct we are going to embedd the simple structs .The new fields in struct are ID, Name ,Email, Token etc
type User struct {
  ID              primitive.ObjectID `json:"_id" bson:"_id"`
  First_Name      *string            `json:"first_name" validate:"required,min=2,max=30"`
  Last_Name       *string            `json:"last_name"  validate:"required,min=2,max=30"`
  Password        *string `json:"password" validate:"required,min=6"`
  Email           *string `json:"email" validate:"email,required"`
  Phone           *string `json:"phone" validate:"required"`
  Token           *string `json:"token"`
  Refresh_Token   *string `josn:"refresh_token"`
  Created_At      time.Time `json:"created_at"`
  Updated_At      time.Time `json:"updtaed_at"`
  User_ID         string `json:"user_id"`
  UserCart        []ProductUser `json:"usercart" bson:"usercart"`
  Address_Details []Address `json:"address" bson:"address"`
  Order_Status    []Order `json:"orders" bson:"orders"`
}

Code At Glance in controllers.go

This file mainly describes about the token authentication process . We have used the JWT authentication from dgrijalwa but now the repository has changed . I have used the same implemtaion for signup and login from https://dev.to/joojodontoh/build-user-authentication-in-golang-with-jwt-and-mongodb-2igd , this blog is clear and precise about jwt auhentication rather than my explanation here.

There is an important thing we have to remember when defining array struct the mongodb converts the array to a nil in document field

So to overcome this problem we make an empty array in signup function like this,whever a user calls the signup function it initialise the documents to empty array

user.UserCart  =   make([]models.ProductUser, 0)
user.Address_Details = make([]models.Address, 0)
user.Order_Status = make([]models.Order, 0)
  • SIGNUP FUNCTION API CALL (POST REQUEST)

http://localhost:8000/users/signup

{
  "first_name": "Joseph",
  "last_name": "Hermis",
  "email": "[email protected]", // Use @example.com for email because that is it's purpose. See https://www.rfc-editor.org/rfc/rfc6761.html and https://www.rfc-editor.org/rfc/rfc2606.html
  "password": "unlucky",
  "phone": "+1558426655"
}

Response :"Successfully Signed Up!!"

{
  "email": "[email protected]",
  "password": "unlucky"
}

response will be like this

{
  "_id": "***********************",
  "first_name": "joseph",
  "last_name": "hermis",
  "password": "$2a$14$UIYjkTfnFnhg4qhIfhtYnuK9qsBQifPKgu/WPZAYBaaN17j0eTQZa",
  "email": "[email protected]",
  "phone": "+1558921455",
  "token": "eyJc0Bwcm90b25vbWFpbC5jb20iLCJGaXJzdF9OYW1lIjoiam9zZXBoIiwiTGFzdF9OYW1lIjoiaGVybWlzIiwiVWlkIjoiNjE2MTRmNTM5ZjI5YmU5NDJiZDlkZjhlIiwiZXhwIjoxNjMzODUzNjUxfQ.NbcpVtPLJJqRF44OLwoanynoejsjdJb5_v2qB41SmB8",
  "Refresh_Token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJFbWFpbCI6IiIsIkZpcnLCJVaWQiOiIiLCJleHAiOjE2MzQzNzIwNTF9.ocpU8-0gCJsejmCeeEiL8DXhFcZsW7Z3OCN34HgIf2c",
  "created_at": "2021-10-09T08:14:11Z",
  "updtaed_at": "2021-10-09T08:14:11Z",
  "user_id": "61614f539f29be942bd9df8e",
  "usercart": [],
  "address": [],
  "orders": []
}

Login Function call create an outlayer for our collection

{
  "product_name": "laptop",
  "price": 300,
  "rating": 10,
  "image": "1.jpg"
}

Response : "Successfully added our Product Admin!!"

Response

[
  {
    "Product_ID": "6153ff8edef2c3c0a02ae39a",
    "product_name": "notepad",
    "price": 50,
    "rating": 10,
    "image": "penc.jpg"
  },
  {
    "Product_ID": "616152679f29be942bd9df8f",
    "product_name": "laptop",
    "price": 300,
    "rating": 10,
    "image": "1.jpg"
  },
  {
    "Product_ID": "616152ee9f29be942bd9df90",
    "product_name": "top",
    "price": 300,
    "rating": 10,
    "image": "1.jpg"
  },
  {
    "Product_ID": "616152fa9f29be942bd9df91",
    "product_name": "table",
    "price": 300,
    "rating": 10,
    "image": "1.jpg"
  },
  {
    "Product_ID": "616153039f29be942bd9df92",
    "product_name": "apple",
    "price": 300,
    "rating": 10,
    "image": "1.jpg"
  }
]
  • Search Product by regex function (GET REQUEST)

defines the word search sorting http://localhost:8000/users/search?name=le

response:

[
  {
    "Product_ID": "616152fa9f29be942bd9df91",
    "product_name": "table",
    "price": 300,
    "rating": 10,
    "image": "1.jpg"
  },
  {
    "Product_ID": "616153039f29be942bd9df92",
    "product_name": "apple",
    "price": 300,
    "rating": 10,
    "image": "1.jpg"
  }
]

The corresponding Query to mongodb is ProductCollection.Find(ctx, bson.M{"product_name": bson.M{"$regex": queryParam}})

filter := bson.D{primitive.E{Key: "_id", Value: id}}
update := bson.D{{Key: "$push", Value: bson.D{primitive.E{Key: "usercart", Value: bson.D{{Key: "$each", Value: productcart}}}}}}
_, err = UserCollection.UpdateOne(ctx, filter, update)
filter := bson.D{primitive.E{Key: "_id", Value: usert_id}}

update := bson.M{"$pull": bson.M{"usercart": bson.M{"_id": removed_id}}}
_, err = UserCollection.UpdateMany(ctx, filter, update)
  • Listing the item in the users cart (GET REQUEST) and total price

    http://localhost:8000/listcart?id=xxxxxxuser_idxxxxxxxxxx

    Corresponding Mongodb Query (WE are using the aggrgate operation to find sum)

     filter_match := bson.D{{Key: "$match", Value: bson.D{primitive.E{Key: "_id", Value: usert_id}}}}
    unwind := bson.D{{Key: "$unwind", Value: bson.D{primitive.E{Key: "path", Value: "$usercart"}}}}
    grouping := bson.D{{Key: "$group", Value: bson.D{primitive.E{Key: "_id", Value: "$_id"}, {Key: "total", Value: bson.D{primitive.E{Key: "$sum", Value: "$usercart.price"}}}}}}
    pointcursor, err := UserCollection.Aggregate(ctx, mongo.Pipeline{filter_match, unwind, grouping})
    
  • Addding the Address (POST REQUEST)

    http://localhost:8000/addadress?id=user_id**\*\***\***\*\***

    The Address array is limited to two values home and work address more than two address is not acceptable

{
  "house_name": "jupyterlab",
  "street_name": "notebook",
  "city_name": "mars",
  "pin_code": "685607"
}

Code At Glance in main.go

All the routes defined here requires the api authentication key

Repo dedicting to my best friend mathappan 🐶 ,who left me without saying a goodbye and fill me with hopes even in my dark days RIP my friend

Here are some of the reference I gone through while working on this project

JWT Authentication using golang 1

MongoDB Quick Introduction with Golang official blog 2

Package context instead of goroutine 3

Context use cases in real scenarios 4

Mongo GO Driver official Documentation 5

Mongo Go official go documentation 6

Is "logout" useless on a REST API? 7

JWT AUTHENTICATION OFFICIAL 8

Gin framework Documentation 9

Footnotes

  1. https://dev.to/joojodontoh/build-user-authentication-in-golang-with-jwt-and-mongodb-2igd

  2. https://www.mongodb.com/blog/post/quick-start-golang-mongodb-starting-and-setup

  3. https://pkg.go.dev/context

  4. https://levelup.gitconnected.com/context-in-golang-98908f042a57

  5. https://docs.mongodb.com/drivers/go/current/

  6. https://pkg.go.dev/go.mongodb.org/mongo-driver/mongo

  7. https://stackoverflow.com/questions/36294359/is-logout-useless-on-a-rest-api

  8. github.com/golang-jwt/jwt

  9. https://github.com/gin-gonic/gin

ecommerce's People

Contributors

5olitude avatar j0holo avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.