微信app支付 php,PHP实现的微信APP支付功能示例【基于TP5框架】
时间: 2023-09-02 12:08:50 浏览: 201
以下是基于TP5框架的微信APP支付功能示例:
1. 首先,在TP5框架的config目录下新建wxpay.php文件,用于存放微信支付相关的配置信息。
```php
<?php
return [
// 应用ID
'app_id' => '',
// 商户号
'mch_id' => '',
// API密钥
'api_key' => '',
// 异步通知地址
'notify_url' => '',
// 交易类型
'trade_type' => 'APP',
// 签名类型
'sign_type' => 'MD5',
];
```
2. 在TP5框架的extend目录下新建WxPay文件夹,并在该文件夹下新建WxPayApi.php文件,用于封装微信支付相关的接口。
```php
<?php
namespace WxPay;
use think\facade\Log;
/**
* 微信支付API
*/
class WxPayApi
{
/**
* 统一下单接口
*
* @param array $data
* @return array
*/
public static function unifiedOrder($data)
{
$url = 'https://api.mch.weixin.qq.com/pay/unifiedorder';
$data['appid'] = config('wxpay.app_id');
$data['mch_id'] = config('wxpay.mch_id');
$data['nonce_str'] = self::getNonceStr();
$data['sign_type'] = config('wxpay.sign_type');
$data['sign'] = self::makeSign($data);
$xml = self::toXml($data);
$response = self::postXmlCurl($xml, $url, true, 6);
$result = self::fromXml($response);
if ($result['return_code'] == 'FAIL') {
Log::error('统一下单失败:' . $result['return_msg']);
return ['errcode' => 1, 'errmsg' => $result['return_msg']];
}
if ($result['result_code'] == 'FAIL') {
Log::error('统一下单失败:' . $result['err_code_des']);
return ['errcode' => 1, 'errmsg' => $result['err_code_des']];
}
$data = [
'appid' => config('wxpay.app_id'),
'partnerid' => config('wxpay.mch_id'),
'prepayid' => $result['prepay_id'],
'package' => 'Sign=WXPay',
'noncestr' => self::getNonceStr(),
'timestamp' => time(),
];
$data['sign_type'] = config('wxpay.sign_type');
$data['sign'] = self::makeSign($data);
return $data;
}
/**
* 生成签名
*
* @param array $data
* @return string
*/
public static function makeSign($data)
{
ksort($data);
$string = self::toUrlParams($data);
$string = $string . '&key=' . config('wxpay.api_key');
if (config('wxpay.sign_type') == 'MD5') {
$string = md5($string);
} elseif (config('wxpay.sign_type') == 'HMAC-SHA256') {
$string = hash_hmac('sha256', $string, config('wxpay.api_key'));
}
return strtoupper($string);
}
/**
* 将数组转换为XML格式
*
* @param array $data
* @return string
*/
public static function toXml($data)
{
$xml = '<xml>';
foreach ($data as $key => $val) {
if (is_numeric($val)) {
$xml .= '<' . $key . '>' . $val . '</' . $key . '>';
} else {
$xml .= '<' . $key . '><![CDATA[' . $val . ']]></' . $key . '>';
}
}
$xml .= '</xml>';
return $xml;
}
/**
* 将XML转换为数组
*
* @param string $xml
* @return array
*/
public static function fromXml($xml)
{
libxml_disable_entity_loader(true);
$result = json_decode(json_encode(simplexml_load_string($xml, 'SimpleXMLElement', LIBXML_NOCDATA)), true);
return $result;
}
/**
* 生成随机字符串
*
* @param int $length
* @return string
*/
public static function getNonceStr($length = 32)
{
$chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
$nonceStr = '';
for ($i = 0; $i < $length; $i++) {
$nonceStr .= substr($chars, mt_rand(0, strlen($chars) - 1), 1);
}
return $nonceStr;
}
/**
* 将数组转换为URL参数
*
* @param array $data
* @return string
*/
public static function toUrlParams($data)
{
$buff = '';
foreach ($data as $k => $v) {
if ($k != 'sign' && $v != '' && !is_array($v)) {
$buff .= $k . '=' . $v . '&';
}
}
$buff = trim($buff, '&');
return $buff;
}
/**
* 发送POST请求
*
* @param string $xml
* @param string $url
* @param bool $useCert
* @param int $timeout
* @return bool|string
*/
public static function postXmlCurl($xml, $url, $useCert = false, $timeout = 30)
{
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
curl_setopt($ch, CURLOPT_USERAGENT, 'Mozilla/5.0 (Windows NT 6.1; WOW64; rv:39.0) Gecko/20100101 Firefox/39.0');
curl_setopt($ch, CURLOPT_HEADER, false);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $xml);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
if ($useCert) {
curl_setopt($ch, CURLOPT_SSLCERTTYPE, 'PEM');
curl_setopt($ch, CURLOPT_SSLCERT, '/path/to/your/cert.pem');
curl_setopt($ch, CURLOPT_SSLKEYTYPE, 'PEM');
curl_setopt($ch, CURLOPT_SSLKEY, '/path/to/your/key.pem');
}
curl_setopt($ch, CURLOPT_TIMEOUT, $timeout);
$result = curl_exec($ch);
curl_close($ch);
return $result;
}
}
```
3. 在控制器中调用WxPayApi类的unifiedOrder方法,实现微信支付功能。
```php
<?php
namespace app\index\controller;
use think\Controller;
use WxPay\WxPayApi;
class Index extends Controller
{
public function index()
{
$data = [
'body' => '测试商品',
'out_trade_no' => date('YmdHis') . mt_rand(10000, 99999),
'total_fee' => 1,
'spbill_create_ip' => $_SERVER['REMOTE_ADDR'],
];
$result = WxPayApi::unifiedOrder($data);
if ($result['errcode']) {
return $result['errmsg'];
}
return json($result);
}
}
```
以上是基于TP5框架的微信APP支付功能示例,具体实现可以根据自己的需要进行调整。
阅读全文