Android支付宝支付封装代码
在做Android支付的时候肯定会用到支付宝支付,根据官方给出的demo做起来非常费劲,所以我们需要一次简单的封装。
封装的代码也很简单,就是将官网给的demo提取出一个类来方便使用。
publicclassAlipay{ //商户PID publicstaticfinalStringPARTNER="123456789"; //商户收款账号 publicstaticfinalStringSELLER="qibin0506@gmail.com"; //商户私钥,pkcs8格式 publicstaticfinalStringRSA_PRIVATE="rsa_private"; //支付宝公钥 publicstaticfinalStringRSA_PUBLIC="rsa_public"; privatestaticfinalintSDK_PAY_FLAG=1; privateWeakReference<Activity>mActivity; privateOnAlipayListenermListener; publicAlipay(Activityactivity){ mActivity=newWeakReference<Activity>(activity); } @SuppressLint("HandlerLeak") privateHandlermHandler=newHandler(){ publicvoidhandleMessage(Messagemsg){ if(msg.what==SDK_PAY_FLAG){ PayResultpayResult=newPayResult((String)msg.obj); //支付宝返回此次支付结果及加签,建议对支付宝签名信息拿签约时支付宝提供的公钥做验签 StringresultInfo=payResult.getResult(); StringresultStatus=payResult.getResultStatus(); //判断resultStatus为“9000”则代表支付成功,具体状态码代表含义可参考接口文档 if(TextUtils.equals(resultStatus,"9000")){ if(mListener!=null)mListener.onSuccess(); }else{ //判断resultStatus为非“9000”则代表可能支付失败 //“8000”代表支付结果因为支付渠道原因或者系统原因还在等待支付结果确认, //最终交易是否成功以服务端异步通知为准(小概率状态) if(TextUtils.equals(resultStatus,"8000")){ if(mListener!=null)mListener.onWait(); }else{ //其他值就可以判断为支付失败,包括用户主动取消支付,或者系统返回的错误 if(mListener!=null)mListener.onCancel(); } } } } }; /** *支付 * *@paramtitle标题不能为空或者“” *@paramdesc描述不能为空或者“” *@paramprice价格不能为空或者“” *@paramsn商品唯一货号不能为空或者“” *@paramurl服务器回调url不能为空或者“” */ publicvoidpay(Stringtitle,Stringdesc,Stringprice,Stringsn,Stringurl){ //订单 StringorderInfo=getOrderInfo(title,desc,price,sn,url); //对订单做RSA签名 Stringsign=sign(orderInfo); try{ //仅需对sign做URL编码 sign=URLEncoder.encode(sign,"UTF-8"); }catch(UnsupportedEncodingExceptione){ e.printStackTrace(); } //完整的符合支付宝参数规范的订单信息 finalStringpayInfo=orderInfo+"&sign=\""+sign+"\"&" +getSignType(); RunnablepayRunnable=newRunnable(){ @Override publicvoidrun(){ Activityactivity=mActivity.get(); if(activity==null)return; //构造PayTask对象 PayTaskalipay=newPayTask(activity); //调用支付接口,获取支付结果 Stringresult=alipay.pay(payInfo); Messagemsg=newMessage(); msg.what=SDK_PAY_FLAG; msg.obj=result; mHandler.sendMessage(msg); } }; //必须异步调用 ThreadpayThread=newThread(payRunnable); payThread.start(); } /** *createtheorderinfo.创建订单信息 * */ publicStringgetOrderInfo(Stringsubject,Stringbody,Stringprice, Stringsn,Stringurl){ //签约合作者身份ID StringorderInfo="partner="+"\""+PARTNER+"\""; //签约卖家支付宝账号 orderInfo+="&seller_id="+"\""+SELLER+"\""; //商户网站唯一订单号 orderInfo+="&out_trade_no="+"\""+sn+"\""; //商品名称 orderInfo+="&subject="+"\""+subject+"\""; //商品详情 orderInfo+="&body="+"\""+body+"\""; //商品金额 orderInfo+="&total_fee="+"\""+price+"\""; //服务器异步通知页面路径 orderInfo+="¬ify_url="+"\""+url+"\""; //服务接口名称,固定值 orderInfo+="&service=\"mobile.securitypay.pay\""; //支付类型,固定值 orderInfo+="&payment_type=\"1\""; //参数编码,固定值 orderInfo+="&_input_charset=\"utf-8\""; //设置未付款交易的超时时间 //默认30分钟,一旦超时,该笔交易就会自动被关闭。 //取值范围:1m~15d。 //m-分钟,h-小时,d-天,1c-当天(无论交易何时创建,都在0点关闭)。 //该参数数值不接受小数点,如1.5h,可转换为90m。 orderInfo+="&it_b_pay=\"30m\""; //extern_token为经过快登授权获取到的alipay_open_id,带上此参数用户将使用授权的账户进行支付 //orderInfo+="&extern_token="+"\""+extern_token+"\""; //支付宝处理完请求后,当前页面跳转到商户指定页面的路径,可空 orderInfo+="&return_url=\"m.alipay.com\""; //调用银行卡支付,需配置此参数,参与签名,固定值(需要签约《无线银行卡快捷支付》才能使用) //orderInfo+="&paymethod=\"expressGateway\""; returnorderInfo; } /** *signtheorderinfo.对订单信息进行签名 * *@paramcontent *待签名订单信息 */ publicStringsign(Stringcontent){ returnSignUtils.sign(content,RSA_PRIVATE); } /** *getthesigntypeweuse.获取签名方式 * */ publicStringgetSignType(){ return"sign_type=\"RSA\""; } publicvoidsetListener(OnAlipayListenerl){ mListener=l; } /** *支付回调接口 * *@authorlenovo * */ publicstaticclassOnAlipayListener{ /** *支付成功 */ publicvoidonSuccess(){} /** *支付取消 */ publicvoidonCancel(){} /** *等待确认 */ publicvoidonWait(){} } } finalclassBase64{ privatestaticfinalintBASELENGTH=128; privatestaticfinalintLOOKUPLENGTH=64; privatestaticfinalintTWENTYFOURBITGROUP=24; privatestaticfinalintEIGHTBIT=8; privatestaticfinalintSIXTEENBIT=16; privatestaticfinalintFOURBYTE=4; privatestaticfinalintSIGN=-128; privatestaticcharPAD='='; privatestaticbyte[]base64Alphabet=newbyte[BASELENGTH]; privatestaticchar[]lookUpBase64Alphabet=newchar[LOOKUPLENGTH]; static{ for(inti=0;i<BASELENGTH;++i){ base64Alphabet[i]=-1; } for(inti='Z';i>='A';i--){ base64Alphabet[i]=(byte)(i-'A'); } for(inti='z';i>='a';i--){ base64Alphabet[i]=(byte)(i-'a'+26); } for(inti='9';i>='0';i--){ base64Alphabet[i]=(byte)(i-'0'+52); } base64Alphabet['+']=62; base64Alphabet['/']=63; for(inti=0;i<=25;i++){ lookUpBase64Alphabet[i]=(char)('A'+i); } for(inti=26,j=0;i<=51;i++,j++){ lookUpBase64Alphabet[i]=(char)('a'+j); } for(inti=52,j=0;i<=61;i++,j++){ lookUpBase64Alphabet[i]=(char)('0'+j); } lookUpBase64Alphabet[62]=(char)'+'; lookUpBase64Alphabet[63]=(char)'/'; } privatestaticbooleanisWhiteSpace(charoctect){ return(octect==0x20||octect==0xd||octect==0xa||octect==0x9); } privatestaticbooleanisPad(charoctect){ return(octect==PAD); } privatestaticbooleanisData(charoctect){ return(octect<BASELENGTH&&base64Alphabet[octect]!=-1); } /** *EncodeshexoctectsintoBase64 * *@parambinaryData *ArraycontainingbinaryData *@returnEncodedBase64array */ publicstaticStringencode(byte[]binaryData){ if(binaryData==null){ returnnull; } intlengthDataBits=binaryData.length*EIGHTBIT; if(lengthDataBits==0){ return""; } intfewerThan24bits=lengthDataBits%TWENTYFOURBITGROUP; intnumberTriplets=lengthDataBits/TWENTYFOURBITGROUP; intnumberQuartet=fewerThan24bits!=0?numberTriplets+1 :numberTriplets; charencodedData[]=null; encodedData=newchar[numberQuartet*4]; bytek=0,l=0,b1=0,b2=0,b3=0; intencodedIndex=0; intdataIndex=0; for(inti=0;i<numberTriplets;i++){ b1=binaryData[dataIndex++]; b2=binaryData[dataIndex++]; b3=binaryData[dataIndex++]; l=(byte)(b2&0x0f); k=(byte)(b1&0x03); byteval1=((b1&SIGN)==0)?(byte)(b1>>2) :(byte)((b1)>>2^0xc0); byteval2=((b2&SIGN)==0)?(byte)(b2>>4) :(byte)((b2)>>4^0xf0); byteval3=((b3&SIGN)==0)?(byte)(b3>>6) :(byte)((b3)>>6^0xfc); encodedData[encodedIndex++]=lookUpBase64Alphabet[val1]; encodedData[encodedIndex++]=lookUpBase64Alphabet[val2|(k<<4)]; encodedData[encodedIndex++]=lookUpBase64Alphabet[(l<<2)|val3]; encodedData[encodedIndex++]=lookUpBase64Alphabet[b3&0x3f]; } //formintegralnumberof6-bitgroups if(fewerThan24bits==EIGHTBIT){ b1=binaryData[dataIndex]; k=(byte)(b1&0x03); byteval1=((b1&SIGN)==0)?(byte)(b1>>2) :(byte)((b1)>>2^0xc0); encodedData[encodedIndex++]=lookUpBase64Alphabet[val1]; encodedData[encodedIndex++]=lookUpBase64Alphabet[k<<4]; encodedData[encodedIndex++]=PAD; encodedData[encodedIndex++]=PAD; }elseif(fewerThan24bits==SIXTEENBIT){ b1=binaryData[dataIndex]; b2=binaryData[dataIndex+1]; l=(byte)(b2&0x0f); k=(byte)(b1&0x03); byteval1=((b1&SIGN)==0)?(byte)(b1>>2) :(byte)((b1)>>2^0xc0); byteval2=((b2&SIGN)==0)?(byte)(b2>>4) :(byte)((b2)>>4^0xf0); encodedData[encodedIndex++]=lookUpBase64Alphabet[val1]; encodedData[encodedIndex++]=lookUpBase64Alphabet[val2|(k<<4)]; encodedData[encodedIndex++]=lookUpBase64Alphabet[l<<2]; encodedData[encodedIndex++]=PAD; } returnnewString(encodedData); } /** *DecodesBase64dataintooctects * *@paramencoded *stringcontainingBase64data *@returnArraycontaininddecodeddata. */ publicstaticbyte[]decode(Stringencoded){ if(encoded==null){ returnnull; } char[]base64Data=encoded.toCharArray(); //removewhitespaces intlen=removeWhiteSpace(base64Data); if(len%FOURBYTE!=0){ returnnull;//shouldbedivisiblebyfour } intnumberQuadruple=(len/FOURBYTE); if(numberQuadruple==0){ returnnewbyte[0]; } bytedecodedData[]=null; byteb1=0,b2=0,b3=0,b4=0; chard1=0,d2=0,d3=0,d4=0; inti=0; intencodedIndex=0; intdataIndex=0; decodedData=newbyte[(numberQuadruple)*3]; for(;i<numberQuadruple-1;i++){ if(!isData((d1=base64Data[dataIndex++])) ||!isData((d2=base64Data[dataIndex++])) ||!isData((d3=base64Data[dataIndex++])) ||!isData((d4=base64Data[dataIndex++]))){ returnnull; }//iffound"nodata"justreturnnull b1=base64Alphabet[d1]; b2=base64Alphabet[d2]; b3=base64Alphabet[d3]; b4=base64Alphabet[d4]; decodedData[encodedIndex++]=(byte)(b1<<2|b2>>4); decodedData[encodedIndex++]=(byte)(((b2&0xf)<<4)|((b3>>2)&0xf)); decodedData[encodedIndex++]=(byte)(b3<<6|b4); } if(!isData((d1=base64Data[dataIndex++])) ||!isData((d2=base64Data[dataIndex++]))){ returnnull;//iffound"nodata"justreturnnull } b1=base64Alphabet[d1]; b2=base64Alphabet[d2]; d3=base64Data[dataIndex++]; d4=base64Data[dataIndex++]; if(!isData((d3))||!isData((d4))){//CheckiftheyarePADcharacters if(isPad(d3)&&isPad(d4)){ if((b2&0xf)!=0)//last4bitsshouldbezero { returnnull; } byte[]tmp=newbyte[i*3+1]; System.arraycopy(decodedData,0,tmp,0,i*3); tmp[encodedIndex]=(byte)(b1<<2|b2>>4); returntmp; }elseif(!isPad(d3)&&isPad(d4)){ b3=base64Alphabet[d3]; if((b3&0x3)!=0)//last2bitsshouldbezero { returnnull; } byte[]tmp=newbyte[i*3+2]; System.arraycopy(decodedData,0,tmp,0,i*3); tmp[encodedIndex++]=(byte)(b1<<2|b2>>4); tmp[encodedIndex]=(byte)(((b2&0xf)<<4)|((b3>>2)&0xf)); returntmp; }else{ returnnull; } }else{//NoPADe.g3cQl b3=base64Alphabet[d3]; b4=base64Alphabet[d4]; decodedData[encodedIndex++]=(byte)(b1<<2|b2>>4); decodedData[encodedIndex++]=(byte)(((b2&0xf)<<4)|((b3>>2)&0xf)); decodedData[encodedIndex++]=(byte)(b3<<6|b4); } returndecodedData; } /** *removeWhiteSpacefromMIMEcontainingencodedBase64data. * *@paramdata *thebytearrayofbase64data(withWS) *@returnthenewlength */ privatestaticintremoveWhiteSpace(char[]data){ if(data==null){ return0; } //countcharactersthat'snotwhitespace intnewSize=0; intlen=data.length; for(inti=0;i<len;i++){ if(!isWhiteSpace(data[i])){ data[newSize++]=data[i]; } } returnnewSize; } } classPayResult{ privateStringresultStatus; privateStringresult; privateStringmemo; publicPayResult(StringrawResult){ if(TextUtils.isEmpty(rawResult)) return; String[]resultParams=rawResult.split(";"); for(StringresultParam:resultParams){ if(resultParam.startsWith("resultStatus")){ resultStatus=gatValue(resultParam,"resultStatus"); } if(resultParam.startsWith("result")){ result=gatValue(resultParam,"result"); } if(resultParam.startsWith("memo")){ memo=gatValue(resultParam,"memo"); } } } @Override publicStringtoString(){ return"resultStatus={"+resultStatus+"};memo={"+memo +"};result={"+result+"}"; } privateStringgatValue(Stringcontent,Stringkey){ Stringprefix=key+"={"; returncontent.substring(content.indexOf(prefix)+prefix.length(), content.lastIndexOf("}")); } /** *@returntheresultStatus */ publicStringgetResultStatus(){ returnresultStatus; } /** *@returnthememo */ publicStringgetMemo(){ returnmemo; } /** *@returntheresult */ publicStringgetResult(){ returnresult; } } classSignUtils{ privatestaticfinalStringALGORITHM="RSA"; privatestaticfinalStringSIGN_ALGORITHMS="SHA1WithRSA"; privatestaticfinalStringDEFAULT_CHARSET="UTF-8"; publicstaticStringsign(Stringcontent,StringprivateKey){ try{ PKCS8EncodedKeySpecpriPKCS8=newPKCS8EncodedKeySpec( Base64.decode(privateKey)); KeyFactorykeyf=KeyFactory.getInstance(ALGORITHM); PrivateKeypriKey=keyf.generatePrivate(priPKCS8); java.security.Signaturesignature=java.security.Signature .getInstance(SIGN_ALGORITHMS); signature.initSign(priKey); signature.update(content.getBytes(DEFAULT_CHARSET)); byte[]signed=signature.sign(); returnBase64.encode(signed); }catch(Exceptione){ e.printStackTrace(); } returnnull; } }
前面的几个常量是需要去支付宝官网获取的,获取后直接替换就ok,
其他的代码基本都是从demo中copy出来的,现在我们就将支付功能封装到了一个类中,那么如何使用呢?
Alipayalipay=newAlipay(OrderConfirmActivity.this); alipay.setListener(mAlipayListener); alipay.pay(desc,mOrder.getShopName(),String.valueOf(orderAmount),orderSn,url);/** *支付宝支付回调 */privateAlipay.OnAlipayListenermAlipayListener=newAlipay.OnAlipayListener(){@OverridepublicvoidonSuccess(){ onOrderSubmitSuccess(); }@OverridepublicvoidonCancel(){ onUserOrderCanceled(); Toast.makeText(OrderConfirmActivity.this,R.string.pay_failed, Toast.LENGTH_SHORT).show(); }@OverridepublicvoidonWait(){ } };
new出对象来,只需要调用pay方法就ok啦,不过支付的回调我们还是必须的,当然这个也不麻烦。这里说一下pay方法的几个参数,
- title支付的标题
- desc支付的描述
- price支付的金额
- sn商品的唯一货号
- url服务器的回调url
这几个参数在做支付的时候服务器都会给到,但是要注意一下,这几个参数都不能为空或者空字符串,否则会支付失败。
以上就是封装Android支付宝支付的代码,希望对大家的学习有所启发。