Probleme implementare plata prin card cu Mobilpay

Buna,

Incerc sa implementez plata prin card cu mobilpay

Folosesc exemplele de pe site-ul mobilpay pe care le-am implementat intr-un site php cu laravel.

Reusesc sa trimit informatii catre mobilpay , xml-ul care se genereaza si pe care il trimit spre sandbox prin POST, pare a fi ok

<?xml version="1.0" encoding="utf-8"?>\n
  <order type="card" id="ccc" timestamp="20200531100845">\n
    <signature></signature>\n
    <invoice currency="RON" amount="0.10" token_id="token_id">\n
      <details><![CDATA[Evenimenteonline_test]]></details>\n
      <contact_info>\n
        <billing type="person">\n
          <first_name><![CDATA[bostan]]></first_name>\n
          <last_name><![CDATA[doina]]></last_name>\n
          <email><![CDATA[doina.bostan%40gmail.com]]></email>\n
          <mobile_phone><![CDATA[222]]></mobile_phone>\n
        </billing>\n
      </contact_info>\n
    </invoice>\n
    <url>\n
      <return>/back</return>\n
      <confirm>/final</confirm>\n
    </url>\n
  </order>\n

Dupa ce efectuez plata cu simlatorul de card sunt redirectata in pagina de return, unde informatiile pe care le primesc prin get nu prin post si nu par a fi in regula

Folosind codul de pe site-ul mobilpay ajung in cazul
“invalid request metod for payment confirmation”
Url-ul pe care il primesc de la mobilpay este de forma
https://url-ul site-uluil/mobilpay/back?&orderId=zzzzzz
nu primesc nici parametrii de care am nevoie env_key si data
Mentionez ca in sandbox comenzile apar cu statusul “Platit” si primesc si mail de confirmare a platii

Multumesc!

poti rezolva foarte usor cu pachetul asta pentru laravel.

M-am uitat pe el. Nu prea e bine documentat

Vezi ca sunt 2 url-uri pe care tu le transmiti (sau ar trebui). Unul este return url-ul unde este redirectat userul dupa ce apasa pe inapoi la comerciant sau ceva asemanator si celalalt este confirm url unde mobilpay iti face post cu toate datele tranzactiei. Teoretic tu ar trebui in pagina de return sa verifici pe baza id-ului acela de comanda ce statusuri ai inregistrat prin confirm url.

Ca flow e ceva de genul (din ce imi amintesc):

  1. Trimiti userul catre procesator
  2. Userul completeaza detaliile cardului
  3. Mobilpay face POST in CONFIRM URL cu detaliile tranzactiei (reusita, on hold etc)
  4. Userul poate apasa pe inapoi la comerciant sau mobilpay face redirect automat la plata reusita catre RETURN URL.

Ce ar trebui sa faci tu:
Cand primesti POST pe CONFIRM url ar trebui sa salvezi detaliile tranzactiei efectuate de client pe baza id-ului de comanda.
Cand userul este redirectionat catre pagina de RETURN URL ar trebui sa ii afisezi ultimul status logat de tine pe acea comanda. Mobilpay chiar insista ca sa poti trece testele lor sa ii afisezi clientului pe acea pagina un mesaj daca tranzactia lui a fost procesata sau nu.

Din ce ai scris, tu tratezi doar RETURN url.

Buna,

Multumesc mult pentru raspuns. Eu trimit si returnUrl si confirmUrl. Obiectul care se genereaza este cam asa

^ Mobilpay_Payment_Request_Card {#230
+invoice: Mobilpay_Payment_Invoice {#235 :arrow_forward:}
+signature: “”
+service: null
+orderId: “12dda3ae2401d1b1f1ad737ede285484”
+timestamp: null
+type: “card”
+objPmNotify: null
+returnUrl: “https://evenimenteonline.zurli.ro/mobilpay/return
+confirmUrl: “https://evenimenteonline.zurli.ro/mobilpay/confirm
+params: []
-outEnvKey: “nFTmkJ+o0rd5mUIB5PFsSn8H6OtbJUBVoJpoJFB85Ktkf96yus/wptCM9rzrYTH1Ut21KMor8sYREy1JD2mYsetxTf4Wfj3WIubrihOvcQRgUvEtiuc0Jqoiqg+A6qBNnblz5lLC321mzFkH77HzzQKC+tDr/z3c :arrow_forward:
-outEncData: “IqWFWH4HGfZz1aX1clW0+0SKtB9WnkBqZPU3DmEXFQNx4XerWF0LaRIfb7lzAaOtiSsFx7dWb62A9g6F75qmNAitrmwAKuakQ2GPWtWxjQiieunUilKwCMUSv/2AVo0P941xxvbaVU3/4RHBF5l4xkiW4o2BVsJ1 :arrow_forward:
#_xmlDoc: DOMDocument {#236
+nodeName: “#document
+nodeValue: null
+nodeType: XML_DOCUMENT_NODE
+parentNode: null
+childNodes: DOMNodeList {#259 :arrow_forward:}
+firstChild: DOMElement {#261 …}
+lastChild: DOMElement {#261 …}
+previousSibling: null
+nextSibling: null
+attributes: null
+ownerDocument: null
+namespaceURI: null
+prefix: “”
+localName: null
+baseURI: null
+textContent: “”
+doctype: null
+implementation: DOMImplementation {#265 :arrow_forward:}
+documentElement: DOMElement {#261 …}
+actualEncoding: “utf-8”
+encoding: “utf-8”
+xmlEncoding: “utf-8”
+standalone: true
+xmlStandalone: true
+version: “1.0”
+xmlVersion: “1.0”
+strictErrorChecking: true
+documentURI: null
+config: null
+formatOutput: false
+validateOnParse: false
+resolveExternals: false
+preserveWhiteSpace: true
+recover: false
+substituteEntities: false
xml: “”"
<?xml version="1.0" encoding="utf-8"?>




<contact_info>

<first_name></first_name>
<last_name></last_name>

<mobile_phone></mobile_phone>

</contact_info>


https://evenimenteonline.zurli.ro/mobilpay/return
https://evenimenteonline.zurli.ro/mobilpay/confirm


“”"
}
#_requestIdentifier: “cda906a85b953952e81287ecd42541ff”
#_objRequestParams: {#234}
#_objRequestInfo: null
+objReqNotify: null

}

Problema este ca atunci cand scriu comada dd($_SERVER[‘REQUEST_METHOD’]); in pagina de return url primesc GET nu POST cum ar trebui. Mai mult variabilele de care am nevoie $env_key si $data nu sun in requestul de la mobilapay

Unde mai exact scrii acea comanda?

Cele 2 url-uri trebuie sa fie doua metode diferite in controller-ul tau ca tratezi 2 chestii diferite.

Mai exact, daca ai un Controller numit MobilpayController ar trebui sa ai doua function return() si confirm() sau cum vrei tu sa le numesti. Din tot ce povestesti se pare ca tu tratezi doar un singur caz, cel de return care este GET si care nu iti va da ce astepti tu. Aia se intampla pe CONFIRM url.

Am functia back (pentru return) in care am puns codul de la ei de pe site pt call back. Am pus in ruta Route::match([‘get’, ‘post’], ‘/mobilpay/return’, ‘[email protected]’); pentru ca daca puneam doar post imi dadea eroare. Cert este ca requestul pe care il primesc e prin get nu prin post…si nici nu are parametrii de care am nevoie.

Asta e functia back()

public function back(Request $request) {
  //  dd($request->post());

$orderId=$request->orderId;
//dd($orderId);
//dd("dfesr");
//dd($_SERVER['REQUEST_METHOD']);

$errorCode 		= 0;
$errorType		= Mobilpay_Payment_Request_Abstract::CONFIRM_ERROR_TYPE_NONE;
$errorMessage		= '';

if (strcasecmp($_SERVER['REQUEST_METHOD'], 'post') == 0)
{
   // dd("data");

   
  //  $data = $request;
   // dd($data);
    if(isset($_post['env_key']) && isset($_post['data']))//
  
	{
     //  dd($request);
		#calea catre cheia privata
		#cheia privata este generata de mobilpay, accesibil in Admin -> Conturi de comerciant -> Detalii -> Setari securitate
		$privateKeyFilePath = public_path('/files/sandbox.private.key');
		
		try
		{
		$objPmReq = Mobilpay_Payment_Request_Abstract::factoryFromEncrypted($_GET['env_key'], $_GET['data'], $privateKeyFilePath);
		#uncomment the line below in order to see the content of the request
		dd($objPmReq);
		$rrn = $objPmReq->objPmNotify->rrn;
		// action = status only if the associated error code is zero
		if ($objPmReq->objPmNotify->errorCode == 0) {
		    	switch($objPmReq->objPmNotify->action)
		    	{
				#orice action este insotit de un cod de eroare si de un mesaj de eroare. Acestea pot fi citite folosind $cod_eroare = $objPmReq->objPmNotify->errorCode; respectiv $mesaj_eroare = $objPmReq->objPmNotify->errorMessage;
				#pentru a identifica ID-ul comenzii pentru care primim rezultatul platii folosim $id_comanda = $objPmReq->orderId;
				case 'confirmed':
					#cand action este confirmed avem certitudinea ca banii au plecat din contul posesorului de card si facem update al starii comenzii si livrarea produsului
				//update DB, SET status = "confirmed/captured"
				$errorMessage = $objPmReq->objPmNotify->errorMessage;
			    break;
				case 'confirmed_pending':
					#cand action este confirmed_pending inseamna ca tranzactia este in curs de verificare antifrauda. Nu facem livrare/expediere. In urma trecerii de aceasta verificare se va primi o noua notificare pentru o actiune de confirmare sau anulare.
				//update DB, SET status = "pending"
				$errorMessage = $objPmReq->objPmNotify->errorMessage;
			    break;
				case 'paid_pending':
					#cand action este paid_pending inseamna ca tranzactia este in curs de verificare. Nu facem livrare/expediere. In urma trecerii de aceasta verificare se va primi o noua notificare pentru o actiune de confirmare sau anulare.
				//update DB, SET status = "pending"
				$errorMessage = $objPmReq->objPmNotify->errorMessage;
			    break;
				case 'paid':
					#cand action este paid inseamna ca tranzactia este in curs de procesare. Nu facem livrare/expediere. In urma trecerii de aceasta procesare se va primi o noua notificare pentru o actiune de confirmare sau anulare.
				//update DB, SET status = "open/preauthorized"
				$errorMessage = $objPmReq->objPmNotify->errorMessage;
			    break;
				case 'canceled':
					#cand action este canceled inseamna ca tranzactia este anulata. Nu facem livrare/expediere.
				//update DB, SET status = "canceled"
				$errorMessage = $objPmReq->objPmNotify->errorMessage;
			    break;
				case 'credit':
					#cand action este credit inseamna ca banii sunt returnati posesorului de card. Daca s-a facut deja livrare, aceasta trebuie oprita sau facut un reverse. 
				//update DB, SET status = "refunded"
				$errorMessage = $objPmReq->objPmNotify->errorMessage;
			    break;
			default:
			    	$errorType	= Mobilpay_Payment_Request_Abstract::CONFIRM_ERROR_TYPE_PERMANENT;
			  	$errorCode 	= Mobilpay_Payment_Request_Abstract::ERROR_CONFIRM_INVALID_ACTION;
			   	$errorMessage 	= 'mobilpay_refference_action paramaters is invalid';
			    break;
		    	}
		}
		else {
		//update DB, SET status = "rejected"
		$errorMessage = $objPmReq->objPmNotify->errorMessage;
			}
		}
		catch(Exception $e)
		{
			$errorType 		= Mobilpay_Payment_Request_Abstract::CONFIRM_ERROR_TYPE_TEMPORARY;
			$errorCode		= $e->getCode();
			$errorMessage 	= $e->getMessage();
		}
	}
	else
	{
		$errorType 			= Mobilpay_Payment_Request_Abstract::CONFIRM_ERROR_TYPE_PERMANENT;
		$errorCode			= Mobilpay_Payment_Request_Abstract::ERROR_CONFIRM_INVALID_POST_PARAMETERS;
		$errorMessage 			= 'mobilpay.ro posted invalid parameters';
	}
}
else 
{
	$errorType 				= Mobilpay_Payment_Request_Abstract::CONFIRM_ERROR_TYPE_PERMANENT;
	$errorCode				= Mobilpay_Payment_Request_Abstract::ERROR_CONFIRM_INVALID_POST_METHOD;
    $errorMessage 				= 'invalid request metod for payment confirmation';
    
    return redirect('mobilpay/final/'.$orderId.'/'.$errorMessage);
}

header('Content-type: application/xml');
echo "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n";
if($errorCode == 0)
{
	echo "<crc>{$errorMessage}</crc>";
}
else
{
	echo "<crc error_type=\"{$errorType}\" error_code=\"{$errorCode}\">{$errorMessage}</crc>";
}

Dintr-un cod destul de vechi, dar ma indoiesc ca s-a schimbat ceva la api-ul mobilpay:

		if (strcasecmp($_SERVER['REQUEST_METHOD'], 'post') == 0):
			if(isset($_POST['env_key']) && isset($_POST['data'])):
				
				try {
					$objPmReq = Mobilpay_Payment_Request_Abstract::factoryFromEncrypted($_POST['env_key'], $_POST['data'], $this->privateKeyFilePath);

Tu zici ca nu primesti POST[env_key] si POST[data].
Te-as sfatui sa incepi prin a pune in metoda de confirm (adica ce apeleaza MP in spate, nu cea de return, unde e redirectat userul) un log basic, gen file_put_contents( “log.txt”, json_encode( $_POST ) . “\n\n”, 8 )

In functie de ce ai acolo ori vei avea o idee despre ce nu e bine si cum sa rezolvi, ori vei avea niste info pe baza carora sa deschizi un tichet la suportul lor. Sau sa ne dai mai multe info aici.

Pe acest cod il folosesc
Am dat dd($_SERVER['REQUEST_METHOD'])
raspunsul e GET
daca scriu dd($_POST['env_key']``) - raspunsul e null dd($_GET[‘env_key’])``` - raspunsul e null
la fel si pentru data

Scuze daca gresesc, sunt destul de incepatoare in programre

Codul lor de callback nu trebuie in metoda de return (back cum ii spui tu). Trebuie in metoda pentru confirm, adica final cum e la tine. Daca esti incepatoare poate nu ar trebui sa te apuci de lucrul cu procesatori de plata (ceva destul de sensibil) pana nu intelegi exact cum functioneaza si care este flow-ul. Nu este nicio problema ce tine de mobilpay dar nu intelegi exact diferenta intre cele 2 url-uri si faci confuzie.

Ceva posturi mai sus ti-am explicat exact flowul si ce ar trebui sa faci in fiecare din cele 2 metode. Mai mult de atat ramane sa iti scriu exact codul.

Recomand sa citesti inca o data toata documentatia lor.

Multumesc foarte mult! Incep sa ma lamuresc.

Totusi dupa ce completez detaliile cardului sunt redirectata in return

Hei,

Primul reply era scris de pe telefon, acum scriu mai usor. :slight_smile:
Cum zice @neamtua, asigura-te ca intelegi ce fac cele 2 URL-uri.

  1. return - este pagina pe care este redirectat userul dupa ce face plata sau ii da cancel. aici ii afisezi, in functie de statusul platii, ceva informatii. status al platii pe care il primesti prin URL-ul (2)
  2. confirm - este un URL pe care il acceseaza MP din backend-ul lor, URL in care tu vei primi prin POST detaliile tranzactiei. Aceasta pagina nu are legatura cu user-ul, acesta nu o vede. Tine doar de server-ul tau si de server-ul MP. In acest URL vei primi POST["env_key"] si POST["data"] pe care va trebui sa le decriptezi folosind private key-ul primit de la ei.
    $objPmReq = Mobilpay_Payment_Request_Abstract::factoryFromEncrypted( $_POST['env_key'], $_POST['data'], $this->privateKeyFilePath );
    Datele astea nu ar trebui vazute de user, ci doar de backend-ul tau. Si probabil nu au un format GET-friendly, de asta sunt trimise prin POST.
1 Like

Multumesc mult. Pare mai clar. Sa vad ce iese :smiley:

1 Like

Multumesc tuturor pentru ajutor. Am reusit sa primesc raspunsul de la mobilpay si sa modific statusul in baza de date

2 Likes