微信支付开发踩坑记录
在做微信支付时,虽然网上已经有了很多的文档和介绍,但是自己做了一遍还是遇到了很多坑,现在记录下来。
首先说一下大概的核心代码:
1、在微信开放平台下载了jar包后导入项目,建议顺便下载官方文档参考。虽然微信的开发文档有点坑,但有总比没有强。
2、按照开发文档,做好相关配置。下面正式开始自己的代码。
2.1、调用统一下单接口,该接口返回的是一个prepayId值。一般这一步都是由公司后台去进行,但有些公司可能需要自己写,现在写一下。
首先准备几个方法。
//获取上网ip地址:
public static String getLocalIpAddress(Context context){
try{// 获取wifi服务
WifiManager wifiManager = (WifiManager) context
.getSystemService(Context.WIFI_SERVICE);
if (!wifiManager.isWifiEnabled()){
//不能使用wifi
return getLocalIpAddress();
}else{WifiInfo wifiInfo = wifiManager.getConnectionInfo();
int i = wifiInfo.getIpAddress();
return int2ip(i);}
} catch (Exception ex){
return " 获取IP出错!!!!请保证是WIFI,或者请重新打开网络!\n" + ex.getMessage();}
}
public static String getLocalIpAddress() { try { for (Enumerationen = NetworkInterface.getNetworkInterfaces(); en.hasMoreElements();) { NetworkInterface intf = en.nextElement(); for (EnumerationenumIpAddr = intf.getInetAddresses(); enumIpAddr.hasMoreElements();) {
InetAddress inetAddress = enumIpAddr.nextElement();
if (!inetAddress.isLoopbackAddress() && inetAddress instanceof Inet4Address) {
//if (!inetAddress.isLoopbackAddress() && inetAddress instanceof Inet6Address) {
return inetAddress.getHostAddress().toString();
}
}
}
} catch (Exception e) {
}
return "";
}
这些代码是我在网上找到的,wifi的可以准确获取,但gps的貌似有时候会出问题,有知道的可以指点一下。
//生成随机数,需要md5加密:
private String genNonceStr()
{
Random random = new Random();
String md5 = "";
try
{
md5 = MD5Util.md5Encode(String.valueOf(random.nextInt(10000)));
} catch (Exception e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
return md5;
}
/***
* MD5加密 生成32位md5码
* @param 待加密字符串
* @return 返回32位md5码
*/
public static String md5Encode(String inStr) throws Exception {
MessageDigest md5 = null;
try {
md5 = MessageDigest.getInstance("MD5");
} catch (Exception e) {
System.out.println(e.toString());
e.printStackTrace();
return "";
}
byte[] byteArray = inStr.getBytes("UTF-8");
byte[] md5Bytes = md5.digest(byteArray);
StringBuffer hexValue = new StringBuffer();
for (int i = 0; i < md5Bytes.length; i++) {
int val = ((int) md5Bytes[i]) & 0xff;
if (val < 16) {
hexValue.append("0");
}
hexValue.append(Integer.toHexString(val));
}
return hexValue.toString();
}
/** * 获取签名 * @param params * @return */private String genAppSign(Listparams)
{
StringBuilder sb = new StringBuilder();
for (int i = 0; i < params.size(); i++)
{
sb.append(((BasicNameValuePair) params.get(i)).getName());
sb.append('=');
sb.append(((BasicNameValuePair) params.get(i)).getValue());
sb.append('&');
}
sb.append("key=");
sb.append(Config.WXMY);
String appSign = "";
try
{
appSign = MD5Util.md5Encode(sb.toString()).toUpperCase(Locale.CHINESE);
} catch (Exception e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
return appSign;
}
在获得后台返回的商品订单号后,开启线程去提交参数。
new Thread(){
public void run(){
try{
int factPaymoney = (int) (rechargeAmount* 100);//微信单位是分
String ip = NetworkUtils.getLocalIpAddress(PayActivity.this);//获取ip地址
String radom32=genNonceStr();//生成随机数
List<BasicNameValuePair>signParams = new LinkedList<BasicNameValuePair>();
//下面的参数你可以看官方文档查看意思,然后填入你自己的数据
signParams.add(new BasicNameValuePair("appid", Config.WXAPPID));
signParams.add(new BasicNameValuePair("body", reChargeName));
signParams.add(new BasicNameValuePair("mch_id", Config.MCHID));//
signParams.add(new BasicNameValuePair("nonce_str",radom32 ));
signParams.add(new BasicNameValuePair("notify_url",""));
signParams.add(new BasicNameValuePair("out_trade_no", paymentID));
signParams.add(new BasicNameValuePair("spbill_create_ip", ip));
signParams.add(new BasicNameValuePair("total_fee", 1+""));
signParams.add(new BasicNameValuePair("trade_type", "APP"));
StringBuilder xml = new StringBuilder();
xml.append("<xml>");
xml.append("<appid>" + Config.WXAPPID+ "</appid>");
xml.append("<body>"+reChargeName+"</body>");
xml.append("<mch_id>" + Config.MCHID+ "</mch_id>");
xml.append("<nonce_str>" +radom32+ "</nonce_str>");
xml.append("<notify_url>" + "自己的通知地址"+ "</notify_url>");
xml.append("<out_trade_no>" + paymentID+ "</out_trade_no>");
xml.append("<sign>"+ genAppSign(signParams)+"</sign>");
xml.append("<spbill_create_ip>"+ip+"</spbill_create_ip>");
xml.append("<total_fee>"+填入金额+"</total_fee>");
xml.append("<trade_type>APP</trade_type>");
xml.append("</xml>");
Stringxmls= new String(xml.toString().getBytes(), "UTF-8");
byte[] xmlbyte = xmls.getBytes("UTF-8");
URL url = new URL("https://api.mch.weixin.qq.com/pay/unifiedorder");//微信统一下单接口
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setDoOutput(true);
conn.setConnectTimeout(5000);
conn.setRequestMethod("POST");
conn.setRequestProperty("Content-Type","text/xml;charset=UTF-8");//此处需要设置你的编码格式,我用的utf-8,不然中文会乱码
conn.setRequestProperty("Content-Length",
String.valueOf(xmlbyte.length));
conn.getOutputStream().write(xmlbyte);
if (conn.getResponseCode() == 200){InputStream is = conn.getInputStream();// 获取返回数据
// 使用输出流来输出字符(可选)
ByteArrayOutputStream out = new ByteArrayOutputStream();
byte[] buf = new byte[1024];
int len;while ((len = is.read(buf)) != -1){out.write(buf, 0, len);}
String string = out.toString("UTF-8");
Message msg= new Message();
msg.what=1;
msg.obj=string;handler.sendMessage(msg);out.close();}
} catch (Exception e){e.printStackTrace();}
};}.start();
@SuppressLint("HandlerLeak")
private Handler handler = new Handler(){
public void handleMessage(Message msg) {
switch (msg.what) {
case 1:
try{
String prepar_id=msg.obj.toString();
int start=prepar_id.indexOf("prepay_id");
int end =prepar_id.indexOf("]]></prepay_id>");
prepar_id=prepar_id.substring(start+19, end);//此处获得我们需要的prepar_id字段
sendPayReq(prepar_id);//最后再次进行传参,发起支付
} catch (Exception e)
{
}
break;
}
};
};
2.2 发起支付
/**
* 调用微信支付页面
*/
private void sendPayReq(String prepayId)
{
api.registerApp(Config.WXAPPID);//此处踩过坑,以为写了appregister注册后不用在注册,事实是需要,所以不知道那个appregister有什么作用
genPayReq(prepayId);
api.sendReq(req);//此处成功后,会回调微信支付结果页面WXPayEntryActivity,这个在官方文档里有
}
/** * 生成签名参数 * @param prepayId */
private void genPayReq(String prepayId){
req.appId = Config.WXAPPID;// appid
req.partnerId = Config.MCHID;// 商户号
req.prepayId = prepayId;// 预支付交易会话ID
req.packageValue = "Sign=WXPay";// 扩展字段,固定的
req.nonceStr = genNonceStr();// 随机字符串
req.timeStamp = String.valueOf(genTimeStamp());// 时间戳
List<BasicNameValuePair> signParams = newLinkedList<BasicNameValuePair>();
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);//再次签名
}
/**
* 时间戳
*
* @return
*/
private long genTimeStamp()
{
return System.currentTimeMillis() / 1000;
}
以上就是微信支付开发的基本步骤了,记录一下,以备以后再用。