赞
踩
随着微信支付的越来越普及,现在几乎所有的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;
- }
- }

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,到这里就结束了。有问题可以评论
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。