Skip to content

globalpayments-samples/online-recurring-payments

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

25 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Online Recurring Payments — GP API

A complete recurring payment implementation using the Global Payments GP API. Developers can set up subscription billing by capturing an initial payment with customer data, tokenizing the card server-side with StoredCredential, and scheduling future charges against the stored payment method — without handling raw card numbers at any point. All implementations use the official Global Payments SDK (GpApiConfig).

Available in four languages: PHP, Node.js, .NET, and Java.


Available Implementations

Language Framework SDK Version
PHP Built-in Server globalpayments/php-sdk ^13.1
Node.js Express.js globalpayments-api ^3.10.6
.NET ASP.NET Core GlobalPayments.Api 9.0.16
Java Jakarta Servlet globalpayments-sdk 14.2.20

Preview links (runs in browser via CodeSandbox):


How It Works

This project demonstrates the full recurring payment lifecycle: an initial charge captures the customer's card and stores it as a reusable payment method. All future charges use the stored method without prompting the customer for card details again.

Browser
  │
  ├─ GET /config ──────────────────► Server
  │                                    └─ GP API: generate scoped access token
  │  ◄── { accessToken } ──────────────┘
  │
  ├─ Hosted fields tokenize card (client-side, PCI-compliant)
  │
  ├─ POST /process-payment ────────► Server
  │   {                               ├─ is_recurring: false → charge().execute()
  │     payment_token,                └─ is_recurring: true  → charge()
  │     amount,                                                 .withStoredCredential()
  │     is_recurring,                                           .withCustomer()
  │     frequency,                                              .withAddress()
  │     start_date,                                             .execute()
  │     first_name, last_name,
  │     email, phone, address         Returns transaction_id + payment_method_id
  │   }
  │  ◄── { transactionId, paymentMethodId, customerId, schedule } ──┘
  │
  └─ Future charges use paymentMethodId (no card re-entry)

StoredCredential Flow

The initial charge uses StoredCredentialType.INSTALLMENT and StoredCredentialSequence.FIRST. All subsequent charges reference the same paymentMethodId with StoredCredentialSequence.SUBSEQUENT. This meets card network requirements for recurring billing and avoids false fraud declines.


Prerequisites

  • Global Payments developer account — Sign up at developer.globalpayments.com
  • GP API credentials: APP_ID and APP_KEY (sandbox available after sign-up)
  • A local runtime for your chosen language:
    • PHP 8.0+ with Composer
    • Node.js 18+ with npm
    • .NET 8.0 SDK
    • Java 17+ with Maven

Quick Start

1. Clone the repository

git clone https://github.com/globalpayments-samples/online-recurring-payments.git
cd online-recurring-payments

2. Choose a language and configure credentials

cd php       # or nodejs, dotnet, java
cp .env.sample .env

Edit .env:

APP_ID=your_gp_api_app_id_here
APP_KEY=your_gp_api_app_key_here
GP_API_ENVIRONMENT=sandbox

3. Install and run

PHP:

composer install
php -S localhost:8000

Open: http://localhost:8000

Node.js:

npm install
npm start

Open: http://localhost:8000

.NET:

dotnet restore
dotnet run

Open: http://localhost:8000

Java:

mvn clean package
mvn cargo:run

Open: http://localhost:8000

4. Test a recurring payment

  1. Open the app in your browser
  2. Enter amount (e.g. 25.00) and select Recurring
  3. Fill in customer details (name, email, address)
  4. Choose frequency (e.g. Monthly) and a start date
  5. Use a test card from Test Cards below
  6. Click Submit — note the paymentMethodId in the response
  7. That ID can be used for all future recurring charges

API Endpoints

GET /config

Returns a scoped GP API access token for client-side hosted field initialization. Token has PMT_POST_Create_Single permission — it can only tokenize cards, not process transactions.

Response:

{
  "success": true,
  "data": {
    "accessToken": "uua7...."
  },
  "message": "Configuration retrieved successfully",
  "timestamp": "2025-01-15T10:00:00.000Z"
}

POST /process-payment

Processes either a one-time payment or an initial recurring charge with customer data.

One-time payment

Request body:

{
  "payment_token": "PMT_abc123...",
  "amount": 25.00,
  "currency": "USD",
  "is_recurring": false
}

Success response:

{
  "success": true,
  "data": {
    "transaction_id": "TRN_abc123xyz",
    "amount": 25.00,
    "currency": "USD",
    "status": "captured",
    "message": "Payment processed successfully"
  }
}

Recurring payment setup

Request body:

{
  "payment_token": "PMT_abc123...",
  "amount": 25.00,
  "currency": "USD",
  "is_recurring": true,
  "frequency": "Monthly",
  "start_date": "2025-02-01",
  "first_name": "Jane",
  "last_name": "Smith",
  "email": "jane.smith@example.com",
  "phone": "555-0100",
  "street_address": "123 Main St",
  "city": "Atlanta",
  "state": "GA",
  "billing_zip": "30301"
}

Success response:

{
  "success": true,
  "data": {
    "transaction_id": "TRN_abc123xyz",
    "payment_method_id": "PMT_stored456",
    "customer_id": "CUS_789xyz",
    "amount": 25.00,
    "currency": "USD",
    "frequency": "Monthly",
    "start_date": "2025-02-01",
    "status": "active",
    "message": "Initial payment successful. Recurring payment method stored."
  },
  "message": "Recurring payment schedule created successfully"
}

Supported frequency values: Weekly, Bi-Weekly, Monthly, Quarterly, Annually

Error response (422):

{
  "success": false,
  "error": "Payment declined: Insufficient funds",
  "timestamp": "2025-01-15T10:00:00.000Z"
}

Test Cards

Use these in sandbox (GP_API_ENVIRONMENT=sandbox). CVV: 123. Expiry: any future date.

Brand Card Number Expected Result
Visa 4263 9826 4026 9299 Approved
Mastercard 5425 2334 2424 1200 Approved
Discover 6011 0000 0000 0012 Approved
Declined 4000 1200 0000 1154 Declined

Sandbox transactions do not move real money.


Project Structure

online-recurring-payments/
├── index.html                 # Shared frontend (served by all backends)
├── LICENSE
├── README.md
│
├── php/                       # Port 8000
│   ├── .env.sample
│   ├── composer.json
│   ├── Dockerfile
│   ├── PaymentUtils.php       # SDK config + shared helpers
│   ├── config.php             # GET /config endpoint
│   ├── process-payment.php    # POST /process-payment endpoint
│   └── run.sh
│
├── nodejs/                    # Port 8000
│   ├── .env.sample
│   ├── package.json
│   ├── Dockerfile
│   ├── server.js              # Express app: /config, /process-payment
│   ├── paymentUtils.js        # SDK config + recurring helpers
│   └── run.sh
│
├── dotnet/                    # Port 8000
│   ├── .env.sample
│   ├── *.csproj
│   ├── Program.cs             # ASP.NET Core app: all endpoints
│   ├── Dockerfile
│   └── wwwroot/               # Static frontend files
│
└── java/                      # Port 8000
    ├── .env.sample
    ├── pom.xml
    ├── Dockerfile
    └── src/
        └── main/java/com/globalpayments/example/
            ├── ConfigServlet.java
            └── ProcessPaymentServlet.java

Environment Variables

Variable Description Example
APP_ID Your GP API application ID UJqPrAhrDkGzzNoFInpzKqoI8vfZtGRV
APP_KEY Your GP API application key zCFrbrn0NKly9sB4
GP_API_ENVIRONMENT sandbox for testing, production for live sandbox

Credentials are available in the GP Developer Portal after creating an account.


Troubleshooting

401 Unauthorized on /config Credentials are invalid or for the wrong environment. Verify APP_ID and APP_KEY in .env. Confirm GP_API_ENVIRONMENT matches the credential set (sandbox vs production).

422 — "Payment declined" on initial charge The test card was declined. Try a different card from the Test Cards table. Confirm GP_API_ENVIRONMENT=sandbox when using test cards.

Recurring charge returns "Invalid payment method" The payment_method_id from the initial charge must be stored and reused in subsequent charges. The stored credential expires if the sandbox session ends — run a new initial charge to get a fresh ID.

Missing customer fields validation error Recurring payments require first_name, last_name, and email. phone, street_address, city, state, and billing_zip are optional but improve auth rates.

Port 8000 already in use Another process is binding the port. Check with lsof -i :8000 and stop the conflicting process, or update the port in run.sh and the server file.

Node.js — Cannot find module 'globalpayments-api' Run npm install before npm start. Confirm Node.js 18+ is installed: node -v.

Java build fails Requires Java 17+ and Maven 3.8+. Verify with java -version and mvn -version. Run mvn clean package before mvn cargo:run.


Features

  • Process one-time payments using GP API hosted fields
  • Process recurring payments with StoredCredential — no card re-entry after the initial charge
  • 4-language implementations (PHP, Node.js, .NET, Java)
  • Docker support with per-language containers

Security Considerations

  • Store credentials in .env files, never commit to source control
  • API keys are never exposed to the frontend
  • All payment processing happens server-side
  • Use HTTPS in production
  • Stored credentials must comply with card network rules

Resources


Community

Have a question or found a bug? Open an issue or reach out at communityexperience@globalpay.com.


License

MIT — see LICENSE.

About

Recurring payment and subscription billing examples with Global Payments SDK. Set up automated payment schedules with customer vault integration.

Topics

Resources

License

Stars

0 stars

Watchers

0 watching

Forks

Releases

No releases published

Packages

 
 
 

Contributors