今年利用业余时间搞了个web应用,在支付环节卡住了,因为支付宝和微信都不支持个人收款,必须要有公司资质,没办法,只能google下看看是否有人和我遇到相同问题,果然有很多解决方案,研究了一个多礼拜,发现个人收款都是收费的,而且还不稳定,服务也非常差,问个问题半天甚至几天后才有回答。最后没办法只能自己各种研究,搞出了一种真正免费的个人免签支付方案(不需了解Andriod,不需了解后端开发,甚至不需要写一行代码),不敢独享,现分享给大家。

基本原理

终极原理很简单,就一句话:Android端应用将收到的个人微信的收款信息通知后端服务,后端服务分析出谁支付了多少钱等信息,然后通知开发者支付完成并自动发货。

操作流程

1. 开发者上传微信的个人收款码到平台。

2. 用户发起请求支付服务。

3. 平台返回相匹配的收款二维码并展示给用户。

4. 用户完成扫码支付。

5. 安装有收款微信的Android手机收到用户完成支付的通知。

6. Android端应用将收款信息通知后端服务。

7. 后端服务分析并校验无误后,通知开发者用户已经完成支付,可以自动发货了。

下面介绍利用「冰狐智能辅助」实现免费的个人免签支付的方案,您只需要详细案以下步骤操作,不需要写一行代码即可实现免费的个人免签支付。分两部分实现,一部分是移动端,负责捕获收款信息;另一部分是后端服务,负责解析并通知开发者支付结果。在之前请先免费注册一个用户。

构建移动端

  • 下载「冰狐智能辅助」APP并安装,安装完成后请登录。登录时请按提示打开所有权限,具体下载地址和详细安装配置过程请参考这里。
  • 登录网页,打开web页面「移动端」/「移动端脚本」,新建一个名为“个人支付”的脚本,将如下JS脚本粘贴到这里并保存。
function main() {while (true) {}
}function cbNotification(textList, className, packageName, event) {for (var item of textList) {if (item.includes('微信支付')) {var arr = item.fetchNumber();if (arr.length > 0) {var ret = callMicroService('pay_notify', [rsUUID, 1, arr[arr.length - 1]]);console.log('call ret:' + ret);}return true;}}return false;
}
  • 打开web页面「移动端」/「我的设备」,找到刚才登录的手机,然后选择“编辑”按钮,修改“默认脚本”为上面新建的“个人支付”脚本。

创建微服务脚本

微服务脚本用于实现后端的业务逻辑,比如:上传和查看支付二维码,查看支付订单,通知开发者支付结果等功能。

打开web页面「微服务」/「微服务脚本」新建如下脚本,并将对应的JS源码粘贴进去:

  • pay_notify,用于处理支付信息,并通知开发者支付结果。JS源码如下:
function main(uuid, type, price) {var ret = false;price = parseInt(price*100);var key = uuid + price;var orderId = cacheGet(key);if (orderId) {console.log('匹配到价格,可以通知了:' + orderId);var data = dbQuery('order', '*', ['id=' + orderId]);if (data && data.length == 1) {var item = data[0];// 通知 调用者var bodyParams = {outTradeNo: item.outTradeNo, price: item.price / 100.0, realPrice: item.realPrice / 100.0};var result = 2, postResult = httpPost(item.notifyUrl, bodyParams);if (postResult && postResult.length > 0) {if (postResult.status == 200 || postResult.status == 302) {result = 1;}}// change statusret = dbUpdate('order', ['status=' + result], ['id=' + orderId]);if (!ret) {console.error('更新状态失败');}cacheRemove(key);}} else {console.error('invalidate price:' + price);}return ret;
}
  • add_price,用于添加支付二维码,JS源码如下:
function main(payType, price, deviceId, file) {price = parseInt(price*100);var ret = false, qrCode = qrDecode(file.inputStream);if (qrCode != '') {var qRet = dbQuery('price', 'count(id) as count', [`userId='${rsOpenId}'`, `price=${price}`, `payType=${payType}`, `deviceId='${deviceId}'`]);if (qRet[0].count > 0) {ret = dbUpdate('price', [`qrCode='${qrCode}'`], [`price=${price}`, `payType=${payType}`, `deviceId='${deviceId}'`]);} else {var iRet = dbInsert('price', {userId:rsOpenId, price:price, payType:payType, deviceId:deviceId, qrCode:qrCode});ret = iRet > 0;}}return ret;
}
  • query_price,用于查询支付二维码,JS源码如下:
function main(fetchCountOnly, conditions, startIndex, itemCount) {var jsonConditions = JSON.parse(conditions), params = [`userId='${rsOpenId}'`];for (var item of jsonConditions) {if (item.name == 'query_type') {var type = parseInt(item.value);if (type > 0) {params.push('payType=' + type);}}}if (fetchCountOnly) {var qRet = dbQuery('price', 'count(id) as count', params);return qRet[0].count;} else {var qRet = dbQuery('price', '*', params, '', startIndex, itemCount);for (var item of qRet) {item.price /= 100.0;if (item.payType == 1) {item.payType = '微信';} else {item.payType = '支付宝';}}return qRet;}
}
  • query_order,用于查询订单,JS源码如下:

    function main(fetchCountOnly, conditions, startIndex, itemCount) {var jsonConditions = JSON.parse(conditions);var params = [`userId='${rsOpenId}'`];for (var item of jsonConditions) {var deviceId = item.value;if (item.name == 'deviceId' && deviceId != '') {params.push(`deviceId='${deviceId}'`);}}if (fetchCountOnly) {var qRet = dbQuery('order', 'count(id) as count', params);return qRet[0].count;} else {var qRet = dbQuery('order', '*', params, 'order by time desc', startIndex, itemCount);for (var item of qRet) {item.price /= 100.0;item.realPrice /= 100.0;if (item.payType == 1) {item.payType = '微信';} else {item.payType = '支付宝';}if (item.status == 0) {item.status = '等待支付';} else if (item.status == 1) {item.status = '交易完成';} else if (item.status == 2) {item.status = '通知失败';} else if (item.status == -1) {item.status = '订单过期';}var datetime = new Date();datetime.setTime(item.time);var year = datetime.getYear();var month = datetime.getMonth() + 1 < 10 ? "0" + (datetime.getMonth() + 1) : datetime.getMonth() + 1;var date = datetime.getDate() < 10 ? "0" + datetime.getDate() : datetime.getDate();var hour = datetime.getHours()< 10 ? "0" + datetime.getHours() : datetime.getHours();var minute = datetime.getMinutes()< 10 ? "0" + datetime.getMinutes() : datetime.getMinutes();var second = datetime.getSeconds()< 10 ? "0" + datetime.getSeconds() : datetime.getSeconds();var t = year + "-" + month + "-" + date+" "+hour+":"+minute+":"+second;item.time = t;}return qRet;}
    }
    
  • unified_order,用于开发者请求支付,返回支付二维码,JS源码如下:
function main(payType, price, outTradeNo, notifyUrl, timeout = 120000) {price = parseInt(price*100);var ret = null, qrImage = '', realPrice = price;var maxCount = 5, i = 0, anyRet = null, findAny = false;while (i < maxCount) {realPrice = price - i;var qRet = dbQuery('price', '*', [`userId='${rsOpenId}'`, `payType=${payType}`, `price=${realPrice}`]);if (qRet.length <= 0) {if (!findAny) {anyRet = dbQuery('price', '*', [`userId='${rsOpenId}'`, `payType=${payType}`, 'price=0']);findAny = true;}qRet = anyRet;}if (qRet.length > 0) {for (var item of qRet) {var key = item.deviceId + realPrice;var cache = cacheGet(key);if (null == cache) {lock('malloc_price');cache = cacheGet(key);if (null == cache) {// 可以分配了ret = dbInsert('order', {userId: rsOpenId,price: price,realPrice: realPrice,outTradeNo: outTradeNo,deviceId: item.deviceId,qrCode: item.qrCode,notifyUrl: notifyUrl});}if (null != ret) {var image = qrEncode(item.qrCode);qrImage = base64Encode(image);cachePut(key, ret, 60000);}unlock('malloc_price');if (null != ret) {break;}}}}if (null != ret) {break;}++i;}if (null == ret) {console.error('unified failed');} else {return {payTye: payType, price: price, realPrice: realPrice, qrImageData: qrImage, timeout: timeout};}return {};
}
  • common,一些通用的函数,JS源码如下:
function deletePrice(item) {var id = item.id;return dbDelete('price', [`id=${id}`]);
}function deleteOrder(item) {var id = item.id;return dbDelete('order', [`id=${id}`]);
}function getDevice(includeAll=false) {var list =  deviceList(rsOpenId);var result = [];if (includeAll) {result.push({name: '全部', value: ''});}for (var item of list) {result.push({name: item.name, value: item.uuid});}return result;
}

创建移动端接口

移动端接口用于「冰狐智能辅助」APP端脚本调用,在这里主要用于手机端通知后端服务支付相关信息。参考文档

  • 打开web页面「微服务」/「移动端接口」,新建名为“pay_notify”的接口,选择“pay_notify”脚本。

创建服务端接口

服务端接口用于第三方服务调用「冰狐智能辅助」的后端功能,这里主要用于开发者在自己的后端服务中调用生成订单的接口。参考文档

  • 打开web页面「微服务」/「服务端接口」,新建名为”unified_order”的接口,选择“unified_order”脚本。
  • 查看unified_order脚本的入口参数可知,接口参数为:[payType, price, outTradeNo, notifyUrl],依次为:支付类型(微信:1,支付宝:2),支付价格,交易序列号,和支付成功后的通知url

创建二维码价格数据库

价格数据库用于存放开发者上传的价格二维码信息。

  • 打开web页面「微服务」/「数据库」,新建名为“price”的数据库。
  • 选择“模式” / “列源码”按钮,将如下列源码粘贴进去并确认修改。
[{"type": "tinyint","name": "payType","default": "1","options": [{"name": "not null","value": false,"description": "不为空"}, {"name": "unique","value": false,"description": "不重复"}, {"name": "unsigned","value": false,"description": "无符号"}]
}, {"type": "varchar(45)","name": "deviceId","default": "''","options": [{"name": "not null","value": true,"description": "不为空"}, {"name": "unique","value": false,"description": "不重复"}]
}, {"type": "varchar(128)","name": "qrCode","default": "''","options": [{"name": "not null","value": false,"description": "不为空"}, {"name": "unique","value": false,"description": "不重复"}]
}, {"type": "int","name": "price","default": "0","options": [{"name": "not null","value": false,"description": "不为空"}, {"name": "unique","value": false,"description": "不重复"}, {"name": "unsigned","value": false,"description": "无符号"}]
}, {"type": "varchar(45)","name": "userId","default": "''","options": [{"name": "not null","value": true,"description": "不为空"}, {"name": "unique","value": false,"description": "不重复"}]
},{"name": "支付类型","id": "payType","type": "select","defaultValue": "微信:1,支付宝:2","description": ""
}, {"name": "价格","id": "price","type": "float","defaultValue": "","description": ""
}, {"name": "设备","id": "deviceId","type": "select","defaultValue": "{\"name\":\"get_device\", \"params\":[], \"isDev\":true}","description": ""
}, {"name": "二维码图片","id": "file","type": "file","defaultValue": "","description": ""
}]
  • 选择“索引”按钮,选择“索引源码”,将如下列源码粘贴进去并确认修改。
[{"indexName": "userId","columnsName": "userId"
}]

创建订单数据库

订单数据库用于存放订单数据。

  • 打开web页面「微服务」/「数据库」,新建名为“order”的数据库。
  • 选择“模式”按钮,选择“列源码”,将如下列源码粘贴进去并确认修改。
[{"type": "char(45)","name": "userId","default": "''","options": [{"name": "not null","value": true,"description": "不为空"}, {"name": "unique","value": false,"description": "不重复"}]
}, {"type": "char(45)","name": "deviceId","default": "''","options": [{"name": "not null","value": true,"description": "不为空"}, {"name": "unique","value": false,"description": "不重复"}]
}, {"type": "char(128)","name": "outTradeNo","default": "''","options": [{"name": "not null","value": false,"description": "不为空"}, {"name": "unique","value": false,"description": "不重复"}]
}, {"type": "tinyint","name": "payType","default": "1","options": [{"name": "not null","value": false,"description": "不为空"}, {"name": "unique","value": false,"description": "不重复"}, {"name": "unsigned","value": false,"description": "无符号"}]
}, {"type": "int","name": "price","default": "","options": [{"name": "not null","value": false,"description": "不为空"}, {"name": "unique","value": false,"description": "不重复"}, {"name": "unsigned","value": false,"description": "无符号"}]
}, {"type": "int","name": "realPrice","default": "","options": [{"name": "not null","value": false,"description": "不为空"}, {"name": "unique","value": false,"description": "不重复"}, {"name": "unsigned","value": false,"description": "无符号"}]
}, {"type": "char(128)","name": "notifyUrl","default": "''","options": [{"name": "not null","value": false,"description": "不为空"}, {"name": "unique","value": false,"description": "不重复"}]
}, {"type": "char(128)","name": "qrCode","default": "''","options": [{"name": "not null","value": false,"description": "不为空"}, {"name": "unique","value": false,"description": "不重复"}]
}, {"type": "tinyint","name": "status","default": "0","options": [{"name": "not null","value": false,"description": "不为空"}, {"name": "unique","value": false,"description": "不重复"}, {"name": "unsigned","value": false,"description": "无符号"}]
}, {"type": "timestamp","name": "time","default": "CURRENT_TIMESTAMP","options": [{"name": "not null","value": false,"description": "不为空"}, {"name": "unique","value": false,"description": "不重复"}]
}]
  • 选择“索引”按钮,选择“索引源码”,将如下列源码粘贴进去并确认修改。
[{"indexName": "userId","columnsName": "userId"
}, {"indexName": "deviceId","columnsName": "deviceId"
}]

创建二维码录入服务

用于开发者录入价格二维码。

  • 打开web页面「微服务」/「业务处理」,新建名为“上传价格”的服务,选择”add_price”脚本。
  • 选择“参数”按钮,选择“参数源码”,将如下参数源码粘贴进去并确认修改。
[{"name": "支付类型","id": "payType","type": "select","defaultValue": "微信:1,支付宝:2","description": ""
}, {"name": "价格","id": "price","type": "float","defaultValue": "","description": ""
}, {"name": "设备","id": "deviceId","type": "select","defaultValue": "{\"scriptName\":\"common\",\"functionName\":\"getDevice\"}","description": ""
}, {"name": "二维码图片","id": "file","type": "file","defaultValue": "","description": ""
}]

创建价格查询服务

用于开发者查询已经录入的价格二维码信息。

  • 打开web页面「微服务」/「数据查询服务」,新建名为“查询价格”的服务,选择”query_price”脚本。
  • 选择“查询参数”按钮,选择“参数源码”,将如下参数源码粘贴进去并确认修改。
[{"name": "支付类型","id": "query_type","type": "select","defaultValue": "微信:1,支付宝:2","description": ""
}]
  • 选择“列”按钮,选择“列源码”,将如下列源码粘贴进去并确认修改。
[{"name": "支付类型","id": "payType"
}, {"name": "价格","id": "price"
}, {"name": "设备ID","id": "deviceId"
}, {"name": "二维码","id": "qrCode"
}]
  • 选择“数据操作”按钮,选择“操作源码”,将如下操作源码粘贴进去并确认修改。
[{"name": "删除","id": "delete","scriptId": "5","scriptName": "common","functionName": "deletePrice"
}]

创建订单查询服务

用于开发者查询历史订单信息。

  • 打开web页面「微服务」/「数据查询服务」,新建名为“查询订单”的服务,选择”query_order”脚本。
  • 选择“查询参数”按钮,选择“参数源码”,将如下参数源码粘贴进去并确认修改。
[{"name": "设备","id": "deviceId","type": "select","defaultValue": "{\"scriptName\":\"common\",\"functionName\":\"getDevice\", \"params\":[true]}\t","description": ""
}]
  • 选择“列”按钮,选择“列源码”,将如下列源码粘贴进去并确认修改。
[{"name": "设备","id": "deviceId"
}, {"name": "交易NO","id": "outTradeNo"
}, {"name": "支付类型","id": "payType"
}, {"name": "价格","id": "price"
}, {"name": "支付价格","id": "realPrice"
}, {"name": "状态","id": "status"
}, {"name": "时间","id": "time"
}]
  • 选择“数据操作”按钮,选择“操作源码”,将如下操作源码粘贴进去并确认修改。
[{"name": "删除","id": "delete","scriptId": "5","scriptName": "common","functionName": "deleteOrder"
}]

启动手机端程序

打开手机端「冰狐智能辅助」APP,点击“点击这里启动设备”启动设备。

上传微信支付二维码

  • 打开web页面「微服务」/「数据录入服务」,找到“上传价格”服务,然后点击“执行”,在弹出的对话框中填入数据、上传微信的支付二维码图片,最后点击“执行”。
  • 打开web页面「微服务」/「数据查询服务」,找到“查询价格”服务,然后点击“查询“按钮查询已经上传的价格二维码。

支付测试

  • 用postman模拟第三方后端服务调用接口,生成订单。 
    https://aznfz.com/api/call_micro_service?clientKey=xxxxx&accessToken=yyyyy&name=unified_order&isDev=true&params=zzz,注意:params必须encodeUriComponent否则无法成功,下图中[1, 0.5, 'xxxxxxxx1', 'https://baidu.com']为原始参数,%5B1%2C%200.5%2C%20'xxxxxxxx1'%2C%20'https%3A%2F%2Fbaidu.com'%5D为encodeUriComponent后的参数(在params行点击右键选择“encodeUriComponent”)。详细请参考文档:冰狐智能辅助
  • 调用后就生成了对应的支付订单,可在「微服务」/「数据查询服务」,“订单查询”服务中,点击“查询”按钮查询订单。
  • 用其他微信向收款微信支付一笔费用,完成后,再次查询订单,看看是否完成。

总结

本文介绍了一种基于「冰狐智能辅助」系统实现的、不需了解Andriod、不需了解后端开发、甚至不需要编写一行代码、免费的、个人免签支付方案和具体实现细节。有任何问题,欢迎评论留言,大家一起讨论

快速实现一个真正的免费个人免签支付相关推荐

  1. 如何快速搭建一个免费的,无限流量的Blog

    转载自   如何快速搭建一个免费的,无限流量的Blog 喜欢写Blog的人,会经历三个阶段. 第一阶段,刚接触Blog,觉得很新鲜,试着选择一个免费空间来写. 第二阶段,发现免费空间限制太多,就自己购 ...

  2. Python基础入门教程:使用 Python 3 协程快速获得一个代理池

    Python基础入门教程:使用 Python 3 协程快速获得一个代理池 前言 在执行 IO 密集型任务的时候,程序会因为等待 IO 而阻塞.比如我们使用 requests 库来进行网络爬虫请求的话, ...

  3. 如何快速开发一个 Dubbo 应用?(含沙龙报名)

    阿里妹导读:在分布式系统中,远程调用是最基础也是最重要的基石.历史上,曾经先后出现过 CORBA.RMI.EJB.WebService 等技术和规范,在服务化以及微服务日趋流行的今天,更多的被广泛使用 ...

  4. 如何快速部署一个Elasticsearch集群?

    作者:无敌码农 来源:无敌码农 今天的文章给大家介绍下Elasticsearch这一目前在"搜索"和"分析"领域使用十分广泛的技术组件.并演示如何快速构建一个E ...

  5. 如何在Linux开启HTTP服务,小技巧:如何快速开启一个静态 HTTP 服务?

    静态 HTTP 服务的几个用途: 静态网页的 HTTP 服务,以访问浏览 如:生成的文档.博客等 公开文件的 HTTP 服务,以访问下载 如:分享的文档.安装包等 以下会介绍目前我了解的方式中,最推荐 ...

  6. 如何快速搭建一个属于自己的网站?

    随着互联网的发展,网站建设的技术也越来越成熟,建站的方式也愈加丰富和多样.同时,互联网时代,无论是组织还是个人,无论是大企业还是小社团,拥有一个属于自己的网站,必不可少. 可是,不同的组织.不同的人, ...

  7. 利用GitHub搭建一个酷炫免费的个人博客

    转载自公众号:python_shequ 由于公众号的文章不易后续整理阅读,于是小吴昨天上午花了半个小时使用 GitHub + Hexo 搭建了一下个人博客,打算将公众号的文章搬过去,支持关键字搜索.分 ...

  8. ChatGPT 使用 拓展资料:使用 HuggingFace+Gradio 部署快速搭建一个ChatGPT的聊天界面

    ChatGPT 使用 拓展资料:使用 HuggingFace+Gradio 部署快速搭建一个ChatGPT的聊天界面 聊天界面链接 https://huggingface.co/spaces/duan ...

  9. 干货!手把手教你如何快速了解一个行业--游戏产业概况

    自己做游戏,但从来没深入了解过游戏行业.最近想了解一下游戏行业的东西,但是又了解不多,所以在知乎看了一些文章.觉得只有理论没用,关键还是要实践,于是一边学,一边看,一边记录.顺便把整个过程分享出来给大 ...

最新文章

  1. [转载] 七龙珠第一部——第035话 北方女孩
  2. appium适用场景
  3. 《C语言深度解剖》学习笔记之符号
  4. 18、java中的泛型
  5. 一般用css设置中文字体的Unicode编码
  6. 深入理解Java main方法
  7. 原型 / 构造函数 / 实例/原型链
  8. 二、CSS基础(1)
  9. 求解偏微分方程开源有限元软件deal.II学习--Step 37
  10. 欠阿里云 1 分钱,数据被删除
  11. 关于AD7124的应用
  12. 向网页中插入透明Flash的方法和技巧
  13. android课设会议室预约系统,教室及会议室预约系统(C#小程序,课堂作业)
  14. Java在手机平台上的Porting
  15. 小数保留两位小数,第三位四舍五入
  16. 如何在office2016(word2016)中安装mathtype6.9及相关问题解决方案
  17. ReactiveUI 入门
  18. 自定义SeekBar实现实现进度提示随thum移动
  19. 企业微信机器人发送消息
  20. 使用matlab深度学习工具箱实现CNN卷积神经网络训练仿真

热门文章

  1. IDEA工具栏tools新增Push按钮(其他类推)
  2. PXI/PXIe控制器 4Link架构 16GB带宽 兼容主流PXIe机箱 设计文件!!! 原理图PCB
  3. 2022.5.7 腾讯天美暑期实习(更新中)
  4. 数据管理解决方案 | 零售行业如何搭建全渠道大数据平台?
  5. 高德地图js点击标记放大地图的操作
  6. 阿里云CentOS 安装 Nginx
  7. python写的平行四边形_python 已知平行四边形三个点,求第四个点的案例
  8. Exception UserExistException is not compatible with throws clause in UserService.findUserByName(Stri
  9. 微信小程序服务商模式支付巨坑解决!
  10. ESP32 ESP-IDF 项目文件结构