android微信支付流程
在做android支付时确实令人崩溃的,希望这篇文章能给做微信支付的一些帮助;
1 我是用的android stuido 要用到demo中的几个类,在Util是提示不支持Apache HttpClient相关的类
解决的办法:在相应的module下的build.gradle中加入即可。
android {
useLibrary ‘org.apache.http.legacy’//手动添加
}
有时候会发现其实并么有什么作用,建议Clean Project/ReBuild Projiect/重启;
2 按照微信文档必须先要统一下单得到prepay_id 才能支付
https://pay.weixin.qq.com/wiki/doc/api/app/app.php?chapter=9_1
在做统一下单的时候注意一点就行:
sign:1 对参数按照key=value的格式,并按照参数名ASCII字典序排序如下:
2 拼接API密钥:在拼接密钥是 官网例子:stringSignTemp=”stringA&key=192006250b4c09247ec02edce69f6a2d”
这里的Key 是密钥,要在商户平台自己添加的(密钥一定要写对,不然返回会出签名错误)
3 在提交订单是会出现xml格式不对,要转换成xml提交
https://pay.weixin.qq.com/index.php/core/home/login?return_url=%2Findex.php
3 订单完成后返回的格式;(例子)
<xml>
<return_code><![CDATA[SUCCESS]]></return_code>
<return_msg><![CDATA[OK]]></return_msg>
<appid><![CDATA[wx2421b1c4370ec43b]]></appid>
<mch_id><![CDATA[10000100]]></mch_id>
<nonce_str><![CDATA[IITRi8Iabbblz1Jc]]></nonce_str>
<sign><![CDATA[7921E432F65EB8ED0CE9755F0E86D72F]]></sign>
<result_code><![CDATA[SUCCESS]]></result_code>
<prepay_id><![CDATA[wx201411101639507cbf6ffd8b0779950874]]></prepay_id>
<trade_type><![CDATA[APP]]></trade_type>
</xml>
4 到这一步就可以调用支付接口了
https://pay.weixin.qq.com/wiki/doc/api/app/app.php?chapter=8_5
在支付时会告知一些必要的信息;
以下是调用支付
IWXAPI api;
PayReq request = new PayReq();
request.appId = “wxd930ea5d5a258f4f”;
request.partnerId = “1900000109”;
request.prepayId= “1101000000140415649af9fc314aa427”,;
request.packageValue = “Sign=WXPay”;
request.nonceStr= “1101000000140429eb40476f8896f4c9”;
request.timeStamp= “1398746574”;
request.sign= “7FFECB600D7157C5AA49810D2D8F28BC2811827B”;
api.sendReq(req);//支付
这里的sign 一定要注意,这个sign是新生成的并不是订单返回的sign,要重新生成签名生成算法,不然会返回 “支付结果报错:errStr=null,code=-1”
签名:https://pay.weixin.qq.com/wiki/doc/api/app/app.php?chapter=4_3
4 记得在包名下边添加一个新的包,..**.wxapi 然会添加WXPayEntryActivity manifest进行注册,这个看Demo就可以;
在做微信支付一定要看他们的文档,而且要仔细看,完成以上基本就可以进行支付了,还有就是不要相信微信的Demo 看了就更蛋疼;
public class Pay {
private static final String TAG = "Pay";
private Context context;
private IWXAPI api;
private String signStr;
private String out_trade_no_str;
private String nonceStr;
private String weixinBody = "test";
private String trade_type = "APP";
public Pay(Context context) {
this.context = context;
api = WXAPIFactory.createWXAPI(context, Constants.APP_ID);
}
public void prePayID() {
GetPrepayIdTask getPrepayId = new GetPrepayIdTask();
getPrepayId.execute();
}
private class GetPrepayIdTask extends AsyncTask<Void, Void, Map<String, String>> {
private ProgressDialog dialog;
@Override
protected void onPreExecute() {
dialog = ProgressDialog.show(context, context.getString(R.string.app_tip), context.getString(R.string.getting_prepayid));
}
@Override
protected void onPostExecute(Map<String, String> result) {
if (dialog != null) {
dialog.dismiss();
}
if (result.get("return_code").equals("SUCCESS")) {
Toast.makeText(context, "开启支付成功", Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(context, "开启支付失败", Toast.LENGTH_SHORT).show();
}
}
@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 = Util.httpPost(url, entity);
String content = new String(buf);
Log.e("orion", content);
Map<String, String> xml = decodeXml(content);
String sign = xml.get("sign");
String return_code = xml.get("return_code");
String trade_type = xml.get("trade_type");
String result_code = xml.get("result_code");
String appid = xml.get("appid");
String mch_id = xml.get("mch_id");
String nonce_str = xml.get("nonce_str");
String prepay_id = xml.get("prepay_id");
String return_msg = xml.get("return_msg");
if (return_code.equals("SUCCESS")) {
PayReq request = new PayReq();
request.appId = appid;
request.partnerId = mch_id;
request.prepayId = prepay_id;
request.packageValue = "Sign=WXPay";
request.nonceStr = nonce_str;
request.timeStamp = String.valueOf(genTimeStamp());
List<NameValuePair> signParams = new LinkedList<NameValuePair>();
signParams.add(new BasicNameValuePair("appid", request.appId));
signParams.add(new BasicNameValuePair("noncestr", request.nonceStr));
/**
* 这里的package参数值必须是Sign=WXPay,否则IOS端调不起微信支付,
* (参数值是"prepay_id="+resultunifiedorder.get("prepay_id")的时候Android可以,IOS不可以)
*/
signParams.add(new BasicNameValuePair("package", request.packageValue));
/**注意二次签名这里不再是mch_id,变成了prepayid;*/
signParams.add(new BasicNameValuePair("partnerid", request.partnerId));
signParams.add(new BasicNameValuePair("prepayid", request.prepayId));
signParams.add(new BasicNameValuePair("timestamp", request.timeStamp));
request.sign = genPackageSign(signParams);
request.extData = "app data"; // optional
api.registerApp(Constants.APP_ID);
api.sendReq(request);
}
return xml;
}
}
Handler handler = new Handler() {
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
Log.i("========", msg.getData().getString("xml"));
}
};
private String genProductArgs() {
StringBuffer xml = new StringBuffer();
try {
genNonceStr();
genOutTradNo();
xml.append("</xml>");
List<NameValuePair> packageParams = new LinkedList<NameValuePair>();
packageParams.add(new BasicNameValuePair("appid", Constants.APP_ID));
packageParams.add(new BasicNameValuePair("body", weixinBody));
packageParams.add(new BasicNameValuePair("mch_id", Constants.MCH_ID));
packageParams.add(new BasicNameValuePair("nonce_str", nonceStr));
packageParams.add(new BasicNameValuePair("notify_url", "http://wxpay.weixin.qq.com/pub_v2/pay/notify.v2.php"));
packageParams.add(new BasicNameValuePair("out_trade_no", out_trade_no_str));
packageParams.add(new BasicNameValuePair("spbill_create_ip", getAddIP()));
packageParams.add(new BasicNameValuePair("total_fee", "1"));
packageParams.add(new BasicNameValuePair("trade_type", trade_type));
genPackageSign(packageParams);
packageParams.add(new BasicNameValuePair("sign", signStr));
String xmlstring = toXml(packageParams);
return xmlstring;
} catch (Exception e) {
Log.e(TAG, "genProductArgs fail, ex = " + e.getMessage());
return null;
}
}
private String getAddIP() {
String str = Tools.getLocalIpAddress(context);
Log.i("IP", str);
return str;
}
private String genNonceStr() {
Random random = new Random();
nonceStr = MD5.getMessageDigest(String.valueOf(random.nextInt(10000)).getBytes());
return nonceStr;
}
private long genTimeStamp() {
long time = System.currentTimeMillis() / 1000;
return time;
}
private String genOutTradNo() {
Random random = new Random();
out_trade_no_str = MD5.getMessageDigest(String.valueOf(random.nextInt(10000)).getBytes());
return out_trade_no_str;
}
/**
* 生成签名
*/
private String genPackageSign(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.KEY);
String packageSign = MD5.getMessageDigest(sb.toString().getBytes()).toUpperCase();
signStr = packageSign;
return packageSign;
}
private String toXml(List<NameValuePair> params) {
StringBuilder sb = new StringBuilder();
sb.append("<xml>");
for (int i = 0; i < params.size(); i++) {
sb.append("<" + params.get(i).getName() + ">");
sb.append(params.get(i).getValue());
sb.append("</" + params.get(i).getName() + ">");
}
sb.append("</xml>");
Log.e("orion", sb.toString());
return sb.toString();
}
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) {
Log.e("error ", e.toString());
}
return null;
}
}