微信支付
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所示。
安卓sdk下载
https://pay.weixin.qq.com/wiki/doc/api/app/app.php?chapter=11_1
微信开放平台
https://open.weixin.qq.com/
微信android开发手册
https://open.weixin.qq.com/cgi-bin/showdocument?action=dir_list&t=resource/res_list&verify=1&id=open1419317784&token=&lang=zh_CN
微信app开发步骤
https://pay.weixin.qq.com/wiki/doc/api/app/app.php?chapter=8_5
开始接入微信支付
1.在项目中引入微信开发包
2.在AndroidManifest.xml中添加相应的权限
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
<uses-permission android:name="android.permission.READ_PHONE_STATE"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
3.在MainActivity中注册到为微信
配置debug签名
创建应用需要填写应用签名,配置在debug下直接用的正式的key,这样就不用每次打包才能调起微信客户端
signingConfigs {
debug {
storeFile file("你的keystore路径")
storePassword "xxx"
keyAlias "xxx"
keyPassword "xxx"
}
release {
storeFile file("你的keystore路径")
storePassword "xxx"
keyAlias "xxx"
keyPassword "xxx"
}
}
3.在MainActivity中注册到为微信
api= WXAPIFactory.createWXAPI(this,ConfigUtil.Wechat_Appid,true);
api.registerApp(ConfigUtil.Wechat_Appid);
4.在点击的时候向微信发送请求
case R.id.wechat_pay:
PayReq request = new PayReq();
request.appId = ConfigUtil.Wechat_Appid;
request.partnerId = "1327244301";
request.prepayId= "wx2016092009564343e737275f0904349502";
request.packageValue = "Sign=WXPay";
request.nonceStr= "70vhVHnJj6ph7mf9";
request.timeStamp= "1474336603";
request.sign= "815BC8D5508FD90F7A978856B2174E21";
api.sendReq(request);
break;
5.配置回调
[1]在微信管理后台中配置的包名下新建wxapi包
[2]在wxapi包下新建WXPayEntryActivity的类(注意这个类的位置和名称不能改变)
[3]WXPayEntryActivity类实现IWXAPIEventHandler继承Activity,该布局文件自己定义即可
[4]在AndroidManifest.xml中注册activity
<activity
android:name=".wxapi.WXPayEntryActivity"
android:exported="true"
android:launchMode="singleTop"/>
[5]在WXPayEntryActivity类中onCreate中注册微信
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实现点击支付按钮,弹起自定义输入法进行密码输入: 点我哦!
微信扫一扫揭秘: 猛戳这里!