Android端接入微信支付的详细流程
Posted 轩辕223
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Android端接入微信支付的详细流程相关的知识,希望对你有一定的参考价值。
随着微信支付的越来越普及,现在几乎所有的app都会接入微信的支付API,我当前也遇到了这个问题,查了 微信的网页介绍,但还是走了很多弯路,所以把我的经验分享出来,防止网友再走弯路。
我会参照微信的api介绍,加上微信给的demo一步一步来说。
微信支付接入介绍参见:https://pay.weixin.qq.com/wiki/doc/api/app.php?chapter=8_5
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
这一步就是用来验证APP合法性的,做APP的人应该都知道,简单配置一下就可以啦。
2、注册APPID
商户APP工程中引入微信JAR包,调用API前,需要先向微信注册您的APPID,代码如下:
API调用前,需要先向微信注册您的APP,代码如下:
final IWXAPI msgApi = WXAPIFactory.createWXAPI(context, null);
// 将该app注册到微信
msgApi.registerApp("wxd930ea5d5a258f4f");
还要在Manifest文件中加入你的APPID
<span style="color:#222222;"><activity
android:name=".PayActivity"
android:label="@string/app_name"
android:exported="true"
android:launchMode="singleTop">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.VIEW"/>
<category android:name="android.intent.category.DEFAULT"/>
</span><span style="color:#ff0000;"><data android:scheme="wxf2f565574a968187"/></span><span style="color:#222222;">
</intent-filter>
</activity></span>
代码里体现在
<span style="color:#222222;">package com.weixin.paydemo;
public class PayActivity extends Activity
private static final String TAG = "MicroMsg.SDKSample.PayActivity";
PayReq req;
</span><span style="color:#ff0000;">final IWXAPI msgApi = WXAPIFactory.createWXAPI(this, null);</span><span style="color:#222222;">
TextView show;
Map<String,String> resultunifiedorder;
StringBuffer sb;
@Override
protected void onCreate(Bundle savedInstanceState)
super.onCreate(savedInstanceState);
setContentView(R.layout.pay);
show =(TextView)findViewById(R.id.editText_prepay_id);
req = new PayReq();
sb=new StringBuffer();
</span><span style="color:#ff0000;">msgApi.registerApp(Constants.APP_ID);</span><span style="color:#222222;">
//生成prepay_id
Button payBtn = (Button) findViewById(R.id.unifiedorder_btn);
payBtn.setOnClickListener(new View.OnClickListener()
@Override
public void onClick(View v)
GetPrepayIdTask getPrepayId = new GetPrepayIdTask();
getPrepayId.execute();
);
Button appayBtn = (Button) findViewById(R.id.appay_btn);
appayBtn.setOnClickListener(new View.OnClickListener()
@Override
public void onClick(View v)
sendPayReq();
);
//生成签名参数
Button appay_pre_btn = (Button) findViewById(R.id.appay_pre_btn);
appay_pre_btn.setOnClickListener(new View.OnClickListener()
@Override
public void onClick(View v)
genPayReq();
);
String packageSign = MD5.getMessageDigest(sb.toString().getBytes()).toUpperCase();
</span>
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
代码Demo
private void sendPayReq()
msgApi.registerApp(Constants.APP_ID);
msgApi.sendReq(req);
这个req包含参数,参数生成方法如下
private void genPayReq()
<span style="color:#ff0000;">req.appId = Constants.APP_ID;
req.partnerId = Constants.MCH_ID;
req.prepayId = resultunifiedorder.get("prepay_id");
req.packageValue = "Sign=WXPay";
req.nonceStr = genNonceStr();
req.timeStamp = String.valueOf(genTimeStamp());</span>
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");
show.setText(sb.toString());
Log.e("orion", 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()).toUpperCase();
Log.e("orion",appSign);
return appSign;
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 void onPostExecute(Map<String,String> result)
if (dialog != null)
dialog.dismiss();
sb.append("prepay_id\\n"+result.get("prepay_id")+"\\n\\n");
show.setText(sb.toString());
resultunifiedorder=result;
@Override
protected void onCancelled()
super.onCancelled();
@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);
String content = new String(buf);
Log.e("orion", content);
Map<String,String> xml=decodeXml(content);
return xml;
4,这样应该就能调起微信支付了,还有最重要的一步是,接收微信的返回结果,微信定义了一个入口,你需要在你自己的应用程序中定义这个入口,微信在支付完成后会回调这个入口的方法,代码如下:
AndroidManifest文件中先定义
<activity
android:name="com.weixin.paydemo.wxapi.WXPayEntryActivity"
android:exported="true"
android:launchMode="singleTop"/>
<receiver
android:name="net.sourceforge.simcpux.AppRegister">
<intent-filter>
<action android:name="com.tencent.mm.plugin.openapi.Intent.ACTION_REFRESH_WXAPP" />
</intent-filter>
</receiver>
public class WXPayEntryActivity extends Activity<span style="color:#ff0000;"> implements IWXAPIEventHandler</span>
private static final String TAG = "MicroMsg.SDKSample.WXPayEntryActivity";
private IWXAPI api;
@Override
public void onCreate(Bundle savedInstanceState)
super.onCreate(savedInstanceState);
setContentView(R.layout.pay_result);
api = WXAPIFactory.createWXAPI(this, Constants.APP_ID);
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)
<span style="color:#ff0000;">@Override
public void onResp(BaseResp resp)
Log.d(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, resp.errStr +";code=" + String.valueOf(resp.errCode)));
builder.show();
</span>
OK,一套完整的微信支付方法就完成了。
之前有网友问,一个APP里面可以有两个微信的APPID吗,也就是可以付款到两个微信账户吗,从代码来看好像是不可以的,因为首先应用程序会注册到一个APPID上,我认为微信会在sendREq的时候验证APPID和应用程序的对应性,但后来我发现其实可以,因为微信并没有这样做,也就是说在第二步注册APPID,你按照正常流程注册完之后,在第三步发送req的时候,你可以使用任意的APPID,想付款到那个账号就发送哪个APPID,是不是很爽,值得注意的是第三步中的req的APPID需要和prepayid里的APPID对应起来。
这样虽然用起来比较方便,但我总觉得可能不安全,也就是说微信之前做了那么多的验证工作,在关键的一步却没有验证,是不是很可笑。虽然还没有想到问题在哪里,再让我考虑下。
OK,到这里就结束了。有问题可以评论
以上是关于Android端接入微信支付的详细流程的主要内容,如果未能解决你的问题,请参考以下文章