Android 微信支付详解与Demo
最近公司弄Ionic框架,项目中需要微信支付,无奈,把我调过去弄,期间也是几近崩溃,好在皇天不负有心人,在看别人的文档,终于是在项目中集成了微信支付,下面作为一个小白的我,想要把我的经验分享给大家,希望对大家有所帮助。
先给一个可用的demo吧(运行前先看txt文件)
http://download.csdn.net/detail/simon_crystin/9699743;
(温馨提示:大家下载下来可能会出错,也有可能不会。下面给出出错的解决方法:1.进入项目中的WeIXinPay->Build Path->configure build path,移除那个报错的jar包。 2.会出现资源找不到的情况,这是因为你没有v7包,下载一个v7包,或者把出错的地方都删除,只是一个主题,删除了看起来不好看而已,当然,你也可以用你有的主题。 还有一个问题需要提出来,就是你可能按照里面的text操作的仍然调不起客户端,有可能是你没有安装微信客户端,因为我没有做判断。这个demo不会出现只能成功支付一次的情况,博主亲测有效。出现只能支付一次只能说明你的签名没有对应)
1.去微信开放平台申请微信支付服务,绑定自己的应用这里具体不多讲,但是一定要申请完成,将会得到是三个参数
//appid 微信分配的公众账号IDpublic static final String APP_ID = "";//商户号 微信分配的公众账号IDpublic static final String MCH_ID = "";// API密钥,在商户平台设置public static final String API_KEY= "";
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
**坑点提示:在微信开发平台设置包名和签名。这里的包名一定要和你自己的包名一样,就是manifest中的package,签名一定要和你用官方app生成的一样(https://open.weixin.qq.com/zh_CN/htmledition/res/dev/download/sdk/Gen_Signature_Android.apk)。
微信会根据你的填写的包名,然后对你的keystore进行一种算法,生成你的签名。包名和签名一定要和微信开放平台的相同。不过这里需要注意的是,如果你发布的正式版本,需要用官方app重新生成签名,然后在开放平台重新设置sign,因为测试版本的keystore与正式版的keystore不一样。总之,就是你用的keystore生成的sign要和微信开放平台的时刻保持一致。**
2.准备工作做好了,接下来就是开发了,先下载微信的jar包,导入。
微信支付分为三个步骤
1.生成prepayId
@Overrideprotected Map<String, String> doInBackground(String... params) {// TODO Auto-generated method stubString url=String.format(params[0]);String entity=getProductArgs();Log.e("Simon",">>>>"+entity);byte[] buf=Util.httpPost(url, entity);String content = new String(buf);Log.e("orion", "----"+content);Map<String,String> xml=decodeXml(content);return xml;}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
2.生成签名参数
private void genPayReq() {req.appId = Constants.APP_ID;req.partnerId = Constants.MCH_ID;if (resultunifiedorder!=null) {req.prepayId = resultunifiedorder.get("prepay_id");req.packageValue = "prepay_id="+resultunifiedorder.get("prepay_id");}else {Toast.makeText(MainActivity.this, "prepayid为空", Toast.LENGTH_SHORT).show();}req.nonceStr = getNonceStr();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");textView.setText(sb.toString());Log.e("Simon", "----"+signParams.toString());}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
3.调起支付。
/** 调起微信支付*/private void sendPayReq() {msgApi.registerApp(Constants.APP_ID);msgApi.sendReq(req);Log.i(">>>>>", req.partnerId);}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
下面给出完整代码
package com.alpha.live;import java.io.StringReader;
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.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.AlertDialog;
import android.app.ProgressDialog;
import android.os.AsyncTask;
import android.os.Bundle;
import android.util.Log;
import android.util.Xml;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;
/*** Created by Simon on 2016/12/2.*/
public class MainActivity extends Activity implements OnClickListener {private Button submitButton;private Button confirmButton;private TextView textView;private StringBuffer sb;private Map<String,String> resultunifiedorder;private PayReq req;private final IWXAPI msgApi = WXAPIFactory.createWXAPI(this, null);@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);submitButton=(Button) findViewById(R.id.bt_submit_order);confirmButton=(Button) findViewById(R.id.bt_corfirm);textView=(TextView) findViewById(R.id.tv_prepay_id);submitButton.setOnClickListener(this);confirmButton.setOnClickListener(this);sb=new StringBuffer();req=new PayReq();}@Overridepublic void onClick(View v) {// TODO Auto-generated method stubswitch (v.getId()) {case R.id.bt_submit_order:String urlString="https://api.mch.weixin.qq.com/pay/unifiedorder";PrePayIdAsyncTask prePayIdAsyncTask=new PrePayIdAsyncTask();prePayIdAsyncTask.execute(urlString); //生成prepayIdbreak;case R.id.bt_corfirm:genPayReq();//生成签名参数sendPayReq();//调起支付break;default:break;}}/** 调起微信支付*/private void sendPayReq() {msgApi.registerApp(Constants.APP_ID);msgApi.sendReq(req);Log.i(">>>>>", req.partnerId);}private long genTimeStamp() {return System.currentTimeMillis() / 1000;}private void genPayReq() {req.appId = Constants.APP_ID;req.partnerId = Constants.MCH_ID;if (resultunifiedorder!=null) {req.prepayId = resultunifiedorder.get("prepay_id");req.packageValue = "prepay_id="+resultunifiedorder.get("prepay_id");}else {Toast.makeText(MainActivity.this, "prepayid为空", Toast.LENGTH_SHORT).show();}req.nonceStr = getNonceStr();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");textView.setText(sb.toString());Log.e("Simon", "----"+signParams.toString());}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.sb.append("sign str\n"+sb.toString()+"\n\n");String appSign = MD5.getMessageDigest(sb.toString().getBytes());Log.e("Simon","----"+appSign);return appSign;}private class PrePayIdAsyncTask extends AsyncTask<String,Void, Map<String, String>>{private ProgressDialog dialog;@Overrideprotected void onPreExecute() {// TODO Auto-generated method stubsuper.onPreExecute();dialog = ProgressDialog.show(MainActivity.this, "提示", "正在提交订单");}@Overrideprotected Map<String, String> doInBackground(String... params) {// TODO Auto-generated method stubString url=String.format(params[0]);String entity=getProductArgs();Log.e("Simon",">>>>"+entity);byte[] buf=Util.httpPost(url, entity);String content = new String(buf);Log.e("orion", "----"+content);Map<String,String> xml=decodeXml(content);return xml;}@Overrideprotected void onPostExecute(Map<String, String> result) {// TODO Auto-generated method stubsuper.onPostExecute(result);if (dialog != null) {dialog.dismiss();}sb.append("prepay_id\n"+result.get("prepay_id")+"\n\n");textView.setText(sb.toString());resultunifiedorder=result;}}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("Simon","----"+e.toString());}return null;}private String getProductArgs() {// TODO Auto-generated method stubStringBuffer xml=new StringBuffer();try {String nonceStr=getNonceStr();xml.append("<xml>");List<NameValuePair> packageParams=new LinkedList<NameValuePair>();packageParams.add(new BasicNameValuePair("appid",Constants.APP_ID));packageParams.add(new BasicNameValuePair("body", "APP pay test"));packageParams.add(new BasicNameValuePair("mch_id", Constants.MCH_ID));packageParams.add(new BasicNameValuePair("nonce_str", nonceStr));packageParams.add(new BasicNameValuePair("notify_url", "https://www.baidu.com"));//写你们的回调地址packageParams.add(new BasicNameValuePair("out_trade_no",genOutTradNo()));packageParams.add(new BasicNameValuePair("total_fee", "1"));packageParams.add(new BasicNameValuePair("trade_type", "APP"));String sign=getPackageSign(packageParams);packageParams.add(new BasicNameValuePair("sign", sign));String xmlString=toXml(packageParams);return xmlString;} catch (Exception e) {// TODO: handle exceptionreturn null;}}//生成订单号,测试用,在客户端生成private String genOutTradNo() {Random random = new Random();
// return "dasgfsdg1234"; //订单号写死的话只能支付一次,第二次不能生成订单return MD5.getMessageDigest(String.valueOf(random.nextInt(10000)).getBytes());}//生成随机号,防重发private String getNonceStr() {// TODO Auto-generated method stubRandom random=new Random();return MD5.getMessageDigest(String.valueOf(random.nextInt(10000)).getBytes());}/**生成签名*/private String getPackageSign(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("Simon",">>>>"+packageSign);return packageSign;}/** 转换成xml*/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("Simon",">>>>"+sb.toString());return sb.toString();}}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
- 90
- 91
- 92
- 93
- 94
- 95
- 96
- 97
- 98
- 99
- 100
- 101
- 102
- 103
- 104
- 105
- 106
- 107
- 108
- 109
- 110
- 111
- 112
- 113
- 114
- 115
- 116
- 117
- 118
- 119
- 120
- 121
- 122
- 123
- 124
- 125
- 126
- 127
- 128
- 129
- 130
- 131
- 132
- 133
- 134
- 135
- 136
- 137
- 138
- 139
- 140
- 141
- 142
- 143
- 144
- 145
- 146
- 147
- 148
- 149
- 150
- 151
- 152
- 153
- 154
- 155
- 156
- 157
- 158
- 159
- 160
- 161
- 162
- 163
- 164
- 165
- 166
- 167
- 168
- 169
- 170
- 171
- 172
- 173
- 174
- 175
- 176
- 177
- 178
- 179
- 180
- 181
- 182
- 183
- 184
- 185
- 186
- 187
- 188
- 189
- 190
- 191
- 192
- 193
- 194
- 195
- 196
- 197
- 198
- 199
- 200
- 201
- 202
- 203
- 204
- 205
- 206
- 207
- 208
- 209
- 210
- 211
- 212
- 213
- 214
- 215
- 216
- 217
- 218
- 219
- 220
- 221
- 222
- 223
- 224
- 225
- 226
- 227
- 228
- 229
- 230
- 231
- 232
- 233
- 234
- 235
- 236
- 237
- 238
- 239
- 240
- 241
- 242
- 243
- 244
- 245
- 246
- 247
- 248
- 249
- 250
- 251
- 252
- 253
- 254
- 255
- 256
- 257
- 258
- 259
- 260
- 261
- 262
- 263
- 264
- 265
- 266
- 267
- 268
- 269
- 270
- 271
- 272
- 273
- 274
- 275
- 276
- 277
- 278
- 279
- 280
- 281
- 282
- 283
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
- 90
- 91
- 92
- 93
- 94
- 95
- 96
- 97
- 98
- 99
- 100
- 101
- 102
- 103
- 104
- 105
- 106
- 107
- 108
- 109
- 110
- 111
- 112
- 113
- 114
- 115
- 116
- 117
- 118
- 119
- 120
- 121
- 122
- 123
- 124
- 125
- 126
- 127
- 128
- 129
- 130
- 131
- 132
- 133
- 134
- 135
- 136
- 137
- 138
- 139
- 140
- 141
- 142
- 143
- 144
- 145
- 146
- 147
- 148
- 149
- 150
- 151
- 152
- 153
- 154
- 155
- 156
- 157
- 158
- 159
- 160
- 161
- 162
- 163
- 164
- 165
- 166
- 167
- 168
- 169
- 170
- 171
- 172
- 173
- 174
- 175
- 176
- 177
- 178
- 179
- 180
- 181
- 182
- 183
- 184
- 185
- 186
- 187
- 188
- 189
- 190
- 191
- 192
- 193
- 194
- 195
- 196
- 197
- 198
- 199
- 200
- 201
- 202
- 203
- 204
- 205
- 206
- 207
- 208
- 209
- 210
- 211
- 212
- 213
- 214
- 215
- 216
- 217
- 218
- 219
- 220
- 221
- 222
- 223
- 224
- 225
- 226
- 227
- 228
- 229
- 230
- 231
- 232
- 233
- 234
- 235
- 236
- 237
- 238
- 239
- 240
- 241
- 242
- 243
- 244
- 245
- 246
- 247
- 248
- 249
- 250
- 251
- 252
- 253
- 254
- 255
- 256
- 257
- 258
- 259
- 260
- 261
- 262
- 263
- 264
- 265
- 266
- 267
- 268
- 269
- 270
- 271
- 272
- 273
- 274
- 275
- 276
- 277
- 278
- 279
- 280
- 281
- 282
- 283
接下来就是有个支付结果的页面代码。是微信官方提供的一个类。你要在manifest注册这个类。这里需要注意的是,这个类必须放在wxapi包下,你自己新建一个包即可。
为了大家可以直接运行这个demo,我的微信加签都是在本地执行的,获取prepayid和加签都应该在服务端完成,还有最终的支付返回结果也是以服务端的为准。
*下面给出运行结果图*
大家下载demo然后把参数换了,弄下keystore,包名,签名。应该就可以用了。
Android 微信支付详解与Demo相关推荐
- android安装多个微信支付,android微信支付详解与坑
要想在自己的APP中实现APP支付必须申请开通支付功能,这些按着文档来吧,我还是直接说Android中的问题吧. 一.签名 一定要在开放平台为自己的APP配置正确的包名和签名(签名:将APP打一个正式 ...
- Java=微信支付详解与日志记录详解
一.二维码: (1)什么是二维码 二维码又称QR Code,QR全称Quick Response,是一个近几年来移动设备上超流行的一种编码方式,它比传统的Bar Code条形码能存更多的信息,也能表示 ...
- Android 集成微信支付详解
打包后才能起调支付 微信支付成功起调 微信skd下载:https://pay.weixin.qq.com/wiki/doc/api/app/app.php?chapter=11_1 签名APK下载:h ...
- 微信小程序API——微信支付详解(顺便讲一下我遇见的坑)
学习微信小程序已经半个多月了,终于接触到小程序中一个很重要的功能--微信支付.接下来就给大家详细讲解一下微信支付功能的调用. 一想到微信支付,大家一定会去看微信小程序的API文档,没错,作为一个菜鸟我 ...
- Java对接微信支付详解
一.介绍 微信支付对于我们日常来说,并不陌生,也许我们日常都在用.现在我就讲一下微信支付的流程是怎么实现的,都有哪些步骤,以及注意点. 支付流程图: 参数说明如图: 二.开发步骤 1.首先需要开通商户 ...
- 微信支付详解与取消支付回调
第一步:绑定域名 先登录微信公众平台进入"公众号设置"的"功能设置"里填写"JS接口安全域名".如果你使用了支付类接口,请确保支付目录在该安 ...
- android+微信支付
微信支付 目录 微信支付 1 一. 创建应用 2 二. 支付集成 5 1.body字段格式 8 三. 参考网址 12 四. Android Studio的两种模式及签名配置 12 一. 创建应用 1& ...
- 字节跳动小程序支付详解
微信支付详解 1.为什么要写这篇文章 参考了字节跳动官方的文档之后发现写的太简单,完全一头雾水摸不清头脑,后来在百度了别人的实现方案,才得以总结出来. 2.背景 我司要开发一个头条小程序,需要支持支付 ...
- android微信支付代码,详解android微信支付实例代码
这篇文章主要为大家详细介绍了http://www.php.cn/wiki/1502.html" target="_blank">android微信支付源码,具有一定 ...
最新文章
- img to image_tag
- 移动通信网络协议 — GTP 协议
- React Native的TextInput组件去掉下划线和使用背景图片
- 数据库以及后台开发之写在前面
- 最大公因数、最小公倍数、因式分解
- 原来流行也可以变成怀旧!
- GCC 链接时出现undefined reference to “...”时可能解决办法
- Mysql中Innodb大量插入数据时SQL语句的优化
- git cherry-pick 复制其他分支内容到当前分支
- registerModule: 动态注册vuex模块,对于自定义生成组件很有用
- java.lang.IllegalArgumentException at java.sql.Date.getHours
- Linux下获取时间差(毫秒级)
- java treetable_00035-layui+java 树形表格treeTable(异步请求)
- Zigbee协议栈中文说明
- 从GDPR和个保法看,为什么要做数据合规?
- 辐射光电流测试软件,资深工程师告诉你如何使用示波器测试EMI辐射干扰
- 手把手教你做一个APP应用(含源码)
- 错误: 找不到符号 符号: 类 DaggerActivityComponent错误解决
- node+express+mysql搭建一个系统
- 分类算法常用的评价指标