-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit 56c25c1
Showing
13 changed files
with
526 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
XSOLLA_PROJECT_ID="YOUR_DATA" | ||
|
||
# https://publisher.xsolla.com/<YOUR_MERCHANT>/projects/<YOUR_PROJECT>/edit/api_key | ||
XSOLLA_API_KEY="YOUR_DATA" | ||
|
||
# https://publisher.xsolla.com/<YOUR_MERCHANT>/projects/<YOUR_PROJECT>/edit/webhooks/ | ||
XSOLLA_WEBHOOK_SECRET_KEY="YOUR_DATA" | ||
|
||
BACKEND_PORT=8080 | ||
|
||
# https://ngrok.com/ - for expose your local app to the internet | ||
NGROK_AUTH_TOKEN="YOUR_DATA" | ||
# ngrok web interface port | ||
NGROK_PORT=4040 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
.idea/ | ||
target/ | ||
pom.xml.tag | ||
pom.xml.releaseBackup | ||
pom.xml.versionsBackup | ||
pom.xml.next | ||
release.properties | ||
dependency-reduced-pom.xml | ||
buildNumber.properties | ||
.mvn/timing.properties | ||
.env | ||
|
||
xsolla-example.war | ||
|
||
# Avoid ignoring Maven wrapper jar file (.jar files are usually ignored) | ||
!/.mvn/wrapper/maven-wrapper.jar |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
# Use Tomcat base image with Java 11 | ||
FROM tomcat:9.0-jdk11-openjdk-slim | ||
|
||
# Install curl, wget, and unzip | ||
RUN apt-get update && apt-get install -y curl wget unzip | ||
|
||
# Add ngrok repository and install ngrok | ||
RUN curl -s https://ngrok-agent.s3.amazonaws.com/ngrok.asc | tee /etc/apt/trusted.gpg.d/ngrok.asc >/dev/null \ | ||
&& echo "deb https://ngrok-agent.s3.amazonaws.com buster main" | tee /etc/apt/sources.list.d/ngrok.list \ | ||
&& apt-get update \ | ||
&& apt-get install -y ngrok |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,73 @@ | ||
# Xsolla Client-Side Integration Example | ||
|
||
This repository offers an example of integrating Xsolla PayStation for payment processing using Maven, Java, Servlets, | ||
Tomcat, and Ngrok. | ||
|
||
## Prerequisites | ||
|
||
Ensure the following tools are installed on your system before proceeding: | ||
|
||
- [Docker](https://docs.docker.com/get-docker/) | ||
- [Docker Compose](https://docs.docker.com/compose/install/) | ||
- [Ngrok](https://ngrok.com/) | ||
|
||
## Setup Instructions | ||
|
||
### 1. Create the .env file | ||
|
||
Copy the .env.example file and rename it to .env: | ||
|
||
```bash | ||
cp .env.example .env | ||
``` | ||
|
||
Update the .env file with the appropriate values. Your project ID is available in your Xsolla Publisher Account. | ||
|
||
 | ||
|
||
### 2. Build the project with Maven | ||
|
||
```markdown | ||
mvn clean install | ||
``` | ||
|
||
The output xsolla-example.war file will be in the target directory. | ||
|
||
**It's crucial to remember that your project needs to be rebuilt whenever changes are made to the codebase or .env variables.** | ||
|
||
### 3. Start Docker Containers | ||
|
||
Run the project using Docker Compose: | ||
|
||
```bash | ||
docker-compose up --build | ||
``` | ||
|
||
The application will be accessible at http://localhost:8080/xsolla-example/server-side. | ||
|
||
**It's crucial to remember that your Docker need to be rebuilt too after every project rebuilt.** | ||
|
||
### 4. Configure Ngrok | ||
|
||
 | ||
Ngrok provides a public URL for accessing your local server. You can open the Ngrok dashboard at http://localhost:4040. | ||
|
||
Copy the resulting URL and append /xsolla-example/webhook to it (for example, https://<random>.ngrok-free.app/xsolla-example/webhook) and add it to the webhook settings of your project at https://publisher.xsolla.com/<YOUR_MERCHANT>/projects/<YOUR_PROJECT>/edit/webhooks/. | ||
|
||
### 5. Add a product in Publisher Account | ||
|
||
Create a product in your Xsolla Publisher Account. Navigate to your project > store > virtual items > add item, or open | ||
the page directly at https://publisher.xsolla.com/<YOUR_MERCHANT>/projects/<YOUR_PROJECT>/storefront/virtual-items. | ||
|
||
### 6. Test the payment process | ||
|
||
Open the example UI at `http://localhost:8080/xsolla-example/server-side` and modify the JSON data to get a token (set | ||
the SKU of the project, user ID, etc.). | ||
|
||
Payment process: | ||
|
||
1. Server: Create a token using your JSON data. | ||
2. Client: Open the payment page with your token. | ||
3. Server: Receive a webhook to validate the user. | ||
4. Client: Complete the payment. | ||
5. Server: Receive a webhook with the payment result and deliver the product to the customer. |
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
version: '3' | ||
services: | ||
app: | ||
build: . | ||
container_name: xsolla-example-server-side | ||
ports: | ||
- "${BACKEND_PORT}:8080" | ||
volumes: | ||
- ./target/:/usr/local/tomcat/webapps/ | ||
command: [ "catalina.sh", "run" ] | ||
networks: | ||
- app-network | ||
|
||
ngrok: | ||
image: wernight/ngrok | ||
container_name: ngrok-xsolla-example-server-side | ||
environment: | ||
- NGROK_AUTHTOKEN=${NGROK_AUTH_TOKEN} | ||
- NGROK_PORT=app:8080 | ||
ports: | ||
- "${NGROK_PORT}:4040" | ||
networks: | ||
- app-network | ||
|
||
networks: | ||
app-network: | ||
driver: bridge |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
version: 2 | ||
web_addr: 0.0.0.0:4040 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,99 @@ | ||
<project xmlns="http://maven.apache.org/POM/4.0.0" | ||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | ||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> | ||
<modelVersion>4.0.0</modelVersion> | ||
<groupId>xsolla</groupId> | ||
<artifactId>xsolla-example</artifactId> | ||
<packaging>war</packaging> | ||
<version>1.0-SNAPSHOT</version> | ||
<name>Xsolla Example Java</name> | ||
<properties> | ||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> | ||
<java.version>1.8</java.version> | ||
<maven.compiler.source>1.8</maven.compiler.source> | ||
<maven.compiler.target>1.8</maven.compiler.target> | ||
</properties> | ||
<dependencies> | ||
<dependency> | ||
<groupId>junit</groupId> | ||
<artifactId>junit</artifactId> | ||
<version>4.13.2</version> | ||
<scope>test</scope> | ||
</dependency> | ||
|
||
<dependency> | ||
<groupId>javax.servlet</groupId> | ||
<artifactId>javax.servlet-api</artifactId> | ||
<version>4.0.1</version> | ||
<scope>provided</scope> | ||
</dependency> | ||
|
||
<!-- dotenv-java --> | ||
<dependency> | ||
<groupId>io.github.cdimascio</groupId> | ||
<artifactId>dotenv-java</artifactId> | ||
<version>3.0.0</version> | ||
</dependency> | ||
|
||
<!-- JSON processing --> | ||
<dependency> | ||
<groupId>org.json</groupId> | ||
<artifactId>json</artifactId> | ||
<version>20231013</version> | ||
</dependency> | ||
|
||
<!-- Apache Commons Codec for SHA-1 hashing --> | ||
<dependency> | ||
<groupId>commons-codec</groupId> | ||
<artifactId>commons-codec</artifactId> | ||
<version>1.15</version> | ||
</dependency> | ||
|
||
<!-- JSTL dependency --> | ||
<dependency> | ||
<groupId>javax.servlet</groupId> | ||
<artifactId>jstl</artifactId> | ||
<version>1.2</version> | ||
</dependency> | ||
|
||
<dependency> | ||
<groupId>com.google.code.gson</groupId> | ||
<artifactId>gson</artifactId> | ||
<version>2.8.9</version> | ||
</dependency> | ||
</dependencies> | ||
|
||
|
||
<build> | ||
<finalName>xsolla-example</finalName> | ||
<plugins> | ||
<plugin> | ||
<groupId>org.apache.maven.plugins</groupId> | ||
<artifactId>maven-compiler-plugin</artifactId> | ||
<version>3.8.1</version> | ||
</plugin> | ||
<plugin> | ||
<groupId>org.apache.tomcat.maven</groupId> | ||
<artifactId>tomcat7-maven-plugin</artifactId> | ||
<version>2.2</version> | ||
<configuration> | ||
<path>/</path> | ||
<port>8081</port> | ||
</configuration> | ||
</plugin> | ||
<plugin> | ||
<groupId>org.apache.maven.plugins</groupId> | ||
<artifactId>maven-war-plugin</artifactId> | ||
<version>3.3.1</version> | ||
</plugin> | ||
</plugins> | ||
<resources> | ||
<resource> | ||
<directory>${PWD}</directory> | ||
<includes> | ||
<include>.env</include> | ||
</includes> | ||
</resource> | ||
</resources> | ||
</build> | ||
</project> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,115 @@ | ||
package xsolla; | ||
|
||
import io.github.cdimascio.dotenv.Dotenv; | ||
|
||
import javax.servlet.ServletException; | ||
import javax.servlet.annotation.WebServlet; | ||
import javax.servlet.http.HttpServlet; | ||
import javax.servlet.http.HttpServletRequest; | ||
import javax.servlet.http.HttpServletResponse; | ||
import java.io.IOException; | ||
import java.io.OutputStream; | ||
import java.net.HttpURLConnection; | ||
import java.net.URL; | ||
import java.nio.charset.StandardCharsets; | ||
import java.util.Scanner; | ||
import java.util.Base64; | ||
|
||
@WebServlet("/server-side") | ||
public class ServerSide extends HttpServlet { | ||
private final String projectId; | ||
private final String apiKey; | ||
private final String backendPort; | ||
private final String webhookSecretKey; | ||
|
||
public ServerSide() { | ||
Dotenv dotenv = Dotenv.load(); | ||
this.projectId = dotenv.get("XSOLLA_PROJECT_ID"); | ||
this.apiKey = dotenv.get("XSOLLA_API_KEY"); | ||
this.backendPort = dotenv.get("BACKEND_PORT"); | ||
this.webhookSecretKey = dotenv.get("XSOLLA_WEBHOOK_SECRET_KEY"); | ||
} | ||
|
||
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { | ||
request.setAttribute("xsollaProjectId", this.projectId); | ||
request.setAttribute("xsollaApiKey", this.apiKey); | ||
request.setAttribute("backendPort", this.backendPort); | ||
request.setAttribute("xsollaWebhookSecretKey", this.webhookSecretKey); | ||
|
||
request.getRequestDispatcher("/server-side.jsp").forward(request, response); | ||
} | ||
|
||
@Override | ||
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { | ||
String projectId = request.getParameter("projectId"); | ||
String apiKey = request.getParameter("apiKey"); | ||
String body = request.getParameter("body"); | ||
|
||
try { | ||
new com.google.gson.JsonParser().parse(body); | ||
} catch (Exception e) { | ||
request.setAttribute("apiResponse", "Json in body is not valid"); | ||
request.getRequestDispatcher("/server-side.jsp").forward(request, response); | ||
return; | ||
} | ||
|
||
try { | ||
String urlString = "https://store.xsolla.com/api/v3/project/" + projectId + "/admin/payment/token"; | ||
URL url = new URL(urlString); | ||
HttpURLConnection conn = (HttpURLConnection) url.openConnection(); | ||
|
||
String auth = Base64.getEncoder().encodeToString((projectId + ":" + apiKey).getBytes()); | ||
conn.setRequestMethod("POST"); | ||
conn.setRequestProperty("Content-Type", "application/json"); | ||
conn.setRequestProperty("Authorization", "Basic " + auth); | ||
conn.setDoOutput(true); | ||
|
||
try (OutputStream os = conn.getOutputStream()) { | ||
byte[] input = body.getBytes(StandardCharsets.UTF_8); | ||
os.write(input, 0, input.length); | ||
} | ||
|
||
StringBuilder apiResponse = new StringBuilder(); | ||
try (Scanner scanner = new Scanner(conn.getInputStream(), StandardCharsets.UTF_8.name())) { | ||
while (scanner.hasNextLine()) { | ||
apiResponse.append(scanner.nextLine()); | ||
} | ||
} | ||
|
||
String responseBody = apiResponse.toString(); | ||
String token = extractToken(responseBody); | ||
|
||
boolean isSandbox = body.contains("\"sandbox\": true"); | ||
String baseUrl = isSandbox ? "https://sandbox-secure.xsolla.com/paystation4/?token=" : "https://secure.xsolla.com/paystation4/?token="; | ||
String fullUrl = baseUrl + token; | ||
|
||
String formattedLink = "<a href=\"" + fullUrl + "\" target=\"_blank\">" + fullUrl + "</a>"; | ||
String completeResponse = "<h3>API Response:</h3><pre>" + escapeHtml(responseBody) + "</pre>" + "<h3>Payment Link:</h3>" + formattedLink; | ||
|
||
request.setAttribute("apiResponse", completeResponse); | ||
request.setAttribute("body", body); | ||
request.setAttribute("xsollaProjectId", this.projectId); | ||
request.setAttribute("xsollaApiKey", this.apiKey); | ||
request.setAttribute("xsollaWebhookSecretKey", this.webhookSecretKey); | ||
|
||
} catch (Exception e) { | ||
request.setAttribute("apiResponse", "Error processing request: " + e.getMessage()); | ||
} | ||
|
||
request.getRequestDispatcher("/server-side.jsp").forward(request, response); | ||
} | ||
|
||
private String extractToken(String json) { | ||
int tokenStart = json.indexOf("\"token\":\"") + 9; | ||
int tokenEnd = json.indexOf("\"", tokenStart); | ||
return json.substring(tokenStart, tokenEnd); | ||
} | ||
|
||
private String escapeHtml(String input) { | ||
return input.replace("&", "&") | ||
.replace("<", "<") | ||
.replace(">", ">") | ||
.replace("\"", """) | ||
.replace("'", "'"); | ||
} | ||
} |
Oops, something went wrong.