Статьи

J2Pay — реализация шлюза

Вступление

Мы очень рады приветствовать участников, если вы работали над любым шлюзом, вы можете реализовать этот шлюз в нашей библиотеке и поддерживать мир с открытым исходным кодом.

Вы можете найти наш репозиторий github здесь

Прежде чем вы начнете реализовывать шлюз, есть несколько других классов, которые вы должны увидеть в первую очередь.

Ниже кратко определены классы.

HTTPClient

Главное при работе со шлюзами вы публикуете некоторые данные в шлюз и разбираете ответ.

Для работы с запросом http post этот класс предоставляет два перегруженных статических метода httpPost.

  1. общедоступный статический HTTPResponse httpPost (строковый URL, строковый postParams, ContentType contentType)
  2. общедоступный статический HTTPResponse httpPost (строковый URL, строковый postParams, ContentType contentType, кодировка Charset)

Так что вам не нужно беспокоиться об обработке http-запросов.

Помощники

Когда вы работаете с несколькими шлюзами, основная проблема, с которой обычно сталкивается разработчик, заключается в том, что некоторые шлюзы получают XML, а некоторые получают JSON или строку запроса, поскольку J2pay всегда возвращает JSON Response, поэтому вам не нужно беспокоиться о преобразовании данных между любым из этих XML, JSON или Строка запроса.

Вот список вспомогательных классов, расположенных в пакете com.tranxactive.paymentprocessor.net.

  1. QueryStringHelper
  2. JSONHelper
  3. StringHelper
  4. XMLHelper

Примечание. Все методы, определенные в вспомогательных классах, являются статическими.

Ответы

Для предоставления общего ответа j2pay предоставляет пять классов ответов, расположенных в пакете com.tranxactive.paymentprocessor.gateways.responses.

  1. ErrorResponse
  2. PurchaseResponse
  3. RebillResponse
  4. RefundResponse
  5. VoidResponse

Как вы можете определить по их именам, если вы работаете с методом покупки, вы будете использовать класс PurchaseResponse, если при работе с методом ребилла вы будете использовать класс RebillRespons и так далее

Класс ErrorResponse является единственным классом, который будет использоваться во всех четырех методах.

Одна вещь, которую вы также должны знать четыре класса, кроме ErrorResponse, которые рассматриваются как успешный ответ. Поэтому мы будем возвращать их, если и только если транзакция прошла успешно.

ParamList

ParamList — это перечисление, расположенное в пакете com.tranxactive.paymentprocessor.gateways.parameters, содержит список переменных, которые должны быть универсальными во всех транзакциях, например, если вы хотите назначить идентификатор транзакции для переменнойactionId, есть некоторые шансы на опечатку, но если вы будете использовать paramList enum, вы очень в безопасности.

Вот как вы можете использовать это при назначении транзакции в JSON.

1
2
JSONObject json = new JSONObject();
    Json.put(ParamList.TRANSACTION_ID.getName(), "1234567890");

пример

Теперь у вас есть все знания, необходимые для интеграции нового шлюза. В этом примере мы будем интегрировать шлюз NMI.

Работая над этим примером, мы предположили, что вы прочитали официальную документацию NMI.

Давайте код.

Для интеграции шлюза NMI мы создадим класс в пакете com.tranxactive.paymentprocessor.gateways с именем NMIGateway.

Далее мы расширим класс Gateway, который приведет нас к реализации всех методов, которые должны присутствовать в шлюзе.

Вот как будет выглядеть наш класс.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
public class NMIGateway  extends Gateway{
 
        @Override
        public HTTPResponse purchase(JSONObject apiParameters, Customer customer, CustomerCard customerCard, Currency currency, float amount) { }
 
        @Override
        public HTTPResponse refund(JSONObject apiParameters, JSONObject refundParameters, float amount) { }
 
        @Override
        public HTTPResponse rebill(JSONObject apiParameters, JSONObject rebillParameters, float amount) { }
 
        @Override
        public HTTPResponse voidTransaction(JSONObject apiParameters, JSONObject voidParameters) { }
 
        @Override
        public JSONObject getApiSampleParameters() { }
 
        @Override
        public JSONObject getRefundSampleParameters() { }
 
        @Override
        public JSONObject getRebillSampleParameters() { }
 
        @Override
        public JSONObject getVoidSampleParameters() { }
    }

Далее мы добавим четыре метода ниже в конце нашего класса. Это поможет нам создать окончательные параметры, которые необходимо разместить на шлюзе.

1
2
3
4
private JSONObject buildPurchaseParameters(JSONObject apiParameters, Customer customer, CustomerCard customerCard, Currency currency, float amount){}
    private JSONObject buildVoidParameters(JSONObject apiParameters, JSONObject voidParameters) {}
    private JSONObject buildRefundParameters(JSONObject apiParameters, JSONObject refundParameters, float amount){}
    private JSONObject buildRebillParameters(JSONObject apiParameters, JSONObject rebillParameters, float amount){}

Далее мы определим переменную apiURL глобально, где будет размещен весь запрос.

1

Далее мы будем работать над четырьмя методами SampleParameters.

Первым и самым важным является метод getApiSampleParameters, который требуется для выполнения всех транзакций.

Если вы прочитали документацию NMI, вы увидите, что параметры API — это имя пользователя и пароль.

Вот как будет выглядеть метод getApiSampleParameters.

1
2
3
4
5
6
@Override
    public JSONObject getApiSampleParameters() {
        return new JSONObject()
            .put("username", "the api user name use demo as the user name for testing")
            .put("password", "the api password use password  as the password for testing");
    }

Ниже приведены три оставшихся метода после обновления.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
@Override
    public JSONObject getRefundSampleParameters() {
        return new JSONObject()
                .put(ParamList.TRANSACTION_ID.getName(), "the transaction id which will be refunded");
    }
 
    @Override
    public JSONObject getRebillSampleParameters() {
        return new JSONObject()
                .put("customerVaultId", "the customer vault id");
    }
 
    @Override
    public JSONObject getVoidSampleParameters() {
        return new JSONObject()
                .put(ParamList.TRANSACTION_ID.getName(), "the transaction id which will be void");
    }

Далее мы будем работать над четырьмя методами buildparameters. Вот как они выглядят после вставки нашего кода.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
private JSONObject buildPurchaseParameters(JSONObject apiParameters, Customer customer, CustomerCard customerCard, Currency currency, float amount) {
 
        JSONObject object = new JSONObject();
        object
                .put("type", "sale")
                .put("username", apiParameters.getString("username"))
                .put("password", apiParameters.getString("password"))
                .put("ccnumber", customerCard.getNumber())
                .put("ccexp", customerCard.getExpiryMonth() + customerCard.getExpiryYear().substring(2))
                .put("cvv", customerCard.getCvv())
                .put("amount", amount)
                .put("currency", currency)
                .put("first_name", customer.getFirstName())
                .put("last_name", customer.getLastName())
                .put("address1", customer.getAddress())
                .put("city", customer.getCity())
                .put("state", customer.getState())
                .put("zip", customer.getZip())
                .put("country", customer.getCountry().getCodeISO2())
                .put("phone", customer.getPhoneNumber())
                .put("email", customer.getEmail())
                .put("ipaddress", customer.getIp())
                .put("customer_vault", "add_customer");
 
        return object;
 
    }
 
    private JSONObject buildVoidParameters(JSONObject apiParameters, JSONObject voidParameters) {
 
        JSONObject object = new JSONObject();
        object
                .put("type", "void")
                .put("username", apiParameters.getString("username"))
                .put("password", apiParameters.getString("password"))
                .put("transactionid", voidParameters.getString(ParamList.TRANSACTION_ID.getName()));
 
        return object;
    }
 
    private JSONObject buildRefundParameters(JSONObject apiParameters, JSONObject refundParameters, float amount) {
 
        JSONObject object = new JSONObject();
        object
                .put("type", "refund")
                .put("username", apiParameters.getString("username"))
                .put("password", apiParameters.getString("password"))
                .put("transactionid", refundParameters.getString(ParamList.TRANSACTION_ID.getName()))
                .put("amount", Float.toString(amount));
 
        return object;
    }
 
    private JSONObject buildRebillParameters(JSONObject apiParameters, JSONObject rebillParameters, float amount) {
 
        JSONObject object = new JSONObject();
        object
                .put("username", apiParameters.getString("username"))
                .put("password", apiParameters.getString("password"))
                .put("customer_vault_id", rebillParameters.getString("customerVaultId"))
                .put("amount", Float.toString(amount));
 
        return object;
    }

Далее мы будем работать над методом покупки.

Прежде всего, мы создадим наши окончательные параметры, которые необходимо опубликовать на шлюзе, с помощью метода buildPurchaseParameters.

1
JSONObject requestObject = this.buildPurchaseParameters(apiParameters, customer, customerCard, currency, amount);

Далее мы определим некоторые переменные для обработки запроса, не волнуйтесь, все зависит от того, как вы кодируете.

01
02
03
04
05
06
07
08
09
10
JSONObject responseObject;
    String requestString;
    String responseString;
    int responseCode;
    requestObject = JSONHelper.encode(requestObject);
    requestString = QueryStringHelper.toQueryString(requestObject);
    HTTPResponse httpResponse;
 
    PurchaseResponse successResponse = null;
    ErrorResponse errorResponse = new ErrorResponse();

Так как NMI требует публикации данных queryString, мы используем два вспомогательных класса.

JSONHelper и QueryStringHelper

Сначала мы будем кодировать json, возвращаемый buildPurchaseParameters с помощью этого кода.

1
requestObject = JSONHelper.encode(requestObject);

Затем мы преобразовали закодированный json в строку запроса с помощью этого кода.

1
requestString = QueryStringHelper.toQueryString(requestObject);

Вам должно быть интересно, почему мы инициализировали errorResponse, но установили successResponse как ноль Это все для некоторого программирования входа в систему для обработки запроса легко.

Далее мы будем публиковать данные в шлюз, вот как мы это сделаем.

1
httpResponse = HTTPClient.httpPost(this.apiURL, requestString, ContentType.APPLICATION_FORM_URLENCODED);

Вот два сценария, которые необходимо учитывать.

  1. Связь с серверами шлюзов прошла успешно.
  2. Возникла неполадка в сети или сервер шлюза временно недоступен.

Вот как вы справитесь со вторым сценарием.

1
2
3
if (httpResponse.getStatusCode() == -1) {
        return httpResponse;
    }

Если связь с сервером шлюза прошла успешно, наш код не вернется с этой точки и продолжит работу.

Затем мы получим ответ шлюза и проанализируем его в JSON, чтобы мы могли легко работать с ответом.

1
2
3
responseString = httpResponse.getContent();
    responseObject = JSONHelper.decode(QueryStringHelper.toJson(responseString));
    responseCode = responseObject.getInt("response_code");

Как видите, мы снова использовали QueryStringHelper и JSONHelper. Не было так просто с помощью вспомогательного класса.

Как мы знаем, если ответ шлюза был успешным, он должен вернуть код ответа 100. См. Код ниже.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
if (responseCode == 100) {
        httpResponse.setSuccessful(true);
        successResponse = new PurchaseResponse();
        successResponse.setMessage(responseObject.getString("responsetext"));
        successResponse.setTransactionId(responseObject.get("transactionid").toString());
        successResponse.setCardValuesFrom(customerCard);
        successResponse.setAmount(amount);
        successResponse.setCurrencyCode(currency);
 
        successResponse.setRebillParams(new JSONObject()
                .put("customerVaultId", responseObject.get("customer_vault_id").toString())
        );
 
        successResponse.setRefundParams(new JSONObject()
                .put(ParamList.TRANSACTION_ID.getName(), responseObject.get("transactionid").toString())
        );
 
        successResponse.setVoidParams(new JSONObject()
                .put(ParamList.TRANSACTION_ID.getName(), responseObject.get("transactionid").toString())
        );
 
    } else {
        errorResponse.setMessage(responseObject.getString("responsetext"));
    }

Давайте разберемся с приведенным выше кодом построчно.

1
httpResponse.setSuccessful(true);

По умолчанию httpResponse устанавливает для параметра false значение false, поэтому мы устанавливаем значение true только в случае успеха, как мы делали выше.

1
successResponse = new PurchaseResponse();

Мы инициализировали переменную successResponse, определенную в начале метода.

Когда вы посмотрите на код класса PurchaseResponse, вы увидите все параметры, которые должны быть установлены перед возвратом ответа.

1
2
//this sets the gateway success message.
    successResponse.setMessage(responseObject.getString("responsetext"));
1
2
//this sets the gateway returned transaction id.
    successResponse.setTransactionId(responseObject.get("transactionid").toString());
1
2
//this is our standard we provide some card detail in purchase response. You will see in final response.
    successResponse.setCardValuesFrom(customerCard);
1
2
successResponse.setAmount(amount);
    successResponse.setCurrencyCode(currency);

Затем мы устанавливаем сумму и валюту, которая была списана.

Поскольку мы несем ответственность за предоставление готовых к использованию параметров, необходимых для пополнения, возврата или аннулирования.

Вот как мы это сделали.

01
02
03
04
05
06
07
08
09
10
11
successResponse.setRebillParams(new JSONObject()
        .put("customerVaultId", responseObject.get("customer_vault_id").toString())
    );
 
    successResponse.setRefundParams(new JSONObject()
        .put(ParamList.TRANSACTION_ID.getName(), responseObject.get("transactionid").toString())
    );
 
    successResponse.setVoidParams(new JSONObject()
        .put(ParamList.TRANSACTION_ID.getName(), responseObject.get("transactionid").toString())
    );

Но что если ответ, а не успех, и мы получили какую-то ошибку, такую ​​как недостаточный фонд или ошибка AVS

Вот как мы это сделали в блоке else.

1
errorResponse.setMessage(responseObject.getString("responsetext"));

Далее мы вернем окончательный ответ, который будет HTTPResponse.

1
2
3
4
5
6
7
8
9
if (successResponse != null) {
        successResponse.setGatewayResponse(responseObject);
        httpResponse.setContent(successResponse.getResponse().toString());
    } else {
        errorResponse.setGatewayResponse(responseObject);
        httpResponse.setContent(errorResponse.getResponse().toString());
    }
 
    return httpResponse;

Это все, что мы успешно интегрировали метод покупки NMI, следующие три метода будут одинаковыми, за исключением того, что вы будете использовать разные классы Response для каждого из них, т.е. вы будете использовать

RebillResponse в методе ребилла.
RefundResponse в методе возврата.
VoidResponse в методе voidTransaction.
Вместо BuyResponse.

Настоятельно рекомендуется просмотреть источник всех этих классов ответов, а также примеры ответов (приведенных здесь).

Полный код шлюза NMI вы можете увидеть в нашем репозитории github .

Опубликовано на Java Code Geeks с разрешения Мухаммеда Ильяса, партнера нашей программы JCG . Смотрите оригинальную статью здесь: Реализация шлюза

Мнения, высказанные участниками Java Code Geeks, являются их собственными.