源:https://blog.ximinghui.org/db407a4b/index.html

〇. 注册VISA开发者中心账号

如果已注册过,请跳过该步,否则参考 VISA信用卡的SDK示范(Hello World) 进行注册。

一. 创建一个项目

如果已创建过,请跳过该步,否则参考 VISA信用卡的SDK示范(Hello World) 进行创建。

二、准备jks文件

如果已经有了jks文件,请跳过该步,否则参考VISA信用卡的SDK示范(Hello World)文章中的 三、Two-Way/Mutual SSL认证方式 部分生成jks文件。

三、创建VISA证书信任库(Trust Store)

1. 从VISA开发者中心下载证书

进入VISA开发者中心页面左侧的“Credentials”界面,根据下面说明或点击 这里 参考图片中标出来的红、绿、蓝框。

点击 "Sandbox Root CA" 链接下载 根证书(Root Certificate) ,将会下载一个 SBX-2024-Prod-Root.pem 这样的文件;

点击 "Sandbox Issuing CA" 链接下载 中间证书(Intermediate Certificate) ,将会下载一个 SBX-2024-Prod-Inter.pem 这样的文件;

点击 "DigiCert Global Root CA certificate" 链接下载 DigiCert根证书 ,将会下载一个 DigiCertGlobalRootCA.crt 这样的文件。

2. 创建信任库

接下来使用上面下载的3个证书创建信任库。

说明:下面命令将信任库创建在 C:\Users\ximinghui\Downloads\ 目录,且3个证书都也都位于该目录,示例密码密码为 123456, 请根据实际情况调整路径和密码。

# 创建信任库
keytool -genkey -alias dummy -keyalg RSA -keystore "C:\Users\ximinghui\Downloads\visa_truststore.jks" -storepass 123456 -keypass 123456 -dname "CN=dummy"

# 删除临时条目
keytool -delete -alias dummy -keystore "C:\Users\ximinghui\Downloads\visa_truststore.jks" -storepass 123456

# 导入3个证书(DigiCert Root CA、Visa Root Certificate、Visa Intermediate Certificate)

keytool -import -trustcacerts -alias digicert-root -file "C:\Users\ximinghui\Downloads\DigiCertGlobalRootCA.crt" -keystore "C:\Users\ximinghui\Downloads\visa_truststore.jks" -storepass 123456

keytool -import -trustcacerts -alias visa-root -file "C:\Users\ximinghui\Downloads\SBX-2024-Prod-Root.pem" -keystore "C:\Users\ximinghui\Downloads\visa_truststore.jks" -storepass 123456

keytool -import -trustcacerts -alias visa-intermediate -file "C:\Users\ximinghui\Downloads\SBX-2024-Prod-Inter.pem" -keystore "C:\Users\ximinghui\Downloads\visa_truststore.jks" -storepass 123456

四、测试VISA的PullFunds API

VISA开发者中心项目详情页侧边栏进入Assert页面,可以找到一些示范代码(GitHub仓库中的代码位置为https://github.com/vandofb/visa-java-sample-code/tree/master/vdp-sample-java-funds-transfer)。以下贴出的是我参考vdp-sample-java-funds-transfer写的Demo。

import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManagerFactory;
import java.io.FileInputStream;
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.security.KeyStore;
import java.util.Base64;
import java.util.UUID;

public class Test {

    public static void main(String[] args) throws Exception {
        String username = "替换成你的username";
        String password = "替换成你的password";

        // 更新localTransactionDateTime时间为调用时的时间(注意时区)
        String requestBody = """
                {
                    "systemsTraceAuditNumber": "451001",
                    "surcharge": "11.99",
                    "senderPrimaryAccountNumber": "4895142232120006",
                    "senderCurrencyCode": "USD",
                    "senderCardExpiryDate": "2015-10",
                    "retrievalReferenceNumber": "330000550000",
                    "localTransactionDateTime": "2024-12-27T07:15:50",
                    "foreignExchangeFeeTransaction": "11.99",
                    "cavv": "0700100038238906000013405823891061668252",
                    "cardAcceptor": {
                        "terminalId": "ABCD1234",
                        "name": "Visa Inc. USA-Foster City",
                        "idCode": "ABCD1234ABCD123",
                        "address": {
                            "zipCode": "94404",
                            "state": "CA",
                            "county": "San Mateo",
                            "country": "USA"
                        }
                    },
                    "businessApplicationId": "AA",
                    "amount": "124.02",
                    "acquiringBin": "408999",
                    "acquirerCountryCode": "840"
                }
                """;

        // 构建 HttpClient
        HttpClient httpClient = HttpClient.newBuilder()
                .sslContext(createSSLContext())
                .version(HttpClient.Version.HTTP_2)
                .build();

        // 构建 HttpRequest
        HttpRequest request = HttpRequest.newBuilder()
                .uri(URI.create("https://sandbox.api.visa.com/visadirect/fundstransfer/v1/pullfundstransactions"))
                .header("Authorization", "Basic " + Base64.getEncoder().encodeToString((username + ":" + password).getBytes()))
                .header("ex-correlation-id", UUID.randomUUID().toString().replace("-", "").substring(0, 10) + "_SC")
                .header("Content-Type", "application/json")
                .header("Accept", "application/json")
                .POST(HttpRequest.BodyPublishers.ofString(requestBody))
                .build();

        // 发送请求并接收响应
        HttpResponse<String> response = httpClient.send(request, HttpResponse.BodyHandlers.ofString());

        // 输出响应信息
        System.out.println("Response Code: " + response.statusCode());
        System.out.println("Response Body: " + response.body());
    }

    private static SSLContext createSSLContext() throws Exception {
        String keystorePath = "替换成你的路径,我的是C:/Users/ximinghui/Downloads/key.jks";
        String trustStorePath = "替换成你的路径,我的是C:/Users/ximinghui/Downloads/visa_truststore.jks";
        String keystorePassword = "替换成你的keystorePassword,我的是C000000";
        String trustStorePassword = "替换成你的trustStorePassword,我的是123456";

        // 加载密钥库(客户端证书)
        KeyStore keyStore = KeyStore.getInstance("JKS");
        try (FileInputStream fis = new FileInputStream(keystorePath)) {
            keyStore.load(fis, keystorePassword.toCharArray());
        }

        // 加载信任库(Visa的证书)
        KeyStore trustStore = KeyStore.getInstance("JKS");
        try (FileInputStream fis = new FileInputStream(trustStorePath)) {
            trustStore.load(fis, trustStorePassword.toCharArray());
        }

        // 初始化 KeyManagerFactory
        KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
        keyManagerFactory.init(keyStore, keystorePassword.toCharArray());

        // 初始化 TrustManagerFactory
        TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
        trustManagerFactory.init(trustStore);

        // 配置 SSLContext
        SSLContext sslContext = SSLContext.getInstance("TLS");
        sslContext.init(keyManagerFactory.getKeyManagers(), trustManagerFactory.getTrustManagers(), null);

        return sslContext;
    }

}

运行代码,调用API成功响应的状态码是2xx,响应体如下:

{
    "transactionIdentifier": 429311337027961,
    "actionCode": "00",
    "approvalCode": "98765X",
    "responseCode": "5",
    "transmissionDateTime": "2024-12-27T09:39:48.000Z",
    "cavvResultCode": "8",
    "cpsAuthorizationCharacteristicsIndicator": "3333"
}

Xi_Minghui
1 声望0 粉丝

一枚普普通通的程序猿