第一步:应用注册,获取APPID
网址:https://open.weixin.qq.com/
申请过程中,这个应用签名使用的基本是使用release_keystore进行打包后,产生的应用签名
获取工具应用签名工具:
申请成功后,可以获得应用的APPID
第二步:在build.gradle里添加
compile 'com.tencent.mm.opensdk:wechat-sdk-android-with-mta:+'
注意需要在manifest里添加
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<!-- for mta statistics -->
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
<uses-permission android:name="android.permission.READ_PHONE_STATE"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
第三步:添加回调类WXPayEntryActivity,目录及目录级别固定
WXPayEntryActivity内容如下:
public class WXPayEntryActivity extends Activity implements IWXAPIEventHandler {
private IWXAPI api;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
api = WXAPIFactory.createWXAPI(this, "wx70adbb05c1b5d516");
api.handleIntent(getIntent(), this);
}
@Override
protected void onNewIntent(Intent intent) {
super.onNewIntent(intent);
setIntent(intent);
api.handleIntent(intent, this);
}
@Override
public void onReq(BaseReq req) {
}
@Override
public void onResp(BaseResp resp) {
Log.e("PAY_GET", "onPayFinish, errCode = " + resp.errCode);
if (resp.getType() == ConstantsAPI.COMMAND_PAY_BY_WX) {
if (resp.errCode == 0) {
Toast.makeText(this, "支付成功", Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(this, "支付失败,请重试", Toast.LENGTH_SHORT).show();
}
finish();
}
}
}
这里只是做了简单的提示,你们也可以根据需求,自定义如何显示
注意需要在manifest里添加:
<activity
android:name=".wxapi.WXPayEntryActivity"
android:exported="true"
android:launchMode="singleTop"/>
第四步:微信支付(服务器生成签名)
①向服务器请求,拿到数据
②微信支付
请求部分我就不写了,随意的OkHttp,HttpURLConnection,使用随意
下面就直接上代码了,拿到请求数据后:
private void wxPay(Context context, String appid, String url) {
IWXAPI api = WXAPIFactory.createWXAPI(context, appid); //初始化微信api
api.registerApp(appid); //注册appid appid可以在开发平台获取
Toast.makeText(context, "获取订单中...", Toast.LENGTH_SHORT).show();
try {
String content = Util.httpGet(url);
Log.e("get server pay params:", content);
JSONObject json = new JSONObject(content);
if (null != json && !json.has("retcode")) {
PayReq req = new PayReq();
req.appId = json.getString("appid"); //应用ID
req.partnerId = json.getString("partnerid"); //商户号
req.prepayId = json.getString("prepayid"); //预支付交易会话ID
req.nonceStr = json.getString("noncestr"); //随机字符串
req.timeStamp = json.getString("timestamp"); //时间戳
req.packageValue = json.getString("package"); //拓展字段
req.sign = json.getString("sign"); //签名
Toast.makeText(context, "正常调起支付", Toast.LENGTH_SHORT).show();
// 在支付之前,如果应用没有注册到微信,应该先调用IWXMsg.registerApp将应用注册到微信
api.sendReq(req);
} else {
Log.d("PAY_GET", "返回错误" + json.getString("retmsg"));
Toast.makeText(context, "返回错误" + json.getString("retmsg"), Toast.LENGTH_SHORT).show();
}
} catch (Exception e) {
Log.e("PAY_GET", "异常:" + e.getMessage());
Toast.makeText(context, "异常:" + e.getMessage(), Toast.LENGTH_SHORT).show();
}
}
基本上到这就结束了,但是在开发过程中,可能还会遇到其他各种各样的事情,在这里,我先把我遇到的问题po出来,作为拓展
拓展 一 :只成功一次,或者一次未成功,即未调用起来微信程序
问题在于应用签名,注册时使用的是release_keystore打包的应用,使用时也是要使用release_keystore打包的应用
拓展 二:签名不在服务器端,在客户端(这个我没遇到,但查找资料的时候碰到过,未经过测试,留着以后备用)
上代码:
/**
* key 根据需求设置,在最后的签名过程中,添加"key = "+ key
*/
public void toWXPayAndSign(Context context, String appid, final String key, String url) {
IWXAPI api = WXAPIFactory.createWXAPI(context, null); //初始化微信api
api.registerApp(appid); //注册appid appid可以在开发平台获取
Toast.makeText(context, "获取订单中...", Toast.LENGTH_SHORT).show();
try {
String content = Util.httpGet(url);
Log.e("get server pay params:", content);
JSONObject json = new JSONObject(content);
if (null != json && !json.has("retcode")) {
PayReq req = new PayReq();
req.appId = json.getString("appid"); //应用ID
req.partnerId = json.getString("partnerid"); //商户号
req.prepayId = json.getString("prepayid"); //预支付交易会话ID
req.nonceStr = genNonceStr(); //随机字符串
req.timeStamp = String.valueOf(genTimeStamp()); //时间戳
req.packageValue = "Sign=WXPay"; //拓展字段
//签名
LinkedHashMap<String, String> signParams = new LinkedHashMap<>();
signParams.put("appid", req.appId);
signParams.put("noncestr", req.nonceStr);
signParams.put("package", req.packageValue);
signParams.put("partnerid", req.partnerId);
signParams.put("prepayid", req.prepayId);
signParams.put("timestamp", req.timeStamp);
req.sign = genPackageSign(signParams, key); //签名
Toast.makeText(context, "正常调起支付", Toast.LENGTH_SHORT).show();
// 在支付之前,如果应用没有注册到微信,应该先调用IWXMsg.registerApp将应用注册到微信
api.sendReq(req);
} else {
Log.d("PAY_GET", "返回错误" + json.getString("retmsg"));
Toast.makeText(context, "返回错误" + json.getString("retmsg"), Toast.LENGTH_SHORT).show();
}
} catch (Exception e) {
Log.e("PAY_GET", "异常:" + e.getMessage());
Toast.makeText(context, "异常:" + e.getMessage(), Toast.LENGTH_SHORT).show();
}
}
/**
* 调起微信APP支付,签名
* 生成签名
*/
private String genPackageSign(LinkedHashMap<String, String> params, String key) {
StringBuilder sb = new StringBuilder();
for (Map.Entry<String, String> entry : params.entrySet()) {
sb.append(entry.getKey());
sb.append('=');
sb.append(entry.getValue());
sb.append('&');
}
sb.append("key=");
sb.append(key);
String packageSign = getMessageDigest(sb.toString().getBytes()).toUpperCase();
return packageSign;
}
/**
* 获取随机数
*
* @return
*/
private String genNonceStr() {
Random random = new Random();
return getMessageDigest(String.valueOf(random.nextInt(10000)).getBytes());
}
/**
* md5加密
*
* @param buffer
* @return
*/
private String getMessageDigest(byte[] buffer) {
char hexDigits[] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
try {
MessageDigest mdTemp = MessageDigest.getInstance("MD5");
mdTemp.update(buffer);
byte[] md = mdTemp.digest();
int j = md.length;
char str[] = new char[j * 2];
int k = 0;
for (int i = 0; i < j; i++) {
byte byte0 = md[i];
str[k++] = hexDigits[byte0 >>> 4 & 0xf];
str[k++] = hexDigits[byte0 & 0xf];
}
return new String(str);
} catch (Exception e) {
return null;
}
}
/**
* 获取时间戳
*
* @return
*/
private long genTimeStamp() {
return System.currentTimeMillis() / 1000;
}
拓展 三:微信支付官方Demo
总有一些小伙伴想把微信支付官方demo跑起来,奈何理想是美好的,现实是残酷的,在运行的过程中,总会遇到这样,那样的奇葩问题,下面附加个地址吧:
解决新版Android studio导入微信支付和支付宝官方Demo的问题
我遇到的问题(问题详情忘记了,只记得解决方法了):
在build.gradle里不要依赖jar包,替换成第二步的依赖
compile 'com.tencent.mm.opensdk:wechat-sdk-android-with-mta:+'
运行过程中出现的奇葩问题:
demo 只有第一次运行成功了,之后都是返回-1:把微信的缓存清了,如果还不行,数据也清了