转载来源:编程小石头

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

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

(小程序支付效果图)

本节知识点

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

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

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

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

准备工作

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

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

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

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

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

3,微信开发者 IDE

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

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

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

商品列表的实现

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

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>

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

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

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

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

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

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

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

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

2,配置入口云函数

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

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

   });

  }

}

}

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

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

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

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

推荐阅读:

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

  1. 小程序云开发搜索功能的实现正则_几行代码实现小程序云开发提现功能

    先看效果: 纯云开发实现,下面说使用步骤:一:开通商户的企业付款到领取功能说明地址: https://pay.weixin.qq.com/wiki/doc/api/tools/mch_pay.php? ...

  2. 云鲸扫拖一体机器人说明书_让做家务更简单:云鲸智能扫拖一体机器人测评

    ​一.前言 说到提升生活质量的家用电器,扫地机器人排名绝对能数得着,从早期简单清理到现在路径规划.App控制,扫地这件事变得更加智能化,甚至多了点乐趣. 扫地的问题虽然解决了,但是智能拖地却一直是一道 ...

  3. audio 小程序 放大_码code | 小程序新能力释放,人人都能拥有对话机器人

    当用户在小程序内发起对话,你是在后台抓紧安排人工回复吗? 由于等待回复时间过长,用户产生不满并弃用了你的小程序. "秒回"是对话的基本要求,及时回复才能给到用户尊重和被重视感.然而 ...

  4. 码code | 腾讯大佬带你深入理解小游戏的架构设计与开发

    转载来源:云加社区 原作者:余国良 小游戏自发布以来,微信平台上已经出现了不少现象级的小游戏,包括跳一跳.在技术上微信小游戏和小程序的区别是什么?开发商在开发一款小游戏的时候通常会遇到什么问题?怎么去 ...

  5. 安卓开发监听外部蓝牙设备断开_这软件能让你的蓝牙耳机,用上 AirPods 的功能...

    打开这篇文章时,大家可能正佩戴着某款无线蓝牙耳机. 不管是头戴式,颈挂式还是分体式,总之现在无线蓝牙耳机已经跟智能手机一样,成为生活中很常见的随身物品. 但在大家渐渐对无线蓝牙耳机习以为常的时候,有个 ...

  6. 了解c语言程序员(工程师)岗位需要掌握哪些能力?_码畜,码农,码皇,程序员有什么区别?...

    这里是开发者交流聚集地,欢迎加入我们一起技术分享,互相交流! 技术交流群:关注本公众号,点击菜单栏即可获取 很多年轻的程序员可能不太了解,虽然大家看着都是写代码的,但从搬砖的码畜到码农到码皇之路还是挺 ...

  7. 小天才被限定使用时长的应用_家庭腕上社交新场景,OPPO Watch、小天才开启暖心联动...

    说到小天才手表,相信家长朋友们都或多或少的听说过,或者正在给孩子使用.可爱的造型和实用的功能还有亲民的价格,让小天才手表成为青少年智能穿戴领域的热门产品.特别是对于正在上幼儿园和小学阶段的小朋友来说, ...

  8. 开发转测试没人要_入行或转行软件测试(测试开发)要怎么学

    在2008年刚刚进入这个行业时,我对于要学什么东西,是迷茫的.记得我在08年的时候,入职的公司给我们这批新人做了培训.培训中介绍了很多概念,告诉我们质量很重要,软件测试前景很好,还教了我们很多软件测试 ...

  9. 1元云购微信支付功能开发 - 1元云购网站开发

    1元云购是时下比较流行的电子商务模式,1元云购系统现在在网上也比较多,但是大多数的网站建设源码是比较老的版本,要么就是没有微信支付功能,要么就是微信支付功能有缺陷,例如 1.微信支付的账户配置在程序里 ...

最新文章

  1. Oracle EXP-00091解决方法
  2. edem颗粒替换_EDEM后处理问题的大汇总,方便易懂!
  3. python 编程该看那些书籍_初学者自学Python要看什么书?
  4. 中国生物医药行业供需形势透析及未来投资风险评估报告2022-2027年版
  5. 【SIP协议】学习初学笔记
  6. SLVS-EC接口学习
  7. 认证鉴权与API权限控制在微服务架构中的设计与实现(一)
  8. 关于Android的应用程序的发布的学习(一)
  9. java工作中mq应用多吗_RabbitMQ消息中间件在工作中的应用场景
  10. 手机里语音转文字怎么实现的呢?看完你就明白了
  11. Anaconda python安装使用
  12. 修改model,映射到表中
  13. rails java_没有Rails Java程序员如何使用Ruby
  14. 图标字体的优缺点和使用
  15. python读取tsv文件_Python 读写 tsv
  16. 在公众号中通过链接下载APP时,如何不通过应用宝,直接跳浏览器下载?
  17. c语言游戏开发之贪吃蛇
  18. linux编程性能,Linux性能评估工具
  19. 艺龙私有化,携程与腾讯眉来眼去
  20. 统计多个wav文件的总音频时长

热门文章

  1. [html] 写一个布局,当页面滚动一定高时,导航始终固定在顶部,反之恢复原位
  2. 前端学习(2867):vue3数据劫持解析2
  3. [css] 浏览器是怎样判断元素是否和某个CSS选择器匹配?
  4. [css] 说说你对CSS样式覆盖规则的理解
  5. 前端学习(2369):组件的创建使用和组件的生命周期
  6. 前端学习(2024)vue之电商管理系统电商系统之根据分页获取订单列表数据
  7. 前端学习(1392):多人管理项目12加密
  8. 前端学习(1384):多人管理项目4资源的路径
  9. 前端学习(392):京东制作页面1京东项目项目介绍
  10. 第一百一十五期:Web开发必须掌握的三个技术:Token、Cookie、Session