You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

468 lines
14 KiB
PHTML

<?php
/**
* 微信支付
*/
include_once("SDKRuntimeException.php");
/**
* 所有接口的基类
*/
class Common_util_pub
{
const SSLCERT_PATH = __DIR__ . '/cacert/apiclient_cert.pem';
const SSLKEY_PATH = __DIR__ . '/cacert/apiclient_key.pem';
function __construct($appid='', $mchid='') {
if ($appid)
$this->appid=$appid;
if ($mchid)
$this->mchid=$mchid;
}
function trimString($value)
{
$ret = null;
if (null != $value)
{
$ret = $value;
if (strlen($ret) == 0)
{
$ret = null;
}
}
return $ret;
}
/**
* 作用产生随机字符串不长于32位
*/
public 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;
}
/**
* 作用:格式化参数,签名过程需要使用
*/
function formatBizQueryParaMap($paraMap, $urlencode)
{
// $buff = "";
// ksort($paraMap);
// foreach ($paraMap as $k => $v)
// {
// if($urlencode)
// {
// $v = urlencode($v);
// }
// //$buff .= strtolower($k) . "=" . $v . "&";
// $buff .= $k . "=" . $v . "&";
// }
// $reqPar;
// if (strlen($buff) > 0)
// {
// $reqPar = substr($buff, 0, strlen($buff)-1);
// }
// return $reqPar;
$buff = "";
foreach ($paraMap as $k => $v)
{
if($k != "sign" && $v != "" && !is_array($v)){
$buff .= $k . "=" . $v . "&";
}
}
$buff = trim($buff, "&");
return $buff;
}
/**
* 作用:生成签名
*/
public function getSign($Obj)
{
foreach ($Obj as $k => $v)
{
$Parameters[$k] = $v;
}
//签名步骤一:按字典序排序参数
ksort($Parameters);
$String = $this->formatBizQueryParaMap($Parameters, false);
//echo '【string1】'.$String.'</br>';
//签名步骤二在string后加入KEY
$String = $String."&key=".$this->key;
// var_dump($String);
//echo "【string2】".$String."</br>";
//签名步骤三MD5加密
$String = md5($String);
//echo "【string3】 ".$String."</br>";
//签名步骤四:所有字符转为大写
$result_ = strtoupper($String);
//echo "【result】 ".$result_."</br>";
return $result_;
}
/**
* 作用array转xml
*/
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;
}
/**
* 作用将xml转为array
*/
public function xmlToArray($xml)
{
//将XML转为array
$array_data = json_decode(json_encode(simplexml_load_string($xml, 'SimpleXMLElement', LIBXML_NOCDATA)), true);
return $array_data;
}
/**
* 作用以post方式提交xml到对应的接口url
*/
function postXmlCurl($xml, $url, $useCert = false, $second = 30,$tt=0)
{
$ch = curl_init();
//设置超时
curl_setopt($ch, CURLOPT_TIMEOUT, $second);
//如果有配置代理这里就设置代理
// if(WxPayConfig::CURL_PROXY_HOST != "0.0.0.0"
// && WxPayConfig::CURL_PROXY_PORT != 0){
// curl_setopt($ch,CURLOPT_PROXY, WxPayConfig::CURL_PROXY_HOST);
// curl_setopt($ch,CURLOPT_PROXYPORT, WxPayConfig::CURL_PROXY_PORT);
// }
curl_setopt($ch,CURLOPT_URL, $url);
curl_setopt($ch,CURLOPT_SSL_VERIFYPEER,false);
curl_setopt($ch,CURLOPT_SSL_VERIFYHOST,FALSE);//严格校验
//设置header
curl_setopt($ch, CURLOPT_HEADER, FALSE);
//要求结果为字符串且输出到屏幕上
curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
if($useCert == true){
if($tt==3){
//设置证书
//使用证书cert 与 key 分别属于两个.pem文件
curl_setopt($ch,CURLOPT_SSLCERTTYPE,'PEM');
curl_setopt($ch,CURLOPT_SSLCERT, WxPayConfig::SSLCERT_PATH_APP);
curl_setopt($ch,CURLOPT_SSLKEYTYPE,'PEM');
curl_setopt($ch,CURLOPT_SSLKEY, WxPayConfig::SSLKEY_PATH_APP);
}else{
//设置证书
//使用证书cert 与 key 分别属于两个.pem文件
curl_setopt($ch,CURLOPT_SSLCERTTYPE,'PEM');
curl_setopt($ch,CURLOPT_SSLCERT, WxPayConfig::SSLCERT_PATH);
curl_setopt($ch,CURLOPT_SSLKEYTYPE,'PEM');
curl_setopt($ch,CURLOPT_SSLKEY, WxPayConfig::SSLKEY_PATH);
}
}
//post提交方式
curl_setopt($ch, CURLOPT_POST, TRUE);
curl_setopt($ch, CURLOPT_POSTFIELDS, $xml);
//运行curl
$data = curl_exec($ch);
//返回结果
if($data){
curl_close($ch);
return $data;
} else {
$error = curl_errno($ch);
curl_close($ch);
throw new WxPayException("curl出错错误码:$error");
}
}
/**
* 作用使用证书以post方式提交xml到对应的接口url
*/
function postXmlSSLCurl($xml,$url,$second=30)
{
$ch = curl_init();
//超时时间
curl_setopt($ch,CURLOPT_TIMEOUT,$second);
//这里设置代理,如果有的话
//curl_setopt($ch,CURLOPT_PROXY, '8.8.8.8');
//curl_setopt($ch,CURLOPT_PROXYPORT, 8080);
curl_setopt($ch,CURLOPT_URL, $url);
curl_setopt($ch,CURLOPT_SSL_VERIFYPEER,FALSE);
curl_setopt($ch,CURLOPT_SSL_VERIFYHOST,FALSE);
//设置header
curl_setopt($ch,CURLOPT_HEADER,FALSE);
//要求结果为字符串且输出到屏幕上
curl_setopt($ch,CURLOPT_RETURNTRANSFER,TRUE);
//设置证书
//使用证书cert 与 key 分别属于两个.pem文件
//默认格式为PEM可以注释
curl_setopt($ch,CURLOPT_SSLCERTTYPE,'PEM');
curl_setopt($ch,CURLOPT_SSLCERT, self::SSLCERT_PATH);
//默认格式为PEM可以注释
curl_setopt($ch,CURLOPT_SSLKEYTYPE,'PEM');
curl_setopt($ch,CURLOPT_SSLKEY, self::SSLKEY_PATH);
//post提交方式
curl_setopt($ch,CURLOPT_POST, true);
curl_setopt($ch,CURLOPT_POSTFIELDS,$xml);
$data = curl_exec($ch);
//返回结果
if($data){
curl_close($ch);
return $data;
}
else {
$error = curl_errno($ch);
echo "curl出错错误码:$error"."<br>";
echo "<a href='http://curl.haxx.se/libcurl/c/libcurl-errors.html'>错误原因查询</a></br>";
curl_close($ch);
return false;
}
}
/**
* 作用:打印数组
*/
function printErr($wording='',$err='')
{
print_r('<pre>');
echo $wording."</br>";
print_r('</pre>');
}
function wite_text($txt,$name){
$myfile = fopen($name, "w") or die("Unable to open file!");
fwrite($myfile, $txt);
fclose($myfile);
}
}
/**
* 请求型接口的基类
*/
class Wxpay_client_pub extends Common_util_pub
{
var $parameters;//请求参数,类型为关联数组
public $response;//微信返回的响应
public $result;//返回参数,类型为关联数组
var $url;//接口链接
var $curl_timeout;//curl超时时间
/**
* 作用:设置请求参数
*/
function setParameter($parameter, $parameterValue)
{
$this->parameters[$this->trimString($parameter)] = $this->trimString($parameterValue);
}
/**
* 作用设置标配的请求参数生成签名生成接口参数xml
*/
function createXml()
{
$this->parameters["appid"] = $this->appid;//公众账号ID
$this->parameters["mch_id"] = $this->mchid;//商户号
$this->parameters["nonce_str"] = $this->createNoncestr();//随机字符串
$this->parameters["sign"] = $this->getSign($this->parameters);//签名
return $this->arrayToXml($this->parameters);
}
/**
* 作用post请求xml
*/
function postXml($tt='')
{
$xml = $this->createXml();
$this->response = $this->postXmlCurl($xml,$this->url,'',$this->curl_timeout,$tt);
return $this->response;
}
/**
* 作用使用证书post请求xml
*/
function postXmlSSL()
{
$xml = $this->createXml();
$this->response = $this->postXmlSSLCurl($xml,$this->url,$this->curl_timeout);
return $this->response;
}
/**
* 作用:获取结果,默认不使用证书
*/
function getResult($tt='')
{
$this->postXml($tt);
$this->result = $this->xmlToArray($this->response);
return $this->result;
}
}
/**
* 统一支付接口类
*/
class WeixinPayBtoC extends Wxpay_client_pub
{
3 years ago
function __construct($config)
{
3 years ago
if(empty($config)){
throw new Exception("请输入配置");
}
$this->appid = $config['appid'];
$this->mchid = $config['mchid'];
$this->secret = $config['secret'];
// if ($appid)
// $this->appid = $appid;
// if ($mchid)
// $this->mchid = $mchid;
//设置接口链接
$this->url = "https://api.mch.weixin.qq.com/mmpaymkttransfers/promotion/transfers";
//设置curl超时时间
$this->curl_timeout = 30;
}
/**
* 生成接口参数xml
*/
function createXml()
{
try
{
$this->parameters["appid"] = $this->appid;//公众账号ID
$this->parameters["mch_id"] = $this->mchid;//商户号
$this->parameters["spbill_create_ip"] = $this->get_real_ip();//$_SERVER['REMOTE_ADDR'];//终端ip
$this->parameters["nonce_str"] = $this->createNoncestr();//随机字符串
$this->parameters["sign"] = $this->getSign($this->parameters);//签名
return $this->arrayToXml($this->parameters);
}catch (SDKRuntimeException $e)
{
die($e->errorMessage());
}
}
//获取真是ip
public function get_real_ip(){
$ip=false;
if(!empty($_SERVER['HTTP_CLIENT_IP'])){
$ip=$_SERVER['HTTP_CLIENT_IP'];
}
if(!empty($_SERVER['HTTP_X_FORWARDED_FOR'])){
$ips=explode (', ', $_SERVER['HTTP_X_FORWARDED_FOR']);
if($ip){ array_unshift($ips, $ip); $ip=FALSE; }
for ($i=0; $i < count($ips); $i++){
if(!preg_match ('/^(10│172.16│192.168)./', $ips[$i])){
// if(!eregi ('^(10│172.16│192.168).', $ips[$i])){
$ip=$ips[$i];
break;
}
}
}
return ($ip ? $ip : $_SERVER['REMOTE_ADDR']);
}
/**
* 获取prepay_id
*/
function getPrepayId()
{
$this->postXml();
$this->result = $this->xmlToArray($this->response);
$prepay_id = $this->result["prepay_id"];
return $prepay_id;
}
public function wxPayBtoC($amount, $openId, $realName, $orderId='', $desc='') {
$totalAmount = (100) * $amount;
$data=array(
'mch_appid'=> $this->appid, //商户账号appid
'mchid'=> $this->mchid,//商户号
3 years ago
'nonce_str'=> $this->createNoncestr(),//随机字符串
'partner_trade_no'=> $orderId ? $orderId : date('YmdHis').rand(1000, 9999),//商户订单号
'openid'=> $openId,//用户openid
'check_name'=>'FORCE_CHECK',//校验用户姓名选项,
're_user_name'=> $realName,//收款用户姓名
'amount'=>$totalAmount,//金额
'desc'=> $desc ? $desc : '打款',//企业付款描述信息
'spbill_create_ip'=> get_client_ip(),//Ip地址
);
//生成签名算法
$secretKey = $this->secret;///这个就是个API密码。MD5 32位。
$data = array_filter($data);
ksort($data);
$str = '';
foreach($data as $k=>$v) {
$str.=$k.'='.$v.'&';
}
$str = $str . 'key='. $secretKey;
$data['sign'] = strtoupper(md5($str));
//生成签名算法
$xml = $this->arraytoxml($data);
$url='https://api.mch.weixin.qq.com/mmpaymkttransfers/promotion/transfers'; //调用接口
3 years ago
$res = $this->postXmlSSLCurl($xml, $url);
$return = $this->xmltoarray($res);
3 years ago
return $return;
//返回来的结果是xml最后转换成数组
/*
array(9) {
["return_code"]=>
string(7) "SUCCESS"
["return_msg"]=>
array(0) {
}
["mch_appid"]=>
string(18) "wx57676786465544b2a5"
["mchid"]=>
string(10) "143345612"
["nonce_str"]=>
string(32) "iw6TtHdOySMAfS81qcnqXojwUMn8l8mY"
["result_code"]=>
string(7) "SUCCESS"
["partner_trade_no"]=>
string(18) "201807011410504098"
["payment_no"]=>
string(28) "1000018301201807019357038738"
["payment_time"]=>
string(19) "2018-07-01 14:56:35"
}
*/
$responseObj = simplexml_load_string($res, 'SimpleXMLElement', LIBXML_NOCDATA);
echo $res= $responseObj->return_code; //SUCCESS 如果返回来SUCCESS,则发生成功,处理自己的逻辑
return $res;
}
}
?>