Skip to content

Payment Flow

To better understand the payment flow, the diagram below illustrates the different steps to complete a payment by your customer through YouCan Pay.

Steps

  • Tokenization — When the customer arrives to the payment page, and you want to display the YouCan Pay form you need to generate a token for the current transaction. This token will allow you to encapsulate your order info (amount, currency, order ID, etc).
  • Form Display — In this step, you include the JS and HTML for display for credit card form where the user will input his card info.
  • Start Payment — When the customer clicks on the pay button, a request will be sent to YouCan Pay server to process the payment. If the customer card has 3DS enabled, he will be redirected to the bank page to validate the transaction and come back to YouCan Pay server. If the customer card doesn't have 3DS enabled, YouCan Pay will process the transaction directly.
  • Payment Processed — When the transaction is processed the customer will be redirected to your application. Depending on the transaction status (success/error) it will redirect to the endpoint you defined.

Creating an Instance of YCPay

The first step is to include the YouCan Pay JS code in your markup. When the code is loaded, we're ready to render the payment form using the code snippet below.

Constructor Parameters

ParameterTypeDescription
publicKeyrequiredThe seller's YouCanPay account public key. This lets us know who is receiving the payment.
optionsExtra configuration options to tailor the integration to your needs.
options.formContainerrequiredThe CSS selector for the container in which we will render the integration. If no container is found, the integration won't render.
options.localeoptionalThe language in which to display the forms and error messages. Currently supports en, ar, and fr. If no locale is specified, it will be automatically inferred from the browser or fall back to en as a default locale.
options.isSandboxoptionalSpecifies whether or not to run the integration in Sandbox Mode, this is useful for testing your integration. It is recommended to set this to false or omit it entirely in production, as it is false by default.
options.errorContaineroptionalThe CSS selector for the container in which we will display all errors related to the usage of the integration. This is set to #ycp-error-container by default. If no container is found, no errors will be displayed.
options.customCSSoptionalCSS code to style the integration to your liking.
options.tokenoptionalIn case you have a single static payment token, you can pass it here in the constructor. By doing so you do not need to pass it to the .pay() method. Token can be updated using the .setToken() method.

Code

html
<script src="https://youcanpay.com/js/ycpay.js"></script>

<div id="error-container"></div>
<div id="payment-container"></div>
<button id="pay">Pay</button>

<script type="text/javascript">
    const ycPay = new YCPay('pub_key', {
        formContainer: '#payment-container',
        locale: 'en',
        isSandbox: false,
        errorContainer: '#error-container',
        customCSS: '',
        token: 'token_x6gf0_....'
    });
</script>

Tokenization

The tokenization is the process of generating a token for your current transaction. This token will hold your order data (order ID, amount, currency). The amount should be in smallest currency unit (e.g., 100 cents to charge $1.00). Since this process is critical, it should be done in your backend using our SDK.

Method Parameters

ParameterTypeDescription
orderIdrequiredIdentifier of the order you want to be paid.
amountrequiredInteger amount: The amount, Example: 25 USD is 2500.
currencyrequiredCurrency: Uppercase currency.
customerIPrequiredCustomer Address IP.
successUrlrequiredThis URL is returned when the payment is successfully processed.
errorUrlrequiredThis URL is returned when payment is invalid.
customerInfooptionalData of the customer who wishes to make this purchase.
metadataoptionalYou can use it to send data to retrieve after the response or in the webhook.

Command

bash
composer require youcanpay/payment-sdk

Code

php
use YouCan\Pay\YouCanPay;

$youCanPay = YouCanPay::instance()->useKeys('pri_key', 'pub_key');

// Data of the customer who wishes to make this purchase.
$customerInfo = [
    'name'         => '',
    'address'      => '',
    'zip_code'     => '',
    'city'         => '',
    'state'        => '',
    'country_code' => '',
    'phone'        => '',
    'email'        => '',
];

$metadata = [
    // Can insert what you want here...
    //'key' => 'value'
];

// generate a token for a new payment
$token = $youCanPay->token->create(
    "order-id",
    "2000",
    "USD",
    "123.123.123.123",
    "https://yourdomain.com/orders-status/success",
    "https://yourdomain.com/orders-status/failed",
    $customerInfo,
    $metadata
);

echo $token->getId();

Form Display

The next step is to render the form in your markup, this is done by using one of the render methods that the instantiated ycPay object provides.

Credit Card Form

renderCreditCardForm(theme?) — Renders the Credit Card form directly inside the specified container. Takes in an optional theme parameter.

CashPlus Form

renderCashPlusForm(theme?) — Renders the CashPlus form directly inside the specified container. Takes in an optional theme parameter.

Available Gateways

renderAvailableGateways(gateways, theme?) — Alternatively, if you wish to allow users to select how they want to pay, you could use this method. Takes in an array of gateway names as an additional parameter; currently supported gateways are "CashPlus" and "CreditCard". If an empty array is provided, renders all available gateways for the account. If only a single gateway is available, it will be rendered directly without prompting the user to pick a method. Takes in an optional theme parameter.

Reset the Integration Form

reset(theme?) — In some cases you might want to refresh the visuals of the form once the payment is done. This method allows you to reset the visuals of the currently rendered form.

Update the YCP Token

setToken(token) — When setting the token from the constructor, you are limited on how you want to handle your payment, especially if your token gets updated regularly and you don't have the ability to set it via the .pay() method. In that case, use this method to update it, guaranteeing your token always being updated.

Code

html
<script src="https://youcanpay.com/js/ycpay.js"></script>

<div id="error-container"></div>
<div id="payment-container"></div>
<button id="pay">Pay</button>

<script type="text/javascript">
    const ycPay = new YCPay('pub_key', {
        locale: 'en',
        isSandbox: false,
        errorContainer: '#error-container',
        formContainer: '#payment-container'
    });

    // render the payment methods
    ycPay.renderAvailableGateways([], 'default')
</script>

Start Payment

The tokenId is the one generated in the tokenization section. The successCallback is called when the transaction is successful, and you get the final transaction ID that you can submit with your order details. Similarly, errorCallback is called when an error occurs during the payment, and you get the error message as a parameter to show to the customer.

Congrats, now you're ready to accept payments from customers using YouCan Pay.

Code

html
<script type="text/javascript">
  const ycPay = new YCPay('pub_key', {
      formContainer: '#payment-container',
  });

  // render the form
  ycPay.renderCreditCardForm();

  // start the payment on button click
  document.getElementById('pay').addEventListener('click', function() {
    // execute the payment
    ycPay.pay(tokenId)
      .then(successCallback)
      .catch(errorCallback);
  })

  function successCallback(response) {
    //your code here
  }

  function errorCallback(response) {
    //your code here
  }
</script>

Payment Processed

Once the payment is done, you can get the details of the transaction in your backend to validate the amount, order ID, etc.

When the payment is processed by a Moroccan card, the transaction currency is converted to MAD. You can get the submitted original amount and currency from getBaseAmount(), getBaseCurrency() in the Transaction object.

Code

php
use YouCan\Pay\YouCanPay;

$youCanPay = YouCanPay::instance()->useKeys('pri_key', 'pub_key');

$transaction = $youCanPay->transaction->get("transaction-id");

if (is_null($transaction)) {
    // invalid transaction ID
}

// fetch your order
$order = Order::first();

// the amount is in smallest currency unit
$amount = $transaction->getBaseAmount() ?? $transaction->getAmount();

if (bccomp($amount, $order->getAmount()) !== 0) {
    // the YouCan Pay transaction amount is different than the order amount
}