Android接入微信支付的方法
1、先在微信开放平台申请开发应用,微信开放平台会生成APP的唯一标识APPID。由于需要保证支付安全,需要在开放平台绑定商户应用包名和应用签名,设置好后才能正常发起支付。
2、注册APPID(这个可以放在项目的application里)
商户APP工程中引入微信JAR包,调用API前,需要先向微信注册您的APPID,代码如下:
finalIWXAPImsgApi=WXAPIFactory.createWXAPI(context,null); //将该app注册到微信 msgApi.registerApp("wxd930ea5d5a258f4f");
3、调用统一下单api生成预付单,获取到prepay_id后将参数再次签名传输给APP发起支付。
例:
下面代码中的订单号是需要后台生成的
Stringurl="https://api.mch.weixin.qq.com/pay/unifiedorder"; WXPrePostpost=newWXPrePost(); post.appid="你的appId"; post.mch_id="你的商户号"; post.nonce_str=StringUtils.genNonceStr();//随机字符串**1 post.body="商品名称"; post.detail="商品的描述"; post.out_trade_no=out_trade_no;//商户订单号**2 post.total_fee="商品价格";//单位是分 post.spbill_create_ip=getLocalIpAddress();//ip地址**3 post.notify_url="";//这里是后台接受支付结果通知的url地址 post.trade_type="APP"; post.sign=genPackageSign(post);//签名**4 ListfirstSignParams=getFirstSignParams(post); Stringxml=toXml(firstSignParams); Stringentity=null; try{ entity=newString(xml.getBytes(),"ISO8859-1"); byte[]buf=Util.httpPost(url,entity); if(buf!=null){ Stringcontent=newString(buf); Map map=decodeXml(content); if(map!=null){ //再次签名(参与签名的字段有:AppidpartnerIdprepayIdnonceStrTimeStamppackage) StringappId=""; StringprepayId=""; StringnonceStr=""; for(Map.Entry entry:map.entrySet()){ if("appid".equals(entry.getKey())){ appId=entry.getValue(); }elseif("prepay_id".equals(entry.getKey())){ prepayId=entry.getValue(); }elseif("nonce_str".equals(entry.getKey())){ nonceStr=entry.getValue(); } } Log.d(TAG,"run::"+appId+"/"+prepayId+"/"+nonceStr+"/"); StringTimeStamp=String.valueOf(genTimeStamp()); //ok获取二次签名 StringsecondPackageSign=genSecondPackageSign(getSecondSignParams(appId,prepayId,nonceStr,TimeStamp)); PayReqreq=newPayReq(); req.appId=appId; req.partnerId="商户号"; req.prepayId=prepayId; req.nonceStr=nonceStr; req.timeStamp=TimeStamp; req.packageValue="Sign=WXPay"; req.sign=secondPackageSign; req.extData="appdata";//optional //System.out.println("genPackageSign3:"+post.getSign()+"/"+secondPackageSign); //在支付之前,如果应用没有注册到微信,应该先调用IWXMsg.registerApp将应用注册到微信 mApi.sendReq(req); Log.d(TAG,"run:"+appId+"/"+prepayId+"/"+nonceStr+"/"+TimeStamp+"/"+secondPackageSign); } } }catch(Exceptione){ }
publicstaticbyte[]httpPost(Stringurl,Stringentity){ if(url==null||url.length()==0){ Log.e(TAG,"httpPost,urlisnull"); returnnull; } HttpClienthttpClient=getNewHttpClient(); HttpPosthttpPost=newHttpPost(url); try{ httpPost.setEntity(newStringEntity(entity)); httpPost.setHeader("Accept","application/json"); httpPost.setHeader("Content-type","application/json"); HttpResponseresp=httpClient.execute(httpPost); if(resp.getStatusLine().getStatusCode()!=HttpStatus.SC_OK){ Log.e(TAG,"httpGetfail,statuscode="+resp.getStatusLine().getStatusCode()); returnnull; } returnEntityUtils.toByteArray(resp.getEntity()); }catch(Exceptione){ Log.e(TAG,"httpPostexception,e="+e.getMessage()); e.printStackTrace(); returnnull; } }
//获取随机字符串的方法 publicstaticStringgenNonceStr(){ Randomrandom=newRandom(); returnMD5.getMessageDigest(String.valueOf(random.nextInt(10000)).getBytes()); }
privateStringtoXml(Listparams){ StringBuildersb=newStringBuilder(); sb.append(" "); for(inti=0;i "); returnsb.toString(); }"); sb.append(params.get(i).getValue()); sb.append(""+params.get(i).getName()+">"); } sb.append("
publicMapdecodeXml(Stringcontent){ try{ Map xml=newHashMap<>(); XmlPullParserparser=Xml.newPullParser(); parser.setInput(newStringReader(content)); intevent=parser.getEventType(); while(event!=XmlPullParser.END_DOCUMENT){ StringnodeName=parser.getName(); switch(event){ caseXmlPullParser.START_DOCUMENT: break; caseXmlPullParser.START_TAG: if(!"xml".equals(nodeName)){ xml.put(nodeName,parser.nextText()); } break; caseXmlPullParser.END_TAG: break; } event=parser.next(); } returnxml; }catch(Exceptione){ } returnnull; }
@NonNull privateListgetFirstSignParams(WXPrePostparams){ List packageParams=newLinkedList<>(); packageParams.add(newBasicNameValuePair("appid","appId")); packageParams.add(newBasicNameValuePair("body",params.body)); packageParams.add(newBasicNameValuePair("detail",params.detail)); packageParams.add(newBasicNameValuePair("mch_id","商户号")); packageParams.add(newBasicNameValuePair("nonce_str",params.nonce_str)); packageParams.add(newBasicNameValuePair("notify_url",params.notify_url)); packageParams.add(newBasicNameValuePair("out_trade_no",params.out_trade_no)); packageParams.add(newBasicNameValuePair("spbill_create_ip",params.spbill_create_ip)); packageParams.add(newBasicNameValuePair("total_fee",params.total_fee+"")); packageParams.add(newBasicNameValuePair("trade_type",params.trade_type)); packageParams.add(newBasicNameValuePair("sign",params.sign)); returnpackageParams; }
publicclassWXPrePost{ //必须带的参数 publicStringappid; //微信开放平台审核通过的应用APPID publicStringmch_id; //微信支付分配的商户号 publicStringnonce_str; //随机字符串,不长于32位。推荐随机数生成算法 publicStringsign; //签名,详见签名生成算法 publicStringbody; //商品描述交易字段格式根据不同的应用场景按照以下格式:APP——需传入应用市场上的APP名字-实际商品名称,天天爱消除-游戏充值。 publicStringout_trade_no; //商户系统内部的订单号,32个字符内、可包含字母,其他说明见商户订单号 publicinttotal_fee; //订单总金额,单位为分,详见支付金额 publicStringspbill_create_ip; //用户端实际ip publicStringnotify_url; //接收微信支付异步通知回调地址,通知url必须为直接可访问的url,不能携带参数。(后台提供的) publicStringtrade_type; //支付类型 //非必须携带的参数 publicStringdevice_info; //终端设备号(门店号或收银设备ID),默认请传"WEB" publicStringdetail; //商品名称明细列表 publicStringattach; //附加数据,在查询API和支付通知中原样返回,该字段主要用于商户携带订单的自定义数据 publicStringfee_type; //符合ISO4217标准的三位字母代码,默认人民币:CNY,其他值列表详见货币类型 // publicStringtime_start; //订单生成时间,格式为yyyyMMddHHmmss,如2009年12月25日9点10分10秒表示为20091225091010。其他详见时间规则 // publicStringtime_expire; //订单失效时间,格式为yyyyMMddHHmmss,如2009年12月27日9点10分10秒表示为20091227091010。其他详见时间规则注意:最短失效时间间隔必须大于5分钟 publicStringgoods_tag; //商品标记,代金券或立减优惠功能的参数,说明详见代金券或立减优惠 // publicStringlimit_pay; //no_credit--指定不能使用信用卡支付 publicStringgetAppid(){ returnappid; } publicvoidsetAppid(Stringappid){ this.appid=appid; } publicStringgetMch_id(){ returnmch_id; } publicvoidsetMch_id(Stringmch_id){ this.mch_id=mch_id; } publicStringgetNonce_str(){ returnnonce_str; } publicvoidsetNonce_str(Stringnonce_str){ this.nonce_str=nonce_str; } publicStringgetSign(){ returnsign; } publicvoidsetSign(Stringsign){ this.sign=sign; } publicStringgetBody(){ returnbody; } publicvoidsetBody(Stringbody){ this.body=body; } publicStringgetOut_trade_no(){ returnout_trade_no; } publicvoidsetOut_trade_no(Stringout_trade_no){ this.out_trade_no=out_trade_no; } publicintgetTotal_fee(){ returntotal_fee; } publicvoidsetTotal_fee(inttotal_fee){ this.total_fee=total_fee; } publicStringgetSpbill_create_ip(){ returnspbill_create_ip; } publicvoidsetSpbill_create_ip(Stringspbill_create_ip){ this.spbill_create_ip=spbill_create_ip; } publicStringgetNotify_url(){ returnnotify_url; } publicvoidsetNotify_url(Stringnotify_url){ this.notify_url=notify_url; } publicStringgetTrade_type(){ returntrade_type; } publicvoidsetTrade_type(Stringtrade_type){ this.trade_type=trade_type; } publicStringgetDevice_info(){ returndevice_info; } publicvoidsetDevice_info(Stringdevice_info){ this.device_info=device_info; } publicStringgetDetail(){ returndetail; } publicvoidsetDetail(Stringdetail){ this.detail=detail; } publicStringgetAttach(){ returnattach; } publicvoidsetAttach(Stringattach){ this.attach=attach; } publicStringgetFee_type(){ returnfee_type; } publicvoidsetFee_type(Stringfee_type){ this.fee_type=fee_type; } publicStringgetTime_start(){ returntime_start; } publicvoidsetTime_start(Stringtime_start){ this.time_start=time_start; } publicStringgetTime_expire(){ returntime_expire; } publicvoidsetTime_expire(Stringtime_expire){ this.time_expire=time_expire; } publicStringgetGoods_tag(){ returngoods_tag; } publicvoidsetGoods_tag(Stringgoods_tag){ this.goods_tag=goods_tag; } publicStringgetLimit_pay(){ returnlimit_pay; } publicvoidsetLimit_pay(Stringlimit_pay){ this.limit_pay=limit_pay; } }
这里给出的参数都是可以移动端自己获取到的,当然,最好是后台提供给我们,出于安全性考虑
支付完成,微信会回调WXPayEntryActivity,这里就不详细说了,微信文档说的很清晰
在WXPayEntryActivity的onResp()里面返回的微信支付的结果(注:这个结果不能作为我们购买商品成功与否的结果,要以微信回调给回台,然后回台告诉我们的支付结果为准)
if(resp.getType()==ConstantsAPI.COMMAND_PAY_BY_WX){ intcode=resp.errCode; switch(code){ case0: Log.d(TAG,"onPayFinish,errCode="+"支付成功"); //微信支付成功后去调后台,以后台返回的支付结果为准 //这里是微信支付完成后的回调,在这里请求后台,让他来告诉我们到底支付成功没。 break; case-1: Toast.makeText(this,"支付失败1",Toast.LENGTH_SHORT).show(); Log.d(TAG,"onPayFinish,errCode="+"支付失败1"); finish(); break; case-2: Toast.makeText(this,"支付取消",Toast.LENGTH_SHORT).show(); Log.d(TAG,"onPayFinish,errCode="+"支付取消"); finish(); break; default: //Toast.makeText(this,"支付失败2",Toast.LENGTH_SHORT).show(); Log.d(TAG,"onPayFinish,errCode="+"支付失败2"); setResult(RESULT_OK); finish(); break; } }
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持毛票票。