欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

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

程序员文章站 2022-06-12 15:37:01
在开发之中经常会使用到支付的功能,现在常用的两种支付方式是支付宝和微信。相对而言,支付宝的文档较为健全,并且配置和调用方式方式比较简单,这里就不过多的描述。 首先去微信官...

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

首先去微信官网网站下去下载服务端的demo:

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

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

  /* 微信app下支付预下单 */
  public function wxapporder(){
    //todo:首先获取订单详情,例如传递过来订单号或订单id,获取订单的详情信息,例如将取出的数据存放入$user_order_info数组,订单中包含的商品在$user_order_product_info之中。
    /* 向微信发起请求 */
    vendor('wxpayapi.lib.wxpay','','.api.php');
    vendor('wxpayapi.lib.wxpay','','.data.php');//生成数据
    //统一下单输入对象
    $order_info= new wxpayunifiedorder();
    $order_info->setout_trade_no($user_order_info['orderno']);//商品订单号
    $body=$user_order_product_info['productname'];
    //   $body=iconv('utf-8', 'iso-8859-1', $user_order_product_info['productname']);
    $order_info->setbody($body);//商品描述
    $order_info->settrade_type('cny');//人民币
    $order_info->settotal_fee(intval($user_order_info['sumprice']*100));//总金额,以分为单位
    $order_info->settrade_type('app');//交易类型
    $order_info->setappid(c('wxappid'));
    $order_info->setmch_id(c('wxmchid'));
    $order_info->setnotify_url('你的回调地址');
    $order_info->setsign();
    //进行统一支付
    $wxpay=new wxpayapi();
    $order_result=$wxpay->unifiedorder($order_info);//统一下单
    if ($order_result['return_code']=='fail') {
      $arr=array(
          'resultcode'=>'99',
          'resultdesc'=>$order_result['return_msg'],
          'resultobj'=>array(''=>''),
      );
      echo json($arr);
      exit();
    }
    if ($order_result['result_code']=='success') {
    //预下单成功后,重新签名返回给移动端
      $wxpay_result=new wxpayresults();
      $timestamp=time();
      $wxpay_result->setdata('appid', $order_result['appid']);
      $wxpay_result->setdata('partnerid', $order_result['mch_id']);
      $wxpay_result->setdata('prepayid', $order_result['prepay_id']);
      $wxpay_result->setdata('timestamp', $timestamp);
      $wxpay_result->setdata('noncestr', $order_result['nonce_str']);
      $wxpay_result->setdata('package', 'sign=wxpay');
      // $wxpay_result->setdata('key', c('wxkey'));
      //上方注释的代码是再签名中必要的一步,只是这个包含在了微信demo的类中,如果像该项目中既有app支付,又有公众号支付,最好是注释类中代码,并自己写入
      $resign_result=$wxpay_result->setsign();
      //处理返回数据
      $result=array(
          'appid'=>$order_result['appid'],//appid
          'partnerid'=>$order_result['mch_id'],//商户号
          'prepayid'=>$order_result['prepay_id'],//与支付id
          'package'=>'sign=wxpay',
          'noncestr'=>$order_result['nonce_str'],
          'timestamp'=>$timestamp,
          'sign'=>$resign_result,
      );
      $arr=array(
          'resultcode'=>'00',
          'resultdesc'=>'成功',
          'resultobj'=>$result,
      );
      echo json($arr);
      exit();
    }else{
      $arr=array(
          'resultcode'=>'99',
          'resultdesc'=>'失败',
          'resultobj'=>$order_result,
      );
      echo json($arr);
      exit();
    }
  }
  /* 微信支付回调函数 */
  public function wxpaynotify(){
    vendor('wxpayapi.lib.logwx','','.log.php');//在回调中最好是引入日志进行记录,在这里因为log类与thinkphp中的log类重复,需要进行处理
    $handle=new clogfilehandler('./public/wxlog.txt');
    $log=logwx::init($handle);
    $xml = $globals['http_raw_post_data'];//获取数据
    vendor('wxpayapi.lib.wxpay','','.api.php');
    vendor('wxpayapi.lib.wxpay','','.data.php');
    $wxpay=new wxpayapi();
    $notify=new wxpaynotifyreply();
    $result=wxpayresults::init($xml);//获取数据并转换为数组
    if ($result['return_code']=='success' && $result['result_code']=='success') {//此字段是通信标识,非交易标识,交易是否成功需要查看result_code来判断
      //todo:进行数据库操作的业务逻辑处理,假设其成功与否的数据为$res
      if ($res) {
        $log->info('订单:'.$result['out_trade_no'].'支付成功');
        $notify->setreturn_code('success');
        $notify->setreturn_msg('ok');
        $notify->setsign();
      }else{
        $log->error('微信支付失败');
        $notify->setreturn_code('fail');
        $notify->setreturn_msg('客户服务器错误');
      }
    }else{
      $log->error('微信回调返回错误');
      $notify->setreturn_code('fail');
      $notify->setreturn_msg('微信支付失败');
    }
    //返回微信端
    $wxpay->replynotify($notify->toxml());
  }
  /* 微信公众账号下单
   * 获取code等信息
  * 跳转至获取信息
  *  */
  public function wxpuborder(){
    //此流程中
    $orderid=$_get['orderid'];
    //注意:此处如果想要回调成功,需要在微信公众平台设置回调域名
//   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');
//   exit();
    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');
    exit();
  }
  /* 微信获取openid,跳转到微信同意下单接口 */
  public function getopenid(){
    //code
    $code=$_get['code'];
    $state=$_get['state'];
    $orderid=$_get['orderid'];
    $appid='******';
    $appsecret='******';
    //获取openid
    $get_token_url = 'https://api.weixin.qq.com/sns/oauth2/access_token?appid='.$appid.'&secret='.$appsecret.'&code='.$code.'&grant_type=authorization_code';
    $ch = curl_init();
    curl_setopt($ch,curlopt_url,$get_token_url);
    curl_setopt($ch,curlopt_header,0);
    curl_setopt($ch, curlopt_returntransfer, 1 );
    curl_setopt($ch, curlopt_connecttimeout, 10);
    $res = curl_exec($ch);
    curl_close($ch);
    $json_obj = json_decode($res,true);
    $openid=$json_obj['openid'];
//   跳转到预下单
    // echo $openid;exit();
    $url='http://******/html5/#/pay/'.$orderid.'openid='.$openid;
    header('location:'.$url);
  }
  /* 微信公众账号统一下单 */
  public function wxorder(){
    $orderid=$_get['orderid'];
    $openid=$_get['openid'];
    if (empty($orderid)||empty($openid)) {
      $arr=array(
          'resultcode'=>'66',
          'resultdesc'=>'缺少参数',
          'resultobj'=>array(),
      );
      echo json($arr);
      exit();
    }
    //todo:获取订单和订单商品信息,分别存储在$user_order_info中和$user_order_good_info中
    if (empty($user_order_info)) {
      $arr=array(
          'resultcode'=>'99',
          'resultdesc'=>'不存在该订单',
          'resultobj'=>array(),
      );
      echo json($arr);
      exit();
    }
    /* 向微信发起请求 */
    vendor('wxpayapi.lib.wxpay','','.api.php');
    vendor('wxpayapi.lib.wxpay','','.data.php');//生成数据
    //   vendor('wxpayapi.lib.wxpay','','.jsapipay.php');
    //统一下单输入对象
    $order_info= new wxpayunifiedorder();
    $wxpay=new wxpayapi();
    $order_info->setmch_id('***');//商户号
    $order_info->setappid('****');//微信号appid//wx70a40dfa2711c4fe
    $order_info->setout_trade_no($user_order_info['orderno']);//商品订单号
    $order_info->setbody($user_order_good_info['productname']);//商品描述
    $order_info->settrade_type('cny');//人民币
    $order_info->settotal_fee(intval($user_order_info['sumprice']*100));//总金额,以分为单位
    $order_info->settrade_type('jsapi');//交易类型
    $order_info->setnonce_str($wxpay->getnoncestr(32));
    $order_info->setspbill_create_ip('1.1.1.1');
    //   $order_info->setopenid($user_info['openid']);
    $order_info->setopenid($openid);
    //todo:
    $order_info->setnotify_url('http://****/pay/wxpaynotify');
    $order_info->setsign();//设置签名
    //进行统一支付
    $order_result=$wxpay->unifiedorder($order_info);//统一下单
    //同意下单后再加
    if ($order_result['return_code']=='fail') {
      $arr=array(
          'resultcode'=>'99',
          'resultdesc'=>$order_result['return_code'].':'.$order_result['return_msg'],
          'resultobj'=>array(),
      );
      echo json($arr);
      exit();
    }
    if ($order_result['result_code']=='success') {
      $jsapi = new wxpayjsapipay();
      $jsapi->setappid($order_result["appid"]);
      $timestamp = time();
      $jsapi->settimestamp("$timestamp");
      $jsapi->setnoncestr(wxpayapi::getnoncestr());
      $jsapi->setpackage("prepay_id=" . $order_result['prepay_id']);
      $jsapi->setsigntype("md5");
      $jsapi->setpaysign($jsapi->makesign());
      $order_result = $jsapi->getvalues();
      //     print_r($order_result);exit();
      $arr=array(
          'resultcode'=>'00',
          'resultdesc'=>'成功',
          'resultobj'=>$order_result,
      );
      echo json($arr);
      exit();
    }else{
      $arr=array(
          'resultcode'=>'99',
          'resultdesc'=>'失败',
          'resultobj'=>$order_result,
      );
      echo json($arr);
      exit();
    }  
  }

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

  • 1、app统一下单后数据返回给前端,前端调用报签名错误:首先验证自己的秘钥信息是否正确,要注意移动端和公众号的是不同的,而类拿着key又去重新签名,可以将微信官方提供的demo中的直接内部调用配置文件那里注释掉
  • 2、在公众号获取openid的时候,显示跨域:这个解决参考yii2框架中对于\yii::$app->response->header,中的remove方法,将报头去掉即可。
  • 3、对于微信支付的配置,包括公众号支付配置白名单、测试目录啥的就不过多说了,请自行搜索资料

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

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,谢谢大家对的支持。如果你想了解更多相关内容请查看下面相关链接