您的位置:首页 > 移动开发 > 微信开发

安卓微信支付开发基本流程-实际开发篇

2016-11-02 11:57 429 查看
之前写过一篇微信支付的官方demo篇,点击查看详情。现在支付模块已经完成了,所以应该把正式项目中的问题和源码和记录下,以备以后参考。

安卓端的app支付流程官方讲的比较详细了,所以开发的时候一定要仔细阅读,按照步骤开发,碰到问题基本百度都能搞定。点击这里查看官方app开发文档

Android开发要点说明

1、后台设置

商户在微信开放平台申请开发应用后,微信开放平台会生成APP的唯一标识APPID。由于需要保证支付安全,需要在开放平台绑定商户应用包名和应用签名,设置好后才能正常发起支付。设置界面在【开放平台】中的栏目【管理中心 / 修改应用 / 修改开发信息】里面,如图8.8红框内所示。



图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,代码如下:



private IWXAPI api= WXAPIFactory.createWXAPI(this, null);


 将该app注册到本地微信

api.registerApp("这里添你申请的appid");


3、调起支付

商户服务器生成支付订单,先调用统一下单API(点这里,这个接口由后台人员调用)生成预付单,获取到prepay_id后封装数据(点击查看需要的参数列表)调其本地微信APP发起支付。app端请求服务器获取预支付订单号,其他信息可以在app端生成。(比如签名key可以保存在app端,但是不太安全)

以下是调起微信支付的关键代码:

<span style="white-space:pre">	</span>/**
* 本地根据key生成签名sign
*/
String randomString = getRandomStringByLength(12);//生成唯一字随机字符串
String time = System.currentTimeMillis()+"";//生成时间戳
String pre_id = json.getString("prepay_id");//从返回数据获取订单号
SortedMap<Object,Object> parameters = new TreeMap<Object,Object>();
parameters.put("appid", "你的appid");
parameters.put("partnerid", "你的商户id");
parameters.put("prepayid", pre_id);
parameters.put("package", "Sign=WXPay");
parameters.put("noncestr", randomString);
parameters.put("timestamp",time );
String signed = createSign("UTF_8", parameters);
/**
* 封装好请求参数
*/

PayReq req = new PayReq();
req.appId = "你的appid";
req.partnerId = "你的商户id";
req.prepayId = pre_id;
req.nonceStr = randomString;
req.timeStamp = time;
req.packageValue = "Sign=WXPay";
req.sign =signed;
LogUtil.d("pre_id",pre_id.toString());

// 在支付之前,如果应用没有注册到微信,应该先调用IWXMsg.registerApp将应用注册到微信
api.sendReq(req);
请求后台获取预支付订单号以后,封装数据加签名,然后调起微信支付。 

生成随机字符串的方法:(直接用)

/**
* 生成随机字符串
* @param length
* @return
*/
public static String getRandomStringByLength(int length) {
String base = "abcdefghijklmnopqrstuvwxyz0123456789";
Random random = new Random();
StringBuffer sb = new StringBuffer();
for (int i = 0; i < length; i++) {
int number = random.nextInt(base.length());
sb.append(base.charAt(number));
}
return sb.toString();
}
签名方法:(直接用)

private static String Key = "输入你设置的key";//<span style="color: rgb(34, 34, 34); font-family: 'Helvetica Neue', 'Hiragino Sans GB', 'Microsoft YaHei', 黑体, Arial, sans-serif; font-size: 14px; line-height: 22.4px;">key设置路径:微信商户平台(pay.weixin.qq.com)-->账户设置-->API安全-->密钥设置</span>
/**
* 微信支付签名算法sign
* @param characterEncoding
* @param parameters
* @return
*/
@SuppressWarnings("unchecked")
public static String createSign(String characterEncoding,SortedMap<Object,Object> parameters){
StringBuffer sb = new StringBuffer();
Set es = parameters.entrySet();//1.所有参与传参的参数按照accsii排序(升序)
Iterator it = es.iterator();
while(it.hasNext()) {//2.生成字符串
Map.Entry entry = (Map.Entry)it.next();
String k = (String)entry.getKey();
Object v = entry.getValue();
if(null != v && !"".equals(v)
&& !"sign".equals(k) && !"key".equals(k)) {
sb.append(k + "=" + v + "&");
}
}
sb.append("key=" + Key);//3.把key拼接进去
String sign = MD5Util.MD5Encode(sb.toString(), characterEncoding).toUpperCase();//md5加密
return sign;
}
附上官方的签名算法解释:点这里

4、支付结果回调

参照微信SDK Sample,在xxx.xxx.xxx.wxapi包路径中实现WXPayEntryActivity类(注意这里的xxx路径要和清单文件中的报名路径一致。)

比如我的路径是这样的

在清单文件中注册的包名必须是

如果这2个路径不一致,无法调起回调方法。

在WXPayEntryActivity类中实现onResp函数,支付完成后,微信APP会返回到商户APP并回调onResp函数,开发者需要在该函数中接收通知,判断返回错误码,如果支付成功则去后台查询支付结果再展示用户实际支付结果。注意一定不能以客户端返回作为用户支付的结果,应以服务器端的接收的支付通知或查询API返回的结果为准。代码示例如下:(代码可以直接用)

package com.dudu.helper3.wxapi;

import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;

import com.dudu.helper3.BaseActivity;
import com.dudu.helper3.R;
import com.dudu.helper3.Utils.LogUtil;
import com.tencent.mm.sdk.modelbase.BaseReq;
import com.tencent.mm.sdk.modelbase.BaseResp;
import com.tencent.mm.sdk.openapi.IWXAPI;
import com.tencent.mm.sdk.openapi.IWXAPIEventHandler;
import com.tencent.mm.sdk.openapi.WXAPIFactory;
public class WXPayEntryActivity extends BaseActivity implements IWXAPIEventHandler {

private IWXAPI api;
private TextView tv_res;

@Override public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
LogUtil.d("jieguo","ol");

setContentView(R.layout.activity_pay_result);
tv_res = (TextView) findViewById(R.id.tv_res);
Button btn_back = (Button) findViewById(R.id.btn_back);
btn_back.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
finish();
}
});
initHeadView("支付结果",true,false,0);
api = WXAPIFactory.createWXAPI(this, "wxa43dd59c979e6ab7");
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) {
int errCode = resp.errCode;
LogUtil.d("resp",resp.errCode+"");

if (errCode == 0) {
// 0成功 展示成功页面
tv_res.setText("支付成功");
}
else if (errCode == -1) {
//-1 错误 可能的原因:签名错误、未注册APPID、项目设置APPID不正确、注册的APPID与设置的不匹配、其他异常等。
tv_res.setText("支付失败:"+resp.errStr);
finish();
}
else if (errCode == -2) {
//-2 用户取消 无需处理。发生场景:用户不支付了,点击取消,返回APP。
finish();
}
}

}


PS:补充一个问题,上线以后反应客户不能正常调起支付,原因是应用签名当时提交的debug版本的,而正式版的keystore是不一样的,所以不能正常调起

在网页那里重新设置下签名就行了
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: