上一篇讲的是支付宝支付,现在讲讲微信支付。微信支付的坑比支付宝多,过程也比支付宝麻烦,很多时候你根本不知道问题出在哪里,网上其他的博客也不是令我满意,特此写这篇博客。
1.参照官方文档配置
Android开发要点说明
1、后台设置
商户在微信开放平台申请开发应用后,微信开放平台会生成APP的唯一标识APPID。由于需要保证支付安全,需要在开放平台绑定商户应用包名和应用签名,设置好后才能正常发起支付。设置界面在【开放平台】中的栏目【管理中心 / 修改应用 / 修改开发信息】里面,如图8.8红框内所示。
应用包名:是在APP项目配置文件AndroidManifest.xml中声明的package值,例如DEMO中的package="net.sourceforge.simcpux"。
应用签名:根据项目的应用包名和编译使用的keystore,可由签名工具生成一个32位的md5串,在调试的手机上安装签名工具后,运行可生成应用签名串,如图8.9所示,绿色串即应用签名。签名工具下载地址https://open.weixin.qq.com/zh_CN/htmledition/res/dev/download/sdk/Gen_Signature_Android.apk
图8.9
2、注册APPID
商户APP工程中引入微信JAR包,调用API前,需要先向微信注册您的APPID,代码如下:
final IWXAPI msgApi = WXAPIFactory.createWXAPI(context, null);
// 将该app注册到微信
msgApi.registerApp("wxd930ea5d5a258f4f");
3、调起支付
商户服务器生成支付订单,先调用统一下单API(详见第7节)生成预付单,获取到prepay_id后将参数再次签名传输给APP发起支付。以下是调起微信支付的关键代码:
IWXAPI api;
PayReq request = new PayReq();
request.appId = "wxd930ea5d5a258f4f";
request.partnerId = "1900000109";
request.prepayId= "1101000000140415649af9fc314aa427",;
request.packageValue = "Sign=WXPay";
request.nonceStr= "1101000000140429eb40476f8896f4c9";
request.timeStamp= "1398746574";
request.sign= "7FFECB600D7157C5AA49810D2D8F28BC2811827B";
api.sendReq(req);
注意:该sign生成字段名列表见调起支付API
4、支付结果回调
参照微信SDK Sample,在net.sourceforge.simcpux.wxapi包路径中实现WXPayEntryActivity类(包名或类名不一致会造成无法回调),在WXPayEntryActivity类中实现onResp函数,支付完成后,微信APP会返回到商户APP并回调onResp函数,开发者需要在该函数中接收通知,判断返回错误码,如果支付成功则去后台查询支付结果再展示用户实际支付结果。注意一定不能以客户端返回作为用户支付的结果,应以服务器端的接收的支付通知或查询API返回的结果为准。代码示例如下:
publicvoidonResp(BaseRespresp){
if(resp.getType()==ConstantsAPI.COMMAND_PAY_BY_WX){
Log.d(TAG,"onPayFinish,errCode="+resp.errCode);
AlertDialog.Builderbuilder=newAlertDialog.Builder(this);
builder.setTitle(R.string.app_tip);
}
}
回调中errCode值列表:
名称 | 描述 | 解决方案 |
---|---|---|
0 | 成功 | 展示成功页面 |
-1 | 错误 | 可能的原因:签名错误、未注册APPID、项目设置APPID不正确、注册的APPID与设置的不匹配、其他异常等。 |
-2 | 用户取消 | 无需处理。发生场景:用户不支付了,点击取消,返回APP。 |
api= WXAPIFactory.createWXAPI(this, WXUtils.APP_ID,false); api.registerApp(WXUtils.APP_ID);
向自己的服务器发送请求获取微信支付需要的各个参数
跑上那个手机,将包名输入到那个签名工具后获取字符串填到微信开放平台那里,记住不用担心什么签名是不是打包的签名,打不打包都可以JSONObject wxpay = new JSONObject(); RequestParams params = new RequestParams(); wxpay.put("tokenId", login.tokenId); wxpay.put("userSid", login.userSid); ServerSell value = serverSells.get(proPosition); wxpay.put("serviceType", value.getServiceType()); wxpay.put("orderId", orderId); wxpay.put("paymentFee", 0.01); String ip = WXUtils.getPhoneIp(BuyOutlayActivity.this); // String ip = WXUtils.getLocalIpAddress(); Log.e(TAG, ip); wxpay.put("spbillCreateIp", ip); Log.e(TAG, wxpay.toJSONString()); params.put("data", wxpay.toJSONString()); Log.e(TAG, params.toString()); client.post(AppNetConfig.signWeixinOrder, params, new AsyncHttpResponseHandler() { @Override public void onSuccess(String content) { super.onSuccess(content); com.alibaba.fastjson.JSONObject jsonObject = JSON.parseObject(content); if (null == jsonObject) { UIUtils.Toast("网络请求失败", false); return; } if (("N01").equals(jsonObject.getString("code"))) { json = jsonObject.getJSONObject("contents"); Log.e(TAG, "json" + json.toString()); Message message = mHandler.obtainMessage(); message.what = SUCCESS_ON_WX; mHandler.sendMessage(message); } else if (("E01").equals(jsonObject.getString("code"))) { } else if (("E04").equals(jsonObject.getString("code"))) { } } });用Handler进行主线程消息传递
case SUCCESS_ON_WX: requestForWX(); break;private void requestForWX() { if (MyApplication.api.getWXAppSupportAPI() >= Build.PAY_SUPPORTED_SDK_INT) { PayReq req = new PayReq(); req.appId = WXUtils.APP_ID; req.partnerId = json.getString("partnerId"); req.prepayId = json.getString("prepayId"); req.nonceStr = json.getString("nonceStr"); req.timeStamp = json.getString("timestamp"); req.packageValue = json.getString("package"); req.sign = json.getString("sign"); req.extData = "app data"; // optional; Log.e(TAG,"req.partnerId"+req.partnerId+"req.prepayId"+req.prepayId); Toast.makeText(BuyOutlayActivity.this, "正常调起支付", Toast.LENGTH_SHORT).show(); // 在支付之前,如果应用没有注册到微信,应该先调用IWXMsg.registerApp将应用注册到微信 boolean sendReq = MyApplication.api.sendReq(req); Toast.makeText(BuyOutlayActivity.this, "sendReq" + sendReq, Toast.LENGTH_SHORT).show(); } else { UIUtils.Toast("您的微信版本暂时不支持支付", false); } }3.在你的项目的包名下(必须是项目的包名下)新建文件夹wxapi,然后新建一个类WXPayEntryActivity 继承 Activity
代码如下
package com.milan.yuanguu.wxapi; import android.app.Activity; import android.app.AlertDialog; import android.content.Intent; import android.os.Bundle; import com.milan.yuanguu.R; import com.milan.yuanguu.common.MyApplication; import com.tencent.mm.sdk.constants.ConstantsAPI; import com.tencent.mm.sdk.modelbase.BaseReq; import com.tencent.mm.sdk.modelbase.BaseResp; import com.tencent.mm.sdk.openapi.IWXAPIEventHandler; public class WXPayEntryActivity extends Activity implements IWXAPIEventHandler { private static final String TAG = "MicroMsg.SDKSample.WXPayEntryActivity"; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.pay_result); MyApplication.api.handleIntent(getIntent(), this); } @Override protected void onNewIntent(Intent intent) { super.onNewIntent(intent); setIntent(intent); MyApplication.api.handleIntent(intent, this); } @Override public void onReq(BaseReq req) { } @Override public void onResp(BaseResp resp) { //Log.e(TAG, "onPayFinish, errCode = " + resp.errCode); if (resp.getType() == ConstantsAPI.COMMAND_PAY_BY_WX) { AlertDialog.Builder builder = new AlertDialog.Builder(this); builder.setTitle(R.string.app_tip); builder.setMessage(getString(R.string.pay_result_callback_msg, String.valueOf(resp.errCode))); builder.show(); } } }《注意》容易出现问题的几个地方1.在微信开放平台注册的那个签名有问题,解决方式是按照官方文档下载那个签名工具,然后把自己的项目同时