在微信开发平台下载微信支付sdk 一般叫 libammsdk.jar‘
然后导入到项目libs包内
然后开始集成
(https://pay.weixin.qq.com/wiki/doc/api/app/app.php?chapter=8_5)
这个是微信支付开发文档地址,不过文档写的真心烂死了,步骤一点也不详细的。
一开始需要调用统一订单接口获取预订单的订单id也就是字段prepay_id
根据文档说明,没特别需要的话我们只传必填的那些字段就行了
每个字段有对应描述,可以根据描述选择你需要的字段。
简单说几个比较重要的
appid字段就是在你在微信开放平台(https://open.weixin.qq.com)创建并审核通过的应用,点查看就能看到如下图。
mch_id微信支付商户号 这个就得申请支付功能并审核通过之后,系统会给你发放一个商户登录账户 登录密码 商户号发送到你的邮箱中。
格式是这样的
mch_id就发给邮箱内的微信支付商户号,也可以用商户帐号密码在(https://pay.weixin.qq.com/)登录商户管理平台查看。
sing签名 这个字段也是比较恶心的,需要把你传的字段全部整合在一起然后用MD5加密,再改大写才行
举个栗子
String a="appid=wx081c8528de654a89&body=测试&detail=测试充值" +
"&mch_id=1000000000&nonce_str="+"5K8264ILTKCH16CQ2502SI8ZNMTM67VS"+"¬ify_url=http://www.baidu.com&out_trade_no="+20150806125346+
"&spbill_create_ip="+192.168.1.1+"&total_fee="+1+"&trade_type=APP&key=192006250b4c09247ec02edce69f6a2d";
sing=MD5.mdjiami(a).toUpperCase();
验证sing是否正确可以在(https://pay.weixin.qq.com/wiki/tools/signverify/)这里进行测试
String a里除了上传的参数外还有一个key,这个key要登录商户平台然后在设置密钥的地方设置的(会提示你要先安装证书,按提示来就行了)
字段选择完成后开始传参数,这个也是比较恶心的他需要用<xml><appid>wx081c8528de654a89</appid><mch_id>1000000000</mch_id></xml>这种格式上传数据,没办法自己拼吧。
ByteArrayOutputStream baos=new ByteArrayOutputStream(); XmlSerializer xml= Xml.newSerializer(); xml.setOutput(baos, "UTF-8"); // xml.startDocument("UTF-8", null); // xml.startTag(null, "zuobiao"); //appid xml.startTag(null, "xml"); xml.startTag(null, "appid"); xml.text("wx081c8528de654a89"); xml.endTag(null, "appid"); //商品名 xml.startTag(null, "body"); xml.text("测试"); xml.endTag(null, "body"); //商品详情 xml.startTag(null, "detail"); xml.text("测试充值"); xml.endTag(null, "detail"); //商户号 xml.startTag(null, "mch_id"); xml.text("1000000000"); xml.endTag(null, "mch_id"); //随机字符串 xml.startTag(null, "nonce_str"); xml.text("5K8264ILTKCH16CQ2502SI8ZNMTM67VS"); xml.endTag(null, "nonce_str"); //回调地址 xml.startTag(null, "notify_url"); xml.text("http://www.baidu.com"); xml.endTag(null, "notify_url"); //商户订单号 xml.startTag(null, "out_trade_no"); xml.text("20150806125346"); xml.endTag(null, "out_trade_no"); //用户ip xml.startTag(null, "spbill_create_ip"); xml.text("192.168.1.1"); xml.endTag(null, "spbill_create_ip"); //金额 xml.startTag(null, "total_fee"); xml.text(1+""); xml.endTag(null, "total_fee"); //类型 xml.startTag(null, "trade_type"); xml.text("APP"); xml.endTag(null, "trade_type"); //签名 xml.startTag(null, "sign"); xml.text(sing); xml.endTag(null, "sign"); //abcdefghijklmnopqrstuvwxyz // xml.endTag(null, "zuobiao"); xml.endDocument(); byte[] xmlData=baos.toByteArray(); String xmlString=new String(xmlData,"ISO8859-1"); baos.flush(); baos.close(); baos=null; return xmlString;注意字段值有中文的时候要改成"IS08859-1"编码不然会提示签名错误
注:这里我遇到几次appid跟mch_id不匹配,要按我前面写的去找appid跟mch_id才行。
然后传上去返回的还是xml格式的值 我们要进行解析并取到prepay_id的值后面用。
解析方法
ByteArrayInputStream is=new ByteArrayInputStream(str.getBytes()); XmlPullParser xpp = Xml.newPullParser(); try{ xpp.setInput(is,"ISO8859-1"); int eventType=xpp.getEventType(); while (eventType!= XmlPullParser.END_DOCUMENT){ switch (eventType) { case XmlPullParser.START_DOCUMENT: break; case XmlPullParser.START_TAG: String name = xpp.getName(); if (name.equalsIgnoreCase("prepay_id")) { xpp.require(XmlPullParser.START_TAG, null, "prepay_id"); id = xpp.nextText(); if (xpp.getEventType() != XmlPullParser.END_TAG) { xpp.nextTag(); } xpp.require(XmlPullParser.END_TAG, null, "prepay_id"); System.out.println("menu option: " + id); // id=xpp.nextText(); } break; case XmlPullParser.END_TAG: break; } eventType = xpp.next(); } is.close(); }catch (Exception e) { e.printStackTrace(); } // Toast.makeText(PayActivity.this, id, Toast.LENGTH_SHORT).show(); return id;将返回的值转成String类型然后传进来就行 返回的值是 prepay_id了
然后开始准备调起支付接口参数。
这里还是需要签名跟前面一样(参数跟我栗子里一样就行了,不需要变,值改对应的就行了。)
这里注意参数名都是小写的,因为调起的代码中参数字段是大写我误以为是签名中参数名也要大写搞的半天一直调不出支付接口直接返回-1String diaoqi = "appid=wx081c8528de654a89&noncestr="+4K8264ILTKCH16CQ2502SI8ZNMTM67V5+"&package="+"Sign=WXPay"+"&partnerid=1000000000&prepayid=" + prepayid +"×tamp="+14000000000+"&key=192006250b4c09247ec02edce69f6a2d";
然后开始调起支付关键代码
boolean isPaySupported = api.getWXAppSupportAPI() >= Build.PAY_SUPPORTED_SDK_INT; if(isPaySupported){//判断微信当前版本是否支持微信支付。 PayReq req = new PayReq(); req.appId = "wx081c8528de654a89"; req.partnerId = "1000000000"; req.prepayId = prepayid; req.nonceStr = 4K8264ILTKCH16CQ2502SI8ZNMTM67V5; req.timeStamp = 14000000000+""; req.packageValue = "Sign=WXPay"; req.sign = MD5.mdjiami(diaoqi).toUpperCase(); // req.extData = "app data"; api.sendReq(req); // Toast.makeText(PayActivity.this, prepayid, Toast.LENGTH_SHORT).show(); }这里就完成了,正常情况下是正常调起来的。
但是有可能出意外因为错误返回都是-1,所以都是自己找原因。
有可能你app包名或者MD5签名跟你在微信开发平台内填写的不一致。MD5签名可在(https://open.weixin.qq.com/zh_CN/htmledition/res/dev/download/sdk/Gen_Signature_Android.apk)下载工具获取。
还有在集成的时候需要注意的地方 需要在项目里建跟官方demo一样包名如图只需要放AppRegister复制官方demo里的就行,然后接受回调,需要在你的项目包名下例如com.ceshi.activity再建一个包wxapi放入WXPayEntryActivity这个是处理回调的复制官方demo里的就行了。
如图还需要在AndroidManifest文件中注册AppRegister
还有这里要注意不然也接收不到回调,schem的值是你的appid
这样基本没有问题了。
32位随机数算法
String val = ""; Random random = new Random(); //参数length,表示生成几位随机数 for(int i = 0; i < 32; i++) { String charOrNum = random.nextInt(2) % 2 == 0 ? "char" : "num"; //输出字母还是数字 if( "char".equalsIgnoreCase(charOrNum) ) { //输出是大写字母还是小写字母 int temp = random.nextInt(2) % 2 == 0 ? 65 : 97; val += (char)(random.nextInt(26) + temp); } else if( "num".equalsIgnoreCase(charOrNum) ) { val += String.valueOf(random.nextInt(10)); } } return val;获取时间搓精确掉秒
timeMillis = System.currentTimeMillis()/1000;
还有调起支付前最好判断下是否安装了微信不然没有任何反映跟提示也没有回调。
判断的代码
private boolean isWXAppInstalledAndSupported() { IWXAPI msgApi = WXAPIFactory.createWXAPI(this, null); msgApi.registerApp("wx081c8528de654a89"); boolean sIsWXAppInstalledAndSupported = msgApi.isWXAppInstalled() && msgApi.isWXAppSupportAPI(); return sIsWXAppInstalledAndSupported; }
后面有发现其它问题我再进行补充,也欢迎大家补充问题。