return async env => { _out = [] _out.push('') html(lang="en") { head { meta(charset="utf-8") {} meta(http-equiv="x-ua-compatible" content="ie=edge") {} meta(name="viewport" content="width=device-width,initial-scale=1") {} link(href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.0-beta1/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-giJF6kkoqNQ00vy+HMDP7azOuL0xtbfIcaT9wjKHr8RbDVddVHyTfAAsrekwKmP1" crossorigin="anonymous") {} script(src="https://cdn.jsdelivr.net/npm/bootstrap@5.0.0-beta1/dist/js/bootstrap.bundle.min.js" integrity="sha384-ygbV9kiqUc6oa4msXn9868pTtWMgiQaeYH7/t7LECLbyPA2x65Kgf80OJFdroafW" crossorigin="anonymous") {} title { 'Checkout With PayPal NodeJs Demo' } style { .header-bg-color { color: #fff; background: -moz-linear-gradient(0deg,#004094 0,#0096d9 50%,#004094 100%); background: -webkit-gradient(linear,left top,right top,color-stop(0,#004094),color-stop(50%,#0096d9),color-stop(100%,#004094)); background: -webkit-linear-gradient(0deg,#004094 0,#0096d9 50%,#004094 100%); background: -o-linear-gradient(0deg,#004094 0,#0096d9 50%,#004094 100%); background: -ms-linear-gradient(0deg,#004094 0,#0096d9 50%,#004094 100%); background: linear-gradient(90deg,#004094 0,#0096d9 50%,#004094 100%) } } } body { div.container { div.row.header-bg-color.'mb-5'.p-3 { h2.text-center { 'Checkout with PayPal Demo' } h4.text-center { 'Using Orders v2 REST API with PayPal JavaScript SDK' } h5.text-center { 'Server-side Integration' } } div.row { div.col-sm { div.card { img.card-img-top.img-responsive(src="https://www.paypalobjects.com/web/res/b0b/e9fea36098a7a8192723a8d3b86b2/img/platform/common/merchantStore/cart/camera-lg.jpg") {} div.card-body { h4.text-center { 'Sample Sandbox Buyer Credentials' } table.table.table-striped { thead { tr { th(scope="col") { 'Buyer Email' } th(scope="col") { 'Password' } } } tbody { tr { td { 'emily_doe@buyer.com' } td { 'qwer1234' } } tr { td { 'bill_bong@buyer.com' } td { 'qwer1234' } } tr { td { 'jack_potter@buyer.com' } td { '123456789' } } tr { td { 'harry_doe@buyer.com' } td { '123456789' } } tr { td { 'ron_brown@buyer.com' } td { 'qwer1234' } } tr { td { 'bella_brown@buyer.com' } td { 'qwer1234' } } } } } } } div.col-sm { h3.text-center { 'Pricing Details' } hr {} form#camera_form { _out.push('') ' ' input(name="return_url" type="hidden" value="http://localhost/pages/success.html") {} ' ' input(name="cancel_url" type="hidden" value="http://localhost/pages/success.html") {} div.form-group { label.'col-sm-5'.control-label(for="camera_amount") { 'Camera' } div.col-sm { input.form-control#camera_amount(type="text" name="item_amt" value="300" readonly="") {} } } div.form-group { label.'col-sm-5'.control-label(for="tax_amt") { 'Tax' } div.col-sm { input.form-control#tax_amt(type="text" name="tax_amt" value="5" readonly="") {} } } div.form-group { label.'col-sm-5'.control-label(for="insurance_fee") { 'Insurance' } div.col-sm { input.form-control#insurance_fee(type="text" name="insurance_fee" value="10" readonly="") {} } } div.form-group { label.'col-sm-5'.control-label(for="handling_fee") { 'Handling Fee' } div.col-sm { input.form-control#handling_fee(type="text" name="handling_fee" value="5" readonly="") {} } } div.form-group { label.'col-sm-5'.control-label(for="shipping_amt") { 'Estimated Shipping' } div.col-sm { input.form-control#shipping_amt(type="text" name="shipping_amt" value="2" readonly="") {} } } div.form-group { label.'col-sm-5'.control-label(for="shipping_discount") { 'Shipping Discount' } div.col-sm { input.form-control#shipping_discount(type="text" name="shipping_discount" value="2" readonly="") {} } } div.form-group { label.'col-sm-5'.control-label(for="total_amt") { 'Total Amount' } div.col-sm { input.form-control#total_amt(type="text" name="total_amt" value="320" readonly="") {} } } div.form-group { label.'col-sm-5'.control-label(for="currency_Code") { 'Currency' } div.col-sm { input.form-control#currency_Code(type="text" name="currency" value="USD" readonly="") {} } } hr {} _out.push('') div.form-group { div.'col-sm-offset-5'.col-sm { _out.push('') div#paypalCheckoutContainer {} _out.push('') div#paypalMarkRedirect { h4.text-center { 'OR' } a.'w-100'.btn.btn-success.btn-block(href="pages/shipping.html" role="button") { h4 { 'Proceed to Checkout' } } } } } } } div.col-sm-4 { hr.m-5 {} h3.text-center { 'Readme' } ol { li { '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 ' i { a(href="https://developer.paypal.com/docs/api-basics/manage-apps/#create-or-edit-sandbox-and-live-apps" target="_blank") { 'here' } ' ' } '.' } li { 'Click on \'PayPal Checkout’ button and see the experience.' } li { 'Checkout with PayPal using a buyer sandbox account provided on this page. And you\'re done!' } li { '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.' } li { '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.' } } hr {} h3.text-center { 'In-Context Checkout integration steps with PayPal JavaScript SDK' } ol { li { 'Copy the files and folders in the package to the same location where you have your shopping cart page.' } li { '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' } li { 'Include the following script on your shopping cart page: (For APMs, the layout must be ' code { 'vertical' } ' and setting up the payment in the alternative payment method ' a(href="https://developer.paypal.com/docs/checkout/integration-features/alternative-payment-methods/#availability" target="_blank") { 'supported currency' } ' is required for the alternative payment method to render.)' pre { code { '\r\n paypal.Buttons({\r\n env: \'sandbox\', // sandbox | production\r\n \r\n // Set style of buttons\r\n style: {\r\n layout: \'vertical\', // horizontal | vertical <-Must be vertical for APMs\r\n size: \'responsive\', // medium | large | responsive\r\n shape: \'pill\', // pill | rect\r\n color: \'gold\', // gold | blue | silver | black,\r\n fundingicons: false, // true | false,\r\n tagline: false // true | false,\r\n },\r\n \r\n // payment() is called when the button is clicked\r\n createOrder: function() {\r\n \r\n return fetch(\'/my-server/create-paypal-transaction\')\r\n .then(function(res) {\r\n return res.json();\r\n }).then(function(data) {\r\n return data.orderID;\r\n });\r\n },\r\n \r\n // onAuthorize() is called when the buyer approves the payment\r\n onApprove: function(data, actions) {\r\n \r\n return fetch(\'/my-server/capture-paypal-transaction\', {\r\n body: JSON.stringify({\r\n orderID: data.orderID\r\n })\r\n }).then(function(res) {\r\n return res.json();\r\n }).then(function(details) {\r\n alert(\'Transaction funds captured from \' + details.payer_given_name);\r\n });\r\n }\r\n }).render(\'#paypal-button-container\');' } '\r\n ' } } li { 'Open your browser and navigate to your Shopping cart page. Click on \'Checkout with PayPal\' button and complete the flow.' } li { 'You can use the sample Buyer Sandbox credentials provided on index/home page.' } li { 'Refer to ' a(href="https://developer.paypal.com/docs/checkout/" target="_blank") { 'PayPal Developer' } ' site for detailed guidelines.' } li { 'Click ' a(href="https://developer.paypal.com/docs/api/orders/v2/" target="_blank") { 'here' } ' for the API reference.' } } } } } _out.push('') script(src="../js/config.js") {} _out.push('') script(type="text/javascript") { init_smart_buttons = (() => { paypal.Buttons({ env: "sandbox", style: { layout: "vertical", size: "responsive", shape: "pill", color: "gold", fundingicons: false, tagline: false }, createOrder: function() { return new Promise((resolve, reject) => { $.ajax({ type: "POST", url: "api/createOrder.json", data: serialize(document.getElementById("camera_form")), success: function(response) { return response; }, error: function(error) { reject(error); } }).then(function(response) { console.log("Order ID: " + response.id); resolve(response.id); }); }); }, onApprove: function(data, actions) { return fetch("api/getOrderDetails.json", { method: "GET" }).then(function(res) { return res.json(); }).then(function(res) { window.location.href = "pages/success.html"; }); } }).render("#paypalCheckoutContainer"); }); } _out.push('') script(src="https://code.jquery.com/jquery.js") {} } } env.site.serve(env, 200, Buffer.from(_out.join('')), 'index.html.jst') }