在我们编写相关支付的时候,经常会使用微信支付,
在PHP中使用微信支付还是比较简单的,
微信支付文档:https://pay.weixin.qq.com/wiki/doc/API/index.HTML
这里简单介绍微信支付的几种使用,
这里微信支付我封装了一个微信支付的类库,
直接传递参数就可使用:
首先把配置文件填写完整(细心不要填错,否则会导致签名错误):
$config = array( 'appID' => '', // 微信支付appID 'xcxappID' => '', // 微信小程序appID 'mch_ID' => '', // 微信支付 mch_ID 商户收款账号 'key' => '', // 微信支付key 'appsecret' => '', // 公众帐号secert(公众号支付专用) 'notify_url' => '', // 接收支付状态的连接 改成自己的回调地址 'redirect_uri' => '', // 公众号支付时,没有code,获取openID使用);
对于相关支付我也也成了函数便于使用,
微信扫码支付:
/** * [qrcodePay 微信扫码支付] * @param [type] $order [订单信息数组] * @return [type] [description] * $order = array( * 'body' => '', // 产品描述 * 'total_fee' => '', // 订单金额(分) * 'out_Trade_no' => '', // 订单编号 * 'product_ID' => '', // 产品ID(可用订单编号) * ); */public static function qrcodePay($order=NulL){ if(!is_array($order) || count($order) < 4){ dIE("数组数据信息缺失!"); } $order['Trade_type'] = 'NATIVE'; // Native支付 $result = self::unifIEdOrder($order); $decodeurl = urldecode($result['code_url']); return $decodeurl; // 使用返回链接直接生成二维码}
微信H5支付:
/** * [weixinH5 微信H5支付] * @param [type] $order [订单信息数组] * @return [type] [description] * $order = array( * 'body' => '', // 产品描述 * 'total_fee' => '', // 订单金额(分) * 'out_Trade_no' => '', // 订单编号 * 'product_ID' => '', // 产品ID(可用订单编号) * ); */public static function h5Pay($order=NulL){ if(!is_array($order) || count($order) < 4){ dIE("数组数据信息缺失!"); } $order['Trade_type'] = 'MWEB'; // H5支付 $result = self::unifIEdOrder($order); if ($result['return_code']=='SUCCESS' && $result['result_code']=='SUCCESS') return $result['mweb_url']; // 返回链接让用户点击跳转 if ($result['err_code_des']) dIE($result['err_code_des']); return false;}
微信小程序支付:
/** * [xcxPay 获取Jssdk需要用到的数据] * @param [type] $order [订单信息数组] * @param boolean $type [区分是否是小程序,默认 true] * @return [type] [description] * $order = array( * 'body' => '', // 产品描述 * 'total_fee' => '', // 订单金额(分) * 'out_Trade_no' => '', // 订单编号 * 'product_ID' => '', // 产品ID(可用订单编号) * 'openID' => '', // 用户openID * ); */public static function xcxPay($order=NulL,$type=true){ if(!is_array($order) || count($order) < 5){ dIE("数组数据信息缺失!"); } $order['Trade_type'] = 'JsAPI'; // 小程序支付 $result = self::unifIEdOrder($order,$type); if ($result['return_code']=='SUCCESS' && $result['result_code']=='SUCCESS') { $data = array ( 'appID' => $type ? $this->config['xcxappID'] : $this->config['appID'], 'timeStamp' => time(), 'nonceStr' => self::get_rand_str(32, 0, 1), // 随机32位字符串 'package' => 'prepay_ID='.$result['prepay_ID'], 'signType' => 'MD5', // 加密方式 ); $data['paySign'] = self::makeSign($data); return $data; // 数据小程序客户端 } else { if ($result['err_code_des']) dIE($result['err_code_des']); return false; }}
使用方法(这里已小程序支付为示例):
<?PHPinclude './WeixinPay.PHP';$get = $_GET;$weixinpay = new \feng\WeixinPay($config);$order_sn = time().rand(1000,9999);$order = array( 'body' => '测试商品', // 产品描述 'total_fee' => '1', // 订单金额(分) 'out_Trade_no' => $order_sn, // 订单编号 'product_ID' => $order_sn, // 产品ID(可用订单编号) 'openID' => $get['openID'], // 用户openID);$re = $weixinpay->xcxPay($order);dIE(Json_encode($re)); // JsON化直接返回小程序客户端
如下代码是封装好的完整支付类文件(WeixinPay.PHP),
可以根据自己需求随意修改(不定期修改完善 Gitee 与 GitHub):
<?PHP/** * @Author: [FENG] <1161634940@qq.com> * @Date: 2019-09-06 09:50:30 * @Last ModifIEd by: [FENG] <1161634940@qq.com> * @Last ModifIEd time: 2020-10-08T17:33:39+08:00 */namespace feng;error_reporting(E_ALL);ini_set('display_errors', '1');// 定义时区ini_set('date.timezone','Asia/Shanghai');class WeixinPay{ // 定义相关配置项 private static $sslcert_path = './cert/apiclient_cert.pem'; // 证书(退款时使用) private static $sslkey_path = './cert/apiclient_key.pem'; // 证书(退款时使用) private static $referer = ''; private static $config = array( 'appID' => '', // 微信支付appID 'xcxappID' => '', // 微信小程序appID 'mch_ID' => '', // 微信支付 mch_ID 商户收款账号 'key' => '', // 微信支付key 'appsecret' => '', // 公众帐号secert(公众号支付专用) 'notify_url' => '', // 接收支付状态的连接 改成自己的回调地址 'redirect_uri' => '', // 公众号支付时,没有code,获取openID使用 ); /** * [__construct 构造函数] * @param [type] $config [传递微信支付相关配置] */ public function __construct($config=NulL, $referer=NulL){ $config && self::$config = $config; self::$referer = $referer ? $referer : $_SERVER['http_HOST']; } /** * [unifIEdOrder 统一下单] * @param [type] $order [订单信息(必须包含支付所需要的参数)] * @param boolean $type [区分是否是小程序,是则传 true] * @return [type] [description] * $order = array( * 'body' => '', // 产品描述 * 'total_fee' => '', // 订单金额(分) * 'out_Trade_no' => '', // 订单编号 * 'product_ID' => '', // 产品ID * 'Trade_type' => '', // 类型:JsAPI--JsAPI支付(或小程序支付)、NATIVE--Native支付、APP--app支付,MWEB--H5支付 * ); */ public static function unifIEdOrder($order, $type=NulL) { $weixinpay_config = array_filter(self::$config); // 获取配置项 $config = array( 'appID' => empty($type) ? $weixinpay_config['appID'] : $weixinpay_config['xcxappID'], 'mch_ID' => $weixinpay_config['mch_ID'], 'nonce_str' => 'test', 'spbill_create_ip' => self::get_iP(), 'notify_url' => $weixinpay_config['notify_url'] ); $data = array_merge($order, $config); // 合并配置数据和订单数据 $sign = self::makeSign($data); // 生成签名 $data['sign'] = $sign; $xml = self::array_to_xml($data); $url = 'https://API.mch.weixin.qq.com/pay/unifIEdorder';//接收xml数据的文件 $header[] = "Content-type: text/xml";//定义content-type为xml,注意是数组 $ch = curl_init ($url); curl_setopt($ch, CURLOPT_URL, $url); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); // 兼容本地没有指定curl.cainfo路径的错误 curl_setopt($ch, CURLOPT_REFERER, self::$referer); //设置 referer curl_setopt($ch, CURLOPT_httpheader, $header); curl_setopt($ch, CURLOPT_POST, 1); curl_setopt($ch, CURLOPT_POSTFIELDS, $xml); $response = curl_exec($ch); if(curl_errno($ch)){ dIE(curl_error($ch)); // 显示报错信息;终止继续执行 } curl_close($ch); $result = self::xml_to_array($response); if ($result['return_code']=='FAIL') dIE($result['return_msg']); // 显示错误信息 if ($result['result_code']=='FAIL') dIE($result['err_code_des']); // 显示错误信息 $result['sign'] = $sign; $result['nonce_str'] = 'test'; return $result; } /** * [qrcodePay 微信扫码支付] * @param [type] $order [订单信息数组] * @return [type] [description] * $order = array( * 'body' => '', // 产品描述 * 'total_fee' => '', // 订单金额(分) * 'out_Trade_no' => '', // 订单编号 * 'product_ID' => '', // 产品ID(可用订单编号) * ); */ public static function qrcodePay($order=NulL) { if(!is_array($order) || count($order) < 4){ dIE("数组数据信息缺失!"); } $order['Trade_type'] = 'NATIVE'; // Native支付 $result = self::unifIEdOrder($order); $decodeurl = urldecode($result['code_url']); return $decodeurl; // qrcode($decodeurl); // qrcodeWithPicture($decodeurl); } /** * [JsPay 获取Jssdk需要用到的数据] * @param [type] $order [订单信息数组] * @return [type] [description] * $order = array( * 'body' => '', // 产品描述 * 'total_fee' => '', // 订单金额(分) * 'out_Trade_no' => '', // 订单编号 * 'product_ID' => '', // 产品ID(可用订单编号) * ); */ public static function JsPay($order=NulL,$code=NulL){ $config=self::$config; if (!is_array($order) || count($order) < 4) dIE("数组数据信息缺失!"); if (count($order) == 5) { $data = self::xcxPay($order, false); // 获取支付相关信息(获取非小程序信息) return $data; } empty($code) && $code = $_GET['code']; // 如果没有get参数没有code;则重定向去获取openID; if (empty($code)) { $out_Trade_no = $order['out_Trade_no']; // 获取订单号 $redirect_uri = $config['redirect_uri']; // 返回的url $redirect_uri = urlencode($redirect_uri); $url = 'https://open.weixin.qq.com/connect/oauth2/authorize?appID='.$config['appID'].'&redirect_uri='.$redirect_uri.'&response_type=code&scope=snsAPI_base&state='.$out_Trade_no.'#wechat_redirect'; header('Location: '.$url); } else { // 组合获取prepay_ID的url $url = 'https://API.weixin.qq.com/sns/oauth2/access_token?appID='.$config['appID'].'&secret='.$config['appsecret'].'&code='.$code.'&grant_type=authorization_code'; $result = self::curl_get_contents($url); // curl获取prepay_ID $result = Json_decode($result,true); $order['openID'] = $result['openID']; // 获取到的openID $data = self::xcxPay($order, false); // 获取支付相关信息(获取非小程序信息) return $data; } } /** * [xcxPay 获取Jssdk需要用到的数据] * @param [type] $order [订单信息数组] * @param boolean $type [区分是否是小程序,默认 true] * @return [type] [description] * $order = array( * 'body' => '', // 产品描述 * 'total_fee' => '', // 订单金额(分) * 'out_Trade_no' => '', // 订单编号 * 'product_ID' => '', // 产品ID(可用订单编号) * 'openID' => '', // 用户openID * ); */ public static function xcxPay($order=NulL,$type=true) { if(!is_array($order) || count($order) < 5){ dIE("数组数据信息缺失!"); } $order['Trade_type'] = 'JsAPI'; // 小程序支付 $result = self::unifIEdOrder($order,$type); if ($result['return_code']=='SUCCESS' && $result['result_code']=='SUCCESS') { $data = array ( 'appID' => $type ? self::$config['xcxappID'] : self::$config['appID'], 'timeStamp' => (string)time(), 'nonceStr' => self::get_rand_str(32, 0, 1), // 随机32位字符串 'package' => 'prepay_ID='.$result['prepay_ID'], 'signType' => 'MD5', // 加密方式 ); $data['paySign'] = self::makeSign($data); return $data; // 数据小程序客户端 } else { if ($result['err_code_des']) dIE($result['err_code_des']); return false; } } /** * [weixinH5 微信H5支付] * @param [type] $order [订单信息数组] * @return [type] [description] * $order = array( * 'body' => '', // 产品描述 * 'total_fee' => '', // 订单金额(分) * 'out_Trade_no' => '', // 订单编号 * 'product_ID' => '', // 产品ID(可用订单编号) * ); */ public static function h5Pay($order=NulL) { if(!is_array($order) || count($order) < 4){ dIE("数组数据信息缺失!"); } $order['Trade_type'] = 'MWEB'; // H5支付 $result = self::unifIEdOrder($order); if ($result['return_code']=='SUCCESS' && $result['result_code']=='SUCCESS') return $result['mweb_url']; // 返回链接让用户点击跳转 if ($result['err_code_des']) dIE($result['err_code_des']); return false; } /** * [refund 微信支付退款] * @param [type] $order [订单信息] * @param [type] $type [是否是小程序] * $order = array( * 'body' => '', // 退款原因 * 'total_fee' => '', // 商品价格(分) * 'out_Trade_no' => '', // 订单编号 * 'transaction_ID'=> '', // 微信订单号 * ); */ public static function refund($order, $type=NulL) { $config = self::$config; $data = array( 'appID' => empty($type) ? $config['appID'] : $config['xcxappID'] , 'mch_ID' => $config['mch_ID'], 'nonce_str' => 'test', 'total_fee' => $order['total_fee'], //订单金额 单位 转为分 'refund_fee' => $order['total_fee'], //退款金额 单位 转为分 'sign_type' => 'MD5', //签名类型 支持HMAC-SHA256和MD5,默认为MD5 'transaction_ID'=> $order['transaction_ID'], //微信订单号 'out_Trade_no' => $order['out_Trade_no'], //商户订单号 'out_refund_no' => $order['out_Trade_no'], //商户退款单号 'refund_desc' => $order['body'], //退款原因(选填) ); // $unifIEd['sign'] = self::makeSign($unifIEd, $config['KEY']); $sign = self::makeSign($data); $data['sign'] = $sign; $xml = self::array_to_xml($data); $url = 'https://API.mch.weixin.qq.com/secAPI/pay/refund';//接收xml数据的文件 $response = self::postXmlSSLCurl($xml,$url); $result = self::xml_to_array($response); // 显示错误信息 if ($result['return_code']=='FAIL') { dIE($result['return_msg']); } $result['sign'] = $sign; $result['nonce_str'] = 'test'; return $result; } /** * [notify 回调验证] * @return [array] [返回数组格式的notify数据] */ public static function notify() { $xml = file_get_contents('PHP://input', 'r'); // 获取xml if (!$xml) dIE('暂无回调信息'); $data = self::xml_to_array($xml); // 转成PHP数组 $data_sign = $data['sign']; // 保存原sign unset($data['sign']); // sign不参与签名 $sign = self::makeSign($data); // 判断签名是否正确 判断支付状态 if ($sign===$data_sign && $data['return_code']=='SUCCESS' && $data['result_code']=='SUCCESS') { $result=$data; }else{ $result=false; } // 返回状态给微信服务器 if ($result) { $str='<xml><return_code><![cdaTA[SUCCESS]]></return_code><return_msg><![cdaTA[OK]]></return_msg></xml>'; }else{ $str='<xml><return_code><![cdaTA[FAIL]]></return_code><return_msg><![cdaTA[签名失败]]></return_msg></xml>'; } echo $str; return $result; } /** * [makeSign 生成签名] * 本方法不覆盖sign成员变量,如要设置签名需要调用SetSign方法赋值 * @param [type] $data [description] * @return [type] [description] */ public static function makeSign($data) { // 去空 $data = array_filter($data); //签名步骤一:按字典序排序参数 ksort($data); $string_a = http_build_query($data); $string_a = urldecode($string_a); //签名步骤二:在string后加入key $config = self::$config; $string_sign_temp = $string_a."&key=".$config['key']; //签名步骤三:MD5加密 $sign = md5($string_sign_temp); // 签名步骤四:所有字符转为大写 $result = strtoupper($sign); return $result; } /** * [xml_to_array 将xml转为array] * @param [type] $xml [xml字符串] * @return [type] [转换得到的数组] */ public static function xml_to_array($xml) { //禁止引用外部xml实体 libxml_disable_entity_loader(true); $result = Json_decode(Json_encode(simplexml_load_string($xml, 'SimpleXMLElement', liBXML_NOcdaTA)), true); return $result; } /** * [array_to_xml 输出xml字符] * @param [type] $data [description] * @return [type] [description] */ public static function array_to_xml($data) { if(!is_array($data) || count($data) <= 0){ dIE("数组数据异常!"); } $xml = "<xml>"; foreach ($data as $key=>$val){ if (is_numeric($val)){ $xml .= "<".$key.">".$val."</".$key.">"; }else{ $xml .= "<".$key."><![cdaTA[".$val."]]></".$key.">"; } } $xml .= "</xml>"; return $xml; } /** * [curl_get_contents get请求] * @param [type] $url [请求地址] * @return [type] [description] */ public static function curl_get_contents($url) { $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, $url); //设置访问的URL地址 // curl_setopt($ch,CURLOPT_header,1); //是否显示头部信息 curl_setopt($ch, CURLOPT_TIMEOUT, 5); //设置超时 curl_setopt($ch, CURLOPT_USERAGENT, $_SERVER['http_USER_AGENT']); //用户访问代理 User-Agent curl_setopt($ch, CURLOPT_REFERER, self::$referer); //设置 referer curl_setopt($ch, CURLOPT_FolLOWLOCATION, 1); //跟踪301 curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); //返回结果 $r=curl_exec($ch); curl_close($ch); return $r; } /** * [postXmlSSLCurl 需要使用证书的请求] * @param [type] $xml [xml数据] * @param [type] $url [post请求地址] * @param integer $second [description] * @return [type] [description] */ public static 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>"; curl_close($ch); return false; } } /** fengkui.net * [get_rand_str 获取随机字符串] * @param integer $randLength [长度] * @param integer $addtime [是否加入当前时间戳] * @param integer $includenumber [是否包含数字] * @return [type] [description] */ public static function get_rand_str($randLength=6,$addtime=1,$includenumber=0) { if ($includenumber) $chars='abcdefghijklmnopqrstuvwxyzABCDEFGHJKLMNPQEST123456789'; $chars='abcdefghijklmnopqrstuvwxyz'; $len=strlen($chars); $randStr=''; for ($i=0;$i<$randLength;$i++){ $randStr .= $chars[rand(0,$len-1)]; } $tokenvalue = $randStr; $addtime && $tokenvalue=$randStr.time(); return $tokenvalue; } /** fengkui.net * [get_iP 定义一个函数get_iP() 客户端IP] * @return [type] [description] */ public static function get_iP() { if (getenv("http_CLIENT_IP")) $ip = getenv("http_CLIENT_IP"); else if(getenv("http_X_FORWARDED_FOR")) $ip = getenv("http_X_FORWARDED_FOR"); else if(getenv("REMOTE_ADDR")) $ip = getenv("REMOTE_ADDR"); else $ip = "UnkNow"; if(preg_match('/^((?:(?:25[0-5]|2[0-4]\d|((1\d{2})|([1-9]?\d)))\.){3}(?:25[0-5]|2[0-4]\d|((1\d{2})|([1 -9]?\d))))$/', $ip)) return $ip; else return ''; }}总结
以上是内存溢出为你收集整理的分享封装的一个PHP微信支付的类库(扫码、H5、小程序)全部内容,希望文章能够帮你解决分享封装的一个PHP微信支付的类库(扫码、H5、小程序)所遇到的程序开发问题。
如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)