接入华为支付

1、华为支付相对微信支付又复杂点,同样包名,签名,appId都必须正确,不能修改
2、配置内容也多点,不过基本按照文档说明认真配置也是没问题的
3、华为支付是没demo源码参考,只有文档的示例代码,其他第三方一般都会有demo的

官方开发文档

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

按照文档一步步来,千万不要跳步骤,要不出问题不好排查
可能出问题的地方
在清单的application节点下增加APPID

  
    android:value="appid=xxx">  
 

记住里面是appid=xxx而不是去掉xxx

初始化Agent

1.在Application类中的onCreate方法中初始化HMS Agent套件

public class MyApplication extends Application {
    @Override
    public void onCreate() {        

            super.onCreate();
            HMSAgent.init(this);
    }} 

2.请务必在应用启动后的首个activity的onCreate方法中调用connect接口,确保HMS SDK和HMS APK的连接

HMSAgent.connect(this, new ConnectHandler() {
@Override
public void onConnect(int rst) {
    showLog("HMS connect end:" + rst);
}});    

注意是启动的第一个activity,要不会上架审核不成功的

调起华为支付

关键方法HuaweiPay.HuaweiPayApi.pay();
只好建个中间的Activity来集成,因为支付返回结果都是在onActivityResult获取。如果只有一个界面有华为支付的,就没必要了。
中间华为支付activity
示例代码:

public  abstract class HuaWeiActivity> extends BaseActivity implements ISetHw {
private static final String TAG = HuaWeiActivity.class.getName();
public HuaweiApiClient client;
private String outTradeNo;

//启动参数,区分startactivityforresult的处理结果
private final int REQ_CODE_PAY = 4001;
//作用同startactivityforresult方法中的requestcode
private static final int REQUEST_HMS_RESOLVE_ERROR = 1000;
private ShowPayDialog showPayDialog;

//初始化init华为支付
private void initClient() {

    //-------------------华为支付----------------------
    if(null == client){
        client = new HuaweiApiClient.Builder(this)
                .addApi(HuaweiPay.PAY_API)
                .addOnConnectionFailedListener(this)
                .addConnectionCallbacks(this)
                .build();
    }

    client.connect(this);
}


@Override
public void onResume() {
    super.onResume();
    initClient();
}

@Override
protected void onDestroy() {
    super.onDestroy();
    if (null != client) {
        client.disconnect();
    }
}

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    LogUtils.i("reCode", requestCode + " " + resultCode + "");
    if (requestCode == REQUEST_HMS_RESOLVE_ERROR) {
        if (resultCode == Activity.RESULT_OK) {
            int result = data.getIntExtra(EXTRA_RESULT, 0);
            if (result == ConnectionResult.SUCCESS) {
                LogUtils.i(TAG, "错误成功解决");
                if (!client.isConnecting() && !client.isConnected()) {
                    client.connect(this);
                }
            } else if (result == ConnectionResult.CANCELED) {
                LogUtils.i(TAG, "解决错误过程被用户取消");
            } else if (result == ConnectionResult.INTERNAL_ERROR) {
                LogUtils.i(TAG, "发生内部错误,重试可以解决");
                //CP可以在此处重试连接华为移动服务等操作,导致失败的原因可能是网络原因等
            } else {
                LogUtils.i(TAG, "未知返回码");
            }
        } else {
            LogUtils.i(TAG, "调用解决方案发生错误");
        }
    } else if (requestCode == REQ_CODE_PAY) {
        //当返回值是-1的时候表明用户支付调用成功
        if (resultCode == Activity.RESULT_OK) {
            //获取支付完成信息
            PayResultInfo payResultInfo = HuaweiPay.HuaweiPayApi.getPayResultInfoFromIntent(data);
            if (payResultInfo != null) {
                Map paramsa = new HashMap();
                if (PayStatusCodes.PAY_STATE_SUCCESS == payResultInfo.getReturnCode()) {
                    

                    //mHuaWeiPayPresenter.getHwPayNotify(b_tag, payResultInfo.getRequestId(), payResultInfo.getReturnCode(), success);
                    payHwSuccessNotify(payResultInfo.getReturnCode());
                    //paySuccess();
                    closeDialog();

                } else if (PayStatusCodes.PAY_STATE_CANCEL == payResultInfo.getReturnCode()) {
                    //支付失败,原因是用户取消了支付,可能是用户取消登录,或者取消支付
                    Log.i(TAG, "支付失败:用户取消" + payResultInfo.getErrMsg());
                    payHwFailNotify();

                } else {
                    //支付失败,其他一些原因
                    Log.i(TAG, "支付失败:" + payResultInfo.getErrMsg() + payResultInfo.getReturnCode());
                    payHwFailNotify();

                }
            } else {
                //支付失败
                payHwFailNotify();
            }
        } else {
            //当resultCode 为0的时候表明用户未登录,则CP可以处理用户不登录事件
            Log.i(TAG, "resultCode为0, 用户未登录 CP可以处理用户不登录事件");

        }
    }
}

protected abstract void payHwSuccessNotify(int payCode);
protected abstract void payHwFailNotify();

@Override
public void onConnected() {

}

@Override
public void onConnectionSuspended(int i) {
    //HuaweiApiClient异常断开连接, if 括号里的条件可以根据需要修改
    if (!this.isDestroyed() && !this.isFinishing()) {
        client.connect(this);
    }
    LogUtils.i(TAG, "HuaweiApiClient 连接异常断开成功");
}

@Override
public void onConnectionFailed(ConnectionResult connectionResult) {
    LogUtils.i(TAG, "HuaweiApiClient连接失败,错误码:" + connectionResult.getErrorCode());
    if (HuaweiApiAvailability.getInstance().isUserResolvableError(connectionResult.getErrorCode())) {
        final int errorCode = connectionResult.getErrorCode();
        new Handler(getMainLooper()).post(new Runnable() {
            @Override
            public void run() {
                // 此方法必须在主线程调用, xxxxxx.this 为当前界面的activity
                HuaweiApiAvailability.getInstance().resolveError(HuaWeiActivity.this, errorCode, REQUEST_HMS_RESOLVE_ERROR);
            }
        });
    } else {
        //其他错误码请参见API文档
    }
}

/**
 * 发起支付流程,开发者可以直接参照该方法写法
 */
protected void hwPay(HashMap params, String sign) {
    if (!client.isConnected()) {
        LogUtils.i(TAG, "支付失败,原因:HuaweiApiClient未连接");
        client.connect(this);
        return;
    }
    PendingResult payResult = HuaweiPay.HuaweiPayApi.pay(client, HwPayUtils.createPayReq(params, sign));
    payResult.setResultCallback(new PayResultCallback());
}

/**
 * 弹框相关
 *
 * @param showPayDialog
 */
public void setShowDialog(ShowPayDialog showPayDialog) {
    this.showPayDialog = showPayDialog;
}

/**
 * 支付接口调用的回调处理
 * 只有当处理结果中的返回码为 PayStatusCodes.PAY_STATE_SUCCESS的时候,CP需要继续调用支付
 * 否则就需要处理支付失败结果
 */
private class PayResultCallback implements ResultCallback {

    @Override
    public void onResult(PayResult result) {
        //支付鉴权结果,处理result.getStatus()
        Status status = result.getStatus();
        if (PayStatusCodes.PAY_STATE_SUCCESS == status.getStatusCode()) {
            //当支付回调 返回码为0的时候,表明支付流程正确,CP需要调用startResolutionForResult接口来进行后续处理
            //支付会先判断华为帐号是否登录,如果未登录,会先提示用户登录帐号。之后才会进行支付流程
            try {
                status.startResolutionForResult(HuaWeiActivity.this, REQ_CODE_PAY);

            } catch (IntentSender.SendIntentException e) {
                LogUtils.i(TAG, "启动支付失败" + e.getMessage());

            }
        } else {
            LogUtils.i(TAG, "支付失败,原因 :" + status.getStatusCode());

        }
    }
}



public void closeDialog() {
    if (null != showPayDialog) {
        showPayDialog.dialogDismiss();
    }
}}

仅仅是示例,把不用的删掉即可,
其中HuaweiPay.HuaweiPayApi.pay是调起华为支付,
PayResultCallback是是否能正常调起华为支付,
onActivityResult是调起后支付成功还是失败

HwPayUtils类

public class HwPayUtils {

private static final String TAG = "HwPayUtils";

/**
 * 获取华为的appId
 *
 * @param context
 * @return
 */
public static String getAppId(Context context) {
    String value = "";
    try {
        ApplicationInfo appInfo = context.getPackageManager().getApplicationInfo(context.getPackageName(),
                PackageManager.GET_META_DATA);
        value = appInfo.metaData.getString("com.huawei.hms.client.appid");
        String[] appidValue = value.split("=");
        return appidValue[appidValue.length-1];
    } catch (PackageManager.NameNotFoundException e) {
        e.printStackTrace();
    }
    return value;
}

/**
 * 生成支付信息map 包含
 * HwPayConstant.KEY_MERCHANTID  必选参数 商户id,开发者联盟网站生成的支付ID
 * HwPayConstant.KEY_APPLICATIONID 必选参数 应用的appid,开发者联盟网站生成
 * HwPayConstant.KEY_AMOUNT 必选参数 支付金额 string类型,精确到小数点后2位 比如 20.00
 * HwPayConstant.KEY_PRODUCTNAME 必选参数 商品名称 此名称将会在支付时显示给用户确认 注意:该字段中不能包含特殊字符,包括# " & / ? $ ^ *:)   ,
 * HwPayConstant.KEY_PRODUCTDESC 必选参数 商品描述 注意:该字段中不能包含特殊字符,包括# " & / ? $ ^ *:)   , |
 * HwPayConstant.KEY_REQUESTID  必选参数 请求订单号。其值由商户定义生成,用于标识一次支付请求,每次请求需唯一,不可重复。
 * 支付平台在服务器回调接口中会原样返回requestId的值。注意:该字段中不能包含特殊字符,包括# " & / ? $ ^ *:)   , .以及中文字符
 * HwPayConstant.KEY_SDKCHANNEL 必选参数 渠道信息。 取值如下:0 代表自有应用,无渠道 1 代表应用市场渠道 2 代表预装渠道 3 代表游戏中心渠道
 * HwPayConstant.KEY_URLVER 可选参数  回调接口版本号。如果传值则必须传2, 额外回调信息,具体参考接口文档
 * HwPayConstant.KEY_URL 可选参数 支付结果回调URL. 华为服务器收到后检查该应用有无在开发者联盟配置回调URL,如果配置了则使用应用配置的URL,否则使用此url
 * 作为该次支付的回调URL,建议直接 以配置在 华为开发者联盟的回调URL为准
 * HwPayConstant.KEY_COUNTRY 可选参数 国家码.建议无特殊需要,不传
 * HwPayConstant.KEY_CURRENCY 可选参数 币种 选填.建议无特殊需要不传此参数。目前仅支持CNY,默认CNY
 */
public static HashMap getPayInfo(PayHwOrderResult result) {
    HashMap params = new HashMap();
    PayHwOrderResult.DataBean obj = result.getData();

    params.put(HwPayConstant.KEY_MERCHANTID, obj.getMerchantId());
    params.put(HwPayConstant.KEY_APPLICATIONID, obj.getAppId());

    params.put(HwPayConstant.KEY_AMOUNT, obj.getAmount());
    params.put(HwPayConstant.KEY_PRODUCTNAME, obj.getProductName());
    params.put(HwPayConstant.KEY_PRODUCTDESC, obj.getProductDesc());

    params.put(HwPayConstant.KEY_REQUESTID, obj.getOutTradeNo());
    params.put(HwPayConstant.KEY_SDKCHANNEL, obj.getSdkChannel());
    params.put(HwPayConstant.KEY_URLVER, obj.getUrlver());
    params.put(HwPayConstant.KEY_URL, obj.getUrl());

    //不需要签名参数
    params.put(HwPayConstant.KEY_MERCHANTNAME, obj.getMerchantName());
    params.put(HwPayConstant.KEY_SERVICECATALOG, obj.getServiceCatalog());
    params.put(HwPayConstant.KEY_EXTRESERVED, obj.getExtReserved());
    return params;
}


/**
 * 封装json参数给后台
 *
 * @param params
 * @return
 */
public static String paramJson(HashMap params) {
    String value = "";
    try {
        JSONObject mJsonobjData = new JSONObject();
        mJsonobjData.put(HwPayConstant.KEY_MERCHANTID, params.get(HwPayConstant.KEY_MERCHANTID));
        mJsonobjData.put(HwPayConstant.KEY_APPLICATIONID, params.get(HwPayConstant.KEY_APPLICATIONID));
        mJsonobjData.put(HwPayConstant.KEY_AMOUNT, params.get(HwPayConstant.KEY_AMOUNT));
        mJsonobjData.put(HwPayConstant.KEY_PRODUCTNAME, params.get(HwPayConstant.KEY_PRODUCTNAME));
        mJsonobjData.put(HwPayConstant.KEY_PRODUCTDESC, params.get(HwPayConstant.KEY_PRODUCTDESC));

        mJsonobjData.put(HwPayConstant.KEY_REQUESTID, params.get(HwPayConstant.KEY_REQUESTID));
        mJsonobjData.put(HwPayConstant.KEY_SDKCHANNEL, params.get(HwPayConstant.KEY_SDKCHANNEL));
        mJsonobjData.put(HwPayConstant.KEY_URLVER, params.get(HwPayConstant.KEY_URLVER));
        mJsonobjData.put(HwPayConstant.KEY_URL, params.get(HwPayConstant.KEY_URL));

        value = mJsonobjData.toString();

    } catch (Exception e) {
        // TODO: handle exception
        e.printStackTrace();
    }

    return value;
}

/**
 * 生成PayReq对象,用来在进行支付请求的时候携带支付相关信息
 * payReq订单参数需要商户使用在华为开发者联盟申请的RSA私钥进行签名,强烈建议将签名操作在商户服务端处理,避免私钥泄露
 */
public static PayReq createPayReq(HashMap params, String sign) {

    PayReq payReq = new PayReq();

    //商品名称
    payReq.productName = (String) params.get(HwPayConstant.KEY_PRODUCTNAME);
    //商品描述
    payReq.productDesc = (String) params.get(HwPayConstant.KEY_PRODUCTDESC);
    // 商户ID:来源于开发者联盟的“支付ID”
    payReq.merchantId = (String) params.get(HwPayConstant.KEY_MERCHANTID);
    // 应用ID
    payReq.applicationID = (String) params.get(HwPayConstant.KEY_APPLICATIONID);
    // 支付金额
    payReq.amount = (String) params.get(HwPayConstant.KEY_AMOUNT);
    // 商户订单号:开发者在支付前生成,用来唯一标识一次支付请求
    payReq.requestId = (String) params.get(HwPayConstant.KEY_REQUESTID);
    // 渠道号
    payReq.sdkChannel = (Integer) params.get(HwPayConstant.KEY_SDKCHANNEL);
    // 回调接口版本号
    payReq.urlVer = (String) params.get(HwPayConstant.KEY_URLVER);
    payReq.url = (String) params.get(HwPayConstant.KEY_URL);
    LogUtils.i("hwPayUrl",payReq.url);
    LogUtils.i(TAG, payReq.productName + " " + payReq.productDesc + " " + payReq.merchantId + " " + payReq.applicationID + " "
            + payReq.amount + " " + payReq.requestId + " " + payReq.sdkChannel + " " + payReq.getUrlVer());
    //以上信息按照一定规则进行签名,建议CP在服务器端储存签名私钥,并在服务器端进行签名操作。

    payReq.sign = sign;

    // 商户名称,必填,不参与签名。开发者注册的公司名
    payReq.merchantName = (String) params.get(HwPayConstant.KEY_MERCHANTNAME);

    //分类,必填,不参与签名。该字段会影响风控策略
    // X4:主题,X5:应用商店,  X6:游戏,X7:天际通,X8:云空间,X9:电子书,X10:华为学习,X11:音乐,X12 视频,
    // X31 话费充值,X32 机票/酒店,X33 电影票,X34 团购,X35 手机预购,X36 公共缴费,X39 流量充值
    payReq.serviceCatalog = (String) params.get(HwPayConstant.KEY_SERVICECATALOG);
    //商户保留信息,选填不参与签名,支付成功后会华为支付平台会原样 回调CP服务端
    payReq.extReserved = (String) params.get(HwPayConstant.KEY_EXTRESERVED);

    return payReq;
}


/**
 * 将商户id,应用id, 商品名称,商品说明,支付金额,订单号,渠道号,回调地址版本号等信息按照key值升序排列后
 * 以key=value并以&的方式连接起来生成待签名的字符串
 *
 * @return
 */
public static String getNoSign(Map params) {
    //对参数按照key做升序排序,对map的所有value进行处理,转化成string类型
    //拼接成key=value&key=value&....格式的字符串
    StringBuffer content = new StringBuffer();
    // 按照key做排序
    List keys = new ArrayList(params.keySet());
    Collections.sort(keys);
    String value = null;
    Object object = null;
    for (int i = 0; i 

发表评论

您的邮箱地址不会被公开。 必填项已用 * 标注