Create a Credit Card Sales Order in Sage 100 ProvideX, C# using SO_SalesOrderPayment_bus business object?

SOLVED

I have recently found how to add a new credit card to Sage100 and the exchange vault without using the exchange vault’s extra UI, screen.  I insert new cards into the system behind the scenes using my own custom windows software written in C#.  I now need to create credit card sales orders but ran into some problems with setting the card specifics. 

I am not making a website or web services.  I am closely emulating the Sage 100 client interface with my custom software and ProvideX or pvx code and the BOI business objects 

How do I create a salesorder / credit card payment record now that the sage exchange vault is involved?  In other words, I used to be able to invoke the sales order header and detail business objects and set the lines and payment details and write that into Sage/MAS. 

No longer is payment information set in the header / detail objects (or SQL tables).  Instead it looks like there is a new SO_SalesOrderPayment_bus.pvc that will deal with the card…and its expiration and bank name and many many other things…yet it is not apparent which of those fields MUST be set, and what is the correct order of operations? 

Is this right?  Is there any documentation on how to do this? (required fields & order of operations)  I can show how I have been doing it with MAS200.  In a follow-up post, I will show how we are currently placing credit card orders using external code BOI / pvx for MAS 200 ver 4.5.  Please assist me in understanding how to do the same for Sage 100 ver 5.4

  • 0

    //I have simplified (truncated) the code to make it readable in this post.
    //First, Sales Order Header and Detail are invoked
    SO_Header_Bus = pvx.GetType().InvokeMember("NewObject", System.Reflection.BindingFlags.InvokeMethod, null, pvx, new object[] { "SO_SalesOrder_bus", oSS });
    SO_Detail_Bus = SO_Header_Bus.GetType().InvokeMember("oLines", System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.GetProperty, SO_Header_Bus);
    //Get new order number to work with and set it
    pvxGetParam(SO_Header_Bus, "GetNextSalesOrderNo", out sNextOrderNo, out sLastErrorMsg);
    pvxSetParam(SO_Header_Bus, "SetKey", sNextOrderNo, out sLastErrorMsg);
    //Other parts of the order are set
    pvxSetString(SO_Header_Bus, "OrderType$", sOrderType, out sLastErrorMsg);
    pvxSetString(SO_Header_Bus, "ARDivisionNo$", sDivNo, out sLastErrorMsg);
    pvxSetString(SO_Header_Bus, "CustomerNo$", sCustNo, out sLastErrorMsg);
    pvxSetString(SO_Header_Bus, "SalespersonDivisionNo$", sSPDivNo, out sLastErrorMsg);
    pvxSetString(SO_Header_Bus, "SalespersonNo$", sSPNo, out sLastErrorMsg);
    pvxSetString(SO_Header_Bus, "CustomerPONo$", sCustomerPONO, out sLastErrorMsg);
    //!!here is the payment information stuff …
    //
    //THIS WOULD BE "CreditCardGUID$" NOW BUT ITS NOT IN THE SALES ORDER HEADER OR DETAILS
    pvxSetString(SO_Header_Bus, "EncryptedCreditCardNo$", sCreditEncryp, out sLastErrorMsg); //"CreditCardGUID$" error ‘column not on the IO list’
    pvxSetString(SO_Header_Bus, "ExpirationDateMonth$", sCreditExpMonth, out sLastErrorMsg);
    pvxSetString(SO_Header_Bus, "ExpirationDateYear$", sCreditExpYear, out sLastErrorMsg);
    pvxSetString(SO_Header_Bus, "TermsCode$", sPaymentTerms, out sLastErrorMsg);
    pvxSetString(SO_Header_Bus, "ShipToCode$", sShipToCode, out sLastErrorMsg);
    pvxSetString(SO_Header_Bus, "PaymentType$", sPaymentType, out sLastErrorMsg);
    //Order detail stuff, not important…just showing a bit for context
    pvxNoParam(SO_Detail_Bus, "AddLine", out sLastErrorMsg);
    pvxSetString(SO_Detail_Bus, "ItemCode$", sItemCode, out sLastErrorMsg);
    //Write Details
    pvxNoParam(SO_Detail_Bus, "Write", out sLastErrorMsg);
    //Write Header
    pvxNoParam(SO_Header_Bus, "Write", out sLastErrorMsg)

    ==========================

    As you can see from the above, EncryptedCreditCardNo used to be in the sales order header business object.  

    The new field is CreditCardGUID but it is not in the SO header.  Instead, it is in the SO Payment business object.  

    I should think that I must additionally invoke the new payment object but where?  and what fields must be used?  In the SQL database, the primary key fields are SalesOrderNo and PaymentSeqNo.  There must be a "getnextpaymentseqno" function?  What is it?  What credit card fields must I then set? thanks

  • +1
    verified answer

    //So I got it to work.  I can now just automate batch sales orders with various credit cards
    //You must Invoke the Sales Order Header business object first, then invoke a SO detail object using the name ‘oLines’, then the new thing you have to do is use the header object again to invoke a SO payment business object using the name ‘oPaymentObj’. Some of the Header object’s variables are moved into the Payment object. Also the Payment object needs to make a new record or to be used to invoke ‘nAddPayment’ so that variables related to the credit card may be set.

    //I have simplified (truncated) the code to make it readable in this post.
    //First, Sales Order Header and Detail are invoked
    SO_Header_Bus = pvx.GetType().InvokeMember("NewObject", System.Reflection.BindingFlags.InvokeMethod, null, pvx, new object[] { "SO_SalesOrder_bus", oSS });
    SO_Detail_Bus = SO_Header_Bus.GetType().InvokeMember("oLines", System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.GetProperty, SO_Header_Bus);
    SO_Payment_Bus = SO_Header_Bus.GetType().InvokeMember("oPaymentObj", System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.GetProperty, SO_Header_Bus);


    So now the differences between MAS200 and SAGE100 (with the Exchange Vault) and my previous post are these:
    if (creditCardTransaction){
    pvxNoParam(SO_Payment_Bus, "AddPayment", out sLastErrorMsg);
    pvxSetString(SO_Payment_Bus, "CreditCardGUID$", sCreditEncryp, out sLastErrorMsg);
    pvxSetString(SO_Payment_Bus, "ExpirationDateMonth$", sCreditExpMonth, out sLastErrorMsg);
    pvxSetString(SO_Payment_Bus, "ExpirationDateYear$", sCreditExpYear, out sLastErrorMsg);}
    pvxSetString(SO_Header_Bus, "TermsCode$", sPaymentTerms, out sLastErrorMsg);
    pvxSetString(SO_Header_Bus, "ShipToCode$", sShipToCode, out sLastErrorMsg);
    pvxSetString(SO_Payment_Bus, "PaymentType$", sPaymentType, out sLastErrorMsg);
    //…and so on

    //and finally, Here is how I invoked the objects
    pvx = System.Activator.CreateInstance(Type.GetTypeFromProgID("ProvideX.Script", true));
    pvx.GetType().InvokeMember("Init", System.Reflection.BindingFlags.InvokeMethod, null, pvx, new object[] { MAS90Path });
    oSS = pvx.GetType().InvokeMember("NewObject", System.Reflection.BindingFlags.InvokeMethod, null, pvx, new object[] { "SY_Session" });
    //pvx and oSS are just base System.Object objects
    //just FYI: public object InvokeMember(string name, BindingFlags invokeAttr, Binder binder, object target, object[] args);
    //So the secret sauce is that “string name” which is why I had been asking all these months for help / documentation but I never got any, I just brute force guessed.