<?php defined('BASEPATH') OR exit('No direct script access allowed');
/**
* 微信支付 - APP - 类
* @author NangongYi
* @time 2020-03-03
*/
class Wechat_payment_service extends FIT_Service
{
/**
* 构造函数,初始化成员变量
* @param string $appid 商户的应用ID
* @param int $mch_id 商户编号
* @param string $key 秘钥
* @param string $notify_url 回调地址
*/
public function __construct($appid, $mch_id, $key, $notify_url)
{
if (is_string($appid) && is_string($mch_id)) {
$this->appid = $appid;
$this->mch_id = $mch_id;
$this->key = $key;
$this->notify_url = $notify_url;
}
}
/**
* 微信支付统一下单,生成预支付交易单
* @param string $body
* @param string $out_trade_no
* @param float $total_fee
* @param string $ip
* @return mixed
*/
public function weChat_pay($body, $out_trade_no, $total_fee, $ip)
{
$request_data = array(
'appid' => $this->appid, //应用APPID
'mch_id' => $this->mch_id, //商户号
'trade_type' => 'APP', //支付类型
'nonce_str' => $this->get_nonce_str(), //随机字符串 不长于32位
'body' => $body, //商品名称
'out_trade_no' => $out_trade_no, //商户后台订单号
'total_fee' => $total_fee * 100, //商品价格
'spbill_create_ip' => $ip, //用户端实际ip
'notify_url' => $this->notify_url, //异步通知回调地址
);
// 获取签名
$request_data['sign'] = $this->get_sign($request_data);
// 发送请求
$res = $this->send_prePay_curl($this->produce_xml_data($request_data));
if($res['return_code'] == 'SUCCESS' && $res['result_code'] == 'SUCCESS'){
$Secondary['appid'] = $this->appid;
$Secondary['partnerid'] = $this->mch_id; //商户号
$Secondary['prepayid'] = $res['prepay_id']; //预支付交易会话标识
$Secondary['noncestr'] = $res['nonce_str']; //$this->get_nonce_str();
$Secondary['timestamp'] = time();
$Secondary['package'] = "Sign=WXPay";
$Secondary['sign'] = $this->get_second_sign($Secondary);
return ['error_code'=>200,'error_msg'=>'支付成功!', 'data'=>$Secondary];
}else{
return ['error_code'=>201,'error_msg'=>$res['return_msg']];
}
}
/**
* 微信回调
* @return mixed
*/
public function wx_notify()
{
//允许从外部加载XML实体(防止XML注入攻击)
libxml_disable_entity_loader(true);
$postStr = $this->post_data();//接收post数据
$postObj = simplexml_load_string($postStr, 'SimpleXMLElement', LIBXML_NOCDATA);
$arr = $this->object_to_array($postObj);//对象转成数组
ksort($arr);// 对数据进行排序
$str = $this->params_to_url($arr);//对数据拼接成字符串
$user_sign = strtoupper(md5($str));
if($user_sign == $arr['sign']){//验证签名
return '<xml><return_code><![CDATA[SUCCESS]]></return_code><return_msg><![CDATA['.json_encode($arr).']]></return_msg></xml>';
}else{
return '<xml><return_code><![CDATA[FAIL]]></return_code><return_msg><![CDATA['.json_encode($arr).']]></return_msg></xml>';
}
}
/**
* 调取支付接口,查询支付状态
* @param string $out_trade_no
* @param int $user_coins
* @return mixed
*/
public function order_query($out_trade_no, $user_coins)
{
$request_data = array(
'appid' => $this->appid, //应用APPID
'mch_id' => $this->mch_id, //商户号
'nonce_str' => $this->get_nonce_str(), //随机字符串 不长于32位
'out_trade_no' => $out_trade_no, //商户后台订单号
);
// 获取签名
$request_data['sign'] = $this->get_sign($request_data);
// 发送请求
$res = $this->send_oQuery_curl($this->produce_xml_data($request_data));
if($res['return_code'] == 'SUCCESS' && $res['result_code'] == 'SUCCESS'){
$data = $user_coins ? ['user_coins'=>$user_coins] : [];
return ['error_code'=>200,'error_msg'=>'支付成功!', 'data'=>$data];
}else{
return ['error_code'=>201,'error_msg'=>$res['err_code_des']];
}
}
/**
* 通过curl发送数据给微信接口 - 下单支付并返回调起数据
* @param array $xmlData
* @return mixed
*/
private function send_prePay_curl($xmlData)
{
$url = "https://api.mch.weixin.qq.com/pay/unifiedorder";
return $this->send_data_curl($url, $xmlData);
}
/**
* 通过curl发送数据给微信接口 - 查询订单支付状态
* @param array $xmlData
* @return mixed
*/
private function send_oQuery_curl($xmlData)
{
$url = "https://api.mch.weixin.qq.com/pay/orderquery";
return $this->send_data_curl($url, $xmlData);
}
/**
* 通过curl发送数据给微信接口的函数
* @param string $url
* @param array $xmlData
* @return mixed
*/
private function send_data_curl($url, $xmlData)
{
$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->xml_to_array($data);
}
/**
* 生成随机数并返回
* @return string 32位字符
*/
private function get_nonce_str()
{
$code = "";
for ($i=0; $i > 10; $i++) {
$code .= mt_rand(1000); //获取随机数
}
$nonceStrTemp = md5($code);
$nonce_str = mb_substr($nonceStrTemp, 5,37); //MD5加密后截取32位字符
return $nonce_str;
}
/**
* 将xml转为array
*
* @param $xml
* @return mixed
*/
private function xml_to_array($xml)
{
//将XML转为array
return json_decode(json_encode(simplexml_load_string($xml, 'SimpleXMLElement', LIBXML_NOCDATA)), TRUE);
}
/**
* 生成xml格式的数据
* @param array $data
* @return mixed
*/
private function produce_xml_data($data)
{
$xmlData = "<xml>";
foreach ($data as $key => $value) {
$xmlData.="<".$key."><![CDATA[".$value."]]></".$key.">";
}
$xmlData = $xmlData."</xml>";
return $xmlData;
}
/**
* 一次签名的函数
* @param array $data
* @return mixed
*/
private function get_sign($data)
{
ksort($data);
$str = '';
foreach ($data as $key => $value) {
$str .= !$str ? $key . '=' . $value : '&' . $key . '=' . $value;
}
$str.='&key='.$this->key;
$sign = strtoupper(md5($str));
return $sign;
}
/**
* 二次签名的函数
* @param array $data
* @return mixed
*/
private function get_second_sign($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);
}
/**
* 接收post数据
* @return array
*/
private function post_data()
{
$receipt = file_get_contents("php://input");
if($receipt == null){
$receipt = $GLOBALS['HTTP_RAW_POST_DATA'];
}
return $receipt;
}
/**
* 把对象转成数组
* @param array $arr
* @return array
*/
private function object_to_array($arr)
{
if(is_object($arr)) {
$arr = (array)$arr;
} if(is_array($arr)) {
foreach($arr as $key=>$value) {
$arr[$key] = $this->object_to_array($value);
}
}
return $arr;
}
/**
* 格式化参数格式化成url参数
* @param array $arr
* @return string
*/
private function params_to_url($arr)
{
$weChat_pay_key = $this->key;
$buff = "";
foreach ($arr as $k => $v)
{
if($k != "sign" && $v != "" && !is_array($v)){
$buff .= $k . "=" . $v . "&";
}
}
$buff = trim($buff, "&");
return $buff.'&key='.$weChat_pay_key;
}
}
PHP之 微信APP支付类
猜你喜欢
转载自blog.csdn.net/LDR1109/article/details/105492650
今日推荐
周排行