How to use Visa +

Push to wallets with Visa +

A new service enabling both transfers between participating P2P payment apps and real-time payouts to participating apps.

📘

Please note that Visa + uses the TabaPay Tag resource

If you see Tag anywhere in the guide below, assume that it is referring to the Visa + Payname.

For more information on what Visa + has to offer, please check out our Visa + overview.

Integrations

The technical integration for Visa + is relatively simple:

  1. Ask your account manager to enable Visa + for you in sandbox.
  2. Integrate with two API calls:
    1. Query Tag - to validate the payname before initiating a transaction.
    2. Create Transaction - to push funds to a payname.
  3. Set up your own consumer flow.
  4. Set up your own risk controls.
    1. TabaPay offers a series of tools to provide merchants with information, including the Query Tag, that can be used as part of an overall fraud control strategy. That being said, it is ultimately the merchant's responsibility to have systems in place to interpret said information and take the appropriate precautions. The Merchant has full responsibility when it comes to the business decisions they make within their system.
    2. Note that this payment type is irreversible. Refer to Best Practices for Instant Payouts and Risk Best Practices for Visa+ for more information.

Configuration

You will need to be configured for:

  1. Visa + API access
    1. Create Transaction tag name fields
    2. Query Tag endpoint
  2. Push transactions with Visa

API Calls

Example Flow:

  1. Merchant receives a payname from their end user.

  2. Merchant sends the payname to the Query Tag endpoint. There are a few options:

    1. Merchant just sends the payname and no match is performed, but they receive the recipients name
      Request:

      const options = {
        method: 'POST',
        headers: {accept: 'application/json', 'content-type': 'application/json'},
        body: JSON.stringify({network: 'Visa', tagName: '+sammy.wallet'})
      };
      
      fetch('https://fqdn/v1/clients//tags', options)
        .then(response => response.json())
        .then(response => console.log(response))
        .catch(err => console.error(err));
      

      Response:

      {
        "SC": 200,
        "EC": "0",
        "codeConfirmResult": "A",
        "name": {
          "first": "Sam",
          "middle": "Wise",
          "last": "Gamkee"
        }
      }
      
    2. Merchant sends both payname and last 4 digits of the recipients phone number and receives both a match and the recipients name.
      Request:

      const options = {
        method: 'POST',
        headers: {accept: 'application/json', 'content-type': 'application/json'},
        body: JSON.stringify({network: 'Visa', tagName: '+sammy.wallet', phoneLast4: '4343'})
      };
      
      fetch('https://fqdn/v1/clients//tags', options)
        .then(response => response.json())
        .then(response => console.log(response))
        .catch(err => console.error(err));
      

      Response:

      {
        "SC": 200,
        "EC": "0",
        "codeConfirmResult": "M",
        "name": {
          "first": "Sam",
          "middle": "Wise",
          "last": "Gamkee"
        }
      }
      
    3. Merchant sends both payname and last 4 digits of the recipients phone number and the phone does not match but they still receive recipients name.
      Request:

      const options = {
        method: 'POST',
        headers: {accept: 'application/json', 'content-type': 'application/json'},
        body: JSON.stringify({network: 'Visa', tagName: '+sammy.wallet', phoneLast4: '5858'})
      };
      
      fetch('https://fqdn/v1/clients//tags', options)
        .then(response => response.json())
        .then(response => console.log(response))
        .catch(err => console.error(err));
      

      Response:

      {
        "SC": 200,
        "EC": "0",
        "codeConfirmResult": "N",
        "name": {
          "first": "Sam",
          "middle": "Wise",
          "last": "Gamkee"
        }
      }
      
  3. Merchant would then consume the result from the Query Tag API and apply their own business rules to the result. Based on that, they may choose to drop the transaction, continue with the transaction, or try something different.

  4. If they decide to move forward with the Create Transaction call, they need to use the the tag name fields:
    Request:

    const options = {
      method: 'POST',
      headers: {
        'Accept': 'application/json',
        'Content-Type': 'application/json',
        'Authorization': 'Bearer *******'
      },
      body: {
        "referenceID": "myUniqueRef",
        "type": "push",
        "accounts": {
          "sourceAccountID": "22_Char_SettlmntAcctID",
          "destinationAccount": {
            "tag": {
              "network": "Visa",
              "name": "+sammy.wallet"
            },
            "owner": {
              "name": {
                "first": "Sammy",
                "last": "Doe"
              }
            }
          }
        },
        "amount": "1.00"
      }
    };
    
    fetch('https://fqdn/v1/clients/22xCharacterxClientIDx_0001/transactions', options)
      .then(response => response.json())
      .then(response => console.log(response))
      .catch(err => console.error(err));
    

    Response:

    {
      "SC": 200,
      "EC": "0",
      "transactionID": "TabaPay_TransactionID_",
      "network": "Visa",
      "networkID": "123454646545645",
      "networkRC": "00",
      "status": "COMPLETED",
      "approvalCode": "000000"
    }
    

Recipes