Updating and Deleting Payment Methods with Acumatica API -
thanks post on creating customer payment method api able create new payment method using api. can't figure out how update or delete existing payment method. there doesn't seem type of key field. i've updated , deleted contacts , locations api, contacts have contact ids, , locations have locationids. there doesn't seem paymentmethodid. thought maybe "card/account no." field might function that, wasn't able make work. , i've noticed can save 2 payment methods identical card numbers, make identical keys if field used anyway.
here's code tried updating. it's chris's code other post linked to, trying add key field update.
public function updatecreditcard(byval customerid string, byval existingacctnum string, byval paymentmethodcode string, byval ccnum string, byval expiration string, byval nameoncard string, byval active boolean) dim paymentmethod ar303010content = m_context.ar303010getschema() m_context.ar303010clear() ' main level fields dim customerval value = createvalue(paymentmethod.paymentmethodselection.customer, customerid) dim paymentmethodcodeval value = createvalue(paymentmethod.paymentmethodselection.paymentmethod, paymentmethodcode) ' inner level fields dim ccnumname value = createvalue(paymentmethod.paymentmethoddetails.description, "ccdnum") dim ccnumvalue value = createvalue(paymentmethod.paymentmethoddetails.value, ccnum, true) dim ccexpname value = createvalue(paymentmethod.paymentmethoddetails.description, "expdate") dim ccexpvalue value = createvalue(paymentmethod.paymentmethoddetails.value, expiration, true) dim ccnamename value = createvalue(paymentmethod.paymentmethoddetails.description, "nameoncc") dim ccnamevalue value = createvalue(paymentmethod.paymentmethoddetails.value, nameoncard, true) dim savecommands() command if existingacctnum = "" ' new credit card savecommands = {customerval, paymentmethod.actions.insert, paymentmethodcodeval, ccnumname, ccnumvalue, ccexpname, ccexpvalue, ccnamename, ccnamevalue, paymentmethod.actions.save} else ' existing credit card, allow update of active or expiration based on "description" dim descriptionval value = createvalue(paymentmethod.paymentmethoddetails.description, existingacctnum) dim activeval value = createvalue(paymentmethod.paymentmethodselection.active, active.tostring()) savecommands = {customerval, descriptionval, ccexpname, ccexpvalue, activeval, paymentmethod.actions.save} end if dim updateresult ar303010content() = m_context.ar303010submit(savecommands) return "" end function
another confusing part of 2 fields let user update either expiration date, or whether card active. active flag 1 of fields in list accessible customer screen, , expiration date field accessible payment method screen. if 2 different api calls, need different key field in each 1 of them?
this screen difficult use via web services few different reasons:
- there no unique key exposed via screen can use locate payment methods. internal key field named pminstanceid, , although can technically refer via web service commands, not obvious use
- in acumatica, payment method details locked once 1 transaction using payment method has been recorded. means make modifications it, need create new payment method, , set old 1 inactive.
- there's bug in screen manifests when using via web services, related item above. when loading payment method, system disable payment method details if there has been transactions, fail re-enable if not. never problem when using acumatica web browser, since fields re-enabled automatically between every round-trip. when automating screen through web services, you're performing operations in single round-trip. problem has been reported , fixed shortly (internal jira reference ac-54456)
that being said, there's few things @ our disposal can use make screen easy use web services other screens, , work around limitations. creating customization project, can add pminstanceid field (hereby referred token id field) screen. can store token on system, , use future operations payment method. within same customization project, can make payment method details enabled, allowing update expiration date on existing cards. doing resolves bug mentioned above system won't allow add new payment method system. customization has 2 parts:
- overriding
customerpaymentmethod
dac make pminstanceid field accessible ui. done appending pxuifield attribute pminstanceid field:[pxuifield(displayname="token id", visibility=pxuivisibility.selectorvisible)]
. after that, field may added screen using layout editor. handling
customerpaymentmethod_rowselected
event force payment methods details enabled. use event handler hide token id field when adding new payment method, since field otherwise showint.minvalue
until payment method has been saved. full code of event looks this:protected void customerpaymentmethod_rowselected(pxcache cache, pxrowselectedeventargs e, pxrowselected invokebasehandler) { if(invokebasehandler != null) invokebasehandler(cache, e); // force payment method details enabled facilitate working via web services pxuifieldattribute.setenabled(base.details.cache, null, true); // when adding new method, field have temporary value corresponding int.minvalue - don't show pxuifieldattribute.setvisible<customerpaymentmethod.pminstanceid>(cache, e.row, cache.getstatus(e.row) != pxentrystatus.inserted); }
once customization published, becomes far easier update existing payment methods. code below shows how can add payment method, , retrieve token id use later on update payment method:
public int addcreditcard(string customerid, string paymentmethod, string cardnumber, string expirationdate, string cvv, string nameoncard) { if(_ar303010 == null) _ar303010 = _context.ar303010getschema(); _context.ar303010clear(); var commands = new command[] { new value { value = customerid, linkedcommand = _ar303010.paymentmethodselection.customer }, new value { commit = true, linkedcommand = _ar303010.actions.insert }, new value { value = paymentmethod, linkedcommand = _ar303010.paymentmethodselection.paymentmethod }, new value { value = "ccdnum", linkedcommand = _ar303010.paymentmethoddetails.description }, new value { value = cardnumber, linkedcommand = _ar303010.paymentmethoddetails.value, commit = true }, new value { value = "expdate", linkedcommand = _ar303010.paymentmethoddetails.description }, new value { value = expirationdate, linkedcommand = _ar303010.paymentmethoddetails.value, commit = true}, new value { value = "cvv", linkedcommand = _ar303010.paymentmethoddetails.description }, new value { value = cvv, linkedcommand = _ar303010.paymentmethoddetails.value, commit = true }, new value { value = "nameoncc", linkedcommand = _ar303010.paymentmethoddetails.description }, new value { value = nameoncard, linkedcommand = _ar303010.paymentmethoddetails.value, commit = true }, _ar303010.actions.save, _ar303010.paymentmethodselection.tokenid }; var result = _context.ar303010submit(commands.toarray()); return int.parse(result[0].paymentmethodselection.tokenid.value); } public void updatecreditcardexpirationdate(string customerid, string paymentmethod, int tokenid, string expirationdate) { if (_ar303010 == null) _ar303010 = _context.ar303010getschema(); _context.ar303010clear(); var commands = new command[] { new value { value = customerid, linkedcommand = _ar303010.paymentmethodselection.customer }, new value { commit = true, linkedcommand = _ar303010.actions.insert }, new value { value = paymentmethod, linkedcommand = _ar303010.paymentmethodselection.paymentmethod }, new value { value = tokenid.tostring(), linkedcommand = _ar303010.paymentmethodselection.tokenid }, new value { value = "expdate", linkedcommand = _ar303010.paymentmethoddetails.description }, new value { value = expirationdate, linkedcommand = _ar303010.paymentmethoddetails.value, commit = true}, _ar303010.actions.save, }; var result = _context.ar303010submit(commands.toarray()); } public void makecardinactive(string customerid, string paymentmethod, int tokenid) { if (_ar303010 == null) _ar303010 = _context.ar303010getschema(); _context.ar303010clear(); var commands = new command[] { new value { value = customerid, linkedcommand = _ar303010.paymentmethodselection.customer }, new value { commit = true, linkedcommand = _ar303010.actions.insert }, new value { value = paymentmethod, linkedcommand = _ar303010.paymentmethodselection.paymentmethod }, new value { value = tokenid.tostring(), linkedcommand = _ar303010.paymentmethodselection.tokenid }, new value { value = "false", linkedcommand = _ar303010.paymentmethodselection.active }, _ar303010.actions.save, }; var result = _context.ar303010submit(commands.toarray()); }
i wrapped these 3 functions class, , actual usage becomes quite simple:
var paymentmethodmanager = new paymentmethodmanager(context); int tokenid = paymentmethodmanager.addcreditcard("abartende", "mastercard", "5111111111111118", "122016", "123", "john doe"); paymentmethodmanager.updatecreditcardexpirationdate("abartende", "mastercard", tokenid, "032017"); paymentmethodmanager.makecardinactive("abartende", "mastercard", tokenid);
as of now, not possible delete existing payment method, , must make inactive instead. i've made request enhancement, , may come in future.
note: have placed code used in answer on github @ https://github.com/gmichaud/acumatica-paymentmethod-ws-extensions.
Comments
Post a Comment