Jump to content
  • Checkout
  • Login
  • Get in touch

osCommerce

The e-commerce.

Official PayPal IPN Support Thread


Mark Evans

Recommended Posts

Hi everyone,

 

Thanks for all the excellent work on this module. Unfortunately, I'm having a similar problem.

 

Customers can successfully order from my site using the IPN module. However, while orders do show up in the Customers/Orders tab, no notifications show up in Customers/PayPal IPN. Also, all orders' statuses always remain at "Pending" despite my getting ridiculous numbers of IPN update e-mails. In Customers/Orders, the status never updates, even when I complete payment or refund the order in PayPal. After clicking on the order in Customers/Orders, it says:

 

Transaction Activity

Date Status Details Action Gross Fee Net Amount

No PayPal Transaction Information Available (f702c916acd790a801a4d945c0179801)

 

Any ideas on how I can begin to debug this?

 

Hi Terra,

 

Thank you very much for helping to support this contribution :thumbsup: I am having some similar problem with the order status not updating.

 

From the questions you have asked others:

 

The order is "prepared" in the admin section at checkout_confirmation.

My IPN and redirects are turned off in my paypal account.

I adjusted the location of the ipn.php file in paypal_ipn.php as I am running on a test site.

My 'id=""' is empty on page source after the payment is made.

My admin is updated on return from paypal but not on payment while still on paypal.

The ordernumber is recorded on both paypal emails and checkout_process emails.

I have implemented the "letter" fix for "this invoice has already been paid" problem, and this is working correctly as the paypal email retains the letter before the invoice# and the checkout_process email has the letter stripped.

I have download controller installed and have transfered the one line :

'last_modified' => 'now()',

that is changed in checkout_process.php over to paypal_ipn.php.

The order is properly displaying in the customers account, it just never changes from "preparing"!

 

I do not get the INVALID email.

 

So, everything appears to be working up to a point. I am just not sure which point. I also need help with how to add emails at various points in the ipn.php to debug the location of the failure.

 

Thanks again for your support :) :)

 

Sheri

Link to comment
Share on other sites

How can I tell if its ot finding ipn.php?

If you insert emails throughout the key stages of ipn.php then you will know - if no email is sent, then PayPal never accesses the right file (access triggers email). The email is just the straight-forward PHP mail function - details in the PHP manual: http://uk.php.net/manual/en/function.mail.php

 

Terra

My code for combining PayPal IPN with ** QTPro 4.25 ** osC Affiliate ** CCGV(trad)

and how to solve the invoice already paid error

General info: Allow customer to delete order comment ** FTP Programs & Text Editors ** Amending order email **

Link to comment
Share on other sites

First - please try this!

In your paypal_ipn.php file around line 341 find this line:

	  $parameters['invoice'] = substr($cart_PayPal_IPN_ID, strpos($cart_PayPal_IPN_ID, '-')+1);

 

and replace with this:

	  // Terra register globals fix
  $parameters['invoice'] = substr($_SESSION['cart_PayPal_IPN_ID'], strpos($_SESSION['cart_PayPal_IPN_ID'], '-')+1);

 

Please try & post back whether it works - if yes, I'll issue an updated contrib package.

 

Second - just for info:

 

Regarding the last posts - I'm including a debugging ipn.php below. To test replace your existing ipn.php file wit the code below. Make sure to enter a valid email address at line 14! Then run a test PayPal order through and check what emails you are getting.

 

The contrib was tested on an Apache server with PHP 4.4.2 and Register Globals OFF in the php.ini file. Folder permissions for /ext/ and folders included are 755 on my test server. When testing with Sandbox there is often a timelag for the order status update to happen (in extreme cases I had to wait several hours, although usually it's just minutes).

 

Please don't forget to replace the file with the original once testing is done. If all works correctly, you shold receive 3 separate emails to confirm the 3 key steps (access / verification / invoice variable).

 

Debug file below:

<?php
/*  
DEBUG FILE		  DEBUG FILE		  DEBUG FILE		  DEBUG FILE		  DEBUG FILE	

THIS IS A DEBUGGING TOOL - ONLY TO BE USED WHEN TESTING - NOT ON LIVE SITES! 

DEBUG FILE		  DEBUG FILE		  DEBUG FILE		  DEBUG FILE		  DEBUG FILE		  
*/




// IMPORTANT - YOU MUST SPECIFY A VALID EMAIL ADDRESS HERE
$debugemail = '[email protected]';




// let's see if PayPal can find my file
mail($debugemail, 'Debug Test', 'PayPal has correctly accessed ipn.php on my server');
// end

 chdir('../../../../');
 require('includes/application_top.php');

 $parameters = 'cmd=_notify-validate';

 foreach ($_POST as $key => $value) {
$parameters .= '&' . $key . '=' . urlencode(stripslashes($value));
 }

 if (MODULE_PAYMENT_PAYPAL_IPN_GATEWAY_SERVER == 'Live') {
$server = 'www.paypal.com';
 } else {
$server = 'www.sandbox.paypal.com';
 }

 $fsocket = false;
 $curl = false;
 $result = false;

 if ( (PHP_VERSION >= 4.3) && ($fp = @fsockopen('ssl://' . $server, 443, $errno, $errstr, 30)) ) {
$fsocket = true;
 } elseif (function_exists('curl_exec')) {
$curl = true;
 } elseif ($fp = @fsockopen($server, 80, $errno, $errstr, 30)) {
$fsocket = true;
 }

 if ($fsocket == true) {
$header = 'POST /cgi-bin/webscr HTTP/1.0' . "\r\n" .
		  'Host: ' . $server . "\r\n" .
		  'Content-Type: application/x-www-form-urlencoded' . "\r\n" .
		  'Content-Length: ' . strlen($parameters) . "\r\n" .
		  'Connection: close' . "\r\n\r\n";

@fputs($fp, $header . $parameters);

$string = '';
while (!@feof($fp)) {
  $res = @fgets($fp, 1024);
  $string .= $res;

  if ( ($res == 'VERIFIED') || ($res == 'INVALID') ) {
	$result = $res;

	break;
  }
}

@fclose($fp);
 } elseif ($curl == true) {
$ch = curl_init();

curl_setopt($ch, CURLOPT_URL, 'https://' . $server . '/cgi-bin/webscr');
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $parameters);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HEADER, false);
curl_setopt($ch, CURLOPT_TIMEOUT, 30);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);

$result = curl_exec($ch);

curl_close($ch);
 }

 if ($result == 'VERIFIED') {

// let's see if the PayPal result is "Verified"
mail($debugemail, 'Debug Test', 'PayPal has correctly verified each parameter');
// end	  


if (isset($_POST['invoice']) && is_numeric($_POST['invoice']) && ($_POST['invoice'] > 0)) {


// let's see if the orderID is okay
mail($debugemail, 'Debug Test', 'The order ID (invoice variable) has been verified as set, being numeric and larger than zero');
// end		

  $order_query = tep_db_query("select currency, currency_value from " . TABLE_ORDERS . " where orders_id = '" . $_POST['invoice'] . "' and customers_id = '" . (int)$_POST['custom'] . "'");
  if (tep_db_num_rows($order_query) > 0) {
	$order = tep_db_fetch_array($order_query);

	$total_query = tep_db_query("select value from " . TABLE_ORDERS_TOTAL . " where orders_id = '" . $_POST['invoice'] . "' and class = 'ot_total' limit 1");
	$total = tep_db_fetch_array($total_query);

	$comment_status = $_POST['payment_status'] . ' (' . ucfirst($_POST['payer_status']) . '; ' . $currencies->format($_POST['mc_gross'], false, $_POST['mc_currency']) . ')';

	if ($_POST['payment_status'] == 'Pending') {
	  $comment_status .= '; ' . $_POST['pending_reason'];
	} elseif ( ($_POST['payment_status'] == 'Reversed') || ($_POST['payment_status'] == 'Refunded') ) {
	  $comment_status .= '; ' . $_POST['reason_code'];
	}

	$order_status_id = DEFAULT_ORDERS_STATUS_ID;

	if ($_POST['mc_gross'] == number_format($total['value'] * $order['currency_value'], $currencies->get_decimal_places($order['currency']))) {
	  if (MODULE_PAYMENT_PAYPAL_IPN_ORDER_STATUS_ID > 0) {
		$order_status_id = MODULE_PAYMENT_PAYPAL_IPN_ORDER_STATUS_ID;
	  }
	}

	tep_db_query("update " . TABLE_ORDERS . " set orders_status = '" . $order_status_id . "', last_modified = now() where orders_id = '" . $_POST['invoice'] . "'");

	$sql_data_array = array('orders_id' => $_POST['invoice'],
							'orders_status_id' => $order_status_id,
							'date_added' => 'now()',
							'customer_notified' => '0',
							'comments' => 'PayPal IPN Verified [' . $comment_status . ']');

	tep_db_perform(TABLE_ORDERS_STATUS_HISTORY, $sql_data_array);
  }
}
 } else {
if (tep_not_null(MODULE_PAYMENT_PAYPAL_IPN_DEBUG_EMAIL)) {
  $email_body = '$_POST:' . "\n\n";
  foreach ($_POST as $key => $value) {
	$email_body .= $key . '=' . $value . "\n";
  }
  $email_body .= "\n" . '$_GET:' . "\n\n";
  foreach ($_GET as $key => $value) {
	$email_body .= $key . '=' . $value . "\n";
  }

  tep_mail('', MODULE_PAYMENT_PAYPAL_IPN_DEBUG_EMAIL, 'PayPal IPN Invalid Process', $email_body, STORE_OWNER, STORE_OWNER_EMAIL_ADDRESS);
}

if (isset($_POST['invoice']) && is_numeric($_POST['invoice']) && ($_POST['invoice'] > 0)) {
  $check_query = tep_db_query("select orders_id from " . TABLE_ORDERS . " where orders_id = '" . $_POST['invoice'] . "' and customers_id = '" . (int)$_POST['custom'] . "'");
  if (tep_db_num_rows($check_query) > 0) {
	$comment_status = $_POST['payment_status'];

	if ($_POST['payment_status'] == 'Pending') {
	  $comment_status .= '; ' . $_POST['pending_reason'];
	} elseif ( ($_POST['payment_status'] == 'Reversed') || ($_POST['payment_status'] == 'Refunded') ) {
	  $comment_status .= '; ' . $_POST['reason_code'];
	}

	tep_db_query("update " . TABLE_ORDERS . " set orders_status = '" . ((MODULE_PAYMENT_PAYPAL_IPN_ORDER_STATUS_ID > 0) ? MODULE_PAYMENT_PAYPAL_IPN_ORDER_STATUS_ID : DEFAULT_ORDERS_STATUS_ID) . "', last_modified = now() where orders_id = '" . $_POST['invoice'] . "'");

	$sql_data_array = array('orders_id' => $_POST['invoice'],
							'orders_status_id' => (MODULE_PAYMENT_PAYPAL_IPN_ORDER_STATUS_ID > 0) ? MODULE_PAYMENT_PAYPAL_IPN_ORDER_STATUS_ID : DEFAULT_ORDERS_STATUS_ID,
							'date_added' => 'now()',
							'customer_notified' => '0',
							'comments' => 'PayPal IPN Invalid [' . $comment_status . ']');

	tep_db_perform(TABLE_ORDERS_STATUS_HISTORY, $sql_data_array);
  }
}
 }

 require('includes/application_bottom.php');
?>

 

all the best, Terra

Edited by Terra

My code for combining PayPal IPN with ** QTPro 4.25 ** osC Affiliate ** CCGV(trad)

and how to solve the invoice already paid error

General info: Allow customer to delete order comment ** FTP Programs & Text Editors ** Amending order email **

Link to comment
Share on other sites

First - please try this!

In your paypal_ipn.php file around line 341 find this line:

	  $parameters['invoice'] = substr($cart_PayPal_IPN_ID, strpos($cart_PayPal_IPN_ID, '-')+1);

 

and replace with this:

	  // Terra register globals fix
  $parameters['invoice'] = substr($_SESSION['cart_PayPal_IPN_ID'], strpos($_SESSION['cart_PayPal_IPN_ID'], '-')+1);

 

Please try & post back whether it works - if yes, I'll issue an updated contrib package.

 

Second - just for info:

 

Regarding the last posts - I'm including a debugging ipn.php below. To test replace your existing ipn.php file wit the code below. Make sure to enter a valid email address at line 14! Then run a test PayPal order through and check what emails you are getting.

 

 

The first "fix" did not appear to work, so I used the debug code. I got only the first of the three emails.

Link to comment
Share on other sites

The first "fix" did not appear to work, so I used the debug code. I got only the first of the three emails.

<_< that means your problem is the verification and the code lines up to " if ($result == 'VERIFIED') {". There were other posts on this thread about issues with CURL, fsockets and server ports - I'd recommend focusing on that for debugging and reading the thread for tweaks others have implemented. Unfortunatey, this is the area I know least about, so I can't help any further. Terra

My code for combining PayPal IPN with ** QTPro 4.25 ** osC Affiliate ** CCGV(trad)

and how to solve the invoice already paid error

General info: Allow customer to delete order comment ** FTP Programs & Text Editors ** Amending order email **

Link to comment
Share on other sites

<_< that means your problem is the verification and the code lines up to " if ($result == 'VERIFIED') {". There were other posts on this thread about issues with CURL, fsockets and server ports - I'd recommend focusing on that for debugging and reading the thread for tweaks others have implemented. Unfortunatey, this is the area I know least about, so I can't help any further. Terra

 

I noticed this line in the code: curl_setopt($ch, CURLOPT_URL, 'https://' . $server . '/cgi-bin/webscr');

 

Hope this isnt a dumb question, but what is "webscr"? I dont find such a file or folder on my site.

Link to comment
Share on other sites

Does your e-mail confirmation contain an ordernumber?

 

nope... my confirmation mail's order number is missing also.

 

i tried to print out the cardID variable during confirmation page, it is there.

 

other payment mode works fine, i have all the invoice generated correctly.

 

one question, during installation of IPN, i didnt change anything on checkout_confirmation.php, in what way if i choose to use IPN, the order will be pre-created during that page? sorry, just want to know more, so that i can debug deeper. thanks.

Link to comment
Share on other sites

Hi Terra,

 

Thanks for all the help!!

 

The $_SESSION fix did not work for me either :(

 

I installed the DEBUG ipn.php file and received only the first email indicating that the file had been correctly accessed.

 

I inserted another email here:

 

} else {
 // let's see if the PayPal result is not "Verified"
mail($debugemail, 'Debug Test', 'PayPal has incorrectly verified each parameter');
// end
if (tep_not_null(MODULE_PAYMENT_PAYPAL_IPN_DEBUG_EMAIL)) {

 

but did not receive this email.

 

So, started inserting emails at each line :lol:

 

It didn't even get past "require application_top" :blink:

 

Could anyone explain this line and it's purpose?:

chdir('../../../../');

 

Sheri

 

Please try & post back whether it works - if yes, I'll issue an updated contrib package.
Link to comment
Share on other sites

I noticed this line in the code: curl_setopt($ch, CURLOPT_URL, 'https://' . $server . '/cgi-bin/webscr');

 

Hope this isnt a dumb question, but what is "webscr"? I dont find such a file or folder on my site.

 

That's the address of paypal. The $server variable inserts your choice: live or sandbox.

 

Sheri

Link to comment
Share on other sites

Could anyone explain this line and it's purpose?:

chdir('../../../../');

That piece of code changes the current directory the directory specified - bit like a shortcut. More info here:

http://uk.php.net/chdir

The slashes & dots basically tell the code how many folders to climb up. If your directory structure differs from the default then you will need to amend this or the file won't be able to load application_top.php and just generate a fatal error. There should be a record in your server error log if that happens - if you haven't checked recently, please do so. Terra

PS: are you on an Apache server? is safe-mode OFF or ON? nb: it's off on my test server

Edited by Terra

My code for combining PayPal IPN with ** QTPro 4.25 ** osC Affiliate ** CCGV(trad)

and how to solve the invoice already paid error

General info: Allow customer to delete order comment ** FTP Programs & Text Editors ** Amending order email **

Link to comment
Share on other sites

I noticed this line in the code: curl_setopt($ch, CURLOPT_URL, 'https://' . $server . '/cgi-bin/webscr');

 

Hope this isnt a dumb question, but what is "webscr"? I dont find such a file or folder on my site.

 

 

It was a dumb question. $server = 'www.paypal.com';

Link to comment
Share on other sites

There should be a record in your server error log if that happens - if you haven't checked recently, please do so. Terra

PS: are you on an Apache server? is safe-mode OFF or ON? nb: it's off on my test server

 

Hi Terra,

 

Thanks once again for the info.

 

I thought it must have been something like that (sorry to ask here, I usually google everything). I checked my errorlogs, both on the server (Apache) and scattered throughout the directory :blush: There are no fatal errors with regard to application top, or anything to do with the transaction (just a couple missing images).

 

Not sure about "safe-mode". The test area I set up is a subdomain (I hope this is how I was supposed to set it up). I'll query my host about "safe".

 

I have adjusted the chdir to reflect the number of folders needed to climb to get to application top. From your great link the directory looks like: home/user/public_html/test/catalog/includes/ translated to be ../../../../../../ , which is how it is now set up.

 

I need to take a break now but I'll check back later to delve into the thread and/or see if you have any other notions ;)

 

Sheri

Link to comment
Share on other sites

Not sure about "safe-mode". The test area I set up is a subdomain (I hope this is how I was supposed to set it up). I'll query my host about "safe".
Sheri - you can tell whether safe-mode is on or off by going to your admin area "Tools -> Server Info". Under PHP you should have an entry for safemode. That page is actually very useful whenever you need to know your server settings. Just don't understand why it's not working on your server ??? Terra Edited by Terra

My code for combining PayPal IPN with ** QTPro 4.25 ** osC Affiliate ** CCGV(trad)

and how to solve the invoice already paid error

General info: Allow customer to delete order comment ** FTP Programs & Text Editors ** Amending order email **

Link to comment
Share on other sites

I have adjusted the chdir to reflect the number of folders needed to climb to get to application top. From your great link the directory looks like: home/user/public_html/test/catalog/includes/ translated to be ../../../../../../ , which is how it is now set Sheri

Sheri - another thought to test whether chdir is causing problems - remove the chdir line & hardcode the URL to application_top in the next line. now in theory, if it works (or at least you receive more emails) then you know that chdir / file structure needs tweaking. PS: and don't forget that the chdir path is for climbing out off the /ext/ structure to the root - form there it then can find its way back to /includes/application_top.php as specified in the next line. Terra

My code for combining PayPal IPN with ** QTPro 4.25 ** osC Affiliate ** CCGV(trad)

and how to solve the invoice already paid error

General info: Allow customer to delete order comment ** FTP Programs & Text Editors ** Amending order email **

Link to comment
Share on other sites

Thank you Terra for all your help. I sent you a PM. If I find the solution to my problem with this contrib I will post it in the thread.

 

Sheri

 

Sheri - another thought to test whether chdir is causing problems - remove the chdir line & hardcode the URL to application_top in the next line. now in theory, if it works (or at least you receive more emails) then you know that chdir / file structure needs tweaking. PS: and don't forget that the chdir path is for climbing out off the /ext/ structure to the root - form there it then can find its way back to /includes/application_top.php as specified in the next line. Terra
Link to comment
Share on other sites

UPDATE ON MY ISSUES!

 

I installed the register globals patch (not needed to run this mod, but thought I would be secure anyway).

 

This patch actually allowed me to receive an error message that was causing problems.

 

There is an .htaccess within my includes file that was denying paypal access to application_top. My host advises this .htaccess is unnecessary, but I decided to keep it and allow only paypal access.

 

adding "Allow from (paypal IP here)" brought my success with ipn.php all the way to this line in the file:

 

if (isset($_POST['invoice']) && is_numeric($_POST['invoice']) && ($_POST['invoice'] > 0)) {

 

which then failed :(

 

But I am on my way!!!

 

I also implemented this shopping cart patch as I discovered through a debugging code that when retreiving cart contents from the database there is no order_id.

 

Sheri

Link to comment
Share on other sites

Just thought I would direct anyone else having problems getting this or any other contrib running to the debugging code that I inserted to discover that there was no order_id when retrieving the order from the database:

 

http://www.oscommerce.com/forums/index.php?s=&...st&p=469630

 

and

 

http://www.oscommerce.com/forums/index.php?s=&...st&p=681270

Link to comment
Share on other sites

Ok ... I have spent hours reading this thread.. and STILL have found no answer to a problem asked many times... If im missing the answer please forgive me and point me in the right direction... a link to the answer would help..

 

anyways I have this contrib wroking semi correctly, it seems to work well with my Points and rewards module which im happy about...

 

but when i do a test transaction on the sandbox servers... on confirm order i get the following message

 

 

We are sorry, we are experiencing temporary difficulties. Please try again later. If this error occurred while making a payment, avoid duplicate payments by checking your Account Overview before resending a payment.

 

Message 3005

 

 

I have tried re doing order... starting new orders, etc... nothing seems to fix this and I simply cant trust that it will work in live mode without testing in test mode...

 

Does anyone have a solution to this???

 

Thanks

Indi

Link to comment
Share on other sites

But I am on my way!!!

Sheri

 

I am about ready to jump for JOY (w00t) (w00t)

 

It WORKS!!!

 

So, everything I implemented so far...register globals, the shopping cart patch, allowing paypal to access the includes file and the final nail in the coffin of my IPN troubles was correctly using the

chdir('../../../../');

at the beginning of the ipn.php file. While hardcoding the location of application top got me my debugging emails, it caused errors that were hidden in an error log and did not show up in my host's log. Once I discovered the error log in question, it let me know that although paypal was accessing ipn.php and initializing application_top.php...app_top was failing on the first require.

 

PayPal IPN along with downloads controller works a treat at providing access to downloadable products when *actually* paid for and denying when not, or when bailing out of paypal at the last moment.

 

Thank-you to this forum, thread and most importantly to Terra for taking the time to help a soul in need o:)

 

Best,

Sheri

P.S. I hope to never see this thread again :P

Link to comment
Share on other sites

I may be having a similar problem as muskokee. I figured ut that the chdir('../../../../') was not working, and thus application_top.php was not loading. I hardcoded the path to app_top, but it failed because its path references are not valid, I presume, again, because the chdir did not work. I have tried varying the number of folder levels in teh chdir command, but have had no success. Suggestions appreciated.

 

Steve

Link to comment
Share on other sites

Ok I thought this was working properly, but possibly not. I receive all of the appropriate emails and so does the customer.

 

However, I have an order that was generated on 6/23 when I was testing. However, there is no order history. I am still in testing mode... However, all of the other orders had histories.

 

Also, is the STATUS for the IPN supposed to change on it's own or am I supposed to change it. For each file the status on each line is

 

Date Added Customer Notified Status Comments

06/23/2006 20:21:31 Processing (CUSTOMER NOTIFIED, GREEN CHECK)

06/23/2006 20:21:38 Processing PayPal IPN Verified [Completed (Verified; $500.00)] (CUSTOMER NOT NOTIFIED, RED "X")

06/24/2006 03:29:35 Shipped (CUSTOMER NOTIFIED, GREEN CHECK)

 

The status never changes for the IPN line from processing. Is it supposed to change on it's own? And, what about the order history being blank on one file. Anyone know what is causing this and the answer to the other questions?

 

Thanks!

Link to comment
Share on other sites

I may be having a similar problem as muskokee. I figured ut that the chdir('../../../../') was not working, and thus application_top.php was not loading. I hardcoded the path to app_top, but it failed because its path references are not valid, I presume, again, because the chdir did not work. I have tried varying the number of folder levels in teh chdir command, but have had no success. Suggestions appreciated.

 

Steve

 

 

I have worked this a bit more, and it seems that the directory does change and application_top is found, but it fails when calling its "requires". Again, help appreciated.

 

Steve

Link to comment
Share on other sites

I have worked this a bit more, and it seems that the directory does change and application_top is found, but it fails when calling its "requires". Again, help appreciated.

 

Steve

 

Hi Steve,

 

As Terra explained it to me, the chdir is climbing out of the /ext/ folder structure towards the root in order to find app_top. So, my test site is in a folder in my root, so I needed to climb 4 (../../../../) levels to get to the "catalog" folder.

 

If you have your shop in the root, then I would guess it would be 3 levels.

 

HTH,

Sheri

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Unfortunately, your content contains terms that we do not allow. Please edit your content to remove the highlighted words below.
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...