ThinkPHP是一款开源的PHP开发框架,是目前最流行的PHP框架之一。而小程序是一种应用领域尚属新生的移动应用,由于小程序的开发和部署是基于微信公众平台,因此需要对微信公众平台相关开发知识做一些了解。本文将介绍如何使用ThinkPHP6开发小程序。
一、创建小程序应用
在开始之前,我们需要在微信公众平台上创建一个小程序应用,并获取到开发者ID和密钥等相关信息。
二、安装ThinkPHP6
1. 打开命令行工具,进入项目根目录,使用Composer命令安装ThinkPHP6:
```composer create-project topthink/think tp6```
2. 修改项目目录权限
```chmod -R 777 runtime```
```chmod -R 777 public/staic```
三、配置小程序开发相关参数
在config目录下面新建wx.php文件,配置微信开发者相关参数:
```php
return [
// 小程序AppID
'app_id' => '',
// 小程序AppSecret
'app_secret' => '',
// 微信服务器域名
'api_host' => 'api.weixin.qq.com',
// 微信接口请求协议 http/https
'api_protocol' => 'https',
// 微信接口请求端口,默认为443
'api_port' => 443,
// 微信接口请求超时时间(秒)
'api_timeout' => 5
];
```
四、编写小程序开发相关代码
1. 获取access token
access token是访问微信开发者接口的重要凭证,需要在接口调用时附上。在开发小程序时,我们需要获取access token。
在应用的app目录下新建wx目录,并在wx目录下新建AccessToken.php文件:
```php
namespace app\wx;
use think\facade\Cache;
use think\facade\Config;
use think\facade\Http;
class AccessToken
{
/**
* 获取access token
* @return string
*/
public static function get()
{
$cacheKey = 'access_token'; // 缓存键名
if (Cache::has($cacheKey)) {
// 如果有缓存,直接返回缓存中的access token
return Cache::get($cacheKey);
} else {
// 如果没有缓存,发起access token请求
$appId = Config::get('wx.app_id'); // 小程序AppID
$appSecret = Config::get('wx.app_secret'); // 小程序AppSecret
$apiUrl = 'https://' . Config::get('wx.api_host') . '/cgi-bin/token?grant_type=client_credential&appid=' . $appId . '&secret=' . $appSecret;
$apiResult = Http::get($apiUrl); // 发起请求
$json = json_decode($apiResult, true); // 解析结果
if (isset($json['access_token'])) {
// 获取access token成功,缓存access token
Cache::set($cacheKey, $json['access_token'], $json['expires_in']);
return $json['access_token'];
} else {
throw new \Exception('access token获取失败');
}
}
}
}
```
2. 接口调用
我们可以使用ThinkPHP的Http库或Curl库来发起接口请求。在应用的app目录下新建wx目录,并在wx目录下新建Api.php文件:
```php
namespace app\wx;
use think\facade\Config;
use think\facade\Http;
class Api
{
/**
* 获取微信用户信息
* @param string $openid 用户openid
* @return string
*/
public static function getUserInfo($openid)
{
$accessToken = AccessToken::get(); // 获取access token
$apiUrl = 'https://' . Config::get('wx.api_host') . '/cgi-bin/user/info?access_token=' . $accessToken . '&openid=' . $openid . '&lang=zh_CN';
$apiResult = Http::get($apiUrl); // 发起请求
return $apiResult;
}
}
```
3. 微信支付
使用微信支付需要配置微信商户号相关信息,并在微信开发平台上进行相关设置。在应用的app目录下新建wx目录,并在wx目录下新建Pay.php文件:
```php
namespace app\wx;
use think\facade\Request;
use think\facade\Log;
class Pay
{
/**
* 扫码支付下单
*/
public static function qrcodePay()
{
$notifyUrl = Request::domain() . '/wx/pay/notify'; // 微信支付回调通知地址
$totalFee = 1 * 100; // 订单总金额,单位:分
$tradeNo = '订单号'; // 商户订单号,建议使用UUID
$appId = Config::get('wx.app_id'); // 小程序AppID
$mchId = Config::get('wx.mch_id'); // 商户号
$mchKey = Config::get('wx.mch_key'); // 商户密钥
$nonceStr = self::getNonceStr(32); // 随机字符串
$ip = Request::ip(); // 客户端IP地址
$params = [
'appid' => $appId,
'mch_id' => $mchId,
'nonce_str' => $nonceStr,
'body' => 'Order-描述-',
'out_trade_no' => $tradeNo,
'total_fee' => $totalFee,
'spbill_create_ip' => $ip,
'notify_url' => $notifyUrl,
'trade_type' => 'NATIVE',
];
$params['sign'] = self::createSign($params, $mchKey); // 签名
$xml = self::arrayToXml($params); // 数组转XML
$result = self::postXmlCurl($xml, 'https://api.mch.weixin.qq.com/pay/unifiedorder'); // 发送请求
$result = self::xmlToArray($result); // XML转数组
if ($result['return_code'] === 'SUCCESS' && $result['result_code'] === 'SUCCESS') {
return $result['code_url']; // 获取二维码链接
} else {
Log::error('微信支付下单失败:' . json_encode($result));
throw new \Exception('微信支付下单失败');
}
}
/**
* 微信支付回调通知处理
*/
public static function notify()
{
$xml = file_get_contents('php://input');
$data = self::xmlToArray($xml);
if ($data['return_code'] === 'SUCCESS' && $data['result_code'] === 'SUCCESS') {
$mchKey = Config::get('wx.mch_key');
$sign = self::createSign($data, $mchKey);
if ($sign === $data['sign']) {
// 处理支付成功逻辑
// $data['out_trade_no'] 商户订单号
// $data['transaction_id'] 微信支付订单号
// $data['total_fee'] 订单总金额
// $data['cash_fee'] 现金支付金额
// $data['time_end'] 支付完成时间
echo '
} else {
Log::error('微信支付回调通知:签名错误');
echo '
}
} else {
Log::error('微信支付回调通知失败:' . json_encode($data));
echo '
}
}
/**
* 数组转XML
* @param array $arr
* @param bool $root
* @return string
*/
private static function arrayToXml($arr, $root = true)
{
$xml = '';
if ($root) $xml .= '
foreach ($arr as $key => $val) {
if (is_array($val)) {
$xml .= self::arrayToXml($val, false);
} else {
$xml .= "<{$key}>{$val}{$key}>";
}
}
if ($root) $xml .= '';
return $xml;
}
/**
* XML转数组
* @param string $xml
* @return array
*/
private static function xmlToArray($xml)
{
$obj = simplexml_load_string($xml, 'SimpleXMLElement', LIBXML_NOCDATA);
return json_decode(json_encode($obj), true);
}
/**
* 生成签名
* @param array $params
* @param string $key
* @return string
*/
private static function createSign($params, $key)
{
ksort($params);
$pairs = [];
foreach ($params as $key => $value) {
$pairs[] = $key . '=' . $value;
}
$signRaw = implode('&', $pairs) . '&key=' . $key;
return strtoupper(md5($signRaw));
}
/**
* 获取指定长度的随机字符串
* @param int $length
* @return string
*/
private static function getNonceStr($length)
{
$chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
$str = '';
for ($i = 0; $i < $length; $i++) {
$str .= substr($chars, mt_rand(0, strlen($chars) - 1), 1);
}
return $str;
}
/**
* POST XML数据
* @param string $xml
* @param string $url
* @param int $timeout
* @return mixed
*/
private static function postXmlCurl($xml, $url, $timeout = 30)
{
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_HEADER, false);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $xml);
curl_setopt($ch, CURLOPT_HTTPHEADER, ['Content-Type: text/xml']);
curl_setopt($ch, CURLOPT_TIMEOUT, $timeout);
$result = curl_exec($ch);
curl_close($ch);
return $result;
}
}
```
五、使用小程序开发相关代码
现在,我们已经完成了小程序开发相关代码的编写,下面我们将使用这些代码来开发小程序。
1. 调用微信接口获取用户信息
在小程序中,我们可以使用wx.login()方法获取用户code,通过code获取用户的openid和session_key,然后使用wx.getUserInfo()方法获取用户信息。
```javascript
wx.login({
success: res => {
wx.getUserInfo({
success: userinfo => {
let data = {
code: res.code,
encryptedData: userinfo.encryptedData,
iv: userinfo.iv
};
// 发起请求获取用户信息
wx.request({
url: 'https://api.example.com/wx/user/getInfo',
method: 'POST',
data: data,
success: result => {
console.log(result.data);
},
fail: res => {
console.log(res);
}
});
}
});
}
});
```
2. 微信支付
在小程序中,我们可以使用wx.requestPayment()方法发起微信支付请求。
```javascript
wx.requestPayment({
timeStamp: '',
nonceStr: '',
package: '',
signType: '',
paySign: '',
success: res => {
console.log(res);
},
fail: res => {
console.log(res);
}
});
```
以上就是使用ThinkPHP6开发小程序的流程和相关代码。