参考资料:https://pay.weixin.QQ.com/wiki/doc/api/app/app.php?chapter=8_5
资料下载:https://open.weixin.qq.com/cgi-bin/showdocument?action=dir_list&t=resource/res_list&verify=1&id=open1419319167&token=&lang=zh_CN
1.导入微信支付jar包
2.新建包wxapi,包下新建一个类WXPayEntryActivity,一定要用这个名称。
3.注册清单文件
<activity android:name=".wxapi.WXPayEntryActivity" android:exported="true" >4.调起微信支付
PRivate IWXAPI iwxapi; private PayReq payReq; //发起支付请求 private void startWxPay() { regToWx();//向微信注册 prePayReqParams();//准备参数 iwxapi.sendReq(payReq);//发起支付请求 } private void regToWx() { iwxapi = WXAPIFactory.createWXAPI(this, PayConstants.WX_APP_ID); iwxapi.registerApp(PayConstants.WX_APP_ID); } private void prePayReqParams() { payReq = new PayReq(); payReq.appId = PayConstants.WX_APP_ID;//应用appId,可由服务器给出 payReq.partnerId = PayConstants.MCH_ID;//商户id,可由服务器给出 payReq.prepayId = "";// TODO: 2016/10/24//预付id,服务器给出 payReq.packageValue = "Sign=WXPay";//固定值 payReq.nonceStr = getNonceStr();//随机字符串 Log.d("wx", "nonceStr: "+payReq.nonceStr); payReq.timeStamp = String.valueOf(getTimeStamp());//时间戳s Log.d("wx", "timeStamp: "+payReq.timeStamp); payReq.sign = genAppSign();//签名 Log.d("wx", "sign: "+payReq.sign); } //拼接的字段要按照字典顺序排序appid noncestr private String genAppSign() { StringBuilder sb = new StringBuilder(); sb.append("appid=").append(payReq.appId).append("&"); sb.append("noncestr=").append(payReq.nonceStr).append("&"); sb.append("package=").append(payReq.packageValue).append("&"); sb.append("partnerid=").append(payReq.partnerId).append("&"); sb.append("prepayid=").append(payReq.prepayId).append("&"); sb.append("timestamp=").append(payReq.timeStamp).append("&"); sb.append("key=").append(PayConstants.API_KEY);//商户APIKEY Log.d("wx", "genAppSign:"+sb.toString()); return md5Utils.getMessageDigest(sb.toString().getBytes()).toUpperCase();//微信要大写的 } private String getNonceStr() { Random random = new Random(); return MD5Utils.getMessageDigest(String.valueOf(random.nextInt(10000)).getBytes()); } private long getTimeStamp() { return System.currentTimeMillis() / 1000; }工具类
//MD5工具类public class MD5Utils { private MD5Utils() { } public static String getMessageDigest(byte[] buffer) { char hexDigits[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' }; try { MessageDigest mdTemp = MessageDigest.getInstance("MD5"); mdTemp.update(buffer); byte[] md = mdTemp.digest(); int j = md.length; char str[] = new char[j * 2]; int k = 0; for (byte byte0 : md) { str[k++] = hexDigits[byte0 >>> 4 & 0xf]; str[k++] = hexDigits[byte0 & 0xf]; } return new String(str); } catch (Exception e) { return null; } }}5.支付结果处理
实现IWXAPIEventHandler这个接口
//处理支付结果界面public class WXPayEntryActivity extends BaseActivity implements IWXAPIEventHandler { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_wx_pay_entry); IWXAPI wxapi = WXAPIFactory.createWXAPI(this, PayConstants.WX_APP_ID); wxapi.handleIntent(getIntent(),this); } @Override protected void initUi() { } @Override public void onReq(BaseReq baseReq) { } /** * 得到支付结果回调 */ @Override public void onResp(BaseResp baseResp) { int errCode = baseResp.errCode; Log.d("WX", "onResp: "+errCode); //0 成功 展示成功页面 //-1 错误 可能的原因:签名错误、未注册APPID、项目设置APPID不正确、注册的APPID与设置的不匹配、其他异常 //-2 用户取消 无需处理。发生场景:用户不支付了,点击取消,返回APP。 if (baseResp.getType() == ConstantsAPI.COMMAND_PAY_BY_WX){ AlertDialog.Builder builder = new AlertDialog.Builder(this); builder.setTitle("提示"); builder.setMessage("微信支付结果:"+baseResp.errStr +";code=" + String.valueOf(baseResp.errCode)); builder.show(); } }}6.如果实在客户端去获取prePayId(正常的华自己服务端给出),可能涉及到的一些方法:
//服务端微信统一下单操作在app端完成(服务器不给prePayId)public void wxUnifiedOrder(float totalMoney) { setActionId(ACTION_WX_UNIFIED_ORDER); //appid mch_id nonce_str sign body out_trade_no total_fee spbill_create_ip notify_url trade_type HashMap<String, String> params = new HashMap<>(); params.put("appid", PayConstants.WX_APP_ID);//微信开放平台审核通过的应用APPID String body = "问兔-购买商品"; params.put("body", body);//天天爱消除-游戏充值 params.put("mch_id", PayConstants.WX_MCH_ID);//微信支付分配的商户号 String nonceStr = PayUtils.getNonceStr(); params.put("nonce_str", nonceStr);//随机字符串,不长于32位。推荐随机数生成算法 params.put("notify_url", NetWorkCons.WX_PAY_NOTIFICATION_URL);//接收微信支付异步通知回调地址,通知url必须为直接可访问的url,不能携带参数。 String wxOrderId = PayUtils.getWxOrderId(); params.put("out_trade_no", wxOrderId);//商户系统内部的订单号,32个字符内、可包含字母, 其他说明见商户订单号 String ip = getLocalHostIP(); params.put("spbill_create_ip", ip);//用户端实际ip String payType = "APP"; params.put("trade_type", payType);//支付类型 String total = String.valueOf((Math.round(totalMoney*100))); params.put("total_fee", total);//订单总金额,单位为分,详见支付金额 UnifiedOrderParams orderParams = new UnifiedOrderParams(); orderParams.appid = PayConstants.WX_APP_ID; orderParams.body = body; orderParams.mch_id = PayConstants.WX_MCH_ID; orderParams.nonce_str = nonceStr; orderParams.notify_url = NetWorkCons.WX_PAY_NOTIFICATION_URL; orderParams.out_trade_no = wxOrderId; orderParams.spbill_create_ip = ip; orderParams.trade_type = payType; orderParams.total_fee = total; String wxSign = getWxSign(orderParams); Log.d("wx", "firstSign=" + wxSign); params.put("sign", wxSign);//签名,参数值要按照ascall码(字典顺序)排序才行! String xml = toXml(params); Log.d("wx", "xml=" + xml); OkHttpUtil.doPost(NetWorkCons.WX_UNIFIED_ORDER_URL, xml, this); } //签名 private String getWxSign(UnifiedOrderParams params) { StringBuilder sb = new StringBuilder(); sb.append("appid").append("=").append(params.appid).append("&"); sb.append("body").append("=").append(params.body).append("&"); sb.append("mch_id").append("=").append(params.mch_id).append("&"); sb.append("nonce_str").append("=").append(params.nonce_str).append("&"); sb.append("notify_url").append("=").append(params.notify_url).append("&"); sb.append("out_trade_no").append("=").append(params.out_trade_no).append("&"); sb.append("spbill_create_ip").append("=").append(params.spbill_create_ip).append("&"); sb.append("total_fee").append("=").append(params.total_fee).append("&"); sb.append("trade_type").append("=").append(params.trade_type).append("&"); sb.append("key=").append(PayConstants.WX_API_KEY); Log.d("wx", "signString=" + sb.toString()); return MD5Utils.getMessageDigest(sb.toString().getBytes()).toUpperCase(); } //获取本机ip private String getLocalHostIP() { try { Enumeration<NetworkInterface> en = NetworkInterface .getNetworkInterfaces(); // 遍历所用的网络接口 while (en.hasMoreElements()) { NetworkInterface nif = en.nextElement();// 得到每一个网络接口绑定的所有ip Enumeration<InetAddress> inet = nif.getInetAddresses(); // 遍历每一个接口绑定的所有ip while (inet.hasMoreElements()) { InetAddress ip = inet.nextElement(); if (!ip.isLoopbackAddress() && (ip instanceof Inet4Address)) { Log.d("IP=", ip.getHostAddress()); return ip.getHostAddress(); } } } } catch (SocketException e) { Log.e("IP", "获取本地ip地址失败"); e.printStackTrace(); } return null; } //将参数封装为xml格式的向微信服务器请求prePayId private String toXml(HashMap<String, String> params) { StringBuilder sb = new StringBuilder(); sb.append("<xml>"); for (Map.Entry<String, String> entry : params.entrySet()) { sb.append("<").append(entry.getKey()).append(">"); sb.append(entry.getValue()); sb.append("</").append(entry.getKey()).append(">"); } sb.append("</xml>"); return sb.toString(); } //解析微信返回的订单号 getDataFromXml(new ByteArrayInputStream(jsonString.getBytes())); public void getDataFromXml(InputStream is) { DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); try { DocumentBuilder db = dbf.newDocumentBuilder(); Document doc = db.parse(is); NodeList WordList = doc.getElementsByTagName("xml"); Log.d("wx", "共有" + wordList.getLength() + "个xml节点"); for (int i = 0; i < wordList.getLength(); i++) { Node aWord = wordList.item(i); Element elem = (Element) aWord; for (Node node = elem.getFirstChild(); node != null; node = node.getNextSibling()) { if (node.getNodeType() == Node.ELEMENT_NODE) { if (node.getFirstChild() == null) { continue; } String name = node.getNodeName(); if (name.equals("prepay_id")) { prePayId = node.getFirstChild().getNodeValue(); Log.d("wx", "prepay_id=" + prePayId); } else if (name.equals("return_code")) { returnCode = node.getFirstChild().getNodeValue(); Log.d("wx", "prepay_id=" + returnCode); } else if (name.equals("result_code")) { resultCode = node.getFirstChild().getNodeValue(); Log.d("wx", "prepay_id=" + resultCode); } } } if (!TextUtils.isEmpty(prePayId)) { payReq.prepayId = prePayId; } } } catch (Exception e) { e.printStackTrace(); } }新闻热点
疑难解答