204 lines
6.2 KiB
PHP
Executable File
204 lines
6.2 KiB
PHP
Executable File
<?php
|
||
namespace tools;
|
||
|
||
/**
|
||
* 微信小程序支付
|
||
*
|
||
*/
|
||
use Org\Util\Date;
|
||
|
||
class WxxiaopayApi {
|
||
|
||
protected $APPID;
|
||
protected $MCHID;
|
||
protected $KEY;
|
||
protected $notify_url;
|
||
|
||
public function __construct($APPID,$MCHID,$KEY,$notify_url)
|
||
{
|
||
$this->APPID = $APPID;
|
||
$this->MCHID = $MCHID;
|
||
$this->KEY = $KEY;
|
||
$this->notify_url = $notify_url;
|
||
}
|
||
|
||
/**
|
||
**$order_sn 原订单号
|
||
**$order_sn 现订单号
|
||
**$totalFee 价格
|
||
**$openid
|
||
**/
|
||
//统一下单调用
|
||
public function prePay($order_sn,$order_by_sn, $totalFee, $openid,$ip){
|
||
$url = 'https://api.mch.weixin.qq.com/pay/unifiedorder';
|
||
$nonce_str = self::getRandChar_l(32);
|
||
$data['appid'] =$this->APPID;
|
||
$data['mch_id'] = $this->MCHID;
|
||
$data['nonce_str'] = $nonce_str;
|
||
$data['body'] = '订单编号:'.$order_sn;
|
||
$data['out_trade_no'] = $order_by_sn;
|
||
$data['total_fee'] = $totalFee*100;
|
||
$data['spbill_create_ip'] =$ip;
|
||
$data['notify_url'] = $this->notify_url;
|
||
$data['trade_type'] = 'JSAPI';
|
||
$data['openid'] = $openid;
|
||
$data['sign'] = self::sign($data,$this->KEY);
|
||
$xml = self::arrayToXml($data);
|
||
$response = self::postXmlCurl($xml, $url);
|
||
$array=self::xmlstr_to_array($response);
|
||
$wxData = self::wxPay($array['prepay_id'],$this->APPID,$this->KEY);
|
||
return $wxData;
|
||
}
|
||
|
||
//微信支付
|
||
static function wxPay($prepayId,$APPID,$KEY){
|
||
$data['appId'] = $APPID;
|
||
$data['nonceStr'] = self::getRandChar_l(32);
|
||
$data['package'] = "prepay_id=".$prepayId;
|
||
$data['signType'] = 'MD5';
|
||
$data['timeStamp'] = time();
|
||
$data['sign'] = self::getSign($data,$KEY);
|
||
return $data;
|
||
}
|
||
|
||
|
||
|
||
///生成签名
|
||
static function getSign($Obj,$KEY){
|
||
foreach ($Obj as $k => $v) {
|
||
$Parameters[strtolower($k)] = $v;
|
||
}
|
||
// 签名步骤一:按字典序排序参数
|
||
ksort($Parameters);
|
||
$String = "appId=".$Obj['appId']."&nonceStr=".$Obj['nonceStr']."&package=".$Obj['package']."&signType=MD5&timeStamp=".$Obj['timeStamp'];
|
||
// 签名步骤二:在string后加入KEY
|
||
$String = $String . "&key=" . $KEY;
|
||
// 签名步骤三:MD5加密
|
||
$result_ = strtoupper(md5($String));
|
||
return $result_;
|
||
}
|
||
|
||
// xml转成数组
|
||
static function xmlstr_to_array($xmlstr){
|
||
//禁止引用外部xml实体
|
||
|
||
libxml_disable_entity_loader(true);
|
||
|
||
$xmlstring = simplexml_load_string($xmlstr, 'SimpleXMLElement', LIBXML_NOCDATA);
|
||
|
||
$val = json_decode(json_encode($xmlstring),true);
|
||
|
||
return $val;
|
||
|
||
|
||
}
|
||
|
||
|
||
// 获取指定长度的随机字符串
|
||
protected function getRandChar($length){
|
||
$str = null;
|
||
$strPol = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789abcdefghijklmnopqrstuvwxyz";
|
||
$max = strlen($strPol) - 1;
|
||
|
||
for ($i = 0; $i < $length; $i ++) {
|
||
$str .= $strPol[rand(0, $max)]; // rand($min,$max)生成介于min和max两个数之间的一个随机整数
|
||
}
|
||
|
||
return $str;
|
||
}
|
||
|
||
|
||
// 将数组转成uri字符串
|
||
static function formatBizQueryParaMap($paraMap, $urlencode){
|
||
$buff = "";
|
||
ksort($paraMap);
|
||
foreach ($paraMap as $k => $v) {
|
||
if ($urlencode) {
|
||
$v = urlencode($v);
|
||
}
|
||
$buff .= strtolower($k) . "=" . $v . "&";
|
||
}
|
||
$reqPar;
|
||
if (strlen($buff) > 0) {
|
||
$reqPar = substr($buff, 0, strlen($buff) - 1);
|
||
}
|
||
return $reqPar;
|
||
}
|
||
|
||
// 数组转xml
|
||
static 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;
|
||
}
|
||
|
||
// post https请求,CURLOPT_POSTFIELDS xml格式
|
||
static function postXmlCurl($xml, $url, $second = 30){
|
||
// 初始化curl
|
||
$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);
|
||
// 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);
|
||
echo "curl出错,错误码:$error" . "<br>";
|
||
echo "<a href='http://curl.haxx.se/libcurl/c/libcurl-errors.html'>错误原因查询</a></br>";
|
||
curl_close($ch);
|
||
return false;
|
||
}
|
||
}
|
||
|
||
|
||
//生成签名
|
||
static function sign($Obj,$KEY){
|
||
foreach ($Obj as $k => $v) {
|
||
$Parameters[strtolower($k)] = $v;
|
||
}
|
||
// 签名步骤一:按字典序排序参数
|
||
ksort($Parameters);
|
||
$String = self::formatBizQueryParaMap($Parameters, false);
|
||
// 签名步骤二:在string后加入KEY
|
||
$String = $String . "&key=" . $KEY;
|
||
// 签名步骤三:MD5加密
|
||
$result_ = strtoupper(md5($String));
|
||
return $result_;
|
||
}
|
||
|
||
// 获取指定长度的随机字符串
|
||
static function getRandChar_l($length){
|
||
$str = null;
|
||
$strPol = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789abcdefghijklmnopqrstuvwxyz";
|
||
$max = strlen($strPol) - 1;
|
||
|
||
for ($i = 0; $i < $length; $i ++) {
|
||
$str .= $strPol[rand(0, $max)]; // rand($min,$max)生成介于min和max两个数之间的一个随机整数
|
||
}
|
||
|
||
return $str;
|
||
}
|
||
} |