Announcement

Collapse
No announcement yet.

Need a little advice with the JSON_API module integration

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

    Need a little advice with the JSON_API module integration

    So I'm trying to add JSON-API module integration to our own module. There are a few features not in the JSON API now that we have independent .mvc scripts do, that don't work with database encryption. The sample gave enough information that I was able to get the module function recognized as valid when making a API call, but neither of the two examples provided in the integration guide pass information to the function. I've tried a few things to pass a part number to the function (I'm looking to return the sum of the basket inventories for a single product), but have not had much luck. And what I thought might allow me to just do some simple things like return the input value have so far failed as well.

    Is anyone passing anything to a module API integration and willing to share an example? I have so far added the json_api feature to the l.module:features of the Module_Description function, have our function included in the Module_JSON_API function, and our own function written. But all I'm getting for a response from calling our function is an empty string. I'm passing l.module to it, but clearly that isn't the right parameter, or I need to add others. Ultimately, what I'm hoping to pass at the end of the JSON call is "Module_Function":"GetBaskInventory","Product_Code ":"SampleProduct".

    #2
    Did you set up an API token, and give it permission for the Module function?

    I've written a module or two that use json_api. When I have trouble debugging something like that, I put in some MvEXPORT tags to write to a log file. My first goal would be to find out if the Module_JSON_API function is getting called; and if not, figure out what's wrong with the hookup.

    If Module_JSON_API is being called, you can use your log to see what data is being passed:
    Code:
    <MvFUNCTION NAME="Module_JSON_API" PARAMETERS="module VAR, function" STANDARDOUTPUTLEVEL="">
        <MvASSIGN NAME="l.xx" VALUE="{ WriteLog('Inbound request to ' $ s.documentURL $ s.query_string) }">
        <MvASSIGN NAME="l.xx" VALUE="{ WriteLog('Inbound request text: ' $ s.content_data) }">
    ...
    WriteLog() is just a wrapper function that puts a time stamp at the front of the text, and also lets me turn logging on and off by an admin setting.

    I learned most of what I know from the LSK. There are several modules in there that use json_api.
    Kent Multer
    Magic Metal Productions
    http://TheMagicM.com
    * Web developer/designer
    * E-commerce and Miva
    * Author, The Official Miva Web Scripting Book -- available on-line:
    http://www.amazon.com/exec/obidos/IS...icmetalproducA

    Comment


      #3
      Thank you for your advice. Yes, I did set up a token and have the permissions set. I can access all of the standard Miva API functions, and have several functions on my local end working to push/pull data from the site already. Now I'm venturing into the module integration so I can add functionality not currently accessible through the standard API. The log is a good idea, and I really appreciate the example you provided. That is the piece I'm likely missing - the proper parameters and how to unpack them. I have dug through the LSK to some degree, and have found a few tips in there, but I'm far from familiar with it, and of course with very few comments in it, it is always a situation of trying to make (hopefully) educated guesses about why some things are done in there.

      Comment


        #4
        I finally have a working version. I'm sharing it just in case someone else dives down this rabbit hole that doesn't do this on a daily basis. Though I suppose the group of us that write modules for our own purposes vs. for hire or for sale is a small group. Constructive criticism is welcome. I'm a Mechanical Engineer, not a Software Engineer. I'm great at making things work, but would probably make a lot of professional software people cringe.

        If there is a better or more elegant way to retrieve the "Part_Number" data, I'd be happy to know. I had to dig a while to find at least one spot where it lived in a reasonable form since several of the functions in the LSK aren't globally available.

        The call is (some information redacted):
        { "Miva_Request_Timestamp":1714878393,"Store_code":" xxx","Function":"Module","Module_Code":"xxx","Modu le_Function":"GetBaskInventory","Part_Number":"001 07"}

        Code:
        Code:
        <MvFUNCTION NAME = "JSON_API_GetBaskInventory" PARAMETERS = "module var" STANDARDOUTPUTLEVEL = "text, html, compresswhitespace">
        <MvComment> Get the part number from the input </MvComment>
        <MvAssign Name="l.PartNo" Value="{g.Session:json_api_operation:Part_Number}" >
        <MvIF Expr="{l.PartNo EQ ''}">
        <MvFUNCTIONRETURN VALUE = "{ [ g.Library_Utilities ].Error( 'partdata', 'Product not found' ) }">
        </MvIF>
        
        <MvComment> Find the sum of the basket inventory for the part number </MvComment>
        <MvAssign Name="l.query" value="{'SELECT Sum(Quantity) AS total FROM `s02_BasketItems` GROUP BY `code` HAVING `code`= ?'}">
        <MvOPENVIEW NAME="Merchant" VIEW="basketinv" QUERY="{l.query}" FIELDS="l.PartNo">
        <MvIF EXPR = "{ MvOPENVIEW_ERROR }" >
        <MvFUNCTIONRETURN VALUE = "{ [ g.Library_Utilities ].Error( 'partdata', 'Failed to open query' ) }">
        <MvELSEIF EXPR = "{ basketinv.d.eof }">
        <MvAssign Name="l.BaskInv" Value="0">
        <MvElse>
        <MvAssign Name="l.BaskInv" Value="{int(basketinv.d.total)}">
        <MvCLOSEVIEW NAME="Merchant" VIEW="basketinv">
        </MvIF>
        
        <MvEVAL EXPR = "{ [ g.Module_JSON ].JSON_Response_Start() }">
        {"BaskInv" : "<MvEval Expr="{l.BaskInv}">"}
        <MvFUNCTIONRETURN VALUE = "{ [ g.Module_JSON ].JSON_Response_End() }">
        </MvFUNCTION>

        Comment


          #5
          Glad you got it working! Your code looks decent for a newcomer; I'm not cringing. :^) I suggest that you use indentation for the nested code inside the MvIFs. It makes the code easier to read, and also makes it more obvious when you leave out a closing tag such as /MvIF.

          I do see a possible problem with the SQL query. The way it's written, it will produce the total quantity of the product in baskets for all active shopping sessions. Depending on how you run your store, it might also include expired baskets. Is that what you had in mind? If you want to restrict it to a single customer, you need to include a basket ID or customer ID in the query.
          Kent Multer
          Magic Metal Productions
          http://TheMagicM.com
          * Web developer/designer
          * E-commerce and Miva
          * Author, The Official Miva Web Scripting Book -- available on-line:
          http://www.amazon.com/exec/obidos/IS...icmetalproducA

          Comment


            #6
            Thanks! There actually is indentation in the code. For some reason, when I set it to a code block in the forum, it removed it??? And you are correct about the query. That is actually by design. My intent was to capture the sum of a part in all active baskets. We display that in our ERP (for lack of a better term) so we can see what people have tied up when we speak to customers. We also do incremental inventory adjustments, so if we want to add one part to inventory (say, from a return), we pull the available inventory, plus the count in all active baskets, plus one to set the total inventory by the native API call. We also clean baskets out after some number of hours to prevent lower inventory count products from being tied up by stale baskets, which seems to take care of your concern about it collecting expired baskets as well. It may seem strange, but it works for us since we have largely two semi-independent inventory counts, and any mistakes usually only impact one. That way we can find them.

            But I honestly can't claim to be a newcomer. I started programming MivaScript in 2008 when we first started setting up our store. But I only do what I need to in order to accomplish what we need done, so I haven't done a lot in the last quite a few years. I'm finally digging into the API parts because we need to migrate some of our functions out of our own modules and into now available native code. It seems I have a habit of being ahead of the curve in some things. I'll write programs to do things that then some number of years later appear as features. It is a double edged sword since it is easier to use my code vs. the later available native functionality, and usually takes something stirring up trouble to make me change it...
            Last edited by BigDummy; 05-06-24, 02:16 PM.

            Comment

            Working...
            X