PHP接入微信H5支付的方法示例


Posted in PHP onOctober 28, 2019

开发前配置

进行代码接入前,需在微信后台填写授权回调域名,此域名必须经过ICP备案

开发主要流程

  • 用户下单时选择微信支付
  • 商户进行业务逻辑处理并调用微信统一下单接口,微信H5交易类型为:trade_type=MWEB
  • 调用下单接口成功时,微信会返回包含支付跳转URL等相关参数,商户通过参数mweb_url调起支付中间页
  • 在中间页微信会进行H5权限的校验
  • 支付成功,微信会向商户发送异步结果通知

正式开发

调起微信支付,只说明必要参数
请求微信统一下单接口,接口地址:https://api.mch.weixin.qq.com/pay/unifiedorder

接口请求参数

  • appid:微信公众号iD
  • mch_id:账户号
  • nonce_str:随机字符串,不长于32位
  • sign:签名
  • body:商品描述
  • out_trade_no:商户订单号,不长于32位
  • total_fee:总金额,以分为单位
  • spbill_create_ip:用户端请求支付时的IP
  • notify_url:异步通知回调地址,必须是可直接访问地址,不能携带参数
  • trade_type:交易类型,如H5则是MWEB

以上便是H5支付下单所需要的参数

签名生成

  • 参与生成签名的参数必须非空
  • 参数按照ASCII码由小到大排序,参数名区分大小写
  • 按照上述规则,将参数拼接成如k1=v1&k2=v2....的字符串
  • 将上一步得到的字符串拼接上key, 如k1=v1&k2=v2&key=192006250b4c09247ec02e
  • 再将最后得到的字符串进行MD5加密,再转为大写,即为最终的sign值

代码:

/**
   * 组建签名
   * @param array $params 请求参数
   * @param string $key 秘钥
   */
  public function genSign($params, $key)
  {
    foreach ($params as $k=>$v) {
      if (!$v) {
        unset($params[$k]);
      }
    }
    ksort($params);
    $paramStr = '';
    foreach ($params as $k => $v) {
      $paramStr = $paramStr . $k . '=' . $v . '&';
    }
    $paramStr = $paramStr . 'key='.$key;
    $sign = strtoupper(md5($paramStr));
    return $sign;
  }

发起请求

将参数转为XML数据,即可发起请求

将数组转为XML代码:

/**
   * 将数组转为XML
   * @param array $params 支付请求参数
   */
  public function array_to_xml($params)
  {
    if(!is_array($params)|| count($params) <= 0) {
      return false;
    }
    $xml = "<xml>";
    foreach ($params as $key=>$val) {
      if (is_numeric($val)) {
        $xml.="<".$key.">".$val."</".$key.">";
      } else {
        $xml.="<".$key."><![CDATA[".$val."]]></".$key.">";
      }
    }
    $xml.="</xml>";
    return $xml;
  }

请求代码:

$ch = curl_init();
    curl_setopt($ch, CURLOPT_URL, $url);
    curl_setopt($ch, CURLOPT_HEADER, 0);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
    curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
    curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE);
    curl_setopt($ch, CURLOPT_POST, 1);
    curl_setopt($ch, CURLOPT_POSTFIELDS, $params);
    $return = curl_exec($ch);
    curl_close($ch);
    return $return;

微信返回的是XML数据:

<xml><return_code><![CDATA[SUCCESS]]></return_code>
<return_msg><![CDATA[OK]]></return_msg>
<appid><![CDATA[wxdded766660f9b840]]></appid>
<mch_id><![CDATA[1516216351]]></mch_id>
<device_info><![CDATA[100]]></device_info>
<nonce_str><![CDATA[2DUN2i2pGnlC6vDi]]></nonce_str>
<sign><![CDATA[95CEA831D598299097A32D8FEEC6BDEF]]></sign>
<result_code><![CDATA[SUCCESS]]></result_code>
<prepay_id><![CDATA[wx22194530678545eb3713f2f10724143329]]></prepay_id>
<trade_type><![CDATA[MWEB]]></trade_type>
<mweb_url><![CDATA[https://wx.tenpay.com/cgi-bin/mmpayweb-bin/checkmweb?prepay_id=wx22194530678545eb3713f2f10724143329&package=87106983]]></mweb_url>

return_code为SUCCESS代表支付请求成功;

mweb_url则为支付跳转页,此时客户端通过mweb_url已经可以调起微信支付

中间页处理

在得到微信返回的mweb_url参数后,可在服务端进一步获得deepLink

代码:

/**
   * 获取微信支付中间页deepLink参数
   * @param string $url 微信返回的mweb_url
   * @param string $ip 用户端IP
   */
  public function getDeeplink(string $url, string $ip)
  {
    $headers = array("X-FORWARDED-FOR:$ip", "CLIENT-IP:$ip");
    ob_start();
    $ch = curl_init();
    curl_setopt ($ch, CURLOPT_URL, $url);
    curl_setopt ($ch, CURLOPT_HTTPHEADER , $headers );
    curl_setopt ($ch, CURLOPT_REFERER, "pay.o9di.cn");
    curl_setopt( $ch, CURLOPT_HEADER, 1);
    curl_setopt($ch, CURLOPT_USERAGENT, 'Mozilla/5.0 (Linux; Android 6.0.1; OPPO R11s Build/MMB29M; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/55.0.2883.91 Mobile Safari/537.36');
    curl_exec($ch);
    curl_close ($ch);
    $out = ob_get_contents();
    ob_clean();
    $a = preg_match('/weixin:\/\/wap.*/',$out, $str);
    if ($a) {
      return substr($str[0], 0, strlen($str[0])-1);
    } else {
      return '';
    }
  }

weixin://wap/pay?prepayid%3Dwx22201221074146ac747121890095299503&package=2656135616&noncestr=1542888966&sign=e31dbc2d1231708ff8a982b15a6c7646即为得到的deepLink值,客户端也可以通过此值直接调起支付

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

PHP 相关文章推荐
php smarty模版引擎中变量操作符及使用方法
Dec 11 PHP
php学习之 认清变量的作用范围
Jan 26 PHP
关于mysql字符集设置了character_set_client=binary 在gbk情况下会出现表描述是乱码的情况
Jan 06 PHP
ThinkPHP权限认证Auth实例详解
Jul 22 PHP
php+mysql实现数据库随机重排实例
Oct 17 PHP
ThinkPHP函数详解之M方法和R方法
Sep 10 PHP
PHP读取大文件的几种方法介绍
Oct 27 PHP
CI框架(ajax分页,全选,反选,不选,批量删除)完整代码详解
Nov 01 PHP
thinkPHP批量删除的实现方法分析
Nov 09 PHP
thinkphp ajaxfileupload实现异步上传图片的示例
Aug 28 PHP
phpStudy 2016 使用教程详解(支持PHP7)
Oct 18 PHP
PHP Swoole异步MySQL客户端实现方法示例
Oct 24 PHP
PHP判断当前使用的是什么浏览器(推荐)
Oct 27 #PHP
php+layui数据表格实现数据分页渲染代码
Oct 26 #PHP
layui数据表格自定义每页条数limit设置
Oct 26 #PHP
在 Laravel 中动态隐藏 API 字段的方法
Oct 25 #PHP
Laravel 实现添加多语言提示信息
Oct 25 #PHP
Laravel5.5 动态切换多语言的操作方式
Oct 25 #PHP
解决php扩展安装不生效问题
Oct 25 #PHP
You might like
mysql 字段类型说明
2007/04/27 PHP
PHP一些常用的正则表达式字符的一些转换
2008/07/29 PHP
深入解析php之apc
2013/05/15 PHP
php购物车实现方法
2015/01/03 PHP
分享ThinkPHP3.2中关联查询解决思路
2015/09/20 PHP
Zend Framework教程之路由功能Zend_Controller_Router详解
2016/03/07 PHP
javascript编程起步(第七课)
2007/01/10 Javascript
国外的为初学者写的JavaScript教程
2008/06/09 Javascript
一个选择最快的服务器转向代码
2009/04/27 Javascript
Safari5中alert的无限循环BUG
2011/04/07 Javascript
修改好的jquery滚动字幕效果实现代码
2011/06/22 Javascript
巧用js提交表单轻松解决一个页面有多个提交按钮
2013/11/17 Javascript
基于javascript实现动态时钟效果
2020/08/18 Javascript
jQuery多个版本和其他js库冲突的解决方法
2016/08/11 Javascript
JS遍历ul下的li点击弹出li的索引的实现方法
2016/09/19 Javascript
浅析Angular2子模块以及异步加载
2017/04/24 Javascript
深入理解Angular.JS中的Scope继承
2017/06/04 Javascript
H5基于iScroll实现下拉刷新和上拉加载更多
2017/07/18 Javascript
angular中实现li或者某个元素点击变色的两种方法
2017/07/27 Javascript
Vue组件内部实现一个双向数据绑定的实例代码
2019/04/04 Javascript
VUE使用 wx-open-launch-app 组件开发微信打开APP功能
2020/08/11 Javascript
python的Crypto模块实现AES加密实例代码
2018/01/22 Python
Python实现的基于优先等级分配糖果问题算法示例
2018/04/25 Python
Python谱减法语音降噪实例
2019/12/18 Python
ansible动态Inventory主机清单配置遇到的坑
2020/01/19 Python
django orm模块中的 is_delete用法
2020/05/20 Python
Python第三方库安装缓慢的解决方法
2021/02/06 Python
网络书店创业计划书
2014/02/07 职场文书
主题班会演讲稿
2014/05/22 职场文书
节约用电标语
2014/06/17 职场文书
学校标语大全
2014/06/19 职场文书
数学教研活动总结
2014/07/02 职场文书
艺术学院毕业生自荐信
2014/07/05 职场文书
创业计划书之水果店
2019/07/18 职场文书
html+css 实现简易导航栏功能
2021/04/07 HTML / CSS
pytorch finetuning 自己的图片进行训练操作
2021/06/05 Python