关于安卓端集成微信支付

1.创建应用的过程
https://pay.weixin.qq.com/guide/inapp_payment.shtml

2.Android Studio添加依赖
在build.gradle文件中,添加如下依赖即可:
1)带统计功能(我们公司用的是友盟,所以采用的是下面一种)

dependencies {
    implementation 'com.tencent.mm.opensdk:wechat-sdk-android-with-mta:+'
}

2)不带统计功能

dependencies {
    implementation 'com.tencent.mm.opensdk:wechat-sdk-android-without-mta:+'
}

3.依赖完成后,在清单文件中配置

<activity
    android:name=".wxapi.WXEntryActivity"
    android:exported="true"
    android:screenOrientation="portrait" />

<activity
     android:name=".wxapi.WXPayEntryActivity"
     android:exported="true"
     android:launchMode="singleInstance"
     android:screenOrientation="portrait"
     android:theme="@style/noStyle" />

这两个avtivity说白了就是继承了IWXAPIEventHandler微信回调监听的页面,方便微信调起和进入微信支付。

先看WXEntryActivity 这个页面:

public class WXEntryActivity extends Activity implements IWXAPIEventHandler {

    protected void onCreate(Bundle savedInstanceState) {
        IWXAPI iwxapi = WXAPIFactory.createWXAPI(this, Constants.WX_APP_ID);
        iwxapi.handleIntent(getIntent(), this);
        super.onCreate(savedInstanceState);
        finish();
    }

    public void onReq(BaseReq arg0) {
    }

    public void onResp(BaseResp resp) {
        if (resp.errCode == BaseResp.ErrCode.ERR_OK) {
            //发送成功
            EventBus.getDefault().post(new EventBusBean(Constants.APP_SHARE_SUCCESS));
        } else if (resp.errCode == BaseResp.ErrCode.ERR_USER_CANCEL) {
            //发送取消
            EventBus.getDefault().post(new EventBusBean(Constants.APP_SHARE_CANCEL));
        } else {
            //发送失败
            EventBus.getDefault().post(new EventBusBean(Constants.APP_SHARE_FAILURE));
        }
    }
}

和官方给的demo差不多,只不过在onResp时做了不同返回值的处理,可以更改为广播或者别的刷新方式。

再来看WXPayEntryActivity这个页面:

public class WXPayEntryActivity extends Activity implements IWXAPIEventHandler {
    private IWXAPI iwxapi;// IWXAPI 是第三方app和微信通信的openapi接口

    @Override
    public void onCreate(Bundle savedInstanceState) {
        iwxapi = WXAPIFactory.createWXAPI(this, Constants.WX_APP_ID);
        iwxapi.handleIntent(getIntent(), this);
        super.onCreate(savedInstanceState);
    }

    @Override
    protected void onNewIntent(Intent intent) {
        super.onNewIntent(intent);
        setIntent(intent);
        iwxapi.handleIntent(intent, this);
    }

    @Override
    public void onReq(BaseReq req) {
    }

    @Override
    public void onResp(BaseResp resp) {
        if (resp.errCode == BaseResp.ErrCode.ERR_OK) {
            //支付成功
            EventBus.getDefault().post(new EventBusBean(Constants.APP_PAY_SUCCESS));
        } else if (resp.errCode == BaseResp.ErrCode.ERR_USER_CANCEL) {
            //支付取消
            EventBus.getDefault().post(new EventBusBean(Constants.APP_PAY_CANCEL));
        } else {
            //支付失败
            EventBus.getDefault().post(new EventBusBean(Constants.APP_PAY_FAILURE));
        }
        finish();
    }

}

由于这个页面我没有在oncreate中就finish掉,在有些手机上退出支付会有闪屏(比如我们老大的小米手机…)所以自写一个style样式,去除这个问题

  <!--充值取消闪屏问题-->
    <style name="noStyle" parent="Theme.AppCompat.Light.NoActionBar">
        <item name="android:background">@color/tran_txt</item>
   <!--<item name="android:windowIsTranslucent">true</item>  8.0部分手机会和指定宽高的属性冲突-->
        <item name="android:windowNoTitle">true</item>
        <item name="android:activityOpenEnterAnimation">@null</item>
        <item name="android:activityOpenExitAnimation">@null</item>
        <item name="android:activityCloseEnterAnimation">@null</item>
        <item name="android:activityCloseExitAnimation">@null</item>
        <item name="android:taskOpenEnterAnimation">@null</item>
        <item name="android:taskOpenExitAnimation">@null</item>
        <item name="android:taskCloseEnterAnimation">@null</item>
        <item name="android:taskCloseExitAnimation">@null</item>
        <item name="android:taskToFrontEnterAnimation">@null</item>
        <item name="android:taskToFrontExitAnimation">@null</item>
        <item name="android:taskToBackEnterAnimation">@null</item>
        <item name="android:taskToBackExitAnimation">@null</item>
    </style>

4.调起微信支付
1)需要调取支付的页面也需要配置一个style样式(同上)否则也会造成闪屏。

2)应用需要打正式包,因为微信要检验签名文件,当然你也可以改官方申请渠道上的校验码,但是万一到时候上架没改回来。。。那就很操蛋了。

3)后台返回的参数需要手机端进行再次签名,否则调不起来(有些后台可能在返回的时候就做了一次签名,可以直接调起)

可以自己写一个工具类,支付的时候传入服务器返回的值

public class WeChatPayUtil {
    private Context context;
    private IWXAPI wxApi;// IWXAPI 是第三方app和微信通信的openapi接口

    public WeChatPayUtil(Context context) {
        this.context = context;
        //通过WXAPIFactory工厂,获取IWXAPI的实例
        wxApi = WXAPIFactory.createWXAPI(context, Constants.WX_APP_ID, true);
        //将应用的appId注册到微信
        wxApi.registerApp(Constants.WX_APP_ID);
    }

    // 支付
    public void toPay(PayReq req) {
        if (!wxApi.isWXAppInstalled()) {
            ToastUtil.mackToastSHORT("您尚未安装微信"), context);
            payErr();
            return;
        }

        if (!wxApi.isWXAppSupportAPI()) {
            ToastUtil.mackToastSHORT("当前版本不支持支付功能"), context);
            payErr();
            return;
        }

        //对参数重新拼接签名
        ArrayMap<String, String> paramsMap = new ArrayMap<>();
        paramsMap.put("appid", req.appId);
        paramsMap.put("noncestr", req.nonceStr);
        paramsMap.put("package", req.packageValue);
        paramsMap.put("partnerid", req.partnerId);
        paramsMap.put("prepayid", req.prepayId);
        paramsMap.put("timestamp", req.timeStamp);
        req.sign = getAppSign(paramsMap);

        boolean sendResult = wxApi.sendReq(req);
        LogUtil.e("支付状态:" + sendResult);
        if (!sendResult) {
            ToastUtil.mackToastSHORT("支付失败,请重试", context);
            payErr();
        }
    }

    //重新对后台返回的sign签名
    private String getAppSign(ArrayMap<String, String> paramsMap) {
        StringBuilder stringBuilder = new StringBuilder();
        for (Map.Entry<String, String> entry : paramsMap.entrySet()) {
            stringBuilder.append(entry.getKey());
            stringBuilder.append('=');
            stringBuilder.append(entry.getValue());
            stringBuilder.append('&');
        }

        String appSign = MD5Util.byteArrayToHex(stringBuilder.toString().getBytes()).toUpperCase();
        LogUtil.e(appSign);
        return appSign;
    }

    private void payErr() {
        EventBus.getDefault().post(new EventBusBean(Constants.APP_PAY_NO_TOAST));
    }

}

重新签名方法:

public static String byteArrayToHex(byte[] byteArray) {
        // 首先初始化一个字符数组,用来存放每个16进制字符
        char[] hexDigits = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
        // new一个字符数组,这个就是用来组成结果字符串的(解释一下:一个byte是八位二进制,也就是2位十六进制字符(2的8次方等于16的2次方))
        char[] resultCharArray = new char[byteArray.length * 2];
        // 遍历字节数组,通过位运算(位运算效率高),转换成字符放到字符数组中去
        int index = 0;
        for (byte b : byteArray) {
            resultCharArray[index++] = hexDigits[b >>> 4 & 0xf];
            resultCharArray[index++] = hexDigits[b & 0xf];
        }
        // 字符数组组合成字符串返回
        return new String(resultCharArray);
    }

服务器返回值:

 PayReq req = new PayReq();
 req.appId = Constants.WX_APP_ID;
 req.partnerId = credentialBean.getMerchantId();
 req.prepayId = credentialBean.getPrepayId();
 req.packageValue = "Sign=WXPay";
 req.nonceStr = credentialBean.getNonceStr();
 req.timeStamp = String.valueOf(System.currentTimeMillis() / 1000);
 req.sign = credentialBean.getSign();
 weChatPayUtil.toPay(req);

以上就是关于集成微信支付的总结,官方文档是真的坑,也是折腾了好久,希望能够让遇到同样问题的同志们能有一定的参考价值。。。

发布了4 篇原创文章 · 获赞 4 · 访问量 1408

猜你喜欢

转载自blog.csdn.net/heromrwang/article/details/82622549