最近项目中集成了华为账号登录与支付的功能,把踩过的坑和过程记录下来。

先看下支付效果图:

支付价格0.01请忽略,因为这是为了测试用的。

刚开始接到这个项目的时候我很奇怪,为什么要集成华为支付呢,原有的微信和支付宝已经能够满足项目需求,难道还有客户偏偏要用华为支付的?看下华为联运人员发来的邮件说明

原来公司是想在华为平台为项目做推广,然后华为的联运应用基础必须要集成华为的账号、支付。然后与我们公司收益三七分成...

ok,那就搞吧。

先说下几个坑点:

1、集成Agent必须保持代码的包和路径的结构不变

2、登录华为账号必须是正式包签名,HMS服务才会起作用(换而言之就是正式包签名下才能登录华为账号)

至于debug模式下如何打正式包,可以看下我这篇博客https://blog.csdn.net/yun382657988/article/details/83928748

3、华为支付的sign签名有可能验证通过不了

这里就需要配合后台开发验证了

4、调试华为推送push,最好在华为手机上调试,其他手机有可能推送不成功(LZ小米5sp手机推送不成功)

一、注册成为华为开发者

接入准备,创建应用、申请HMS服务等巴拉巴拉的一堆就不细说了,可以看详细的华为联运应用文档(注:文档说明,接入华为支付服务的前提,必须成为企业开发者,所以个人的,咱只好歇菜了)给上链接

https://developer.huawei.com/consumer/cn/service/hms/catalog/HwJointOperationApp.html?page=hmssdk_jointOper_app_prepare

然后还需要完成appid,支付公钥,支付私钥等,这个很好弄,按文档操作

二、集成sdk

集成sdk用Gradle+maven集成方式,依旧看文档操作。这里主要说下集成Agent,通过里面的脚本操作,选择需要的代码拷贝到项目中,这里有个坑,需要注意一下:

保持HMSAgent代码的包的路径和结构不变,什么意思呢?看下图

必须要这样的结构才行,不然会报错!!!!!!

三、配置manifest文件、配置混淆、配置签名等

这里也不做过多说明,根据需求按照文档操作

四、华为账号登录

 private void signIn(boolean forceLogin) {HMSAgent.Hwid.signIn(forceLogin, (rtnCode, signInResult) -> {if (rtnCode == HMSAgent.AgentResultCode.HMSAGENT_SUCCESS && signInResult != null) {Map<String, String> params = new HashMap<>();params.put("username", signInResult.getDisplayName());if((signInResult.getPhotoUrl()).equals("")){params.put("head_photo", "https://pan.baidu.com/s/17ZznCBxsde53WfWqFgU2Wg");}else {params.put("head_photo", signInResult.getPhotoUrl());}params.put("openid", signInResult.getOpenId());JLogger.d("head_photo:"+signInResult.getPhotoUrl());uploadUserInfo(params);} else {JLogger.e("signIn---error: " + rtnCode);}});}

代码很简单,调用HMSAgent.Hwid.signIn接口即可。这里主要是获取用户的OpenId(应用内用户的唯一标识)、昵称和头像

uploadUserInfo(params)方法是把用户的信息上传到自己项目的服务器上,这里不做过多说明。

非华为手机调试需要安装华为移动服务

全部点击同意。这里建议用华为的手机调试(华为push的集成就不在这说了,网上有很多例子,要用华为的手机,lz用的小米的push推送老是不成功哦,这个是我踩的坑二,哈哈)

五、华为支付

支付的代码也不多,主要是调用HMSAgent.Pay.pay接口,贴上代码

package com.jm.ec.main.pay;import android.app.Activity;
import android.content.SharedPreferences;import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.huawei.android.hms.agent.HMSAgent;
import com.huawei.android.hms.agent.pay.PaySignUtil;
import com.huawei.hms.support.api.entity.pay.OrderRequest;
import com.huawei.hms.support.api.entity.pay.PayReq;
import com.huawei.hms.support.api.entity.pay.PayStatusCodes;
import com.huawei.hms.support.api.pay.PayResultInfo;
import com.jm.core.delegates.JumeiDelegate;
import com.jm.core.net.RestClient;
import com.jm.core.util.log.JLogger;
import com.jm.ec.constant.JConstants;
import com.jm.ec.event.StartOrderEvent;
import com.jm.ec.main.design.IEvnValues;import org.greenrobot.eventbus.EventBus;import java.security.SecureRandom;
import java.text.DateFormat;
import java.util.Date;import static com.jm.core.app.Jumei.getActivity;public class HuaWeiPay {private Activity mActivity = null;private static final String pay_priv_key = IEvnValues.pay_priv_key;private static final String pay_pub_key = IEvnValues.pay_pub_key;private static final String appId = IEvnValues.appId;private static final String cpId = IEvnValues.cpId;private static int RESULT ;private static String AMOUNT = null;private static String ORDERID = null;private static String REQUESTID = null;private static String NOTIFYTIME = null;private static String USERNAME= null;private static String PAYNAME = "";private HuaWeiPay(JumeiDelegate delegate) {this.mActivity = delegate.getProxyActivity();}public static HuaWeiPay create(JumeiDelegate delegate) {return new HuaWeiPay(delegate);}/*** 普通支付示例*/public static void pay(float amount, String orderNumber, String name) {PayReq payReq = createPayReq(amount,orderNumber,name);HMSAgent.Pay.pay(payReq, (int retCode, PayResultInfo payInfo) -> {if (retCode == HMSAgent.AgentResultCode.HMSAGENT_SUCCESS && payInfo != null) {boolean checkRst = PaySignUtil.checkSign(payInfo, pay_pub_key);JLogger.d("pay: onResult: pay success and checksign=" + checkRst);if (checkRst) {// 支付成功并且验签成功,发放商品RESULT = payInfo.getReturnCode();AMOUNT = payInfo.getAmount();ORDERID = payInfo.getOrderID();REQUESTID = orderNumber;NOTIFYTIME = payInfo.getTime();USERNAME = payInfo.getUserName();PAYNAME = name;RestClient.builder().url("这个主要是获取华为sign的接口,因为上传payInfo.getSign()获取的sign,后台那边死活通过不了,于是写了个接口获取华为sign").params("result",payInfo.getReturnCode()).params("amount",payInfo.getAmount()).params("orderId",payInfo.getOrderID()).params("requestId",orderNumber).params("notifyTime",payInfo.getTime()).params("userName",payInfo.getUserName()).params("productName",name).params("payType",4).params("sign",payInfo.getSign()).success(response -> handleResultHuawei(response)).build().post();JLogger.d("PayResultInfo================="+payInfo.getSign());} else {// 签名失败,需要查询订单状态:对于没有服务器的单机应用,调用查询订单接口查询;其他应用到开发者服务器查询订单状态。getPayDetail(orderNumber);}} else if (retCode == HMSAgent.AgentResultCode.ON_ACTIVITY_RESULT_ERROR|| retCode == PayStatusCodes.PAY_STATE_TIME_OUT|| retCode == PayStatusCodes.PAY_STATE_NET_ERROR) {// 需要查询订单状态:对于没有服务器的单机应用,调用查询订单接口查询;其他应用到开发者服务器查询订单状态。getPayDetail(orderNumber);} else {JLogger.d("pay: onResult: pay fail=" + retCode);// 其他错误码意义参照支付api参考}});// 将requestid缓存,供查询订单addRequestIdToCache(payReq.getRequestId());}private static void handleResultHuawei(String response) {final JSONObject jsonObject = JSON.parseObject(response);if (JConstants.OK.equals(jsonObject.getString("code"))) {JSONObject data = jsonObject.getJSONObject("data");final String sign = data.getString("sign");JLogger.d(sign);RestClient.builder().url("这个接口是验证获取的华为singn").params("result",RESULT).params("amount",AMOUNT).params("orderId",ORDERID).params("requestId",REQUESTID).params("notifyTime",NOTIFYTIME).params("userName",USERNAME).params("productName",PAYNAME).params("payType",4).params("appSign",sign)//就是这个appSign咯.success(response1 -> handleResultSign(response1)).build().post();}}private static void handleResultSign(String response) {JLogger.json(response);final JSONObject jsonObject = JSON.parseObject(response);if (JConstants.OK.equals(jsonObject.getString("code"))) {updatePaySuccessUI();}}private static void addRequestIdToCache(String requestId) {SharedPreferences sp = getActivity().getSharedPreferences("pay_request_ids", 0);sp.edit().putBoolean(requestId, false).commit();}/*** 创建普通支付请求对象* @param totalAmount 要支付的金额* @param orderNumber* @return 普通支付请求对象*/private static PayReq createPayReq(float totalAmount, String orderNumber, String name) {PayReq payReq = new PayReq();/*** 生成requestId*/DateFormat format = new java.text.SimpleDateFormat("yyyyMMddhhmmssSSS");int random= new SecureRandom().nextInt() % 100000;random = random < 0 ? -random : random;String requestId = format.format(new Date());requestId = String.format("%s%05d", requestId, random);/*** 生成总金额 | Generate Total Amount*/String amount = String.format("%.2f", totalAmount);//商品名称payReq.productName = name;//商品描述payReq.productDesc = "发型设计、形象设计、脸型分析";// 商户ID,来源于开发者联盟,也叫“支付id”payReq.merchantId = cpId;// 应用ID,来源于开发者联盟payReq.applicationID = appId;// 支付金额 | Amount paidpayReq.amount = amount;// 支付订单号payReq.requestId = orderNumber;// 国家码 | Country codepayReq.country = "CN";//币种payReq.currency = "CNY";// 渠道号payReq.sdkChannel = 1;// 回调接口版本号payReq.urlVer = "2";// 商户名称,必填,不参与签名。会显示在支付结果页面payReq.merchantName = "合肥聚美网络科技有限公司";//分类,必填,不参与签名。该字段会影响风控策略// X4:主题,X5:应用商店,    X6:游戏,X7:天际通,X8:云空间,X9:电子书,X10:华为学习,X11:音乐,X12 视频,// X31 话费充值,X32 机票/酒店,X33 电影票,X34 团购,X35 手机预购,X36 公共缴费,X39 流量充值payReq.serviceCatalog = "X5";//商户保留信息,选填不参与签名,支付成功后会华为支付平台会原样 回调CP服务端payReq.extReserved = "Here to fill in the Merchant reservation information";//对单机应用可以直接调用此方法对请求信息签名,非单机应用一定要在服务器端储存签名私钥,并在服务器端进行签名操作。// 在服务端进行签名的cp可以将getStringForSign返回的待签名字符串传给服务端进行签名payReq.sign = PaySignUtil.rsaSign(PaySignUtil.getStringForSign(payReq), pay_priv_key);return payReq;}private static void getPayDetail(final String reqId) {OrderRequest or = new OrderRequest();JLogger.d("checkPay: begin=" + reqId);or.setRequestId(reqId);or.setTime(String.valueOf(System.currentTimeMillis()));or.setKeyType("1");or.setMerchantId(cpId);or.sign = PaySignUtil.rsaSign(PaySignUtil.getStringForSign(or), pay_priv_key);HMSAgent.Pay.getOrderDetail(or, (retCode, checkPayResult) -> {JLogger.d("checkPay: requId="+reqId+"  retCode=" + retCode);if (checkPayResult != null && checkPayResult.getReturnCode() == retCode) {// 处理支付业务返回码 | Processing Payment Business return codeif (retCode == HMSAgent.AgentResultCode.HMSAGENT_SUCCESS) {boolean checkRst = PaySignUtil.checkSign(checkPayResult, pay_pub_key);if (checkRst) {// 支付成功,发放对应商品JLogger.d("checkPay: Pay successfully, distribution of goods");} else {// 验签失败,当支付失败处理JLogger.d("checkPay: Failed to verify signature, pay failed");}// 不需要再查询 | No more queriesremoveCacheRequestId(checkPayResult.getRequestId());} else if (retCode == PayStatusCodes.ORDER_STATUS_HANDLING|| retCode == PayStatusCodes.ORDER_STATUS_UNTREATED|| retCode == PayStatusCodes.PAY_STATE_TIME_OUT) {// 未处理完,需要重新查询。如30分钟后再次查询。超过24小时当支付失败处理JLogger.d("checkPay: Pay failed. errorCode="+retCode+"  errMsg=" + checkPayResult.getReturnDesc());} else if (retCode == PayStatusCodes.PAY_STATE_NET_ERROR) {// 网络失败,需要重新查询JLogger.d("checkPay: A network problem caused the payment to fail. errorCode="+retCode+"  errMsg=" + checkPayResult.getReturnDesc());} else {// 支付失败,不需要再查询JLogger.d("checkPay: Pay failed. errorCode="+retCode+"  errMsg=" + checkPayResult.getReturnDesc());removeCacheRequestId(reqId);}} else {// 没有结果回来,需要重新查询。如30分钟后再次查询。超过24小时当支付失败处理JLogger.d("checkPay: Pay failed. errorCode="+retCode);}});}private static void removeCacheRequestId(String reqId) {SharedPreferences sp = getActivity().getSharedPreferences("pay_request_ids", 0);sp.edit().remove(reqId).commit();}private static void updatePaySuccessUI() {EventBus.getDefault().post(new StartOrderEvent());//发送消息给主线程,跳转到订单详情页}
}

上面的支付代码,在华为demo里也有,建议,先把私钥、公钥、AppID、cpid放到demo里看能否运行起来,再接入到项目中,省时省力。其实华为文档上建议把私钥放在开发者的服务器端,客户端请求,私钥生成这些处理放在服务器端处理,这样是为了安全起见哦。我们这边后端没写,只能放里面了。

这里支付做了简单的封装处理,需要支付的时候HuaWeiPay.pay(Float.parseFloat(price),orderNumber,name);写上这行代码,传进来的参数分别是价格、订单编号、和支付产品的名字

以上即是华为账号登录与华为支付了,这里总结起来容易,前几天弄的时候可是踩了不少坑,哈哈。

Android项目中集成华为账号登录、支付相关推荐

  1. android支付宝支付微信支付封装,如何在Android App中集成支付宝和微信支付功能

    前言 本文主要介绍如何在 Android App 里集成支付宝和微信支付的功能,文中将实现的步骤一步步介绍的非常详细,对同样遇到这个问题的朋友相信会是一个很好的参考,下面话不多说了,来一起看看详细的介 ...

  2. cordova 人脸识别,如何在Cordova项目中集成华为远程配置服务

    最近发现AGC远程配置服务支持Cordova了,于是自己在项目里试了下,集成还是非常简单的,推荐大家使用. 集成步骤 本地新建项目目录,目录下通过npm命令安装cordova环境. npm insta ...

  3. android项目中集成融云IM之实现消息提供者来显示群名

    融云的消息提供者可以用来设置群名,昵称,头像等等.由于套路都是一样的,正好现在做到显示群名这块.所以就说说这个,其他消息提供者跟这个是大同小异. 思路: 1.创建一个类,集成群组信息接口GroupIn ...

  4. 在android项目上集成libyuv库以及使用libyuv库完成camera的缩放,旋转,翻转,裁剪操作

    目录 一.下拉google官方的libyuv库代码 二.在android项目中集成libyuv库 1.环境配置 2.拷贝libyuv源码文件 ​编辑3.配置cmake libyuv相关的链接编译等 三 ...

  5. 【AGC】通过AGC认证服务在Android平台实现华为账号登录功能

    简介 AppGallery Connect认证服务提供了云侧服务和SDK,可以帮助开发者为应用快速构建安全可靠的用户认证系统,以便应用可以对用户进行身份认证.AppGallery Connect认证服 ...

  6. uniapp android原生,在uni-app项目中集成Android原生工程

    [TOC] # 在uni-app项目中集成Android原生工程 按照官方的方案,我们如果进行本地打包的话,需要重新创建一个Android原生工程,于是就会导致我们管理多个项目,切来切去的也麻烦. 经 ...

  7. 在原有Android项目中快速集成React Native

    前言 对于现有的大多数项目来说都不是从头构建的,而要在原有项目的基础上引入React Native则肯定和用react-native init xxx创建工程不同.因此下面就来说下具体操作.不过在真正 ...

  8. SpringBoot项目中集成第三方登录功能

    SpringBoot项目中集成第三方登录功能 引言 1 环境准备 2 代码实现 3 第三方平台认证申请 4 打包和部署项目 5 第三方平台登录认证测试 6 参考文章 引言 最近想把自己在公众号上介绍过 ...

  9. HarmonyOS应用开发JSAPI—js获取华为账号登录

    前置: Api:6 语言:js开发 添加编译依赖参考地址: 文档中心 需要权限: ohos.permission.INTERNET 开始: 1.创建项目: 2.示例代码 test.hml <di ...

最新文章

  1. 教程:14、系统性能分析
  2. Belkatalog CMS SQL 注入漏洞(图)
  3. AD数据采集的“数字滤波”:10个“软件滤波程序”
  4. Linux监听进程是否存在,并加入定时任务
  5. VMware Device/Credential Guard 不兼容
  6. 如何使用iOS AddressBook
  7. 前端经典面试题 不经典不要star!
  8. oracle实验七 答案,Oracle表的常用查询实验(七)
  9. 冬天来了,温暖甜品热饮海报设计psd模板,勾住你的胃!
  10. fork()成为负担,需要淘汰 | 极客头条
  11. 数据结构与算法之链式栈
  12. 临时变量、引用参数和const
  13. php://input
  14. java集合的相互转化(map,set,list,array)
  15. mysql2000 sp4_【sql2000 sp4补丁下载】sql2000 sp4补丁64位下载 官方版-七喜软件园
  16. 穷举法破解密码-方法详解
  17. C++中2、8、10、16进制数字的表示及计算
  18. AWVS安装(Windows)
  19. [经济管理]《余世维-有效沟通II》VOB AVI双版本下载及我的笔记
  20. Linux环境下无UI界面进行WEB认证

热门文章

  1. 阿里Java三面:分布式延时任务方案解析,长文一篇点通你
  2. 如何排查、解决那些长时间GC停顿的问题
  3. java如何90度旋转mp4文件,旋转MP4视频的方法
  4. win10鼠标灵敏度怎么调_吃鸡:和平精英2020灵敏度怎么调比较稳 2020最稳灵敏度设置攻略...
  5. python做考勤统计
  6. 用Python做垃圾分类代码
  7. Java实现N*N矩阵旋转(360度)
  8. AutoCAD 2008 创建闭合边界
  9. 老荒说数据结构---暴走二叉树
  10. 【技巧】苹果系统的一些快捷键