当前位置:首页 > PHP教程 > php高级应用 > 列表

PHP的微信支付接口使用方法讲解

发布:smiling 来源: PHP粉丝网  添加日期:2021-11-11 17:10:45 浏览: 评论:0 

在开发之中经常会使用到支付的功能,现在常用的两种支付方式是支付宝和微信。相对而言,支付宝的文档较为健全,并且配置和调用方式方式比较简单,这里就不过多的描述。

首先去微信官网网站下去下载服务端的demo:https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=11_1

这里虽然是官网提供的公众号支付的demo,虽然微信支付的预下单等都可以在前端进行实现,不过官方还是建议在服务端进行处理。下载后,将其中的demo引入你的项目就好,注意的是如果是公众号的支付用到的类文件WxPay.JsApiPay.php在文件中example目录下。

接下来我们就可以进行引用了并实现。以thinkphp框架下进行调用为例(以下案例包括移动端以及公众号支付以及公众号获取openid等功能)。以下代码为了能够更容易理解,将一些类中的方法提取了出来,写的有点乱,请见谅。

  1.   /* 微信APP下支付预下单 */ 
  2.   public function wxAppOrder(){ 
  3.     //TODO:首先获取订单详情,例如传递过来订单号或订单id,获取订单的详情信息,例如将取出的数据存放入$user_order_info数组,订单中包含的商品在$user_order_product_info之中。 
  4.     /* 向微信发起请求 */ 
  5.     vendor('WxpayAPI.lib.WxPay','','.Api.php'); 
  6.     vendor('WxpayAPI.lib.WxPay','','.Data.php');//生成数据 
  7.     //统一下单输入对象 
  8.     $order_infonew WxPayUnifiedOrder(); 
  9.     $order_info->SetOut_trade_no($user_order_info['orderNo']);//商品订单号 
  10.     $body=$user_order_product_info['productName']; 
  11.     //   $body=iconv('UTF-8', 'ISO-8859-1', $user_order_product_info['productName']); 
  12.     $order_info->SetBody($body);//商品描述 
  13.     $order_info->SetTrade_type('CNY');//人民币 
  14.     $order_info->SetTotal_fee(intval($user_order_info['sumPrice']*100));//总金额,以分为单位 
  15.     $order_info->SetTrade_type('APP');//交易类型 
  16.     $order_info->SetAppid(C('wxAPPID')); 
  17.     $order_info->SetMch_id(C('wxMCHID')); 
  18.     $order_info->SetNotify_url('你的回调地址'); 
  19.     $order_info->SetSign(); 
  20.     //进行统一支付 
  21.     $wxpay=new WxPayApi(); 
  22.     $order_result=$wxpay->unifiedOrder($order_info);//统一下单 
  23.     if ($order_result['return_code']=='FAIL') { 
  24.       $arr=array
  25.           'resultCode'=>'99'
  26.           'resultDesc'=>$order_result['return_msg'], 
  27.           'resultObj'=>array(''=>''), 
  28.       ); 
  29.       echo JSON($arr); 
  30.       exit(); 
  31.     } 
  32.     if ($order_result['result_code']=='SUCCESS') { 
  33.     //预下单成功后,重新签名返回给移动端 
  34.       $wxpay_result=new WxPayResults(); 
  35.       $timestamp=time(); 
  36.       $wxpay_result->SetData('appid'$order_result['appid']); 
  37.       $wxpay_result->SetData('partnerid'$order_result['mch_id']); 
  38.       $wxpay_result->SetData('prepayid'$order_result['prepay_id']); 
  39.       $wxpay_result->SetData('timestamp'$timestamp); 
  40.       $wxpay_result->SetData('noncestr'$order_result['nonce_str']); 
  41.       $wxpay_result->SetData('package''Sign=WXPay'); 
  42.       // $wxpay_result->SetData('key', C('wxKEY')); 
  43.       //上方注释的代码是再签名中必要的一步,只是这个包含在了微信demo的类中,如果像该项目中既有app支付,又有公众号支付,最好是注释类中代码,并自己写入 
  44.       $resign_result=$wxpay_result->SetSign(); 
  45.       //处理返回数据 
  46.       $result=array
  47.           'appid'=>$order_result['appid'],//appid 
  48.           'partnerid'=>$order_result['mch_id'],//商户号 
  49.           'prepayid'=>$order_result['prepay_id'],//与支付id 
  50.           'package'=>'Sign=WXPay'
  51.           'noncestr'=>$order_result['nonce_str'], 
  52.           'timestamp'=>$timestamp
  53.           'sign'=>$resign_result
  54.       ); 
  55.       $arr=array
  56.           'resultCode'=>'00'
  57.           'resultDesc'=>'成功'
  58.           'resultObj'=>$result
  59.       ); 
  60.       echo JSON($arr); 
  61.       exit(); 
  62.     }else
  63.       $arr=array
  64.           'resultCode'=>'99'
  65.           'resultDesc'=>'失败'
  66.           'resultObj'=>$order_result
  67.       ); 
  68.       echo JSON($arr); 
  69.       exit(); 
  70.     } 
  71.   } 
  72.   /* 微信支付回调函数 */ 
  73.   public function wxpayNotify(){ 
  74.     vendor('WxpayAPI.lib.Logwx','','.Log.php');//在回调中最好是引入日志进行记录,在这里因为Log类与thinkphp中的log类重复,需要进行处理 
  75.     $handle=new CLogFileHandler('./Public/wxlog.txt'); 
  76.     $log=Logwx::Init($handle); 
  77.     $xml = $GLOBALS['HTTP_RAW_POST_DATA'];//获取数据 
  78.     vendor('WxpayAPI.lib.WxPay','','.Api.php'); 
  79.     vendor('WxpayAPI.lib.WxPay','','.Data.php'); 
  80.     $wxpay=new WxPayApi(); 
  81.     $notify=new WxPayNotifyReply(); 
  82.     $result=WxPayResults::Init($xml);//获取数据并转换为数组 
  83.     if ($result['return_code']=='SUCCESS' && $result['result_code']=='SUCCESS') {//此字段是通信标识,非交易标识,交易是否成功需要查看result_code来判断 
  84.       //TODO:进行数据库操作的业务逻辑处理,假设其成功与否的数据为$res 
  85.       if ($res) { 
  86.         $log->INFO('订单:'.$result['out_trade_no'].'支付成功'); 
  87.         $notify->SetReturn_code('SUCCESS'); 
  88.         $notify->SetReturn_msg('OK'); 
  89.         $notify->SetSign(); 
  90.       }else
  91.         $log->ERROR('微信支付失败'); 
  92.         $notify->SetReturn_code('FAIL'); 
  93.         $notify->SetReturn_msg('客户服务器错误'); 
  94.       } 
  95.     }else
  96.       $log->ERROR('微信回调返回错误'); 
  97.       $notify->SetReturn_code('FAIL'); 
  98.       $notify->SetReturn_msg('微信支付失败'); 
  99.     } 
  100.     //返回微信端 
  101.     $wxpay->replyNotify($notify->ToXml()); 
  102.   } 
  103.   /* 微信公众账号下单 
  104.    * 获取code等信息 
  105.   * 跳转至获取信息 
  106.   *  */ 
  107.   public function wxPubOrder(){ 
  108.     //此流程中 
  109.     $orderId=$_GET['orderId']; 
  110.     //注意:此处如果想要回调成功,需要在微信公众平台设置回调域名 
  111. //   print_r('Location:https://open.weixin.qq.com/connect/oauth2/authorize?appid='.C('wxAPPID').'&redirect_uri='.'http://你的域名/Pay/getOpenid/orderId/'.$orderId.'&response_type=code&scope=snsapi_base&state=123#wechat_redirect'); 
  112. //   exit(); 
  113.     header('Location:https://open.weixin.qq.com/connect/oauth2/authorize?appid='.'*******'.'&redirect_uri='.urlencode('http://*****/Pay/getOpenid/orderId/'.$orderId).'&response_type=code&scope=snsapi_base&state=123#wechat_redirect'); 
  114.     exit(); 
  115.   } 
  116.   /* 微信获取openid,跳转到微信同意下单接口 */ 
  117.   public function getOpenid(){ 
  118.     //code 
  119.     $code=$_GET['code']; 
  120.     $state=$_GET['state']; 
  121.     $orderId=$_GET['orderId']; 
  122.     $appid='******'
  123.     $appsecret='******'
  124.     //获取openid 
  125.     $get_token_url = 'https://api.weixin.qq.com/sns/oauth2/access_token?appid='.$appid.'&secret='.$appsecret.'&code='.$code.'&grant_type=authorization_code'
  126.     $ch = curl_init(); 
  127.     curl_setopt($ch,CURLOPT_URL,$get_token_url); 
  128.     curl_setopt($ch,CURLOPT_HEADER,0); 
  129.     curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1 ); 
  130.     curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 10); 
  131.     $res = curl_exec($ch); 
  132.     curl_close($ch); 
  133.     $json_obj = json_decode($res,true); 
  134.     $openId=$json_obj['openid']; 
  135. //   跳转到预下单 
  136.     // echo $openId;exit(); 
  137.     $url='http://******/html5/#/pay/'.$orderId.'openid='.$openId
  138.     header('Location:'.$url); 
  139.   } 
  140.   /* 微信公众账号统一下单 */ 
  141.   public function wxOrder(){ 
  142.     $orderId=$_GET['orderId']; 
  143.     $openId=$_GET['openId']; 
  144.     if (emptyempty($orderId)||emptyempty($openId)) { 
  145.       $arr=array
  146.           'resultCode'=>'66'
  147.           'resultDesc'=>'缺少参数'
  148.           'resultObj'=>array(), 
  149.       ); 
  150.       echo JSON($arr); 
  151.       exit(); 
  152.     } 
  153.     //TODO:获取订单和订单商品信息,分别存储在$user_order_info中和$user_order_good_info中 
  154.     if (emptyempty($user_order_info)) { 
  155.       $arr=array
  156.           'resultCode'=>'99'
  157.           'resultDesc'=>'不存在该订单'
  158.           'resultObj'=>array(), 
  159.       ); 
  160.       echo JSON($arr); 
  161.       exit(); 
  162.     } 
  163.     /* 向微信发起请求 */ 
  164.     vendor('WxpayAPI.lib.WxPay','','.Api.php'); 
  165.     vendor('WxpayAPI.lib.WxPay','','.Data.php');//生成数据 
  166.     //   vendor('WxpayAPI.lib.WxPay','','.JsApiPay.php'); 
  167.     //统一下单输入对象 
  168.     $order_infonew WxPayUnifiedOrder(); 
  169.     $wxpay=new WxPayApi(); 
  170.     $order_info->SetMch_id('***');//商户号 
  171.     $order_info->SetAppid('****');//微信号APPID//wx70a40dfa2711c4fe 
  172.     $order_info->SetOut_trade_no($user_order_info['orderNo']);//商品订单号 
  173.     $order_info->SetBody($user_order_good_info['productName']);//商品描述 
  174.     $order_info->SetTrade_type('CNY');//人民币 
  175.     $order_info->SetTotal_fee(intval($user_order_info['sumPrice']*100));//总金额,以分为单位 
  176.     $order_info->SetTrade_type('JSAPI');//交易类型 
  177.     $order_info->SetNonce_str($wxpay->getNonceStr(32)); 
  178.     $order_info->SetSpbill_create_ip('1.1.1.1'); 
  179.     //   $order_info->SetOpenid($user_info['openId']); 
  180.     $order_info->SetOpenid($openId); 
  181.     //TODO: 
  182.     $order_info->SetNotify_url('http://****/Pay/wxpayNotify'); 
  183.     $order_info->SetSign();//设置签名 
  184.     //进行统一支付 
  185.     $order_result=$wxpay->unifiedOrder($order_info);//统一下单 
  186.     //同意下单后再加 
  187.     if ($order_result['return_code']=='FAIL') { 
  188.       $arr=array
  189.           'resultCode'=>'99'
  190.           'resultDesc'=>$order_result['return_code'].':'.$order_result['return_msg'], 
  191.           'resultObj'=>array(), 
  192.       ); 
  193.       echo JSON($arr); 
  194.       exit(); 
  195.     } 
  196.     if ($order_result['result_code']=='SUCCESS') { 
  197.       $jsapi = new WxPayJsApiPay(); 
  198.       $jsapi->SetAppid($order_result["appid"]); 
  199.       $timeStamp = time(); 
  200.       $jsapi->SetTimeStamp("$timeStamp"); 
  201.       $jsapi->SetNonceStr(WxPayApi::getNonceStr()); 
  202.       $jsapi->SetPackage("prepay_id=" . $order_result['prepay_id']); 
  203.       $jsapi->SetSignType("MD5"); 
  204.       $jsapi->SetPaySign($jsapi->MakeSign()); 
  205.       $order_result = $jsapi->GetValues(); 
  206.       //     print_r($order_result);exit(); 
  207.       $arr=array
  208.           'resultCode'=>'00'
  209.           'resultDesc'=>'成功'
  210.           'resultObj'=>$order_result
  211.       ); 
  212.       echo JSON($arr); 
  213.       exit(); 
  214.     }else
  215.       $arr=array
  216.           'resultCode'=>'99'
  217.           'resultDesc'=>'失败'
  218.           'resultObj'=>$order_result
  219.       ); 
  220.       echo JSON($arr); 
  221.       exit(); 
  222.     }   
  223.   } 

这就是一个支付的流程,在这之中会遇到很多问题,在此给出一个大多数会遇到的问题的解决方法的大概思路:

1、APP统一下单后数据返回给前端,前端调用报签名错误:首先验证自己的秘钥信息是否正确,要注意移动端和公众号的是不同的,而类拿着key又去重新签名,可以将微信官方提供的demo中的直接内部调用配置文件那里注释掉

2、在公众号获取openid的时候,显示跨域:这个解决参考YII2框架中对于\yii::$app->response->header,中的remove方法,将报头去掉即可。

3、对于微信支付的配置,包括公众号支付配置白名单、测试目录啥的就不过多说了,请自行搜索资料

过程中肯定还遇到很多问题,这里不一一写了,如果还有问题可以在评论中留言,大家一起讨论学习,共同进步。

Tags: PHP微信支付接口

分享到: