@nait-aits/moneris
v0.0.2
Published
```console // with npm npm install @nait-aits/moneris ```
Downloads
5
Readme
Installation
// with npm
npm install @nait-aits/moneris
What is this?
This package contains a control(MonerisChecoutPanel) that will help using moneris for payment. You can include this component on your page and it will make it easier to integrate into your application.
There are a few things that make using moneris a bit difficult when using react/typescript, so hopefully this simplifies things a bit.
Usage
<MonerisChecoutPanel<{data: number}>
createTransactionData={{
someData: {order: 123},
}}
createTransactionUrl={'https://urlToCreateTransaction'}
processPaymentUrl={'https://urlToProcessAfterPayment'}
cancelTransactionUrl={'https://urlForCancelledTransaction'}
getAuthToken={promiseToGetToken}
onComplete={paymentData => {
//Handle what the app should do when everything is done
//payment data is the type of the generic for the panel
console.log('onComplete called', paymentData);
}}
onCancel={() => {
//Handle what the app should do when user cancels
console.log('onCancel called');
}}
onError={error => {
//Handle what the app should do when moneris errors
console.log('onError called');
}}
activated={trueIfYouWantToActivate}
/>
Order things happen
- User Clicks Pay Button
- set activated parameter to true
- createTransactionUrl is called, with the createTransactionData data posted
- Server creates moneris ticket and returns moneris ticket to the client
- Client pays via moneris interface
- processPaymentUrl is called with the ticket as a parameter
- server verifies ticket is paid and then processes
- onComplete is called
Server side notes
- There is code at the end for the MonerisRepository
Sample C# code
[Authorize]
[HttpPost("CreateOrderTransaction")]
public async Task<object> CreateOrderTransaction([FromForm] List<string> slugs)
{
...
var totals = GetPaymentValues(slugs);
var transactionId = Guid.NewGuid();
//create moneris ticket for order (Due to the Kount verification, orderID cannot exceed 32 digits so we need to remove the dashes from the guid)
var ticket = await _monerisRepo.CreateOrder(totals.Total, transactionId.ToString().Replace("-",""), cartItems);
...
//create some record somewhere to make a note of this transaction that is pending
//You MUST return an obejct with the monerisTicket property
return new
{
monerisTicket = ticket
};
}
[Authorize]
[HttpPost("CancelOrderTransaction")]
public async Task<object> CancelOrderTransaction([FromForm] string monerisTicket)
{
...
//do any cleanup you need to do
...
return new
{
ok = true
};
}
[Authorize]
[HttpPost("ProcessPayment")]
public async Task<object> ProcessPayment([FromForm] string monerisTicket)
{
var user = CurrentUser;
//load the transaction
//get the recept from moneris
var receiptString = await _monerisRepo.GetPaymentReceipt(monerisTicket);
transaction.ReceiptJsonData = receiptString;
//Get the receipt
var receipt = _monerisRepo.GetReceiptResponse(receiptString);
if (receipt.success != "true" || receipt.receipt.result != "a")
{
if ( receipt.success != "true")
{
//The payment was NOT successful
}
if( receipt.receipt.result == "d")
{
//credit card was declined
}
}
//make sure to validate that it is correct amount was paid vs what you were expecting
//receipt.request.cc_total is the total from the payment
//payment completed, so do what you need to do now
//return the obejct that matches the generic type of the control.
return new
{
orderId = newOrder.Id,
transactionId = transaction.Id,
subTotal = transaction.Subtotal,
taxes = transaction.Taxes,
total = transaction.Total,
monerisTicket = monerisTicket
};
}
Pages/notes
Server Side Code
You must use .NET Core as it requires IHttpClientFactory (this is injected in Startup.cs)
- services.AddHttpClient();
Moneris Documentation
https://developer.moneris.com:3000/livedemo/checkout/overview/guide/dotnet
Moneris Test Card Numbers
https://developer.moneris.com/More/Testing/Testing%20a%20Solution
Moneris development merchant setup
Login info is also displayed on this page
https://esqa.moneris.com/mpg/
public/index.html
You need to make sure that you include the link to the Moneris library.
<!DOCTYPE html>
<html lang="en">
<head>
...
<script src="https://gatewayt.moneris.com/chkt/js/chkt_v1.00.js"></script>
...
</head>
<body>
<noscript>You need to enable JavaScript to run this app.</noscript>
<div id="root"></div>
</body>
</html>
C# MonerisRepository Library
using System;
using System.Collections.Generic;
using System.Net.Http;
using System.Net.Http.Json;
using System.Text.Json;
using System.Threading.Tasks;
namespace YourNameSpace.Repositories.Moneris
{
public class MonerisRepository
{
private IHttpClientFactory _httpClientFactory;
private string _baseUrl;
private string _storeId;
private string _token;
private string _checkoutId;
public MonerisRepository(string baseUrl, string storeId, string token, string checkoutId, IHttpClientFactory httpClientFactory)
{
_httpClientFactory = httpClientFactory;
_baseUrl = baseUrl;
_storeId = storeId;
_token = token;
_checkoutId = checkoutId;
}
public async Task<string> CreateOrder(decimal amountDue, string orderId, List<MonerisPreloadRequest.CartItem> cartItems = null)
{
MonerisPreloadRequest orderData = new MonerisPreloadRequest()
{
store_id = _storeId,
api_token = _token,
checkout_id = _checkoutId,
txn_total = String.Format("{0:0.00}", amountDue),
environment = "qa",
action = "preload",
order_no = orderId
};
if (cartItems != null && cartItems.Count > 0)
{
orderData.cart.items = cartItems;
}
var httpClient = _httpClientFactory.CreateClient();
HttpResponseMessage res = await httpClient.PostAsJsonAsync($"{_baseUrl}/chkt/request/request.php", orderData);
if (res.IsSuccessStatusCode && res.StatusCode != System.Net.HttpStatusCode.NoContent)
{
var response = await res.Content.ReadFromJsonAsync<MonerisPreloadResponse>();
if (response.response.success == "true")
{
return response.response.ticket;
}
throw new Exception(response.response.error.ToString());
}
else
{
throw new HttpRequestException("Error Creating Ticket from Moneris", inner: null, statusCode: res.StatusCode);
}
}
//we need this as a string as if the object returned isnt as expected we still need to save
//it to our database or something
public async Task<string> GetPaymentReceipt(string monerisTicket)
{
MonerisReceiptRequest requestData = new MonerisReceiptRequest()
{
store_id = _storeId,
api_token = _token,
checkout_id = _checkoutId,
environment = "qa",
action = "receipt",
ticket = monerisTicket
};
var httpClient = _httpClientFactory.CreateClient();
HttpResponseMessage res = await httpClient.PostAsJsonAsync($"{_baseUrl}/chkt/request/request.php", requestData);
if (res.IsSuccessStatusCode && res.StatusCode != System.Net.HttpStatusCode.NoContent)
{
var resultText = await res.Content.ReadAsStringAsync();
return resultText;
}
else
{
throw new HttpRequestException("Error Retrieving Receipt Request from Moneris", inner: null, statusCode: res.StatusCode);
}
}
public ReceiptResponseItem GetReceiptResponse(string responseContent)
{
try
{
var response = JsonSerializer.Deserialize<MonerisReceiptResponse>(responseContent);
if (responseContent == null)
{
throw new Exception("Unable to parse MonerisReceiptResponse object from stream");
}
return response.response;
}
catch (Exception ex)
{
throw new Exception("Unable to parse response JSON");
}
}
}
public class MonerisReceiptRequest
{
public string store_id { get; set; }
public string api_token { get; set; }
public string checkout_id { get; set; }
public string environment { get; set; }
public string action { get; set; }
public string ticket { get; set; }
}
public class MonerisPreloadRequest
{
public string store_id { get; set; }
public string api_token { get; set; }
public string checkout_id { get; set; }
public string txn_total { get; set; }
public string environment { get; set; }
public string action { get; set; }
public string order_no { get; set; }
public Cart cart { get; set; } = new Cart();
public class Cart
{
public List<CartItem> items { get; set; } = new List<CartItem>();
}
public class CartItem
{
public string url { get; set; }
public string description { get; set; }
public string product_code { get; set; }
public decimal unit_cost { get; set; }
public int quantity { get; set; }
}
}
public class PreloadResponseItem
{
public string success { get; set; }
public string ticket { get; set; }
public object error { get; set; }
}
public class MonerisPreloadResponse
{
public PreloadResponseItem response { get; set; }
}
}