Code Sample

Collecting payments and updating existing account details

Client Code

function loadPaysimpleJs(auth) {
   // Initialize the PaySimpleJS SDK with the checkout token and styles
   var paysimplejs = window.paysimpleJs({
      debug: true,
      container: document.querySelector('#psjs'),
      // auth is an object containing a checkout token in the form of:
      // {
      //    token: "checkout_token from server"
      // }
      auth: auth,            
      styles: {
         body: {
            backgroundColor: '#f9f9f9'
         }
      }
   });

   var psjsFormValid = false;

   // Configure a callback to complete the checkout after the
   // PaySimpleJS SDK retrieves the account
   paysimplejs.on('accountRetrieved', onAccountRetrieved);

   paysimplejs.on('formValidityChanged', function(body) {
      psjsFormValid = body.valid;
   });

   // Load the credit card or ach key enter form
   if (window.location.href.indexOf('ach=1') > 0) {
      paysimplejs.send.setMode('ach-key-enter');
   }
   else {
      paysimplejs.send.setMode('cc-key-enter');
   }

   // Add an event listener to your submit button
   document.querySelector('#sample-form')
      .addEventListener('submit', onSubmit);

   // Called when the PaySimpleJS SDK retrieves the account info
   function onAccountRetrieved(accountInfo) {
      /* Example accountInfo:
      * {
      *    "account": {
      *        "id": 7313702
      *    },
      *    "customer": {
      *        "id": 8041997
      *    },
      *    "paymentToken": "e1f1bb19-9fe4-4c96-a35e-cd921298d8e6"
      * }
      */

      // Send the accountInfo to your server to collect a payment
      // for an existing customer
      var xhr = new XMLHttpRequest();
      xhr.open('POST', 'PaySimple/Payment');
      xhr.setRequestHeader('Content-Type', 'application/json');
      xhr.onload = function(e) {
         if (xhr.status < 300) {
            var data = JSON.parse(this.response);
            document.getElementById('message')
               .innerHTML = 'Successfully created Payment:\nTrace #: ' + data.TraceNumber;
            //alert('Successfully created Payment:\nTrace #: ' + data.TraceNumber);
         } else {
            document.getElementById('message')
               .innerHTML = 'Failed to create Payment: (' + xhr.status + ')' + xhr.responseText;
            // alert('Failed to create Payment: (' + xhr.status + ') '
            //       + xhr.responseText);
         }
      }
      accountInfo.amount = document.querySelector('#amount').value;
      xhr.send(JSON.stringify(accountInfo));
   }

   // Submit button event listener -- triggered when the user clicks
   // the submit button.
   // Sumbits the merchant form data to the PaySimpleJS SDK
   function onSubmit(event) {
      // Prevent the default submit behavior of the form
      event.preventDefault();
      document.getElementById('message').innerHTML = '';
         
      // Request the PaySimpleJS SDK to add a new cc or ach account for the
      // customer which the server generated the customer token was granted
      getCustomerToken(function(customerToken) {
         return paysimplejs.send.matchOrCreateAccount(customerToken);
      });
   }
}

function getToken(tokenType, callback) {
   var xhr = new XMLHttpRequest();
   xhr.open('POST', 'PaySimple/' + tokenType);
   xhr.onload = function(e) {
      if (xhr.status < 300){
         var data = JSON.parse(this.response);
         callback.call(null, {
            // Make sure to fix the shape for auth to .token
            token: data.JwtToken
         });
         return;
      }

      alert('Failed to get Auth Token: (' + xhr.status + ') '
         + xhr.responseText);
   }
   xhr.send();
}

function getAuth(callback) {
   getToken('CheckoutToken', callback);
}

function getCustomerToken(callback) {
   getToken('CustomerToken', callback);
}

getAuth(loadPaysimpleJs);

Server Code

using System;
using System.Configuration;
using System.Linq;
using System.Threading.Tasks;
using System.Web.Mvc;
using PaySimpleSdk.Accounts;
using PaySimpleSdk.Customers;
using PaySimpleSdk.Models;
using PaySimpleSdk.Payments;

namespace PaySimple.NetSDKSample.Web.Controllers
{
    public class PaySimpleController : Controller
    {
        private static readonly IPaySimpleSettings PSSettings = new PaySimpleSettings(ConfigurationManager.AppSettings["PS.ApiKey"], ConfigurationManager.AppSettings["PS.UserId"],
                ConfigurationManager.AppSettings["PS.BaseUrl"]);

        [HttpPost]
        public async Task<ActionResult> CheckoutToken()
        {
            var paymentService = new PaymentService(PSSettings);
            var token = await paymentService.GetCheckoutTokenAsync();
            return Json(token);
        }

        [HttpPost]
        public async Task<ActionResult> PaymentToken(PaymentTokenRequest paymentTokenRequest)
        {
            var paymentService = new PaymentService(PSSettings);
            var token = await paymentService.GetPaymentTokenAsync(paymentTokenRequest);
            return Json(token);
        }

        [HttpPost]
        public async Task<ActionResult> CustomerToken()
        {
            var customerService = new CustomerService(PSSettings);
            // do not allow the customer id to be passed in from the UI here or any 
            // customer would have access to other customers data!
            // in real life this would be usually mapped to a logged in user's account 
            // on your system.
            var customerId = (await customerService.GetCustomersAsync()).Items.FirstOrDefault()?.Id;

            if (!customerId.HasValue)
                throw new ApplicationException("No customer exists to use");

            var token = await customerService.GetCustomerTokenAsync(customerId.Value);
            return Json(token);
        }

        [HttpPost]
        public async Task<ActionResult> Payment(decimal amount, Account account, Customer customer, string paymentToken)
        {
            var payment = new Payment
            {
                Amount = amount,
                AccountId = account.Id,
                PaymentToken = paymentToken
            };

            var paymentService = new PaymentService(PSSettings);
            payment = await paymentService.CreatePaymentAsync(payment);
            return Json(payment);
        }
    }
}
'use strict';
const express = require('express');
const bodyParser = require('body-parser');
const request = require('request');
const crypto = require('crypto');
// Replace username and apikey with your PaySimple 4.0 API credentials
const settings = {
    port: 8080,
    apiv4url: https: //api.paysimple.com/v4, // set to https://sandbox-api.paysimple.com/v4 for testing in the sandbox environment
        username: 'APIUser9999999',
    apikey: 'NTqVg...V8W0'
};
let app = express();
app.use(express.static('public'));
app.use(bodyParser.json());
// The authorization header for PaySimple 4.0
function getAuthHeader() {
    let time = (new Date()).toISOString();
    let hash = crypto.createHmac('SHA256', settings.apikey)
        .update(time)
        .digest('base64');
    return 'PSSERVER ' + "accessid=" + settings.username +
        "; timestamp=" + time + "; signature=" + hash;
}
// Simple endpoint to communicate with PaySimple 4.0 API to retrieve a JWT
// that can be passed to the PaySimpleJS.
// Example response body:
// {
// "JwtToken": "eyJ0eXAiOiJKV1...lNbw",
// "Expiration":"2017-02-28T22:03:36Z"
// }
app.get('/token', function(req, res) {
    let options = {
        method: "POST",
        uri: settings.apiv4url + '/checkouttoken',
        headers: {
            Authorization: getAuthHeader()
        },
        body: {},
        json: true,
    };
    request(options, function(error, response, body) {
        if (!error && response && response.statusCode < 300) {
            res.json(body.Response);
            return;
        }
        res.status((response && response.statusCode) || 500).send(error);
    });
});
// Mocked up endpoint to initiate a payment via the PaySimple 4.0 API with
// the payment token returned by the PaySimpleJS
app.post('/payment', function(req, res) {
    var accountInfo = req.body;
    let options = {
        method: "POST",
        uri: settings.apiv4url + '/payment',
        headers: {
            Authorization: getAuthHeader()
        },
        body: {
            AccountId: accountInfo.account.id,
            PaymentToken: accountInfo.paymentToken,
            // Payment Specific information...
            Amount: 3.50,
            PurchaseOrderNumber: '123456',
            OrderId: 'O-4242',
            Description: 'Really good description of order',
            PaymentSubType: 'MOTO'
        },
        json: true,
    };
    request(options, function(error, response, body) {
        // The return code for /payment will be a 201 (CREATED)
        if (!error && response && response.statusCode < 300) {
            res.json(body.Response);
            return;
        }
        res.status((response && response.statusCode) || 500).send(error);
    });
});
// Endpoint to get a JWT token for a customer that has been authenticated
// by the merchant. The PaySimple customer id should NOT be passed into this service
// to prevent unauthorized access.
app.get('/customertoken, function(req, res) {
let customerid = 1234; // do a lookup in your system to fetch the PaySimple customer id for the authenticated customer
let options = {
    method: "GET",
    uri: settings.apiv4url + '/customer/' + customerId + "/token",
    headers: {
        Authorization: getAuthHeader()
    },
    json: true,
};
request(options, function(error, response, body) {
    if (!error && response && response.statusCode < 300) {
        res.json(body.Response);
        return;
    }
    res.status((response && response.statusCode) || 500).send(error);
	});
});
app.listen(settings.port, function() {
    console.log('PaySimpleJS backend listening on port ' + settings.port);
});