Android项目中集成华为账号登录、支付

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

先看下支付效果图:

 支付价格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);写上这行代码,传进来的参数分别是价格、订单编号、和支付产品的名字

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/49588.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

接入华为推送用API给iOS应用发消息时,如何获取access_token?

经常有开发小伙伴向我们提问关于使用华为推送给苹果手机推送消息的问题&#xff0c;那么华为推送到底支不支持苹果手机呢&#xff1f;答案是肯定的。 华为推送服务支持的设备详见下图&#xff1a; 苹果手机如何接入华为推送&#xff1f; 首先需要提前准备好开发环境&#xff…

[个性化设置]win11终端美化

1.开始界面搜索 终端 &#xff0c;右键点击运行框的边框&#xff0c;打开设置 2.点击左下角 打开JSON文件 3. 进入配置文件&#xff0c;下滑找到 defaults 4.在大括号内添加以下代码↓ "backgroundImage": " ", //图片路径 "backgroundImage…

Win11运行安卓超详细教程!芜湖起飞!

一、前提 Windows 11 版本号为 Build 22000.xxx 或更高版本。 您的电脑硬件 BIOS/UEFI 支持虚拟化功能。 二、支持 本教程适用于 Windows 11 正式版和预览版&#xff0c;包括 Dev 频道、Beta 频道和 Release Preview 频道。 本教程适用于搭载 Intel 和 AMD 等处理器的 Windows…

电脑技巧:分享8个Win11系统必备小技巧

目录 1、让任务栏显示“右键菜单” 2、任务栏置顶 3、还原经典右键菜单 4、Win11版任务管理器 5、新版AltTab 6、开始菜单不再卡 7、为Edge浏览器添加云母效果 8、自动切换日/夜模式 Win11在很多地方都做了调整&#xff0c;但由于涉及到诸多旧有习惯&#xff0c;再加上…

如何在工作中利用Prompt高效使用ChatGPT

导读 AI 不是来替代你的&#xff0c;是来帮助你更好工作。用better prompt使用chatgpt&#xff0c;替换搜索引擎&#xff0c;让你了解如何在工作中利用Prompt高效使用ChatGPT。 01背景 现在 GPT 已经开启了人工智能狂潮&#xff0c;不过是IT圈&#xff0c;还是金融圈。 一开…

操作系统:分享Win11几个实用小技巧,赶快收藏吧

目录 1、让任务栏显示“右键菜单” 2、任务栏置顶 3、还原经典右键菜单 4、Win11版任务管理器 5、新版AltTab 6、开始菜单不再卡 7、为Edge浏览器添加云母效果 8、自动切换日/夜模式 Win11在很多地方都做了调整&#xff0c;但由于涉及到诸多旧有习惯&#xff0c;再加上前期Bug的…

【高效开发工具系列】Windows 怎么使用 telnet

&#x1f49d;&#x1f49d;&#x1f49d;欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 非常期待和您一起在这个小…

Windows系统工具MSG的使用,给局域网内的其他电脑发消息

msg 将消息发送给用户。MSG {username | sessionname | sessionid | filename | *}[/SERVER:servername] [/TIME:seconds] [/V] [/W] [message]username 标识指定的用户名。sessionname 会话名。sessionid 会话 ID。filename 识别这样一…

什么是 prompts, completions, tokens and meta-learning /in-context-learning

从字面上看&#xff0c;任何文本都可以用作提示(prompts)——输入一些文本然后得到一些文本。 我们虽然知道 GPT-3 对随机字符串的处理很有趣&#xff0c;但是编写一个有效的提示才能更好的真正的让GPT理解我们要它做什么。 提示&#xff08;prompts&#xff09; Prompt是怎么…

ChatDoctor本地部署应用的实战方案

大家好,我是herosunly。985院校硕士毕业,现担任算法研究员一职,热衷于机器学习算法研究与应用。曾获得阿里云天池比赛第一名,CCF比赛第二名,科大讯飞比赛第三名。拥有多项发明专利。对机器学习和深度学习拥有自己独到的见解。曾经辅导过若干个非计算机专业的学生进入到算法…

电信青年员工踏上三千里数字化追梦之旅,数字员工为电信高质量发展注智赋能

导语&#xff1a; 近年来&#xff0c;广西电信紧紧围绕集团战略&#xff0c;聚焦产业数字化发展机遇&#xff0c;加强前瞻性技术研究和人工智能产业应用研究&#xff0c;为夯实高质量发展增添科技动力。 在数字中国建设的大背景下&#xff0c;广西电信全资子公司广西壮族自治区…

AI加速财务智能化,实在智能、优贲财税、楚云科技共探数字员工新未来

作为财务发展的最新前沿&#xff0c;智能财务正在逐步渗入日常工作中&#xff0c;加快企业数字化转型步伐&#xff0c;促进我国财务信息化建设的快速发展。在当前形势下&#xff0c;企业应如何进行数字化转型以重塑业务、财务和税务等关系&#xff0c;形成管理闭环&#xff0c;…

AI安全03:如何监督AI

前言 菜鸟入门中~请ChatGPT老师继续上文讨论的话题&#xff1a;如果AI监督AI&#xff0c;甚至AI攻击AI&#xff0c;那么人类应该为AI的行为设置哪些监控措施&#xff1f; 写在前面&#xff1a; 1 以下讨论均针对自然语言模型~ 2 是个菜鸟的空想&#xff0c;肯定会有说错的地…

卡塔尔世界杯起航了

卡塔尔世界杯&#xff0c;从申请成功之初&#xff0c;就充满了争议&#xff0c;卡塔尔夏天最低温度是35度&#xff0c;经过协调&#xff0c;挪到了冬天举行&#xff0c;但这正是欧洲各国联赛最忙的时候&#xff0c;导致很多球员不得不一周双赛&#xff0c;调整空间有限&#xf…

【我爱世界杯】伪球迷眼里的世界杯

大家好&#xff0c;我是【架构师李肯】&#xff0c;一个专注于嵌入式物联网架构设计的攻城狮。 文章目录 按理说聊一聊我和足球第一次热衷于关注世界杯后ying情时代的卡塔尔世界杯祝愿世界杯 按理说 嗯&#xff0c;按理说&#xff0c;我一个程序猿&#xff0c;既不踢球&#x…

卡塔尔世界杯︱足球游戏的打开方式

距离卡塔尔世界杯开始还有一周的时间&#xff0c;你为此做好什么准备了吗&#xff1f; 一些狂热的球迷为了追求极致的观感和身临其境感&#xff0c;不惜在电视、音响上下重金&#xff1b;也有一些为了享受世界杯热闹氛围的人&#xff0c;囤好零食&#xff0c;或是和好友早早约…

世界杯数据清单:真球迷看球必备,伪球迷速成指南(附数据amp;论文)

来源&#xff1a;大数据 本文共5583字&#xff0c;建议阅读10分钟。 本文基于数据从球队、球员、比赛三个方面与你聊世界杯的热门知识与冷知识&#xff0c;全面解读2018世界杯。 [ 导读 ]每隔4年都有那么1个月&#xff0c;无论是线上还是线下&#xff0c;不管是真球迷还是真球盲…

卡塔尔世界杯——你认为今年谁会是冠军?

本届世界杯从小组赛开始就爆冷不断&#xff0c;阿根廷在首场失利&#xff0c;德国小组赛没出线&#xff0c;五星巴西被非洲冠军摩洛哥给干趴下了&#xff0c;C罗止步4强&#xff0c;39岁的莫德里奇也被裁判终结了&#xff0c;谁才能是笑道最后的队伍&#xff1f;莫德里奇率领的…

上传用户头像-后端

每个网站中都有用户头像的上传功能&#xff0c;刚刚再刷后springboot项目有些心得分享一下&#xff0c;如某站上的电脑商城的项目为例&#xff0c;先给出它的数据库 其中avatar字段名就是用户存储在服务器端的图片的地址&#xff0c;这个表在上传用户头像时要更改的字段名是修改…