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 相关文章推荐
不用数据库的多用户文件自由上传投票系统(2)
Oct 09 PHP
解决控件遮挡问题:关于有窗口元素和无窗口元素
Jan 28 PHP
Wordpress php 分页代码
Oct 21 PHP
php+javascript的日历控件
Nov 19 PHP
php自动获取目录下的模板的代码
Aug 08 PHP
php设计模式 Factory(工厂模式)
Jun 26 PHP
php 获取本地IP代码
Jun 23 PHP
PHP下的Oracle客户端扩展(OCI8)安装教程
Sep 10 PHP
PHP使用curl制作简易百度搜索
Nov 03 PHP
php实现的二分查找算法示例
Jun 20 PHP
浅谈php的TS和NTS的区别
Mar 13 PHP
PHP获取类私有属性的3种方法
Sep 10 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+MYSQL实现用户的增删改查
2015/03/24 PHP
浅谈PHP中Stream(流)
2015/06/08 PHP
浅谈php错误提示及查错方法
2015/07/14 PHP
php技巧小结【推荐】
2017/01/19 PHP
PHP空值检测函数与方法汇总
2017/11/19 PHP
Laravel获取所有的数据库表及结构的方法
2019/10/10 PHP
js获取单选按钮的数据
2006/11/27 Javascript
什么是DOM(Document Object Model)文档对象模型
2012/03/05 Javascript
关于JS判断图片是否加载完成且获取图片宽度的方法
2013/04/09 Javascript
JavaScript获取onclick、onchange等事件值的代码
2013/07/22 Javascript
自定义Angular指令与jQuery实现的Bootstrap风格数据双向绑定的单选与多选下拉框
2015/12/12 Javascript
JS针对Array的各种操作汇总
2016/11/29 Javascript
vue2.0 keep-alive最佳实践
2017/07/06 Javascript
cocos creator Touch事件应用(触控选择多个子节点的实例)
2017/09/10 Javascript
用vue构建多页面应用的示例代码
2017/09/20 Javascript
jQuery中 DOM节点操作方法大全
2017/10/12 jQuery
vue cli使用绝对路径引用图片问题的解决
2017/12/06 Javascript
一文了解Vue中的nextTick
2019/05/06 Javascript
Vue列表循环从指定下标开始的多种解决方案
2020/04/08 Javascript
Vue中通过属性绑定为元素绑定style行内样式的实例代码
2020/04/30 Javascript
学习 Vue.js 遇到的那些坑
2021/02/02 Vue.js
js闭包和垃圾回收机制示例详解
2021/03/01 Javascript
Python中的exec、eval使用实例
2014/09/23 Python
Python语法快速入门指南
2015/10/12 Python
对Python3.6 IDLE常用快捷键介绍
2018/07/16 Python
使用python实现http及ftp服务进行数据传输的方法
2018/10/26 Python
python调用opencv实现猫脸检测功能
2019/01/15 Python
python从内存地址上加载python对象过程详解
2020/01/08 Python
一些关于python 装饰器的个人理解
2020/08/31 Python
Python调用ffmpeg开源视频处理库,批量处理视频
2020/11/16 Python
如何避免常见的6种HTML5错误用法
2017/11/06 HTML / CSS
韩国三星集团旗下时尚品牌官网:SSF SHOP
2016/08/02 全球购物
高三地理教学反思
2014/01/11 职场文书
元宵节主持词
2014/03/25 职场文书
教师自我剖析材料(四风问题)
2014/09/30 职场文书
Python Django / Flask如何使用Elasticsearch
2022/04/19 Python