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新手上路(三)
Oct 09 PHP
建站常用13种PHP开源CMS比较
Aug 23 PHP
PHP中图片等比缩放的实例
Mar 24 PHP
php结合ajax实现赞、顶、踩功能实例
May 12 PHP
php curl 获取https请求的2种方法
Apr 27 PHP
Zend Framework框架实现类似Google搜索分页效果
Nov 25 PHP
PHP jQuery+Ajax结合写批量删除功能
May 19 PHP
对于Laravel 5.5核心架构的深入理解
Feb 22 PHP
实例介绍PHP中zip_open()函数用法
Feb 15 PHP
Laravel推荐使用的十个辅助函数
May 10 PHP
php设计模式之抽象工厂模式分析【星际争霸游戏案例】
Jan 23 PHP
PHP大文件及断点续传下载实现代码
Aug 18 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数组总结篇(一)
2008/09/30 PHP
php foreach、while性能比较
2009/10/15 PHP
解决ajax+php中文乱码的方法详解
2013/06/09 PHP
php中JSON的使用与转换
2015/01/14 PHP
PHP实现微信网页授权开发教程
2016/01/19 PHP
同时使用n个window onload加载实例介绍
2013/04/25 Javascript
给超链接添加特效鼠标移动展示提示信息且随鼠标移动
2013/10/17 Javascript
实例讲解JS中数组Array的操作方法
2014/05/09 Javascript
setinterval()与clearInterval()JS函数的调用方法
2015/01/21 Javascript
jquery.fastLiveFilter.js实现输入自动过滤的方法
2015/08/11 Javascript
AngularJS 路由详解和简单实例
2016/07/28 Javascript
概述BootStrap中role=&quot;form&quot;及role作用角色
2016/12/08 Javascript
详解vue服务端渲染(SSR)初探
2017/06/19 Javascript
ionic App问题总结系列之ionic点击系统返回键退出App
2017/08/19 Javascript
bootstrap时间控件daterangepicker使用方法及各种小bug修复
2017/10/25 Javascript
微信小程序开发技巧汇总
2019/07/15 Javascript
js实现旋转的星空效果
2019/11/01 Javascript
手写Vue源码之数据劫持示例详解
2021/01/04 Vue.js
Python用UUID库生成唯一ID的方法示例
2016/12/15 Python
Python解惑之True和False详解
2017/04/24 Python
Python实现调度算法代码详解
2017/12/01 Python
Python下载网络小说实例代码
2018/02/03 Python
Python多重继承之菱形继承的实例详解
2020/02/12 Python
Python内存泄漏和内存溢出的解决方案
2020/09/26 Python
html5录音功能实战示例
2019/03/25 HTML / CSS
标签和贴纸印刷:Lightning Labels
2018/03/22 全球购物
加拿大时装零售商:Influence U
2018/12/22 全球购物
公司财务工作总结的自我评价
2013/11/23 职场文书
精彩的英文自荐信
2014/01/30 职场文书
四查四看剖析材料
2014/02/14 职场文书
企业管理标语
2014/06/10 职场文书
副主任竞聘演讲稿
2014/08/18 职场文书
员工离职通知函
2015/04/25 职场文书
2016年社会管理综治宣传月活动总结
2016/03/16 职场文书
一篇文章带你复习java知识点
2021/06/28 Java/Android
uniapp引入支付宝原生扫码插件步骤详解
2022/07/23 Javascript