Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -54,4 +54,8 @@ build
# Ignore Docker env file
docker.env

# Ignore environment file
.env

# Ignore Examples Dependencies file
examples/**/Dependencies.toml
4 changes: 4 additions & 0 deletions ballerina/Dependencies.toml
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,9 @@ version = "0.0.0"
dependencies = [
{org = "ballerina", name = "jballerina.java"}
]
modules = [
{org = "ballerina", packageName = "lang.runtime", moduleName = "lang.runtime"}
]

[[package]]
org = "ballerina"
Expand Down Expand Up @@ -338,6 +341,7 @@ dependencies = [
{org = "ballerina", name = "constraint"},
{org = "ballerina", name = "data.jsondata"},
{org = "ballerina", name = "http"},
{org = "ballerina", name = "lang.runtime"},
{org = "ballerina", name = "log"},
{org = "ballerina", name = "test"},
{org = "ballerina", name = "time"},
Expand Down
2 changes: 1 addition & 1 deletion ballerina/tests/mock_service.bal
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
import ballerina/http;
import ballerina/log;

configurable boolean isLiveServer = ?;
configurable boolean isLiveServer = false;

listener http:Listener httpListener = new (9090);

Expand Down
52 changes: 52 additions & 0 deletions ballerina/tests/sts_service.bal
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
// Copyright (c) 2025, WSO2 LLC. (http://www.wso2.com).
//
// WSO2 LLC. licenses this file to you under the Apache License,
// Version 2.0 (the "License"); you may not use this file except
// in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.

import ballerina/http;

configurable int HTTP_SERVER_PORT = 9444;
configurable int TOKEN_VALIDITY_PERIOD = 10000;

http:Listener stsListener = check new (HTTP_SERVER_PORT);

http:Service sts = service object {
resource function post token() returns json {
return {
"access_token": "test-access-token",
"token_type": "example",
"expires_in": TOKEN_VALIDITY_PERIOD,
"example_parameter": "example_value"
};
}

resource function post introspect() returns json {
return {
"active": true,
"scope": "read write",
"client_id": "test-client-id",
"username": "test-user",
"token_type": "example",
"exp": TOKEN_VALIDITY_PERIOD,
"iat": 1419350238,
"nbf": 1419350238,
"sub": "Z5O3upPC88QrAjx00dis",
"aud": "https://protected.example.net/resource",
"iss": "https://server.example.com/",
"jti": "JlbmMiOiJBMTI4Q0JDLUhTMjU2In",
"extension_field": "twenty-seven",
"scp": "admin"
};
}
};
32 changes: 26 additions & 6 deletions ballerina/tests/tests.bal
Original file line number Diff line number Diff line change
Expand Up @@ -15,29 +15,49 @@
// under the License.

import ballerina/http;
import ballerina/lang.runtime;
import ballerina/log;
import ballerina/test;
import ballerina/time;

configurable string serviceUrl = isLiveServer ? "https://api-m.sandbox.paypal.com/v1/billing" : "http://localhost:9090/v1/billing";
configurable string clientId = ?;
configurable string clientSecret = ?;
configurable string testActivatedSubscriptionId = ?;
configurable string clientId = "mock-client-id";
configurable string clientSecret = "mock-client-secret";
configurable string testActivatedSubscriptionId = "mock-activated-subscription-id";

string testProductId = "";
string testPlanId = "";
string testSubscriptionId = "";
string testActivatedSubscriptionPlanId = "";
string mockTokenUrl = "http://localhost:" + HTTP_SERVER_PORT.toString() + "/oauth2/token";

ConnectionConfig config = {
auth: {
clientId,
clientSecret
clientSecret,
tokenUrl: isLiveServer ? "https://api-m.sandbox.paypal.com/v1/oauth2/token" : mockTokenUrl
}
};

final Client paypal = check new Client(config, serviceUrl);
Client paypal = test:mock(Client);

@test:BeforeSuite
function initClient() returns error? {
if isLiveServer {
paypal = check new (config, serviceUrl);
}
else {
check stsListener.attach(sts, "/oauth2");
check stsListener.'start();

runtime:registerListener(stsListener);
log:printInfo(string `STS started on port: ${HTTP_SERVER_PORT} (HTTP)`);

paypal = check new (config, serviceUrl);
}
check createProduct();
}

function createProduct() returns error? {
if !isLiveServer {
testProductId = "PRD-TEMP";
Expand All @@ -47,7 +67,7 @@ function createProduct() returns error? {
int timestamp = currentTime[0];
http:Client productClient = check new ("https://api-m.sandbox.paypal.com/v1/catalogs", config = {
auth: {
tokenUrl: "https://api-m.sandbox.paypal.com/v1/oauth2/token",
tokenUrl: isLiveServer ? "https://api-m.sandbox.paypal.com/v1/oauth2/token" : mockTokenUrl,
clientId,
clientSecret
}
Expand Down
19 changes: 13 additions & 6 deletions examples/README.md
Original file line number Diff line number Diff line change
@@ -1,16 +1,23 @@
# Examples

The `ballerinax/paypal.subscriptions` connector provides practical examples illustrating usage in various scenarios.
The `ballerinax/paypal.subscriptions` connector provides practical examples illustrating usage in various scenarios. Explore these [examples](https://github.com/ballerina-platform/module-ballerinax-paypal.subscriptions/tree/main/examples), covering use cases like creating and listing subscription plans, and monitoring and managing subscription status.

[//]: # (TODO: Add examples)
1.
2.
1. [Create and list plans](https://github.com/ballerina-platform/module-ballerinax-paypal.subscriptions/tree/main/examples/create-and-list-plans/create-and-list-plans.md) - Create a subscription plan and list all available plans for subscription-based services.
2. [Monitor and manage subscription status](https://github.com/ballerina-platform/module-ballerinax-paypal.subscriptions/tree/main/examples/monitor-and-manage-subscription/monitor-and-manage-subscription.md) - Retrieve a subscription's status and suspend or reactivate it based on its current state.

## Prerequisites

[//]: # (TODO: Add prerequisites)
1. Generate PayPal credentials to authenticate the connector as described in the [Setup guide](https://central.ballerina.io/ballerinax/paypal.subscriptions/latest#setup-guide).
2. For each example, create a `Config.toml` file with the related configuration. Here's an example of how your `Config.toml` file should look:

## Running an example
```toml
clientId = "<your_client_id>"
clientSecret = "<your_client_secret>"
productId = "<your_product_id>" # Required for create-and-list-plans
subscriptionId = "<your_subscription_id>" # Required for monitor-and-manage-subscription
```

## Running an Example

Execute the following commands to build an example from the source:

Expand Down
8 changes: 8 additions & 0 deletions examples/create-and-list-plans/Ballerina.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
[package]
org = "wso2"
name = "create_and_list_plans"
version = "0.1.0"
distribution = "2201.12.7"

[build-options]
observabilityIncluded = true
27 changes: 27 additions & 0 deletions examples/create-and-list-plans/create-and-list-plans.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
## Create and List Subscription Plans

This use case demonstrates how the PayPal Subscriptions API can be used to create a new subscription plan and list all available plans. It showcases the ability to define billing plans for services and retrieve plan details, which is useful for applications managing subscription-based offerings, such as SaaS platforms.

## Prerequisites

### 1. Set up PayPal Developer account

Refer to the [Setup Guide](https://github.com/ballerina-platform/module-ballerinax-paypal.subscriptions#setup-guide) to obtain necessary credentials (`clientId`, `clientSecret`) and create a product to get a `productId`.

### 2. Configuration

Create a `Config.toml` file in the example's root directory and provide your PayPal credentials and product ID as follows:

```toml
clientId = "<your_client_id>"
clientSecret = "<your_client_secret>"
productId = "<your_product_id>"
```

## Run the Example

Execute the following command to run the example:

```bash
bal run
```
69 changes: 69 additions & 0 deletions examples/create-and-list-plans/main.bal
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
// Copyright (c) 2025, WSO2 LLC. (http://www.wso2.com).
//
// WSO2 LLC. licenses this file to you under the Apache License,
// Version 2.0 (the "License"); you may not use this file except
// in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.

import ballerina/io;
import ballerinax/paypal.subscriptions as paypal;

configurable string clientId = ?;
configurable string clientSecret = ?;
configurable string productId = ?;

final paypal:Client paypal = check new paypal:Client({auth: {clientId, clientSecret}});

public function main() returns error? {
// Create a subscription plan
paypal:PlanRequestPOST planPayload = {
product_id: productId,
name: "Basic Monthly Plan",
description: "Monthly subscription for premium access",
status: "ACTIVE",
billing_cycles: [
{
frequency: {
interval_unit: "MONTH",
interval_count: 1
},
tenure_type: "REGULAR",
sequence: 1,
total_cycles: 12,
pricing_scheme: {
fixed_price: {
value: "10.00",
currency_code: "USD"
}
}
}
],
payment_preferences: {
auto_bill_outstanding: true,
setup_fee: {
value: "0.00",
currency_code: "USD"
},
setup_fee_failure_action: "CONTINUE",
payment_failure_threshold: 3
}
};
paypal:Plan createdPlan = check paypal->/plans.post(planPayload);
io:println("Created Plan ID: ", createdPlan.id);

// List all plans
paypal:PlanCollection planList = check paypal->/plans();
io:println("Available Plans:");
foreach var plan in planList.plans ?: [] {
io:println("- Plan ID: ", plan.id, ", Name: ", plan.name);
}
}
8 changes: 8 additions & 0 deletions examples/monitor-and-manage-subscription/Ballerina.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
[package]
org = "wso2"
name = "monitor_and_manage_subscription"
version = "0.1.0"
distribution = "2201.12.7"

[build-options]
observabilityIncluded = true
55 changes: 55 additions & 0 deletions examples/monitor-and-manage-subscription/main.bal
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
// Copyright (c) 2025, WSO2 LLC. (http://www.wso2.com).
//
// WSO2 LLC. licenses this file to you under the Apache License,
// Version 2.0 (the "License"); you may not use this file except
// in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.

import ballerina/io;
import ballerinax/paypal.subscriptions as paypal;

configurable string clientId = ?;
configurable string clientSecret = ?;
configurable string subscriptionId = ?;

final paypal:Client paypal = check new ({
auth: {
clientId,
clientSecret
}
});

public function main() returns error? {
// Retrieve subscription details
paypal:SubscriptionsGetQueries queries = {
fields: "id,plan_id,status"
};
paypal:Subscription subscription = check paypal->/subscriptions/[subscriptionId].get(queries = queries);
io:println("Subscription ID: ", subscription.id, ", Status: ", subscription.status);

// Suspend or reactivate based on status
if subscription.status == "ACTIVE" {
paypal:SubscriptionSuspendRequest suspendPayload = {
reason: "Temporary pause due to customer request"
};
check paypal->/subscriptions/[subscriptionId]/suspend.post(suspendPayload);
io:println("Subscription suspended successfully");
} else if subscription.status == "SUSPENDED" {
paypal:SubscriptionActivateRequest activatePayload = {
reason: "Reactivating subscription per customer request"
};
check paypal->/subscriptions/[subscriptionId]/activate.post(activatePayload);
io:println("Subscription reactivated successfully");
} else {
io:println("Subscription status is ", subscription.status, "; no action taken");
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
## Monitor and Manage Subscription Status

This use case demonstrates how the PayPal Subscriptions API can be used to monitor a subscription's status and manage it by suspending or reactivating it. It is useful for applications that need to handle customer subscription status changes, such as pausing a subscription due to payment issues or reactivating it upon resolution, in scenarios like SaaS or subscription-based services.

## Prerequisites

### 1. Set up PayPal Developer account

Refer to the [Setup Guide](https://github.com/ballerina-platform/module-ballerinax-paypal.subscriptions#setup-guide) to obtain necessary credentials (`clientId`, `clientSecret`) and create a subscription to get a `subscriptionId`.

### 2. Configuration

Create a `Config.toml` file in the example's root directory and provide your PayPal credentials and subscription ID as follows:

```toml
clientId = "<your_client_id>"
clientSecret = "<your_client_secret>"
subscriptionId = "<your_subscription_id>"
```

## Run the Example

Execute the following command to run the example:

```bash
bal run
```
Loading