/** Updated for E2E Status: Should be functional once device is available */ private function send_auth($domain = "w1.mercurypay.com") { // initialize $dbTrans = PaycardLib::paycard_db(); if (!$dbTrans) { PaycardLib::paycard_reset(); // database error, nothing sent (ok to retry) return $this->setErrorMsg(PaycardLib::PAYCARD_ERR_NOSEND); } $request = new PaycardRequest($this->refnum(CoreLocal::get('paycard_id'))); $request->setProcessor('MercuryE2E'); if (CoreLocal::get("paycard_voiceauthcode") != "") { $request->setMode("VoiceAuth"); } else { if (CoreLocal::get("ebt_authcode") != "" && CoreLocal::get("ebt_vnum") != "") { $request->setMode("Voucher"); } } $termID = $this->getTermID(); $password = $this->getPw(); $mcTerminalID = CoreLocal::get('PaycardsTerminalID'); if ($mcTerminalID === '') { $mcTerminalID = CoreLocal::get('laneno'); } $e2e = EncBlock::parseEncBlock(CoreLocal::get("paycard_PAN")); $pin = EncBlock::parsePinBlock(CoreLocal::get("CachePinEncBlock")); $request->setIssuer($e2e['Issuer']); CoreLocal::set('paycard_issuer', $e2e['Issuer']); $request->setCardholder($e2e['Name']); $request->setPAN($e2e['Last4']); CoreLocal::set('paycard_partial', false); $request->setSent(0, 0, 0, 1); // store request in the database before sending it try { $request->saveRequest(); } catch (Exception $ex) { PaycardLib::paycard_reset(); // internal error, nothing sent (ok to retry) return $this->setErrorMsg(PaycardLib::PAYCARD_ERR_NOSEND); } // weird string concat here so vim's color highlighting // doesn't screw up with what LOOKS LIKE a close-PHP tag $msgXml = '<?xml version="1.0"?' . '> <TStream> <Transaction> <MerchantID>' . $termID . '</MerchantID> <OperatorID>' . $request->cashierNo . '</OperatorID> <LaneID>' . $mcTerminalID . '</LaneID>'; if (substr($request->type, 0, 3) == 'EBT') { $msgXml .= '<TranType>EBT</TranType>'; if ($request->type == 'EBTFOOD') { CoreLocal::set('EbtFsBalance', 'unknown'); $request->msgXml .= '<CardType>Foodstamp</CardType>'; } else { if ($request->type == 'EBTCASH') { $msgXml .= '<CardType>Cash</CardType>'; CoreLocal::set('EbtCaBalance', 'unknown'); } } } else { $msgXml .= '<TranType>' . $request->type . '</TranType>'; } $msgXml .= '<TranCode>' . $request->mode . '</TranCode> <InvoiceNo>' . $request->refNum . '</InvoiceNo> <RefNo>' . $request->refNum . '</RefNo> <Memo>CORE POS 1.0.0</Memo>'; if ($request->type == 'Credit' && $request->mode == 'Sale') { $msgXml .= "<PartialAuth>Allow</PartialAuth>"; } $msgXml .= '<RecordNo>RecordNumberRequested</RecordNo>'; $msgXml .= '<Frequency>OneTime</Frequency>'; $msgXml .= '<Account> <EncryptedFormat>' . $e2e['Format'] . '</EncryptedFormat> <AccountSource>' . ($request->manual ? 'Keyed' : 'Swiped') . '</AccountSource> <EncryptedBlock>' . $e2e['Block'] . '</EncryptedBlock> <EncryptedKey>' . $e2e['Key'] . '</EncryptedKey> </Account> <Amount> <Purchase>' . $request->formattedAmount() . '</Purchase>'; if ($request->cashback > 0 && ($request->type == "Debit" || $request->type == "EBTCASH")) { $msgXml .= "<CashBack>" . $request->formattedCashBack() . "</CashBack>"; } $msgXml .= "</Amount>"; if ($request->type == "Debit" || substr($request->type, 0, 3) == "EBT" && $request->mode != "Voucher") { $msgXml .= "<PIN>\n <PINBlock>" . $pin['block'] . "</PINBlock>\n <DervdKey>" . $pin['key'] . "</DervdKey>\n </PIN>"; } if (CoreLocal::get("paycard_voiceauthcode") != "") { $msgXml .= "<TransInfo>"; $msgXml .= "<AuthCode>"; $msgXml .= CoreLocal::get("paycard_voiceauthcode"); $msgXml .= "</AuthCode>"; $msgXml .= "</TransInfo>"; } else { if (CoreLocal::get("ebt_authcode") != "" && CoreLocal::get("ebt_vnum") != "") { $msgXml .= $this->ebtVoucherXml(); } } $msgXml .= "</Transaction>\n </TStream>"; $soaptext = $this->soapify("CreditTransaction", array("tran" => $msgXml, "pw" => $password), "http://www.mercurypay.com"); /** In switched mode, use the backup URL first then retry on the primary URL Switched mode is triggered when a request to the primary URL fails with some kind of cURL error and the subsequent request to the backup URL succeeds. The idea is to use the backup URL for a few transactions before trying the primary again. The most common error is a timeout and waiting 30 seconds for the primary to fail every single transaction isn't ideal. */ if (CoreLocal::get('MercurySwitchUrls') > 0) { if (!$this->second_try) { $domain = self::BACKUP_URL; } else { $domain = self::PRIMARY_URL; } } else { if (!$this->second_try) { $domain = self::PRIMARY_URL; } else { $domain = self::BACKUP_URL; } } /** SwitchUrls is a counter Go back to normal order when it reaches zero */ if (CoreLocal::get('MercurySwitchUrls') > 0) { $switch_count = CoreLocal::get('MercurySwitchUrls'); $switch_count--; CoreLocal::set('MercurySwitchUrls', $switch_count); } if (CoreLocal::get("training") == 1) { $this->GATEWAY = "https://w1.mercurydev.net/ws/ws.asmx"; } else { $this->GATEWAY = "https://{$domain}/ws/ws.asmx"; } $this->last_request = $request; return $this->curlSend($soaptext, 'SOAP'); }