很多公司都有需求接入第三方支付,如支付宝,银联,微信等等;
但是由于文档的一些老旧。所以,第一次接入时,开发人员可能就有点想日狗了~~!
废话不多说了,我今天介绍的是其中的一种:微信支付;
准备工作:
- 首先去微信开发者平台中注册好自己的应用,并申请支付权限,得到appkey;且在
微信平台中下载获得签名工具,输入包名获取签名填写到开发者平台中去(这一步必须要有); - 导入微信的libs包libammsdk.jar;
- 创建一个“应用包名+wxapi“+包名的包;
//回调Actvity,用于支付后的回调
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("0".equals(String.valueOf(resp.errCode))){
Utils.newInstance().showToast(WXPayEntryActivity.this, "支付成功");
}
if("-1".equals(String.valueOf(resp.errCode))){
Utils.newInstance().showToast
(WXPayEntryActivity.this, "未知错误,请联系客服");
finish();
}
if("-2".equals(String.valueOf(resp.errCode))){
(WXPayEntryActivity.this, "支付已取消");
finish();
}
}
}
}
- 调用微信支付
/**
* 因为微信给的官方demo是连在一起的
* 我现在把他拆开来,方便大家看的更清楚点
*/
private void WeiXinPay() {
// TODO Auto-generated method stub
Utils.showToast(context, "微信支付启动中...请稍后");
GetPrepayIdTask getPrepayId = new GetPrepayIdTask();
getPrepayId.execute();
}
- 传入商品信息数据,生成订单json数据,这边可以使用微信写好的方法;不过,大家最好整理一下代码;微信的源码有点乱。
private class GetPrepayIdTask extends AsyncTask<Void, Void, Map<String, String>> {
@Override
protected void onPreExecute() {
}
@Override
protected void onPostExecute(Map<String, String> result) {
WeixinPay.resultunifiedorder = result;
WeixinPay.genPayReq();
//查看返回订单数据
Log.e("tag","resultunifiedorder=="+WeixinPay.resultunifiedorder);
api.sendReq(WeixinPay.req);
}
@Override
protected void onCancelled() {
super.onCancelled();
}
//这边注意注释下的这几点
@Override
protected Map<String, String> doInBackground(Void... params) {
//这边微信使用已“分”为单位,这里要注意噢~~
int a = (int) (Double.valueOf(fee) * 100);
String url =
String.format("https://api.mch.weixin.qq.com/pay/unifiedorder");
/*
*“NO”为订单号,自己服务器生成的,“a”为金额要转换String格式(微信要
* 求的),"HttpHelp.BuyCallback",为通知服务器回调url;
*/
String entity = WeixinPay.genProductArgs(NO,
String.valueOf(a),HttpHelp.BuyCallback);
Log.e("orion", entity);
byte[] buf = Util.httpPost(url, entity);
String content = new String(buf);
Log.e("orion", content);
Map<String, String> xml = decodeXml(content);
return 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) {
//实例化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;
}
- 序列化订单数据,用于生成xml订单数据,发送给微信调用起微信支付;
/**
* 类说明:
* @author MyT
* @version 创建时间:20152015-10-8 下午5:00:40
*/
public class WeixinPay {
private static final String TAG = "MicroMsg.SDKSample.WeixinPay";
public static Map<String,String> resultunifiedorder
=new HashMap<String, String>();
public static PayReq req=new PayReq();
public static String genProductArgs(String name, String total,String url) {
StringBuffer xml = new StringBuffer();
try {
String nonceStr = genNonceStr();
xml.append("</xml>");
List<NameValuePair> packageParams = new LinkedList<NameValuePair>();
packageParams.add(new BasicNameValuePair("appid",
Constants.APP_ID));//微信appid
packageParams.add(new BasicNameValuePair("body", "*******"));//商品备注
packageParams.add(new BasicNameValuePair("mch_id", Constants.MCH_ID));//商户ID
packageParams.add(new BasicNameValuePair("nonce_str", nonceStr));
packageParams.add(new BasicNameValuePair("notify_url", url));
packageParams.add(new BasicNameValuePair("out_trade_no",name));
packageParams.add(new
BasicNameValuePair("spbill_create_ip","127.0.0.1"));
packageParams.add(new BasicNameValuePair("total_fee", total));
packageParams.add(new BasicNameValuePair("trade_type", "APP"));
String sign = genPackageSign(packageParams);
packageParams.add(new BasicNameValuePair("sign", sign));
String xmlstring =toXml(packageParams);
//有转码错误的风险,参考其他人的做法要加上就可以了吧xml转码下
return new String(xmlstring.toString().getBytes(),
} catch (Exception e) {
Log.e(TAG, "genProductArgs fail, ex = " + e.getMessage());
return null;
}
}
public static String genNonceStr() {
Random random = new Random();
return
MD5.getMessageDigest(String.valueOf(random.nextInt(10000)).getBytes());
}
public static String genOutTradNo() {
Random random = new Random();
return
MD5.getMessageDigest(String.valueOf(random.nextInt(10000)).getBytes());
}
/** 生成签名
*/
public static 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;
}
public static 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 static void genPayReq() {
req.appId = Constants.APP_ID;
req.partnerId =Constants.MCH_ID;
req.prepayId =WeixinPay.resultunifiedorder.get("prepay_id");
req.packageValue ="Sign=WXPay";
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);
Log.e("orion", signParams.toString());
}
public static long genTimeStamp() {
return System.currentTimeMillis() / 1000;
}
public static 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);
String appSign = MD5.getMessageDigest(sb.toString().getBytes()).toUpperCase();
Log.e("orion",appSign);
return appSign;
}
}
- 最后注意一点:一定要用正式包名,就是提交给微信的签名去支付,否则会支付失败;有许多人支付失败,请先清理微信缓存,再进行支付,这个问题,微信也没给出具体的解决方案,只叫我们去清除缓存;
- 最好自己看一遍微信的文档,虽然旧,但是看的懂大概就行;其他的工具类,全部是微信那边提供下载的,这边我就不提供了;^(* ̄(oo) ̄)^