Skip to main content

Final Project Deliverables

Solstra Payments is a final project for II3160 Integrated Systems Technology by Muhammad Faiz A (18222063)

Business Goals: Help business accept Borderless Decentralized Payment using Solana Cryptocurrency

Core Unique Capabilities: Solana-based payment creation address as payment gateway and email payment invoice

Main Feature: Payment Gateway


Source Code: https://git.faizath.com/solstra/core API Domain: https://api-staging.solstra.fi

Obtain JWT Bearer Token and API key by login using email login endpoint and Google Oauth login through

https://api-staging.solstra.fi/user/auth/google

API Endpoints

MethodEndpointUsage
POST/user/auth/email/sendLogin using email, login link will be sent to email
POST/service/pay/createCreate new unique payment adress
POST/service/pay/${paymentID}/checkVerify transaction paid and expired status
POST/service/invoice/createCreate Email Invoice, new unique payment address is sent to email
GET/user/encryptedSecretKeyBackupDownload User Encrypted Secret key Backup

API Endpoints Details

POST /user/auth/email/send

  • Description: Login using email, login link will be sent to email
  • Request Body:
    {
    "name": "Faiz A",
    "email": "m@faiz.at"
    }
  • Responses:
    • 200 (Success):
      {
      "status": "success",
      "message": "Email sent. Please check yout inbox",
      "data": {}
      }
    • 400 (Error):
       {
      "status": "error",
      "message": "{error message}",
      "data": {}
      }

POST /service/pay/create

  • Description: Create new unique payment adress
  • Authorization: X-API-Key
  • Request Body:
    {
    "currency": "SOL",
    "amount": 0.0001
    }
  • Responses:
    • 200 (Success):
      {
      "status": "success",
      "message": "New Payment Order Created",
      "data": {
      "id": "67814ad7cb7cd94e48929a8d",
      "currency": "SOL",
      "amount": 0.0001,
      "walletAddress": "5nFwLbKbaNbDMCgFxgmvArZEHZEFY2ucskCzHeD6TKve",
      "checkPaid": "http://api-staging.solstra.fi/service/pay/67814ad7cb7cd94e48929a8d/check",
      "expireAt": "2025-01-10T16:34:11.923Z"
      }
      }
    • 400 (Error):
       {
      "status": "error",
      "message": "{error message}",
      "data": {}
      }

POST /service/pay/${paymentID}/check

  • Description: Verify transaction paid and expired status
  • Authorization: X-API-Key
  • Responses:
    • 200 (Success):
      {
      "status": "success",
      "message": "Payment Status: Paid",
      "data": {
      "id": "677eba192141a7f1f0765ba7",
      "currency": "SOL",
      "amount": 0.0265625,
      "walletAddress": "AEaAarW5kyVfj8qn4FZxJkfTajS9xofKztNsB48vUH5C",
      "checkPaid": "http://api-staging.solstra.fi/service/pay/677eba192141a7f1f0765ba7/check",
      "isPaid": true,
      "isExpired": false
      }
      }
    • 400 (Error):
       {
      "status": "error",
      "message": "{error message}",
      "data": {}
      }

POST /service/invoice/create

  • Description: Create Email Invoice, new unique payment address is sent to email
  • Authorization: X-API-Key
  • Request Body:
    {
    "currency": "SOL",
    "amount": 0.0001,
    "email": "m@faiz.at"
    }
  • Responses:
    • 200 (Success):
      {
      "status": "success",
      "message": "New Payment Order Created and Sent to Email",
      "data": {
      "id": "67814c17cb7cd94e48929bbf",
      "currency": "SOL",
      "amount": 0.0001,
      "walletAddress": "G6RDf6DiXNhPdjkd3ismFxBRvjG58goMeyCd5utJseie",
      "checkPaid": "http://api-staging.solstra.fi/service/pay/67814c17cb7cd94e48929bbf/check",
      "expireAt": "2025-01-10T16:39:31.613Z"
      }
      }
    • 400 (Error):
       {
      "status": "error",
      "message": "{error message}",
      "data": {}
      }

GET /user/encryptedSecretKeyBackup

  • Description: Download User Encrypted Secret key Backup
  • Authorization: Bearer Token
  • Responses:
    • 200 (Success):
      {
      "status": "success",
      "message": "Downloading Encrypted Secret Key Backup Successful",
      "data": {
      "encryptedSecretKeyBackup": "{\"key_id\":\"r8q6LggYiMV0XFxuro-ZRA\",\"cipher_text\":\"VTLipGKQqC6/9Dpe2WpmSiGIcRM5biLce83pilp9ZA8VAClWYDtq28dOs6oWxGFDlDGqsjcJ/c6Zp9Un1rdiA8tWsfkL1TcsDVEHGk656dT0FoUx5u2RIxjId9HriQ+rmFwsTF0XZNEDKmiCehQjD8iR3iXo2GlRiWw5qVcqOh50Rp2iCytm6Di9+sBIbLeyzgeqCAS4l9QVLItacrPGiNaye5oqm1siBqbMSCUo52NTbvzh2cG9qLaW92vnRLIXLvZa5R/U+jp5oGuGUEBD9ZzTGPuepi7nk4i6+Nr+/p9aNAvGQZnvas+JofH7aOF3dtVWI/Dpu9jmF3J3LDAFCMTbQkqj9jRT3dk+uv7xQ/LRCjlSqvOVF69FBhsO81jc5bih7tmPrZLObbPTtgnhvkeZJafLVuSdrvStkFpxhN5HaRJwjUWTgq90AV2s2Il70uZwRHt1hSWJGPVw6EK85da/uN+I4RtpLf82mEyCuoZHs+ZuDqvkvMEv+CKqKVXXz3W1LLMGW2k73CKovXsDT0LTSav4brVL4YwTFtOTvzZw31m1iAXmtYNIKN5FcTpunYt5Atgncw4ikxhFJ+FYyjzzT3J2yEV5Yaes4qxJU5a67Vzu5az3HPGMdHdcGHu+bHZuR3o7z2I8ZaxtqhuEthSxJk4oRUOpnGJsjVWrkjnOD/dVlm/M1MzTyfXukoe3fuquF0e1qYtSIEFx+rwbFcbTedkK78X9ccINrslUB4xP5bJouvqZdIlHHV+cMoooJLI=\",\"iv\":\"CtbOTBRobnASHX2RBf5S+A==\"}"
      }
      }
    • 400 (Error):
       {
      "status": "error",
      "message": "{error message}",
      "data": {}
      }

Business Capability Map

Business Capability Map

Subdomain

Subdomain

  1. Payment Wallet Creation Create Solana payment address on the fly by generating keypair locally.

  2. Transaction Status Checking Check transaction status by connecting to blockchain and evaluate if Solana wallet balance are greater than or equal to the required transaction amount created previously.

  3. Email Payment Invoice Create Solana payment address and send the transaction address to customer email address.

  4. User Authentication Authenticate user API request using JWT Bearer token for User-related API and API Key for PAyment-related API

  5. Encrypted Secret Key Backup Encrypted Secret Key is backed-up using third-party service “Furina Encryption Service”. The backup is encrypted so the third-party service cant read the plaintext state of the content. User also can download the Encrypted Secret Key Backup through the API.

  6. Transaction Status Check Scheduler Pending transaction is stored in cached and periodically checked using scheduler. Every transaction is checked whether the transaction is paid or expired and if one condition met is removed from cache.

Software Architecture

Backend

javascript logonodejs logoexpress logomongodb logoredis logo

  1. Javascript

    As the backend server that serve core API is using Nodejs runtime environment and Express.js web framework, Javascipt is the main language used in this project.

  2. Nodejs

    Nodejs is the javascript runtime environment that execute javascript code in the backend server. Nodejs is chosen because Nodejs is the most well-known javascript runtime and has a lot of dependencies available to use.

  3. Express.js

    Express.js is the web framework that handle http request in the backend. Express.js is a part of MERN Stack (MongoDB, Express.js, React and Nodejs) so it's a powerful nodejs web framework and optimized for MERN Stack.

  4. MongoDB

    MongoDB is the non-relational database used to store services data. MongoDB is a part of MERN Stack (MongoDB, Express.js, React and Nodejs) so it's a powerful non-relational database and optimized for MERN Stack.

  5. Redis

    Redis is a key-value Cache used to store pending transaction and rate-limit. Redis is chosen as it's simple yet powerful key-value cache.

Payment Gateway Functionality

Create payment address

https://git.faizath.com/solstra/core/src/branch/staging/app/domains/services/payment/service.payment.controller.js

const web3 = require("@solana/web3.js");
let userKeypair = web3.Keypair.generate();
let walletAddress = userKeypair.publicKey.toString();

Check if payment address is paid

https://git.faizath.com/solstra/core/src/branch/staging/app/utils/web3/checkPaid.js

const web3 = require('@solana/web3.js');
const connection = new web3.Connection(RPC_URL, 'confirmed');
const balance = await connection.getBalance(publicKey);
const formattedBalance = balance / (10 ** 9);
if (formattedBalance > required_balance_to_pay) {
// Payment address is paid
} else {
// Payment address is still unpaid
}

Authentication

Payment-related API is authorized using API Key

https://git.faizath.com/solstra/core/src/branch/staging/app/middlewares/auth/api-key/api.verify.js

const api_key = req.header("x-api-key");
if (!api_key) {
return res.status(401).json({
status: "error",
message: "Unauthorized: X-Api-Key Header required",
data: {}
});
}
const paymentProfile = await Payment.findOne({ apiKey: api_key });
if (!paymentProfile) {
return res.status(401).json({
status: 'error',
message: 'Unauthorized: Invalid Authentication',
data: {}
});
}
req.paymentProfile = paymentProfile;
next();

User-related API is authorized using JWT Bearer token

https://git.faizath.com/solstra/core/src/branch/staging/app/middlewares/auth/jwt/jwt.verify.js

const jwt = require("jsonwebtoken");
jwt.verify(token, process.env.JWT_SECRET, (err, decoded) => {
if (err) {
return res.status(401).json({
status: "error",
message: "Unauthorized: Invalid Authentication",
data: {}
});
}
req.user = decoded;
next();
});

Hosting

linux logoubuntu logodocker logonginx logo

Backend Server is hosted on VPS running Ubuntu (GNU/Linux). Backend Server is built to Docker container image and served using Nginx reverse proxy. Docker container is managed using Caprover.

Implementation

  1. Git repository is initialized in developer's local machine and Caprover app created with CI/CD enabled using Gitea webhook to Caprover

  2. Npm is initialized in developer's local machine. Dependencies (Tech stacks) is installed using Npm. MongoDB database schema is created.

  3. Backend server is developed using VSCodium IDE by creating Express.js Router and Controller. First handling user creation, then payment address creation, and transaction status checker.

  4. Third-party service is integrated by adding required database schema and API endpoint.

  5. Git repository is pushed to remote, sending webhook to Caprover, then the Caprover will do git pull to the repository. The Caprover then build and run the Docker image from the Dockerfile.

Features

  1. Create Payment Address (Solana)
  2. Automatic Transaction Status Checking
  3. Email Payment Invoice (New Payment Address sent directly to customers)

Integration

This service used the third-party service, Furina Encryption Service (https://furina-encryption-service.codebloop.my.id/docs) provided by Wisyendra Lunarmalam (18222095) to encrypt and backup User Encrypted Wallet Secret Key. The backup is encrypted so the third-party service cant read the plaintext state of the content. User also can download the Encrypted Secret Key Backup through the API.

Source Code Directory Structure

app
├── configs
│   ├── cache
│   │   └── redis // Redis cache config
│   └── database
│   └── mongodb // MongoDB config
├── domains // Domains directory, using Domain Driven Design Architecture
│   ├── services
│   │   ├── invoice // Invoice generator
│   │   └── payment // Payment generator
│   └── users
│   ├── actions
│   │   └── auth
│   │   ├── email
│   │   └── google
│   └── entities
├── middlewares
│   └── auth
│   ├── api-key
│   ├── jwt
│   └── passport
├── routes
├── templates
│   ├── email
│   └── pages
└── utils
├── auth
│   └── jwt
├── mail
├── scheduler
└── web3