微信支付接口开发php
一、统一下单
官方文档 https://pay.weixin.qq.com/wiki/doc/api/app/app.php?chapter=9_1
二、微信支付异步通知
官方文档 https://pay.weixin.qq.com/wiki/doc/api/app/app.php?chapter=9_7&index=3
微信官方文档提示:
注意: 该链接 不能携带参数 ,有些php框架默认的路由形式是带有参数的,如:index.php?r=site/index,这样也会导致返回失败。
三、代码
<?php
class wxpay
{
public $appid = 'wxXXXXXXXXX'; #应用APPID
public $mchud = '14XXXXXXXX'; #商户号
public $wxkey = '7cXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX';
/**
* 微信支付统一下单
*/
public function wxpay()
{
$name = 'apple';
$orderno = '100100100';
$price = '10000';
$request_data = array(
'appid' => $this->appid, #应用APPID
'mch_id' => $this->mchud, #商户号
'trade_type' => 'APP', #支付类型
'nonce_str' => $this->unicode(), #随机字符串 不长于32位
'body' => $name, #商品名称
'out_trade_no' => $orderno, #商户后台订单号
'total_fee' => $price, #商品价格(单位分)
'spbill_create_ip' => $_SERVER['SERVER_ADDR'], #用户端实际ip
'notify_url' => 'http://127.0.0.1:9000/wxpay/wx_notify' #异步通知回调地址(wx_notify方法)
);
// 获取签名
$request_data['sign'] = $this->get_sign($request_data);
// 拼装数据
$xml_data = $this->set_xmldata($request_data);
// 发送请求
$res = $this->send_prePaycurl($xml_data);
if ($res['return_code'] == 'SUCCESS' && $res['result_code'] == 'SUCCESS') {
$two_data['appid'] = $this->appid; #APPID
$two_data['partnerid'] = $this->mchud; #商户号
$two_data['prepayid'] = $res['prepay_id']; //预支付交易会话标识
$two_data['noncestr'] = $this->unicode();
$two_data['timestamp'] = time();
$two_data['package'] = "Sign=WXPay";
$two_data['sign'] = $this->get_twosign($two_data);
$arr['code'] = 1;
$arr['showMsg'] = 'success';
$arr['errorMsg'] = '';
$arr['data'] = $two_data;
} else {
$arr['code'] = 0;
$arr['showMsg'] = '';
$arr['errorMsg'] = $res['err_code_des'];
$arr['data'] = [];
}
echo json_encode($arr);
}
//通过curl发送数据给微信接口的函数
private function send_prePaycurl($xmlData)
{
header("Content-Type: text/html; charset=utf-8");
$url = "https://api.mch.weixin.qq.com/pay/unifiedorder";
$header[] = "Content-type: text/xml;";
$curl = curl_init();
curl_setopt($curl, CURLOPT_HTTPHEADER, $header);
curl_setopt($curl, CURLOPT_URL, $url);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
curl_setopt($curl, CURLOPT_POST, 1);
curl_setopt($curl, CURLOPT_POSTFIELDS, $xmlData);
$data = curl_exec($curl);
if (curl_errno($curl)) {
print curl_error($curl);
}
curl_close($curl);
return $this->_xmldataparse($data);
}
//xml数据解析函数
private function _xmldataparse($data)
{
$msg = array();
$msg = (array) simplexml_load_string($data, 'SimpleXMLElement', LIBXML_NOCDATA);
return $msg;
}
//生成xml格式的函数
private function set_xmldata($data)
{
$xmlData = "<xml>";
foreach ($data as $key => $value) {
$xmlData .= "<" . $key . "><![CDATA[" . $value . "]]></" . $key . ">";
}
$xmlData = $xmlData . "</xml>";
return $xmlData;
}
//一次签名的函数
private function get_sign($data)
{
ksort($data);
$str = '';
foreach ($data as $key => $value) {
$str .= !$str ? $key . '=' . $value : '&' . $key . '=' . $value;
}
$str .= '&key=' . $this->wxkey;
// echo $str;die;
$sign = strtoupper(md5($str));
return $sign;
}
//二次签名的函数
private function get_twosign($data)
{
$sign_data = array(
"appid" => $data['appid'],
"partnerid" => $data['partnerid'],
"prepayid" => $data['prepayid'],
"noncestr" => $data['noncestr'],
"timestamp" => $data['timestamp'],
"package" => $data['package'],
);
return $this->get_sign($sign_data);
}
//微信回调
public function wx_notify()
{
//允许从外部加载XML实体(防止XML注入攻击)
libxml_disable_entity_loader(true);
$postStr = $this->post_data(); //接收post数据
$obj = simplexml_load_string($postStr,"SimpleXMLElement", LIBXML_NOCDATA);
$result_arr = json_decode(json_encode($obj),true);
if($result_arr['result_code'] == 'SUCCESS'){//交易成功
return '<xml><return_code><![CDATA[SUCCESS]]></return_code><return_msg><![CDATA[OK]]></return_msg></xml>';
}else{
return '<xml><return_code><![CDATA[FAIL]]></return_code><return_msg><![CDATA[OK]]></return_msg></xml>';
}
}
/*
* 接收post数据
* 微信是用$GLOBALS['HTTP_RAW_POST_DATA'];这个函数接收post数据的
*/
public function post_data()
{
$receipt = $_REQUEST;
if ($receipt == null) {
$receipt = file_get_contents("php://input");
if ($receipt == null) {
$receipt = $GLOBALS['HTTP_RAW_POST_DATA'];
}
}
return $receipt;
}
//把对象转成数组
public function object_toarray($arr)
{
if (is_object($arr)) {
$arr = (array) $arr;
}if (is_array($arr)) {
foreach ($arr as $key => $value) {
$arr[$key] = $this->object_toarray($value);
}
}
return $arr;
}
/**
* 格式化参数格式化成url参数
*/
private function params_tourl($arr)
{
$weipay_key = $this->wxkey; //微信的key,这个是微信支付给你的key,不要瞎填。
$buff = "";
foreach ($arr as $k => $v) {
if ($k != "sign" && $v != "" && !is_array($v)) {
$buff .= $k . "=" . $v . "&";
}
}
$buff = trim($buff, "&");
return $buff . '&key=' . $weipay_key;
}
//随机字符串
public function unicode() {
$str = uniqid(mt_rand(),1);
$str=sha1($str);
return md5($str);
}
//生成订单号
function genRandomString($len = 5) {
$chars = array(
"a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k",
"l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v",
"w", "x", "y", "z", "A", "B", "C", "D", "E", "F", "G",
"H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R",
"S", "T", "U", "V", "W", "X", "Y", "Z", "0", "1", "2",
"3", "4", "5", "6", "7", "8", "9"
);
$charsLen = count($chars) - 1;
// 将数组打乱
shuffle($chars);
$output = "";
for ($i = 0; $i < $len; $i++) {
$output .= $chars[mt_rand(0, $charsLen)];
}
return $output;
}
}