1:去微信开放平台注册应用https://open.weixin.QQ.com/cgi-bin/index?t=home/index&lang=zh_CN&token=2c0fee9c43e1eb8f9febcc7cb73abf598e2d4011
这里需要注意的是:
微信提供的签名生成工具把包名添加上去就可以获取签名注意:把要获取签名的应用安装在手机上https://res.wx.qq.com/open/zh_CN/htmledition/res/dev/download/sdk/Gen_Signature_Android2.apk
创建移动应用并成功之后会收到腾讯发来的邮件:
通过邮件你能获得重要的参数:(1):AppID(2):微信支付商户号(4):前往商户平台完成入驻(4):API秘钥(自己设置即可,注意一定要32位字母加数字的组合)记得保存好秘钥,以后要使用
开发前的准备
先了解下交互时序图,统一下单API、支付结果通知API和查询订单API等都涉及签名过程,调用都必须在商户服务器端完成。如图8.6所示。
下载开发工具包https://open.weixin.qq.com/cgi-bin/showdocument?action=dir_list&t=resource/res_list&verify=1&id=open1419319167&lang=zh_CN
1.在项目中引入微信开发包
2.在AndroidManifest.xml中添加相应的权限
signingConfigs { debug { storeFile file("你的keystore路径") storePassWord "xxx" keyAlias "xxx" keyPassword "xxx" } release { storeFile file("你的keystore路径") storePassword "xxx" keyAlias "xxx" keyPassword "xxx" }}3.在MainActivity中注册到为微信
4.在点击的时候向微信发送请求
5.配置回调[1]在微信管理后台中配置的包名下新建wxapi包[2]在wxapi包下新建WXPayEntryActivity的类(注意这个类的位置和名称不能改变)
[3]WXPayEntryActivity类实现IWXAPIEventHandler继承Activity,该布局文件自己定义即可
[4]在AndroidManifest.xml中注册activity
protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); api = WXAPIFactory.createWXAPI(this, ConfigUtil.Wechat_Appid); api.handleIntent(getIntent(), this);}@Override protected void onNewIntent(Intent intent) { super.onNewIntent(intent); setIntent(intent); api.handleIntent(intent, this); }[6]实现onResp
public void onResp(BaseResp baseResp) { Log.d(TAG, "onPayFinish, errCode = " + baseResp.errCode); if (baseResp.getType() == ConstantsAPI.COMMAND_PAY_BY_WX) { AlertDialog.Builder builder = new AlertDialog.Builder(this); builder.setTitle("标题"); builder.setMessage(String.valueOf(baseResp.errCode)); builder.show(); }}baseResp.errCode是返回的错误码
错误码
注意:WXPayEntryActivity类必须叫这个名必须在wxapi包下
微信调不起来:检查签名是否正确包名是否与微信后台配置的一致检查是否添加权限检查代码 是否在初始化时注册微信 是否正确发送请求微信支付调用起来没有回调:查看包名是否正确类名是否正确在AndroidManifest.xml是否注册activity
解决方法:实在掉不起来微信(包名正确签名正确)就重新安装微信客户端 和重新安装 测试项目
预支付订单和sign最好在服务器中完成,但若是就想在客户端做怎么弄呢?为方便,那么我这里就直接给出代码,可供大家参考:
/** *该类用于在客户端处理吊起微信支付前,生成prepay_id和sign的方式举例, * 但建议在服务器端处理prepay_id和sign **/public class PayActivity extends Activity { // appid // 请同时修改 androidmanifest.xml里面,.PayActivity里的属性<data // android:scheme=""/>为新设置的appid public static String APP_ID; // 商户号 public static String MCH_ID ; // API密钥,在商户平台设置 public static String API_KEY ; private String body; private String total; PayReq req; final IWXAPI msgApi = WXAPIFactory.createWXAPI(this, null); Map<String, String> resultunifiedorder; StringBuffer sb; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); APP_ID= getIntent().getStringExtra("appid"); MCH_ID=getIntent().getStringExtra("partnerid"); API_KEY=getIntent().getStringExtra("apikey"); body=getIntent().getStringExtra("body"); req = new PayReq(); sb = new StringBuffer(); msgApi.registerApp(APP_ID); // 生成prepay_id 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(PayActivity.this, getString(R.string.app_tip), getString(R.string.getting_prepayid)); } @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); //执行与获取预付款订单请求,并获得订单byte String content = new String(buf); Log.e("orion", content); Map<String, String> map = decodeXml(content); return map; } @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; if (result.get("prepay_id") != null) { genPayReq(); //吊起支付请求 } else { Toast.makeText(getapplicationContext(), "调用微信支付失败!", Toast.LENGTH_SHORT).show(); } } } 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; } private String genNonceStr() { Random random = new Random(); return md5.getMessageDigest(String.valueOf(random.nextInt(10000)).getBytes()); } private long genTimeStamp() { return System.currentTimeMillis() / 1000; } private String genOutTradNo() { Random random = new Random(); String out_trade_no = MD5.getMessageDigest(String.valueOf(random.nextInt(10000)).getBytes()); return out_trade_no; } private String genProductArgs() { StringBuffer xml = new StringBuffer(); try { String nonceStr = genNonceStr(); xml.append("</xml>"); List<NameValuePair> packageParams = new LinkedList<NameValuePair>(); packageParams.add(new BasicNameValuePair("appid", APP_ID)); packageParams.add(new BasicNameValuePair("body", body));//物品 packageParams.add(new BasicNameValuePair("mch_id", MCH_ID)); packageParams.add(new BasicNameValuePair("nonce_str", nonceStr)); packageParams.add(new BasicNameValuePair("notify_url", "http://baidu.com")); packageParams.add(new BasicNameValuePair("out_trade_no", genOutTradNo())); packageParams.add(new BasicNameValuePair("spbill_create_ip", getPhoneIp())); packageParams.add(new BasicNameValuePair("total_fee", getIntent().getStringExtra("total_fee")));//金额 packageParams.add(new BasicNameValuePair("trade_type", "APP")); String sign = genPackageSign(packageParams); packageParams.add(new BasicNameValuePair("sign", sign)); String xmlstring = toXml(packageParams); return new String(xmlstring.getBytes(), "ISO8859-1"); // return xmlstring; } catch (Exception e) { // Log.e(TAG, "genProductArgs fail, ex = " + e.getMessage()); return null; } } private void genPayReq() { req.appId = APP_ID; req.partnerId = MCH_ID; req.prepayId = 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); sb.append("sign/n" + req.sign + "/n/n"); sendPayReq(); Log.e("orion", signParams.toString()); } /** * 获取预支付订单时需要生成的PackageSign签名 */ 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(API_KEY); String packageSign = MD5.getMessageDigest(sb.toString().getBytes()).toUpperCase(); Log.e("orion", packageSign); return packageSign; } //吊起支付时需要生成的AppSign签名 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(API_KEY); this.sb.append("sign str/n" + sb.toString() + "/n/n"); String appSign = MD5.getMessageDigest(sb.toString().getBytes()).toUpperCase(); 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 void sendPayReq() { msgApi.registerApp(APP_ID); msgApi.sendReq(req); } public static String getPhoneIp() { 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() && inetAddress instanceof Inet4Address) { return inetAddress.getHostAddress().toString(); } } } } catch (Exception e) { } return "127.0.0.1"; }}其中Util中涉及的代码如下:
public static byte[] httpPost(String url, String entity) { if (url == null || url.length() == 0) { Log.e(TAG, "httpPost, url is null"); return null; } HttpClient httpClient = getNewHttpClient(); HttpPost httpPost = new HttpPost(url); try { httpPost.setEntity(new StringEntity(entity)); httpPost.setHeader("Accept", "application/json"); httpPost.setHeader("Content-type", "application/json"); HttpResponse resp = httpClient.execute(httpPost); if (resp.getStatusLine().getStatusCode() != HttpStatus.SC_OK) { Log.e(TAG, "httpGet fail, status code = " + resp.getStatusLine().getStatusCode()); return null; } return EntityUtils.toByteArray(resp.getEntity()); } catch (Exception e) { Log.e(TAG, "httpPost exception, e = " + e.getMessage()); e.printStackTrace(); return null; } }其他文档:
微信开发平台官网:申请流、业务流程、订单签名算法及验证
微信支付集成及爬坑:代码详谈
集成微信登录 :http://www.jianshu.com/p/d95e4343e231
Android实现点击支付按钮,弹起自定义输入法进行密码输入: 点我哦!
微信扫一扫揭秘: 猛戳这里!
新闻热点
疑难解答