FoxPro and .NET Interop
wwDotnetBridge + TransbankPosSDK.dll
Gravatar is a globally recognized avatar based on your email address. wwDotnetBridge + TransbankPosSDK.dll
  mariano
  All
  Dec 7, 2022 @ 07:34am

Hi, I can't access any method of this dll (https://github.com/TransbankDevelopers/transbank-sdk-dotnet). Could you help me ?

I just need an example of how to start.

DO wwUtils
do wwDotNetBridge
LOCAL loBridge as wwDotNetBridge
loBridge = CreateObject("wwDotNetBridge","V4")
lobridge.loadassembly("TransbankPosSDK.dll")
loPOSIntegrado = loBridge.CreateInstance("Transbank.POSIntegrado.POSIntegrado")
Gravatar is a globally recognized avatar based on your email address. re: wwDotnetBridge + TransbankPosSDK.dll
  Rick Strahl
  mariano
  Dec 8, 2022 @ 02:58pm

We're not going to do your work for you with your business specific example.

Please: Provide some working code or code that fails with precise examples and/or a reference to what .NET functions you're trying to call and we can try to give you more information on what you can try.

Nobody here is going to go through the steps to clone a repo and install a library locally just to test your code for you unless you want to pay for support so you can have "just an example of how to start".

+++ Rick ---

Gravatar is a globally recognized avatar based on your email address. re: wwDotnetBridge + TransbankPosSDK.dll
  mariano
  Rick Strahl
  Dec 12, 2022 @ 11:55am

Hello, expression "just an example of how to start" was not for them to do my job but it would not be the first time q I do not see a mistake in front of my eyes.

My problem is that following the examples and having the library registered. When I run

lobridge.loadassembly("TransbankPosSDK.dll") 
loCallBack = CREATEOBJECT("MyCallback")
loPOSIntegrado = loBridge.CreateInstance("Transbank.POSIntegrado.POSIntegrado")
DEFINE CLASS MyCallback as custom 

*** Returns the result of the method and the name of the method name
FUNCTION OnCompleted(lvResult,lcMethod)
? "Success: " + lcMethod,lvResult
ENDFUNC


* Returns an error message, a .NET Exception and the method name
FUNCTION OnError(lcMessage,loException,lcMethod)
? "Error: " + lcMethod,lcMessage
ENDFUNC

ENDDEFINE

I don't get any error. loPOSIntegrated is type object but has no visible properties or methods.

I try to access this code. public async Task Sale(int amount, string ticket, bool sendStatus = false)

loBridge.InvokeMethodAsync(loCallback,loPOSIntegrado,"Sale",12345)

namespace Transbank.POSIntegrado
{
    public class POSIntegrado : Serial
    {
        public POSIntegrado()
        {
            
        }

        public static POSIntegrado Instance { get; } = new POSIntegrado();
        
        public async Task<SaleResponse> Sale(int amount, string ticket, bool sendStatus = false)

Gravatar is a globally recognized avatar based on your email address. re: wwDotnetBridge + TransbankPosSDK.dll
  Rick Strahl
  mariano
  Dec 12, 2022 @ 07:24pm

You have to pass all the parameters to the method. No such thing as optional parameters when calling with Reflection via wwDotnetBridge.

+++ Rick ---

Gravatar is a globally recognized avatar based on your email address. re: wwDotnetBridge + TransbankPosSDK.dll
  mariano
  mariano
  Dec 15, 2022 @ 12:00pm

Hi, One step and new error 😦

Cannot load file or assembly 'System.IO.Ports, Version=4.0.1.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51' or one of its dependencies. The system cannot find the specified file.

I have the dll registered. I tried copy to system32 didn't work, SysWOW64 didn't work either. What can be? I keep investigating.

Gravatar is a globally recognized avatar based on your email address. re: wwDotnetBridge + TransbankPosSDK.dll
  Rick Strahl
  mariano
  Dec 15, 2022 @ 12:18pm

System.IO.Ports is a built-in .NET assembly that lives in the GAC. It should be referenced by the API you're calling unless you are accessing a type in that namespace directly in your code, in which case you have to reference the GAC assembly via its fully qualified assembly name or the path in the GAC folder.

The fully qualified assembly name is the name in the error message.

+++ Rick ---

Gravatar is a globally recognized avatar based on your email address. re: wwDotnetBridge + TransbankPosSDK.dll
  mariano
  Rick Strahl
  Dec 28, 2022 @ 12:02pm

Hi, New problem Delete system.io.ports from my project, install same and diferent version but doesnt work.

Gravatar is a globally recognized avatar based on your email address. re: wwDotnetBridge + TransbankPosSDK.dll
  Rick Strahl
  mariano
  Dec 29, 2022 @ 11:04am

What is the full error message? It looks like you're running on a non-supported version of Windows?

+++ Rick ---

Gravatar is a globally recognized avatar based on your email address. re: wwDotnetBridge + TransbankPosSDK.dll
  Alberto Meneses
  mariano
  Apr 19, 2023 @ 12:18pm

Hi Mariano, Rick,

Please can you help me, I am getting an error:

Constructor on type 'Transbank.POSIntegrado.POSIntegrado' not found

I am using this code:

CLEAR

SET STEP ON

SET DEFAULT TO c:\foxware\wwdotnetbridge-master\Examples

DO wwUtils

do wwDotNetBridge

LOCAL loBridge as wwDotNetBridge

loBridge = CreateObject("wwDotNetBridge","V4")

? loBridge.LoadAssembly("TransbankPosSDK.dll")

loPop = loBridge.CreateInstance("Transbank.POSIntegrado.POSIntegrado")

IF ISNULL(loPop)

? loBridge.cErrorMsg

RETURN

ENDIF

best regards Alberto

Gravatar is a globally recognized avatar based on your email address. re: wwDotnetBridge + TransbankPosSDK.dll
  Rick Strahl
  Alberto Meneses
  Apr 19, 2023 @ 02:02pm

Look up the .NET syntax for the constructor. Constructor probably has parameters that are required.

Please read the White Paper or documentation on how you can look up Dotnet Syntax using a decompiler.

ps.
Please format your code. RTFM on the bottom of the input box!

+++ Rick ---

Gravatar is a globally recognized avatar based on your email address. re: wwDotnetBridge + TransbankPosSDK.dll
  Alberto Meneses
  Rick Strahl
  Apr 19, 2023 @ 04:33pm

Hi, I decompile the Dll and the constructor has not parameters, see please:

using System; using System.Collections.Generic; using System.Threading.Tasks; using Transbank.Exceptions.CommonExceptions; using Transbank.Exceptions.IntegradoExceptions; using Transbank.Responses.CommonResponses; using Transbank.Responses.IntegradoResponses; using Transbank.Utils;

namespace Transbank.POSIntegrado { public class POSIntegrado : Serial { private POSIntegrado() { }

public static Transbank.POSIntegrado.POSIntegrado Instance { get; } = new Transbank.POSIntegrado.POSIntegrado();

public async Task<SaleResponse> Sale(
  int amount,
  string ticket,
  bool sendStatus = false)
{
Gravatar is a globally recognized avatar based on your email address. re: wwDotnetBridge + TransbankPosSDK.dll
  Alberto Meneses
  Alberto Meneses
  Apr 19, 2023 @ 04:37pm

Sorry, I hope the code is well formatted, as you can see the constructor has no parametres:


using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Transbank.Exceptions.CommonExceptions;
using Transbank.Exceptions.IntegradoExceptions;
using Transbank.Responses.CommonResponses;
using Transbank.Responses.IntegradoResponses;
using Transbank.Utils;

namespace Transbank.POSIntegrado
{
  public class POSIntegrado : Serial
  {
    private POSIntegrado()
    {
    }

    public static Transbank.POSIntegrado.POSIntegrado Instance { get; } = new Transbank.POSIntegrado.POSIntegrado();

    public async Task<SaleResponse> Sale(
      int amount,
      string ticket,
      bool sendStatus = false)
    {...}

Gravatar is a globally recognized avatar based on your email address. re: wwDotnetBridge + TransbankPosSDK.dll
  Rick Strahl
  Alberto Meneses
  Apr 19, 2023 @ 07:41pm

Class only has a private constructor, so it can't be instatiated via its constructor. Looks like a it has a static Singleton.

Use GetStaticProperty() to retrieve POSIntegrado.Instance.

+++ Rick ---

Gravatar is a globally recognized avatar based on your email address. re: wwDotnetBridge + TransbankPosSDK.dll
  Alberto Meneses
  Rick Strahl
  Apr 20, 2023 @ 04:40am

**Hi, If it is necessary to pay your assistance, no problem.

Here is the complete code of a class that I need to CretateInstance() using vfp: **

? loBridge.LoadAssembly("TransbankPosSDK.dll")
loPop = loBridge.Createinstance("Transbank.POSIntegrado.InicializaPuerto","COM6")

C# class

using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Transbank.Exceptions.CommonExceptions;
using Transbank.Exceptions.IntegradoExceptions;
using Transbank.Responses.CommonResponses;
using Transbank.Responses.IntegradoResponses;
using Transbank.Utils;

namespace Transbank.POSIntegrado
{
  public class POSIntegrado : Serial
  {
    private POSIntegrado()
    {
    }

    public static Transbank.POSIntegrado.POSIntegrado Instance { get; } = new Transbank.POSIntegrado.POSIntegrado();

    public async Task<SaleResponse> Sale(
      int amount,
      string ticket,
      bool sendStatus = false)
    {
      Transbank.POSIntegrado.POSIntegrado posIntegrado = this;
      if (amount < 50)
        throw new TransbankSaleException("Amount must be greater than 50.");
      if (amount > 999999999)
        throw new TransbankSaleException("Amount must be less than 999999999.");
      string message = string.Format("\x00020200|{0}|{1}|||{2}|\x0003", (object) amount, (object) ticket, (object) Convert.ToInt32(sendStatus));
      SaleResponse saleResponse;
      try
      {
        await posIntegrado.WriteData(posIntegrado.MessageWithLRC(message), sendStatus);
        saleResponse = new SaleResponse(posIntegrado.CurrentResponse);
      }
      catch (Exception ex)
      {
        throw new TransbankSaleException("Unable to execute sale on pos", ex);
      }
      return saleResponse;
    }

    public async Task<MultiCodeSaleResponse> MultiCodeSale(
      int amount,
      string ticket,
      long commerceCode = 0,
      bool sendStatus = false)
    {
      Transbank.POSIntegrado.POSIntegrado posIntegrado = this;
      if (amount < 50)
        throw new TransbankMultiCodeSaleException("Amount must be greater than 50.");
      if (amount > 999999999)
        throw new TransbankMultiCodeSaleException("Amount must be less than 999999999.");
      if (ticket.Length != 6)
        throw new TransbankSaleException("Ticket must be 6 characters.");
      string str = commerceCode != 0L ? commerceCode.ToString() : "";
      string message = string.Format("\x00020270|{0}|{1}|| |{2}|{3}|\x0003", (object) amount, (object) ticket, (object) Convert.ToInt32(sendStatus), (object) str);
      MultiCodeSaleResponse codeSaleResponse;
      try
      {
        await posIntegrado.WriteData(posIntegrado.MessageWithLRC(message), sendStatus);
        codeSaleResponse = new MultiCodeSaleResponse(posIntegrado.CurrentResponse);
      }
      catch (Exception ex)
      {
        throw new TransbankMultiCodeSaleException("Unable to execute multicode sale on pos", ex);
      }
      return codeSaleResponse;
    }

    public async Task<LastSaleResponse> LastSale()
    {
      Transbank.POSIntegrado.POSIntegrado posIntegrado = this;
      LastSaleResponse lastSaleResponse;
      try
      {
        await posIntegrado.WriteData("\x00020250|\x0003x");
        lastSaleResponse = new LastSaleResponse(posIntegrado.CurrentResponse);
      }
      catch (Exception ex)
      {
        throw new TransbankLastSaleException("Unable to recover last sale from pos", ex);
      }
      return lastSaleResponse;
    }

    public async Task<MultiCodeLastSaleResponse> MultiCodeLastSale(
      bool getVoucherInfo)
    {
      Transbank.POSIntegrado.POSIntegrado posIntegrado = this;
      MultiCodeLastSaleResponse lastSaleResponse;
      try
      {
        string message = string.Format("\x00020280|{0}\x0003", (object) Convert.ToInt32(getVoucherInfo));
        await posIntegrado.WriteData(posIntegrado.MessageWithLRC(message));
        lastSaleResponse = new MultiCodeLastSaleResponse(posIntegrado.CurrentResponse);
      }
      catch (Exception ex)
      {
        throw new TransbankMultiCodeLastSaleException("Unable to recover last sale from pos", ex);
      }
      return lastSaleResponse;
    }

    public async Task<RefundResponse> Refund(int operationID)
    {
      Transbank.POSIntegrado.POSIntegrado posIntegrado = this;
      string message = string.Format("\x00021200|{0}|\x0003", (object) operationID);
      RefundResponse refundResponse;
      try
      {
        await posIntegrado.WriteData(posIntegrado.MessageWithLRC(message));
        refundResponse = new RefundResponse(posIntegrado.CurrentResponse);
      }
      catch (Exception ex)
      {
        throw new TransbankRefundException("Unable to make Refund on POS", ex);
      }
      return refundResponse;
    }

    public async Task<TotalsResponse> Totals()
    {
      Transbank.POSIntegrado.POSIntegrado posIntegrado = this;
      TotalsResponse totalsResponse;
      try
      {
        await posIntegrado.WriteData("\x00020700||\x0003\x0004");
        totalsResponse = new TotalsResponse(posIntegrado.CurrentResponse);
      }
      catch (Exception ex)
      {
        throw new TransbankTotalsException("Unable to get totals from POS", ex);
      }
      return totalsResponse;
    }

    public async Task<List<DetailResponse>> Details(bool printOnPOS = true)
    {
      Transbank.POSIntegrado.POSIntegrado posIntegrado = this;
      string message = string.Format("\x00020260|{0}|\x0003", (object) Convert.ToInt32(!printOnPOS));
      List<DetailResponse> details = new List<DetailResponse>();
      try
      {
        await posIntegrado.WriteData(posIntegrado.MessageWithLRC(message), saleDetail: true, printOnPOS: printOnPOS);
        foreach (string detail in posIntegrado.SaleDetail)
          details.Add(new DetailResponse(detail));
      }
      catch (Exception ex)
      {
        throw new TransbankSalesDetailException("Unabel to request sale detail on pos", ex);
      }
      List<DetailResponse> detailResponseList = details;
      details = (List<DetailResponse>) null;
      return detailResponseList;
    }

    public async Task<List<MultiCodeDetailResponse>> MultiCodeDetails(
      bool printOnPOS = true)
    {
      Transbank.POSIntegrado.POSIntegrado posIntegrado = this;
      string message = string.Format("\x00020260|{0}|\x0003", (object) Convert.ToInt32(!printOnPOS));
      List<MultiCodeDetailResponse> details = new List<MultiCodeDetailResponse>();
      try
      {
        await posIntegrado.WriteData(posIntegrado.MessageWithLRC(message), saleDetail: true, printOnPOS: printOnPOS);
        foreach (string detail in posIntegrado.SaleDetail)
          details.Add(new MultiCodeDetailResponse(detail));
      }
      catch (Exception ex)
      {
        throw new TransbankMultiCodeDetailException("Unabel to request sale detail on pos", ex);
      }
      List<MultiCodeDetailResponse> codeDetailResponseList = details;
      details = (List<MultiCodeDetailResponse>) null;
      return codeDetailResponseList;
    }

    public async Task<CloseResponse> Close()
    {
      Transbank.POSIntegrado.POSIntegrado posIntegrado = this;
      CloseResponse closeResponse;
      try
      {
        await posIntegrado.WriteData("\x00020500||\x0003\x0006");
        closeResponse = new CloseResponse(posIntegrado.CurrentResponse);
      }
      catch (Exception ex)
      {
        throw new TransbankCloseException("Unable to execute close in pos", ex);
      }
      return closeResponse;
    }

    public async Task<LoadKeysResponse> LoadKeys()
    {
      Transbank.POSIntegrado.POSIntegrado posIntegrado = this;
      LoadKeysResponse loadKeysResponse;
      try
      {
        await posIntegrado.WriteData("\x00020800\x0003\v");
        loadKeysResponse = new LoadKeysResponse(posIntegrado.CurrentResponse);
      }
      catch (Exception ex)
      {
        throw new TransbankLoadKeysException("Unable to execute Load Keys in pos", ex);
      }
      return loadKeysResponse;
    }

    public async Task<bool> Poll()
    {
      Transbank.POSIntegrado.POSIntegrado posIntegrado = this;
      Serial.Port.DiscardInBuffer();
      Serial.Port.DiscardOutBuffer();
      if (posIntegrado.CantWrite())
        throw new TransbankException("Unable to Poll port " + Serial.Port.PortName + " is closed");
      bool flag;
      try
      {
        byte[] buffer = new byte[1];
        string text = "\x00020100\x0003\x0002";
        Console.WriteLine("Out (Hex): " + posIntegrado.ToHexString(text));
        Console.WriteLine("Out (ASCII): " + text);
        Serial.Port.Write(text);
        int num = await Serial.Port.BaseStream.ReadAsync(buffer, 0, 1);
        flag = posIntegrado.CheckACK(buffer[0]);
      }
      catch (Exception ex)
      {
        throw new TransbankException("Unable to send Poll command on port " + Serial.Port.PortName, ex);
      }
      return flag;
    }

    public async Task<bool> SetNormalMode()
    {
      Transbank.POSIntegrado.POSIntegrado posIntegrado = this;
      Serial.Port.DiscardInBuffer();
      Serial.Port.DiscardOutBuffer();
      if (posIntegrado.CantWrite())
        throw new TransbankException("Unable to Set Normal Mode port " + Serial.Port.PortName + " is closed");
      bool flag;
      try
      {
        byte[] buffer = new byte[1];
        string text = "\x00020300\x0003\0";
        Console.WriteLine("Out (Hex): " + posIntegrado.ToHexString(text));
        Console.WriteLine("Out (ASCII): " + text);
        Serial.Port.Write(text);
        int num = await Serial.Port.BaseStream.ReadAsync(buffer, 0, 1);
        flag = posIntegrado.CheckACK(buffer[0]);
      }
      catch (Exception ex)
      {
        throw new TransbankException("Unable to send Normal Mode command on port " + Serial.Port.PortName, ex);
      }
      return flag;
    }
  }
}

Gravatar is a globally recognized avatar based on your email address. re: wwDotnetBridge + TransbankPosSDK.dll
  Rick Strahl
  Alberto Meneses
  Apr 20, 2023 @ 08:12am

For paid support you can contact me privately. More info here:

Contact - Paid Support

+++ Rick ---

© 1996-2024