微信小程序web-view公众号与小程序支付的切换使用

微信小程序web-view公众号与小程序支付间的切换使用

        最近小程序开放了新功能,支持内嵌网页。html写的网页,官网,网站,运行在浏览器上的,有域名的那种,可以内嵌到小程序里了!
  • 1
  • 2

那么这意味着什么呢?你还需要开发独立开发官网小程序吗?之前的微信公众号功能大部分也可以直接通过小程序webview实现了。 
这几天刚好公司也有这方面的需求,怀着激动心情的我开始了踩坑之旅。

     开发之前我们需要把需要的环境配置好,这里就引用官方的介绍了————
  • 1
  • 2

1. 开发者登录小程序后台,选择设置-开发设置-业务域名,新增配置域名模块。目前小程序内嵌网页能力暂不开放给个人类型帐号和海外类型帐号。 
2.配置的业务域名必须时https

那么配置好后,马上可以进入开发啦! 

  页面中引入公众号的首页,小程序端的代码不是很多,主要的是后台进行结合。

1.在后端添加一个小程序的入口方法,
  • 1
  • 2
  • 3
  • 4

/**
 * 小程序第一次入口
 * @return
 */
public String wxIndex(){//返回首页
    sessions=request.getSession().getId();
    return "home";
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

这里我没有做任何的处理,这个项目首页是不用登陆的,直接返回首页;来到这一步时我们发现之前公众号后台保存在session中的信息获取不到,使用后发现小程序每次请求sessionId都会发生改变,这样后台无法使用session储存数据。

解决方案:
  • 1
  • 2

小程序第一次请求后台返回一个sessionId,之后小程序在参数或header中带入这个sessionId,后台使用这个session来处理。注意session销毁以及过期设置。


wx.login({
  success: function (res) {        wx.getSetting({
      success(setRes) {
        // 判断是否已授权  
        if (!setRes.authSetting['scope.userInfo']) {
          // 授权访问  
          wx.authorize({
            scope: 'scope.userInfo',
            success() {
              //获取用户信息  
              wx.getUserInfo({
                lang: "zh_CN",
                success: function (userRes) {
                  // var session_id= wx.getStorageSync('JSESSIONID');
                  //发起网络请求  
                  wx.request({
                    url: 'https://www.ulin5.com/vip/buser-bind-mobile_wxXiaoChengXuLogin.html',
                    data: {
                      code: res.code,
                      encryptedData: userRes.encryptedData,
                      iv: userRes.iv
                    },
                    header: {
                      "Content-Type": "application/x-www-form-urlencoded"
                    },
                    method: 'POST',
                    //服务端的回掉  
                    success: function (result) {
                      console.log(result)
                      // var session_id = wx.getStorageSync('JSESSIONID');//本地取存储的sessionID  
                      // if (session_id == null || session_id == "") {
                        wx.setStorageSync('JSESSIONID', result.data.sessionId) //如果本地没有就说明第一次请求 把返回的session id 存入本地  

                      // }
                      console.log(result.data.openId)
                      getApp().openid = result.data.openId
                      // var data = result.data.result;
                      // data.expireTime = nowDate + EXPIRETIME;
                      // wx.setStorageSync("userInfo", data);
                      // userInfo = data;
                    }
                  })
                }
              })
            }
          })
          })
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48

 把小程序所需要的openid和unionid拿到,由于公众号的openid   和小程序的openid不同,所以这需要用到unionid。
换句话说,同一用户,对同一个微信开放平台帐号下的不同应用,UnionID是相同的。
此前的OpenID机制,每个微信号对应每个公众号只有唯一的OpenID,所以不同微信公众号之间是不能共享用户的,现在有了UnionID就可以了。
   前面说到小程序每次请求的sessionId不同,所以通过sessionId可以获取到我们存储的数据信息。
   注意Servlet2.1之后不支持SessionContext里面getSession(String id)方法。
   我这里通过HttpSessionListener监听器和全局静态map自己实现一个SessionContext。
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

public class MySessionContext {

 private static HashMap mymap = new HashMap();

    public static synchronized void AddSession(HttpSession session) {
        if (session != null) {
            mymap.put(session.getId(), session);
        }
    }

    public static synchronized void DelSession(HttpSession session) {
        if (session != null) {
            mymap.remove(session.getId());
        }
    }

    public static synchronized HttpSession getSession(String session_id) {
        if (session_id == null)
        return null;
        return (HttpSession) mymap.get(session_id);
    }
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23

        public class SessionListener implements HttpSessionListener {
/*public static Map userMap = new HashMap();  */
/*private   MySessionContext myc=MySessionContext.getInstance();  */

@Override
public void sessionCreated(HttpSessionEvent arg0) {
    /*myc.AddSession(arg0.getSession()); */
    MySessionContext.AddSession(arg0.getSession());
}

@Override
public void sessionDestroyed(HttpSessionEvent arg0) {
    HttpSession session = arg0.getSession();  
    /*myc.DelSession(session);*/
     MySessionContext.DelSession(session);
}

}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19

web.xml添加一个监听器:

<listener>  
<listenerclass>com.common.util.SessionListener</istener-class>  
</listener>  
  • 1
  • 2
  • 3
  • 4

根据sessionId获取Session对象:

String sessionId = request.getParameter("sessionId");

HttpSession session = MySessionContext.getSession(sessionId);

写到这里已经算是完成一半了,只要在后台加一个处理小程序进来的方法,把所需要的用户信息保存到数据库中。
我们不需要改变以前写好处理公众号的任何代码(根据项目进行整合),
  • 1
  • 2
  • 3

public String wxLogin(){//java后端
String Code = request.getParameter("code");// 登陆状态码
    String typeDate = request.getParameter("encryptedData");// 用户加密信息,用于解密获取unionid
    String iv = request.getParameter("iv");// 解密密钥
    String OPENID_URL = "https://api.weixin.qq.com/sns/jscode2session?appid=APPID&secret"
            + "=SECRET&js_code=JSCODE&grant_type=authorization_code";// 获取openid的地址
    UserInfo userInfo = null;
    String url = OPENID_URL.replace("APPID", Pkcs7Encoder.APPID)
            .replace("SECRET", Pkcs7Encoder.APPSECRET)
            .replace("JSCODE", Code);
    JSONObject jsonObject = null;
    jsonObject = Pkcs7Encoder.doGetStr(url);// 调取Get提交方法
    String OpenId = jsonObject.getString("openid"); // 获取openid
    /*
     * ResourceBundle resource = ResourceBundle.getBundle("weixin");
     * //读取属性文件
     */String requestUrl = "https://api.weixin.qq.com/sns/jscode2session"; // 请求地址
    /* String wxUserInfo=Pkcs7Encoder.sendPost(requestUrl, requestUrlParam); */
    // 获取会话密钥(session_key)
    String session_key = jsonObject.getString("session_key");   
    ....     //通过逻辑代码保存我们需要的信息
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23

  接下来到最重要的环节了,到了我们最期待的支付环节了。由于web-view目前还不支持支付接口。
  我们需要判断是否运行在小程序环境中进行支付的互换,从而实现支付功能。
  • 1
  • 2
  • 3

<script type="text/javascript"src="https://res.wx.qq.com/open/js/jweixin-1.3.0.js"></script>

在网页内可通过window.__wxjs_environment变量判断是否在小程序环境。
  • 1
  • 2


// web-view下的页面内 
wx.ready(function() { 
console.log(window.__wxjs_environment === 'miniprogram') // true 
})

例如:

  var isWxMini = window.__wxjs_environment ===       'miniprogram';
    if (isWxMini) {//判断是否在微信小程序环境中调用支付接口
    $("#wxloading").hide();
    var jumpUrl = encodeURIComponent(window.location)
    //把要用到的参数传到小程序中进行支付
    var path = '/pages/pay/pay?jhNum='+jhNum+'&cproType='+cproType+'&zcProId='+zcProId+'&url='+url+'&cproId='+cproId+'&esOrderc='+esOrderc;
    wx.miniProgram.navigateTo({
        url: path
    })

}else{//公众号支付
window.location.href="/vip/buy-group_saveJoinPt.html?cproId="+cproId+"&jhNum="+jhNum+"&cproType="+cproType+"&zcProId="+zcProId+"&esOrderc="+esOrderc;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

小程序pay文件夹下新建pay.js和pay.wxml

 pay.js
          Page({
  onLoad: function (options) {
  console.log(options)
    // 获取网页传过来的值
 // TODO 用es6解构来获取值TODO
var jhNum = options.jhNum
var cproType = options.cproType
var zcProId = options.zcProId
var cproId = options.cproId
var esOrderc = options.esOrderc
// var jumpUrl = decodeURIComponent(options.jumpUrl)
var tourl=options.url
// console.log(tourl)
var openid = getApp().openid
console.log(openid)
var session_id = wx.getStorageSync('JSESSIONID')//本地取存储的sessionID
// console.log('----------sessionid' + session_id+'-----------------')
wx.request({
  url: tourl,
  data: {
    openid: openid,
    jhNum: jhNum,
    cproType: cproType,
    zcProId: zcProId,
    cproId: cproId,
    esOrderc: esOrderc
  },
  header: {
    "Content-Type": "application/x-www-form-urlencoded",
    'Cookie': 'JSESSIONID=' + session_id
  },
  method: 'POST',
  success: function (res){
    console.log(res)
    wx.requestPayment({
      'timeStamp': res.data.timeStamp,
      'nonceStr': res.data.nonceStr,
      'package': res.data.package,
      'signType': 'MD5',
      'paySign': res.data.sign,
      'success': function (res) {
        console.log('支付成功')
         wx.navigateBack() //返回会上个页面
      },
      'fail': function (res) {
        console.log('支付失败')
          wx.navigateBack() //返回会上个页面
      }
    })
  }
})
}
})
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55

到这基本上已经完成,个人感觉这种实现方式在用户体验度上并不是很友好,但是基本的功能都可以实现。
相信官方也会对webview更进一步的优化。能在webview中直接调用支付的接口。
如果大家有更好的实现思路,千万别忘了告诉我哦。
由于作者还是个工作不到一年的小菜。在代码编写上还有很多的不足,欢迎大家指正。
这也是我的第一篇博客,嗯嗯嗯还是有点小激动。^_^
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值