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分页函数
Jul 08 PHP
php分页示例代码
Mar 19 PHP
php下防止单引号,双引号在接受页面转义的设置方法
Sep 25 PHP
PHP 采集程序 常用函数
Dec 18 PHP
PHP中3种生成XML文件方法的速度效率比较
Oct 06 PHP
php中通过curl检测页面是否被百度收录
Sep 27 PHP
使用php计算排列组合的方法
Nov 13 PHP
PHP生成迅雷、快车、旋风等软件的下载链接代码实例
May 12 PHP
php+mysqli实现将数据库中一张表信息打印到表格里的方法
Jan 28 PHP
php提交表单发送邮件的方法
Mar 20 PHP
PHP测试成功的邮件发送案例
Oct 26 PHP
php 二维数组快速排序算法的实现代码
Oct 17 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通过curl模拟登陆DZ论坛
2015/05/11 PHP
php类中的$this,static,final,const,self这几个关键字使用方法
2015/12/14 PHP
Laravel框架查询构造器 CURD操作示例
2019/09/04 PHP
PHP设计模式(六)桥连模式Bridge实例详解【结构型】
2020/05/02 PHP
一些相见恨晚的 JavaScript 技巧
2010/04/25 Javascript
基于jquery的图片幻灯展示源码
2012/07/15 Javascript
javascript实现十六进制颜色值(HEX)和RGB格式相互转换
2014/06/20 Javascript
JavaScript使用Prototype实现面向对象的方法
2015/04/14 Javascript
jQuery实现仿QQ在线客服效果的滚动层代码
2015/10/15 Javascript
prototype框架中美元符号$用法分析
2016/01/22 Javascript
分类解析jQuery选择器
2016/11/23 Javascript
详解Node.js 命令行程序开发教程
2017/06/07 Javascript
不得不看之JavaScript构造函数及new运算符
2017/08/21 Javascript
LayUI表格批量删除方法
2018/08/15 Javascript
微信小程序实现简易table表格
2020/06/19 Javascript
Python入门篇之编程习惯与特点
2014/10/17 Python
python使用KNN算法手写体识别
2018/02/01 Python
浅析Python3爬虫登录模拟
2018/02/07 Python
python实现画五角星和螺旋线的示例
2019/01/20 Python
django-allauth入门学习和使用详解
2019/07/03 Python
Django模板Templates使用方法详解
2019/07/19 Python
Python 词典(Dict) 加载与保存示例
2019/12/06 Python
Python爬虫UA伪装爬取的实例讲解
2021/02/19 Python
深入CSS3 动画效果的总结详解
2013/05/09 HTML / CSS
购买200个世界上最好的内衣品牌:Bare Necessities
2017/02/11 全球购物
财务部副经理岗位职责范本
2014/06/17 职场文书
群众路线学习笔记范文
2014/11/06 职场文书
承兑汇票转让证明怎么写?
2014/11/30 职场文书
给老师的感谢信
2015/01/20 职场文书
写给父母的感谢信
2015/01/22 职场文书
小区物业管理2015年度工作总结
2015/10/22 职场文书
(开源)微信小程序+mqtt,esp8266温湿度读取
2021/04/02 Javascript
python实现自动化群控的步骤
2021/04/11 Python
Python道路车道线检测的实现
2021/06/27 Python
一文带你探究MySQL中的NULL
2021/11/11 MySQL
LeetCode189轮转数组python示例
2022/08/05 Python