ThinkPHP5.0 实现 app微信支付功能 技术标签: 微信支付

释放双眼,带上耳机,听听看~!

微信支付的步骤大致和支付宝支付的步骤差不多,这里我讲的详细一点。

第一步:建立一个支付控制器pay.php,是由上个页面选择好支付方式之后确认支付后需要经过的控制器(这里选择的是微信支付),代码 如下:

  1. <?php
  2. namespace app\mobile\controller;
  3. use think\Controller;
  4. class Pay extends Controller
  5. {
  6.     public function pay_order()
  7.     {
  8.         $res = new OrderGoods();
  9.         //获取订单号
  10.         $where['id'] = input('post.order_sn');
  11.         $reoderSn = input('post.order_sn');
  12.         //查询订单信息
  13.         $order_info = $res->where($where)->find();
  14.         //获取支付方式
  15.         $pay_type = input('post.pay_type');//微信支付 或者支付宝支付
  16.         //获取支付金额
  17.         $money = input('post.totle_sum');
  18.         //判断支付方式
  19.         switch ($pay_type) {
  20.             case 'ali';//如果支付方式为支付宝支付
  21.                 break;
  22.             case 'wx';
  23.                 $type['pay_type'] = 'wx';//更新支付方式为微信
  24.                 $res->where($where)->update($type);
  25.                 $wx = new Wxpay();//实例化微信支付控制器
  26.                 $body = '订单号' . $order_info;//支付说明
  27.                 $out_trade_no = $reoderSn;//订单号
  28.                 $total_fee = $money * 100;//支付金额(乘以100)
  29.                 $notify_url = '';//回调地址
  30.                 $order = $wx->getPrePayOrder($body, $out_trade_no, $total_fee, $notify_url);//调用微信支付的方法
  31.                 if ($order['prepay_id']){//判断返回参数中是否有prepay_id
  32.                     $order1 = $wx->getOrder($order['prepay_id']);//执行二次签名返回参数
  33.                     echo json_encode(array('status' => 1'prepay_order' => no_null($order1)));
  34.                 } else {
  35.                     echo json_encode(array('status' => 0'msg' => $order['err_code_des']));
  36.                 }
  37.                 break;
  38.         }
  39.     }
  40. }

 

然后创建微信支付控制器了。命名为wx.php,用于执行微信支付,代码如下:

  1. <?php
  2. namespace app\mobile\controller;
  3. use think\Controller;
  4. use think\Db;
  5. class WxPay extends Controller{
  6.     /*
  7.     配置参数
  8.     */
  9.     private $config = array(
  10.         'appid' => "",//"wxcf1dded808489e2c",    /*微信开放平台上的应用id*/
  11.         'mch_id' => "",//"1440493402",   /*微信申请成功之后邮件中的商户id*/
  12.         'api_key' => ""    /*在微信商户平台上自己设定的api密钥 32位*/
  13.     );
  14.     //获取预支付订单
  15.     public function getPrePayOrder($body, $out_trade_no, $total_fee, $notify_url){
  16.         $url = "https://api.mch.weixin.qq.com/pay/unifiedorder";
  17.         $onoce_str = $this->getRandChar(32);
  18.         $data["appid"] = $this->config["appid"];
  19.         $data["body"] = $body;
  20.         $data["mch_id"] = $this->config['mch_id'];
  21.         $data["nonce_str"] = $onoce_str;
  22.         $data["notify_url"] = $notify_url;
  23.         $data["out_trade_no"] = $out_trade_no;
  24.         $data["spbill_create_ip"] = $this->get_client_ip();
  25.         $data["total_fee"] = $total_fee;
  26.         $data["trade_type"] = "APP";
  27.         $s = $this->getSign($data, false);
  28.         $data["sign"] = $s;
  29.         $xml = $this->arrayToXml($data);
  30.         $response = $this->postXmlCurl($xml, $url);
  31.         //将微信返回的结果xml转成数组
  32. //        return $this->xmlstr_to_array($response);
  33.         return xmlToArray($response);
  34.     }
  35.     //执行第二次签名,才能返回给客户端使用
  36.     public function getOrder($prepayId){
  37.         $data["appid"] = $this->config["appid"];
  38.         $data["noncestr"] = $this->getRandChar(32);;
  39.         $data["package"] = "Sign=WXPay";
  40.         $data["partnerid"] = $this->config['mch_id'];
  41.         $data["prepayid"] = $prepayId;
  42.         $data["timestamp"] = time();
  43.         $s = $this->getSign($data, false);
  44.         $data["sign"] = $s;
  45.         return $data;
  46.     }
  47.     /*
  48.         生成签名
  49.     */
  50.     function getSign($Obj)
  51.     {
  52.         foreach ($Obj as $k => $v)
  53.         {
  54.             $Parameters[strtolower($k)] = $v;
  55.         }
  56.         //签名步骤一:按字典序排序参数
  57.         ksort($Parameters);
  58.         $String = $this->formatBizQueryParaMap($Parameters, false);
  59.         //echo "【string】 =".$String."</br>";
  60.         //签名步骤二:在string后加入KEY
  61.         $String = $String."&key=".$this->config['api_key'];
  62. //        echo "<textarea style='width: 50%; height: 150px;'>$String</textarea> <br />";
  63.         //签名步骤三:MD5加密
  64.         $result_ = strtoupper(md5($String));
  65.         return $result_;
  66.     }
  67.     //获取指定长度的随机字符串
  68.     function getRandChar($length){
  69.         $str = null;
  70.         $strPol = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789abcdefghijklmnopqrstuvwxyz";
  71.         $max = strlen($strPol)-1;
  72.         for($i=0;$i<$length;$i++){
  73.             $str.=$strPol[rand(0,$max)];//rand($min,$max)生成介于min和max两个数之间的一个随机整数
  74.         }
  75.         return $str;
  76.     }
  77.     //数组转xml
  78.     function arrayToXml($arr)
  79.     {
  80.         $xml = "<xml>";
  81.         foreach ($arr as $key=>$val)
  82.         {
  83.             if (is_numeric($val))
  84.             {
  85.                 $xml.="<".$key.">".$val."</".$key.">";
  86.             }
  87.             else
  88.                 $xml.="<".$key."><![CDATA[".$val."]]></".$key.">";
  89.         }
  90.         $xml.="</xml>";
  91.         return $xml;
  92.     }
  93.     //post https请求,CURLOPT_POSTFIELDS xml格式
  94.     function postXmlCurl($xml,$url,$second=30)
  95.     {
  96.         //初始化curl
  97.         $ch = curl_init();
  98.         //超时时间
  99.         curl_setopt($ch,CURLOPT_TIMEOUT,$second);
  100.         //这里设置代理,如果有的话
  101.         //curl_setopt($ch,CURLOPT_PROXY, '8.8.8.8');
  102.         //curl_setopt($ch,CURLOPT_PROXYPORT, 8080);
  103.         curl_setopt($ch,CURLOPT_URL, $url);
  104.         curl_setopt($ch,CURLOPT_SSL_VERIFYPEER,FALSE);
  105.         curl_setopt($ch,CURLOPT_SSL_VERIFYHOST,FALSE);
  106.         //设置header
  107.         curl_setopt($ch, CURLOPT_HEADER, FALSE);
  108.         //要求结果为字符串且输出到屏幕上
  109.         curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
  110.         //post提交方式
  111.         curl_setopt($ch, CURLOPT_POST, TRUE);
  112.         curl_setopt($ch, CURLOPT_POSTFIELDS, $xml);
  113.         //运行curl
  114.         $data = curl_exec($ch);
  115.         //返回结果
  116.         if($data)
  117.         {
  118.             curl_close($ch);
  119.             return $data;
  120.         }
  121.         else
  122.         {
  123.             $error = curl_errno($ch);
  124.             echo "curl出错,错误码:$error"."<br>";
  125.             echo "<a href='http://curl.haxx.se/libcurl/c/libcurl-errors.html'>错误原因查询</a></br>";
  126.             curl_close($ch);
  127.             return false;
  128.         }
  129.     }
  130.     /*
  131.         获取当前服务器的IP
  132.     */
  133.     function get_client_ip()
  134.     {
  135.         if ($_SERVER['REMOTE_ADDR']) {
  136.             $cip = $_SERVER['REMOTE_ADDR'];
  137.         } elseif (getenv("REMOTE_ADDR")) {
  138.             $cip = getenv("REMOTE_ADDR");
  139.         } elseif (getenv("HTTP_CLIENT_IP")) {
  140.             $cip = getenv("HTTP_CLIENT_IP");
  141.         } else {
  142.             $cip = "unknown";
  143.         }
  144.         return $cip;
  145.     }
  146.     //将数组转成uri字符串
  147.     function formatBizQueryParaMap($paraMap, $urlencode)
  148.     {
  149.         $buff = "";
  150.         ksort($paraMap);
  151.         foreach ($paraMap as $k => $v)
  152.         {
  153.             if($urlencode)
  154.             {
  155.                 $v = urlencode($v);
  156.             }
  157.             $buff .= strtolower($k) . "=" . $v . "&";
  158.         }
  159.         $reqPar;
  160.         if (strlen($buff) > 0)
  161.         {
  162.             $reqPar = substr($buff, 0, strlen($buff)-1);
  163.         }
  164.         return $reqPar;
  165.     }
  166.     /**
  167.     xml转成数组
  168.      */
  169. //    function xmlstr_to_array($xmlstr) {
  170. //        $doc = new DOMDocument();
  171. //        $doc->loadXML($xmlstr);
  172. //        return $this->domnode_to_array($doc->documentElement);
  173. //    }
  174.     function domnode_to_array($node) {
  175.         $output = array();
  176.         switch ($node->nodeType) {
  177.             case XML_CDATA_SECTION_NODE:
  178.             case XML_TEXT_NODE:
  179.                 $output = trim($node->textContent);
  180.                 break;
  181.             case XML_ELEMENT_NODE:
  182.                 for ($i=0, $m=$node->childNodes->length; $i<$m; $i++) {
  183.                     $child = $node->childNodes->item($i);
  184.                     $v = $this->domnode_to_array($child);
  185.                     if(isset($child->tagName)) {
  186.                         $t = $child->tagName;
  187.                         if(!isset($output[$t])) {
  188.                             $output[$t] = array();
  189.                         }
  190.                         $output[$t][] = $v;
  191.                     }
  192.                     elseif($v) {
  193.                         $output = (string) $v;
  194.                     }
  195.                 }
  196.                 if(is_array($output)) {
  197.                     if($node->attributes->length) {
  198.                         $a = array();
  199.                         foreach($node->attributes as $attrName => $attrNode) {
  200.                             $a[$attrName] = (string) $attrNode->value;
  201.                         }
  202.                         $output['@attributes'] = $a;
  203.                     }
  204.                     foreach ($output as $t => $v) {
  205.                         if(is_array($v) && count($v)==1 && $t!='@attributes') {
  206.                             $output[$t] = $v[0];
  207.                         }
  208.                     }
  209.                 }
  210.                 break;
  211.         }
  212.         return $output;
  213.     }
  214. }

 

微信支付控制器里面基本不用动,只需要改几个参数就行了。很简单。

回调控制器和方法我这里就不写了,很简单的,不懂得可以私信。

流程已经没了,执行一下程序,看一下返回给前端的参数示例:

把这些参数通过和前端交互给到前端就行了,接下来就是前端拿着参数去进行支付,支付成功系统会自动调用你写的回调地址改写你所需要的代码逻辑。

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。

本文链接:https://blog.csdn.net/weixin_42677083/article/details/85221104

人已赞赏
PHP微信小程序

小程序开发之场景值及使用方法

2020-9-21 16:54:41

thinkPHP

thinkphp+redis实现秒杀功能

2020-10-6 15:43:09

0 条回复 A文章作者 M管理员
    暂无讨论,说说你的看法吧
个人中心
购物车
优惠劵
今日签到
有新私信 私信列表
搜索