Рубрики
Без рубрики

Использование Marqeta для создания платежного сервиса в Spring Boot

В течение последних двух лет я пользовался сервисом Uber во время поездки из аэропорта Лас-Вегаса… С тегами java, spring, marqeta, webdev.

В течение последних двух лет я пользовался услугой Uber во время поездки из аэропорта Лас-Вегаса в прекрасное поместье моей невестки в отдаленных пригородах. В каждом случае поездки на Uber были куплены для меня — приятный жест со стороны моего шурина. В результате я смог сосредоточиться на возможности познакомиться с кем-то новым, пока мы пересекали скалистую и засушливую пустынную растительность Невады, содержащую более чем изрядную долю модных отелей и казино.

В июле мой обратный рейс на средний запад был встречен с несколькими задержками. Вместо того чтобы прибыть домой вскоре после полуночи, самолет Southwest приземлился в 4 часа утра по местному времени. Я не собирался просить свою жену (и маленького сына) совершить 30-минутную поездку (в одну сторону), чтобы забрать меня. Вместо этого я решил впервые воспользоваться Uber, запланировав свою собственную поездку.

Я был впечатлен. Я не только познакомился с другой замечательной душой, но и испытал удивительный опыт оплаты проезда с помощью только своего мобильного телефона. На самом деле я создал свою учетную запись перед отъездом, как только понял, что мне понадобится транспорт, когда большая часть города крепко спала.

Отдохнув несколько часов и вернувшись в свой домашний офис, я решил узнать больше о сервисе обработки платежей, стоящем за Uber. Это привело меня к Marqeta , компания, о которой я никогда раньше не слышал. Просматривая их платежную платформу и API, я хотел посмотреть, насколько легко я мог бы создать платежный сервис в Spring Boot, используя платформу Marqeta.

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

О Маркете

Генеральный директор Джейсон Гарднер основал Marqeta “для демократизации инноваций, позволяя любой компании — совершенно новому стартапу или самому известному предприятию — использовать нашу современную платформу для выпуска карт, не беспокоясь о сложности платежной инфраструктуры”.

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

Успех Marqeta можно легко измерить по списку “кто есть кто” клиентов, ориентированных на технологии, которые полагаются на Marqeta в режиме 24x7x365. Как отмечалось ранее, бренд Uber использует Marqeta. Дополнительные клиенты включают DoorDash , Площадь , Инстакарт , Подтверждаю , и Брексит (который поддерживает Airbnb, Classpass и Flexport), все из которых стали именами нарицательными за последние пять лет.

По состоянию на 31 марта 2021 года Marqeta обработала более 320 миллионов карт (платежных источников) и 1,6 миллиарда транзакций. Успех Marqeta был признан Forbes (премия Fintech 50 award), Fast Company (премия 50 самых инновационных компаний) и CNBC (премия Disruptor Top 50 award).

Маркета кажется мне “настоящей сделкой”.

Нет Java SDK, Нет проблем

Marqeta предлагает очень впечатляющий Core API Explorer , который позволяет разработчикам получить представление о платежной платформе. Фактически, мой предыдущий опыт научил меня тому, что когда я начинаю видеть возможности и получаю удовольствие от простого просмотра API, тогда я получаю качественный продукт.

В то время как наборы для разработки программного обеспечения (SDK) в настоящее время существуют для Python и Ruby, для Java их не существует. Однако, ознакомившись с основным API, я почувствовал, что создание платежного сервиса в Spring Boot, который действует как продукт промежуточного программного обеспечения и выполняет вызовы RESTful на платформу Marqeta, было бы интересным заданием.

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

Прежде чем идти по этому пути, возможно, мне следует предоставить некоторые подробные сведения о платформе Marqeta на высоком уровне.

Начало работы с Marqeta

Чтобы все было проще, в основе дизайна рынка лежат четыре основные концепции:

  • Пользователь – клиент, который планирует совершать транзакции (вы)
  • Источник финансирования – финансовое учреждение, в котором находятся ваши средства (ваш банк)
  • Карточный продукт – карточные услуги, предлагаемые вашим источником финансирования (например, Visa, Mastercard, Discover и т. Д.)
  • Карта – экземпляр карточного продукта, привязанный к вашему источнику финансирования (вашей кредитной карте).

Я создал следующую иллюстрацию, чтобы продемонстрировать эти взаимосвязи:

Для целей этой статьи я решил настроить пользователя, источник финансирования, карточный продукт и карту, используя прямые вызовы API ядра Marqeta с помощью базовых команд CURL.

Однако, прежде чем я смог начать, мне нужно было создать новую учетную запись в Marqeta, которая предоставила бы доступ к песочнице Marqeta.

Установление доступа к песочнице Marqeta

Начать работу с Marqeta с нулевыми затратами так же просто, как создать учетную запись по ссылке ниже:

Начать работу с Marqeta с нулевыми затратами так же просто, как создать учетную запись по ссылке ниже:

Как только ваша учетная запись будет создана, при переходе на панель управления разработкой будут предоставлены сведения, аналогичные тем, что отображаются ниже:

В оставшейся части этой статьи будут даны ссылки на следующие элементы на изображении выше.:

  • Токен приложения = ${APPLICATION_TOKEN} и APPLICATION_TOKEN_GOES_HERE
  • Токен доступа администратора = ${ADMIN_ACCESS_TOKEN} и ADMIN_ACCESS_TOKEN_GOES_HERE

Создание нового пользователя

Следующая команда cURL может быть использована для создания нового пользователя по имени Рэнди Керн :

curl -i \
  -X POST \
  -H 'Content-Type: application/json' \
  --user APPLICATION_TOKEN_GOES_HERE:ADMIN_ACCESS_TOKEN_GOES_HERE \
  -d '{
    "first_name": "Randy",
    "last_name": "Kern",
    "active": true
  }' \
  https://sandbox-api.marqeta.com/v3/users

Успешное СООБЩЕНИЕ дает 2xx HTTP-ответ и уникальный токен для пользователя Randy Kern:

{
"token" : "1017b62c-6b61-4fcd-b663-5c81feab6524",
"active" : true,
"first_name" : "Randy",
"last_name" : "Kern",
"uses_parent_account" : false,
"corporate_card_holder" : false,
"created_time" : "2021-08-14T13:01:13Z",
"last_modified_time" : "2021-08-14T13:01:14Z",
"metadata" : { },
"account_holder_group_token" : "DEFAULT_AHG",
"status" : "ACTIVE",
"deposit_account" : {
  "token" : "6716c09f-c0dd-430f-ada5-d39f6c5059bb",
  "account_number" : "40018215000000810",
  "routing_number" : "293748000",
  "allow_immediate_credit" : false
  }
}

Обратите внимание на значение токена, поскольку оно потребуется для последующего использования.

Создание своевременного источника финансирования

Далее требуется источник финансирования. В этом примере мы будем использовать источник финансирования “точно в срок” (JIT). Подумайте о модели JIT, как о том, что происходит, когда вы используете дебетовую карту, а не подарочную карту, на которую предварительно загружена определенная сумма.

Следующая команда CURL устанавливает источник финансирования JIT под названием “funding_source_bank” в моей песочнице Marqeta:

curl -X POST "https://sandbox-api.marqeta.com/v3/fundingsources/program" \
  --user APPLICATION_TOKEN_GOES_HERE:ADMIN_ACCESS_TOKEN_GOES_HERE \
  -H "accept: application/json"  \
  -H "Content-Type: application/json"  \

  -d '{"name":"funding_source_bank","active":true}'

Результирующая полезная нагрузка должна быть аналогична тому, что указано ниже:

{
  "name": "funding_source_bank",
  "active": true,
  "token": "069e4f6c-a731-48e2-82b7-0df9f44dea62",
  "created_time": "2021-08-15T02:42:06Z",
  "last_modified_time": "2021-08-15T02:42:06Z",
  "account": "12.003.001.000000"
}

Обратите внимание на значение токена из этого недавно созданного источника финансирования, так как это будет наш funding_source_token в следующей команде CURL.

Создание карточного продукта

Карточный продукт ссылается на источник финансирования JIT и карту, принадлежащую данному пользователю. Следующая команда CURL создает новый карточный продукт, который использует созданный выше “funding_source_bank”.:

curl -X POST "https://sandbox-api.marqeta.com/v3/cardproducts"  \
  --user APPLICATION_TOKEN_GOES_HERE:ADMIN_ACCESS_TOKEN_GOES_HERE \
  -H "accept: application/json"  \
  -H "Content-Type: application/json"  \
  -d '{
       "start_date":"2020-05-01",
       "name":"Funding Source Bank Card",
       "config":{
          "fulfillment":{
             "payment_instrument":"VIRTUAL_PAN"
          },
          "poi":{
             "ecommerce":true,
             "atm":true
          },
          "card_life_cycle":{
             "activate_upon_issue":true
          },
          "jit_funding":{
             "program_funding_source":{
                "funding_source_token":"JIT_TOKEN_GOES_HERE",
                "refunds_destination":"PROGRAM_FUNDING_SOURCE",
                "enabled":true
             }
          }
       }
    }'

Этот запрос выдает токен продукта card, который будет использоваться при создании карты для Рэнди Керна. Часть результирующей полезной нагрузки отображается ниже:

{
  "token": "99db1d05-9199-446c-9ff1-047df5ccf154",
  "name": "Funding Source Bank Card",
  "active": true,
  ...

Создание новой карты

Карта в Marqeta – это платежное устройство, которое позволяет пользователю совершать транзакции в торговых точках. Чтобы все было проще, просто думайте о карте как о дебетовой или кредитной карте. Для нашего примера мы создадим карту из карточного продукта “Банковская карта источника финансирования”, установленного выше.

Чтобы создать карточку для Рэнди Керна, выполните следующую команду cURL:

curl -X POST "https://sandbox-api.marqeta.com/v3/cards"  \
  --user APPLICATION_TOKEN_GOES_HERE:ADMIN_ACCESS_TOKEN_GOES_HERE \
  -H "accept: application/json"  \
  -H "Content-Type: application/json"  \
  -d '{
       "user_token":"RANDY_KERN_USER_TOKEN_GOES_HERE",
       "card_product_token":"FUNDING_SOURCE_BANK_CARD_PRODUCT_TOKEN_GOES_HERE
   }'

Должна появиться полезная нагрузка, подобная той, что показана ниже:

{
  "created_time": "2021-08-15T02:47:52Z",
  "last_modified_time": "2021-08-15T02:47:52Z",
  "token": "9d32f3b7-2fb6-43ec-b4a8-99fc81312301",
  "user_token": "1017b62c-6b61-4fcd-b663-5c81feab6524",
  "card_product_token": "99db1d05-9199-446c-9ff1-047df5ccf154",
  "last_four": "4445",
  "pan": "111111______4445",
  "expiration": "0825",
  "expiration_time": "2025-08-31T23:59:59Z",
  "barcode": "11195778081390829687",
  "pin_is_set": false,
  "state": "ACTIVE",
  "state_reason": "New card activated",
  "fulfillment_status": "ISSUED",
  "instrument_type": "VIRTUAL_PAN",
  "expedite": false,
  "metadata": {}
}

На этом этапе мы готовы настроить службу Spring Boot.

Начало работы с Spring Boot

С базовым набором данных, созданным в моей песочнице Marqeta, следующим шагом будет создание простого платежного сервиса с использованием Spring Boot. Служба Spring Boot использует следующие URI:

  • НАСТРОЙТЕ пользователей на платформе Marqeta
  • ПОЛУЧАТЬ карты, связанные с данным пользовательским токеном
  • ПОЛУЧАТЬ транзакции, связанные с данным пользовательским токеном
  • ОПУБЛИКОВАТЬ новую транзакцию для карты, связанной с пользователем, использующим источник финансирования

Чтобы начать, я добавил следующие зависимости в проект Spring Boot, который я создал в своей среде разработки IntelliJ IDEA:


    
        org.springframework.boot
        spring-boot-starter-jersey
    
    
        org.springframework.boot
        spring-boot-starter-web
    
    
        org.apache.commons
        commons-collections4
        4.1
    
    
        org.apache.httpcomponents
        httpclient
        4.5.13
    
    
        org.springframework.boot
        spring-boot-configuration-processor
        true
    
    
        org.projectlombok
        lombok
        true
    

Затем я создал серию объектов преобразования данных (DTO), чтобы соответствовать контракту на передачу данных, используемому и ожидаемому платформой Marqeta. Ниже приведен скриншот классов DTO, которые я представил:

Вместо того, чтобы описывать все эти пункты здесь, вы всегда можете более подробно ознакомиться с результирующим исходным кодом для проекта Spring Boot здесь:

Вместо того, чтобы описывать все эти пункты здесь, вы всегда можете более подробно ознакомиться с результирующим исходным кодом для проекта Spring Boot здесь:

Конфигурация Marqeta

Следующие свойства выводятся наружу в конфигурационный файл application.yml при загрузке Spring:

marqeta:
  application-token: ${APPLICATION_TOKEN}
  admin-access-token: ${ADMIN_ACCESS_TOKEN}
  hostname: sandbox-api.marqeta.com
  secure: true
  base-uri: /v3

Значения application-token и admin-access-token будут установлены вне программы (например, в качестве переменной среды), чтобы избежать проверки секретной информации в хранилище.

В реалистичном примере свойство hostname также было бы внешним, но я решил сделать этот пример как можно более простым.

Свойства конфигурации Marqeta доступны в Spring Boot в результате использования класса MarqetaConfigurationProperties :

@Data
@Configuration("marqetaConfigurationProperties")
@ConfigurationProperties("marqeta")
public class MarqetaConfigurationProperties {
    private String applicationToken;
    private String adminAccessToken;
    private String hostname;
    private boolean secure;
    private String baseUri;
}

В результате этого изменения значения конфигурации становятся доступными для любого компонента или службы посредством внедрения зависимостей. Ниже приведен пример из пользовательского сервиса:

@RequiredArgsConstructor
@Service
public class UserService {
    private final MarqetaConfigurationProperties marqetaConfigurationProperties;
    ...
}

Связь с основным API Marqeta

Чтобы все оставалось “сухим” (не повторяйтесь), я создал служебный класс MarqetaUtils для размещения вспомогательных методов для обмена данными GET и POST с API ядра Marqeta. Для простоты я перечисляю метод marquette() ниже:

public final class MarqetaUtils {
    private MarqetaUtils() { }

    public static CloseableHttpResponse marqetaGet(MarqetaConfigurationProperties marqetaConfigurationProperties, String contextUrl, List nameValuePairs) throws Exception {
        CloseableHttpClient closeableHttpClient = getCloseableHttpClient(marqetaConfigurationProperties);
        URIBuilder uriBuilder = createUriBuilder(marqetaConfigurationProperties, contextUrl, nameValuePairs);

        HttpGet httpGet = new HttpGet(uriBuilder.build());
        httpGet.setHeader(HttpHeaders.ACCEPT, MediaType.APPLICATION_JSON_VALUE);
        httpGet.setHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE);

        CloseableHttpResponse closeableHttpResponse = closeableHttpClient.execute(httpGet);
        HttpUtils.checkResponse(closeableHttpResponse);
        return closeableHttpResponse;
    }

    ...
}

В результате пользовательский API в Spring Boot просто должен предоставить следующую информацию, чтобы выполнить запрос GET к API ядра Marqeta:

CloseableHttpResponse closeableHttpResponse = MarqetaUtils.marqetaGet(marqetaConfigurationProperties, "/users", null)

Создание GET URI в Spring Boot

Как отмечалось выше, URI на основе GET будут существовать для пользователей, карт и транзакций. Ниже приведена иллюстрация, на которой показан процесс использования пользовательского API:

Чтобы получить список пользователей из службы Spring Boot, мы бы использовали следующий cURL:

curl --location -X GET 'localhost:9999/users'

Этот запрос приводит к вызову метода getUsers() в классе UserController :

@RequiredArgsConstructor
@Slf4j
@CrossOrigin
@RequestMapping(produces = MediaType.APPLICATION_JSON_VALUE)
@RestController
public class UserController {
    private final UserService userService;

    @GetMapping(value = "/users")
    public ResponseEntity> getUsers() {
        try {
            return new ResponseEntity<>(userService.getAllUsers(), HttpStatus.OK);
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            return new ResponseEntity<>(HttpStatus.BAD_REQUEST);
        }
    }
}

Метод UserService.getAllUsers() взаимодействует с классом UserService для возврата списка объектов User :

public List getAllUsers() throws Exception {
    try (CloseableHttpResponse closeableHttpResponse = MarqetaUtils.marqetaGet(marqetaConfigurationProperties, "/users", null)) {
        HttpEntity httpEntity = closeableHttpResponse.getEntity();

        if (httpEntity != null) {
            MarqetaUserResponse marqetaUserResponse = objectMapper.readValue(EntityUtils.toString(httpEntity), MarqetaUserResponse.class);

            if (marqetaUserResponse != null) {
                return marqetaUserResponse.getUsers();
            }
        }

        return new ArrayList<>();
    }
}

Метод || UserService.getAllUsers() || взаимодействует с классом || UserService || для возврата списка объектов || User ||:

[
    {
        "token": string,
        "createdTime": number,
        "lastModifiedTime": number,
        "metadata": {},
        "active": boolean,
        "firstName": string,
        "lastName": string,
        "usersParentAccount": boolean,
        "corporateCardHolder": boolean,
        "accountHolderGroupToken": string,
        "status": string
    }
]

Метод || UserService.getAllUsers() || взаимодействует с классом || UserService || для возврата списка объектов || User ||: Каждый запрос к API ядра Marqeta использует статический класс MarqetaUtils, чтобы уменьшить количество повторяющегося кода в службе Spring Boot.

Чтобы просмотреть все сервисы, созданные для этой статьи, просто откройте следующий URL-адрес:

Чтобы просмотреть все сервисы, созданные для этой статьи, просто откройте следующий URL-адрес:

Собирая Все это Воедино

Создав песочницу Marqeta и подготовив службу загрузки Spring к использованию, я запустил службу загрузки Spring:

Чтобы проверить правильность настроек конфигурации, я также создал URI/ping в Spring Boot для взаимодействия с API ядра Marqeta без запроса каких-либо данных. Я выполнил следующий cURL для службы Spring Boot:

curl --location -X GET 'localhost:9999/ping'

URI/ping ответил следующей полезной нагрузкой и HTTP-ответом 200:

{
    "success": true,
    "version": "rel-21.7.1",
    "revision": "7b6bf2842d024b0d26f5e29f5cc50617b0d49872",
    "timestamp": "Fri Jul 16 22:37:50 UTC 2021",
    "env": "sandbox",
    "id": "i-0e0a4a9bc40f8d05d:us-east-1a:10.128.19.176"
}

HTTP-ответ 200 и значение true для свойства “success” указывают на то, что запрос прошел успешно.

Получение списка пользователей в Marqeta

Как отмечалось ранее, следующая команда cURL вернет список пользователей:

curl --location -X GET 'localhost:9999/users'

Я получил следующую полезную нагрузку ответа от службы Spring Boot:

[
    {
        "token": "1017b62c-6b61-4fcd-b663-5c81feab6524",
        "createdTime": 1628946073000,
        "lastModifiedTime": 1628946074000,
        "metadata": {},
        "active": true,
        "firstName": "Randy",
        "lastName": "Kern",
        "usersParentAccount": false,
        "corporateCardHolder": false,
        "accountHolderGroupToken": "DEFAULT_AHG",
        "status": "ACTIVE"
    }
]

Получение списка карточек для данного пользователя в Marqeta

Следующая команда cURL предоставит список карточек, связанных с пользовательским токеном Рэнди Керна:

curl --location --request GET 'localhost:9999/cards/user/1017b62c-6b61-4fcd-b663-5c81feab6524'

Полезная нагрузка ответа содержит сводку карточек для пользователя Randy Kern:

[
    {
        "token": "9d32f3b7-2fb6-43ec-b4a8-99fc81312301",
        "createdTime": 1628995672000,
        "lastModifiedTime": 1628995672000,
        "metadata": {},
        "userToken": "1017b62c-6b61-4fcd-b663-5c81feab6524",
        "cardProductToken": "99db1d05-9199-446c-9ff1-047df5ccf154",
        "lastFour": "4445",
        "pan": "111111______4445",
        "expiration": "0825",
        "expirationTime": 1756684799000,
        "barcode": "11195778081390829687",
        "pinSet": false,
        "state": "ACTIVE",
        "stateReason": "New card activated",
        "fulfillmentStatus": "ISSUED",
        "instrumentType": "VIRTUAL_PAN",
        "expedite": false
    }
]

Размещение транзакции на рынке

Служба Spring Boot принимает простой POST-запрос для создания новой транзакции на платформе Marqeta, используя полезную нагрузку MarqetaTransactionRequest body.

Приведенный ниже пример представляет собой Запрос транзакции Marqeta полезную нагрузку для транзакции в размере 7,50 доллара США в Дружественную таверну:

{
    "amount": "7.50",
    "mid": "11111",
    "card_token": "9d32f3b7-2fb6-43ec-b4a8-99fc81312301",
    "card_acceptor": {
        "name": "The Friendly Tavern",
        "address": "290 S. Main St",
        "city": "Zionsville",
        "state": "IN",
        "zip": "46077",
        "country": "USA"
    },
    "webhook": {
        "endpoint": "https://mywebook.url.goes.here.com",
        "username": "some_username",
        "password": "some_password"
    }
}

Приведенная выше полезная нагрузка может быть включена в следующий оператор cURL для использования API авторизации в службе Spring Boot:

curl --location --request POST 'localhost:9999/authorization' \
  --user APPLICATION_TOKEN_GOES_HERE:ADMIN_ACCESS_TOKEN_GOES_HERE \
  --H 'accept: application/json' \
  --H 'Content-Type: application/json' \
  --d '{
        "amount": "7.50",
        "mid": "11111",
        "card_token": "CARD_TOKEN_GOES_HERE",
        "card_acceptor": {
            "name": "The Friendly Tavern",
            "address": "290 S. Main St",
            "city": "Zionsville",
            "state": "IN",
            "zip": "46077",
            "country": "USA"
        },
        "webhook": {
            "endpoint": "SOME_WEBHOOK_URL_GOES_HERE",
            "username": "USERNAME_GOES_HERE",
            "password": "PASSWORD_GOES_HERE"
        }
    }'

После успешной отправки СООБЩЕНИЯ отображается полная информация об этой транзакции. Кроме того, объект webhook предоставляет возможность выполнить вызов указанной конечной точки после обработки запроса. Более подробную информацию об использовании веб-крючков Marqeta можно найти здесь .

Получение списка сделок на рынках

Создав единственную транзакцию, совершенную пользователем Randy Kern, мы можем получить доступ к URI “транзакции пользователя” с помощью следующей команды cURL:

curl --location --request GET 'localhost:9999/transactions/user/1017b62c-6b61-4fcd-b663-5c81feab6524'

Результатом являются следующие данные для одной транзакции:

[
    {
        "token": "ca66618d-43c7-4c74-aa30-5b2fedfc676f",
        "createdTime": 1629083511000,
        "type": "authorization",
        "state": "PENDING",
        "identifier": "19",
        "userToken": "1017b62c-6b61-4fcd-b663-5c81feab6524",
        "actingUserToken": "1017b62c-6b61-4fcd-b663-5c81feab6524",
        "cardToken": "9d32f3b7-2fb6-43ec-b4a8-99fc81312301",
        "gpa": {
            "ledgerBalance": 7.50,
            "availableBalance": 0.00,
            "creditBalance": 0.00,
            "pendingCredits": 0.00,
            "impactedAmount": -7.50,
            "currencyCode": "USD",
            "balances": {
                "USD": {
                    "ledgerBalance": 7.50,
                    "availableBalance": 0.00,
                    "creditBalance": 0.00,
                    "pendingCredits": 0.00,
                    "impactedAmount": -7.50,
                    "currencyCode": "USD"
                }
            }
        },
        "gpaOrder": {
            "token": "be3dc1b6-fa22-4ef9-8157-8fc10c86d632",
            "createdTime": 1629083511000,
            "lastModifiedTime": 1629083511000,
            "amount": 7.50,
            "transactionToken": "23976c31-efc2-4a44-8834-b5390ab131ab",
            "state": "PENDING",
            "response": {
                "code": "0000",
                "memo": "Approved or completed successfully"
            },
            "funding": {
                "amount": 7.50,
                "source": {
                    "token": "**********ea62",
                    "createdTime": 1628995326000,
                    "lastModifiedTime": 1628995326000,
                    "type": "program",
                    "active": true,
                    "name": "funding_source_bank",
                    "defaultAccount": false
                }
            },
            "fundingSourceToken": "**********ea62",
            "userToken": "1017b62c-6b61-4fcd-b663-5c81feab6524",
            "currencyCode": "USD"
        },
        "duration": 127,
        "userTransactionTime": 1629083511000,
        "settlementDate": 1629072000000,
        "requestAmount": 5.00,
        "amount": 5.00,
        "issuerReceivedTime": 1629083511084,
        "issuerPaymentNode": "00b8d031e0a4759766b5b5266f5229d8",
        "networkReferenceId": "765766405219",
        "currencyCode": "USD",
        "approvalCode": "223355",
        "response": {
            "code": "0000",
            "memo": "Approved or completed successfully"
        },
        "network": "DISCOVER",
        "acquirer": {
            "systemTraceAuditNumber": "940779"
        },
        "acquirerFeeAmount": 0,
        "user": {
            "metadata": {}
        },
        "card": {
            "lastFour": "4445",
            "metadata": {}
        },
        "cardAcceptor": {
            "mid": "11111",
            "mcc": "6411",
            "name": "The Friendly Tavern",
            "streetAddress": "290 S. Main St",
            "city": "Zionsville",
            "state": "IN",
            "zip": "46077",
            "countryCode": "USA"
        },
        "pos": {
            "pinPresent": false,
            "partialApprovalCapable": true,
            "purchaseAmountOnly": false,
            "recurring": false,
            "installment": false
        }
    }
]

В то время как результирующая полезная нагрузка, безусловно, не является скудной, это финансовая транзакция — с ожидаемой надежной защитой и системой сдержек и противовесов.

Вывод

Начиная с 2021 года, я пытаюсь следовать следующей миссии, которая, как я чувствую, может быть применима к любому ИТ-специалисту:

“Сосредоточьте свое время на предоставлении функций/функциональности, которые повышают ценность вашей интеллектуальной собственности. Используйте фреймворки, продукты и услуги для всего остального”.

  • J. Ваш

Marqeta, безусловно, вписывается в мою миссию, устраняя путаницу и проблемы, связанные с внедрением платежной платформы с использованием Java и Spring Boot.

В 2020 году DZone попросил меня написать рефкарту, ориентированную на обработку платежей с использованием Java. Я отклонил это предложение, потому что мне показалось, что было бы намного проще воспользоваться услугой обработки платежей. Если бы я знал о Маркете в то время, я бы, конечно, сделал ссылку на Маркету в своем ответе.

Если цели вашего проекта могут быть достигнуты благодаря полнофункциональной платформе обработки платежей, которой доверяют Uber, DoorDash, Square, Instacart, Affirm и Brex, я бы настоятельно рекомендовал добавить Marqeta в ваш короткий список поставщиков для оценки.

Я надеюсь глубже погрузиться в другие аспекты того, что может предложить Marqeta, продолжая развивать сервис Spring Boot, который я уже создал. Моя цель будет состоять в том, чтобы публиковать будущие статьи на этом пути.

Если вас интересует полный исходный код, используемый в этой статье, просто откройте следующий репозиторий на GitLab:

Если вас интересует полный исходный код, используемый в этой статье, просто откройте следующий репозиторий на GitLab:

Хорошего вам дня!

Оригинал: “https://dev.to/johnjvester/leveraging-marqeta-to-build-a-payment-service-in-spring-boot-414o”