虽然我不怎么用微擎,但是微擎作为微信开发框架确实挺成功的,而且其插件众多,为很多新手程序员提供了极大的方便。在微擎官方文档中是有支付的,但是发现很多人通过百度和社区问关于微信支付的问题,所以为了一劳永逸封装了一下H5的支付方式,方便后期使用。
类库源码:
- <?php
- /**
- * Created by 波波.
- * Date: 2018/7/16
- * Function:微信H5支付
- */
- if (!defined('IN_IA')) {
- exit('Access Denied');
- }
- class Wxpay_EweiShopV2Model{
- protected $appScrect;//微信公众平台的appscrect
- protected $appId;//微信公众平台appid
- protected $key;//微信商户平台配置的秘钥
- protected $mch_id;//微信商户号
- protected $values = array();
- public function __construct($appScrect="adfasdf",$appId="wx2cf4a9fa4", $key="ucskmsdffdfgxr3movndg",$mch_id ='1492355454542'){
- $this->appScrect=$appScrect;
- $this->appId=$appId;
- $this->key=$key;
- $this->mch_id=$mch_id;
- }
- public function payh5($total_fee,$body,$out_trade_no,$ip){
- //$ip= request()->ip();
- $url = "https://api.mch.weixin.qq.com/pay/unifiedorder";
- $notify_url ='http://'.$_SERVER['HTTP_HOST'].'/index/index/notify';
- $onoce_str = $this->createNoncestr();
- $data["appid"] = $this->appId;
- $data["body"] = $body;
- $data["mch_id"] = $this->mch_id;
- $data["nonce_str"] = $onoce_str;
- $data["notify_url"] = $notify_url;
- $data["out_trade_no"] = $out_trade_no;
- $data["spbill_create_ip"] = $ip;
- $data["total_fee"] = $total_fee*100;
- $data["trade_type"] = "MWEB";
- // $data["openid"] = $openid;
- $data["scene_info"] = "{'h5_info': {'type':'Wap','wap_url': $notify_url,'wap_name': '测试充值'}}";
- $sign = $this->getSign($data);
- // halt($data);
- $data["sign"] = $sign;
- $xml = $this->arrayToXml($data);
- $response = $this->postXmlCurl($xml, $url);
- //将微信返回的结果xml转成数组
- $response = $this->xmlToArray($response);
- //请求数据,统一下单
- return $response;
- }
- public static function getNonceStr($length = 32)
- {
- $chars = "abcdefghijklmnopqrstuvwxyz0123456789";
- $str ="";
- for ( $i = 0; $i < $length; $i++ ) {
- $str .= substr($chars, mt_rand(0, strlen($chars)-1), 1);
- }
- return $str;
- }
- // /*生成签名*/
- 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;
- //echo "【string2】".$String."</br>";
- //签名步骤三:MD5加密
- $String = md5($String);
- //echo "【string3】 ".$String."</br>";
- //签名步骤四:所有字符转为大写
- $result_ = strtoupper($String);
- //echo "【result】 ".$result_."</br>";
- return $result_;
- }
- /**
- * 作用:产生随机字符串,不长于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;
- }
- //数组转xml
- public 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
- */
- public 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>";
- curl_close($ch);
- return false;
- }
- }
- /*
- 获取当前服务器的IP
- */
- public function get_client_ip(){
- if ($_SERVER['REMOTE_ADDR']) {
- $cip = $_SERVER['REMOTE_ADDR'];
- } elseif (getenv("REMOTE_ADDR")) {
- $cip = getenv("REMOTE_ADDR");
- } elseif (getenv("HTTP_CLIENT_IP")) {
- $cip = getenv("HTTP_CLIENT_IP");
- } else {
- $cip = "unknown";
- }
- return $cip;
- }
- /**
- * 作用:格式化参数,签名过程需要使用
- */
- public function formatBizQueryParaMap($paraMap, $urlencode){
- $buff = "";
- ksort($paraMap);
- foreach ($paraMap as $k => $v){
- if($urlencode){
- $v = urlencode($v);
- }
- $buff .= $k . "=" . $v . "&";
- }
- $reqPar;
- if (strlen($buff) > 0){
- $reqPar = substr($buff, 0, strlen($buff)-1);
- }
- return $reqPar;
- }
- public function MakeSign($unifiedorder)
- {
- $this->values=$unifiedorder;
- //签名步骤一:按字典序排序参数
- // ksort($this->values);
- $string = $this->ToUrlParams();
- // halt($string);
- //签名步骤二:在string后加入KEY
- $string = $string . "&key=".$this->key;
- //签名步骤三:MD5加密
- $string = md5($string);
- //签名步骤四:所有字符转为大写
- $result = strtoupper($string);
- return $result;
- }
- public function ToUrlParams()
- {
- $buff = "";
- foreach ($this->values as $k => $v)
- {
- if($k != "sign" && $v != "" && !is_array($v)){
- $buff .= $k . "=" . $v . "&";
- }
- }
- $buff = trim($buff, "&");
- return $buff;
- }
- function array2xml($array)
- {
- $xml='<xml>';
- foreach($array as $key=>$val){
- if(is_numeric($key)){
- $key="item id=\"$key\"";
- }else{
- //去掉空格,只取空格之前文字为key
- list($key,)=explode(' ',$key);
- }
- $xml.="<$key>";
- $xml.=is_array($val)?$this->_array2xml($val):$val;
- //去掉空格,只取空格之前文字为key
- list($key,)=explode(' ',$key);
- $xml.="</$key>";
- }
- $xml.="</xml>";
- return $xml;
- }
- function xml2array($xml)
- {
- //禁止引用外部xml实体
- libxml_disable_entity_loader(true);
- $values = json_decode(json_encode(simplexml_load_string($xml, 'SimpleXMLElement', LIBXML_NOCDATA)), true);
- return $values;
- }
- public function request_post($url = '', $param = '')
- {
- if (emptyempty($url) || emptyempty($param)) {
- return false;
- }
- $postUrl = $url;
- $curlPost = $param;
- $ch = curl_init(); //初始化curl
- curl_setopt($ch, CURLOPT_URL, $postUrl); //抓取指定网页
- 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, $curlPost);
- $data = curl_exec($ch); //运行curl
- curl_close($ch);
- return $data;
- }
- function curl_post_ssl($url, $vars, $second=30,$aHeader=array())
- {
- $ch = curl_init();
- //curl_setopt($ch,CURLOPT_VERBOSE,'1');
- curl_setopt($ch,CURLOPT_TIMEOUT,$second);
- curl_setopt($ch,CURLOPT_RETURNTRANSFER, 1);
- curl_setopt($ch,CURLOPT_URL,$url);
- curl_setopt($ch,CURLOPT_SSL_VERIFYPEER,false);
- curl_setopt($ch,CURLOPT_SSL_VERIFYHOST,false);
- curl_setopt($ch,CURLOPT_SSLCERTTYPE,'PEM');
- curl_setopt($ch,CURLOPT_SSLCERT,'/data/cert/php.pem');
- curl_setopt($ch,CURLOPT_SSLCERTPASSWD,'1234');
- curl_setopt($ch,CURLOPT_SSLKEYTYPE,'PEM');
- curl_setopt($ch,CURLOPT_SSLKEY,'/data/cert/php_private.pem');
- if( count($aHeader) >= 1 ){
- curl_setopt($ch, CURLOPT_HTTPHEADER, $aHeader);
- }
- curl_setopt($ch,CURLOPT_POST, 1);
- curl_setopt($ch,CURLOPT_POSTFIELDS,$vars);
- $data = curl_exec($ch);
- curl_close($ch);
- if($data){
- return $data;
- }else{
- return false;
- }
- }
- }
使用方法:
1、将类库源码下载后,可以通过配置获取查询微信支付的配置信息,然后填入类库最上方的配置中。
2、在后端控制器位置,编写以下代码:
- $ip = $_W['clientip'];
- $pay_body = "购买商品";
- $h5pay = m('wxpay')->payh5($order['price'],$pay_body,$order['ordersn'],$ip);
- $redirect_url = mobileUrl('order/pay/success',array('id'=>$orderid,'result'=>"true")); //支付成功后跳转地址
- $redirect_url = urlencode($_W['siteroot'].substr($redirect_url,2));
- if($h5pay['return_code'] == "SUCCESS"){
- $pay_url = $h5pay['mweb_url']."&redirect_url=".$redirect_url;
- }else{
- $pay_url = "#";
- }
3、在前端HTML页面只需要在对应按钮上添加跳转链接{$pay_url}即可。
温馨提示:H5的支付方式并非APP支付,所以在封装APP的应用中慎用。仅可通过手机浏览器调起微信支付。