Android—基于微信开放平台v3SDK开发(微信支付填坑)
接触微信支付之前听说过这是一个坑,,,心里已经有了准备。。。我以为我没准跳坑出不来了,没有想到我填上了,调用成功之后我感觉公司所有的同事都是漂亮的,隔着北京的大雾霾我仿佛看见了太阳~~~好了,装逼结束。。。进入正题
开发准备:
1.在微信开放平台申请账号
2.成功后创建应用,就是填一些看似很官方很正经的资料了。。。(说审核7天左右,没有意外的情况下你的app第二天就审核成功了是不是很开心,有了appid,是不是就可以调用微 信支付了????-------想多了,真的)
3.微信支付是需要额外申请的:需要资料审核,账户验证,协议签署等步骤,(我记得,,资料审核要填写的东西好多,,,好多,,,账户验证就是你审核成功后微信会发送邮件到你 注册时登记的邮箱账号,其中含有随机金额用于账户验证,协议签署,略,太简单)一定要好好阅读你邮件的任何信息,因为有的细节错了,,,你可能填坑很久。。。。。。
正式开发阶段:
问题1:
调用官方的sdk发现只能成功的调起一次微信,再次支付的时候怎么也调用不起来了
解决:
似乎不是什么正经方法:在手机设置中管理应用程序,清除微信数据,缓存,,再来一遍,绝对可以调起来(当然还是只是一次。。。。)
继续:
我认为要用微信支付嘛,,就只看了调用支付接口的文档:
后来发现需要的参数prepayid是怎么也找不到啊,,后来才发现这个prepayid是先调用”统一下单“这个接口时候温馨反过来的东西,但是官方的sdk中并没有统一下单的代码。坑吗???
所以要先看统一下单文档了
1.使用自己的app调用的时候把官网down下来的sdk中wxpayentryactivity拷贝到自己的项目,所在包的名字最后一定是.wxapi(我连包一起拷了。。。。)
2.在项目清单文件中填写:
3.sdk中的appregister拷贝下来,,,里面换成你自己的appid,然后在项目清单中也注册一下。
4.重点来了,,就是你app要调微信支付的activity,我这还叫payactivity
要调起微信支付页面,要在这个activity中,将你的app注册到微信
接下来先调用统一下单获取prepayid,参数,微信人家要xml格式的!我们就得发送xml格式的!
好了调用的时候把这个方法的返回值当参数传,,等待微信返回success吧!。。
我遇见的错误:签名错误
我的原因是大意了 configutil.notify_url这个参数写的空字符串
还有是因为debug版运行的,没有打包运行
返回成功之后,可以调用支付接口了
不要忘了这一步去跳转界面,,,,,
没有跳转到微信支付可能是你由运行的debug版本,,,,没有打包。。。。。
下面是我的payactivity完整代码:
package com.example.taijiapp.ui; import java.io.stringreader; import java.net.inetaddress; import java.net.networkinterface; import java.net.socketexception; import java.util.enumeration; import java.util.hashmap; import java.util.linkedlist; import java.util.list; import java.util.map; import java.util.random; import org.apache.http.namevaluepair; import org.apache.http.message.basicnamevaluepair; import org.xmlpull.v1.xmlpullparser; import com.example.taijiapp.r; import com.example.taijiapp.util.constants; import com.example.taijiapp.util.md5; import com.example.taijiapp.util.t; import com.example.taijiapp.util.util; import com.example.taijiapp.utils.configutil; import com.tencent.mm.sdk.modelpay.payreq; import com.tencent.mm.sdk.openapi.iwxapi; import com.tencent.mm.sdk.openapi.wxapifactory; import android.app.activity; import android.app.progressdialog; import android.content.context; import android.net.wifi.wifiinfo; import android.net.wifi.wifimanager; import android.os.asynctask; import android.os.bundle; import android.util.log; import android.util.xml; import android.view.view; import android.widget.button; public class payactivity extends activity { payreq req; private iwxapi msgapi; map<string, string=""> resultunifiedorder; stringbuffer sb; @override protected void oncreate(bundle savedinstancestate) { super.oncreate(savedinstancestate); setcontentview(r.layout.pay); req = new payreq(); sb = new stringbuffer(); msgapi = wxapifactory.createwxapi(this, constants.app_id); /** * 将app注册到微信 */ boolean registerapp = msgapi.registerapp(constants.app_id); t.show(this, "注册========"+registerapp+""); button appaybtn = (button) findviewbyid(r.id.appay_btn); button check_pay_btn = (button) findviewbyid(r.id.check_pay_btn); appaybtn.setonclicklistener(new view.onclicklistener() { @override public void onclick(view v) { getprepayidtask getprepayid = new getprepayidtask(); getprepayid.execute(); } }); /** * 将该app注册到微信 */ check_pay_btn.setonclicklistener(new view.onclicklistener() { @override public void onclick(view v) { genpayreq(); sendpayreq(); } }); // // 生成签名参数 // button appay_pre_btn = (button) findviewbyid(r.id.appay_pre_btn); // appay_pre_btn.setonclicklistener(new view.onclicklistener() { // // @override // public void onclick(view v) { // genpayreq(); // } // }); } /** * 生成签名 */ 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); log.e("拼接=====", sb.tostring()); string packagesign = md5.getmessagedigest(sb.tostring().getbytes()).touppercase(); log.e("orion生成签名===", packagesign); return packagesign; } /** * 签名工具 不含商户密钥 -暂时不用 = * 编码格式 utf-8 = * @return */ public static string createsignnokey(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('&'); } string signstr = sb.tostring(); string substr = signstr.substring(0, signstr.length() - 1); // 注意sign转为大写 return md5.getmessagedigest(substr.getbytes()).touppercase(); } 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.key); this.sb.append("sign str\n" + sb.tostring() + "\n\n"); string appsign = md5.getmessagedigest(sb.tostring().getbytes()); log.e("orion", appsign); return appsign; } 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(); } private class getprepayidtask extends asynctask<void, void,="" map<string,="" string="">> { private progressdialog dialog; @override protected void onpreexecute() { dialog = progressdialog.show(payactivity.this, getstring(r.string.app_tip), getstring(r.string.getting_prepayid)); } @override protected void onpostexecute(map<string, string=""> result) { if (dialog != null) { dialog.dismiss(); } sb.append("prepay_id\n" + result.get("prepay_id") + "\n\n"); resultunifiedorder = result; } @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 = 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; } /** * 生成随机数 * @return */ private string gennoncestr() { random random = new random(); return md5.getmessagedigest(string.valueof(random.nextint(10000)).getbytes()); } /** * 时间戳 * @return */ private long gentimestamp() { return system.currenttimemillis() / 1000; } /** * 随机数 * @return */ private string genouttradno() { random random = new random(); return md5.getmessagedigest(string.valueof(random.nextint(10000)).getbytes()); } /** * 获取设备的ip地址 * @return */ public string getlocalipaddress() { try { for (enumeration<networkinterface> en = networkinterface.getnetworkinterfaces(); en.hasmoreelements();) { networkinterface intf = en.nextelement(); for (enumeration<inetaddress> enumipaddr = intf.getinetaddresses(); enumipaddr.hasmoreelements();) { inetaddress inetaddress = enumipaddr.nextelement(); if (!inetaddress.isloopbackaddress()) { return inetaddress.gethostaddress().tostring(); } } } } catch (socketexception ex) { } return null; } private string getwifiip() { // 获取wifi服务 wifimanager wifimanager = (wifimanager) getsystemservice(context.wifi_service); // 判断wifi是否开启 if (!wifimanager.iswifienabled()) { wifimanager.setwifienabled(true); } wifiinfo wifiinfo = wifimanager.getconnectioninfo(); int ipaddress = wifiinfo.getipaddress(); string ip = inttoip(ipaddress); return ip; } /** * 转化成ip地址的格式 * @param i * @return */ private string inttoip(int i) { return (i & 0xff) + "." + ((i >> 8) & 0xff) + "." + ((i >> 16) & 0xff) + "." + (i >> 24 & 0xff); } private string genproductargs() { stringbuffer xml = new stringbuffer(); string ip = getwifiip(); if (ip == "" && ip == "") { ip = getlocalipaddress(); } try { string noncestr = gennoncestr(); xml.append(""); list<namevaluepair> packageparams = new linkedlist<namevaluepair>(); packageparams.add(new basicnamevaluepair("appid", constants.app_id)); packageparams.add(new basicnamevaluepair("body", "apptest")); packageparams.add(new basicnamevaluepair("mch_id", constants.mch_id)); packageparams.add(new basicnamevaluepair("nonce_str", noncestr)); packageparams.add(new basicnamevaluepair("notify_url", configutil.notify_url)); packageparams.add(new basicnamevaluepair("out_trade_no", genouttradno())); packageparams.add(new basicnamevaluepair("spbill_create_ip", ip)); packageparams.add(new basicnamevaluepair("total_fee", "100")); packageparams.add(new basicnamevaluepair("trade_type", "app")); string sign = genpackagesign(packageparams); packageparams.add(new basicnamevaluepair("sign", sign)); string xmlstring = toxml(packageparams); return xmlstring; } catch (exception e) { log.e("tag", "fail, ex = " + e.getmessage()); return null; } } private void genpayreq() { 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); sb.append("sign\n" + req.sign + "\n\n"); log.e("orion==genpayreq===============", signparams.tostring()); } private void sendpayreq() { boolean sendreq = msgapi.sendreq(req); t.show(this, "微信跳转====="+sendreq+""); } } </namevaluepair></namevaluepair></namevaluepair></namevaluepair></inetaddress></networkinterface></string,></string,></string,></string,></string,></string,></void,></namevaluepair></namevaluepair></namevaluepair></namevaluepair></string,>
里面没有的类,,,,呐:。自己下载一下拷贝一下。。。
参考文章:
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。
上一篇: Django的信号机制详解