Update Helcim webhook handling for better transaction reliability (issue #1)
This commit is contained in:
parent
37c8672e4a
commit
ee989accee
@ -9,7 +9,7 @@ rm Helcim.zip
|
||||
|
||||
cd build
|
||||
|
||||
zip -r ../Helcim.v0.0.1.zip Helcim
|
||||
zip -r ../Helcim.v0.0.2.zip Helcim
|
||||
|
||||
cd ..
|
||||
|
||||
|
||||
2
Helcim/package-lock.json
generated
2
Helcim/package-lock.json
generated
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "postalpoint_helcim_plugin",
|
||||
"version": "0.0.1",
|
||||
"version": "0.0.2",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "postalpoint_helcim_plugin",
|
||||
"version": "0.0.1",
|
||||
"version": "0.0.2",
|
||||
"main": "plugin.js",
|
||||
"author": "PostalPortal LLC",
|
||||
"license": "BSD-3-Clause",
|
||||
|
||||
@ -116,6 +116,10 @@ function getCardBrand(cardType) {
|
||||
return cardType;
|
||||
}
|
||||
|
||||
var currentReceiptID = null;
|
||||
|
||||
var checkoutCancelled = false;
|
||||
|
||||
exports.init = function () {
|
||||
global.apis.pos.registerCardProcessor({
|
||||
name: "Helcim",
|
||||
@ -133,12 +137,15 @@ exports.init = function () {
|
||||
// it is assumed the payment was successful.
|
||||
const code = global.apis.settings.get(PLUGINID + ".devicecode", "");
|
||||
const receiptID = global.apis.pos.getReceiptID();
|
||||
checkoutCancelled = false;
|
||||
currentReceiptID = receiptID;
|
||||
try {
|
||||
var transactionAmount = global.apis.i18n.moneyToFixed(amount / 100.0) * 1.0;
|
||||
// authorize, capture, add a ReceiptPayment to the receipt, and return boolean true.
|
||||
global.apis.pos.addOnscreenPaymentLog("Getting card payment..."); // Add a line to the onscreen card processing status log
|
||||
var purchaseResp = await apiRequest(`devices/${code}/payment/purchase`, {
|
||||
currency: global.apis.i18n.currency().toUpperCase(),
|
||||
transactionAmount: global.apis.i18n.moneyToFixed(amount / 100.0) * 1.0,
|
||||
transactionAmount: transactionAmount,
|
||||
invoiceNumber: receiptID
|
||||
}, "POST", "text");
|
||||
if (purchaseResp.length > 0) {
|
||||
@ -151,18 +158,28 @@ exports.init = function () {
|
||||
}
|
||||
|
||||
var paymentID = "";
|
||||
|
||||
var purchaseResp;
|
||||
while (paymentID == "") {
|
||||
if (checkoutCancelled) {
|
||||
checkoutCancelled = false;
|
||||
global.apis.pos.addOnscreenPaymentLog("Checkout cancelled. Warning: It's still possible for the payment to succeed on the reader but not be recognized in PostalPoint; cancel it on the reader too.");
|
||||
return false;
|
||||
}
|
||||
await global.apis.util.delay(1000); // Wait a second
|
||||
try {
|
||||
var pollResults = await global.apis.util.http.webhook.poll(WEBHOOK_SOURCE);
|
||||
for (var i = 0; i < pollResults.length; i++) {
|
||||
var resultBody = JSON.parse(pollResults[i].body);
|
||||
if (resultBody.type == "cardTransaction") {
|
||||
paymentID = resultBody.id;
|
||||
purchaseResp = await apiRequest(`card-transactions/${resultBody.id}`, null, "GET");
|
||||
global.apis.util.http.webhook.ack(pollResults[i].id);
|
||||
if (purchaseResp.invoiceNumber == currentReceiptID) {
|
||||
console.log("Got transaction ID from Helcim webhook:", paymentID);
|
||||
console.log("purchaseResp", purchaseResp);
|
||||
paymentID = resultBody.id;
|
||||
}
|
||||
} else if (resultBody.type == "terminalCancel") {
|
||||
if (resultBody.data.deviceCode == code && resultBody.data.invoiceNumber == receiptID) {
|
||||
if (resultBody.data.deviceCode == code && resultBody.data.invoiceNumber == currentReceiptID && resultBody.data.transactionAmount == transactionAmount) {
|
||||
paymentID = "CANCEL";
|
||||
global.apis.util.http.webhook.ack(pollResults[i].id);
|
||||
}
|
||||
@ -174,18 +191,17 @@ exports.init = function () {
|
||||
}
|
||||
|
||||
if (paymentID == "CANCEL") {
|
||||
global.apis.pos.addOnscreenPaymentLog("Helcim payment not completed.");
|
||||
global.apis.alert("The card payment was canceled.", "Payment canceled");
|
||||
global.apis.pos.addOnscreenPaymentLog("Helcim payment not completed: cancelled on the card terminal.");
|
||||
global.apis.alert("The card payment was cancelled on the card terminal.", "Payment cancelled");
|
||||
currentReceiptID = null;
|
||||
return false;
|
||||
}
|
||||
|
||||
console.log("Got transaction ID from Helcim webhook:", paymentID);
|
||||
|
||||
purchaseResp = await apiRequest(`card-transactions/${paymentID}`, null, "GET");
|
||||
console.log("purchaseResp", purchaseResp);
|
||||
if (typeof purchaseResp?.errors != "undefined" && purchaseResp.errors.length > 0) {
|
||||
global.apis.pos.addOnscreenPaymentLog("Helcim card payment error: " + purchaseResp.errors[0]);
|
||||
global.apis.alert("Could not finish card payment: " + purchaseResp.errors[0], "Card Payment Error");
|
||||
currentReceiptID = null;
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -200,6 +216,7 @@ exports.init = function () {
|
||||
pstring
|
||||
)
|
||||
);
|
||||
currentReceiptID = null;
|
||||
return true;
|
||||
}
|
||||
} else if (purchaseResp.status == "DECLINED") {
|
||||
@ -209,6 +226,7 @@ exports.init = function () {
|
||||
} else {
|
||||
global.apis.alert("The customer's card was declined.", "Card Error");
|
||||
}
|
||||
currentReceiptID = null;
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -220,6 +238,7 @@ exports.init = function () {
|
||||
global.apis.alert("The transaction didn't complete correctly (Helcim card plugin reached an undefined state)", "Card Error");
|
||||
}
|
||||
|
||||
currentReceiptID = null;
|
||||
return false;
|
||||
} catch (ex) {
|
||||
global.apis.pos.addOnscreenPaymentLog(`Error: ${ex.message}`);
|
||||
@ -235,6 +254,8 @@ exports.init = function () {
|
||||
},
|
||||
cancelCheckout: async function () {
|
||||
// The user requested to cancel the payment.
|
||||
// Stop the webhook wait loop.
|
||||
checkoutCancelled = true;
|
||||
},
|
||||
finishPayment: async function ( {checkoutResponse}) {
|
||||
// Finish a payment that was authorized but not captured because checkout was called with capture = false
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user