Skip to content

Latest commit

 

History

History
269 lines (223 loc) · 10.5 KB

File metadata and controls

269 lines (223 loc) · 10.5 KB

5. Visa and Mastercard Specific Requests

When implementing a jPOS client for processing Visa and Mastercard transactions, it's crucial to create custom services that handle the specific requirements of each card network. These services will encapsulate the logic for creating and sending ISO-8583 messages tailored to Visa and Mastercard specifications.

Let's create two services: one for Visa and one for Mastercard. Each service will handle common transaction types such as purchases, cash advances, refunds, and balance inquiries.

5.1 Visa Transaction Service

First, let's create an interface for our Visa transaction service:

package com.example.jpos.service;

import org.jpos.iso.ISOException;
import org.jpos.iso.ISOMsg;

public interface VisaTransactionService {
    ISOMsg createPurchaseRequest(String pan, String amount, String merchantId) throws ISOException;
    ISOMsg createCashAdvanceRequest(String pan, String amount, String merchantId) throws ISOException;
    ISOMsg createRefundRequest(String pan, String amount, String merchantId, String originalRrn) throws ISOException;
    ISOMsg createBalanceInquiryRequest(String pan, String merchantId) throws ISOException;
}

Now, let's implement this interface:

package com.example.jpos.service.impl;

import com.example.jpos.service.VisaTransactionService;
import org.jpos.iso.ISOException;
import org.jpos.iso.ISOMsg;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;

@Service
public class VisaTransactionServiceImpl implements VisaTransactionService {

    private static final String VISA_MTI_REQUEST = "0100";
    private static final DateTimeFormatter DATE_TIME_FORMATTER = DateTimeFormatter.ofPattern("MMddHHmmss");

    @Override
    public ISOMsg createPurchaseRequest(String pan, String amount, String merchantId) throws ISOException {
        ISOMsg msg = new ISOMsg();
        msg.setMTI(VISA_MTI_REQUEST);
        msg.set(2, pan);
        msg.set(3, "000000"); // Processing code for purchase
        msg.set(4, amount);
        msg.set(7, LocalDateTime.now().format(DATE_TIME_FORMATTER));
        msg.set(11, generateStan());
        msg.set(18, "5999"); // Merchant category code (example)
        msg.set(32, "123456"); // Acquiring Institution ID Code
        msg.set(41, merchantId);
        msg.set(49, "840"); // Currency code (USD)
        return msg;
    }

    @Override
    public ISOMsg createCashAdvanceRequest(String pan, String amount, String merchantId) throws ISOException {
        ISOMsg msg = new ISOMsg();
        msg.setMTI(VISA_MTI_REQUEST);
        msg.set(2, pan);
        msg.set(3, "010000"); // Processing code for cash advance
        msg.set(4, amount);
        msg.set(7, LocalDateTime.now().format(DATE_TIME_FORMATTER));
        msg.set(11, generateStan());
        msg.set(18, "6011"); // Merchant category code for ATM
        msg.set(32, "123456"); // Acquiring Institution ID Code
        msg.set(41, merchantId);
        msg.set(49, "840"); // Currency code (USD)
        return msg;
    }

    @Override
    public ISOMsg createRefundRequest(String pan, String amount, String merchantId, String originalRrn) throws ISOException {
        ISOMsg msg = new ISOMsg();
        msg.setMTI(VISA_MTI_REQUEST);
        msg.set(2, pan);
        msg.set(3, "200000"); // Processing code for refund
        msg.set(4, amount);
        msg.set(7, LocalDateTime.now().format(DATE_TIME_FORMATTER));
        msg.set(11, generateStan());
        msg.set(18, "5999"); // Merchant category code (example)
        msg.set(32, "123456"); // Acquiring Institution ID Code
        msg.set(37, originalRrn); // Retrieval Reference Number of the original transaction
        msg.set(41, merchantId);
        msg.set(49, "840"); // Currency code (USD)
        return msg;
    }

    @Override
    public ISOMsg createBalanceInquiryRequest(String pan, String merchantId) throws ISOException {
        ISOMsg msg = new ISOMsg();
        msg.setMTI(VISA_MTI_REQUEST);
        msg.set(2, pan);
        msg.set(3, "300000"); // Processing code for balance inquiry
        msg.set(7, LocalDateTime.now().format(DATE_TIME_FORMATTER));
        msg.set(11, generateStan());
        msg.set(18, "6011"); // Merchant category code for ATM
        msg.set(32, "123456"); // Acquiring Institution ID Code
        msg.set(41, merchantId);
        msg.set(49, "840"); // Currency code (USD)
        return msg;
    }

    private String generateStan() {
        // Generate a unique 6-digit STAN (System Trace Audit Number)
        return String.format("%06d", (int) (Math.random() * 999999));
    }
}

5.2 Mastercard Transaction Service

Now, let's create a similar service for Mastercard transactions:

package com.example.jpos.service;

import org.jpos.iso.ISOException;
import org.jpos.iso.ISOMsg;

public interface MastercardTransactionService {
    ISOMsg createPurchaseRequest(String pan, String amount, String merchantId) throws ISOException;
    ISOMsg createCashAdvanceRequest(String pan, String amount, String merchantId) throws ISOException;
    ISOMsg createRefundRequest(String pan, String amount, String merchantId, String originalRrn) throws ISOException;
    ISOMsg createBalanceInquiryRequest(String pan, String merchantId) throws ISOException;
}

And its implementation:

package com.example.jpos.service.impl;

import com.example.jpos.service.MastercardTransactionService;
import org.jpos.iso.ISOException;
import org.jpos.iso.ISOMsg;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;

@Service
public class MastercardTransactionServiceImpl implements MastercardTransactionService {

    private static final String MASTERCARD_MTI_REQUEST = "0100";
    private static final DateTimeFormatter DATE_TIME_FORMATTER = DateTimeFormatter.ofPattern("MMddHHmmss");

    @Override
    public ISOMsg createPurchaseRequest(String pan, String amount, String merchantId) throws ISOException {
        ISOMsg msg = new ISOMsg();
        msg.setMTI(MASTERCARD_MTI_REQUEST);
        msg.set(2, pan);
        msg.set(3, "000000"); // Processing code for purchase
        msg.set(4, amount);
        msg.set(7, LocalDateTime.now().format(DATE_TIME_FORMATTER));
        msg.set(11, generateStan());
        msg.set(18, "5999"); // Merchant category code (example)
        msg.set(32, "654321"); // Acquiring Institution ID Code
        msg.set(41, merchantId);
        msg.set(49, "840"); // Currency code (USD)
        msg.set(61, "0000000000000001"); // Point-of-Service Data (example)
        return msg;
    }

    @Override
    public ISOMsg createCashAdvanceRequest(String pan, String amount, String merchantId) throws ISOException {
        ISOMsg msg = new ISOMsg();
        msg.setMTI(MASTERCARD_MTI_REQUEST);
        msg.set(2, pan);
        msg.set(3, "010000"); // Processing code for cash advance
        msg.set(4, amount);
        msg.set(7, LocalDateTime.now().format(DATE_TIME_FORMATTER));
        msg.set(11, generateStan());
        msg.set(18, "6011"); // Merchant category code for ATM
        msg.set(32, "654321"); // Acquiring Institution ID Code
        msg.set(41, merchantId);
        msg.set(49, "840"); // Currency code (USD)
        msg.set(61, "0000000000000002"); // Point-of-Service Data (example)
        return msg;
    }

    @Override
    public ISOMsg createRefundRequest(String pan, String amount, String merchantId, String originalRrn) throws ISOException {
        ISOMsg msg = new ISOMsg();
        msg.setMTI(MASTERCARD_MTI_REQUEST);
        msg.set(2, pan);
        msg.set(3, "200000"); // Processing code for refund
        msg.set(4, amount);
        msg.set(7, LocalDateTime.now().format(DATE_TIME_FORMATTER));
        msg.set(11, generateStan());
        msg.set(18, "5999"); // Merchant category code (example)
        msg.set(32, "654321"); // Acquiring Institution ID Code
        msg.set(37, originalRrn); // Retrieval Reference Number of the original transaction
        msg.set(41, merchantId);
        msg.set(49, "840"); // Currency code (USD)
        msg.set(61, "0000000000000003"); // Point-of-Service Data (example)
        return msg;
    }

    @Override
    public ISOMsg createBalanceInquiryRequest(String pan, String merchantId) throws ISOException {
        ISOMsg msg = new ISOMsg();
        msg.setMTI(MASTERCARD_MTI_REQUEST);
        msg.set(2, pan);
        msg.set(3, "300000"); // Processing code for balance inquiry
        msg.set(7, LocalDateTime.now().format(DATE_TIME_FORMATTER));
        msg.set(11, generateStan());
        msg.set(18, "6011"); // Merchant category code for ATM
        msg.set(32, "654321"); // Acquiring Institution ID Code
        msg.set(41, merchantId);
        msg.set(49, "840"); // Currency code (USD)
        msg.set(61, "0000000000000004"); // Point-of-Service Data (example)
        return msg;
    }

    private String generateStan() {
        // Generate a unique 6-digit STAN (System Trace Audit Number)
        return String.format("%06d", (int) (Math.random() * 999999));
    }
}

5.3 Using the Transaction Services

To use these services in your application, you can inject them into your controllers or other services. Here's an example of how you might use them in a transaction processing service:

package com.example.jpos.service;

import org.jpos.iso.ISOException;
import org.jpos.iso.ISOMsg;
import org.jpos.iso.MUX;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
public class TransactionProcessingService {

    @Autowired
    private VisaTransactionService visaService;

    @Autowired
    private MastercardTransactionService mastercardService;

    @Autowired
    private MUX mux;

    public ISOMsg processPurchase(String pan, String amount, String merchantId, String cardNetwork) throws ISOException {
        ISOMsg request;
        if ("visa".equalsIgnoreCase(cardNetwork)) {
            request = visaService.createPurchaseRequest(pan, amount, merchantId);
        } else if ("mastercard".equalsIgnoreCase(cardNetwork)) {
            request = mastercardService.createPurchaseRequest(pan, amount, merchantId);
        } else {
            throw new IllegalArgumentException("Unsupported card network: " + cardNetwork);
        }

        return mux.request(request, 30000); // 30 seconds timeout
    }

    // Similar methods for cash advance, refund, and balance inquiry
}

This implementation provides a clean separation of concerns, making it easy to handle the specific requirements of each card network while providing a unified interface for transaction processing.