Skip to content
Merged
Show file tree
Hide file tree
Changes from 8 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
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -53,3 +53,4 @@ build

# Ignore Docker env file
docker.env
examples/**/Dependencies.toml
110 changes: 104 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,26 +1,124 @@
# Ballerina Paypal Payments connector
# Ballerina PayPal Payments connector

[![Build](https://github.com/ballerina-platform/module-ballerinax-paypal.payments/actions/workflows/ci.yml/badge.svg)](https://github.com/ballerina-platform/module-ballerinax-paypal.payments/actions/workflows/ci.yml)
[![GitHub Last Commit](https://img.shields.io/github/last-commit/ballerina-platform/module-ballerinax-paypal.payments.svg)](https://github.com/ballerina-platform/module-ballerinax-paypal.payments/commits/master)
[![GitHub Issues](https://img.shields.io/github/issues/ballerina-platform/ballerina-library/module/paypal.payments.svg?label=Open%20Issues)](https://github.com/ballerina-platform/ballerina-library/labels/module%paypal.payments)

## Overview

[//]: # (TODO: Add overview mentioning the purpose of the module, supported REST API versions, and other high-level details.)
[PayPal](https://www.paypal.com/) is a global online payment platform enabling individuals and businesses to securely send and receive money, process transactions, and access merchant services across multiple currencies.

The `ballerinax/paypal.payments` package provides a Ballerina connector for interacting with the [PayPal Payments API v2](https://developer.paypal.com/docs/api/payments/v2/), allowing you to authorize payments, capture authorized payments, refund captured payments, void authorizations, and reauthorize expired authorizations in your Ballerina applications.

## Setup guide

[//]: # (TODO: Add detailed steps to obtain credentials and configure the module.)
To use the PayPal Payments connector, you must have access to a [PayPal Developer account](https://developer.paypal.com/).

### Step 1: Create a business account

1. Open the [PayPal Developer Dashboard](https://developer.paypal.com/dashboard).

2. Click on "Sandbox Accounts" under "Testing Tools".

![Sandbox accounts](https://raw.githubusercontent.com/ballerina-platform/module-ballerinax-paypal.payments/main/docs/setup/resources/sandbox-accounts.png)

3. Create a Business account

> Note: Some PayPal options and features may vary by region or country; check availability before creating an account.

![Create business account](https://raw.githubusercontent.com/ballerina-platform/module-ballerinax-paypal.payments/main/docs/setup/resources/create-account.png)

### Step 2: Create a REST API app

1. Navigate to the "Apps and Credentials" tab and create a new merchant app.

Provide a name for the application and select the Business account you created earlier.

![Create app](https://raw.githubusercontent.com/ballerina-platform/module-ballerinax-paypal.payments/main/docs/setup/resources/create-app.png)

### Step 3: Obtain Client ID and Client Secret

1. After creating your new app, you will see your **Client ID** and **Client Secret**. Make sure to copy and securely store these credentials.

![Credentials](https://raw.githubusercontent.com/ballerina-platform/module-ballerinax-paypal.payments/main/docs/setup/resources/get-credentials.png)

## Quickstart

[//]: # (TODO: Add a quickstart guide to demonstrate a basic functionality of the module, including sample code snippets.)
To use the `paypal.payments` connector in your Ballerina application, update the `.bal` file as follows:

### Step 1: Import the module

Import the `paypal.payments` module.

```ballerina
import ballerinax/paypal.payments as paypal;
```

### Step 2: Instantiate a new connector

1. Create a `Config.toml` file and configure the obtained credentials in the above steps as follows:

```toml
clientId = "<test-client-id>"
clientSecret = "<test-client-secret>"

serviceUrl = "<paypal-service-url>"
tokenUrl = "<paypal-token-url>"
```

2. Create a `paypal:ConnectionConfig` with the obtained credentials and initialize the connector with it.

```ballerina
configurable string clientId = ?;
configurable string clientSecret = ?;

configurable string serviceUrl = ?;
configurable string tokenUrl = ?;
```

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

### Step 3: Invoke the connector operation

Now, utilize the available connector operations.

#### Capture an authorized payment

```ballerina
public function main() returns error? {
paypal:CaptureRequest captureRequest = {
amount: {
currency_code: "USD",
value: "100.00"
},
final_capture: true
};

paypal:Capture2 response = check paypal->/authorizations/[authorizationId]/capture.post(captureRequest);
}
```

### Step 4: Run the Ballerina application

```bash
bal run
```

## Examples

The `Paypal Payments` connector provides practical examples illustrating usage in various scenarios. Explore these [examples](https://github.com/module-ballerinax-paypal.payments/tree/main/examples/), covering the following use cases:
The `PayPal Payments` connector provides practical examples illustrating usage in various scenarios. Explore these [examples](https://github.com/ballerina-platform/module-ballerinax-paypal.payments/tree/main/examples/), covering the following use cases:

1. [**Order creation**](https://github.com/ballerina-platform/module-ballerinax-paypal.payments/tree/main/examples/order-creation): Process a complete product purchase from order creation through payment authorization, capture, and partial refunds.

[//]: # (TODO: Add examples)
2. [**Subscription management**](https://github.com/ballerina-platform/module-ballerinax-paypal.payments/tree/main/examples/subscription-management): Simulate a recurring billing flow with subscription-style orders, monthly payments, plan switching, and pro-rated refunds.

## Build from the source

Expand Down
2 changes: 1 addition & 1 deletion ballerina/Dependencies.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

[ballerina]
dependencies-toml-version = "2"
distribution-version = "2201.12.7"
distribution-version = "2201.12.6"

[[package]]
org = "ballerina"
Expand Down
26 changes: 13 additions & 13 deletions ballerina/tests/mock_service.bal
Original file line number Diff line number Diff line change
Expand Up @@ -43,12 +43,12 @@ service / on httpListener {

Authorization2 auth = {
status: "CREATED",
id: id,
id,
amount: {
value: "100.00",
currency_code: "USD"
},
links: links,
links,
create_time: time:utcToString(time:utcNow()),
update_time: time:utcToString(time:utcNow())
};
Expand Down Expand Up @@ -81,9 +81,9 @@ service / on httpListener {
Capture2 capture = {
status: "COMPLETED",
id: captureId,
amount: amount,
amount,
final_capture: finalCapture,
links: links,
links,
create_time: time:utcToString(time:utcNow()),
update_time: time:utcToString(time:utcNow())
};
Expand Down Expand Up @@ -111,8 +111,8 @@ service / on httpListener {
Authorization2 reauth = {
status: "CREATED",
id: reauthId,
amount: amount,
links: links,
amount,
links,
create_time: time:utcToString(time:utcNow()),
update_time: time:utcToString(time:utcNow())
};
Expand All @@ -123,7 +123,7 @@ service / on httpListener {
resource function post v2/payments/authorizations/[string id]/void() returns Authorization2|error? {
Authorization2 voidedAuth = {
status: "VOIDED",
id: id,
id,
create_time: time:utcToString(time:utcNow()),
update_time: time:utcToString(time:utcNow())
};
Expand All @@ -142,13 +142,13 @@ service / on httpListener {

Capture2 capture = {
status: "COMPLETED",
id: id,
id,
amount: {
value: "50.00",
currency_code: "USD"
},
final_capture: false,
links: links,
links,
create_time: time:utcToString(time:utcNow()),
update_time: time:utcToString(time:utcNow())
};
Expand Down Expand Up @@ -176,11 +176,11 @@ service / on httpListener {
Refund refund = {
status: "COMPLETED",
id: refundId,
amount: amount,
amount,
custom_id: requestBody.custom_id,
invoice_id: requestBody.invoice_id,
note_to_payer: requestBody.note_to_payer,
links: links,
links,
create_time: time:utcToString(time:utcNow()),
update_time: time:utcToString(time:utcNow())
};
Expand All @@ -199,12 +199,12 @@ service / on httpListener {

Refund refund = {
status: "COMPLETED",
id: id,
id,
amount: {
value: "25.00",
currency_code: "USD"
},
links: links,
links,
create_time: time:utcToString(time:utcNow()),
update_time: time:utcToString(time:utcNow())
};
Expand Down
2 changes: 1 addition & 1 deletion ballerina/tests/tests.bal
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ import ballerina/time;

configurable string sandboxClientId = os:getEnv("PAYPAL_CLIENT_ID");
configurable string sandboxClientSecret = os:getEnv("PAYPAL_CLIENT_SECRET");
configurable boolean isLiveServer = ?;
configurable boolean isLiveServer = false;
configurable string testOrderId = os:getEnv("PAYPAL_TEST_ORDER_ID");
configurable string testAuthId = os:getEnv("PAYPAL_TEST_AUTH_ID");
configurable string testCaptureId = os:getEnv("PAYPAL_TEST_CAPTURE_ID");
Expand Down
Binary file added docs/setup/resources/create-account.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/setup/resources/create-app.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/setup/resources/get-credentials.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/setup/resources/sandbox-accounts.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Loading