Can AI Build a Secure Payment Form? Using GPT-4 and Rapyd to Create a Payment Workflow

By: Artem Oppermann

Advancements in AI (Artificial Intelligence) continue to revolutionize different industry sectors, and the field of fintech is no exception. Machine learning, a subset of AI, has long been used to detect trends or for verification services. One of the most remarkable innovations in this domain is GPT-4, or Generative Pre-trained Transformer 4. GPT-4 was developed by OpenAI and is an advanced language model that can generate text closely resembling human communication based on the input it receives. The utility of such AI models extends from natural language processing to more complex problem-solving applications like code generation. This signifies a paradigm shift in how software can be developed and interacted with.

In parallel, the omnipresence of e-commerce and online services has required seamless and secure integration of payment gateways into modern web applications. Payment gateways act as intermediaries that facilitate the transaction process by transmitting information between websites or mobile applications and payment processors. Any online platform must ensure a smooth, secure, and user-friendly payment experience. Therefore, it has become an important skill for developers to understand how to effectively integrate payment gateways.

With AI like GPT-4, there is potential to simplify or even automate some aspects of this complex integration process, which can make it easier for a business to adapt and thrive in the digital economy. Remember, even when using AI, you still need to consider important regulations like PCI Compliance and how to handle personal information for credit cards. However, for this tutorial, you’ll work in a sandbox environment using fake information.

In this article, you will learn how to create a secure payment form using GPT-4 and Rapyd’s API. You’ll also gain insights into some of the best practices for using AI assistance during programming.

Using GPT-4 and Rapyd’s API to Create a Payment Workflow

The following sections demonstrate how to use GPT-4 as AI support to help implement a payment workflow using the Rapyd API. Specifically, you’ll create an input form in the browser on the frontend page for a credit card payment. On the backend side, the data entered into the form is recorded and the payment is processed via Rapyd’s API.

Note: The examples and responses provided in this guide are based on a specific set of interactions with GPT-4. Your experience may vary as the model can generate different responses based on the input it receives.

The entire source code can be found in the GitHub repository of the project.

Prerequisites

Before diving into creating a secure payment form and workflow using Rapyd’s API, you’ll need the following to complete the tutorial:

  1. Python installed: Ensure that you have a working Python environment on your machine. You can download the latest Python version from Python’s official website.

  2. Flask Python library: Install Flask to create your web server. You can install it via pip using the following command in the command prompt:

pip install Flask
  1. Requests Python library: This library is essential for making HTTP calls to the Rapyd API. Install it using pip with the following command:
pip install requests
  1. Rapyd API credentials: You’ll need an API access key and secret key to make authenticated calls to the Rapyd API. First, sign up for a free account on Rapyd’s platform. After that, go to the Developers section on the left side of the screen to get these credentials.

  1. Basic understanding of Flask and REST APIs: It’s important to have a basic understanding of Flask for the server-side logic and REST APIs to understand how to interact with the Rapyd API.

  2. A ChatGPT Plus Account: You can sign up here to get a ChatGPT account. Please note that GPT Plus is a paid service that costs approximately $20 per month depending on the geographical location of the user.

Initial Prompt for ChatGPT

Before starting, make sure you are using the GPT-4 model when interacting with ChatGPT. For this, simply select the GPT-4 model in the middle of the screen, as depicted in the picture below:

Let’s start by creating a payment workflow using the Rapyd API. For this purpose, you’ll instruct ChatGPT to create it using the following prompt:

Hello ChatGPT. I want to create a secure payment form and workflow using Rapyd's API. Specifically, I want: 
- To use Python 
- To use a Flask Server 
- Create a form where I can create payment requests for a credit card 
- The form should be nice looking and incorporate some .css 
- To get the code step-by-step + explanations

As an answer, ChatGPT immediately generates the entire code base. While doing so, the AI breaks down the code into several parts. Let’s discuss each part in detail.

Step 1: Initialize as Flask App

First, ChatGPT creates a Python file named app.py:

@app.route('/')
def index():
      return render_template('index.html')
    
if __name__ == '__main__':
      app.run(debug=True)

This section of code sets up a very basic Flask application with a single route that serves an HTML template (index.html) when the root URL is accessed.

The @app.route('/') decorator specifies that this function should be triggered when the root URL (/) is accessed. Essentially, it’s telling Flask to execute the following function whenever someone visits the home page of your app.

The function index() is defined immediately after the route decorator. This function will be executed when the route is accessed. render_template('index.html') is called within index(). Flask then looks for an HTML file named index.html within a folder named templates in the same directory as the Flask app. It will render this template and send it as the response to the client’s request.

Step 2: Create HTML/CSS for the Form

Next, ChatGPT creates an index.html file with the instruction to store it in a templates folder on the same level as app.py. This HTML file provides the form where the user will enter the data to make a credit card payment. Specifically, the user must enter their name, amount to transfer, currency, card number, expiration month and year, and CVV.

<!DOCTYPE html>
<html>
<head>
    <title>Payment Form</title>
    <link rel="stylesheet" type="text/css" href="{{ url_for('static', filename='styles.css') }}">
</head>
<body>
    <h1>Create a Payment</h1>
    <form action="/create_payment" method="post">
        Name: <input type="text" name="name"><br>
        Amount: <input type="text" name="amount"><br>
        Currency: <input type="text" name="currency"><br>
        Card Number: <input type="text" name="card_number"><br>
        Expiration Month: <input type="text" name="expiration_month"><br>
        Expiration Year: <input type="text" name="expiration_year"><br>
        CVV: <input type="text" name="cvv"><br>
        <input type="submit" value="Submit">
    </form>
</body>
</html>

After that, ChatGPT requests that the user add some custom CSS to a styles.css file within the static folder to make the form more visually appealing. Noticeably, ChatGPT did not provide CSS, as specifically requested in the prompt. This will be addressed later.

Step 3: Use Python to Interact with Rapyd’s API

Next, ChatGPT provides the Python code that integrates with Rapyd’s API to create a payment charge. It defines a Flask route and associated function for handling the payment. In the following, the code is broken down into smaller parts and explained step by step:

# Replace with your actual Rapyd API keys
RAPYD_ACCESS_KEY = 'your_rapyd_access_key_here'
RAPYD_SECRET_KEY = 'your_rapyd_secret_key_here'

BASE_URL = 'https://sandboxapi.rapyd.net'

RAPYD_ACCESS_KEY and RAPYD_SECRET_KEY are placeholders for the Rapyd API keys, and the BASE_URL is the base URL for the Rapyd API call.

The following code is used to generate the salt and the signature:

def generate_salt(length=8):
    letters_and_digits = string.ascii_letters + string.digits
    return ''.join(random.choice(letters_and_digits) for i in range(length))

def create_signature(http_method, url_path, salt, timestamp, body=""):
    to_sign = (http_method + url_path + salt + str(timestamp) + RAPYD_ACCESS_KEY + RAPYD_SECRET_KEY + body).encode('utf-8')
    return hashlib.sha256(to_sign).hexdigest()

The utility function generate_salt() generates a random “salt” string using ASCII letters and digits. create_signature() generates an SHA-256 hash, which is used as a signature for API requests to Rapyd. The signature is computed using several pieces of information, including the HTTP method, URL path, salt, timestamp, and your API keys.

The following code defines a Flask API endpoint that accepts POST requests to create a new payment using Rapyd’s payment service:

@app.route('/create_payment', methods=['POST'])
def create_payment():
    amount = request.form['amount']
    currency = request.form['currency']
    card_number = request.form['card_number']
    expiration_month = request.form['expiration_month']
    expiration_year = request.form['expiration_year']
    cvv = request.form['cvv']
    name = request.form['name']

    # Generate necessary headers
    timestamp = int(time.time())
    salt = generate_salt()
    url_path = '/v1/charges'
    http_method = 'post'

    body = json.dumps({
        'amount': amount,
        'currency': currency,
        'payment_method': {
            'type': 'card',
            'fields': {
                'number': card_number,
                'expiration_month': expiration_month,
                'expiration_year': expiration_year,
                'cvv': cvv,
                'name': name
            }
        }
    })

    signature = create_signature(http_method, url_path, salt, timestamp, body)

    headers = {
        'access_key': RAPYD_ACCESS_KEY,
        'salt': salt,
        'timestamp': str(timestamp),
        'signature': signature,
        'Content-Type': 'application/json'
    }

    response = requests.post(BASE_URL + url_path, headers=headers, data=body)
    return jsonify(response.json())

The Flask route for creating payment is defined with the @app.route('/create_payment', methods=['POST']) decorator, which means that the server will listen for POST requests at the /create_payment endpoint. When a POST request is received at this endpoint, the associated create_payment function is invoked.

Inside the function, several variables like amount, currency, card_number, expiration_month, expiration_year, and cvv are initialized by extracting the corresponding values from the form data in the POST request. Then, the function generates a timestamp and a random salt string, which are used along with other details like the HTTP method and API keys to create an SHA-256 signature. This signature authenticates the subsequent API request to Rapyd’s service.

The function prepares a JSON payload, specifying all necessary payment details, including the amount, currency, and card information. This payload is then sent as the body of an HTTP POST request to Rapyd’s API, specifically to the /v1/charges endpoint. You should note that ChatGPT has provided an incorrect endpoint that does not exist. When working with APIs, especially for payment processing, you should refer to the official documentation provided by the service provider to ensure accurate and secure transactions. The API request is made with headers, including the previously generated salt, timestamp, and signature, and the API access key.

Finally, the function receives the API response, which contains information about the success or failure of the payment operation, and returns this as a JSON object to the client.

Step 4: Make the Form More Visually Appealing

By now, the code is finished and is ready to be tested. But before that, you’ll first want to make the form more visually appealing. Although ChatGPT was instructed to provide some CSS for the form, the AI did not do it and instead instructed you to provide your own code. The form without the CSS does not look great.

You’ll now fix that using another prompt for ChatGPT that instructs the AI explicitly to generate some CSS:

ChatGPT, I kindly asked you to use .css to make the form more visually appealing. You ignored that. Can you do it now, please?

After that, ChatGPT apologized and provided the following requested CSS:

/* Global Styles */
body {
    font-family: Arial, sans-serif;
    margin: 0;
    padding: 0;
    background: linear-gradient(135deg, #71b7e6, #9b59b6);
    height: 100vh;
    display: flex;
    justify-content: center;
    align-items: center;
}

/* Form Container */
.form-container {
    width: 400px;
    background-color: rgba(255, 255, 255, 0.9);
    padding: 30px;
    border-radius: 10px;
    box-shadow: 0 8px 16px 0 rgba(0,0,0,0.2);
    transition: 0.3s;
}

.form-container:hover {
    box-shadow: 0 12px 20px 0 rgba(0,0,0,0.3);
}

/* Headline */
.headline {
    font-size: 24px;
    text-align: center;
    margin-bottom: 20px;
}

/* Input Fields */
input[type="text"] {
    width: 100%;
    padding: 12px;
    border: none;
    border-radius: 4px;
    margin: 8px 0;
    box-shadow: 0 2px 4px 0 rgba(0,0,0,0.2);
    transition: 0.3s;
}

input[type="text"]:focus {
    box-shadow: 0 4px 8px 0 rgba(0,0,0,0.4);
}

/* Submit Button */
button[type="submit"] {
    width: 100%;
    padding: 14px;
    background: linear-gradient(135deg, #71b7e6, #9b59b6);
    color: white;
    border: none;
    border-radius: 4px;
    cursor: pointer;
    transition: all 0.3s;
}

button[type="submit"]:hover {
    background: linear-gradient(135deg, #9b59b6, #71b7e6);
}

The HTML file was also adjusted as follows:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Payment Form</title>
    <link rel="stylesheet" type="text/css" href="{{ url_for('static', filename='styles.css') }}">
</head>
<body>

<div class="form-container">
    <h1 class="headline">Payment Form</h1>
    <form action="/create_payment" method="post">
        Name: <input type="text" name="name"><br>
        Amount: <input type="text" name="amount"><br>
        Currency: <input type="text" name="currency"><br>
        Card Number: <input type="text" name="card_number"><br>
        Expiration Month: <input type="text" name="expiration_month"><br>
        Expiration Year: <input type="text" name="expiration_year"><br>
        CVV: <input type="text" name="cvv"><br>
        <input type="submit" value="Submit">
    </form>
</body>
</html>

The new form looks as follows:

Step 5: Testing and Debugging the App

Now that the form looks a bit more visually appealing, you can enter some data into it and make a payment request using the Rapyd API.

After clicking on the submit button, you’ll get the following error in the browser:

{
  "status": {
    "error_code": "UNAUTHORIZED_API_CALL",
    "message": "",
    "operation_id": "6c7f2c73-92bd-4839-b902-6126bb962029",
    "response_code": "UNAUTHORIZED_API_CALL",
    "status": "ERROR"
  }
}

The error message UNAUTHORIZED_API_CALL generally indicates that the API call did not have the proper authentication or permission to access the resource. The status ERROR further confirms that the operation was unsuccessful. The empty message field could have provided more details, but it’s empty in this case, so the exact reason for the error is not specified.

To debug the code, we can use the exact error message as an input prompt for ChatGPT and ask it to provide a possible reason for it. The following screenshot shows ChatGPT’s response:

When pressed about whether ChatGPT provided the correct calculation of the signature, header, and endpoint definition, ChatGPT is sure that it made no errors. However, further research into Rapyd’s API documentation reveals that the endpoint ‘/v1/charges’ provided by ChatGPT was not correct. The correct endpoint should be ‘/v1/payments’.

After correcting the endpoint in the code and submitting the payment once more, it returns another error message:

{
  "status": {
    "error_code": "UNAUTHENTICATED_API_CALL",
    "message": "The API received a request, but the signature did not match. The request was rejected. Corrective action: (1) Remove all whitespace that is not inside a string. (2) Remove trailing zeroes and decimal points, or wrap numbers in a string.",
    "operation_id": "b49d2d3a-45f9-44e5-ad09-a303e453db23",
    "response_code": "UNAUTHENTICATED_API_CALL",
    "status": "ERROR"
  }
}

This time, the error message again indicates that the API call did not have the proper authentication. However, now we get a message field that provides more details regarding the error. It seems that the API received the request, but the signature did not match. Hence, the signature is not calculated correctly.

ChatGPT’s answer to the cause of this error message as an input prompt is as follows:

In the response of ChatGPT (depicted in the picture above), the AI provides some points to double-check to ensure that the signature is calculated correctly. When asked to provide an alternative way of calculating the signature that incorporates all of these mentioned points that must be fulfilled, ChatGPT finds and corrects a previously introduced error, which was not using the separators=(',', ':') to minimize the resulting JSON string of the variable body, by omitting whitespace between separators and delimiters. However, the error message remains when payment is submitted, and the AI tool seems unable to provide a successful way to calculate the signature. Rapyd’s API documentation outlines the correct method for calculating the signature, as demonstrated in the following snippet:

def create_signature(http_method, path, salt, timestamp, body=None):
    to_sign = (http_method, path, salt, str(timestamp), RAPYD_ACCESS_KEY, RAPYD_SECRET_KEY, body)
    h = hmac.new(RAPYD_SECRET_KEY.encode('utf-8'), ''.join(to_sign).encode('utf-8'), hashlib.sha256)
    signature = base64.urlsafe_b64encode(str.encode(h.hexdigest()))
    return signature

Using this method to calculate the signature, the API call is now successful, and Rapyd responds:

Writing Effective Prompts for ChatGPT-4

Using ChatGPT as a programming support tool is convenient but not always straightforward. The following are some tips for writing effective ChatGPT prompts:

  1. Ask for specific languages or libraries: Always specify the programming language or library you are working with to get the most relevant code examples or explanations.
  2. Include error messages: If you are debugging, include the error message in the input prompt to get the most valuable troubleshooting tips.
  3. Define the scope: If you are working on a large problem, break it down. Ask GPT-4 to solve a specific subproblem or a part of the code. This is analogous to modular programming.
  4. Indicate code vs. prose: If you need an explanation in comments and not executable code, make that clear in your prompt. For instance, “Explain in comments how the following sorting algorithm works.”

The following are some tips for using ChatGPT efficiently for code improvements and documentation:

  1. Refactor: If you have a piece of code that you think is too verbose or can be optimized, you can ask GPT-4 for a refactored version. For example, “Refactor the following Python code for better performance.”
  2. Review code: GPT-4 can simulate basic code reviews. You could ask, “Perform a code review of this JavaScript function, focusing on readability and best practices.”
  3. Generate comments: For uncommented or poorly commented code, you can ask GPT-4 to generate meaningful comments (eg “Generate comments for the following C++ code to improve its readability”).
  4. Automate documentation: If you have a series of functions or a class that you’d like to document, you can ask GPT-4 to generate a Markdown- or Javadoc-style documentation based on the code you provide.
  5. Write test cases: You can even ask GPT-4 to write test cases for your existing code. For example, “Write unit tests for the following Python function.”

Pros and Cons of Using ChatGPT to Create a Payment Workflow

The experience quality of using ChatGPT to create a payment workflow is mixed. On the one hand, ChatGPT can provide the entire code base from frontend to backend very quickly to process the payment. For someone with little to no experience with Flask, Rest API, or Rapyd API, this would be a great help. The potential for saving time is enormous. On the other hand, the code that ChatGPT had supplied was not fully functional. There were some crucial parts that were error-prone, and ChatGPT was unable to correct this error itself. Only human intervention after online research was able to correct this error.

A possible reason for this inadequacy is the fact that ChatGPT’s training data spans only until September 2021. Hence, the AI did not see any changes to the Rapyd API that occurred after. Therefore, ChatGPT and, by extension, GPT-4 cannot yet replace a human developer. However, the added value and time saving offered by AI as an assistant during programming are enormous.

Conclusion

Combining AI with API services like Rapyd can streamline and simplify complex processes such as payment gateway integration. However, it’s important to validate and test the code thoroughly. This is especially true when it comes to financial transactions. ChatGPT can be an invaluable tool for code generation, debugging, understanding workflows, and even documentation, but the generated code should always be reviewed carefully for security and compliance reasons. Using effective prompts and following best practices can significantly enhance the quality of support you get from AI-powered coding assistants like ChatGPT. It might not replace a seasoned developer, but it can undoubtedly make the development process quicker and maybe even a little more enjoyable.

Rapyd is a global fintech company that provides a wide range of financial services through a single API. It aims to simplify the complexity associated with offering local payment methods and related financial services, such as collecting payments, disbursing funds, or simply making it easier for businesses to operate in different parts of the world. By integrating Rapyd’s API, businesses can offer multiple payment methods to customers without the hassle of dealing with regulatory requirements, different currencies, and local payment behaviors.

1 Like