PHP实现个人免签约微信支付接口原理+源码

news2024/12/19 1:43:19

什么是个人免签支付

个人免签支付就是给个人用的支付接口,一般的支付接口都需要营业执照才能申请,个人很难申请的到,或者是没有资质去申请,要和支付商进行签约的。免签,顾名思义就是不需要签约。那么个人免签支付就有市场了,就是为了解决个人无法轻易申请到支付接口的问题。

免签的方案有很多种

  1. APP监听收款码的支付结果,然后修改页面的支付结果。
  2. 二次清算。款先到拥有官方支付接口的商户中,由商户给你结算。
  3. Xposed微信插件实现全自动监听创建收款码、以及收款过程,容易封号。

方案其实有很多种,但是以上的方案都有不少的缺点,当然这些方案仍有不少人在用,没办法,确实是解决问题的一种办法。而本次文章我也是通过简单的技术开发实现第一种APP监听收款码的免签支付方式。

APP监听收款码的支付结果

整个过程很简单:

访问URL -> 检查数据库2分钟内未支付的订单金额 -> 如果2分钟内未支付的订单金额中存在当前订单一样的金额,需要在当前金额基础上+0.01元用于区分订单的唯一性 -> 用户扫码支付 -> 安卓手机APP监听到这笔订单的收款 -> 将收款金额异步发送到服务器 -> 服务器修改数据库该笔订单金额的支付状态 -> 扫码页面一直在轮询订单的支付状态,发现已支付就修改页面的支付结果 -> 完成支付。

上代码

index.php

该页面是用于创建订单的,其中 $order_price = 0.01; 就是创建一笔0.01元的订单。创建订单前,程序会查询数据库来确定当前金额是否存在未支付的订单,如果存在,需支付的金额会在当前订单金额基础上+0.01元。

为什么要这么做?因为APP监听只能监听到收到了多少钱,无法监听到订单号,所以无法区分这个金额是你支付的还是其他人支付的。

所以在当前订单有效期内,你需要注意两件事,第一,你这个程序的访问量一定不能太高,不允许高并发的情况出现,适合小众,小规模,小流量的业务使用,一旦人多了,短时间内订单量多了,很难做到精准的监听支付结果。

<!DOCTYPE html>
<html>
<head>
	<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
	<meta http-equiv="X-UA-Compatible" content="IE=edge">
	<meta name="viewport" content="width=device-width,initial-scale=1.0,maximum-scale=1.0,user-scalable=0,viewport-fit=cover">
	<meta charset="utf-8">
	<script src="./js/jquery.min.js"></script>
	<link rel="stylesheet" href="./css/style.css">
	<title>微信赞赏码免签约支付实现原理Demo</title>
</head>

<body onload="clock(120)">
    
    <?php
    
        // 数据库配置
    	include './Db.php';
    	
    	// 实例化类
    	$db = new DB_API($config);
    	
        // 订单号
        $order_num = date('Ymd').time();
        
        // 订单金额
        $order_price = 0.01;
    	
    	// 获取未支付订单列表
        $getOrderList = $db->set_table('mqpay_order')->findAll(['order_status' => 1]);
        
        // 遍历订单
        $orderNoExpire = array();
        for ($i = 0; $i < count($getOrderList); $i++) {
            
            // 订单时间
            $order_time = json_decode(json_encode($getOrderList[$i]))->order_time;
            
            // 订单金额
            $order_money = json_decode(json_encode($getOrderList[$i]))->order_money;
            
            // 获取2分钟未支付的订单
            if(countTimes(time(),strtotime($order_time)) <= 2){
                
                // 如果存在
                $orderNoExpire[] = $order_money;
    
            }
        }
        
        // 判断是否有2分钟未支付的订单
        if(count($orderNoExpire) == 0){
            
            $needPay = $order_price;
        }else{
            
            // 获取2分钟未支付的订单的最大金额+0.01
            $needPay = max($orderNoExpire) + 0.01;
            
        }
        
        // 创建订单
        creatOrder($order_num,$order_price,$needPay,$db);
        
        
        // 创建订单
        function creatOrder($order_num,$order_price,$needPay,$db){
            
            // 订单参数
            $createOrder = [
                'order_num' => $order_num,
                'order_price' => $order_price,
                'order_money' => $needPay,
            ];
            
            // 创建
            $createOrderResult = $db->set_table('mqpay_order')->add($createOrder);
            if($createOrderResult){
                
                // 成功
                echo '<div class="payInfoCard">
            	    <div class="header">里客云科技</div>
            	    <div class="moneyCard">
            	        <div class="text">支付金额</div>
            	        <div class="money"><span class="rmb">¥</span>'.$needPay.'</div>
            	        <!--二维码-->
            	        <img src="./img/zsm.jpg" id="zsmQrcode" class="zsmQrcode" />
            	        <p class="payWarning">请识别上方赞赏码</p>
            	        <p class="payWarning">点击<span class="blueFont">其他金额</span>输入'.$needPay.'元</p>
            	        <p class="payWarningMini">输入的金额必须要完全一致</p>
            	        <p id="orderExpireTime"></p>
            	        <p id="orderNum" style="display:none;">'.$order_num.'</p>
            	        <p id="needPay" style="display:none;">'.$needPay.'</p>
            	    </div>
            	</div>
            	
            	<!--提示-->
            	<p class="payTips">我们通过机器人监测本次支付<br/>支付后会立刻显示支付结果<br/>支付后没显示支付结果请联系人工处理<br/>人工微信号:sansure2016</p>';
            }else{
                
                // 失败
                echo '<div class="payInfoCard">
            	    <div class="header">里客云科技</div>
            	    <div class="moneyCard" style="padding:20px 20px;">
            	        创建订单失败!
            	    </div>
            	</div>';
            }
        }
        
        
        // 计算时间戳的差值
        function countTimes($begin,$end){
            
            $begintimes = $begin;
            $endtimes = $end;
            $timediff = abs($endtimes - $begintimes);
            $days = intval($timediff / 86400);
            $remain = $timediff % 86400;
            $hours = intval($remain / 3600);
            $remain = $remain % 3600;
            $mins = intval($remain / 60);
            $secs = $remain % 60;
            return $mins;
        }
        
    ?>
    
    <script>
    
        // 每2秒获取一次支付结果
        var checkPayInterval = setInterval('checkPay()',2000);
        
        // 获取支付结果
        function checkPay(){
            
            // 获取订单号和支付金额
            var orderNum = $("#orderNum").text();
            var needPay = $("#needPay").text();
            
            $.ajax({
                type: "GET",
                url: "./checkPay.php?order_num="+orderNum+"&order_money="+needPay,
                success: function(res){
  
                    // 判断支付结果
                    if(res.code == 200){
                        
                        console.log('支付成功');
                        $("#zsmQrcode").prop("src","./img/success.png");
                        $('#orderExpireTime').css('display','none');
                        clearInterval(checkPayInterval);
  
                    }else{
                        
                        console.log(res.msg);
                    }
                }
            });
        }
        
        // 倒计时
        function clock(times){
            
            // 获取时分秒
            var h=parseInt(times/3600);
            var m=parseInt((times%3600)/60);
            var s=(times%3600)%60;
            
            // 在页面中显示倒计时
            $('#orderExpireTime').html(m+"分"+s+"秒后过期");
            
            // 倒计时
            if(times > 0){
                times = times-1;
                setTimeout(function (){
                    clock(times);
                }, 1000);
            }else{
                
                // 显示订单过期
                $("#zsmQrcode").prop("src","./img/expire.png");
                $('#orderExpireTime').text('订单已过期,请刷新页面!');
                
                // 结束轮询
                clearInterval(checkPayInterval);
                
                console.log('订单过期,停止监听');
            }
        }
    </script>
</body>

</html>

checkPay.php

这个是用于订单页面实时监听支付结果的,每2秒就查一次数据库获取订单的支付结果,2分钟后未支付会停止查询。

<?php

    // 页面编码
    header("Content-type:application/json");
    
    // 数据库配置
	include './Db.php';

	// 实例化类
	$db = new DB_API($config);
	
    // 获取订单号和支付金额
	$order_num = $_GET['order_num'];
	$order_money = $_GET['order_money'];
	
    // 根据订单号和订单金额来查询支付结果
    $getOrderPayStatus = $db->set_table('mqpay_order')->find(['order_num'=>$order_num,'order_money'=>$order_money]);
    
    // 判断支付结果
    if($getOrderPayStatus){
        
        // 支付状态
        $order_status = json_decode(json_encode($getOrderPayStatus))->order_status;
        
        if($order_status == 2){
            
            // 支付成功
            $payResult = array(
                'code' => 200,
                'msg' => '支付成功'
            );
        }else{
            
            // 未支付
            $payResult = array(
                'code' => 202,
                'msg' => '未支付'
            );
        }
        
    }else{
        
        // 无结果
        $payResult = array(
            'code' => 201,
            'msg' => '未支付'
        );
    }
    
    // 返回JSON
    echo json_encode($payResult,JSON_UNESCAPED_UNICODE);
    
?>

notify.php

这个是异步回调,在APP监听软件需要配置这个文件的URL和传递的参数,将监听到的金额POST给你的服务器然后修改数据库的支付结果,以实现支付回调的目的。

<?php

    // 页面编码
    header("Content-type:application/json");

    // 原文
    $orderMsg = $_GET['orderMsg'];
    
    // 数据库配置
	include './Db.php';

	// 实例化类
	$db = new DB_API($config);
	
    // 订单金额、需支付的金额、通知原文、db实例
	updateOrder($orderMsg,$db);
    
    // 修改支付结果
    function updateOrder($orderMsg,$db){
        
        // 截取
        // 示例:二维码赞赏到账1.00元
        // 截取【到账】后面的
        $money_1 = substr($orderMsg, strripos($orderMsg, "到账") + 6);
        
        // 截取【元】前面的
        $money_2 = substr($money_1, 0, strrpos($money_1, "元"));
        
        // 更新订单
        $updateOrderResult = $db->set_table('mqpay_order')->update(['order_status'=>1,'order_money'=>$money_2],['order_status'=>2,'order_paytime'=>time(),'order_msg'=>$orderMsg]);

        if($updateOrderResult){
            
            // 成功
            $ret = array(
                'code' => 200,
                'msg' => '支付成功',
                'order_num' => $order_num,
                'order_money' => $money_2,
                'order_msg' => $orderMsg
            );
        }else{
            
            // 失败
            $ret = array(
                'code' => 200,
                'msg' => '支付失败',
                'order_num' => $order_num
            );
        }
    }
    
    // 返回JSON
    echo json_encode($ret,JSON_UNESCAPED_UNICODE);
    
?>

完整代码

以上3个文件是核心代码,仅作技术分析实现原理。完整的代码涉及到样式、图片、数据库操作类、以及数据库表SQL语句、监听APP源码及安装包。

在这里插入图片描述

Demo图片

页面也是非常简单的,也是由本人设计,页面精简美观。

在这里插入图片描述

监听APP配置

监听APP配置也挺简单的,只需要将notify.php的线上URL配置至APP即可。具体操作请看截图:

1、打开APP,选择**【发送通道】点击【Webhook】,选择【GET请求】** ,输入notify.php 所在服务器的URL,下面的参数填写**【orderMsg=[msg]】**即可。

在这里插入图片描述

2、选择**【转发规则】,点击【应用】,添加转发规则,【APP包名】,选择【是】,包名输入【com.tencent.mm】**,选择的发送通道是上一步你创建的通道,下方的模板直接选择通知内容即可。

在这里插入图片描述

到这里,APP基本完成配置,然后将这个APP的自动启动开启,以及加入电池优化白名单,保证这个APP能一直在后台运行不被杀死。

赞赏码获取

为什么用赞赏码而不用收款码?因为收款码更容易被风控,收款码更加适合面对面扫码收款,而不适合线上远程收款,因为你的每一笔支付,都会记录付款ip地址,定位等信息,扫码次数多了,就会被系统判断远程付款,容易触发风控。赞赏码是用于网络上的赞赏使用,相对来说是比收款码安全的。

在这里插入图片描述

获得自己的赞赏码后,将赞赏码的那部分裁剪出来,替换掉源码中 zsm.jpg 这个文件就行了。赞赏码是可以设置赞赏的引导语的,可以将引导语修改为【请点击其他金额输入】,引导用户。

源码下载

这个源码只有单页面,没有后台,只适合个人单页部署使用或者研究、学习、二次开发,不适合开箱即用,当然其实你有点基础,也算是开箱即用,上传到服务器,修改数据库配置,导入数据库表,配置好赞赏码,配制好APP异步回调,也是可以用来做单页的收款的,只要你的金额是固定的,确实是开箱即用。

https://download.csdn.net/download/weixin_39927850/87500404

作者

TANKING

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/371888.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

企业数字化运营平台软件开发框架项目

【版权声明】本资料来源网络&#xff0c;知识分享&#xff0c;仅供个人学习&#xff0c;请勿商用。【侵删致歉】如有侵权请联系小编&#xff0c;将在收到信息后第一时间删除&#xff01;完整资料领取见文末&#xff0c;部分资料内容&#xff1a; 目录 1 项目总体概述 1.1 项目…

Unity Avatar Camera Controller 第一、第三人称相机控制

文章目录简介Variables实现Target PositionTarget RotationOthers简介 本文介绍如何实现用于Avatar角色的相机控制脚本&#xff0c;支持第一人称、第三人称以及两种模式之间的切换&#xff0c;工具已上传至SKFramework框架的Package Manager中&#xff1a; Variables Avatar&…

51单片机入门 - 简短的位运算实现扫描矩阵键盘

介绍 例程使用 SDCC 编译、 stcgal 烧录&#xff0c;如果你想要配置一样的环境&#xff0c;可以参考本专栏的第一篇文章“51单片机开发环境搭建 - VS Code 从编写到烧录”&#xff0c;我的设备是 Windows 10&#xff0c;使用普中51单片机开发板&#xff08;STC89C52RC&#xf…

Qt编写微信支付宝支付

文章目录一 微信支付配置参数二 支付宝支付配置参数三 功能四 Demo效果图五 体验地址一 微信支付配置参数 微信支付API&#xff0c;需要三个基本必填参数。 微信公众号或者小程序等的appid&#xff1b;微信支付商户号mchId&#xff1b;微信支付商户密钥mchKey&#xff1b; 具…

文件基础IO

目录 前言 用库进行文件操作 文件描述符 理解Linux一切皆文件 缓冲区 认识缓冲区 缓冲区缓冲策略 磁盘结构 磁盘分区 软链接和硬链接 硬链接本质 软连接本质 动态库和静态库进阶 写一个静态库 动态库的产生和使用 动静态库的加载 总结&#xff1a; 前言 在我们了…

SE | 哇哦!让人不断感叹真香的数据格式!~

1写在前面 最近在用的包经常涉及到SummarizedExperiment格式的文件&#xff0c;不知道大家有没有遇到过。&#x1f912; 一开始觉得这种格式真麻烦&#xff0c;后面搞懂了之后发现真是香啊&#xff0c;爱不释手&#xff01;~&#x1f61c; 2什么是SummarizedExperiment 这种cla…

lighthouse的介绍和基本使用方法

Lighthouse简介 Lighthouse是一个开源的自动化性能测试工具&#xff0c;我们可以使用该功能检测我们的页面存在那些性能方面的问题&#xff0c;并会生成一个详细的性能报告来帮助我们来优化页面 使用方式 LH一共有四种使用方式 Chrome开发者工具Chrome扩展Node 命令行Node …

数据结构与算法(一)-软件设计(十七)

设计模式&#xff08;十五&#xff09;-面向对象概念https://blog.csdn.net/ke1ying/article/details/129171047 数组 存储地址的计算&#xff1a; 一维数组a[n]&#xff0c;当a[2]的存储地址为&#xff1a;a2*len&#xff0c;如果每一个数组元素只占用一个字节&#xff0c;那…

Spring Batch 高级篇-分区步骤

目录 引言 概念 分区器 分区处理器 案例 转视频版 引言 接着上篇&#xff1a;Spring Batch 高级篇-并行步骤了解Spring Batch并行步骤后&#xff0c;接下来一起学习一下Spring Batch 高级功能-分区步骤 概念 分区&#xff1a;有划分&#xff0c;区分意思&#xff0c;在…

中国ETC行业市场规模及未来发展趋势

中国ETC行业市场规模及未来发展趋势编辑根据市场调研在线网发布的2023-2029年中国ETC行业发展策略分析及战略咨询研究报告分析&#xff1a;随着政府坚持实施绿色出行政策&#xff0c;ETC行业也受到了极大的支持。根据中国智能交通协会统计&#xff0c;2017年中国ETC行业市场规模…

浅析Linux内核进程间通信(信号量)

信号灯与其他进程间通信方式不大相同&#xff0c;它主要提供对进程间共享资源访问控制机制。相当于内存中的标志&#xff0c;进程可以根据它判定是否能够访问某些共享资源&#xff08;临界区&#xff0c;类似于互斥锁&#xff09;&#xff0c;同时&#xff0c;进程也可以修改该…

FreeRTOS任务基础知识

单任务和多任务系统单任务系统单任务系统的编程方式&#xff0c;即裸机的编程方式&#xff0c;这种编程方式的框架一般都是在main&#xff08;&#xff09;函数中使用一个大循环&#xff0c;在循环中顺序的执行相应的函数以处理相应的事务&#xff0c;这个大循环的部分可以视为…

Linux内核共享内存使用常见陷阱与分析

所谓共享内存就是使得多个进程可以访问同一块内存空间&#xff0c;是最快的可用IPC形式。是针对其他通信机制运行效率较低而设计的。往往与其它通信机制&#xff0c;如 信号量结合使用&#xff0c;来达到进程间的同步及互斥。其他进程能把同一段共享内存段“连接到”他们自己的…

【华为OD机试模拟题】用 C++ 实现 - 最小叶子节点(2023.Q1)

最近更新的博客 【华为OD机试模拟题】用 C++ 实现 - 获得完美走位(2023.Q1) 文章目录 最近更新的博客使用说明最小叶子节点题目输入输出示例一输入输出示例二输入输出Code使用说明 参加华为od机试,一定要注意不要完全背诵代码,需要理解之后模仿写出,通过率才会高。 华…

oracle数据库使用JDBC导入ClickHouse数据

一、背景 需求要把oracle中的数据导入到clickhouse中&#xff0c;使用clickhouse的jdbc表引擎&#xff0c;把oracle11g的数据导入到clickhouse中。 二、方案 通过clickhouse-jdbc-bridge&#xff1a;是clickhouse提供的一个jdbc组件&#xff0c;用于通过JDBC的方式远程访问其他…

[面试直通版]网络协议面试核心之IP,TCP,UDP-TCP与UDP协议的区别

点击->计算机网络复习的文章集<-点击 目录 前言 UDP TCP 区别小总结 前言 TCP和UDP都是在传输层&#xff0c;在程序之间传输数据传输层OSI模型&#xff1a;第四层TCP/IP模型&#xff1a;第三层关键协议&#xff1a;TCP协议、UDP协议传输层属于主机间不同进程的通信传…

Unity Lighting -- 光照入门

识别光源 首先来看一张图&#xff0c;看看我们能在这个场景中找到几个光源。 相信大家能够很容易看出来&#xff0c;四盏路灯模型带有四个光源&#xff0c;右边的红绿蓝三个发光的灯也是光源。场景中还有一个光源&#xff0c;这个光源来自天空&#xff0c;让场景看起来有点日落…

尚医通(二十四)就医提醒和预约统计

目录一、就医提醒1、搭建定时任务模块二、后台管理系统-预约统计功能1、开发每天预约数据接口2、封装远程调用接口4、整合统计功能前端一、就医提醒 我们通过定时任务&#xff0c;每天8点执行&#xff0c;提醒就诊 1、搭建定时任务模块 &#xff08;1&#xff09;添加依赖 &l…

【MySQL】调控 字符集

一、 MySQL 启动选项 & 系统变量 启动选项 是在程序启动时我们程序员传递的一些参数&#xff0c;而 系统变量 是影响服务器程序运行行为的变量 1.1 启动项 MySQL 客户端设置项包括&#xff1a; 允许连入的客户端数量 、 客户端与服务器的通信方式 、 表的默认存储引擎 、…

zookeeper入门到精通

文章目录一、zookeeper入门1. 概述zookeeper的工作机制2.特点3.数据结构4.应用场景4.1.统一命名服务4.2.统一配置管理4.3.统一集群管理4.4.服务器节点动态上下线4.5.软负载均衡5.下载地址二、zookeeper安装1.本地模式安装2.配置参数解读三、zookeeper集群操作1.集群操作1.1 集群…