快速实现一个真正的免费个人免签支付

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

基本原理

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

操作流程

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

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

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

4. 用户完成扫码支付。

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

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

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

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

构建移动端

  • 下载「冰狐智能辅助」APP并安装,安装完成后请登录。登录时请按提示打开所有权限,具体下载地址和详细安装配置过程请参考这里
  • 登录网页,打开web页面「移动端」/「移动端脚本」,新建一个名为“个人支付”的脚本,将如下JS脚本粘贴到这里并保存。

    
    
  1. function main( ) {
  2. while ( true) {
  3. }
  4. }
  5. function cbNotification( textList, className, packageName, event) {
  6. for ( var item of textList) {
  7. if (item. includes( '微信支付')) {
  8. var arr = item. fetchNumber();
  9. if (arr. length > 0) {
  10. var ret = callMicroService( 'pay_notify', [rsUUID, 1, arr[arr. length - 1]]);
  11. console. log( 'call ret:' + ret);
  12. }
  13. return true;
  14. }
  15. }
  16. return false;
  17. }
  • 打开web页面「移动端」/「我的设备」,找到刚才登录的手机,然后选择“编辑”按钮,修改“默认脚本”为上面新建的“个人支付”脚本。

创建微服务脚本

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

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

  • pay_notify,用于处理支付信息,并通知开发者支付结果。JS源码如下:

    
    
  1. function main( uuid, type, price) {
  2. var ret = false;
  3. price = parseInt(price* 100);
  4. var key = uuid + price;
  5. var orderId = cacheGet(key);
  6. if (orderId) {
  7. console. log( '匹配到价格,可以通知了:' + orderId);
  8. var data = dbQuery( 'order', '*', [ 'id=' + orderId]);
  9. if (data && data. length == 1) {
  10. var item = data[ 0];
  11. // 通知 调用者
  12. var bodyParams = { outTradeNo: item. outTradeNo, price: item. price / 100.0, realPrice: item. realPrice / 100.0};
  13. var result = 2, postResult = httpPost(item. notifyUrl, bodyParams);
  14. if (postResult && postResult. length > 0) {
  15. if (postResult. status == 200 || postResult. status == 302) {
  16. result = 1;
  17. }
  18. }
  19. // change status
  20. ret = dbUpdate( 'order', [ 'status=' + result], [ 'id=' + orderId]);
  21. if (!ret) {
  22. console. error( '更新状态失败');
  23. }
  24. cacheRemove(key);
  25. }
  26. } else {
  27. console. error( 'invalidate price:' + price);
  28. }
  29. return ret;
  30. }
  • add_price,用于添加支付二维码,JS源码如下:

    
    
  1. function main( payType, price, deviceId, file) {
  2. price = parseInt(price* 100);
  3. var ret = false, qrCode = qrDecode(file. inputStream);
  4. if (qrCode != '') {
  5. var qRet = dbQuery( 'price', 'count(id) as count', [ `userId='${rsOpenId}'`, `price=${price}`, `payType=${payType}`, `deviceId='${deviceId}'`]);
  6. if (qRet[ 0]. count > 0) {
  7. ret = dbUpdate( 'price', [ `qrCode='${qrCode}'`], [ `price=${price}`, `payType=${payType}`, `deviceId='${deviceId}'`]);
  8. } else {
  9. var iRet = dbInsert( 'price', { userId:rsOpenId, price:price, payType:payType, deviceId:deviceId, qrCode:qrCode});
  10. ret = iRet > 0;
  11. }
  12. }
  13. return ret;
  14. }
  • query_price,用于查询支付二维码,JS源码如下:

    
    
  1. function main( fetchCountOnly, conditions, startIndex, itemCount) {
  2. var jsonConditions = JSON. parse(conditions), params = [ `userId='${rsOpenId}'`];
  3. for ( var item of jsonConditions) {
  4. if (item. name == 'query_type') {
  5. var type = parseInt(item. value);
  6. if ( type > 0) {
  7. params. push( 'payType=' + type);
  8. }
  9. }
  10. }
  11. if (fetchCountOnly) {
  12. var qRet = dbQuery( 'price', 'count(id) as count', params);
  13. return qRet[ 0]. count;
  14. } else {
  15. var qRet = dbQuery( 'price', '*', params, '', startIndex, itemCount);
  16. for ( var item of qRet) {
  17. item. price /= 100.0;
  18. if (item. payType == 1) {
  19. item. payType = '微信';
  20. } else {
  21. item. payType = '支付宝';
  22. }
  23. }
  24. return qRet;
  25. }
  26. }
  • query_order,用于查询订单,JS源码如下:
    
         
         
    1. function main (fetchCountOnly, conditions, startIndex, itemCount) {
    2. var jsonConditions = JSON.parse(conditions);
    3. var params = [`userId= '${rsOpenId}'`];
    4. for ( var item of jsonConditions) {
    5. var deviceId = item.value;
    6. if (item.name == 'deviceId' && deviceId != '') {
    7. params.push(`deviceId= '${deviceId}'`);
    8. }
    9. }
    10. if (fetchCountOnly) {
    11. var qRet = dbQuery( 'order', 'count(id) as count', params);
    12. return qRet[ 0].count;
    13. } else {
    14. var qRet = dbQuery( 'order', '*', params, 'order by time desc', startIndex, itemCount);
    15. for ( var item of qRet) {
    16. item.price /= 100.0;
    17. item.realPrice /= 100.0;
    18. if (item.payType == 1) {
    19. item.payType = '微信';
    20. } else {
    21. item.payType = '支付宝';
    22. }
    23. if (item.status == 0) {
    24. item.status = '等待支付';
    25. } else if (item.status == 1) {
    26. item.status = '交易完成';
    27. } else if (item.status == 2) {
    28. item.status = '通知失败';
    29. } else if (item.status == - 1) {
    30. item.status = '订单过期';
    31. }
    32. var datetime = new Date();
    33. datetime.setTime(item.time);
    34. var year = datetime.getYear();
    35. var month = datetime.getMonth() + 1 < 10 ? "0" + (datetime.getMonth() + 1) : datetime.getMonth() + 1;
    36. var date = datetime.getDate() < 10 ? "0" + datetime.getDate() : datetime.getDate();
    37. var hour = datetime.getHours()< 10 ? "0" + datetime.getHours() : datetime.getHours();
    38. var minute = datetime.getMinutes()< 10 ? "0" + datetime.getMinutes() : datetime.getMinutes();
    39. var second = datetime.getSeconds()< 10 ? "0" + datetime.getSeconds() : datetime.getSeconds();
    40. var t = year + "-" + month + "-" + date+ " "+hour+ ":"+minute+ ":"+second;
    41. item.time = t;
    42. }
    43. return qRet;
    44. }
    45. }

  • unified_order,用于开发者请求支付,返回支付二维码,JS源码如下:

    
    
  1. function main( payType, price, outTradeNo, notifyUrl, timeout = 120000) {
  2. price = parseInt(price* 100);
  3. var ret = null, qrImage = '', realPrice = price;
  4. var maxCount = 5, i = 0, anyRet = null, findAny = false;
  5. while (i < maxCount) {
  6. realPrice = price - i;
  7. var qRet = dbQuery( 'price', '*', [ `userId='${rsOpenId}'`, `payType=${payType}`, `price=${realPrice}`]);
  8. if (qRet. length <= 0) {
  9. if (!findAny) {
  10. anyRet = dbQuery( 'price', '*', [ `userId='${rsOpenId}'`, `payType=${payType}`, 'price=0']);
  11. findAny = true;
  12. }
  13. qRet = anyRet;
  14. }
  15. if (qRet. length > 0) {
  16. for ( var item of qRet) {
  17. var key = item. deviceId + realPrice;
  18. var cache = cacheGet(key);
  19. if ( null == cache) {
  20. lock( 'malloc_price');
  21. cache = cacheGet(key);
  22. if ( null == cache) {
  23. // 可以分配了
  24. ret = dbInsert( 'order', {
  25. userId: rsOpenId,
  26. price: price,
  27. realPrice: realPrice,
  28. outTradeNo: outTradeNo,
  29. deviceId: item. deviceId,
  30. qrCode: item. qrCode,
  31. notifyUrl: notifyUrl
  32. });
  33. }
  34. if ( null != ret) {
  35. var image = qrEncode(item. qrCode);
  36. qrImage = base64Encode(image);
  37. cachePut(key, ret, 60000);
  38. }
  39. unlock( 'malloc_price');
  40. if ( null != ret) {
  41. break;
  42. }
  43. }
  44. }
  45. }
  46. if ( null != ret) {
  47. break;
  48. }
  49. ++i;
  50. }
  51. if ( null == ret) {
  52. console. error( 'unified failed');
  53. } else {
  54. return { payTye: payType, price: price, realPrice: realPrice, qrImageData: qrImage, timeout: timeout};
  55. }
  56. return {};
  57. }
  • common,一些通用的函数,JS源码如下:

    
    
  1. function deletePrice( item) {
  2. var id = item. id;
  3. return dbDelete( 'price', [ `id=${id}`]);
  4. }
  5. function deleteOrder( item) {
  6. var id = item. id;
  7. return dbDelete( 'order', [ `id=${id}`]);
  8. }
  9. function getDevice( includeAll=false) {
  10. var list = deviceList(rsOpenId);
  11. var result = [];
  12. if (includeAll) {
  13. result. push({ name: '全部', value: ''});
  14. }
  15. for ( var item of list) {
  16. result. push({ name: item. name, value: item. uuid});
  17. }
  18. return result;
  19. }

创建移动端接口

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

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

创建服务端接口

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

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

创建二维码价格数据库

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

  • 打开web页面「微服务」/「数据库」,新建名为“price”的数据库。
  • 选择“模式” / “列源码”按钮,将如下列源码粘贴进去并确认修改。

    
    
  1. [{
  2. "type": "tinyint",
  3. "name": "payType",
  4. "default": "1",
  5. "options": [{
  6. "name": "not null",
  7. "value": false,
  8. "description": "不为空"
  9. }, {
  10. "name": "unique",
  11. "value": false,
  12. "description": "不重复"
  13. }, {
  14. "name": "unsigned",
  15. "value": false,
  16. "description": "无符号"
  17. }]
  18. }, {
  19. "type": "varchar(45)",
  20. "name": "deviceId",
  21. "default": "''",
  22. "options": [{
  23. "name": "not null",
  24. "value": true,
  25. "description": "不为空"
  26. }, {
  27. "name": "unique",
  28. "value": false,
  29. "description": "不重复"
  30. }]
  31. }, {
  32. "type": "varchar(128)",
  33. "name": "qrCode",
  34. "default": "''",
  35. "options": [{
  36. "name": "not null",
  37. "value": false,
  38. "description": "不为空"
  39. }, {
  40. "name": "unique",
  41. "value": false,
  42. "description": "不重复"
  43. }]
  44. }, {
  45. "type": "int",
  46. "name": "price",
  47. "default": "0",
  48. "options": [{
  49. "name": "not null",
  50. "value": false,
  51. "description": "不为空"
  52. }, {
  53. "name": "unique",
  54. "value": false,
  55. "description": "不重复"
  56. }, {
  57. "name": "unsigned",
  58. "value": false,
  59. "description": "无符号"
  60. }]
  61. }, {
  62. "type": "varchar(45)",
  63. "name": "userId",
  64. "default": "''",
  65. "options": [{
  66. "name": "not null",
  67. "value": true,
  68. "description": "不为空"
  69. }, {
  70. "name": "unique",
  71. "value": false,
  72. "description": "不重复"
  73. }]
  74. },{
  75. "name": "支付类型",
  76. "id": "payType",
  77. "type": "select",
  78. "defaultValue": "微信:1,支付宝:2",
  79. "description": ""
  80. }, {
  81. "name": "价格",
  82. "id": "price",
  83. "type": "float",
  84. "defaultValue": "",
  85. "description": ""
  86. }, {
  87. "name": "设备",
  88. "id": "deviceId",
  89. "type": "select",
  90. "defaultValue": "{\"name\":\"get_device\", \"params\":[], \"isDev\":true}",
  91. "description": ""
  92. }, {
  93. "name": "二维码图片",
  94. "id": "file",
  95. "type": "file",
  96. "defaultValue": "",
  97. "description": ""
  98. }]
  • 选择“索引”按钮,选择“索引源码”,将如下列源码粘贴进去并确认修改。

    
    
  1. [ {
  2. "indexName" : "userId" ,
  3. "columnsName" : "userId"
  4. } ]

创建订单数据库

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

  • 打开web页面「微服务」/「数据库」,新建名为“order”的数据库。
  • 选择“模式”按钮,选择“列源码”,将如下列源码粘贴进去并确认修改。

    
    
  1. [{
  2. "type": "char(45)",
  3. "name": "userId",
  4. "default": "''",
  5. "options": [{
  6. "name": "not null",
  7. "value": true,
  8. "description": "不为空"
  9. }, {
  10. "name": "unique",
  11. "value": false,
  12. "description": "不重复"
  13. }]
  14. }, {
  15. "type": "char(45)",
  16. "name": "deviceId",
  17. "default": "''",
  18. "options": [{
  19. "name": "not null",
  20. "value": true,
  21. "description": "不为空"
  22. }, {
  23. "name": "unique",
  24. "value": false,
  25. "description": "不重复"
  26. }]
  27. }, {
  28. "type": "char(128)",
  29. "name": "outTradeNo",
  30. "default": "''",
  31. "options": [{
  32. "name": "not null",
  33. "value": false,
  34. "description": "不为空"
  35. }, {
  36. "name": "unique",
  37. "value": false,
  38. "description": "不重复"
  39. }]
  40. }, {
  41. "type": "tinyint",
  42. "name": "payType",
  43. "default": "1",
  44. "options": [{
  45. "name": "not null",
  46. "value": false,
  47. "description": "不为空"
  48. }, {
  49. "name": "unique",
  50. "value": false,
  51. "description": "不重复"
  52. }, {
  53. "name": "unsigned",
  54. "value": false,
  55. "description": "无符号"
  56. }]
  57. }, {
  58. "type": "int",
  59. "name": "price",
  60. "default": "",
  61. "options": [{
  62. "name": "not null",
  63. "value": false,
  64. "description": "不为空"
  65. }, {
  66. "name": "unique",
  67. "value": false,
  68. "description": "不重复"
  69. }, {
  70. "name": "unsigned",
  71. "value": false,
  72. "description": "无符号"
  73. }]
  74. }, {
  75. "type": "int",
  76. "name": "realPrice",
  77. "default": "",
  78. "options": [{
  79. "name": "not null",
  80. "value": false,
  81. "description": "不为空"
  82. }, {
  83. "name": "unique",
  84. "value": false,
  85. "description": "不重复"
  86. }, {
  87. "name": "unsigned",
  88. "value": false,
  89. "description": "无符号"
  90. }]
  91. }, {
  92. "type": "char(128)",
  93. "name": "notifyUrl",
  94. "default": "''",
  95. "options": [{
  96. "name": "not null",
  97. "value": false,
  98. "description": "不为空"
  99. }, {
  100. "name": "unique",
  101. "value": false,
  102. "description": "不重复"
  103. }]
  104. }, {
  105. "type": "char(128)",
  106. "name": "qrCode",
  107. "default": "''",
  108. "options": [{
  109. "name": "not null",
  110. "value": false,
  111. "description": "不为空"
  112. }, {
  113. "name": "unique",
  114. "value": false,
  115. "description": "不重复"
  116. }]
  117. }, {
  118. "type": "tinyint",
  119. "name": "status",
  120. "default": "0",
  121. "options": [{
  122. "name": "not null",
  123. "value": false,
  124. "description": "不为空"
  125. }, {
  126. "name": "unique",
  127. "value": false,
  128. "description": "不重复"
  129. }, {
  130. "name": "unsigned",
  131. "value": false,
  132. "description": "无符号"
  133. }]
  134. }, {
  135. "type": "timestamp",
  136. "name": "time",
  137. "default": "CURRENT_TIMESTAMP",
  138. "options": [{
  139. "name": "not null",
  140. "value": false,
  141. "description": "不为空"
  142. }, {
  143. "name": "unique",
  144. "value": false,
  145. "description": "不重复"
  146. }]
  147. }]
  • 选择“索引”按钮,选择“索引源码”,将如下列源码粘贴进去并确认修改。

    
    
  1. [ {
  2. "indexName" : "userId" ,
  3. "columnsName" : "userId"
  4. } , {
  5. "indexName" : "deviceId" ,
  6. "columnsName" : "deviceId"
  7. } ]

创建二维码录入服务

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

  • 打开web页面「微服务」/「数据录入服务」,新建名为“上传价格”的服务,选择”add_price”脚本。
  • 选择“参数”按钮,选择“参数源码”,将如下参数源码粘贴进去并确认修改。

    
    
  1. [{
  2. "name": "支付类型",
  3. "id": "payType",
  4. "type": "select",
  5. "defaultValue": "微信:1,支付宝:2",
  6. "description": ""
  7. }, {
  8. "name": "价格",
  9. "id": "price",
  10. "type": "float",
  11. "defaultValue": "",
  12. "description": ""
  13. }, {
  14. "name": "设备",
  15. "id": "deviceId",
  16. "type": "select",
  17. "defaultValue": "{\"scriptName\":\"common\",\"functionName\":\"getDevice\"}",
  18. "description": ""
  19. }, {
  20. "name": "二维码图片",
  21. "id": "file",
  22. "type": "file",
  23. "defaultValue": "",
  24. "description": ""
  25. }]

创建价格查询服务

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

  • 打开web页面「微服务」/「数据查询服务」,新建名为“查询价格”的服务,选择”query_price”脚本。
  • 选择“查询参数”按钮,选择“参数源码”,将如下参数源码粘贴进去并确认修改。

    
    
  1. [ {
  2. "name" : "支付类型" ,
  3. "id" : "query_type" ,
  4. "type" : "select" ,
  5. "defaultValue" : "微信:1,支付宝:2" ,
  6. "description" : ""
  7. } ]
  • 选择“列”按钮,选择“列源码”,将如下列源码粘贴进去并确认修改。

    
    
  1. [ {
  2. "name" : "支付类型" ,
  3. "id" : "payType"
  4. } , {
  5. "name" : "价格" ,
  6. "id" : "price"
  7. } , {
  8. "name" : "设备ID" ,
  9. "id" : "deviceId"
  10. } , {
  11. "name" : "二维码" ,
  12. "id" : "qrCode"
  13. } ]
  • 选择“数据操作”按钮,选择“操作源码”,将如下操作源码粘贴进去并确认修改。

    
    
  1. [ {
  2. "name" : "删除" ,
  3. "id" : "delete" ,
  4. "scriptId" : "5" ,
  5. "scriptName" : "common" ,
  6. "functionName" : "deletePrice"
  7. } ]

创建订单查询服务

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

  • 打开web页面「微服务」/「数据查询服务」,新建名为“查询订单”的服务,选择”query_order”脚本。
  • 选择“查询参数”按钮,选择“参数源码”,将如下参数源码粘贴进去并确认修改。

    
    
  1. [{
  2. "name": "设备",
  3. "id": "deviceId",
  4. "type": "select",
  5. "defaultValue": "{\"scriptName\":\"common\",\"functionName\":\"getDevice\", \"params\":[true]}\t",
  6. "description": ""
  7. }]
  • 选择“列”按钮,选择“列源码”,将如下列源码粘贴进去并确认修改。

    
    
  1. [ {
  2. "name" : "设备" ,
  3. "id" : "deviceId"
  4. } , {
  5. "name" : "交易NO" ,
  6. "id" : "outTradeNo"
  7. } , {
  8. "name" : "支付类型" ,
  9. "id" : "payType"
  10. } , {
  11. "name" : "价格" ,
  12. "id" : "price"
  13. } , {
  14. "name" : "支付价格" ,
  15. "id" : "realPrice"
  16. } , {
  17. "name" : "状态" ,
  18. "id" : "status"
  19. } , {
  20. "name" : "时间" ,
  21. "id" : "time"
  22. } ]
  • 选择“数据操作”按钮,选择“操作源码”,将如下操作源码粘贴进去并确认修改。

    
    
  1. [ {
  2. "name" : "删除" ,
  3. "id" : "delete" ,
  4. "scriptId" : "5" ,
  5. "scriptName" : "common" ,
  6. "functionName" : "deleteOrder"
  7. } ]

启动手机端程序

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

上传微信支付二维码

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

  • 打开web页面「微服务」/「数据查询服务」,找到“查询价格”服务,然后点击“查询“按钮查询已经上传的价格二维码。

支付测试

  • 用postman模拟第三方后端服务调用接口,生成订单。 
    https://aznfz.com/api/call_micro_service?clientKey=xxxxx&accessToken=yyyyy&name=unified_order&isDev=true&params=zzz,详细请参考文档:冰狐智能辅助
  • 调用后就生成了对应的支付订单,可在「微服务」/「数据查询服务」,“订单查询”服务中,点击“查询”按钮查询订单。

  • 用其他微信向收款微信支付一笔费用,完成后,再次查询订单,看看是否完成。

总结

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

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值