|
微信支付遇到了无数的坑,总算是一个个解决了,官方文档真是让人郁闷到死,不多说,直接上代码。 一.生成预支付订单
private StringBuffer strbuffer;
private Map<String,String> resultunifiedorder; private final IWXAPI msgApi = WXAPIFactory.createWXAPI(this, null);
1.1准备工作 strbuffer=new StringBuffer();
msgApi.registerApp(Constants.APP_ID);
GetPrepayIdTask getPrepayId = new GetPrepayIdTask();
getPrepayId.execute(); 1.2GetPrepayIdTask //1.获取预支付订单编号
private class GetPrepayIdTask extends AsyncTask<Void, Void, Map<String,String>> {
private ProgressDialog dialog;
@Override
protected void onPreExecute() {
dialog = ProgressDialog.show(EShopWEIXIN_EPAYActivity.this, "提示", "正在获取预支付订单...");
}
@Override
protected void onPostExecute(Map<String,String> result) {
if (dialog != null) {
dialog.dismiss();
}
resultunifiedorder=result;
if(result.get("return_code").contentEquals("SUCCESS") ){//预支付成功
genPayReq();//2生成签名参数
}
strbuffer.append("prepay_id\n"+result.get("prepay_id")+"\n\n");
}
@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();//生成预支付订单请求
Log.e("orion",entity);
byte[] buf = WXUtil.httpPost(url, entity);//提交预支付订单
String content = new String(buf);
Log.e("orion", content);
Map<String,String> xml=decodeXml(content);
return xml;
}
}1.3生成预支付订单请求 private String genProductArgs() {
StringBuffer xml = new StringBuffer();
try {
String nonceStr = genNonceStr();
String strIP=genWifiIp();//获取手机ip
xml.append("</xml>");
List<NameValuePair> packageParams = new LinkedList<NameValuePair>();
packageParams.add(new BasicNameValuePair("appid", Constants.APP_ID));//应用ID
packageParams.add(new BasicNameValuePair("body", "e"));//商品描述e路通-保险支付
packageParams.add(new BasicNameValuePair("mch_id", Constants.MCH_ID));//商户号
packageParams.add(new BasicNameValuePair("nonce_str", nonceStr));//随机字符串nonceStr
packageParams.add(new BasicNameValuePair("notify_url", "http://wxpay.wxutil.com/pub_v2/pay/notify.v2.php"));//通知地址
packageParams.add(new BasicNameValuePair("out_trade_no", "15036257092394985"));//商户订单号
packageParams.add(new BasicNameValuePair("spbill_create_ip", strIP));//用户端实际ip
packageParams.add(new BasicNameValuePair("total_fee", "1"));//订单总金额,单位为分
packageParams.add(new BasicNameValuePair("trade_type", "APP"));//支付类型
String sign = genPackageSign(packageParams);
packageParams.add(new BasicNameValuePair("sign", sign));
String xmlstring = toXml(packageParams);
// xmlstring = new String(xmlstring.getBytes(), "ISO-8859-1");
return xmlstring;//String(xmlstring.getBytes("UTF-8"), "ISO8859-1"),body使用中文xml要转码
} catch (Exception e) {
return null;
}
}
1.4随机数 private String genNonceStr() {
Random random = new Random();
return MD5.getMessageDigest(String.valueOf(random.nextInt(10000))
.getBytes());
}
1.5通过wifi获取用户手机IP private String genWifiIp() {
//获取wifi管理服务
WifiManager wifiManager = (WifiManager) getApplicationContext().getSystemService(WIFI_SERVICE);
//判断wifi是否开启
if (!wifiManager.isWifiEnabled()) {
wifiManager.setWifiEnabled(true);
}
WifiInfo wifiInfo = wifiManager.getConnectionInfo();
int ipAddress = wifiInfo.getIpAddress();
String ip = intToIp(ipAddress);
return ip;
}
private String intToIp(int i) {
return (i & 0xFF ) + "." +
((i >> 8 ) & 0xFF) + "." +
((i >> 16 ) & 0xFF) + "." +
( i >> 24 & 0xFF) ;
}
1.6商户订单号(只要唯一就可以) private String genOutTradNo() {
Random rand = new Random();
int randNum = rand.nextInt(9999);
String randStr = String.format("%04d", randNum);
String orderseq = String.valueOf(System.currentTimeMillis())+randStr;
return orderseq;
}
1.7sign预支付签名 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.API_KEY);
String packageSign = MD5.getMessageDigest(sb.toString().getBytes()).toUpperCase();
Log.e("orion",packageSign);
return packageSign;
}
1.8提交数据的格式化 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();
}
1.9WXUtil文件 2.0返回数据格式化 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){
//实例化student对象
xml.put(nodeName,parser.nextText());
}
break;
case XmlPullParser.END_TAG:
break;
}
event = parser.next();
}
return xml;
} catch (Exception e) {
Log.e("orion",e.toString());
}
return null;
}
二、调起微信支付 1.1调起genPayReq()开始微信支付; private void genPayReq() {
PayReq req= new PayReq();
req.appId = Constants.APP_ID;
req.partnerId = Constants.MCH_ID;
req.prepayId = resultunifiedorder.get("prepay_id");
req.packageValue = "prepay_id="+resultunifiedorder.get("prepay_id");
req.nonceStr = genNonceStr();
req.timeStamp = String.valueOf(genTimeStamp());
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);
strbuffer.append("sign\n"+req.sign+"\n\n");
msgApi.registerApp(Constants.APP_ID); msgApi.sendReq(req); Log.e("orion", signParams.toString());}
1.2时间戳 private long genTimeStamp() {
return System.currentTimeMillis() / 1000;
}1.3sign二次签名 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.strbuffer.append("sign str\n"+sb.toString()+"\n\n");
String appSign = MD5.getMessageDigest(sb.toString().getBytes()).toUpperCase();
Log.e("orion",appSign);
return appSign;
}
三、支付结果 参照微信SDK Sample,在net.sourceforge.simcpux.wxapi包路径中实现WXPayEntryActivity类 (包名或类名不一致会造成无法回调)在WXPayEntryActivity类中实现onResp函数,支付完成后, 微信APP会返回到商户APP并回调onResp函数,开发者需要在该函数中接收通知,判断返回错误码, 如果支付成功则去后台查询支付结果再展示用户实际支付结果。注意一定不能以客户端返回作为用户支付的结果, 应以服务器端的接收的支付通知或查询API返回的结果为准。 package cn.com.siyuan.eshop.wxapi;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.widget.Toast;
import com.tencent.mm.sdk.constants.ConstantsAPI;
import com.tencent.mm.sdk.modelbase.BaseReq;
import com.tencent.mm.sdk.modelbase.BaseResp;
import com.tencent.mm.sdk.openapi.IWXAPI;
import com.tencent.mm.sdk.openapi.IWXAPIEventHandler;
import com.tencent.mm.sdk.openapi.WXAPIFactory;
import cn.com.siyuan.eshop.utils.Util;
import cn.com.siyuan.eshop.weixinepay.Constants;
import cn.com.siyuan.rbeshop.R;
public class WXPayEntryActivity extends Activity implements IWXAPIEventHandler{
private static final String TAG = "MicroMsg.SDKSample.WXPayEntryActivity";
private IWXAPI api;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.pay_result);
api = WXAPIFactory.createWXAPI(this, Constants.APP_ID);
api.handleIntent(getIntent(), this);
}
@Override
protected void onNewIntent(Intent intent) {
super.onNewIntent(intent);
setIntent(intent);
api.handleIntent(intent, this);
}
@Override
public void onReq(BaseReq req) {
}
@Override
public void onResp(BaseResp resp) {
Log.d(TAG, "onPayFinish, errCode = " + resp.errCode);
if (resp.getType() == ConstantsAPI.COMMAND_PAY_BY_WX) {
if(resp.errCode==0){
Toast.makeText(WXPayEntryActivity.this,"支付成功!",Toast.LENGTH_LONG).show();
}else if(resp.errCode==-1){
Toast.makeText(WXPayEntryActivity.this,"支付失败!",Toast.LENGTH_LONG).show();
}else if(resp.errCode==-2){
Toast.makeText(WXPayEntryActivity.this,"用户取消支付!支付失败!",Toast.LENGTH_LONG).show();
}
Util.isPay=resp.errCode;
finish();
}
}
} |