关于我做安卓微信支付3.0的总结,发给大家看看,让大家少走一些弯路

   前几天做了一个项目,有关于微信支付的一项,在网上找到的很多还是老的,走了很多弯路,经过三天的奋斗才做出来,下面就讲讲我在做微信支付时遇到的问题

  在做微信支付前,必须准备的几个有关微信支付的参数:

  1. APP_ID  就是你在微信公众平台申请后得到的

   2. MCH_ID  在商户平台注册得到的商户号

   3.API_KEY  api key这个微信官方API没有说明,就是一个坑人的货,这么重要的官方API也不说一下,就为这个让我搞了一个上午,具体就在 在商户平台  账户设置》API安全 哪里 设置,记住,新注册的用户必须重新设置一遍,不然在获取prepay_id时会报签名错误;

当这三个参数得到后,就可以执行微信支付了,下面我的的项目的一些代码

/*
* 生成随机字符串
*/

Map<String,String> resultunifiedorder;
private String genNonceStr() {
Random random = new Random();
return MD5.getMessageDigest(String.valueOf(random.nextInt(10000)).getBytes());
}
//生成时间戳
private long genTimeStamp() {
return System.currentTimeMillis() / 1000;
}

/*
* 生成预定单参数
*/
private String genProductArgs() {
String nonceStr = genNonceStr().toUpperCase();
SortedMap<Object,Object> parameters = new TreeMap<Object,Object>();  
       parameters.put("appid", Constants.APP_ID);  
       parameters.put("mch_id",  Constants.MCH_ID);  
       parameters.put("device_info", "APP-001");  
       parameters.put("body", getShopname());  
       parameters.put("nonce_str", nonceStr); 
       parameters.put("notify_url", "http://www.ruweiwang.com.cn/Shop/weixinNotify.action");
       parameters.put("out_trade_no",mQueRenDingDanJieMian.getOrderList().get(0).getOrderId());
       parameters.put("spbill_create_ip","120.24.250.188");
       parameters.put("total_fee", "1");
       parameters.put("trade_type", "APP");
       parameters.put("attach", getattach());          
       String characterEncoding = "UTF-8";  
       String mySign = createSign(characterEncoding,parameters); 

String xml="<xml>"
+"<appid>"+Constants.APP_ID+"</appid>" 
+"<mch_id>"+Constants.MCH_ID+"</mch_id>"
+"<device_info>"+"APP-001"+"</device_info>"
+"<body>"+getShopname()+"</body>"
+"<nonce_str>"+nonceStr+"</nonce_str>"
+"<notify_url>"+"http://www.ruweiwang.com.cn/Shop/weixinNotify.action"+"</notify_url>"
+"<out_trade_no>"+mQueRenDingDanJieMian.getOrderList().get(0).getOrderId()+"</out_trade_no>"
+"<spbill_create_ip>"+"120.24.250.188"+"</spbill_create_ip>"
+"<total_fee>"+1+"</total_fee>"
+"<trade_type>"+"APP"+"</trade_type>"
+"<attach>"+getattach()+"</attach>"
+"<sign>"+mySign+"</sign>"
+"</xml>";
return xml;
}

//上面生产第一次签名时先进行字体编码,因为我在网上看到有一些人提到订单名是中文会出现签名错误

//生产XML文件在官方的demo有一个方法,可以不按照我的方法写,各个参数代表什么在官方上有

//<attach>"+getattach()+"</attach>"这句话可以不加,因为是我做项目时需要的

/*
     * 微信支付签名算法sign 
     * @param characterEncoding 
     * @param parameters 
     * @return 
     */  
//主要是对sign的第一次签名,从网上直接复制过来的
    @SuppressWarnings("rawtypes")
public static String createSign(String characterEncoding,SortedMap<Object,Object> parameters){  
        StringBuffer sb = new StringBuffer();  
        Set es = parameters.entrySet();//所有参与传参的参数按照accsii排序(升序)  
        Iterator it = es.iterator();  
        while(it.hasNext()) {  
            Map.Entry entry = (Map.Entry)it.next();  
            String k = (String)entry.getKey();  
            Object v = entry.getValue();  
            if(null != v && !"".equals(v)   
                    && !"sign".equals(k) && !"key".equals(k)) {  
                sb.append(k + "=" + v + "&");  
            }  
        }  
        sb.append("key=" +Constants.API_KEY);
        //MD5Util这个文件也是从官方demo里面直接复制过来
        String sign = MD5Util.MD5Encode(sb.toString(), characterEncoding).toUpperCase();  
        return sign;  
    }    


//当上面的参数准备好后可以先得到微信支付的prepay_id 预支付ID,在发起支付时要用到

/*
* 得到预支付ID
* post形式
*/
private class GetPrepayIdTask extends AsyncTask<Void, Void, Map<String,String>> {
private ProgressDialog dialog;
@Override
protected void onPreExecute() {
dialog = ProgressDialog.show(QueRenDingDanActivity.this, getString(R.string.app_tip),getString(R.string.getting_prepayid));
}


@Override
protected void onPostExecute(Map<String,String> result) {
if (dialog != null) {
dialog.dismiss();
}
sb.append("prepay_id\n"+result.get("prepay_id")+"\n\n");
resultunifiedorder=result;

}


@Override
protected void onCancelled() {
super.onCancelled();
}


@Override
protected Map<String,String>  doInBackground(Void... params) {


String url = String.format("https://api.mch.weixin.qq.com/pay/unifiedorder");
String entity = genProductArgs();
byte[] buf = null;
try {
buf = Util.httpPost(url, new String(entity.getBytes(),"ISO8859-1"));
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}


String content = new String(buf);
Map<String,String> xml=decodeXml(content);
return xml;
}
}

//上面是联网请求的方法,具体调用可以在自己要调用的位置加上下面的代码

GetPrepayIdTask getPrepayId = new GetPrepayIdTask();
getPrepayId.execute();

//上面的发送中加了一句buf = Util.httpPost(url, new String(entity.getBytes(),"ISO8859-1")); 就是发送的时候要再进行一次编码,就为这句话我整了两天

如果有跟我一样获取预支付ID老是出现签名错误,而各个参数又检查无误,不妨加上这句试试,具体为什么,网上的解释是给自己当前的开发环境的

编码有关

//得到预支付ID后,可以准备支付的参数了



/*
* 生成支付参数
*/


private void genPayReq() {
String nonceStr = genNonceStr().toUpperCase();
String timeStamp=String.valueOf(genTimeStamp());
if(resultunifiedorder.get("prepay_id")!=null){
req.appId = Constants.APP_ID;
req.partnerId = Constants.MCH_ID;
req.prepayId = resultunifiedorder.get("prepay_id");
req.packageValue ="Sign=WXPay";
req.nonceStr =nonceStr;
req.timeStamp =timeStamp;

List<NameValuePair> signParams = new LinkedList<NameValuePair>();
       signParams.add(new BasicNameValuePair("appid", req.appId));
       signParams.add(new BasicNameValuePair("noncestr", req.nonceStr));
       signParams.add(new BasicNameValuePair("package", req.packageValue));
       signParams.add(new BasicNameValuePair("partnerid", req.partnerId));
       signParams.add(new BasicNameValuePair("prepayid", req.prepayId));
       signParams.add(new BasicNameValuePair("timestamp", req.timeStamp));


       req.sign = genAppSign(signParams);

sb.append("sign\n"+req.sign+"\n\n");

}
}
/
/参数生产后就可以发起支付,至于后续的内容看官方的API

//调起支付
private void sendPayReq() {
genPayReq();

final IWXAPI msgApi = WXAPIFactory.createWXAPI(
context,Constants.APP_ID, false);
msgApi.registerApp(Constants.APP_ID);
msgApi.sendReq(req);

}

//如果想一步完成可以将sendPayReq()放到得到预支付ID的方法中

//加在这一步既可以了

@Override
protected void onPostExecute(Map<String,String> result) {
if (dialog != null) {
dialog.dismiss();
}
sb.append("prepay_id\n"+result.get("prepay_id")+"\n\n");
resultunifiedorder=result;
sendPayReq();
}

/*
* 第二步签名生成
*/
private String genAppSign(List<NameValuePair> params) {
StringBuilder sb = new StringBuilder();


for (int i = 0; i < params.size(); i++) {
sb.append(params.get(i).getName());
sb.append('=');
sb.append(params.get(i).getValue());
sb.append('&');
}
sb.append("key=");
sb.append(Constants.API_KEY);


        this.sb.append("sign str\n"+sb.toString()+"\n\n");
String appSign = MD5.getMessageDigest(sb.toString().getBytes()).toUpperCase();
return appSign;
}

//上面的MD5文件在下载的微信官方demo里面直接复制过来


/*
* 解析XML格式,主要是用于解析从微信官方返回来的数据
*/
public Map<String,String> decodeXml(String content) {


try {
Map<String, String> xml = new HashMap<String, String>();
XmlPullParser parser = Xml.newPullParser();
parser.setInput(new StringReader(content));
int event = parser.getEventType();
while (event != XmlPullParser.END_DOCUMENT) {


String nodeName=parser.getName();
switch (event) {
case XmlPullParser.START_DOCUMENT:


break;
case XmlPullParser.START_TAG:


if("xml".equals(nodeName)==false){
xml.put(nodeName,parser.nextText());
}
break;
case XmlPullParser.END_TAG:
break;
}
event = parser.next();
}


return xml;
} catch (Exception e) {
}
return null;
}

//当以上完成后调不起支付界面可以检查以下几个方面

1.看一下你的WXPayEntryActivity类包名和类名是否一样

2.把你的项目打包成apk再安装到手机上,微信支付必须要到真机上测试,而且还要安装微信

3.以上两步还没有出现,就先把你的APK卸载掉,把微信也卸载掉,关机在重启,然后安装微信,安装项目APK,在调试

4.如果这样还没有出现,只能自己去找答案了,因为我到这一步就行了

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值