1 В избранное 0 Ответвления 0

OSCHINA-MIRROR/woden-nami-demo-pay

В этом репозитории не указан файл с открытой лицензией (LICENSE). При использовании обратитесь к конкретному описанию проекта и его зависимостям в коде.
Клонировать/Скачать
微信小程序《赞赏》案例实战.MD 12 КБ
Копировать Редактировать Web IDE Исходные данные Просмотреть построчно История
woden Отправлено 22.02.2017 16:00 6afe6a3

微信小程序《赞赏》案例实战

麻雀案例,五脏俱全

写在最前

微信小程序推出以后,笔者在公司内部开过几场小程序开发培训课。出于培训课程需要,笔者以公众号“赞赏”功能作为需求,制作出一个《赞赏》DEMO。本案例涵盖前后端完整设计与代码讲解,其中包括2个小程序前端页面,3个后端JSON接口,涉及到的相关知识要点包括了登录、后端信息获取(AES-128-CBC解密算法)、微信支付、后端数据存储等,是个完整的麻雀案例。 案例借助开源NAMI框架(https://github.com/wodenwang/nami),十分钟即可完成前后端本地部署。

案例效果一览:

运行环境部署

  1. 下载源码:从github获取《赞赏》案例源码(地址:https://github.com/wodenwang/nami-demo-pay),代码分为三部分,分别是:client,server,sql

  2. 前端代码安装:打开微信开发工具,导入源码的client部分。(注意:必须填写appid,否则无法发起支付;勾选“不校验域名与TLS版本”方便本地调试)

  3. 下载NAMI框架(https://github.com/wodenwang/nami):可自行编译,也可以从官方的云盘(http://pan.baidu.com/s/1bJmUtg)直接下载编译完的版本(匹配操作系统,解压即可用)。

  4. 后端代码安装:将《赞赏》案例的server端源码拷贝到NAMI框架中,只需覆盖function与request两个目录即可。

  5. 初始化数据库:双击NAMI的db.bat打开内置数据库控制台,执行sql中的h2.sql建表语句。

  6. 修改NAMI/conf/wx.properties,设置小程序appid,appsecret,小程序支付的密匙、密匙文件路径等。

  7. 好了,运行NAMI的start.bat,然后在微信开发工具中将/nami/config.js中的服务端路径修改成http://localhost:8080,即可运行DEMO。

小程序登录

微信公众平台(包括公众号、小程序)相比APP的一个明显优势,是开发者可以直接利用微信的用户鉴权体系,免去注册、密码登录的步骤。微信小程序对于登录的设计,更是用之于无形,在整个用户使用过程中都是无感知的,一进小程序其实就已经登录了。 也许有读者会说,小程序登录的时候不是会弹出一个用户信息的询问框吗?错了,这个询问框是调用wx.getUserInfo获取“用户资料”时候弹出的,调用wx.login的“登录”操作是不会弹出任何询问框的。

关于微信小程序登录,官方文档的流程实现起来挺不容易的(如下图),需要服务端维护一个保存openid等用户资料的缓存池,同时小程序客户端还需要维护一个3rd session key,并且在之后每次做服务端请求的时候都要带入这个3rd session key。

所幸NAMI框架已经把这块封装好,下面我们用一点篇幅来看看案例是如何做login的。

  1. app.js
import nami from '/nami/index';

App({
  data: {
    userInfo: null,
    rankLoaded: false //排行榜已加载
  },

  onLaunch: function () {
    var app = this;
    //登录
    nami.login(() => {
      nami.getUserInfo((userInfo) => {
        console.log("已获取数据", userInfo);
        app.data.userInfo = userInfo;
      }, () => {
        console.log("用户拒绝提供信息");
      });
    });
  }
})

案例在小程序入口的时候实现nami封装的登录,登录成功之后可以看到localstorage中保存了一个叫做NAMI_TOKEN的字符,这个就是小程序登录之后要求前端保存的3rd session key了。
2) rank.js

    /**
     *下拉刷新
     */
    onPullDownRefresh: function () {
        wx.stopPullDownRefresh();
        var that = this;
		//这里使用了nami封装的request而不是wx.request
        nami.request({
            loading: true,
            url: '/request/scholes_pay/rank.groovy',
            success: function (res) {
                that.setData({
                    dataList: res.data.list
                });
                app.data.rankLoaded = true;//加载完成
            }
        });
    },

截取一个服务端请求的代码片段做分析,发现NAMI框架将request也做了封装,其主要目的是在每次服务端请求的时候将localstorage中的NAMI_TOKEN带入,如图。
3) 服务端代码:rank.groovy

/**
 * 排行榜
 * @author woden
 */

//重点是这一句获取已登录的用户信息
//NAMI框架中通过nami_token在服务端缓存池找到对应的用户资料,并返回给逻辑代码
//这里的session指的是NAMI框架中封装的会话上下文
def user = session.appUser();

//根据被赞赏金额排名的用户列表
def list = db.query("""
select b.*,a.TOTAL_FEE from
(
	select sum(TOTAL_FEE) TOTAL_FEE,OPEN_ID from PAY_DETAIL group by OPEN_ID
) a 
left join PAY_USER b on a.OPEN_ID = b.OPEN_ID
order by a.TOTAL_FEE desc,b.UPDATE_TIME asc 
limit 10
""".toString());

def result = [];
def i=1;
for(def o:list){
	def vo = [:];
	vo.avatar = o.AVATAR_URL;
	vo.nickName = o.NICK_NAME;
	vo.fee = fmt.formatPrice(o.TOTAL_FEE/100);
	if(user.openId == o.OPEN_ID){
		vo.my = true;
	}
	vo.rank = i++;
	result += vo;
}

return [list:result];

从这个案例看出,NAMI框架遵循规范推荐的技术原则,将缓存池、3rd key等业务无关的技术细节封装在框架中,让开发人员可以更专注于业务逻辑本身。

小程序支付

小程序推出之初,许多开发人员对于小程序支付的实现也是焦头烂额,官方给出的时序图如下,读者可以自己感受一下。
微信小程序的支付对于前端的接口倒是简单,只需事先一个wx.requestPayment接口,至于API里面指定的参数,填空就是了。先看看案例中前端支付是怎么写的。
1) index.js


  /**
   * 绑定选中赞赏金额按钮
   */
  selectItem: function (event) {
	//获取待支付金额,单位:元
    var total = event.currentTarget.dataset.item;
    var that = this;
    that.setData({ selected: total });

	//向服务端发起支付请求,获取wx.requestPayment需要的信息
    nami.request({
      loading: true,
      url: '/request/scholes_pay/pay.groovy',
      data: {
        total: total * 100 //元转为分
      },
      success: function (res) {
        console.log("获取支付密匙", res);

		//发起支付,根据服务端的返回填空
        wx.requestPayment({
          timeStamp: '' + res.data.signature.timestamp,
          nonceStr: res.data.signature.nonce,
          package: res.data.signature.pack,
          signType: 'MD5',
          paySign: res.data.signature.signature,
          success: function (res) {
            app.data.rankLoaded = false;//通知排行榜重新加载
            wx.showToast({
              title: '支付成功,感谢',
              icon: 'success'
            });
          },
          fail: function (res) {
            wx.showToast({
              title: '已取消支付',
              icon: 'success'
            });
          },
          complete: function () {
            that.setData({ selected: 0 });//取消选中
          }
        });

      },
      fail: function (res) {
		//do anything
      }
    });
  }

上面的代码看出,调用wx.requestPayment之前需先请求服务端下单,并返回对应的支付密匙信息。好,接下来我们看看服务端下单的逻辑怎么写。
2) 服务端代码:pay.groovy

/**
 * 下单支付
 * 
 * @author woden
 *
 */

//获取当前用户
def user = session.appUser();
log.debug("user:{}",user);
if(!user?.nickName){
	nami.error("用户拒绝提供资料,无法支付.");
}

//更新用户信息
if(db.find("select OPEN_ID from PAY_USER where OPEN_ID=?",user.openId)){//找得到则更新
	db.exec("update PAY_USER set NICK_NAME=?,AVATAR_URL=?,UPDATE_TIME=? where OPEN_ID=?"
			,user.nickName
			,user.avatarUrl
			,now
			,user.openId
			);
}else{//否则新增
	db.exec("insert into PAY_USER (OPEN_ID,NICK_NAME,AVATAR_URL,UPDATE_TIME) values (?,?,?,?)"
			,user.openId
			,user.nickName
			,user.avatarUrl
			,now
			);
}

//支付下单
//调用NAMI框架的app.pay.order接口(封装了微信支付下单),直接获取订单order对象
def total = request.getInteger("total");
def order =app.pay.order([
	openId : user.openId,
	total : total,
	body : '多谢赞赏',
	notify : nami.invoke('host.groovy')+'/request/scholes_pay/pay_callback.groovy' //回调
]);

//向客户端生成支付加密串
//调用NAMI框架的app.pay.signatur接口(根据prepayId换取支付密匙)
return [tradeNumber:order.tradeNumber,signature:app.pay.signature(order.prepayId)];

这里NAMI有两个接口,分别是:

看,支付的例子再一次说明NAMI框架化繁为简,把接口调用、基于支付安全考虑的签名加密算法都封装好,让开发人员关注业务逻辑本身而非这些技术细节,这在实际项目开发的时候可以大大提升效率。

踩坑

即使开发这么小的案例,数数也踩了不少坑,除了像兼容性问题、工具BUG、各种组件BUG这种已经让开发者们“习以为常”的坑以外,我重点列几个被官方升级“升”出来的坑。

  • **获取用户资料的确认框被“拒绝”后不再弹出,导致获取不到用户资料。**调用wx.getUserInfo弹出询问框,假如点了“拒绝”之后,再次调用wx.getUserInfo不再弹出,任你结束进程、清理缓存都没有,硬是要等大概十多分钟后,才会再次弹出询问框。这时候可别再点错了,否则又得等十多分钟。 这是小程序某个版本升级“升”出来的。在此之前我看过有些产品喜欢把wx.getUserInfo设计成用户主动点击按钮去获取的事件,例如设计一颗“登录”按钮,用户一点击就调用wx.getUserInfo,用户点击“允许”就相当于登录了;这个“十多分钟不弹出”的特性升级之后,以前这类主动登录的模式就得改改了。
  • **内置的Promise被废除。**一开始看到小程序支持ES6,支持Promise的时候非常高兴,想着可以写更优雅的异步代码块了。谁知道在某个版本升级之后,Promise就不被支持了,实在不知何故。虽然说有一些例如es6-promise的第三方框架可以代替,但不是终归总是不爽。
  • **地理位置API,获取不了当前坐标对应的地名。**我一怒之下使用百度地图API实现了,还是终归不爽。

FOR FUN

  • 说个血泪小教训,调试微信支付的时候千万千万不要用银行卡或信用卡去测试,频繁的支付1分钱1毛钱1块钱,会导致卡被银行封掉,有图有真相。
  • 用内置的DB console可以查看案例的运营数据,观摩一下。读者可以看出谁赞赏了最多,最多又是多少钱吗?

(完)

Опубликовать ( 0 )

Вы можете оставить комментарий после Вход в систему

1
https://api.gitlife.ru/oschina-mirror/woden-nami-demo-pay.git
git@api.gitlife.ru:oschina-mirror/woden-nami-demo-pay.git
oschina-mirror
woden-nami-demo-pay
woden-nami-demo-pay
master