diff --git a/README.md b/README.md index 352f566..3754feb 100644 --- a/README.md +++ b/README.md @@ -89,6 +89,15 @@ stripe:Customer customerDetails = check stripe->/customers.post(newCustomer); stripe:CustomerResourceCustomerList availableCustomers = check stripe->/customers; ``` +## Examples + +The `ballerinax/stripe` connector provides practical examples illustrating usage in various scenarios. Explore these [examples](https://github.com/ballerina-platform/module-ballerinax-stripe/tree/main/examples), covering various Stripe functionalities. + +1. [Manage stripe payments](https://github.com/ballerina-platform/module-ballerinax-stripe/tree/main/examples/manage-payments) - Manage business payments with Stripe. + +2. [Manage one-time charges](https://github.com/ballerina-platform/module-ballerinax-stripe/tree/main/examples/manage-one-time-charges) - Manage one-time charges with Stripe. + + ## Build from the source ### Setting up the prerequisites diff --git a/ballerina/Module.md b/ballerina/Module.md index 9a273d0..03971e2 100644 --- a/ballerina/Module.md +++ b/ballerina/Module.md @@ -82,3 +82,11 @@ stripe:Customer customerDetails = check stripe->/customers.post(newCustomer); ```ballerina stripe:CustomerResourceCustomerList availableCustomers = check stripe->/customers; ``` + +## Examples + +The `ballerinax/stripe` connector provides practical examples illustrating usage in various scenarios. Explore these [examples](https://github.com/ballerina-platform/module-ballerinax-stripe/tree/main/examples), covering various Stripe functionalities. + +1. [Manage stripe payments](https://github.com/ballerina-platform/module-ballerinax-stripe/tree/main/examples/manage-payments) - Manage business payments with Stripe. + +2. [Manage one-time charges](https://github.com/ballerina-platform/module-ballerinax-stripe/tree/main/examples/manage-one-time-charges) - Manage one-time charges with Stripe. diff --git a/ballerina/Package.md b/ballerina/Package.md index 9a273d0..03971e2 100644 --- a/ballerina/Package.md +++ b/ballerina/Package.md @@ -82,3 +82,11 @@ stripe:Customer customerDetails = check stripe->/customers.post(newCustomer); ```ballerina stripe:CustomerResourceCustomerList availableCustomers = check stripe->/customers; ``` + +## Examples + +The `ballerinax/stripe` connector provides practical examples illustrating usage in various scenarios. Explore these [examples](https://github.com/ballerina-platform/module-ballerinax-stripe/tree/main/examples), covering various Stripe functionalities. + +1. [Manage stripe payments](https://github.com/ballerina-platform/module-ballerinax-stripe/tree/main/examples/manage-payments) - Manage business payments with Stripe. + +2. [Manage one-time charges](https://github.com/ballerina-platform/module-ballerinax-stripe/tree/main/examples/manage-one-time-charges) - Manage one-time charges with Stripe. diff --git a/examples/README.md b/examples/README.md new file mode 100644 index 0000000..e0e5163 --- /dev/null +++ b/examples/README.md @@ -0,0 +1,52 @@ +# Examples + +The `ballerinax/stripe` connector provides practical examples illustrating usage in various scenarios. Explore these [examples](https://github.com/ballerina-platform/module-ballerinax-stripe/tree/main/examples), covering various Stripe functionalities. + +1. [Manage stripe payments](https://github.com/ballerina-platform/module-ballerinax-stripe/tree/main/examples/manage-payments) - Manage business payments with Stripe. + +2. [Manage one-time charges](https://github.com/ballerina-platform/module-ballerinax-stripe/tree/main/examples/manage-one-time-charges) - Manage one-time charges with Stripe. + + +## Prerequisites + +1. Retrieve Stripe API token to authenticate the connector as described in the [Setup guide](https://central.ballerina.io/ballerinax/stripe/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: + + ```toml + secretKey="" + ``` + +## Running an Example + +Execute the following commands to build an example from the source: + +* To build an example: + + ```bash + bal build + ``` + +* To run an example: + + ```bash + bal run + ``` + +## Building the Examples with the Local Module + +**Warning**: Due to the absence of support for reading local repositories for single Ballerina files, the Bala of the module is manually written to the central repository as a workaround. Consequently, the bash script may modify your local Ballerina repositories. + +Execute the following commands to build all the examples against the changes you have made to the module locally: + +* To build all the examples: + + ```bash + ./build.sh build + ``` + +* To run all the examples: + + ```bash + ./build.sh run + ``` diff --git a/examples/build.gradle b/examples/build.gradle new file mode 100644 index 0000000..9a02a4a --- /dev/null +++ b/examples/build.gradle @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2024, 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 org.apache.tools.ant.taskdefs.condition.Os + +apply plugin: 'java' + +def graalvmFlag = "" + +task testExamples { + if (project.hasProperty("balGraalVMTest")) { + graalvmFlag = "--graalvm" + } + doLast { + try { + exec { + workingDir project.projectDir + println("Working dir: ${workingDir}") + if (Os.isFamily(Os.FAMILY_WINDOWS)) { + commandLine 'cmd', "/c", "chmod +x ./build.sh && ./build.sh run && exit %%ERRORLEVEL%%" + } else { + commandLine 'sh', "-c", "chmod +x ./build.sh && ./build.sh run" + } + } + } catch (Exception e) { + println("Example Build failed: " + e.message) + throw e + } + } +} + +task buildExamples { + gradle.taskGraph.whenReady { graph -> + if (graph.hasTask(":stripe-examples:test")) { + buildExamples.enabled = false + } else { + testExamples.enabled = false + } + } + doLast { + try { + exec { + workingDir project.projectDir + println("Working dir: ${workingDir}") + if (Os.isFamily(Os.FAMILY_WINDOWS)) { + commandLine 'cmd', "/c", "chmod +x ./build.sh && ./build.sh build && exit %%ERRORLEVEL%%" + } else { + commandLine 'sh', "-c", "chmod +x ./build.sh && ./build.sh build" + } + } + } catch (Exception e) { + println("Example Build failed: " + e.message) + throw e + } + } +} + +buildExamples.dependsOn ":stripe-ballerina:build" +testExamples.dependsOn ":stripe-ballerina:build" + +// TODO: Enable the examples build once https://github.com/ballerina-platform/ballerina-library/issues/6135 is fixed +// test.dependsOn testExamples +// build.dependsOn buildExamples diff --git a/examples/build.sh b/examples/build.sh new file mode 100644 index 0000000..10fe84c --- /dev/null +++ b/examples/build.sh @@ -0,0 +1,63 @@ +#!/bin/bash + +BAL_EXAMPLES_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +BAL_CENTRAL_DIR="$HOME/.ballerina/repositories/central.ballerina.io" +BAL_HOME_DIR="$BAL_EXAMPLES_DIR/../ballerina" + +set -e + +case "$1" in +build) + BAL_CMD="build" + ;; +run) + BAL_CMD="run" + ;; +*) + echo "Invalid command provided: '$1'. Please provide 'build' or 'run' as the command." + exit 1 + ;; +esac + +# Read Ballerina package name +BAL_PACKAGE_NAME=$(awk -F'"' '/^name/ {print $2}' "$BAL_HOME_DIR/Ballerina.toml") + +# Push the package to the local repository +cd "$BAL_HOME_DIR" && + bal pack && + bal push --repository=local + +# Remove the cache directories in the repositories +cacheDirs=$(ls -d $BAL_CENTRAL_DIR/cache-* 2>/dev/null) || true +for dir in "${cacheDirs[@]}"; do + [ -d "$dir" ] && rm -r "$dir" +done +echo "Successfully cleaned the cache directories" + +# Create the package directory in the central repository, this will not be present if no modules are pulled +mkdir -p "$BAL_CENTRAL_DIR/bala/ballerinax/$BAL_PACKAGE_NAME" + +# Update the central repository +BAL_DESTINATION_DIR="$HOME/.ballerina/repositories/central.ballerina.io/bala/ballerinax/$BAL_PACKAGE_NAME" +BAL_SOURCE_DIR="$HOME/.ballerina/repositories/local/bala/ballerinax/$BAL_PACKAGE_NAME" +[ -d "$BAL_DESTINATION_DIR" ] && rm -r "$BAL_DESTINATION_DIR" +[ -d "$BAL_SOURCE_DIR" ] && cp -r "$BAL_SOURCE_DIR" "$BAL_DESTINATION_DIR" +echo "Successfully updated the local central repositories" + +echo "$BAL_DESTINATION_DIR" +echo "$BAL_SOURCE_DIR" + +# Loop through examples in the examples directory +cd "$BAL_EXAMPLES_DIR" +for dir in $(find "$BAL_EXAMPLES_DIR" -type d -maxdepth 1 -mindepth 1); do + # Skip the build directory + if [[ "$dir" == *build ]]; then + continue + fi + (cd "$dir" && bal "$BAL_CMD" --offline && cd ..); +done + +# Remove generated JAR files +find "$BAL_HOME_DIR" -maxdepth 1 -type f -name "*.jar" | while read -r JAR_FILE; do + rm "$JAR_FILE" +done diff --git a/examples/manage-one-time-charges/.github/README.md b/examples/manage-one-time-charges/.github/README.md new file mode 120000 index 0000000..fb61d90 --- /dev/null +++ b/examples/manage-one-time-charges/.github/README.md @@ -0,0 +1 @@ +../Manage Stripe One-Time Charges.md \ No newline at end of file diff --git a/examples/manage-one-time-charges/Ballerina.toml b/examples/manage-one-time-charges/Ballerina.toml new file mode 100644 index 0000000..3ecea90 --- /dev/null +++ b/examples/manage-one-time-charges/Ballerina.toml @@ -0,0 +1,8 @@ +[package] +org = "wso2" +name = "manage_one_time_charges" +version = "0.1.0" +distribution = "2201.9.2" + +[build-options] +observabilityIncluded = true diff --git a/examples/manage-one-time-charges/Manage Stripe One-Time Charges.md b/examples/manage-one-time-charges/Manage Stripe One-Time Charges.md new file mode 100644 index 0000000..9b2b1c0 --- /dev/null +++ b/examples/manage-one-time-charges/Manage Stripe One-Time Charges.md @@ -0,0 +1,26 @@ +# Manage stripe one-time charges + +This example demonstrates how Stripe REST API v1 can be utilized to manage one-time charges. + +## Prerequisites + +### 1. Setup Stripe account + +Refer to the [Setup guide](https://central.ballerina.io/ballerinax/stripe/latest#setup-guide) to set up your stripe +account, if you do not have one. + +### 2. Configuration + +Update your Stripe account-related configurations in the `Config.toml` file in the example root directory: + +```toml +secretKey="" +``` + +## Run the example + +Execute the following command to run the example: + +```ballerina +bal run +``` diff --git a/examples/manage-one-time-charges/main.bal b/examples/manage-one-time-charges/main.bal new file mode 100644 index 0000000..f92bbd0 --- /dev/null +++ b/examples/manage-one-time-charges/main.bal @@ -0,0 +1,42 @@ +// Copyright (c) 2024 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/stripe; + +// Configuration for Stripe API access +configurable string secretKey = ?; + +public function main() returns error? { + stripe:Client stripe = check new ({auth: {token: secretKey}}); + + // Initiate a one-time charge + stripe:charges_body chargeDetails = { + amount: 100, + currency: "usd", + // Update the payment-source token here + 'source: "tok_xxxx" + }; + stripe:Charge charge = check stripe->/charges.post(chargeDetails); + io:println("Onetime charge was successful: ", charge.id); + + // Refund a one-time charge + stripe:charge_refund_body chargeRefund = { + amount: 100 + }; + charge = check stripe->/charges/[charge.id]/refund.post(chargeRefund); + io:println("Onetime charge refund was successful: ", charge.id); +} diff --git a/examples/manage-payments/.github/README.md b/examples/manage-payments/.github/README.md new file mode 120000 index 0000000..3df3c6e --- /dev/null +++ b/examples/manage-payments/.github/README.md @@ -0,0 +1 @@ +../Manage Stripe Payments.md \ No newline at end of file diff --git a/examples/manage-payments/Ballerina.toml b/examples/manage-payments/Ballerina.toml new file mode 100644 index 0000000..66ba6fd --- /dev/null +++ b/examples/manage-payments/Ballerina.toml @@ -0,0 +1,8 @@ +[package] +org = "wso2" +name = "manage_payments" +version = "0.1.0" +distribution = "2201.9.2" + +[build-options] +observabilityIncluded = true diff --git a/examples/manage-payments/Manage Stripe Payments.md b/examples/manage-payments/Manage Stripe Payments.md new file mode 100644 index 0000000..db07f4b --- /dev/null +++ b/examples/manage-payments/Manage Stripe Payments.md @@ -0,0 +1,26 @@ +# Manage stripe payments + +This example demonstrates how Stripe REST API v1 can be utilized to manage business payments. + +## Prerequisites + +### 1. Setup Stripe account + +Refer to the [Setup guide](https://central.ballerina.io/ballerinax/stripe/latest#setup-guide) to set up your stripe +account, if you do not have one. + +### 2. Configuration + +Update your Stripe account-related configurations in the `Config.toml` file in the example root directory: + +```toml +secretKey="" +``` + +## Run the example + +Execute the following command to run the example: + +```ballerina +bal run +``` diff --git a/examples/manage-payments/main.bal b/examples/manage-payments/main.bal new file mode 100644 index 0000000..e7c75a7 --- /dev/null +++ b/examples/manage-payments/main.bal @@ -0,0 +1,49 @@ +// Copyright (c) 2024 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/stripe; + +// Configuration for Stripe API access +configurable string secretKey = ?; + +public function main() returns error? { + stripe:Client stripe = check new ({auth: {token: secretKey}}); + + // Create a payment intent + stripe:payment_intents_body paymentDetails = { + amount: 100, + currency: "usd" + }; + stripe:Payment_intent payment = check stripe->/payment_intents.post(paymentDetails); + + // Confirm the payment + stripe:intent_confirm_body confirmation = { + // Update the payment method here + payment_method: "pm_xxxxxx", + return_url: "https://www.example.com" + }; + payment = check stripe->/payment_intents/[payment.id]/confirm.post(confirmation); + io:println("Payment confirmed successfully: ", payment.id); + + // Refund a confirmed payment + stripe:refunds_body refundDetails = { + // Update the payment-id here + payment_intent: payment.id + }; + stripe:Refund paymentRefund = check stripe->/refunds.post(refundDetails); + io:println("Payment refund was successful. Refund ID: ", paymentRefund.id); +}