BCPay { private void reqPaymentAsync(final BCReqParams.BCChannelTypes channelType, final String billTitle, final Integer billTotalFee, final String billNum, final Integer billTimeout, final String notifyUrl, final String returnUrl, final String cardNum, final String qrCodeMode, final String buyerId, final String couponId, final Map<String, String> optional, final Map<String, String> analysis, final BCCallback callback) { if (callback == null) { Log.w(TAG, "请初始化callback"); return; } payCallback = callback; BCCache.executorService.execute(new Runnable() { @Override public void run() { BCPayReqParams parameters; try { parameters = new BCPayReqParams(channelType); } catch (BCException e) { callback.done(new BCPayResult(BCPayResult.RESULT_FAIL, BCPayResult.APP_INTERNAL_EXCEPTION_ERR_CODE, BCPayResult.FAIL_EXCEPTION, e.getMessage())); return; } String paramValidRes = BCValidationUtil.prepareParametersForPay(billTitle, billTotalFee, billNum, optional, parameters); if (paramValidRes != null) { callback.done(new BCPayResult(BCPayResult.RESULT_FAIL, BCPayResult.APP_INTERNAL_PARAMS_ERR_CODE, BCPayResult.FAIL_INVALID_PARAMS, paramValidRes)); return; } parameters.billTimeout = billTimeout; parameters.analysis = analysis; parameters.notifyUrl = notifyUrl; parameters.returnUrl = returnUrl; parameters.cardNum = cardNum; parameters.qrPayMode = qrCodeMode; parameters.buyerId = buyerId; parameters.couponId = couponId; String payURL = BCHttpClientUtil.getBillPayURL(); BCHttpClientUtil.Response response = BCHttpClientUtil .httpPost(payURL, parameters.transToBillReqMapParams()); if (response.code == 200 || (response.code >= 400 && response.code < 500)) { String ret = response.content; Gson res = new Gson(); Type type = new TypeToken<Map<String, Object>>() { }.getType(); Map<String, Object> responseMap; try { responseMap = res.fromJson(ret, type); } catch (JsonSyntaxException ex) { callback.done(new BCPayResult(BCPayResult.RESULT_FAIL, BCPayResult.APP_INTERNAL_EXCEPTION_ERR_CODE, BCPayResult.FAIL_EXCEPTION, "JsonSyntaxException or Network Error:" + response.code + " # " + response.content)); return; } Integer resultCode = ((Double) responseMap.get("result_code")).intValue(); if (resultCode == 0) { if (mContextActivity != null) { BCCache.getInstance().billID = (String) responseMap.get("id"); if (BCCache.getInstance().isTestMode) { reqTestModePayment(billTitle, billTotalFee); return; } switch (channelType) { case WX_APP: reqWXPaymentViaAPP(responseMap); break; case ALI_APP: case BC_ALI_APP: reqAliPaymentViaAPP(responseMap); break; case UN_APP: case BC_APP: reqUnionPaymentViaAPP(responseMap); break; case BD_APP: reqBaiduPaymentViaAPP(responseMap); break; case BC_WX_WAP: reqWXWapPaymentViaWebView(responseMap); break; default: callback.done(new BCPayResult( BCPayResult.RESULT_UNKNOWN, resultCode, String.valueOf(responseMap.get("result_msg")), String.valueOf(responseMap.get("err_detail")), String.valueOf(responseMap.get("id")), responseMap.get("url") == null ? null : String.valueOf(responseMap.get("url")), responseMap.get("html") == null ? null : String.valueOf(responseMap.get("html")))); } } else { callback.done(new BCPayResult(BCPayResult.RESULT_FAIL, BCPayResult.APP_INTERNAL_EXCEPTION_ERR_CODE, BCPayResult.FAIL_EXCEPTION, "Context-Activity NP-Exception")); } } else { String serverMsg = String.valueOf(responseMap.get("result_msg")); String serverDetail = String.valueOf(responseMap.get("err_detail")); callback.done(new BCPayResult(BCPayResult.RESULT_FAIL, resultCode, serverMsg, serverDetail)); } } else { callback.done(new BCPayResult(BCPayResult.RESULT_FAIL, BCPayResult.APP_INTERNAL_NETWORK_ERR_CODE, BCPayResult.FAIL_NETWORK_ISSUE, "Network Error:" + response.code + " # " + response.content)); } } }); } private  BCPay(); synchronized static BCPay getInstance(Context context); static String initWechatPay(Context context, String wechatAppID); static void clear(); static void detachWechat(); static void detachBaiduPay(); static boolean isWXPaySupported(); static boolean isWXAppInstalledAndSupported(); void reqPaymentAsync(final PayParams payParam, final BCCallback callback); void reqWXPaymentAsync(final String billTitle, final Integer billTotalFee,
                                  final String billNum,
                                  final Map<String, String> optional, final BCCallback callback); void reqAliPaymentAsync(final String billTitle, final Integer billTotalFee,
                                   final String billNum,
                                   final Map<String, String> optional,
                                   final BCCallback callback); void reqUnionPaymentAsync(final String billTitle, final Integer billTotalFee,
                                     final String billNum,
                                     final Map<String, String> optional,
                                     final BCCallback callback); void reqBaiduPaymentAsync(final String billTitle, final Integer billTotalFee,
                                     final String billNum,
                                     final Map<String, String> optional,
                                     final BCCallback callback); @Deprecated void reqAliInlineQRCodeAsync(final String billTitle, final Integer billTotalFee,
                                        final String billNum, final Map<String, String> optional,
                                        final String returnUrl,
                                        final String qrPayMode,
                                        final BCCallback callback); void reqBCNativeAsync(final String billTitle, final Integer billTotalFee,
                                 final String billNum, final Map<String, String> optional,
                                 final Boolean genQRCode, final Integer qrCodeWidth,
                                 final BCCallback callback); void prefund(final RefundParams params, final BCCallback callback); void sendSmsCode(final String phone, final BCCallback callback); void subscribe(final BCSubscription params, final String smsId, final String smsCode,
                          final String couponCode, final BCCallback callback); void cancelSubscription(final String sid, final BCCallback callback);  }
@Test public void testReqPaymentAsyncParamsInvalid() throws Exception { Object[][] test = new Object[][]{ new Object[]{BCReqParams.BCChannelTypes.JD_WAP, null, null, null}, new Object[]{BCReqParams.BCChannelTypes.WX_APP, null, null, null}, new Object[]{BCReqParams.BCChannelTypes.ALI_APP, "试一个很长的title--参数公共返回参数取值及含义参见支付公共返回参数部分", null, null}, new Object[]{BCReqParams.BCChannelTypes.UN_APP, "正常title", null, null}, new Object[]{BCReqParams.BCChannelTypes.BD_APP, "正常title", -1, null}, }; for (Object[] objects : test) { BCPay.PayParams payParams = new BCPay.PayParams(); payParams.channelType = (BCReqParams.BCChannelTypes)objects[0]; payParams.billTitle = (String)objects[1]; payParams.billTotalFee = (Integer)objects[2]; payParams.billNum = (String)objects[3]; final CountDownLatch localLatch = new CountDownLatch(1); pay.reqPaymentAsync(payParams, new BCCallback() { @Override public void done(BCResult result) { Assert.assertTrue(result instanceof BCPayResult); BCPayResult payResult = (BCPayResult)result; Assert.assertEquals(BCPayResult.RESULT_FAIL, payResult.getResult()); Assert.assertTrue(payResult.getErrCode() == BCPayResult.APP_INTERNAL_EXCEPTION_ERR_CODE || payResult.getErrCode() == BCPayResult.APP_INTERNAL_PARAMS_ERR_CODE); Assert.assertTrue(payResult.getErrMsg().equals(BCPayResult.FAIL_EXCEPTION) || payResult.getErrMsg().equals(BCPayResult.FAIL_INVALID_PARAMS)); localLatch.countDown(); } }); localLatch.await(2000, TimeUnit.MILLISECONDS); } }
@Test public void testReqPaymentAsyncNetworkError() throws Exception { final BCHttpClientUtil.Response response = new BCHttpClientUtil.Response(); response.code = 400; response.content = "mocked"; PowerMockito.stub(PowerMockito.method(BCHttpClientUtil.class, "httpPost", String.class, Map.class)).toReturn(response); final BCPay.PayParams payParams = new BCPay.PayParams(); payParams.channelType = BCReqParams.BCChannelTypes.WX_APP; payParams.billTitle = "正常title"; payParams.billTotalFee = 3; payParams.billNum = "123456789ABCDE"; pay.reqPaymentAsync(payParams, new BCCallback() { @Override public void done(BCResult result) { Assert.assertTrue(result instanceof BCPayResult); BCPayResult payResult = (BCPayResult) result; Assert.assertEquals(BCPayResult.RESULT_FAIL, payResult.getResult()); Assert.assertEquals((Integer)BCPayResult.APP_INTERNAL_EXCEPTION_ERR_CODE, payResult.getErrCode()); Assert.assertEquals(BCPayResult.FAIL_EXCEPTION, payResult.getErrMsg()); latch.countDown(); } }); latch.await(2000, TimeUnit.MILLISECONDS); }
@Test public void testReqPaymentAsyncErrorFromServer() throws Exception { final BCHttpClientUtil.Response response = new BCHttpClientUtil.Response(); response.code = 200; response.content = "{\"result_msg\":\"PAY_FACTOR_NOT_SET\",\"err_detail\":\"支付宝参数: partner, seller_id, RSA密钥未配置\",\"result_code\":2}"; PowerMockito.stub(PowerMockito.method(BCHttpClientUtil.class, "httpPost", String.class, Map.class)).toReturn(response); final BCPay.PayParams payParams = new BCPay.PayParams(); payParams.channelType = BCReqParams.BCChannelTypes.WX_APP; payParams.billTitle = "正常title"; payParams.billTotalFee = 3; payParams.billNum = "123456789ABCDE"; Map<String, String> analysis = new HashMap<String, String>(); analysis.put("category","en"); payParams.analysis = analysis; pay.reqPaymentAsync(payParams, new BCCallback() { @Override public void done(BCResult result) { Assert.assertTrue(result instanceof BCPayResult); BCPayResult payResult = (BCPayResult) result; Assert.assertEquals(BCPayResult.RESULT_FAIL, payResult.getResult()); Assert.assertEquals((Integer) 2, payResult.getErrCode()); Assert.assertEquals("PAY_FACTOR_NOT_SET", payResult.getErrMsg()); Assert.assertEquals("支付宝参数: partner, seller_id, RSA密钥未配置", payResult.getDetailInfo()); latch.countDown(); } }); latch.await(2000, TimeUnit.MILLISECONDS); }