微信刷脸支付全部流程(普通商户号)

  • 1.创建移动应用
  • 2.申请商户号, 开通APP支付和刷脸支付,关联APPID
  • 3.开发指引 | 微信刷脸支付
  • 4.刷脸支付流程
    • 名词解释
    • 时序图
  • 5.接口调用踩坑
    • (1)初始化(initWxpayface)
    • (2)获取数据 (getWxpayfaceRawdata)
    • (3)获取调用凭证(get_wxpayface_authinfo)
      • Sign参数获取
    • (4)获取人脸支付凭证(getWxpayfaceCode)
    • (5)支付 (pay),并更新支付结果(updateWxpayfacePayResult)
      • 1. pay
      • 2. updateWxpayfacePayResult(final Map info, final IWxPayfaceCallback wxpayfaceCallBack)
        • 接口参数
        • 接口返回
        • 实践指引

本文着重是 开发前的准备工作和开发过程中遇到的一些坑, 不涉及 优化 ,订单查询 ,退款和 具体商户后台server的开发。
开发环境: rk开发板 +华捷艾米A200 camera
最终实现 用自己的应用和商户信息成功进行了一笔刷脸支付过程的demo 并且 不需要搭建自己的商户后台server。

1.创建移动应用

微信开放平台
在微信开放平台中创建 移动应用,填写 包名 和 签名信息 等。创建需要等审核完成,一般审核过程很快。


然后开通微信支付,未认证用户需要进行认证。认证过程也需要审核,这个比创建应用的时候要慢。



认证过程需要填写一些企业资料 和收取一定费用 ,好像是 300/年 。

2.申请商户号, 开通APP支付和刷脸支付,关联APPID

微信商户号申请


点击APP支付 申请开通



开通后 在APPID授权管理 标签页中 关联 步骤1 中所申请的 APPID (必须已经完成认证并且开通APP支付权限)。

如果APPID未认证 会提示

如果未开通APP支付权限

所以必须先要认证并且开通支付权限。

正常情况:

然后去微信开放平台 对应的APP设置中确认 关联。


至此绑定完成

3.开发指引 | 微信刷脸支付

微信刷脸支付 开发指引
微信刷脸支付SDK 目前应该也在快速迭代中,前几天还是1.30版本,现在就已经更新2.10版本了。
使用方式:

  1. 安装人脸App。WxPayFace 微信刷脸支付SDK
  2. 商户接入人脸SDK。项目中引入1中的aar包。商户APP demo
  3. 商户server .商户server demo 此server是在商户自己开发整套流程的参考demo ,如果只是跑通商户App demo 则不需要此server。

4.刷脸支付流程

名词解释

人脸授权 :通过人脸识别,返回微信用户信息(openid, face_code)。

face_code:人脸凭证。常用于人脸支付,作为订单的支付凭证。

时序图

商户APP微信人脸sdk商户server微信支付后台API1. 程序启动时初始化 initWxpayfacedoInitWxpayface(返回初始化结果)2. 获取数据 getWxpayfaceRawdatadoGetWxpayfaceRawdata(返回rawdata)3.获取SDK调用凭证3.get_wxpayface_authinfo(rawdata)返回authinfo返回authinfo4. 进行人脸识别 getWxpayfaceCode启动人脸识别activity进行人脸识别完成人脸识别回调返回人脸识别结果(face_code, openid)doWxPayfaceCodeCallback(返回人脸识别结果)进行支付5. 发起订单人脸支付发起订单支付facepay(face_code, orderinfo)返回支付结果返回支付结果查询支付结果查询订单状态queryorder返回订单状态loop[ 直到:返回确定的订单状态(成功/失败/订单不存在)/超过轮询时间 ]返回支付结果撤销交易,以避免用户扣款,而没有发货的情况(撤销可后台异步进行)3. 撤销交易reverseorder返回撤销结果loop[ 撤销交易直到成功 ]opt[ 轮询结束仍然没有支付成功 ]alt[ 支付成功/失败 ][ 支付结果未明(比如:支付中/网络超时) ]6. 更新支付结果updateWxpayfacePayResult(callback)用户确认支付结果关闭人脸应用界面doUpdatePayResultCallBack(界面关闭,触发回调)程序退出(...)6. 释放资源 releaseWxpayface商户APP微信人脸sdk商户server微信支付后台API

注:

  1. 初始化 initWxpayface, 只需要在程序启动时调用;
  2. 释放资源 releaseWxpayface,只需要在程序退出时调用;
    每个方法的具体参数可在文档内查看。接口文档

5.接口调用踩坑

(1)初始化(initWxpayface)

这个一般放在自己定义的Application#onCreate()中调用就可以了。官方示例copy即可

//对人脸SDK进行初始化
WxPayFace.getInstance().initWxpayface(this, new IWxPayfaceCallback() {@Overridepublic void response(Map info) throws RemoteException {if (info == null) {new RuntimeException("调用返回为空").printStackTrace();return ;}String code = (String) info.get("return_code");String msg = (String) info.get("return_msg");Log.d(TAG, "response info :: " + code + " | " + msg);if (code == null || !code.equals("SUCCESS")) {new RuntimeException("调用返回非成功信息: " + msg).printStackTrace();return ;}Log.d(TAG, "调用返回成功");}});

(2)获取数据 (getWxpayfaceRawdata)

此过程 一定要保证 两点:
1.设备能联网,应用要添加<uses-permission android:name="android.permission.INTERNET"/>权限,
官方demo中还添加以下权限:

   <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /><uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" /><uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /><uses-permission android:name="android.permission.READ_PHONE_STATE" /><uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /><uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />

2.设备有SN号 。在android设备上,开机后进入setting->about devices->status->Serial number查看
当时使用的是 rk开发板,IMG没有写入SN号。当时在论坛上找的写入SN号工具只能写入 "ro.boot.serialno"的值,"ro.serialno"还是空的,所以最后只能修改源代码,重新编译烧录版本。

    /** 2. 人脸识别第二步 获取raw data*/private void getWxpayfaceRawdata() {WxPayFace.getInstance().getWxpayfaceRawdata(new IWxPayfaceCallback() {@Overridepublic void response(Map info) throws RemoteException {if (info == null) {new RuntimeException("调用返回为空").printStackTrace();return;}String code = (String) info.get("return_code");String msg = (String) info.get("return_msg");rawdata = info.get("rawdata").toString();Log.d(TAG, "rawdata ==" + rawdata);if (code == null || rawdata == null || !code.equals("SUCCESS")) {new RuntimeException("调用返回非成功信息,return_msg:" + msg + "   ").printStackTrace();return ;}/**在这里处理您自己的业务逻辑可以紧接着执行第三步 获取调用凭证getAuthInfo,这应该是向 商户server 发起请求。*/getAuthInfo(rawdata);}});}

(3)获取调用凭证(get_wxpayface_authinfo)

这是一个后端调用接口 采用xml格式
因为demo为了省事,省去商户后台server的开发,所以这一步也是在Android端直接调用。
获取凭证需要很多的 参数

参数 必填 类型 说明
store_id string(32) 门店编号, 由商户定义, 各门店唯一。
store_name string(128) 门店名称,由商户定义。(可用于展示)
device_id string(32) 终端设备编号,由商户定义。
attach string 附加字段。字段格式使用Json
rawdata string(2048) 初始化数据。由微信人脸SDK的接口返回。
获取方式参见:
[获取数据 getWxpayfaceRawdata](#获取数据 getWxpayfaceRawdata)
[获取数据 getWxpayfaceRawdata](#获取数据 getWxpayfaceRawdata)
appid string(32) 商户号绑定的公众号/小程序 appid
mch_id string(32) 商户号
sub_appid string(32) 子商户绑定的公众号/小程序 appid(服务商模式)
sub_mch_id string(32) 子商户号(服务商模式)
now int 取当前时间,10位unix时间戳。 例如:1239878956
version string 版本号。固定为1
sign_type string 签名类型,目前支持HMAC-SHA256和MD5,默认为MD5
nonce_str string(32) 随机字符串,不长于32位
sign string 参数签名。详见微信支付签名算法
Sign参数获取

签名算法

签名生成的通用步骤如下:

第一步,设所有发送或者接收到的数据为集合M,将集合M内非空参数值的参数按照参数名ASCII码从小到大排序(字典序),使用URL键值对的格式(即key1=value1&key2=value2…)拼接成字符串stringA。

特别注意以下重要规则:

参数名ASCII码从小到大排序(字典序)
◆ 如果参数的值为空不参与签名;
◆ 参数名区分大小写;
◆ 验证调用返回或微信主动通知签名时,传送的sign参数不参与签名,将生成的签名与该sign值作校验。
◆ 微信接口可能增加字段,验证签名时必须支持增加的扩展字段
第二步,在stringA最后拼接上key得到stringSignTemp字符串,并对stringSignTemp进行MD5运算,再将得到的字符串所有字符转换为大写,得到sign值signValue。

◆ key设置路径:微信商户平台(pay.weixin.qq.com)–>账户设置–>API安全–>密钥设置
,获取方法:

安装插件 ,浏览器最好别用QQ浏览器。
自家的插件不知道为什么唤不起来。重启N遍无用,推荐Chrome.
密钥是32位字符串 。
在上面第二步代码回调成功后紧接着 可以调用第三步。

    private void getAuthInfo(String rawdata){//now 参数 是unix 10位时间戳long  time = System.currentTimeMillis()/1000L;//为了对比起来方便 下面所有请求 都是用 字符串拼接的方式。//注意参数顺序 参数名ASCII码从小到大排序(字典序).String a ="appid=appid应用ID&device_id=DEV001&mch_id=mch_id商户号&nonce_str=V37ZHZVf2OrwsUV7kXTjTguP74c0byvE&now="+time+"&rawdata="+rawdata+"&sign_type=MD5&store_id=IMG001&store_name=门店名称&version=1";String stringSignTemp=a+"&key=32位的字符串";//注:key为商户平台设置的密钥keyString sign= md5(stringSignTemp).toUpperCase(); //注:MD5签名方式Log.d(TAG, "sign : " +sign);String  finalStr = "<xml>\n" +"     <appid>appid应用ID</appid>\n" +"     <device_id>DEV001</device_id>\n" +"     <nonce_str>V37ZHZVf2OrwsUV7kXTjTguP74c0byvE</nonce_str>\n" +"     <now>"+time+"</now>\n" +"     <mch_id>mch_id商户号</mch_id>\n" +"     <rawdata>"+rawdata+"</rawdata>\n" +"     <store_id>IMG001</store_id>\n" +"     <store_name>门店名称</store_name>\n" +"     <sign_type>MD5</sign_type>\n" +"     <version>1</version>\n" +"     <sign>"+sign+"</sign>\n" +"</xml>";//SSL可以不用管try {// Create a trust manager that does not validate certificate chainsfinal TrustManager[] trustAllCerts = new TrustManager[]{new X509TrustManager() {@Overridepublic void checkClientTrusted(java.security.cert.X509Certificate[] chain, String authType) throws CertificateException {}@Overridepublic void checkServerTrusted(java.security.cert.X509Certificate[] chain, String authType) throws CertificateException {}@Overridepublic java.security.cert.X509Certificate[] getAcceptedIssuers() {return new java.security.cert.X509Certificate[]{};}}};// Install the all-trusting trust managerfinal SSLContext sslContext = SSLContext.getInstance("SSL");sslContext.init(null, trustAllCerts, new java.security.SecureRandom());// Create an ssl socket factory with our all-trusting managerfinal SSLSocketFactory sslSocketFactory = sslContext.getSocketFactory();OkHttpClient client = new OkHttpClient.Builder().sslSocketFactory(sslSocketFactory).hostnameVerifier(new HostnameVerifier() {@Overridepublic boolean verify(String hostname, SSLSession session) {return true;}}).build();//请求格式xml ,请求方式postRequestBody body=RequestBody.create(MediaType.parse("application/xml"),finalStr);Request request = new Request.Builder().url("https://payapp.weixin.qq.com/face/get_wxpayface_authinfo")//后台接口地址,具体见后台开发文档.post(body).build();client.newCall(request).enqueue(new Callback() {@Overridepublic void onFailure(Call call, IOException e) {Log.d(TAG, "onFailure | getAuthInfo " + e.toString());}@Overridepublic void onResponse(Call call, Response response) throws IOException {try {String bodyStr = response.body().string();Log.d(TAG, "onResponse | getAuthInfo " + bodyStr);//这里返回的不是标准的xml格式,缺少 开始标签 ,拼接后用XmlPullParser解析String  xmlStr = "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n"+bodyStr;//ReturnXMLParser 类在官方的demo中//最终获取到 AuthInfo信息。mAuthInfo = ReturnXMLParser.parseGetAuthInfoXML( new ByteArrayInputStream(xmlStr.getBytes()));} catch (Exception e) {e.printStackTrace();}}});} catch (Exception e) {e.printStackTrace();throw new RuntimeException(e);}

这里需要注意的很多 :

  1. now 参数 注意是 10位的 时间戳 。并且拼接字符串a 时用的now 和 最后请求Body中xml内容中的Now的值一定要相同,两个地方切勿直接用 System.currentTimeMillis()/1000L
  2. 获取sign值 拼接的字符串a 一定要按照参数名ASCII码从小到大排序。sign值可以用签名校验工具验证
  3. 请求接口 https://payapp.weixin.qq.com/face/get_wxpayface_authinfo
  4. 返回值不是标准的xml格式,不包括"<?xml version=\"1.0\" encoding=\"utf-8\"?>\n"部分,所以可以先拼接在解析。

就这样最终拿到了AuthInfo字符串 。

(4)获取人脸支付凭证(getWxpayfaceCode)

启动人脸APP主界面入口,开启人脸识别,获取用户信息(openid)和支付凭证()。

参数 必填 类型 说明
appid string 商户号绑定的公众号/小程序 appid
mch_id string 商户号
sub_appid string(32) 子商户绑定的公众号/小程序 appid(可不填)
sub_mch_id string(32) 子商户号(非服务商模式不填)
store_id string 门店编号
telephone string 用户手机号。用于传递会员手机,此手机将作为默认值, 填写到手机输入栏。
out_trade_no string 商户订单号,须与调用支付接口时字段一致,该字段在在face_code_type为"1"时可不填,为"0"时必填
total_fee string 订单金额(数字), 单位分. 该字段在在face_code_type为"1"时可不填,为"0"时必填
face_authtype string 可选值:
FACEPAY: 人脸凭证,常用于人脸支付
FACEPAY_DELAY: 延迟支付(提供商户号信息联系微信支付开通权限)
authinfo string 调用凭证。获取方式参见: get_wxpayface_authinfo
ask_face_permit string 支付成功页是否需要展示人脸识别授权项。
展示:1
不展示:0
人脸识别授权项:
用户授权后用于1:N识别,可返回用户信息openid,建议商户有自己会员系统时,填1。
ask_ret_page string 是否展示微信支付成功页,可选值:“0”,不展示;“1”,展示
face_code_type string 目标face_code类型,可选值:“0”,人脸付款码:数字字母混合,通过「刷脸支付」接口完成支付;“1”,刷卡付款码:18位数字,通过「付款码支付/被扫支付」接口完成支付。如果不填写则默认为"0"
ignore_update_pay_result string 商户端是否对SDK返回支付结果,可选值:“0”,返回支付结果,商户需在确认⽀付结果后调⽤[updateWxpayfacePayResult]通知SDK;“1”,不返回支付结果。如果不填写则默认为"0"。
    private void getWXPayFaceCode(String mAuthInfo){if (mAuthInfo== null){Log.d(TAG, "mAuthInfo 为 null");return;}HashMap params = new HashMap();params.put(BaseUtils.FACE_AUTHTYPE, "FACEPAY");params.put(BaseUtils.APPID, "wxefawffetat56");params.put(BaseUtils.MCH_ID, "11534ef6121");params.put(BaseUtils.STORE_ID, "IMG001");//订单号 ,注意后后面支付pay中的订单号要一致out_trade_no = "" +(System.currentTimeMillis() / 100000); params.put(BaseUtils.OUT_TRADE_NO, out_trade_no);//订单金额params.put(BaseUtils.TOTAL_FEE, "1");//第三步中获取的AuthInfoparams.put(BaseUtils.AUTHINFO, mAuthInfo);WxPayFace.getInstance().getWxpayfaceCode(params, new IWxPayfaceCallback() {@Overridepublic void response(final Map info) throws RemoteException {//                if (!isSuccessInfo(info)) {//                    return;
//                }Log.d(TAG, "response | getWxpayfaceCode" );final String code = (String)info.get(BaseUtils.RETURN_CODE);// open id  , face coderunOnUiThread(new Runnable() {@Overridepublic void run() {//请求成功if (TextUtils.equals(code, WxfacePayCommonCode.VAL_RSP_PARAMS_SUCCESS)) {//获取openid 和 face_code face_code = (String)info.get("face_code");openID = (String)info.get("openid");ip = "174.207.250.66";try {Thread.sleep(2000);//第5步 支付pay(openID,face_code,ip);} catch (Exception e) {}} else if (TextUtils.equals(code, WxfacePayCommonCode.VAL_RSP_PARAMS_USER_CANCEL)) {Log.d(TAG, "run: 用户取消");} else if (TextUtils.equals(code, WxfacePayCommonCode.VAL_RSP_PARAMS_SCAN_PAYMENT)) {Log.d(TAG, "run: 扫码支付");} else if (TextUtils.equals(code, WxfacePayCommonCode.VAL_RSP_PARAMS_ERROR)) {Log.d(TAG, "run: 发生错误");}}});}});}

这个过程没什么说的,就是用第三步的AuthInfo ,还有就是订单号 要和后面第五步支付过程的订单号要保持一致。

(5)支付 (pay),并更新支付结果(updateWxpayfacePayResult)

1. pay

支付 同样是一个后端server接口 后端server接口
接口地址 :https://api.mch.weixin.qq.com/pay/facepay
请求方式 POST、XML

参数 必填 类型 说明
appid string 商户号绑定的公众号/小程序 appid
mch_id string 商户号
sub_appid string(32) 子商户绑定的公众号/小程序 appid(可不填)
sub_mch_id string(32) 子商户号(非服务商模式不填)
device_info string(32) 终端设备号(商户自定义,如门店编号)。
out_trade_no string(32) 商户系统内部的订单号,32个字符内、可包含字母;更换授权码必须要换新的商户订单号 其他说明见商户订单号
total_fee string 订单金额(数字), 单位分. 该字段在在face_code_type为"1"时可不填,为"0"时必填
nonce_str string(32) 随机字符串,不长于32位。推荐随机数生成算法
sign string(32) 参数签名。详见微信支付签名算法
body String(128) 商品或支付单简要描述,格式要求:门店品牌名-城市分店名-实际商品名称
total_fee Int 订单总金额,单位为分,只能为整数,详见支付金额
spbill_create_ip String(16) 调用微信支付API的机器IP
openid String(128) 用户在商户appid 下的唯一标识
face_code String(128) 人脸凭证,用于刷脸支付

更多不必要参数可查看文档。
举例如下:

<xml><appid>wx2421b1c4370ec43b</appid><attach>订单额外描述</attach><body>刷卡支付测试</body><device_info>1000</device_info><goods_tag></goods_tag><mch_id>10000100</mch_id><nonce_str>8aaee146b1dee7cec9100add9b96cbe2</nonce_str><out_trade_no>1415757673</out_trade_no><spbill_create_ip>14.17.22.52</spbill_create_ip><time_expire></time_expire><total_fee>1</total_fee><openid><![CDATA[oUpF8uN95-Ptaags6E_roPHg7AG0]]></openid><face_code>Qpoqwhsdjhfausrhqieofnq90w=w8233wdwjdjiwq</face_code><sign>C29DB7DB1FD4136B84AE35604756362C</sign>
</xml>

pay方法中Http请求 返回结果请查看文档

2. updateWxpayfacePayResult(final Map info, final IWxPayfaceCallback wxpayfaceCallBack)
接口参数
参数 必填 类型 说明
appid string 商户绑定的公众号/小程序 appid
mch_id string 商户号
store_id string 门店编号
authinfo string 调用凭证。获取方式参见: get_wxpayface_authinfo
payresult string 支付结果。可取值:
SUCCESS: 支付成功
ERROR: 支付失败
接口返回
参数 必填 类型 说明
return_code string 错误码。公共定义见 公共错误码
return_msg string(128) 对错误码的描述
实践指引
  private void updateWxpayfacePayResult() {HashMap<String, String> map = new HashMap<String, String>();map.put("appid", "填您的公众号"); // 公众号,必填map.put("mch_id", "填您的商户号"); // 商户号,必填map.put("store_id", "填您的门店编号"); // 门店编号,必填map.put("authinfo", "填您的调用凭证"); // 调用凭证,必填map.put("payresult", "SUCCESS"); // 支付结果,SUCCESS:支付成功   ERROR:支付失败   必填WxPayFace.getInstance().updateWxpayfacePayResult(map, new IWxPayfaceCallback() {@Overridepublic void response(Map info) throws RemoteException {if (info == null) {new RuntimeException("调用返回为空").printStackTrace();return;}String code = (String) info.get("return_code"); // 错误码String msg = (String) info.get("return_msg"); // 错误码描述if (code == null || !code.equals("SUCCESS")) {new RuntimeException("调用返回非成功信息,return_msg:" + msg + "   ").printStackTrace();return ;}/*在这里处理您自己的业务逻辑:执行到这里说明用户已经确认支付结果且成功了,此时刷脸支付界面关闭,您可以在这里选择跳转到其它界面*/}});}

最后第五步整体过程代码:

    private void pay(String openID,String faceCode,String ipAddress){Log.d(TAG, "-------------start pay-----------");String a ="appid=APPID&body=刷脸支付测试&device_info=DEV001&face_code="+faceCode+"&mch_id=MCH_ID&nonce_str=V37ZHZVf2OrwsUV7kXTjTguP74c0byvE&openid="+openID+"&out_trade_no="+out_trade_no+"&spbill_create_ip="+ipAddress+"&total_fee=1";String stringSignTemp=a+"&key=32KEY";//注:key为商户平台设置的密钥keyString sign= md5(stringSignTemp).toUpperCase();String  finalStr = "<xml>\n" +"     <appid>APPID</appid>\n" +"     <body>刷脸支付测试</body>\n" +"     <device_info>DEV001</device_info>\n"+"     <face_code>"+faceCode+"</face_code>\n"+"     <mch_id>MCHID</mch_id>\n" +"     <nonce_str>V37ZHZVf2OrwsUV7kXTjTguP74c0byvE</nonce_str>\n" +"     <openid>"+openID+"</openid>\n"+"     <out_trade_no>"+out_trade_no+"</out_trade_no>\n"+"     <spbill_create_ip>"+ipAddress+"</spbill_create_ip>\n" +"     <total_fee>1</total_fee>\n"+"     <sign>"+sign+"</sign>\n" +"</xml>";OkHttpClient client = new OkHttpClient.Builder().hostnameVerifier(new HostnameVerifier() {@Overridepublic boolean verify(String hostname, SSLSession session) {return true;}}).build();RequestBody body=RequestBody.create(MediaType.parse("application/xml"),finalStr);Request request = new Request.Builder().url("https://api.mch.weixin.qq.com/pay/facepay").post(body).build();client.newCall(request).enqueue(new Callback() {@Overridepublic void onFailure(Call call, IOException e) {Log.d(TAG, "onFailure | getAuthInfo " + e.toString());}@Overridepublic void onResponse(Call call, Response response) throws IOException {try {String bodyStr = response.body().string();Log.d(TAG, "支付结果  ====\n" + bodyStr);String  xmlStr = "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n"+bodyStr;
//                            String retrunCode = ReturnXMLParser.parseCodeXML( new ByteArrayInputStream(xmlStr.getBytes()),"return_code");String result_code = ReturnXMLParser.parseCodeXML( new ByteArrayInputStream(xmlStr.getBytes()),"result_code");Map map =new HashMap();map.put("appid","APPID应用ID");map.put("mch_id",商户号);map.put("store_id","IMG001");map.put("authinfo",mAuthInfo);boolean resultStatus = TextUtils.equals(result_code, WxfacePayCommonCode.VAL_RSP_PARAMS_SUCCESS);if (result_code!=null && resultStatus ){map.put("payresult","SUCCESS");}else {map.put("payresult","ERROR");}//更新支付状态 WxPayFace.getInstance().updateWxpayfacePayResult(map, new IWxPayfaceCallback() {@Overridepublic void response(Map info) throws RemoteException {Log.d(TAG, "-------------更新支付状态 -----------"+info.get("return_code"));}});} catch (Exception e) {e.printStackTrace();}}});}

请求成功后一定要 调用更新支付结果的方法(不然一直卡在 支付等待界面),调用后会根据结果提示支付成功或者失败。 至此整个支付流程就完事了。

最后可以去商户平台 查看订单信息:

Andorid微信刷脸支付使用过程解析相关推荐

  1. python读取excel单元格填充色rgb_Python openpyxl读取单元格字体颜色过程解析

    Python openpyxl读取单元格字体颜色过程解析 问题 我试图打印some_cell.font.color.rgb并得到各种结果. 对于一些人,我得到了我想要的东西(比如" FF00 ...

  2. JAVA接入微信刷脸支付分支付【V2、V3两种接入都有提供】

    支付宝支付 开发前准备 文档 开发准备 maven 微信配置类 微信V2-SDK 微信V3工具 开发调用 V2刷脸授权接口[get_wxpayface_authinfo] V3支付相关接口[接口太多部 ...

  3. 微信刷脸支付开放政策启动,亿万级市场待你加入!

    当大家认为扫码支付已是未来的支付方式时,支付宝与微信两大行业巨头,却用实际行动告诉我们,未来移动支付是不需要手机的,靠脸就能走天下,刷脸支付正在革新扫码支付,成为2019年支付生态的重头戏. 5月22 ...

  4. android微信刷脸支付宝,录指纹、敲密码太麻烦,OPPO Find X完成安卓首个微信刷脸支付...

    原标题:录指纹.敲密码太麻烦,OPPO Find X完成安卓首个微信刷脸支付 科技改变生活,最直观的体现就是能够将过去的一些方式摒弃掉,用新科技来替代,最好的代表就是现如今越来越多的人只带一部手机就出 ...

  5. 客快物流大数据项目(十四):DockerFile介绍与构建过程解析

    目录 DockerFile介绍与构建过程解析 一.什么是Dockerfile 1.介绍 2.Dockerfile构建步骤

  6. java操作es聚合操作并显示其他字段_java使用elasticsearch分组进行聚合查询过程解析...

    这篇文章主要介绍了java使用elasticsearch分组进行聚合查询过程解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 java连接elas ...

  7. aop springboot 传入参数_java相关:springboot配置aop切面日志打印过程解析

    java相关:springboot配置aop切面日志打印过程解析 发布于 2020-3-31| 复制链接 摘记: 这篇文章主要介绍了springboot配置aop切面日志打印过程解析,文中通过示例代码 ...

  8. python画散点图程序-Python散点图与折线图绘制过程解析

    这篇文章主要介绍了Python散点图与折线图绘制过程解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 在数据分析的过程中,经常需要将数据可视化,目 ...

  9. Apache ZooKeeper -从初始化到对外提供服务的过程解析( 集群模式 )

    文章目录 流程图 Pre 什么是集群模式? ZooKeeper 集群模式的特点 底层实现原理 程序启动 QuorumPeer 类 Leader 服务器启动过程 Follow 服务器启动过程 小结 流程 ...

最新文章

  1. 1.8 finally和return的执行顺序
  2. linux下批量修改文件名的方法
  3. Python基础day05 作业解析【10道 函数作业题】
  4. [Project Euler] 来做欧拉项目练习题吧: 题目004
  5. 第十七章 特殊类成员
  6. 风客科技网管培训资料
  7. android 按钮点击返回顶部,微信浏览器点击系统返回,安卓返回会重载页面回到页面顶部,iOS则返回则会保留之前浏览位置的解决方法...
  8. React Native RSA加密
  9. thinkphp5 图片压缩旋转_有非常多的图片,该怎么制作PPT?
  10. Kafka高可用机制入门
  11. BZOJ 2756: [SCOI2012]奇怪的游戏
  12. IOS第11天(4:UIDatePicker时间选择,和键盘处理,加载xib文件,代理模式)
  13. 10个线程同时执行i++操作1000次,如何保证结果是1w
  14. SocksCap64全局代理设置教程
  15. void value not ignored as it ought to be
  16. Qt 信号与槽机制及实战案例
  17. XP需要计算机管理权限,xp无法无法使用管理员权限运行软件的解决步骤
  18. 信息系统项目管理9大知识领域及其概要说明
  19. chrome控制台设置网页自动刷新
  20. 以分割栅格为例实现FME模板的方案优化

热门文章

  1. fedora13中安装五笔
  2. html 语言怎么弄英语,HTML语言,HTML language,音标,读音,翻译,英文例句,英语词典
  3. win10禁用全角,教你恢复win10系统屏蔽全角/半角快捷键的办法
  4. 基带、射频,到底是什么?
  5. 小数输出最简分数c语言,小数化成最简式分数
  6. 如何从零基础入门并精通PS?PS如何快速入门?
  7. Android Launcher启动流程
  8. 论文经验 - 计算机视觉(CV)方向
  9. ssm+bootsrap人力资源考勤系统-JAVA【数据库设计、源码、开题报告】
  10. html5 mp3播放器源码,HTML5自定义mp3播放器源码