How To Use Stripe Connect With Custom Account (Vendor Account) In Magento 2?

stripe connect with custom account in magento 2

Stripe is one of the most popular payment gateways for Magento 2 e-commerce stores. In this Magento tutorial, we will show you how to integrate Stripe to Magento 2 websites and use a custom account.

With the custom account (vendor account), you can modify the connected account’s details and settings through the API, including managing their bank accounts and payout schedule.

Step 1: Stripe connect module installation & configuration

  • Download the Stripe Payment For Magento 2 module here and install it on your site.
  • Create a new Stripe account here.
  • After finishing the installation process, open your admin panel, navigate to STORES > Configuration > SALES > Payment Methods. Under Stripe Payment Gateway, expand Stripe Core, and enter your Production Publishable API Key and Production Secret API Key (taken from your Stripe account information).
stripe connect magento 2
  • Enable all Stripe payment method(s) you want to use.

Step 2: Module customization to use with the custom account

1/ Create a module named Tigren_StripeConnect with front name = tigren

2/ Make a new form for connecting Stripe custom account

  • Create a new controller in Tigren/StripeConnect/Controller/Stripe name account with the following content:
<?php

namespace Tigren\StripeConnect\Controller\Stripe;

use Magento\Backend\App\Action\Context;
use Magento\Framework\View\Result\PageFactory;

class Account extends \Magento\Backend\App\Action
{
    /**
     * @var PageFactory
     */
    protected $resultPagee;

    /**
     * @param Context     $context
     * @param PageFactory $resultPageFactory
     */
    public function __construct(
        Context $context,
        PageFactory $resultPageFactory
    ) {
        parent::__construct($context);
        $this->resultPageFactory = $resultPageFactory;
    }

    /**
     * Index action
     *
     * @return void
     */
    public function execute()
    {
        /** @var \Magento\Backend\Model\View\Result\Page $resultPage */
        $resultPage = $this->resultPageFactory->create();


        return $resultPage;
    }
}

?>
  • Create a new layout in Tigren/StripeConnect/view/frontend/layout named tigren_stripe_account.xml with the following content:
<?xml version="1.0"?>
<page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xsi:noNamespaceSchemaLocation="../../../../../../../lib/internal/Magento/Framework/View/Layout/etc/page_configuration.xsd">
    <body>
        <referenceContainer name="content">
            <block class="Tigren\StripeConnect\Block\Stripe\Form" name="tigren-stripeconnnect-form " template="Tigren_StripeConnect::stripe/form.phtml"/>
        </referenceContainer>
    </body>
</page>
  • In “Tigren\StripeConnect\Block\Stripe\Form” add the following content:
<?php
namespace Tigren\StripeConnect\Block\Stripe;

class Form extends \Magento\Backend\Block\Template
{

    protected $_url;

    public function __construct(
        \Magento\Framework\UrlInterface $url,
        \Magento\Backend\Block\Template\Context $context, array $data = []
    ) {
        parent::__construct($context, $data);
        $this->Url = $url;
    }
    public function getPostUrl()
    {
        $url = $this->url->getUrl("tigren/stripe/createandconnect");
        return $url;
    }

}
  • In Tigren/StripeConnect /view/templates/stripe/form.phtml add the following content:
<form class="form" action='<?php echo $this->getPostUrl() ?>' method="post">
    <input name="form_key" type="hidden" value="<?php /* @escapeNotVerified */ echo $this->getFormKey() ?>" />
    <fieldset class="fieldset">
        <legend class="legend"><span><?php echo __('Create Account') ?></span></legend><br>
        <div class="field required">
            <label for="account_country" class="label">
                <span><?php echo __('Country') ?></span>
            </label>
            <div class="control">
                <select name="account_country" id="account_country">
                    <option value="NZ">New Zealand</option>
                </select>
            </div>
        </div>
        <div class="field required">
            <label for="account_currency" class="label">
                <span><?php echo __('Currency') ?></span>
            </label>
            <div class="control">
                <select name="account_currency" id="account_currency">
                    <option value="NZD">New Zealand Dollar
                    </option>
                </select>
            </div>
        </div>
        <div class="field required">
            <label for="account_number" class="label">
                <span><?php echo __('Account Number') ?></span>
            </label>

            <div class="control">
                <input type="text" id="account_number"
                       name="account_number"
                       class="input-text">
            </div>
        </div>
<div class="field required">
            <label for="account_holder_name" class="label">
                <span><?php echo __('Account Holder Name') ?></span>
            </label>

            <div class="control">
                <input type="text" id="account_holder_name"
                       name="account_holder_name"
                       class="input-text">
            </div>
        </div>
        <div class="field required">
            <label for="account_holder_type" class="label">
                <span><?php echo __('Account Holder Type  ') ?></span>
            </label>

            <div class="control">
                <select name="account_holder_type"  id="account_holder_type">
                    <option value="company">Company</option>
                </select>
            </div>
        </div>
<div class="field required">
            <label for="account_email" class="label">
                <span><?php echo __('Account Email') ?></span>
            </label>

            <div class="control">
                <input type="text" id="account_email"
                       name="account_email"
                       class="input-text">
            </div>
        </div>
        <div class="field required">
            <label for="business_name" class="label">
                <span><?php echo __('Business name') ?></span>
            </label>

            <div class="control">
                <input type="text" id="business_name"
                       name="business_name"
                       class="input-text">
            </div>
        </div>
        <div class="field required">
            <label for="support_phone" class="label">
                <span><?php echo __('Support Phone') ?></span>
            </label>

            <div class="control">
                <input type="text" id="support_phone"
                       name="support_phone"
                       class="input-text">
            </div>
        </div>
<div class="field required">
            <label for="support_url" class="label">
                <span><?php echo __('Support Url') ?></span>
            </label>

            <div class="control">
                <input type="text" id="support_url"
                       name="support_url"
                       class="input-text">
            </div>
        </div>
        <div class="field required">
            <label for="account_url" class="label">
                <span><?php echo __('Url') ?></span>
            </label>

            <div class="control">
                <input type="text" id="account_url"
                       name="account_url"
                       class="input-text">
            </div>
        </div>



    </fieldset>

    <div class="actions-toolbar">
        <div class="primary">
            <button type="submit" class="action submit primary" title="<?php echo __('Submit') ?>">
                <span><?php echo __('Submit') ?></span>
            </button>
        </div>
    </div>

</form>

Note: Your form field may vary, depending on which country you are in.

3/ Create a function to create and connect the custom account to the main account:

  • Create new config to save Account ID of your Stripe account, under “app/code/Tigren/Stripe Connect/etc/adminhtml/system.xml” with the following content:
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Config:etc/system_file.xsd">
    <system>
        <section id="payment">
            <group id="stripecore" translate="label" type="text" sortOrder="1" showInDefault="1" showInWebsite="1" showInStore="1">
                <field id="client_account_id" translate="label" type="text" showInDefault="1" showInWebsite="1" showInStore="0">
                    <label>Client Account Id</label>
                    <config_path>payment/stripecore/client_account_id</config_path>
                </field>
                <field id="test_client_account_id" translate="label" type="text" showInDefault="1" showInWebsite="1" showInStore="0">
                    <label>Test Client Account Id</label>
                    <config_path>payment/stripecore/test_client_account_id</config_path>
                </field>
            </group>
        </section>
    </system>
</config>
  • Go to STORES > Configuration > SALES > Payment Methods > Stripe > Stripe Core, enter Client Account ID (taken from your Stripe account information). The Test Client Account ID is only needed for testing using the sandbox.
  • Create “app\code\Tigren\StripeConnect\etc\di.xml” with the following content:
<?xml version="1.0"?>
<!--
/**
 * Copyright © Magento, Inc. All rights reserved.
 * See COPYING.txt for license details.
 */
-->
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
<preference for="Stripeofficial\Core\Helper\Data" type="Tigren\StripeConnect\Helper\Stripe\Data" />
</config>
  • Create new helper under “app/code/Tigren/StripeConnect/Helper/Stripe” name Stripe.php with the following content:
<?php

namespace Tigren\StripeConnect\Helper\Stripe;

use Magento\Store\Model\ScopeInterface;
use \Magento\Checkout\Model\Session as CheckoutSession;
use Magento\Framework\Encryption\EncryptorInterface;
use Magento\Framework\App\Config\ScopeConfigInterface;
use Stripeofficial\Core\Model\Logger;

// class Data extends \Magento\Framework\App\Helper\AbstractHelper
class Data extends \Stripeofficial\Core\Helper\Data
{
    /**
     * @var ScopeConfigInterface
     */
    protected $scopeConfig;

    /**
     * @var EncryptorInterface
     */
    protected $encryptor;

    /**
     * @var Logger
     */
    protected $logger;

    /**
     * @var bool|null
     */
    protected $isDebug = null;

    protected $checkoutSession;
    public function __construct(
        ScopeConfigInterface $scopeConfig,
        EncryptorInterface $encryptor,
        Logger $logger,
        CheckoutSession $checkoutSession
    ) {
        parent::__construct($scopeConfig, $encryptor, $logger);
        $this->scopeConfig = $scopeConfig;
        $this->encryptor = $encryptor;
        $this->logger = $logger;
        $this->checkoutSession = $checkoutSession;
    }



    /**
     * Get default statement descriptor;
     *
     * @return string
     */
    public function getStatementDescriptor()
    {
        $result = (string)$this->scopeConfig->getValue('payment/stripecore/statement_descriptor', ScopeInterface::SCOPE_STORE);

        if (empty($result)) {
            return '';
        }

        return $result;
    }

    /**
     * Get the publishable api key
     *
     * @return string
     */
    public function getAPIKey()
    {
        if ($this->getTestMode()) {
            return $this->encryptor->decrypt((string)$this->scopeConfig->getValue('payment/stripecore/test_api_key', \Magento\Store\Model\ScopeInterface::SCOPE_STORE));
        } else {
            return $this->encryptor->decrypt((string)$this->scopeConfig->getValue('payment/stripecore/api_key', \Magento\Store\Model\ScopeInterface::SCOPE_STORE));
        }
    }

    /**
     * Get the secret api key
     *
     * @return string
     */
    public function getAPISecretKey()
    {
        if ($this->getTestMode()) {
            return $this->encryptor->decrypt((string)$this->scopeConfig->getValue('payment/stripecore/test_api_secret_key', \Magento\Store\Model\ScopeInterface::SCOPE_STORE));
        } else {
            return $this->encryptor->decrypt((string)$this->scopeConfig->getValue('payment/stripecore/api_secret_key', \Magento\Store\Model\ScopeInterface::SCOPE_STORE));
        }
    }
    /**
     * @return bool
     */
    public function getTestMode()
    {
        return $this->scopeConfig->isSetFlag('payment/stripecore/test_mode', \Magento\Store\Model\ScopeInterface::SCOPE_STORE);
    }

    /**
     * @return bool
     */
    public function getDebugMode()
    {
        if ($this->isDebug === null) {
            $this->isDebug = $this->scopeConfig->isSetFlag('payment/stripecore/debug', \Magento\Store\Model\ScopeInterface::SCOPE_STORE);
        }

        return $this->isDebug;
    }

    /**
     * @return Logger
     */
    public function getLogger()
    {
        return $this->logger;
    }

    /**
     * @return ScopeConfigInterface
     */
    public function getScopeConfig()
    {
        return $this->scopeConfig;
    }
    public function getClientId()
    {
        if ($this->getTestMode()) {
            return (string)$this->scopeConfig->getValue('payment/stripecore/test_client_account_id', \Magento\Store\Model\ScopeInterface::SCOPE_STORE);
        } else {
            return (string)$this->scopeConfig->getValue('payment/stripecore/client_account_id', \Magento\Store\Model\ScopeInterface::SCOPE_STORE);
        }
    }
}
  • Create new controller under “app/code/Tigren/StripeConnect/Controller/Stripe” named Createandconnect.php with following content:
<?php

namespace Tigren\StripeConnect\Controller\Stripe;

use Stripe\Stripe;
use Stripe\Account;
use Stripe\Token;

class Createandconnect extends \Magento\Backend\App\Action
{
    public $data;
    protected $session;

    public function __construct(
        \Magento\Backend\App\Action\Context $context,
        \Tigren\StripeConnect\Helper\Stripe\Data $data

    )
    {
        $this->data = $data;
        parent::__construct($context);
    }

    public function execute()
    {
        Stripe::setApiKey($this->data->getAPISecretKey());
        $formData = $this->getRequest()->getParams();
            ///create bank token
            $bankToken = Token::create(
                [
                    'bank_account' => [
                        'country' => $formData['account_country'],
                        'currency' => $formData['account_currency'],
                        'account_holder_name' => $formData['account_holder_name'],
                        'account_holder_type' => $formData['account_holder_type'],
                        'account_number' => $formData['account_number']
                    ]
                ]
            );
            if (isset($bankToken['id'])) {
                //create custom account
                $account = Account::create([
                    'country' => $formData['account_country'],
                    'type' => 'custom',
                    'email' => $formData['account_email'],
                    'tos_acceptance' => array(
                        'date' => time(),
                        'ip' => $_SERVER['REMOTE_ADDR']
                    ),
                    "business_type" => "company",
                    "business_profile" => array(
                        "mcc" => null,
                        "name" => $formData['business_name'],
                        "product_description" => 'treatment',
                        "support_email" => $formData['account_email'],
                        "support_phone" => $formData['support_phone'],
                        "support_url" => $formData['support_url'],
                        "url" => $formData['account_url']
                    ),

                ]);
                if (isset($account['id'])) {
                    //creat bank account for custom account

                    $bank_account = Account::createExternalAccount(
                        $account['id'],
                        [
                            'external_account' => $bankToken['id'],
                        ]
                    );
                }
                else {
                    $this->handleError("can't create account");
                }
            }
            else {
                $this->handleError("can't create bank token");
            }
            
            ///////you should save account id and bank account id to  your model
            
            $yourModel->setData('account_id', $account['id']);
            $yourModel->setData('bank_account_id', $bank_account['id']);
            $yourModel->save();
           
            $this->getMessageManager()->addSuccessMessage('your account is now connected');
            $this->_redirect('/');


    }
    public function handleError($message)
    {
        $this->getMessageManager()->addErrorMessage($message);
        $this->_redirect('/');
    }
}
  • Now you can go to BaseUrl/tigren/stripe/account fill out the information, and then the custom account will be created and connected to your main platform

Step 3: Check out and transfer money to the custom account (vendor account)

  • In “app\code\Tigren\Stripe Connect\etc\di.xml” add new preference:
<preference for="Stripeofficial\Core\Model\Payment" type="Tigren\ StripeConnect \Model\Stripe\Payment" />
  • Create new php file “Tigren\Stripe Connect\Model\Stripe\Payment” with the following content:
<?php
namespace Tigren\StripeConnect\Model\Stripe;

use Stripe\Charge as StripeCharge;
use Stripe\Customer;
use Stripe\Error\InvalidRequest;
use Magento\Framework\Exception\LocalizedException;


class Payment extends \Stripeofficial\Core\Model\Payment
{

    public function charge($capture, $token, $amount, $currencyCode, $customerId, $method = null, $metaData = null, $saveSource = null)
    {
        $isCoin = $this->data->checkQuoteIsHealthCoin();
        if($isCoin){
            return parent::charge($capture, $token, $amount, $currencyCode, $customerId, $method, $metaData, $saveSource);
        }
        $statement = $this->data->getStatementDescriptor();
        $this->init();
        $request = [
            "amount" => $amount,
            "currency" => $currencyCode,
            "source" => $token,
            "metadata" => $metaData,
        ];

        if (!empty($customerId)) {
            $request['customer'] = $customerId;
        }

        if (!in_array($method, ['giropay', 'sofort','bancontact','sepa', 'sepa_debit', 'p24','ideal', 'alipay'])) {
            // Add statement_descriptior when payment is not redirect methods
            $request['capture'] = $capture;

            if ($currencyCode == 'jpy') {
                $statement = self::DEFAULT_STATEMENT;
            }

            if (!empty($statement)) {
                $request['statement_descriptor'] = $statement;
            }
        }

        if ($customerId !== null) {
            $source = $this->getSource($token);

            if ($source->usage == 'reusable') {
                $request["customer"] = $customerId;
                $customer = Customer::retrieve($customerId);
                /** @var Collection $collection */
                $collection = $customer->sources;

                try {
                    if ($collection->total_count > 5) {
                        $data = $collection->all();
                        foreach ($data->data as $c) {
                            /** @var StripeSource $c */
                            $c->detach();
                        }
                    }

                    $collection->retrieve($token);
                } catch (InvalidRequest $e) {
                    $customer->sources->create(["source" => $token]);
                }
            }
        }

        if ($this->data->getDebugMode()) {
            $this->logger->info('Make charge request', $request);
        }

        //add transfer_data/destination to request
        $vendorAccountId=$yourModel->getData('account_id');
        if($vendorAccountId!=null && $ vendorAccountId!=false)
        {
            $request['transfer_data']=["destination"=> vendorAccountId];

        }else
        {
            throw new LocalizedException(__('This account not yet connected to platform account'));
        }

        //end
        return StripeCharge::create($request);
    }

}

Now, after checkout, the money will be transferred instantly from the platform to the vendor account.

[ratings]