From 74e333576cd1550089c455de0b727753a4b58287 Mon Sep 17 00:00:00 2001 From: Nick Downing Date: Sun, 19 Dec 2021 13:16:07 +1100 Subject: [PATCH] Initial commit, port PayPalCheckoutServerSideV2_nodejs.zip to jst_server --- .gitignore | 9 + _config/config.json | 7 + _config/server.jst | 16 + _config/site.jst | 26 ++ _library/basic_functions.js | 176 ++++++++ _library/random_number.js | 1 + _orig/PayPalCheckoutServerSideV2_nodejs.zip | Bin 0 -> 49713 bytes _ssl/ca.conf | 25 ++ _ssl/ca_cert.pem | 21 + _ssl/ca_cert.srl | 1 + _ssl/ca_key.pem | 27 ++ _ssl/localhost.conf | 66 +++ _ssl/localhost_cert.pem | 21 + _ssl/localhost_cert_bundle.pem | 42 ++ _ssl/localhost_csr.pem | 19 + _ssl/localhost_ext.conf | 13 + _ssl/localhost_key.pem | 27 ++ _ssl/n.sh | 30 ++ api/captureOrder.json.jst | 15 + api/createOrder.json.jst | 117 ++++++ api/getOrderDetails.json.jst | 15 + api/patchOrder.json.jst | 73 ++++ img/camera.jpg | Bin 0 -> 23438 bytes index.html | 263 ++++++++++++ js/config.js | 258 ++++++++++++ package.json | 16 + pages/shipping.html | 435 ++++++++++++++++++++ pages/success.html | 255 ++++++++++++ 28 files changed, 1974 insertions(+) create mode 100644 .gitignore create mode 100644 _config/config.json create mode 100644 _config/server.jst create mode 100644 _config/site.jst create mode 100644 _library/basic_functions.js create mode 100644 _library/random_number.js create mode 100644 _orig/PayPalCheckoutServerSideV2_nodejs.zip create mode 100644 _ssl/ca.conf create mode 100644 _ssl/ca_cert.pem create mode 100644 _ssl/ca_cert.srl create mode 100644 _ssl/ca_key.pem create mode 100644 _ssl/localhost.conf create mode 100644 _ssl/localhost_cert.pem create mode 100644 _ssl/localhost_cert_bundle.pem create mode 100644 _ssl/localhost_csr.pem create mode 100644 _ssl/localhost_ext.conf create mode 100644 _ssl/localhost_key.pem create mode 100755 _ssl/n.sh create mode 100644 api/captureOrder.json.jst create mode 100644 api/createOrder.json.jst create mode 100644 api/getOrderDetails.json.jst create mode 100644 api/patchOrder.json.jst create mode 100644 img/camera.jpg create mode 100644 index.html create mode 100644 js/config.js create mode 100644 package.json create mode 100644 pages/shipping.html create mode 100644 pages/success.html diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..e0ecbc3 --- /dev/null +++ b/.gitignore @@ -0,0 +1,9 @@ +.*.deps +.*.html +.*.json +.*.jst +.*.less +.*.min +.*.svg +/node_modules +/pnpm-lock.yaml diff --git a/_config/config.json b/_config/config.json new file mode 100644 index 0000000..4d54786 --- /dev/null +++ b/_config/config.json @@ -0,0 +1,7 @@ +{ + "environment": "sandbox", + "sandbox_client_id": "Aa2IfcoEvHnfJRnVQLSFrSs3SmTTkv5N1weMEL66ysqYIeHfAqXpDVkjOv3vLhkhbP4eKB6MpRlQIcJw", + "sandbox_secret": "EF6l6PDQJEZbdKTeg35pbBSft6WRdALQC3Xrl5vvG0VNgBUehQyTCQ09QdIauxoccvJOf5Aoy-OGsH5G", + "production_client_id": "", + "production_secret": "" +} \ No newline at end of file diff --git a/_config/server.jst b/_config/server.jst new file mode 100644 index 0000000..e6ebffc --- /dev/null +++ b/_config/server.jst @@ -0,0 +1,16 @@ +return async (resources, prev_server) => new _jst_server.Server( + resources, + { + hosts: { + 'localhost': { + type: 'site', + root: '.' + }, + 'localhost.localdomain': { + type: 'redirect', + host: 'localhost' + } + } + }, + prev_server +) diff --git a/_config/site.jst b/_config/site.jst new file mode 100644 index 0000000..dd80b4d --- /dev/null +++ b/_config/site.jst @@ -0,0 +1,26 @@ +let CustomSite = function(resources, root, options, prev_site) { + if (!this instanceof CustomSite) + throw Error('CustomSite is a constructor') + _jst_server.Site.call(this, resources, root, options, prev_site) +} + +CustomSite.prototype = Object.create(_jst_server.Site.prototype) + +CustomSite.prototype.respond = async function(env) { + if ( + env.parsed_url.pathname === '/node_modules' || + env.parsed_url.pathname.slice(0, 14) === '/node_modules/' || + env.parsed_url.pathname === '/package.json' + ) { + this.die(env, `banned file ${env.parsed_url.pathname}`) + return + } + return /*await*/ _jst_server.Site.prototype.respond.call(this, env) +} + +return async (resources, root, prev_site) => new CustomSite( + resources, + root, + {}, + prev_site +) diff --git a/_library/basic_functions.js b/_library/basic_functions.js new file mode 100644 index 0000000..b6ac0a9 --- /dev/null +++ b/_library/basic_functions.js @@ -0,0 +1,176 @@ +const https = require('https'); +const config = require('../_config/config.json'); +const get_oauth = () => { + return new Promise(resolve => { + + const data = 'grant_type=client_credentials'; + + const options = { + hostname: 'api.' + (config.environment === 'sandbox' ? 'sandbox.' : '') + 'paypal.com', + port: 443, + path: '/v1/oauth2/token', + method: 'POST', + headers: { + 'Content-Type': 'application/x-www-form-urlencoded', + 'Content-Length': data.length, + 'Authorization': 'Basic ' + Buffer.from((config.environment === 'sandbox' ? config.sandbox_client_id : config.production_client_id) + ':' + (config.environment === 'sandbox' ? config.sandbox_secret : config.production_secret)).toString('base64') + } + } + const my_callback = function(res){ + + let str=''; + + res.on('data',function(chunk){ + str+=chunk; + }); + + res.on('end',function(){ + obj=JSON.parse(str); + resolve(obj); + }); + } + let request = https.request(options, my_callback); + request.write(data); + request.end(); + + }); +}; +const get_access_token = () => { + return new Promise(resolve => { + get_oauth().then((response) => { + resolve(response.access_token); + }); + }); +}; +const create_order = (item_obj) => { + return new Promise(resolve => { + get_access_token().then((access_token) => { + + const options = { + hostname: 'api.' + (config.environment === 'sandbox' ? 'sandbox.' : '') + 'paypal.com', + port: 443, + path: '/v2/checkout/orders', + method: 'POST', + headers: { + 'Content-Type': 'application/json', + 'Authorization': 'Bearer ' + access_token + } + } + const my_callback = function(res){ + + let str=''; + + res.on('data',function(chunk){ + str+=chunk; + }); + + res.on('end',function(){ + obj=JSON.parse(str); + resolve(obj); + }); + } + let request = https.request(options,my_callback); + request.write(JSON.stringify(item_obj)); + request.end(); + + }); + + }); +}; +const get_order_details = (order_id) => { + return new Promise(resolve => { + get_access_token().then((access_token) => { + + const options = { + hostname: 'api.' + (config.environment === 'sandbox' ? 'sandbox.' : '') + 'paypal.com', + port: 443, + path: '/v2/checkout/orders/' + order_id, + method: 'GET', + headers: { + 'Content-Type': 'application/json', + 'Authorization': 'Bearer ' + access_token + } + } + const my_callback = function(res){ + + let str=''; + + res.on('data',function(chunk){ + str+=chunk; + }); + + res.on('end',function(){ + obj=JSON.parse(str); + resolve(obj); + }); + } + let request = https.request(options,my_callback); + request.end(); + + }); + + }); +}; +const patch_order_details = (new_order_details) => { + return new Promise((resolve, reject) => { + get_access_token().then((access_token) => { + patch_details = new_order_details.patch_details; + order_id = new_order_details.order_id; + const options = { + hostname: 'api.' + (config.environment === 'sandbox' ? 'sandbox.' : '') + 'paypal.com', + port: 443, + path: '/v2/checkout/orders/' + order_id, + method: 'PATCH', + headers: { + 'Content-Type': 'application/json', + 'Authorization': 'Bearer ' + access_token + } + } + let request = https.request(options, function (response) { + resolve(response.statusCode); + }); + request.write(JSON.stringify(patch_details)); + request.end(); + }); +}); + +}; +const capture_order = (order_id) => { + return new Promise(resolve => { + get_access_token().then((access_token) => { + const options = { + hostname: 'api.' + (config.environment === 'sandbox' ? 'sandbox.' : '') + 'paypal.com', + port: 443, + path: '/v2/checkout/orders/' + order_id + '/capture', + method: 'POST', + headers: { + 'Content-Type': 'application/json', + 'Authorization': 'Bearer ' + access_token, + 'return': 'representation', + 'PayPal-Partner-Attribution-Id': 'PP-DemoPortal-Checkout-NodeJS-SDK' + } + } + const my_callback = function(res){ + let str=''; + res.on('data',function(chunk){ + str+=chunk; + }); + res.on('end',function(){ + obj=JSON.parse(str); + resolve(obj); + }); + } + let request = https.request(options,my_callback); + request.end(); + }); + }); +}; + +module.exports = { + get_access_token: get_access_token, + get_oauth: get_oauth, + create_order: create_order, + get_order_details: get_order_details, + patch_order_details: patch_order_details, + capture_order: capture_order +}; diff --git a/_library/random_number.js b/_library/random_number.js new file mode 100644 index 0000000..a446935 --- /dev/null +++ b/_library/random_number.js @@ -0,0 +1 @@ +module.exports = () => Math.floor(100000 + Math.random() * 900000) diff --git a/_orig/PayPalCheckoutServerSideV2_nodejs.zip b/_orig/PayPalCheckoutServerSideV2_nodejs.zip new file mode 100644 index 0000000000000000000000000000000000000000..5e2c706c9f1539e08ae10cce5563e56323d2e13f GIT binary patch literal 49713 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 literal 0 HcmV?d00001 diff --git a/_ssl/ca.conf b/_ssl/ca.conf new file mode 100644 index 0000000..d0d9a5f --- /dev/null +++ b/_ssl/ca.conf @@ -0,0 +1,25 @@ +[ ca ] +default_ca = CA_default # The default ca section + +[ CA_default ] + +#dir = ./demoCA # top dir +#database = $dir/index.txt # index file. +#new_certs_dir = $dir/newcerts # new certs dir +# +#certificate = $dir/cacert.pem # The CA cert +#serial = $dir/serial # serial no file +#private_key = $dir/private/cakey.pem# CA private key +#RANDFILE = $dir/private/.rand # random number file +# +default_days = 365 # how long to certify for +#default_crl_days= 30 # how long before next CRL +#default_md = md5 # md to use +# +#policy = policy_any # default policy +#email_in_dn = no # Don't add the email into cert DN +# +#name_opt = ca_default # Subject name display option +#cert_opt = ca_default # Certificate display option +#copy_extensions = none +copy_extensions = copyall diff --git a/_ssl/ca_cert.pem b/_ssl/ca_cert.pem new file mode 100644 index 0000000..74cb479 --- /dev/null +++ b/_ssl/ca_cert.pem @@ -0,0 +1,21 @@ +-----BEGIN CERTIFICATE----- +MIIDazCCAlOgAwIBAgIUFREyB8FfpEHUio8HY7b0d7FaKdcwDQYJKoZIhvcNAQEL +BQAwRTELMAkGA1UEBhMCQVUxEzARBgNVBAgMClNvbWUtU3RhdGUxITAfBgNVBAoM +GEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDAeFw0yMTExMDgwNzU0MTNaFw0yMTEy +MDgwNzU0MTNaMEUxCzAJBgNVBAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEw +HwYDVQQKDBhJbnRlcm5ldCBXaWRnaXRzIFB0eSBMdGQwggEiMA0GCSqGSIb3DQEB +AQUAA4IBDwAwggEKAoIBAQDLY+eBF29tRNWwNb4uDdWUAs+7jDybeos94E8tgPKO +JEc2flBwolka9GU357x9J5v2KCnOuCkKArhL2tmkms5f2F4Eezb/l9DnryUdckqC +MI2bwAz/a/T+3HLjqI4l5mawE21JXNggqAccixRUY/gK3+V7M+zOdpwRc4v7Ca0R +sBwwfve8Ws8xqKryVFvzJM0QXiAjZvxMpLygdbnmjCKKVCY00Mfh20KqHYBMIMHa +M0RhdRrvi8/2oPfRcMByjZdjn8BQ+yUwQXbzP2MC+iq87lLuxUxEYGaQU4nzIMH1 +7Ga05t6zhF41jqDnrbjKgbgxPGNNxvau/rrpCnr++NQ/AgMBAAGjUzBRMB0GA1Ud +DgQWBBRBtnDR6bDQjBctACDXe2FTsASBEzAfBgNVHSMEGDAWgBRBtnDR6bDQjBct +ACDXe2FTsASBEzAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBCwUAA4IBAQCM +H2UzfYIphO/16z8SO0thdjexjfad0bMIZC39kD92ILHvxk68D0uel4q5Rp3+F66j +J7OupHIzEGSB23suw6n/cDrIJOa5VU9geaUZBVIH8GSy6nQTnkukiX92OTS11ecW +qABoACcptQz4oC3E68K6BYre4/QamJDAqdP4aNVbka040XTiWzvfRlOVeWz+gZTa +zObQiEzj1SwsYgcNSkrquZ/7vcEBaCncxXD8oRxqfEgNA6BRqUqnKCUSUmk/ed3b +hRSpHURjJGntHAzzFzaCC5dfMBEnAszfoOdLua/BV/JZcB7t4YIcIYMKdSYxpvoO +Nr3opPQhzBXur01KZuUA +-----END CERTIFICATE----- diff --git a/_ssl/ca_cert.srl b/_ssl/ca_cert.srl new file mode 100644 index 0000000..b882cea --- /dev/null +++ b/_ssl/ca_cert.srl @@ -0,0 +1 @@ +D29D1C6A226490AD diff --git a/_ssl/ca_key.pem b/_ssl/ca_key.pem new file mode 100644 index 0000000..e65d8ce --- /dev/null +++ b/_ssl/ca_key.pem @@ -0,0 +1,27 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIEowIBAAKCAQEAy2PngRdvbUTVsDW+Lg3VlALPu4w8m3qLPeBPLYDyjiRHNn5Q +cKJZGvRlN+e8fSeb9igpzrgpCgK4S9rZpJrOX9heBHs2/5fQ568lHXJKgjCNm8AM +/2v0/txy46iOJeZmsBNtSVzYIKgHHIsUVGP4Ct/lezPsznacEXOL+wmtEbAcMH73 +vFrPMaiq8lRb8yTNEF4gI2b8TKS8oHW55owiilQmNNDH4dtCqh2ATCDB2jNEYXUa +74vP9qD30XDAco2XY5/AUPslMEF28z9jAvoqvO5S7sVMRGBmkFOJ8yDB9exmtObe +s4ReNY6g5624yoG4MTxjTcb2rv666Qp6/vjUPwIDAQABAoIBAA3vOEsl2eJ4ltNN +u0vYcsuDLcxBnV1hleyVU5dggD2wypg3KzesR8KK/+xGmilQ72R79/FLuLQQ36OC +yOp4GK+EWVyhPHFia1OUMkzEKcqlnO4QyFMviEd1vwFN6P87u8lQa2pdTAlguawA +81Gcz7+e+0/njM/QXHztl6eJUCwn7zEbG8+we0g8GkLILOBA3Tuy5Vu+ox1LQZQp +WPqIMhm0GXPOVRKBr0mPVWtJvyAYvTX13GqNM1YFbElkbnkbsTaJhg/L3J9UJNsm +BbOg0oUdq1yWoy7cjOXiq3aG9rNws9PBXbbDB/G67aae/1SJ7eBTV/kCEuYh0YDx +MSn5xYECgYEA/uZueW4dFTKMBebNFvJreQei1ecaGwEFckUYD5u02VugtYc9inQ2 +sK7ENq/CsA10WKBxV84lIdiG5yXjG1RwCLvTV6YBP5uL9dVMln25x6ZDUxOlYzuZ +OZUcabR3Y3Ar349vDV+vFle47J0YW8H89O5YlVxvLfZ+CFFFSBSMRCECgYEAzESS +5IvNH1RUCR0tqRkHA0SXMiNxF85lFbUrbS2yMI60LCaTE2q/uK5008f5laD3LYKU +Gq7SVP1U4z0+g9jGa0rvYd1h3o6fJMrFBiBN1ZRRzMFaiQxxNbyjCV7LR86m6aSo +pz4f7k8EmzrsmZw7MF/l9Dy3AWHpg1cwYdR6DF8CgYB17kS0d6aK9Rzlahf/At+I +WmkTD937Gmjbqm3sYry0R3k+IzjswsG+0szDBGRNsZvfmTN3TU/OrfAUJ2pAbbt7 +vvKTvaEcPanubeYGRlrarOi/GfrNw3grtPo1SaJm5jHWN/VIObm225UaG8B2S3Tu +GQvw5pglqsI6tOcZ5y/SIQKBgBVJuD1VTIVNVoy0m8OZth9jEJbLFsgyXFqMzP/N +2VoyJRjM1FsbrutiUw6XMq2jXt9BUooNWiI9XJFqGo/HEbaw0o3ScpatKmy9LRdc +WoA9uuCp7fOGdm3xQNSDKpBLOx3yaRk04kMFvScoVuwTWh/Kfr6bbT8Zoypq9cHc +UPPlAoGBAIEtVPhH6R51/HREPMWXWgwZujkeD0VQX+hNP8VOgSlts9L4bDn7res5 +DXHDXU3Q+vY+86qDvJgJaOdmt7IoNXgRlU9tUZP4MD8YG32Xjn3dnB5e/3SmBJwD +NV4mVx+7X6me5rb4NdpMcSzulVXy3SfnQTaDsNghpcTqOXLFI0ti +-----END RSA PRIVATE KEY----- diff --git a/_ssl/localhost.conf b/_ssl/localhost.conf new file mode 100644 index 0000000..fa3ef54 --- /dev/null +++ b/_ssl/localhost.conf @@ -0,0 +1,66 @@ +# The main section is named req because the command we are using is req +# (openssl req ...) +[ req ] +## This specifies the default key size in bits. If not specified then 512 is +## used. It is used if the -new option is used. It can be overridden by using +## the -newkey option. +#default_bits = 2048 +# +## This is the default filename to write a private key to. If not specified the +## key is written to standard output. This can be overridden by the -keyout +## option. +#default_keyfile = oats.key +# +## If this is set to no then if a private key is generated it is not encrypted. +## This is equivalent to the -nodes command line option. For compatibility +## encrypt_rsa_key is an equivalent option. +#encrypt_key = no + +# This option specifies the digest algorithm to use. Possible values include +# md5 sha1 mdc2. If not present then MD5 is used. This option can be overridden +# on the command line. +default_md = sha1 + +# if set to the value no this disables prompting of certificate fields and just +# takes values from the config file directly. It also changes the expected +# format of the distinguished_name and attributes sections. +prompt = no + +# if set to the value yes then field values to be interpreted as UTF8 strings, +# by default they are interpreted as ASCII. This means that the field values, +# whether prompted from a terminal or obtained from a configuration file, must +# be valid UTF8 strings. +utf8 = yes + +# This specifies the section containing the distinguished name fields to +# prompt for when generating a certificate or certificate request. +distinguished_name = my_req_distinguished_name + +# this specifies the configuration file section containing a list of extensions +# to add to the certificate request. It can be overridden by the -reqexts +# command line switch. See the x509v3_config(5) manual page for details of the +# extension section format. +req_extensions = my_extensions + +[ my_req_distinguished_name ] +C = PT +ST = Lisboa +L = Lisboa +O = Oats In The Water +#CN = *.oats.org +CN = localhost + +[ my_extensions ] +basicConstraints=CA:FALSE +subjectAltName=@my_subject_alt_names +subjectKeyIdentifier = hash + +[ my_subject_alt_names ] +#DNS.1 = *.oats.org +#DNS.2 = *.oats.net +#DNS.3 = *.oats.in +#DNS.4 = oats.org +#DNS.5 = oats.net +#DNS.6 = oats.in +DNS.1 = localhost +DNS.2 = localhost.localdomain diff --git a/_ssl/localhost_cert.pem b/_ssl/localhost_cert.pem new file mode 100644 index 0000000..13a969f --- /dev/null +++ b/_ssl/localhost_cert.pem @@ -0,0 +1,21 @@ +-----BEGIN CERTIFICATE----- +MIIDgDCCAmigAwIBAgIJANKdHGoiZJCtMA0GCSqGSIb3DQEBCwUAMEUxCzAJBgNV +BAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRlcm5ldCBX +aWRnaXRzIFB0eSBMdGQwHhcNMjExMTA4MDc1NDEzWhcNMjExMjA4MDc1NDEzWjBf +MQswCQYDVQQGEwJQVDEPMA0GA1UECAwGTGlzYm9hMQ8wDQYDVQQHDAZMaXNib2Ex +GjAYBgNVBAoMEU9hdHMgSW4gVGhlIFdhdGVyMRIwEAYDVQQDDAlsb2NhbGhvc3Qw +ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDDJLav5I1Dxx9Lzv7DyHig +ApIkm9U8tcRKuM3Q4q3xj8P2VmSHVHZ0FfjKs/NZ8hLi3go+EzGolmiRKPA7V9UQ +Zgm5MmC6tewiol76lsjehUKuG+DmT3n79xSHsj5PC6wkE/IkifcQIeGVJWgQbRR4 +JSGaX4tmmpxNrDDgpVnaXEO8I5KR/jvniAn2DoTKlY5XSIUXlbZQPHdlLdLUU7in +5M19b9qnIdJRxa4mcOWNtsUHU16SJZAmQBmg4vAhMc4XyJ23YE8cNxUxusKrhoUB +sWmvjGgbbaYgtwBmCFQNSFiJhyzgg6sdUot7wVXDkXBTJPQRQO82CJyw6YoDnTCL +AgMBAAGjWTBXMAkGA1UdEwQCMAAwKwYDVR0RBCQwIoIJbG9jYWxob3N0ghVsb2Nh +bGhvc3QubG9jYWxkb21haW4wHQYDVR0OBBYEFPKfGhTkosDI90l245Si/Ce/CLr/ +MA0GCSqGSIb3DQEBCwUAA4IBAQCMjFo4qbgRHefLMc5yc53qn9OVa693lR9RQb+n +HgVHUuhPRQfNr6WgbfiWjpK5r2RU7Tj7GsueNZlK+tdJxXIvo29yjrdFZ4uUfCMB +Rr9VrjdBhv5/MLuLLnNGuC4LxNaZaZZEPF5DtVh5FZajisgB4jYFOEJNvltWgBca +pR469W8qte2NYprjni1lzMlr0cQBMFt00jt5ZU8u7oeFt7/lzpiStA9W5FIv7DZV +FoEzq51uwGK6FvRhil8x9pr1GzSrZdLfsEELNRZNqLG8rRhcKAUsMER+lS6LtRdJ +ORQ3LnfodE2bCNO8MMx0A5ZA1CGlMOOE5twSlYLgS/hvkK6y +-----END CERTIFICATE----- diff --git a/_ssl/localhost_cert_bundle.pem b/_ssl/localhost_cert_bundle.pem new file mode 100644 index 0000000..a1ed9bc --- /dev/null +++ b/_ssl/localhost_cert_bundle.pem @@ -0,0 +1,42 @@ +-----BEGIN CERTIFICATE----- +MIIDgDCCAmigAwIBAgIJANKdHGoiZJCtMA0GCSqGSIb3DQEBCwUAMEUxCzAJBgNV +BAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRlcm5ldCBX +aWRnaXRzIFB0eSBMdGQwHhcNMjExMTA4MDc1NDEzWhcNMjExMjA4MDc1NDEzWjBf +MQswCQYDVQQGEwJQVDEPMA0GA1UECAwGTGlzYm9hMQ8wDQYDVQQHDAZMaXNib2Ex +GjAYBgNVBAoMEU9hdHMgSW4gVGhlIFdhdGVyMRIwEAYDVQQDDAlsb2NhbGhvc3Qw +ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDDJLav5I1Dxx9Lzv7DyHig +ApIkm9U8tcRKuM3Q4q3xj8P2VmSHVHZ0FfjKs/NZ8hLi3go+EzGolmiRKPA7V9UQ +Zgm5MmC6tewiol76lsjehUKuG+DmT3n79xSHsj5PC6wkE/IkifcQIeGVJWgQbRR4 +JSGaX4tmmpxNrDDgpVnaXEO8I5KR/jvniAn2DoTKlY5XSIUXlbZQPHdlLdLUU7in +5M19b9qnIdJRxa4mcOWNtsUHU16SJZAmQBmg4vAhMc4XyJ23YE8cNxUxusKrhoUB +sWmvjGgbbaYgtwBmCFQNSFiJhyzgg6sdUot7wVXDkXBTJPQRQO82CJyw6YoDnTCL +AgMBAAGjWTBXMAkGA1UdEwQCMAAwKwYDVR0RBCQwIoIJbG9jYWxob3N0ghVsb2Nh +bGhvc3QubG9jYWxkb21haW4wHQYDVR0OBBYEFPKfGhTkosDI90l245Si/Ce/CLr/ +MA0GCSqGSIb3DQEBCwUAA4IBAQCMjFo4qbgRHefLMc5yc53qn9OVa693lR9RQb+n +HgVHUuhPRQfNr6WgbfiWjpK5r2RU7Tj7GsueNZlK+tdJxXIvo29yjrdFZ4uUfCMB +Rr9VrjdBhv5/MLuLLnNGuC4LxNaZaZZEPF5DtVh5FZajisgB4jYFOEJNvltWgBca +pR469W8qte2NYprjni1lzMlr0cQBMFt00jt5ZU8u7oeFt7/lzpiStA9W5FIv7DZV +FoEzq51uwGK6FvRhil8x9pr1GzSrZdLfsEELNRZNqLG8rRhcKAUsMER+lS6LtRdJ +ORQ3LnfodE2bCNO8MMx0A5ZA1CGlMOOE5twSlYLgS/hvkK6y +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIDazCCAlOgAwIBAgIUFREyB8FfpEHUio8HY7b0d7FaKdcwDQYJKoZIhvcNAQEL +BQAwRTELMAkGA1UEBhMCQVUxEzARBgNVBAgMClNvbWUtU3RhdGUxITAfBgNVBAoM +GEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDAeFw0yMTExMDgwNzU0MTNaFw0yMTEy +MDgwNzU0MTNaMEUxCzAJBgNVBAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEw +HwYDVQQKDBhJbnRlcm5ldCBXaWRnaXRzIFB0eSBMdGQwggEiMA0GCSqGSIb3DQEB +AQUAA4IBDwAwggEKAoIBAQDLY+eBF29tRNWwNb4uDdWUAs+7jDybeos94E8tgPKO +JEc2flBwolka9GU357x9J5v2KCnOuCkKArhL2tmkms5f2F4Eezb/l9DnryUdckqC +MI2bwAz/a/T+3HLjqI4l5mawE21JXNggqAccixRUY/gK3+V7M+zOdpwRc4v7Ca0R +sBwwfve8Ws8xqKryVFvzJM0QXiAjZvxMpLygdbnmjCKKVCY00Mfh20KqHYBMIMHa +M0RhdRrvi8/2oPfRcMByjZdjn8BQ+yUwQXbzP2MC+iq87lLuxUxEYGaQU4nzIMH1 +7Ga05t6zhF41jqDnrbjKgbgxPGNNxvau/rrpCnr++NQ/AgMBAAGjUzBRMB0GA1Ud +DgQWBBRBtnDR6bDQjBctACDXe2FTsASBEzAfBgNVHSMEGDAWgBRBtnDR6bDQjBct +ACDXe2FTsASBEzAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBCwUAA4IBAQCM +H2UzfYIphO/16z8SO0thdjexjfad0bMIZC39kD92ILHvxk68D0uel4q5Rp3+F66j +J7OupHIzEGSB23suw6n/cDrIJOa5VU9geaUZBVIH8GSy6nQTnkukiX92OTS11ecW +qABoACcptQz4oC3E68K6BYre4/QamJDAqdP4aNVbka040XTiWzvfRlOVeWz+gZTa +zObQiEzj1SwsYgcNSkrquZ/7vcEBaCncxXD8oRxqfEgNA6BRqUqnKCUSUmk/ed3b +hRSpHURjJGntHAzzFzaCC5dfMBEnAszfoOdLua/BV/JZcB7t4YIcIYMKdSYxpvoO +Nr3opPQhzBXur01KZuUA +-----END CERTIFICATE----- diff --git a/_ssl/localhost_csr.pem b/_ssl/localhost_csr.pem new file mode 100644 index 0000000..b28c691 --- /dev/null +++ b/_ssl/localhost_csr.pem @@ -0,0 +1,19 @@ +-----BEGIN CERTIFICATE REQUEST----- +MIIDDDCCAfQCAQAwXzELMAkGA1UEBhMCUFQxDzANBgNVBAgMBkxpc2JvYTEPMA0G +A1UEBwwGTGlzYm9hMRowGAYDVQQKDBFPYXRzIEluIFRoZSBXYXRlcjESMBAGA1UE +AwwJbG9jYWxob3N0MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAwyS2 +r+SNQ8cfS87+w8h4oAKSJJvVPLXESrjN0OKt8Y/D9lZkh1R2dBX4yrPzWfIS4t4K +PhMxqJZokSjwO1fVEGYJuTJgurXsIqJe+pbI3oVCrhvg5k95+/cUh7I+TwusJBPy +JIn3ECHhlSVoEG0UeCUhml+LZpqcTaww4KVZ2lxDvCOSkf4754gJ9g6EypWOV0iF +F5W2UDx3ZS3S1FO4p+TNfW/apyHSUcWuJnDljbbFB1NekiWQJkAZoOLwITHOF8id +t2BPHDcVMbrCq4aFAbFpr4xoG22mILcAZghUDUhYiYcs4IOrHVKLe8FVw5FwUyT0 +EUDvNgicsOmKA50wiwIDAQABoGgwZgYJKoZIhvcNAQkOMVkwVzAJBgNVHRMEAjAA +MCsGA1UdEQQkMCKCCWxvY2FsaG9zdIIVbG9jYWxob3N0LmxvY2FsZG9tYWluMB0G +A1UdDgQWBBTynxoU5KLAyPdJduOUovwnvwi6/zANBgkqhkiG9w0BAQUFAAOCAQEA +L4XofNRjzahIDCj/pHVnsaXtioidv5Hp0vE+9LPhzZz/bH/e7s8lJnTalEkPNUxD +FPwiRar6MILQwn5N1b+kToSoiYDsCL77Y5WSlhcwe7gLwgDTlNwu2H030BZEr0ve +AEAems45TJk8o3kC5s3dt0KaGbRikub1HMTpFrlQUBLbO848t6qXcZCVjoAWYKlp +jaYn7r3bWVyZ2W2oIlQ19Tbxz+kG81Vxrg1FtAo7aBHTaOvEskgnEQ2Emc0mbLoe +YoT0Gg7Vrurl+T5gazmV1WMKszSjP8NKhTUcMESiRIUsmQczWiDBONiH9PGmGKHI +7aEBzQIK7m3goyS3I4q6nw== +-----END CERTIFICATE REQUEST----- diff --git a/_ssl/localhost_ext.conf b/_ssl/localhost_ext.conf new file mode 100644 index 0000000..d5005dc --- /dev/null +++ b/_ssl/localhost_ext.conf @@ -0,0 +1,13 @@ +basicConstraints=CA:FALSE +subjectAltName=@my_subject_alt_names +subjectKeyIdentifier = hash + +[ my_subject_alt_names ] +#DNS.1 = *.oats.org +#DNS.2 = *.oats.net +#DNS.3 = *.oats.in +#DNS.4 = oats.org +#DNS.5 = oats.net +#DNS.6 = oats.in +DNS.1 = localhost +DNS.2 = localhost.localdomain diff --git a/_ssl/localhost_key.pem b/_ssl/localhost_key.pem new file mode 100644 index 0000000..6c94353 --- /dev/null +++ b/_ssl/localhost_key.pem @@ -0,0 +1,27 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIEpAIBAAKCAQEAwyS2r+SNQ8cfS87+w8h4oAKSJJvVPLXESrjN0OKt8Y/D9lZk +h1R2dBX4yrPzWfIS4t4KPhMxqJZokSjwO1fVEGYJuTJgurXsIqJe+pbI3oVCrhvg +5k95+/cUh7I+TwusJBPyJIn3ECHhlSVoEG0UeCUhml+LZpqcTaww4KVZ2lxDvCOS +kf4754gJ9g6EypWOV0iFF5W2UDx3ZS3S1FO4p+TNfW/apyHSUcWuJnDljbbFB1Ne +kiWQJkAZoOLwITHOF8idt2BPHDcVMbrCq4aFAbFpr4xoG22mILcAZghUDUhYiYcs +4IOrHVKLe8FVw5FwUyT0EUDvNgicsOmKA50wiwIDAQABAoIBAEuOiImcJbIrhAuX +Lv9hPIs/05QHHk4uVr1TxqTtT8orDwXvN2dKpb6Wz0i02jFmUDe1HyQfzGdpLT2f +Kzze6ik6SOODBP7l93MFiV7fSREXadT+CFtERIfxh+pucj+q1lD1xBivrpB5fd2A +qUVK5tUKE3OxMMlebcyJMjeY7ixkRVgjROFeXs0t50xitzn/wPN0dVPZ6JFCPgRD +fc72E1K+DmfrzFZ2+rzqoVzAE7OSYQns3r2jNXlCEVw2jXsmnIRIi9wejbRthjbx +gA1IdenZcf4FkOMTTFuWGynT5tfF3cVzy5QtYemGZWSK4LNuWaTSzZCk3/sCxWk5 +Vbz/AdkCgYEA8gc2WEfbk5kVhU7UV5SRDRFtGuS8fmZ0RnqFdx6qy2EWYnwYXgzT +cZc6TiEuJ5getmEVsqzxFm3gWMyD0bEhY0jqoMVKMM70QQOQOZOB4lykXmpRDKny +/DU7/0bp7sBzFCKCWISCjGKWc98KWy24ZdKl8ZAr3zjDxE5UYvquKIcCgYEAzmie +r+1Y7DUtniogqpDLr6NnuvH52d1s4DEsHZQ6KRWE82d/X+2YU2R7/0QwfLBvcbT7 +OxlQP5rRoL6pX+ViZBmky0CSc/HYZZ+8uGwFc1X46zGfuvTSWaAStdIFPOX2O0JF +LLyF5/0/CK56agL3YxGREx2iQdauqTsOyr2LLN0CgYEAzYEgPN9u6ymd415m4KKO +c1krmh1Ei9M0wa9A6j9I6H3cgu05x4n+c8HjyPlVdlstINDYmqlL4C6VwvCMsR1E +60e7qZ07fKwNK7L54FmGfI0LJ/wAK8+WOV5+PiiZc5dHX35ZzQ1eyBLiCysEYR02 +KIcvTiiLh/NsDqAv+Qc/n7sCgYAup0z+3LnVoeturXz2sIWpbFi804ayrK64OcUL +5n4C3T9QuNr8drqQVs0EFIiVFlgKLmr+n6kYx0iMeavU5gcIMxehbTXtCQPtbF5+ +nMPantsFZhEBc+a7pUe1WwQeEKhIGqGCDBaEKiR+NNmsboE2HjlZRcBv+zM9QwED +6DW17QKBgQCRZfGUWasWXW6s9aZ1FgLPAXz/M9BLZjnx627KvbF4C+ZwfszntJxn +1A74mhHWJyKbt8YzfOTsTj40lp/npSpgjRQmUoqThx8d2cA41ALo0ktk6E9Zpp1j +phi0woa+TdEpqE2Jb8hJcyRKGCOVOKL/bnZL/QVgMebhg02n//wa9w== +-----END RSA PRIVATE KEY----- diff --git a/_ssl/n.sh b/_ssl/n.sh new file mode 100755 index 0000000..9fbf379 --- /dev/null +++ b/_ssl/n.sh @@ -0,0 +1,30 @@ +#!/bin/sh + +# see https://gist.github.com/Soarez/9688998 + +# note that the CSR contains X509 extensions, particularly the SAN which +# is mandatory for getting Google Chrome to accept the certificate, but +# unfortunately "openssl x509" will strip extensions -- this can be fixed +# by using the "openssl ca" command with "extensions = copyall" (or in +# the normal case filters would be specified on what extensions to copy), +# but the "openssl ca" command is very complicated and requires a directory +# structure to be set up, so we fake it with the "localhost_ext.conf" file + +# generate a key for the subject +#openssl genrsa -out localhost_key.pem 2048 + +# generate a CSR +openssl req -new -key localhost_key.pem -out localhost_csr.pem -config localhost.conf + +# generate a key for the CA +#openssl genrsa -out ca_key.pem 2048 + +# generate a self signed certificate for the CA +openssl req -new -x509 -key ca_key.pem -out ca_cert.pem + +# sign the certificate +#openssl x509 -req -in localhost_csr.pem -extfile localhost_ext.conf -CA ca_cert.pem -CAkey ca_key.pem -CAcreateserial -out localhost_cert.pem +openssl x509 -req -in localhost_csr.pem -extfile localhost_ext.conf -CA ca_cert.pem -CAkey ca_key.pem -CAserial ca_cert.srl -out localhost_cert.pem + +# resolve problems with not including the signing chain (can improve this?) +cat localhost_cert.pem ca_cert.pem > localhost_cert_bundle.pem diff --git a/api/captureOrder.json.jst b/api/captureOrder.json.jst new file mode 100644 index 0000000..3186882 --- /dev/null +++ b/api/captureOrder.json.jst @@ -0,0 +1,15 @@ +let basic_functions = require('../_library/basic_functions.js') +let cookie = require('cookie') + +return async env => { + let cookies = cookie.parse(env.request.headers.cookie || '') + let response = await basic_functions.capture_order(cookies.order_id) + console.log('capture_order()', response) + + env.site.serve( + env, + 200, + Buffer.from(JSON.stringify(response)), + 'getOrderDetails.json.jst' + ) +} diff --git a/api/createOrder.json.jst b/api/createOrder.json.jst new file mode 100644 index 0000000..4cdb0fb --- /dev/null +++ b/api/createOrder.json.jst @@ -0,0 +1,117 @@ +let basic_functions = require('../_library/basic_functions.js') +let querystring = require('querystring') +let random_number = require('../_library/random_number.js') +let stream_buffers = require('stream-buffers') +let XDate = require('xdate') + +return async env => { + let response = null; + if (env.request.method === 'POST') { + let write_stream = new stream_buffers.WritableStreamBuffer() + let data = new Promise( + (resolve, reject) => { + write_stream. + on('finish', () => {resolve(write_stream.getContents())}). + on('error', () => {reject()}) + } + ) + env.request.pipe(write_stream) + let query = querystring.parse((await data).toString()) + console.log('received createOrder form:', JSON.stringify(query)) + + //Build the PayPal object to create order and populate with POST params from website + let item_obj = { + "intent" : "CAPTURE", + "application_context" : { + "return_url" : query.return_url, + "cancel_url" : query.cancel_url + }, + "purchase_units" : [ + { + "reference_id" : "PU1", + "description" : "Camera Shop", + "invoice_id" : "INV-CameraShop-" + random_number(), + "custom_id" : "CUST-CameraShop", + "amount" : { + "currency_code" : query.currency, + "value" : query.total_amt, + "breakdown" : { + "item_total" : { + "currency_code" : query.currency, + "value" : query.item_amt + }, + "shipping" : { + "currency_code" : query.currency, + "value" : query.shipping_amt + }, + "tax_total" : { + "currency_code" : query.currency, + "value" : query.tax_amt + }, + "handling" : { + "currency_code" : query.currency, + "value" : query.handling_fee + }, + "shipping_discount" : { + "currency_code" : query.currency, + "value" : query.shipping_discount + }, + "insurance" : { + "currency_code" : query.currency, + "value" : query.insurance_fee + } + } + }, + "items" : [{ + "name" : "DSLR Camera", + "description" : "Black Camera - Digital SLR", + "sku" : "sku01", + "unit_amount" : { + "currency_code" : query.currency, + "value" : query.item_amt + }, + "quantity" : "1", + "category" : "PHYSICAL_GOODS" + }] + } + ] + }; + //If order details contain shipping, append shipping and preferences + if (query.line1 !== undefined) { + item_obj.application_context.shipping_preference = "SET_PROVIDED_ADDRESS"; + item_obj.application_context.user_action = "PAY_NOW"; + item_obj.purchase_units[0].shipping = { + "address" : { + "address_line_1": query.line1, + "address_line_2": query.line2, + "admin_area_2": query.city, + "admin_area_1": query.state, + "postal_code": query.zip, + "country_code": query.countrySelect + } + }; + } + console.log('item_obj', item_obj) + response = await basic_functions.create_order(item_obj) + console.log('create_order()', response) + + //sess.order_id = response.id; + let expires = new XDate() + expires.addDays(1) + env.response.setHeader( + 'Set-Cookie', + 'order_id=' + + response.id + + '; expires=' + + expires + + '; path=/;' + ) + } + + env.site.serve( + env, + 200, + Buffer.from(JSON.stringify(response)), + 'createOrder.json.jst' + ) +} diff --git a/api/getOrderDetails.json.jst b/api/getOrderDetails.json.jst new file mode 100644 index 0000000..b8cfaa9 --- /dev/null +++ b/api/getOrderDetails.json.jst @@ -0,0 +1,15 @@ +let basic_functions = require('../_library/basic_functions.js') +let cookie = require('cookie') + +return async env => { + let cookies = cookie.parse(env.request.headers.cookie || '') + let response = await basic_functions.get_order_details(cookies.order_id) + console.log('get_order_details()', response) + + env.site.serve( + env, + 200, + Buffer.from(JSON.stringify(response)), + 'getOrderDetails.json.jst' + ) +} diff --git a/api/patchOrder.json.jst b/api/patchOrder.json.jst new file mode 100644 index 0000000..0094534 --- /dev/null +++ b/api/patchOrder.json.jst @@ -0,0 +1,73 @@ +let basic_functions = require('../_library/basic_functions.js') +let cookie = require('cookie') +let querystring = require('querystring') +let random_number = require('../_library/random_number.js') +let stream_buffers = require('stream-buffers') +let XDate = require('xdate') + +return async env => { + let response = null; + if (env.request.method === 'POST') { + let write_stream = new stream_buffers.WritableStreamBuffer() + let data = new Promise( + (resolve, reject) => { + write_stream. + on('finish', () => {resolve(write_stream.getContents())}). + on('error', () => {reject()}) + } + ) + env.request.pipe(write_stream) + let query = querystring.parse((await data).toString()) + console.log('received patchOrder form:', JSON.stringify(query)) + + let cookies = cookie.parse(env.request.headers.cookie || '') + let new_order_details = { + "patch_details": [{ + "op" : "replace", + "path" : "/purchase_units/@reference_id==\'PU1\'/amount", + "value" : { + "currency_code" : query.currency, + "value" : parseInt(query.total_amt) + parseInt(query.updated_shipping) - parseInt(query.current_shipping), + "breakdown" : { + "item_total" : { + "currency_code" : query.currency, + "value" : query.item_amt, + }, + "shipping" : { + "currency_code" : query.currency, + "value" : query.updated_shipping + }, + "tax_total" : { + "currency_code" : query.currency, + "value" : query.tax_amt + }, + "shipping_discount" : { + "currency_code" : query.currency, + "value" : query.shipping_discount + }, + "handling" : { + "currency_code" : query.currency, + "value" : query.handling_fee + }, + "insurance" : { + "currency_code" : query.currency, + "value" : query.insurance_fee + } + } + } + }], + "order_id": cookies.order_id + }; + response = { + http_code: await basic_functions.patch_order_details(new_order_details) + } + console.log('patch_order_details()', response) + } + + env.site.serve( + env, + 200, + Buffer.from(JSON.stringify(response)), + 'patchOrder.json.jst' + ) +} diff --git a/img/camera.jpg b/img/camera.jpg new file mode 100644 index 0000000000000000000000000000000000000000..acfbbf199774f3c748272120df71e95e7b4a0467 GIT binary patch literal 23438 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 literal 0 HcmV?d00001 diff --git a/index.html b/index.html new file mode 100644 index 0000000..d8e5cce --- /dev/null +++ b/index.html @@ -0,0 +1,263 @@ + + + + + + + + + + Checkout With PayPal NodeJs Demo + + + + + + + + + + + + + + diff --git a/js/config.js b/js/config.js new file mode 100644 index 0000000..a5e380b --- /dev/null +++ b/js/config.js @@ -0,0 +1,258 @@ +//Helper Functions +function showDom(id) { + let arr; + if (!Array.isArray(id)) { + arr = [id]; + } else { + arr = id; + } + arr.forEach(function (domId) { + document.getElementById(domId).style.display = "block"; + }); +} + +function hideDom(id) { + let arr; + if (!Array.isArray(id)) { + arr = [id]; + } else { + arr = id; + } + arr.forEach(function (domId) { + document.getElementById(domId).style.display = "none"; + }); +} + +function getUrlParams(prop) { + let params = {}, + search = decodeURIComponent(window.location.href.slice(window.location.href.indexOf("?") + 1)), + definitions = search.split("&"); + + definitions.forEach(function (val) { + let parts = val.split("=", 2); + params[parts[0]] = parts[1]; + }); + + return (prop && prop in params) ? params[prop] : params; +} + +document.addEventListener("input", function (event) { + if ((event.target.id === "countrySelect") && event.target.id !== null) { + window.location.href = + window.location.pathname + + "?buyer-country=" + + event.target.options[event.target.selectedIndex].value; + } +}); + +ready = function (fn) { + if (document.readyState != "loading") { + fn(); + } else { + document.addEventListener("DOMContentLoaded", fn); + } +} + +select_country_dropdown = function () { + const queryString = window.location.search; + const urlParams = new URLSearchParams(queryString); + const buyer_country = urlParams.get("buyer-country") + //If this param exists in URL + if (buyer_country) { + //Build script tag for head based on buyer country + let head = document.getElementsByTagName("head")[0]; + let paypal_sdk_script = document.createElement("script"); + paypal_sdk_script.type = "text/javascript"; + paypal_sdk_script.setAttribute("async", ""); + paypal_sdk_script.src = "https://www.paypal.com/sdk/js?intent=capture&vault=false&client-id=Aa2IfcoEvHnfJRnVQLSFrSs3SmTTkv5N1weMEL66ysqYIeHfAqXpDVkjOv3vLhkhbP4eKB6MpRlQIcJw&buyer-country=" + buyer_country; + paypal_sdk_script.onload = init_smart_buttons; + head.appendChild(paypal_sdk_script); + //Pre-populate fields + for (let i = 0; i < document.getElementById("countrySelect").options.length; i++) { + if (document.getElementById("countrySelect").options[i].value == buyer_country) { + document.getElementById("countrySelect").options[i].selected = true; + } + } + apm_country_list = [ + { + country: "DE", address: { + address_line_1: "Bayreuther Straße 42", + address_line_2: "", + city: "Gmindersdorf", + state: "Reutlingen", + postal_code: "72760", + }, recipient_name: "Jane Doe" + }, + { + country: "US", address: { + address_line_1: "2211 North Street", + address_line_2: "", + city: "San Jose", + state: "CA", + postal_code: "95123" + }, recipient_name: "Jane Doe" + }, + { + country: "BE", address: { + address_line_1: "Putstraat 478", + address_line_2: "", + city: "Sint-Pauwels", + state: "", + postal_code: "9170" + }, recipient_name: "Marina Beich" + }, + { + country: "PL", address: { + address_line_1: "ul. Królewska 78", + address_line_2: "", + city: "Kraków", + state: "", + postal_code: "30-081" + }, recipient_name: "August Pedersen" + }, + { + country: "AT", address: { + address_line_1: "Hauptstrasse 85", + address_line_2: "", + city: "PULGARN", + state: "", + postal_code: "4221" + }, recipient_name: "Berrie Hulstein" + }, + { + country: "NL", address: { + address_line_1: "Asterstraat 135", + address_line_2: "", + city: "Almelo", + state: "", + postal_code: "7601 AK" + }, recipient_name: "Joos Voorham" + }, + { + country: "IT", address: { + address_line_1: "Via Longhena, 132", + address_line_2: "", + city: "Galloro RM", + state: "", + postal_code: "00040" + }, recipient_name: "Colette Jalbert" + }, + { + country: "ES", address: { + address_line_1: "Calle Alcalá 22", + address_line_2: "", + city: "Madrid", + state: "", + postal_code: "28055" + }, recipient_name: "Ana García López" + }, + { + country: "AU", address: { + address_line_1: "15 Mary Street", + address_line_2: "", + city: "North Sydney", + state: "NSW", + postal_code: "2001" + }, recipient_name: "Jane Doe" + }, + { + country: "MX", address: { + address_line_1: "Av. Caudillo del Sur 1234, Edificio B-5", + address_line_2: "11560, Col. Municipio Libre, D.F.", + city: "Mexico City", + state: "Morelos", + postal_code: "11560" + }, recipient_name: "Raúl Uriarte, Jr." + }, + { + country: "BR", address: { + address_line_1: "Rua da Matriz 123", + address_line_2: "apto 25 Centro", + city: "Rio de Janeiro", + state: "Paraná", + postal_code: "01000-001" + }, recipient_name: "João da Silva" + }, + { + country: "JP", address: { + address_line_1: "123-4567 東京都港区", + address_line_2: "青山 1-1-1 ペイパルビル 1037", + city: "港区", + state: "東京都", + postal_code: "104-0051" + }, recipient_name: "山田 花子" + }, + { + country: "GB", address: { + address_line_1: "1 Main Terrace", + address_line_2: "", + city: "Wolverhampton", + state: "West Midlands", + postal_code: "W12 4LQ" + }, recipient_name: "Jane Doe" + } + ]; + apm_country_check = false; + apm_country_list.forEach(function (country_object) { + if (country_object.country === buyer_country) { + apm_country_check = true; + document.getElementById("recipient_name").value = country_object.recipient_name; + document.getElementById("line1").value = country_object.address.address_line_1; + document.getElementById("line2").value = country_object.address.address_line_2; + document.getElementById("city").value = country_object.address.city; + document.getElementById("state").value = country_object.address.state; + document.getElementById("zip").value = country_object.address.postal_code; + } + }); + if (apm_country_check === false && buyer_country !== null) { + document.getElementById("recipient_name").value = "Jane Doe"; + document.getElementById("line1").value = + document.getElementById("line2").value = + document.getElementById("city").value = + document.getElementById("state").value = + document.getElementById("zip").value = ""; + } + } else { + //Build script tag with no particular buyer country + let head = document.getElementsByTagName("head")[0]; + let paypal_sdk_script = document.createElement("script"); + paypal_sdk_script.type = "text/javascript"; + paypal_sdk_script.setAttribute("async", ""); + paypal_sdk_script.src = "https://www.paypal.com/sdk/js?intent=capture&vault=false&client-id=Aa2IfcoEvHnfJRnVQLSFrSs3SmTTkv5N1weMEL66ysqYIeHfAqXpDVkjOv3vLhkhbP4eKB6MpRlQIcJw"; + paypal_sdk_script.onload = init_smart_buttons; + head.appendChild(paypal_sdk_script); + } +} + +ready(select_country_dropdown); + +let serialize = function (form) { + + // Setup our serialized data + let serialized = []; + + // Loop through each field in the form + for (let i = 0; i < form.elements.length; i++) { + + let field = form.elements[i]; + + // Don't serialize fields without a name, submits, buttons, file and reset inputs, and disabled fields + if (!field.name || field.disabled || field.type === "file" || field.type === "reset" || field.type === "submit" || field.type === "button") continue; + + // If a multi-select, get all selections + if (field.type === "select-multiple") { + for (let n = 0; n < field.options.length; n++) { + if (!field.options[n].selected) continue; + serialized.push(encodeURIComponent(field.name) + "=" + encodeURIComponent(field.options[n].value)); + } + } + + // Convert field data to a query string + else if ((field.type !== "checkbox" && field.type !== "radio") || field.checked) { + serialized.push(encodeURIComponent(field.name) + "=" + encodeURIComponent(field.value)); + } + } + + return serialized.join("&"); + +}; \ No newline at end of file diff --git a/package.json b/package.json new file mode 100644 index 0000000..9a95157 --- /dev/null +++ b/package.json @@ -0,0 +1,16 @@ +{ + "name": "@ndcode/paypal_example_site", + "version": "0.0.1", + "description": "Example website using JavaScript Template system", + "directories": {}, + "dependencies": { + "cookie": "^0.3.1", + "querystring": "^0.2.0", + "stream-buffers": "^3.0.2", + "xdate": "^0.8.2" + }, + "devDependencies": {}, + "scripts": {}, + "author": "Nick Downing", + "license": "CC-BY-SA-3.0" +} diff --git a/pages/shipping.html b/pages/shipping.html new file mode 100644 index 0000000..f47efb1 --- /dev/null +++ b/pages/shipping.html @@ -0,0 +1,435 @@ + + + + + + + + + + Checkout With PayPal NodeJs Demo + + + + +
+
+

Checkout with PayPal Demo

+

Using Orders v2 REST API with PayPal JavaScript SDK

+
Server-side Integration
+
+
+
+

Shipping Information

+
+
+ + + + + + + + + + +
+ +
+ +
+
+
+ +
+
+
+
+ +
+
+
+
+ +
+
+
+
+ +
+
+
+
+ +
+
+
+
+ +
+ +
+
+
+ +
+ +
+
+ +
+
+ +
+ +
+
+
+
+ +
+
+
+
+
+
+
+ + + + + + + + + diff --git a/pages/success.html b/pages/success.html new file mode 100644 index 0000000..437d54b --- /dev/null +++ b/pages/success.html @@ -0,0 +1,255 @@ + + + + + + + + + + Checkout With PayPal NodeJs Demo + + + + +
+
+

Checkout with PayPal Demo

+

Using Orders v2 REST API with PayPal JavaScript SDK

+
Server-side Integration
+
+
+
+ + + +
+
+
+
+ + + + + + + + -- 2.34.1
+
+

Checkout with PayPal Demo

+

Using Orders v2 REST API with PayPal JavaScript SDK

+
Server-side Integration
+
+
+
+
+

Sample Sandbox Buyer Credentials

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Buyer EmailPassword
emily_doe@buyer.comqwer1234
bill_bong@buyer.comqwer1234
jack_potter@buyer.com123456789
harry_doe@buyer.com123456789
ron_brown@buyer.comqwer1234
bella_brown@buyer.comqwer1234
+
+
+
+
+
+
+

Readme

+
    +
  1. Enter REST API credentials in common/config/config.json. You can get your own REST app credentials by creating a REST app with the steps outlined + here + .
  2. +
  3. Click on 'PayPal Checkout’ button and see the experience.
  4. +
  5. Checkout with PayPal using a buyer sandbox account provided on this page. And you're done!
  6. +
  7. In the guest checkout experience, the buyer country can be switched. When switched to one of Germany, Poland, Austria, Netherlands, Italy and Spain, you will be able to choose the alternative payment methods offered in those countries.
  8. +
  9. For example: Selecting 'Germany' in the country drop down will pre-fill the shipping address on the Shipping Information page. For all other countries not mentioned in step 5, the address has to be manually entered.
  10. +
+
+

In-Context Checkout integration steps with PayPal JavaScript SDK

+
    +
  1. Copy the files and folders in the package to the same location where you have your shopping cart page.
  2. +
  3. In order to view Alternative Payment Methods as part of the guest checkout flow, you must add query parameters intent=capture, commit=true, vault=false and buyer-country= and you must provide a supported buyer country
  4. +
  5. Include the following script on your shopping cart page: (For APMs, the layout must be vertical and setting up the payment in the alternative payment method supported currency is required for the alternative payment method to render.)
    
    +        paypal.Buttons({
    +        env: 'sandbox', // sandbox | production
    +    
    +            // Set style of buttons
    +            style: {
    +                layout: 'vertical',   // horizontal | vertical <-Must be vertical for APMs
    +                size:   'responsive',   // medium | large | responsive
    +                shape:  'pill',         // pill | rect
    +                color:  'gold',         // gold | blue | silver | black,
    +                fundingicons: false,    // true | false,
    +                tagline: false          // true | false,
    +            },
    +    
    +        // payment() is called when the button is clicked
    +        createOrder: function() {
    +    
    +            return fetch('/my-server/create-paypal-transaction')
    +                .then(function(res) {
    +                    return res.json();
    +                }).then(function(data) {
    +                    return data.orderID;
    +                });
    +        },
    +    
    +        // onAuthorize() is called when the buyer approves the payment
    +        onApprove: function(data, actions) {
    +    
    +            return fetch('/my-server/capture-paypal-transaction', {
    +                    body: JSON.stringify({
    +                    orderID: data.orderID
    +                    })
    +                }).then(function(res) {
    +                    return res.json();
    +                }).then(function(details) {
    +                    alert('Transaction funds captured from ' + details.payer_given_name);
    +                });
    +        }
    +    }).render('#paypal-button-container');
    +                
  6. +
  7. Open your browser and navigate to your Shopping cart page. Click on 'Checkout with PayPal' button and complete the flow.
  8. +
  9. You can use the sample Buyer Sandbox credentials provided on index/home page.
  10. +
  11. Refer to PayPal Developer site for detailed guidelines.
  12. +
  13. Click here for the API reference.
  14. +
+
+
+