前言:公司需要做一个人脸识别项目。用户点击商品 》 选择支付方式 》 微信人脸支付或微信、支付宝二维码支付。但不是我们的后端来和我合作,我需要自己去微信官方拿rawdata和AuthInfo(需要注意的是微信的接口请求都是XML请求)

微信人脸支付

1.选择设备。微信人脸需要选择微信官方提供的设备

微信人脸设备展示

2.商户APP Demo。仔细查看demo中的人脸支付流程。(demo中的流程同样是不需要有后端的,需要的参数都需要自己去微信要)

商户APP Demo(查看的是商户APP Demo)

微信刷脸支付文档 # 刷脸支付场景说明

3.把wxfacepay-release加到libs中。

4.Application中微信人脸SDK初始化

    private fun initWxpayface() {val m1: Map<String?, String?> = HashMap()
//      m1.put("ip", "192.168.1.1"); //若没有代理,则不需要此行
//      m1.put("port", "8888");//若没有代理,则不需要此行
//      m1.put("user", mEtnUser.getText().toString());//若没有代理,则不需要此行
//      m1.put("passwd", mEtnPassword.getText().toString());//若没有代理,则不需要此行
//      m1.put("proxy_type", 1 ); //若没有代理,则不需要此行
//      m1.put("perform_mode", "LOW_PERFORM");//低性能表现,默认关闭美颜等WxPayFace.getInstance().initWxpayface(this, m1, object : IWxPayfaceCallback() {@Throws(RemoteException::class)override fun response(info: Map<*, *>?) {if (info == null) {e("调用返回为空, 请查看日志")RuntimeException("调用返回为空").printStackTrace()return}val code = info["return_code"] as String?val msg = info["return_msg"] as String?e("初始化完成")}})}

5.获取rawdata。getWxpayfaceRawdata

        /*** 获取rawdata*/WxPayFace.getInstance().getWxpayfaceRawdata(object : IWxPayfaceCallback() {override fun response(info: Map<*, *>?) {if (info == null) {e("调用返回为空, 请查看日志")java.lang.RuntimeException("调用返回为空").printStackTrace()return}val code = info["return_code"] as String?val msg = info["return_msg"] as String?val rawData = info["rawdata"] as String?e(rawData)getAuthInfo(rawData)}})

6.获取AuthInfo。https://payapp.weixin.qq.com/face/get_wxpayface_authinfo

   private fun getAuthInfo(rawData: String?) {var map = mutableMapOf<String, String>()map["rawdata"] = rawData!!//门店编号map["store_id"] = Constance.store_id//门店名称map["store_name"] = Constance.store_name//终端设备编号,由商户定义。map["device_id"] = Constance.device_id//商户号绑定的公众号/小程序 appidmap["appid"] = orderInfoBean!!.data.wxappid// 商户号map["mch_id"] = orderInfoBean!!.data.wxmchid//版本号:固定是1map["version"] = "1"var now = (System.currentTimeMillis() / 1000).toString()map["now"] = nowmap["sign_type"] = "MD5"map["nonce_str"] = Constance.nonce_str//按字典顺序排序val infoIds: List<Map.Entry<String, String>> =ArrayList(map.entries)Collections.sort(infoIds, { o1, o2 -> o1.key.compareTo(o2.key) })//使用&符号进行拼接val sbR: String =Tools.getStringBuffer(infoIds).toString() + "&key=" + orderInfoBean!!.data.wxmchkey//进行MD5加密之后  转大写val sign: String = Tools.encode(sbR).toUpperCase()map["sign"] = sign/*将map集合转为xml*/val toXml = Tools.mapToXml(map)
//        e("认证参数XMl$toXml")val body = RequestBody.create(null, toXml)e(toXml.toString())OkGo.post<String>(UrlUtils.WECHAT).tag(UrlUtils.WECHAT).upRequestBody(body).execute(object : StringCallback() {override fun onError(response: com.lzy.okgo.model.Response<String?>?) {e("获取到的微信支付凭证${response!!.body()}")}override fun onSuccess(response: com.lzy.okgo.model.Response<String?>?) {val payVoucher = response!!.body()!!val headers = response.headers()!!try {var code = Tools.parseGetAuthInfoXML(payVoucher, "return_code")if ("SUCCESS" == code) {val authinfo: String = Tools.parseGetAuthInfoXML(payVoucher, "authinfo")pay(authinfo)} else {val msg: String = Tools.parseGetAuthInfoXML(payVoucher, "return_msg")e("获取微信凭证失败$msg")}} catch (e: Exception) {e.printStackTrace()e("获取微信凭证失败$e")}}})}

7.调起微信人脸识别。进行人脸识别getWxpayfaceCode(获取用户信息facecode)

    private fun pay(mAuthInfo: String?) {e("pay", "onClick | pay ")var params: HashMap<String, String> = HashMap()//FACEPAY: 人脸凭证,常用于人脸支付params["face_authtype"] = "FACEPAY"//商户号绑定的公众号/小程序 appidparams["appid"] = orderInfoBean!!.data.wxappid//  商户号params["mch_id"] = orderInfoBean!!.data.wxmchid//门店编号params["store_id"] = Constance.store_id//目标face_code类型,可选值:"1",刷卡付款码:18位数字,通过「付款码支付/被扫支付」接口完成支付。如果不填写则默认为"0"params["face_code_type"] = "1"//支付成功页是否需要展示人脸识别授权项。 展示:1 不展示:0params["ask_face_permit"] = "0"//商户端是否对SDK返回支付结果,可选值:"0",返回支付结果,商户需在确认?付结果后调?[updateWxpayfacePayResult]通知SDK;"1"params["ignore_update_pay_result"] = "1"//   指定刷脸界面的运行屏幕,可选值:“0”, 运行在默认屏幕; "1", 运行在第二屏幕(副屏); "2", 自动选择屏幕; "3", 强制用presentation方式在第二屏幕(副屏)启动。params["screen_index"] = "0"//商户订单号,须与调用支付接口时字段一致params["out_trade_no"] = orderInfoBean!!.data.order_number//订单金额(数字)params["total_fee"] = allPrice.times(100).toInt().toString()params["authinfo"] = mAuthInfo.toString()e("pay | single callback")WxPayFace.getInstance().getWxpayfaceCode(params, object : IWxPayfaceCallback() {@Throws(RemoteException::class)override fun response(info: Map<*, *>?) {if (info != null) {e(info.toString())getWxfaceCode(info)} elsee("调用返回为空, 请查看日志")}}, object : IWxPayfaceCallback() {override fun response(info: MutableMap<Any?, Any?>?) {e(info.toString())if (info == null) {RuntimeException("调用返回为空").printStackTrace()return}val code = info["return_code"] as String // 错误码val msg = info["return_msg"] as String // 错误码描述if (code == null || code != "SUCCESS") {RuntimeException("调用返回非成功信息,return_msg:$msg   ").printStackTrace()return}}})}private fun getWxfaceCode(info: Map<*, *>) {val code = info["return_code"] as String?val facecode = info["face_code"] as String?when {//用户确认支付TextUtils.equals(code, WxfacePayCommonCode.VAL_RSP_PARAMS_SUCCESS) ->doPay(facecode)TextUtils.equals(code, WxfacePayCommonCode.VAL_RSP_PARAMS_USER_CANCEL) ->e("用户取消")TextUtils.equals(code, WxfacePayCommonCode.VAL_RSP_PARAMS_SCAN_PAYMENT) ->e("扫码支付")TextUtils.equals(code, WxfacePayCommonCode.VAL_RSP_PARAMS_ERROR) ->e("发生错误")TextUtils.equals(code, WxfacePayCommonCode.VAL_RSP_PARAMS_USER_QUERY_CANCEL) ->e("请与商户确认支付结果")}}

8.进行发起订单支付micropay。接口地址:https://api.mch.weixin.qq.com/pay/micropay

    private fun doPay(facecode: String?) {var map = mutableMapOf<String, String>()map["auth_code"] = facecode.toString()map["spbill_create_ip"] = "192.168.0.143"map["body"] = "捷视商品"map["attach"] = "订单额外描述"map["device_info"] = Constance.device_idmap["sign_type"] = "MD5"map["total_fee"] = allPrice.times(100).toInt().toString()map["out_trade_no"] = orderInfoBean!!.data.order_number//商户号绑定的公众号/小程序 appidmap["appid"] = orderInfoBean!!.data.wxappid//    商户号map["mch_id"] = orderInfoBean!!.data.wxmchidvar now = (System.currentTimeMillis() / 1000).toString()map["time_start"] = nowmap["nonce_str"] = Constance.nonce_str//按字典顺序排序val infoIds: List<Map.Entry<String, String>> = ArrayList(map.entries)Collections.sort(infoIds) { o1, o2 -> o1.key.compareTo(o2.key) }//使用&符号进行拼接商户Keyval sbR: String =Tools.getStringBuffer(infoIds).toString() + "&key=" + orderInfoBean!!.data.wxmchkey//进行MD5加密之后  转大写val sign: String = Tools.encode(sbR).toUpperCase()map["sign"] = signe(map.toString())/*将map集合转为xml*/val toXml = Tools.mapToXml(map)
//        e("认证参数XMl$toXml")val body = RequestBody.create(null, toXml)OkGo.post<String>("https://com.api.mch.weixin.qq.com/pay/micropay").tag(this).upRequestBody(body).execute(object : StringCallback() {override fun onError(response: com.lzy.okgo.model.Response<String?>?) {e("获取微信支付${response!!.body()}")}override fun onSuccess(response: com.lzy.okgo.model.Response<String?>?) {val payVoucher = response!!.body()!!val headers = response.headers()!!e("微信支付${payVoucher}")try {var code = Tools.parseGetAuthInfoXML(payVoucher, "return_code")var resultCode = Tools.parseGetAuthInfoXML(payVoucher, "result_code")var msg = Tools.parseGetAuthInfoXML(payVoucher, "return_msg")if ("SUCCESS" == code) {if ("SUCCESS" == resultCode) {//支付成功,返回,告诉后端我们支付成功了,把支付成功参数给后台returServerCode(payVoucher)} else {queryPay()}} else {e("微信支付失败$msg")}} catch (e: Exception) {e.printStackTrace()e("微信支付失败$e")}}})}

9.因为微信的人脸支付没有“notify_url”参数,所以需要我们主动去给后台消息说我们支付成功了。有时候微信给我们的订单支付成功消息不是SUCCESS,而是SYSTEMERROR(系统超时)(我有时候遇到了这种情况,用户明明付款成功了,但是返回的不是SUCCESS),所以我们要主动去查询订单一次

查询订单状态orderquery。接口地址:https://api.mch.weixin.qq.com/pay/orderquery

    private fun returServerCode(payVoucher: String) {//微信支付订单号var transactionid = Tools.parseGetAuthInfoXML(payVoucher, "transaction_id")var openid = Tools.parseGetAuthInfoXML(payVoucher, "openid")var totalfee = Tools.parseGetAuthInfoXML(payVoucher, "total_fee")var map = mutableMapOf<String, String>()map["api_name"] = "wxFaceNotify"map["shop_id"] = orderInfoBean!!.data.shop_idmap["order_id"] = orderInfoBean!!.data.order_idmap["order_number"] = orderInfoBean!!.data.order_numbermap["transaction_id"] = transactionidmap["openid"] = openidmap["total_fee"] = (totalfee.toDouble() / 100).toString()e(map.toString())OkGo.post<String>(UrlUtils.SHOPLIST).tag(this).params(map).execute(object : StringCallback() {override fun onError(response: com.lzy.okgo.model.Response<String?>?) {ToastUtil.showTextToast("网络连接失败请重试!!")}override fun onSuccess(response: com.lzy.okgo.model.Response<String?>?) {e(response!!.body()!!)}})}

微信二维码(NATIVE支付)

获取微信二维码要开启NATIVE支付,我们要去统一下单中获取二维码

微信统一下单API

URL地址:https://api.mch.weixin.qq.com/pay/unifiedorder

   private fun showWeChatCodePay(payType: Int) {var map = mutableMapOf<String, String>()//商户号绑定的公众号/小程序 appidmap["appid"] = orderInfoBean!!.data.wxappid// 商户号map["mch_id"] = orderInfoBean!!.data.wxmchid//    商户号map["device_info"] = MyApplication.IMEI.toString()//  商户系统内部订单号map["out_trade_no"] = orderInfoBean!!.data.order_number//   商户系统内部IDmap["product_id"] = orderInfoBean!!.data.order_id//随机字符串map["nonce_str"] = Constance.nonce_str//商品描述map["body"] = "捷视商品"//订单金额(数字)map["total_fee"] = allPrice.times(100).toInt().toString()//终端IPmap["spbill_create_ip"] = "192.168.0.143"//通知地址map["notify_url"] = "http://www.jieshishop.com/Wxsite/Wxpay/wxf2fNotify"//交易类型map["trade_type"] = "NATIVE"//按字典顺序排序val infoIds: List<Map.Entry<String, String>> =ArrayList(map.entries)Collections.sort(infoIds) { o1, o2 -> o1.key.compareTo(o2.key) }//使用&符号进行频率val sbR: String =Tools.getStringBuffer(infoIds).toString() + "&key=" + orderInfoBean!!.data.wxmchkey//进行MD5加密之后  转大写val sign: String = Tools.encode(sbR).toUpperCase()map["sign"] = signe(map.toString())/*将map集合转为xml*/val toXml = Tools.mapToXml(map)//        e("认证参数XMl$toXml")val body = RequestBody.create(null, toXml)e(toXml.toString())OkGo.post<String>("https://api.mch.weixin.qq.com/pay/unifiedorder").tag(this).upRequestBody(body).execute(object : StringCallback() {override fun onError(response: com.lzy.okgo.model.Response<String?>?) {e("微信二维码支付失败${response!!.body()}")}override fun onSuccess(response: com.lzy.okgo.model.Response<String?>?) {val payVoucher = response!!.body()try {var msg = Tools.parseGetAuthInfoXML(payVoucher, "return_msg")var code = Tools.parseGetAuthInfoXML(payVoucher, "return_code")var resultCode = Tools.parseGetAuthInfoXML(payVoucher, "result_code")var codeUrl = Tools.parseGetAuthInfoXML(payVoucher, "code_url")if ("SUCCESS" == code) {if ("SUCCESS" == resultCode) {//支付成功dialog = PayCodeDialog(mContext, payType, codeUrl)dialog!!.show()}} else {ToastUtil.showTextToast("微信二维码支付失败:$msg")}} catch (e: Exception) {e.printStackTrace()ToastUtil.showTextToast("微信二维码支付失败:$e")}}})}

Tools 工具类:

public class Tools {/***      * 将Map转换为XML格式的字符串*      **      * @param data Map类型数据*      * @return XML格式的字符串*      * @throws Exception*      */public static String mapToXml(Map<String, String> data) throws Exception {DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder();org.w3c.dom.Document document = documentBuilder.newDocument();org.w3c.dom.Element root = document.createElement("xml");document.appendChild(root);for (String key : data.keySet()) {String value = data.get(key);if (value == null) {value = "";}value = value.trim();org.w3c.dom.Element filed = document.createElement(key);filed.appendChild(document.createTextNode(value));root.appendChild(filed);}TransformerFactory tf = TransformerFactory.newInstance();Transformer transformer = tf.newTransformer();DOMSource source = new DOMSource(document);transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8");transformer.setOutputProperty(OutputKeys.INDENT, "yes");StringWriter writer = new StringWriter();StreamResult result = new StreamResult(writer);transformer.transform(source, result);String output = writer.getBuffer().toString(); //.replaceAll("\n|\r", "");try {writer.close();} catch (Exception ex) {}return output;}/*** 拼接** @param infoIds* @return*/@NonNullpublic static String getStringBuffer(List<Map.Entry<String, Object>> infoIds) {StringBuffer sb = new StringBuffer();for (int i = 0; i < infoIds.size(); i++) {Map.Entry<String, Object> stringStringEntry = infoIds.get(i);if (stringStringEntry.getKey() == null) {stringStringEntry.getKey();}String key = stringStringEntry.getKey();Object val = stringStringEntry.getValue();if (i != infoIds.size() - 1) {if (val != null && !TextUtils.equals("", val.toString())) {sb.append(key).append("=").append(val).append("&");}} else {if (val != null && !TextUtils.equals("", val.toString())) {sb.append(key).append("=").append(val);}}}return sb.toString();}/*** 作 者: yzhg* 历 史: (版本) 1.0* 描 述: md5加密*/public static String encode(String password) {try {MessageDigest digest = MessageDigest.getInstance("md5");byte[] result = digest.digest(password.getBytes());StringBuilder sb = new StringBuilder();for (byte b : result) {int number = b & 0xff;String str = Integer.toHexString(number);if (str.length() == 1) {sb.append("0");}sb.append(str);}return sb.toString();} catch (NoSuchAlgorithmException e) {e.printStackTrace();return "";}}public static String parseGetAuthInfoXML(String resultText, String indexText) throws Exception {InputStream is = new ByteArrayInputStream(resultText.getBytes());String result = null;XmlPullParser parser = Xml.newPullParser();parser.setInput(is, "UTF-8");int eventType = parser.getEventType();while (eventType != XmlPullParser.END_DOCUMENT) {switch (eventType) {case XmlPullParser.START_TAG:if (parser.getName().equals(indexText)) {eventType = parser.next();result = parser.getText();}}eventType = parser.next();}return result;}}

Android 微信人脸识别+微信二维码相关推荐

  1. IOS人脸识别和二维码识别

    人脸识别应用于许多领域.二维码的识别更是疯狂.下面,我们一起去看看简单的人脸识别和二维码识别. 1.测试数据的展示(人脸). 原图: 1.人脸的大小 // 人脸大小 CGRect FaceRect  ...

  2. URL转微信可识别的二维码

    jquery.qrcode.js 是一个能够在客户端生成矩阵二维码QRCode 的jquery插件 ,使用它可以很方便的在页面上生成二维条码. 用法: 1.引入jquery.qrcode.min.js ...

  3. 人脸识别、二维码电子签到,让会议会展入场更加智能!

    签到,是一种识别,辩证,是出入一场活动的凭证,趋于不同类型的活动,不同规模使用的签到方式是不一样的. 在会议会展活动当中,往往第一关就是签到环节,一个巧妙专业的签到安排往往比会议本身更能给参会嘉宾留下 ...

  4. 了解人脸识别和二维码识别

    人脸识别方案 CoreImage (二维码识别,人脸识别) face++ 2014阿里 收费(两种方案本地计算 服务器计算) 腾讯优图 OpenCV (人脸识别 滤镜等) libefacedetect ...

  5. Android 基于google Zxing实现二维码 条形码扫描,仿微信二维码扫描效果

    分享一下我老师大神的人工智能教程!零基础,通俗易懂!http://blog.csdn.net/jiangjunshow 也欢迎大家转载本篇文章.分享知识,造福人民,实现我们中华民族伟大复兴! 转载请注 ...

  6. Android 基于google Zxing实现二维码、条形码扫描,仿微信二维码扫描效果

    转载请注明出处:http://blog.csdn.net/xiaanming/article/details/10163203 了解二维码这个东西还是从微信中,当时微信推出二维码扫描功能,自己感觉挺新 ...

  7. 【微信小程序】二维码跳转规则的前缀匹配是什么意思?

    前言 基础库 2.12.0 开发者工具 1.03.2008270 微信小程序的二维码跳转规则 为了方便小程序开发者更便捷地推广小程序,兼容线下已有的二维码,微信公众平台开放扫描普通链接二维码跳转小程序 ...

  8. 微信公众号使用:查看和下载微信公众号的二维码

    作为微信公众号的维护人员来说,不仅要知道微信公众号的基本功能,还要知道微信公平台的法律法规,发布文章的规则等常识.微信公众号申请成功之后,查看并下载微信公众号的二维码是比较常见的需求,而且添加微信公众 ...

  9. uni-app微信小程序生成自定义参数二维码,跳转小程序指定页面,获取参数;uni-app微信小程序获取二维码自定义参数;微信小程序生成动态参数二维码;uni-app微信小程序获取动态参数二维码;

    一.场景需求: 在小程序个人名片页面A页面,生成用户的个人名片二维码(该二维码携带用户的唯一标识id):微信扫一扫或长按图片识别这个二维码,可以跳转到小程序的B页面,并且在B页面拿到二维码上的唯一标识 ...

  10. Android 识别图片二维码

    zxing依赖: compile 'cn.yipianfengye.android:zxing-library:2.2' 初始化:private String SAVE_PIC_PATH = Envi ...

最新文章

  1. C#模拟鼠标键盘控制其他窗口(一)
  2. Android好评功能,Android应用评分功能的实现
  3. 李嘉诚那么有钱,为什么还要把国内很多资产卖掉?
  4. 【剑指offer】面试题29:顺时针打印矩阵(Java)
  5. 在html中 正确的嵌套方式是( ).,HTML及网页制作练习题-完整版
  6. block,inline和inlinke-block细节对比
  7. mysql有dataguard吗_Oracle查看是否搭建DataGuard
  8. gdb查看空指针 linux_资深程序员总结:分析Linux进程的6个方法,全都告诉你!
  9. Leetcode每日一题:面试题17.10.find-majority-element-lcci(主要元素)
  10. cdn搭建原理_直播平台搭建并不难,最难的是这两点
  11. 遇见Flask-Script
  12. 51单片机引脚内部电路
  13. linux opensource,GitHub - opensourceteams/linux: linux命令
  14. 【音频】削波失真(爆音)问题定位与解决
  15. 程序员掉入传销组织用“代码”求救,同事秒懂
  16. python手机壁纸高清_python爬取手机壁纸
  17. 重定位——重定位的简介与操作(涉及位置无关码)
  18. win10软件拒绝访问删不掉_Win10文件夹无法访问拒绝访问怎么解决?
  19. 计算机二级系统班C语言讲义,计算机二级C语言讲义8
  20. 做好如何融洽处理人际关系文章 把握是前言

热门文章

  1. 记录一下SlickEdit回退命令
  2. chrome浏览器 自带网页截取长图功能
  3. 传送带计数器c语言程序,脉搏计数器的程序(用C语言编写程序)
  4. 腾讯文档快捷键在哪里
  5. 谷歌学术Google Scholar超实用干货(拒绝翻墙/插件)
  6. 网页上直接sql查询操作数据库,并在网页上展示列表数据的工具页面
  7. 闭环整流电路matlab仿真,分享:基于双闭环的单相整流器原理简介及仿真验证
  8. 如何实现数据大屏在各种场景下的时间展示?
  9. 网页上的时间显示设置
  10. 国内ERP系统和SAP系统架构存在哪些差异?