Make Shopify transaction register system handle marked payments slightly more

This commit is contained in:
Kukks 2020-09-21 15:34:41 +02:00
parent 42df6d58b1
commit c9f0295516
2 changed files with 65 additions and 35 deletions

View file

@ -20,12 +20,16 @@ namespace BTCPayServer.Services.Shopify
{
currency = currency.ToUpperInvariant().Trim();
var existingShopifyOrderTransactions = (await _client.TransactionsList(orderId)).transactions;
// only register transactions if first, parent_id transaction is present and we haven't already registered transaction for this invoice( or if there was one registered but it was a failure and this one is success, in the case of a merchant marking it as complete)
if (existingShopifyOrderTransactions != null && existingShopifyOrderTransactions.Count >= 1 && existingShopifyOrderTransactions.All(a => a.authorization != invoiceId || (!success || a.status == "failure")))
{
var transaction = existingShopifyOrderTransactions[0];
if (currency.ToUpperInvariant().Trim() != transaction.currency.ToUpperInvariant().Trim())
if (existingShopifyOrderTransactions?.Count < 1)
{
return null;
}
var baseParentTransaction = existingShopifyOrderTransactions[0];
if (currency.ToUpperInvariant().Trim() != baseParentTransaction.currency.ToUpperInvariant().Trim())
{
// because of parent_id present, currency will always be the one from parent transaction
// malicious attacker could potentially exploit this by creating invoice
@ -34,26 +38,44 @@ namespace BTCPayServer.Services.Shopify
return null;
}
var kind = "capture";
var parentId = baseParentTransaction.id;
var status = success ? "success" : "failure";
var existingShopifyOrderTransactionsOnSameInvoice =
existingShopifyOrderTransactions.Where(holder => holder.authorization == invoiceId);
var successfulActions =
existingShopifyOrderTransactionsOnSameInvoice.Where(holder => holder.status == "success").ToArray();
var successfulCaptures = successfulActions.Where(holder => holder.kind == "capture").ToArray();
var refunds = successfulActions.Where(holder => holder.kind == "refund").ToArray();
if (!success && successfulCaptures.Length > 0 && (successfulCaptures.Length - refunds.Length) > 0)
{
kind = "void";
parentId = successfulCaptures.Last().id;
status = "success";
}
else if(success && successfulCaptures.Length >0 && (successfulCaptures.Length - refunds.Length ) > 0 )
{
return null;
}
var createTransaction = new TransactionsCreateReq
{
transaction = new TransactionsCreateReq.DataHolder
{
parent_id = transaction.id,
parent_id = parentId,
currency = currency,
amount = amountCaptured,
kind = "capture",
kind = kind,
gateway = "BTCPayServer",
source = "external",
authorization = invoiceId,
status = success? "success": "failure"
status = status
}
};
var createResp = await _client.TransactionCreate(orderId, createTransaction);
return createResp;
}
return null;
}
}
}

View file

@ -81,7 +81,14 @@ window.BTCPayShopifyIntegrationModule = function () {
function handleInvoiceData(data, opts) {
currentInvoiceData = data;
if (!currentInvoiceData) {
if (modalShown) {
window.btcpay.hideFrame();
fail();
}else if(opts && opts.backgroundCheck){
injectPaymentButtonHtml();
}else{
fail();
}
return;
}
if (["complete", "confirmed", "paid"].indexOf(currentInvoiceData.status.toLowerCase()) >= 0) {
@ -110,7 +117,9 @@ window.BTCPayShopifyIntegrationModule = function () {
window.btcpay.onModalWillLeave(function () {
modalShown = false;
fail();
getOrCheckInvoice(true).then(function (d) {
handleInvoiceData(d, {backgroundCheck: true})
});
});
window.btcpay.showInvoice(currentInvoiceData.invoiceId);
}
@ -139,7 +148,6 @@ window.BTCPayShopifyIntegrationModule = function () {
return;
}
showPaymentInstructions();
injectPaymentButtonHtml();
window.onPayButtonClicked = onPayButtonClicked.bind(this);
getOrCheckInvoice(true).then(function (d) {
handleInvoiceData(d, {backgroundCheck: true})