小程序云开发搜索功能的实现正则_码code | 如何借助小程序云开发实现小程序支付功能...

转载来源:编程小石头

我们在做小程序支付相关的开发时,总会遇到这些难题。小程序调用微信支付时,必须要有自己的服务器,有自己的备案域名,有自己的后台开发。这就导致我们做小程序支付时的成本很大。

本节就来教大家如何使用小程序·云开发实现小程序支付功能的开发。不用搭建自己的服务器,不用有自己的备案域名。只需要简简单单的使用小程序·云开发。

64e8adb3db8e50f4ae935c2bc042710f.gif

(小程序支付效果图)

本节知识点

1,云开发的部署和使用
2,支付相关的云函数开发
3,商品列表
4,订单列表
5,微信支付与支付成功回调

下面就来教大家如何借助云开发使用小程序支付功能。

支付所需要用到的配置信息

1,小程序appid
2,云开发环境id
3,微信商户号
4,商户密匙

准备工作

1,已经申请小程序,获取小程序 AppID 和 Secret 在小程序管理后台中,【设置】 →【开发设置】 下可以获取微信小程序 AppID 和 Secret。

aa40d757702c254b8e186fbfcd7a1293.png

2,微信支付商户号在微信支付商户管理平台中获取商户号和商户密钥。

【账户中心】→【商户信息】 下可以获取微信支付商户号。

c5fe5df5956df61abdb7b253952a4981.png

在【账户中心】 ‒> 【API安全】 下可以设置商户密钥。

5df6a87e2ef0dc0aeea87d6054599dd0.png

这里特殊说明下,个人小程序是没有办法使用微信支付的。所以如果想使用微信支付功能,必须是非个人账号(当然个人可以办个体户工商执照来注册非个人小程序账号)

3,微信开发者 IDE

 https://developers.weixin.qq.com/miniprogram/dev/devtools/download.html

4,开通小程序云开发功能

https://edu.csdn.net/course/play/9604/204526

商品列表的实现

效果图如下,由于本节重点是支付的实现,所以这里只简单贴出关键代码。

8ff4e323d51988025ddb222dbf691864.png

wxml布局如下:

class="container">

 class="good-item" wx:for="{{goods}}" wx:key="*this" ontap="getDetail" data-goodid="{{item._id}}">

   class="good-image">

     "{{pic}}">

   class="good-detail">

     class="title">商品: {{item.name}}

     class="content">价格:{{item.price / 100}} 元

       class="button"

       type="primary"

       bindtap="makeOrder"

       data-goodid="{{item._id}}"

     >下单

 </view>view>

我们所需要做的就是借助云开发获取云数据库里的商品信息,然后展示到商品列表,关于云开发获取商品列表并展示本节不做讲解。

9c4b563e87772bcbf12f2724d1d35096.png

支付云函数的创建

首先看下我们支付云函数都包含哪些内容:

a57923389ef2620e62f7f71c23ae80dd.png

简单先讲解下每个的用处:

  • config下的index.js是做支付配置用的,主要配置支付相关的账号信息

  • lib是用的第三方的支付库,这里不做讲解。

  • 重点讲解的是云函数入口 index.js

下面就来教大家如何去配置:

1,配置config下的index.js,
这一步所需要做的就是把小程序appid,云开发环境ID,商户id,商户密匙。填进去。

41698878e8c47f99711040ccc5aa9b44.png

2,配置入口云函数

6e76f9ebb471ff5ebd54e93e675b83af.png

详细代码如下,代码里注释很清除了,这里不再做单独讲解:

const cloud = require('wx-server-sdk')

cloud.init()const app = require('tcb-admin-node');const pay = require('./lib/pay');const {

mpAppId,

KEY

} = require('./config/index');const {

WXPayConstants,

WXPayUtil

} = require('wx-js-utils');const Res = require('./lib/res');const ip = require('ip');/**

*

* @param {obj} event

* @param {string} event.type 功能类型

* @param {} userInfo.openId 用户的openid

*/exports.main = async function(event, context) { const {

 type,

 data,

 userInfo

} = event; const wxContext = cloud.getWXContext() const openid = userInfo.openId;

app.init(); const db = app.database(); const goodCollection = db.collection('goods'); const orderCollection = db.collection('order'); // 订单文档的status 0 未支付 1 已支付 2 已关闭

switch (type) {  // [在此处放置 unifiedorder 的相关代码]

 case 'unifiedorder':

  {    // 查询该商品 ID 是否存在于数据库中,并将数据提取出来

   const goodId = data.goodId    let goods = await goodCollection.doc(goodId).get();    if (!goods.data.length) {     return new Res({      code: 1,      message: '找不到商品'

    });

   }    // 在云函数中提取数据,包括名称、价格才更合理安全,

   // 因为从端里传过来的商品数据都是不可靠的

   let good = goods.data[0];    // 拼凑微信支付统一下单的参数

   const curTime = Date.now();    const tradeNo = `${goodId}-${curTime}`;    const body = good.name;    const spbill_create_ip = ip.address() || '127.0.0.1';    // 云函数暂不支付 http 触发器,因此这里回调 notify_url 可以先随便填。

   const notify_url = 'http://www.qq.com'; //'127.0.0.1';

   const total_fee = good.price;    const time_stamp = '' + Math.ceil(Date.now() / 1000);    const out_trade_no = `${tradeNo}`;    const sign_type = WXPayConstants.SIGN_TYPE_MD5;    let orderParam = {

    body,

    spbill_create_ip,

    notify_url,

    out_trade_no,

    total_fee,

    openid,     trade_type: 'JSAPI',     timeStamp: time_stamp,

   };    // 调用 wx-js-utils 中的统一下单方法

   const {

    return_code,

    ...restData

   } = await pay.unifiedOrder(orderParam);    let order_id = null;    if (return_code === 'SUCCESS' && restData.result_code === 'SUCCESS') {     const {

     prepay_id,

     nonce_str

    } = restData;     // 微信小程序支付要单独进地签名,并返回给小程序端

    const sign = WXPayUtil.generateSignature({      appId: mpAppId,      nonceStr: nonce_str,      package: `prepay_id=${prepay_id}`,      signType: 'MD5',      timeStamp: time_stamp

    }, KEY);     let orderData = {

     out_trade_no,

     time_stamp,

     nonce_str,

     sign,

     sign_type,

     body,

     total_fee,

     prepay_id,

     sign,      status: 0, // 订单文档的status 0 未支付 1 已支付 2 已关闭

     _openid: openid,

    };     let order = await orderCollection.add(orderData);

    order_id = order.id;

   }    return new Res({     code: return_code === 'SUCCESS' ? 0 : 1,     data: {

     out_trade_no,

     time_stamp,

     order_id,

     ...restData

    }

   });

  }   // [在此处放置 payorder 的相关代码]

 case 'payorder':

  {    // 从端里出来相关的订单相信

   const {

    out_trade_no,

    prepay_id,

    body,

    total_fee

   } = data;    // 到微信支付侧查询是否存在该订单,并查询订单状态,看看是否已经支付成功了。

   const {

    return_code,

    ...restData

   } = await pay.orderQuery({

    out_trade_no

   });    // 若订单存在并支付成功,则开始处理支付

   if (restData.trade_state === 'SUCCESS') {     let result = await orderCollection

     .where({

      out_trade_no

     })

     .update({       status: 1,       trade_state: restData.trade_state,       trade_state_desc: restData.trade_state_desc

     });     let curDate = new Date();     let time = `${curDate.getFullYear()}-${curDate.getMonth() +          1}-${curDate.getDate()} ${curDate.getHours()}:${curDate.getMinutes()}:${curDate.getSeconds()}`;

   }    return new Res({     code: return_code === 'SUCCESS' ? 0 : 1,     data: restData

   });

  }  case 'orderquery':

  {    const {

    transaction_id,

    out_trade_no

   } = data;    // 查询订单

   const {     data: dbData

   } = await orderCollection

   .where({

    out_trade_no

   })

   .get();    const {

    return_code,

    ...restData

   } = await pay.orderQuery({

    transaction_id,

    out_trade_no

   });    return new Res({     code: return_code === 'SUCCESS' ? 0 : 1,     data: { ...restData,

     ...dbData[0]

    }

   });

  }  case 'closeorder':

  {    // 关闭订单

   const {

    out_trade_no

   } = data;    const {

    return_code,

    ...restData

   } = await pay.closeOrder({

    out_trade_no

   });    if (return_code === 'SUCCESS' &&

    restData.result_code === 'SUCCESS') {     await orderCollection

     .where({

      out_trade_no

     })

     .update({       status: 2,       trade_state: 'CLOSED',       trade_state_desc: '订单已关闭'

     });

   }    return new Res({     code: return_code === 'SUCCESS' ? 0 : 1,     data: restData

   });

  }

}

}

其实我们支付的关键功能都在上面这些代码里面了。

71ba75c9ce79bbd7321b3773b65c3a8a.png

再来看下,支付的相关流程截图:

287fda7cb6a66d31e2eb2c63a04ddbc6.png

上图就涉及到了我们的订单列表,支付状态,支付成功后的回调。其实支付的其他功能,比如支付成功后的消息推送也是可以借助云开发实现的,欢迎大家自己动手去尝试。

如果你想学习小程序·云开发,欢迎扫码进群,这周四晚将进行《小程序·云开发实战:从0到1快速开发电商小程序》的直播课程分享。

321a514d78bedd1177d60ab13a944f39.png

推荐阅读:

2768777b23894463de958ccd6c496a77.png

f0858ed74097486d49bc9825d2f86cb8.png

2f7263e41bc2c538b3ebe84f22f72ad6.gif

17b0e62437140d6547cb17576053e96d.gif

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

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

相关文章

python接口自动化(二十五)--unittest断言——下(详解)

简介 本篇还是回归到我们最初始的话题&#xff0c;想必大家都忘记了&#xff0c;没关系看这里&#xff1a;传送门 没错最初的话题就是登录&#xff0c;由于博客园的登录机制改变了&#xff0c;本篇以我找到的开源免费的登录API为案例&#xff0c;结合 unittest 框架写 2 个用例…

mysql-bin磁盘满数据库重启不_liunx磁盘空间满了,导致mysql数据库无法启动

如何启动/遏制/重启MySQLA、1、启动圆式1、哄骗 service 启动&#xff1a;service mysqld start2、哄骗 mysqld 脚本启动&#xff1a;/etc/inint.d/mysqld start3、哄骗 safe_mysqld 启动&#xff1a;safe_mysqld&二、遏制1、哄骗 service 启动&#xff1a;service mysqld …

[导入]C# Tips 2 右键单击listBox时弹出右键菜单并选中单击的行

C#,Listbox,右键,菜单,选中文章来源:http://blog.csdn.net/geyunfei_hit/archive/2008/07/16/2661153.aspx 转载于:https://www.cnblogs.com/geyunfei/archive/2008/10/08/1306335.html

python真的可以减少工作强度_用Python写几行代码,一分钟搞定一天工作量,同事直呼:好家伙!...

前几天有一个读者说最近要整理几千份文件&#xff0c;头都要整秃了&#xff0c;不知道能不能用Python解决&#xff0c;我们来看一下&#xff0c;你也可以思考一下。由于涉及文件私密所以具体内容已做脱敏处理。大概是这样&#xff0c;一个文件夹下有多份会议通知信息(本文以 7 …

Jmeter之逻辑控制器(Logic Controller)

一、简单控制器&#xff08;Simple Controller&#xff09;&#xff1a; 作用&#xff1a;这是Jmeter里最简单的一个控制器&#xff0c;它可以让我们组织我们的采样器和其它的逻辑控制器&#xff08;分组功能&#xff09;&#xff0c;提供一个块的结构和控制&#xff0c;并不具…

python需要掌握的词汇量_北大保安英语词汇量1.5万,会用Python编程,孟母三迁真有道理...

这就是良好学习环境的重要性啊&#xff0c;不然你以为“孟母三迁”是咋来的&#xff1f;人家孟母为了孩子有个好的学习环境&#xff0c;宁愿搬三次家。而这些保安小哥一步到位&#xff0c;直接就进入了无数人梦寐以求的最高学府&#xff0c;想不牛都不行啊。01、北大是最高学府…

Visual Studio Team System 2008 安装失败

微软的东西 看样子也没怎么测试就发布了。。。 [10/27/08,23:05:56] Microsoft .NET Framework 3.5: [2] Error code 1603 for this component means "安装时发生严重错误"[10/27/08,23:05:58] Microsoft .NET Framework 3.5: [2] Setup Failed on component Microso…

【题解】序列

题目描述 一个长度为k的整数序列b1&#xff0c;b2&#xff0c;...&#xff0c;bk&#xff08;1≤b1≤b2≤...≤bk≤N&#xff09;称为“好序列”当且仅当后一个数是前一个数的倍数&#xff0c;即bi1是bi的倍数对任意的i&#xff08;1≤i≤k-1&#xff09;成立。 给定N和k&#…

Struts2 文件上传

JSP界面&#xff1a; 必须把表单的enctype属性改为 multipart/form-data才能上传 Action&#xff1a; 程序如果多人使用&#xff0c;必须保证文件名是唯一&#xff0c;文件名相同会覆盖掉原来的文件&#xff0c;所以使用时间作为文件名。可以把生成的文件名直接存入数据库中&am…

看新闻的时间用的太多了

也不知从什么时候开始习惯每天看新闻,好像有五六年的习惯了,只是现在每天看新闻的时间用的太多了(每天都至少5-6小时),而且越来越严重了,除了看新闻,基本只剩下工作和睡觉时间了.cctv2,央视新闻频道,第一财经每天必看,新浪,搜狐,凤凰网,时寒冰,牛刀等等,从时事,到经济,到体育,到…

第五章学习小结

第5章学习树和二叉树 树 1.树的结构定义是一个递归定义&#xff1a;树的定义中又用到树的定义 2.结点的度即为结点的分支数&#xff0c;树的度是树内各结点度的最大值&#xff0c;二叉树每个结点至多只有两颗子树&#xff08;即二叉树中不存在度大于2的结点&#xff09; 二叉树…

[html] 浏览器内多个标签页之间的通信方式有哪些?

[html] 浏览器内多个标签页之间的通信方式有哪些&#xff1f; 个人简介 我是歌谣&#xff0c;欢迎和大家一起交流前后端知识。放弃很容易&#xff0c; 但坚持一定很酷。欢迎大家一起讨论 主目录 与歌谣一起通关前端面试题

java 优酷视频缩略图_java获取优酷等视频缩略图

类型&#xff1a;Android平台大小&#xff1a;6.8M语言&#xff1a;中文 评分&#xff1a;7.2标签&#xff1a;立即下载想获取优酷等视频缩略图&#xff0c;在网上没有找到满意的资料&#xff0c;参考了huangdijia的PHP版工具一些思路&#xff0c;写了下面的JAVA版代码。。其实…

java篇 之 变量存放位置

一&#xff1a;在方法中声明的变量&#xff0c;即该变量是局部变量&#xff0c;每当程序调用方法时&#xff0c;系统都会为该方法建立一个方法栈&#xff0c;其所在方法中声明的变量就放在方法栈中&#xff0c;当方法结束系统会释放方法栈&#xff0c;其对应在该方法中声明的变…

import json java_JAVA的JSON数据包装-博客园老牛大讲

标签&#xff1a;一、什么是json呢&#xff1f;{"id":"1","username":"老牛大讲堂","password":"123"}这就是json数据。用来和页面(HTMl)进行通信的。二、通信为什么用json呢&#xff1f;没有为啥&#xff0c;因为…

砂.随笔.二十.微笑

左脑和右脑在争吵 左手和右手在撕扯 左脚和右脚走向两端 撕扯着神经 我想要疯狂地尖叫 但熟悉的人和面孔在对着我微笑 那么弯起嘴角吧 那么眯起眼角吧 那么就这样吧 就只能是这样了 我的尖叫和痛哭掩盖在微笑的面具下慢慢窒息 这样或许是最好的 谁都不知道你们曾经到来过 那么就…

electron-关闭之前,弹出提示窗

tips:写的时候&#xff0c;如果不在弹窗之前调用一次阻止默认事件&#xff0c;窗口就会直接关闭&#xff1b; 对话框dialog 在主进程中调用&#xff0c;const {dialog} require(electron); 传送门&#xff1a;electron dialog对话框 转载于:https://www.cnblogs.com/huangmin1…

进程(二)

import osimport timefrom multiprocessing import Processdef func(args,args2): print(args,args2) time.sleep(3) print(子进程 :, os.getpid()) print(子进程的父进程 :, os.getppid()) print(12345)if __name__ __main__: p Process(targetfunc,args(…

uushare新增类似美味(del.icio.us)的书签服务

书签是用于收藏网址的一种工具&#xff08;又称为网络收藏夹&#xff09;&#xff0c;通过它你可以将常访问的网站或平时发现感兴趣的网址收藏起来。 跟浏览器中的收藏夹不同&#xff0c;书签的优点是可以随时随地收藏大量的网址并且便于管理和寻找&#xff0c;同时不用担心因系…

HttpClient系列~StringContent与FormUrlEncodedContent

知识点 本文是一个很另类的文章&#xff0c;在项目中用的比较少&#xff0c;但如果项目中真的出现了这种情况&#xff0c;我们也需要知道如何去解决&#xff0c;对于知识点StringContent和FormUrlEncodedContent我们应该了解的多一点&#xff0c;FormUrlEncodedContent是以键/值…