After watching thinkPHP practice, I downloaded the code in the book from github and prepared to run it A program developed for WeChat public accounts.
However, because the book uses ThinkPHP3.2.3, and the latest version is already 6.0.X, I am not familiar with ThinkPHP anyway, so I downloaded the latest version to use. I expected that there would be problems running the program because of the different versions. What I think is that we should solve each problem one by one. Unexpectedly, I encountered a lot of difficulties and it took me two days to get the program running. Finally, I changed a little bit of code in the framework.
Without further ado, let me list the difficulties I encountered in turn.
How to introduce ThinkWechat.php in TP
In the book, ThinkWechat.php is placed under /Application/Home/Library. But TP6 no longer has Application, so I created a new library directory under /app and put the files in it.
You need to introduce this file in Index.php
use app\library\ThinkWechat;
Add namespace## in the ThinkWechat.php file
#namespace app\library;
The result still doesn’t work. I brewed it for several hours. I don’t know how I found out later that namespace was used in tp6, so when using SimpleXMLElement, you have to write the following statement at the beginning of the file
use SimpleXMLElement;
How about TP6 Print the log to the log file
Because I interact with the WeChat official account, I don’t know how to facilitate debugging. I tried the interface debugging tool provided by WeChat, but it can only check whether the parameter settings are correct. So I used the stupidest method of printing logs.To print logs, you need to make the following settings in TP6:
1. Set the logging level
'level' => [' emergency'],
1. Set the log saving directory
'path' => App()->getRuntimePath() .'/log',2. Then use the following in the program The statements are written to the log file in real time
Log::write('index _get session id before set ID '. Session::getId(), 'notice');
After following the test public account, enter 999 to receive a normal reply. Enter 1 and the program will exit
This problem stuck with me for most of the day! ! At first, I thought there was a problem with the response returned to the WeChat platform, because I printed a lot of logs in ThinkWechat.php and found that as long as I entered information other than 999, the data2xml method could not be fully executed. , the log cannot be printed after
$node = dom_import_simplexml($child);.
$node->appendChild($node->ownerDocument->createCDATASection($value));There was a problem with the execution of this code.
Therefore, I also found from the book "WeChat Public Platform Development" that the response xml is generated by setting the xml template and replacing the variables in the template with the sprintf method.
I looked at the development documentation of TP6, and sure enough, it says that the session is not initialized by default. I feel like crying here.
\think\middleware\SessionInit::class in app/middleware.php.
At this time, I found that multiple session files were generated in the runtime/session directory. For the same user, there should be only one session file that is correct. It is equivalent to a new session file being generated every time the user interacts with the official account, so that the information previously entered by the user cannot be obtained.
Baidu later discovered that the reason for this is that
session is stored on the server side, so to distinguish each user's session, you need to use the client's cookie. The WeChat server does not send cookies to the developer server. Therefore, cookie-based sessions cannot be used.
But as long as a unique session_id is set for each user, the same effect can be achieved.
Everyone's WeChat ID is unique, so we can use WeChat ID as the user's session_id, or we can use it after md5 encryption.
I plan to use the value of FromUserName as the sessionid. That is, each user's own openid. However, TP6 does not support the session_id() method to set the sessionid. I later read the documentation and found that Session::setId can be used to set the SessionID, but I don't know why a different sessionID is still generated every time.
It says on the Internet that you can use openid. I found that every time the URL sent by the WeChat public account to the server does come with openid, I configured openid in session.php, hoping that TP6 will use the openid in the request every time. as sessionid. But it still didn't take effect.
TP6's session.php has the following configuration:
SESSION_ID submission variable to solve flash upload cross-domain'var_session_id' => 'openid',
Checked the setId of the framework, the original code is as follows
public function setId($id = null): void { $this->id = is_string($id) && strlen($id) === 32 && ctype_alnum($id) ? $id : md5(microtime (true).session_create_id()); }
It turns out that the sessionid must be a 32-bit string containing alphanumeric characters. If it does not meet the requirements (openid length is 28 bits), use The current time is used as the sessionid, so I changed the setId to the following, and then printed the sessionid in the index method, and found that it is the same every time.
public function setId($id = null): void { $this->id = is_string($id) && strlen(md5($id)) === 32 && ctype_alnum(md5($id)) ? md5($id) : md5(microtime (true).session_create_id()); }
Run the program and everything works fine. It feels great.
At this time, I think that all the problems I encountered before should have nothing to do with xml response. So I used the previous ThinkWechat.php, but found that the session file was not generated in the runtime/session directory.
After checking, I found that the response method of the original ThinkWechat.php ended with
exit($xml->asXML());
The TP6 official document has the following reminder:
Note that the operation of writing data to the Session will be localized and stored uniformly at the end of the request, so do not use exit and other interrupt operations after writing the Session data, which may This will cause the Session to not be written normally.
So I changed the exit statement to return $xml->asXML();
At this time, the session file is generated normally, and the information replied by the official account is also correct.
PS code has been hosted on github
https://github.com/sarawang9012/thinkwechat