Card Acquiring and Transfers
In the MBanq Cloud API, acquiring cards refers to the process of linking cards from other institutions to an end user's account. This functionality allows users to conveniently manage their funds across multiple financial institutions within the MBanq Cloud ecosystem. With acquiring cards, users can perform push or pull transfers to and from external accounts using the card network, enabling fast and secure fund transfers.
Available Funds Transfer Methods
There are multiple transfer channels to facilitate moving money into and out of your customer accounts.
Transfer Mechanism | Speed | Cost | Bank Coverage | Operating | Max Transfer | Funds Guaranteed |
---|---|---|---|---|---|---|
Card Acquiring | Fast | Moderate | Every Bank | Every Day | $1,000 | Mostly |
ACH | 2 Day | Low | Every Bank | Business Days | $1,000,000 | No |
Same Day ACH | Same Day | Moderate | Every Bank | Business Day | $1,000,000 | No |
Wire | Same Day | Expensive | Most Banks | Business Days | Unlimited | Yes |
Real Time Payment (RTP) | Fast | Moderate | Some Banks | Every Day | $1,000,000 | Yes |
Card acquiring transfers offer a good balance of speed and cost.
API References:
Flow of External Cards Usage
Using external cards in MBanq Cloud involves the following flow:
-
Linking the Card: Users can link cards from other institutions to their MBanq Cloud account.
-
Push Transfers: Users can perform push transfers, where funds are transferred from their MBanq Cloud account to the linked external account. This allows users to conveniently push funds to cover expenses or make payments using their card.
-
Pull Transfers: Users can initiate pull transfers, where funds are transferred from an external account to their MBanq Cloud account. This facilitates easy consolidation and management of funds.
To comply with the Payment Card Industry Data Security Standard (PCI DSS), which ensures the security of cardholder data, Mbanq aims to minimize the FinTech's PCI compliance requirements. One way to achieve this is by not storing sensitive card data, such as the card number, expiry date, and CVV code. Instead, all sensitive data will be encrypted with a public key on the user's device at the time of card entry. The encrypted data will then be securely transmitted to Mbanq, where it will be tokenized. A unique token will be issued to identify the acquired card, which will be used for all subsequent activities on the cards.
Encryption Standards and Requirements
To ensure strong encryption, Mbanq adopts the RSA encryption algorithm with the transformation of RSA/ECB/OAEPWithSHA-256AndMGF1Padding. This ensures the secure encryption of sensitive card data before transmission. The following requirements are important for implementing encryption:
- RSA Encryption with OAEP and SHA-256: Use the RSA algorithm with Optimal Asymmetric Encryption Padding (OAEP) and SHA-256 hash for encryption.
- Public Key: Obtain the public key required for encryption using the API : Public Key API . The public key is used to encrypt the sensitive card data.
- Base64 URL-Safe Encoding: Convert the encrypted data to Base64 URL-Safe format before transmitting it to Mbanq's servers.
Example: Card Encryption in Java
package com.mbanq;
import javax.crypto.Cipher;
import javax.crypto.spec.OAEPParameterSpec;
import javax.crypto.spec.PSource;
import java.nio.charset.StandardCharsets;
import java.security.KeyFactory;
import java.security.PublicKey;
import java.security.spec.MGF1ParameterSpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.Base64;
public class Encryption {
private static final String msf_sRSA_ALGORITHM = "RSA";
private static final String msf_sRSA_TRANSFORMATION = "RSA/ECB/OAEPPadding";
private static final Base64.Encoder msf_encoderBase64 = Base64.getUrlEncoder().withoutPadding();
private static final Base64.Decoder msf_decoderBase64 = Base64.getUrlDecoder();
public static void main(String[] args) throws Exception {
final var result = encryptUsingPublicKey("Public Key",
"Card Number|Expired|CVV");
System.out.println("Encrypted : " + result);
}
public static String encryptUsingPublicKey(String p_sEncodedPublicKey, String p_sData) throws Exception {
if (p_sEncodedPublicKey != null && p_sEncodedPublicKey.length() != 0) {
if (p_sData != null && p_sData.length() != 0) {
byte[] abPublicKey;
try {
abPublicKey = msf_decoderBase64.decode(p_sEncodedPublicKey);
} catch (Throwable var10) {
throw new Exception("Data", var10);
}
try {
KeyFactory factoryKey = KeyFactory.getInstance("RSA");
X509EncodedKeySpec specX509EncodedKey = new X509EncodedKeySpec(abPublicKey);
PublicKey keyPublic = factoryKey.generatePublic(specX509EncodedKey);
Cipher cipher = Cipher.getInstance("RSA/ECB/OAEPPadding");
OAEPParameterSpec paramSpec = new OAEPParameterSpec("SHA-256", "MGF1", MGF1ParameterSpec.SHA256, PSource.PSpecified.DEFAULT);
cipher.init(1, keyPublic, paramSpec);
byte[] abData = cipher.doFinal(p_sData.getBytes(StandardCharsets.UTF_8));
return msf_encoderBase64.encodeToString(abData);
} catch (Throwable var9) {
throw new Exception("Encrypt Using Public Key", var9);
}
} else {
throw new Exception("Data");
}
} else {
throw new Exception("Public Key");
}
}
}
/**
* @param {string} str
*/
function unescapeBase64(str) {
// convert Base64 URL-Safe to Base64 regular
return (str + '==='.slice((str.length + 3) % 4)).replace(/-/g, '+').replace(/_/g, '/');
}
/**
* @param {string} str
*/
function escapeBase64(str) {
// convert Base64 regular to Base64 URL-Safe
return str.replace(/\+/g, '-').replace(/\//g, '_').replace(/=/g, '');
}
/**
* @param {string} keyID
*/
function importRSAKey(keyID) {
// fetch the part of the PEM string between header and footer
const pemContents = unescapeBase64(keyID)
// base64 decode the string to get the binary data
const binaryDerString = window.atob(pemContents);
// convert from a binary string to an ArrayBuffer
const binaryDer = stringToArrayBuffer(binaryDerString);
return window.crypto.subtle.importKey("spki", binaryDer, { name: "RSA-OAEP", hash: "SHA-256" }, true, ["encrypt"]);
}
/**
* @param {string} str
*/
function stringToArrayBuffer(str) {
// String to array buffer
const buf = new ArrayBuffer(str.length);
const bufView = new Uint8Array(buf);
for (let i = 0, strLen = str.length; i < strLen; i++) {
bufView[i] = str.charCodeAt(i);
}
return buf;
}
/**
* @param {string} value
*/
function getStringEncoding(value) {
let enc = new TextEncoder();
return enc.encode(value);
}
/**
* @param {ArrayBuffer} buffer
*/
function arrayBufferToBase64(buffer) {
let binary = '';
const bytes = new Uint8Array(buffer);
const len = bytes.byteLength;
for (let i = 0; i < len; i++) {
binary += String.fromCharCode(bytes[i]);
}
return window.btoa(binary);
}
(function () {
// keyID is ASN.1 Format Base64 URL-Safe
const keyID = 'WcCBIjAnBGkhki...';
// cardInfo format `${cardAccountNumber}|${cardExpirationDate format('YYYYMM')}|${cardSecurityCode}`
const cardInfo = '9010100999999995|209912|123';
importRSAKey(keyID).then(RSAKey => {
let encoded = getStringEncoding(cardInfo);
window.crypto.subtle.encrypt({ name: "RSA-OAEP" }, RSAKey, encoded)
.then(data => {
// encrypted data
const dataEncrypted = arrayBufferToBase64(data);
// use value return from escapeBase64(dataEncrypted) with Tabapay
console.log(escapeBase64(dataEncrypted))
});
});
})();
In the provided code snippets, you can see an example implementation of encrypting card information using a public key. The code demonstrates how to perform encryption using RSA/ECB/OAEPPadding transformation. You can adapt this code to your specific implementation needs, ensuring that you handle the encryption and decryption processes securely.
Additional Considerations
- Test Card Numbers: When testing the implementation, make sure to use test card numbers provided below. Never use real card numbers in the Sandbox Environment to comply with PCI requirements. The following Card Numbers were randomly generated, and any resemblance to actual Card Numbers is purely coincidental.
Network | Card Number | Regulated | Card Type- Debit | Card Type - Credit | Card Type- PrePaid | Pull | Push (Availability) - Immediate | Push (Availability) - Next | Push (Availability) - Few |
---|---|---|---|---|---|---|---|---|---|
Visa | 4000056655665556 | ✘ No | ✔ | ✔ | ✔ | ||||
4005519200000004 | ✔ Yes | ✔ | ✔ | ✔ | |||||
4111111111111111 | ✔ Yes | ✔ | ✔ | ✔ | |||||
4012000077777777 | ✔ Yes | ✔ | ✔ | ✔ | |||||
4000000760000002 | ✔ Yes | ✔ | ✔ | ✔ | |||||
4000001240000000 | ✔ Yes | ✔ | ✔ | ✔ | |||||
4000004840008001 | ✔ Yes | ✔ | ✔ | ✔ | |||||
4500600000000061 | ✘ No | ✔ | ✔ | ✔ | |||||
4217651111111119 | ✘ No | ✔ | ✘ | ✔ | |||||
4242424242424242 | ✘ No | ✔ | ✘ | ||||||
Mastercard | 2223000048400011 | ✘ No | ✔ | ✔ | ✘ | ||||
5200828282828210 | ✔ Yes | ✔ | ✔ | ✘ | |||||
5403879999999997 | ✔ Yes | ✔ | ✔ | ✘ | |||||
5105105105105100 | ✔ Yes | ✔ | ✔ | ✘ | |||||
MoneySend | 2223003122003222 | ✘ No | ✘ | ✔ | |||||
5555555555554444 | ✔ Yes | ✘ | ✔ | ||||||
American Express | 371449635398431 | ✔ Yes | ✔ | ✔ | ✔ | ||||
378282246310005 | ✔ Yes | ✔ | ✔ | ✔ | |||||
378734493671000 | ✔ Yes | ✔ | ✔ | ✔ | |||||
Discover | 6011111111111117 | ✔ Yes | ✔ | ✔ | ✔ | ||||
6011000990139424 | ✔ Yes | ✔ | ✔ | ✔ | |||||
6011000991300009 | ✔ Yes | ✔ | ✔ | ✔ |
- Security Measures: Follow best practices for authentication and security measures to protect user data and ensure secure transactions.
For more detailed information on using external cards in MBanq Cloud API, refer to the tutorial in the next section.
Updated 9 months ago