<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Ahmed Ben Bettaieb</title>
    <description>The latest articles on DEV Community by Ahmed Ben Bettaieb (@ahmedbenbettaieb).</description>
    <link>https://dev.to/ahmedbenbettaieb</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F856108%2Fae5fb5f3-58dd-4b92-9a39-402f3ddd49dc.png</url>
      <title>DEV Community: Ahmed Ben Bettaieb</title>
      <link>https://dev.to/ahmedbenbettaieb</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/ahmedbenbettaieb"/>
    <language>en</language>
    <item>
      <title>Create custom connect and transfer money stripe for non registered countries</title>
      <dc:creator>Ahmed Ben Bettaieb</dc:creator>
      <pubDate>Thu, 15 Jun 2023 14:19:26 +0000</pubDate>
      <link>https://dev.to/ahmedbenbettaieb/create-custom-connect-and-transfer-money-stripe-for-non-registered-countries-3o9m</link>
      <guid>https://dev.to/ahmedbenbettaieb/create-custom-connect-and-transfer-money-stripe-for-non-registered-countries-3o9m</guid>
      <description>&lt;p&gt;Hello, &lt;br&gt;
Through this post I will show how to create a stripe account and make a connect , and transfer money to the connect  using node js (express  with typescript) .&lt;br&gt;
Assuming that your node js project is setup. &lt;br&gt;
first of all you need to create a stripe account (in estonia) :&lt;br&gt;
&lt;a href="https://www.youtube.com/watch?v=vEbD8SQg5So&amp;amp;ab_channel=DistroTechnologies"&gt;https://www.youtube.com/watch?v=vEbD8SQg5So&amp;amp;ab_channel=DistroTechnologies&lt;/a&gt;&lt;br&gt;
follow this video .&lt;br&gt;
after creating the stripe account you will get your publishable key and secret key , copy  them and put them in .env file .&lt;br&gt;
then run this command :&lt;br&gt;
&lt;code&gt;npm install stripe @types/stripe&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;then make a user model (mongoose) :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;`import { Schema, Document, model } from 'mongoose';

// Define the User interface
interface IUser extends Document {
  name: string;
  email: string;
  birthDate: Date;
  accountId: string;
  password: string;
}

// Define the User schema
const UserSchema = new Schema&amp;lt;IUser&amp;gt;({
  name: { type: String, required: true },
  email: { type: String, required: true },
  birthDate: { type: Date, required: true },
  accountId: { type: String, required: true },
  password: { type: String, required: true },
});

// Create and export the User model
const User = model&amp;lt;IUser&amp;gt;('User', UserSchema);
export default User;`
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and make sure to make an authMiddleware to verify that the user is authenticated:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;`import { Request, Response, NextFunction } from "express";
import jwt from "jsonwebtoken";
import dotenv from "dotenv";
dotenv.config();

const authMiddleware = (
  req: Request,
  res: Response,
  next: NextFunction
) =&amp;gt; {
  try {
    const token = req.headers["authorization"]?.split(" ")[1];

    if (!token &amp;amp;&amp;amp; !process.env.JWT_SECRET) {
      // Token does not exist or JWT_SECRET is not set in the environment variables
      console.log("Token does not exist");
      return res.status(401).send({
        message: "Authentication failed!",
        success: false,
      });
    } else {
      jwt.verify(
        token as string,
        process.env.JWT_SECRET as string,
        (err, decoded: any) =&amp;gt; {
          // Verifying the token
          console.log("Verifying token");
          if (err) {
            // Error occurred during token verification
            console.log(err);
            return res.status(401).send({
              message: "JWT verification failed!",
              success: false,
            });
          } else {
            // Token is valid, extracting the user ID from the decoded token and attaching it to the request body
            (req.body as any).userId = (decoded as any)._id;
            next();
          }
        }
      );
    }
  } catch (error: any) {
    // Catching any other errors that might occur
    console.log(error.message);
    return res.status(401).send({
      message: "Authentication failed",
      success: false,
    });
  }
};

export default authMiddleware;`

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;then create a folder named routes and under this folder we will create a file named paymentRoute.ts, first of all :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;`
//we import the stripe secret key and the public key from .env

const secret: string | undefined = process.env.STRIPE_SECRETKEY;
const publicKey: string | undefined = process.env.STRIPE_PUBLISHABLEKEY;

if (!secret) {
  throw new Error("Stripe secret key not found in environment variables.");
}

// Creating a new instance of the Stripe API using the secret key
const stripe = new Stripe(secret, {
  apiVersion: "2022-11-15",
});

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;after creating a new instance of stripe  ,we pass to creating the connect ,&lt;br&gt;
first  we create the custom connect  (assuming that the user is already defined ):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;router.post(
  "/create-stripe-account",
  authMiddleware,
  async (req: Request, res: Response) =&amp;gt; {
    try {
      const user = await User.findOne({ _id: req.body.userId });

      if (user) {
        if (!user.accountId) {
          // Creating a custom Stripe account for the user
          const accountParams: Stripe.AccountCreateParams = {
            country: "EE",
            type: "custom",
            business_type: "individual",
            email: user.email,
            capabilities: {
              card_payments: {
                requested: true,
              },
              transfers: {
                requested: true,
              },
            },
          };

          const account = await stripe.accounts.create(accountParams);

          // Saving the account ID to the user document
          user.accountId = account.id;
          await user.save();

          res.status(200).json({ data: account, success: true });
        } else {
          res
            .status(200)
            .json({ message: "You already have an account", success: false });
        }
      } else {
        res.status(404).json({ message: "User not found" });
      }
    } catch (error) {
      res.status(200).json("Something went wrong");
    }
  }
);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;if you access to your stripe account ,you will find a new connect but it is restricted .&lt;br&gt;
so , we must update the account using this route :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;router.put(
  "/update-stripe-account",
  authMiddleware,
  async (req: Request, res: Response) =&amp;gt; {
    try {
      const user = await User.findOne({ _id: req.body.userId });
      if (user) {
        const { firstName, lastName, email, accountId } = user;
        const birthDateString = user.birthDate; // Assuming `user.birthDate` is defined

        if (birthDateString) {
          const dateObj = new Date(birthDateString);

          const day = dateObj.getDate();
          const month = dateObj.getMonth() + 1; // Month is zero-based, so we add 1 to get the correct month
          const year = dateObj.getFullYear();



          const { city, line, postalCode, state, ipAddress, phone ,url,} = req.body;
          const date = Math.floor(Date.now() / 1000);

          const stripeAccount = await stripe.accounts.update(accountId, {
            business_type: "individual",
            settings: {
              payouts: {
                schedule: {
                  interval: "manual" as any,
                },
              },
            },
            email,

            individual: {
              first_name: firstName,
              last_name: lastName,
              email: email,
              maiden_name: firstName + " " + lastName,
              phone: phone,
              address: {
                city,
                line1: line,
                line2: line,
                postal_code: postalCode,
                state,
              },
              dob: {
                day,
                month,
                year,
              },
            },

            business_profile: {
              mcc: "7372",

              url: url,
              product_description:
                "Description of the business's products or services",
            },
            tos_acceptance: {
              date: date,
              ip: ipAddress,
            },
          });
          res.status(200).send({
            success: true,
            data: stripeAccount,
            message: "account updated successfully",
          });
        } else {
          res.status(404).send({
            message:
              "You should update your profile and add the missing information",
            success: false,
          });
        }
      }
    } catch (error) {
      console.log(error);
      res.status(500).json({ message: "something went wrong" });
    }
  }
);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;MCC stands for Merchant Category Code. It is a four-digit code used to categorize businesses based on the products or services they provide.  you can find mored details in this doc &lt;a href="https://stripe.com/docs/connect/setting-mcc"&gt;https://stripe.com/docs/connect/setting-mcc&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;now we should add a payout method , this is the route for adding payout method :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;router.post(
  "/add-payout-method",
  authMiddleware,
  async (req: Request, res: Response) =&amp;gt; {
    try {
      const user = await User.findOne({ _id: req.body.userId });
      if (user) {
        const accountId = user.accountId;
        const { accountType, accountDetails } = req.body;
        const account_holder_name = `${user.firstName} ${user.lastName}`;

        // Create a bank account or debit card token
        let externalAccountToken;
        if (accountType === "bank") {
          externalAccountToken = await stripe.tokens.create({
            bank_account: {
              country: "EE",
              currency: "eur",
              account_holder_name: account_holder_name,
              account_holder_type: "individual",
              account_number: accountDetails.accountNumber,
            },
          });
        } else if (accountType === "card") {
          externalAccountToken = await stripe.tokens.create({
            card: {
              number: accountDetails.cardNumber,
              exp_month: accountDetails.expMonth,
              exp_year: accountDetails.expYear,
              cvc: accountDetails.cvc,
              currency: "eur",
            },
          });

          const externalAccount = await stripe.accounts.createExternalAccount(
            accountId,
            {
              external_account: externalAccountToken.id,
            }
          );

          await stripe.accounts.update(accountId, {
            capabilities: {
              transfers: { requested: true },
            },
          });
        } else {
          return res.status(400).json({ message: "Invalid account type" });
        }

        // Associate the bank account or debit card with the Stripe account
        await stripe.accounts.createExternalAccount(accountId, {
          external_account: externalAccountToken.id,
        });

        res
          .status(200)
          .json({ success: true, message: "Payout method added successfully" });
      } else {
        res.status(404).json({ message: "User not found" });
      }
    } catch (error) {
      res.status(500).json({ error });
    }
  }
);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;test this route with this json file :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "accountType": "bank",
  "accountDetails": {
    "accountNumber": "EE382200221020145685"
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;after adding payout method now the custom connect is ready to receive money  , this is the route for making transfer:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;router.post("/transaction/:contractId", authMiddleware, async (req, res) =&amp;gt; {
  try {
    const user = await User.findOne({ _id: req.body.userId });

    const contract = await Contract.findOne({
      _id: req.params.contractId,
    });
    if (user &amp;amp;&amp;amp; contract) {
      const paymentIntent = await stripe.paymentIntents.create(
        {
          amount: contract.price,
          currency: "eur",
          automatic_payment_methods: {
            enabled: true,
          },
        },
        {
          stripeAccount: user.accountId,
        }
      );

      console.log("user and contract found");
      const freelancerTransfer = await stripe.transfers.create({
        amount: contract.price*99,
        currency: "eur",
        destination: user.accountId,
      });


      user.unSeenNotifications.push(
        "your transaction is  created successfully"
      );
      user.save();

      res.status(200).json({
        message: "Transfer created successfully",

      });
    } else {
      res.status(404).json({ message: "User or contract not found" });
    }
  } catch (error) {
    res.status(500).json({ error });
  }
});

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;for my project , the amount was taken from the contract price .&lt;br&gt;
after making the the last route and test it with postman  ,and we can access to our stripe dashboard :&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--J_P4Gynv--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/5lrn1ptmwny73bzk6f00.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--J_P4Gynv--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/5lrn1ptmwny73bzk6f00.png" alt="Dashboard" width="800" height="113"&gt;&lt;/a&gt;&lt;br&gt;
we see that the connect has received his money and he is ready to payout.&lt;/p&gt;

&lt;p&gt;Note:I'm speaking for test mode&lt;/p&gt;

&lt;p&gt;That's it , I wish  it was helpful !&lt;br&gt;
I'm waiting for  your feedbacks&lt;/p&gt;

</description>
    </item>
    <item>
      <title>TypeError: this.userRepository.signUp is not a function</title>
      <dc:creator>Ahmed Ben Bettaieb</dc:creator>
      <pubDate>Mon, 24 Oct 2022 22:47:04 +0000</pubDate>
      <link>https://dev.to/ahmedbenbettaieb/typeerror-thisuserrepositorysignup-is-not-a-function-47cm</link>
      <guid>https://dev.to/ahmedbenbettaieb/typeerror-thisuserrepositorysignup-is-not-a-function-47cm</guid>
      <description>&lt;p&gt;I'm new on nest js and I encountered this error while developping login service ``import { Injectable } from '@nestjs/common';&lt;br&gt;
import { UserRepository } from './user.repository';&lt;br&gt;
import { InjectRepository } from '@nestjs/typeorm';&lt;br&gt;
import { AuthSignUpDto } from './dto/auth-signup.dto';&lt;/p&gt;

&lt;p&gt;@Injectable()&lt;br&gt;
export class AuthService {&lt;br&gt;
  constructor(&lt;br&gt;
    @InjectRepository(UserRepository)&lt;br&gt;
    private userRepository: UserRepository,&lt;br&gt;
  ) {}&lt;br&gt;
  async signUp(authSignUpDto: AuthSignUpDto): Promise {&lt;br&gt;
    return this.userRepository.signUp(authSignUpDto)&lt;br&gt;
  }&lt;br&gt;
}&lt;code&gt;&lt;br&gt;
&lt;/code&gt;&lt;/p&gt;

</description>
      <category>nestjs</category>
    </item>
    <item>
      <title>Route is not working</title>
      <dc:creator>Ahmed Ben Bettaieb</dc:creator>
      <pubDate>Sun, 01 May 2022 14:07:01 +0000</pubDate>
      <link>https://dev.to/ahmedbenbettaieb/route-is-not-working-4llk</link>
      <guid>https://dev.to/ahmedbenbettaieb/route-is-not-working-4llk</guid>
      <description>&lt;p&gt;I'am working on a full stach web site using spring and angular  but the routes are not working &lt;br&gt;
this is the spring boot application code to  search category by ID &lt;br&gt;
 &lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--gskC8x39--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ue2atxt5lvo5m43d2x23.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--gskC8x39--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ue2atxt5lvo5m43d2x23.png" alt="Image description" width="800" height="133"&gt;&lt;/a&gt;&lt;br&gt;
and here is the routes &lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--S84WK5si--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/6ye90xky84mudlpg50rt.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--S84WK5si--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/6ye90xky84mudlpg50rt.png" alt="Image description" width="664" height="230"&gt;&lt;/a&gt;&lt;br&gt;
and this is the product service  class and the his urls &lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--ofPa32xS--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/kor1myrl3ykee394xv1z.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ofPa32xS--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/kor1myrl3ykee394xv1z.png" alt="Image description" width="800" height="346"&gt;&lt;/a&gt;&lt;br&gt;
and this is the product list component &lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s---EHohXv_--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/igixvjg0mkc14qnx5fxe.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s---EHohXv_--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/igixvjg0mkc14qnx5fxe.png" alt="Image description" width="800" height="571"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
    </item>
  </channel>
</rss>
