Skip to content

Instantly share code, notes, and snippets.

@LeCoupa
Last active November 21, 2022 13:19
Show Gist options
  • Star 4 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save LeCoupa/85e71a30eb51d2eae76b to your computer and use it in GitHub Desktop.
Save LeCoupa/85e71a30eb51d2eae76b to your computer and use it in GitHub Desktop.
# This gist illustrates how to create and execute a payment with Paypal using their REST API.
# For additional informations, check the documentation: https://developer.paypal.com/docs/api/
# Note 1: I assume that you have already created a developer account for Paypal and an application.
# To test that your code is working, use the sandbox accounts.
# https://developer.paypal.com/webapps/developer/applications/accounts
# Note 2: we will not use the Paypal REST API SDK package for Node.js
# https://github.com/paypal/rest-api-sdk-nodejs
# The following code must be only run on the server!
# 1. Create your paypal configuration object.
@paypalConf =
host: "api.sandbox.paypal.com"
clientId: "pHQcZ1cH0lnX5Mub4MGzo_-FH6witB3_2zuRYgvUFxMHFH6wiAe3zCRDqatu3"
clientSecret:"Xk7-EDJqERAU5up6wjeVoRE6WM2OoIsUT3ouxVRKUmjX38b4k0-q6t_UHei"
# 2. Create two collections to save our payments and the Paypal tokens.
@PaypalPayments = new Meteor.Collection 'paypal_payments'
@PaypalTokens = new Meteor.Collection 'paypal_tokens'
# 3. Create the three methods to:
# - Get a valid token to make API calls. (retrieve a new one if invalid)
# - Create a payment
# - Execute a payment.
Meteor.methods
'getPaypalToken': ->
isTokenValid = 0
token = PaypalTokens.findOne({ timestamp: { $exists: true } },
{ sort: { timestamp: -1 } })
if token?
isTokenValid = Math.ceil((new Date().getTime() - token.timestamp) / 1000)
# is the token invalid?
if isTokenValid is 0 or isTokenValid > token.expires_in
auth = paypalConf['clientId'] + ':' +
paypalConf['clientSecret']
token = EJSON.parse(
Meteor.http.post('https://api.sandbox.paypal.com/v1/oauth2/token',
headers:
'Accept': 'application/json'
'Accept-Language': 'en_US'
auth: auth
params:
'grant_type': 'client_credentials'
).content)
token['timestamp'] = new Date().getTime()
# we insert the new valid token to retrieve it later
PaypalTokens.insert token
return token
'createPaypalPayment': (product) ->
token = Meteor.call 'getPaypalToken'
payment =
intent: 'sale'
payer:
payment_method: 'paypal'
redirect_urls:
return_url: 'http://localhost:3000/dashboard/payment/paypal/execute'
cancel_url: 'http://localhost:3000/dashboard'
transactions: [
item_list:
'items': [
'name': product.name,
'price': product.price,
'currency': 'USD',
'quantity': 1
]
amount:
total: product.price
currency: 'USD'
description: product.description
]
res = Meteor.http.post 'https://api.sandbox.paypal.com/v1/payments/payment',
headers:
Authorization: 'Bearer ' + token.access_token
'Content-Type': 'application/json'
data: payment
res.data['userId'] = @userId
# we insert the payment details (for the payment id during execution)
PaypalPayments.insert res.data
return res.data
'executePaypalPayment': (payerId) ->
payment = PaypalPayments.findOne({ userId: @userId },
{ sort: { 'create_time': -1 } })
token = Meteor.call 'getPaypalToken'
url = 'https://api.sandbox.paypal.com/v1/payments/payment/' +
payment.id + '/execute'
res = Meteor.http.post url,
headers:
Authorization: 'Bearer ' + token.access_token
'Content-Type': 'application/json'
data:
payer_id: payerId
payment = res.data
payment['userId'] = @userId
if payment.state in ['approved' , 'pending'] # Be careful, in production the payment state is "pending"
# we insert the sucessful payment here
PaypalPayments.insert payment
return if payment.state is 'approved' then true else false
# The following code must be accessible to the client.
# 4. We configure Iron Router to handle the different payment steps.
# For more informations: https://github.com/EventedMind/iron-router
Router.map ->
@route 'DashboardRoot',
path: '/dashboard/'
@route 'DashboardPaymentPaypalExecute',
path: '/dashboard/payment/paypal/execute/'
# 5. Templates Events.
Template.DashboardRoot.events
'click .buy-product': ->
product =
name: 'product name'
description: 'production description'
price: 30.00
Meteor.call 'createPaypalPayment', product, (err, res) ->
window.location.replace res.links[1].href
Template.DashboardPaymentPaypalExecute.created = ->
payerId = window.location.search.split('PayerID=')[1]
Meteor.call 'executePaypalPayment', payerId, (err, res) ->
if res is true
console.log 'Your payment has been successfully executed.'
else
console.log 'Your payment has been refused.'
Router.go 'DashboardRoot'
<!-- 6. The Dashboard Template -->
<template name="DashboardRoot">
<span class="buy-product">Buy this product</span>
</template>
<!-- 7. The Dashboard Payment Paypal Execute Template -->
<template name="DashboardPaymentPaypalExecute">
<span class="loading">Wait a few seconds, we are processing your payment.</span>
</template>
@odesey
Copy link

odesey commented May 15, 2014

Great gist!
I am attempting to test it out with an app I am developing and cant seem to get it to work however. The first thing I did was convert the code from coffee script to javascript at http://js2coffee.org/ . I then created all the necessary files on the client and server. However when I click the "buy this product" link I get the following errors;
client:
Exception in delivering result of invoking 'createPaypalPayment': TypeError: Cannot read property 'links' of undefined
at http://localhost:3000/client/views/paypal/DashboardRoot.js?c9ac527f12033c2ff0d64317caed7e262304d1b0:10:41
(this is the line in question) -> return window.location.replace(res.links[1].href);

server:
Exception while invoking method 'createPaypalPayment' TypeError: Cannot call method 'post' of undefined
at Meteor.methods.getPaypalToken (app/server/paypal_config.js:30:39)
(this is the line in question) -> token = EJSON.parse(Meteor.http.post('https://api.sandbox.paypal.com/v1/oauth2/token', { ...

Any idea what might be causing this?

Thanks.

_edit_*
Found the issue, I needed to include the http package in my project
mrt add http resolved the problem.

@hellygeorge
Copy link

Meteor is a full-stack framework for building top-quality web apps in a fraction of the time, whether you're an expert developer or just getting started. Paypal API is a Payment Gateway API for payments in your application. It can be used to accept payments from your app or website. Learn how to accept payments from your app using our REST API. In this article, we will learn how to use this API with Meteor. We will create two example apps, one for doing payments and the other for logging in.

Follow these instructions:
https://mmcgbl.com/api-development/

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment