前言

统一支付是JSAPI/NATIVE/APP各种支付场景下生成支付订单,返回预支付订单号的接口,目前微信支付所有场景均使用这一接口。下面介绍的是其中NATIVE的支付实现流程与PC端实现扫码支付流程

流程实现(后端)(PHP)

  1. 创建Wechatpay.php文件,放到指定文件目录下(我是放到了extend目录)
  1. <?php
  2. class Wechatpay{
  3. /**
  4. * 模拟提交参数,支持https提交 可用于各类api请求
  5. * @param string $url : 提交的地址
  6. * @param array $data :POST数组
  7. * @param string $method : POST/GET,默认GET方式
  8. * @return mixed
  9. */
  10. function curl_https($url, $xml='', $useCert=false){
  11. $ch = curl_init();
  12. //设置超时
  13. curl_setopt($ch, CURLOPT_TIMEOUT, 30);
  14. curl_setopt($ch,CURLOPT_URL, $url);
  15. //设置header
  16. curl_setopt($ch, CURLOPT_HEADER, FALSE);
  17. //要求结果为字符串且输出到屏幕上
  18. curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
  19. if(stripos($url,"https://")!==FALSE){
  20. curl_setopt($ch, CURLOPT_SSLVERSION, CURL_SSLVERSION_TLSv1);
  21. curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
  22. curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE);
  23. }else{
  24. curl_setopt($ch,CURLOPT_SSL_VERIFYPEER,TRUE);
  25. curl_setopt($ch,CURLOPT_SSL_VERIFYHOST,2);//严格校验
  26. }
  27. if($useCert == true){
  28. //设置证书
  29. //使用证书:cert 与 key 分别属于两个.pem文件
  30. curl_setopt($ch,CURLOPT_SSLCERTTYPE,'PEM');
  31. curl_setopt($ch,CURLOPT_SSLCERT,"");
  32. curl_setopt($ch,CURLOPT_SSLKEYTYPE,'PEM');
  33. curl_setopt($ch,CURLOPT_SSLKEY,"");
  34. }
  35. //post提交方式
  36. curl_setopt($ch, CURLOPT_POST, TRUE);
  37. curl_setopt($ch, CURLOPT_POSTFIELDS, $xml);
  38. //运行curl
  39. $data = curl_exec($ch);
  40. //返回结果
  41. if($data){
  42. curl_close($ch);
  43. return $data;
  44. } else {
  45. $error = curl_errno($ch);
  46. curl_close($ch);
  47. //echo $error;
  48. }
  49. }
  50. /**
  51. *
  52. * 拼接签名字符串
  53. * @param array $urlObj
  54. *
  55. * @return 返回已经拼接好的字符串
  56. */
  57. function ToUrlParams($urlObj)
  58. {
  59. $buff = "";
  60. foreach ($urlObj as $k => $v)
  61. {
  62. if($k != "sign"){
  63. $buff .= $k . "=" . $v . "&";
  64. }
  65. }
  66. $buff = trim($buff, "&");
  67. return $buff;
  68. }
  69. //数组转XML
  70. function arrayToXml($arr)
  71. {
  72. $xml = "<xml>";
  73. foreach ($arr as $key=>$val)
  74. { if (is_numeric($val)){
  75. $xml.="<".$key.">".$val."</".$key.">";
  76. }else{
  77. $xml.="<".$key."><![CDATA[".$val."]]></".$key.">";
  78. }
  79. }
  80. $xml.="</xml>";
  81. return $xml;
  82. }
  83. //将XML转为array
  84. function xmlToArray($xml)
  85. {
  86. //禁止引用外部xml实体
  87. libxml_disable_entity_loader(true);
  88. $values = json_decode(json_encode(simplexml_load_string($xml, 'SimpleXMLElement', LIBXML_NOCDATA)), true);
  89. return $values;
  90. }
  91. /**
  92. * 获取随机字符串
  93. * @return mixed
  94. */
  95. function getRandString($len=12,$str='ABCDEFGHIJKLMNOPQRSTUVWYXZabcdefghijklmnopqrstuvwyxz1234567890'){
  96. $strlen=strlen($str)-1;
  97. $string='';
  98. for ($i=0; $i < $len; $i++) {
  99. $r=rand(1,$strlen);
  100. $string=$string.$str[$r];
  101. }
  102. return $string;
  103. }
  104. }

2.定义公共变量

  1. private $config = array(
  2. 'appid' => "wxa******", /*微信小程序的appid*/
  3. 'appid_app' => "wx******", /*微信开放平台上的应用id*/
  4. 'mch_id' => "*******", /*微信申请成功之后邮件中的商户id*/
  5. 'api_key' => "*************", /*在微信商户平台上自己设定的api密钥 32位*/
  6. 'notify_url' => 'https://***', /*支付回调地址,确保可以访问*/
  7. );

3.支付接口

  1. public function NativePay($id,$price,$body,$type,$attach){
  2. Loader::import('wechatpay.Wechatpay', EXTEND_PATH,".php");
  3. $wechatpay = new \Wechatpay();
  4. $url='https://api.mch.weixin.qq.com/pay/unifiedorder';
  5. $orderID='XXX'.time().rand(0,9).rand(0,9).rand(0,9);
  6. $parameters=array(
  7. 'appid'=>$this->config["appid"],//appID
  8. 'mch_id'=>$this->config['mch_id'],//商户号
  9. 'nonce_str'=>$wechatpay->getRandString(30),//随机字符串
  10. 'body'=>$body,//商品描述
  11. 'out_trade_no'=>$orderID,//商户订单号
  12. 'total_fee'=>$price*100,//总金额 单位 分
  13. 'spbill_create_ip'=>$this->get_client_ip(),//终端IP
  14. 'notify_url'=>$this->config["notify_url"],//通知地址
  15. 'trade_type'=>'NATIVE',//交易类型
  16. 'attach'=>$attach
  17. );
  18. //参数名ASCII码从小到大排序
  19. ksort($parameters);
  20. //统一下单签名
  21. $String = $wechatpay->ToUrlParams($parameters);
  22. //签名步骤二:在string后加入KEY
  23. $String = $String."&key=".$this->config['api_key']; // key设置路径:微信商户平台(pay.weixin.qq.com)-->账户设置-->API安全-->密钥设置
  24. //签名步骤三:MD5加密
  25. $parameters['sign']=strtoupper(md5($String));
  26. $xmlData=$wechatpay->arrayToXml($parameters);
  27. $return=$wechatpay->xmlToArray($wechatpay->curl_https($url,$xmlData));
  28. if($return["return_code"]=="SUCCESS" && $return["result_code"]=="SUCCESS"){
  29. //生成订单或其他逻辑
  30. //返回二维码链接给前端
  31. $returnData=[
  32. 'code_url'=>$return["code_url"],
  33. 'orderID'=>$orderID
  34. ];
  35. // echo $this->creatqrcode($return["code_url"]);
  36. $this->result($returnData,'1','支付二维码生成成功!','json');
  37. }else{
  38. echo json_encode(array("status"=>false,"msg"=>$return));
  39. }
  40. }
  41. /*
  42. 获取当前服务器的IP
  43. */
  44. public function get_client_ip(){
  45. if ($_SERVER['REMOTE_ADDR']) {
  46. $cip = $_SERVER['REMOTE_ADDR'];
  47. } elseif (getenv("REMOTE_ADDR")) {
  48. $cip = getenv("REMOTE_ADDR");
  49. } elseif (getenv("HTTP_CLIENT_IP")) {
  50. $cip = getenv("HTTP_CLIENT_IP");
  51. } else {
  52. $cip = "unknown";
  53. }
  54. return $cip;
  55. }
  1. 支付回调
  1. //微信支付回调接口
  2. public function wxpaynotify(){
  3. $xml = file_get_contents('php://input');
  4. Loader::import('wechatpay.Wechatpay', EXTEND_PATH,".php");
  5. $wechatpay = new \Wechatpay();
  6. //将服务器返回的XML数据转化为数组
  7. $data = $wechatpay->xmlToArray($xml);
  8. // 保存微信服务器返回的签名sign
  9. $data_sign = $data['sign'];
  10. // sign不参与签名算法
  11. unset($data['sign']);
  12. $sign = $wechatpay->ToUrlParams($data);
  13. $payData=$sign;
  14. $sign=strtoupper(md5($sign."&key=".$this->config["api_key"]));
  15. // 判断签名是否正确 判断支付状态
  16. if ( ($sign===$data_sign) && ($data['result_code']=='SUCCESS') ) {
  17. // 更新消费订单状态等操作
  18. $result = true;
  19. }else{
  20. file_put_contents('payResult.tex','验签失败!');
  21. $result = false;
  22. }
  23. // 返回状态给微信服务器
  24. if ($result) {
  25. $str='<xml><return_code><![CDATA[SUCCESS]]></return_code><return_msg><![CDATA[OK]]></return_msg></xml>';
  26. }else{
  27. $str='<xml><return_code><![CDATA[FAIL]]></return_code><return_msg><![CDATA[签名失败]]></return_msg></xml>';
  28. }
  29. echo $str;
  30. }

流程实现(前端)(Vue)

  1. <!-- HTML -->
  2. <!-- 支付二维码 (切记别在canvas使用v-if/v-show等做条件判断,会导致渲染不出来的)-->
  3. <canvas id="qrcode" ref="qrcode"></canvas>
  4. <!-- JS -->
  5. //导入二维码组件QRCode
  6. import QRCode from 'qrcode';
  7. let qrcodeUrl = res.data.code_url
  8. const canvas = this.$refs.qrcode
  9. QRCode.toCanvas(canvas, qrcodeUrl, function (error) {
  10. if (error) console.error(error)
  11. console.log('QR code generated successfully.')
  12. })

vue+thinkphp5实现微信扫码支付(NATIVE支付)的更多相关文章

  1. Thinkphp5整合微信扫码支付开发实例

    ThinkPHP框架是比较多人用的,曾经做过的一个Thinkphp5整合微信扫码支付开发实例,分享出来大家一起学习 打开首页生成订单,并显示支付二维码 public function index() ...

  2. thinkphp5.0 微信扫码支付模式二

    仅供个人参考,方便大家. 一.1)https://pay.weixin.qq.com/index.php/core/home/login  复制此地址 打开微信商户平台. 2)下载安全操作证书(最好在 ...

  3. ThinkPHP5微信扫码支付

    1.把微信官网下载的demo放在根目录/vendor/目录下,这里我的是/vendor/wxpay_pc目录 2.把cert里面的文件替换成自己项目的证书(登陆微信商户平台,账户中心,API安全下载) ...

  4. thinkphp.2 thinkphp5微信支付 微信公众号支付 thinkphp 微信扫码支付 thinkphp 微信企业付款5

    前面已经跑通了微信支付的流程,接下来吧微信支付和微信企业付款接入到thinkphp中,版本是3.2 把微信支付类.企业付款类整合到一起放到第三方类库,这里我把微信支付帮助类和企业付款类放到同一个文件了 ...

  5. 【移动支付】.NET微信扫码支付接入(模式二-NATIVE)

    一.前言       经过两三天的琢磨总算完成了微信扫码支付功能,不得不感叹几句: 微信提供的DEMO不错,直接复制粘贴就可以跑起来了: 微信的配置平台我真是服了.公众平台.商户平台.开放平台,一个平 ...

  6. java微信扫码支付Native(模式二)

    官方开发文档模式二的地址:https://pay.weixin.qq.com/wiki/doc/api/native.php?chapter=6_5 pom文件的依赖: <?xml versio ...

  7. 微信扫码支付+Asp.Net MVC

    这里的扫码支付指的是PC网站上面使用微信支付,也就是官方的模式二,网站是Asp.net MVC,整理如下.(demo在最下方) 一.准备工作 使用的微信API中的统一下单方法,关键的参数是‘公众账号I ...

  8. 微信扫码i支付~官方DEMO的坑

    返回目录 之前写过关于微信支付那些坑的文章(<微信JSApi支付~集成到MVC环境后的最后一个坑(网上没有这种解决方案)>,<微信JSApi支付~坑和如何填坑>),下面说一下微 ...

  9. MVC 微信扫码支付

    微信扫码支付有两种模式, 模式一和模式二, 两者具体的区别可参考官网文档:https://pay.weixin.qq.com/wiki/doc/api/native.php?chapter=6_4 微 ...

  10. C# 微信扫码支付API (微信扫码支付模式二)

    一.SDK下载地址:https://pay.weixin.qq.com/wiki/doc/api/native.php?chapter=11_1,下载.NET C#版本: 二.微信相关设置:(微信扫码 ...

随机推荐

  1. gorm使用小结

    增 db.Create(user) db.Save(user) 参数只能用**结构体指针****,因为要根据指针写入该条插入的数据, 所以user可以作为该条数据使用. 新增只能用结构体 save方法 ...

  2. leaflet 河流颜色渐变效果

    1.Leaflet-polycolor github地址:https://github.com/Oliv/leaflet-polycolor 插件缺陷:需要把每个折点的颜色都指定才行,一般做不到 2. ...

  3. vue特殊atribute-is

    1.解决dom内模板限制 有些 HTML 元素,诸如 <ul>.<ol>.<table> 和 <select>,对于哪些元素可以出现在其内部是有严格限制 ...

  4. 在 WPF 中集成 ASP.NET Core 和 WebView2 用于集成 SPA 应用

    背景 我们有些工具在 Web 版中已经有了很好的实践,而在 WPF 中重新开发也是一种费时费力的操作,那么直接集成则是最省事省力的方法了. 修改项目文件 我们首先修改项目文件,让 WPF 项目可以包含 ...

  5. C#的关于窗体的类库方案 - 开源研究系列文章

    这次想到了以前编写的关于应用的那个类库,不过当时的只是定义了显示接口,然后调用窗体显示.现在想到要把这个关于窗体的类库进行集合,统一调用,于是就把原来的代码进行了修改完善,终于得到了这次这个例子. 这 ...

  6. JDK源码阅读-------自学笔记(十五)(java.lang.Math数学类)

    Math类简介 用于常见的数学方法 如果需要更加强大的数学运算能力,计算高等数学中的相关内容,可以使用apache commons下面的Math类库 常用方法及实战 abs 绝对值 实例: 1 //绝 ...

  7. 基于FPGA的电子琴设计(按键和蜂鸣器)----第一版

    欢迎各位朋友关注"郝旭帅电子设计团队",本篇为各位朋友介绍基于FPGA的电子琴设计(按键和蜂鸣器)----第一版. 功能说明: 外部输入七个按键,分别对应音符的"1.2. ...

  8. MinIo对象存储文件上传,下载,预览,批量上传,创建桶等

    MinIo 操作工具类 MinIo 旧中文文档 MinIo 英文文档 MinIo 官网地址 https://min.io/ package com.ming.utils; import io.mini ...

  9. 将外部jar打入本地maven仓库

    1.将jar包放入某不含中文的路径下 ,例如:E:\file\zip4j-1.3.2.jar 2.在命令行输入操作命令 mvn install:install-file -DgroupId=zip4j ...

  10. Maven项目中整合SSH(pom.xml文件的配置详解)

    Maven项目中整合SSH比较繁琐,需要解决版本冲突问题,博主在下面给出了pom.xml文件的配置信息,改配置文件整合的是:struts2-2.3.24.spring4.2.4.hibernate5. ...