Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Python Flask/Ruby Sinatra examples #160

Merged
merged 17 commits into from
Oct 16, 2024
Merged
Show file tree
Hide file tree
Changes from 12 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
7 changes: 7 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -102,3 +102,10 @@ dist

# dotnet
*.sln

# Python
.venv
__pycache__

# Environment
.env
5 changes: 5 additions & 0 deletions advanced-integration/v2/server/python/.env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# Create an application to obtain credentials at
# https://developer.paypal.com/dashboard/applications/sandbox

PAYPAL_CLIENT_ID=YOUR_CLIENT_ID_GOES_HERE
PAYPAL_CLIENT_SECRET=YOUR_SECRET_GOES_HERE
1 change: 1 addition & 0 deletions advanced-integration/v2/server/python/.flaskenv
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
FLASK_RUN_PORT=8080
25 changes: 25 additions & 0 deletions advanced-integration/v2/server/python/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# Standard Integartion Python Flask Sample

PayPal Standard Integration sample in Python using Flask

## Running the sample

1. Setup a virtual environment

```sh
python3 -m vene .venv
```

1. Install the dependencies

```sh
pip install -r requirements.txt
```

1. Run the server

```sh
flask --app server run
```

1. Go to [http://localhost:8080/](http://localhost:8080/)
3 changes: 3 additions & 0 deletions advanced-integration/v2/server/python/requirements.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
Flask==3.0.3
paypal-server-sdk==0.5.1
python-dotenv==1.0.1
89 changes: 89 additions & 0 deletions advanced-integration/v2/server/python/server.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
import logging
import os

from dotenv import load_dotenv
from flask import Flask, request
from paypalserversdk.http.auth.o_auth_2 import ClientCredentialsAuthCredentials
from paypalserversdk.logging.configuration.api_logging_configuration import LoggingConfiguration, \
RequestLoggingConfiguration, ResponseLoggingConfiguration
from paypalserversdk.paypalserversdk_client import PaypalserversdkClient
from paypalserversdk.controllers.orders_controller import OrdersController
from paypalserversdk.models.amount_with_breakdown import AmountWithBreakdown
from paypalserversdk.models.checkout_payment_intent import CheckoutPaymentIntent
from paypalserversdk.models.order_request import OrderRequest
from paypalserversdk.models.purchase_unit_request import PurchaseUnitRequest
from paypalserversdk.api_helper import ApiHelper

app = Flask(__name__)

load_dotenv()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we can remove the dotenv reference as the README steps for other languages direct the user to explicitly add the environment variables in their shell.

ref: https://github.com/paypal-examples/docs-examples/blob/c964b7083a62e76886251f34dd822fb02258b3c6/advanced-integration/v2/server/dotnet/README.md#running-the-sample

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removed the .env files and update the README to match.

I also caught at the last moment that Integration appears to be misspelled as Integartion in all the server README files. I've corrected it here for the new additions which were based on the existing READMEs, but thought I'd point that out.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @LeonarthusMectus, It has been fixed in other languages


paypal_client: PaypalserversdkClient = PaypalserversdkClient(
client_credentials_auth_credentials=ClientCredentialsAuthCredentials(
o_auth_client_id=os.getenv('PAYPAL_CLIENT_ID'),
o_auth_client_secret=os.getenv('PAYPAL_CLIENT_SECRET')
),
logging_configuration=LoggingConfiguration(
log_level=logging.INFO,
# Disable masking of sensitive headers for Sandbox testing.
# This should be set to True (the default if unset)in production.
mask_sensitive_headers=False,
request_logging_config=RequestLoggingConfiguration(
log_headers=True,
log_body=True
),
response_logging_config=ResponseLoggingConfiguration(
log_headers=True,
log_body=True
)
)
)

'''
Health check
'''
@app.route('/', methods=['GET'])
def index():
return {"message": "Server is running"}

orders_controller: OrdersController = paypal_client.orders

'''
Create an order to start the transaction.

@see https://developer.paypal.com/docs/api/orders/v2/#orders_create
'''
@app.route('/api/orders', methods=['POST'])
def create_order():
request_body = request.get_json()
# use the cart information passed from the front-end to calculate the order amount detals
cart = request_body['cart']
order = orders_controller.orders_create({
"body": OrderRequest(
intent=CheckoutPaymentIntent.CAPTURE,
purchase_units=[
PurchaseUnitRequest(
AmountWithBreakdown(
currency_code='USD',
value='100.00'
)
)
]
),
"prefer": 'return=representation'
}
)
return ApiHelper.json_serialize(order.body)

'''
Capture payment for the created order to complete the transaction.

@see https://developer.paypal.com/docs/api/orders/v2/#orders_capture
'''
@app.route('/api/orders/<order_id>/capture', methods=['POST'])
def capture_order(order_id):
order = orders_controller.orders_capture({
'id': order_id,
'prefer': 'return=representation'
})
return ApiHelper.json_serialize(order.body)
5 changes: 5 additions & 0 deletions advanced-integration/v2/server/ruby/.env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# Create an application to obtain credentials at
# https://developer.paypal.com/dashboard/applications/sandbox

PAYPAL_CLIENT_ID=YOUR_CLIENT_ID_GOES_HERE
PAYPAL_CLIENT_SECRET=YOUR_SECRET_GOES_HERE
1 change: 1 addition & 0 deletions advanced-integration/v2/server/ruby/.ruby-version
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
3.3.5
10 changes: 10 additions & 0 deletions advanced-integration/v2/server/ruby/Gemfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# frozen_string_literal: true

source "https://rubygems.org"

gem "dotenv", "~> 3.1"
gem "paypal-server-sdk", "~> 0.5.1"
gem "puma", "~> 6.4"
gem "rackup", "~> 2.1"
gem "sinatra", "~> 4.0"
gem "sinatra-contrib", "~> 4.0"
21 changes: 21 additions & 0 deletions advanced-integration/v2/server/ruby/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# Standard Integartion Ruby Sinatra Sample

PayPal Standard Integration sample in Ruby using Sinatra

## Running the sample

1. Ensure you have a supported Ruby version installed: [Ruby Maintenance Branches](https://www.ruby-lang.org/en/downloads/branches/)

1. Install the dependencies

```sh
bundle install
```

1. Run the server

```sh
bundle exec ruby server.rb
```

1. Go to [http://localhost:8080/](http://localhost:8080/)
70 changes: 70 additions & 0 deletions advanced-integration/v2/server/ruby/server.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
require 'dotenv'
require 'paypal_server_sdk'
require 'sinatra'
require 'sinatra/json'

include PaypalServerSdk

Dotenv.load(".env")

set :port, 8080

paypal_client = PaypalServerSdk::Client.new(
client_credentials_auth_credentials: ClientCredentialsAuthCredentials.new(
o_auth_client_id: ENV['PAYPAL_CLIENT_ID'],
o_auth_client_secret: ENV['PAYPAL_CLIENT_SECRET']
),
environment: Environment::SANDBOX,
logging_configuration: LoggingConfiguration.new(
mask_sensitive_headers: false,
log_level: Logger::INFO,
request_logging_config: RequestLoggingConfiguration.new(
log_headers: true,
log_body: true,
),
response_logging_config: ResponseLoggingConfiguration.new(
log_headers: true,
log_body: true
)
)
)

# Health Check
get '/' do
json :message => "Server is running"
end

# Create an order to start the transaction.
#
# @see https://developer.paypal.com/docs/api/orders/v2/#orders_create
post "/api/orders" do
# use the cart information passed from the front-end to calculate the order amount detals
cart = JSON.parse request.body.read
order_response = paypal_client.orders.orders_create({
'body' => OrderRequest.new(
intent: CheckoutPaymentIntent::CAPTURE,
purchase_units: [
PurchaseUnitRequest.new(
amount: AmountWithBreakdown.new(
currency_code: 'USD',
value: '100.00'
)
)
]
),
'prefer' => 'return=representation'
})
order_response.data.to_json
end

# Capture payment for the created order to complete the transaction.
#
# @see https://developer.paypal.com/docs/api/orders/v2/#orders_capture
post '/api/orders/:order_id/capture' do |order_id|
capture_response = paypal_client.orders.orders_capture({
'id' => order_id,
'prefer' => 'return=representation'
})
capture_response.data.to_json
rescue ErrorException => e
end
5 changes: 5 additions & 0 deletions standard-integration/server/python/.env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# Create an application to obtain credentials at
# https://developer.paypal.com/dashboard/applications/sandbox

PAYPAL_CLIENT_ID=YOUR_CLIENT_ID_GOES_HERE
PAYPAL_CLIENT_SECRET=YOUR_SECRET_GOES_HERE
1 change: 1 addition & 0 deletions standard-integration/server/python/.flaskenv
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
FLASK_RUN_PORT=8080
25 changes: 25 additions & 0 deletions standard-integration/server/python/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# Standard Integartion Python Flask Sample

PayPal Standard Integration sample in Python using Flask

## Running the sample

1. Setup a virtual environment

```sh
python3 -m vene .venv
```

1. Install the dependencies

```sh
pip install -r requirements.txt
```

1. Run the server

```sh
flask --app server run
```

1. Go to [http://localhost:8080/](http://localhost:8080/)
3 changes: 3 additions & 0 deletions standard-integration/server/python/requirements.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
Flask==3.0.3
paypal-server-sdk==0.5.1
python-dotenv==1.0.1
89 changes: 89 additions & 0 deletions standard-integration/server/python/server.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
import logging
import os

from dotenv import load_dotenv
from flask import Flask, request
from paypalserversdk.http.auth.o_auth_2 import ClientCredentialsAuthCredentials
from paypalserversdk.logging.configuration.api_logging_configuration import LoggingConfiguration, \
RequestLoggingConfiguration, ResponseLoggingConfiguration
from paypalserversdk.paypalserversdk_client import PaypalserversdkClient
from paypalserversdk.controllers.orders_controller import OrdersController
from paypalserversdk.models.amount_with_breakdown import AmountWithBreakdown
from paypalserversdk.models.checkout_payment_intent import CheckoutPaymentIntent
from paypalserversdk.models.order_request import OrderRequest
from paypalserversdk.models.purchase_unit_request import PurchaseUnitRequest
from paypalserversdk.api_helper import ApiHelper

app = Flask(__name__)

load_dotenv()

paypal_client: PaypalserversdkClient = PaypalserversdkClient(
client_credentials_auth_credentials=ClientCredentialsAuthCredentials(
o_auth_client_id=os.getenv('PAYPAL_CLIENT_ID'),
o_auth_client_secret=os.getenv('PAYPAL_CLIENT_SECRET')
),
logging_configuration=LoggingConfiguration(
log_level=logging.INFO,
# Disable masking of sensitive headers for Sandbox testing.
# This should be set to True (the default if unset)in production.
mask_sensitive_headers=False,
request_logging_config=RequestLoggingConfiguration(
log_headers=True,
log_body=True
),
response_logging_config=ResponseLoggingConfiguration(
log_headers=True,
log_body=True
)
)
)

'''
Health check
'''
@app.route('/', methods=['GET'])
def index():
return {"message": "Server is running"}

orders_controller: OrdersController = paypal_client.orders

'''
Create an order to start the transaction.

@see https://developer.paypal.com/docs/api/orders/v2/#orders_create
'''
@app.route('/api/orders', methods=['POST'])
def create_order():
request_body = request.get_json()
# use the cart information passed from the front-end to calculate the order amount detals
cart = request_body['cart']
order = orders_controller.orders_create({
"body": OrderRequest(
intent=CheckoutPaymentIntent.CAPTURE,
purchase_units=[
PurchaseUnitRequest(
AmountWithBreakdown(
currency_code='USD',
value='100.00'
)
)
]
),
"prefer": 'return=representation'
}
)
return ApiHelper.json_serialize(order.body)

'''
Capture payment for the created order to complete the transaction.

@see https://developer.paypal.com/docs/api/orders/v2/#orders_capture
'''
@app.route('/api/orders/<order_id>/capture', methods=['POST'])
def capture_order(order_id):
order = orders_controller.orders_capture({
'id': order_id,
'prefer': 'return=representation'
})
return ApiHelper.json_serialize(order.body)
5 changes: 5 additions & 0 deletions standard-integration/server/ruby/.env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# Create an application to obtain credentials at
# https://developer.paypal.com/dashboard/applications/sandbox

PAYPAL_CLIENT_ID=YOUR_CLIENT_ID_GOES_HERE
PAYPAL_CLIENT_SECRET=YOUR_SECRET_GOES_HERE
1 change: 1 addition & 0 deletions standard-integration/server/ruby/.ruby-version
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
3.3.5
Loading