<?php
/**
* 微信 app 支付
*
* @license
* @link
* @since
*/
class wxAppPay
{
private $key = '8102b22a111111176d9f381ec6f837'; // 商户号的是 key 在微信商户平台上自己设定的 api 密钥 32 位
private $appid = 'wxbca5555502a91e9a'; // 在微信开放平台申请的 appid
private $mchId = '1000000'; // 商户号
private $payUrl = 'https://api.mch.weixin.qq.com/pay/unifiedorder'; // 统一下单请求接口
/*
* total_fee 支付金额
* out_trade_no 订单号
* notify_url 回调地址
*/
public function doPay($params)
{$postData = array();
$postData['appid'] = $this->appid;
$postData['mch_id'] = $this->mchId;
$postData['nonce_str'] = $this->createNoncestr();
$postData['body'] = 'app 支付';
$postData['out_trade_no'] = date("YmdHis");
$postData['total_fee'] = $params['total_fee'];
$postData["spbill_create_ip"] = $_SERVER["REMOTE_ADDR"];
$postData['notify_url'] = $params['notify_url'];
$postData['trade_type'] = 'APP';
$postData["sign"] = $this->createSign($postData);
// 把数组转化成 xml 格式
$xmlData = $this->arrayToXml($postData);
$res = $this->curl_post($this->payUrl, $xmlData);
$res = simplexml_load_string($res,NULL,LIBXML_NOCDATA);
// 生成正式支付参数
$data = array();
$data['appid'] = $this->appid;
$data['noncestr'] = $postData['nonce_str'];
// 微信修改接口参数,否则 IOS 报解析失败
$data['package'] = 'Sign=WXPay';
$data['partnerid'] = $this->mchId;
$data['prepayid'] = (string)$res->prepay_id;
$data['timestamp'] = time();
$sign = $postData["sign"];
$data['sign'] = $sign;
return $data;
}
// 发送 curl post
private function curl_post($url = '', $param = array(),$headers = array()){if (empty($url)) {return false;}
$ch = curl_init();// 初始化 curl
curl_setopt($ch, CURLOPT_URL,$url);// 抓取指定网页
curl_setopt($ch, CURLOPT_HEADER, 0);// 设置 header
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);// 要求结果为字符串且输出到屏幕上
curl_setopt($ch, CURLOPT_POST, 1);//post 提交方式
curl_setopt($ch, CURLOPT_POSTFIELDS, $param);
if($cookie_jar)
curl_setopt($ch, CURLOPT_COOKIEJAR, $cookie_jar); // 保存 cookie 信息
if($headers) curl_setopt($ch,CURLOPT_HTTPHEADER,$headers);
$data = curl_exec($ch);// 运行 curl
curl_close($ch);
return $data;
}
// 生成签名
private function createSign($params)
{
// 签名步骤一:按字典序排序参数
ksort($params);
$String = $this->formatBizQueryParaMap($params, false);
// 签名步骤二:在 string 后加入 KEY
$String = $String."&key=".$this->key;
// 签名步骤三:MD5 加密
$String = md5($String);
// 签名步骤四:所有字符转为大写
$result_ = strtoupper($String);
return $result_;
}
// 按字典序排序参数
private function formatBizQueryParaMap($params,$urlencode=false)
{ksort($params);
$buff = '';
foreach($params as $key=>$val)
{$buff .= $key . "=" . $val . "&";}
$reqPar = substr($buff, 0, strlen($buff)-1);
return $reqPar;
}
// 将数组转换为 xml 格式
private function arrayToXml($arr)
{
$xml = "<xml>";
foreach($arr as $key=>$val)
{if(is_numeric($val))
$xml .= '<' . $key .'>' . $val . '</' . $key . '>';
else
$xml .= "<".$key."><![CDATA[".$val."]]></".$key.">";
}
$xml .="</xml>";
return $xml;
}
// 随机字符串
private function createNoncestr($length=32)
{
$chars = 'abcdefghijklmnopqrstuvwxyz0123456789';
$str = '';
for($i=0;$i<$length;$i++){$str .= substr($chars, mt_rand(0, strlen($chars)-1), 1);
}
return $str;
}
}
调用
$payObj = new wxAppPay();
$params = array(
‘total_fee’ => 100,
‘out_trade_no’ => date(‘YmdHis’),
‘notify_url’ => ‘ 你自己的回调地址 ’
);
$data = $payObj->doPay();
小坑提示:如果参数都没有问题,在签名工具上也是说的签名成功。很大的可能是 api key 的问题。重新设置一下 key 就可以了。
如果需要证书的,也是在这个商户后台去获取证书。