This repository has been archived by the owner on May 12, 2020. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 454
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge in stable release branch
- Loading branch information
Showing
91 changed files
with
2,789 additions
and
1,222 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,120 @@ | ||
/* Copyright 2014 PayPal */ | ||
"use strict"; | ||
|
||
var client = require('./client'); | ||
var utils = require('./utils'); | ||
var configuration = require('./configure'); | ||
|
||
/* Merge user provided configurations otherwise use default settings */ | ||
var configure = exports.configure = function configure(options) { | ||
if (options !== undefined && typeof options === 'object') { | ||
configuration.default_options = utils.merge(configuration.default_options, options); | ||
} | ||
}; | ||
|
||
/** | ||
* Generate new access token by making a POST request to /oauth2/token by | ||
* exchanging base64 encoded client id/secret pair or valid refresh token. | ||
* | ||
* Otherwise authorization code from a mobile device can be exchanged for a long | ||
* living refresh token used to charge user who has consented to future payments. | ||
*/ | ||
var generateToken = exports.generateToken = function generateToken(config, cb) { | ||
|
||
if (typeof config === "function") { | ||
cb = config; | ||
config = configuration.default_options; | ||
} else if (!config) { | ||
config = configuration.default_options; | ||
} else { | ||
config = utils.copyMissing(config, configuration.default_options); | ||
} | ||
|
||
var payload = 'grant_type=client_credentials'; | ||
if (config.authorization_code) { | ||
payload = 'grant_type=authorization_code&response_type=token&redirect_uri=urn:ietf:wg:oauth:2.0:oob&code=' + config.authorization_code; | ||
} else if (config.refresh_token) { | ||
payload = 'grant_type=refresh_token&refresh_token=' + config.refresh_token; | ||
} | ||
|
||
var basicAuthString = 'Basic ' + new Buffer(config.client_id + ':' + config.client_secret).toString('base64'); | ||
|
||
var http_options = { | ||
schema: config.schema || configuration.default_options.schema, | ||
host: utils.getDefaultApiEndpoint(config.mode) || config.host || configuration.default_options.host, | ||
port: config.port || configuration.default_options.port, | ||
headers: { | ||
'Authorization': basicAuthString, | ||
'Accept': 'application/json', | ||
'Content-Type': 'application/x-www-form-urlencoded' | ||
} | ||
}; | ||
|
||
client.invoke('POST', '/v1/oauth2/token', payload, http_options, function (err, res) { | ||
var token = null; | ||
if (res) { | ||
if (!config.authorization_code) { | ||
token = res.token_type + ' ' + res.access_token; | ||
} | ||
else { | ||
token = res.refresh_token; | ||
} | ||
} | ||
cb(err, token); | ||
}); | ||
}; | ||
|
||
/* Update authorization header with new token obtained by calling | ||
generateToken */ | ||
function updateToken(http_options, error_callback, callback) { | ||
generateToken(http_options, function (error, token) { | ||
if (error) { | ||
error_callback(error, token); | ||
} else { | ||
http_options.headers.Authorization = token; | ||
callback(); | ||
} | ||
}); | ||
} | ||
|
||
/** | ||
* Make a PayPal REST API call, most REST functions wrap this function. | ||
* Handles error and token expiration cases | ||
*/ | ||
var executeHttp = exports.executeHttp = function executeHttp(http_method, path, data, http_options, cb) { | ||
if (typeof http_options === "function") { | ||
cb = http_options; | ||
http_options = null; | ||
} | ||
if (!http_options) { | ||
http_options = configuration.default_options; | ||
} else { | ||
http_options = utils.copyMissing(http_options, configuration.default_options); | ||
} | ||
|
||
//Get host endpoint using mode | ||
http_options.host = utils.getDefaultApiEndpoint(http_options.mode) || http_options.host; | ||
|
||
function retryInvoke() { | ||
client.invoke(http_method, path, data, http_options, cb); | ||
} | ||
|
||
if (http_options.correlation_id) { | ||
http_options.headers['Paypal-Application-Correlation-Id'] = http_options.correlation_id; | ||
} | ||
|
||
// Don't reprompt already authenticated user for login by updating Authorization header | ||
// if token expires | ||
if (http_options.headers.Authorization) { | ||
client.invoke(http_method, path, data, http_options, function (error, response) { | ||
if (error && error.httpStatusCode === 401 && http_options.client_id && http_options.headers.Authorization) { | ||
http_options.headers.Authorization = null; | ||
updateToken(http_options, cb, retryInvoke); | ||
} else { | ||
cb(error, response); | ||
} | ||
}); | ||
} else { | ||
updateToken(http_options, cb, retryInvoke); | ||
} | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,122 @@ | ||
/* Copyright 2014 PayPal */ | ||
"use strict"; | ||
|
||
var http = require('http'); | ||
var https = require('https'); | ||
var querystring = require('querystring'); | ||
var uuid = require('node-uuid'); | ||
var configuration = require('./configure'); | ||
|
||
/* Wraps the http client, handles request parameters, populates request headers, handles response */ | ||
var invoke = exports.invoke = function invoke(http_method, path, data, http_options_param, cb) { | ||
var client = (http_options_param.schema === 'http') ? http : https; | ||
|
||
var request_data = data; | ||
|
||
if (http_method === 'GET') { | ||
//format object parameters into GET request query string | ||
if (typeof request_data !== 'string') { | ||
request_data = querystring.stringify(request_data); | ||
} | ||
if (request_data) { | ||
path = path + "?" + request_data; | ||
request_data = ""; | ||
} | ||
} else if (typeof request_data !== 'string') { | ||
request_data = JSON.stringify(request_data); | ||
} | ||
|
||
var http_options = {}; | ||
|
||
if (http_options_param) { | ||
|
||
http_options = JSON.parse(JSON.stringify(http_options_param)); | ||
|
||
if (!http_options.headers) { | ||
http_options.headers = {}; | ||
} | ||
http_options.path = path; | ||
http_options.method = http_method; | ||
if (request_data) { | ||
http_options.headers['Content-Length'] = Buffer.byteLength(request_data, 'utf-8'); | ||
} | ||
|
||
if (!http_options.headers.Accept) { | ||
http_options.headers.Accept = 'application/json'; | ||
} | ||
|
||
if (!http_options.headers['Content-Type']) { | ||
http_options.headers['Content-Type'] = 'application/json'; | ||
} | ||
|
||
if (http_method === 'POST' && !http_options.headers['PayPal-Request-Id']) { | ||
http_options.headers['PayPal-Request-Id'] = uuid.v4(); | ||
} | ||
|
||
http_options.headers['User-Agent'] = configuration.userAgent; | ||
} | ||
|
||
var req = client.request(http_options); | ||
|
||
req.on('error', function (e) { | ||
console.log('problem with request: ' + e.message); | ||
cb(e, null); | ||
}); | ||
|
||
req.on('response', function (res) { | ||
var response = ''; | ||
res.setEncoding('utf8'); | ||
|
||
res.on('data', function (chunk) { | ||
response += chunk; | ||
}); | ||
|
||
res.on('end', function () { | ||
var err = null; | ||
|
||
try { | ||
//Set response to be parsed JSON object if data received is json | ||
//expect that content-type header has application/json when it | ||
//returns data | ||
if (res.headers['content-type'] === "application/json") { | ||
response = JSON.parse(response); | ||
} | ||
//Set response to an empty object if no data was received | ||
if (response === '') { | ||
response = {}; | ||
} | ||
response.httpStatusCode = res.statusCode; | ||
|
||
//TURN NODE_ENV to development to get access to paypal-debug-id | ||
//for questions to merchant technical services. Similar convention | ||
//to express.js | ||
if (res.headers['paypal-debug-id'] !== undefined && process.env.NODE_ENV === 'development') { | ||
console.log(res.headers['paypal-debug-id']); | ||
} | ||
} catch (e) { | ||
err = new Error('Invalid JSON Response Received'); | ||
err.error = { | ||
name: 'Invalid JSON Response Received, JSON Parse Error' | ||
}; | ||
// response contains the full json description of the error | ||
// that PayPal returns and information link | ||
err.response = response; | ||
err.httpStatusCode = res.statusCode; | ||
response = null; | ||
} | ||
|
||
if (!err && (res.statusCode < 200 || res.statusCode >= 300)) { | ||
err = new Error('Response Status : ' + res.statusCode); | ||
err.response = response; | ||
err.httpStatusCode = res.statusCode; | ||
response = null; | ||
} | ||
cb(err, response); | ||
}); | ||
}); | ||
|
||
if (request_data) { | ||
req.write(request_data); | ||
} | ||
req.end(); | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
/* Copyright 2014 PayPal */ | ||
"use strict"; | ||
|
||
var sdkVersion = exports.sdkVersion = '0.10.0'; | ||
var userAgent = exports.userAgent = 'PayPalSDK/rest-sdk-nodejs ' + sdkVersion + ' (node ' + process.version + '-' + process.arch + '-' + process.platform + ')'; | ||
|
||
var default_options = exports.default_options = { | ||
'mode': 'sandbox', | ||
'schema': 'https', | ||
'host': 'api.sandbox.paypal.com', | ||
'port': '', | ||
'openid_connect_schema': 'https', | ||
'openid_connect_host': 'api.sandbox.paypal.com', | ||
'openid_connect_port': '', | ||
'authorize_url': 'https://www.sandbox.paypal.com/webapps/auth/protocol/openidconnect/v1/authorize', | ||
'logout_url': 'https://www.sandbox.paypal.com/webapps/auth/protocol/openidconnect/v1/endsession', | ||
'headers': {} | ||
}; |
Oops, something went wrong.