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 相关文章推荐
关于mysql 字段的那个点为是定界符
Jan 15 PHP
使用GROUP BY的时候如何统计记录条数 COUNT(*) DISTINCT
Apr 23 PHP
wamp下修改mysql访问密码的解决方法
May 07 PHP
解析数组非数字键名引号的必要性
Aug 09 PHP
php实现天干地支计算器示例
Mar 14 PHP
zend framework框架中url大小写问题解决方法
Aug 19 PHP
Zend Guard使用指南及问题处理
Jan 07 PHP
PHP实现CSV文件的导入和导出类
Mar 24 PHP
PHP结合Jquery和ajax实现瀑布流特效
Jan 07 PHP
php登录超时检测功能实例详解
Mar 21 PHP
php版本CKEditor 4和CKFinder安装及配置方法图文教程
Jun 05 PHP
PHP7 标准库修改
Mar 09 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
php和jquery实现地图区域数据统计展示数据示例
2014/02/12 PHP
带你了解PHP7 性能翻倍的关键
2015/11/19 PHP
thinkphp框架下404页面设置 仅三步
2016/05/14 PHP
PHP字符串中抽取子串操作实例分析
2019/06/22 PHP
JavaScript获取一个范围内日期的方法
2015/04/24 Javascript
JavaScript和jquery获取父级元素、子级元素、兄弟元素的方法
2016/06/05 Javascript
Nodejs高扩展性的模板引擎 functmpl简介
2017/02/13 NodeJs
Vue 2.0在IE11中打开项目页面空白的问题解决
2017/07/16 Javascript
jQuery结合jQuery.cookie.js插件实现换肤功能示例
2017/10/14 jQuery
vue.js 微信支付前端代码分享
2018/02/10 Javascript
详解webpack模块加载器兼打包工具
2018/09/11 Javascript
bootstrap table实现iview固定列的效果实例代码详解
2019/09/30 Javascript
JS控制GIF图片的停止与显示
2019/10/24 Javascript
vue.js使用v-model实现父子组件间的双向通信示例
2020/02/05 Javascript
Python常用的日期时间处理方法示例
2015/02/08 Python
python获取指定目录下所有文件名列表的方法
2015/05/20 Python
Python标准库shutil用法实例详解
2018/08/13 Python
神经网络相关之基础概念的讲解
2018/12/29 Python
Python基本socket通信控制操作示例
2019/01/30 Python
详解python opencv、scikit-image和PIL图像处理库比较
2019/12/26 Python
python em算法的实现
2020/10/03 Python
英国知名化妆品网站:Revolution Beauty(原TAM Beauty)
2018/02/28 全球购物
ESDlife健康生活易:身体检查预订、搜寻及比较
2019/05/10 全球购物
意大利巧克力店:Chocolate Shop
2019/07/24 全球购物
Clos19英国:高档香槟、葡萄酒和烈酒在线购物平台
2020/07/10 全球购物
什么是serialVersionUID
2016/03/04 面试题
行政经理岗位职责
2013/11/09 职场文书
上课玩手机检讨书
2014/02/08 职场文书
产品销售计划书
2014/05/04 职场文书
村干部群众路线整改措施思想汇报
2014/10/12 职场文书
2014年学校体育工作总结
2014/12/08 职场文书
2016党员学习作风建设心得体会
2016/01/21 职场文书
公司会议开幕词
2016/03/03 职场文书
基于flask实现五子棋小游戏
2021/05/25 Python
python爬取网页版QQ空间,生成各类图表
2021/06/02 Python
Django实现WebSocket在线聊天室功能(channels库)
2021/09/25 Python